[ADD] Added Recurring Modules

This commit is contained in:
Poojan Patel
2021-03-09 15:46:58 +00:00
committed by Parthiv Patel
parent a0283481a0
commit 76aaf535a5
65 changed files with 2173 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing
# details.
from . import models
+31
View File
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing
# details.
{
'name': 'Recurring Documents',
'category': 'Extra Tools',
'author': 'FlectraHQ',
'description': """
Create recurring documents.
===========================
This module allows to create new documents and add recurring on that
document.
e.g. To have an invoice generated automatically periodically:
-------------------------------------------------------------
* Define a document type based on Invoice object
* Define a recurring whose source document is the document defined as
above. Specify the interval information and partner to be invoiced.
Module taken from odoov10 subscription.
""",
'depends': ['account', 'purchase', 'sales_team', 'base', 'contacts', 'sale',
'l10n_generic_coa'],
'data': [
'security/ir.model.access.csv',
'views/recurring_view.xml',
],
'demo': ['demo/recurring_demo.xml'],
'license': 'LGPL-3',
}
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" ?>
<flectra noupdate="1">
<record id="recurring_document_partner0" model="recurring.document">
<field eval="1" name="active"/>
<field name="model" ref="account.model_account_move"/>
<field name="name">Invoice Recurring Type</field>
</record>
<record id="recurring_document_fields_2" model="recurring.document.fields">
<field name="document_id" ref="recurring_document_partner0"/>
<field name="field" ref="account.field_account_move__name"/>
<field name="value">false</field>
</record>
<record id="recurring_partner0" model="recurring">
<field name="name">Invoice Recurring Document</field>
<field name="exec_init">5</field>
<field name="interval_type">months</field>
<field name="date_init" eval="datetime.now()"/>
<field name="doc_source" ref='l10n_generic_coa.demo_invoice_1'/>
</record>
</flectra>
+415
View File
@@ -0,0 +1,415 @@
# Translation of Flectra Server.
# This file contains the translation of the following modules:
# * recurring
#
msgid ""
msgstr ""
"Project-Id-Version: Flectra Server 2.0alpha\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-08 12:35+0000\n"
"PO-Revision-Date: 2021-03-08 12:35+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__active
#: model:ir.model.fields,field_description:recurring.field_recurring_document__active
msgid "Active"
msgstr ""
#. module: recurring
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_wizard_form
msgid "Cancel"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__create_uid
#: model:ir.model.fields,field_description:recurring.field_recurring_document__create_uid
#: model:ir.model.fields,field_description:recurring.field_recurring_document_fields__create_uid
#: model:ir.model.fields,field_description:recurring.field_recurring_history__create_uid
msgid "Created by"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__create_date
#: model:ir.model.fields,field_description:recurring.field_recurring_document__create_date
#: model:ir.model.fields,field_description:recurring.field_recurring_document_fields__create_date
#: model:ir.model.fields,field_description:recurring.field_recurring_history__create_date
msgid "Created on"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__cron_id
msgid "Cron Job"
msgstr ""
#. module: recurring
#: code:addons/recurring/tests/test_recurring.py:0
#, python-format
msgid "Cron is not created"
msgstr ""
#. module: recurring
#: model:ir.model.fields.selection,name:recurring.selection__recurring_document_fields__value__date
msgid "Current Date"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring_history__date
msgid "Date"
msgstr ""
#. module: recurring
#: model:ir.model.fields.selection,name:recurring.selection__recurring__interval_type__days
msgid "Days"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring_document_fields__value
msgid "Default Value"
msgstr ""
#. module: recurring
#: model:ir.model.fields,help:recurring.field_recurring_document_fields__value
msgid "Default value is considered for field when new document is generated."
msgstr ""
#. module: recurring
#: model:ir.model.fields,help:recurring.field_recurring__note
msgid "Description or Summary of Recurring"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__display_name
#: model:ir.model.fields,field_description:recurring.field_recurring_document__display_name
#: model:ir.model.fields,field_description:recurring.field_recurring_document_fields__display_name
#: model:ir.model.fields,field_description:recurring.field_recurring_history__display_name
msgid "Display Name"
msgstr ""
#. module: recurring
#: code:addons/recurring/models/recurring.py:0
#, python-format
msgid "Document is already recurring"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__doc_lines
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_form
msgid "Documents created"
msgstr ""
#. module: recurring
#: model:ir.model.fields.selection,name:recurring.selection__recurring__state__done
msgid "Done"
msgstr ""
#. module: recurring
#: model:ir.model.fields.selection,name:recurring.selection__recurring__state__draft
msgid "Draft"
msgstr ""
#. module: recurring
#: code:addons/recurring/models/recurring.py:0
#, python-format
msgid "Error! Source Document should be related to partner %s"
msgstr ""
#. module: recurring
#: model:ir.model.fields.selection,name:recurring.selection__recurring_document_fields__value__false
msgid "False"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring_document_fields__field
msgid "Field"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring_document__field_ids
msgid "Fields"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__date_init
msgid "First Date"
msgstr ""
#. module: recurring
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_filter
msgid "Group By"
msgstr ""
#. module: recurring
#: model:ir.model.fields.selection,name:recurring.selection__recurring__interval_type__hours
msgid "Hours"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__id
#: model:ir.model.fields,field_description:recurring.field_recurring_document__id
#: model:ir.model.fields,field_description:recurring.field_recurring_document_fields__id
#: model:ir.model.fields,field_description:recurring.field_recurring_history__id
msgid "ID"
msgstr ""
#. module: recurring
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_wizard_form
msgid "IR Recurring"
msgstr ""
#. module: recurring
#: model:ir.model.fields,help:recurring.field_recurring_document__active
msgid ""
"If the active field is set to False, it will allow you to hide the recurring"
" document without removing it."
msgstr ""
#. module: recurring
#: model:ir.model.fields,help:recurring.field_recurring__active
msgid ""
"If the active field is set to False, it will allow you to hide the recurring"
" without removing it."
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__notes
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_form
msgid "Internal Notes"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__interval_number
msgid "Interval Qty"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__interval_type
msgid "Interval Unit"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring____last_update
#: model:ir.model.fields,field_description:recurring.field_recurring_document____last_update
#: model:ir.model.fields,field_description:recurring.field_recurring_document_fields____last_update
#: model:ir.model.fields,field_description:recurring.field_recurring_history____last_update
msgid "Last Modified on"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__write_uid
#: model:ir.model.fields,field_description:recurring.field_recurring_document__write_uid
#: model:ir.model.fields,field_description:recurring.field_recurring_document_fields__write_uid
#: model:ir.model.fields,field_description:recurring.field_recurring_history__write_uid
msgid "Last Updated by"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__write_date
#: model:ir.model.fields,field_description:recurring.field_recurring_document__write_date
#: model:ir.model.fields,field_description:recurring.field_recurring_document_fields__write_date
#: model:ir.model.fields,field_description:recurring.field_recurring_history__write_date
msgid "Last Updated on"
msgstr ""
#. module: recurring
#: model:ir.model.fields.selection,name:recurring.selection__recurring__interval_type__minutes
msgid "Minutes"
msgstr ""
#. module: recurring
#: model:ir.model.fields.selection,name:recurring.selection__recurring__interval_type__months
msgid "Months"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__name
#: model:ir.model.fields,field_description:recurring.field_recurring_document__name
msgid "Name"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__note
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_form
msgid "Notes"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__exec_init
msgid "Number of Documents"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring_document__model
msgid "Object"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__partner_id
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_filter
msgid "Partner"
msgstr ""
#. module: recurring
#: code:addons/recurring/models/recurring.py:0
#, python-format
msgid ""
"Please provide another source document.\n"
"This one does not exist!"
msgstr ""
#. module: recurring
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_form
msgid "Process"
msgstr ""
#. module: recurring
#: model:ir.model,name:recurring.model_recurring
#: model:ir.model.fields,field_description:recurring.field_recurring_history__recurring_id
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_filter
msgid "Recurring"
msgstr ""
#. module: recurring
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_form
msgid "Recurring Data"
msgstr ""
#. module: recurring
#: model:ir.model,name:recurring.model_recurring_document
#: model:ir.model.fields,field_description:recurring.field_recurring_document_fields__document_id
#: model_terms:ir.ui.view,arch_db:recurring.document_form
#: model_terms:ir.ui.view,arch_db:recurring.document_tree
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_document_filter
msgid "Recurring Document"
msgstr ""
#. module: recurring
#: model:ir.model,name:recurring.model_recurring_document_fields
#: model_terms:ir.ui.view,arch_db:recurring.document_fields_form
#: model_terms:ir.ui.view,arch_db:recurring.document_fields_tree
msgid "Recurring Document Fields"
msgstr ""
#. module: recurring
#: model:ir.actions.act_window,name:recurring.action_recurring_form
#: model:ir.actions.act_window,name:recurring.action_recurring_wizard
#: model:ir.ui.menu,name:recurring.menu_action_recurring_form
msgid "Recurring Documents"
msgstr ""
#. module: recurring
#: model_terms:ir.ui.view,arch_db:recurring.recurring_history_form
#: model_terms:ir.ui.view,arch_db:recurring.recurring_history_tree
msgid "Recurring History"
msgstr ""
#. module: recurring
#: model:ir.actions.act_window,name:recurring.action_document_form
#: model:ir.ui.menu,name:recurring.menu_action_document_form
msgid "Recurring Types"
msgstr ""
#. module: recurring
#: model:ir.model,name:recurring.model_recurring_history
msgid "Recurring history"
msgstr ""
#. module: recurring
#: code:addons/recurring/tests/test_recurring.py:0
#, python-format
msgid "Recurring is in running state"
msgstr ""
#. module: recurring
#: code:addons/recurring/tests/test_recurring.py:0
#, python-format
msgid "Recurring is not in draft state"
msgstr ""
#. module: recurring
#: code:addons/recurring/models/recurring.py:0
#, python-format
msgid "Recurring of the selected Source Document already exist"
msgstr ""
#. module: recurring
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_form
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_tree
msgid "Recurrings"
msgstr ""
#. module: recurring
#: model:ir.model.fields.selection,name:recurring.selection__recurring__state__running
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_filter
msgid "Running"
msgstr ""
#. module: recurring
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_wizard_form
msgid "Save"
msgstr ""
#. module: recurring
#: model:ir.model.fields,help:recurring.field_recurring__cron_id
msgid "Scheduler which runs on recurring"
msgstr ""
#. module: recurring
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_filter
msgid "Search Recurring"
msgstr ""
#. module: recurring
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_form
msgid "Set to Draft"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__doc_source
#: model:ir.model.fields,field_description:recurring.field_recurring_history__document_id
msgid "Source Document"
msgstr ""
#. module: recurring
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_wizard_form
msgid "Start Recurring"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__state
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_filter
msgid "Status"
msgstr ""
#. module: recurring
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_form
msgid "Stop"
msgstr ""
#. module: recurring
#: model:ir.model.fields,field_description:recurring.field_recurring__user_id
#: model_terms:ir.ui.view,arch_db:recurring.view_recurring_filter
msgid "User"
msgstr ""
#. module: recurring
#: model:ir.model.fields,help:recurring.field_recurring__doc_source
msgid ""
"User can choose the source document on which he wants to create documents"
msgstr ""
#. module: recurring
#: model:ir.model.fields.selection,name:recurring.selection__recurring__interval_type__weeks
msgid "Weeks"
msgstr ""
#. module: recurring
#: code:addons/recurring/models/recurring.py:0
#, python-format
msgid "You cannot delete an active recurring!"
msgstr ""
+5
View File
@@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing
# details.
from . import recurring
+281
View File
@@ -0,0 +1,281 @@
# -*- coding: utf-8 -*-
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing
# details.
# TODO:
# Error treatment: exception, request, ... -> send request to user_id
from flectra import api, fields, models, _
from flectra.exceptions import UserError, ValidationError
def _get_document_types(self):
return [(doc.model.model, doc.name) for doc in self.env[
'recurring.document'].search([], order='name')]
class RecurringDocument(models.Model):
_name = "recurring.document"
_description = "Recurring Document"
name = fields.Char(string='Name')
active = fields.Boolean(
help="If the active field is set to False, it will allow you to hide "
"the recurring document without removing it.", default=True)
model = fields.Many2one('ir.model', string="Object")
field_ids = fields.One2many('recurring.document.fields',
'document_id', string='Fields', copy=True)
class RecurringDocumentFields(models.Model):
_name = "recurring.document.fields"
_description = "Recurring Document Fields"
_rec_name = 'field'
field = fields.Many2one('ir.model.fields', domain="[('model_id', '=', "
"parent.model)]")
value = fields.Selection(
[('false', 'False'), ('date', 'Current Date')], string='Default Value',
help="Default value is considered for field when new document is "
"generated.")
document_id = fields.Many2one('recurring.document',
string='Recurring Document',
ondelete='cascade')
class Recurring(models.Model):
_name = "recurring"
_description = "Recurring"
@api.model
def default_get(self, fields):
res = super(Recurring, self).default_get(fields)
active_model = self._context.get('active_model')
active_id = self._context.get('active_id')
if active_model and active_id:
record = self.env[active_model].browse(active_id)
if 'partner_id' in self.env[active_model]._fields:
res['partner_id'] = record.partner_id.id
else:
res['name'] = record.name
if not res['name']:
res['name'] = record.number
return res
@api.onchange('partner_id')
def _onchange_partner_id(self):
active_model = self._context.get('active_model')
active_id = self._context.get('active_id')
if self.partner_id and active_model and active_id:
record = self.env[active_model].browse(active_id)
name = record.name
if not name:
name = record.number
if name:
self.name = name + '-' + self.partner_id.name
else:
self.name = self.partner_id.name
@api.constrains('partner_id', 'doc_source')
def _check_partner_id_doc_source(self):
for record in self:
if record.partner_id and record.doc_source and 'partner_id' in \
self.env[record.doc_source._name]._fields and \
record.doc_source.partner_id != record.partner_id:
raise ValidationError(_(
'Error! Source Document should be related to partner %s' %
record.doc_source.partner_id.name))
name = fields.Char(string='Name')
active = fields.Boolean(
help="If the active field is set to False, it will allow you to hide "
"the recurring without removing it.", default=True)
partner_id = fields.Many2one('res.partner', string='Partner')
notes = fields.Text(string='Internal Notes')
user_id = fields.Many2one('res.users', string='User',
default=lambda self: self.env.user)
interval_number = fields.Integer(string='Interval Qty', default=1)
interval_type = fields.Selection(
[('minutes', 'Minutes'), ('hours', 'Hours'), ('days', 'Days'),
('weeks', 'Weeks'), ('months', 'Months')], string='Interval Unit',
default='months')
exec_init = fields.Integer(string='Number of Documents')
date_init = fields.Datetime(string='First Date',
default=fields.Datetime.now)
state = fields.Selection(
[('draft', 'Draft'), ('running', 'Running'), ('done', 'Done')],
string='Status', copy=False, default='draft')
doc_source = fields.Reference(
selection=_get_document_types, string='Source Document',
help="User can choose the source document on which he wants to "
"create documents")
doc_lines = fields.One2many('recurring.history',
'recurring_id', string='Documents created')
cron_id = fields.Many2one('ir.cron', string='Cron Job',
help="Scheduler which runs on recurring",
states={'running': [('readonly', True)],
'done': [('readonly', True)]})
note = fields.Text(string='Notes',
help="Description or Summary of Recurring")
@api.model
def _auto_end(self):
super(Recurring, self)._auto_end()
# drop the FK from recurring to ir.cron, as it would cause deadlocks
# during cron job execution. When model_copy() tries to write() on
# the recurring,
# it has to wait for an ExclusiveLock on the cron job record,
# but the latter is locked by the cron system for the duration of
# the job!
# FIXME: the recurring module should be reviewed to simplify the
# scheduling process
# and to use a unique cron job for all recurrings, so that it
# never needs to be updated during its execution.
self.env.cr.execute("ALTER TABLE %s DROP CONSTRAINT %s" % (
self._table, '%s_cron_id_fkey' % self._table))
def create_recurring_type(self):
rec_doc_obj = self.env['recurring.document']
ir_model_id = self.env['ir.model'].search(
[('model', '=', self._context.get('active_model', False))])
rec_doc_id = rec_doc_obj.search([('model', '=', ir_model_id.id)])
if not rec_doc_id:
rec_doc_id = rec_doc_obj.create({
'name': ir_model_id.name,
'model': ir_model_id.id,
})
return rec_doc_id
def btn_recurring(self):
self.ensure_one()
rec_doc_id = self.create_recurring_type()
if rec_doc_id:
active_model = self._context.get('active_model')
active_id = self._context.get('active_id')
if active_id and active_model:
record = self.env[active_model].browse(active_id)
self.doc_source = record._name + "," + str(record.id)
record.recurring_id = self.id
record.rec_source_id = record.id
if self._context.get('process') == 'start':
self.set_process()
def set_process(self):
for recurring in self:
model = 'recurring'
cron_data = {
'name': recurring.name,
'interval_number': recurring.interval_number,
'interval_type': recurring.interval_type,
'numbercall': recurring.exec_init,
'nextcall': recurring.date_init,
'model_id': self.env['ir.model'].search(
[('model', '=', model)]).id,
'priority': 6,
'user_id': recurring.user_id.id,
'state': 'code',
'code': 'model._cron_model_copy(' + repr([recurring.id]) + ')',
}
cron = self.env['ir.cron'].sudo().create(cron_data)
recurring.write({'cron_id': cron.id, 'state': 'running'})
def set_recurring_id(self):
if self.doc_source and 'recurring_id' and 'rec_source_id' in \
self.env[self.doc_source._name]._fields:
rec_id = self.env[self.doc_source._name].browse(self.doc_source.id)
if not rec_id.recurring_id and not rec_id.rec_source_id:
rec_id.recurring_id = self.id
rec_id.rec_source_id = self.doc_source.id
else:
raise ValidationError(
_('Document is already recurring'))
@api.model
def create(self, vals):
if vals.get('doc_source', False) and self.search(
[('doc_source', '=', vals['doc_source'])]):
raise ValidationError(
_('Recurring of the selected Source Document already exist'))
res = super(Recurring, self).create(vals)
res.set_recurring_id()
return res
def write(self, values):
doc_source_id = False
if values.get('doc_source', False):
doc_source_id = self.doc_source
res = super(Recurring, self).write(values)
if doc_source_id:
rec_id = self.env[doc_source_id._name].browse(doc_source_id.id)
rec_id.recurring_id = False
self.set_recurring_id()
return res
def get_recurring(self, model, active_id):
result = self.env.ref('recurring.action_recurring_form').read()[0]
record = self.env[model].browse(active_id)
rec_ids = self.env['recurring'].search(
[('doc_source', '=', record._name + "," + str(record.id))])
result['domain'] = [('id', 'in', rec_ids.ids)]
return result
def get_recurring_documents(self, model, action, recurring_id):
result = self.env.ref(action).read()[0]
res_ids = self.env[model].search(
[('recurring_id', '=', recurring_id.id)])
result['domain'] = [('id', 'in', res_ids.ids)]
return result
@api.model
def _cron_model_copy(self, ids):
self.browse(ids).model_copy()
def model_copy(self):
for recurring in self.filtered(lambda sub: sub.cron_id):
if not recurring.doc_source.exists():
raise UserError(_('Please provide another source '
'document.\nThis one does not exist!'))
default = {}
documents = self.env['recurring.document'].search(
[('model.model', '=', recurring.doc_source._name)], limit=1)
fieldnames = dict((f.field.name, f.value == 'date' and
fields.Date.today() or False)
for f in documents.field_ids)
default.update(fieldnames)
# if there was only one remaining document to generate
# the recurring is over and we mark it as being done
if recurring.cron_id.numbercall == 1:
recurring.write({'state': 'done'})
else:
recurring.write({'state': 'running'})
copied_doc = recurring.doc_source.copy(default)
self.env['recurring.history'].create({
'recurring_id': recurring.id,
'date': fields.Datetime.now(),
'document_id': '%s,%s' % (recurring.doc_source._name,
copied_doc.id)})
def unlink(self):
if any(self.filtered(lambda s: s.state == "running")):
raise UserError(_('You cannot delete an active recurring!'))
return super(Recurring, self).unlink()
def set_done(self):
self.mapped('cron_id').write({'active': False})
self.write({'state': 'done'})
def set_draft(self):
self.write({'state': 'draft'})
class RecurringHistory(models.Model):
_name = "recurring.history"
_description = "Recurring history"
_rec_name = 'date'
date = fields.Datetime(string='Date')
recurring_id = fields.Many2one('recurring', string='Recurring',
ondelete='cascade')
document_id = fields.Reference(
selection=_get_document_types, string='Source Document')
@@ -0,0 +1,35 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_recurring_document_fields,access_recurring_document_fields,model_recurring_document_fields,base.group_erp_manager,1,1,1,1
access_recurring_user,access_recurring_user,model_recurring,base.group_erp_manager,1,1,1,1
access_recurringhistory_user,access_recurring_history_user,model_recurring_history,base.group_erp_manager,1,1,1,1
access_recurring_document_user,access_recurring_document_user,model_recurring_document,base.group_erp_manager,1,1,1,1
access_res_partner_user,access_res_partner_user,base.model_res_partner,base.group_erp_manager,1,1,1,1
access_ir_cron_user,access_ir_cron_user,base.model_ir_cron,base.group_erp_manager,1,1,1,1
access_recurring_document_fields_account_manager,access_recurring_document_fields,model_recurring_document_fields,account.group_account_manager,1,1,1,1
access_recurring_user_account_manager,access_recurring_user,model_recurring,account.group_account_manager,1,1,1,1
access_recurringhistory_user_account_manager,access_recurring_history_user,model_recurring_history,account.group_account_manager,1,1,1,1
access_recurring_document_user_account_manager,access_recurring_document_user,model_recurring_document,account.group_account_manager,1,1,1,1
access_res_partner_user_account_manager,access_res_partner_user,base.model_res_partner,account.group_account_manager,1,1,1,1
access_ir_cron_user_account_manager,access_ir_cron_user,base.model_ir_cron,account.group_account_manager,1,1,1,1
access_recurring_document_fields_sale_manager,access_recurring_document_fields,model_recurring_document_fields,sales_team.group_sale_manager,1,1,1,1
access_recurring_user_sale_manager,access_recurring_user,model_recurring,sales_team.group_sale_manager,1,1,1,1
access_recurringhistory_user_sale_manager,access_recurring_history_user,model_recurring_history,sales_team.group_sale_manager,1,1,1,1
access_recurring_document_user_sale_manager,access_recurring_document_user,model_recurring_document,sales_team.group_sale_manager,1,1,1,1
access_res_partner_user_sale_manager,access_res_partner_user,base.model_res_partner,sales_team.group_sale_manager,1,1,1,1
access_ir_cron_user_sale_manager,access_ir_cron_user,base.model_ir_cron,sales_team.group_sale_manager,1,1,1,1
access_recurring_document_fields_purchase_manager,access_recurring_document_fields,model_recurring_document_fields,purchase.group_purchase_manager,1,1,1,1
access_recurring_user_purchase_manager,access_recurring_user,model_recurring,purchase.group_purchase_manager,1,1,1,1
access_recurringhistory_user_purchase_manager,access_recurring_history_user,model_recurring_history,purchase.group_purchase_manager,1,1,1,1
access_recurring_document_user_purchase_manager,access_recurring_document_user,model_recurring_document,purchase.group_purchase_manager,1,1,1,1
access_res_partner_user_purchase_manager,access_res_partner_user,base.model_res_partner,purchase.group_purchase_manager,1,1,1,1
access_ir_cron_user_purchase_manager,access_ir_cron_user,base.model_ir_cron,purchase.group_purchase_manager,1,1,1,1
access_recurring_document_fields_group,access_recurring_document_fields,model_recurring_document_fields,base.group_user,1,0,0,0
access_recurring_user_group,access_recurring_user,model_recurring,base.group_user,1,0,0,0
access_recurringhistory_user_group,access_recurring_history_user,model_recurring_history,base.group_user,1,0,0,0
access_recurring_document_user_group,access_recurring_document_user,model_recurring_document,base.group_user,1,0,0,0
access_res_partner_user_group,access_res_partner_user,base.model_res_partner,base.group_user,1,0,0,0
access_ir_cron_user_group,access_ir_cron_user,base.model_ir_cron,base.group_user,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_recurring_document_fields access_recurring_document_fields model_recurring_document_fields base.group_erp_manager 1 1 1 1
3 access_recurring_user access_recurring_user model_recurring base.group_erp_manager 1 1 1 1
4 access_recurringhistory_user access_recurring_history_user model_recurring_history base.group_erp_manager 1 1 1 1
5 access_recurring_document_user access_recurring_document_user model_recurring_document base.group_erp_manager 1 1 1 1
6 access_res_partner_user access_res_partner_user base.model_res_partner base.group_erp_manager 1 1 1 1
7 access_ir_cron_user access_ir_cron_user base.model_ir_cron base.group_erp_manager 1 1 1 1
8 access_recurring_document_fields_account_manager access_recurring_document_fields model_recurring_document_fields account.group_account_manager 1 1 1 1
9 access_recurring_user_account_manager access_recurring_user model_recurring account.group_account_manager 1 1 1 1
10 access_recurringhistory_user_account_manager access_recurring_history_user model_recurring_history account.group_account_manager 1 1 1 1
11 access_recurring_document_user_account_manager access_recurring_document_user model_recurring_document account.group_account_manager 1 1 1 1
12 access_res_partner_user_account_manager access_res_partner_user base.model_res_partner account.group_account_manager 1 1 1 1
13 access_ir_cron_user_account_manager access_ir_cron_user base.model_ir_cron account.group_account_manager 1 1 1 1
14 access_recurring_document_fields_sale_manager access_recurring_document_fields model_recurring_document_fields sales_team.group_sale_manager 1 1 1 1
15 access_recurring_user_sale_manager access_recurring_user model_recurring sales_team.group_sale_manager 1 1 1 1
16 access_recurringhistory_user_sale_manager access_recurring_history_user model_recurring_history sales_team.group_sale_manager 1 1 1 1
17 access_recurring_document_user_sale_manager access_recurring_document_user model_recurring_document sales_team.group_sale_manager 1 1 1 1
18 access_res_partner_user_sale_manager access_res_partner_user base.model_res_partner sales_team.group_sale_manager 1 1 1 1
19 access_ir_cron_user_sale_manager access_ir_cron_user base.model_ir_cron sales_team.group_sale_manager 1 1 1 1
20 access_recurring_document_fields_purchase_manager access_recurring_document_fields model_recurring_document_fields purchase.group_purchase_manager 1 1 1 1
21 access_recurring_user_purchase_manager access_recurring_user model_recurring purchase.group_purchase_manager 1 1 1 1
22 access_recurringhistory_user_purchase_manager access_recurring_history_user model_recurring_history purchase.group_purchase_manager 1 1 1 1
23 access_recurring_document_user_purchase_manager access_recurring_document_user model_recurring_document purchase.group_purchase_manager 1 1 1 1
24 access_res_partner_user_purchase_manager access_res_partner_user base.model_res_partner purchase.group_purchase_manager 1 1 1 1
25 access_ir_cron_user_purchase_manager access_ir_cron_user base.model_ir_cron purchase.group_purchase_manager 1 1 1 1
26 access_recurring_document_fields_group access_recurring_document_fields model_recurring_document_fields base.group_user 1 0 0 0
27 access_recurring_user_group access_recurring_user model_recurring base.group_user 1 0 0 0
28 access_recurringhistory_user_group access_recurring_history_user model_recurring_history base.group_user 1 0 0 0
29 access_recurring_document_user_group access_recurring_document_user model_recurring_document base.group_user 1 0 0 0
30 access_res_partner_user_group access_res_partner_user base.model_res_partner base.group_user 1 0 0 0
31 access_ir_cron_user_group access_ir_cron_user base.model_ir_cron base.group_user 1 0 0 0
Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

