From 9b08269d2efbd556035bcb65ceb733778c78918f Mon Sep 17 00:00:00 2001 From: Emanuel Cino Date: Tue, 27 Aug 2024 14:32:53 +0200 Subject: [PATCH] T1771 recurring_contract : import from v14 --- recurring_contract/README.rst | 12 +- .../{__openerp__.py => __manifest__.py} | 2 +- .../data/recurring_invoicer_sequence.xml | 21 - recurring_contract/demo/contract_demo.xml | 98 ---- .../migrations/1.2/post-migration.py | 39 -- .../migrations/14.0.1.0.1/post-migration.py | 22 - .../migrations/14.0.1.0.2/post-migration.py | 35 -- .../migrations/14.0.1.0.2/pre-migration.py | 97 ---- .../migrations/14.0.1.0.4/pre-migration.py | 6 - .../migrations/9.0.1.0.0/pre-migration.py | 25 - recurring_contract/model/__init__.py | 15 - recurring_contract/model/contract_group.py | 265 ---------- recurring_contract/model/invoice.py | 53 -- .../model/recurring_contract.py | 481 ------------------ .../model/recurring_invoicer.py | 70 --- recurring_contract/requirements.txt | 0 .../static/description/index.html | 15 +- .../view/contract_group_view.xml | 44 -- .../view/recurring_contract_view.xml | 145 ------ .../view/recurring_invoicer_view.xml | 60 --- .../view/recurring_invoicer_wizard_view.xml | 43 -- recurring_contract/wizard/__init__.py | 12 - .../wizard/recurring_invoicer_wizard.py | 50 -- recurring_contract/wizards/__init__.py | 3 + .../workflow/recurring_contract_workflow.xml | 53 -- requirements.txt | 1 - 26 files changed, 18 insertions(+), 1649 deletions(-) rename recurring_contract/{__openerp__.py => __manifest__.py} (97%) delete mode 100644 recurring_contract/data/recurring_invoicer_sequence.xml delete mode 100644 recurring_contract/demo/contract_demo.xml delete mode 100644 recurring_contract/migrations/1.2/post-migration.py delete mode 100644 recurring_contract/migrations/14.0.1.0.1/post-migration.py delete mode 100644 recurring_contract/migrations/14.0.1.0.2/post-migration.py delete mode 100644 recurring_contract/migrations/14.0.1.0.2/pre-migration.py delete mode 100644 recurring_contract/migrations/14.0.1.0.4/pre-migration.py delete mode 100644 recurring_contract/migrations/9.0.1.0.0/pre-migration.py delete mode 100644 recurring_contract/model/__init__.py delete mode 100644 recurring_contract/model/contract_group.py delete mode 100644 recurring_contract/model/invoice.py delete mode 100644 recurring_contract/model/recurring_contract.py delete mode 100644 recurring_contract/model/recurring_invoicer.py create mode 100644 recurring_contract/requirements.txt delete mode 100644 recurring_contract/view/contract_group_view.xml delete mode 100644 recurring_contract/view/recurring_contract_view.xml delete mode 100644 recurring_contract/view/recurring_invoicer_view.xml delete mode 100644 recurring_contract/view/recurring_invoicer_wizard_view.xml delete mode 100644 recurring_contract/wizard/__init__.py delete mode 100644 recurring_contract/wizard/recurring_invoicer_wizard.py create mode 100644 recurring_contract/wizards/__init__.py delete mode 100644 recurring_contract/workflow/recurring_contract_workflow.xml delete mode 100644 requirements.txt diff --git a/recurring_contract/README.rst b/recurring_contract/README.rst index f80586e44..6f4f2fa5e 100644 --- a/recurring_contract/README.rst +++ b/recurring_contract/README.rst @@ -16,9 +16,9 @@ Recurring contract .. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 -.. |badge3| image:: https://img.shields.io/badge/github-CompassionCH%2Ftest--repo-lightgray.png?logo=github - :target: https://github.com/CompassionCH/test-repo/tree/14.0/recurring_contract - :alt: CompassionCH/test-repo +.. |badge3| image:: https://img.shields.io/badge/github-CompassionCH%2Fcompassion--accounting-lightgray.png?logo=github + :target: https://github.com/CompassionCH/compassion-accounting/tree/17.0/recurring_contract + :alt: CompassionCH/compassion-accounting |badge1| |badge2| |badge3| @@ -41,10 +41,10 @@ To use this module, you need to: Bug Tracker =========== -Bugs are tracked on `GitHub Issues `_. +Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -67,6 +67,6 @@ Contributors Maintainers ----------- -This module is part of the `CompassionCH/test-repo `_ project on GitHub. +This module is part of the `CompassionCH/compassion-accounting `_ project on GitHub. You are welcome to contribute. diff --git a/recurring_contract/__openerp__.py b/recurring_contract/__manifest__.py similarity index 97% rename from recurring_contract/__openerp__.py rename to recurring_contract/__manifest__.py index 3cda5381b..03ddc466d 100644 --- a/recurring_contract/__openerp__.py +++ b/recurring_contract/__manifest__.py @@ -33,7 +33,7 @@ "license": "AGPL-3", "author": "Compassion CH", "development_status": "Production/Stable", - "website": "https://github.com/CompassionCH/test-repo", + "website": "https://github.com/CompassionCH/compassion-accounting", "category": "Accounting", "depends": [ "account_invoice_pricelist", # OCA/account-invoicing diff --git a/recurring_contract/data/recurring_invoicer_sequence.xml b/recurring_contract/data/recurring_invoicer_sequence.xml deleted file mode 100644 index e5c46d22f..000000000 --- a/recurring_contract/data/recurring_invoicer_sequence.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - Recurring Invoicer Identifier - rec.invoicer.ident - - - - Recurring Invoicer Identifier - rec.invoicer.ident - %(year)s/%(month)s/%(day)s- - - - - diff --git a/recurring_contract/demo/contract_demo.xml b/recurring_contract/demo/contract_demo.xml deleted file mode 100644 index dac0d59e7..000000000 --- a/recurring_contract/demo/contract_demo.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - Analytic Journal Test - - - - - Journal Test - sale - True - 12345 - - - - - - - - Account Test - unreconciled - 87963 - - - Account Second Test - none - 87964 - - - - - - Property Account Receivable Test - receivable - - 45917 - True - - - - - - Property Account Payable Test - payable - - 45877 - True - - - - Property Account Income Test - 45646 - - other - True - - - - Property Account Expense Test - 14447 - - other - True - - - - - - 15 Days - - - - - - 15 - - - - - Category_id - - - diff --git a/recurring_contract/migrations/1.2/post-migration.py b/recurring_contract/migrations/1.2/post-migration.py deleted file mode 100644 index 0cb1dcb10..000000000 --- a/recurring_contract/migrations/1.2/post-migration.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Copyright (C) 2015 Compassion CH (http://www.compassion.ch) -# Releasing children from poverty in Jesus' name -# @author: Coninckx David -# -# The licence is in the file __openerp__.py -# -############################################################################## -import sys - - -def migrate(cr, version): - reload(sys) - sys.setdefaultencoding('UTF8') - - if not version: - return - delay_dict = {'annual': 12, 'biannual': 6, 'fourmonthly': 4, - 'quarterly': 3, 'bimonthly': 2, 'monthly': 1} - cr.execute( - ''' - SELECT id, advance_billing FROM recurring_contract_group - ''' - ) - - contract_groups = cr.fetchall() - - for contract_group in contract_groups: - delay = delay_dict.get(contract_group[1], 1) - cr.execute( - ''' - UPDATE recurring_contract_group - SET advance_billing_months = {0} - WHERE id = {1} - '''.format(delay, contract_group[0]) - - ) diff --git a/recurring_contract/migrations/14.0.1.0.1/post-migration.py b/recurring_contract/migrations/14.0.1.0.1/post-migration.py deleted file mode 100644 index 978ad8cd3..000000000 --- a/recurring_contract/migrations/14.0.1.0.1/post-migration.py +++ /dev/null @@ -1,22 +0,0 @@ -from openupgradelib import openupgrade - - -@openupgrade.migrate() -def migrate(env, version): - if not version: - return - # Restore contract_id value on move lines - openupgrade.logged_query( - env.cr, - """ - update account_move_line m - set contract_id=i.contract_id - from account_invoice_line i - where m.contract_id is null and old_invoice_line_id = i.id - and i.contract_id is not null; - """, - ) - for contract in env["recurring.contract"].search( - [("pricelist_id", "=", False), ("state", "not in", ["terminated", "cancelled"])] - ): - contract.on_change_company_id() diff --git a/recurring_contract/migrations/14.0.1.0.2/post-migration.py b/recurring_contract/migrations/14.0.1.0.2/post-migration.py deleted file mode 100644 index 057ff272c..000000000 --- a/recurring_contract/migrations/14.0.1.0.2/post-migration.py +++ /dev/null @@ -1,35 +0,0 @@ -def migrate(cr, version): - if version: - cr.execute( - """ - update recurring_contract_group - set invoice_suspended_until = ( - select date_trunc('month', min(next_invoice_date)) from recurring_contract - where group_id = recurring_contract_group.id - and state in ('waiting','active') - and child_id is not null - and next_invoice_date > ( - CURRENT_DATE + - INTERVAL '1 month' * recurring_contract_group.advance_billing_months + - INTERVAL '1 month' - ) - group by group_id - having count(*) = 1) - """ - ) - cr.execute( - """ - ALTER TABLE account_move_recurring_contract_rel - DROP COLUMN account_invoice_id; - """ - ) - cr.execute( - """INSERT INTO account_move_recurring_contract_rel (recurring_contract_id, - account_move_id) - SELECT DISTINCT aml.contract_id, aml.move_id - FROM account_move_line aml - JOIN account_move m ON m.id = aml.move_id - WHERE aml.contract_id IS NOT NULL - AND m.payment_state != 'paid' AND m.state = 'posted' - AND aml.due_date < NOW()""", - ) diff --git a/recurring_contract/migrations/14.0.1.0.2/pre-migration.py b/recurring_contract/migrations/14.0.1.0.2/pre-migration.py deleted file mode 100644 index 83a6691e4..000000000 --- a/recurring_contract/migrations/14.0.1.0.2/pre-migration.py +++ /dev/null @@ -1,97 +0,0 @@ -from openupgradelib import openupgrade - - -@openupgrade.migrate() -def migrate(env, version): - # Precompute fields to speed up the migration - openupgrade.add_fields( - env, - [ - ( - "last_payment", - "account.move", - "account_move", - "date", - False, - "recurring_contract", - False, - ), - ( - "last_payment", - "account.move.line", - "account_move_line", - "date", - False, - "recurring_contract", - False, - ), - ( - "payment_state", - "account.move.line", - "account_move_line", - "selection", - False, - "recurring_contract", - False, - ), - ( - "missing_invoices", - "recurring.contract", - "recurring_contract", - "boolean", - False, - "recurring_contract", - False, - ), - ], - ) - openupgrade.logged_query( - env.cr, - """ - UPDATE account_move m - SET last_payment = ( - SELECT MAX(date) - FROM account_move_line aml - WHERE (CASE - WHEN m.move_type = 'out_invoice' THEN aml.credit - WHEN m.move_type = 'in_invoice' THEN aml.debit - ELSE 0 - END) > 0 AND full_reconcile_id = ANY( - SELECT full_reconcile_id - FROM account_move_line - WHERE move_id = m.id - ) - ) - WHERE payment_state = 'paid' AND move_type IN ('out_invoice', 'in_invoice'); - """, - ) - openupgrade.logged_query( - env.cr, - """ - UPDATE account_move_line aml - SET last_payment = ( - SELECT last_payment - FROM account_move - WHERE id = aml.move_id - ), - payment_state = ( - SELECT payment_state - FROM account_move - WHERE id = aml.move_id - ) - WHERE move_id IS NOT NULL; - """, - ) - if not openupgrade.table_exists(env.cr, "account_move_recurring_contract_rel"): - openupgrade.logged_query( - env.cr, - """ - ALTER TABLE account_invoice_recurring_contract_rel - RENAME TO account_move_recurring_contract_rel; - ALTER TABLE account_move_recurring_contract_rel - ADD COLUMN account_move_id INTEGER; - UPDATE account_move_recurring_contract_rel rel SET account_move_id = m.id - FROM account_move m - WHERE m.old_invoice_id = rel.account_invoice_id; - """, - ) diff --git a/recurring_contract/migrations/14.0.1.0.4/pre-migration.py b/recurring_contract/migrations/14.0.1.0.4/pre-migration.py deleted file mode 100644 index 9209d269b..000000000 --- a/recurring_contract/migrations/14.0.1.0.4/pre-migration.py +++ /dev/null @@ -1,6 +0,0 @@ -def migrate(cr, version): - if version: - cr.execute( - "update account_move set invoice_date = date, invoice_date_due = date " - "where invoice_date is null" - ) diff --git a/recurring_contract/migrations/9.0.1.0.0/pre-migration.py b/recurring_contract/migrations/9.0.1.0.0/pre-migration.py deleted file mode 100644 index cd831cc3e..000000000 --- a/recurring_contract/migrations/9.0.1.0.0/pre-migration.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Copyright (C) 2017 Compassion CH (http://www.compassion.ch) -# Releasing children from poverty in Jesus' name -# @author: Emanuel Cino -# -# The licence is in the file __openerp__.py -# -############################################################################## -from openupgradelib import openupgrade - - -@openupgrade.migrate(use_env=True) -def migrate(env, version): - if not version: - return - - cr = env.cr - # Install dependency - openupgrade.logged_query(cr, """ - UPDATE ir_module_module - SET state='to install' - WHERE name = 'account_payment_mode' AND state='uninstalled'; - """) diff --git a/recurring_contract/model/__init__.py b/recurring_contract/model/__init__.py deleted file mode 100644 index 43e5fcaa6..000000000 --- a/recurring_contract/model/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Copyright (C) 2014 Compassion CH (http://www.compassion.ch) -# Releasing children from poverty in Jesus' name -# @author: Cyril Sester -# -# The licence is in the file __openerp__.py -# -############################################################################## - -from . import contract_group -from . import invoice -from . import recurring_invoicer -from . import recurring_contract diff --git a/recurring_contract/model/contract_group.py b/recurring_contract/model/contract_group.py deleted file mode 100644 index 6d53f317a..000000000 --- a/recurring_contract/model/contract_group.py +++ /dev/null @@ -1,265 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Copyright (C) 2014 Compassion CH (http://www.compassion.ch) -# Releasing children from poverty in Jesus' name -# @author: Cyril Sester -# -# The licence is in the file __openerp__.py -# -############################################################################## - -from datetime import datetime -from dateutil.relativedelta import relativedelta - -from openerp import api, fields, models -from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DF -from openerp.tools.translate import _ -import logging -logger = logging.getLogger(__name__) - - -class contract_group(models.Model): - _name = 'recurring.contract.group' - _description = 'A group of contracts' - _inherit = 'mail.thread' - _rec_name = 'ref' - - def _get_change_methods(self): - """ Method for applying changes """ - return [ - ('do_nothing', - 'Nothing'), - ('clean_invoices', - 'Clean invoices') - ] - - def __get_change_methods(self): - """ Call method which can be inherited """ - return self._get_change_methods() - - def _get_gen_states(self): - return ['active'] - - @api.depends('contract_ids.next_invoice_date', 'contract_ids.state') - @api.one - def _set_next_invoice_date(self): - next_inv_date = min( - [c.next_invoice_date for c in self.contract_ids - if c.state in self._get_gen_states()] or [False]) - self.next_invoice_date = next_inv_date - - def _set_last_paid_invoice(self): - for group in self: - group.last_paid_invoice_date = max( - [c.last_paid_invoice_date for c in group.contract_ids] or - [False]) - - partner_id = fields.Many2one( - 'res.partner', _('Partner'), required=True, - ondelete='cascade', track_visibility="onchange") - - ref = fields.Char(_('Reference'), default="/") - recurring_unit = fields.Selection([ - ('day', _('Day(s)')), - ('week', _('Week(s)')), - ('month', _('Month(s)')), - ('year', _('Year(s)'))], _('Reccurency'), - default='month', required=True) - recurring_value = fields.Integer( - _('Generate every'), default=1, required=True) - contract_ids = fields.One2many( - 'recurring.contract', 'group_id', _('Contracts'), readonly=True) - # TODO Add unit for advance_billing - advance_billing_months = fields.Integer( - _('Advance billing months'), - help=_( - 'Advance billing allows you to generate invoices in ' - 'advance. For example, you can generate the invoices ' - 'for each month of the year and send them to the ' - 'customer in january.' - ), default=1, ondelete='no action') - payment_term_id = fields.Many2one('account.payment.term', - _('Payment Term'), - track_visibility="onchange") - - next_invoice_date = fields.Date( - compute='_set_next_invoice_date', - string=_('Next invoice date'), store=True) - - last_paid_invoice_date = fields.Date( - compute='_set_last_paid_invoice', - string=_('Last paid invoice date')) - - change_method = fields.Selection( - selection=__get_change_methods, default='do_nothing', - string=_('Change method')) - - def write(self, vals): - """ - Perform various check at contract modifications - - Advance billing increased or decrease - - Recurring value or unit changes - - Another change method was selected - """ - res = True - # to solve "NotImplementedError: Iteration is not allowed" error - # Any of these modifications implies generate and validate invoices - generate_again = ('advance_billing_months' in vals or - 'recurring_value' in vals or - 'recurring_unit' in vals) - - for group in self: - - # Check if group has an next_invoice_date - if not group.next_invoice_date: - res = super(contract_group, self).write(vals) and res - break - - # Get the method to apply changes - change_method = vals.get('change_method', group.change_method) - change_method = getattr(self, change_method) - - res = super(contract_group, self).write(vals) & res - - if generate_again: - change_method() - - if generate_again: - invoicer_id = self.generate_invoices() - self.validate_invoices(invoicer_id) - - return res - - def button_generate_invoices(self): - invoicer = self.generate_invoices() - self.validate_invoices(invoicer) - return invoicer - - @api.one - def validate_invoices(self, invoicer): - # Check if there is invoice waiting for validation - if invoicer.invoice_ids: - invoicer.validate_invoices() - - def clean_invoices(self): - """ Change method which cancels generated invoices and rewinds - the next_invoice_date of contracts, so that new invoices can be - generated taking into consideration the modifications of the - contract group. - """ - since_date = datetime.date.today() - if self.last_paid_invoice_date: - last_paid_invoice_date = datetime.strptime( - self.last_paid_invoice_date, DF) - since_date = max(since_date, last_paid_invoice_date) - res = self.contract_ids.clean_invoices(since_date=since_date) - self.contract_ids.rewind_next_invoice_date() - return res - - def do_nothing(self): - """ No changes before generation """ - pass - - def generate_invoices(self, invoicer_id=None): - """ Checks all contracts and generate invoices if needed. - Create an invoice per contract group per date. - """ - logger.info("Invoice generation started.") - inv_obj = self.env['account.invoice'] - journal_obj = self.env['account.journal'] - gen_states = self._get_gen_states() - if not invoicer_id: - invoicer_id = self.env['recurring.invoicer'].create( - {'source': self._name}) - - journal_ids = journal_obj.search( - [('type', '=', 'sale'), ('company_id', '=', 1 or False)], limit=1) - - nb_groups = len(self) - count = 1 - for contract_group in self: - logger.info("Generating invoices for group {0}/{1}".format( - count, nb_groups)) - month_delta = contract_group.advance_billing_months or 1 - limit_date = datetime.today() + relativedelta(months=+month_delta) - while True: # Emulate a do-while loop - # contract_group update 'cause next_inv_date has been modified - group_inv_date = contract_group.next_invoice_date - contracts = [] - if group_inv_date and datetime.strptime(group_inv_date, - DF) <= limit_date: - contracts = [c - for c in contract_group.contract_ids - if c.next_invoice_date <= group_inv_date and - c.state in gen_states] - if not contracts: - break - inv_data = contract_group._setup_inv_data(journal_ids, - invoicer_id) - invoice = inv_obj.create(inv_data) - for contract in contracts: - contract_group._generate_invoice_lines(contract, invoice) - if invoice.invoice_line: - invoice.button_compute() - else: - invoice.unlink() - - # After a contract_group is done, we commit all writes in order to - # avoid doing it again in case of an error or a timeout - self.env.cr.commit() - count += 1 - logger.info("Invoice generation successfully finished.") - return invoicer_id - - def _setup_inv_data(self, journal_ids, invoicer): - """ Setup a dict with data passed to invoice.create. - If any custom data is wanted in invoice from contract group, just - inherit this method. - """ - partner = self.partner_id - inv_data = { - 'account_id': partner.property_account_receivable.id, - 'type': 'out_invoice', - 'partner_id': partner.id, - 'journal_id': len(journal_ids) and journal_ids[0].id or False, - 'currency_id': - partner.property_product_pricelist.currency_id.id or False, - 'date_invoice': self.next_invoice_date, - 'recurring_invoicer_id': invoicer.id, - 'payment_term': self.payment_term_id and - self.payment_term_id.id or False, - } - - return inv_data - - def _setup_inv_line_data(self, contract_line, invoice): - """ Setup a dict with data passed to invoice_line.create. - If any custom data is wanted in invoice line from contract, - just inherit this method. - """ - product = contract_line.product_id - account = product.property_account_income - inv_line_data = { - 'name': product.name, - 'price_unit': contract_line.amount or 0.0, - 'quantity': contract_line.quantity, - 'uos_id': False, - 'product_id': product.id or False, - 'invoice_id': invoice.id, - 'contract_id': contract_line.contract_id.id, - } - if account: - inv_line_data['account_id'] = account.id - return inv_line_data - - @api.one - def _generate_invoice_lines(self, contract, invoice): - inv_line_obj = self.env['account.invoice.line'] - for contract_line in contract.contract_line_ids: - inv_line_data = self._setup_inv_line_data(contract_line, invoice) - if inv_line_data: - inv_line_obj.create(inv_line_data) - - if not self.env.context.get('no_next_date_update'): - contract.update_next_invoice_date() diff --git a/recurring_contract/model/invoice.py b/recurring_contract/model/invoice.py deleted file mode 100644 index 90049b760..000000000 --- a/recurring_contract/model/invoice.py +++ /dev/null @@ -1,53 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Copyright (C) 2014 Compassion CH (http://www.compassion.ch) -# Releasing children from poverty in Jesus' name -# @author: Cyril Sester -# -# The licence is in the file __openerp__.py -# -############################################################################## - -from openerp import api, fields, models -from openerp.tools.translate import _ - - -class account_invoice(models.Model): - _name = 'account.invoice' - _inherit = 'account.invoice' - - recurring_invoicer_id = fields.Many2one( - 'recurring.invoicer', _('Invoicer')) - - -class account_invoice_line(models.Model): - _name = 'account.invoice.line' - _inherit = 'account.invoice.line' - - @api.depends('invoice_id.state') - def _get_invoice_lines_state(self): - for invoice_line in self: - invoice_line.state = invoice_line.invoice_id.state - - @api.depends('invoice_id.date_due') - def _get_invoice_lines_date_due(self): - for invoice_line in self: - invoice_line.due_date = invoice_line.invoice_id.date_due - - contract_id = fields.Many2one( - 'recurring.contract', _('Source contract')) - - due_date = fields.Date( - compute='_get_invoice_lines_date_due', string=_('Due date'), - readonly=True, strore=True) - - state = fields.Selection( - compute='_get_invoice_lines_state', string=_('State'), - readonly=True, strore=True, - selection=[('draft', 'Draft'), - ('proforma', 'Pro-forma'), - ('proforma2', 'Pro-forma'), - ('open', 'Open'), - ('paid', 'Paid'), - ('cancel', 'Cancelled')]) diff --git a/recurring_contract/model/recurring_contract.py b/recurring_contract/model/recurring_contract.py deleted file mode 100644 index 32eab5bcf..000000000 --- a/recurring_contract/model/recurring_contract.py +++ /dev/null @@ -1,481 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Copyright (C) 2014 Compassion CH (http://www.compassion.ch) -# Releasing children from poverty in Jesus' name -# @author: Cyril Sester -# -# The licence is in the file __openerp__.py -# -############################################################################## - -from datetime import datetime -from dateutil.relativedelta import relativedelta - -from openerp import api, exceptions, fields, models, netsvc -from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DF -from openerp.tools.translate import _ -import openerp.addons.decimal_precision as dp - - -class recurring_contract_line(models.Model): - """ Each product sold through a contract """ - - _name = "recurring.contract.line" - _description = "A contract line" - - def name_get(self, ids): - if not ids: - return [] - res = [(cl.id, cl.product_id.name_template) for cl in self.browse(ids)] - return res - - contract_id = fields.Many2one( - 'recurring.contract', _('Contract'), required=True, - ondelete='cascade', readonly=True) - product_id = fields.Many2one('product.product', _('Product'), - required=True) - amount = fields.Float(_('Price'), required=True) - quantity = fields.Integer(_('Quantity'), default=1, required=True) - subtotal = fields.Float(compute='_compute_subtotal', store=True, - digits_compute=dp.get_precision('Account')) - - @api.depends('amount', 'quantity') - @api.one - def _compute_subtotal(self): - self.subtotal = self.amount * self.quantity - - @api.onchange('product_id') - def on_change_product_id(self): - if not self.product_id: - self.amount = 0.0 - else: - self.amount = self.product_id.list_price - - -class recurring_contract(models.Model): - """ A contract to perform recurring invoicing to a partner """ - - _name = "recurring.contract" - _description = "Contract for recurring invoicing" - _inherit = ['mail.thread'] - _rec_name = 'reference' - - @api.depends('contract_line_ids', 'contract_line_ids.amount', - 'contract_line_ids.quantity') - def _get_total_amount(self): - for contract in self: - contract.total_amount = sum([ - line.subtotal for line in contract.contract_line_ids - ]) - - @api.one - def _get_last_paid_invoice(self): - self.last_paid_invoice_date = max( - [invl.invoice_id.date_invoice for invl in self.invoice_line_ids - if invl.state == 'paid'] or [False]) - - reference = fields.Char( - _('Reference'), default="/", required=True, readonly=True, - states={'draft': [('readonly', False)]}) - start_date = fields.Date( - _('Start date'), default=datetime.today().strftime(DF), - required=True, readonly=True, - states={'draft': [('readonly', False)]}, - track_visibility="onchange") - end_date = fields.Date( - _('End date'), readonly=False, - states={'terminated': [('readonly', True)]}, - track_visibility="onchange") - next_invoice_date = fields.Date( - _('Next invoice date'), readonly=False, - states={'draft': [('readonly', False)]}, - track_visibility="onchange") - last_paid_invoice_date = fields.Date( - compute='_get_last_paid_invoice', string=_('Last paid invoice date')) - partner_id = fields.Many2one( - 'res.partner', string=_('Partner'), required=True, - readonly=True, states={'draft': [('readonly', False)]}, - ondelete='restrict') - group_id = fields.Many2one( - 'recurring.contract.group', _('Payment Options'), - required=True, ondelete='cascade', - track_visibility="onchange") - invoice_line_ids = fields.One2many( - 'account.invoice.line', 'contract_id', - _('Related invoice lines'), readonly=True) - contract_line_ids = fields.One2many( - 'recurring.contract.line', 'contract_id', - _('Contract lines'), track_visibility="onchange") - state = fields.Selection([ - ('draft', _('Draft')), - ('active', _('Active')), - ('terminated', _('Terminated'))], _('Status'), default='draft', - select=True, readonly=True, track_visibility='onchange', - help=_(" * The 'Draft' status is used when a user is encoding a " - "new and unconfirmed Contract.\n" - "* The 'Active' status is used when the contract is " - "confirmed and until it's terminated.\n" - "* The 'Terminated' status is used when a contract is no " - "longer active.")) - total_amount = fields.Float( - compute='_get_total_amount', string='Total', - digits_compute=dp.get_precision('Account'), - track_visibility="onchange", store=True) - payment_term_id = fields.Many2one( - relation='account.payment.term', - related='group_id.payment_term_id', readonly=True, - string=_('Payment Term'), store=True) - - @api.constrains('reference') - @api.one - def _check_unique_reference(self): - chk_list_contracts = self.search([]) - self - ref_lst = [contract.reference for contract in chk_list_contracts - if contract.reference] - if self.reference in ref_lst: - raise exceptions.ValidationError( - _('Error: Reference should be unique')) - return True - - ################################# - # PUBLIC METHODS # - ################################# - @api.model - def create(self, vals): - """ Add a sequence generated ref if none is given """ - if vals.get('reference', '/') == '/': - vals['reference'] = self.env['ir.sequence'].next_by_code( - 'recurring.contract.ref') - - return super(recurring_contract, self).create(vals) - - def write(self, vals): - """ Perform various checks when a contract is modified. """ - if 'next_invoice_date' in vals: - self._on_change_next_invoice_date(vals['next_invoice_date']) - - res = super(recurring_contract, self).write(vals) - - if 'contract_line_ids' in vals: - self._on_contract_lines_changed() - - return res - - @api.one - def copy(self, default=None): - default = default or dict() - today = datetime.today() - old_contract = self - next_invoice_date = datetime.strptime(old_contract.next_invoice_date, - DF) - next_invoice_date = next_invoice_date.replace(month=today.month) - default.update({ - 'state': 'draft', - 'reference': '/', - 'start_date': today.strftime(DF), - 'end_date': False, - 'next_invoice_date': next_invoice_date.strftime(DF), - 'invoice_line_ids': False, - }) - return super(recurring_contract, self).copy(default) - - @api.one - def unlink(self): - if self.state == 'active': - raise exceptions.Warning( - 'UserError', - _('You cannot delete a contract that is still active. ' - 'Terminate it first.')) - else: - super(recurring_contract, self).unlink() - - return True - - @api.multi - def button_generate_invoices(self): - return self.group_id.button_generate_invoices() - - @api.one - def clean_invoices(self, since_date=None, to_date=None, keep_lines=None): - """ This method deletes invoices lines generated for a given contract - having a due date >= current month. If the invoice_line was the - only line in the invoice, we cancel the invoice. In the other - case, we have to revalidate the invoice to update the move lines. - """ - invl_search = [('contract_id', '=', self.id), - ('state', 'not in', ('paid', 'cancel'))] - if since_date: - invl_search.append(('due_date', '>=', since_date)) - if to_date: - invl_search.append(('due_date', '<=', to_date)) - - # Find all unpaid invoice lines after the given date - inv_lines = self.invoice_line_ids.search(invl_search) - - inv_ids = set() - empty_inv_ids = set() - to_remove_ids = [] # Invoice lines that will be moved or removed - for inv_line in inv_lines: - invoice = inv_line.invoice_id - inv_ids.add(invoice.id) - # Check if invoice is empty after removing the invoice_lines - # of the given contract - if invoice.id not in empty_inv_ids: - remaining_lines_ids = [ - invl.id for invl in invoice.invoice_line if - not invl.contract_id or - invl.contract_id and invl.contract_id.id != self.id] - if remaining_lines_ids: - # We can move or remove the line - to_remove_ids.append(inv_line.id) - else: - # The invoice would be empty if we remove the line - empty_inv_ids.add(invoice.id) - - if keep_lines: - self._move_cancel_lines(to_remove_ids, keep_lines) - else: - to_remove_recset = self.browse(to_remove_ids) - to_remove_recset.unlink() - - # Invoices to set back in open state - renew_inv_ids = list(inv_ids - empty_inv_ids) - - self._cancel_confirm_invoices(list(inv_ids), renew_inv_ids, - keep_lines) - - return inv_ids - - @api.one - def _cancel_confirm_invoices(self, cancel_ids, confirm_ids, - keep_lines=None): - """ Cancels given invoices and validate again given invoices. - confirm_ids must be a subset of cancel_ids ! """ - inv_obj = self.env['account.invoice'] - wf_service = netsvc.LocalService('workflow') - invoice_confirm = inv_obj.browse(confirm_ids) - - for invoice_id in cancel_ids: - wf_service.trg_validate(self.env.user.id, 'account.invoice', - invoice_id, 'invoice_cancel', self.env.cr) - invoice_confirm.action_cancel_draft() - for invoice_id in confirm_ids: - wf_service.trg_validate(self.env.user.id, 'account.invoice', - invoice_id, 'invoice_open', self.env.cr) - - def rewind_next_invoice_date(self): - """ Rewinds the next invoice date of contract after the last - generated invoice. No open invoices exist after that date. """ - gen_states = self.env['recurring.contract.group']._get_gen_states() - for contract in self: - if contract.state in gen_states: - last_invoice_date = max([ - datetime.strptime(line.invoice_id.date_invoice, DF) for - line in contract.invoice_line_ids - if line.state in ('open', 'paid')] or [False]) - if last_invoice_date: - # Call super for allowing rewind. - super(recurring_contract, self).write( - [contract.id], { - 'next_invoice_date': - last_invoice_date.strftime(DF)}) - contract.update_next_invoice_date() - else: - # No open/paid invoices, look for cancelled ones - next_invoice_date = min([ - datetime.strptime(line.invoice_id.date_invoice, DF) - for line in contract.invoice_line_ids - if line.state == 'cancel']) - if next_invoice_date: - super(recurring_contract, self).write( - [contract.id], { - 'next_invoice_date': - next_invoice_date.strftime(DF)}) - - return True - - ################################# - # PRIVATE METHODS # - ################################# - - def update_next_invoice_date(self): - """ Recompute and set next_invoice date. """ - next_date = self._compute_next_invoice_date() - self.write({'next_invoice_date': next_date}) - return True - - def _compute_next_invoice_date(self): - """ Compute next_invoice_date for a single contract. """ - next_date = datetime.strptime(self.next_invoice_date, DF) - rec_unit = self.group_id.recurring_unit - rec_value = self.group_id.recurring_value - if rec_unit == 'day': - next_date = next_date + relativedelta(days=+rec_value) - elif rec_unit == 'week': - next_date = next_date + relativedelta(weeks=+rec_value) - elif rec_unit == 'month': - next_date = next_date + relativedelta(months=+rec_value) - else: - next_date = next_date + relativedelta(years=+rec_value) - - return next_date.strftime(DF) - - @api.one - def _update_invoice_lines(self, invoice_ids): - """Update invoice lines generated by a contract, when the contract - was modified and corresponding invoices were cancelled. - - Parameters: - - invoice_ids (list): ids of draft invoices to be - updated and validated - """ - invoice_obj = self.env['account.invoice'] - inv_line_obj = self.env['account.invoice.line'] - group_obj = self.env['recurring.contract.group'] - for invoice in invoice_obj.browse(invoice_ids): - # Update payment term and generate new invoice_lines - invoice.write({ - 'payment_term': self.group_id.payment_term_id and - self.group_id.payment_term_id.id or False}) - old_lines_ids = [invl.id for invl in invoice.invoice_line - if invl.contract_id.id == self.id] - inv_line_obj.browse(old_lines_ids).unlink() - self.with_context(no_next_date_update=True) - group_obj._generate_invoice_lines(self, invoice.id) - self.with_context(no_next_date_update=False) - - @api.one - def _on_change_next_invoice_date(self, new_invoice_date): - new_invoice_date = datetime.strptime(new_invoice_date, DF) - if self.next_invoice_date: - next_invoice_date = datetime.strptime(self.next_invoice_date, DF) - if next_invoice_date > new_invoice_date: - raise exceptions.Warning( - 'Error', _('You cannot rewind the next invoice date.')) - return True - - @api.one - def _on_contract_lines_changed(self): - """Update related invoices to reflect the changes to the contract. - """ - invoice_obj = self.env['account.invoice'] - inv_line_obj = self.env['account.invoice.line'] - # Find all unpaid invoice lines after the given date - since_date = datetime.today().replace(day=1).strftime(DF) - inv_line_ids = inv_line_obj.search( - [('contract_id', '=', self.id), - ('due_date', '>=', since_date), - ('state', 'not in', ('paid', 'cancel'))]) - - con_ids = set() - inv_ids = set() - for inv_line in inv_line_ids: - invoice = inv_line.invoice_id - if invoice.id not in inv_ids or \ - inv_line.contract_id.id not in con_ids: - con_ids.add(inv_line.contract_id.id) - inv_ids.add(invoice.id) - invoice.action_cancel() - invoice.action_cancel_draft() - self._update_invoice_lines([invoice.id]) - - wf_service = netsvc.LocalService('workflow') - for invoice in invoice_obj.browse(list(inv_ids)): - wf_service.trg_validate(self.env.user.id, 'account.invoice', - invoice.id, 'invoice_open', self.env.cr) - - @api.one - def _move_cancel_lines(self, invoice_line_ids, message=None): - """ Method that takes out given invoice_lines from their invoice - and put them in a cancelled copy of that invoice. - Warning : this method does not recompute totals of original invoices, - and does not update related move lines. - """ - invoice_obj = self.env['account.invoice'] - invoice_line_obj = self.env['account.invoice.line'] - invoices_copy = dict() - for invoice_line in invoice_line_obj.browse(invoice_line_ids): - invoice = invoice_line.invoice_id - copy_invoice_id = invoices_copy.get(invoice.id) - if not copy_invoice_id: - invoice_obj.copy(invoice.id, { - 'date_invoice': invoice.date_invoice}) - copy_invoice_id = invoice_obj.search( - [('partner_id', '=', invoice.partner_id.id), - ('state', '=', 'draft'), ('id', '!=', invoice.id), - ('date_invoice', '=', invoice.date_invoice)])[0] - # Empty the new invoice - cancel_lines = invoice_line_obj.search([ - ('invoice_id', '=', copy_invoice_id)]) - invoice_line_obj.unlink(cancel_lines) - invoices_copy[invoice.id] = copy_invoice_id - - # Move the line in the invoice copy - invoice_line.write({'invoice_id': copy_invoice_id}) - - # Compute and cancel invoice copies - cancel_ids = invoices_copy.values() - if cancel_ids: - invoice_obj.button_compute(cancel_ids, set_total=True) - wf_service = netsvc.LocalService('workflow') - for cancel_id in cancel_ids: - wf_service.trg_validate( - self.env.user.id, 'account.invoice', cancel_id, - 'invoice_cancel', self.env.cr) - - self.env.with_context(thread_model='account.invoice') - self.pool.get('mail.thread').message_post( - message, _("Invoice Cancelled"), 'comment') - - return True - - ########################## - # CALLBACKS # - ########################## - @api.onchange('start_date') - def on_change_start_date(self): - """ We automatically update next_invoice_date on start_date change """ - if self.start_date: - self.next_invoice_date = self.start_date - return - - @api.onchange('partner_id') - def on_change_partner_id(self): - """ On partner change, we update the group_id. If partner has - only 1 group, we take it. Else, we take nothing. - """ - group_ids = self.env['recurring.contract.group'].search( - [('partner_id', '=', self.partner_id.id)]) - - self.group_id = None - if len(group_ids) == 1: - self.group_id = group_ids[0] - return - - @api.one - def contract_draft(self): - self.state = 'draft' - return True - - @api.one - def contract_active(self): - self.state = 'active' - return True - - @api.one - def contract_terminated(self): - today = datetime.today().strftime(DF) - self.write({'state': 'terminated', 'end_date': today}) - self.clean_invoices() - return True - - def end_date_reached(self): - today = datetime.today().strftime(DF) - contract_ids = self.search([('state', '=', 'active'), - ('end_date', '<=', today)]) - - if contract_ids: - contract_ids.contract_terminated() - - return True diff --git a/recurring_contract/model/recurring_invoicer.py b/recurring_contract/model/recurring_invoicer.py deleted file mode 100644 index d77417426..000000000 --- a/recurring_contract/model/recurring_invoicer.py +++ /dev/null @@ -1,70 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Copyright (C) 2014 Compassion CH (http://www.compassion.ch) -# Releasing children from poverty in Jesus' name -# @author: Cyril Sester -# -# The licence is in the file __openerp__.py -# -############################################################################## - -from datetime import datetime - -from odoo import api, fields, models -from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DF - -import logging - -logger = logging.getLogger(__name__) - - -class RecurringInvoicer(models.Model): - ''' An invoicer holds a bunch of invoices that have been generated - in the same context. It also makes the validating or cancelling process - of these contracts easy. - ''' - _name = 'recurring.invoicer' - _rec_name = 'identifier' - _order = 'generation_date desc' - - identifier = fields.Char( - required=True, default=lambda self: self.calculate_id()) - source = fields.Char('Source model', required=True) - generation_date = fields.Date(default=datetime.today().strftime(DF)) - invoice_ids = fields.One2many( - 'account.invoice', 'recurring_invoicer_id', - 'Generated invoices') - - def calculate_id(self): - return self.env['ir.sequence'].next_by_code('rec.invoicer.ident') - - @api.multi - def validate_invoices(self): - ''' Validates created invoices (set state from draft to open)''' - self.ensure_one() - invoice_to_validate = self.invoice_ids.filtered( - lambda invoice: invoice.state == 'draft') - - logger.info("Invoice validation started.") - count = 1 - nb_invoice = len(invoice_to_validate) - for invoice in invoice_to_validate: - logger.info("Validating invoice {0}/{1}".format( - count, nb_invoice)) - invoice.action_invoice_open() - # After an invoice is validated, we commit all writes in order to - # avoid doing it again in case of an error or a timeout - self.env.cr.commit() - count += 1 - return invoice_to_validate - - @api.multi - def cancel_invoices(self): - ''' Cancel created invoices (set state from open to cancelled) ''' - invoice_to_cancel = self.mapped('invoice_ids').filtered( - lambda invoice: invoice.state != 'cancel') - - invoice_to_cancel.action_invoice_cancel() - - return True diff --git a/recurring_contract/requirements.txt b/recurring_contract/requirements.txt new file mode 100644 index 000000000..e69de29bb diff --git a/recurring_contract/static/description/index.html b/recurring_contract/static/description/index.html index aa47cec90..729ca40b2 100644 --- a/recurring_contract/static/description/index.html +++ b/recurring_contract/static/description/index.html @@ -8,10 +8,11 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $ +:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $ :Copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. +Despite the name, some widely supported CSS2 features are used. See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to customize this style sheet. @@ -274,7 +275,7 @@ margin-left: 2em ; margin-right: 2em } -pre.code .ln { color: grey; } /* line numbers */ +pre.code .ln { color: gray; } /* line numbers */ pre.code, code { background-color: #eeeeee } pre.code .comment, code .comment { color: #5C6576 } pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } @@ -300,7 +301,7 @@ span.pre { white-space: pre } -span.problematic { +span.problematic, pre.problematic { color: red } span.section-subtitle { @@ -368,7 +369,7 @@

