Browse Source

[REF] - add method to get quantity to invoice

the contract line quantity can be in some use cases variable, to simplify
the way it is changed we add a new method _get_quantity_to_invoice.
pull/207/head
sbejaoui 6 years ago
parent
commit
2f7aed2744
  1. 3
      contract/models/abstract_contract.py
  2. 30
      contract/models/abstract_contract_line.py
  3. 40
      contract/models/contract.py
  4. 29
      contract/models/contract_line.py
  5. 99
      contract/tests/test_contract.py

3
contract/models/abstract_contract.py

@ -19,8 +19,7 @@ class AbstractAccountAnalyticContract(models.AbstractModel):
name = fields.Char(required=True) name = fields.Char(required=True)
# Needed for avoiding errors on several inherited behaviors # Needed for avoiding errors on several inherited behaviors
partner_id = fields.Many2one( partner_id = fields.Many2one(
comodel_name="res.partner", string="Partner (always False)",
index=True,
comodel_name="res.partner", string="Partner (always False)", index=True
) )
pricelist_id = fields.Many2one( pricelist_id = fields.Many2one(
comodel_name='product.pricelist', string='Pricelist' comodel_name='product.pricelist', string='Pricelist'

30
contract/models/abstract_contract_line.py

@ -81,7 +81,7 @@ class AccountAbstractAnalyticContractLine(models.AbstractModel):
) )
date_start = fields.Date(string='Date Start') date_start = fields.Date(string='Date Start')
recurring_next_date = fields.Date(string='Date of Next Invoice') 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_canceled = fields.Boolean(string="Canceled", default=False)
is_auto_renew = fields.Boolean(string="Auto Renew", default=False) is_auto_renew = fields.Boolean(string="Auto Renew", default=False)
auto_renew_interval = fields.Integer( auto_renew_interval = fields.Integer(
@ -116,6 +116,17 @@ class AccountAbstractAnalyticContractLine(models.AbstractModel):
oldname='analytic_account_id', oldname='analytic_account_id',
) )
@api.multi
def _get_invoiced_period(self, last_date_invoiced, recurring_next_date):
return self.date_start, last_date_invoiced, recurring_next_date
@api.multi
def _get_quantity_to_invoice(
self, period_first_date, period_last_date, invoice_date
):
self.ensure_one()
return self.quantity
@api.depends( @api.depends(
'automatic_price', 'automatic_price',
'specific_price', 'specific_price',
@ -130,9 +141,13 @@ class AccountAbstractAnalyticContractLine(models.AbstractModel):
""" """
for line in self: for line in self:
if line.automatic_price: if line.automatic_price:
dates = line._get_invoiced_period(
line.last_date_invoiced, line.recurring_next_date
)
product = line.product_id.with_context( product = line.product_id.with_context(
quantity=line.env.context.get( quantity=line.env.context.get(
'contract_line_qty', line.quantity
'contract_line_qty',
line._get_quantity_to_invoice(*dates),
), ),
pricelist=line.contract_id.pricelist_id.id, pricelist=line.contract_id.pricelist_id.id,
partner=line.contract_id.partner_id.id, partner=line.contract_id.partner_id.id,
@ -155,7 +170,10 @@ class AccountAbstractAnalyticContractLine(models.AbstractModel):
@api.depends('quantity', 'price_unit', 'discount') @api.depends('quantity', 'price_unit', 'discount')
def _compute_price_subtotal(self): def _compute_price_subtotal(self):
for line in self: for line in self:
subtotal = line.quantity * line.price_unit
dates = line._get_invoiced_period(
line.last_date_invoiced, line.recurring_next_date
)
subtotal = line._get_quantity_to_invoice(*dates) * line.price_unit
discount = line.discount / 100 discount = line.discount / 100
subtotal *= 1 - discount subtotal *= 1 - discount
if line.contract_id.pricelist_id: if line.contract_id.pricelist_id:
@ -192,11 +210,13 @@ class AccountAbstractAnalyticContractLine(models.AbstractModel):
date = self.recurring_next_date or fields.Date.context_today(self) date = self.recurring_next_date or fields.Date.context_today(self)
partner = self.contract_id.partner_id or self.env.user.partner_id partner = self.contract_id.partner_id or self.env.user.partner_id
dates = self._get_invoiced_period(
self.last_date_invoiced, self.recurring_next_date
)
product = self.product_id.with_context( product = self.product_id.with_context(
lang=partner.lang, lang=partner.lang,
partner=partner.id, partner=partner.id,
quantity=self.quantity,
quantity=self._get_quantity_to_invoice(*dates),
date=date, date=date,
pricelist=self.contract_id.pricelist_id.id, pricelist=self.contract_id.pricelist_id.id,
uom=self.uom_id.id, uom=self.uom_id.id,

40
contract/models/contract.py

@ -48,8 +48,7 @@ class AccountAnalyticAccount(models.Model):
compute='_compute_date_end', string='Date End', store=True compute='_compute_date_end', string='Date End', store=True
) )
payment_term_id = fields.Many2one( 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") invoice_count = fields.Integer(compute="_compute_invoice_count")
fiscal_position_id = fields.Many2one( fiscal_position_id = fields.Many2one(
@ -63,8 +62,7 @@ class AccountAnalyticAccount(models.Model):
ondelete='restrict', ondelete='restrict',
) )
partner_id = fields.Many2one( partner_id = fields.Many2one(
comodel_name='res.partner',
inverse='_inverse_partner_id',
comodel_name='res.partner', inverse='_inverse_partner_id'
) )
@api.multi @api.multi
@ -72,7 +70,8 @@ class AccountAnalyticAccount(models.Model):
for rec in self: for rec in self:
if not rec.invoice_partner_id: if not rec.invoice_partner_id:
rec.invoice_partner_id = rec.partner_id.address_get( rec.invoice_partner_id = rec.partner_id.address_get(
['invoice'])['invoice']
['invoice']
)['invoice']
@api.multi @api.multi
def _get_related_invoices(self): def _get_related_invoices(self):
@ -104,11 +103,16 @@ class AccountAnalyticAccount(models.Model):
@api.multi @api.multi
def action_show_invoices(self): def action_show_invoices(self):
self.ensure_one() self.ensure_one()
tree_view_ref = 'account.invoice_supplier_tree' \
if self.contract_type == 'purchase' \
tree_view_ref = (
'account.invoice_supplier_tree'
if self.contract_type == 'purchase'
else 'account.invoice_tree_with_onboarding' else 'account.invoice_tree_with_onboarding'
form_view_ref = 'account.invoice_supplier_form' \
if self.contract_type == 'purchase' else 'account.invoice_form'
)
form_view_ref = (
'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) 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) form_view = self.env.ref(form_view_ref, raise_if_not_found=False)
action = { action = {
@ -184,12 +188,18 @@ class AccountAnalyticAccount(models.Model):
def _onchange_partner_id(self): def _onchange_partner_id(self):
self.pricelist_id = self.partner_id.property_product_pricelist.id self.pricelist_id = self.partner_id.property_product_pricelist.id
self.fiscal_position_id = self.partner_id.property_account_position_id self.fiscal_position_id = self.partner_id.property_account_position_id
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)]}}
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),
]
}
}
@api.constrains('partner_id', 'recurring_invoices') @api.constrains('partner_id', 'recurring_invoices')
def _check_partner_id_recurring_invoices(self): def _check_partner_id_recurring_invoices(self):