@@ -0,0 +1,111 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Recurring</h2>
<h3 class="oe_slogan">Create recurring of document of any module</h3>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Recurring Type</h2>
</div>
<div class="oe_span6">
<p class="oe_mt32">
To generate recurring document of any module its Recurring type
is first created. Here recurring type of sale is created.
Recurring type is created from Settings > Technical >
Automation > Recurring Types
</p>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="recurring_type.png">
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Recurring Document</h2>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="recurring_document.png">
</div>
</div>
<div class="oe_span6">
<p class="oe_mt32">
Recurring Document is created of any document which is
needed to be generated everytime at a specific interval of
time.
Number of documents - The number of times the document
should be recurred.
Interval Unit - The interval when the recurring should occur.
Source Document - Choose the source document on which needs
to be generated at every specific interval.
Recurring Documents is created from Settings > Technical >
Automation > Recurring Documents
</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Recurring Document Started</h2>
</div>
<div class="oe_span6">
<p class="oe_mt32">
Recurring of the selected document can be started any time
by clicking on the 'Process' Button
Cron job is automatically created and is linked here.
</p>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="recurring_document_started.png"/>
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Scheduled Actions</h2>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="cron_job.png">
</div>
</div>
<div class="oe_span6">
<p class="oe_mt32">The generated cron job from the
recurring document</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Sale Orders</h2>
</div>
<div class="oe_span6">
<p class="oe_mt32">
Sale Orders that are generated through recurring.
</p>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="sale_order.png"/>
</div>
</div>
</div>
</section>
Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

