diff --git a/contract_variable_quantity/__manifest__.py b/contract_variable_quantity/__manifest__.py index 2c0a42e52..e5c8ea88a 100644 --- a/contract_variable_quantity/__manifest__.py +++ b/contract_variable_quantity/__manifest__.py @@ -4,21 +4,20 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { - 'name': 'Variable quantity in contract recurrent invoicing', - 'version': '12.0.3.0.0', - 'category': 'Contract Management', - 'license': 'AGPL-3', - 'author': "Tecnativa," - "Odoo Community Association (OCA)", - 'website': 'https://www.tecnativa.com', - 'depends': ['contract'], - 'data': [ - 'security/ir.model.access.csv', - 'views/abstract_contract_line.xml', - 'views/contract_line_formula.xml', - 'views/contract_line_views.xml', - 'views/contract_template.xml', - 'views/contract.xml', + "name": "Variable quantity in contract recurrent invoicing", + "version": "12.0.3.0.0", + "category": "Contract Management", + "license": "AGPL-3", + "author": "Tecnativa," "Odoo Community Association (OCA)", + "website": "https://www.tecnativa.com", + "depends": ["contract"], + "data": [ + "security/ir.model.access.csv", + "views/abstract_contract_line.xml", + "views/contract_line_formula.xml", + "views/contract_line_views.xml", + "views/contract_template.xml", + "views/contract.xml", ], - 'installable': True, + "installable": True, } diff --git a/contract_variable_quantity/migrations/12.0.2.0.0/pre-migration.py b/contract_variable_quantity/migrations/12.0.2.0.0/pre-migration.py index 696654698..78533de77 100644 --- a/contract_variable_quantity/migrations/12.0.2.0.0/pre-migration.py +++ b/contract_variable_quantity/migrations/12.0.2.0.0/pre-migration.py @@ -10,23 +10,41 @@ _logger = logging.getLogger(__name__) def migrate(cr, version): xmlids_to_rename = [ - ('contract_sale.account_analytic_account_own_salesman', - 'contract_sale.contract_contract_own_salesman'), - ('contract_sale.account_analytic_account_see_all', - 'contract_sale.contract_contract_see_all'), - ('contract_sale.account_analytic_contract_salesman', - 'contract_sale.contract_template_salesman'), - ('contract_sale.account_analytic_contract_sale_manager', - 'contract_sale.contract_template_sale_manager'), - ('contract_sale.account_analytic_invoice_line_saleman', - 'contract_sale.contract_line_saleman'), - ('contract_sale.account_analytic_invoice_line_manager', - 'contract_sale.contract_line_manager'), - ('contract_sale.account_analytic_contract_line_salesman', - 'contract_sale.contract_template_line_salesman'), - ('contract_sale.account_analytic_contract_line_manager', - 'contract_sale.contract_template_line_manager'), - ('contract_sale.account_analytic_account_contract_salesman', - 'contract_sale.contract_contract_salesman'), + ( + "contract_sale.account_analytic_account_own_salesman", + "contract_sale.contract_contract_own_salesman", + ), + ( + "contract_sale.account_analytic_account_see_all", + "contract_sale.contract_contract_see_all", + ), + ( + "contract_sale.account_analytic_contract_salesman", + "contract_sale.contract_template_salesman", + ), + ( + "contract_sale.account_analytic_contract_sale_manager", + "contract_sale.contract_template_sale_manager", + ), + ( + "contract_sale.account_analytic_invoice_line_saleman", + "contract_sale.contract_line_saleman", + ), + ( + "contract_sale.account_analytic_invoice_line_manager", + "contract_sale.contract_line_manager", + ), + ( + "contract_sale.account_analytic_contract_line_salesman", + "contract_sale.contract_template_line_salesman", + ), + ( + "contract_sale.account_analytic_contract_line_manager", + "contract_sale.contract_template_line_manager", + ), + ( + "contract_sale.account_analytic_account_contract_salesman", + "contract_sale.contract_contract_salesman", + ), ] openupgrade.rename_xmlids(cr, xmlids_to_rename) diff --git a/contract_variable_quantity/models/abstract_contract_line.py b/contract_variable_quantity/models/abstract_contract_line.py index 07c4ec128..9d9dfa91b 100644 --- a/contract_variable_quantity/models/abstract_contract_line.py +++ b/contract_variable_quantity/models/abstract_contract_line.py @@ -7,15 +7,12 @@ from odoo import fields, models class ContractAbstractContractLine(models.AbstractModel): - _inherit = 'contract.abstract.contract.line' + _inherit = "contract.abstract.contract.line" qty_type = fields.Selection( - selection=[ - ('fixed', 'Fixed quantity'), - ('variable', 'Variable quantity'), - ], + selection=[("fixed", "Fixed quantity"), ("variable", "Variable quantity")], required=True, - default='fixed', + default="fixed", string="Qty. type", ) qty_formula_id = fields.Many2one( diff --git a/contract_variable_quantity/models/contract.py b/contract_variable_quantity/models/contract.py index b0f6755b6..c6be92da2 100644 --- a/contract_variable_quantity/models/contract.py +++ b/contract_variable_quantity/models/contract.py @@ -10,6 +10,6 @@ class ContractContract(models.Model): _inherit = "contract.contract" skip_zero_qty = fields.Boolean( - string='Skip Zero Qty Lines', + string="Skip Zero Qty Lines", help="If checked, contract lines with 0 qty don't create invoice line", ) diff --git a/contract_variable_quantity/models/contract_line.py b/contract_variable_quantity/models/contract_line.py index 714e8eb51..683b849d6 100644 --- a/contract_variable_quantity/models/contract_line.py +++ b/contract_variable_quantity/models/contract_line.py @@ -9,30 +9,28 @@ from odoo.tools.safe_eval import safe_eval class AccountAnalyticInvoiceLine(models.Model): - _inherit = 'contract.line' + _inherit = "contract.line" @api.multi def _get_quantity_to_invoice( self, period_first_date, period_last_date, invoice_date ): - quantity = super( - AccountAnalyticInvoiceLine, self - )._get_quantity_to_invoice( + quantity = super(AccountAnalyticInvoiceLine, self)._get_quantity_to_invoice( period_first_date, period_last_date, invoice_date ) if not period_first_date or not period_last_date or not invoice_date: return quantity - if self.qty_type == 'variable': + if self.qty_type == "variable": eval_context = { - 'env': self.env, - 'context': self.env.context, - 'user': self.env.user, - 'line': self, - 'quantity': quantity, - 'period_first_date': period_first_date, - 'period_last_date': period_last_date, - 'invoice_date': invoice_date, - 'contract': self.contract_id, + "env": self.env, + "context": self.env.context, + "user": self.env.user, + "line": self, + "quantity": quantity, + "period_first_date": period_first_date, + "period_last_date": period_last_date, + "invoice_date": invoice_date, + "contract": self.contract_id, } safe_eval( self.qty_formula_id.code.strip(), @@ -40,7 +38,7 @@ class AccountAnalyticInvoiceLine(models.Model): mode="exec", nocopy=True, ) # nocopy for returning result - quantity = eval_context.get('result', 0) + quantity = eval_context.get("result", 0) return quantity @api.multi @@ -49,13 +47,11 @@ class AccountAnalyticInvoiceLine(models.Model): invoice_id=invoice_id, invoice_values=invoice_values, ) if ( - 'quantity' in vals + "quantity" in vals and self.contract_id.skip_zero_qty and float_is_zero( - vals['quantity'], - self.env['decimal.precision'].precision_get( - 'Product Unit of Measure' - ), + vals["quantity"], + self.env["decimal.precision"].precision_get("Product Unit of Measure"), ) ): vals = {} diff --git a/contract_variable_quantity/models/contract_line_formula.py b/contract_variable_quantity/models/contract_line_formula.py index 3493cb974..2760af000 100644 --- a/contract_variable_quantity/models/contract_line_formula.py +++ b/contract_variable_quantity/models/contract_line_formula.py @@ -3,38 +3,36 @@ # Copyright 2018 ACSONE SA/NV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import _, api, fields, models, exceptions +from odoo import _, api, exceptions, fields, models from odoo.tools.safe_eval import safe_eval class ContractLineFormula(models.Model): - _name = 'contract.line.qty.formula' - _description = 'Contract Line Formula' + _name = "contract.line.qty.formula" + _description = "Contract Line Formula" name = fields.Char(required=True, translate=True) code = fields.Text(required=True, default="result = 0") - @api.constrains('code') + @api.constrains("code") def _check_code(self): eval_context = { - 'env': self.env, - 'context': self.env.context, - 'user': self.env.user, - 'line': self.env['contract.line'], - 'contract': self.env['contract.contract'], - 'invoice': self.env['account.invoice'], - 'quantity': 0, - 'period_first_date': False, - 'period_last_date': False, - 'invoice_date': False, + "env": self.env, + "context": self.env.context, + "user": self.env.user, + "line": self.env["contract.line"], + "contract": self.env["contract.contract"], + "invoice": self.env["account.invoice"], + "quantity": 0, + "period_first_date": False, + "period_last_date": False, + "invoice_date": False, } try: - safe_eval( - self.code.strip(), eval_context, mode="exec", nocopy=True - ) + safe_eval(self.code.strip(), eval_context, mode="exec", nocopy=True) except Exception as e: raise exceptions.ValidationError( - _('Error evaluating code.\nDetails: %s') % e + _("Error evaluating code.\nDetails: %s") % e ) - if 'result' not in eval_context: - raise exceptions.ValidationError(_('No valid result returned.')) + if "result" not in eval_context: + raise exceptions.ValidationError(_("No valid result returned.")) diff --git a/contract_variable_quantity/tests/test_contract_variable_quantity.py b/contract_variable_quantity/tests/test_contract_variable_quantity.py index 3e295a284..d7a829f1d 100644 --- a/contract_variable_quantity/tests/test_contract_variable_quantity.py +++ b/contract_variable_quantity/tests/test_contract_variable_quantity.py @@ -12,48 +12,46 @@ from odoo import exceptions class TestContractVariableQuantity(odoo.tests.HttpCase): def setUp(self): super(TestContractVariableQuantity, self).setUp() - self.partner = self.env['res.partner'].create({'name': 'Test partner'}) - self.product = self.env['product.product'].create( - {'name': 'Test product'} - ) - self.contract = self.env['contract.contract'].create( + self.partner = self.env["res.partner"].create({"name": "Test partner"}) + self.product = self.env["product.product"].create({"name": "Test product"}) + self.contract = self.env["contract.contract"].create( { - 'name': 'Test Contract', - 'partner_id': self.partner.id, - 'pricelist_id': self.partner.property_product_pricelist.id, + "name": "Test Contract", + "partner_id": self.partner.id, + "pricelist_id": self.partner.property_product_pricelist.id, } ) - self.formula = self.env['contract.line.qty.formula'].create( + self.formula = self.env["contract.line.qty.formula"].create( { - 'name': 'Test formula', + "name": "Test formula", # For testing each of the possible variables - 'code': 'env["res.users"]\n' + "code": 'env["res.users"]\n' 'context.get("lang")\n' - 'user.id\n' - 'line.qty_type\n' - 'contract.id\n' - 'quantity\n' - 'period_first_date\n' - 'period_last_date\n' - 'invoice_date\n' - 'result = 12', + "user.id\n" + "line.qty_type\n" + "contract.id\n" + "quantity\n" + "period_first_date\n" + "period_last_date\n" + "invoice_date\n" + "result = 12", } ) - self.contract_line = self.env['contract.line'].create( + self.contract_line = self.env["contract.line"].create( { - 'contract_id': self.contract.id, - 'product_id': self.product.id, - 'name': 'Test', - 'qty_type': 'variable', - 'qty_formula_id': self.formula.id, - 'quantity': 1, - 'uom_id': self.product.uom_id.id, - 'price_unit': 100, - 'discount': 50, - 'recurring_rule_type': 'monthly', - 'recurring_interval': 1, - 'date_start': '2016-02-15', - 'recurring_next_date': '2016-02-29', + "contract_id": self.contract.id, + "product_id": self.product.id, + "name": "Test", + "qty_type": "variable", + "qty_formula_id": self.formula.id, + "quantity": 1, + "uom_id": self.product.uom_id.id, + "price_unit": 100, + "discount": 50, + "recurring_rule_type": "monthly", + "recurring_interval": 1, + "date_start": "2016-02-15", + "recurring_next_date": "2016-02-29", } ) @@ -71,7 +69,7 @@ class TestContractVariableQuantity(odoo.tests.HttpCase): self.assertEqual(invoice.invoice_line_ids[0].quantity, 12) def test_check_skip_zero_qty(self): - self.formula.code = 'result=0' + self.formula.code = "result=0" self.contract.skip_zero_qty = True invoice = self.contract.recurring_create_invoice() self.assertFalse(invoice.invoice_line_ids) diff --git a/contract_variable_quantity/views/abstract_contract_line.xml b/contract_variable_quantity/views/abstract_contract_line.xml index 8a5f2a88e..b6cd8af1d 100644 --- a/contract_variable_quantity/views/abstract_contract_line.xml +++ b/contract_variable_quantity/views/abstract_contract_line.xml @@ -1,18 +1,20 @@ - + - - + Abstract Contract Line Form View contract.abstract.contract.line - + - + - @@ -22,5 +24,4 @@ - diff --git a/contract_variable_quantity/views/contract.xml b/contract_variable_quantity/views/contract.xml index 5d6330a99..bf1be85d2 100644 --- a/contract_variable_quantity/views/contract.xml +++ b/contract_variable_quantity/views/contract.xml @@ -1,24 +1,30 @@ - + - contract.contract - + - + - - + + - - {'invisible': [('qty_type', '!=', 'fixed')]} + + {'invisible': [('qty_type', '!=', 'fixed')]} - diff --git a/contract_variable_quantity/views/contract_line_formula.xml b/contract_variable_quantity/views/contract_line_formula.xml index 97791d0f7..b1dec49ef 100644 --- a/contract_variable_quantity/views/contract_line_formula.xml +++ b/contract_variable_quantity/views/contract_line_formula.xml @@ -1,15 +1,13 @@ - + - contract.line.qty.formula - + - contract.line.qty.formula @@ -17,13 +15,17 @@

- +

- +

Help with Python expressions.

You have to insert valid Python code block that stores at some moment a float/integer value of @@ -65,9 +67,7 @@ - - + Formulas (quantity) contract.line.qty.formula form @@ -78,10 +78,9 @@

- - - diff --git a/contract_variable_quantity/views/contract_line_views.xml b/contract_variable_quantity/views/contract_line_views.xml index f74106298..1d6d3ec90 100644 --- a/contract_variable_quantity/views/contract_line_views.xml +++ b/contract_variable_quantity/views/contract_line_views.xml @@ -1,24 +1,26 @@ - + - - contract.line tree view (in contract) - Add variable qty fields + contract.line tree view (in contract) - Add variable qty fields contract.line - + - + - {'invisible': [('qty_type', '!=', 'fixed')]} + {'invisible': [('qty_type', '!=', 'fixed')]} - diff --git a/contract_variable_quantity/views/contract_template.xml b/contract_variable_quantity/views/contract_template.xml index 3deb0bace..72964a3ef 100644 --- a/contract_variable_quantity/views/contract_template.xml +++ b/contract_variable_quantity/views/contract_template.xml @@ -1,23 +1,33 @@ - + - Contract Template Variable Qty contract.template - + - - + + - - + - - {'required': [('qty_type', '=', 'fixed')], 'invisible': [('qty_type', '!=', 'fixed')]} + + {'required': [('qty_type', '=', 'fixed')], 'invisible': [('qty_type', '!=', 'fixed')]} -