mirror of
https://github.com/OCA/bank-payment.git
synced 2025-02-02 10:37:31 +02:00
[ADD] Foreporting crude support for full payment workflow including
transferral move that pays the invoices
This commit is contained in:
@@ -810,6 +810,12 @@ class banking_import_transaction(orm.Model):
|
||||
move_info['invoice_ids'][0]
|
||||
)
|
||||
return vals
|
||||
|
||||
def hook_match_payment(self, cr, uid, transaction, log, context=None):
|
||||
"""
|
||||
To override in module 'account_banking_payment'
|
||||
"""
|
||||
return False
|
||||
|
||||
def match(self, cr, uid, ids, results=None, context=None):
|
||||
if not ids:
|
||||
@@ -1020,13 +1026,13 @@ class banking_import_transaction(orm.Model):
|
||||
), context=context)
|
||||
# rebrowse the current record after writing
|
||||
transaction = self.browse(cr, uid, transaction.id, context=context)
|
||||
# Match full direct debit orders
|
||||
if transaction.type == bt.DIRECT_DEBIT and has_payment:
|
||||
move_info = self._match_debit_order(
|
||||
cr, uid, transaction, results['log'], context)
|
||||
if transaction.type == bt.STORNO and has_payment:
|
||||
move_info = self._match_storno(
|
||||
cr, uid, transaction, results['log'], context)
|
||||
|
||||
# Match payment and direct debit orders
|
||||
move_info_payment = hook_match_payment(
|
||||
cr, uid, transaction, results['log'], context=context)
|
||||
if move_info_payment:
|
||||
move_info = move_info_payment
|
||||
|
||||
# Allow inclusion of generated bank invoices
|
||||
if transaction.type == bt.BANK_COSTS:
|
||||
lines = self._match_costs(
|
||||
|
||||
@@ -45,6 +45,7 @@ As a counter measure, all imported data is converted to SWIFT-format before usag
|
||||
from account_banking.parsers import models
|
||||
from account_banking.parsers.convert import str2date, to_swift
|
||||
from tools.translate import _
|
||||
import re
|
||||
import csv
|
||||
|
||||
bt = models.mem_bank_transaction
|
||||
@@ -105,6 +106,13 @@ class transaction_message(object):
|
||||
self.date = str2date(self.date, '%Y%m%d')
|
||||
if self.direction == 'A':
|
||||
self.transferred_amount = -float(self.transferred_amount)
|
||||
if (self.transfer_type == 'VZ'
|
||||
and (not self.remote_account or self.remote_account == '0')
|
||||
and (not self.message or re.match('^\s*$', self.message))
|
||||
and self.remote_owner.startswith('TOTAAL ')):
|
||||
self.transfer_type = 'PB'
|
||||
self.message = self.remote_owner
|
||||
self.remove_owner = False
|
||||
else:
|
||||
self.transferred_amount = float(self.transferred_amount)
|
||||
self.local_account = self.local_account.zfill(10)
|
||||
@@ -140,7 +148,8 @@ class transaction(models.mem_bank_transaction):
|
||||
'GT': bt.ORDER,
|
||||
'IC': bt.DIRECT_DEBIT,
|
||||
'OV': bt.ORDER,
|
||||
'VZ': bt.PAYMENT_BATCH,
|
||||
'VZ': bt.ORDER,
|
||||
'PB': bt.PAYMENT_BATCH,
|
||||
}
|
||||
|
||||
def __init__(self, line, *args, **kwargs):
|
||||
@@ -171,11 +180,14 @@ class transaction(models.mem_bank_transaction):
|
||||
4. Cash withdrawals from banks are too not seen as a transfer between
|
||||
two accounts - the cash exits the banking system. These withdrawals
|
||||
have their transfer_type set to 'GM'.
|
||||
5. Aggregated payment batches. These transactions have transfer type
|
||||
'VZ' natively but are changed to 'PB' while parsing. These transactions
|
||||
have no remote account.
|
||||
'''
|
||||
return bool(self.transferred_amount and self.execution_date and (
|
||||
self.remote_account or
|
||||
self.transfer_type in [
|
||||
'DV', 'BT', 'BA', 'GM',
|
||||
'DV', 'PB', 'BT', 'BA', 'GM',
|
||||
]))
|
||||
|
||||
def refold_message(self, message):
|
||||
|
||||
@@ -32,24 +32,30 @@ from openerp.addons.decimal_precision import decimal_precision as dp
|
||||
class banking_import_transaction(orm.Model):
|
||||
_inherit = 'banking.import.transaction'
|
||||
|
||||
def _match_debit_order(
|
||||
self, cr, uid, trans, log, context=None):
|
||||
def _match_payment_order(
|
||||
self, cr, uid, trans, log, order_type='payment', context=None):
|
||||
|
||||
def is_zero(total):
|
||||
def equals_order_amount(payment_order, transferred_amount):
|
||||
if (not hasattr(payment_order, 'payment_order_type')
|
||||
or payment_order.payment_order_type == 'payment'):
|
||||
sign = 1
|
||||
else:
|
||||
sign = -1
|
||||
total = payment_order.total + sign * transferred_amount
|
||||
return self.pool.get('res.currency').is_zero(
|
||||
cr, uid, trans.statement_id.currency, total)
|
||||
|
||||
payment_order_obj = self.pool.get('payment.order')
|
||||
|
||||
order_ids = payment_order_obj.search(
|
||||
cr, uid, [('payment_order_type', '=', 'debit'),
|
||||
cr, uid, [('payment_order_type', '=', order_type),
|
||||
('state', '=', 'sent'),
|
||||
('date_sent', '<=', trans.execution_date),
|
||||
],
|
||||
limit=0, context=context)
|
||||
orders = payment_order_obj.browse(cr, uid, order_ids, context)
|
||||
candidates = [x for x in orders if
|
||||
is_zero(x.total - trans.transferred_amount)]
|
||||
equals_order_amount(x.total - trans.transferred_amount)]
|
||||
if len(candidates) > 0:
|
||||
# retrieve the common account_id, if any
|
||||
account_id = False
|
||||
@@ -170,10 +176,6 @@ class banking_import_transaction(orm.Model):
|
||||
raise orm.except_orm(
|
||||
_("Cannot reconcile"),
|
||||
_("Cannot reconcile: no direct debit order"))
|
||||
if transaction.payment_order_id.payment_order_type != 'debit':
|
||||
raise orm.except_orm(
|
||||
_("Cannot reconcile"),
|
||||
_("Reconcile payment order not implemented"))
|
||||
reconcile_id = payment_order_obj.debit_reconcile_transfer(
|
||||
cr, uid,
|
||||
transaction.payment_order_id.id,
|
||||
@@ -231,11 +233,7 @@ class banking_import_transaction(orm.Model):
|
||||
if not transaction.payment_order_id:
|
||||
raise orm.except_orm(
|
||||
_("Cannot unreconcile"),
|
||||
_("Cannot unreconcile: no direct debit order"))
|
||||
if transaction.payment_order_id.payment_order_type != 'debit':
|
||||
raise orm.except_orm(
|
||||
_("Cannot unreconcile"),
|
||||
_("Unreconcile payment order not implemented"))
|
||||
_("Cannot unreconcile: no payment or direct debit order"))
|
||||
return payment_order_obj.debit_unreconcile_transfer(
|
||||
cr, uid, transaction.payment_order_id.id,
|
||||
transaction.statement_line_id.reconcile_id.id,
|
||||
@@ -355,11 +353,25 @@ class banking_import_transaction(orm.Model):
|
||||
)
|
||||
return vals
|
||||
|
||||
def match(self, cr, uid, ids, results=None, context=None):
|
||||
res = super(banking_import_transaction, self).match(
|
||||
cr, uid, ids, results=results, context=context)
|
||||
|
||||
return res
|
||||
def hook_match_payment(cr, uid, transaction, log, context=None):
|
||||
"""
|
||||
Called from match() in the core module.
|
||||
Match payment batches, direct debit orders and stornos
|
||||
"""
|
||||
move_info = False
|
||||
if transaction.type == bt.PAYMENT_BATCH:
|
||||
move_info = self._match_payment_order(
|
||||
cr, uid, transaction, log,
|
||||
order_type='payment', context=context)
|
||||
elif transaction.type == bt.DIRECT_DEBIT:
|
||||
move_info = self._match_payment_order(
|
||||
cr, uid, transaction, log,
|
||||
order_type='debit', context=context)
|
||||
elif transaction.type == bt.STORNO:
|
||||
move_info = self._match_storno(
|
||||
cr, uid, transaction, log,
|
||||
context=context)
|
||||
return move_info
|
||||
|
||||
def __init__(self, pool, cr):
|
||||
"""
|
||||
|
||||
@@ -102,7 +102,7 @@ class payment_order(osv.osv):
|
||||
if not wkf_ok:
|
||||
raise osv.except_osv(
|
||||
_("Cannot unreconcile"),
|
||||
_("Cannot unreconcile debit order: "+
|
||||
_("Cannot unreconcile payment order: "+
|
||||
"Workflow will not allow it."))
|
||||
return True
|
||||
|
||||
@@ -119,7 +119,7 @@ class payment_order(osv.osv):
|
||||
return False
|
||||
else:
|
||||
# TODO: define conditions for 'payment' orders
|
||||
return False
|
||||
return True
|
||||
return True
|
||||
|
||||
def action_sent(self, cr, uid, ids, context=None):
|
||||
@@ -135,8 +135,6 @@ class payment_order(osv.osv):
|
||||
account_move_line_obj = self.pool.get('account.move.line')
|
||||
payment_line_obj = self.pool.get('payment.line')
|
||||
for order in self.browse(cr, uid, ids, context=context):
|
||||
if order.payment_order_type != 'debit':
|
||||
continue
|
||||
for line in order.line_ids:
|
||||
# basic checks
|
||||
if not line.move_line_id:
|
||||
@@ -152,23 +150,28 @@ class payment_order(osv.osv):
|
||||
|
||||
move_id = account_move_obj.create(cr, uid, {
|
||||
'journal_id': order.mode.transfer_journal_id.id,
|
||||
'name': 'Debit order %s' % line.move_line_id.move_id.name,
|
||||
'reference': 'DEB%s' % line.move_line_id.move_id.name,
|
||||
'name': '%s order %s' % (order.payment_order_type,
|
||||
line.move_line_id.move_id.name),
|
||||
'reference': '%s%s' % (order.payment_order_type[:3].upper(),
|
||||
line.move_line_id.move_id.name),
|
||||
}, context=context)
|
||||
|
||||
# TODO: take multicurrency into account
|
||||
|
||||
# create the debit move line on the transfer account
|
||||
vals = {
|
||||
'name': 'Debit order for %s' % (
|
||||
'name': '%s order for %s' % (
|
||||
order.payment_order_type,
|
||||
line.move_line_id.invoice and
|
||||
line.move_line_id.invoice.number or
|
||||
line.move_line_id.name),
|
||||
'move_id': move_id,
|
||||
'partner_id': line.partner_id.id,
|
||||
'account_id': order.mode.transfer_account_id.id,
|
||||
'credit': 0.0,
|
||||
'debit': line.amount,
|
||||
'credit': (order.payment_order_type == 'payment'
|
||||
and line.amount or 0.0),
|
||||
'debit': (order.payment_order_type == 'debit'
|
||||
and line.amount or 0.0),
|
||||
'date': time.strftime('%Y-%m-%d'),
|
||||
}
|
||||
transfer_move_line_id = account_move_line_obj.create(
|
||||
@@ -177,8 +180,10 @@ class payment_order(osv.osv):
|
||||
# create the debit move line on the receivable account
|
||||
vals.update({
|
||||
'account_id': line.move_line_id.account_id.id,
|
||||
'credit': line.amount,
|
||||
'debit': 0.0,
|
||||
'credit': (order.payment_order_type == 'debit'
|
||||
and line.amount or 0.0),
|
||||
'debit': (order.payment_order_type == 'payment'
|
||||
and line.amount or 0.0),
|
||||
})
|
||||
reconcile_move_line_id = account_move_line_obj.create(
|
||||
cr, uid, vals, context=context)
|
||||
|
||||
Reference in New Issue
Block a user