Recurring contract

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:a26bde9147e1bb5f2055b3bd06da9438a1b8c4fbc54582735b56c247532f175e !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Production/Stable License: AGPL-3 CompassionCH/test-repo

+

Production/Stable License: AGPL-3 CompassionCH/compassion-accounting

Recurring contracts are made to handle recurring invoice generation. Each contract is part of a contract group. This way, only one invoice is generated for each group.

@@ -394,10 +395,10 @@

Usage

Bug Tracker

-

Bugs are tracked on GitHub Issues. +

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -feedback.

+feedback.

Do not contact contributors directly about support or help with technical issues.

@@ -419,7 +420,7 @@

Contributors

Maintainers

-

This module is part of the CompassionCH/test-repo project on GitHub.

+

This module is part of the CompassionCH/compassion-accounting project on GitHub.

You are welcome to contribute.

diff --git a/recurring_contract/view/contract_group_view.xml b/recurring_contract/view/contract_group_view.xml deleted file mode 100644 index 0e23dcab2..000000000 --- a/recurring_contract/view/contract_group_view.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - group.contract.form - recurring.contract.group - -
- -

- - - - - - - - - - -

Contracts

- -
-
- - -
-
-
-
-
-
diff --git a/recurring_contract/view/recurring_contract_view.xml b/recurring_contract/view/recurring_contract_view.xml deleted file mode 100644 index c1ff90ba5..000000000 --- a/recurring_contract/view/recurring_contract_view.xml +++ /dev/null @@ -1,145 +0,0 @@ - - - - - - - recurring.contract.tree - recurring.contract - - - - - - - - - - - - - - - - recurring.contract.form - recurring.contract - -
-
- -
- -
-
- -
-