+4
View File
@@ -0,0 +1,4 @@
# Part of Flectra. See LICENSE file for full copyright and licensing
# details.
from . import test_recurring
+37
View File
@@ -0,0 +1,37 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from flectra import _
from flectra.exceptions import UserError
from flectra.tests.common import TransactionCase
import logging
_logger = logging.getLogger(__name__)
class RecurringTransactionCase(TransactionCase):
def setUp(self):
super(RecurringTransactionCase, self).setUp()
self.recurring_id = self.env.ref("recurring.recurring_partner0")
def check_recurring(self):
self.recurring_id.set_process()
if not self.recurring_id.cron_id:
raise UserError(_("Cron is not created"))
else:
self.recurring_id.cron_id.method_direct_trigger()
try:
self.recurring_id.unlink()
except Exception as e:
_logger.info(
"You cannot delete an active recurring!")
self.recurring_id.set_done()
if not self.recurring_id.state == 'done':
raise UserError(_("Recurring is in running state"))
self.recurring_id.set_draft()
if not self.recurring_id.state == 'draft':
raise UserError(_("Recurring is not in draft state"))
def test_01_recurring(self):
self.check_recurring()
+274
View File
@@ -0,0 +1,274 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<!-- Recurring Views -->
<record id="view_recurring_form" model="ir.ui.view">
<field name="name">recurring.form</field>
<field name="model">recurring</field>
<field name="arch" type="xml">
<form string="Recurrings">
<header>
<button name="set_process" states="draft" string="Process"
type="object" class="oe_highlight"/>
<button name="set_done" states="running" string="Stop"
type="object" class="oe_highlight"/>
<button name="set_draft" states="done"
string="Set to Draft" type="object"/>
<field name="state" widget="statusbar"
statusbar_visible="draft,running"/>
</header>
<sheet>
<group col="4">
<field name="name" required="1"/>
<field name="partner_id"/>
<field name="user_id" required="1"/>
<field name="active"/>
</group>
<notebook>
<page string="Recurring Data">
<group col="4">
<field name="interval_number"/>
<field name="interval_type"/>
<field name="exec_init"/>
<field name="date_init"/>
<field name="doc_source" required="1"/>
<field name="cron_id"/>
</group>
<separator string="Internal Notes"/>
<field name="notes"/>
</page>
<page string="Documents created">
<field name="doc_lines" widget="one2many_list"
readonly="1"/>
</page>
<page string="Notes">
<field name="note"/>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="view_recurring_tree" model="ir.ui.view">
<field name="name">recurring.tree</field>
<field name="model">recurring</field>
<field name="arch" type="xml">
<tree string="Recurrings">
<field name="name"/>
<field name="partner_id"/>
<field name="active"/>
<field name="user_id"/>
<field name="state"/>
</tree>
</field>
</record>
<record id="view_recurring_filter" model="ir.ui.view">
<field name="name">recurring.filter</field>
<field name="model">recurring</field>
<field name="arch" type="xml">
<search string="Search Recurring">
<field name="name" string="Recurring"/>
<field name="date_init"/>
<filter string="Running" name="Running"
domain="[('state','=','running')]"/>
<field name="user_id"/>
<field name="partner_id"/>
<group expand="0" string="Group By">
<filter string="User" name="User" domain="[]"
context="{'group_by':'user_id'}"/>
<filter string="Partner" name="Partner" domain="[]"
context="{'group_by':'partner_id'}"/>
<filter string="Status" domain="[]" name="Status"
context="{'group_by':'state'}"/>
</group>
</search>
</field>
</record>
<record id="action_recurring_form" model="ir.actions.act_window">
<field name="name">Recurring Documents</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">recurring</field>
<field name="binding_view_types">form</field>
<field name="view_id" ref="view_recurring_tree"/>
<field name="context">{'search_default_User':1,
'disable':False}
</field>
<field name="search_view_id" ref="view_recurring_filter"/>
</record>
<record model="ir.actions.act_window.view"
id="action_recurring_tree_view">
<field name="sequence" eval="2"/>
<field name="view_mode">tree</field>
<field name="view_id" ref="view_recurring_tree"/>
<field name="act_window_id" ref="action_recurring_form"/>
</record>
<record model="ir.actions.act_window.view"
id="action_recurring_form_view">
<field name="sequence" eval="2"/>
<field name="view_mode">form</field>
<field name="view_id" ref="view_recurring_form"/>
<field name="act_window_id" ref="action_recurring_form"/>
</record>
<menuitem action="action_recurring_form" id="menu_action_recurring_form"
parent="base.menu_automation"/>
<record id="recurring_history_tree" model="ir.ui.view">
<field name="name">recurring.history.tree</field>
<field name="model">recurring.history</field>
<field name="arch" type="xml">
<tree string="Recurring History">
<field name="date"/>
<field name="document_id"/>
</tree>
</field>
</record>
<record id="recurring_history_form" model="ir.ui.view">
<field name="name">recurring.history.form</field>
<field name="model">recurring.history</field>
<field name="arch" type="xml">
<form string="Recurring History">
<group col="4">
<field name="date"/>
<field name="document_id" required="1"/>
</group>
</form>
</field>
</record>
<record id="document_form" model="ir.ui.view">
<field name="name">recurring.document.form</field>
<field name="model">recurring.document</field>
<field name="arch" type="xml">
<form string="Recurring Document">
<group col="4">
<field name="name" required="1"/>
<field name="model" required="1"/>
<field name="active"/>
</group>
<field name="field_ids"/>
</form>
</field>
</record>
<record id="document_tree" model="ir.ui.view">
<field name="name">recurring.document.tree</field>
<field name="model">recurring.document</field>
<field name="arch" type="xml">
<tree string="Recurring Document">
<field name="name"/>
<field name="active"/>
<field name="model"/>
</tree>
</field>
</record>
<record id="view_recurring_document_filter" model="ir.ui.view">
<field name="name">recurring.document.filter</field>
<field name="model">recurring.document</field>
<field name="arch" type="xml">
<search string="Recurring Document">
<field name="name" string="Recurring Document"/>
<field name="model"/>
</search>
</field>
</record>
<record id="document_fields_form" model="ir.ui.view">
<field name="name">recurring.document.fields.form</field>
<field name="model">recurring.document.fields</field>
<field name="arch" type="xml">
<form string="Recurring Document Fields">
<group>
<field name="field" required="1"/>
<field name="value"/>
</group>
</form>
</field>
</record>
<record id="document_fields_tree" model="ir.ui.view">
<field name="name">recurring.document.fields.tree</field>
<field name="model">recurring.document.fields</field>
<field name="arch" type="xml">
<tree string="Recurring Document Fields">
<field name="field"/>
<field name="value"/>
</tree>
</field>
</record>
<record id="action_document_form" model="ir.actions.act_window">
<field name="name">Recurring Types</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">recurring.document</field>
<field name="binding_view_types">form</field>
<field name="view_id" ref="document_tree"/>
<field name="search_view_id" ref="view_recurring_document_filter"/>
</record>
<menuitem id="menu_action_document_form" action="action_document_form"
parent="base.menu_automation"/>
<record id="view_recurring_wizard_form" model="ir.ui.view">
<field name="name">recurring</field>
<field name="model">recurring</field>
<field name="type">form</field>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<form string="IR Recurring">
<div class="oe_title">
<h1>
<field name="name" readonly="1" force_save="1"/>
</h1>
</div>
<group>
<group>
<field name="partner_id"/>
<field name="user_id" required="1"/>
<field name="active"/>
<field name="exec_init"/>
</group>
<group>
<field name="interval_number"/>
<field name="interval_type"/>
<field name="date_init"/>
<field name="doc_source" invisible="1"/>
</group>
</group>
<footer>
<button name="btn_recurring" type="object"
string="Start Recurring" class="oe_highlight"
context="{'process':'start'}"/>
<button name="btn_recurring" type="object"
string="Save"/>
<button string="Cancel" special="cancel"/>
</footer>
</form>
</field>
</record>
<record id="action_recurring_wizard" model="ir.actions.act_window">
<field name="name">Recurring Documents</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">recurring</field>
<field name="binding_view_types">form</field>
<field name="view_mode">form</field>
<field name="view_id" ref="view_recurring_wizard_form"/>
<field name="target">new</field>
</record>
<record model="ir.actions.act_window.view"
id="action_recurring_wizard_form_view">
<field name="sequence" eval="2"/>
<field name="view_mode">form</field>
<field name="view_id" ref="view_recurring_wizard_form"/>
<field name="act_window_id" ref="action_recurring_wizard"/>
</record>
</flectra>
+3
View File
@@ -0,0 +1,3 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from . import models
+21
View File
@@ -0,0 +1,21 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
{
'name': 'Account Invoice Recurrings',
'version': '1.0',
'category': 'Extra Tools',
'summary': 'Create recurring of invoices',
'description': """
Account Invoice Recurring allows to automatically create
recurring of any particular invoice
""",
'author': 'FlectraHQ',
'website': 'https://www.flectrahq.com/',
'depends': ['account', 'recurring'],
'data': [
'views/account_invoice_view.xml',
],
'license': 'LGPL-3',
'installable': True,
'auto_install': False,
}
@@ -0,0 +1,65 @@
# Translation of Flectra Server.
# This file contains the translation of the following modules:
# * recurring_account
#
msgid ""
msgstr ""
"Project-Id-Version: Flectra Server 2.0alpha\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-08 12:36+0000\n"
"PO-Revision-Date: 2021-03-08 12:36+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: recurring_account
#: model:ir.model.fields,field_description:recurring_account.field_account_move__display_name
msgid "Display Name"
msgstr ""
#. module: recurring_account
#: model_terms:ir.ui.view,arch_db:recurring_account.invoice_form_inherit
msgid "Document"
msgstr ""
#. module: recurring_account
#: model_terms:ir.ui.view,arch_db:recurring_account.invoice_form_inherit
msgid "Generate Recurring"
msgstr ""
#. module: recurring_account
#: model:ir.model.fields,field_description:recurring_account.field_account_move__id
msgid "ID"
msgstr ""
#. module: recurring_account
#: model:ir.model,name:recurring_account.model_account_move
msgid "Journal Entry"
msgstr ""
#. module: recurring_account
#: model:ir.model.fields,field_description:recurring_account.field_account_move____last_update
msgid "Last Modified on"
msgstr ""
#. module: recurring_account
#: model_terms:ir.ui.view,arch_db:recurring_account.invoice_form_inherit
msgid "Recurring"
msgstr ""
#. module: recurring_account
#: model:ir.model.fields,field_description:recurring_account.field_account_bank_statement_line__recurring_id
#: model:ir.model.fields,field_description:recurring_account.field_account_move__recurring_id
#: model:ir.model.fields,field_description:recurring_account.field_account_payment__recurring_id
msgid "Recurring Reference"
msgstr ""
#. module: recurring_account
#: model:ir.model.fields,field_description:recurring_account.field_account_bank_statement_line__rec_source_id
#: model:ir.model.fields,field_description:recurring_account.field_account_move__rec_source_id
#: model:ir.model.fields,field_description:recurring_account.field_account_payment__rec_source_id
msgid "Recurring Source"
msgstr ""
@@ -0,0 +1,3 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from . import account_invoice
@@ -0,0 +1,29 @@
# Part of Flectra. See LICENSE file for full copyright and licensing
# details.
from flectra import api, models, fields
class AccountMove(models.Model):
_inherit = "account.move"
recurring_id = fields.Many2one('recurring', string='Recurring Reference')
rec_source_id = fields.Many2one('account.move',
string='Recurring Source')
def get_recurring(self):
result = self.env['recurring'].get_recurring(
'account.move', self.id)
return result
def get_recurring_documents(self):
result = self.env['recurring'].get_recurring_documents(
'account.move', 'account.action_move_out_invoice_type',
self.recurring_id)
return result
def action_invoice_cancel(self):
res = super(AccountMove, self).action_invoice_cancel()
if self.recurring_id:
self.recurring_id.set_done()
return res
Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

