diff --git a/contract/__manifest__.py b/contract/__manifest__.py index ce97ace1..74af9b40 100644 --- a/contract/__manifest__.py +++ b/contract/__manifest__.py @@ -9,7 +9,7 @@ { 'name': 'Recurring - Contracts Management', - 'version': '12.0.3.0.1', + 'version': '12.0.4.0.0', 'category': 'Contract Management', 'license': 'AGPL-3', 'author': "OpenERP SA, " @@ -18,10 +18,9 @@ "ACSONE SA/NV, " "Odoo Community Association (OCA)", 'website': 'https://github.com/oca/contract', - 'depends': ['base', 'account', 'analytic', 'product'], + 'depends': ['base', 'account', 'product'], "external_dependencies": {"python": ["dateutil"]}, 'data': [ - 'wizards/contract_line_wizard.xml', 'security/ir.model.access.csv', 'security/contract_security.xml', 'report/report_contract.xml', @@ -29,11 +28,12 @@ 'data/contract_cron.xml', 'data/contract_renew_cron.xml', 'data/mail_template.xml', + 'wizards/contract_line_wizard.xml', 'views/abstract_contract_line.xml', 'views/contract.xml', - 'views/contract_template_line.xml', - 'views/contract_template.xml', 'views/contract_line.xml', + 'views/contract_template.xml', + 'views/contract_template_line.xml', 'views/res_partner_view.xml', ], 'installable': True, diff --git a/contract/data/contract_cron.xml b/contract/data/contract_cron.xml index c864374d..754efa29 100644 --- a/contract/data/contract_cron.xml +++ b/contract/data/contract_cron.xml @@ -1,9 +1,9 @@ - + Generate Recurring Invoices from Contracts - + code model.cron_recurring_create_invoice() diff --git a/contract/data/contract_renew_cron.xml b/contract/data/contract_renew_cron.xml index dfc83d91..3365fd21 100644 --- a/contract/data/contract_renew_cron.xml +++ b/contract/data/contract_renew_cron.xml @@ -3,7 +3,7 @@ Renew Contract lines - + code model.cron_renew_contract_line() diff --git a/contract/data/mail_template.xml b/contract/data/mail_template.xml index 9d3728b0..78368c9a 100644 --- a/contract/data/mail_template.xml +++ b/contract/data/mail_template.xml @@ -6,7 +6,7 @@ ${(object.user_id.email and '%s <%s>' % (object.user_id.name, object.user_id.email) or '')|safe} ${object.company_id.name} Contract (Ref ${object.name or 'n/a'}) ${object.partner_id.id} - + Contract diff --git a/contract/migrations/12.0.4.0.0/post-migration.py b/contract/migrations/12.0.4.0.0/post-migration.py new file mode 100644 index 00000000..2c808205 --- /dev/null +++ b/contract/migrations/12.0.4.0.0/post-migration.py @@ -0,0 +1,145 @@ +# Copyright 2019 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging + +from openupgradelib import openupgrade + +_logger = logging.getLogger(__name__) + + +def migrate(cr, version): + cr.execute( + """ + INSERT INTO contract_contract ( + id, + name, + partner_id, + pricelist_id, + contract_type, + journal_id, + company_id, + analytic_account_id, + active, + code, + group_id, + contract_template_id, + recurring_invoices, + user_id, + recurring_next_date, + date_end, + payment_term_id, + fiscal_position_id, + invoice_partner_id, + message_main_attachment_id, + create_uid, + create_date, + write_uid, + write_date + ) + SELECT id, + name, + partner_id, + pricelist_id, + contract_type, + journal_id, + company_id, + id, + active, + code, + group_id, + contract_template_id, + recurring_invoices, + user_id, + recurring_next_date, + date_end, + payment_term_id, + fiscal_position_id, + invoice_partner_id, + message_main_attachment_id, + create_uid, + create_date, + write_uid, + write_date + FROM account_analytic_account + WHERE recurring_invoices = TRUE + """ + ) + cr.execute( + """ + INSERT INTO contract_line ( + id, + product_id, + name, + quantity, + uom_id, + automatic_price, + specific_price, + discount, + recurring_rule_type, + recurring_invoicing_type, + recurring_interval, + sequence, + contract_id, + date_start, + date_end, + recurring_next_date, + last_date_invoiced, + termination_notice_date, + successor_contract_line_id, + predecessor_contract_line_id, + manual_renew_needed, + active, + create_uid, + create_date, + write_uid, + write_date + ) + SELECT id, + product_id, + name, + quantity, + uom_id, + automatic_price, + specific_price, + discount, + recurring_rule_type, + recurring_invoicing_type, + recurring_interval, + sequence, + contract_id, + date_start, + date_end, + recurring_next_date, + last_date_invoiced, + termination_notice_date, + successor_contract_line_id, + predecessor_contract_line_id, + manual_renew_needed, + active, + create_uid, + create_date, + write_uid, + write_date + FROM account_analytic_invoice_line + """ + ) + openupgrade.rename_models(cr, [('account.analytic.invoice.line', + 'contract.line')]) + cr.execute( + """ + DROP TABLE account_analytic_invoice_line + """ + ) + cr.execute( + """ + UPDATE account_invoice_line + SET contract_line_id = contract_line_id_tmp + """ + ) + cr.execute( + """ + ALTER TABLE account_invoice_line + DROP COLUMN contract_line_id_tmp + """ + ) diff --git a/contract/migrations/12.0.4.0.0/pre-migration.py b/contract/migrations/12.0.4.0.0/pre-migration.py new file mode 100644 index 00000000..fae43695 --- /dev/null +++ b/contract/migrations/12.0.4.0.0/pre-migration.py @@ -0,0 +1,72 @@ +# Copyright 2019 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging + +from openupgradelib import openupgrade + +_logger = logging.getLogger(__name__) + + +def migrate(cr, version): + models_to_rename = [ + # Contract Line Wizard + ('account.analytic.invoice.line.wizard', 'contract.line.wizard'), + # Abstract Contract + ('account.abstract.analytic.contract', 'contract.abstract.contract'), + # Abstract Contract Line + ('account.abstract.analytic.contract.line', + 'contract.abstract.contract.line'), + # Contract Line + ('account.analytic.invoice.line', 'contract.line'), + # Contract Template + ('account.analytic.contract', 'contract.template'), + # Contract Template Line + ('account.analytic.contract.line', 'contract.template.line'), + ] + tables_to_rename = [ + # Contract Line Wizard + ('account_analytic_invoice_line_wizard', 'contract_line_wizard'), + # Contract Template + ('account_analytic_contract', 'contract_template'), + # Contract Template Line + ('account_analytic_contract_line', 'contract_template_line'), + ] + xmlids_to_rename = [ + ('contract.account_analytic_cron_for_invoice', + 'contract.contract_cron_for_invoice'), + ('contract.account_analytic_contract_manager', + 'contract.contract_template_manager'), + ('contract.account_analytic_contract_user', + 'contract.contract_template_user'), + ('contract.account_analytic_invoice_line_manager', + 'contract.contract_line_manager'), + ('contract.account_analytic_invoice_line_user', + 'contract.contract_line_user'), + ('contract.account_analytic_contract_line_manager', + 'contract.contract_template_line_manager'), + ('contract.account_analytic_contract_line_user', + 'contract.contract_template_line_user'), + ] + openupgrade.rename_models(cr, models_to_rename) + openupgrade.rename_tables(cr, tables_to_rename) + openupgrade.rename_xmlids(cr, xmlids_to_rename) + # A temporary column is needed to avoid breaking the foreign key constraint + # The temporary column is dropped in the post-migration script + cr.execute( + """ + ALTER TABLE account_invoice_line + ADD COLUMN contract_line_id_tmp INTEGER + """ + ) + cr.execute( + """ + UPDATE account_invoice_line + SET contract_line_id_tmp = contract_line_id + """ + ) + cr.execute( + """ + UPDATE account_invoice_line SET contract_line_id = NULL + """ + ) diff --git a/contract/models/abstract_contract.py b/contract/models/abstract_contract.py index 93d7098e..75dd9030 100644 --- a/contract/models/abstract_contract.py +++ b/contract/models/abstract_contract.py @@ -9,8 +9,8 @@ from odoo import api, models, fields -class AbstractAccountAnalyticContract(models.AbstractModel): - _name = 'account.abstract.analytic.contract' +class ContractAbstractContract(models.AbstractModel): + _name = 'contract.abstract.contract' _description = 'Abstract Recurring Contract' # These fields will not be synced to the contract @@ -50,7 +50,7 @@ class AbstractAccountAnalyticContract(models.AbstractModel): @api.onchange('contract_type') def _onchange_contract_type(self): if self.contract_type == 'purchase': - self.recurring_invoice_line_ids.filtered('automatic_price').update( + self.contract_line_ids.filtered('automatic_price').update( {'automatic_price': False} ) self.journal_id = self.env['account.journal'].search( diff --git a/contract/models/abstract_contract_line.py b/contract/models/abstract_contract_line.py index a338cb7d..10da1a7e 100644 --- a/contract/models/abstract_contract_line.py +++ b/contract/models/abstract_contract_line.py @@ -12,8 +12,8 @@ from odoo.exceptions import ValidationError from odoo.tools.translate import _ -class AccountAbstractAnalyticContractLine(models.AbstractModel): - _name = 'account.abstract.analytic.contract.line' +class ContractAbstractContractLine(models.AbstractModel): + _name = 'contract.abstract.contract.line' _description = 'Abstract Recurring Contract Line' product_id = fields.Many2one( @@ -110,7 +110,7 @@ class AccountAbstractAnalyticContractLine(models.AbstractModel): ) contract_id = fields.Many2one( string='Contract', - comodel_name='account.abstract.analytic.contract', + comodel_name='contract.abstract.contract', required=True, ondelete='cascade', oldname='analytic_account_id', diff --git a/contract/models/account_invoice.py b/contract/models/account_invoice.py index 7d9f4ceb..fa2208f7 100644 --- a/contract/models/account_invoice.py +++ b/contract/models/account_invoice.py @@ -9,5 +9,5 @@ class AccountInvoice(models.Model): # We keep this field for migration purpose old_contract_id = fields.Many2one( - 'account.analytic.account', oldname="contract_id" + 'contract.contract', oldname="contract_id" ) diff --git a/contract/models/account_invoice_line.py b/contract/models/account_invoice_line.py index 30e1829c..31454e41 100644 --- a/contract/models/account_invoice_line.py +++ b/contract/models/account_invoice_line.py @@ -8,5 +8,5 @@ class AccountInvoiceLine(models.Model): _inherit = 'account.invoice.line' contract_line_id = fields.Many2one( - 'account.analytic.invoice.line', string='Contract Line', index=True + 'contract.line', string='Contract Line', index=True ) diff --git a/contract/models/contract.py b/contract/models/contract.py index ae20506e..1767b156 100644 --- a/contract/models/contract.py +++ b/contract/models/contract.py @@ -11,21 +11,39 @@ from odoo.exceptions import ValidationError from odoo.tools.translate import _ -class AccountAnalyticAccount(models.Model): - _name = 'account.analytic.account' - _inherit = [ - 'account.analytic.account', - 'account.abstract.analytic.contract', - ] +class ContractContract(models.Model): + _name = 'contract.contract' + _inherit = ['mail.thread', 'contract.abstract.contract'] + active = fields.Boolean( + default=True, + ) + code = fields.Char( + string="Reference", + ) + group_id = fields.Many2one( + string="Group", + comodel_name='account.analytic.account', + ondelete='restrict', + ) + analytic_account_id = fields.Many2one( + string="Analytic account", + comodel_name='account.analytic.account', + ) + currency_id = fields.Many2one( + related="company_id.currency_id", + string="Currency", + readonly=True, + ) contract_template_id = fields.Many2one( - string='Contract Template', comodel_name='account.analytic.contract' + string='Contract Template', comodel_name='contract.template' ) - recurring_invoice_line_ids = fields.One2many( - string='Invoice Lines', - comodel_name='account.analytic.invoice.line', + contract_line_ids = fields.One2many( + string='Contract lines', + comodel_name='contract.line', inverse_name='contract_id', copy=True, + oldnae='contract_line_ids', ) recurring_invoices = fields.Boolean( string='Generate recurring invoices automatically' @@ -84,7 +102,7 @@ class AccountAnalyticAccount(models.Model): ( 'contract_line_id', 'in', - self.recurring_invoice_line_ids.ids, + self.contract_line_ids.ids, ) ] ) @@ -127,31 +145,31 @@ class AccountAnalyticAccount(models.Model): action['views'] = [(tree_view.id, 'tree'), (form_view.id, 'form')] return action - @api.depends('recurring_invoice_line_ids.date_end') + @api.depends('contract_line_ids.date_end') def _compute_date_end(self): for contract in self: contract.date_end = False - date_end = contract.recurring_invoice_line_ids.mapped('date_end') + date_end = contract.contract_line_ids.mapped('date_end') if date_end and all(date_end): contract.date_end = max(date_end) @api.depends( - 'recurring_invoice_line_ids.recurring_next_date', - 'recurring_invoice_line_ids.is_canceled', + 'contract_line_ids.recurring_next_date', + 'contract_line_ids.is_canceled', ) def _compute_recurring_next_date(self): for contract in self: - recurring_next_date = contract.recurring_invoice_line_ids.filtered( + recurring_next_date = contract.contract_line_ids.filtered( lambda l: l.recurring_next_date and not l.is_canceled ).mapped('recurring_next_date') if recurring_next_date: contract.recurring_next_date = min(recurring_next_date) - @api.depends('recurring_invoice_line_ids.create_invoice_visibility') + @api.depends('contract_line_ids.create_invoice_visibility') def _compute_create_invoice_visibility(self): for contract in self: contract.create_invoice_visibility = any( - contract.recurring_invoice_line_ids.mapped( + contract.contract_line_ids.mapped( 'create_invoice_visibility' ) ) @@ -160,7 +178,7 @@ class AccountAnalyticAccount(models.Model): def _onchange_contract_template_id(self): """Update the contract fields with that of the template. - Take special consideration with the `recurring_invoice_line_ids`, + Take special consideration with the `contract_line_ids`, which must be created using the data from the contract lines. Cascade deletion ensures that any errant lines that are created are also deleted. @@ -169,9 +187,9 @@ class AccountAnalyticAccount(models.Model): if not contract_template_id: return for field_name, field in contract_template_id._fields.items(): - if field.name == 'recurring_invoice_line_ids': + if field.name == 'contract_line_ids': lines = self._convert_contract_lines(contract_template_id) - self.recurring_invoice_line_ids += lines + self.contract_line_ids += lines elif not any( ( field.compute, @@ -219,9 +237,9 @@ class AccountAnalyticAccount(models.Model): @api.multi def _convert_contract_lines(self, contract): self.ensure_one() - new_lines = self.env['account.analytic.invoice.line'] - contract_line_model = self.env['account.analytic.invoice.line'] - for contract_line in contract.recurring_invoice_line_ids: + new_lines = self.env['contract.line'] + contract_line_model = self.env['contract.line'] + for contract_line in contract.contract_line_ids: vals = contract_line._convert_to_write(contract_line.read()[0]) # Remove template link field vals.pop('contract_template_id', False) @@ -282,7 +300,7 @@ class AccountAnalyticAccount(models.Model): template = self.env.ref('contract.email_contract_template', False) compose_form = self.env.ref('mail.email_compose_message_wizard_form') ctx = dict( - default_model='account.analytic.account', + default_model='contract.contract', default_res_id=self.id, default_use_template=bool(template), default_template_id=template and template.id or False, @@ -368,9 +386,9 @@ class AccountAnalyticAccount(models.Model): def _get_contracts_to_invoice_domain(self, date_ref=None): """ This method builds the domain to use to find all - contracts (account.analytic.account) to invoice. + contracts (contract.contract) to invoice. :param date_ref: optional reference date to use instead of today - :return: list (domain) usable on account.analytic.account + :return: list (domain) usable on contract.contract """ domain = [] if not date_ref: @@ -389,10 +407,10 @@ class AccountAnalyticAccount(models.Model): This method fetches and returns the lines to invoice on the contract (self), based on the given date. :param date_ref: date used as reference date to find lines to invoice - :return: contract lines (account.analytic.invoice.line recordset) + :return: contract lines (contract.line recordset) """ self.ensure_one() - return self.recurring_invoice_line_ids.filtered( + return self.contract_line_ids.filtered( lambda l: not l.is_canceled and l.recurring_next_date and l.recurring_next_date <= date_ref diff --git a/contract/models/contract_line.py b/contract/models/contract_line.py index f2f833b3..3ae0600c 100644 --- a/contract/models/contract_line.py +++ b/contract/models/contract_line.py @@ -11,12 +11,15 @@ from odoo.exceptions import ValidationError from .contract_line_constraints import get_allowed -class AccountAnalyticInvoiceLine(models.Model): - _name = 'account.analytic.invoice.line' - _inherit = 'account.abstract.analytic.contract.line' +class ContractLine(models.Model): + _name = 'contract.line' + _inherit = 'contract.abstract.contract.line' + sequence = fields.Integer( + string="Sequence", + ) contract_id = fields.Many2one( - comodel_name='account.analytic.account', + comodel_name='contract.contract', string='Contract', required=True, index=True, @@ -43,7 +46,7 @@ class AccountAnalyticInvoiceLine(models.Model): compute='_compute_create_invoice_visibility' ) successor_contract_line_id = fields.Many2one( - comodel_name='account.analytic.invoice.line', + comodel_name='contract.line', string="Successor Contract Line", required=False, readonly=True, @@ -53,7 +56,7 @@ class AccountAnalyticInvoiceLine(models.Model): "contract line created.", ) predecessor_contract_line_id = fields.Many2one( - comodel_name='account.analytic.invoice.line', + comodel_name='contract.line', string="Predecessor Contract Line", required=False, readonly=True, @@ -511,12 +514,11 @@ class AccountAnalyticInvoiceLine(models.Model): invoice_line._onchange_product_id() invoice_line_vals = invoice_line._convert_to_write(invoice_line._cache) # Insert markers - contract = self.contract_id name = self._insert_markers(dates[0], dates[1]) invoice_line_vals.update( { 'name': name, - 'account_analytic_id': contract.id, + 'account_analytic_id': self.contract_id.analytic_account_id.id, 'price_unit': self.price_unit, } ) @@ -737,7 +739,7 @@ class AccountAnalyticInvoiceLine(models.Model): successor_contract_line :return: successor_contract_line """ - contract_line = self.env['account.analytic.invoice.line'] + contract_line = self.env['contract.line'] for rec in self: if not rec.is_plan_successor_allowed: raise ValidationError( @@ -804,7 +806,7 @@ class AccountAnalyticInvoiceLine(models.Model): raise ValidationError( _('Stop/Plan successor not allowed for this line') ) - contract_line = self.env['account.analytic.invoice.line'] + contract_line = self.env['contract.line'] for rec in self: if rec.date_start >= date_start: if rec.date_start < date_end: @@ -935,7 +937,7 @@ class AccountAnalyticInvoiceLine(models.Model): return { 'type': 'ir.actions.act_window', 'name': 'Un-Cancel Contract Line', - 'res_model': 'account.analytic.invoice.line.wizard', + 'res_model': 'contract.line.wizard', 'view_type': 'form', 'view_mode': 'form', 'views': [(view_id, 'form')], @@ -957,7 +959,7 @@ class AccountAnalyticInvoiceLine(models.Model): return { 'type': 'ir.actions.act_window', 'name': 'Plan contract line successor', - 'res_model': 'account.analytic.invoice.line.wizard', + 'res_model': 'contract.line.wizard', 'view_type': 'form', 'view_mode': 'form', 'views': [(view_id, 'form')], @@ -979,7 +981,7 @@ class AccountAnalyticInvoiceLine(models.Model): return { 'type': 'ir.actions.act_window', 'name': 'Resiliate contract line', - 'res_model': 'account.analytic.invoice.line.wizard', + 'res_model': 'contract.line.wizard', 'view_type': 'form', 'view_mode': 'form', 'views': [(view_id, 'form')], @@ -1001,7 +1003,7 @@ class AccountAnalyticInvoiceLine(models.Model): return { 'type': 'ir.actions.act_window', 'name': 'Suspend contract line', - 'res_model': 'account.analytic.invoice.line.wizard', + 'res_model': 'contract.line.wizard', 'view_type': 'form', 'view_mode': 'form', 'views': [(view_id, 'form')], @@ -1020,7 +1022,7 @@ class AccountAnalyticInvoiceLine(models.Model): @api.multi def renew(self): - res = self.env['account.analytic.invoice.line'] + res = self.env['contract.line'] for rec in self: is_auto_renew = rec.is_auto_renew rec.stop(rec.date_end, post_message=False) @@ -1067,18 +1069,18 @@ class AccountAnalyticInvoiceLine(models.Model): default_contract_type = self.env.context.get('default_contract_type') if view_type == 'tree' and default_contract_type == 'purchase': view_id = self.env.ref( - 'contract.account_analytic_invoice_line_purchase_view_tree' + 'contract.contract_line_supplier_tree_view' ).id if view_type == 'form': if default_contract_type == 'purchase': view_id = self.env.ref( - 'contract.account_analytic_invoice_line_purchase_view_form' + 'contract.contract_line_supplier_form_view' ).id elif default_contract_type == 'sale': view_id = self.env.ref( - 'contract.account_analytic_invoice_line_sale_view_form' + 'contract.contract_line_customer_form_view' ).id - return super(AccountAnalyticInvoiceLine, self).fields_view_get( + return super(ContractLine, self).fields_view_get( view_id, view_type, toolbar, submenu ) @@ -1089,7 +1091,7 @@ class AccountAnalyticInvoiceLine(models.Model): raise ValidationError( _("Contract line must be canceled before delete") ) - return super(AccountAnalyticInvoiceLine, self).unlink() + return super(ContractLine, self).unlink() @api.multi def _get_quantity_to_invoice( diff --git a/contract/models/contract_template.py b/contract/models/contract_template.py index 5bf8af08..68fd5bed 100644 --- a/contract/models/contract_template.py +++ b/contract/models/contract_template.py @@ -9,14 +9,15 @@ from odoo import fields, models -class AccountAnalyticContract(models.Model): - _name = 'account.analytic.contract' - _inherit = 'account.abstract.analytic.contract' - _description = "Account Analytic Contract" +class ContractTemplate(models.Model): + _name = 'contract.template' + _inherit = 'contract.abstract.contract' + _description = "Contract Template" - recurring_invoice_line_ids = fields.One2many( - comodel_name='account.analytic.contract.line', + contract_line_ids = fields.One2many( + comodel_name='contract.template.line', inverse_name='contract_id', copy=True, - string='Invoice Lines', + string='Contract template lines', + oldname='contract_line_ids', ) diff --git a/contract/models/contract_template_line.py b/contract/models/contract_template_line.py index 208187e3..25f0cd52 100644 --- a/contract/models/contract_template_line.py +++ b/contract/models/contract_template_line.py @@ -9,15 +9,15 @@ from odoo import fields, models -class AccountAnalyticContractLine(models.Model): - _name = 'account.analytic.contract.line' - _inherit = 'account.abstract.analytic.contract.line' - _description = 'Contract Lines' +class ContractTemplateLine(models.Model): + _name = 'contract.template.line' + _inherit = 'contract.abstract.contract.line' + _description = "Contract Template Line" _order = "sequence,id" contract_id = fields.Many2one( string='Contract', - comodel_name='account.analytic.contract', + comodel_name='contract.template', required=True, ondelete='cascade', oldname='analytic_account_id', diff --git a/contract/models/res_partner.py b/contract/models/res_partner.py index c18e00e9..7fb6038a 100644 --- a/contract/models/res_partner.py +++ b/contract/models/res_partner.py @@ -15,7 +15,7 @@ class ResPartner(models.Model): ) def _compute_contract_count(self): - contract_model = self.env['account.analytic.account'] + contract_model = self.env['contract.contract'] fetch_data = contract_model.read_group( [ ('recurring_invoices', '=', True), @@ -69,9 +69,9 @@ class ResPartner(models.Model): def _get_act_window_contract_xml(self, contract_type): if contract_type == 'purchase': return self.env['ir.actions.act_window'].for_xml_id( - 'contract', 'action_account_analytic_purchase_overdue_all' + 'contract', 'action_supplier_contract' ) else: return self.env['ir.actions.act_window'].for_xml_id( - 'contract', 'action_account_analytic_sale_overdue_all' + 'contract', 'action_customer_contract' ) diff --git a/contract/report/contract_views.xml b/contract/report/contract_views.xml index bcbb1459..81030664 100644 --- a/contract/report/contract_views.xml +++ b/contract/report/contract_views.xml @@ -3,7 +3,7 @@ - diff --git a/contract/security/contract_security.xml b/contract/security/contract_security.xml index 3884e6ef..08b0f9b9 100644 --- a/contract/security/contract_security.xml +++ b/contract/security/contract_security.xml @@ -2,7 +2,7 @@ Contract template multi-company - + ['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])] diff --git a/contract/security/ir.model.access.csv b/contract/security/ir.model.access.csv index 549a2d7a..4b3e42de 100644 --- a/contract/security/ir.model.access.csv +++ b/contract/security/ir.model.access.csv @@ -1,7 +1,9 @@ "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" -"account_analytic_contract_manager","Recurring manager","model_account_analytic_contract","account.group_account_manager",1,1,1,1 -"account_analytic_contract_user","Recurring user","model_account_analytic_contract","account.group_account_invoice",1,0,0,0 -"account_analytic_invoice_line_manager","Recurring manager","model_account_analytic_invoice_line","account.group_account_manager",1,1,1,1 -"account_analytic_invoice_line_user","Recurring user","model_account_analytic_invoice_line","account.group_account_invoice",1,0,0,0 -"account_analytic_contract_line_manager","Recurring manager","model_account_analytic_contract_line","account.group_account_manager",1,1,1,1 -"account_analytic_contract_line_user","Recurring user","model_account_analytic_contract_line","account.group_account_invoice",1,0,0,0 +"contract_template_manager","Recurring manager","model_contract_template","account.group_account_manager",1,1,1,1 +"contract_template_user","Recurring user","model_contract_template","account.group_account_invoice",1,0,0,0 +"contract_manager","Recurring manager","model_contract_contract","account.group_account_manager",1,1,1,1 +"contract_user","Recurring user","model_contract_contract","account.group_account_invoice",1,0,0,0 +"contract_line_manager","Recurring manager","model_contract_line","account.group_account_manager",1,1,1,1 +"contract_line_user","Recurring user","model_contract_line","account.group_account_invoice",1,0,0,0 +"contract_template_line_manager","Recurring manager","model_contract_template_line","account.group_account_manager",1,1,1,1 +"contract_template_line_user","Recurring user","model_contract_template_line","account.group_account_invoice",1,0,0,0 diff --git a/contract/tests/test_contract.py b/contract/tests/test_contract.py index 566cbc59..95604f54 100644 --- a/contract/tests/test_contract.py +++ b/contract/tests/test_contract.py @@ -37,9 +37,9 @@ class TestContractBase(common.SavepointCase): } cls.template_vals = { 'name': 'Test Contract Template', - 'recurring_invoice_line_ids': [(0, 0, cls.line_template_vals)], + 'contract_line_ids': [(0, 0, cls.line_template_vals)], } - cls.template = cls.env['account.analytic.contract'].create( + cls.template = cls.env['contract.template'].create( cls.template_vals ) # For being sure of the applied price @@ -51,7 +51,7 @@ class TestContractBase(common.SavepointCase): 'base': 'list_price', } ) - cls.contract = cls.env['account.analytic.account'].create( + cls.contract = cls.env['contract.contract'].create( { 'name': 'Test Contract', 'partner_id': cls.partner.id, @@ -59,14 +59,14 @@ class TestContractBase(common.SavepointCase): 'recurring_invoices': True, } ) - cls.contract2 = cls.env['account.analytic.account'].create( + cls.contract2 = cls.env['contract.contract'].create( { 'name': 'Test Contract 2', 'partner_id': cls.partner.id, 'pricelist_id': cls.partner.property_product_pricelist.id, 'recurring_invoices': True, 'contract_type': 'purchase', - 'recurring_invoice_line_ids': [ + 'contract_line_ids': [ ( 0, 0, @@ -100,7 +100,7 @@ class TestContractBase(common.SavepointCase): 'recurring_next_date': '2018-01-15', 'is_auto_renew': False, } - cls.acct_line = cls.env['account.analytic.invoice.line'].create( + cls.acct_line = cls.env['contract.line'].create( cls.line_vals ) cls.acct_line.product_id.is_auto_renew = True @@ -115,7 +115,7 @@ class TestContract(TestContractBase): del vals['date_start'] vals['contract_id'] = self.template.id vals.update(overrides) - return self.env['account.analytic.contract.line'].create(vals) + return self.env['contract.template.line'].create(vals) def test_check_discount(self): with self.assertRaises(ValidationError): @@ -360,7 +360,7 @@ class TestContract(TestContractBase): ) def test_onchange_product_id(self): - line = self.env['account.analytic.invoice.line'].new() + line = self.env['contract.line'].new() res = line._onchange_product_id() self.assertFalse(res['domain']['uom_id']) @@ -400,7 +400,7 @@ class TestContract(TestContractBase): self.contract.contract_template_id = self.template self.contract._onchange_contract_template_id() res = { - 'recurring_invoice_line_ids': [ + 'contract_line_ids': [ ( 0, 0, @@ -427,15 +427,15 @@ class TestContract(TestContractBase): self.contract.contract_template_id = self.template self.assertFalse( - self.contract.recurring_invoice_line_ids, + self.contract.contract_line_ids, 'Recurring lines were not removed.', ) self.contract.contract_template_id = self.template self.contract._onchange_contract_template_id() - self.assertEqual(len(self.contract.recurring_invoice_line_ids), 1) + self.assertEqual(len(self.contract.contract_line_ids), 1) for key, value in self.line_template_vals.items(): - test_value = self.contract.recurring_invoice_line_ids[0][key] + test_value = self.contract.contract_line_ids[0][key] try: test_value = test_value.id except AttributeError: @@ -456,7 +456,7 @@ class TestContract(TestContractBase): self.contract._onchange_contract_type() self.assertFalse( any( - self.contract.recurring_invoice_line_ids.mapped( + self.contract.contract_line_ids.mapped( 'automatic_price' ) ) @@ -464,7 +464,7 @@ class TestContract(TestContractBase): def test_contract_onchange_product_id_domain_blank(self): """It should return a blank UoM domain when no product.""" - line = self.env['account.analytic.contract.line'].new() + line = self.env['contract.template.line'].new() res = line._onchange_product_id() self.assertFalse(res['domain']['uom_id']) @@ -533,8 +533,8 @@ class TestContract(TestContractBase): 'name': 'Customer Contracts', 'type': 'ir.actions.act_window', 'view_type': 'form', - 'res_model': 'account.analytic.account', - 'xml_id': 'contract.action_account_analytic_sale_overdue_all', + 'res_model': 'contract.contract', + 'xml_id': 'contract.action_customer_contract', }, show_contract, 'There was an error and the view couldn\'t be opened.', @@ -605,7 +605,7 @@ class TestContract(TestContractBase): (to_date('2018-01-05'), 'post-paid', 'yearly', 1), ), ] - contract_line_env = self.env['account.analytic.invoice.line'] + contract_line_env = self.env['contract.line'] for recurring_next_date, combination in combinations: self.assertEqual( recurring_next_date, @@ -621,7 +621,7 @@ class TestContract(TestContractBase): self.assertEqual( self.contract.recurring_next_date, min( - self.contract.recurring_invoice_line_ids.mapped( + self.contract.contract_line_ids.mapped( 'recurring_next_date' ) ), @@ -701,7 +701,7 @@ class TestContract(TestContractBase): 'is_auto_renew': True, } ) - wizard = self.env['account.analytic.invoice.line.wizard'].create( + wizard = self.env['contract.line.wizard'].create( { 'date_end': self.today + relativedelta(months=3), 'contract_line_id': self.acct_line.id, @@ -754,7 +754,7 @@ class TestContract(TestContractBase): suspension_start, suspension_end, True ) self.assertEqual(self.acct_line.date_end, end_date) - new_line = self.env['account.analytic.invoice.line'].search( + new_line = self.env['contract.line'].search( [('predecessor_contract_line_id', '=', self.acct_line.id)] ) self.assertFalse(new_line) @@ -785,7 +785,7 @@ class TestContract(TestContractBase): self.assertEqual( self.acct_line.date_end, suspension_start - relativedelta(days=1) ) - new_line = self.env['account.analytic.invoice.line'].search( + new_line = self.env['contract.line'].search( [('predecessor_contract_line_id', '=', self.acct_line.id)] ) self.assertTrue(new_line) @@ -826,7 +826,7 @@ class TestContract(TestContractBase): self.assertEqual( self.acct_line.date_end, suspension_start - relativedelta(days=1) ) - new_line = self.env['account.analytic.invoice.line'].search( + new_line = self.env['contract.line'].search( [('predecessor_contract_line_id', '=', self.acct_line.id)] ) self.assertTrue(new_line) @@ -868,7 +868,7 @@ class TestContract(TestContractBase): self.assertEqual( self.acct_line.date_end, suspension_start - relativedelta(days=1) ) - new_line = self.env['account.analytic.invoice.line'].search( + new_line = self.env['contract.line'].search( [('predecessor_contract_line_id', '=', self.acct_line.id)] ) self.assertTrue(new_line) @@ -906,7 +906,7 @@ class TestContract(TestContractBase): self.acct_line.date_end, end_date + (suspension_end - start_date) + timedelta(days=1), ) - new_line = self.env['account.analytic.invoice.line'].search( + new_line = self.env['contract.line'].search( [('predecessor_contract_line_id', '=', self.acct_line.id)] ) self.assertFalse(new_line) @@ -939,7 +939,7 @@ class TestContract(TestContractBase): self.acct_line.date_end, end_date + (suspension_end - start_date) + timedelta(days=1), ) - new_line = self.env['account.analytic.invoice.line'].search( + new_line = self.env['contract.line'].search( [('predecessor_contract_line_id', '=', self.acct_line.id)] ) self.assertFalse(new_line) @@ -970,7 +970,7 @@ class TestContract(TestContractBase): start_date + (suspension_end - start_date) + timedelta(days=1), ) self.assertFalse(self.acct_line.date_end) - new_line = self.env['account.analytic.invoice.line'].search( + new_line = self.env['contract.line'].search( [('predecessor_contract_line_id', '=', self.acct_line.id)] ) self.assertFalse(new_line) @@ -1005,7 +1005,7 @@ class TestContract(TestContractBase): self.acct_line.date_end, end_date + (suspension_end - suspension_start) + timedelta(days=1), ) - new_line = self.env['account.analytic.invoice.line'].search( + new_line = self.env['contract.line'].search( [('predecessor_contract_line_id', '=', self.acct_line.id)] ) self.assertFalse(new_line) @@ -1038,7 +1038,7 @@ class TestContract(TestContractBase): + timedelta(days=1), ) self.assertFalse(self.acct_line.date_end) - new_line = self.env['account.analytic.invoice.line'].search( + new_line = self.env['contract.line'].search( [('predecessor_contract_line_id', '=', self.acct_line.id)] ) self.assertFalse(new_line) @@ -1055,7 +1055,7 @@ class TestContract(TestContractBase): 'date_end': end_date, } ) - wizard = self.env['account.analytic.invoice.line.wizard'].create( + wizard = self.env['contract.line.wizard'].create( { 'date_start': suspension_start, 'date_end': suspension_end, @@ -1074,7 +1074,7 @@ class TestContract(TestContractBase): self.acct_line.date_end, end_date + (suspension_end - suspension_start) + timedelta(days=1), ) - new_line = self.env['account.analytic.invoice.line'].search( + new_line = self.env['contract.line'].search( [('predecessor_contract_line_id', '=', self.acct_line.id)] ) self.assertFalse(new_line) @@ -1093,7 +1093,7 @@ class TestContract(TestContractBase): self.today + relativedelta(months=7), True, ) - new_line = self.env['account.analytic.invoice.line'].search( + new_line = self.env['contract.line'].search( [('predecessor_contract_line_id', '=', self.acct_line.id)] ) self.assertFalse(self.acct_line.is_auto_renew) @@ -1120,7 +1120,7 @@ class TestContract(TestContractBase): self.today + relativedelta(months=7), True, ) - new_line = self.env['account.analytic.invoice.line'].search( + new_line = self.env['contract.line'].search( [('predecessor_contract_line_id', '=', self.acct_line.id)] ) with self.assertRaises(ValidationError): @@ -1137,7 +1137,7 @@ class TestContract(TestContractBase): 'is_auto_renew': False, } ) - wizard = self.env['account.analytic.invoice.line.wizard'].create( + wizard = self.env['contract.line.wizard'].create( { 'date_start': self.today + relativedelta(months=3), 'date_end': self.today + relativedelta(months=5), @@ -1146,7 +1146,7 @@ class TestContract(TestContractBase): } ) wizard.plan_successor() - new_line = self.env['account.analytic.invoice.line'].search( + new_line = self.env['contract.line'].search( [('predecessor_contract_line_id', '=', self.acct_line.id)] ) self.assertFalse(self.acct_line.is_auto_renew) @@ -1177,7 +1177,7 @@ class TestContract(TestContractBase): def test_uncancel_wizard(self): self.acct_line.cancel() self.assertTrue(self.acct_line.is_canceled) - wizard = self.env['account.analytic.invoice.line.wizard'].create( + wizard = self.env['contract.line.wizard'].create( { 'recurring_next_date': self.today, 'contract_line_id': self.acct_line.id, @@ -1204,7 +1204,7 @@ class TestContract(TestContractBase): self.assertEqual( self.acct_line.date_end, suspension_start - relativedelta(days=1) ) - new_line = self.env['account.analytic.invoice.line'].search( + new_line = self.env['contract.line'].search( [('predecessor_contract_line_id', '=', self.acct_line.id)] ) self.assertEqual(self.acct_line.successor_contract_line_id, new_line) @@ -1235,7 +1235,7 @@ class TestContract(TestContractBase): self.acct_line.stop_plan_successor( suspension_start, suspension_end, True ) - new_line = self.env['account.analytic.invoice.line'].search( + new_line = self.env['contract.line'].search( [('predecessor_contract_line_id', '=', self.acct_line.id)] ) new_line.cancel() @@ -1324,12 +1324,13 @@ class TestContract(TestContractBase): contracts = self.contract2 for i in range(10): contracts |= self.contract.copy() - self.env['account.analytic.account'].cron_recurring_create_invoice() + self.env['contract.contract'].cron_recurring_create_invoice() invoice_lines = self.env['account.invoice.line'].search( - [('account_analytic_id', 'in', contracts.ids)] + [('contract_line_id', 'in', + contracts.mapped('contract_line_ids').ids)] ) self.assertEqual( - len(contracts.mapped('recurring_invoice_line_ids')), + len(contracts.mapped('contract_line_ids')), len(invoice_lines), ) @@ -1535,7 +1536,7 @@ class TestContract(TestContractBase): self.acct_line.unlink() def test_contract_line_state(self): - lines = self.env['account.analytic.invoice.line'] + lines = self.env['contract.line'] # upcoming lines |= self.acct_line.copy( { @@ -1607,39 +1608,39 @@ class TestContract(TestContractBase): ] self.assertEqual(set(lines.mapped('state')), set(states)) for state in states: - lines = self.env['account.analytic.invoice.line'].search( + lines = self.env['contract.line'].search( [('state', '=', state)] ) self.assertEqual(len(set(lines.mapped('state'))), 1, state) self.assertEqual(lines.mapped('state')[0], state, state) for state in states: - lines = self.env['account.analytic.invoice.line'].search( + lines = self.env['contract.line'].search( [('state', '!=', state)] ) self.assertFalse(state in lines.mapped('state')) - lines = self.env['account.analytic.invoice.line'].search( + lines = self.env['contract.line'].search( [('state', 'in', states)] ) self.assertEqual(set(lines.mapped('state')), set(states)) - lines = self.env['account.analytic.invoice.line'].search( + lines = self.env['contract.line'].search( [('state', 'in', [])] ) self.assertFalse(lines.mapped('state')) with self.assertRaises(TypeError): - self.env['account.analytic.invoice.line'].search( + self.env['contract.line'].search( [('state', 'in', 'upcoming')] ) - lines = self.env['account.analytic.invoice.line'].search( + lines = self.env['contract.line'].search( [('state', 'not in', [])] ) self.assertEqual(set(lines.mapped('state')), set(states)) - lines = self.env['account.analytic.invoice.line'].search( + lines = self.env['contract.line'].search( [('state', 'not in', states)] ) self.assertFalse(lines.mapped('state')) - lines = self.env['account.analytic.invoice.line'].search( + lines = self.env['contract.line'].search( [('state', 'not in', ['upcoming', 'in-progress'])] ) self.assertEqual( @@ -1780,10 +1781,10 @@ class TestContract(TestContractBase): def test_purchase_fields_view_get(self): purchase_tree_view = self.env.ref( - 'contract.account_analytic_invoice_line_purchase_view_tree' + 'contract.contract_line_supplier_tree_view' ) purchase_form_view = self.env.ref( - 'contract.account_analytic_invoice_line_purchase_view_form' + 'contract.contract_line_supplier_form_view' ) view = self.acct_line.with_context( default_contract_type='purchase' @@ -1796,7 +1797,7 @@ class TestContract(TestContractBase): def test_sale_fields_view_get(self): sale_form_view = self.env.ref( - 'contract.account_analytic_invoice_line_sale_view_form' + 'contract.contract_line_customer_form_view' ) view = self.acct_line.with_context( default_contract_type='sale' @@ -1832,8 +1833,8 @@ class TestContract(TestContractBase): self.assertFalse(self.contract.create_invoice_visibility) def test_invoice_contract_without_lines(self): - self.contract.recurring_invoice_line_ids.cancel() - self.contract.recurring_invoice_line_ids.unlink() + self.contract.contract_line_ids.cancel() + self.contract.contract_line_ids.unlink() self.assertFalse(self.contract.recurring_create_invoice()) def test_stop_at_last_date_invoiced(self): diff --git a/contract/views/abstract_contract_line.xml b/contract/views/abstract_contract_line.xml index 5e822fb1..b66077ee 100644 --- a/contract/views/abstract_contract_line.xml +++ b/contract/views/abstract_contract_line.xml @@ -1,13 +1,13 @@ - - Account Abstract Analytic Contract Line Form View - - account.abstract.analytic.contract.line + + + contract.abstract.contract.line form view (in contract) + contract.abstract.contract.line
+
@@ -60,7 +60,7 @@ + attrs="{'invisible': [('recurring_rule_type', '=', 'monthlylastday')]}"/> diff --git a/contract/views/contract.xml b/contract/views/contract.xml index 308bbd14..302aea98 100644 --- a/contract/views/contract.xml +++ b/contract/views/contract.xml @@ -1,10 +1,10 @@ - - Contract form - account.analytic.account + + + contract.contract form view (in contract) + contract.contract
@@ -70,7 +70,7 @@ - @@ -119,20 +119,18 @@ - - account.analytic.account.sale.form - account.analytic.account - + + + contract.contract customer form view (in contract) + contract.contract + primary Customer [('customer', '=', True)] - {'default_customer': True, - 'default_supplier': False} - + {'default_customer': True, 'default_supplier': False} [('type', '=', 'sale'),('company_id', '=', company_id)] @@ -140,20 +138,18 @@ - - account.analytic.account.purchase.form - account.analytic.account - + + + contract.contract supplier form view (in contract) + contract.contract + primary Supplier [('supplier', '=', True)] - {'default_customer': False, - 'default_supplier': True} - + {'default_customer': False, 'default_supplier': True} [('type', '=', 'purchase'),('company_id', '=', company_id)] @@ -161,30 +157,30 @@ - - - Contract list - account.analytic.account - - primary - + + + contract.contract tree view (in contract) + contract.contract - + + + - + + + + - - - Contract search - account.analytic.account - + + + contract.contract search view (in contract) + contract.contract - + + @@ -201,37 +197,44 @@ string="Finished" domain="[('date_end', '<', context_today().strftime('%Y-%m-%d')), ('recurring_next_date', '=', False)]" /> + + - + - - + - - + + Customer Contracts - account.analytic.account + contract.contract form tree,form [('contract_type', '=', 'sale')] {'is_contract':1, - 'search_default_not_finished':1, - 'search_default_recurring_invoices':1, - 'default_recurring_invoices': 1, 'default_contract_type': 'sale'} + 'search_default_not_finished':1, + 'search_default_recurring_invoices':1, + 'default_recurring_invoices': 1, + 'default_contract_type': 'sale'} - +

