mirror of
https://github.com/OCA/contract.git
synced 2025-02-13 17:57:24 +02:00
[REF] contract: make recurring_invoicing_offset a computed field
In preparation to making it user modifiable.
This commit is contained in:
committed by
Francisco Ivan Anton Prieto
parent
d74f65ff97
commit
198060511c
@@ -4,7 +4,7 @@
|
|||||||
# Copyright 2016-2018 Tecnativa - Carlos Dauden
|
# Copyright 2016-2018 Tecnativa - Carlos Dauden
|
||||||
# Copyright 2017 Tecnativa - Vicent Cubells
|
# Copyright 2017 Tecnativa - Vicent Cubells
|
||||||
# Copyright 2016-2017 LasLabs Inc.
|
# Copyright 2016-2017 LasLabs Inc.
|
||||||
# Copyright 2018 ACSONE SA/NV
|
# Copyright 2018-2019 ACSONE SA/NV
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -70,9 +70,20 @@ class ContractAbstractContractLine(models.AbstractModel):
|
|||||||
[('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')],
|
[('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')],
|
||||||
default='pre-paid',
|
default='pre-paid',
|
||||||
string='Invoicing type',
|
string='Invoicing type',
|
||||||
help="Specify if process date is 'from' or 'to' invoicing date",
|
help=(
|
||||||
|
"Specify if the invoice must be generated at the beginning "
|
||||||
|
"(pre-paid) or end (post-paid) of the period."
|
||||||
|
),
|
||||||
required=True,
|
required=True,
|
||||||
)
|
)
|
||||||
|
recurring_invoicing_offset = fields.Integer(
|
||||||
|
compute="_compute_recurring_invoicing_offset",
|
||||||
|
string="Invoicing offset",
|
||||||
|
help=(
|
||||||
|
"Number of days to offset the invoice from the period end "
|
||||||
|
"date (in post-paid mode) or beginning date (in pre-paid mode)."
|
||||||
|
)
|
||||||
|
)
|
||||||
recurring_interval = fields.Integer(
|
recurring_interval = fields.Integer(
|
||||||
default=1,
|
default=1,
|
||||||
string='Invoice Every',
|
string='Invoice Every',
|
||||||
@@ -115,6 +126,27 @@ class ContractAbstractContractLine(models.AbstractModel):
|
|||||||
ondelete='cascade',
|
ondelete='cascade',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _get_default_recurring_invoicing_offset(
|
||||||
|
self, recurring_invoicing_type, recurring_rule_type
|
||||||
|
):
|
||||||
|
if (
|
||||||
|
recurring_invoicing_type == 'pre-paid'
|
||||||
|
or recurring_rule_type == 'monthlylastday'
|
||||||
|
):
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
@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
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
@api.depends(
|
@api.depends(
|
||||||
'automatic_price',
|
'automatic_price',
|
||||||
'specific_price',
|
'specific_price',
|
||||||
|
|||||||
@@ -375,32 +375,20 @@ class ContractLine(models.Model):
|
|||||||
return self._get_recurring_next_date(
|
return self._get_recurring_next_date(
|
||||||
date_start,
|
date_start,
|
||||||
recurring_invoicing_type,
|
recurring_invoicing_type,
|
||||||
|
self._get_default_recurring_invoicing_offset(
|
||||||
|
recurring_invoicing_type, recurring_rule_type
|
||||||
|
),
|
||||||
recurring_rule_type,
|
recurring_rule_type,
|
||||||
recurring_interval,
|
recurring_interval,
|
||||||
max_date_end=False,
|
max_date_end=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.model
|
|
||||||
def _get_offset(self, recurring_invoicing_type, recurring_rule_type):
|
|
||||||
"""Return a relativedelta to offset the invoice date compared
|
|
||||||
to the period start or end date.
|
|
||||||
|
|
||||||
This method will disappear when the offset becomes user controlled.
|
|
||||||
"""
|
|
||||||
if (
|
|
||||||
recurring_invoicing_type == 'pre-paid'
|
|
||||||
or recurring_rule_type == 'monthlylastday'
|
|
||||||
):
|
|
||||||
offset = 0
|
|
||||||
else:
|
|
||||||
offset = 1
|
|
||||||
return relativedelta(days=offset)
|
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _get_recurring_next_date(
|
def _get_recurring_next_date(
|
||||||
self,
|
self,
|
||||||
next_period_date_start,
|
next_period_date_start,
|
||||||
recurring_invoicing_type,
|
recurring_invoicing_type,
|
||||||
|
recurring_invoicing_offset,
|
||||||
recurring_rule_type,
|
recurring_rule_type,
|
||||||
recurring_interval,
|
recurring_interval,
|
||||||
max_date_end,
|
max_date_end,
|
||||||
@@ -408,17 +396,23 @@ class ContractLine(models.Model):
|
|||||||
next_period_date_end = self._get_next_period_date_end(
|
next_period_date_end = self._get_next_period_date_end(
|
||||||
next_period_date_start,
|
next_period_date_start,
|
||||||
recurring_invoicing_type,
|
recurring_invoicing_type,
|
||||||
|
recurring_invoicing_offset,
|
||||||
recurring_rule_type,
|
recurring_rule_type,
|
||||||
recurring_interval,
|
recurring_interval,
|
||||||
max_date_end=max_date_end,
|
max_date_end=max_date_end,
|
||||||
)
|
)
|
||||||
if not next_period_date_end:
|
if not next_period_date_end:
|
||||||
return False
|
return False
|
||||||
offset = self._get_offset(recurring_invoicing_type, recurring_rule_type)
|
|
||||||
if recurring_invoicing_type == 'pre-paid':
|
if recurring_invoicing_type == 'pre-paid':
|
||||||
recurring_next_date = next_period_date_start + offset
|
recurring_next_date = (
|
||||||
|
next_period_date_start
|
||||||
|
+ relativedelta(days=recurring_invoicing_offset)
|
||||||
|
)
|
||||||
else: # post-paid
|
else: # post-paid
|
||||||
recurring_next_date = next_period_date_end + offset
|
recurring_next_date = (
|
||||||
|
next_period_date_end
|
||||||
|
+ relativedelta(days=recurring_invoicing_offset)
|
||||||
|
)
|
||||||
return recurring_next_date
|
return recurring_next_date
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
@@ -426,6 +420,7 @@ class ContractLine(models.Model):
|
|||||||
self,
|
self,
|
||||||
next_period_date_start,
|
next_period_date_start,
|
||||||
recurring_invoicing_type,
|
recurring_invoicing_type,
|
||||||
|
recurring_invoicing_offset,
|
||||||
recurring_rule_type,
|
recurring_rule_type,
|
||||||
recurring_interval,
|
recurring_interval,
|
||||||
max_date_end,
|
max_date_end,
|
||||||
@@ -448,18 +443,20 @@ class ContractLine(models.Model):
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# special algorithm when the next invoice date is forced
|
# special algorithm when the next invoice date is forced
|
||||||
offset = self._get_offset(recurring_invoicing_type, recurring_rule_type)
|
|
||||||
if recurring_invoicing_type == 'pre-paid':
|
if recurring_invoicing_type == 'pre-paid':
|
||||||
next_period_date_end = (
|
next_period_date_end = (
|
||||||
next_invoice_date
|
next_invoice_date
|
||||||
- offset
|
- relativedelta(days=recurring_invoicing_offset)
|
||||||
+ self.get_relative_delta(
|
+ self.get_relative_delta(
|
||||||
recurring_rule_type, recurring_interval
|
recurring_rule_type, recurring_interval
|
||||||
)
|
)
|
||||||
- relativedelta(days=1)
|
- relativedelta(days=1)
|
||||||
)
|
)
|
||||||
else: # post-paid
|
else: # post-paid
|
||||||
next_period_date_end = next_invoice_date - 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:
|
if max_date_end and next_period_date_end > max_date_end:
|
||||||
# end date is past max_date_end: trim it
|
# end date is past max_date_end: trim it
|
||||||
next_period_date_end = max_date_end
|
next_period_date_end = max_date_end
|
||||||
@@ -481,6 +478,7 @@ class ContractLine(models.Model):
|
|||||||
@api.depends(
|
@api.depends(
|
||||||
'next_period_date_start',
|
'next_period_date_start',
|
||||||
'recurring_invoicing_type',
|
'recurring_invoicing_type',
|
||||||
|
'recurring_invoicing_offset',
|
||||||
'recurring_rule_type',
|
'recurring_rule_type',
|
||||||
'recurring_interval',
|
'recurring_interval',
|
||||||
'date_end',
|
'date_end',
|
||||||
@@ -491,6 +489,7 @@ class ContractLine(models.Model):
|
|||||||
rec.next_period_date_end = self._get_next_period_date_end(
|
rec.next_period_date_end = self._get_next_period_date_end(
|
||||||
rec.next_period_date_start,
|
rec.next_period_date_start,
|
||||||
rec.recurring_invoicing_type,
|
rec.recurring_invoicing_type,
|
||||||
|
rec.recurring_invoicing_offset,
|
||||||
rec.recurring_rule_type,
|
rec.recurring_rule_type,
|
||||||
rec.recurring_interval,
|
rec.recurring_interval,
|
||||||
max_date_end=rec.date_end,
|
max_date_end=rec.date_end,
|
||||||
@@ -538,6 +537,7 @@ class ContractLine(models.Model):
|
|||||||
rec.recurring_next_date = self._get_recurring_next_date(
|
rec.recurring_next_date = self._get_recurring_next_date(
|
||||||
rec.date_start,
|
rec.date_start,
|
||||||
rec.recurring_invoicing_type,
|
rec.recurring_invoicing_type,
|
||||||
|
rec.recurring_invoicing_offset,
|
||||||
rec.recurring_rule_type,
|
rec.recurring_rule_type,
|
||||||
rec.recurring_interval,
|
rec.recurring_interval,
|
||||||
max_date_end=rec.date_end,
|
max_date_end=rec.date_end,
|
||||||
@@ -673,6 +673,7 @@ class ContractLine(models.Model):
|
|||||||
last_date_invoiced = self._get_next_period_date_end(
|
last_date_invoiced = self._get_next_period_date_end(
|
||||||
first_date_invoiced,
|
first_date_invoiced,
|
||||||
self.recurring_invoicing_type,
|
self.recurring_invoicing_type,
|
||||||
|
self.recurring_invoicing_offset,
|
||||||
self.recurring_rule_type,
|
self.recurring_rule_type,
|
||||||
self.recurring_interval,
|
self.recurring_interval,
|
||||||
max_date_end=(self.date_end if stop_at_date_end else False),
|
max_date_end=(self.date_end if stop_at_date_end else False),
|
||||||
@@ -702,6 +703,7 @@ class ContractLine(models.Model):
|
|||||||
recurring_next_date = rec._get_recurring_next_date(
|
recurring_next_date = rec._get_recurring_next_date(
|
||||||
last_date_invoiced + relativedelta(days=1),
|
last_date_invoiced + relativedelta(days=1),
|
||||||
rec.recurring_invoicing_type,
|
rec.recurring_invoicing_type,
|
||||||
|
rec.recurring_invoicing_offset,
|
||||||
rec.recurring_rule_type,
|
rec.recurring_rule_type,
|
||||||
rec.recurring_interval,
|
rec.recurring_interval,
|
||||||
max_date_end=rec.date_end,
|
max_date_end=rec.date_end,
|
||||||
@@ -778,6 +780,7 @@ class ContractLine(models.Model):
|
|||||||
new_recurring_next_date = self._get_recurring_next_date(
|
new_recurring_next_date = self._get_recurring_next_date(
|
||||||
new_date_start,
|
new_date_start,
|
||||||
rec.recurring_invoicing_type,
|
rec.recurring_invoicing_type,
|
||||||
|
rec.recurring_invoicing_offset,
|
||||||
rec.recurring_rule_type,
|
rec.recurring_rule_type,
|
||||||
rec.recurring_interval,
|
rec.recurring_interval,
|
||||||
max_date_end=new_date_end
|
max_date_end=new_date_end
|
||||||
@@ -842,6 +845,7 @@ class ContractLine(models.Model):
|
|||||||
recurring_next_date = self._get_recurring_next_date(
|
recurring_next_date = self._get_recurring_next_date(
|
||||||
date_start,
|
date_start,
|
||||||
self.recurring_invoicing_type,
|
self.recurring_invoicing_type,
|
||||||
|
self.recurring_invoicing_offset,
|
||||||
self.recurring_rule_type,
|
self.recurring_rule_type,
|
||||||
self.recurring_interval,
|
self.recurring_interval,
|
||||||
max_date_end=date_end,
|
max_date_end=date_end,
|
||||||
|
|||||||
@@ -537,6 +537,33 @@ class TestContract(TestContractBase):
|
|||||||
'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']
|
||||||
|
self.assertEqual(
|
||||||
|
clm._get_default_recurring_invoicing_offset(
|
||||||
|
"pre-paid", "monthly"
|
||||||
|
),
|
||||||
|
0
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
clm._get_default_recurring_invoicing_offset(
|
||||||
|
"post-paid", "monthly"
|
||||||
|
),
|
||||||
|
1
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
clm._get_default_recurring_invoicing_offset(
|
||||||
|
"pre-paid", "monthlylastday"
|
||||||
|
),
|
||||||
|
0
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
clm._get_default_recurring_invoicing_offset(
|
||||||
|
"post-paid", "monthlylastday"
|
||||||
|
),
|
||||||
|
0
|
||||||
|
)
|
||||||
|
|
||||||
def test_get_recurring_next_date(self):
|
def test_get_recurring_next_date(self):
|
||||||
"""Test different combination to compute recurring_next_date
|
"""Test different combination to compute recurring_next_date
|
||||||
Combination format
|
Combination format
|
||||||
@@ -555,87 +582,92 @@ class TestContract(TestContractBase):
|
|||||||
def error_message(
|
def error_message(
|
||||||
date_start,
|
date_start,
|
||||||
recurring_invoicing_type,
|
recurring_invoicing_type,
|
||||||
|
recurring_invoicing_offset,
|
||||||
recurring_rule_type,
|
recurring_rule_type,
|
||||||
recurring_interval,
|
recurring_interval,
|
||||||
max_date_end,
|
max_date_end,
|
||||||
):
|
):
|
||||||
return "Error in %s every %d %s case, start with %s (max_date_end=%s)" % (
|
return (
|
||||||
recurring_invoicing_type,
|
"Error in %s-%d every %d %s case, "
|
||||||
recurring_interval,
|
"start with %s (max_date_end=%s)" % (
|
||||||
recurring_rule_type,
|
recurring_invoicing_type,
|
||||||
date_start,
|
recurring_invoicing_offset,
|
||||||
max_date_end,
|
recurring_interval,
|
||||||
|
recurring_rule_type,
|
||||||
|
date_start,
|
||||||
|
max_date_end,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
combinations = [
|
combinations = [
|
||||||
(
|
(
|
||||||
to_date('2018-01-01'),
|
to_date('2018-01-01'),
|
||||||
(to_date('2018-01-01'), 'pre-paid', 'monthly', 1,
|
(to_date('2018-01-01'), 'pre-paid', 0, 'monthly', 1,
|
||||||
False),
|
False),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
to_date('2018-01-01'),
|
to_date('2018-01-01'),
|
||||||
(to_date('2018-01-01'), 'pre-paid', 'monthly', 1,
|
(to_date('2018-01-01'), 'pre-paid', 0, 'monthly', 1,
|
||||||
to_date('2018-01-15')),
|
to_date('2018-01-15')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
False,
|
False,
|
||||||
(to_date('2018-01-16'), 'pre-paid', 'monthly', 1,
|
(to_date('2018-01-16'), 'pre-paid', 0, 'monthly', 1,
|
||||||
to_date('2018-01-15')),
|
to_date('2018-01-15')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
to_date('2018-01-01'),
|
to_date('2018-01-01'),
|
||||||
(to_date('2018-01-01'), 'pre-paid', 'monthly', 2,
|
(to_date('2018-01-01'), 'pre-paid', 0, 'monthly', 2,
|
||||||
False),
|
False),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
to_date('2018-02-01'),
|
to_date('2018-02-01'),
|
||||||
(to_date('2018-01-01'), 'post-paid', 'monthly', 1,
|
(to_date('2018-01-01'), 'post-paid', 1, 'monthly', 1,
|
||||||
False),
|
False),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
to_date('2018-01-16'),
|
to_date('2018-01-16'),
|
||||||
(to_date('2018-01-01'), 'post-paid', 'monthly', 1,
|
(to_date('2018-01-01'), 'post-paid', 1, 'monthly', 1,
|
||||||
to_date('2018-01-15')),
|
to_date('2018-01-15')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
False,
|
False,
|
||||||
(to_date('2018-01-16'), 'post-paid', 'monthly', 1,
|
(to_date('2018-01-16'), 'post-paid', 1, 'monthly', 1,
|
||||||
to_date('2018-01-15')),
|
to_date('2018-01-15')),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
to_date('2018-03-01'),
|
to_date('2018-03-01'),
|
||||||
(to_date('2018-01-01'), 'post-paid', 'monthly', 2,
|
(to_date('2018-01-01'), 'post-paid', 1, 'monthly', 2,
|
||||||
False),
|
False),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
to_date('2018-01-31'),
|
to_date('2018-01-31'),
|
||||||
(to_date('2018-01-05'), 'post-paid', 'monthlylastday', 1,
|
(to_date('2018-01-05'), 'post-paid', 0, 'monthlylastday', 1,
|
||||||
False),
|
False),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
to_date('2018-01-06'),
|
to_date('2018-01-06'),
|
||||||
(to_date('2018-01-06'), 'pre-paid', 'monthlylastday', 1,
|
(to_date('2018-01-06'), 'pre-paid', 0, 'monthlylastday', 1,
|
||||||
False),
|
False),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
to_date('2018-02-28'),
|
to_date('2018-02-28'),
|
||||||
(to_date('2018-01-05'), 'post-paid', 'monthlylastday', 2,
|
(to_date('2018-01-05'), 'post-paid', 0, 'monthlylastday', 2,
|
||||||
False),
|
False),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
to_date('2018-01-05'),
|
to_date('2018-01-05'),
|
||||||
(to_date('2018-01-05'), 'pre-paid', 'monthlylastday', 2,
|
(to_date('2018-01-05'), 'pre-paid', 0, 'monthlylastday', 2,
|
||||||
False),
|
False),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
to_date('2018-01-05'),
|
to_date('2018-01-05'),
|
||||||
(to_date('2018-01-05'), 'pre-paid', 'yearly', 1,
|
(to_date('2018-01-05'), 'pre-paid', 0, 'yearly', 1,
|
||||||
False),
|
False),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
to_date('2019-01-05'),
|
to_date('2019-01-05'),
|
||||||
(to_date('2018-01-05'), 'post-paid', 'yearly', 1,
|
(to_date('2018-01-05'), 'post-paid', 1, 'yearly', 1,
|
||||||
False),
|
False),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user