@@ -0,0 +1,124 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Recurring Invoices</h2>
<h3 class="oe_slogan">Create recurring invoices</h3>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Recurring Wizard</h2>
</div>
<div class="oe_span6">
<p class="oe_mt32">
A 'Generate Recurring' button is displayed on the invoice.<br/>
Recurring Document, Recurring Type and Scheduled action of this
particular invoice is automatically created.<br/>
Number of documents - The number of times the document
should be recurred.<br/>
Interval Unit - The interval when the recurring should
occur.<br/>
Start Recurring - Activates the generated recurring.<br/>
Save - Creates the recurring but doesn't activates it.
</p>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="recurring_document_wizard1.png">
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Invoice</h2>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="invoice.png">
</div>
</div>
<div class="oe_span6">
<p class="oe_mt32">
Recurring - Shows the generated recurring.<br/>
Document - Links the invoices that are generated by the
recurring of that particular invoice.
</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Invoice Recurring Documents</h2>
</div>
<div class="oe_span6">
<p class="oe_mt32">
Invoices that are generated through recurring are linked here.
</p>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="recurring_documents.png"/>
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Recurring Document</h2>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="rec_doc.png"/>
</div>
</div>
<div class="oe_span6">
<p class="oe_mt32">
Recurring Document is automatically created.
</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Recurring Type</h2>
</div>
<div class="oe_span6">
<p class="oe_mt32">Recurring Type is automatically
created</p>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="rec_type.png">
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Scheduled Actions</h2>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="cron_job.png">
</div>
</div>
<div class="oe_span6">
<p class="oe_mt32">Cron job is automatically
created</p>
</div>
</div>
</section>
Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="invoice_form_inherit" model="ir.ui.view">
<field name="name">account.move.form.inherit</field>
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_move_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='invoice_user_id']" position="after">
<field name="recurring_id" invisible="1"/>
<field name="rec_source_id" readonly="1"/>
</xpath>
<xpath expr="//button[@name='action_reverse']"
position="before">
<button name="%(recurring.action_recurring_wizard)d"
id="generate_recurring"
string="Generate Recurring" class="btn-primary"
type="action"
attrs="{'invisible': [('recurring_id', '!=', False)]}"
groups="account.group_account_manager"/>
</xpath>
<xpath expr="//sheet/div[@name='button_box']" position="inside">
<button class="oe_stat_button" type="object"
string="Recurring" name="get_recurring"
icon="fa-tasks" attrs="{'invisible': [('recurring_id', '=', False)]}"
groups="account.group_account_manager"/>
<button class="oe_stat_button" type="object"
string="Document" name="get_recurring_documents"
icon="fa-tasks" attrs="{'invisible': [('recurring_id', '=', False)]}"
groups="account.group_account_manager"/>
</xpath>
</field>
</record>
</flectra>
+3
View File
@@ -0,0 +1,3 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from . import models
+22
View File
@@ -0,0 +1,22 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
{
'name': 'Purchase Order Recurring',
'version': '1.0',
'category': 'Extra Tools',
'summary': 'Create recurring of purchase order',
'description': """
Purchase Order Recurring allows to automatically create recurring of
any particular purchase order
""",
'author': 'FlectraHQ',
'website': 'https://www.flectrahq.com/',
'depends': ['recurring', 'purchase', 'sale_purchase'],
'data': [
'views/purchase_views.xml',
],
'demo': ['demo/purchase_recurring_demo.xml'],
'license': 'LGPL-3',
'installable': True,
'auto_install': False,
}
@@ -0,0 +1,38 @@
<?xml version="1.0" ?>
<flectra noupdate="1">
<record id="purchase_order_demo_1" model="purchase.order">
<field name="name">PO001</field>
<field name="partner_id" ref="base.res_partner_2"/>
</record>
<record id="purchase_order_line_demo" model="purchase.order.line">
<field name="order_id"
ref="recurring_purchase.purchase_order_demo_1"/>
<field name="date_planned" eval="time.strftime('%Y-%m-10')"/>
<field name="product_id" ref="product.product_product_13"/>
<field name="product_uom" ref="uom.product_uom_unit"/>
<field name="price_unit">60</field>
<field name="product_qty">5</field>
</record>
<record id="recurring_document_purchase0" model="recurring.document">
<field eval="1" name="active"/>
<field name="model" ref="purchase.model_purchase_order"/>
<field name="name">Purchase Recurring Type</field>
</record>
<record id="recurring_document_fields_3" model="recurring.document.fields">
<field name="document_id" ref="recurring_document_purchase0"/>
<field name="field" ref="purchase.field_purchase_order__name"/>
<field name="value">false</field>
</record>
<record id="recurring_purchase1" model="recurring">
<field name="name">Purchase Recurring Document</field>
<field name="exec_init">2</field>
<field name="interval_type">months</field>
<field name="date_init" eval="datetime.now()"/>
<field name="doc_source" ref='recurring_purchase.purchase_order_demo_1'/>
</record>
</flectra>
@@ -0,0 +1,61 @@
# Translation of Flectra Server.
# This file contains the translation of the following modules:
# * recurring_purchase
#
msgid ""
msgstr ""
"Project-Id-Version: Flectra Server 2.0alpha\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-08 12:37+0000\n"
"PO-Revision-Date: 2021-03-08 12:37+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: recurring_purchase
#: model:ir.model.fields,field_description:recurring_purchase.field_purchase_order__display_name
msgid "Display Name"
msgstr ""
#. module: recurring_purchase
#: model_terms:ir.ui.view,arch_db:recurring_purchase.view_purchase_order_form_inherit
msgid "Document"
msgstr ""
#. module: recurring_purchase
#: model_terms:ir.ui.view,arch_db:recurring_purchase.view_purchase_order_form_inherit
msgid "Generate Recurring"
msgstr ""
#. module: recurring_purchase
#: model:ir.model.fields,field_description:recurring_purchase.field_purchase_order__id
msgid "ID"
msgstr ""
#. module: recurring_purchase
#: model:ir.model.fields,field_description:recurring_purchase.field_purchase_order____last_update
msgid "Last Modified on"
msgstr ""
#. module: recurring_purchase
#: model:ir.model,name:recurring_purchase.model_purchase_order
msgid "Purchase Order"
msgstr ""
#. module: recurring_purchase
#: model_terms:ir.ui.view,arch_db:recurring_purchase.view_purchase_order_form_inherit
msgid "Recurring"
msgstr ""
#. module: recurring_purchase
#: model:ir.model.fields,field_description:recurring_purchase.field_purchase_order__recurring_id
msgid "Recurring Reference"
msgstr ""
#. module: recurring_purchase
#: model:ir.model.fields,field_description:recurring_purchase.field_purchase_order__rec_source_id
msgid "Recurring Source"
msgstr ""
@@ -0,0 +1,3 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from . import purchase
@@ -0,0 +1,25 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from flectra import api, models, fields
class PurchaseOrder(models.Model):
_inherit = 'purchase.order'
recurring_id = fields.Many2one('recurring', string='Recurring Reference')
rec_source_id = fields.Many2one('purchase.order',
string='Recurring Source')
def get_recurring(self):
result = self.env['recurring'].get_recurring('purchase.order', self.id)
return result
def get_recurring_documents(self):
result = self.env['recurring'].get_recurring_documents(
'purchase.order', 'purchase.purchase_rfq', self.recurring_id)
return result
def button_cancel(self):
if self.recurring_id:
self.recurring_id.set_done()
return super(PurchaseOrder, self).button_cancel()
Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