- -

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - -
-
-
-
- - - - recurring.contract.line.tree - recurring.contract.line - - - - - - - - - - - - recurring.contract.select - recurring.contract - - - - - - - - - - - - - - - - - - - - - - - Contracts - ir.actions.act_window - recurring.contract - form - tree,form - -

- Click to add a contract. -

- OpenERP helps you to generate recurrent invoices. -

-
-
- - - -
-
diff --git a/recurring_contract/view/recurring_invoicer_view.xml b/recurring_contract/view/recurring_invoicer_view.xml deleted file mode 100644 index c7802a328..000000000 --- a/recurring_contract/view/recurring_invoicer_view.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - recurring.invoicer.tree - recurring.invoicer - - - - - - - - - - - - - - recurring.invoicer.form - recurring.invoicer - -
-
-
- -
-

- -

-
- -

- - -
-
-
-
- - - - Generated invoices - ir.actions.act_window - recurring.invoicer - form - tree,form - - - -
-
diff --git a/recurring_contract/view/recurring_invoicer_wizard_view.xml b/recurring_contract/view/recurring_invoicer_wizard_view.xml deleted file mode 100644 index 66c7f1157..000000000 --- a/recurring_contract/view/recurring_invoicer_wizard_view.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - Recurring invoicer wizard view - recurring.invoicer.wizard - -
- -
-
- -
-
- - - Automatic invoice generation from contracts - recurring.invoicer.wizard - ir.actions.act_window - form - form - - {} - new - - - -
-
diff --git a/recurring_contract/wizard/__init__.py b/recurring_contract/wizard/__init__.py deleted file mode 100644 index 98feaeb74..000000000 --- a/recurring_contract/wizard/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Copyright (C) 2014 Compassion CH (http://www.compassion.ch) -# Releasing children from poverty in Jesus' name -# @author: Cyril Sester -# -# The licence is in the file __openerp__.py -# -############################################################################## - -from . import recurring_invoicer_wizard diff --git a/recurring_contract/wizard/recurring_invoicer_wizard.py b/recurring_contract/wizard/recurring_invoicer_wizard.py deleted file mode 100644 index ba30eb00e..000000000 --- a/recurring_contract/wizard/recurring_invoicer_wizard.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Copyright (C) 2014 Compassion CH (http://www.compassion.ch) -# Releasing children from poverty in Jesus' name -# @author: Cyril Sester -# -# The licence is in the file __openerp__.py -# -############################################################################## - -from openerp import exceptions, fields, models, api -from openerp.tools.translate import _ - - -class recurring_invoicer_wizard(models.TransientModel): - - ''' This wizard generate invoices from contract groups when launched. - By default, all contract groups are used. - ''' - _name = 'recurring.invoicer.wizard' - - invoice_ids = fields.One2many( - 'account.invoice', 'recurring_invoicer_id', - _('Generated invoices'), readonly=True) - generation_date = fields.Date(_('Generation date'), readonly=True) - - @api.one - def generate(self, *args, **kwargs): - recurring_invoicer_obj = self.env['recurring.invoicer'] - contract_groups = self.env['recurring.contract.group'].search([]) - invoicer = recurring_invoicer_obj.create({'source': self._name}) - - contract_groups.generate_invoices(invoicer) - if not invoicer.invoice_ids: - raise exceptions.Warning('ZeroGenerationError', - _('0 invoices have been generated.')) - - return { - 'name': 'recurring.invoicer.form', - 'view_mode': 'form', - 'view_type': 'form', - 'res_id': invoicer.id, # id of the object to which to redirect - 'res_model': 'recurring.invoicer', # object name - 'type': 'ir.actions.act_window', - } - - @api.model - def generate_from_cron(self, *args, **kwargs): - self.generate() diff --git a/recurring_contract/wizards/__init__.py b/recurring_contract/wizards/__init__.py new file mode 100644 index 000000000..afcc5482d --- /dev/null +++ b/recurring_contract/wizards/__init__.py @@ -0,0 +1,3 @@ +from . import recurring_invoicer_wizard +from . import contract_activation_wizard +from . import end_contract_wizard diff --git a/recurring_contract/workflow/recurring_contract_workflow.xml b/recurring_contract/workflow/recurring_contract_workflow.xml deleted file mode 100644 index 453610363..000000000 --- a/recurring_contract/workflow/recurring_contract_workflow.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - recurring.contract.wkf - recurring.contract - - - - - - - - draft - function - contract_draft() - - - - - active - function - contract_active() - - - - - terminated - function - contract_terminated() - - - - - - - - contract_validated - - - - - - contract_terminated - - - \ No newline at end of file diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 9cd162922..000000000 --- a/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -# generated from manifests external_dependencies