Indeed the counterpart of the clearing move should be the bank party but we do not have access to this information. issue4225 review11521002
144 lines
5.3 KiB
Python
144 lines
5.3 KiB
Python
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
|
# this repository contains the full copyright notices and license terms.
|
|
from collections import defaultdict
|
|
from decimal import Decimal
|
|
|
|
from trytond.pool import PoolMeta, Pool
|
|
from trytond.model import ModelView, Workflow, fields
|
|
from trytond.pyson import Eval, Bool
|
|
|
|
__all__ = ['Journal', 'Payment']
|
|
__metaclass__ = PoolMeta
|
|
|
|
|
|
class Journal:
|
|
__name__ = 'account.payment.journal'
|
|
clearing_account = fields.Many2One('account.account', 'Clearing Account',
|
|
domain=[('party_required', '=', False)],
|
|
states={
|
|
'required': Bool(Eval('clearing_journal')),
|
|
},
|
|
depends=['clearing_journal'])
|
|
clearing_journal = fields.Many2One('account.journal', 'Clearing Journal',
|
|
states={
|
|
'required': Bool(Eval('clearing_account')),
|
|
},
|
|
depends=['clearing_account'])
|
|
|
|
|
|
class Payment:
|
|
__name__ = 'account.payment'
|
|
clearing_move = fields.Many2One('account.move', 'Clearing Move',
|
|
readonly=True)
|
|
|
|
@classmethod
|
|
@ModelView.button
|
|
@Workflow.transition('succeeded')
|
|
def succeed(cls, payments):
|
|
pool = Pool()
|
|
Move = pool.get('account.move')
|
|
Line = pool.get('account.move.line')
|
|
|
|
super(Payment, cls).succeed(payments)
|
|
|
|
moves = []
|
|
for payment in payments:
|
|
move = payment.create_clearing_move()
|
|
if move:
|
|
moves.append(move)
|
|
if moves:
|
|
Move.save(moves)
|
|
cls.write(*sum((([m.origin], {'clearing_move': m.id})
|
|
for m in moves), ()))
|
|
|
|
to_reconcile = defaultdict(list)
|
|
for payment in payments:
|
|
if (payment.line
|
|
and not payment.line.reconciliation
|
|
and payment.clearing_move):
|
|
lines = [l for l in payment.clearing_move.lines
|
|
if l.account == payment.line.account] + [payment.line]
|
|
if not sum(l.debit - l.credit for l in lines):
|
|
to_reconcile[payment.party].extend(lines)
|
|
for lines in to_reconcile.itervalues():
|
|
Line.reconcile(lines)
|
|
|
|
def create_clearing_move(self, date=None):
|
|
pool = Pool()
|
|
Move = pool.get('account.move')
|
|
Line = pool.get('account.move.line')
|
|
Period = pool.get('account.period')
|
|
Date = pool.get('ir.date')
|
|
|
|
if not self.line:
|
|
return
|
|
if (not self.journal.clearing_account
|
|
or not self.journal.clearing_journal):
|
|
return
|
|
if self.clearing_move:
|
|
return self.clearing_move
|
|
|
|
if date is None:
|
|
date = Date.today()
|
|
period = Period.find(self.company.id, date=date)
|
|
|
|
move = Move(journal=self.journal.clearing_journal, origin=self,
|
|
date=date, period=period)
|
|
line = Line()
|
|
line.debit = self.amount if self.line.credit else Decimal(0)
|
|
line.credit = self.amount if self.line.debit else Decimal(0)
|
|
line.account = self.line.account
|
|
line.amount_second_currency = (-self.line.amount_second_currency
|
|
if self.line.amount_second_currency else None)
|
|
line.second_currency = self.line.second_currency
|
|
line.party = (self.line.party
|
|
if self.line.account.party_required else None)
|
|
counterpart = Line()
|
|
counterpart.debit = self.amount if self.line.debit else Decimal(0)
|
|
counterpart.credit = self.amount if self.line.credit else Decimal(0)
|
|
counterpart.account = self.journal.clearing_account
|
|
counterpart.amount_second_currency = self.line.amount_second_currency
|
|
counterpart.second_currency = self.line.second_currency
|
|
move.lines = (line, counterpart)
|
|
return move
|
|
|
|
@classmethod
|
|
@ModelView.button
|
|
@Workflow.transition('failed')
|
|
def fail(cls, payments):
|
|
pool = Pool()
|
|
Move = pool.get('account.move')
|
|
Line = pool.get('account.move.line')
|
|
Reconciliation = pool.get('account.move.reconciliation')
|
|
|
|
super(Payment, cls).fail(payments)
|
|
|
|
to_delete = []
|
|
to_reconcile = defaultdict(lambda: defaultdict(list))
|
|
to_unreconcile = []
|
|
for payment in payments:
|
|
if payment.clearing_move:
|
|
if payment.clearing_move.state == 'draft':
|
|
to_delete.append(payment.clearing_move)
|
|
for line in payment.clearing_move.lines:
|
|
if line.reconciliation:
|
|
to_unreconcile.append(line.reconciliation)
|
|
else:
|
|
cancel_move = payment.clearing_move.cancel()
|
|
for line in (payment.clearing_move.lines
|
|
+ cancel_move.lines):
|
|
if line.reconciliation:
|
|
to_unreconcile.append(line.reconciliation)
|
|
if line.account.reconcile:
|
|
to_reconcile[payment.party][line.account].append(
|
|
line)
|
|
if to_unreconcile:
|
|
Reconciliation.delete(to_unreconcile)
|
|
if to_delete:
|
|
Move.delete(to_delete)
|
|
for party in to_reconcile:
|
|
for lines in to_reconcile[party].itervalues():
|
|
Line.reconcile(lines)
|
|
|
|
cls.write(payments, {'clearing_move': None})
|