@@ -0,0 +1,127 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Recurring Purchase</h2>
<h3 class="oe_slogan">Create recurring purchase order</h3>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Recurring Wizard</h2>
</div>
<div class="oe_span6">
<p class="oe_mt32">
A 'Generate Recurring' button is displayed on the purchase
order.<br/>
Recurring Document, Recurring Type and Scheduled action of this
particular purchase order is automatically created.<br/>
Number of documents - The number of times the document
should be recurred.<br/>
Interval Unit - The interval when the recurring should
occur.<br/>
Start Recurring - Activates the generated recurring.<br/>
Save - Creates the recurring but doesn't activates it.
</p>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="recurring_document_wizard1.png">
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Purchase Order</h2>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="purchase_order.png">
</div>
</div>
<div class="oe_span6">
<p class="oe_mt32">
Recurring - Shows the generated recurring.<br/>
Document - Links the purchase order that are generated by the
recurring of that particular purchase order.
</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">PO Recurring Documents</h2>
</div>
<div class="oe_span6">
<p class="oe_mt32">
Purchase Orders that are generated through recurring.
</p>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="recurring_documents.png"/>
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Recurring Document</h2>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="rec_doc.png">
</div>
</div>
<div class="oe_span6">
<p class="oe_mt32">Recurring Document is
automatically created and is linked with the purchase order
</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Recurring Type</h2>
</div>
<div class="oe_span6">
<p class="oe_mt32">
Recurring Type is automatically
created
</p>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="rec_type.png"/>
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Scheduled Actions</h2>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="cron_job.png">
</div>
</div>
<div class="oe_span6">
<p class="oe_mt32">Cron job is automatically
created</p>
</div>
</div>
</section>
Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@@ -0,0 +1,3 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from . import test_puchase_recurring
@@ -0,0 +1,21 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from flectra.tests.common import TransactionCase
class PurchaseRecurringTransactionCase(TransactionCase):
def setUp(self):
super(PurchaseRecurringTransactionCase, self).setUp()
self.purchase_order = self.env.ref(
"purchase.purchase_order_2")
def create_purchase_recurring(self):
recurring_id = self.env['recurring'].create({
'name': 'PO00002',
'exec_init': 5,
})
recurring_id.btn_recurring()
def test_01_recurring(self):
self.create_purchase_recurring()
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="view_purchase_order_form_inherit" model="ir.ui.view">
<field name="name">purchase.order.form.inherit</field>
<field name="model">purchase.order</field>
<field name="inherit_id" ref="purchase.purchase_order_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='partner_ref']" position="after">
<field name="recurring_id" invisible="1"/>
<field name="rec_source_id" readonly="1"/>
</xpath>
<xpath expr="//button[@name='button_confirm']" position="before">
<button name="%(recurring.action_recurring_wizard)d"
id="generate_recurring"
string="Generate Recurring" class="btn-primary"
type="action"
attrs="{'invisible': [('recurring_id', '!=', False)]}"
groups="purchase.group_purchase_manager"/>
</xpath>
<xpath expr="//sheet/div[@name='button_box']" position="inside">
<button class="oe_stat_button" type="object"
string="Recurring"
name="get_recurring"
icon="fa-tasks" attrs="{'invisible': [('recurring_id', '=', False)]}"
groups="purchase.group_purchase_manager"/>
<button class="oe_stat_button" type="object"
string="Document"
name="get_recurring_documents"
icon="fa-tasks" attrs="{'invisible': [('recurring_id', '=', False)]}"
groups="purchase.group_purchase_manager"/>
</xpath>
</field>
</record>
</flectra>
+3
View File
@@ -0,0 +1,3 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from . import models
+22
View File
@@ -0,0 +1,22 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
{
'name': 'Sale Order Recurring',
'version': '1.0',
'category': 'Extra Tools',
'summary': 'Create recurring of sale order',
'description': """
Sale Order Recurring allows to automatically create recurring of
any particular sale order
""",
'author': 'FlectraHQ',
'website': 'https://www.flectrahq.com/',
'depends': ['sale_management', 'recurring'],
'data': [
'views/sale_views.xml',
],
'demo': ['demo/sale_recurring_demo.xml'],
'license': 'LGPL-3',
'installable': True,
'auto_install': False,
}
@@ -0,0 +1,36 @@
<?xml version="1.0" ?>
<flectra noupdate="1">
<record id="sale_order_demo_recurring" model="sale.order">
<field name="name">SO001</field>
<field name="partner_id" ref="base.res_partner_2"/>
</record>
<record id="sale_order_line_demo" model="sale.order.line">
<field name="order_id"
ref="recurring_sale.sale_order_demo_recurring"/>
<field name="product_id" ref="product.product_product_13"/>
<field name="product_uom_qty">5</field>
<field name="price_unit">60</field>
</record>
<record id="recurring_document_sale0" model="recurring.document">
<field eval="1" name="active"/>
<field name="model" ref="sale.model_sale_order"/>
<field name="name">Sale Recurring Type</field>
</record>
<record id="recurring_document_fields_4" model="recurring.document.fields">
<field name="document_id" ref="recurring_document_sale0"/>
<field name="field" ref="sale.field_sale_order__name"/>
<field name="value">false</field>
</record>
<record id="recurring_sale1" model="recurring">
<field name="name">Sale Recurring Document</field>
<field name="exec_init">2</field>
<field name="interval_type">months</field>
<field name="date_init" eval="datetime.now()"/>
<field name="doc_source" ref='recurring_sale.sale_order_demo_recurring'/>
</record>
</flectra>
@@ -0,0 +1,61 @@
# Translation of Flectra Server.
# This file contains the translation of the following modules:
# * recurring_sale
#
msgid ""
msgstr ""
"Project-Id-Version: Flectra Server 2.0alpha\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-08 12:37+0000\n"
"PO-Revision-Date: 2021-03-08 12:37+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: recurring_sale
#: model:ir.model.fields,field_description:recurring_sale.field_sale_order__display_name
msgid "Display Name"
msgstr ""
#. module: recurring_sale
#: model_terms:ir.ui.view,arch_db:recurring_sale.view_order_form_inherit
msgid "Document"
msgstr ""
#. module: recurring_sale
#: model_terms:ir.ui.view,arch_db:recurring_sale.view_order_form_inherit
msgid "Generate Recurring"
msgstr ""
#. module: recurring_sale
#: model:ir.model.fields,field_description:recurring_sale.field_sale_order__id
msgid "ID"
msgstr ""
#. module: recurring_sale
#: model:ir.model.fields,field_description:recurring_sale.field_sale_order____last_update
msgid "Last Modified on"
msgstr ""
#. module: recurring_sale
#: model_terms:ir.ui.view,arch_db:recurring_sale.view_order_form_inherit
msgid "Recurring"
msgstr ""
#. module: recurring_sale
#: model:ir.model.fields,field_description:recurring_sale.field_sale_order__recurring_id
msgid "Recurring Reference"
msgstr ""
#. module: recurring_sale
#: model:ir.model.fields,field_description:recurring_sale.field_sale_order__rec_source_id
msgid "Recurring Source"
msgstr ""
#. module: recurring_sale
#: model:ir.model,name:recurring_sale.model_sale_order
msgid "Sales Order"
msgstr ""
+3
View File
@@ -0,0 +1,3 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from . import sale
+25
View File
@@ -0,0 +1,25 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from flectra import api, models, fields
class SaleOrder(models.Model):
_inherit = "sale.order"
recurring_id = fields.Many2one('recurring', string='Recurring Reference')
rec_source_id = fields.Many2one('sale.order', string='Recurring Source')
def get_recurring(self):
result = self.env['recurring'].get_recurring('sale.order', self.id)
return result
def get_recurring_documents(self):
result = self.env['recurring'].get_recurring_documents(
'sale.order', 'sale.action_quotations', self.recurring_id)
return result
def action_cancel(self):
res = super(SaleOrder, self).action_cancel()
if self.recurring_id:
self.recurring_id.set_done()
return res
Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