29
contract/models/contract_line.py

@ -486,9 +486,12 @@ class AccountAnalyticInvoiceLine(models.Model):
@api.multi @api.multi
def _prepare_invoice_line(self, invoice_id=False): def _prepare_invoice_line(self, invoice_id=False):
self.ensure_one() self.ensure_one()
dates = self._get_invoiced_period(
self.last_date_invoiced, self.recurring_next_date
)
invoice_line_vals = { invoice_line_vals = {
'product_id': self.product_id.id, 'product_id': self.product_id.id,
'quantity': self.quantity,
'quantity': self._get_quantity_to_invoice(*dates),
'uom_id': self.uom_id.id, 'uom_id': self.uom_id.id,
'discount': self.discount, 'discount': self.discount,
'contract_line_id': self.id, 'contract_line_id': self.id,
@ -501,8 +504,7 @@ class AccountAnalyticInvoiceLine(models.Model):
invoice_line_vals = invoice_line._convert_to_write(invoice_line._cache) invoice_line_vals = invoice_line._convert_to_write(invoice_line._cache)
# Insert markers # Insert markers
contract = self.contract_id contract = self.contract_id
first_date_invoiced, last_date_invoiced = self._get_invoiced_period()
name = self._insert_markers(first_date_invoiced, last_date_invoiced)
name = self._insert_markers(dates[0], dates[1])
invoice_line_vals.update( invoice_line_vals.update(
{ {
'name': name, 'name': name,
@ -513,10 +515,11 @@ class AccountAnalyticInvoiceLine(models.Model):
return invoice_line_vals return invoice_line_vals
@api.multi @api.multi
def _get_next_invoiced_period(
self, last_date_invoiced, recurring_next_date
):
def _get_invoiced_period(self, last_date_invoiced, recurring_next_date):
self.ensure_one() self.ensure_one()
first_date_invoiced = False
if not recurring_next_date:
return first_date_invoiced, last_date_invoiced, recurring_next_date
first_date_invoiced = ( first_date_invoiced = (
last_date_invoiced + relativedelta(days=1) last_date_invoiced + relativedelta(days=1)
if last_date_invoiced if last_date_invoiced
@ -537,21 +540,9 @@ class AccountAnalyticInvoiceLine(models.Model):
last_date_invoiced = recurring_next_date - relativedelta( last_date_invoiced = recurring_next_date - relativedelta(
days=1 days=1
) )
recurring_next_date = recurring_next_date + self.get_relative_delta(
self.recurring_rule_type, self.recurring_interval
)
return first_date_invoiced, last_date_invoiced, recurring_next_date
@api.multi
def _get_invoiced_period(self):
self.ensure_one()
dates = self._get_next_invoiced_period(
self.last_date_invoiced, self.recurring_next_date
)
first_date_invoiced, last_date_invoiced, recurring_next_date = dates
if self.date_end and self.date_end < last_date_invoiced: if self.date_end and self.date_end < last_date_invoiced:
last_date_invoiced = self.date_end last_date_invoiced = self.date_end
return first_date_invoiced, last_date_invoiced
return first_date_invoiced, last_date_invoiced, recurring_next_date
@api.multi @api.multi
def _insert_markers(self, first_date_invoiced, last_date_invoiced): def _insert_markers(self, first_date_invoiced, last_date_invoiced):

99
contract/tests/test_contract.py

@ -153,9 +153,7 @@ class TestContract(TestContractBase):
self.inv_line = self.invoice_monthly.invoice_line_ids[0] self.inv_line = self.invoice_monthly.invoice_line_ids[0]
self.assertTrue(self.inv_line.invoice_line_tax_ids) self.assertTrue(self.inv_line.invoice_line_tax_ids)
self.assertAlmostEqual(self.inv_line.price_subtotal, 50.0) self.assertAlmostEqual(self.inv_line.price_subtotal, 50.0)
self.assertEqual(
self.contract.user_id, self.invoice_monthly.user_id
)
self.assertEqual(self.contract.user_id, self.invoice_monthly.user_id)
def test_contract_recurring_next_date(self): def test_contract_recurring_next_date(self):
recurring_next_date = to_date('2018-01-15') recurring_next_date = to_date('2018-01-15')
@ -1332,15 +1330,24 @@ class TestContract(TestContractBase):
self.acct_line.recurring_rule_type = 'monthlylastday' self.acct_line.recurring_rule_type = 'monthlylastday'
self.acct_line.date_end = '2018-03-15' self.acct_line.date_end = '2018-03-15'
self.acct_line._onchange_date_start() self.acct_line._onchange_date_start()
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2018-01-05')) self.assertEqual(first, to_date('2018-01-05'))
self.assertEqual(last, to_date('2018-01-31')) self.assertEqual(last, to_date('2018-01-31'))
self.contract.recurring_create_invoice() self.contract.recurring_create_invoice()
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2018-02-01')) self.assertEqual(first, to_date('2018-02-01'))
self.assertEqual(last, to_date('2018-02-28')) self.assertEqual(last, to_date('2018-02-28'))
self.contract.recurring_create_invoice() self.contract.recurring_create_invoice()
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2018-03-01')) self.assertEqual(first, to_date('2018-03-01'))
self.assertEqual(last, to_date('2018-03-15')) self.assertEqual(last, to_date('2018-03-15'))
self.acct_line.manual_renew_needed = True self.acct_line.manual_renew_needed = True
@ -1352,11 +1359,17 @@ class TestContract(TestContractBase):
self.acct_line.date_end = '2018-08-15' self.acct_line.date_end = '2018-08-15'
self.acct_line._onchange_date_start() self.acct_line._onchange_date_start()
self.contract.recurring_create_invoice() self.contract.recurring_create_invoice()
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2018-02-05')) self.assertEqual(first, to_date('2018-02-05'))
self.assertEqual(last, to_date('2018-03-04')) self.assertEqual(last, to_date('2018-03-04'))
self.acct_line.recurring_next_date = '2018-06-05' self.acct_line.recurring_next_date = '2018-06-05'
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2018-02-05')) self.assertEqual(first, to_date('2018-02-05'))
self.assertEqual(last, to_date('2018-07-04')) self.assertEqual(last, to_date('2018-07-04'))
@ -1367,11 +1380,17 @@ class TestContract(TestContractBase):
self.acct_line.date_end = '2018-08-15' self.acct_line.date_end = '2018-08-15'
self.acct_line._onchange_date_start() self.acct_line._onchange_date_start()
self.contract.recurring_create_invoice() self.contract.recurring_create_invoice()
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2018-02-05')) self.assertEqual(first, to_date('2018-02-05'))
self.assertEqual(last, to_date('2018-03-04')) self.assertEqual(last, to_date('2018-03-04'))
self.acct_line.recurring_next_date = '2018-06-05' self.acct_line.recurring_next_date = '2018-06-05'
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2018-02-05')) self.assertEqual(first, to_date('2018-02-05'))
self.assertEqual(last, to_date('2018-06-04')) self.assertEqual(last, to_date('2018-06-04'))
@ -1381,15 +1400,24 @@ class TestContract(TestContractBase):
self.acct_line.recurring_rule_type = 'monthly' self.acct_line.recurring_rule_type = 'monthly'
self.acct_line.date_end = '2018-03-15' self.acct_line.date_end = '2018-03-15'
self.acct_line._onchange_date_start() self.acct_line._onchange_date_start()
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2018-01-05')) self.assertEqual(first, to_date('2018-01-05'))
self.assertEqual(last, to_date('2018-02-04')) self.assertEqual(last, to_date('2018-02-04'))
self.contract.recurring_create_invoice() self.contract.recurring_create_invoice()
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2018-02-05')) self.assertEqual(first, to_date('2018-02-05'))
self.assertEqual(last, to_date('2018-03-04')) self.assertEqual(last, to_date('2018-03-04'))
self.contract.recurring_create_invoice() self.contract.recurring_create_invoice()
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2018-03-05')) self.assertEqual(first, to_date('2018-03-05'))
self.assertEqual(last, to_date('2018-03-15')) self.assertEqual(last, to_date('2018-03-15'))
@ -1399,15 +1427,24 @@ class TestContract(TestContractBase):
self.acct_line.recurring_rule_type = 'monthly' self.acct_line.recurring_rule_type = 'monthly'
self.acct_line.date_end = '2018-03-15' self.acct_line.date_end = '2018-03-15'
self.acct_line._onchange_date_start() self.acct_line._onchange_date_start()
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2018-01-05')) self.assertEqual(first, to_date('2018-01-05'))
self.assertEqual(last, to_date('2018-02-04')) self.assertEqual(last, to_date('2018-02-04'))
self.contract.recurring_create_invoice() self.contract.recurring_create_invoice()
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2018-02-05')) self.assertEqual(first, to_date('2018-02-05'))
self.assertEqual(last, to_date('2018-03-04')) self.assertEqual(last, to_date('2018-03-04'))
self.contract.recurring_create_invoice() self.contract.recurring_create_invoice()
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2018-03-05')) self.assertEqual(first, to_date('2018-03-05'))
self.assertEqual(last, to_date('2018-03-15')) self.assertEqual(last, to_date('2018-03-15'))
@ -1417,15 +1454,24 @@ class TestContract(TestContractBase):
self.acct_line.recurring_rule_type = 'yearly' self.acct_line.recurring_rule_type = 'yearly'
self.acct_line.date_end = '2020-03-15' self.acct_line.date_end = '2020-03-15'
self.acct_line._onchange_date_start() self.acct_line._onchange_date_start()
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2018-01-05')) self.assertEqual(first, to_date('2018-01-05'))
self.assertEqual(last, to_date('2019-01-04')) self.assertEqual(last, to_date('2019-01-04'))
self.contract.recurring_create_invoice() self.contract.recurring_create_invoice()
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2019-01-05')) self.assertEqual(first, to_date('2019-01-05'))
self.assertEqual(last, to_date('2020-01-04')) self.assertEqual(last, to_date('2020-01-04'))
self.contract.recurring_create_invoice() self.contract.recurring_create_invoice()
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2020-01-05')) self.assertEqual(first, to_date('2020-01-05'))
self.assertEqual(last, to_date('2020-03-15')) self.assertEqual(last, to_date('2020-03-15'))
@ -1435,15 +1481,24 @@ class TestContract(TestContractBase):
self.acct_line.recurring_rule_type = 'yearly' self.acct_line.recurring_rule_type = 'yearly'
self.acct_line.date_end = '2020-03-15' self.acct_line.date_end = '2020-03-15'
self.acct_line._onchange_date_start() self.acct_line._onchange_date_start()
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2018-01-05')) self.assertEqual(first, to_date('2018-01-05'))
self.assertEqual(last, to_date('2019-01-04')) self.assertEqual(last, to_date('2019-01-04'))
self.contract.recurring_create_invoice() self.contract.recurring_create_invoice()
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2019-01-05')) self.assertEqual(first, to_date('2019-01-05'))
self.assertEqual(last, to_date('2020-01-04')) self.assertEqual(last, to_date('2020-01-04'))
self.contract.recurring_create_invoice() self.contract.recurring_create_invoice()
first, last = self.acct_line._get_invoiced_period()
first, last, recurring_next_date = self.acct_line._get_invoiced_period(
self.acct_line.last_date_invoiced,
self.acct_line.recurring_next_date,
)
self.assertEqual(first, to_date('2020-01-05')) self.assertEqual(first, to_date('2020-01-05'))
self.assertEqual(last, to_date('2020-03-15')) self.assertEqual(last, to_date('2020-03-15'))

Loading…
Cancel
Save