diff --git a/contract/models/contract.py b/contract/models/contract.py index 74eb8fe0..5b849cbe 100644 --- a/contract/models/contract.py +++ b/contract/models/contract.py @@ -225,6 +225,7 @@ class AccountAnalyticAccount(models.Model): ) new_lines += contract_line_model.new(vals) new_lines._onchange_date_start() + new_lines._onchange_is_auto_renew() return new_lines @api.multi diff --git a/contract/models/contract_line.py b/contract/models/contract_line.py index 1fc654eb..f2f833b3 100644 --- a/contract/models/contract_line.py +++ b/contract/models/contract_line.py @@ -409,6 +409,14 @@ class AccountAnalyticInvoiceLine(models.Model): rec.recurring_interval, ) + @api.constrains('is_canceled', 'is_auto_renew') + def _check_auto_renew_canceled_lines(self): + for rec in self: + if rec.is_canceled and rec.is_auto_renew: + raise ValidationError( + _("A canceled contract line can't be set to auto-renew") + ) + @api.constrains('recurring_next_date', 'date_start') def _check_recurring_next_date_start_date(self): for line in self.filtered('recurring_next_date'): @@ -886,7 +894,7 @@ class AccountAnalyticInvoiceLine(models.Model): self.mapped('predecessor_contract_line_id').write( {'successor_contract_line_id': False} ) - return self.write({'is_canceled': True}) + return self.write({'is_canceled': True, 'is_auto_renew': False}) @api.multi def uncancel(self, recurring_next_date): diff --git a/contract/readme/USAGE.rst b/contract/readme/USAGE.rst index 55474837..0fecae98 100644 --- a/contract/readme/USAGE.rst +++ b/contract/readme/USAGE.rst @@ -1,27 +1,25 @@ -To use this module, you need to: +#. Contracts are in Invoicing -> Customers -> Customer and Invoicing -> Vendors -> Supplier Contracts +#. When creating a contract, fill fields for selecting the invoicing parameters: -#. Go to Accounting -> Contracts and select or create a new contract. -#. Check *Generate recurring invoices automatically*. -#. Fill fields for selecting the recurrency and invoice parameters: + * a journal + * a price list (optional) - * Journal - * Pricelist - * Period. It can be any interval of days, weeks, months, months last day or - years. - * Start date and next invoice date. - * Invoicing type: pre-paid or post-paid. +#. And add the lines to be invoiced with: -#. Add the lines to be invoiced with the product, description, quantity and - price. -#. You can mark Auto-price? for having a price automatically obtained applying - the pricelist to the product price. -#. You have the possibility to use the markers #START# or #END# in the - description field to show the start and end date of the invoiced period. -#. Choosing between pre-paid and post-paid, you modify the dates that are shown - with the markers. -#. A cron is created with daily interval, but if you are in debug mode, you can - click on *Create invoices* to force this action. -#. Click *Show recurring invoices* link to show all invoices created by the + * the product with a description, a quantity and a price + * the recurrence parameters: interval (days, weeks, months, months last day or years), + start date, date of next invoice (automatically computed, can be modified) and end date (optional) + * auto-price, for having a price automatically obtained from the price list + * #START# or #END# in the description field to display the start/end date of + the invoiced period in the invoice line description + * pre-paid (invoice at period start) or post-paid (invoice at start of next period) + +#. The "Generate Recurring Invoices from Contracts" cron runs daily to generate the invoices. + If you are in debug mode, you can click on the invoice creation button. +#. The *Show recurring invoices* shortcut on contracts shows all invoices created from the contract. -#. Click on *Print > Contract* menu to print contract report. -#. Click on *Send by Email* button to send contract by email. +#. The contract report can be printed from the Print menu +#. The contract can be sent by email with the *Send by Email* button +#. Contract templates can be created from the Configuration -> Contracts -> Contract Templates menu. + They allow to define default journal, price list and lines when creating a contract. + To use it, just select the template on the contract and fields will be filled automatically. diff --git a/contract/tests/test_contract.py b/contract/tests/test_contract.py index b21a9f8b..566cbc59 100644 --- a/contract/tests/test_contract.py +++ b/contract/tests/test_contract.py @@ -1160,8 +1160,17 @@ class TestContract(TestContractBase): ) def test_cancel(self): + self.acct_line.write( + { + 'date_end': self.today + relativedelta(months=5), + 'is_auto_renew': True, + } + ) self.acct_line.cancel() self.assertTrue(self.acct_line.is_canceled) + self.assertFalse(self.acct_line.is_auto_renew) + with self.assertRaises(ValidationError): + self.acct_line.is_auto_renew = True self.acct_line.uncancel(self.today) self.assertFalse(self.acct_line.is_canceled) @@ -1330,24 +1339,27 @@ class TestContract(TestContractBase): self.acct_line.recurring_rule_type = 'monthlylastday' self.acct_line.date_end = '2018-03-15' self.acct_line._onchange_date_start() - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2018-01-05')) self.assertEqual(last, to_date('2018-01-31')) self.contract.recurring_create_invoice() - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2018-02-01')) self.assertEqual(last, to_date('2018-02-28')) self.contract.recurring_create_invoice() - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2018-03-01')) self.assertEqual(last, to_date('2018-03-15')) self.acct_line.manual_renew_needed = True @@ -1359,17 +1371,19 @@ class TestContract(TestContractBase): self.acct_line.date_end = '2018-08-15' self.acct_line._onchange_date_start() self.contract.recurring_create_invoice() - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2018-02-05')) self.assertEqual(last, to_date('2018-03-04')) self.acct_line.recurring_next_date = '2018-06-05' - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2018-02-05')) self.assertEqual(last, to_date('2018-07-04')) @@ -1380,17 +1394,19 @@ class TestContract(TestContractBase): self.acct_line.date_end = '2018-08-15' self.acct_line._onchange_date_start() self.contract.recurring_create_invoice() - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2018-02-05')) self.assertEqual(last, to_date('2018-03-04')) self.acct_line.recurring_next_date = '2018-06-05' - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2018-02-05')) self.assertEqual(last, to_date('2018-06-04')) @@ -1400,24 +1416,27 @@ class TestContract(TestContractBase): self.acct_line.recurring_rule_type = 'monthly' self.acct_line.date_end = '2018-03-15' self.acct_line._onchange_date_start() - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2018-01-05')) self.assertEqual(last, to_date('2018-02-04')) self.contract.recurring_create_invoice() - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2018-02-05')) self.assertEqual(last, to_date('2018-03-04')) self.contract.recurring_create_invoice() - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2018-03-05')) self.assertEqual(last, to_date('2018-03-15')) @@ -1427,24 +1446,27 @@ class TestContract(TestContractBase): self.acct_line.recurring_rule_type = 'monthly' self.acct_line.date_end = '2018-03-15' self.acct_line._onchange_date_start() - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2018-01-05')) self.assertEqual(last, to_date('2018-02-04')) self.contract.recurring_create_invoice() - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2018-02-05')) self.assertEqual(last, to_date('2018-03-04')) self.contract.recurring_create_invoice() - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2018-03-05')) self.assertEqual(last, to_date('2018-03-15')) @@ -1454,24 +1476,27 @@ class TestContract(TestContractBase): self.acct_line.recurring_rule_type = 'yearly' self.acct_line.date_end = '2020-03-15' self.acct_line._onchange_date_start() - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2018-01-05')) self.assertEqual(last, to_date('2019-01-04')) self.contract.recurring_create_invoice() - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2019-01-05')) self.assertEqual(last, to_date('2020-01-04')) self.contract.recurring_create_invoice() - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2020-01-05')) self.assertEqual(last, to_date('2020-03-15')) @@ -1481,24 +1506,27 @@ class TestContract(TestContractBase): self.acct_line.recurring_rule_type = 'yearly' self.acct_line.date_end = '2020-03-15' self.acct_line._onchange_date_start() - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2018-01-05')) self.assertEqual(last, to_date('2019-01-04')) self.contract.recurring_create_invoice() - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2019-01-05')) self.assertEqual(last, to_date('2020-01-04')) self.contract.recurring_create_invoice() - first, last, recurring_next_date = self.acct_line._get_period_to_invoice( - self.acct_line.last_date_invoiced, - self.acct_line.recurring_next_date, - ) + first, last, recurring_next_date = \ + self.acct_line._get_period_to_invoice( + self.acct_line.last_date_invoiced, + self.acct_line.recurring_next_date, + ) self.assertEqual(first, to_date('2020-01-05')) self.assertEqual(last, to_date('2020-03-15'))