@@ -0,0 +1,125 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Recurring Sale</h2>
<h3 class="oe_slogan">Create recurring sale order</h3>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Recurring Wizard</h2>
</div>
<div class="oe_span6">
<p class="oe_mt32">
A 'Generate Recurring' button is displayed on the sale
order.<br/>
Recurring Document, Recurring Type and Scheduled action of this
particular sale order is automatically created.<br/>
Number of documents - The number of times the document
should be recurred.<br/>
Interval Unit - The interval when the recurring should
occur.<br/>
Start Recurring - Activates the generated recurring.<br/>
Save - Creates the recurring but doesn't activates it.
</p>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="recurring_document_wizard1.png">
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Sale Order</h2>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="sale_order.png">
</div>
</div>
<div class="oe_span6">
<p class="oe_mt32">
Recurring - Shows the generated recurring.<br/>
Document - Links the sale order that are generated by the
recurring of that particular sale order.
</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">SO Recurring Documents</h2>
</div>
<div class="oe_span6">
<p class="oe_mt32">
Sale Orders that are generated through recurring.
</p>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="recurring_documents.png"/>
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Recurring Document</h2>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="rec_doc.png"/>
</div>
</div>
<div class="oe_span6">
<p class="oe_mt32">
Recurring Document is automatically created.
</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Recurring Type</h2>
</div>
<div class="oe_span6">
<p class="oe_mt32">Recurring Type is automatically
created</p>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="rec_type.png">
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<h2 class="oe_slogan">Scheduled Actions</h2>
</div>
<div class="oe_span6">
<div class="oe_demo oe_picture oe_screenshot">
<img src="cron_job.png">
</div>
</div>
<div class="oe_span6">
<p class="oe_mt32">Cron job is automatically
created</p>
</div>
</div>
</section>
Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

