[ADD] contract_variable_quantity:

=================================================
Variable quantity in contract recurrent invoicing
=================================================

With this module, you will be able to define in recurring contracts some
lines with variable quantity according a provided formula.

Configuration
=============

* Go to Sales > Configuration > Contracts > Formulas (quantity).
* Define any formula based on Python code that stores at some moment a
  float/integer value of the quantity to invoice in the variable 'result'.

  You can use these variables to compute your formula:

  * *env*: Environment variable for getting other models.
  * *context*: Current context dictionary.
  * *user*: Current user.
  * *line*: Contract recurring invoice line that triggers this formula.
  * *contract*: Contract whose line belongs to.
  * *invoice*: Invoice (header) being created.

Usage
=====

To use this module, you need to:

* Go to Sales -> Contracts and select or create a new contract.
* Check *Generate recurring invoices automatically*.
* Add a new recurring invoicing line.
* Select "Variable quantity" in column "Qty. type".
* Select one of the possible formulas to use (previously created).
This commit is contained in:
Pedro M. Baeza
2016-09-09 03:03:38 +02:00
committed by Carolina Fernandez
parent 11c08aacc3
commit 7c282e0157
11 changed files with 625 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import contract

View File

@@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
# © 2016 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import _, api, fields, models, exceptions
from openerp.tools.safe_eval import safe_eval
class AccountAnalyticAccount(models.Model):
_inherit = "account.analytic.account"
@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
vals['quantity'] = eval_context.get('result', 0)
return vals
class AccountAnalyticInvoiceLine(models.Model):
_inherit = 'account.analytic.invoice.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)
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.'))