Files
contract/contract_variable_quantity/models/contract.py
Dmytro Katyukha b5f549ebac [FIX] analytic invoice/contract lines inheritance
Bug description
---------------

`account.analytic.contract.line` inherits
`account.analytic.invoice.line`

`account.analytic.invoice.line` defines field `analytic_account_id`:
   - comodel='account.analytic.account'

`account.analytic.contract.line` redefines field `analytic_account_id`:
   - comodel='account.analytic.contract'

On attempt to extend `account.analytic.invoice.line` model adding
field that depends on `analytic_account_id.date_start`
Odoo fails to update, because it adds this field to
`account.analytic.contract.line` through inheritance,
and `account.analytic.contract` model have no this field.

What is done
------------

Change inheritance order:
- `account.analytic.invoice.line` inherits
`account.analytic.contract.line`
- no file renames at this stage (this wil be done in next commit)
2021-09-23 16:47:59 +02:00

84 lines
3.1 KiB
Python

# Copyright 2016 Tecnativa - Pedro M. Baeza
# Copyright 2018 Tecnativa - Carlos Dauden
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models, exceptions
from odoo.tools import float_is_zero
from odoo.tools.safe_eval import safe_eval
class AccountAnalyticAccount(models.Model):
_inherit = "account.analytic.account"
skip_zero_qty = fields.Boolean(
string='Skip Zero Qty Lines',
help="If checked, contract lines with 0 qty don't create invoice line",
)
@api.model
def _prepare_invoice_line(self, line, invoice_id):
vals = super(AccountAnalyticAccount, self)._prepare_invoice_line(
line, invoice_id)
if line.qty_type == 'variable':
eval_context = {
'env': self.env,
'context': self.env.context,
'user': self.env.user,
'line': line,
'contract': line.analytic_account_id,
'invoice': self.env['account.invoice'].browse(invoice_id),
}
safe_eval(line.qty_formula_id.code.strip(), eval_context,
mode="exec", nocopy=True) # nocopy for returning result
qty = eval_context.get('result', 0)
if self.skip_zero_qty and float_is_zero(
qty, self.env['decimal.precision'].precision_get(
'Product Unit of Measure')):
# Return empty dict to skip line create
vals = {}
else:
vals['quantity'] = qty
# Re-evaluate price with this new quantity
vals['price_unit'] = line.with_context(
contract_line_qty=qty,
).price_unit
return vals
class AccountAnalyticContractLine(models.Model):
_inherit = 'account.analytic.contract.line'
qty_type = fields.Selection(
selection=[
('fixed', 'Fixed quantity'),
('variable', 'Variable quantity'),
], required=True, default='fixed', string="Qty. type")
qty_formula_id = fields.Many2one(
comodel_name="contract.line.qty.formula", string="Qty. formula")
class ContractLineFormula(models.Model):
_name = 'contract.line.qty.formula'
name = fields.Char(required=True, translate=True)
code = fields.Text(required=True, default="result = 0")
@api.constrains('code')
def _check_code(self):
eval_context = {
'env': self.env,
'context': self.env.context,
'user': self.env.user,
'line': self.env['account.analytic.invoice.line'],
'contract': self.env['account.analytic.account'],
'invoice': self.env['account.invoice'],
}
try:
safe_eval(
self.code.strip(), eval_context, mode="exec", nocopy=True)
except Exception as e:
raise exceptions.ValidationError(
_('Error evaluating code.\nDetails: %s') % e)
if 'result' not in eval_context:
raise exceptions.ValidationError(_('No valid result returned.'))