From a2f71595bfa0b750e70752a0bcbbf8429002f085 Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Mon, 13 Jul 2020 18:28:03 +0200 Subject: [PATCH] [IMP] : black, isort, prettier --- contract/__manifest__.py | 72 +- contract/data/contract_cron.xml | 6 +- contract/data/contract_renew_cron.xml | 6 +- contract/data/ir_ui_menu.xml | 13 +- contract/data/mail_template.xml | 20 +- .../migrations/12.0.4.0.0/post-migration.py | 22 +- .../migrations/12.0.4.0.0/pre-migration.py | 113 +- contract/models/abstract_contract.py | 55 +- contract/models/abstract_contract_line.py | 187 +- contract/models/account_invoice.py | 5 +- contract/models/account_invoice_line.py | 4 +- contract/models/contract.py | 362 ++- contract/models/contract_line.py | 689 +++--- contract/models/contract_line_constraints.py | 68 +- contract/models/contract_tag.py | 8 +- contract/models/contract_template.py | 10 +- contract/models/contract_template_line.py | 12 +- contract/models/contract_terminate_reason.py | 4 +- contract/models/ir_ui_view.py | 8 +- contract/models/res_company.py | 2 +- contract/models/res_config_settings.py | 2 +- contract/models/res_partner.py | 58 +- contract/report/contract_views.xml | 7 +- contract/report/report_contract.xml | 127 +- contract/security/contract_security.xml | 37 +- contract/security/contract_tag.xml | 24 +- .../security/contract_terminate_reason.xml | 30 +- contract/security/groups.xml | 7 +- .../src/js/section_and_note_fields_backend.js | 32 +- contract/tests/test_contract.py | 2098 +++++++---------- contract/views/abstract_contract_line.xml | 160 +- contract/views/assets.xml | 13 +- contract/views/contract.xml | 519 ++-- contract/views/contract_line.xml | 224 +- contract/views/contract_tag.xml | 33 +- contract/views/contract_template.xml | 105 +- contract/views/contract_template_line.xml | 6 +- contract/views/contract_terminate_reason.xml | 23 +- contract/views/res_config_settings.xml | 12 +- contract/views/res_partner_view.xml | 51 +- .../wizards/contract_contract_terminate.py | 2 +- .../wizards/contract_contract_terminate.xml | 36 +- contract/wizards/contract_line_wizard.py | 10 +- contract/wizards/contract_line_wizard.xml | 116 +- .../contract_manually_create_invoice.py | 30 +- .../contract_manually_create_invoice.xml | 86 +- 46 files changed, 2703 insertions(+), 2811 deletions(-) diff --git a/contract/__manifest__.py b/contract/__manifest__.py index c2a68fe6b..b32d652e7 100644 --- a/contract/__manifest__.py +++ b/contract/__manifest__.py @@ -8,42 +8,42 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { - 'name': 'Recurring - Contracts Management', - 'version': '12.0.7.2.2', - 'category': 'Contract Management', - 'license': 'AGPL-3', - 'author': "OpenERP SA, " - "Tecnativa, " - "LasLabs, " - "Odoo Community Association (OCA)", - 'website': 'https://github.com/oca/contract', - 'depends': ['base', 'account', 'product'], + "name": "Recurring - Contracts Management", + "version": "12.0.7.2.2", + "category": "Contract Management", + "license": "AGPL-3", + "author": "OpenERP SA, " + "Tecnativa, " + "LasLabs, " + "Odoo Community Association (OCA)", + "website": "https://github.com/oca/contract", + "depends": ["base", "account", "product"], "external_dependencies": {"python": ["dateutil"]}, - 'data': [ - 'security/groups.xml', - 'security/contract_tag.xml', - 'security/ir.model.access.csv', - 'security/contract_security.xml', - 'security/contract_terminate_reason.xml', - 'report/report_contract.xml', - 'report/contract_views.xml', - 'data/contract_cron.xml', - 'data/contract_renew_cron.xml', - 'data/mail_template.xml', - 'data/ir_ui_menu.xml', - 'wizards/contract_line_wizard.xml', - 'wizards/contract_manually_create_invoice.xml', - 'wizards/contract_contract_terminate.xml', - 'views/contract_tag.xml', - 'views/assets.xml', - 'views/abstract_contract_line.xml', - 'views/contract.xml', - 'views/contract_line.xml', - 'views/contract_template.xml', - 'views/contract_template_line.xml', - 'views/res_partner_view.xml', - 'views/res_config_settings.xml', - 'views/contract_terminate_reason.xml', + "data": [ + "security/groups.xml", + "security/contract_tag.xml", + "security/ir.model.access.csv", + "security/contract_security.xml", + "security/contract_terminate_reason.xml", + "report/report_contract.xml", + "report/contract_views.xml", + "data/contract_cron.xml", + "data/contract_renew_cron.xml", + "data/mail_template.xml", + "data/ir_ui_menu.xml", + "wizards/contract_line_wizard.xml", + "wizards/contract_manually_create_invoice.xml", + "wizards/contract_contract_terminate.xml", + "views/contract_tag.xml", + "views/assets.xml", + "views/abstract_contract_line.xml", + "views/contract.xml", + "views/contract_line.xml", + "views/contract_template.xml", + "views/contract_template_line.xml", + "views/res_partner_view.xml", + "views/res_config_settings.xml", + "views/contract_terminate_reason.xml", ], - 'installable': True, + "installable": True, } diff --git a/contract/data/contract_cron.xml b/contract/data/contract_cron.xml index 754efa292..5fcb4b961 100644 --- a/contract/data/contract_cron.xml +++ b/contract/data/contract_cron.xml @@ -1,9 +1,8 @@ - + - Generate Recurring Invoices from Contracts - + code model.cron_recurring_create_invoice() @@ -12,5 +11,4 @@ -1 - diff --git a/contract/data/contract_renew_cron.xml b/contract/data/contract_renew_cron.xml index 3365fd218..2fa24b1d0 100644 --- a/contract/data/contract_renew_cron.xml +++ b/contract/data/contract_renew_cron.xml @@ -1,9 +1,8 @@ - + - Renew Contract lines - + code model.cron_renew_contract_line() @@ -12,5 +11,4 @@ -1 - diff --git a/contract/data/ir_ui_menu.xml b/contract/data/ir_ui_menu.xml index 2f8765704..2d92a51e8 100644 --- a/contract/data/ir_ui_menu.xml +++ b/contract/data/ir_ui_menu.xml @@ -1,10 +1,9 @@ - + - - - diff --git a/contract/data/mail_template.xml b/contract/data/mail_template.xml index 78368c9a5..9d677bfe6 100644 --- a/contract/data/mail_template.xml +++ b/contract/data/mail_template.xml @@ -1,17 +1,22 @@ - Email Contract Template - ${(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.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 ${object.partner_id.lang} -

Hello ${object.partner_id.name or ''},

A new contract has been created:

@@ -60,5 +65,4 @@ ]]>
-
diff --git a/contract/migrations/12.0.4.0.0/post-migration.py b/contract/migrations/12.0.4.0.0/post-migration.py index 57d48ae80..02d2895f7 100644 --- a/contract/migrations/12.0.4.0.0/post-migration.py +++ b/contract/migrations/12.0.4.0.0/post-migration.py @@ -4,6 +4,7 @@ import logging from openupgradelib import openupgrade + from odoo.tools import parse_version _logger = logging.getLogger(__name__) @@ -11,22 +12,20 @@ _logger = logging.getLogger(__name__) def _update_no_update_ir_cron(env): # Update ir.cron - env.ref('contract.contract_cron_for_invoice').model_id = env.ref( - 'contract.model_contract_contract' + env.ref("contract.contract_cron_for_invoice").model_id = env.ref( + "contract.model_contract_contract" ) - env.ref('contract.contract_line_cron_for_renew').model_id = env.ref( - 'contract.model_contract_line' + env.ref("contract.contract_line_cron_for_renew").model_id = env.ref( + "contract.model_contract_line" ) - env.ref('contract.email_contract_template').model_id = env.ref( - 'contract.model_contract_contract' + env.ref("contract.email_contract_template").model_id = env.ref( + "contract.model_contract_contract" ) def _init_last_date_invoiced_on_contract_lines(env): _logger.info("init last_date_invoiced field for contract lines") - contract_lines = env["contract.line"].search( - [("recurring_next_date", "!=", False)] - ) + contract_lines = env["contract.line"].search([("recurring_next_date", "!=", False)]) contract_lines._init_last_date_invoiced() @@ -43,7 +42,8 @@ def assign_salesman(env): will have admin as responsible. """ openupgrade.logged_query( - env.cr, """ + env.cr, + """ UPDATE contract_contract cc SET user_id = rp.user_id FROM res_partner rp @@ -54,7 +54,7 @@ def assign_salesman(env): @openupgrade.migrate() def migrate(env, version): _update_no_update_ir_cron(env) - if parse_version(version) < parse_version('12.0.2.0.0'): + if parse_version(version) < parse_version("12.0.2.0.0"): # We check the version here as this post-migration script was in # 12.0.2.0.0 and already done for those who used the module when # it was a PR diff --git a/contract/migrations/12.0.4.0.0/pre-migration.py b/contract/migrations/12.0.4.0.0/pre-migration.py index a99aa2abd..306206ea6 100644 --- a/contract/migrations/12.0.4.0.0/pre-migration.py +++ b/contract/migrations/12.0.4.0.0/pre-migration.py @@ -11,62 +11,51 @@ _logger = logging.getLogger(__name__) models_to_rename = [ # Contract Line Wizard - ('account.analytic.invoice.line.wizard', 'contract.line.wizard'), + ("account.analytic.invoice.line.wizard", "contract.line.wizard"), # Abstract Contract - ('account.abstract.analytic.contract', 'contract.abstract.contract'), + ("account.abstract.analytic.contract", "contract.abstract.contract"), # Abstract Contract Line - ( - 'account.abstract.analytic.contract.line', - 'contract.abstract.contract.line', - ), + ("account.abstract.analytic.contract.line", "contract.abstract.contract.line",), # Contract Line - ('account.analytic.invoice.line', 'contract.line'), + ("account.analytic.invoice.line", "contract.line"), # Contract Template - ('account.analytic.contract', 'contract.template'), + ("account.analytic.contract", "contract.template"), # Contract Template Line - ('account.analytic.contract.line', 'contract.template.line'), + ("account.analytic.contract.line", "contract.template.line"), ] tables_to_rename = [ # Contract Line - ('account_analytic_invoice_line', 'contract_line'), + ("account_analytic_invoice_line", "contract_line"), # Contract Template - ('account_analytic_contract', 'contract_template'), + ("account_analytic_contract", "contract_template"), # Contract Template Line - ('account_analytic_contract_line', 'contract_template_line'), + ("account_analytic_contract_line", "contract_template_line"), ] columns_to_copy = { - 'contract_line': [ - ('analytic_account_id', 'contract_id', None), - ], + "contract_line": [("analytic_account_id", "contract_id", None),], } xmlids_to_rename = [ ( - 'contract.account_analytic_cron_for_invoice', - 'contract.contract_cron_for_invoice', + "contract.account_analytic_cron_for_invoice", + "contract.contract_cron_for_invoice", ), ( - 'contract.account_analytic_contract_manager', - 'contract.contract_template_manager', + "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_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', + "contract.account_analytic_contract_line_user", + "contract.contract_template_line_user", ), ] @@ -77,33 +66,34 @@ def _get_contract_field_name(cr): in 12.0.2.0.0. This method used to get the contract field name in account_analytic_invoice_line""" return ( - 'contract_id' - if openupgrade.column_exists( - cr, 'account_analytic_invoice_line', 'contract_id' - ) - else 'analytic_account_id' + "contract_id" + if openupgrade.column_exists(cr, "account_analytic_invoice_line", "contract_id") + else "analytic_account_id" ) def create_contract_records(cr): contract_field_name = _get_contract_field_name(cr) openupgrade.logged_query( - cr, """ + cr, + """ CREATE TABLE contract_contract (LIKE account_analytic_account INCLUDING ALL)""", ) openupgrade.logged_query( - cr, sql.SQL(""" + cr, + sql.SQL( + """ INSERT INTO contract_contract SELECT * FROM account_analytic_account WHERE id IN (SELECT DISTINCT {} FROM contract_line) - """).format( - sql.Identifier(contract_field_name), - ), + """ + ).format(sql.Identifier(contract_field_name),), ) # Deactivate disabled contracts openupgrade.logged_query( - cr, """UPDATE contract_contract cc + cr, + """UPDATE contract_contract cc SET active = False FROM account_analytic_account aaa WHERE aaa.id = cc.id @@ -111,24 +101,31 @@ def create_contract_records(cr): ) # Handle id sequence cr.execute("CREATE SEQUENCE IF NOT EXISTS contract_contract_id_seq") - cr.execute("SELECT setval('contract_contract_id_seq', " - "(SELECT MAX(id) FROM contract_contract))") - cr.execute("ALTER TABLE contract_contract ALTER id " - "SET DEFAULT NEXTVAL('contract_contract_id_seq')") + cr.execute( + "SELECT setval('contract_contract_id_seq', " + "(SELECT MAX(id) FROM contract_contract))" + ) + cr.execute( + "ALTER TABLE contract_contract ALTER id " + "SET DEFAULT NEXTVAL('contract_contract_id_seq')" + ) # Move common stuff from one table to the other mapping = [ - ('ir_attachment', 'res_model', 'res_id'), - ('mail_message', 'model', 'res_id'), - ('mail_activity', 'res_model', 'res_id'), - ('mail_followers', 'res_model', 'res_id'), + ("ir_attachment", "res_model", "res_id"), + ("mail_message", "model", "res_id"), + ("mail_activity", "res_model", "res_id"), + ("mail_followers", "res_model", "res_id"), ] for table, model_column, id_column in mapping: openupgrade.logged_query( - cr, sql.SQL(""" + cr, + sql.SQL( + """ UPDATE {table} SET {model_column}='contract.contract' WHERE {model_column}='account.analytic.account' AND {id_column} IN (SELECT DISTINCT {col} FROM contract_line) - """).format( + """ + ).format( table=sql.Identifier(table), model_column=sql.Identifier(model_column), id_column=sql.Identifier(id_column), diff --git a/contract/models/abstract_contract.py b/contract/models/abstract_contract.py index 398d79d4d..d8c00fae7 100644 --- a/contract/models/abstract_contract.py +++ b/contract/models/abstract_contract.py @@ -6,68 +6,61 @@ # Copyright 2018 ACSONE SA/NV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import api, models, fields +from odoo import api, fields, models class ContractAbstractContract(models.AbstractModel): - _name = 'contract.abstract.contract' - _description = 'Abstract Recurring Contract' + _name = "contract.abstract.contract" + _description = "Abstract Recurring Contract" # These fields will not be synced to the contract - NO_SYNC = ['name', 'partner_id', 'company_id'] + NO_SYNC = ["name", "partner_id", "company_id"] name = fields.Char(required=True) # Needed for avoiding errors on several inherited behaviors partner_id = fields.Many2one( comodel_name="res.partner", string="Partner", index=True ) - pricelist_id = fields.Many2one( - comodel_name='product.pricelist', string='Pricelist' - ) + pricelist_id = fields.Many2one(comodel_name="product.pricelist", string="Pricelist") contract_type = fields.Selection( - selection=[('sale', 'Customer'), ('purchase', 'Supplier')], - default='sale', + selection=[("sale", "Customer"), ("purchase", "Supplier")], + default="sale", index=True, ) journal_id = fields.Many2one( - 'account.journal', - string='Journal', + "account.journal", + string="Journal", default=lambda s: s._default_journal(), - domain="[('type', '=', contract_type)," - "('company_id', '=', company_id)]", + domain="[('type', '=', contract_type)," "('company_id', '=', company_id)]", index=True, ) company_id = fields.Many2one( - 'res.company', - string='Company', + "res.company", + string="Company", required=True, - default=lambda self: self.env['res.company']._company_default_get( - self._name - ), + default=lambda self: self.env["res.company"]._company_default_get(self._name), ) - @api.onchange('contract_type') + @api.onchange("contract_type") def _onchange_contract_type(self): - if self.contract_type == 'purchase': - self.contract_line_ids.filtered('automatic_price').update( - {'automatic_price': False} + if self.contract_type == "purchase": + self.contract_line_ids.filtered("automatic_price").update( + {"automatic_price": False} ) - self.journal_id = self.env['account.journal'].search( + self.journal_id = self.env["account.journal"].search( [ - ('type', '=', self.contract_type), - ('company_id', '=', self.company_id.id), + ("type", "=", self.contract_type), + ("company_id", "=", self.company_id.id), ], limit=1, ) @api.model def _default_journal(self): - company_id = self.env.context.get( - 'company_id', self.env.user.company_id.id - ) + company_id = self.env.context.get("company_id", self.env.user.company_id.id) domain = [ - ('type', '=', self.contract_type), - ('company_id', '=', company_id), + ("type", "=", self.contract_type), + ("company_id", "=", company_id), ] - return self.env['account.journal'].search(domain, limit=1) + return self.env["account.journal"].search(domain, limit=1) diff --git a/contract/models/abstract_contract_line.py b/contract/models/abstract_contract_line.py index 5d2598a65..fc2c05082 100644 --- a/contract/models/abstract_contract_line.py +++ b/contract/models/abstract_contract_line.py @@ -6,47 +6,44 @@ # Copyright 2018 ACSONE SA/NV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import api, models, fields -from odoo.addons import decimal_precision as dp +from odoo import api, fields, models from odoo.exceptions import ValidationError from odoo.tools.translate import _ +from odoo.addons import decimal_precision as dp + class ContractAbstractContractLine(models.AbstractModel): - _name = 'contract.abstract.contract.line' - _description = 'Abstract Recurring Contract Line' + _name = "contract.abstract.contract.line" + _description = "Abstract Recurring Contract Line" - product_id = fields.Many2one( - 'product.product', string='Product' - ) + product_id = fields.Many2one("product.product", string="Product") - name = fields.Text(string='Description', required=True) + name = fields.Text(string="Description", required=True) quantity = fields.Float(default=1.0, required=True) - uom_id = fields.Many2one( - 'uom.uom', string='Unit of Measure' - ) + uom_id = fields.Many2one("uom.uom", string="Unit of Measure") automatic_price = fields.Boolean( string="Auto-price?", help="If this is marked, the price will be obtained automatically " "applying the pricelist to the product. If not, you will be " "able to introduce a manual price", ) - specific_price = fields.Float(string='Specific Price') + specific_price = fields.Float(string="Specific Price") price_unit = fields.Float( - string='Unit Price', + string="Unit Price", compute="_compute_price_unit", inverse="_inverse_price_unit", ) price_subtotal = fields.Float( - compute='_compute_price_subtotal', - digits=dp.get_precision('Account'), - string='Sub Total', + compute="_compute_price_subtotal", + digits=dp.get_precision("Account"), + string="Sub Total", ) discount = fields.Float( - string='Discount (%)', - digits=dp.get_precision('Discount'), - help='Discount that is applied in generated invoices.' - ' It should be less or equal to 100', + string="Discount (%)", + digits=dp.get_precision("Discount"), + help="Discount that is applied in generated invoices." + " It should be less or equal to 100", ) sequence = fields.Integer( string="Sequence", @@ -55,23 +52,23 @@ class ContractAbstractContractLine(models.AbstractModel): ) recurring_rule_type = fields.Selection( [ - ('daily', 'Day(s)'), - ('weekly', 'Week(s)'), - ('monthly', 'Month(s)'), - ('monthlylastday', 'Month(s) last day'), - ('quarterly', 'Quarter(s)'), - ('semesterly', 'Semester(s)'), - ('yearly', 'Year(s)'), + ("daily", "Day(s)"), + ("weekly", "Week(s)"), + ("monthly", "Month(s)"), + ("monthlylastday", "Month(s) last day"), + ("quarterly", "Quarter(s)"), + ("semesterly", "Semester(s)"), + ("yearly", "Year(s)"), ], - default='monthly', - string='Recurrence', + default="monthly", + string="Recurrence", help="Specify Interval for automatic invoice generation.", required=True, ) recurring_invoicing_type = fields.Selection( - [('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')], - default='pre-paid', - string='Invoicing type', + [("pre-paid", "Pre-paid"), ("post-paid", "Post-paid")], + default="pre-paid", + string="Invoicing type", help=( "Specify if the invoice must be generated at the beginning " "(pre-paid) or end (post-paid) of the period." @@ -84,68 +81,63 @@ class ContractAbstractContractLine(models.AbstractModel): help=( "Number of days to offset the invoice from the period end " "date (in post-paid mode) or start date (in pre-paid mode)." - ) + ), ) recurring_interval = fields.Integer( default=1, - string='Invoice Every', + string="Invoice Every", help="Invoice every (Days/Week/Month/Year)", required=True, ) - date_start = fields.Date(string='Date Start') - recurring_next_date = fields.Date(string='Date of Next Invoice') - last_date_invoiced = fields.Date(string='Last Date Invoiced') + date_start = fields.Date(string="Date Start") + recurring_next_date = fields.Date(string="Date of Next Invoice") + last_date_invoiced = fields.Date(string="Last Date Invoiced") is_canceled = fields.Boolean(string="Canceled", default=False) is_auto_renew = fields.Boolean(string="Auto Renew", default=False) auto_renew_interval = fields.Integer( - default=1, - string='Renew Every', - help="Renew every (Days/Week/Month/Year)", + default=1, string="Renew Every", help="Renew every (Days/Week/Month/Year)", ) auto_renew_rule_type = fields.Selection( [ - ('daily', 'Day(s)'), - ('weekly', 'Week(s)'), - ('monthly', 'Month(s)'), - ('yearly', 'Year(s)'), + ("daily", "Day(s)"), + ("weekly", "Week(s)"), + ("monthly", "Month(s)"), + ("yearly", "Year(s)"), ], - default='yearly', - string='Renewal type', + default="yearly", + string="Renewal type", help="Specify Interval for automatic renewal.", ) termination_notice_interval = fields.Integer( - default=1, string='Termination Notice Before' + default=1, string="Termination Notice Before" ) termination_notice_rule_type = fields.Selection( - [('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)')], - default='monthly', - string='Termination Notice type', + [("daily", "Day(s)"), ("weekly", "Week(s)"), ("monthly", "Month(s)")], + default="monthly", + string="Termination Notice type", ) contract_id = fields.Many2one( - string='Contract', - comodel_name='contract.abstract.contract', + string="Contract", + comodel_name="contract.abstract.contract", required=True, - ondelete='cascade', + ondelete="cascade", ) display_type = fields.Selection( - selection=[ - ('line_section', "Section"), - ('line_note', "Note"), - ], + selection=[("line_section", "Section"), ("line_note", "Note"),], default=False, - help="Technical field for UX purpose." + help="Technical field for UX purpose.", ) note_invoicing_mode = fields.Selection( selection=[ - ('with_previous_line', 'With previous line'), - ('with_next_line', 'With next line'), - ('custom', 'Custom'), + ("with_previous_line", "With previous line"), + ("with_next_line", "With next line"), + ("custom", "Custom"), ], - default='with_previous_line', + default="with_previous_line", help="Defines when the Note is invoiced:\n" - "- With previous line: If the previous line can be invoiced.\n" - "- With next line: If the next line can be invoiced.\n" - "- Custom: Depending on the recurrence to be define." + "- With previous line: If the previous line can be invoiced.\n" + "- With next line: If the next line can be invoiced.\n" + "- Custom: Depending on the recurrence to be define.", ) is_recurring_note = fields.Boolean(compute="_compute_is_recurring_note") @@ -154,8 +146,8 @@ class ContractAbstractContractLine(models.AbstractModel): self, recurring_invoicing_type, recurring_rule_type ): if ( - recurring_invoicing_type == 'pre-paid' - or recurring_rule_type == 'monthlylastday' + recurring_invoicing_type == "pre-paid" + or recurring_rule_type == "monthlylastday" ): return 0 else: @@ -164,26 +156,24 @@ class ContractAbstractContractLine(models.AbstractModel): def is_recurring_note(self): for record in self: record.is_recurring_note = ( - record.display_type == 'line_note' - and record.note_invoicing_mode == 'custom' + record.display_type == "line_note" + and record.note_invoicing_mode == "custom" ) - @api.depends('recurring_invoicing_type', 'recurring_rule_type') + @api.depends("recurring_invoicing_type", "recurring_rule_type") def _compute_recurring_invoicing_offset(self): for rec in self: - rec.recurring_invoicing_offset = ( - self._get_default_recurring_invoicing_offset( - rec.recurring_invoicing_type, rec.recurring_rule_type - ) + rec.recurring_invoicing_offset = self._get_default_recurring_invoicing_offset( + rec.recurring_invoicing_type, rec.recurring_rule_type ) @api.depends( - 'automatic_price', - 'specific_price', - 'product_id', - 'quantity', - 'contract_id.pricelist_id', - 'contract_id.partner_id', + "automatic_price", + "specific_price", + "product_id", + "quantity", + "contract_id.pricelist_id", + "contract_id.partner_id", ) def _compute_price_unit(self): """Get the specific price if no auto-price, and the price obtained @@ -192,20 +182,17 @@ class ContractAbstractContractLine(models.AbstractModel): for line in self: if line.automatic_price: pricelist = ( - line.contract_id.pricelist_id or - line.contract_id.partner_id.with_context( + line.contract_id.pricelist_id + or line.contract_id.partner_id.with_context( force_company=line.contract_id.company_id.id, ).property_product_pricelist ) product = line.product_id.with_context( - quantity=line.env.context.get( - 'contract_line_qty', - line.quantity, - ), + quantity=line.env.context.get("contract_line_qty", line.quantity,), pricelist=pricelist.id, partner=line.contract_id.partner_id.id, date=line.env.context.get( - 'old_date', fields.Date.context_today(line) + "old_date", fields.Date.context_today(line) ), ) line.price_unit = product.price @@ -213,14 +200,14 @@ class ContractAbstractContractLine(models.AbstractModel): line.price_unit = line.specific_price # Tip in https://github.com/odoo/odoo/issues/23891#issuecomment-376910788 - @api.onchange('price_unit') + @api.onchange("price_unit") def _inverse_price_unit(self): """Store the specific price in the no auto-price records.""" for line in self.filtered(lambda x: not x.automatic_price): line.specific_price = line.price_unit @api.multi - @api.depends('quantity', 'price_unit', 'discount') + @api.depends("quantity", "price_unit", "discount") def _compute_price_subtotal(self): for line in self: subtotal = line.quantity * line.price_unit @@ -233,30 +220,26 @@ class ContractAbstractContractLine(models.AbstractModel): line.price_subtotal = subtotal @api.multi - @api.constrains('discount') + @api.constrains("discount") def _check_discount(self): for line in self: if line.discount > 100: - raise ValidationError( - _("Discount should be less or equal to 100") - ) + raise ValidationError(_("Discount should be less or equal to 100")) @api.multi - @api.onchange('product_id') + @api.onchange("product_id") def _onchange_product_id(self): if not self.product_id: - return {'domain': {'uom_id': []}} + return {"domain": {"uom_id": []}} vals = {} domain = { - 'uom_id': [ - ('category_id', '=', self.product_id.uom_id.category_id.id) - ] + "uom_id": [("category_id", "=", self.product_id.uom_id.category_id.id)] } if not self.uom_id or ( self.product_id.uom_id.category_id.id != self.uom_id.category_id.id ): - vals['uom_id'] = self.product_id.uom_id + vals["uom_id"] = self.product_id.uom_id date = self.recurring_next_date or fields.Date.context_today(self) partner = self.contract_id.partner_id or self.env.user.partner_id @@ -268,7 +251,7 @@ class ContractAbstractContractLine(models.AbstractModel): pricelist=self.contract_id.pricelist_id.id, uom=self.uom_id.id, ) - vals['name'] = self.product_id.get_product_multiline_description_sale() - vals['price_unit'] = product.price + vals["name"] = self.product_id.get_product_multiline_description_sale() + vals["price_unit"] = product.price self.update(vals) - return {'domain': domain} + return {"domain": domain} diff --git a/contract/models/account_invoice.py b/contract/models/account_invoice.py index 3510c3542..faaa009cc 100644 --- a/contract/models/account_invoice.py +++ b/contract/models/account_invoice.py @@ -5,8 +5,7 @@ from odoo import fields, models class AccountInvoice(models.Model): - _inherit = 'account.invoice' + _inherit = "account.invoice" # We keep this field for migration purpose - old_contract_id = fields.Many2one( - 'contract.contract', oldname='contract_id') + old_contract_id = fields.Many2one("contract.contract", oldname="contract_id") diff --git a/contract/models/account_invoice_line.py b/contract/models/account_invoice_line.py index 31454e41c..262d0c1b5 100644 --- a/contract/models/account_invoice_line.py +++ b/contract/models/account_invoice_line.py @@ -5,8 +5,8 @@ from odoo import fields, models class AccountInvoiceLine(models.Model): - _inherit = 'account.invoice.line' + _inherit = "account.invoice.line" contract_line_id = fields.Many2one( - 'contract.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 2317f5adf..5f97581f4 100644 --- a/contract/models/contract.py +++ b/contract/models/contract.py @@ -7,30 +7,24 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import api, fields, models -from odoo.exceptions import ValidationError, UserError +from odoo.exceptions import UserError, ValidationError from odoo.tools.translate import _ class ContractContract(models.Model): - _name = 'contract.contract' + _name = "contract.contract" _description = "Contract" - _order = 'code, name asc' + _order = "code, name asc" _inherit = [ - 'mail.thread', - 'mail.activity.mixin', - 'contract.abstract.contract', + "mail.thread", + "mail.activity.mixin", + "contract.abstract.contract", ] - active = fields.Boolean( - default=True, - ) - code = fields.Char( - string="Reference", - ) + active = fields.Boolean(default=True,) + code = fields.Char(string="Reference",) group_id = fields.Many2one( - string="Group", - comodel_name='account.analytic.account', - ondelete='restrict', + string="Group", comodel_name="account.analytic.account", ondelete="restrict", ) currency_id = fields.Many2one( compute="_compute_currency_id", @@ -38,70 +32,59 @@ class ContractContract(models.Model): comodel_name="res.currency", string="Currency", ) - manual_currency_id = fields.Many2one( - comodel_name="res.currency", - readonly=True, - ) + manual_currency_id = fields.Many2one(comodel_name="res.currency", readonly=True,) contract_template_id = fields.Many2one( - string='Contract Template', comodel_name='contract.template' + string="Contract Template", comodel_name="contract.template" ) contract_line_ids = fields.One2many( - string='Contract lines', - comodel_name='contract.line', - inverse_name='contract_id', + string="Contract lines", + comodel_name="contract.line", + inverse_name="contract_id", copy=True, ) user_id = fields.Many2one( - comodel_name='res.users', - string='Responsible', + comodel_name="res.users", + string="Responsible", index=True, default=lambda self: self.env.user, ) create_invoice_visibility = fields.Boolean( - compute='_compute_create_invoice_visibility' + compute="_compute_create_invoice_visibility" ) recurring_next_date = fields.Date( - compute='_compute_recurring_next_date', - string='Date of Next Invoice', + compute="_compute_recurring_next_date", + string="Date of Next Invoice", store=True, ) - date_end = fields.Date( - compute='_compute_date_end', string='Date End', store=True - ) + date_end = fields.Date(compute="_compute_date_end", string="Date End", store=True) payment_term_id = fields.Many2one( - comodel_name='account.payment.term', string='Payment Terms', index=True + comodel_name="account.payment.term", string="Payment Terms", index=True ) invoice_count = fields.Integer(compute="_compute_invoice_count") fiscal_position_id = fields.Many2one( - comodel_name='account.fiscal.position', - string='Fiscal Position', - ondelete='restrict', + comodel_name="account.fiscal.position", + string="Fiscal Position", + ondelete="restrict", ) invoice_partner_id = fields.Many2one( - string="Invoicing contact", - comodel_name='res.partner', - ondelete='restrict', + string="Invoicing contact", comodel_name="res.partner", ondelete="restrict", ) partner_id = fields.Many2one( - comodel_name='res.partner', - inverse='_inverse_partner_id', - required=True + comodel_name="res.partner", inverse="_inverse_partner_id", required=True ) commercial_partner_id = fields.Many2one( - 'res.partner', + "res.partner", compute_sudo=True, - related='partner_id.commercial_partner_id', + related="partner_id.commercial_partner_id", store=True, - string='Commercial Entity', - index=True + string="Commercial Entity", + index=True, ) tag_ids = fields.Many2many(comodel_name="contract.tag", string="Tags") note = fields.Text(string="Notes") - is_terminated = fields.Boolean( - string="Terminated", readonly=True, copy=False - ) + is_terminated = fields.Boolean(string="Terminated", readonly=True, copy=False) terminate_reason_id = fields.Many2one( comodel_name="contract.terminate.reason", string="Termination Reason", @@ -127,55 +110,40 @@ class ContractContract(models.Model): def _inverse_partner_id(self): for rec in self: if not rec.invoice_partner_id: - rec.invoice_partner_id = rec.partner_id.address_get( - ['invoice'] - )['invoice'] + rec.invoice_partner_id = rec.partner_id.address_get(["invoice"])[ + "invoice" + ] @api.multi def _get_related_invoices(self): self.ensure_one() invoices = ( - self.env['account.invoice.line'] - .search( - [ - ( - 'contract_line_id', - 'in', - self.contract_line_ids.ids, - ) - ] - ) - .mapped('invoice_id') + self.env["account.invoice.line"] + .search([("contract_line_id", "in", self.contract_line_ids.ids,)]) + .mapped("invoice_id") ) - invoices |= self.env['account.invoice'].search( - [('old_contract_id', '=', self.id)] + invoices |= self.env["account.invoice"].search( + [("old_contract_id", "=", self.id)] ) return invoices def _get_computed_currency(self): """Helper method for returning the theoretical computed currency.""" self.ensure_one() - currency = self.env['res.currency'] - if any(self.contract_line_ids.mapped('automatic_price')): + currency = self.env["res.currency"] + if any(self.contract_line_ids.mapped("automatic_price")): # Use pricelist currency currency = ( - self.pricelist_id.currency_id or - self.partner_id.with_context( + self.pricelist_id.currency_id + or self.partner_id.with_context( force_company=self.company_id.id, ).property_product_pricelist.currency_id ) - return ( - currency or self.journal_id.currency_id or - self.company_id.currency_id - ) + return currency or self.journal_id.currency_id or self.company_id.currency_id @api.depends( - "manual_currency_id", - "pricelist_id", - "partner_id", - "journal_id", - "company_id", + "manual_currency_id", "pricelist_id", "partner_id", "journal_id", "company_id", ) def _compute_currency_id(self): for rec in self: @@ -203,60 +171,60 @@ class ContractContract(models.Model): def action_show_invoices(self): self.ensure_one() tree_view_ref = ( - 'account.invoice_supplier_tree' - if self.contract_type == 'purchase' - else 'account.invoice_tree_with_onboarding' + "account.invoice_supplier_tree" + if self.contract_type == "purchase" + else "account.invoice_tree_with_onboarding" ) form_view_ref = ( - 'account.invoice_supplier_form' - if self.contract_type == 'purchase' - else 'account.invoice_form' + "account.invoice_supplier_form" + if self.contract_type == "purchase" + else "account.invoice_form" ) tree_view = self.env.ref(tree_view_ref, raise_if_not_found=False) form_view = self.env.ref(form_view_ref, raise_if_not_found=False) action = { - 'type': 'ir.actions.act_window', - 'name': 'Invoices', - 'res_model': 'account.invoice', - 'view_type': 'form', - 'view_mode': 'tree,kanban,form,calendar,pivot,graph,activity', - 'domain': [('id', 'in', self._get_related_invoices().ids)], + "type": "ir.actions.act_window", + "name": "Invoices", + "res_model": "account.invoice", + "view_type": "form", + "view_mode": "tree,kanban,form,calendar,pivot,graph,activity", + "domain": [("id", "in", self._get_related_invoices().ids)], } if tree_view and form_view: - action['views'] = [(tree_view.id, 'tree'), (form_view.id, 'form')] + action["views"] = [(tree_view.id, "tree"), (form_view.id, "form")] return action - @api.depends('contract_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.contract_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( - 'contract_line_ids.recurring_next_date', - 'contract_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.contract_line_ids.filtered( - lambda l: (l.recurring_next_date and not l.is_canceled - and (not l.display_type or l.is_recurring_note)) - ).mapped('recurring_next_date') + lambda l: ( + l.recurring_next_date + and not l.is_canceled + and (not l.display_type or l.is_recurring_note) + ) + ).mapped("recurring_next_date") if recurring_next_date: contract.recurring_next_date = min(recurring_next_date) - @api.depends('contract_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.contract_line_ids.mapped( - 'create_invoice_visibility' - ) + contract.contract_line_ids.mapped("create_invoice_visibility") ) - @api.onchange('contract_template_id') + @api.onchange("contract_template_id") def _onchange_contract_template_id(self): """Update the contract fields with that of the template. @@ -269,7 +237,7 @@ class ContractContract(models.Model): if not contract_template_id: return for field_name, field in contract_template_id._fields.items(): - if field.name == 'contract_line_ids': + if field.name == "contract_line_ids": lines = self._convert_contract_lines(contract_template_id) self.contract_line_ids += lines elif not any( @@ -285,7 +253,7 @@ class ContractContract(models.Model): if self.contract_template_id[field_name]: self[field_name] = self.contract_template_id[field_name] - @api.onchange('partner_id', 'company_id') + @api.onchange("partner_id", "company_id") def _onchange_partner_id(self): partner = ( self.partner_id @@ -294,21 +262,19 @@ class ContractContract(models.Model): ) self.pricelist_id = partner.property_product_pricelist.id self.fiscal_position_id = partner.env[ - 'account.fiscal.position' + "account.fiscal.position" ].get_fiscal_position(partner.id) - if self.contract_type == 'purchase': + if self.contract_type == "purchase": self.payment_term_id = partner.property_supplier_payment_term_id else: self.payment_term_id = partner.property_payment_term_id - self.invoice_partner_id = self.partner_id.address_get(['invoice'])[ - 'invoice' - ] + self.invoice_partner_id = self.partner_id.address_get(["invoice"])["invoice"] return { - 'domain': { - 'invoice_partner_id': [ - '|', - ('id', 'parent_of', self.partner_id.id), - ('id', 'child_of', self.partner_id.id), + "domain": { + "invoice_partner_id": [ + "|", + ("id", "parent_of", self.partner_id.id), + ("id", "child_of", self.partner_id.id), ] } } @@ -316,16 +282,14 @@ class ContractContract(models.Model): @api.multi def _convert_contract_lines(self, contract): self.ensure_one() - new_lines = self.env['contract.line'] - contract_line_model = self.env['contract.line'] + 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) - vals['date_start'] = fields.Date.context_today(contract_line) - vals['recurring_next_date'] = fields.Date.context_today( - contract_line - ) + vals.pop("contract_template_id", False) + vals["date_start"] = fields.Date.context_today(contract_line) + vals["recurring_next_date"] = fields.Date.context_today(contract_line) new_lines += contract_line_model.new(vals) new_lines._onchange_date_start() new_lines._onchange_is_auto_renew() @@ -338,10 +302,10 @@ class ContractContract(models.Model): journal = ( self.journal_id if self.journal_id.type == self.contract_type - else self.env['account.journal'].search( + else self.env["account.journal"].search( [ - ('type', '=', self.contract_type), - ('company_id', '=', self.company_id.id), + ("type", "=", self.contract_type), + ("company_id", "=", self.company_id.id), ], limit=1, ) @@ -349,56 +313,62 @@ class ContractContract(models.Model): if not journal: raise ValidationError( _("Please define a %s journal for the company '%s'.") - % (self.contract_type, self.company_id.name or '') + % (self.contract_type, self.company_id.name or "") ) - invoice_type = 'out_invoice' - if self.contract_type == 'purchase': - invoice_type = 'in_invoice' - vinvoice = self.env['account.invoice'].with_context( - force_company=self.company_id.id, - ).new({ - 'company_id': self.company_id.id, - 'partner_id': self.invoice_partner_id.id, - 'type': invoice_type, - }) + invoice_type = "out_invoice" + if self.contract_type == "purchase": + invoice_type = "in_invoice" + vinvoice = ( + self.env["account.invoice"] + .with_context(force_company=self.company_id.id,) + .new( + { + "company_id": self.company_id.id, + "partner_id": self.invoice_partner_id.id, + "type": invoice_type, + } + ) + ) vinvoice._onchange_partner_id() invoice_vals = vinvoice._convert_to_write(vinvoice._cache) - invoice_vals.update({ - 'name': self.code, - 'currency_id': self.currency_id.id, - 'date_invoice': date_invoice, - 'journal_id': journal.id, - 'origin': self.name, - 'user_id': self.user_id.id, - }) + invoice_vals.update( + { + "name": self.code, + "currency_id": self.currency_id.id, + "date_invoice": date_invoice, + "journal_id": journal.id, + "origin": self.name, + "user_id": self.user_id.id, + } + ) if self.payment_term_id: - invoice_vals['payment_term_id'] = self.payment_term_id.id + invoice_vals["payment_term_id"] = self.payment_term_id.id if self.fiscal_position_id: - invoice_vals['fiscal_position_id'] = self.fiscal_position_id.id + invoice_vals["fiscal_position_id"] = self.fiscal_position_id.id return invoice_vals @api.multi def action_contract_send(self): self.ensure_one() - template = self.env.ref('contract.email_contract_template', False) - compose_form = self.env.ref('mail.email_compose_message_wizard_form') + template = self.env.ref("contract.email_contract_template", False) + compose_form = self.env.ref("mail.email_compose_message_wizard_form") ctx = dict( - default_model='contract.contract', + default_model="contract.contract", default_res_id=self.id, default_use_template=bool(template), default_template_id=template and template.id or False, - default_composition_mode='comment', + default_composition_mode="comment", ) return { - 'name': _('Compose Email'), - 'type': 'ir.actions.act_window', - 'view_type': 'form', - 'view_mode': 'form', - 'res_model': 'mail.compose.message', - 'views': [(compose_form.id, 'form')], - 'view_id': compose_form.id, - 'target': 'new', - 'context': ctx, + "name": _("Compose Email"), + "type": "ir.actions.act_window", + "view_type": "form", + "view_mode": "form", + "res_model": "mail.compose.message", + "views": [(compose_form.id, "form")], + "view_id": compose_form.id, + "target": "new", + "context": ctx, } @api.model @@ -430,10 +400,8 @@ class ContractContract(models.Model): final_invoices_values = [] # TODO: This call must be removed in >=13.0 for invoice_values in invoices_values: - final_invoices_values.append( - self._finalize_invoice_values(invoice_values) - ) - invoices = self.env['account.invoice'].create(final_invoices_values) + final_invoices_values.append(self._finalize_invoice_values(invoice_values)) + invoices = self.env["account.invoice"].create(final_invoices_values) self._finalize_invoice_creation(invoices) return invoices @@ -448,7 +416,7 @@ class ContractContract(models.Model): domain = [] if not date_ref: date_ref = fields.Date.context_today(self) - domain.extend([('recurring_next_date', '<=', date_ref)]) + domain.extend([("recurring_next_date", "<=", date_ref)]) return domain @api.multi @@ -462,16 +430,18 @@ class ContractContract(models.Model): self.ensure_one() def can_be_invoiced(l): - return (not l.is_canceled and l.recurring_next_date - and l.recurring_next_date <= date_ref) + return ( + not l.is_canceled + and l.recurring_next_date + and l.recurring_next_date <= date_ref + ) - lines2invoice = previous = self.env['contract.line'] + lines2invoice = previous = self.env["contract.line"] current_section = current_note = False for line in self.contract_line_ids: - if line.display_type == 'line_section': + if line.display_type == "line_section": current_section = line - elif (line.display_type == 'line_note' and - not line.is_recurring_note): + elif line.display_type == "line_note" and not line.is_recurring_note: if line.note_invoicing_mode == "with_previous_line": if previous in lines2invoice: lines2invoice |= line @@ -511,12 +481,12 @@ class ContractContract(models.Model): continue invoice_values = contract._prepare_invoice(date_ref) for line in contract_lines: - invoice_values.setdefault('invoice_line_ids', []) + invoice_values.setdefault("invoice_line_ids", []) invoice_line_values = line._prepare_invoice_line( invoice_values=invoice_values, ) if invoice_line_values: - invoice_values['invoice_line_ids'].append( + invoice_values["invoice_line_ids"].append( (0, 0, invoice_line_values) ) invoices_values.append(invoice_values) @@ -533,9 +503,9 @@ class ContractContract(models.Model): if invoice: self.message_post( body=_( - 'Contract manually invoiced: ' + "Contract manually invoiced: " 'Invoice' - '' + "" ) % (invoice._name, invoice.id) ) @@ -566,13 +536,13 @@ class ContractContract(models.Model): self.ensure_one() context = {"default_contract_id": self.id} return { - 'type': 'ir.actions.act_window', - 'name': _('Terminate Contract'), - 'res_model': 'contract.contract.terminate', - 'view_type': 'form', - 'view_mode': 'form', - 'target': 'new', - 'context': context, + "type": "ir.actions.act_window", + "name": _("Terminate Contract"), + "res_model": "contract.contract.terminate", + "view_type": "form", + "view_mode": "form", + "target": "new", + "context": context, } @api.multi @@ -581,22 +551,26 @@ class ContractContract(models.Model): ): self.ensure_one() if not self.env.user.has_group("contract.can_terminate_contract"): - raise UserError(_('You are not allowed to terminate contracts.')) - self.contract_line_ids.filtered('is_stop_allowed').stop(terminate_date) - self.write({ - 'is_terminated': True, - 'terminate_reason_id': terminate_reason_id.id, - 'terminate_comment': terminate_comment, - 'terminate_date': terminate_date, - }) + raise UserError(_("You are not allowed to terminate contracts.")) + self.contract_line_ids.filtered("is_stop_allowed").stop(terminate_date) + self.write( + { + "is_terminated": True, + "terminate_reason_id": terminate_reason_id.id, + "terminate_comment": terminate_comment, + "terminate_date": terminate_date, + } + ) return True @api.multi def action_cancel_contract_termination(self): self.ensure_one() - self.write({ - 'is_terminated': False, - 'terminate_reason_id': False, - 'terminate_comment': False, - 'terminate_date': False, - }) + self.write( + { + "is_terminated": False, + "terminate_reason_id": False, + "terminate_comment": False, + "terminate_date": False, + } + ) diff --git a/contract/models/contract_line.py b/contract/models/contract_line.py index d67447965..762bd62cd 100644 --- a/contract/models/contract_line.py +++ b/contract/models/contract_line.py @@ -3,68 +3,63 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from datetime import timedelta + from dateutil.relativedelta import relativedelta -from odoo import api, fields, models, _ +from odoo import _, api, fields, models from odoo.exceptions import ValidationError from .contract_line_constraints import get_allowed class ContractLine(models.Model): - _name = 'contract.line' + _name = "contract.line" _description = "Contract Line" - _inherit = 'contract.abstract.contract.line' - _order = 'sequence,id' + _inherit = "contract.abstract.contract.line" + _order = "sequence,id" - sequence = fields.Integer( - string="Sequence", - ) + sequence = fields.Integer(string="Sequence",) contract_id = fields.Many2one( - comodel_name='contract.contract', - string='Contract', + comodel_name="contract.contract", + string="Contract", required=True, index=True, auto_join=True, - ondelete='cascade', + ondelete="cascade", ) analytic_account_id = fields.Many2one( - string="Analytic account", - comodel_name='account.analytic.account', + string="Analytic account", comodel_name="account.analytic.account", ) analytic_tag_ids = fields.Many2many( - comodel_name='account.analytic.tag', - string='Analytic Tags', + comodel_name="account.analytic.tag", string="Analytic Tags", ) date_start = fields.Date( - string='Date Start', + string="Date Start", required=True, default=lambda self: fields.Date.context_today(self), ) - date_end = fields.Date(string='Date End', index=True) - recurring_next_date = fields.Date(string='Date of Next Invoice') + date_end = fields.Date(string="Date End", index=True) + recurring_next_date = fields.Date(string="Date of Next Invoice") last_date_invoiced = fields.Date( - string='Last Date Invoiced', readonly=True, copy=False + string="Last Date Invoiced", readonly=True, copy=False ) next_period_date_start = fields.Date( - string='Next Period Start', - compute='_compute_next_period_date_start', + string="Next Period Start", compute="_compute_next_period_date_start", ) next_period_date_end = fields.Date( - string='Next Period End', - compute='_compute_next_period_date_end', + string="Next Period End", compute="_compute_next_period_date_end", ) termination_notice_date = fields.Date( - string='Termination notice date', + string="Termination notice date", compute="_compute_termination_notice_date", store=True, copy=False, ) create_invoice_visibility = fields.Boolean( - compute='_compute_create_invoice_visibility' + compute="_compute_create_invoice_visibility" ) successor_contract_line_id = fields.Many2one( - comodel_name='contract.line', + comodel_name="contract.line", string="Successor Contract Line", required=False, readonly=True, @@ -74,7 +69,7 @@ class ContractLine(models.Model): "contract line created.", ) predecessor_contract_line_id = fields.Many2one( - comodel_name='contract.line', + comodel_name="contract.line", string="Predecessor Contract Line", required=False, readonly=True, @@ -90,32 +85,30 @@ class ContractLine(models.Model): "successor in advance", ) is_plan_successor_allowed = fields.Boolean( - string="Plan successor allowed?", compute='_compute_allowed' + string="Plan successor allowed?", compute="_compute_allowed" ) is_stop_plan_successor_allowed = fields.Boolean( - string="Stop/Plan successor allowed?", compute='_compute_allowed' - ) - is_stop_allowed = fields.Boolean( - string="Stop allowed?", compute='_compute_allowed' + string="Stop/Plan successor allowed?", compute="_compute_allowed" ) + is_stop_allowed = fields.Boolean(string="Stop allowed?", compute="_compute_allowed") is_cancel_allowed = fields.Boolean( - string="Cancel allowed?", compute='_compute_allowed' + string="Cancel allowed?", compute="_compute_allowed" ) is_un_cancel_allowed = fields.Boolean( - string="Un-Cancel allowed?", compute='_compute_allowed' + string="Un-Cancel allowed?", compute="_compute_allowed" ) state = fields.Selection( string="State", selection=[ - ('upcoming', 'Upcoming'), - ('in-progress', 'In-progress'), - ('to-renew', 'To renew'), - ('upcoming-close', 'Upcoming Close'), - ('closed', 'Closed'), - ('canceled', 'Canceled'), + ("upcoming", "Upcoming"), + ("in-progress", "In-progress"), + ("to-renew", "To renew"), + ("upcoming-close", "Upcoming Close"), + ("closed", "Closed"), + ("canceled", "Canceled"), ], compute="_compute_state", - search='_search_state', + search="_search_state", ) active = fields.Boolean( string="Active", @@ -127,23 +120,17 @@ class ContractLine(models.Model): @api.multi @api.depends( - 'date_end', - 'termination_notice_rule_type', - 'termination_notice_interval', + "date_end", "termination_notice_rule_type", "termination_notice_interval", ) def _compute_termination_notice_date(self): for rec in self: if rec.date_end: - rec.termination_notice_date = ( - rec.date_end - - self.get_relative_delta( - rec.termination_notice_rule_type, - rec.termination_notice_interval, - ) + rec.termination_notice_date = rec.date_end - self.get_relative_delta( + rec.termination_notice_rule_type, rec.termination_notice_interval, ) @api.multi - @api.depends('is_canceled', 'date_start', 'date_end', 'is_auto_renew') + @api.depends("is_canceled", "date_start", "date_end", "is_auto_renew") def _compute_state(self): today = fields.Date.context_today(self) for rec in self: @@ -151,12 +138,12 @@ class ContractLine(models.Model): rec.state = False continue if rec.is_canceled: - rec.state = 'canceled' + rec.state = "canceled" continue if rec.date_start and rec.date_start > today: # Before period - rec.state = 'upcoming' + rec.state = "upcoming" continue if ( rec.date_start @@ -170,9 +157,9 @@ class ContractLine(models.Model): and not rec.is_auto_renew and not rec.manual_renew_needed ): - rec.state = 'upcoming-close' + rec.state = "upcoming-close" else: - rec.state = 'in-progress' + rec.state = "in-progress" continue if rec.date_end and rec.date_end < today: # After @@ -181,136 +168,138 @@ class ContractLine(models.Model): and not rec.successor_contract_line_id or rec.is_auto_renew ): - rec.state = 'to-renew' + rec.state = "to-renew" else: - rec.state = 'closed' + rec.state = "closed" @api.model def _get_state_domain(self, state): today = fields.Date.context_today(self) - if state == 'upcoming': + if state == "upcoming": return [ "&", - ('date_start', '>', today), - ('is_canceled', '=', False), + ("date_start", ">", today), + ("is_canceled", "=", False), ] - if state == 'in-progress': + if state == "in-progress": return [ "&", "&", "&", - ('date_start', '<=', today), - ('is_canceled', '=', False), + ("date_start", "<=", today), + ("is_canceled", "=", False), "|", - ('date_end', '>=', today), - ('date_end', '=', False), + ("date_end", ">=", today), + ("date_end", "=", False), "|", "&", - ('is_auto_renew', '=', True), - ('is_auto_renew', '=', False), - ('termination_notice_date', '>', today), + ("is_auto_renew", "=", True), + ("is_auto_renew", "=", False), + ("termination_notice_date", ">", today), ] - if state == 'to-renew': + if state == "to-renew": return [ "&", "&", - ('is_canceled', '=', False), - ('date_end', '<', today), + ("is_canceled", "=", False), + ("date_end", "<", today), "|", "&", - ('manual_renew_needed', '=', True), - ('successor_contract_line_id', '=', False), - ('is_auto_renew', '=', True), + ("manual_renew_needed", "=", True), + ("successor_contract_line_id", "=", False), + ("is_auto_renew", "=", True), ] - if state == 'upcoming-close': + if state == "upcoming-close": return [ "&", "&", "&", "&", "&", - ('date_start', '<=', today), - ('is_auto_renew', '=', False), - ('manual_renew_needed', '=', False), - ('is_canceled', '=', False), - ('termination_notice_date', '<', today), - ('date_end', '>=', today), + ("date_start", "<=", today), + ("is_auto_renew", "=", False), + ("manual_renew_needed", "=", False), + ("is_canceled", "=", False), + ("termination_notice_date", "<", today), + ("date_end", ">=", today), ] - if state == 'closed': + if state == "closed": return [ "&", "&", "&", - ('is_canceled', '=', False), - ('date_end', '<', today), - ('is_auto_renew', '=', False), + ("is_canceled", "=", False), + ("date_end", "<", today), + ("is_auto_renew", "=", False), "|", "&", - ('manual_renew_needed', '=', True), - ('successor_contract_line_id', '!=', False), - ('manual_renew_needed', '=', False), + ("manual_renew_needed", "=", True), + ("successor_contract_line_id", "!=", False), + ("manual_renew_needed", "=", False), ] - if state == 'canceled': - return [('is_canceled', '=', True)] + if state == "canceled": + return [("is_canceled", "=", True)] if not state: - return [('display_type', '!=', False)] + return [("display_type", "!=", False)] @api.model def _search_state(self, operator, value): states = [ - 'upcoming', - 'in-progress', - 'to-renew', - 'upcoming-close', - 'closed', - 'canceled', + "upcoming", + "in-progress", + "to-renew", + "upcoming-close", + "closed", + "canceled", False, ] - if operator == '=': + if operator == "=": return self._get_state_domain(value) - if operator == '!=': + if operator == "!=": domain = [] for state in states: if state != value: if domain: - domain.insert(0, '|') + domain.insert(0, "|") domain.extend(self._get_state_domain(state)) return domain - if operator == 'in': + if operator == "in": domain = [] for state in value: if domain: - domain.insert(0, '|') + domain.insert(0, "|") domain.extend(self._get_state_domain(state)) return domain - if operator == 'not in': + if operator == "not in": if set(value) == set(states): - return [('id', '=', False)] + return [("id", "=", False)] return self._search_state( - 'in', [state for state in states if state not in value] + "in", [state for state in states if state not in value] ) @api.depends( - 'date_start', - 'date_end', - 'last_date_invoiced', - 'is_auto_renew', - 'successor_contract_line_id', - 'predecessor_contract_line_id', - 'is_canceled', - 'contract_id.is_terminated', + "date_start", + "date_end", + "last_date_invoiced", + "is_auto_renew", + "successor_contract_line_id", + "predecessor_contract_line_id", + "is_canceled", + "contract_id.is_terminated", ) def _compute_allowed(self): for rec in self: if rec.contract_id.is_terminated: - rec.update({ - 'is_plan_successor_allowed': False, - 'is_stop_plan_successor_allowed': False, - 'is_stop_allowed': False, - 'is_cancel_allowed': False, - 'is_un_cancel_allowed': False, - }) + rec.update( + { + "is_plan_successor_allowed": False, + "is_stop_plan_successor_allowed": False, + "is_stop_allowed": False, + "is_cancel_allowed": False, + "is_un_cancel_allowed": False, + } + ) continue if rec.date_start: allowed = get_allowed( @@ -323,16 +312,17 @@ class ContractLine(models.Model): rec.is_canceled, ) if allowed: - rec.update({ - 'is_plan_successor_allowed': allowed.plan_successor, - 'is_stop_plan_successor_allowed': - allowed.stop_plan_successor, - 'is_stop_allowed': allowed.stop, - 'is_cancel_allowed': allowed.cancel, - 'is_un_cancel_allowed': allowed.uncancel, - }) + rec.update( + { + "is_plan_successor_allowed": allowed.plan_successor, + "is_stop_plan_successor_allowed": allowed.stop_plan_successor, + "is_stop_allowed": allowed.stop, + "is_cancel_allowed": allowed.cancel, + "is_un_cancel_allowed": allowed.uncancel, + } + ) - @api.constrains('is_auto_renew', 'successor_contract_line_id', 'date_end') + @api.constrains("is_auto_renew", "successor_contract_line_id", "date_end") def _check_allowed(self): """ logical impossible combination: @@ -351,19 +341,14 @@ class ContractLine(models.Model): ) ) if not rec.date_end: - raise ValidationError( - _("An auto-renew line must have a end date") - ) + raise ValidationError(_("An auto-renew line must have a end date")) else: if not rec.date_end and rec.successor_contract_line_id: raise ValidationError( - _( - "A contract line with a successor " - "must have a end date" - ) + _("A contract line with a successor " "must have a end date") ) - @api.constrains('successor_contract_line_id', 'date_end') + @api.constrains("successor_contract_line_id", "date_end") def _check_overlap_successor(self): for rec in self: if rec.date_end and rec.successor_contract_line_id: @@ -372,7 +357,7 @@ class ContractLine(models.Model): _("Contract line and its successor overlapped") ) - @api.constrains('predecessor_contract_line_id', 'date_start') + @api.constrains("predecessor_contract_line_id", "date_start") def _check_overlap_predecessor(self): for rec in self: if rec.predecessor_contract_line_id: @@ -387,7 +372,7 @@ class ContractLine(models.Model): date_start, recurring_invoicing_type, recurring_rule_type, - recurring_interval + recurring_interval, ): # deprecated method for backward compatibility return self.get_next_invoice_date( @@ -419,15 +404,13 @@ class ContractLine(models.Model): ) if not next_period_date_end: return False - if recurring_invoicing_type == 'pre-paid': - recurring_next_date = ( - next_period_date_start - + relativedelta(days=recurring_invoicing_offset) + if recurring_invoicing_type == "pre-paid": + recurring_next_date = next_period_date_start + relativedelta( + days=recurring_invoicing_offset ) else: # post-paid - recurring_next_date = ( - next_period_date_end - + relativedelta(days=recurring_invoicing_offset) + recurring_next_date = next_period_date_end + relativedelta( + days=recurring_invoicing_offset ) return recurring_next_date @@ -459,39 +442,32 @@ class ContractLine(models.Model): # regular algorithm next_period_date_end = ( next_period_date_start - + self.get_relative_delta( - recurring_rule_type, recurring_interval - ) + + self.get_relative_delta(recurring_rule_type, recurring_interval) - relativedelta(days=1) ) else: # special algorithm when the next invoice date is forced - if recurring_invoicing_type == 'pre-paid': + if recurring_invoicing_type == "pre-paid": next_period_date_end = ( next_invoice_date - relativedelta(days=recurring_invoicing_offset) - + self.get_relative_delta( - recurring_rule_type, recurring_interval - ) + + self.get_relative_delta(recurring_rule_type, recurring_interval) - relativedelta(days=1) ) else: # post-paid - next_period_date_end = ( - next_invoice_date - - relativedelta(days=recurring_invoicing_offset) + next_period_date_end = next_invoice_date - relativedelta( + days=recurring_invoicing_offset ) if max_date_end and next_period_date_end > max_date_end: # end date is past max_date_end: trim it next_period_date_end = max_date_end return next_period_date_end - @api.depends('last_date_invoiced', 'date_start', 'date_end') + @api.depends("last_date_invoiced", "date_start", "date_end") def _compute_next_period_date_start(self): for rec in self: if rec.last_date_invoiced: - next_period_date_start = ( - rec.last_date_invoiced + relativedelta(days=1) - ) + next_period_date_start = rec.last_date_invoiced + relativedelta(days=1) else: next_period_date_start = rec.date_start if rec.date_end and next_period_date_start > rec.date_end: @@ -499,13 +475,13 @@ class ContractLine(models.Model): rec.next_period_date_start = next_period_date_start @api.depends( - 'next_period_date_start', - 'recurring_invoicing_type', - 'recurring_invoicing_offset', - 'recurring_rule_type', - 'recurring_interval', - 'date_end', - 'recurring_next_date', + "next_period_date_start", + "recurring_invoicing_type", + "recurring_invoicing_offset", + "recurring_rule_type", + "recurring_interval", + "date_end", + "recurring_next_date", ) def _compute_next_period_date_end(self): for rec in self: @@ -525,38 +501,31 @@ class ContractLine(models.Model): ): return ( date_start - + self.get_relative_delta( - auto_renew_rule_type, auto_renew_interval - ) + + self.get_relative_delta(auto_renew_rule_type, auto_renew_interval) - relativedelta(days=1) ) @api.onchange( - 'date_start', - 'is_auto_renew', - 'auto_renew_rule_type', - 'auto_renew_interval', + "date_start", "is_auto_renew", "auto_renew_rule_type", "auto_renew_interval", ) def _onchange_is_auto_renew(self): """Date end should be auto-computed if a contract line is set to auto_renew""" - for rec in self.filtered('is_auto_renew'): + for rec in self.filtered("is_auto_renew"): if rec.date_start: rec.date_end = self._get_first_date_end( - rec.date_start, - rec.auto_renew_rule_type, - rec.auto_renew_interval, + rec.date_start, rec.auto_renew_rule_type, rec.auto_renew_interval, ) @api.onchange( - 'date_start', - 'date_end', - 'recurring_invoicing_type', - 'recurring_rule_type', - 'recurring_interval', + "date_start", + "date_end", + "recurring_invoicing_type", + "recurring_rule_type", + "recurring_interval", ) def _onchange_date_start(self): - for rec in self.filtered('date_start'): + for rec in self.filtered("date_start"): rec.recurring_next_date = self.get_next_invoice_date( rec.next_period_date_start, rec.recurring_invoicing_type, @@ -566,7 +535,7 @@ class ContractLine(models.Model): max_date_end=rec.date_end, ) - @api.constrains('is_canceled', 'is_auto_renew') + @api.constrains("is_canceled", "is_auto_renew") def _check_auto_renew_canceled_lines(self): for rec in self: if rec.is_canceled and rec.is_auto_renew: @@ -574,9 +543,9 @@ class ContractLine(models.Model): _("A canceled contract line can't be set to auto-renew") ) - @api.constrains('recurring_next_date', 'date_start') + @api.constrains("recurring_next_date", "date_start") def _check_recurring_next_date_start_date(self): - for line in self.filtered('recurring_next_date'): + for line in self.filtered("recurring_next_date"): if line.date_start and line.recurring_next_date: if line.date_start > line.recurring_next_date: raise ValidationError( @@ -588,10 +557,10 @@ class ContractLine(models.Model): ) @api.constrains( - 'date_start', 'date_end', 'last_date_invoiced', 'recurring_next_date' + "date_start", "date_end", "last_date_invoiced", "recurring_next_date" ) def _check_last_date_invoiced(self): - for rec in self.filtered('last_date_invoiced'): + for rec in self.filtered("last_date_invoiced"): if rec.date_start and rec.date_start > rec.last_date_invoiced: raise ValidationError( _( @@ -620,7 +589,7 @@ class ContractLine(models.Model): % rec.name ) - @api.constrains('recurring_next_date') + @api.constrains("recurring_next_date") def _check_recurring_next_date_recurring_invoices(self): for rec in self: if not rec.recurring_next_date and ( @@ -636,9 +605,9 @@ class ContractLine(models.Model): % rec.name ) - @api.constrains('date_start', 'date_end') + @api.constrains("date_start", "date_end") def _check_start_end_dates(self): - for line in self.filtered('date_end'): + for line in self.filtered("date_end"): if line.date_start and line.date_end: if line.date_start > line.date_end: raise ValidationError( @@ -649,14 +618,17 @@ class ContractLine(models.Model): % line.name ) - @api.depends('recurring_next_date', 'date_start', 'date_end') + @api.depends("recurring_next_date", "date_start", "date_end") def _compute_create_invoice_visibility(self): # TODO: depending on the lines, and their order, some sections # have no meaning in certain invoices today = fields.Date.context_today(self) for rec in self: - if ((not rec.display_type or rec.is_recurring_note) - and rec.date_start and today >= rec.date_start): + if ( + (not rec.display_type or rec.is_recurring_note) + and rec.date_start + and today >= rec.date_start + ): rec.create_invoice_visibility = bool(rec.recurring_next_date) else: rec.create_invoice_visibility = False @@ -668,22 +640,26 @@ class ContractLine(models.Model): self.last_date_invoiced, self.recurring_next_date ) invoice_line_vals = { - 'display_type': self.display_type, - 'product_id': self.product_id.id, - 'quantity': self._get_quantity_to_invoice(*dates), - 'uom_id': self.uom_id.id, - 'discount': self.discount, - 'contract_line_id': self.id, + "display_type": self.display_type, + "product_id": self.product_id.id, + "quantity": self._get_quantity_to_invoice(*dates), + "uom_id": self.uom_id.id, + "discount": self.discount, + "contract_line_id": self.id, } if invoice_id: - invoice_line_vals['invoice_id'] = invoice_id.id - invoice_line = self.env['account.invoice.line'].with_context( - force_company=self.contract_id.company_id.id, - ).new(invoice_line_vals) + invoice_line_vals["invoice_id"] = invoice_id.id + invoice_line = ( + self.env["account.invoice.line"] + .with_context(force_company=self.contract_id.company_id.id,) + .new(invoice_line_vals) + ) if invoice_values and not invoice_id: - invoice = self.env['account.invoice'].with_context( - force_company=self.contract_id.company_id.id, - ).new(invoice_values) + invoice = ( + self.env["account.invoice"] + .with_context(force_company=self.contract_id.company_id.id,) + .new(invoice_values) + ) invoice_line.invoice_id = invoice # Get other invoice line values from product onchange invoice_line._onchange_product_id() @@ -692,11 +668,11 @@ class ContractLine(models.Model): name = self._insert_markers(dates[0], dates[1]) invoice_line_vals.update( { - 'sequence': self.sequence, - 'name': name, - 'account_analytic_id': self.analytic_account_id.id, - 'analytic_tag_ids': [(6, 0, self.analytic_tag_ids.ids)], - 'price_unit': self.price_unit, + "sequence": self.sequence, + "name": name, + "account_analytic_id": self.analytic_account_id.id, + "analytic_tag_ids": [(6, 0, self.analytic_tag_ids.ids)], + "price_unit": self.price_unit, } ) return invoice_line_vals @@ -729,16 +705,12 @@ class ContractLine(models.Model): @api.multi def _insert_markers(self, first_date_invoiced, last_date_invoiced): self.ensure_one() - lang_obj = self.env['res.lang'] - lang = lang_obj.search( - [('code', '=', self.contract_id.partner_id.lang)] - ) - date_format = lang.date_format or '%m/%d/%Y' + lang_obj = self.env["res.lang"] + lang = lang_obj.search([("code", "=", self.contract_id.partner_id.lang)]) + date_format = lang.date_format or "%m/%d/%Y" name = self.name - name = name.replace( - '#START#', first_date_invoiced.strftime(date_format) - ) - name = name.replace('#END#', last_date_invoiced.strftime(date_format)) + name = name.replace("#START#", first_date_invoiced.strftime(date_format)) + name = name.replace("#END#", last_date_invoiced.strftime(date_format)) return name @api.multi @@ -753,19 +725,19 @@ class ContractLine(models.Model): rec.recurring_interval, max_date_end=rec.date_end, ) - rec.write({ - "recurring_next_date": recurring_next_date, - "last_date_invoiced": last_date_invoiced, - }) + rec.write( + { + "recurring_next_date": recurring_next_date, + "last_date_invoiced": last_date_invoiced, + } + ) @api.multi def _init_last_date_invoiced(self): """Used to init last_date_invoiced for migration purpose""" for rec in self: - last_date_invoiced = rec.recurring_next_date - relativedelta( - days=1 - ) - if rec.recurring_rule_type == 'monthlylastday': + last_date_invoiced = rec.recurring_next_date - relativedelta(days=1) + if rec.recurring_rule_type == "monthlylastday": last_date_invoiced = ( rec.recurring_next_date - self.get_relative_delta( @@ -773,7 +745,7 @@ class ContractLine(models.Model): ) - relativedelta(days=1) ) - elif rec.recurring_invoicing_type == 'post-paid': + elif rec.recurring_invoicing_type == "post-paid": last_date_invoiced = ( rec.recurring_next_date - self.get_relative_delta( @@ -791,17 +763,17 @@ class ContractLine(models.Model): When added to the first day of the period, it gives the first day of the next period. """ - if recurring_rule_type == 'daily': + if recurring_rule_type == "daily": return relativedelta(days=interval) - elif recurring_rule_type == 'weekly': + elif recurring_rule_type == "weekly": return relativedelta(weeks=interval) - elif recurring_rule_type == 'monthly': + elif recurring_rule_type == "monthly": return relativedelta(months=interval) - elif recurring_rule_type == 'monthlylastday': + elif recurring_rule_type == "monthlylastday": return relativedelta(months=interval, day=1) - elif recurring_rule_type == 'quarterly': + elif recurring_rule_type == "quarterly": return relativedelta(months=3 * interval) - elif recurring_rule_type == 'semesterly': + elif recurring_rule_type == "semesterly": return relativedelta(months=6 * interval) else: return relativedelta(years=interval) @@ -816,10 +788,7 @@ class ContractLine(models.Model): for rec in self: if rec.last_date_invoiced: raise ValidationError( - _( - "You can't delay a contract line " - "invoiced at least one time." - ) + _("You can't delay a contract line " "invoiced at least one time.") ) new_date_start = rec.date_start + delay_delta if rec.date_end: @@ -832,22 +801,24 @@ class ContractLine(models.Model): rec.recurring_invoicing_offset, rec.recurring_rule_type, rec.recurring_interval, - max_date_end=new_date_end + max_date_end=new_date_end, + ) + rec.write( + { + "date_start": new_date_start, + "date_end": new_date_end, + "recurring_next_date": new_recurring_next_date, + } ) - rec.write({ - "date_start": new_date_start, - "date_end": new_date_end, - "recurring_next_date": new_recurring_next_date, - }) @api.multi def _prepare_value_for_stop(self, date_end, manual_renew_needed): self.ensure_one() return { - 'date_end': date_end, - 'is_auto_renew': False, - 'manual_renew_needed': manual_renew_needed, - 'recurring_next_date': self.get_next_invoice_date( + "date_end": date_end, + "is_auto_renew": False, + "manual_renew_needed": manual_renew_needed, + "recurring_next_date": self.get_next_invoice_date( self.next_period_date_start, self.recurring_invoicing_type, self.recurring_invoicing_offset, @@ -865,8 +836,8 @@ class ContractLine(models.Model): :param date_end: new date end for contract line :return: True """ - if not all(self.mapped('is_stop_allowed')): - raise ValidationError(_('Stop not allowed for this line')) + if not all(self.mapped("is_stop_allowed")): + raise ValidationError(_("Stop not allowed for this line")) for rec in self: if date_end < rec.date_start: rec.cancel() @@ -874,9 +845,7 @@ class ContractLine(models.Model): if not rec.date_end or rec.date_end > date_end: old_date_end = rec.date_end rec.write( - rec._prepare_value_for_stop( - date_end, manual_renew_needed - ) + rec._prepare_value_for_stop(date_end, manual_renew_needed) ) if post_message: msg = _( @@ -893,7 +862,7 @@ class ContractLine(models.Model): else: rec.write( { - 'is_auto_renew': False, + "is_auto_renew": False, "manual_renew_needed": manual_renew_needed, } ) @@ -917,11 +886,11 @@ class ContractLine(models.Model): new_vals.pop("id", None) new_vals.pop("last_date_invoiced", None) values = self._convert_to_write(new_vals) - values['date_start'] = date_start - values['date_end'] = date_end - values['recurring_next_date'] = recurring_next_date - values['is_auto_renew'] = is_auto_renew - values['predecessor_contract_line_id'] = self.id + values["date_start"] = date_start + values["date_end"] = date_end + values["recurring_next_date"] = recurring_next_date + values["is_auto_renew"] = is_auto_renew + values["predecessor_contract_line_id"] = self.id return values @api.multi @@ -942,12 +911,10 @@ class ContractLine(models.Model): successor_contract_line :return: successor_contract_line """ - contract_line = self.env['contract.line'] + contract_line = self.env["contract.line"] for rec in self: if not rec.is_plan_successor_allowed: - raise ValidationError( - _('Plan successor not allowed for this line') - ) + raise ValidationError(_("Plan successor not allowed for this line")) rec.is_auto_renew = False new_line = self.create( rec._prepare_value_for_plan_successor( @@ -1005,11 +972,9 @@ class ContractLine(models.Model): :param is_auto_renew: is the new line is set to auto_renew :return: created contract line """ - if not all(self.mapped('is_stop_plan_successor_allowed')): - raise ValidationError( - _('Stop/Plan successor not allowed for this line') - ) - contract_line = self.env['contract.line'] + if not all(self.mapped("is_stop_plan_successor_allowed")): + raise ValidationError(_("Stop/Plan successor not allowed for this line")) + contract_line = self.env["contract.line"] for rec in self: if rec.date_start >= date_start: if rec.date_start < date_end: @@ -1028,9 +993,7 @@ class ContractLine(models.Model): ): new_date_start = date_end + relativedelta(days=1) new_date_end = ( - date_end - + (rec.date_end - date_start) - + relativedelta(days=1) + date_end + (rec.date_end - date_start) + relativedelta(days=1) ) rec.stop( date_start - relativedelta(days=1), @@ -1038,10 +1001,7 @@ class ContractLine(models.Model): post_message=False, ) contract_line |= rec.plan_successor( - new_date_start, - new_date_end, - is_auto_renew, - post_message=False, + new_date_start, new_date_end, is_auto_renew, post_message=False, ) else: new_date_start = date_end + relativedelta(days=1) @@ -1060,10 +1020,7 @@ class ContractLine(models.Model): post_message=False, ) contract_line |= rec.plan_successor( - new_date_start, - new_date_end, - is_auto_renew, - post_message=False, + new_date_start, new_date_end, is_auto_renew, post_message=False, ) msg = _( """Contract line for {product} @@ -1072,9 +1029,7 @@ class ContractLine(models.Model):
- Suspension End: {new_date_end} """.format( - product=rec.name, - new_date_start=date_start, - new_date_end=date_end, + product=rec.name, new_date_start=date_start, new_date_end=date_end, ) ) rec.contract_id.message_post(body=msg) @@ -1082,38 +1037,32 @@ class ContractLine(models.Model): @api.multi def cancel(self): - if not all(self.mapped('is_cancel_allowed')): - raise ValidationError(_('Cancel not allowed for this line')) - for contract in self.mapped('contract_id'): + if not all(self.mapped("is_cancel_allowed")): + raise ValidationError(_("Cancel not allowed for this line")) + for contract in self.mapped("contract_id"): lines = self.filtered(lambda l, c=contract: l.contract_id == c) msg = _( """Contract line canceled: %s""" % "
- ".join( - [ - "%s" % name - for name in lines.mapped('name') - ] + ["%s" % name for name in lines.mapped("name")] ) ) contract.message_post(body=msg) - self.mapped('predecessor_contract_line_id').write( - {'successor_contract_line_id': False} + self.mapped("predecessor_contract_line_id").write( + {"successor_contract_line_id": False} ) - return self.write({'is_canceled': True, 'is_auto_renew': False}) + return self.write({"is_canceled": True, "is_auto_renew": False}) @api.multi def uncancel(self, recurring_next_date): - if not all(self.mapped('is_un_cancel_allowed')): - raise ValidationError(_('Un-cancel not allowed for this line')) - for contract in self.mapped('contract_id'): + if not all(self.mapped("is_un_cancel_allowed")): + raise ValidationError(_("Un-cancel not allowed for this line")) + for contract in self.mapped("contract_id"): lines = self.filtered(lambda l, c=contract: l.contract_id == c) msg = _( """Contract line Un-canceled: %s""" % "
- ".join( - [ - "%s" % name - for name in lines.mapped('name') - ] + ["%s" % name for name in lines.mapped("name")] ) ) contract.message_post(body=msg) @@ -1130,88 +1079,84 @@ class ContractLine(models.Model): def action_uncancel(self): self.ensure_one() context = { - 'default_contract_line_id': self.id, - 'default_recurring_next_date': fields.Date.context_today(self), + "default_contract_line_id": self.id, + "default_recurring_next_date": fields.Date.context_today(self), } context.update(self.env.context) - view_id = self.env.ref( - 'contract.contract_line_wizard_uncancel_form_view' - ).id + view_id = self.env.ref("contract.contract_line_wizard_uncancel_form_view").id return { - 'type': 'ir.actions.act_window', - 'name': 'Un-Cancel Contract Line', - 'res_model': 'contract.line.wizard', - 'view_type': 'form', - 'view_mode': 'form', - 'views': [(view_id, 'form')], - 'target': 'new', - 'context': context, + "type": "ir.actions.act_window", + "name": "Un-Cancel Contract Line", + "res_model": "contract.line.wizard", + "view_type": "form", + "view_mode": "form", + "views": [(view_id, "form")], + "target": "new", + "context": context, } @api.multi def action_plan_successor(self): self.ensure_one() context = { - 'default_contract_line_id': self.id, - 'default_is_auto_renew': self.is_auto_renew, + "default_contract_line_id": self.id, + "default_is_auto_renew": self.is_auto_renew, } context.update(self.env.context) view_id = self.env.ref( - 'contract.contract_line_wizard_plan_successor_form_view' + "contract.contract_line_wizard_plan_successor_form_view" ).id return { - 'type': 'ir.actions.act_window', - 'name': 'Plan contract line successor', - 'res_model': 'contract.line.wizard', - 'view_type': 'form', - 'view_mode': 'form', - 'views': [(view_id, 'form')], - 'target': 'new', - 'context': context, + "type": "ir.actions.act_window", + "name": "Plan contract line successor", + "res_model": "contract.line.wizard", + "view_type": "form", + "view_mode": "form", + "views": [(view_id, "form")], + "target": "new", + "context": context, } @api.multi def action_stop(self): self.ensure_one() context = { - 'default_contract_line_id': self.id, - 'default_date_end': self.date_end, + "default_contract_line_id": self.id, + "default_date_end": self.date_end, } context.update(self.env.context) - view_id = self.env.ref( - 'contract.contract_line_wizard_stop_form_view' - ).id + view_id = self.env.ref("contract.contract_line_wizard_stop_form_view").id return { - 'type': 'ir.actions.act_window', - 'name': 'Terminate contract line', - 'res_model': 'contract.line.wizard', - 'view_type': 'form', - 'view_mode': 'form', - 'views': [(view_id, 'form')], - 'target': 'new', - 'context': context, + "type": "ir.actions.act_window", + "name": "Terminate contract line", + "res_model": "contract.line.wizard", + "view_type": "form", + "view_mode": "form", + "views": [(view_id, "form")], + "target": "new", + "context": context, } @api.multi def action_stop_plan_successor(self): self.ensure_one() context = { - 'default_contract_line_id': self.id, - 'default_is_auto_renew': self.is_auto_renew, + "default_contract_line_id": self.id, + "default_is_auto_renew": self.is_auto_renew, } context.update(self.env.context) view_id = self.env.ref( - 'contract.contract_line_wizard_stop_plan_successor_form_view' + "contract.contract_line_wizard_stop_plan_successor_form_view" ).id return { - 'type': 'ir.actions.act_window', - 'name': 'Suspend contract line', - 'res_model': 'contract.line.wizard', - 'view_type': 'form', - 'view_mode': 'form', - 'views': [(view_id, 'form')], - 'target': 'new', - 'context': context, + "type": "ir.actions.act_window", + "name": "Suspend contract line", + "res_model": "contract.line.wizard", + "view_type": "form", + "view_mode": "form", + "views": [(view_id, "form")], + "target": "new", + "context": context, } @api.multi @@ -1243,7 +1188,7 @@ class ContractLine(models.Model): @api.multi def renew(self): - res = self.env['contract.line'] + res = self.env["contract.line"] for rec in self: company = rec.contract_id.company_id date_end = rec._get_renewal_new_date_end() @@ -1260,9 +1205,7 @@ class ContractLine(models.Model):
- End: {new_date_end} """.format( - product=rec.name, - new_date_start=date_start, - new_date_end=date_end, + product=rec.name, new_date_start=date_start, new_date_end=date_end, ) ) rec.contract_id.message_post(body=msg) @@ -1271,10 +1214,10 @@ class ContractLine(models.Model): @api.model def _contract_line_to_renew_domain(self): return [ - ('contract_id.is_terminated', '=', False), - ('is_auto_renew', '=', True), - ('is_canceled', '=', False), - ('termination_notice_date', '<=', fields.Date.context_today(self)), + ("contract_id.is_terminated", "=", False), + ("is_auto_renew", "=", True), + ("is_canceled", "=", False), + ("termination_notice_date", "<=", fields.Date.context_today(self)), ] @api.model @@ -1285,34 +1228,24 @@ class ContractLine(models.Model): @api.model def fields_view_get( - self, view_id=None, view_type='form', toolbar=False, submenu=False + self, view_id=None, view_type="form", toolbar=False, submenu=False ): - 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.contract_line_supplier_tree_view' - ).id - if view_type == 'form': - if default_contract_type == 'purchase': - view_id = self.env.ref( - 'contract.contract_line_supplier_form_view' - ).id - elif default_contract_type == 'sale': - view_id = self.env.ref( - 'contract.contract_line_customer_form_view' - ).id - return super().fields_view_get( - view_id, view_type, toolbar, submenu - ) + 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.contract_line_supplier_tree_view").id + if view_type == "form": + if default_contract_type == "purchase": + view_id = self.env.ref("contract.contract_line_supplier_form_view").id + elif default_contract_type == "sale": + view_id = self.env.ref("contract.contract_line_customer_form_view").id + return super().fields_view_get(view_id, view_type, toolbar, submenu) @api.multi def unlink(self): """stop unlink uncnacled lines""" for record in self: if not (record.is_canceled or record.display_type): - raise ValidationError( - _("Contract line must be canceled before delete") - ) + raise ValidationError(_("Contract line must be canceled before delete")) return super().unlink() @api.multi diff --git a/contract/models/contract_line_constraints.py b/contract/models/contract_line_constraints.py index b1fa37984..ac7dd7c09 100644 --- a/contract/models/contract_line_constraints.py +++ b/contract/models/contract_line_constraints.py @@ -3,17 +3,18 @@ import itertools from collections import namedtuple + from odoo.fields import Date Criteria = namedtuple( - 'Criteria', + "Criteria", [ - 'when', # Contract line relatively to today (BEFORE, IN, AFTER) - 'has_date_end', # Is date_end set on contract line (bool) - 'has_last_date_invoiced', # Is last_date_invoiced set on contract line - 'is_auto_renew', # Is is_auto_renew set on contract line (bool) - 'has_successor', # Is contract line has_successor (bool) - 'predecessor_has_successor', + "when", # Contract line relatively to today (BEFORE, IN, AFTER) + "has_date_end", # Is date_end set on contract line (bool) + "has_last_date_invoiced", # Is last_date_invoiced set on contract line + "is_auto_renew", # Is is_auto_renew set on contract line (bool) + "has_successor", # Is contract line has_successor (bool) + "predecessor_has_successor", # Is contract line predecessor has successor (bool) # In almost of the cases # contract_line.predecessor.successor == contract_line @@ -23,12 +24,11 @@ Criteria = namedtuple( # If contract_line.predecessor.successor != False # and contract_line is canceled, we don't allow uncancel # else we re-link contract_line and its predecessor - 'canceled', # Is contract line canceled (bool) + "canceled", # Is contract line canceled (bool) ], ) Allowed = namedtuple( - 'Allowed', - ['plan_successor', 'stop_plan_successor', 'stop', 'cancel', 'uncancel'], + "Allowed", ["plan_successor", "stop_plan_successor", "stop", "cancel", "uncancel"], ) @@ -36,8 +36,8 @@ def _expand_none(criteria): variations = [] for attribute, value in criteria._asdict().items(): if value is None: - if attribute == 'when': - variations.append(['BEFORE', 'IN', 'AFTER']) + if attribute == "when": + variations.append(["BEFORE", "IN", "AFTER"]) else: variations.append([True, False]) else: @@ -53,7 +53,7 @@ def _add(matrix, criteria, allowed): CRITERIA_ALLOWED_DICT = { Criteria( - when='BEFORE', + when="BEFORE", has_date_end=True, has_last_date_invoiced=False, is_auto_renew=True, @@ -68,7 +68,7 @@ CRITERIA_ALLOWED_DICT = { uncancel=False, ), Criteria( - when='BEFORE', + when="BEFORE", has_date_end=True, has_last_date_invoiced=False, is_auto_renew=False, @@ -83,7 +83,7 @@ CRITERIA_ALLOWED_DICT = { uncancel=False, ), Criteria( - when='BEFORE', + when="BEFORE", has_date_end=True, has_last_date_invoiced=False, is_auto_renew=False, @@ -98,7 +98,7 @@ CRITERIA_ALLOWED_DICT = { uncancel=False, ), Criteria( - when='BEFORE', + when="BEFORE", has_date_end=False, has_last_date_invoiced=False, is_auto_renew=False, @@ -113,7 +113,7 @@ CRITERIA_ALLOWED_DICT = { uncancel=False, ), Criteria( - when='IN', + when="IN", has_date_end=True, has_last_date_invoiced=False, is_auto_renew=True, @@ -128,7 +128,7 @@ CRITERIA_ALLOWED_DICT = { uncancel=False, ), Criteria( - when='IN', + when="IN", has_date_end=True, has_last_date_invoiced=False, is_auto_renew=False, @@ -143,7 +143,7 @@ CRITERIA_ALLOWED_DICT = { uncancel=False, ), Criteria( - when='IN', + when="IN", has_date_end=True, has_last_date_invoiced=False, is_auto_renew=False, @@ -158,7 +158,7 @@ CRITERIA_ALLOWED_DICT = { uncancel=False, ), Criteria( - when='IN', + when="IN", has_date_end=False, has_last_date_invoiced=False, is_auto_renew=False, @@ -173,7 +173,7 @@ CRITERIA_ALLOWED_DICT = { uncancel=False, ), Criteria( - when='BEFORE', + when="BEFORE", has_date_end=True, has_last_date_invoiced=True, is_auto_renew=True, @@ -188,7 +188,7 @@ CRITERIA_ALLOWED_DICT = { uncancel=False, ), Criteria( - when='BEFORE', + when="BEFORE", has_date_end=True, has_last_date_invoiced=True, is_auto_renew=False, @@ -203,7 +203,7 @@ CRITERIA_ALLOWED_DICT = { uncancel=False, ), Criteria( - when='BEFORE', + when="BEFORE", has_date_end=True, has_last_date_invoiced=True, is_auto_renew=False, @@ -218,7 +218,7 @@ CRITERIA_ALLOWED_DICT = { uncancel=False, ), Criteria( - when='BEFORE', + when="BEFORE", has_date_end=False, has_last_date_invoiced=True, is_auto_renew=False, @@ -233,7 +233,7 @@ CRITERIA_ALLOWED_DICT = { uncancel=False, ), Criteria( - when='IN', + when="IN", has_date_end=True, has_last_date_invoiced=True, is_auto_renew=True, @@ -248,7 +248,7 @@ CRITERIA_ALLOWED_DICT = { uncancel=False, ), Criteria( - when='IN', + when="IN", has_date_end=True, has_last_date_invoiced=True, is_auto_renew=False, @@ -263,7 +263,7 @@ CRITERIA_ALLOWED_DICT = { uncancel=False, ), Criteria( - when='IN', + when="IN", has_date_end=True, has_last_date_invoiced=True, is_auto_renew=False, @@ -278,7 +278,7 @@ CRITERIA_ALLOWED_DICT = { uncancel=False, ), Criteria( - when='IN', + when="IN", has_date_end=False, has_last_date_invoiced=True, is_auto_renew=False, @@ -293,7 +293,7 @@ CRITERIA_ALLOWED_DICT = { uncancel=False, ), Criteria( - when='AFTER', + when="AFTER", has_date_end=True, has_last_date_invoiced=None, is_auto_renew=True, @@ -308,7 +308,7 @@ CRITERIA_ALLOWED_DICT = { uncancel=False, ), Criteria( - when='AFTER', + when="AFTER", has_date_end=True, has_last_date_invoiced=None, is_auto_renew=False, @@ -323,7 +323,7 @@ CRITERIA_ALLOWED_DICT = { uncancel=False, ), Criteria( - when='AFTER', + when="AFTER", has_date_end=True, has_last_date_invoiced=None, is_auto_renew=False, @@ -377,10 +377,10 @@ for c in CRITERIA_ALLOWED_DICT: def compute_when(date_start, date_end): today = Date.today() if today < date_start: - return 'BEFORE' + return "BEFORE" if date_end and today > date_end: - return 'AFTER' - return 'IN' + return "AFTER" + return "IN" def compute_criteria( diff --git a/contract/models/contract_tag.py b/contract/models/contract_tag.py index cfe170209..2fb71ae6e 100644 --- a/contract/models/contract_tag.py +++ b/contract/models/contract_tag.py @@ -6,12 +6,10 @@ from odoo import fields, models class ContractTag(models.Model): - _name = 'contract.tag' - _description = 'Contract Tag' + _name = "contract.tag" + _description = "Contract Tag" name = fields.Char(requirment=True) company_id = fields.Many2one( - 'res.company', - string='Company', - default=lambda self: self.env.user.company_id, + "res.company", string="Company", default=lambda self: self.env.user.company_id, ) diff --git a/contract/models/contract_template.py b/contract/models/contract_template.py index 66915c98f..ec2aec826 100644 --- a/contract/models/contract_template.py +++ b/contract/models/contract_template.py @@ -10,13 +10,13 @@ from odoo import fields, models class ContractTemplate(models.Model): - _name = 'contract.template' - _inherit = 'contract.abstract.contract' + _name = "contract.template" + _inherit = "contract.abstract.contract" _description = "Contract Template" contract_line_ids = fields.One2many( - comodel_name='contract.template.line', - inverse_name='contract_id', + comodel_name="contract.template.line", + inverse_name="contract_id", copy=True, - string='Contract template lines', + string="Contract template lines", ) diff --git a/contract/models/contract_template_line.py b/contract/models/contract_template_line.py index 25f0cd52d..cb7cb0ec7 100644 --- a/contract/models/contract_template_line.py +++ b/contract/models/contract_template_line.py @@ -10,15 +10,15 @@ from odoo import fields, models class ContractTemplateLine(models.Model): - _name = 'contract.template.line' - _inherit = 'contract.abstract.contract.line' + _name = "contract.template.line" + _inherit = "contract.abstract.contract.line" _description = "Contract Template Line" _order = "sequence,id" contract_id = fields.Many2one( - string='Contract', - comodel_name='contract.template', + string="Contract", + comodel_name="contract.template", required=True, - ondelete='cascade', - oldname='analytic_account_id', + ondelete="cascade", + oldname="analytic_account_id", ) diff --git a/contract/models/contract_terminate_reason.py b/contract/models/contract_terminate_reason.py index 21f2c0c1c..f5ec8b507 100644 --- a/contract/models/contract_terminate_reason.py +++ b/contract/models/contract_terminate_reason.py @@ -6,8 +6,8 @@ from odoo import fields, models class ContractTerminateReason(models.Model): - _name = 'contract.terminate.reason' - _description = 'Contract Termination Reason' + _name = "contract.terminate.reason" + _description = "Contract Termination Reason" name = fields.Char(required=True) terminate_comment_required = fields.Boolean( diff --git a/contract/models/ir_ui_view.py b/contract/models/ir_ui_view.py index 6897ad1c1..7b0f0c609 100644 --- a/contract/models/ir_ui_view.py +++ b/contract/models/ir_ui_view.py @@ -13,7 +13,9 @@ class IrUiView(models.Model): # TODO Delete this method in v13; it's upstream there result = super()._prepare_qcontext() if self.env.context.get("allowed_company_ids"): - result["res_company"] = self.env["res.company"].browse( - self.env.context["allowed_company_ids"][0] - ).sudo() + result["res_company"] = ( + self.env["res.company"] + .browse(self.env.context["allowed_company_ids"][0]) + .sudo() + ) return result diff --git a/contract/models/res_company.py b/contract/models/res_company.py index ce53ded81..c43e504ab 100644 --- a/contract/models/res_company.py +++ b/contract/models/res_company.py @@ -6,7 +6,7 @@ from odoo import fields, models class ResCompany(models.Model): - _inherit = 'res.company' + _inherit = "res.company" create_new_line_at_contract_line_renew = fields.Boolean( string="Create New Line At Contract Line Renew", diff --git a/contract/models/res_config_settings.py b/contract/models/res_config_settings.py index 7ab0e91dc..00a784ed6 100644 --- a/contract/models/res_config_settings.py +++ b/contract/models/res_config_settings.py @@ -6,7 +6,7 @@ from odoo import fields, models class ResConfigSettings(models.TransientModel): - _inherit = 'res.config.settings' + _inherit = "res.config.settings" create_new_line_at_contract_line_renew = fields.Boolean( related="company_id.create_new_line_at_contract_line_renew", diff --git a/contract/models/res_partner.py b/contract/models/res_partner.py index 0e4e7149b..b4805492e 100644 --- a/contract/models/res_partner.py +++ b/contract/models/res_partner.py @@ -5,45 +5,49 @@ from odoo import fields, models class ResPartner(models.Model): - _inherit = 'res.partner' + _inherit = "res.partner" sale_contract_count = fields.Integer( - string='Sale Contracts', - compute='_compute_contract_count', + string="Sale Contracts", compute="_compute_contract_count", ) purchase_contract_count = fields.Integer( - string='Purchase Contracts', - compute='_compute_contract_count', + string="Purchase Contracts", compute="_compute_contract_count", ) contract_ids = fields.One2many( - comodel_name='contract.contract', - inverse='partner_id', - string="Contracts", + comodel_name="contract.contract", inverse="partner_id", string="Contracts", ) def _compute_contract_count(self): - contract_model = self.env['contract.contract'] - fetch_data = contract_model.read_group([ - ('partner_id', 'child_of', self.ids)], - ['partner_id', 'contract_type'], ['partner_id', 'contract_type'], - lazy=False) - result = [[data['partner_id'][0], data['contract_type'], - data['__count']] for data in fetch_data] + contract_model = self.env["contract.contract"] + fetch_data = contract_model.read_group( + [("partner_id", "child_of", self.ids)], + ["partner_id", "contract_type"], + ["partner_id", "contract_type"], + lazy=False, + ) + result = [ + [data["partner_id"][0], data["contract_type"], data["__count"]] + for data in fetch_data + ] for partner in self: partner_child_ids = partner.child_ids.ids + partner.ids - partner.sale_contract_count = sum([ - r[2] for r in result - if r[0] in partner_child_ids and r[1] == 'sale']) - partner.purchase_contract_count = sum([ - r[2] for r in result - if r[0] in partner_child_ids and r[1] == 'purchase']) + partner.sale_contract_count = sum( + [r[2] for r in result if r[0] in partner_child_ids and r[1] == "sale"] + ) + partner.purchase_contract_count = sum( + [ + r[2] + for r in result + if r[0] in partner_child_ids and r[1] == "purchase" + ] + ) def act_show_contract(self): """ This opens contract view @return: the contract view """ self.ensure_one() - contract_type = self._context.get('contract_type') + contract_type = self._context.get("contract_type") res = self._get_act_window_contract_xml(contract_type) res.update( @@ -57,11 +61,11 @@ class ResPartner(models.Model): return res 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_supplier_contract' + if contract_type == "purchase": + return self.env["ir.actions.act_window"].for_xml_id( + "contract", "action_supplier_contract" ) else: - return self.env['ir.actions.act_window'].for_xml_id( - 'contract', 'action_customer_contract' + return self.env["ir.actions.act_window"].for_xml_id( + "contract", "action_customer_contract" ) diff --git a/contract/report/contract_views.xml b/contract/report/contract_views.xml index 81030664e..1dcabeeb4 100644 --- a/contract/report/contract_views.xml +++ b/contract/report/contract_views.xml @@ -1,12 +1,11 @@ - + - - + file="contract.report_contract" + /> diff --git a/contract/report/report_contract.xml b/contract/report/report_contract.xml index c66f538ef..4a2ead661 100644 --- a/contract/report/report_contract.xml +++ b/contract/report/report_contract.xml @@ -1,80 +1,125 @@ - - diff --git a/contract/security/contract_security.xml b/contract/security/contract_security.xml index ee648bbea..796169942 100644 --- a/contract/security/contract_security.xml +++ b/contract/security/contract_security.xml @@ -1,31 +1,34 @@ - Contract contract multi-company - - - ['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])] + + + ['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])] - Contract line multi-company - - - ['|', ('contract_id.company_id', '=', False), ('contract_id.company_id', 'child_of', [user.company_id.id])] + + + ['|', ('contract_id.company_id', '=', False), ('contract_id.company_id', 'child_of', [user.company_id.id])] - Contract template multi-company - - - ['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])] + + + ['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])] - Contract template line multi-company - - - ['|', ('contract_id.company_id', '=', False), ('contract_id.company_id', 'child_of', [user.company_id.id])] + + + ['|', ('contract_id.company_id', '=', False), ('contract_id.company_id', 'child_of', [user.company_id.id])] - diff --git a/contract/security/contract_tag.xml b/contract/security/contract_tag.xml index 8866afaee..459c0e009 100644 --- a/contract/security/contract_tag.xml +++ b/contract/security/contract_tag.xml @@ -1,23 +1,21 @@ - + - - contract.tag access - - - - - - + + + + + + - Contract tag multi-company - - ['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])] + + ['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])] - diff --git a/contract/security/contract_terminate_reason.xml b/contract/security/contract_terminate_reason.xml index b34cd9089..5da45af92 100644 --- a/contract/security/contract_terminate_reason.xml +++ b/contract/security/contract_terminate_reason.xml @@ -1,27 +1,23 @@ - + - - contract.terminate.reason access manager - - - - - - + + + + + + - contract.terminate.reason access user - - - - - - + + + + + + - diff --git a/contract/security/groups.xml b/contract/security/groups.xml index a954b2a21..428a1b783 100644 --- a/contract/security/groups.xml +++ b/contract/security/groups.xml @@ -1,12 +1,9 @@ - + - - Contract: Can Terminate Contracts - + - diff --git a/contract/static/src/js/section_and_note_fields_backend.js b/contract/static/src/js/section_and_note_fields_backend.js index ff63ecf74..1ad69ad94 100644 --- a/contract/static/src/js/section_and_note_fields_backend.js +++ b/contract/static/src/js/section_and_note_fields_backend.js @@ -2,37 +2,37 @@ * License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). */ /* - If in the sub-tree view where the sections and notes are to be used -there are fields that have defined in the XML attrs = {'invisible': ....} -and this condition is met, then an extra space appears in the rows + If in the sub-tree view where the sections and notes are to be used +there are fields that have defined in the XML attrs = {'invisible': ....} +and this condition is met, then an extra space appears in the rows corresponding to the sections and lines. - This js was written to deal with that problem, but a solution based on + This js was written to deal with that problem, but a solution based on this can be applied directly to Odoo*/ -odoo.define('contract.section_and_note_backend', function (require) { +odoo.define("contract.section_and_note_backend", function(require) { "use strict"; - var fieldRegistry = require('web.field_registry'); - var section_and_note_one2many = fieldRegistry.get('section_and_note_one2many'); + var fieldRegistry = require("web.field_registry"); + var section_and_note_one2many = fieldRegistry.get("section_and_note_one2many"); section_and_note_one2many.include({ - _getRenderer: function () { + _getRenderer: function() { var result = this._super.apply(this, arguments); - if (this.view.arch.tag === 'tree') { + if (this.view.arch.tag === "tree") { result.include({ - _renderBodyCell: function (record, node, index, options) { + _renderBodyCell: function(record, node, index, options) { var $cell = this._super.apply(this, arguments); - var isSection = record.data.display_type === 'line_section'; - var isNote = record.data.display_type === 'line_note'; + var isSection = record.data.display_type === "line_section"; + var isNote = record.data.display_type === "line_note"; if (isSection || isNote) { - $cell.removeClass('o_invisible_modifier'); + $cell.removeClass("o_invisible_modifier"); } return $cell; - } - }) + }, + }); } - return result + return result; }, }); }); diff --git a/contract/tests/test_contract.py b/contract/tests/test_contract.py index c795e1eff..e3e6b0524 100644 --- a/contract/tests/test_contract.py +++ b/contract/tests/test_contract.py @@ -4,9 +4,11 @@ from collections import namedtuple from datetime import timedelta + from dateutil.relativedelta import relativedelta + from odoo import fields -from odoo.exceptions import ValidationError, UserError +from odoo.exceptions import UserError, ValidationError from odoo.tests import common @@ -19,107 +21,105 @@ class TestContractBase(common.SavepointCase): def setUpClass(cls): super().setUpClass() cls.today = fields.Date.today() - cls.pricelist = cls.env['product.pricelist'].create({ - 'name': 'pricelist for contract test', - }) - cls.partner = cls.env['res.partner'].create({ - 'name': 'partner test contract', - 'property_product_pricelist': cls.pricelist.id, - }) - cls.product_1 = cls.env.ref('product.product_product_1') - cls.product_2 = cls.env.ref('product.product_product_2') - cls.product_1.taxes_id += cls.env['account.tax'].search( - [('type_tax_use', '=', 'sale')], limit=1 + cls.pricelist = cls.env["product.pricelist"].create( + {"name": "pricelist for contract test",} ) - cls.product_1.description_sale = 'Test description sale' + cls.partner = cls.env["res.partner"].create( + { + "name": "partner test contract", + "property_product_pricelist": cls.pricelist.id, + } + ) + cls.product_1 = cls.env.ref("product.product_product_1") + cls.product_2 = cls.env.ref("product.product_product_2") + cls.product_1.taxes_id += cls.env["account.tax"].search( + [("type_tax_use", "=", "sale")], limit=1 + ) + cls.product_1.description_sale = "Test description sale" cls.line_template_vals = { - 'product_id': cls.product_1.id, - 'name': 'Services from #START# to #END#', - 'quantity': 1, - 'uom_id': cls.product_1.uom_id.id, - 'price_unit': 100, - 'discount': 50, - 'recurring_rule_type': 'yearly', - 'recurring_interval': 1, + "product_id": cls.product_1.id, + "name": "Services from #START# to #END#", + "quantity": 1, + "uom_id": cls.product_1.uom_id.id, + "price_unit": 100, + "discount": 50, + "recurring_rule_type": "yearly", + "recurring_interval": 1, } cls.section_template_vals = { - 'display_type': 'line_section', - 'name': 'Test section', + "display_type": "line_section", + "name": "Test section", } cls.template_vals = { - 'name': 'Test Contract Template', - 'contract_line_ids': [ + "name": "Test Contract Template", + "contract_line_ids": [ (0, 0, cls.section_template_vals), (0, 0, cls.line_template_vals), ], } - cls.template = cls.env['contract.template'].create( - cls.template_vals - ) + cls.template = cls.env["contract.template"].create(cls.template_vals) # For being sure of the applied price - cls.env['product.pricelist.item'].create( + cls.env["product.pricelist.item"].create( { - 'pricelist_id': cls.partner.property_product_pricelist.id, - 'product_id': cls.product_1.id, - 'compute_price': 'formula', - 'base': 'list_price', + "pricelist_id": cls.partner.property_product_pricelist.id, + "product_id": cls.product_1.id, + "compute_price": "formula", + "base": "list_price", } ) - cls.contract = cls.env['contract.contract'].create( + cls.contract = cls.env["contract.contract"].create( { - 'name': 'Test Contract', - 'partner_id': cls.partner.id, - 'pricelist_id': cls.partner.property_product_pricelist.id, + "name": "Test Contract", + "partner_id": cls.partner.id, + "pricelist_id": cls.partner.property_product_pricelist.id, } ) - cls.contract2 = cls.env['contract.contract'].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, - 'contract_type': 'purchase', - 'contract_line_ids': [ + "name": "Test Contract 2", + "partner_id": cls.partner.id, + "pricelist_id": cls.partner.property_product_pricelist.id, + "contract_type": "purchase", + "contract_line_ids": [ ( 0, 0, { - 'product_id': cls.product_1.id, - 'name': 'Services from #START# to #END#', - 'quantity': 1, - 'uom_id': cls.product_1.uom_id.id, - 'price_unit': 100, - 'discount': 50, - 'recurring_rule_type': 'monthly', - 'recurring_interval': 1, - 'date_start': '2018-02-15', - 'recurring_next_date': '2018-02-22', + "product_id": cls.product_1.id, + "name": "Services from #START# to #END#", + "quantity": 1, + "uom_id": cls.product_1.uom_id.id, + "price_unit": 100, + "discount": 50, + "recurring_rule_type": "monthly", + "recurring_interval": 1, + "date_start": "2018-02-15", + "recurring_next_date": "2018-02-22", }, ) ], } ) cls.line_vals = { - 'contract_id': cls.contract.id, - 'product_id': cls.product_1.id, - 'name': 'Services from #START# to #END#', - 'quantity': 1, - 'uom_id': cls.product_1.uom_id.id, - 'price_unit': 100, - 'discount': 50, - 'recurring_rule_type': 'monthly', - 'recurring_interval': 1, - 'date_start': '2018-01-01', - 'recurring_next_date': '2018-01-15', - 'is_auto_renew': False, + "contract_id": cls.contract.id, + "product_id": cls.product_1.id, + "name": "Services from #START# to #END#", + "quantity": 1, + "uom_id": cls.product_1.uom_id.id, + "price_unit": 100, + "discount": 50, + "recurring_rule_type": "monthly", + "recurring_interval": 1, + "date_start": "2018-01-01", + "recurring_next_date": "2018-01-15", + "is_auto_renew": False, } - cls.acct_line = cls.env['contract.line'].create( - cls.line_vals - ) + cls.acct_line = cls.env["contract.line"].create(cls.line_vals) cls.acct_line.product_id.is_auto_renew = True cls.contract.company_id.create_new_line_at_contract_line_renew = True - cls.terminate_reason = cls.env['contract.terminate.reason'].create({ - 'name': 'terminate_reason' - }) + cls.terminate_reason = cls.env["contract.terminate.reason"].create( + {"name": "terminate_reason"} + ) class TestContract(TestContractBase): @@ -127,15 +127,15 @@ class TestContract(TestContractBase): if overrides is None: overrides = {} vals = self.line_vals.copy() - del vals['contract_id'] - del vals['date_start'] - vals['contract_id'] = self.template.id + del vals["contract_id"] + del vals["date_start"] + vals["contract_id"] = self.template.id vals.update(overrides) - return self.env['contract.template.line'].create(vals) + return self.env["contract.template.line"].create(vals) def test_check_discount(self): with self.assertRaises(ValidationError): - self.acct_line.write({'discount': 120}) + self.acct_line.write({"discount": 120}) def test_automatic_price(self): self.acct_line.automatic_price = True @@ -152,214 +152,172 @@ class TestContract(TestContractBase): self.assertEqual(self.acct_line.price_unit, 10) def test_contract(self): - recurring_next_date = to_date('2018-02-15') + recurring_next_date = to_date("2018-02-15") self.assertAlmostEqual(self.acct_line.price_subtotal, 50.0) res = self.acct_line._onchange_product_id() - self.assertIn('uom_id', res['domain']) + self.assertIn("uom_id", res["domain"]) self.acct_line.price_unit = 100.0 self.contract.partner_id = self.partner.id self.contract.recurring_create_invoice() self.invoice_monthly = self.contract._get_related_invoices() self.assertTrue(self.invoice_monthly) - self.assertEqual( - self.acct_line.recurring_next_date, recurring_next_date - ) + self.assertEqual(self.acct_line.recurring_next_date, recurring_next_date) self.inv_line = self.invoice_monthly.invoice_line_ids[0] self.assertTrue(self.inv_line.invoice_line_tax_ids) self.assertAlmostEqual(self.inv_line.price_subtotal, 50.0) self.assertEqual(self.contract.user_id, self.invoice_monthly.user_id) def test_contract_recurring_next_date(self): - recurring_next_date = to_date('2018-01-15') - self.assertEqual( - self.contract.recurring_next_date, recurring_next_date - ) - contract_line = self.acct_line.copy( - {'recurring_next_date': '2018-01-14'} - ) - recurring_next_date = to_date('2018-01-14') - self.assertEqual( - self.contract.recurring_next_date, recurring_next_date - ) + recurring_next_date = to_date("2018-01-15") + self.assertEqual(self.contract.recurring_next_date, recurring_next_date) + contract_line = self.acct_line.copy({"recurring_next_date": "2018-01-14"}) + recurring_next_date = to_date("2018-01-14") + self.assertEqual(self.contract.recurring_next_date, recurring_next_date) contract_line.cancel() - recurring_next_date = to_date('2018-01-15') - self.assertEqual( - self.contract.recurring_next_date, recurring_next_date - ) + recurring_next_date = to_date("2018-01-15") + self.assertEqual(self.contract.recurring_next_date, recurring_next_date) def test_contract_daily(self): - recurring_next_date = to_date('2018-02-23') - last_date_invoiced = to_date('2018-02-22') - self.acct_line.recurring_next_date = '2018-02-22' - self.acct_line.recurring_rule_type = 'daily' + recurring_next_date = to_date("2018-02-23") + last_date_invoiced = to_date("2018-02-22") + self.acct_line.recurring_next_date = "2018-02-22" + self.acct_line.recurring_rule_type = "daily" self.contract.pricelist_id = False self.contract.recurring_create_invoice() invoice_daily = self.contract._get_related_invoices() self.assertTrue(invoice_daily) - self.assertEqual( - self.acct_line.recurring_next_date, recurring_next_date - ) + self.assertEqual(self.acct_line.recurring_next_date, recurring_next_date) self.assertEqual(self.acct_line.last_date_invoiced, last_date_invoiced) def test_contract_weekly_post_paid(self): - recurring_next_date = to_date('2018-03-01') - last_date_invoiced = to_date('2018-02-21') - self.acct_line.recurring_next_date = '2018-02-22' - self.acct_line.recurring_rule_type = 'weekly' - self.acct_line.recurring_invoicing_type = 'post-paid' + recurring_next_date = to_date("2018-03-01") + last_date_invoiced = to_date("2018-02-21") + self.acct_line.recurring_next_date = "2018-02-22" + self.acct_line.recurring_rule_type = "weekly" + self.acct_line.recurring_invoicing_type = "post-paid" self.contract.recurring_create_invoice() invoices_weekly = self.contract._get_related_invoices() self.assertTrue(invoices_weekly) - self.assertEqual( - self.acct_line.recurring_next_date, recurring_next_date - ) + self.assertEqual(self.acct_line.recurring_next_date, recurring_next_date) self.assertEqual(self.acct_line.last_date_invoiced, last_date_invoiced) def test_contract_weekly_pre_paid(self): - recurring_next_date = to_date('2018-03-01') - last_date_invoiced = to_date('2018-02-28') - self.acct_line.recurring_next_date = '2018-02-22' - self.acct_line.recurring_rule_type = 'weekly' - self.acct_line.recurring_invoicing_type = 'pre-paid' + recurring_next_date = to_date("2018-03-01") + last_date_invoiced = to_date("2018-02-28") + self.acct_line.recurring_next_date = "2018-02-22" + self.acct_line.recurring_rule_type = "weekly" + self.acct_line.recurring_invoicing_type = "pre-paid" self.contract.recurring_create_invoice() invoices_weekly = self.contract._get_related_invoices() self.assertTrue(invoices_weekly) - self.assertEqual( - self.acct_line.recurring_next_date, recurring_next_date - ) + self.assertEqual(self.acct_line.recurring_next_date, recurring_next_date) self.assertEqual(self.acct_line.last_date_invoiced, last_date_invoiced) def test_contract_yearly_post_paid(self): - recurring_next_date = to_date('2019-02-22') - last_date_invoiced = to_date('2018-02-21') - self.acct_line.recurring_next_date = '2018-02-22' - self.acct_line.recurring_rule_type = 'yearly' - self.acct_line.recurring_invoicing_type = 'post-paid' + recurring_next_date = to_date("2019-02-22") + last_date_invoiced = to_date("2018-02-21") + self.acct_line.recurring_next_date = "2018-02-22" + self.acct_line.recurring_rule_type = "yearly" + self.acct_line.recurring_invoicing_type = "post-paid" self.contract.recurring_create_invoice() invoices_weekly = self.contract._get_related_invoices() self.assertTrue(invoices_weekly) - self.assertEqual( - self.acct_line.recurring_next_date, recurring_next_date - ) + self.assertEqual(self.acct_line.recurring_next_date, recurring_next_date) self.assertEqual(self.acct_line.last_date_invoiced, last_date_invoiced) def test_contract_yearly_pre_paid(self): - recurring_next_date = to_date('2019-02-22') - last_date_invoiced = to_date('2019-02-21') - self.acct_line.date_end = '2020-02-22' - self.acct_line.recurring_next_date = '2018-02-22' - self.acct_line.recurring_rule_type = 'yearly' - self.acct_line.recurring_invoicing_type = 'pre-paid' + recurring_next_date = to_date("2019-02-22") + last_date_invoiced = to_date("2019-02-21") + self.acct_line.date_end = "2020-02-22" + self.acct_line.recurring_next_date = "2018-02-22" + self.acct_line.recurring_rule_type = "yearly" + self.acct_line.recurring_invoicing_type = "pre-paid" self.contract.recurring_create_invoice() invoices_weekly = self.contract._get_related_invoices() self.assertTrue(invoices_weekly) - self.assertEqual( - self.acct_line.recurring_next_date, recurring_next_date - ) + self.assertEqual(self.acct_line.recurring_next_date, recurring_next_date) self.assertEqual(self.acct_line.last_date_invoiced, last_date_invoiced) def test_contract_monthly_lastday(self): - recurring_next_date = to_date('2018-02-28') - last_date_invoiced = to_date('2018-02-22') - self.acct_line.recurring_next_date = '2018-02-22' - self.acct_line.recurring_invoicing_type = 'post-paid' - self.acct_line.recurring_rule_type = 'monthlylastday' + recurring_next_date = to_date("2018-02-28") + last_date_invoiced = to_date("2018-02-22") + self.acct_line.recurring_next_date = "2018-02-22" + self.acct_line.recurring_invoicing_type = "post-paid" + self.acct_line.recurring_rule_type = "monthlylastday" self.contract.recurring_create_invoice() invoices_monthly_lastday = self.contract._get_related_invoices() self.assertTrue(invoices_monthly_lastday) - self.assertEqual( - self.acct_line.recurring_next_date, recurring_next_date - ) + self.assertEqual(self.acct_line.recurring_next_date, recurring_next_date) self.assertEqual(self.acct_line.last_date_invoiced, last_date_invoiced) def test_contract_quarterly_pre_paid(self): - recurring_next_date = to_date('2018-05-22') - last_date_invoiced = to_date('2018-05-21') - self.acct_line.date_end = '2020-02-22' - self.acct_line.recurring_next_date = '2018-02-22' - self.acct_line.recurring_rule_type = 'quarterly' - self.acct_line.recurring_invoicing_type = 'pre-paid' + recurring_next_date = to_date("2018-05-22") + last_date_invoiced = to_date("2018-05-21") + self.acct_line.date_end = "2020-02-22" + self.acct_line.recurring_next_date = "2018-02-22" + self.acct_line.recurring_rule_type = "quarterly" + self.acct_line.recurring_invoicing_type = "pre-paid" self.contract.recurring_create_invoice() invoices_weekly = self.contract._get_related_invoices() self.assertTrue(invoices_weekly) - self.assertEqual( - self.acct_line.recurring_next_date, recurring_next_date - ) + self.assertEqual(self.acct_line.recurring_next_date, recurring_next_date) self.assertEqual(self.acct_line.last_date_invoiced, last_date_invoiced) def test_contract_quarterly_post_paid(self): - recurring_next_date = to_date('2018-05-22') - last_date_invoiced = to_date('2018-02-21') - self.acct_line.date_end = '2020-02-22' - self.acct_line.recurring_next_date = '2018-02-22' - self.acct_line.recurring_rule_type = 'quarterly' - self.acct_line.recurring_invoicing_type = 'post-paid' + recurring_next_date = to_date("2018-05-22") + last_date_invoiced = to_date("2018-02-21") + self.acct_line.date_end = "2020-02-22" + self.acct_line.recurring_next_date = "2018-02-22" + self.acct_line.recurring_rule_type = "quarterly" + self.acct_line.recurring_invoicing_type = "post-paid" self.contract.recurring_create_invoice() invoices_weekly = self.contract._get_related_invoices() self.assertTrue(invoices_weekly) - self.assertEqual( - self.acct_line.recurring_next_date, recurring_next_date - ) + self.assertEqual(self.acct_line.recurring_next_date, recurring_next_date) self.assertEqual(self.acct_line.last_date_invoiced, last_date_invoiced) def test_contract_semesterly_pre_paid(self): - recurring_next_date = to_date('2018-08-22') - last_date_invoiced = to_date('2018-08-21') - self.acct_line.date_end = '2020-02-22' - self.acct_line.recurring_next_date = '2018-02-22' - self.acct_line.recurring_rule_type = 'semesterly' - self.acct_line.recurring_invoicing_type = 'pre-paid' + recurring_next_date = to_date("2018-08-22") + last_date_invoiced = to_date("2018-08-21") + self.acct_line.date_end = "2020-02-22" + self.acct_line.recurring_next_date = "2018-02-22" + self.acct_line.recurring_rule_type = "semesterly" + self.acct_line.recurring_invoicing_type = "pre-paid" self.contract.recurring_create_invoice() invoices_weekly = self.contract._get_related_invoices() self.assertTrue(invoices_weekly) - self.assertEqual( - self.acct_line.recurring_next_date, recurring_next_date - ) + self.assertEqual(self.acct_line.recurring_next_date, recurring_next_date) self.assertEqual(self.acct_line.last_date_invoiced, last_date_invoiced) def test_contract_semesterly_post_paid(self): - recurring_next_date = to_date('2018-08-22') - last_date_invoiced = to_date('2018-02-21') - self.acct_line.date_end = '2020-02-22' - self.acct_line.recurring_next_date = '2018-02-22' - self.acct_line.recurring_rule_type = 'semesterly' - self.acct_line.recurring_invoicing_type = 'post-paid' + recurring_next_date = to_date("2018-08-22") + last_date_invoiced = to_date("2018-02-21") + self.acct_line.date_end = "2020-02-22" + self.acct_line.recurring_next_date = "2018-02-22" + self.acct_line.recurring_rule_type = "semesterly" + self.acct_line.recurring_invoicing_type = "post-paid" self.contract.recurring_create_invoice() invoices_weekly = self.contract._get_related_invoices() self.assertTrue(invoices_weekly) - self.assertEqual( - self.acct_line.recurring_next_date, recurring_next_date - ) + self.assertEqual(self.acct_line.recurring_next_date, recurring_next_date) self.assertEqual(self.acct_line.last_date_invoiced, last_date_invoiced) def test_last_invoice_post_paid(self): - self.acct_line.date_start = '2018-01-01' - self.acct_line.recurring_invoicing_type = 'post-paid' - self.acct_line.date_end = '2018-03-15' + self.acct_line.date_start = "2018-01-01" + self.acct_line.recurring_invoicing_type = "post-paid" + self.acct_line.date_end = "2018-03-15" self.acct_line._onchange_date_start() self.assertTrue(self.acct_line.create_invoice_visibility) - self.assertEqual( - self.acct_line.recurring_next_date, to_date('2018-02-01') - ) + self.assertEqual(self.acct_line.recurring_next_date, to_date("2018-02-01")) self.assertFalse(self.acct_line.last_date_invoiced) self.contract.recurring_create_invoice() - self.assertEqual( - self.acct_line.recurring_next_date, to_date('2018-03-01') - ) - self.assertEqual( - self.acct_line.last_date_invoiced, to_date('2018-01-31') - ) + self.assertEqual(self.acct_line.recurring_next_date, to_date("2018-03-01")) + self.assertEqual(self.acct_line.last_date_invoiced, to_date("2018-01-31")) self.contract.recurring_create_invoice() - self.assertEqual( - self.acct_line.recurring_next_date, to_date('2018-3-16') - ) - self.assertEqual( - self.acct_line.last_date_invoiced, to_date('2018-02-28') - ) + self.assertEqual(self.acct_line.recurring_next_date, to_date("2018-3-16")) + self.assertEqual(self.acct_line.last_date_invoiced, to_date("2018-02-28")) self.contract.recurring_create_invoice() - self.assertEqual( - self.acct_line.last_date_invoiced, to_date('2018-03-15') - ) + self.assertEqual(self.acct_line.last_date_invoiced, to_date("2018-03-15")) self.assertFalse(self.acct_line.recurring_next_date) self.assertFalse(self.acct_line.create_invoice_visibility) invoices = self.contract._get_related_invoices() @@ -372,33 +330,21 @@ class TestContract(TestContractBase): ) def test_last_invoice_pre_paid(self): - self.acct_line.date_start = '2018-01-01' - self.acct_line.recurring_invoicing_type = 'pre-paid' - self.acct_line.date_end = '2018-03-15' + self.acct_line.date_start = "2018-01-01" + self.acct_line.recurring_invoicing_type = "pre-paid" + self.acct_line.date_end = "2018-03-15" self.acct_line._onchange_date_start() self.assertTrue(self.acct_line.create_invoice_visibility) - self.assertEqual( - self.acct_line.recurring_next_date, to_date('2018-01-01') - ) + self.assertEqual(self.acct_line.recurring_next_date, to_date("2018-01-01")) self.assertFalse(self.acct_line.last_date_invoiced) self.contract.recurring_create_invoice() - self.assertEqual( - self.acct_line.recurring_next_date, to_date('2018-02-01') - ) - self.assertEqual( - self.acct_line.last_date_invoiced, to_date('2018-01-31') - ) + self.assertEqual(self.acct_line.recurring_next_date, to_date("2018-02-01")) + self.assertEqual(self.acct_line.last_date_invoiced, to_date("2018-01-31")) self.contract.recurring_create_invoice() - self.assertEqual( - self.acct_line.last_date_invoiced, to_date('2018-02-28') - ) - self.assertEqual( - self.acct_line.last_date_invoiced, to_date('2018-02-28') - ) + self.assertEqual(self.acct_line.last_date_invoiced, to_date("2018-02-28")) + self.assertEqual(self.acct_line.last_date_invoiced, to_date("2018-02-28")) self.contract.recurring_create_invoice() - self.assertEqual( - self.acct_line.last_date_invoiced, to_date('2018-03-15') - ) + self.assertEqual(self.acct_line.last_date_invoiced, to_date("2018-03-15")) self.assertFalse(self.acct_line.recurring_next_date) self.assertFalse(self.acct_line.create_invoice_visibility) invoices = self.contract._get_related_invoices() @@ -418,25 +364,21 @@ class TestContract(TestContractBase): ) def test_onchange_date_start(self): - recurring_next_date = to_date('2018-01-01') + recurring_next_date = to_date("2018-01-01") self.acct_line.date_start = recurring_next_date self.acct_line._onchange_date_start() - self.assertEqual( - self.acct_line.recurring_next_date, recurring_next_date - ) + self.assertEqual(self.acct_line.recurring_next_date, recurring_next_date) def test_uom(self): - uom_litre = self.env.ref('uom.product_uom_litre') + uom_litre = self.env.ref("uom.product_uom_litre") self.acct_line.uom_id = uom_litre.id self.acct_line._onchange_product_id() - self.assertEqual( - self.acct_line.uom_id, self.acct_line.product_id.uom_id - ) + self.assertEqual(self.acct_line.uom_id, self.acct_line.product_id.uom_id) def test_onchange_product_id(self): - line = self.env['contract.line'].new() + line = self.env["contract.line"].new() res = line._onchange_product_id() - self.assertFalse(res['domain']['uom_id']) + self.assertFalse(res["domain"]["uom_id"]) def test_no_pricelist(self): self.contract.pricelist_id = False @@ -444,22 +386,19 @@ class TestContract(TestContractBase): self.assertAlmostEqual(self.acct_line.price_subtotal, 100.0) def test_check_journal(self): - journal = self.env['account.journal'].search([('type', '=', 'sale')]) - journal.write({'type': 'general'}) + journal = self.env["account.journal"].search([("type", "=", "sale")]) + journal.write({"type": "general"}) with self.assertRaises(ValidationError): self.contract.recurring_create_invoice() def test_check_date_end(self): with self.assertRaises(ValidationError): - self.acct_line.date_end = '2015-12-31' + self.acct_line.date_end = "2015-12-31" def test_check_recurring_next_date_start_date(self): with self.assertRaises(ValidationError): self.acct_line.write( - { - 'date_start': '2018-01-01', - 'recurring_next_date': '2017-01-01', - } + {"date_start": "2018-01-01", "recurring_next_date": "2017-01-01",} ) def test_onchange_contract_template_id(self): @@ -469,32 +408,25 @@ class TestContract(TestContractBase): self.contract.contract_template_id = self.template self.contract._onchange_contract_template_id() res = { - 'contract_line_ids': [ + "contract_line_ids": [ + (0, 0, {"display_type": "line_section", "name": "Test section",}), ( 0, 0, { - 'display_type': 'line_section', - 'name': 'Test section', - } - ), - ( - 0, - 0, - { - 'product_id': self.product_1.id, - 'name': 'Services from #START# to #END#', - 'quantity': 1, - 'uom_id': self.product_1.uom_id.id, - 'price_unit': 100, - 'discount': 50, - 'recurring_rule_type': 'yearly', - 'recurring_interval': 1, + "product_id": self.product_1.id, + "name": "Services from #START# to #END#", + "quantity": 1, + "uom_id": self.product_1.uom_id.id, + "price_unit": 100, + "discount": 50, + "recurring_rule_type": "yearly", + "recurring_interval": 1, }, - ) + ), ] } - del self.template_vals['name'] + del self.template_vals["name"] self.assertDictEqual(res, self.template_vals) def test_onchange_contract_template_id_lines(self): @@ -504,15 +436,14 @@ class TestContract(TestContractBase): self.contract.contract_template_id = self.template self.assertFalse( - self.contract.contract_line_ids, - 'Recurring lines were not removed.', + 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.contract_line_ids), 2) for index, vals in [ (0, self.section_template_vals), - (1, self.line_template_vals) + (1, self.line_template_vals), ]: contract_line = self.contract.contract_line_ids[index] for key, value in vals.items(): @@ -525,52 +456,44 @@ class TestContract(TestContractBase): def test_send_mail_contract(self): result = self.contract.action_contract_send() - self.assertEqual(result['res_model'], 'mail.compose.message') + self.assertEqual(result["res_model"], "mail.compose.message") def test_onchange_contract_type(self): self.contract._onchange_contract_type() - self.assertEqual(self.contract.journal_id.type, 'sale') - self.assertEqual( - self.contract.journal_id.company_id, self.contract.company_id - ) - self.contract.type = 'purchase' + self.assertEqual(self.contract.journal_id.type, "sale") + self.assertEqual(self.contract.journal_id.company_id, self.contract.company_id) + self.contract.type = "purchase" self.contract._onchange_contract_type() - self.assertFalse( - any( - self.contract.contract_line_ids.mapped( - 'automatic_price' - ) - ) - ) + self.assertFalse(any(self.contract.contract_line_ids.mapped("automatic_price"))) def test_contract_onchange_product_id_domain_blank(self): """It should return a blank UoM domain when no product.""" - line = self.env['contract.template.line'].new() + line = self.env["contract.template.line"].new() res = line._onchange_product_id() - self.assertFalse(res['domain']['uom_id']) + self.assertFalse(res["domain"]["uom_id"]) def test_contract_onchange_product_id_domain(self): """It should return UoM category domain.""" line = self._add_template_line() res = line._onchange_product_id() self.assertEqual( - res['domain']['uom_id'][0], - ('category_id', '=', self.product_1.uom_id.category_id.id), + res["domain"]["uom_id"][0], + ("category_id", "=", self.product_1.uom_id.category_id.id), ) def test_contract_onchange_product_id_uom(self): """It should update the UoM for the line.""" line = self._add_template_line( - {'uom_id': self.env.ref('uom.product_uom_litre').id} + {"uom_id": self.env.ref("uom.product_uom_litre").id} ) - line.product_id.uom_id = self.env.ref('uom.product_uom_day').id + line.product_id.uom_id = self.env.ref("uom.product_uom_day").id line._onchange_product_id() self.assertEqual(line.uom_id, line.product_id.uom_id) def test_contract_onchange_product_id_name(self): """It should update the name for the line.""" line = self._add_template_line() - line.product_id.description_sale = 'Test' + line.product_id.description_sale = "Test" line._onchange_product_id() self.assertEqual( line.name, line.product_id.get_product_multiline_description_sale() @@ -591,9 +514,9 @@ class TestContract(TestContractBase): """It should create one invoice with same start and end date.""" self.acct_line.write( { - 'date_start': self.today, - 'date_end': self.today, - 'recurring_next_date': self.today, + "date_start": self.today, + "date_end": self.today, + "recurring_next_date": self.today, } ) self.contract._compute_recurring_next_date() @@ -607,45 +530,34 @@ class TestContract(TestContractBase): def test_act_show_contract(self): show_contract = self.partner.with_context( - contract_type='sale' + contract_type="sale" ).act_show_contract() self.assertDictContainsSubset( { - 'name': 'Customer Contracts', - 'type': 'ir.actions.act_window', - 'view_type': 'form', - 'res_model': 'contract.contract', - 'xml_id': 'contract.action_customer_contract', + "name": "Customer Contracts", + "type": "ir.actions.act_window", + "view_type": "form", + "res_model": "contract.contract", + "xml_id": "contract.action_customer_contract", }, show_contract, - 'There was an error and the view couldn\'t be opened.', + "There was an error and the view couldn't be opened.", ) def test_get_default_recurring_invoicing_offset(self): - clm = self.env['contract.line'] + clm = self.env["contract.line"] self.assertEqual( - clm._get_default_recurring_invoicing_offset( - "pre-paid", "monthly" - ), - 0 + clm._get_default_recurring_invoicing_offset("pre-paid", "monthly"), 0 ) self.assertEqual( - clm._get_default_recurring_invoicing_offset( - "post-paid", "monthly" - ), - 1 + clm._get_default_recurring_invoicing_offset("post-paid", "monthly"), 1 ) self.assertEqual( - clm._get_default_recurring_invoicing_offset( - "pre-paid", "monthlylastday" - ), - 0 + clm._get_default_recurring_invoicing_offset("pre-paid", "monthlylastday"), 0 ) self.assertEqual( - clm._get_default_recurring_invoicing_offset( - "post-paid", "monthlylastday" - ), - 0 + clm._get_default_recurring_invoicing_offset("post-paid", "monthlylastday"), + 0, ) def test_get_next_invoice_date(self): @@ -673,7 +585,8 @@ class TestContract(TestContractBase): ): return ( "Error in %s-%d every %d %s case, " - "start with %s (max_date_end=%s)" % ( + "start with %s (max_date_end=%s)" + % ( recurring_invoicing_type, recurring_invoicing_offset, recurring_interval, @@ -685,83 +598,95 @@ class TestContract(TestContractBase): combinations = [ ( - to_date('2018-01-01'), - (to_date('2018-01-01'), 'pre-paid', 0, 'monthly', 1, - False), + to_date("2018-01-01"), + (to_date("2018-01-01"), "pre-paid", 0, "monthly", 1, False), ), ( - to_date('2018-01-01'), - (to_date('2018-01-01'), 'pre-paid', 0, 'monthly', 1, - to_date('2018-01-15')), + to_date("2018-01-01"), + ( + to_date("2018-01-01"), + "pre-paid", + 0, + "monthly", + 1, + to_date("2018-01-15"), + ), ), ( False, - (to_date('2018-01-16'), 'pre-paid', 0, 'monthly', 1, - to_date('2018-01-15')), + ( + to_date("2018-01-16"), + "pre-paid", + 0, + "monthly", + 1, + to_date("2018-01-15"), + ), ), ( - to_date('2018-01-01'), - (to_date('2018-01-01'), 'pre-paid', 0, 'monthly', 2, - False), + to_date("2018-01-01"), + (to_date("2018-01-01"), "pre-paid", 0, "monthly", 2, False), ), ( - to_date('2018-02-01'), - (to_date('2018-01-01'), 'post-paid', 1, 'monthly', 1, - False), + to_date("2018-02-01"), + (to_date("2018-01-01"), "post-paid", 1, "monthly", 1, False), ), ( - to_date('2018-01-16'), - (to_date('2018-01-01'), 'post-paid', 1, 'monthly', 1, - to_date('2018-01-15')), + to_date("2018-01-16"), + ( + to_date("2018-01-01"), + "post-paid", + 1, + "monthly", + 1, + to_date("2018-01-15"), + ), ), ( False, - (to_date('2018-01-16'), 'post-paid', 1, 'monthly', 1, - to_date('2018-01-15')), + ( + to_date("2018-01-16"), + "post-paid", + 1, + "monthly", + 1, + to_date("2018-01-15"), + ), ), ( - to_date('2018-03-01'), - (to_date('2018-01-01'), 'post-paid', 1, 'monthly', 2, - False), + to_date("2018-03-01"), + (to_date("2018-01-01"), "post-paid", 1, "monthly", 2, False), ), ( - to_date('2018-01-31'), - (to_date('2018-01-05'), 'post-paid', 0, 'monthlylastday', 1, - False), + to_date("2018-01-31"), + (to_date("2018-01-05"), "post-paid", 0, "monthlylastday", 1, False), ), ( - to_date('2018-01-06'), - (to_date('2018-01-06'), 'pre-paid', 0, 'monthlylastday', 1, - False), + to_date("2018-01-06"), + (to_date("2018-01-06"), "pre-paid", 0, "monthlylastday", 1, False), ), ( - to_date('2018-02-28'), - (to_date('2018-01-05'), 'post-paid', 0, 'monthlylastday', 2, - False), + to_date("2018-02-28"), + (to_date("2018-01-05"), "post-paid", 0, "monthlylastday", 2, False), ), ( - to_date('2018-01-05'), - (to_date('2018-01-05'), 'pre-paid', 0, 'monthlylastday', 2, - False), + to_date("2018-01-05"), + (to_date("2018-01-05"), "pre-paid", 0, "monthlylastday", 2, False), ), ( - to_date('2018-01-05'), - (to_date('2018-01-05'), 'pre-paid', 0, 'yearly', 1, - False), + to_date("2018-01-05"), + (to_date("2018-01-05"), "pre-paid", 0, "yearly", 1, False), ), ( - to_date('2019-01-05'), - (to_date('2018-01-05'), 'post-paid', 1, 'yearly', 1, - False), + to_date("2019-01-05"), + (to_date("2018-01-05"), "post-paid", 1, "yearly", 1, False), ), ] - contract_line_env = self.env['contract.line'] + contract_line_env = self.env["contract.line"] for recurring_next_date, combination in combinations: self.assertEqual( recurring_next_date, - contract_line_env.get_next_invoice_date( - *combination - ), + contract_line_env.get_next_invoice_date(*combination), error_message(*combination), ) @@ -799,14 +724,14 @@ class TestContract(TestContractBase): ): self.acct_line.write( { - 'date_start': date_start, - 'date_end': date_end, - 'last_date_invoiced': last_date_invoiced, - 'recurring_next_date': recurring_next_date, - 'recurring_invoicing_type': recurring_invoicing_type, - 'recurring_rule_type': recurring_rule_type, - 'recurring_interval': recurring_interval, - 'max_date_end': max_date_end, + "date_start": date_start, + "date_end": date_end, + "last_date_invoiced": last_date_invoiced, + "recurring_next_date": recurring_next_date, + "recurring_invoicing_type": recurring_invoicing_type, + "recurring_rule_type": recurring_rule_type, + "recurring_interval": recurring_interval, + "max_date_end": max_date_end, } ) @@ -851,247 +776,237 @@ class TestContract(TestContractBase): ) Result = namedtuple( - 'Result', - [ - 'recurring_next_date', - 'next_period_date_start', - 'next_period_date_end', - ], + "Result", + ["recurring_next_date", "next_period_date_start", "next_period_date_end",], ) Combination = namedtuple( - 'Combination', + "Combination", [ - 'case', - 'date_start', - 'date_end', - 'last_date_invoiced', - 'recurring_next_date', - 'recurring_invoicing_type', - 'recurring_rule_type', - 'recurring_interval', - 'max_date_end', + "case", + "date_start", + "date_end", + "last_date_invoiced", + "recurring_next_date", + "recurring_invoicing_type", + "recurring_rule_type", + "recurring_interval", + "max_date_end", ], ) combinations = { Result( - recurring_next_date=to_date('2019-01-01'), - next_period_date_start=to_date('2019-01-01'), - next_period_date_end=to_date('2019-01-31'), + recurring_next_date=to_date("2019-01-01"), + next_period_date_start=to_date("2019-01-01"), + next_period_date_end=to_date("2019-01-31"), ): Combination( case="1", - date_start='2019-01-01', + date_start="2019-01-01", date_end=False, last_date_invoiced=False, - recurring_next_date='2019-01-01', - recurring_invoicing_type='pre-paid', - recurring_rule_type='monthly', + recurring_next_date="2019-01-01", + recurring_invoicing_type="pre-paid", + recurring_rule_type="monthly", recurring_interval=1, max_date_end=False, ), Result( - recurring_next_date=to_date('2019-01-01'), - next_period_date_start=to_date('2019-01-01'), - next_period_date_end=to_date('2019-01-15'), + recurring_next_date=to_date("2019-01-01"), + next_period_date_start=to_date("2019-01-01"), + next_period_date_end=to_date("2019-01-15"), ): Combination( case="2", - date_start='2019-01-01', - date_end='2019-01-15', + date_start="2019-01-01", + date_end="2019-01-15", last_date_invoiced=False, - recurring_next_date='2019-01-01', - recurring_invoicing_type='pre-paid', - recurring_rule_type='monthly', + recurring_next_date="2019-01-01", + recurring_invoicing_type="pre-paid", + recurring_rule_type="monthly", recurring_interval=1, max_date_end=False, ), Result( - recurring_next_date=to_date('2019-01-05'), - next_period_date_start=to_date('2019-01-05'), - next_period_date_end=to_date('2019-01-15'), + recurring_next_date=to_date("2019-01-05"), + next_period_date_start=to_date("2019-01-05"), + next_period_date_end=to_date("2019-01-15"), ): Combination( case="3", - date_start='2019-01-05', - date_end='2019-01-15', + date_start="2019-01-05", + date_end="2019-01-15", last_date_invoiced=False, - recurring_next_date='2019-01-05', - recurring_invoicing_type='pre-paid', - recurring_rule_type='monthly', + recurring_next_date="2019-01-05", + recurring_invoicing_type="pre-paid", + recurring_rule_type="monthly", recurring_interval=1, max_date_end=False, ), Result( - recurring_next_date=to_date('2019-01-05'), - next_period_date_start=to_date('2019-01-01'), - next_period_date_end=to_date('2019-01-15'), + recurring_next_date=to_date("2019-01-05"), + next_period_date_start=to_date("2019-01-01"), + next_period_date_end=to_date("2019-01-15"), ): Combination( case="4", - date_start='2019-01-01', - date_end='2019-01-15', + date_start="2019-01-01", + date_end="2019-01-15", last_date_invoiced=False, - recurring_next_date='2019-01-05', - recurring_invoicing_type='pre-paid', - recurring_rule_type='monthly', + recurring_next_date="2019-01-05", + recurring_invoicing_type="pre-paid", + recurring_rule_type="monthly", recurring_interval=1, max_date_end=False, ), Result( - recurring_next_date=to_date('2019-02-01'), - next_period_date_start=to_date('2019-01-01'), - next_period_date_end=to_date('2019-01-31'), + recurring_next_date=to_date("2019-02-01"), + next_period_date_start=to_date("2019-01-01"), + next_period_date_end=to_date("2019-01-31"), ): Combination( case="5", - date_start='2019-01-01', + date_start="2019-01-01", date_end=False, last_date_invoiced=False, - recurring_next_date='2019-02-01', - recurring_invoicing_type='post-paid', - recurring_rule_type='monthly', + recurring_next_date="2019-02-01", + recurring_invoicing_type="post-paid", + recurring_rule_type="monthly", recurring_interval=1, max_date_end=False, ), Result( - recurring_next_date=to_date('2019-02-01'), - next_period_date_start=to_date('2019-01-01'), - next_period_date_end=to_date('2019-01-15'), + recurring_next_date=to_date("2019-02-01"), + next_period_date_start=to_date("2019-01-01"), + next_period_date_end=to_date("2019-01-15"), ): Combination( case="6", - date_start='2019-01-01', - date_end='2019-01-15', + date_start="2019-01-01", + date_end="2019-01-15", last_date_invoiced=False, - recurring_next_date='2019-02-01', - recurring_invoicing_type='post-paid', - recurring_rule_type='monthly', + recurring_next_date="2019-02-01", + recurring_invoicing_type="post-paid", + recurring_rule_type="monthly", recurring_interval=1, max_date_end=False, ), Result( - recurring_next_date=to_date('2019-02-01'), - next_period_date_start=to_date('2019-01-05'), - next_period_date_end=to_date('2019-01-31'), + recurring_next_date=to_date("2019-02-01"), + next_period_date_start=to_date("2019-01-05"), + next_period_date_end=to_date("2019-01-31"), ): Combination( case="7", - date_start='2019-01-05', + date_start="2019-01-05", date_end=False, last_date_invoiced=False, - recurring_next_date='2019-02-01', - recurring_invoicing_type='post-paid', - recurring_rule_type='monthly', + recurring_next_date="2019-02-01", + recurring_invoicing_type="post-paid", + recurring_rule_type="monthly", recurring_interval=1, max_date_end=False, ), Result( - recurring_next_date=to_date('2019-01-05'), - next_period_date_start=to_date('2019-01-01'), - next_period_date_end=to_date('2019-01-15'), + recurring_next_date=to_date("2019-01-05"), + next_period_date_start=to_date("2019-01-01"), + next_period_date_end=to_date("2019-01-15"), ): Combination( case="8", - date_start='2019-01-01', - date_end='2019-01-15', + date_start="2019-01-01", + date_end="2019-01-15", last_date_invoiced=False, - recurring_next_date='2019-01-05', - recurring_invoicing_type='pre-paid', - recurring_rule_type='monthly', + recurring_next_date="2019-01-05", + recurring_invoicing_type="pre-paid", + recurring_rule_type="monthly", recurring_interval=1, max_date_end=False, ), Result( - recurring_next_date=to_date('2019-01-01'), - next_period_date_start=to_date('2018-12-16'), - next_period_date_end=to_date('2019-01-31'), + recurring_next_date=to_date("2019-01-01"), + next_period_date_start=to_date("2018-12-16"), + next_period_date_end=to_date("2019-01-31"), ): Combination( case="9", - date_start='2018-01-01', - date_end='2020-01-15', - last_date_invoiced='2018-12-15', - recurring_next_date='2019-01-01', - recurring_invoicing_type='pre-paid', - recurring_rule_type='monthly', + date_start="2018-01-01", + date_end="2020-01-15", + last_date_invoiced="2018-12-15", + recurring_next_date="2019-01-01", + recurring_invoicing_type="pre-paid", + recurring_rule_type="monthly", recurring_interval=1, max_date_end=False, ), Result( - recurring_next_date=to_date('2019-01-01'), - next_period_date_start=to_date('2018-12-16'), - next_period_date_end=to_date('2018-12-31'), + recurring_next_date=to_date("2019-01-01"), + next_period_date_start=to_date("2018-12-16"), + next_period_date_end=to_date("2018-12-31"), ): Combination( case="10", - date_start='2018-01-01', - date_end='2020-01-15', - last_date_invoiced='2018-12-15', - recurring_next_date='2019-01-01', - recurring_invoicing_type='post-paid', - recurring_rule_type='monthly', + date_start="2018-01-01", + date_end="2020-01-15", + last_date_invoiced="2018-12-15", + recurring_next_date="2019-01-01", + recurring_invoicing_type="post-paid", + recurring_rule_type="monthly", recurring_interval=1, max_date_end=False, ), Result( - recurring_next_date=to_date('2018-12-31'), - next_period_date_start=to_date('2018-12-16'), - next_period_date_end=to_date('2018-12-31'), + recurring_next_date=to_date("2018-12-31"), + next_period_date_start=to_date("2018-12-16"), + next_period_date_end=to_date("2018-12-31"), ): Combination( case="11", - date_start='2018-01-01', - date_end='2020-01-15', - last_date_invoiced='2018-12-15', - recurring_next_date='2018-12-31', - recurring_invoicing_type='post-paid', - recurring_rule_type='monthlylastday', + date_start="2018-01-01", + date_end="2020-01-15", + last_date_invoiced="2018-12-15", + recurring_next_date="2018-12-31", + recurring_invoicing_type="post-paid", + recurring_rule_type="monthlylastday", recurring_interval=1, max_date_end=False, ), Result( - recurring_next_date=to_date('2018-12-16'), - next_period_date_start=to_date('2018-12-16'), - next_period_date_end=to_date('2018-12-31'), + recurring_next_date=to_date("2018-12-16"), + next_period_date_start=to_date("2018-12-16"), + next_period_date_end=to_date("2018-12-31"), ): Combination( case="12", - date_start='2018-01-01', - date_end='2020-01-15', - last_date_invoiced='2018-12-15', - recurring_next_date='2018-12-16', - recurring_invoicing_type='pre-paid', - recurring_rule_type='monthlylastday', + date_start="2018-01-01", + date_end="2020-01-15", + last_date_invoiced="2018-12-15", + recurring_next_date="2018-12-16", + recurring_invoicing_type="pre-paid", + recurring_rule_type="monthlylastday", recurring_interval=1, max_date_end=False, ), Result( - recurring_next_date=to_date('2018-01-05'), - next_period_date_start=to_date('2018-01-05'), - next_period_date_end=to_date('2018-03-31'), + recurring_next_date=to_date("2018-01-05"), + next_period_date_start=to_date("2018-01-05"), + next_period_date_end=to_date("2018-03-31"), ): Combination( case="12", - date_start='2018-01-05', - date_end='2020-01-15', + date_start="2018-01-05", + date_end="2020-01-15", last_date_invoiced=False, - recurring_next_date='2018-01-05', - recurring_invoicing_type='pre-paid', - recurring_rule_type='monthlylastday', + recurring_next_date="2018-01-05", + recurring_invoicing_type="pre-paid", + recurring_rule_type="monthlylastday", recurring_interval=3, max_date_end=False, ), } for result, combination in combinations.items(): _update_contract_line(*combination) - self.assertEqual( - result, _get_result(), _error_message(*combination) - ) + self.assertEqual(result, _get_result(), _error_message(*combination)) def test_recurring_next_date(self): """recurring next date for a contract is the min for all lines""" self.contract.recurring_create_invoice() self.assertEqual( self.contract.recurring_next_date, - min( - self.contract.contract_line_ids.mapped( - 'recurring_next_date' - ) - ), + min(self.contract.contract_line_ids.mapped("recurring_next_date")), ) def test_date_end(self): """recurring next date for a contract is the min for all lines""" - self.acct_line.date_end = '2018-01-01' + self.acct_line.date_end = "2018-01-01" self.acct_line.copy() - self.acct_line.write({'date_end': False, 'is_auto_renew': False}) + self.acct_line.write({"date_end": False, "is_auto_renew": False}) self.assertFalse(self.contract.date_end) def test_cancel_contract_line(self): @@ -1104,95 +1019,80 @@ class TestContract(TestContractBase): """It should put end to the contract line""" self.acct_line.write( { - 'date_start': self.today, - 'recurring_next_date': self.today, - 'date_end': self.today + relativedelta(months=7), - 'is_auto_renew': True, + "date_start": self.today, + "recurring_next_date": self.today, + "date_end": self.today + relativedelta(months=7), + "is_auto_renew": True, } ) self.acct_line.stop(self.today + relativedelta(months=5)) - self.assertEqual( - self.acct_line.date_end, self.today + relativedelta(months=5) - ) + self.assertEqual(self.acct_line.date_end, self.today + relativedelta(months=5)) def test_stop_upcoming_contract_line(self): """It should put end to the contract line""" self.acct_line.write( { - 'date_start': self.today + relativedelta(months=3), - 'recurring_next_date': self.today + relativedelta(months=3), - 'date_end': self.today + relativedelta(months=7), - 'is_auto_renew': True, + "date_start": self.today + relativedelta(months=3), + "recurring_next_date": self.today + relativedelta(months=3), + "date_end": self.today + relativedelta(months=7), + "is_auto_renew": True, } ) self.acct_line.stop(self.today) - self.assertEqual( - self.acct_line.date_end, self.today + relativedelta(months=7) - ) + self.assertEqual(self.acct_line.date_end, self.today + relativedelta(months=7)) self.assertTrue(self.acct_line.is_canceled) def test_stop_past_contract_line(self): """Past contract line are ignored on stop""" self.acct_line.write( - { - 'date_end': self.today + relativedelta(months=5), - 'is_auto_renew': True, - } + {"date_end": self.today + relativedelta(months=5), "is_auto_renew": True,} ) self.acct_line.stop(self.today + relativedelta(months=7)) - self.assertEqual( - self.acct_line.date_end, self.today + relativedelta(months=5) - ) + self.assertEqual(self.acct_line.date_end, self.today + relativedelta(months=5)) def test_stop_contract_line_without_date_end(self): """Past contract line are ignored on stop""" - self.acct_line.write({'date_end': False, 'is_auto_renew': False}) + self.acct_line.write({"date_end": False, "is_auto_renew": False}) self.acct_line.stop(self.today + relativedelta(months=7)) - self.assertEqual( - self.acct_line.date_end, self.today + relativedelta(months=7) - ) + self.assertEqual(self.acct_line.date_end, self.today + relativedelta(months=7)) def test_stop_wizard(self): self.acct_line.write( { - 'date_start': self.today, - 'recurring_next_date': self.today, - 'date_end': self.today + relativedelta(months=5), - 'is_auto_renew': True, + "date_start": self.today, + "recurring_next_date": self.today, + "date_end": self.today + relativedelta(months=5), + "is_auto_renew": True, } ) - wizard = self.env['contract.line.wizard'].create( + wizard = self.env["contract.line.wizard"].create( { - 'date_end': self.today + relativedelta(months=3), - 'contract_line_id': self.acct_line.id, + "date_end": self.today + relativedelta(months=3), + "contract_line_id": self.acct_line.id, } ) wizard.stop() - self.assertEqual( - self.acct_line.date_end, self.today + relativedelta(months=3) - ) + self.assertEqual(self.acct_line.date_end, self.today + relativedelta(months=3)) self.assertFalse(self.acct_line.is_auto_renew) def test_stop_plan_successor_contract_line_0(self): successor_contract_line = self.acct_line.copy( { - 'date_start': self.today + relativedelta(months=5), - 'recurring_next_date': self.today + relativedelta(months=5), + "date_start": self.today + relativedelta(months=5), + "recurring_next_date": self.today + relativedelta(months=5), } ) self.acct_line.write( { - 'successor_contract_line_id': successor_contract_line.id, - 'is_auto_renew': False, - 'date_end': self.today, + "successor_contract_line_id": successor_contract_line.id, + "is_auto_renew": False, + "date_end": self.today, } ) suspension_start = self.today + relativedelta(months=5) suspension_end = self.today + relativedelta(months=6) with self.assertRaises(ValidationError): - self.acct_line.stop_plan_successor( - suspension_start, suspension_end, True - ) + self.acct_line.stop_plan_successor(suspension_start, suspension_end, True) def test_stop_plan_successor_contract_line_1(self): """ @@ -1205,17 +1105,15 @@ class TestContract(TestContractBase): end_date = self.today + relativedelta(months=4) self.acct_line.write( { - 'date_start': start_date, - 'recurring_next_date': start_date, - 'date_end': end_date, + "date_start": start_date, + "recurring_next_date": start_date, + "date_end": end_date, } ) - self.acct_line.stop_plan_successor( - suspension_start, suspension_end, True - ) + self.acct_line.stop_plan_successor(suspension_start, suspension_end, True) self.assertEqual(self.acct_line.date_end, end_date) - new_line = self.env['contract.line'].search( - [('predecessor_contract_line_id', '=', self.acct_line.id)] + new_line = self.env["contract.line"].search( + [("predecessor_contract_line_id", "=", self.acct_line.id)] ) self.assertFalse(new_line) @@ -1234,29 +1132,23 @@ class TestContract(TestContractBase): end_date = self.today + relativedelta(months=4) self.acct_line.write( { - 'date_start': start_date, - 'recurring_next_date': start_date, - 'date_end': end_date, + "date_start": start_date, + "recurring_next_date": start_date, + "date_end": end_date, } ) - self.acct_line.stop_plan_successor( - suspension_start, suspension_end, True - ) + self.acct_line.stop_plan_successor(suspension_start, suspension_end, True) self.assertEqual( self.acct_line.date_end, suspension_start - relativedelta(days=1) ) - new_line = self.env['contract.line'].search( - [('predecessor_contract_line_id', '=', self.acct_line.id)] + new_line = self.env["contract.line"].search( + [("predecessor_contract_line_id", "=", self.acct_line.id)] ) self.assertTrue(new_line) new_date_end = ( - suspension_end - + (end_date - suspension_start) - + relativedelta(days=1) - ) - self.assertEqual( - new_line.date_start, suspension_end + relativedelta(days=1) + suspension_end + (end_date - suspension_start) + relativedelta(days=1) ) + self.assertEqual(new_line.date_start, suspension_end + relativedelta(days=1)) self.assertEqual(new_line.date_end, new_date_end) self.assertTrue(self.acct_line.manual_renew_needed) @@ -1275,29 +1167,23 @@ class TestContract(TestContractBase): end_date = self.today + relativedelta(months=6) self.acct_line.write( { - 'date_start': start_date, - 'recurring_next_date': start_date, - 'date_end': end_date, + "date_start": start_date, + "recurring_next_date": start_date, + "date_end": end_date, } ) - self.acct_line.stop_plan_successor( - suspension_start, suspension_end, True - ) + self.acct_line.stop_plan_successor(suspension_start, suspension_end, True) self.assertEqual( self.acct_line.date_end, suspension_start - relativedelta(days=1) ) - new_line = self.env['contract.line'].search( - [('predecessor_contract_line_id', '=', self.acct_line.id)] + new_line = self.env["contract.line"].search( + [("predecessor_contract_line_id", "=", self.acct_line.id)] ) self.assertTrue(new_line) new_date_end = ( - end_date - + (suspension_end - suspension_start) - + relativedelta(days=1) - ) - self.assertEqual( - new_line.date_start, suspension_end + relativedelta(days=1) + end_date + (suspension_end - suspension_start) + relativedelta(days=1) ) + self.assertEqual(new_line.date_start, suspension_end + relativedelta(days=1)) self.assertEqual(new_line.date_end, new_date_end) self.assertTrue(self.acct_line.manual_renew_needed) @@ -1316,25 +1202,21 @@ class TestContract(TestContractBase): end_date = False self.acct_line.write( { - 'date_start': start_date, - 'recurring_next_date': start_date, - 'date_end': end_date, - 'is_auto_renew': False, + "date_start": start_date, + "recurring_next_date": start_date, + "date_end": end_date, + "is_auto_renew": False, } ) - self.acct_line.stop_plan_successor( - suspension_start, suspension_end, False - ) + self.acct_line.stop_plan_successor(suspension_start, suspension_end, False) self.assertEqual( self.acct_line.date_end, suspension_start - relativedelta(days=1) ) - new_line = self.env['contract.line'].search( - [('predecessor_contract_line_id', '=', self.acct_line.id)] + new_line = self.env["contract.line"].search( + [("predecessor_contract_line_id", "=", self.acct_line.id)] ) self.assertTrue(new_line) - self.assertEqual( - new_line.date_start, suspension_end + relativedelta(days=1) - ) + self.assertEqual(new_line.date_start, suspension_end + relativedelta(days=1)) self.assertFalse(new_line.date_end) self.assertTrue(self.acct_line.manual_renew_needed) @@ -1350,14 +1232,12 @@ class TestContract(TestContractBase): end_date = self.today + relativedelta(months=4) self.acct_line.write( { - 'date_start': start_date, - 'recurring_next_date': start_date, - 'date_end': end_date, + "date_start": start_date, + "recurring_next_date": start_date, + "date_end": end_date, } ) - self.acct_line.stop_plan_successor( - suspension_start, suspension_end, True - ) + self.acct_line.stop_plan_successor(suspension_start, suspension_end, True) self.assertEqual( self.acct_line.date_start, start_date + (suspension_end - start_date) + timedelta(days=1), @@ -1366,8 +1246,8 @@ class TestContract(TestContractBase): self.acct_line.date_end, end_date + (suspension_end - start_date) + timedelta(days=1), ) - new_line = self.env['contract.line'].search( - [('predecessor_contract_line_id', '=', self.acct_line.id)] + new_line = self.env["contract.line"].search( + [("predecessor_contract_line_id", "=", self.acct_line.id)] ) self.assertFalse(new_line) @@ -1383,14 +1263,12 @@ class TestContract(TestContractBase): end_date = self.today + relativedelta(months=6) self.acct_line.write( { - 'date_start': start_date, - 'recurring_next_date': start_date, - 'date_end': end_date, + "date_start": start_date, + "recurring_next_date": start_date, + "date_end": end_date, } ) - self.acct_line.stop_plan_successor( - suspension_start, suspension_end, True - ) + self.acct_line.stop_plan_successor(suspension_start, suspension_end, True) self.assertEqual( self.acct_line.date_start, start_date + (suspension_end - start_date) + timedelta(days=1), @@ -1399,8 +1277,8 @@ class TestContract(TestContractBase): self.acct_line.date_end, end_date + (suspension_end - start_date) + timedelta(days=1), ) - new_line = self.env['contract.line'].search( - [('predecessor_contract_line_id', '=', self.acct_line.id)] + new_line = self.env["contract.line"].search( + [("predecessor_contract_line_id", "=", self.acct_line.id)] ) self.assertFalse(new_line) @@ -1416,22 +1294,20 @@ class TestContract(TestContractBase): end_date = False self.acct_line.write( { - 'date_start': start_date, - 'recurring_next_date': start_date, - 'date_end': end_date, - 'is_auto_renew': False, + "date_start": start_date, + "recurring_next_date": start_date, + "date_end": end_date, + "is_auto_renew": False, } ) - self.acct_line.stop_plan_successor( - suspension_start, suspension_end, True - ) + self.acct_line.stop_plan_successor(suspension_start, suspension_end, True) self.assertEqual( self.acct_line.date_start, start_date + (suspension_end - start_date) + timedelta(days=1), ) self.assertFalse(self.acct_line.date_end) - new_line = self.env['contract.line'].search( - [('predecessor_contract_line_id', '=', self.acct_line.id)] + new_line = self.env["contract.line"].search( + [("predecessor_contract_line_id", "=", self.acct_line.id)] ) self.assertFalse(new_line) @@ -1447,26 +1323,22 @@ class TestContract(TestContractBase): end_date = self.today + relativedelta(months=6) self.acct_line.write( { - 'date_start': start_date, - 'recurring_next_date': start_date, - 'date_end': end_date, + "date_start": start_date, + "recurring_next_date": start_date, + "date_end": end_date, } ) - self.acct_line.stop_plan_successor( - suspension_start, suspension_end, True - ) + self.acct_line.stop_plan_successor(suspension_start, suspension_end, True) self.assertEqual( self.acct_line.date_start, - start_date - + (suspension_end - suspension_start) - + timedelta(days=1), + start_date + (suspension_end - suspension_start) + timedelta(days=1), ) self.assertEqual( self.acct_line.date_end, end_date + (suspension_end - suspension_start) + timedelta(days=1), ) - new_line = self.env['contract.line'].search( - [('predecessor_contract_line_id', '=', self.acct_line.id)] + new_line = self.env["contract.line"].search( + [("predecessor_contract_line_id", "=", self.acct_line.id)] ) self.assertFalse(new_line) @@ -1482,24 +1354,20 @@ class TestContract(TestContractBase): end_date = False self.acct_line.write( { - 'date_start': start_date, - 'recurring_next_date': start_date, - 'date_end': end_date, - 'is_auto_renew': False, + "date_start": start_date, + "recurring_next_date": start_date, + "date_end": end_date, + "is_auto_renew": False, } ) - self.acct_line.stop_plan_successor( - suspension_start, suspension_end, True - ) + self.acct_line.stop_plan_successor(suspension_start, suspension_end, True) self.assertEqual( self.acct_line.date_start, - start_date - + (suspension_end - suspension_start) - + timedelta(days=1), + start_date + (suspension_end - suspension_start) + timedelta(days=1), ) self.assertFalse(self.acct_line.date_end) - new_line = self.env['contract.line'].search( - [('predecessor_contract_line_id', '=', self.acct_line.id)] + new_line = self.env["contract.line"].search( + [("predecessor_contract_line_id", "=", self.acct_line.id)] ) self.assertFalse(new_line) @@ -1510,42 +1378,40 @@ class TestContract(TestContractBase): end_date = self.today + relativedelta(months=6) self.acct_line.write( { - 'date_start': start_date, - 'recurring_next_date': start_date, - 'date_end': end_date, + "date_start": start_date, + "recurring_next_date": start_date, + "date_end": end_date, } ) - wizard = self.env['contract.line.wizard'].create( + wizard = self.env["contract.line.wizard"].create( { - 'date_start': suspension_start, - 'date_end': suspension_end, - 'is_auto_renew': False, - 'contract_line_id': self.acct_line.id, + "date_start": suspension_start, + "date_end": suspension_end, + "is_auto_renew": False, + "contract_line_id": self.acct_line.id, } ) wizard.stop_plan_successor() self.assertEqual( self.acct_line.date_start, - start_date - + (suspension_end - suspension_start) - + timedelta(days=1), + start_date + (suspension_end - suspension_start) + timedelta(days=1), ) self.assertEqual( self.acct_line.date_end, end_date + (suspension_end - suspension_start) + timedelta(days=1), ) - new_line = self.env['contract.line'].search( - [('predecessor_contract_line_id', '=', self.acct_line.id)] + new_line = self.env["contract.line"].search( + [("predecessor_contract_line_id", "=", self.acct_line.id)] ) self.assertFalse(new_line) def test_plan_successor_contract_line(self): self.acct_line.write( { - 'date_start': self.today, - 'recurring_next_date': self.today, - 'date_end': self.today + relativedelta(months=3), - 'is_auto_renew': False, + "date_start": self.today, + "recurring_next_date": self.today, + "date_end": self.today + relativedelta(months=3), + "is_auto_renew": False, } ) self.acct_line.plan_successor( @@ -1553,26 +1419,22 @@ class TestContract(TestContractBase): self.today + relativedelta(months=7), True, ) - new_line = self.env['contract.line'].search( - [('predecessor_contract_line_id', '=', self.acct_line.id)] + new_line = self.env["contract.line"].search( + [("predecessor_contract_line_id", "=", self.acct_line.id)] ) self.assertFalse(self.acct_line.is_auto_renew) self.assertTrue(new_line.is_auto_renew) self.assertTrue(new_line, "should create a new contract line") - self.assertEqual( - new_line.date_start, self.today + relativedelta(months=5) - ) - self.assertEqual( - new_line.date_end, self.today + relativedelta(months=7) - ) + self.assertEqual(new_line.date_start, self.today + relativedelta(months=5)) + self.assertEqual(new_line.date_end, self.today + relativedelta(months=7)) def test_overlap(self): self.acct_line.write( { - 'date_start': self.today, - 'recurring_next_date': self.today, - 'date_end': self.today + relativedelta(months=3), - 'is_auto_renew': False, + "date_start": self.today, + "recurring_next_date": self.today, + "date_end": self.today + relativedelta(months=3), + "is_auto_renew": False, } ) self.acct_line.plan_successor( @@ -1580,8 +1442,8 @@ class TestContract(TestContractBase): self.today + relativedelta(months=7), True, ) - new_line = self.env['contract.line'].search( - [('predecessor_contract_line_id', '=', self.acct_line.id)] + new_line = self.env["contract.line"].search( + [("predecessor_contract_line_id", "=", self.acct_line.id)] ) with self.assertRaises(ValidationError): new_line.date_start = self.today + relativedelta(months=2) @@ -1591,40 +1453,33 @@ class TestContract(TestContractBase): def test_plan_successor_wizard(self): self.acct_line.write( { - 'date_start': self.today, - 'recurring_next_date': self.today, - 'date_end': self.today + relativedelta(months=2), - 'is_auto_renew': False, + "date_start": self.today, + "recurring_next_date": self.today, + "date_end": self.today + relativedelta(months=2), + "is_auto_renew": False, } ) - wizard = self.env['contract.line.wizard'].create( + wizard = self.env["contract.line.wizard"].create( { - 'date_start': self.today + relativedelta(months=3), - 'date_end': self.today + relativedelta(months=5), - 'is_auto_renew': True, - 'contract_line_id': self.acct_line.id, + "date_start": self.today + relativedelta(months=3), + "date_end": self.today + relativedelta(months=5), + "is_auto_renew": True, + "contract_line_id": self.acct_line.id, } ) wizard.plan_successor() - new_line = self.env['contract.line'].search( - [('predecessor_contract_line_id', '=', self.acct_line.id)] + new_line = self.env["contract.line"].search( + [("predecessor_contract_line_id", "=", self.acct_line.id)] ) self.assertFalse(self.acct_line.is_auto_renew) self.assertTrue(new_line.is_auto_renew) self.assertTrue(new_line, "should create a new contract line") - self.assertEqual( - new_line.date_start, self.today + relativedelta(months=3) - ) - self.assertEqual( - new_line.date_end, self.today + relativedelta(months=5) - ) + self.assertEqual(new_line.date_start, self.today + relativedelta(months=3)) + self.assertEqual(new_line.date_end, self.today + relativedelta(months=5)) def test_cancel(self): self.acct_line.write( - { - 'date_end': self.today + relativedelta(months=5), - 'is_auto_renew': True, - } + {"date_end": self.today + relativedelta(months=5), "is_auto_renew": True,} ) self.acct_line.cancel() self.assertTrue(self.acct_line.is_canceled) @@ -1637,11 +1492,8 @@ class TestContract(TestContractBase): def test_uncancel_wizard(self): self.acct_line.cancel() self.assertTrue(self.acct_line.is_canceled) - wizard = self.env['contract.line.wizard'].create( - { - 'recurring_next_date': self.today, - 'contract_line_id': self.acct_line.id, - } + wizard = self.env["contract.line.wizard"].create( + {"recurring_next_date": self.today, "contract_line_id": self.acct_line.id,} ) wizard.uncancel() self.assertFalse(self.acct_line.is_canceled) @@ -1653,19 +1505,17 @@ class TestContract(TestContractBase): end_date = self.today + relativedelta(months=4) self.acct_line.write( { - 'date_start': start_date, - 'recurring_next_date': start_date, - 'date_end': end_date, + "date_start": start_date, + "recurring_next_date": start_date, + "date_end": end_date, } ) - self.acct_line.stop_plan_successor( - suspension_start, suspension_end, True - ) + self.acct_line.stop_plan_successor(suspension_start, suspension_end, True) self.assertEqual( self.acct_line.date_end, suspension_start - relativedelta(days=1) ) - new_line = self.env['contract.line'].search( - [('predecessor_contract_line_id', '=', self.acct_line.id)] + 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) new_line.cancel() @@ -1676,8 +1526,7 @@ class TestContract(TestContractBase): self.assertFalse(new_line.is_canceled) self.assertEqual(self.acct_line.successor_contract_line_id, new_line) self.assertEqual( - new_line.recurring_next_date, - suspension_end + relativedelta(days=1), + new_line.recurring_next_date, suspension_end + relativedelta(days=1), ) def test_cancel_uncancel_with_predecessor_has_successor(self): @@ -1687,63 +1536,49 @@ class TestContract(TestContractBase): end_date = self.today + relativedelta(months=8) self.acct_line.write( { - 'date_start': start_date, - 'recurring_next_date': start_date, - 'date_end': end_date, + "date_start": start_date, + "recurring_next_date": start_date, + "date_end": end_date, } ) - self.acct_line.stop_plan_successor( - suspension_start, suspension_end, True - ) - new_line = self.env['contract.line'].search( - [('predecessor_contract_line_id', '=', self.acct_line.id)] + self.acct_line.stop_plan_successor(suspension_start, suspension_end, True) + new_line = self.env["contract.line"].search( + [("predecessor_contract_line_id", "=", self.acct_line.id)] ) new_line.cancel() suspension_start = self.today + relativedelta(months=4) suspension_end = self.today + relativedelta(months=5) - self.acct_line.stop_plan_successor( - suspension_start, suspension_end, True - ) + self.acct_line.stop_plan_successor(suspension_start, suspension_end, True) with self.assertRaises(ValidationError): new_line.uncancel(suspension_end) def test_check_has_not_date_end_has_successor(self): - self.acct_line.write({'date_end': False, 'is_auto_renew': False}) + self.acct_line.write({"date_end": False, "is_auto_renew": False}) with self.assertRaises(ValidationError): self.acct_line.plan_successor( - to_date('2016-03-01'), to_date('2016-09-01'), False + to_date("2016-03-01"), to_date("2016-09-01"), False ) def test_check_has_not_date_end_is_auto_renew(self): with self.assertRaises(ValidationError): - self.acct_line.write({'date_end': False, 'is_auto_renew': True}) + self.acct_line.write({"date_end": False, "is_auto_renew": True}) def test_check_has_successor_is_auto_renew(self): with self.assertRaises(ValidationError): self.acct_line.plan_successor( - to_date('2016-03-01'), to_date('2018-09-01'), False + to_date("2016-03-01"), to_date("2018-09-01"), False ) def test_search_contract_line_to_renew(self): - self.acct_line.write({'date_end': self.today, 'is_auto_renew': True}) - line_1 = self.acct_line.copy( - {'date_end': self.today + relativedelta(months=1)} - ) - line_2 = self.acct_line.copy( - {'date_end': self.today - relativedelta(months=1)} - ) - line_3 = self.acct_line.copy( - {'date_end': self.today - relativedelta(months=2)} - ) - line_4 = self.acct_line.copy( - {'date_end': self.today + relativedelta(months=2)} - ) + self.acct_line.write({"date_end": self.today, "is_auto_renew": True}) + line_1 = self.acct_line.copy({"date_end": self.today + relativedelta(months=1)}) + line_2 = self.acct_line.copy({"date_end": self.today - relativedelta(months=1)}) + line_3 = self.acct_line.copy({"date_end": self.today - relativedelta(months=2)}) + line_4 = self.acct_line.copy({"date_end": self.today + relativedelta(months=2)}) to_renew = self.acct_line.search( self.acct_line._contract_line_to_renew_domain() ) - self.assertEqual( - set(to_renew), set((self.acct_line, line_1, line_2, line_3)) - ) + self.assertEqual(set(to_renew), {self.acct_line, line_1, line_2, line_3}) self.acct_line.cron_renew_contract_line() self.assertTrue(self.acct_line.successor_contract_line_id) self.assertTrue(line_1.successor_contract_line_id) @@ -1753,15 +1588,13 @@ class TestContract(TestContractBase): def test_renew_create_new_line(self): date_start = self.today - relativedelta(months=9) - date_end = ( - date_start + relativedelta(months=12) - relativedelta(days=1) - ) + date_end = date_start + relativedelta(months=12) - relativedelta(days=1) self.acct_line.write( { - 'is_auto_renew': True, - 'date_start': date_start, - 'recurring_next_date': date_start, - 'date_end': self.today, + "is_auto_renew": True, + "date_start": date_start, + "recurring_next_date": date_start, + "date_end": self.today, } ) self.acct_line._onchange_is_auto_renew() @@ -1769,450 +1602,380 @@ class TestContract(TestContractBase): new_line = self.acct_line.renew() self.assertFalse(self.acct_line.is_auto_renew) self.assertTrue(new_line.is_auto_renew) - self.assertEqual( - new_line.date_start, date_start + relativedelta(months=12) - ) - self.assertEqual( - new_line.date_end, date_end + relativedelta(months=12) - ) + self.assertEqual(new_line.date_start, date_start + relativedelta(months=12)) + self.assertEqual(new_line.date_end, date_end + relativedelta(months=12)) def test_renew_extend_original_line(self): self.contract.company_id.create_new_line_at_contract_line_renew = False date_start = self.today - relativedelta(months=9) - date_end = ( - date_start + relativedelta(months=12) - relativedelta(days=1) - ) + date_end = date_start + relativedelta(months=12) - relativedelta(days=1) self.acct_line.write( { - 'is_auto_renew': True, - 'date_start': date_start, - 'recurring_next_date': date_start, - 'date_end': self.today, + "is_auto_renew": True, + "date_start": date_start, + "recurring_next_date": date_start, + "date_end": self.today, } ) self.acct_line._onchange_is_auto_renew() self.assertEqual(self.acct_line.date_end, date_end) self.acct_line.renew() self.assertTrue(self.acct_line.is_auto_renew) - self.assertEqual( - self.acct_line.date_start, date_start - ) - self.assertEqual( - self.acct_line.date_end, date_end + relativedelta(months=12) - ) + self.assertEqual(self.acct_line.date_start, date_start) + self.assertEqual(self.acct_line.date_end, date_end + relativedelta(months=12)) def test_cron_recurring_create_invoice(self): - self.acct_line.date_start = '2018-01-01' - self.acct_line.recurring_invoicing_type = 'post-paid' - self.acct_line.date_end = '2018-03-15' + self.acct_line.date_start = "2018-01-01" + self.acct_line.recurring_invoicing_type = "post-paid" + self.acct_line.date_end = "2018-03-15" self.acct_line._onchange_date_start() contracts = self.contract2 for i in range(10): contracts |= self.contract.copy() - self.env['contract.contract'].cron_recurring_create_invoice() - invoice_lines = self.env['account.invoice.line'].search( - [('contract_line_id', 'in', - contracts.mapped('contract_line_ids').ids)] + self.env["contract.contract"].cron_recurring_create_invoice() + invoice_lines = self.env["account.invoice.line"].search( + [("contract_line_id", "in", contracts.mapped("contract_line_ids").ids)] ) self.assertEqual( - len(contracts.mapped('contract_line_ids')), - len(invoice_lines), + len(contracts.mapped("contract_line_ids")), len(invoice_lines), ) def test_contract_manually_create_invoice(self): - self.acct_line.date_start = '2018-01-01' - self.acct_line.recurring_invoicing_type = 'post-paid' - self.acct_line.date_end = '2018-03-15' + self.acct_line.date_start = "2018-01-01" + self.acct_line.recurring_invoicing_type = "post-paid" + self.acct_line.date_end = "2018-03-15" self.acct_line._onchange_date_start() self.contract2.unlink() contracts = self.contract for i in range(10): contracts |= self.contract.copy() - wizard = self.env['contract.manually.create.invoice'].create({ - 'invoice_date': self.today - }) + wizard = self.env["contract.manually.create.invoice"].create( + {"invoice_date": self.today} + ) wizard.action_show_contract_to_invoice() contract_to_invoice_count = wizard.contract_to_invoice_count self.assertEqual( contracts, - self.env['contract.contract'].search( - wizard.action_show_contract_to_invoice()['domain'] + self.env["contract.contract"].search( + wizard.action_show_contract_to_invoice()["domain"] ), ) action = wizard.create_invoice() - invoice_lines = self.env['account.invoice.line'].search( - [('contract_line_id', 'in', - contracts.mapped('contract_line_ids').ids)] + invoice_lines = self.env["account.invoice.line"].search( + [("contract_line_id", "in", contracts.mapped("contract_line_ids").ids)] ) self.assertEqual( - len(contracts.mapped('contract_line_ids')), - len(invoice_lines), + len(contracts.mapped("contract_line_ids")), len(invoice_lines), ) - invoices = self.env['account.invoice'].search(action['domain']) - self.assertEqual(invoice_lines.mapped('invoice_id'), invoices) + invoices = self.env["account.invoice"].search(action["domain"]) + self.assertEqual(invoice_lines.mapped("invoice_id"), invoices) self.assertEqual(len(invoices), contract_to_invoice_count) def test_get_period_to_invoice_monthlylastday_postpaid(self): - self.acct_line.date_start = '2018-01-05' - self.acct_line.recurring_invoicing_type = 'post-paid' - self.acct_line.recurring_rule_type = 'monthlylastday' - self.acct_line.date_end = '2018-03-15' + self.acct_line.date_start = "2018-01-05" + self.acct_line.recurring_invoicing_type = "post-paid" + self.acct_line.recurring_rule_type = "monthlylastday" + self.acct_line.date_end = "2018-03-15" self.acct_line._onchange_date_start() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2018-01-05')) - self.assertEqual(last, to_date('2018-01-31')) + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2018-01-05")) + self.assertEqual(last, to_date("2018-01-31")) self.contract.recurring_create_invoice() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2018-02-01')) - self.assertEqual(last, to_date('2018-02-28')) + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2018-02-01")) + self.assertEqual(last, to_date("2018-02-28")) self.contract.recurring_create_invoice() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2018-03-01')) - self.assertEqual(last, to_date('2018-03-15')) + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2018-03-01")) + self.assertEqual(last, to_date("2018-03-15")) self.acct_line.manual_renew_needed = True def test_get_period_to_invoice_monthlylastday_prepaid(self): - self.acct_line.date_start = '2018-01-05' - self.acct_line.recurring_invoicing_type = 'pre-paid' - self.acct_line.recurring_rule_type = 'monthlylastday' - self.acct_line.date_end = '2018-03-15' + self.acct_line.date_start = "2018-01-05" + self.acct_line.recurring_invoicing_type = "pre-paid" + self.acct_line.recurring_rule_type = "monthlylastday" + self.acct_line.date_end = "2018-03-15" self.acct_line._onchange_date_start() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2018-01-05')) - self.assertEqual(last, to_date('2018-01-31')) - self.assertEqual(recurring_next_date, to_date('2018-01-05')) - self.assertEqual( - self.acct_line.recurring_next_date, to_date('2018-01-05') + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, ) + self.assertEqual(first, to_date("2018-01-05")) + self.assertEqual(last, to_date("2018-01-31")) + self.assertEqual(recurring_next_date, to_date("2018-01-05")) + self.assertEqual(self.acct_line.recurring_next_date, to_date("2018-01-05")) self.contract.recurring_create_invoice() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2018-02-01')) - self.assertEqual(last, to_date('2018-02-28')) - self.assertEqual(recurring_next_date, to_date('2018-02-01')) - self.assertEqual( - self.acct_line.recurring_next_date, to_date('2018-02-01') - ) - self.assertEqual( - self.acct_line.last_date_invoiced, to_date('2018-01-31') + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, ) + self.assertEqual(first, to_date("2018-02-01")) + self.assertEqual(last, to_date("2018-02-28")) + self.assertEqual(recurring_next_date, to_date("2018-02-01")) + self.assertEqual(self.acct_line.recurring_next_date, to_date("2018-02-01")) + self.assertEqual(self.acct_line.last_date_invoiced, to_date("2018-01-31")) self.contract.recurring_create_invoice() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2018-03-01')) - self.assertEqual(last, to_date('2018-03-15')) - self.assertEqual(recurring_next_date, to_date('2018-03-01')) - self.assertEqual( - self.acct_line.recurring_next_date, to_date('2018-03-01') - ) - self.assertEqual( - self.acct_line.last_date_invoiced, to_date('2018-02-28') + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, ) + self.assertEqual(first, to_date("2018-03-01")) + self.assertEqual(last, to_date("2018-03-15")) + self.assertEqual(recurring_next_date, to_date("2018-03-01")) + self.assertEqual(self.acct_line.recurring_next_date, to_date("2018-03-01")) + self.assertEqual(self.acct_line.last_date_invoiced, to_date("2018-02-28")) self.contract.recurring_create_invoice() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) self.assertFalse(first) self.assertFalse(last) self.assertFalse(recurring_next_date) self.assertFalse(self.acct_line.recurring_next_date) - self.assertEqual( - self.acct_line.last_date_invoiced, to_date('2018-03-15') - ) + self.assertEqual(self.acct_line.last_date_invoiced, to_date("2018-03-15")) def test_get_period_to_invoice_monthly_pre_paid_2(self): - self.acct_line.date_start = '2018-01-05' - self.acct_line.recurring_invoicing_type = 'pre-paid' - self.acct_line.recurring_rule_type = 'monthly' - self.acct_line.date_end = '2018-08-15' + self.acct_line.date_start = "2018-01-05" + self.acct_line.recurring_invoicing_type = "pre-paid" + self.acct_line.recurring_rule_type = "monthly" + self.acct_line.date_end = "2018-08-15" self.acct_line._onchange_date_start() self.contract.recurring_create_invoice() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2018-02-05')) - self.assertEqual(last, to_date('2018-03-04')) - self.acct_line.recurring_next_date = '2018-06-05' - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2018-02-05')) - self.assertEqual(last, to_date('2018-07-04')) + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2018-02-05")) + self.assertEqual(last, to_date("2018-03-04")) + self.acct_line.recurring_next_date = "2018-06-05" + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2018-02-05")) + self.assertEqual(last, to_date("2018-07-04")) def test_get_period_to_invoice_monthly_post_paid_2(self): - self.acct_line.date_start = '2018-01-05' - self.acct_line.recurring_invoicing_type = 'post-paid' - self.acct_line.recurring_rule_type = 'monthly' - self.acct_line.date_end = '2018-08-15' + self.acct_line.date_start = "2018-01-05" + self.acct_line.recurring_invoicing_type = "post-paid" + self.acct_line.recurring_rule_type = "monthly" + self.acct_line.date_end = "2018-08-15" self.acct_line._onchange_date_start() self.contract.recurring_create_invoice() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2018-02-05')) - self.assertEqual(last, to_date('2018-03-04')) - self.acct_line.recurring_next_date = '2018-06-05' - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2018-02-05')) - self.assertEqual(last, to_date('2018-06-04')) + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2018-02-05")) + self.assertEqual(last, to_date("2018-03-04")) + self.acct_line.recurring_next_date = "2018-06-05" + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2018-02-05")) + self.assertEqual(last, to_date("2018-06-04")) def test_get_period_to_invoice_monthly_post_paid(self): - self.acct_line.date_start = '2018-01-05' - self.acct_line.recurring_invoicing_type = 'post-paid' - self.acct_line.recurring_rule_type = 'monthly' - self.acct_line.date_end = '2018-03-15' + self.acct_line.date_start = "2018-01-05" + self.acct_line.recurring_invoicing_type = "post-paid" + self.acct_line.recurring_rule_type = "monthly" + self.acct_line.date_end = "2018-03-15" self.acct_line._onchange_date_start() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2018-01-05')) - self.assertEqual(last, to_date('2018-02-04')) + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2018-01-05")) + self.assertEqual(last, to_date("2018-02-04")) self.contract.recurring_create_invoice() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2018-02-05')) - self.assertEqual(last, to_date('2018-03-04')) + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2018-02-05")) + self.assertEqual(last, to_date("2018-03-04")) self.contract.recurring_create_invoice() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2018-03-05')) - self.assertEqual(last, to_date('2018-03-15')) + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2018-03-05")) + self.assertEqual(last, to_date("2018-03-15")) def test_get_period_to_invoice_monthly_pre_paid(self): - self.acct_line.date_start = '2018-01-05' - self.acct_line.recurring_invoicing_type = 'pre-paid' - self.acct_line.recurring_rule_type = 'monthly' - self.acct_line.date_end = '2018-03-15' + self.acct_line.date_start = "2018-01-05" + self.acct_line.recurring_invoicing_type = "pre-paid" + self.acct_line.recurring_rule_type = "monthly" + self.acct_line.date_end = "2018-03-15" self.acct_line._onchange_date_start() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2018-01-05')) - self.assertEqual(last, to_date('2018-02-04')) + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2018-01-05")) + self.assertEqual(last, to_date("2018-02-04")) self.contract.recurring_create_invoice() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2018-02-05')) - self.assertEqual(last, to_date('2018-03-04')) + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2018-02-05")) + self.assertEqual(last, to_date("2018-03-04")) self.contract.recurring_create_invoice() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2018-03-05')) - self.assertEqual(last, to_date('2018-03-15')) + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2018-03-05")) + self.assertEqual(last, to_date("2018-03-15")) def test_get_period_to_invoice_yearly_post_paid(self): - self.acct_line.date_start = '2018-01-05' - self.acct_line.recurring_invoicing_type = 'post-paid' - self.acct_line.recurring_rule_type = 'yearly' - self.acct_line.date_end = '2020-03-15' + self.acct_line.date_start = "2018-01-05" + self.acct_line.recurring_invoicing_type = "post-paid" + self.acct_line.recurring_rule_type = "yearly" + self.acct_line.date_end = "2020-03-15" self.acct_line._onchange_date_start() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2018-01-05')) - self.assertEqual(last, to_date('2019-01-04')) + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2018-01-05")) + self.assertEqual(last, to_date("2019-01-04")) self.contract.recurring_create_invoice() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2019-01-05')) - self.assertEqual(last, to_date('2020-01-04')) + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2019-01-05")) + self.assertEqual(last, to_date("2020-01-04")) self.contract.recurring_create_invoice() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2020-01-05')) - self.assertEqual(last, to_date('2020-03-15')) + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2020-01-05")) + self.assertEqual(last, to_date("2020-03-15")) def test_get_period_to_invoice_yearly_pre_paid(self): - self.acct_line.date_start = '2018-01-05' - self.acct_line.recurring_invoicing_type = 'pre-paid' - self.acct_line.recurring_rule_type = 'yearly' - self.acct_line.date_end = '2020-03-15' + self.acct_line.date_start = "2018-01-05" + self.acct_line.recurring_invoicing_type = "pre-paid" + self.acct_line.recurring_rule_type = "yearly" + self.acct_line.date_end = "2020-03-15" self.acct_line._onchange_date_start() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2018-01-05')) - self.assertEqual(last, to_date('2019-01-04')) + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2018-01-05")) + self.assertEqual(last, to_date("2019-01-04")) self.contract.recurring_create_invoice() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2019-01-05')) - self.assertEqual(last, to_date('2020-01-04')) + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2019-01-05")) + self.assertEqual(last, to_date("2020-01-04")) self.contract.recurring_create_invoice() - first, last, recurring_next_date = \ - self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) - self.assertEqual(first, to_date('2020-01-05')) - self.assertEqual(last, to_date('2020-03-15')) + first, last, recurring_next_date = self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, self.acct_line.recurring_next_date, + ) + self.assertEqual(first, to_date("2020-01-05")) + self.assertEqual(last, to_date("2020-03-15")) def test_unlink(self): with self.assertRaises(ValidationError): self.acct_line.unlink() def test_contract_line_state(self): - lines = self.env['contract.line'] + lines = self.env["contract.line"] # upcoming lines |= self.acct_line.copy( { - 'date_start': self.today + relativedelta(months=3), - 'recurring_next_date': self.today + relativedelta(months=3), - 'date_end': self.today + relativedelta(months=5), + "date_start": self.today + relativedelta(months=3), + "recurring_next_date": self.today + relativedelta(months=3), + "date_end": self.today + relativedelta(months=5), } ) # in-progress lines |= self.acct_line.copy( { - 'date_start': self.today, - 'recurring_next_date': self.today, - 'date_end': self.today + relativedelta(months=5), + "date_start": self.today, + "recurring_next_date": self.today, + "date_end": self.today + relativedelta(months=5), } ) # in-progress lines |= self.acct_line.copy( { - 'date_start': self.today, - 'recurring_next_date': self.today, - 'date_end': self.today + relativedelta(months=5), - 'manual_renew_needed': True, + "date_start": self.today, + "recurring_next_date": self.today, + "date_end": self.today + relativedelta(months=5), + "manual_renew_needed": True, } ) # to-renew lines |= self.acct_line.copy( { - 'date_start': self.today - relativedelta(months=5), - 'recurring_next_date': self.today - relativedelta(months=5), - 'date_end': self.today - relativedelta(months=2), - 'manual_renew_needed': True, + "date_start": self.today - relativedelta(months=5), + "recurring_next_date": self.today - relativedelta(months=5), + "date_end": self.today - relativedelta(months=2), + "manual_renew_needed": True, } ) # upcoming-close lines |= self.acct_line.copy( { - 'date_start': self.today - relativedelta(months=5), - 'recurring_next_date': self.today - relativedelta(months=5), - 'date_end': self.today + relativedelta(days=20), - 'is_auto_renew': False, + "date_start": self.today - relativedelta(months=5), + "recurring_next_date": self.today - relativedelta(months=5), + "date_end": self.today + relativedelta(days=20), + "is_auto_renew": False, } ) # closed lines |= self.acct_line.copy( { - 'date_start': self.today - relativedelta(months=5), - 'recurring_next_date': self.today - relativedelta(months=5), - 'date_end': self.today - relativedelta(months=2), - 'is_auto_renew': False, + "date_start": self.today - relativedelta(months=5), + "recurring_next_date": self.today - relativedelta(months=5), + "date_end": self.today - relativedelta(months=2), + "is_auto_renew": False, } ) # canceled lines |= self.acct_line.copy( { - 'date_start': self.today - relativedelta(months=5), - 'recurring_next_date': self.today - relativedelta(months=5), - 'date_end': self.today - relativedelta(months=2), - 'is_canceled': True, + "date_start": self.today - relativedelta(months=5), + "recurring_next_date": self.today - relativedelta(months=5), + "date_end": self.today - relativedelta(months=2), + "is_canceled": True, } ) # section - lines |= self.env['contract.line'].create({ - "contract_id": self.contract.id, - "display_type": "line_section", - "name": "Test section", - }) + lines |= self.env["contract.line"].create( + { + "contract_id": self.contract.id, + "display_type": "line_section", + "name": "Test section", + } + ) states = [ - 'upcoming', - 'in-progress', - 'to-renew', - 'upcoming-close', - 'closed', - 'canceled', + "upcoming", + "in-progress", + "to-renew", + "upcoming-close", + "closed", + "canceled", False, ] - self.assertEqual(set(lines.mapped('state')), set(states)) + self.assertEqual(set(lines.mapped("state")), set(states)) # Test search method for state in states: - lines = self.env['contract.line'].search([('state', '=', state)]) + lines = self.env["contract.line"].search([("state", "=", state)]) self.assertTrue(lines, state) - self.assertTrue(state in lines.mapped('state'), state) - lines = self.env['contract.line'].search([('state', '!=', state)]) - self.assertFalse(state in lines.mapped('state'), state) - lines = self.env['contract.line'].search([('state', 'in', states)]) - self.assertEqual(set(lines.mapped('state')), set(states)) - lines = self.env['contract.line'].search([('state', 'in', [])]) - self.assertFalse(lines.mapped('state')) + self.assertTrue(state in lines.mapped("state"), state) + lines = self.env["contract.line"].search([("state", "!=", state)]) + self.assertFalse(state in lines.mapped("state"), state) + lines = self.env["contract.line"].search([("state", "in", states)]) + self.assertEqual(set(lines.mapped("state")), set(states)) + lines = self.env["contract.line"].search([("state", "in", [])]) + self.assertFalse(lines.mapped("state")) with self.assertRaises(TypeError): - self.env['contract.line'].search([('state', 'in', 'upcoming')]) - lines = self.env['contract.line'].search([('state', 'not in', [])]) - self.assertEqual(set(lines.mapped('state')), set(states)) - lines = self.env['contract.line'].search([('state', 'not in', states)]) - self.assertFalse(lines.mapped('state')) - state2 = ['upcoming', 'in-progress'] - lines = self.env['contract.line'].search([('state', 'not in', state2)]) - self.assertEqual(set(lines.mapped('state')), set(states) - set(state2)) + self.env["contract.line"].search([("state", "in", "upcoming")]) + lines = self.env["contract.line"].search([("state", "not in", [])]) + self.assertEqual(set(lines.mapped("state")), set(states)) + lines = self.env["contract.line"].search([("state", "not in", states)]) + self.assertFalse(lines.mapped("state")) + state2 = ["upcoming", "in-progress"] + lines = self.env["contract.line"].search([("state", "not in", state2)]) + self.assertEqual(set(lines.mapped("state")), set(states) - set(state2)) def test_check_auto_renew_contract_line_with_successor(self): """ @@ -2222,8 +1985,8 @@ class TestContract(TestContractBase): with self.assertRaises(ValidationError): self.acct_line.write( { - 'is_auto_renew': True, - 'successor_contract_line_id': successor_contract_line.id, + "is_auto_renew": True, + "successor_contract_line_id": successor_contract_line.id, } ) @@ -2235,8 +1998,8 @@ class TestContract(TestContractBase): with self.assertRaises(ValidationError): self.acct_line.write( { - 'date_end': False, - 'successor_contract_line_id': successor_contract_line.id, + "date_end": False, + "successor_contract_line_id": successor_contract_line.id, } ) @@ -2247,7 +2010,7 @@ class TestContract(TestContractBase): with self.assertRaises(ValidationError): self.acct_line.write( { - 'last_date_invoiced': self.acct_line.date_start + "last_date_invoiced": self.acct_line.date_start - relativedelta(days=1) } ) @@ -2256,67 +2019,46 @@ class TestContract(TestContractBase): """ start date can't be after the date of last invoice """ - self.acct_line.write({'date_end': self.today}) + self.acct_line.write({"date_end": self.today}) with self.assertRaises(ValidationError): self.acct_line.write( - { - 'last_date_invoiced': self.acct_line.date_end - + relativedelta(days=1) - } + {"last_date_invoiced": self.acct_line.date_end + relativedelta(days=1)} ) def test_init_last_date_invoiced(self): self.acct_line.write( - {'date_start': '2019-01-01', 'recurring_next_date': '2019-03-01'} + {"date_start": "2019-01-01", "recurring_next_date": "2019-03-01"} ) line_monthlylastday = self.acct_line.copy( { - 'recurring_rule_type': 'monthlylastday', - 'recurring_next_date': '2019-03-31', + "recurring_rule_type": "monthlylastday", + "recurring_next_date": "2019-03-31", } ) line_prepaid = self.acct_line.copy( - { - 'recurring_invoicing_type': 'pre-paid', - 'recurring_rule_type': 'monthly', - } + {"recurring_invoicing_type": "pre-paid", "recurring_rule_type": "monthly",} ) line_postpaid = self.acct_line.copy( - { - 'recurring_invoicing_type': 'post-paid', - 'recurring_rule_type': 'monthly', - } + {"recurring_invoicing_type": "post-paid", "recurring_rule_type": "monthly",} ) lines = line_monthlylastday | line_prepaid | line_postpaid - lines.write({'last_date_invoiced': False}) - self.assertFalse(any(lines.mapped('last_date_invoiced'))) + lines.write({"last_date_invoiced": False}) + self.assertFalse(any(lines.mapped("last_date_invoiced"))) lines._init_last_date_invoiced() - self.assertEqual( - line_monthlylastday.last_date_invoiced, to_date("2019-02-28") - ) - self.assertEqual( - line_prepaid.last_date_invoiced, to_date("2019-02-28") - ) - self.assertEqual( - line_postpaid.last_date_invoiced, to_date("2019-01-31") - ) + self.assertEqual(line_monthlylastday.last_date_invoiced, to_date("2019-02-28")) + self.assertEqual(line_prepaid.last_date_invoiced, to_date("2019-02-28")) + self.assertEqual(line_postpaid.last_date_invoiced, to_date("2019-01-31")) def test_delay_invoiced_contract_line(self): self.acct_line.write( - { - 'last_date_invoiced': self.acct_line.date_start - + relativedelta(days=1) - } + {"last_date_invoiced": self.acct_line.date_start + relativedelta(days=1)} ) with self.assertRaises(ValidationError): self.acct_line._delay(relativedelta(months=1)) def test_cancel_invoiced_contract_line(self): self.acct_line.write( - { - 'last_date_invoiced': self.acct_line.date_start - + relativedelta(days=1) - } + {"last_date_invoiced": self.acct_line.date_start + relativedelta(days=1)} ) with self.assertRaises(ValidationError): self.acct_line.cancel() @@ -2324,76 +2066,68 @@ class TestContract(TestContractBase): def test_action_uncancel(self): action = self.acct_line.action_uncancel() self.assertEqual( - action['context']['default_contract_line_id'], self.acct_line.id + action["context"]["default_contract_line_id"], self.acct_line.id ) def test_action_plan_successor(self): action = self.acct_line.action_plan_successor() self.assertEqual( - action['context']['default_contract_line_id'], self.acct_line.id + action["context"]["default_contract_line_id"], self.acct_line.id ) def test_action_stop(self): action = self.acct_line.action_stop() self.assertEqual( - action['context']['default_contract_line_id'], self.acct_line.id + action["context"]["default_contract_line_id"], self.acct_line.id ) def test_action_stop_plan_successor(self): action = self.acct_line.action_stop_plan_successor() self.assertEqual( - action['context']['default_contract_line_id'], self.acct_line.id + action["context"]["default_contract_line_id"], self.acct_line.id ) def test_purchase_fields_view_get(self): - purchase_tree_view = self.env.ref( - 'contract.contract_line_supplier_tree_view' - ) - purchase_form_view = self.env.ref( - 'contract.contract_line_supplier_form_view' - ) + purchase_tree_view = self.env.ref("contract.contract_line_supplier_tree_view") + purchase_form_view = self.env.ref("contract.contract_line_supplier_form_view") view = self.acct_line.with_context( - default_contract_type='purchase' - ).fields_view_get(view_type='tree') - self.assertEqual(view['view_id'], purchase_tree_view.id) + default_contract_type="purchase" + ).fields_view_get(view_type="tree") + self.assertEqual(view["view_id"], purchase_tree_view.id) view = self.acct_line.with_context( - default_contract_type='purchase' - ).fields_view_get(view_type='form') - self.assertEqual(view['view_id'], purchase_form_view.id) + default_contract_type="purchase" + ).fields_view_get(view_type="form") + self.assertEqual(view["view_id"], purchase_form_view.id) def test_multicompany_partner_edited(self): """Editing a partner with contracts in several companies works.""" - company2 = self.env['res.company'].create({ - "name": "Company 2", - }) - unprivileged_user = self.env["res.users"].create({ - "name": "unprivileged test user", - "login": "test", - "company_id": company2.id, - "company_ids": [(4, company2.id, False)], - }) - parent_partner = self.env["res.partner"].create({ - "name": "parent partner", - "is_company": True, - }) + company2 = self.env["res.company"].create({"name": "Company 2",}) + unprivileged_user = self.env["res.users"].create( + { + "name": "unprivileged test user", + "login": "test", + "company_id": company2.id, + "company_ids": [(4, company2.id, False)], + } + ) + parent_partner = self.env["res.partner"].create( + {"name": "parent partner", "is_company": True,} + ) # Assume contract 2 is for company 2 self.contract2.company_id = company2 # Update the partner attached to both contracts self.partner.sudo(unprivileged_user).with_context( company_id=company2.id, force_company=company2.id - ).write({ - "is_company": False, - "parent_id": parent_partner.id, - }) + ).write( + {"is_company": False, "parent_id": parent_partner.id,} + ) def test_sale_fields_view_get(self): - sale_form_view = self.env.ref( - 'contract.contract_line_customer_form_view' - ) + sale_form_view = self.env.ref("contract.contract_line_customer_form_view") view = self.acct_line.with_context( - default_contract_type='sale' - ).fields_view_get(view_type='form') - self.assertEqual(view['view_id'], sale_form_view.id) + default_contract_type="sale" + ).fields_view_get(view_type="form") + self.assertEqual(view["view_id"], sale_form_view.id) def test_contract_count_invoice(self): self.contract.recurring_create_invoice() @@ -2403,30 +2137,32 @@ class TestContract(TestContractBase): self.assertEqual(self.contract.invoice_count, 3) def test_contract_count_invoice_2(self): - invoices = self.env['account.invoice'] + invoices = self.env["account.invoice"] invoices |= self.contract.recurring_create_invoice() invoices |= self.contract.recurring_create_invoice() invoices |= self.contract.recurring_create_invoice() action = self.contract.action_show_invoices() - self.assertEqual(set(action['domain'][0][2]), set(invoices.ids)) + self.assertEqual(set(action["domain"][0][2]), set(invoices.ids)) def test_compute_create_invoice_visibility(self): self.assertTrue(self.contract.create_invoice_visibility) self.acct_line.write( { - 'date_start': '2018-01-01', - 'date_end': '2018-12-31', - 'last_date_invoiced': '2018-12-31', - 'recurring_next_date': False, + "date_start": "2018-01-01", + "date_end": "2018-12-31", + "last_date_invoiced": "2018-12-31", + "recurring_next_date": False, } ) self.assertFalse(self.acct_line.create_invoice_visibility) self.assertFalse(self.contract.create_invoice_visibility) - section = self.env['contract.line'].create({ - "contract_id": self.contract.id, - "display_type": "line_section", - "name": "Test section", - }) + section = self.env["contract.line"].create( + { + "contract_id": self.contract.id, + "display_type": "line_section", + "name": "Test section", + } + ) self.assertFalse(section.create_invoice_visibility) def test_invoice_contract_without_lines(self): @@ -2442,56 +2178,52 @@ class TestContract(TestContractBase): def test_check_last_date_invoiced_before_next_invoice_date(self): with self.assertRaises(ValidationError): - self.acct_line.write({ - 'date_start': '2019-01-01', - 'date_end': '2019-12-01', - 'recurring_next_date': '2019-01-01', - 'last_date_invoiced': '2019-06-01', - }) + self.acct_line.write( + { + "date_start": "2019-01-01", + "date_end": "2019-12-01", + "recurring_next_date": "2019-01-01", + "last_date_invoiced": "2019-06-01", + } + ) def test_stop_and_update_recurring_invoice_date(self): self.acct_line.write( { - 'date_start': '2019-01-01', - 'date_end': '2019-12-31', - 'recurring_next_date': '2020-01-01', - 'recurring_invoicing_type': 'post-paid', - 'recurring_rule_type': 'yearly', + "date_start": "2019-01-01", + "date_end": "2019-12-31", + "recurring_next_date": "2020-01-01", + "recurring_invoicing_type": "post-paid", + "recurring_rule_type": "yearly", } ) - self.acct_line.stop(to_date('2019-05-31')) - self.assertEqual(self.acct_line.date_end, to_date('2019-05-31')) - self.assertEqual( - self.acct_line.recurring_next_date, to_date('2019-06-01') - ) + self.acct_line.stop(to_date("2019-05-31")) + self.assertEqual(self.acct_line.date_end, to_date("2019-05-31")) + self.assertEqual(self.acct_line.recurring_next_date, to_date("2019-06-01")) def test_action_terminate_contract(self): action = self.contract.action_terminate_contract() wizard = ( - self.env[action['res_model']] - .with_context(action['context']) - .create( + self.env[action["res_model"]] + .with_context(action["context"]) + .create( { - 'terminate_date': '2018-03-01', - 'terminate_reason_id': self.terminate_reason.id, - 'terminate_comment': 'terminate_comment', + "terminate_date": "2018-03-01", + "terminate_reason_id": self.terminate_reason.id, + "terminate_comment": "terminate_comment", } ) ) self.assertEqual(wizard.contract_id, self.contract) with self.assertRaises(UserError): wizard.terminate_contract() - group_can_terminate_contract = self.env.ref( - "contract.can_terminate_contract" - ) + group_can_terminate_contract = self.env.ref("contract.can_terminate_contract") group_can_terminate_contract.users |= self.env.user wizard.terminate_contract() self.assertTrue(self.contract.is_terminated) - self.assertEqual(self.contract.terminate_date, to_date('2018-03-01')) - self.assertEqual( - self.contract.terminate_reason_id.id, self.terminate_reason.id - ) - self.assertEqual(self.contract.terminate_comment, 'terminate_comment') + self.assertEqual(self.contract.terminate_date, to_date("2018-03-01")) + self.assertEqual(self.contract.terminate_reason_id.id, self.terminate_reason.id) + self.assertEqual(self.contract.terminate_comment, "terminate_comment") self.contract.action_cancel_contract_termination() self.assertFalse(self.contract.is_terminated) self.assertFalse(self.contract.terminate_reason_id) @@ -2499,18 +2231,12 @@ class TestContract(TestContractBase): def test_terminate_date_before_last_date_invoiced(self): self.contract.recurring_create_invoice() - self.assertEqual( - self.acct_line.last_date_invoiced, to_date('2018-02-14') - ) - group_can_terminate_contract = self.env.ref( - "contract.can_terminate_contract" - ) + self.assertEqual(self.acct_line.last_date_invoiced, to_date("2018-02-14")) + group_can_terminate_contract = self.env.ref("contract.can_terminate_contract") group_can_terminate_contract.users |= self.env.user with self.assertRaises(ValidationError): self.contract._terminate_contract( - self.terminate_reason, - 'terminate_comment', - to_date('2018-02-13'), + self.terminate_reason, "terminate_comment", to_date("2018-02-13"), ) def test_currency(self): @@ -2519,21 +2245,23 @@ class TestContract(TestContractBase): # Get currency from company self.contract2.journal_id = False self.assertEqual( - self.contract2.currency_id, self.contract2.company_id.currency_id) + self.contract2.currency_id, self.contract2.company_id.currency_id + ) # Get currency from journal - journal = self.env["account.journal"].create({ - "name": "Test journal CAD", - "code": "TCAD", - "type": "sale", - "currency_id": currency_cad.id, - }) + journal = self.env["account.journal"].create( + { + "name": "Test journal CAD", + "code": "TCAD", + "type": "sale", + "currency_id": currency_cad.id, + } + ) self.contract2.journal_id = journal.id self.assertEqual(self.contract2.currency_id, currency_cad) # Get currency from contract pricelist - pricelist = self.env['product.pricelist'].create({ - "name": "Test pricelist", - "currency_id": currency_eur.id, - }) + pricelist = self.env["product.pricelist"].create( + {"name": "Test pricelist", "currency_id": currency_eur.id,} + ) self.contract2.pricelist_id = pricelist.id self.contract2.contract_line_ids.automatic_price = True self.assertEqual(self.contract2.currency_id, currency_eur) diff --git a/contract/views/abstract_contract_line.xml b/contract/views/abstract_contract_line.xml index 44feec0a6..140ffb3fb 100644 --- a/contract/views/abstract_contract_line.xml +++ b/contract/views/abstract_contract_line.xml @@ -1,89 +1,137 @@ - + - - contract.abstract.contract.line form view (in contract) + contract.abstract.contract.line form view (in contract) contract.abstract.contract.line
- -
+ +
- - - - - diff --git a/contract/views/assets.xml b/contract/views/assets.xml index d48b516ad..804879c36 100644 --- a/contract/views/assets.xml +++ b/contract/views/assets.xml @@ -1,10 +1,17 @@ - + -