diff --git a/contract/models/abstract_contract.py b/contract/models/abstract_contract.py index 1c6292f93..93d7098e5 100644 --- a/contract/models/abstract_contract.py +++ b/contract/models/abstract_contract.py @@ -19,8 +19,7 @@ class AbstractAccountAnalyticContract(models.AbstractModel): name = fields.Char(required=True) # Needed for avoiding errors on several inherited behaviors partner_id = fields.Many2one( - comodel_name="res.partner", string="Partner (always False)", - index=True, + comodel_name="res.partner", string="Partner (always False)", index=True ) pricelist_id = fields.Many2one( comodel_name='product.pricelist', string='Pricelist' diff --git a/contract/models/abstract_contract_line.py b/contract/models/abstract_contract_line.py index 9d171ca65..a338cb7dc 100644 --- a/contract/models/abstract_contract_line.py +++ b/contract/models/abstract_contract_line.py @@ -81,7 +81,7 @@ class AccountAbstractAnalyticContractLine(models.AbstractModel): ) date_start = fields.Date(string='Date Start') recurring_next_date = fields.Date(string='Date of Next Invoice') - + last_date_invoiced = fields.Date(string='Last Date Invoiced') is_canceled = fields.Boolean(string="Canceled", default=False) is_auto_renew = fields.Boolean(string="Auto Renew", default=False) auto_renew_interval = fields.Integer( @@ -132,7 +132,8 @@ class AccountAbstractAnalyticContractLine(models.AbstractModel): if line.automatic_price: product = line.product_id.with_context( quantity=line.env.context.get( - 'contract_line_qty', line.quantity + 'contract_line_qty', + line.quantity, ), pricelist=line.contract_id.pricelist_id.id, partner=line.contract_id.partner_id.id, @@ -192,7 +193,6 @@ class AccountAbstractAnalyticContractLine(models.AbstractModel): date = self.recurring_next_date or fields.Date.context_today(self) partner = self.contract_id.partner_id or self.env.user.partner_id - product = self.product_id.with_context( lang=partner.lang, partner=partner.id, diff --git a/contract/models/contract.py b/contract/models/contract.py index 1212a459e..5b849cbea 100644 --- a/contract/models/contract.py +++ b/contract/models/contract.py @@ -48,8 +48,7 @@ class AccountAnalyticAccount(models.Model): compute='_compute_date_end', string='Date End', store=True ) payment_term_id = fields.Many2one( - comodel_name='account.payment.term', string='Payment Terms', - index=True, + comodel_name='account.payment.term', string='Payment Terms', index=True ) invoice_count = fields.Integer(compute="_compute_invoice_count") fiscal_position_id = fields.Many2one( @@ -63,8 +62,7 @@ class AccountAnalyticAccount(models.Model): ondelete='restrict', ) partner_id = fields.Many2one( - comodel_name='res.partner', - inverse='_inverse_partner_id', + comodel_name='res.partner', inverse='_inverse_partner_id' ) @api.multi @@ -72,7 +70,8 @@ class AccountAnalyticAccount(models.Model): for rec in self: if not rec.invoice_partner_id: rec.invoice_partner_id = rec.partner_id.address_get( - ['invoice'])['invoice'] + ['invoice'] + )['invoice'] @api.multi def _get_related_invoices(self): @@ -104,11 +103,16 @@ class AccountAnalyticAccount(models.Model): @api.multi def action_show_invoices(self): self.ensure_one() - tree_view_ref = 'account.invoice_supplier_tree' \ - if self.contract_type == 'purchase' \ + tree_view_ref = ( + 'account.invoice_supplier_tree' + if self.contract_type == 'purchase' else 'account.invoice_tree_with_onboarding' - form_view_ref = 'account.invoice_supplier_form' \ - if self.contract_type == 'purchase' else 'account.invoice_form' + ) + form_view_ref = ( + 'account.invoice_supplier_form' + if self.contract_type == 'purchase' + else 'account.invoice_form' + ) tree_view = self.env.ref(tree_view_ref, raise_if_not_found=False) form_view = self.env.ref(form_view_ref, raise_if_not_found=False) action = { @@ -167,7 +171,7 @@ class AccountAnalyticAccount(models.Model): for field_name, field in contract_template_id._fields.items(): if field.name == 'recurring_invoice_line_ids': lines = self._convert_contract_lines(contract_template_id) - self.recurring_invoice_line_ids = lines + self.recurring_invoice_line_ids += lines elif not any( ( field.compute, @@ -184,12 +188,18 @@ class AccountAnalyticAccount(models.Model): def _onchange_partner_id(self): self.pricelist_id = self.partner_id.property_product_pricelist.id self.fiscal_position_id = self.partner_id.property_account_position_id - self.invoice_partner_id = self.partner_id.address_get( - ['invoice'])['invoice'] - return {'domain': {'invoice_partner_id': [ - '|', - ('id', 'parent_of', self.partner_id.id), - ('id', 'child_of', self.partner_id.id)]}} + self.invoice_partner_id = self.partner_id.address_get(['invoice'])[ + 'invoice' + ] + return { + 'domain': { + 'invoice_partner_id': [ + '|', + ('id', 'parent_of', self.partner_id.id), + ('id', 'child_of', self.partner_id.id), + ] + } + } @api.constrains('partner_id', 'recurring_invoices') def _check_partner_id_recurring_invoices(self): @@ -203,7 +213,8 @@ class AccountAnalyticAccount(models.Model): @api.multi def _convert_contract_lines(self, contract): self.ensure_one() - new_lines = [] + new_lines = self.env['account.analytic.invoice.line'] + contract_line_model = self.env['account.analytic.invoice.line'] for contract_line in contract.recurring_invoice_line_ids: vals = contract_line._convert_to_write(contract_line.read()[0]) # Remove template link field @@ -212,8 +223,9 @@ class AccountAnalyticAccount(models.Model): vals['recurring_next_date'] = fields.Date.context_today( contract_line ) - self.recurring_invoice_line_ids._onchange_date_start() - new_lines.append((0, 0, vals)) + 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 13f923572..f2f833b30 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'): @@ -486,9 +494,12 @@ class AccountAnalyticInvoiceLine(models.Model): @api.multi def _prepare_invoice_line(self, invoice_id=False): self.ensure_one() + dates = self._get_period_to_invoice( + self.last_date_invoiced, self.recurring_next_date + ) invoice_line_vals = { 'product_id': self.product_id.id, - 'quantity': self.quantity, + 'quantity': self._get_quantity_to_invoice(*dates), 'uom_id': self.uom_id.id, 'discount': self.discount, 'contract_line_id': self.id, @@ -501,8 +512,7 @@ class AccountAnalyticInvoiceLine(models.Model): invoice_line_vals = invoice_line._convert_to_write(invoice_line._cache) # Insert markers contract = self.contract_id - first_date_invoiced, last_date_invoiced = self._get_invoiced_period() - name = self._insert_markers(first_date_invoiced, last_date_invoiced) + name = self._insert_markers(dates[0], dates[1]) invoice_line_vals.update( { 'name': name, @@ -513,31 +523,37 @@ class AccountAnalyticInvoiceLine(models.Model): return invoice_line_vals @api.multi - def _get_invoiced_period(self): + def _get_period_to_invoice( + self, last_date_invoiced, recurring_next_date, stop_at_date_end=True + ): self.ensure_one() + first_date_invoiced = False + if not recurring_next_date: + return first_date_invoiced, last_date_invoiced, recurring_next_date first_date_invoiced = ( - self.last_date_invoiced + relativedelta(days=1) - if self.last_date_invoiced + last_date_invoiced + relativedelta(days=1) + if last_date_invoiced else self.date_start ) if self.recurring_rule_type == 'monthlylastday': - last_date_invoiced = self.recurring_next_date + last_date_invoiced = recurring_next_date else: if self.recurring_invoicing_type == 'pre-paid': last_date_invoiced = ( - self.recurring_next_date + recurring_next_date + self.get_relative_delta( self.recurring_rule_type, self.recurring_interval ) - relativedelta(days=1) ) else: - last_date_invoiced = self.recurring_next_date - relativedelta( + last_date_invoiced = recurring_next_date - relativedelta( days=1 ) - if self.date_end and self.date_end < last_date_invoiced: - last_date_invoiced = self.date_end - return first_date_invoiced, last_date_invoiced + if stop_at_date_end: + if self.date_end and self.date_end < last_date_invoiced: + last_date_invoiced = self.date_end + return first_date_invoiced, last_date_invoiced, recurring_next_date @api.multi def _insert_markers(self, first_date_invoiced, last_date_invoiced): @@ -650,8 +666,16 @@ class AccountAnalyticInvoiceLine(models.Model): rec.cancel() else: if not rec.date_end or rec.date_end > date_end: + old_date_end = rec.date_end + values = { + 'date_end': date_end, + 'is_auto_renew': False, + 'manual_renew_needed': manual_renew_needed, + } + if rec.last_date_invoiced == date_end: + values['recurring_next_date'] = False + rec.write(values) if post_message: - old_date_end = rec.date_end msg = _( """Contract line for {product} stopped:
@@ -663,13 +687,6 @@ class AccountAnalyticInvoiceLine(models.Model): ) ) rec.contract_id.message_post(body=msg) - rec.write( - { - 'date_end': date_end, - 'is_auto_renew': False, - "manual_renew_needed": manual_renew_needed, - } - ) else: rec.write( { @@ -877,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): @@ -1073,3 +1090,10 @@ class AccountAnalyticInvoiceLine(models.Model): _("Contract line must be canceled before delete") ) return super(AccountAnalyticInvoiceLine, self).unlink() + + @api.multi + def _get_quantity_to_invoice( + self, period_first_date, period_last_date, invoice_date + ): + self.ensure_one() + return self.quantity diff --git a/contract/models/res_partner.py b/contract/models/res_partner.py index 038ab3fcf..c18e00e96 100644 --- a/contract/models/res_partner.py +++ b/contract/models/res_partner.py @@ -16,14 +16,10 @@ class ResPartner(models.Model): def _compute_contract_count(self): contract_model = self.env['account.analytic.account'] - today = fields.Date.today() fetch_data = contract_model.read_group( [ ('recurring_invoices', '=', True), ('partner_id', 'child_of', self.ids), - '|', - ('date_end', '=', False), - ('date_end', '>=', today), ], ['partner_id', 'contract_type'], ['partner_id', 'contract_type'], @@ -62,7 +58,6 @@ class ResPartner(models.Model): context=dict( self.env.context, search_default_recurring_invoices=True, - search_default_not_finished=True, search_default_partner_id=self.id, default_partner_id=self.id, default_recurring_invoices=True, diff --git a/contract/readme/USAGE.rst b/contract/readme/USAGE.rst index 554748378..0fecae989 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 54e71c2eb..566cbc59f 100644 --- a/contract/tests/test_contract.py +++ b/contract/tests/test_contract.py @@ -153,9 +153,7 @@ class TestContract(TestContractBase): self.inv_line = self.invoice_monthly.invoice_line_ids[0] self.assertTrue(self.inv_line.invoice_line_tax_ids) self.assertAlmostEqual(self.inv_line.price_subtotal, 50.0) - self.assertEqual( - self.contract.user_id, self.invoice_monthly.user_id - ) + self.assertEqual(self.contract.user_id, self.invoice_monthly.user_id) def test_contract_recurring_next_date(self): recurring_next_date = to_date('2018-01-15') @@ -1162,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) @@ -1326,124 +1333,200 @@ class TestContract(TestContractBase): len(invoice_lines), ) - def test_get_invoiced_period_monthlylastday(self): + def test_get_period_to_invoice_monthlylastday(self): self.acct_line.date_start = '2018-01-05' self.acct_line.recurring_invoicing_type = 'post-paid' self.acct_line.recurring_rule_type = 'monthlylastday' self.acct_line.date_end = '2018-03-15' self.acct_line._onchange_date_start() - first, last = self.acct_line._get_invoiced_period() + 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 = self.acct_line._get_invoiced_period() + 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 = self.acct_line._get_invoiced_period() + 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 - def test_get_invoiced_period_monthly_pre_paid_2(self): + def test_get_period_to_invoice_monthly_pre_paid_2(self): self.acct_line.date_start = '2018-01-05' self.acct_line.recurring_invoicing_type = 'pre-paid' self.acct_line.recurring_rule_type = 'monthly' self.acct_line.date_end = '2018-08-15' self.acct_line._onchange_date_start() self.contract.recurring_create_invoice() - first, last = self.acct_line._get_invoiced_period() + 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 = self.acct_line._get_invoiced_period() + 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')) - def test_get_invoiced_period_monthly_post_paid_2(self): + def test_get_period_to_invoice_monthly_post_paid_2(self): self.acct_line.date_start = '2018-01-05' self.acct_line.recurring_invoicing_type = 'post-paid' self.acct_line.recurring_rule_type = 'monthly' self.acct_line.date_end = '2018-08-15' self.acct_line._onchange_date_start() self.contract.recurring_create_invoice() - first, last = self.acct_line._get_invoiced_period() + 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 = self.acct_line._get_invoiced_period() + 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')) - def test_get_invoiced_period_monthly_post_paid(self): + def test_get_period_to_invoice_monthly_post_paid(self): self.acct_line.date_start = '2018-01-05' self.acct_line.recurring_invoicing_type = 'post-paid' self.acct_line.recurring_rule_type = 'monthly' self.acct_line.date_end = '2018-03-15' self.acct_line._onchange_date_start() - first, last = self.acct_line._get_invoiced_period() + 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 = self.acct_line._get_invoiced_period() + 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 = self.acct_line._get_invoiced_period() + 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')) - def test_get_invoiced_period_monthly_pre_paid(self): + def test_get_period_to_invoice_monthly_pre_paid(self): self.acct_line.date_start = '2018-01-05' self.acct_line.recurring_invoicing_type = 'pre-paid' self.acct_line.recurring_rule_type = 'monthly' self.acct_line.date_end = '2018-03-15' self.acct_line._onchange_date_start() - first, last = self.acct_line._get_invoiced_period() + 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 = self.acct_line._get_invoiced_period() + 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 = self.acct_line._get_invoiced_period() + 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')) - def test_get_invoiced_period_yearly_post_paid(self): + def test_get_period_to_invoice_yearly_post_paid(self): self.acct_line.date_start = '2018-01-05' self.acct_line.recurring_invoicing_type = 'post-paid' self.acct_line.recurring_rule_type = 'yearly' self.acct_line.date_end = '2020-03-15' self.acct_line._onchange_date_start() - first, last = self.acct_line._get_invoiced_period() + 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 = self.acct_line._get_invoiced_period() + 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 = self.acct_line._get_invoiced_period() + 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')) - def test_get_invoiced_period_yearly_pre_paid(self): + def test_get_period_to_invoice_yearly_pre_paid(self): self.acct_line.date_start = '2018-01-05' self.acct_line.recurring_invoicing_type = 'pre-paid' self.acct_line.recurring_rule_type = 'yearly' self.acct_line.date_end = '2020-03-15' self.acct_line._onchange_date_start() - first, last = self.acct_line._get_invoiced_period() + 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 = self.acct_line._get_invoiced_period() + 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 = self.acct_line._get_invoiced_period() + 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')) @@ -1752,3 +1835,9 @@ class TestContract(TestContractBase): self.contract.recurring_invoice_line_ids.cancel() self.contract.recurring_invoice_line_ids.unlink() self.assertFalse(self.contract.recurring_create_invoice()) + + def test_stop_at_last_date_invoiced(self): + self.contract.recurring_create_invoice() + self.assertTrue(self.acct_line.recurring_next_date) + self.acct_line.stop(self.acct_line.last_date_invoiced) + self.assertFalse(self.acct_line.recurring_next_date) diff --git a/contract/views/contract.xml b/contract/views/contract.xml index e842a333b..08398ca5f 100644 --- a/contract/views/contract.xml +++ b/contract/views/contract.xml @@ -184,11 +184,6 @@ - - - @@ -200,7 +195,7 @@ - +