Files
bank-payment/account_direct_debit/models/payment_line.py
Stéphane Bidoul 77753a3392 [FIX] flake8 W503
2015-02-27 16:17:24 +01:00

146 lines
7.1 KiB
Python

# -*- coding: utf-8 -*-
from openerp.osv import orm, fields
from openerp import netsvc
from openerp.tools.translate import _
class PaymentLine(orm.Model):
_inherit = 'payment.line'
def debit_storno(self, cr, uid, payment_line_id, amount,
currency, storno_retry=True, context=None):
"""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.
"""
reconcile_obj = self.pool.get('account.move.reconcile')
line = self.browse(cr, uid, payment_line_id)
reconcile_id = False
if (line.transit_move_line_id and not line.storno and
self.pool.get('res.currency').is_zero(
cr, uid, 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_id = \
line.transit_move_line_id.reconcile_partial_id.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_obj.write(
cr, uid, reconcile_id,
{'line_id': [(6, 0, line.transit_move_line_id.id)],
'line_partial_ids': [(6, 0, [])]}, context=context)
else:
# split up the original reconcile in a partial one
# and a new one for reconciling the storno transfer
reconcile = {
'line_partial_ids': [(3, line.transit_move_line_id.id)]
}
reconcile_obj.write(
cr, uid, reconcile_id, reconcile, context=context)
reconcile_id = reconcile_obj.create(
cr, uid,
{'type': 'auto',
'line_id': [(6, 0, line.transit_move_line_id.id)]},
context=context)
elif line.transit_move_line_id.reconcile_id:
reconcile_id = line.transit_move_line_id.reconcile_id.id
if len(line.transit_move_line_id.reconcile_id.line_id) == 2:
# reuse the simple reconcile for the storno transfer
reconcile_obj.write(
cr, uid, reconcile_id,
{'line_id': [(6, 0, [line.transit_move_line_id.id])]},
context=context)
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_obj.write(
cr, uid, reconcile_id,
{'line_partial_ids': [(6, 0, partial_ids)],
'line_id': [(6, 0, [])]}, context=context)
reconcile_id = reconcile_obj.create(
cr, uid,
{'type': 'auto',
'line_id': [(6, 0, line.transit_move_line_id.id)]},
context=context)
# mark the payment line for storno processed
if reconcile_id:
self.write(cr, uid, [payment_line_id],
{'storno': True}, context=context)
# put forth the invoice workflow
if line.move_line_id.invoice:
activity = (storno_retry and 'open_test' or
'invoice_debit_denied')
netsvc.LocalService("workflow").trg_validate(
uid, 'account.invoice', line.move_line_id.invoice.id,
activity, cr)
return reconcile_id
def get_storno_account_id(
self, cr, uid, payment_line_id, amount, currency, context=None):
"""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.
"""
line = self.browse(cr, uid, payment_line_id)
account_id = False
if (line.transit_move_line_id and not line.storno and
self.pool.get('res.currency').is_zero(
cr, uid, currency, (
(line.transit_move_line_id.credit or 0.0) -
(line.transit_move_line_id.debit or 0.0) + amount))):
account_id = line.transit_move_line_id.account_id.id
return account_id
def debit_reconcile(self, cr, uid, payment_line_id, context=None):
"""Raise if a payment line is passed for which storno is True."""
if isinstance(payment_line_id, (list, tuple)):
payment_line_id = payment_line_id[0]
payment_line_vals = self.read(
cr, uid, payment_line_id, ['storno', 'name'], context=context)
if payment_line_vals['storno']:
raise orm.except_orm(
_('Can not reconcile'),
_('Cancelation of payment line \'%s\' has already been '
'processed') % payment_line_vals['name'])
return super(PaymentLine, self).debit_reconcile(
cr, uid, payment_line_id, context=context)
_columns = {
'storno': fields.boolean(
'Storno',
readonly=True,
help=("If this is true, the debit order has been canceled "
"by the bank or by the customer")),
}