mirror of
https://github.com/OCA/contract.git
synced 2025-02-13 17:57:24 +02:00
[IMP] - Replace is_suspended flag by manual_renew_needed
Add a computed field for the first date of the termination notice period Adapt state compute and search method [IMP] - Improve unit tests
This commit is contained in:
committed by
Francisco Ivan Anton Prieto
parent
8a388b3d9a
commit
c2555ea18a
@@ -33,6 +33,12 @@ class AccountAnalyticInvoiceLine(models.Model):
|
||||
last_date_invoiced = fields.Date(
|
||||
string='Last Date Invoiced', readonly=True, copy=False
|
||||
)
|
||||
termination_notice_date = fields.Date(
|
||||
string='Termination notice date',
|
||||
compute="_compute_termination_notice_date",
|
||||
store=True,
|
||||
copy=False,
|
||||
)
|
||||
create_invoice_visibility = fields.Boolean(
|
||||
compute='_compute_create_invoice_visibility'
|
||||
)
|
||||
@@ -55,7 +61,13 @@ class AccountAnalyticInvoiceLine(models.Model):
|
||||
copy=False,
|
||||
help="Contract Line origin of this one.",
|
||||
)
|
||||
is_suspended = fields.Boolean(string="Suspended", default=False)
|
||||
manual_renew_needed = fields.Boolean(
|
||||
string="Manual renew needed",
|
||||
default=False,
|
||||
help="This flag is used to make a difference between a definitive stop"
|
||||
"and temporary one for which a user is not able to plan a"
|
||||
"successor in advance",
|
||||
)
|
||||
is_plan_successor_allowed = fields.Boolean(
|
||||
string="Plan successor allowed?", compute='_compute_allowed'
|
||||
)
|
||||
@@ -76,8 +88,7 @@ class AccountAnalyticInvoiceLine(models.Model):
|
||||
selection=[
|
||||
('upcoming', 'Upcoming'),
|
||||
('in-progress', 'In-progress'),
|
||||
('suspension-planed', 'Suspension Planed'),
|
||||
('suspended', 'Suspended'),
|
||||
('to-renew', 'To renew'),
|
||||
('upcoming-close', 'Upcoming Close'),
|
||||
('closed', 'Closed'),
|
||||
('canceled', 'Canceled'),
|
||||
@@ -94,6 +105,24 @@ class AccountAnalyticInvoiceLine(models.Model):
|
||||
)
|
||||
|
||||
@api.multi
|
||||
@api.depends(
|
||||
'date_end',
|
||||
'termination_notice_rule_type',
|
||||
'termination_notice_interval',
|
||||
)
|
||||
def _compute_termination_notice_date(self):
|
||||
for rec in self:
|
||||
if rec.date_end:
|
||||
rec.termination_notice_date = (
|
||||
rec.date_end
|
||||
- self.get_relative_delta(
|
||||
rec.termination_notice_rule_type,
|
||||
rec.termination_notice_interval,
|
||||
)
|
||||
)
|
||||
|
||||
@api.multi
|
||||
@api.depends('is_canceled', 'date_start', 'date_end', 'is_auto_renew')
|
||||
def _compute_state(self):
|
||||
today = fields.Date.context_today(self)
|
||||
for rec in self:
|
||||
@@ -111,17 +140,24 @@ class AccountAnalyticInvoiceLine(models.Model):
|
||||
and (not rec.date_end or rec.date_end >= today)
|
||||
):
|
||||
# In period
|
||||
if rec.is_suspended:
|
||||
rec.state = 'suspension-planed'
|
||||
continue
|
||||
if rec.date_end and not rec.is_auto_renew:
|
||||
if (
|
||||
rec.termination_notice_date
|
||||
and rec.termination_notice_date < today
|
||||
and not rec.is_auto_renew
|
||||
and not rec.manual_renew_needed
|
||||
):
|
||||
rec.state = 'upcoming-close'
|
||||
else:
|
||||
rec.state = 'in-progress'
|
||||
continue
|
||||
if rec.date_end and rec.date_end < today:
|
||||
if rec.is_suspended and not rec.successor_contract_line_id:
|
||||
rec.state = 'suspended'
|
||||
# After
|
||||
if (
|
||||
rec.manual_renew_needed
|
||||
and not rec.successor_contract_line_id
|
||||
or rec.is_auto_renew
|
||||
):
|
||||
rec.state = 'to-renew'
|
||||
else:
|
||||
rec.state = 'closed'
|
||||
|
||||
@@ -139,36 +175,28 @@ class AccountAnalyticInvoiceLine(models.Model):
|
||||
"&",
|
||||
"&",
|
||||
"&",
|
||||
"&",
|
||||
('date_start', '<=', today),
|
||||
('is_auto_renew', '=', True),
|
||||
('is_suspended', '=', False),
|
||||
('is_canceled', '=', False),
|
||||
"|",
|
||||
('date_end', '>=', today),
|
||||
('date_end', '=', False),
|
||||
"|",
|
||||
"&",
|
||||
('is_auto_renew', '=', True),
|
||||
('is_auto_renew', '=', False),
|
||||
('termination_notice_date', '>', today),
|
||||
]
|
||||
if state == 'suspension-planed':
|
||||
if state == 'to-renew':
|
||||
return [
|
||||
"&",
|
||||
"&",
|
||||
"&",
|
||||
('date_start', '<=', today),
|
||||
('is_suspended', '=', True),
|
||||
('is_canceled', '=', False),
|
||||
'|',
|
||||
('date_end', '>=', today),
|
||||
('date_end', '=', False),
|
||||
]
|
||||
if state == 'suspended':
|
||||
return [
|
||||
"&",
|
||||
"&",
|
||||
"&",
|
||||
('date_end', '<', today),
|
||||
"|",
|
||||
"&",
|
||||
('manual_renew_needed', '=', True),
|
||||
('successor_contract_line_id', '=', False),
|
||||
('is_suspended', '=', True),
|
||||
('is_canceled', '=', False),
|
||||
('is_auto_renew', '=', True),
|
||||
]
|
||||
if state == 'upcoming-close':
|
||||
return [
|
||||
@@ -176,32 +204,41 @@ class AccountAnalyticInvoiceLine(models.Model):
|
||||
"&",
|
||||
"&",
|
||||
"&",
|
||||
"&",
|
||||
('date_start', '<=', today),
|
||||
('is_auto_renew', '=', False),
|
||||
('is_suspended', '=', False),
|
||||
('manual_renew_needed', '=', False),
|
||||
('is_canceled', '=', False),
|
||||
'|',
|
||||
('termination_notice_date', '<', today),
|
||||
('date_end', '>=', today),
|
||||
('date_end', '=', False),
|
||||
]
|
||||
if state == 'closed':
|
||||
return [
|
||||
"&",
|
||||
"&",
|
||||
"&",
|
||||
('is_canceled', '=', False),
|
||||
('date_end', '<', today),
|
||||
('is_auto_renew', '=', False),
|
||||
"|",
|
||||
"&",
|
||||
('is_suspended', '=', True),
|
||||
('manual_renew_needed', '=', True),
|
||||
('successor_contract_line_id', '!=', False),
|
||||
('is_suspended', '=', False),
|
||||
('manual_renew_needed', '=', False),
|
||||
]
|
||||
|
||||
if state == 'canceled':
|
||||
return [('is_canceled', '=', True)]
|
||||
|
||||
@api.model
|
||||
def _search_state(self, operator, value):
|
||||
states = [
|
||||
'upcoming',
|
||||
'in-progress',
|
||||
'to-renew',
|
||||
'upcoming-close',
|
||||
'closed',
|
||||
'canceled',
|
||||
]
|
||||
if operator == '!=' and not value:
|
||||
return []
|
||||
if operator == '=' and not value:
|
||||
@@ -209,15 +246,6 @@ class AccountAnalyticInvoiceLine(models.Model):
|
||||
if operator == '=':
|
||||
return self._get_state_domain(value)
|
||||
if operator == '!=':
|
||||
states = [
|
||||
'upcoming',
|
||||
'in-progress',
|
||||
'suspension-planed',
|
||||
'suspended',
|
||||
'upcoming-close',
|
||||
'closed',
|
||||
'canceled',
|
||||
]
|
||||
domain = []
|
||||
for state in states:
|
||||
if state != value:
|
||||
@@ -225,6 +253,20 @@ class AccountAnalyticInvoiceLine(models.Model):
|
||||
domain.insert(0, '|')
|
||||
domain.extend(self._get_state_domain(state))
|
||||
return domain
|
||||
if operator == 'in':
|
||||
domain = []
|
||||
if not value:
|
||||
return [('id', '=', False)]
|
||||
for state in value:
|
||||
if domain:
|
||||
domain.insert(0, '|')
|
||||
domain.extend(self._get_state_domain(state))
|
||||
return domain
|
||||
|
||||
if operator == 'not in':
|
||||
return self._search_state(
|
||||
'in', [state for state in states if state not in value]
|
||||
)
|
||||
|
||||
@api.depends(
|
||||
'date_start',
|
||||
@@ -583,7 +625,7 @@ class AccountAnalyticInvoiceLine(models.Model):
|
||||
rec.date_start = new_date_start
|
||||
|
||||
@api.multi
|
||||
def stop(self, date_end, is_suspended=False, post_message=True):
|
||||
def stop(self, date_end, manual_renew_needed=False, post_message=True):
|
||||
"""
|
||||
Put date_end on contract line
|
||||
We don't consider contract lines that end's before the new end date
|
||||
@@ -614,12 +656,15 @@ class AccountAnalyticInvoiceLine(models.Model):
|
||||
{
|
||||
'date_end': date_end,
|
||||
'is_auto_renew': False,
|
||||
"is_suspended": is_suspended,
|
||||
"manual_renew_needed": manual_renew_needed,
|
||||
}
|
||||
)
|
||||
else:
|
||||
rec.write(
|
||||
{'is_auto_renew': False, "is_suspended": is_suspended}
|
||||
{
|
||||
'is_auto_renew': False,
|
||||
"manual_renew_needed": manual_renew_needed,
|
||||
}
|
||||
)
|
||||
return True
|
||||
|
||||
@@ -756,7 +801,7 @@ class AccountAnalyticInvoiceLine(models.Model):
|
||||
)
|
||||
rec.stop(
|
||||
date_start - relativedelta(days=1),
|
||||
is_suspended=True,
|
||||
manual_renew_needed=True,
|
||||
post_message=False,
|
||||
)
|
||||
contract_line |= rec.plan_successor(
|
||||
@@ -778,7 +823,7 @@ class AccountAnalyticInvoiceLine(models.Model):
|
||||
|
||||
rec.stop(
|
||||
date_start - relativedelta(days=1),
|
||||
is_suspended=True,
|
||||
manual_renew_needed=True,
|
||||
post_message=False,
|
||||
)
|
||||
contract_line |= rec.plan_successor(
|
||||
@@ -954,7 +999,7 @@ class AccountAnalyticInvoiceLine(models.Model):
|
||||
res = self.env['account.analytic.invoice.line']
|
||||
for rec in self:
|
||||
is_auto_renew = rec.is_auto_renew
|
||||
rec.stop(rec.date_end, post_message=False)
|
||||
rec.is_auto_renew = False
|
||||
date_start, date_end = rec._get_renewal_dates()
|
||||
new_line = rec.plan_successor(
|
||||
date_start, date_end, is_auto_renew, post_message=False
|
||||
@@ -982,21 +1027,13 @@ class AccountAnalyticInvoiceLine(models.Model):
|
||||
('is_auto_renew', '=', True),
|
||||
('is_canceled', '=', False),
|
||||
('contract_id.recurring_invoices', '=', True),
|
||||
('termination_notice_date', '<=', fields.Date.context_today(self)),
|
||||
]
|
||||
|
||||
@api.model
|
||||
def cron_renew_contract_line(self):
|
||||
domain = self._contract_line_to_renew_domain()
|
||||
to_renew = self
|
||||
for contract_line in self.search(domain):
|
||||
date_ref = fields.Date.context_today(
|
||||
self
|
||||
) + self.get_relative_delta(
|
||||
contract_line.termination_notice_rule_type,
|
||||
contract_line.termination_notice_interval,
|
||||
)
|
||||
if contract_line.date_end <= date_ref:
|
||||
to_renew |= contract_line
|
||||
to_renew = self.search(domain)
|
||||
to_renew.renew()
|
||||
|
||||
@api.model
|
||||
|
||||
@@ -17,17 +17,19 @@ class TestContractBase(common.SavepointCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestContractBase, cls).setUpClass()
|
||||
cls.today = fields.Date.today()
|
||||
cls.partner = cls.env.ref('base.res_partner_2')
|
||||
cls.product = cls.env.ref('product.product_product_2')
|
||||
cls.product.taxes_id += cls.env['account.tax'].search(
|
||||
cls.product_1 = cls.env.ref('product.product_product_1')
|
||||
cls.product_2 = cls.env.ref('product.product_product_2')
|
||||
cls.product_1.taxes_id += cls.env['account.tax'].search(
|
||||
[('type_tax_use', '=', 'sale')], limit=1
|
||||
)
|
||||
cls.product.description_sale = 'Test description sale'
|
||||
cls.product_1.description_sale = 'Test description sale'
|
||||
cls.line_template_vals = {
|
||||
'product_id': cls.product.id,
|
||||
'product_id': cls.product_1.id,
|
||||
'name': 'Services from #START# to #END#',
|
||||
'quantity': 1,
|
||||
'uom_id': cls.product.uom_id.id,
|
||||
'uom_id': cls.product_1.uom_id.id,
|
||||
'price_unit': 100,
|
||||
'discount': 50,
|
||||
'recurring_rule_type': 'yearly',
|
||||
@@ -44,7 +46,7 @@ class TestContractBase(common.SavepointCase):
|
||||
cls.env['product.pricelist.item'].create(
|
||||
{
|
||||
'pricelist_id': cls.partner.property_product_pricelist.id,
|
||||
'product_id': cls.product.id,
|
||||
'product_id': cls.product_1.id,
|
||||
'compute_price': 'formula',
|
||||
'base': 'list_price',
|
||||
}
|
||||
@@ -69,10 +71,10 @@ class TestContractBase(common.SavepointCase):
|
||||
0,
|
||||
0,
|
||||
{
|
||||
'product_id': cls.product.id,
|
||||
'product_id': cls.product_1.id,
|
||||
'name': 'Services from #START# to #END#',
|
||||
'quantity': 1,
|
||||
'uom_id': cls.product.uom_id.id,
|
||||
'uom_id': cls.product_1.uom_id.id,
|
||||
'price_unit': 100,
|
||||
'discount': 50,
|
||||
'recurring_rule_type': 'monthly',
|
||||
@@ -86,10 +88,10 @@ class TestContractBase(common.SavepointCase):
|
||||
)
|
||||
cls.line_vals = {
|
||||
'contract_id': cls.contract.id,
|
||||
'product_id': cls.product.id,
|
||||
'product_id': cls.product_1.id,
|
||||
'name': 'Services from #START# to #END#',
|
||||
'quantity': 1,
|
||||
'uom_id': cls.product.uom_id.id,
|
||||
'uom_id': cls.product_1.uom_id.id,
|
||||
'price_unit': 100,
|
||||
'discount': 50,
|
||||
'recurring_rule_type': 'monthly',
|
||||
@@ -121,7 +123,7 @@ class TestContract(TestContractBase):
|
||||
|
||||
def test_automatic_price(self):
|
||||
self.acct_line.automatic_price = True
|
||||
self.product.list_price = 1100
|
||||
self.product_1.list_price = 1100
|
||||
self.assertEqual(self.acct_line.price_unit, 1100)
|
||||
# Try to write other price
|
||||
self.acct_line.price_unit = 10
|
||||
@@ -395,6 +397,8 @@ class TestContract(TestContractBase):
|
||||
|
||||
def test_onchange_contract_template_id(self):
|
||||
"""It should change the contract values to match the template."""
|
||||
self.contract.contract_template_id = False
|
||||
self.contract._onchange_contract_template_id()
|
||||
self.contract.contract_template_id = self.template
|
||||
self.contract._onchange_contract_template_id()
|
||||
res = {
|
||||
@@ -403,10 +407,10 @@ class TestContract(TestContractBase):
|
||||
0,
|
||||
0,
|
||||
{
|
||||
'product_id': self.product.id,
|
||||
'product_id': self.product_1.id,
|
||||
'name': 'Services from #START# to #END#',
|
||||
'quantity': 1,
|
||||
'uom_id': self.product.uom_id.id,
|
||||
'uom_id': self.product_1.uom_id.id,
|
||||
'price_unit': 100,
|
||||
'discount': 50,
|
||||
'recurring_rule_type': 'yearly',
|
||||
@@ -450,6 +454,15 @@ class TestContract(TestContractBase):
|
||||
self.assertEqual(
|
||||
self.contract.journal_id.company_id, self.contract.company_id
|
||||
)
|
||||
self.contract.type = 'purchase'
|
||||
self.contract._onchange_contract_type()
|
||||
self.assertFalse(
|
||||
any(
|
||||
self.contract.recurring_invoice_line_ids.mapped(
|
||||
'automatic_price'
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def test_contract_onchange_product_id_domain_blank(self):
|
||||
"""It should return a blank UoM domain when no product."""
|
||||
@@ -463,7 +476,7 @@ class TestContract(TestContractBase):
|
||||
res = line._onchange_product_id()
|
||||
self.assertEqual(
|
||||
res['domain']['uom_id'][0],
|
||||
('category_id', '=', self.product.uom_id.category_id.id),
|
||||
('category_id', '=', self.product_1.uom_id.category_id.id),
|
||||
)
|
||||
|
||||
def test_contract_onchange_product_id_uom(self):
|
||||
@@ -502,9 +515,9 @@ class TestContract(TestContractBase):
|
||||
"""It should create one invoice with same start and end date."""
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_start': fields.Date.today(),
|
||||
'date_end': fields.Date.today(),
|
||||
'recurring_next_date': fields.Date.today(),
|
||||
'date_start': self.today,
|
||||
'date_end': self.today,
|
||||
'recurring_next_date': self.today,
|
||||
}
|
||||
)
|
||||
self.contract._compute_recurring_next_date()
|
||||
@@ -630,33 +643,40 @@ class TestContract(TestContractBase):
|
||||
"""It should put end to the contract line"""
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_start': fields.Date.today(),
|
||||
'recurring_next_date': fields.Date.today(),
|
||||
'date_end': fields.Date.today() + relativedelta(months=7),
|
||||
'date_start': self.today - relativedelta(months=7),
|
||||
'recurring_next_date': self.today - relativedelta(months=7),
|
||||
'date_end': self.today - relativedelta(months=5),
|
||||
'is_auto_renew': False,
|
||||
}
|
||||
)
|
||||
with self.assertRaises(ValidationError):
|
||||
self.acct_line.stop(self.today)
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_start': self.today,
|
||||
'recurring_next_date': self.today,
|
||||
'date_end': self.today + relativedelta(months=7),
|
||||
'is_auto_renew': True,
|
||||
}
|
||||
)
|
||||
self.acct_line.stop(fields.Date.today() + relativedelta(months=5))
|
||||
self.acct_line.stop(self.today + relativedelta(months=5))
|
||||
self.assertEqual(
|
||||
self.acct_line.date_end,
|
||||
fields.Date.today() + relativedelta(months=5),
|
||||
self.acct_line.date_end, self.today + relativedelta(months=5)
|
||||
)
|
||||
|
||||
def test_stop_upcoming_contract_line(self):
|
||||
"""It should put end to the contract line"""
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_start': fields.Date.today() + relativedelta(months=3),
|
||||
'recurring_next_date': fields.Date.today()
|
||||
+ relativedelta(months=3),
|
||||
'date_end': fields.Date.today() + relativedelta(months=7),
|
||||
'date_start': self.today + relativedelta(months=3),
|
||||
'recurring_next_date': self.today + relativedelta(months=3),
|
||||
'date_end': self.today + relativedelta(months=7),
|
||||
'is_auto_renew': True,
|
||||
}
|
||||
)
|
||||
self.acct_line.stop(fields.Date.today())
|
||||
self.acct_line.stop(self.today)
|
||||
self.assertEqual(
|
||||
self.acct_line.date_end,
|
||||
fields.Date.today() + relativedelta(months=7),
|
||||
self.acct_line.date_end, self.today + relativedelta(months=7)
|
||||
)
|
||||
self.assertTrue(self.acct_line.is_canceled)
|
||||
|
||||
@@ -664,56 +684,74 @@ class TestContract(TestContractBase):
|
||||
"""Past contract line are ignored on stop"""
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_end': fields.Date.today() + relativedelta(months=5),
|
||||
'date_end': self.today + relativedelta(months=5),
|
||||
'is_auto_renew': True,
|
||||
}
|
||||
)
|
||||
self.acct_line.stop(fields.Date.today() + relativedelta(months=7))
|
||||
self.acct_line.stop(self.today + relativedelta(months=7))
|
||||
self.assertEqual(
|
||||
self.acct_line.date_end,
|
||||
fields.Date.today() + relativedelta(months=5),
|
||||
self.acct_line.date_end, self.today + relativedelta(months=5)
|
||||
)
|
||||
|
||||
def test_stop_contract_line_without_date_end(self):
|
||||
"""Past contract line are ignored on stop"""
|
||||
self.acct_line.write({'date_end': False, 'is_auto_renew': False})
|
||||
self.acct_line.stop(fields.Date.today() + relativedelta(months=7))
|
||||
self.acct_line.stop(self.today + relativedelta(months=7))
|
||||
self.assertEqual(
|
||||
self.acct_line.date_end,
|
||||
fields.Date.today() + relativedelta(months=7),
|
||||
self.acct_line.date_end, self.today + relativedelta(months=7)
|
||||
)
|
||||
|
||||
def test_stop_plan_successor_wizard(self):
|
||||
def test_stop_wizard(self):
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_start': fields.Date.today(),
|
||||
'recurring_next_date': fields.Date.today(),
|
||||
'date_end': fields.Date.today() + relativedelta(months=5),
|
||||
'date_start': self.today,
|
||||
'recurring_next_date': self.today,
|
||||
'date_end': self.today + relativedelta(months=5),
|
||||
'is_auto_renew': True,
|
||||
}
|
||||
)
|
||||
wizard = self.env['account.analytic.invoice.line.wizard'].create(
|
||||
{
|
||||
'date_end': fields.Date.today() + relativedelta(months=7),
|
||||
'date_end': self.today + relativedelta(months=3),
|
||||
'contract_line_id': self.acct_line.id,
|
||||
}
|
||||
)
|
||||
wizard.stop()
|
||||
self.assertEqual(
|
||||
self.acct_line.date_end,
|
||||
fields.Date.today() + relativedelta(months=7),
|
||||
self.acct_line.date_end, self.today + relativedelta(months=3)
|
||||
)
|
||||
self.assertFalse(self.acct_line.is_auto_renew)
|
||||
|
||||
def test_stop_plan_successor_contract_line_0(self):
|
||||
successor_contract_line = self.acct_line.copy(
|
||||
{
|
||||
'date_start': self.today + relativedelta(months=5),
|
||||
'recurring_next_date': self.today + relativedelta(months=5),
|
||||
}
|
||||
)
|
||||
self.acct_line.write(
|
||||
{
|
||||
'successor_contract_line_id': successor_contract_line.id,
|
||||
'is_auto_renew': False,
|
||||
'date_end': self.today,
|
||||
}
|
||||
)
|
||||
suspension_start = self.today + relativedelta(months=5)
|
||||
suspension_end = self.today + relativedelta(months=6)
|
||||
with self.assertRaises(ValidationError):
|
||||
self.acct_line.stop_plan_successor(
|
||||
suspension_start, suspension_end, True
|
||||
)
|
||||
|
||||
def test_stop_plan_successor_contract_line_1(self):
|
||||
"""
|
||||
* contract line end's before the suspension period:
|
||||
-> apply stop
|
||||
"""
|
||||
suspension_start = fields.Date.today() + relativedelta(months=5)
|
||||
suspension_end = fields.Date.today() + relativedelta(months=6)
|
||||
start_date = fields.Date.today()
|
||||
end_date = fields.Date.today() + relativedelta(months=4)
|
||||
suspension_start = self.today + relativedelta(months=5)
|
||||
suspension_end = self.today + relativedelta(months=6)
|
||||
start_date = self.today
|
||||
end_date = self.today + relativedelta(months=4)
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_start': start_date,
|
||||
@@ -739,10 +777,10 @@ class TestContract(TestContractBase):
|
||||
- date_end: suspension.date_end + (contract_line.date_end
|
||||
- suspension.date_start)
|
||||
"""
|
||||
suspension_start = fields.Date.today() + relativedelta(months=3)
|
||||
suspension_end = fields.Date.today() + relativedelta(months=5)
|
||||
start_date = fields.Date.today()
|
||||
end_date = fields.Date.today() + relativedelta(months=4)
|
||||
suspension_start = self.today + relativedelta(months=3)
|
||||
suspension_end = self.today + relativedelta(months=5)
|
||||
start_date = self.today
|
||||
end_date = self.today + relativedelta(months=4)
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_start': start_date,
|
||||
@@ -769,7 +807,7 @@ class TestContract(TestContractBase):
|
||||
new_line.date_start, suspension_end + relativedelta(days=1)
|
||||
)
|
||||
self.assertEqual(new_line.date_end, new_date_end)
|
||||
self.assertTrue(self.acct_line.is_suspended)
|
||||
self.assertTrue(self.acct_line.manual_renew_needed)
|
||||
|
||||
def test_stop_plan_successor_contract_line_3(self):
|
||||
"""
|
||||
@@ -780,10 +818,10 @@ class TestContract(TestContractBase):
|
||||
- date_end: suspension.date_end + (suspension.date_end
|
||||
- suspension.date_start)
|
||||
"""
|
||||
suspension_start = fields.Date.today() + relativedelta(months=3)
|
||||
suspension_end = fields.Date.today() + relativedelta(months=5)
|
||||
start_date = fields.Date.today()
|
||||
end_date = fields.Date.today() + relativedelta(months=6)
|
||||
suspension_start = self.today + relativedelta(months=3)
|
||||
suspension_end = self.today + relativedelta(months=5)
|
||||
start_date = self.today
|
||||
end_date = self.today + relativedelta(months=6)
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_start': start_date,
|
||||
@@ -810,7 +848,7 @@ class TestContract(TestContractBase):
|
||||
new_line.date_start, suspension_end + relativedelta(days=1)
|
||||
)
|
||||
self.assertEqual(new_line.date_end, new_date_end)
|
||||
self.assertTrue(self.acct_line.is_suspended)
|
||||
self.assertTrue(self.acct_line.manual_renew_needed)
|
||||
|
||||
def test_stop_plan_successor_contract_line_3_without_end_date(self):
|
||||
"""
|
||||
@@ -821,9 +859,9 @@ class TestContract(TestContractBase):
|
||||
- date_end: suspension.date_end + (suspension.date_end
|
||||
- suspension.date_start)
|
||||
"""
|
||||
suspension_start = fields.Date.today() + relativedelta(months=3)
|
||||
suspension_end = fields.Date.today() + relativedelta(months=5)
|
||||
start_date = fields.Date.today()
|
||||
suspension_start = self.today + relativedelta(months=3)
|
||||
suspension_end = self.today + relativedelta(months=5)
|
||||
start_date = self.today
|
||||
end_date = False
|
||||
self.acct_line.write(
|
||||
{
|
||||
@@ -847,7 +885,7 @@ class TestContract(TestContractBase):
|
||||
new_line.date_start, suspension_end + relativedelta(days=1)
|
||||
)
|
||||
self.assertFalse(new_line.date_end)
|
||||
self.assertTrue(self.acct_line.is_suspended)
|
||||
self.assertTrue(self.acct_line.manual_renew_needed)
|
||||
|
||||
def test_stop_plan_successor_contract_line_4(self):
|
||||
"""
|
||||
@@ -855,10 +893,10 @@ class TestContract(TestContractBase):
|
||||
-> apply delay
|
||||
- delay: suspension.date_end - contract_line.end_date
|
||||
"""
|
||||
suspension_start = fields.Date.today() + relativedelta(months=2)
|
||||
suspension_end = fields.Date.today() + relativedelta(months=5)
|
||||
start_date = fields.Date.today() + relativedelta(months=3)
|
||||
end_date = fields.Date.today() + relativedelta(months=4)
|
||||
suspension_start = self.today + relativedelta(months=2)
|
||||
suspension_end = self.today + relativedelta(months=5)
|
||||
start_date = self.today + relativedelta(months=3)
|
||||
end_date = self.today + relativedelta(months=4)
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_start': start_date,
|
||||
@@ -888,10 +926,10 @@ class TestContract(TestContractBase):
|
||||
-> apply delay
|
||||
- delay: suspension.date_end - contract_line.date_start
|
||||
"""
|
||||
suspension_start = fields.Date.today() + relativedelta(months=2)
|
||||
suspension_end = fields.Date.today() + relativedelta(months=5)
|
||||
start_date = fields.Date.today() + relativedelta(months=3)
|
||||
end_date = fields.Date.today() + relativedelta(months=6)
|
||||
suspension_start = self.today + relativedelta(months=2)
|
||||
suspension_end = self.today + relativedelta(months=5)
|
||||
start_date = self.today + relativedelta(months=3)
|
||||
end_date = self.today + relativedelta(months=6)
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_start': start_date,
|
||||
@@ -921,9 +959,9 @@ class TestContract(TestContractBase):
|
||||
-> apply delay
|
||||
- delay: suspension.date_end - contract_line.date_start
|
||||
"""
|
||||
suspension_start = fields.Date.today() + relativedelta(months=2)
|
||||
suspension_end = fields.Date.today() + relativedelta(months=5)
|
||||
start_date = fields.Date.today() + relativedelta(months=3)
|
||||
suspension_start = self.today + relativedelta(months=2)
|
||||
suspension_end = self.today + relativedelta(months=5)
|
||||
start_date = self.today + relativedelta(months=3)
|
||||
end_date = False
|
||||
self.acct_line.write(
|
||||
{
|
||||
@@ -952,10 +990,10 @@ class TestContract(TestContractBase):
|
||||
-> apply delay
|
||||
- delay: suspension.date_end - suspension.start_date
|
||||
"""
|
||||
suspension_start = fields.Date.today() + relativedelta(months=2)
|
||||
suspension_end = fields.Date.today() + relativedelta(months=3)
|
||||
start_date = fields.Date.today() + relativedelta(months=4)
|
||||
end_date = fields.Date.today() + relativedelta(months=6)
|
||||
suspension_start = self.today + relativedelta(months=2)
|
||||
suspension_end = self.today + relativedelta(months=3)
|
||||
start_date = self.today + relativedelta(months=4)
|
||||
end_date = self.today + relativedelta(months=6)
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_start': start_date,
|
||||
@@ -987,9 +1025,9 @@ class TestContract(TestContractBase):
|
||||
-> apply delay
|
||||
- delay: suspension.date_end - suspension.start_date
|
||||
"""
|
||||
suspension_start = fields.Date.today() + relativedelta(months=2)
|
||||
suspension_end = fields.Date.today() + relativedelta(months=3)
|
||||
start_date = fields.Date.today() + relativedelta(months=4)
|
||||
suspension_start = self.today + relativedelta(months=2)
|
||||
suspension_end = self.today + relativedelta(months=3)
|
||||
start_date = self.today + relativedelta(months=4)
|
||||
end_date = False
|
||||
self.acct_line.write(
|
||||
{
|
||||
@@ -1015,10 +1053,10 @@ class TestContract(TestContractBase):
|
||||
self.assertFalse(new_line)
|
||||
|
||||
def test_stop_plan_successor_wizard(self):
|
||||
suspension_start = fields.Date.today() + relativedelta(months=2)
|
||||
suspension_end = fields.Date.today() + relativedelta(months=3)
|
||||
start_date = fields.Date.today() + relativedelta(months=4)
|
||||
end_date = fields.Date.today() + relativedelta(months=6)
|
||||
suspension_start = self.today + relativedelta(months=2)
|
||||
suspension_end = self.today + relativedelta(months=3)
|
||||
start_date = self.today + relativedelta(months=4)
|
||||
end_date = self.today + relativedelta(months=6)
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_start': start_date,
|
||||
@@ -1053,15 +1091,15 @@ class TestContract(TestContractBase):
|
||||
def test_plan_successor_contract_line(self):
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_start': fields.Date.today(),
|
||||
'recurring_next_date': fields.Date.today(),
|
||||
'date_end': fields.Date.today() + relativedelta(months=3),
|
||||
'date_start': self.today,
|
||||
'recurring_next_date': self.today,
|
||||
'date_end': self.today + relativedelta(months=3),
|
||||
'is_auto_renew': False,
|
||||
}
|
||||
)
|
||||
self.acct_line.plan_successor(
|
||||
fields.Date.today() + relativedelta(months=5),
|
||||
fields.Date.today() + relativedelta(months=7),
|
||||
self.today + relativedelta(months=5),
|
||||
self.today + relativedelta(months=7),
|
||||
True,
|
||||
)
|
||||
new_line = self.env['account.analytic.invoice.line'].search(
|
||||
@@ -1071,49 +1109,47 @@ class TestContract(TestContractBase):
|
||||
self.assertTrue(new_line.is_auto_renew)
|
||||
self.assertTrue(new_line, "should create a new contract line")
|
||||
self.assertEqual(
|
||||
new_line.date_start, fields.Date.today() + relativedelta(months=5)
|
||||
new_line.date_start, self.today + relativedelta(months=5)
|
||||
)
|
||||
self.assertEqual(
|
||||
new_line.date_end, fields.Date.today() + relativedelta(months=7)
|
||||
new_line.date_end, self.today + relativedelta(months=7)
|
||||
)
|
||||
|
||||
def test_overlap(self):
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_start': fields.Date.today(),
|
||||
'recurring_next_date': fields.Date.today(),
|
||||
'date_end': fields.Date.today() + relativedelta(months=3),
|
||||
'date_start': self.today,
|
||||
'recurring_next_date': self.today,
|
||||
'date_end': self.today + relativedelta(months=3),
|
||||
'is_auto_renew': False,
|
||||
}
|
||||
)
|
||||
self.acct_line.plan_successor(
|
||||
fields.Date.today() + relativedelta(months=5),
|
||||
fields.Date.today() + relativedelta(months=7),
|
||||
self.today + relativedelta(months=5),
|
||||
self.today + relativedelta(months=7),
|
||||
True,
|
||||
)
|
||||
new_line = self.env['account.analytic.invoice.line'].search(
|
||||
[('predecessor_contract_line_id', '=', self.acct_line.id)]
|
||||
)
|
||||
with self.assertRaises(ValidationError):
|
||||
new_line.date_start = fields.Date.today() + relativedelta(months=2)
|
||||
new_line.date_start = self.today + relativedelta(months=2)
|
||||
with self.assertRaises(ValidationError):
|
||||
self.acct_line.date_end = fields.Date.today() + relativedelta(
|
||||
months=6
|
||||
)
|
||||
self.acct_line.date_end = self.today + relativedelta(months=6)
|
||||
|
||||
def test_plan_successor_wizard(self):
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_start': fields.Date.today(),
|
||||
'recurring_next_date': fields.Date.today(),
|
||||
'date_end': fields.Date.today() + relativedelta(months=2),
|
||||
'date_start': self.today,
|
||||
'recurring_next_date': self.today,
|
||||
'date_end': self.today + relativedelta(months=2),
|
||||
'is_auto_renew': False,
|
||||
}
|
||||
)
|
||||
wizard = self.env['account.analytic.invoice.line.wizard'].create(
|
||||
{
|
||||
'date_start': fields.Date.today() + relativedelta(months=3),
|
||||
'date_end': fields.Date.today() + relativedelta(months=5),
|
||||
'date_start': self.today + relativedelta(months=3),
|
||||
'date_end': self.today + relativedelta(months=5),
|
||||
'is_auto_renew': True,
|
||||
'contract_line_id': self.acct_line.id,
|
||||
}
|
||||
@@ -1126,23 +1162,35 @@ class TestContract(TestContractBase):
|
||||
self.assertTrue(new_line.is_auto_renew)
|
||||
self.assertTrue(new_line, "should create a new contract line")
|
||||
self.assertEqual(
|
||||
new_line.date_start, fields.Date.today() + relativedelta(months=3)
|
||||
new_line.date_start, self.today + relativedelta(months=3)
|
||||
)
|
||||
self.assertEqual(
|
||||
new_line.date_end, fields.Date.today() + relativedelta(months=5)
|
||||
new_line.date_end, self.today + relativedelta(months=5)
|
||||
)
|
||||
|
||||
def test_cancel(self):
|
||||
self.acct_line.cancel()
|
||||
self.assertTrue(self.acct_line.is_canceled)
|
||||
self.acct_line.uncancel(fields.Date.today())
|
||||
self.acct_line.uncancel(self.today)
|
||||
self.assertFalse(self.acct_line.is_canceled)
|
||||
|
||||
def test_uncancel_wizard(self):
|
||||
self.acct_line.cancel()
|
||||
self.assertTrue(self.acct_line.is_canceled)
|
||||
wizard = self.env['account.analytic.invoice.line.wizard'].create(
|
||||
{
|
||||
'recurring_next_date': self.today,
|
||||
'contract_line_id': self.acct_line.id,
|
||||
}
|
||||
)
|
||||
wizard.uncancel()
|
||||
self.assertFalse(self.acct_line.is_canceled)
|
||||
|
||||
def test_cancel_uncancel_with_predecessor(self):
|
||||
suspension_start = fields.Date.today() + relativedelta(months=3)
|
||||
suspension_end = fields.Date.today() + relativedelta(months=5)
|
||||
start_date = fields.Date.today()
|
||||
end_date = fields.Date.today() + relativedelta(months=4)
|
||||
suspension_start = self.today + relativedelta(months=3)
|
||||
suspension_end = self.today + relativedelta(months=5)
|
||||
start_date = self.today
|
||||
end_date = self.today + relativedelta(months=4)
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_start': start_date,
|
||||
@@ -1173,10 +1221,10 @@ class TestContract(TestContractBase):
|
||||
)
|
||||
|
||||
def test_cancel_uncancel_with_predecessor_has_successor(self):
|
||||
suspension_start = fields.Date.today() + relativedelta(months=6)
|
||||
suspension_end = fields.Date.today() + relativedelta(months=7)
|
||||
start_date = fields.Date.today()
|
||||
end_date = fields.Date.today() + relativedelta(months=8)
|
||||
suspension_start = self.today + relativedelta(months=6)
|
||||
suspension_end = self.today + relativedelta(months=7)
|
||||
start_date = self.today
|
||||
end_date = self.today + relativedelta(months=8)
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_start': start_date,
|
||||
@@ -1191,8 +1239,8 @@ class TestContract(TestContractBase):
|
||||
[('predecessor_contract_line_id', '=', self.acct_line.id)]
|
||||
)
|
||||
new_line.cancel()
|
||||
suspension_start = fields.Date.today() + relativedelta(months=4)
|
||||
suspension_end = fields.Date.today() + relativedelta(months=5)
|
||||
suspension_start = self.today + relativedelta(months=4)
|
||||
suspension_end = self.today + relativedelta(months=5)
|
||||
self.acct_line.stop_plan_successor(
|
||||
suspension_start, suspension_end, True
|
||||
)
|
||||
@@ -1217,23 +1265,18 @@ class TestContract(TestContractBase):
|
||||
)
|
||||
|
||||
def test_search_contract_line_to_renew(self):
|
||||
self.acct_line.write(
|
||||
{'date_end': fields.Date.today(), 'is_auto_renew': True}
|
||||
)
|
||||
self.acct_line.write({'date_end': self.today, 'is_auto_renew': True})
|
||||
line_1 = self.acct_line.copy(
|
||||
{'date_end': fields.Date.today() + relativedelta(months=1)}
|
||||
{'date_end': self.today + relativedelta(months=1)}
|
||||
)
|
||||
line_2 = self.acct_line.copy(
|
||||
{'date_end': fields.Date.today() - relativedelta(months=1)}
|
||||
{'date_end': self.today - relativedelta(months=1)}
|
||||
)
|
||||
line_3 = self.acct_line.copy(
|
||||
{'date_end': fields.Date.today() - relativedelta(months=2)}
|
||||
{'date_end': self.today - relativedelta(months=2)}
|
||||
)
|
||||
self.acct_line.copy(
|
||||
{
|
||||
'date_end': fields.Date.today() + relativedelta(months=2),
|
||||
'is_auto_renew': False,
|
||||
}
|
||||
line_4 = self.acct_line.copy(
|
||||
{'date_end': self.today + relativedelta(months=2)}
|
||||
)
|
||||
to_renew = self.acct_line.search(
|
||||
self.acct_line._contract_line_to_renew_domain()
|
||||
@@ -1241,9 +1284,15 @@ class TestContract(TestContractBase):
|
||||
self.assertEqual(
|
||||
set(to_renew), set((self.acct_line, line_1, line_2, line_3))
|
||||
)
|
||||
self.acct_line.cron_renew_contract_line()
|
||||
self.assertTrue(self.acct_line.successor_contract_line_id)
|
||||
self.assertTrue(line_1.successor_contract_line_id)
|
||||
self.assertTrue(line_2.successor_contract_line_id)
|
||||
self.assertTrue(line_3.successor_contract_line_id)
|
||||
self.assertFalse(line_4.successor_contract_line_id)
|
||||
|
||||
def test_renew(self):
|
||||
date_start = fields.Date.today() - relativedelta(months=9)
|
||||
date_start = self.today - relativedelta(months=9)
|
||||
date_end = (
|
||||
date_start + relativedelta(months=12) - relativedelta(days=1)
|
||||
)
|
||||
@@ -1252,7 +1301,7 @@ class TestContract(TestContractBase):
|
||||
'is_auto_renew': True,
|
||||
'date_start': date_start,
|
||||
'recurring_next_date': date_start,
|
||||
'date_end': fields.Date.today(),
|
||||
'date_end': self.today,
|
||||
}
|
||||
)
|
||||
self.acct_line._onchange_is_auto_renew()
|
||||
@@ -1301,6 +1350,7 @@ class TestContract(TestContractBase):
|
||||
first, last = self.acct_line._get_invoiced_period()
|
||||
self.assertEqual(first, to_date('2018-03-01'))
|
||||
self.assertEqual(last, to_date('2018-03-15'))
|
||||
self.acct_line.manual_renew_needed = True
|
||||
|
||||
def test_get_invoiced_period_monthly_pre_paid_2(self):
|
||||
self.acct_line.date_start = '2018-01-05'
|
||||
@@ -1407,3 +1457,305 @@ class TestContract(TestContractBase):
|
||||
def test_unlink(self):
|
||||
with self.assertRaises(ValidationError):
|
||||
self.acct_line.unlink()
|
||||
|
||||
def test_contract_line_state(self):
|
||||
lines = self.env['account.analytic.invoice.line']
|
||||
# upcoming
|
||||
lines |= self.acct_line.copy(
|
||||
{
|
||||
'date_start': self.today + relativedelta(months=3),
|
||||
'recurring_next_date': self.today + relativedelta(months=3),
|
||||
'date_end': self.today + relativedelta(months=5),
|
||||
}
|
||||
)
|
||||
# in-progress
|
||||
lines |= self.acct_line.copy(
|
||||
{
|
||||
'date_start': self.today,
|
||||
'recurring_next_date': self.today,
|
||||
'date_end': self.today + relativedelta(months=5),
|
||||
}
|
||||
)
|
||||
# in-progress
|
||||
lines |= self.acct_line.copy(
|
||||
{
|
||||
'date_start': self.today,
|
||||
'recurring_next_date': self.today,
|
||||
'date_end': self.today + relativedelta(months=5),
|
||||
'manual_renew_needed': True,
|
||||
}
|
||||
)
|
||||
# to-renew
|
||||
lines |= self.acct_line.copy(
|
||||
{
|
||||
'date_start': self.today - relativedelta(months=5),
|
||||
'recurring_next_date': self.today - relativedelta(months=5),
|
||||
'date_end': self.today - relativedelta(months=2),
|
||||
'manual_renew_needed': True,
|
||||
}
|
||||
)
|
||||
# upcoming-close
|
||||
lines |= self.acct_line.copy(
|
||||
{
|
||||
'date_start': self.today - relativedelta(months=5),
|
||||
'recurring_next_date': self.today - relativedelta(months=5),
|
||||
'date_end': self.today + relativedelta(days=20),
|
||||
'is_auto_renew': False,
|
||||
}
|
||||
)
|
||||
# closed
|
||||
lines |= self.acct_line.copy(
|
||||
{
|
||||
'date_start': self.today - relativedelta(months=5),
|
||||
'recurring_next_date': self.today - relativedelta(months=5),
|
||||
'date_end': self.today - relativedelta(months=2),
|
||||
'is_auto_renew': False,
|
||||
}
|
||||
)
|
||||
# canceled
|
||||
lines |= self.acct_line.copy(
|
||||
{
|
||||
'date_start': self.today - relativedelta(months=5),
|
||||
'recurring_next_date': self.today - relativedelta(months=5),
|
||||
'date_end': self.today - relativedelta(months=2),
|
||||
'is_canceled': True,
|
||||
}
|
||||
)
|
||||
states = [
|
||||
'upcoming',
|
||||
'in-progress',
|
||||
'to-renew',
|
||||
'upcoming-close',
|
||||
'closed',
|
||||
'canceled',
|
||||
]
|
||||
self.assertEqual(set(lines.mapped('state')), set(states))
|
||||
for state in states:
|
||||
lines = self.env['account.analytic.invoice.line'].search(
|
||||
[('state', '=', state)]
|
||||
)
|
||||
self.assertEqual(len(set(lines.mapped('state'))), 1, state)
|
||||
self.assertEqual(lines.mapped('state')[0], state, state)
|
||||
|
||||
for state in states:
|
||||
lines = self.env['account.analytic.invoice.line'].search(
|
||||
[('state', '!=', state)]
|
||||
)
|
||||
self.assertFalse(state in lines.mapped('state'))
|
||||
|
||||
lines = self.env['account.analytic.invoice.line'].search(
|
||||
[('state', 'in', states)]
|
||||
)
|
||||
self.assertEqual(set(lines.mapped('state')), set(states))
|
||||
lines = self.env['account.analytic.invoice.line'].search(
|
||||
[('state', 'in', [])]
|
||||
)
|
||||
self.assertFalse(lines.mapped('state'))
|
||||
with self.assertRaises(TypeError):
|
||||
self.env['account.analytic.invoice.line'].search(
|
||||
[('state', 'in', 'upcoming')]
|
||||
)
|
||||
lines = self.env['account.analytic.invoice.line'].search(
|
||||
[('state', 'not in', [])]
|
||||
)
|
||||
self.assertEqual(set(lines.mapped('state')), set(states))
|
||||
lines = self.env['account.analytic.invoice.line'].search(
|
||||
[('state', 'not in', states)]
|
||||
)
|
||||
self.assertFalse(lines.mapped('state'))
|
||||
lines = self.env['account.analytic.invoice.line'].search(
|
||||
[('state', 'not in', ['upcoming', 'in-progress'])]
|
||||
)
|
||||
self.assertEqual(
|
||||
set(lines.mapped('state')),
|
||||
set(['to-renew', 'upcoming-close', 'closed', 'canceled']),
|
||||
)
|
||||
|
||||
def test_check_auto_renew_contract_line_with_successor(self):
|
||||
"""
|
||||
A contract line with a successor can't be set to auto-renew
|
||||
"""
|
||||
successor_contract_line = self.acct_line.copy()
|
||||
with self.assertRaises(ValidationError):
|
||||
self.acct_line.write(
|
||||
{
|
||||
'is_auto_renew': True,
|
||||
'successor_contract_line_id': successor_contract_line.id,
|
||||
}
|
||||
)
|
||||
|
||||
def test_check_no_date_end_contract_line_with_successor(self):
|
||||
"""
|
||||
A contract line with a successor must have a end date
|
||||
"""
|
||||
successor_contract_line = self.acct_line.copy()
|
||||
with self.assertRaises(ValidationError):
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_end': False,
|
||||
'successor_contract_line_id': successor_contract_line.id,
|
||||
}
|
||||
)
|
||||
|
||||
def test_check_last_date_invoiced_1(self):
|
||||
"""
|
||||
start end can't be before the date of last invoice
|
||||
"""
|
||||
with self.assertRaises(ValidationError):
|
||||
self.acct_line.write(
|
||||
{
|
||||
'last_date_invoiced': self.acct_line.date_start
|
||||
- relativedelta(days=1)
|
||||
}
|
||||
)
|
||||
|
||||
def test_check_last_date_invoiced_2(self):
|
||||
"""
|
||||
start date can't be after the date of last invoice
|
||||
"""
|
||||
self.acct_line.write({'date_end': self.today})
|
||||
with self.assertRaises(ValidationError):
|
||||
self.acct_line.write(
|
||||
{
|
||||
'last_date_invoiced': self.acct_line.date_end
|
||||
+ relativedelta(days=1)
|
||||
}
|
||||
)
|
||||
|
||||
def test_init_last_date_invoiced(self):
|
||||
self.acct_line.write(
|
||||
{'date_start': '2019-01-01', 'recurring_next_date': '2019-03-01'}
|
||||
)
|
||||
line_monthlylastday = self.acct_line.copy(
|
||||
{
|
||||
'recurring_rule_type': 'monthlylastday',
|
||||
'recurring_next_date': '2019-03-31',
|
||||
}
|
||||
)
|
||||
line_prepaid = self.acct_line.copy(
|
||||
{
|
||||
'recurring_invoicing_type': 'pre-paid',
|
||||
'recurring_rule_type': 'monthly',
|
||||
}
|
||||
)
|
||||
line_postpaid = self.acct_line.copy(
|
||||
{
|
||||
'recurring_invoicing_type': 'post-paid',
|
||||
'recurring_rule_type': 'monthly',
|
||||
}
|
||||
)
|
||||
lines = line_monthlylastday | line_prepaid | line_postpaid
|
||||
lines.write({'last_date_invoiced': False})
|
||||
self.assertFalse(any(lines.mapped('last_date_invoiced')))
|
||||
lines._init_last_date_invoiced()
|
||||
self.assertEqual(
|
||||
line_monthlylastday.last_date_invoiced, to_date("2019-02-28")
|
||||
)
|
||||
self.assertEqual(
|
||||
line_prepaid.last_date_invoiced, to_date("2019-02-28")
|
||||
)
|
||||
self.assertEqual(
|
||||
line_postpaid.last_date_invoiced, to_date("2019-01-31")
|
||||
)
|
||||
|
||||
def test_delay_invoiced_contract_line(self):
|
||||
self.acct_line.write(
|
||||
{
|
||||
'last_date_invoiced': self.acct_line.date_start
|
||||
+ relativedelta(days=1)
|
||||
}
|
||||
)
|
||||
with self.assertRaises(ValidationError):
|
||||
self.acct_line._delay(relativedelta(months=1))
|
||||
|
||||
def test_cancel_invoiced_contract_line(self):
|
||||
self.acct_line.write(
|
||||
{
|
||||
'last_date_invoiced': self.acct_line.date_start
|
||||
+ relativedelta(days=1)
|
||||
}
|
||||
)
|
||||
with self.assertRaises(ValidationError):
|
||||
self.acct_line.cancel()
|
||||
|
||||
def test_action_uncancel(self):
|
||||
action = self.acct_line.action_uncancel()
|
||||
self.assertEqual(
|
||||
action['context']['default_contract_line_id'], self.acct_line.id
|
||||
)
|
||||
|
||||
def test_action_plan_successor(self):
|
||||
action = self.acct_line.action_plan_successor()
|
||||
self.assertEqual(
|
||||
action['context']['default_contract_line_id'], self.acct_line.id
|
||||
)
|
||||
|
||||
def test_action_stop(self):
|
||||
action = self.acct_line.action_stop()
|
||||
self.assertEqual(
|
||||
action['context']['default_contract_line_id'], self.acct_line.id
|
||||
)
|
||||
|
||||
def test_action_stop_plan_successor(self):
|
||||
action = self.acct_line.action_stop_plan_successor()
|
||||
self.assertEqual(
|
||||
action['context']['default_contract_line_id'], self.acct_line.id
|
||||
)
|
||||
|
||||
def test_purchase_fields_view_get(self):
|
||||
purchase_tree_view = self.env.ref(
|
||||
'contract.account_analytic_invoice_line_purchase_view_tree'
|
||||
)
|
||||
purchase_form_view = self.env.ref(
|
||||
'contract.account_analytic_invoice_line_purchase_view_form'
|
||||
)
|
||||
view = self.acct_line.with_context(
|
||||
default_contract_type='purchase'
|
||||
).fields_view_get(view_type='tree')
|
||||
self.assertEqual(view['view_id'], purchase_tree_view.id)
|
||||
view = self.acct_line.with_context(
|
||||
default_contract_type='purchase'
|
||||
).fields_view_get(view_type='form')
|
||||
self.assertEqual(view['view_id'], purchase_form_view.id)
|
||||
|
||||
def test_sale_fields_view_get(self):
|
||||
sale_form_view = self.env.ref(
|
||||
'contract.account_analytic_invoice_line_sale_view_form'
|
||||
)
|
||||
view = self.acct_line.with_context(
|
||||
default_contract_type='sale'
|
||||
).fields_view_get(view_type='form')
|
||||
self.assertEqual(view['view_id'], sale_form_view.id)
|
||||
|
||||
def test_contract_count_invoice(self):
|
||||
self.contract.recurring_create_invoice()
|
||||
self.contract.recurring_create_invoice()
|
||||
self.contract.recurring_create_invoice()
|
||||
self.contract._compute_invoice_count()
|
||||
self.assertEqual(self.contract.invoice_count, 3)
|
||||
|
||||
def test_contract_count_invoice(self):
|
||||
invoices = self.env['account.invoice']
|
||||
invoices |= self.contract.recurring_create_invoice()
|
||||
invoices |= self.contract.recurring_create_invoice()
|
||||
invoices |= self.contract.recurring_create_invoice()
|
||||
action = self.contract.action_show_invoices()
|
||||
self.assertEqual(set(action['domain'][0][2]), set(invoices.ids))
|
||||
|
||||
def test_compute_create_invoice_visibility(self):
|
||||
self.assertTrue(self.contract.create_invoice_visibility)
|
||||
self.acct_line.write(
|
||||
{
|
||||
'date_start': '2018-01-01',
|
||||
'date_end': '2018-12-31',
|
||||
'last_date_invoiced': '2018-12-31',
|
||||
'recurring_next_date': False,
|
||||
}
|
||||
)
|
||||
self.assertFalse(self.acct_line.create_invoice_visibility)
|
||||
self.assertFalse(self.contract.create_invoice_visibility)
|
||||
|
||||
def test_invoice_contract_without_lines(self):
|
||||
self.contract.recurring_invoice_line_ids.cancel()
|
||||
self.contract.recurring_invoice_line_ids.unlink()
|
||||
self.assertFalse(self.contract.recurring_create_invoice())
|
||||
|
||||
@@ -26,6 +26,14 @@
|
||||
<field name="date_end"
|
||||
attrs="{'required': [('is_auto_renew', '=', True)]}"/>
|
||||
</group>
|
||||
<group groups="base.group_no_one">
|
||||
<field name="last_date_invoiced" readonly="True"/>
|
||||
<field name="termination_notice_date" readonly="True"/>
|
||||
</group>
|
||||
<group groups="base.group_no_one">
|
||||
<field name="manual_renew_needed"/>
|
||||
</group>
|
||||
|
||||
<group>
|
||||
<field name="predecessor_contract_line_id"/>
|
||||
</group>
|
||||
|
||||
@@ -13,7 +13,13 @@ class AccountAnalyticInvoiceLineWizard(models.TransientModel):
|
||||
date_end = fields.Date(string='Date End')
|
||||
recurring_next_date = fields.Date(string='Next Invoice Date')
|
||||
is_auto_renew = fields.Boolean(string="Auto Renew", default=False)
|
||||
is_suspended = fields.Boolean(string="Is a suspension", default=False)
|
||||
manual_renew_needed = fields.Boolean(
|
||||
string="Manual renew needed",
|
||||
default=False,
|
||||
help="This flag is used to make a difference between a definitive stop"
|
||||
"and temporary one for which a user is not able to plan a"
|
||||
"successor in advance",
|
||||
)
|
||||
contract_line_id = fields.Many2one(
|
||||
comodel_name="account.analytic.invoice.line",
|
||||
string="Contract Line",
|
||||
@@ -25,7 +31,7 @@ class AccountAnalyticInvoiceLineWizard(models.TransientModel):
|
||||
def stop(self):
|
||||
for wizard in self:
|
||||
wizard.contract_line_id.stop(
|
||||
wizard.date_end, is_suspended=wizard.is_suspended
|
||||
wizard.date_end, manual_renew_needed=wizard.manual_renew_needed
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<group>
|
||||
<field name="contract_line_id" invisible="True"/>
|
||||
<field string="Stop Date" name="date_end" required="True"/>
|
||||
<field string="Is a suspension" name="is_suspended"/>
|
||||
<field string="Is a suspension" name="manual_renew_needed"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="stop"
|
||||
|
||||
Reference in New Issue
Block a user