From adedae3bc2f34abb3e6b4cc8bb15523754970e43 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Thu, 24 Sep 2015 10:00:45 +0200 Subject: [PATCH] Remove storno, which seems specific to one particular country. --- .../model/payment_line.py | 46 ----- account_direct_debit/README.rst | 13 +- account_direct_debit/__openerp__.py | 1 - account_direct_debit/models/__init__.py | 4 +- .../models/account_invoice.py | 165 ------------------ .../models/account_payment.py | 19 -- account_direct_debit/models/payment_line.py | 126 +------------ .../views/account_payment.xml | 12 -- .../workflow/account_invoice.xml | 51 ------ 9 files changed, 8 insertions(+), 429 deletions(-) delete mode 100644 account_direct_debit/models/account_invoice.py delete mode 100644 account_direct_debit/models/account_payment.py delete mode 100644 account_direct_debit/workflow/account_invoice.xml diff --git a/account_banking_payment_transfer/model/payment_line.py b/account_banking_payment_transfer/model/payment_line.py index 2eed8de85..76262a4b3 100644 --- a/account_banking_payment_transfer/model/payment_line.py +++ b/account_banking_payment_transfer/model/payment_line.py @@ -37,45 +37,6 @@ class PaymentLine(models.Model): msg = fields.Char('Message', required=False, readonly=True, default='') date_done = fields.Date('Date Confirmed', select=True, readonly=True) - """ - Hooks for processing direct debit orders, such as implemented in - account_direct_debit module. - """ - @api.multi - def get_storno_account_id(self, amount, currency_id): - """ - Hook for verifying a match of the payment line with the amount. - Return the account associated with the storno. - Used in account_banking interactive mode - :param payment_line_id: the single payment line id - :param amount: the (signed) amount debited from the bank account - :param currency: the bank account's currency *browse object* - :return: an account if there is a full match, False otherwise - :rtype: database id of an account.account resource. - """ - - return False - - @api.multi - def debit_storno(self, amount, currency_id, storno_retry=True): - """ - Hook for handling a canceled item of a direct debit order. - Presumably called from a bank statement import routine. - - Decide on the direction that the invoice's workflow needs to take. - You may optionally return an incomplete reconcile for the caller - to reconcile the now void payment. - - :param payment_line_id: the single payment line id - :param amount: the (negative) amount debited from the bank account - :param currency: the bank account's currency *browse object* - :param boolean storno_retry: whether the storno is considered fatal \ - or not. - :return: an incomplete reconcile for the caller to fill - :rtype: database id of an account.move.reconcile resource. - """ - - return False class BankPaymentLine(models.Model): @@ -137,10 +98,3 @@ class BankPaymentLine(models.Model): lines_to_rec += payment_line.move_line_id lines_to_rec.reconcile_partial(type='auto') - - # If a bank transaction of a storno was first confirmed - # and now canceled (the invoice is now in state 'debit_denied' -# if torec_move_line.invoice: -# workflow.trg_validate( -# self.env.uid, 'account.invoice', torec_move_line.invoice.id, -# 'undo_debit_denied', self.env.cr) diff --git a/account_direct_debit/README.rst b/account_direct_debit/README.rst index 1d82305be..337f4a7ad 100644 --- a/account_direct_debit/README.rst +++ b/account_direct_debit/README.rst @@ -8,11 +8,8 @@ This module adds support for direct debit orders, analogous to payment orders. A new entry in the Accounting/Payment menu allow you to create a direct debit order that helps you to select any customer invoices for you to collect. -This module explicitely implements direct debit orders as applicable -in the Netherlands. Debit orders are advanced in total by the bank. -Amounts that cannot be debited or are canceled by account owners are -credited afterwards. Such a creditation is called a storno. This style of -direct debit order may not apply to your country. +Debit orders are advanced in total by the bank. Amounts that cannot be +debited or are canceled by account owners are credited afterwards. Installation ============ @@ -25,12 +22,12 @@ This module is part of the OCA/bank-payment suite. Configuration ============= -Please refer to module "Account Banking SEPA Direct Debit" +Please refer to module *Account Banking SEPA Direct Debit* Usage ===== -Please refer to module "Account Banking SEPA Direct Debit" +Please refer to module *Account Banking SEPA Direct Debit* For further information, please visit: @@ -58,7 +55,7 @@ Contributors * Stefan Rijnhart * Pedro M. Baeza -* Alexis de Lattre +* Alexis de Lattre * Danimar Ribeiro * Stéphane Bidoul * Alexandre Fayolle diff --git a/account_direct_debit/__openerp__.py b/account_direct_debit/__openerp__.py index 790dd0896..ace7cda3d 100644 --- a/account_direct_debit/__openerp__.py +++ b/account_direct_debit/__openerp__.py @@ -33,7 +33,6 @@ 'views/account_invoice.xml', 'views/payment_mode.xml', 'views/payment_mode_type.xml', - 'workflow/account_invoice.xml', 'data/account_payment_term.xml', 'data/payment_mode_type.xml' ], diff --git a/account_direct_debit/models/__init__.py b/account_direct_debit/models/__init__.py index ffb948151..cb28fc53b 100644 --- a/account_direct_debit/models/__init__.py +++ b/account_direct_debit/models/__init__.py @@ -1,4 +1,4 @@ -from . import account_payment +# -*- coding: utf-8 -*- + from . import payment_line from . import account_move_line -from . import account_invoice diff --git a/account_direct_debit/models/account_invoice.py b/account_direct_debit/models/account_invoice.py deleted file mode 100644 index 66c30ac53..000000000 --- a/account_direct_debit/models/account_invoice.py +++ /dev/null @@ -1,165 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# Copyright (C) 2011 - 2013 Therp BV (). -# -# All other contributions are (C) by their respective contributors -# -# All Rights Reserved -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -""" -This module adds support for Direct debit orders as applicable -in the Netherlands. Debit orders are advanced in total by the bank. -Amounts that cannot be debited or are canceled by account owners are -credited afterwards. Such a creditation is called a storno. - -Invoice workflow: - -1 the sale leads to - 1300 Debtors 100 - 8000 Sales 100 - -Balance: - Debtors 2000 | - Sales | 2000 - -2 an external booking takes place - 1100 Bank 100 - 1300 Debtors 100 - This booking is reconciled with [1] - The invoice gets set to state 'paid', and 'reconciled' = True - -Balance: - Debtors 1900 | - Bank 100 | - Sales | 2000 - -This module implements the following diversion: - -2a the invoice is included in a direct debit order. When the order is - confirmed, a move is created per invoice: - - 2000 Transfer account 100 | - 1300 Debtors | 100 - Reconciliation takes place between 1 and 2a. - The invoice gets set to state 'paid', and 'reconciled' = True - -Balance: - Debtors 0 | - Transfer account 2000 | - Bank 0 | - Sales | 2000 - -3a the direct debit order is booked on the bank account - -Balance: - 1100 Bank 2000 | - 2000 Transfer account | 2000 - Reconciliation takes place between 3a and 2a - -Balance: - Debtors 0 | - Transfer account 0 | - Bank 2000 | - Sales | 2000 - -4 a storno from invoice [1] triggers a new booking on the bank account - 1300 Debtors 100 | - 1100 Bank | 100 - -Balance: - Debtors 100 | - Transfer account 0 | - Bank 1900 | - Sales | 2000 - - The reconciliation of 2a is undone. The booking of 2a is reconciled - with the booking of 4 instead. - The payment line attribute 'storno' is set to True and the invoice - state is no longer 'paid'. - -Two cases need to be distinguisted: - 1) If the storno is a manual storno from the partner, the invoice is set to - state 'debit_denied', with 'reconciled' = False - This module implements this option by allowing the bank module to call - - netsvc.LocalService("workflow").trg_validate( - uid, 'account.invoice', ids, 'debit_denied', cr) - - 2) If the storno is an error generated by the bank (assumingly non-fatal), - the invoice is reopened for the next debit run. This is a call to - existing - - netsvc.LocalService("workflow").trg_validate( - uid, 'account.invoice', ids, 'open_test', cr) - - Should also be adding a log entry on the invoice for tracing purposes - - self._log_event(cr, uid, ids, -1.0, 'Debit denied') - - If not for that funny comment - "#TODO: implement messages system" in account/invoice.py - - Repeating non-fatal fatal errors need to be dealt with manually by checking - open invoices with a matured invoice- or due date. -""" - -from openerp.osv import orm -from openerp.tools.translate import _ - - -class AccountInvoice(orm.Model): - _inherit = "account.invoice" - - def _register_hook(self, cr): - """ - Adding a state to the hardcoded state list of the inherited - model. The alternative is duplicating the field definition - in columns but only one module can do that! - - Maybe apply a similar trick when overriding the buttons' 'states' - attributes in the form view, manipulating the xml in fields_view_get(). - """ - self._columns['state'].selection.append( - ('debit_denied', 'Debit denied')) - return super(AccountInvoice, self)._register_hook(cr) - - def action_debit_denied(self, cr, uid, ids, context=None): - for invoice_id in ids: - if self.test_paid(cr, uid, [invoice_id], context): - number = self.read( - cr, uid, invoice_id, ['number'], context=context)['number'] - raise orm.except_orm( - _('Error !'), - _("You cannot set invoice '%s' to state 'debit " - "denied', as it is still reconciled.") % number) - self.write(cr, uid, ids, {'state': 'debit_denied'}, context=context) - for inv_id, name in self.name_get(cr, uid, ids, context=context): - message = _("Invoice '%s': direct debit is denied.") % name - self.log(cr, uid, inv_id, message) - return True - - def test_undo_debit_denied(self, cr, uid, ids, context=None): - """ - Called from the workflow. Used to unset paid state on - invoices that were paid with bank transfers which are being cancelled - """ - for invoice in self.read(cr, uid, ids, ['reconciled'], context): - if not invoice['reconciled']: - return False - return True diff --git a/account_direct_debit/models/account_payment.py b/account_direct_debit/models/account_payment.py deleted file mode 100644 index 702477107..000000000 --- a/account_direct_debit/models/account_payment.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -from openerp.osv import orm - - -class PaymentOrder(orm.Model): - _inherit = 'payment.order' - - def test_undo_done(self, cr, uid, ids, context=None): - """Called from the workflow. Used to unset done state on - payment orders that were reconciled with bank transfers - which are being cancelled - """ - for order in self.browse(cr, uid, ids, context=context): - if order.payment_order_type == 'debit': - for line in order.line_ids: - if line.storno: - return False - return super(PaymentOrder, self).test_undo_done( - cr, uid, ids, context=context) diff --git a/account_direct_debit/models/payment_line.py b/account_direct_debit/models/payment_line.py index 4fc667daf..120a41145 100644 --- a/account_direct_debit/models/payment_line.py +++ b/account_direct_debit/models/payment_line.py @@ -1,134 +1,10 @@ # -*- coding: utf-8 -*- -from openerp import api, exceptions, models, fields, _, workflow +from openerp import models, fields class PaymentLine(models.Model): _inherit = 'payment.line' - @api.multi - def debit_storno(self, amount, currency, storno_retry=True): - """The processing of a storno is triggered by a debit - transfer on one of the company's bank accounts. - This method offers to re-reconcile the original debit - payment. For this purpose, we have registered that - payment move on the payment line. - - Return the (now incomplete) reconcile id. The caller MUST - re-reconcile this reconcile with the bank transfer and - re-open the associated invoice. - - :param payment_line_id: the single payment line id - :param amount: the (signed) amount debited from the bank account - :param currency: the bank account's currency *browse object* - :param boolean storno_retry: when True, attempt to reopen the invoice, - set the invoice to 'Debit denied' otherwise. - :return: an incomplete reconcile for the caller to fill - :rtype: database id of an account.move.reconcile resource. - """ - self.ensure_one() - reconcile_obj = self.env['account.move.reconcile'] - line = self - reconcile = reconcile_obj.browse([]) - if (line.transit_move_line_id and not line.storno and - self.env['res.currency'].is_zero( - currency, ( - (line.transit_move_line_id.credit or 0.0) - - (line.transit_move_line_id.debit or 0.0) + amount))): - # Two different cases, full and partial - # Both cases differ subtly in the procedure to follow - # Needs refractoring, but why is this not in the OpenERP API? - # Actually, given the nature of a direct debit order and storno, - # we should not need to take partial into account on the side of - # the transit_move_line. - if line.transit_move_line_id.reconcile_partial_id: - reconcile_partial = \ - line.transit_move_line_id.reconcile_partial_id - reconcile = line.transit_move_line_id.reconcile_id - if len(reconcile.line_partial_ids) == 2: - # reuse the simple reconcile for the storno transfer - reconcile_partial.write({ - 'line_id': [(6, 0, line.transit_move_line_id.id)], - 'line_partial_ids': [(6, 0, [])] - }) - else: - # split up the original reconcile in a partial one - # and a new one for reconciling the storno transfer - reconcile_partial.write({ - 'line_partial_ids': [(3, line.transit_move_line_id.id)] - }) - reconcile = reconcile_obj.create({ - 'type': 'auto', - 'line_id': [(6, 0, line.transit_move_line_id.id)] - }) - elif line.transit_move_line_id.reconcile_id: - reconcile = line.transit_move_line_id.reconcile_id - if len(line.transit_move_line_id.reconcile_id.line_id) == 2: - # reuse the simple reconcile for the storno transfer - reconcile.write({ - 'line_id': [(6, 0, [line.transit_move_line_id.id])], - }) - else: - # split up the original reconcile in a partial one - # and a new one for reconciling the storno transfer - reconcile = line.transit_move_line_id.reconcile_id - partial_ids = [x.id for x in reconcile.line_id - if x.id != line.transit_move_line_id.id] - reconcile.write({ - 'line_partial_ids': [(6, 0, partial_ids)], - 'line_id': [(6, 0, [])], - }) - reconcile = reconcile_obj.create({ - 'type': 'auto', - 'line_id': [(6, 0, line.transit_move_line_id.id)] - }) - # mark the payment line for storno processed - if reconcile: - self.write({'storno': True}) - # put forth the invoice workflow - if line.move_line_id.invoice: - activity = (storno_retry and 'open_test' or - 'invoice_debit_denied') - workflow.trg_validate( - self.env.uid, 'account.invoice', - line.move_line_id.invoice.id, activity, self.env.cr) - return reconcile.id - - @api.multi - def get_storno_account_id(self, amount, currency): - """Check the match of the arguments, and return the account associated - with the storno. - Used in account_banking interactive mode - - :param payment_line_id: the single payment line id - :param amount: the (signed) amount debited from the bank account - :param currency: the bank account's currency *browse object* - :return: an account if there is a full match, False otherwise - :rtype: database id of an account.account resource. - """ - self.ensure_one() - account_id = False - if (self.transit_move_line_id and not self.storno and - self.env['res.currency'].is_zero( - currency, ( - (self.transit_move_line_id.credit or 0.0) - - (self.transit_move_line_id.debit or 0.0) + amount))): - account_id = self.transit_move_line_id.account_id.id - return account_id - - @api.one - def debit_reconcile(self): - """Raise if a payment line is passed for which storno is True.""" - if self.storno: - raise exceptions.except_orm( - _('Can not reconcile'), - _('Cancelation of payment line \'%s\' has already been ' - 'processed') % self.name) - return super(PaymentLine, self).debit_reconcile() - - storno = fields.Boolean( - 'Storno', readonly=True, - help="If this is true, the debit order has been canceled by the bank " - "or by the customer") # The original string is "Destination Bank Account"... # but in direct debit this field is the *Source* Bank Account ! bank_id = fields.Many2one(string='Partner Bank Account') diff --git a/account_direct_debit/views/account_payment.xml b/account_direct_debit/views/account_payment.xml index 016b4bc71..3b0977577 100644 --- a/account_direct_debit/views/account_payment.xml +++ b/account_direct_debit/views/account_payment.xml @@ -47,17 +47,5 @@ - - Payment Lines - payment.line - - - - - - - - - diff --git a/account_direct_debit/workflow/account_invoice.xml b/account_direct_debit/workflow/account_invoice.xml deleted file mode 100644 index d3099e85d..000000000 --- a/account_direct_debit/workflow/account_invoice.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - debit_denied - action_debit_denied() - function - - - - - - - invoice_debit_denied - - - - - - test_undo_debit_denied() - undo_debit_denied - - - - - - open_test - - -