|
@ -2,6 +2,7 @@ |
|
|
# Copyright 2018 Tecnativa - Pedro M. Baeza |
|
|
# Copyright 2018 Tecnativa - Pedro M. Baeza |
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
|
|
|
|
|
|
|
|
|
|
|
from collections import namedtuple |
|
|
from datetime import timedelta |
|
|
from datetime import timedelta |
|
|
from dateutil.relativedelta import relativedelta |
|
|
from dateutil.relativedelta import relativedelta |
|
|
from odoo import fields |
|
|
from odoo import fields |
|
@ -681,6 +682,316 @@ class TestContract(TestContractBase): |
|
|
error_message(*combination), |
|
|
error_message(*combination), |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
def test_next_invoicing_period(self): |
|
|
|
|
|
"""Test different combination for next invoicing period |
|
|
|
|
|
{ |
|
|
|
|
|
( |
|
|
|
|
|
'recurring_next_date', # date |
|
|
|
|
|
'next_period_date_start', # date |
|
|
|
|
|
'next_period_date_end' # date |
|
|
|
|
|
): ( |
|
|
|
|
|
date_start, # date |
|
|
|
|
|
date_end, # date |
|
|
|
|
|
last_date_invoiced, # date |
|
|
|
|
|
recurring_next_date, # date |
|
|
|
|
|
recurring_invoicing_type, # ('pre-paid','post-paid',) |
|
|
|
|
|
recurring_rule_type, # ('daily', 'weekly', 'monthly', |
|
|
|
|
|
# 'monthlylastday', 'yearly'), |
|
|
|
|
|
recurring_interval, # integer |
|
|
|
|
|
max_date_end, # date |
|
|
|
|
|
), |
|
|
|
|
|
} |
|
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
def _update_contract_line( |
|
|
|
|
|
case, |
|
|
|
|
|
date_start, |
|
|
|
|
|
date_end, |
|
|
|
|
|
last_date_invoiced, |
|
|
|
|
|
recurring_next_date, |
|
|
|
|
|
recurring_invoicing_type, |
|
|
|
|
|
recurring_rule_type, |
|
|
|
|
|
recurring_interval, |
|
|
|
|
|
max_date_end, |
|
|
|
|
|
): |
|
|
|
|
|
self.acct_line.write( |
|
|
|
|
|
{ |
|
|
|
|
|
'date_start': date_start, |
|
|
|
|
|
'date_end': date_end, |
|
|
|
|
|
'last_date_invoiced': last_date_invoiced, |
|
|
|
|
|
'recurring_next_date': recurring_next_date, |
|
|
|
|
|
'recurring_invoicing_type': recurring_invoicing_type, |
|
|
|
|
|
'recurring_rule_type': recurring_rule_type, |
|
|
|
|
|
'recurring_interval': recurring_interval, |
|
|
|
|
|
'max_date_end': max_date_end, |
|
|
|
|
|
} |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
def _get_result(): |
|
|
|
|
|
return Result( |
|
|
|
|
|
recurring_next_date=self.acct_line.recurring_next_date, |
|
|
|
|
|
next_period_date_start=self.acct_line.next_period_date_start, |
|
|
|
|
|
next_period_date_end=self.acct_line.next_period_date_end, |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
def _error_message( |
|
|
|
|
|
case, |
|
|
|
|
|
date_start, |
|
|
|
|
|
date_end, |
|
|
|
|
|
last_date_invoiced, |
|
|
|
|
|
recurring_next_date, |
|
|
|
|
|
recurring_invoicing_type, |
|
|
|
|
|
recurring_rule_type, |
|
|
|
|
|
recurring_interval, |
|
|
|
|
|
max_date_end, |
|
|
|
|
|
): |
|
|
|
|
|
return ( |
|
|
|
|
|
"Error in case %s:" |
|
|
|
|
|
"date_start: %s, " |
|
|
|
|
|
"date_end: %s, " |
|
|
|
|
|
"last_date_invoiced: %s, " |
|
|
|
|
|
"recurring_next_date: %s, " |
|
|
|
|
|
"recurring_invoicing_type: %s, " |
|
|
|
|
|
"recurring_rule_type: %s, " |
|
|
|
|
|
"recurring_interval: %s, " |
|
|
|
|
|
"max_date_end: %s, " |
|
|
|
|
|
) % ( |
|
|
|
|
|
case, |
|
|
|
|
|
date_start, |
|
|
|
|
|
date_end, |
|
|
|
|
|
last_date_invoiced, |
|
|
|
|
|
recurring_next_date, |
|
|
|
|
|
recurring_invoicing_type, |
|
|
|
|
|
recurring_rule_type, |
|
|
|
|
|
recurring_interval, |
|
|
|
|
|
max_date_end, |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
Result = namedtuple( |
|
|
|
|
|
'Result', |
|
|
|
|
|
[ |
|
|
|
|
|
'recurring_next_date', |
|
|
|
|
|
'next_period_date_start', |
|
|
|
|
|
'next_period_date_end', |
|
|
|
|
|
], |
|
|
|
|
|
) |
|
|
|
|
|
Combination = namedtuple( |
|
|
|
|
|
'Combination', |
|
|
|
|
|
[ |
|
|
|
|
|
'case', |
|
|
|
|
|
'date_start', |
|
|
|
|
|
'date_end', |
|
|
|
|
|
'last_date_invoiced', |
|
|
|
|
|
'recurring_next_date', |
|
|
|
|
|
'recurring_invoicing_type', |
|
|
|
|
|
'recurring_rule_type', |
|
|
|
|
|
'recurring_interval', |
|
|
|
|
|
'max_date_end', |
|
|
|
|
|
], |
|
|
|
|
|
) |
|
|
|
|
|
combinations = { |
|
|
|
|
|
Result( |
|
|
|
|
|
recurring_next_date=to_date('2019-01-01'), |
|
|
|
|
|
next_period_date_start=to_date('2019-01-01'), |
|
|
|
|
|
next_period_date_end=to_date('2019-01-31'), |
|
|
|
|
|
): Combination( |
|
|
|
|
|
case="1", |
|
|
|
|
|
date_start='2019-01-01', |
|
|
|
|
|
date_end=False, |
|
|
|
|
|
last_date_invoiced=False, |
|
|
|
|
|
recurring_next_date='2019-01-01', |
|
|
|
|
|
recurring_invoicing_type='pre-paid', |
|
|
|
|
|
recurring_rule_type='monthly', |
|
|
|
|
|
recurring_interval=1, |
|
|
|
|
|
max_date_end=False, |
|
|
|
|
|
), |
|
|
|
|
|
Result( |
|
|
|
|
|
recurring_next_date=to_date('2019-01-01'), |
|
|
|
|
|
next_period_date_start=to_date('2019-01-01'), |
|
|
|
|
|
next_period_date_end=to_date('2019-01-15'), |
|
|
|
|
|
): Combination( |
|
|
|
|
|
case="2", |
|
|
|
|
|
date_start='2019-01-01', |
|
|
|
|
|
date_end='2019-01-15', |
|
|
|
|
|
last_date_invoiced=False, |
|
|
|
|
|
recurring_next_date='2019-01-01', |
|
|
|
|
|
recurring_invoicing_type='pre-paid', |
|
|
|
|
|
recurring_rule_type='monthly', |
|
|
|
|
|
recurring_interval=1, |
|
|
|
|
|
max_date_end=False, |
|
|
|
|
|
), |
|
|
|
|
|
Result( |
|
|
|
|
|
recurring_next_date=to_date('2019-01-05'), |
|
|
|
|
|
next_period_date_start=to_date('2019-01-05'), |
|
|
|
|
|
next_period_date_end=to_date('2019-01-15'), |
|
|
|
|
|
): Combination( |
|
|
|
|
|
case="3", |
|
|
|
|
|
date_start='2019-01-05', |
|
|
|
|
|
date_end='2019-01-15', |
|
|
|
|
|
last_date_invoiced=False, |
|
|
|
|
|
recurring_next_date='2019-01-05', |
|
|
|
|
|
recurring_invoicing_type='pre-paid', |
|
|
|
|
|
recurring_rule_type='monthly', |
|
|
|
|
|
recurring_interval=1, |
|
|
|
|
|
max_date_end=False, |
|
|
|
|
|
), |
|
|
|
|
|
Result( |
|
|
|
|
|
recurring_next_date=to_date('2019-01-05'), |
|
|
|
|
|
next_period_date_start=to_date('2019-01-01'), |
|
|
|
|
|
next_period_date_end=to_date('2019-01-15'), |
|
|
|
|
|
): Combination( |
|
|
|
|
|
case="4", |
|
|
|
|
|
date_start='2019-01-01', |
|
|
|
|
|
date_end='2019-01-15', |
|
|
|
|
|
last_date_invoiced=False, |
|
|
|
|
|
recurring_next_date='2019-01-05', |
|
|
|
|
|
recurring_invoicing_type='pre-paid', |
|
|
|
|
|
recurring_rule_type='monthly', |
|
|
|
|
|
recurring_interval=1, |
|
|
|
|
|
max_date_end=False, |
|
|
|
|
|
), |
|
|
|
|
|
Result( |
|
|
|
|
|
recurring_next_date=to_date('2019-02-01'), |
|
|
|
|
|
next_period_date_start=to_date('2019-01-01'), |
|
|
|
|
|
next_period_date_end=to_date('2019-01-31'), |
|
|
|
|
|
): Combination( |
|
|
|
|
|
case="5", |
|
|
|
|
|
date_start='2019-01-01', |
|
|
|
|
|
date_end=False, |
|
|
|
|
|
last_date_invoiced=False, |
|
|
|
|
|
recurring_next_date='2019-02-01', |
|
|
|
|
|
recurring_invoicing_type='post-paid', |
|
|
|
|
|
recurring_rule_type='monthly', |
|
|
|
|
|
recurring_interval=1, |
|
|
|
|
|
max_date_end=False, |
|
|
|
|
|
), |
|
|
|
|
|
Result( |
|
|
|
|
|
recurring_next_date=to_date('2019-02-01'), |
|
|
|
|
|
next_period_date_start=to_date('2019-01-01'), |
|
|
|
|
|
next_period_date_end=to_date('2019-01-15'), |
|
|
|
|
|
): Combination( |
|
|
|
|
|
case="6", |
|
|
|
|
|
date_start='2019-01-01', |
|
|
|
|
|
date_end='2019-01-15', |
|
|
|
|
|
last_date_invoiced=False, |
|
|
|
|
|
recurring_next_date='2019-02-01', |
|
|
|
|
|
recurring_invoicing_type='post-paid', |
|
|
|
|
|
recurring_rule_type='monthly', |
|
|
|
|
|
recurring_interval=1, |
|
|
|
|
|
max_date_end=False, |
|
|
|
|
|
), |
|
|
|
|
|
Result( |
|
|
|
|
|
recurring_next_date=to_date('2019-02-01'), |
|
|
|
|
|
next_period_date_start=to_date('2019-01-05'), |
|
|
|
|
|
next_period_date_end=to_date('2019-01-31'), |
|
|
|
|
|
): Combination( |
|
|
|
|
|
case="7", |
|
|
|
|
|
date_start='2019-01-05', |
|
|
|
|
|
date_end=False, |
|
|
|
|
|
last_date_invoiced=False, |
|
|
|
|
|
recurring_next_date='2019-02-01', |
|
|
|
|
|
recurring_invoicing_type='post-paid', |
|
|
|
|
|
recurring_rule_type='monthly', |
|
|
|
|
|
recurring_interval=1, |
|
|
|
|
|
max_date_end=False, |
|
|
|
|
|
), |
|
|
|
|
|
Result( |
|
|
|
|
|
recurring_next_date=to_date('2019-01-05'), |
|
|
|
|
|
next_period_date_start=to_date('2019-01-01'), |
|
|
|
|
|
next_period_date_end=to_date('2019-01-15'), |
|
|
|
|
|
): Combination( |
|
|
|
|
|
case="8", |
|
|
|
|
|
date_start='2019-01-01', |
|
|
|
|
|
date_end='2019-01-15', |
|
|
|
|
|
last_date_invoiced=False, |
|
|
|
|
|
recurring_next_date='2019-01-05', |
|
|
|
|
|
recurring_invoicing_type='pre-paid', |
|
|
|
|
|
recurring_rule_type='monthly', |
|
|
|
|
|
recurring_interval=1, |
|
|
|
|
|
max_date_end=False, |
|
|
|
|
|
), |
|
|
|
|
|
Result( |
|
|
|
|
|
recurring_next_date=to_date('2019-01-01'), |
|
|
|
|
|
next_period_date_start=to_date('2018-12-16'), |
|
|
|
|
|
next_period_date_end=to_date('2019-01-31'), |
|
|
|
|
|
): Combination( |
|
|
|
|
|
case="9", |
|
|
|
|
|
date_start='2018-01-01', |
|
|
|
|
|
date_end='2020-01-15', |
|
|
|
|
|
last_date_invoiced='2018-12-15', |
|
|
|
|
|
recurring_next_date='2019-01-01', |
|
|
|
|
|
recurring_invoicing_type='pre-paid', |
|
|
|
|
|
recurring_rule_type='monthly', |
|
|
|
|
|
recurring_interval=1, |
|
|
|
|
|
max_date_end=False, |
|
|
|
|
|
), |
|
|
|
|
|
Result( |
|
|
|
|
|
recurring_next_date=to_date('2019-01-01'), |
|
|
|
|
|
next_period_date_start=to_date('2018-12-16'), |
|
|
|
|
|
next_period_date_end=to_date('2018-12-31'), |
|
|
|
|
|
): Combination( |
|
|
|
|
|
case="10", |
|
|
|
|
|
date_start='2018-01-01', |
|
|
|
|
|
date_end='2020-01-15', |
|
|
|
|
|
last_date_invoiced='2018-12-15', |
|
|
|
|
|
recurring_next_date='2019-01-01', |
|
|
|
|
|
recurring_invoicing_type='post-paid', |
|
|
|
|
|
recurring_rule_type='monthly', |
|
|
|
|
|
recurring_interval=1, |
|
|
|
|
|
max_date_end=False, |
|
|
|
|
|
), |
|
|
|
|
|
Result( |
|
|
|
|
|
recurring_next_date=to_date('2018-12-31'), |
|
|
|
|
|
next_period_date_start=to_date('2018-12-16'), |
|
|
|
|
|
next_period_date_end=to_date('2018-12-31'), |
|
|
|
|
|
): Combination( |
|
|
|
|
|
case="11", |
|
|
|
|
|
date_start='2018-01-01', |
|
|
|
|
|
date_end='2020-01-15', |
|
|
|
|
|
last_date_invoiced='2018-12-15', |
|
|
|
|
|
recurring_next_date='2018-12-31', |
|
|
|
|
|
recurring_invoicing_type='post-paid', |
|
|
|
|
|
recurring_rule_type='monthlylastday', |
|
|
|
|
|
recurring_interval=1, |
|
|
|
|
|
max_date_end=False, |
|
|
|
|
|
), |
|
|
|
|
|
Result( |
|
|
|
|
|
recurring_next_date=to_date('2018-12-16'), |
|
|
|
|
|
next_period_date_start=to_date('2018-12-16'), |
|
|
|
|
|
next_period_date_end=to_date('2018-12-31'), |
|
|
|
|
|
): Combination( |
|
|
|
|
|
case="12", |
|
|
|
|
|
date_start='2018-01-01', |
|
|
|
|
|
date_end='2020-01-15', |
|
|
|
|
|
last_date_invoiced='2018-12-15', |
|
|
|
|
|
recurring_next_date='2018-12-16', |
|
|
|
|
|
recurring_invoicing_type='pre-paid', |
|
|
|
|
|
recurring_rule_type='monthlylastday', |
|
|
|
|
|
recurring_interval=1, |
|
|
|
|
|
max_date_end=False, |
|
|
|
|
|
), |
|
|
|
|
|
Result( |
|
|
|
|
|
recurring_next_date=to_date('2018-01-05'), |
|
|
|
|
|
next_period_date_start=to_date('2018-01-05'), |
|
|
|
|
|
next_period_date_end=to_date('2018-03-31'), |
|
|
|
|
|
): Combination( |
|
|
|
|
|
case="12", |
|
|
|
|
|
date_start='2018-01-05', |
|
|
|
|
|
date_end='2020-01-15', |
|
|
|
|
|
last_date_invoiced=False, |
|
|
|
|
|
recurring_next_date='2018-01-05', |
|
|
|
|
|
recurring_invoicing_type='pre-paid', |
|
|
|
|
|
recurring_rule_type='monthlylastday', |
|
|
|
|
|
recurring_interval=3, |
|
|
|
|
|
max_date_end=False, |
|
|
|
|
|
), |
|
|
|
|
|
} |
|
|
|
|
|
for result, combination in combinations.items(): |
|
|
|
|
|
_update_contract_line(*combination) |
|
|
|
|
|
self.assertEqual( |
|
|
|
|
|
result, _get_result(), _error_message(*combination) |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
def test_recurring_next_date(self): |
|
|
def test_recurring_next_date(self): |
|
|
"""recurring next date for a contract is the min for all lines""" |
|
|
"""recurring next date for a contract is the min for all lines""" |
|
|
self.contract.recurring_create_invoice() |
|
|
self.contract.recurring_create_invoice() |
|
|