+3
View File
@@ -0,0 +1,3 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from . import test_sale_recurring
@@ -0,0 +1,20 @@
# Part of Flectra. See LICENSE file for full copyright and licensing details.
from flectra.tests.common import TransactionCase
class RecurringTransactionCase(TransactionCase):
def setUp(self):
super(RecurringTransactionCase, self).setUp()
self.sale_order = self.env.ref("sale.sale_order_2")
def create_sale_recurring(self):
recurring_id = self.env['recurring'].create({
'name': 'SO0002',
'exec_init': 5,
})
recurring_id.btn_recurring()
def test_01_recurring(self):
self.create_sale_recurring()
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="view_order_form_inherit" model="ir.ui.view">
<field name="name">sale.order.form.inherit</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='payment_term_id']" position="after">
<field name="recurring_id" invisible="1"/>
<field name="rec_source_id" readonly="1"/>
</xpath>
<xpath expr="//button[@name='action_cancel']" position="before">
<button name="%(recurring.action_recurring_wizard)d"
id="generate_recurring"
string="Generate Recurring" class="btn-primary"
type="action"
attrs="{'invisible': [('recurring_id', '!=', False)]}"
groups="sales_team.group_sale_manager"/>
</xpath>
<xpath expr="//sheet/div[@name='button_box']" position="inside">
<button class="oe_stat_button" type="object"
string="Recurring" name="get_recurring"
icon="fa-tasks" attrs="{'invisible': [('recurring_id', '=', False)]}"
groups="sales_team.group_sale_manager"/>
<button class="oe_stat_button" type="object"
string="Document" name="get_recurring_documents"
icon="fa-tasks" attrs="{'invisible': [('recurring_id', '=', False)]}"
groups="sales_team.group_sale_manager"/>
</xpath>
</field>
</record>
</flectra>