mirror of
https://github.com/OCA/bank-payment.git
synced 2025-02-02 10:37:31 +02:00
132 lines
6.2 KiB
Python
132 lines
6.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
from openerp import api, exceptions, models, fields, _, workflow
|
|
|
|
|
|
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")
|