Click to create a new contract. @@ -239,47 +242,41 @@ - + tree - - + + - + form - - + + - - - + + Supplier Contracts - account.analytic.account + contract.contract form tree,form [('contract_type', '=', 'purchase')] {'is_contract':1, - 'search_default_not_finished':1, - 'search_default_recurring_invoices':1, - 'default_recurring_invoices': 1, 'default_contract_type': - 'purchase'} + 'search_default_not_finished':1, + 'search_default_recurring_invoices':1, + 'default_recurring_invoices': 1, + 'default_contract_type': + 'purchase'} - +

Click to create a new contract. @@ -287,28 +284,23 @@ - + tree - - + + - + form - - + + - diff --git a/contract/views/contract_line.xml b/contract/views/contract_line.xml index 66e5e017..08abea47 100644 --- a/contract/views/contract_line.xml +++ b/contract/views/contract_line.xml @@ -1,22 +1,17 @@ - - account.analytic.invoice.line.form - account.analytic.invoice.line - + + + contract.line form view (in contract) + contract.line + primary - -

- -
- - - Contract Line - - +
+ +
+ @@ -33,23 +28,21 @@ - -
+
- - account.analytic.invoice.line.sale.form - account.analytic.invoice.line - + + + contract.line customer form view (in contract) + contract.line + primary @@ -59,29 +52,27 @@ - - account.analytic.invoice.line.purchase.form - account.analytic.invoice.line - + + + contract.line supplier form view (in contract) + contract.line + primary - [('purchase_ok', '=', True)] - + [('purchase_ok', '=', True)] - + True - + - - account.analytic.invoice.line.tree - account.analytic.invoice.line + + + contract.line tree view (in contract) + contract.line @@ -155,19 +146,17 @@ - - account.analytic.invoice.line.purchase.tree - account.analytic.invoice.line + + + contract.line supplier tree view (in contract) + contract.line primary - + - + True - + diff --git a/contract/views/contract_template.xml b/contract/views/contract_template.xml index 6d6b4b1a..dad5db29 100644 --- a/contract/views/contract_template.xml +++ b/contract/views/contract_template.xml @@ -1,9 +1,10 @@ - - Account Analytic Contract Form View - account.analytic.contract + + + contract.template form view (in contract) + contract.template @@ -17,9 +18,9 @@ - - - + + + @@ -46,11 +47,12 @@ - - Account Analytic Contract Tree View - account.analytic.contract + + + contract.template tree view (in contract) + contract.template - + @@ -58,11 +60,12 @@ - - Account Analytic Contract Search View - account.analytic.contract + + + contract.template search view (in contract) + contract.template - + @@ -83,12 +86,13 @@ - + + Contract Templates - account.analytic.contract + contract.template form tree,form - +

Click to create a new contract template. @@ -102,9 +106,9 @@ parent="account.menu_finance_configuration" /> - diff --git a/contract/views/contract_template_line.xml b/contract/views/contract_template_line.xml index 64e2067a..596afff7 100644 --- a/contract/views/contract_template_line.xml +++ b/contract/views/contract_template_line.xml @@ -1,16 +1,16 @@ - - account.analytic.contract.line.form - account.analytic.contract.line - + + + contract.template.line form view (in contract) + contract.template.line + primary - - Contract Line Template - + + Contract Template Line + diff --git a/contract/wizards/contract_line_wizard.py b/contract/wizards/contract_line_wizard.py index 17928340..f136d36d 100644 --- a/contract/wizards/contract_line_wizard.py +++ b/contract/wizards/contract_line_wizard.py @@ -4,9 +4,9 @@ from odoo import api, fields, models -class AccountAnalyticInvoiceLineWizard(models.TransientModel): +class ContractLineWizard(models.TransientModel): - _name = 'account.analytic.invoice.line.wizard' + _name = 'contract.line.wizard' _description = 'Contract Line Wizard' date_start = fields.Date(string='Date Start') @@ -21,7 +21,7 @@ class AccountAnalyticInvoiceLineWizard(models.TransientModel): "successor in advance", ) contract_line_id = fields.Many2one( - comodel_name="account.analytic.invoice.line", + comodel_name="contract.line", string="Contract Line", required=True, index=True, diff --git a/contract/wizards/contract_line_wizard.xml b/contract/wizards/contract_line_wizard.xml index 98ca67c9..faf0cfe5 100644 --- a/contract/wizards/contract_line_wizard.xml +++ b/contract/wizards/contract_line_wizard.xml @@ -6,7 +6,7 @@ contract.line.stop.wizard.form (in contract) - account.analytic.invoice.line.wizard + contract.line.wizard

@@ -29,7 +29,7 @@ contract.line.plan_successor.wizard.form (in contract) - account.analytic.invoice.line.wizard + contract.line.wizard @@ -53,7 +53,7 @@ contract.line.stop_plan_successor.wizard.form (in contract) - account.analytic.invoice.line.wizard + contract.line.wizard @@ -77,7 +77,7 @@ contract.line.stop_plan_successor.wizard.form (in contract) - account.analytic.invoice.line.wizard + contract.line.wizard