2014-09-17 21:54:48 +02:00
|
|
|
# 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 trytond.pool import PoolMeta, Pool
|
|
|
|
|
from trytond.model import fields
|
|
|
|
|
from trytond.pyson import Eval, If, Bool
|
|
|
|
|
from trytond.transaction import Transaction
|
|
|
|
|
|
2015-01-07 14:56:17 +01:00
|
|
|
__all__ = ['Statement', 'StatementLine']
|
2014-09-17 21:54:48 +02:00
|
|
|
|
|
|
|
|
|
2018-06-26 19:11:43 +02:00
|
|
|
class Statement(metaclass=PoolMeta):
|
2015-01-07 14:56:17 +01:00
|
|
|
__name__ = 'account.statement'
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def create_move(cls, statements):
|
|
|
|
|
pool = Pool()
|
|
|
|
|
MoveLine = pool.get('account.move.line')
|
2016-08-29 09:58:06 +02:00
|
|
|
Payment = pool.get('account.payment')
|
2015-01-07 14:56:17 +01:00
|
|
|
|
|
|
|
|
moves = super(Statement, cls).create_move(statements)
|
|
|
|
|
|
2016-08-29 09:58:06 +02:00
|
|
|
to_success = []
|
2016-10-12 22:38:11 +02:00
|
|
|
to_fail = []
|
2016-08-29 09:58:06 +02:00
|
|
|
for move, statement, lines in moves:
|
|
|
|
|
for line in lines:
|
|
|
|
|
if line.payment:
|
2016-10-12 22:38:11 +02:00
|
|
|
payments = [line.payment]
|
|
|
|
|
kind = line.payment.kind
|
|
|
|
|
elif line.payment_group:
|
|
|
|
|
payments = line.payment_group.payments
|
|
|
|
|
kind = line.payment_group.kind
|
|
|
|
|
else:
|
|
|
|
|
continue
|
|
|
|
|
if (kind == 'receivable') == (line.amount >= 0):
|
|
|
|
|
to_success.extend(payments)
|
|
|
|
|
else:
|
|
|
|
|
to_fail.extend(payments)
|
|
|
|
|
# The failing should be done last because success is usually not a
|
|
|
|
|
# definitive state
|
2016-08-29 09:58:06 +02:00
|
|
|
if to_success:
|
|
|
|
|
Payment.succeed(to_success)
|
2016-10-12 22:38:11 +02:00
|
|
|
if to_fail:
|
|
|
|
|
Payment.fail(to_fail)
|
2016-08-29 09:58:06 +02:00
|
|
|
|
2015-01-07 14:56:17 +01:00
|
|
|
for move, statement, lines in moves:
|
|
|
|
|
assert len({l.payment for l in lines}) == 1
|
|
|
|
|
line = lines[0]
|
|
|
|
|
if line.payment and line.payment.clearing_move:
|
|
|
|
|
clearing_account = line.payment.journal.clearing_account
|
|
|
|
|
if clearing_account.reconcile:
|
|
|
|
|
to_reconcile = []
|
|
|
|
|
for line in move.lines + line.payment.clearing_move.lines:
|
|
|
|
|
if (line.account == clearing_account
|
|
|
|
|
and not line.reconciliation):
|
|
|
|
|
to_reconcile.append(line)
|
|
|
|
|
if not sum((l.debit - l.credit) for l in to_reconcile):
|
|
|
|
|
MoveLine.reconcile(to_reconcile)
|
|
|
|
|
return moves
|
|
|
|
|
|
|
|
|
|
def _group_key(self, line):
|
|
|
|
|
key = super(Statement, self)._group_key(line)
|
|
|
|
|
return key + (('payment', line.payment),)
|
|
|
|
|
|
|
|
|
|
|
2018-06-26 19:11:43 +02:00
|
|
|
class StatementLine(metaclass=PoolMeta):
|
2014-09-17 21:54:48 +02:00
|
|
|
__name__ = 'account.statement.line'
|
|
|
|
|
payment = fields.Many2One('account.payment', 'Payment',
|
|
|
|
|
domain=[
|
|
|
|
|
If(Bool(Eval('party')), [('party', '=', Eval('party'))], []),
|
2016-10-12 22:38:11 +02:00
|
|
|
('state', 'in', ['processing', 'succeeded', 'failed']),
|
2014-09-17 21:54:48 +02:00
|
|
|
],
|
2016-10-12 22:38:11 +02:00
|
|
|
states={
|
|
|
|
|
'invisible': Bool(Eval('payment_group')) | Bool(Eval('invoice')),
|
|
|
|
|
'readonly': Eval('statement_state') != 'draft',
|
|
|
|
|
},
|
|
|
|
|
depends=['party', 'statement_state'])
|
|
|
|
|
payment_group = fields.Many2One(
|
|
|
|
|
'account.payment.group', "Payment Group",
|
|
|
|
|
domain=[
|
2018-12-22 06:34:33 +01:00
|
|
|
('company', '=', Eval('company', -1)),
|
2016-10-12 22:38:11 +02:00
|
|
|
],
|
|
|
|
|
states={
|
|
|
|
|
'invisible': Bool(Eval('payment')) | Bool(Eval('invoice')),
|
|
|
|
|
'readonly': Eval('statement_state') != 'draft',
|
|
|
|
|
},
|
2018-12-22 06:34:33 +01:00
|
|
|
depends=['company', 'statement_state'])
|
2016-10-12 22:38:11 +02:00
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def __setup__(cls):
|
|
|
|
|
super(StatementLine, cls).__setup__()
|
|
|
|
|
invoice_invisible = Bool(Eval('payment')) | Bool(Eval('payment_group'))
|
|
|
|
|
if 'invisible' in cls.invoice.states:
|
|
|
|
|
cls.invoice.states['invisible'] |= invoice_invisible
|
|
|
|
|
else:
|
|
|
|
|
cls.invoice.states['invisible'] = invoice_invisible
|
2014-09-17 21:54:48 +02:00
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def copy(cls, lines, default=None):
|
|
|
|
|
if default is None:
|
|
|
|
|
default = {}
|
2016-10-12 22:38:11 +02:00
|
|
|
else:
|
|
|
|
|
default = default.copy()
|
2014-09-17 21:54:48 +02:00
|
|
|
default.setdefault('payment', None)
|
2018-09-01 01:02:03 +02:00
|
|
|
default.setdefault('payment_group', None)
|
2014-09-17 21:54:48 +02:00
|
|
|
return super(StatementLine, cls).copy(lines, default=default)
|
|
|
|
|
|
2019-01-17 17:22:22 +01:00
|
|
|
@fields.depends('payment', 'party', 'account',
|
|
|
|
|
'statement', '_parent_statement.journal')
|
2014-09-17 21:54:48 +02:00
|
|
|
def on_change_payment(self):
|
|
|
|
|
pool = Pool()
|
|
|
|
|
Currency = pool.get('currency.currency')
|
|
|
|
|
if self.payment:
|
|
|
|
|
if not self.party:
|
2014-10-29 20:39:19 +01:00
|
|
|
self.party = self.payment.party
|
2014-09-17 21:54:48 +02:00
|
|
|
clearing_account = self.payment.journal.clearing_account
|
2016-08-24 11:53:54 +02:00
|
|
|
if not self.account and clearing_account:
|
2014-10-29 20:39:19 +01:00
|
|
|
self.account = clearing_account
|
2014-09-17 21:54:48 +02:00
|
|
|
if self.statement and self.statement.journal:
|
|
|
|
|
with Transaction().set_context(date=self.payment.date):
|
|
|
|
|
amount = Currency.compute(self.payment.currency,
|
|
|
|
|
self.payment.amount, self.statement.journal.currency)
|
2014-10-29 20:39:19 +01:00
|
|
|
self.amount = amount
|
2014-09-17 21:54:48 +02:00
|
|
|
if self.payment.kind == 'payable':
|
2014-10-29 20:39:19 +01:00
|
|
|
self.amount *= -1
|
2014-09-17 21:54:48 +02:00
|
|
|
|
2016-10-12 22:38:11 +02:00
|
|
|
@fields.depends('payment_group', 'account')
|
|
|
|
|
def on_change_payment_group(self):
|
|
|
|
|
if self.payment_group:
|
|
|
|
|
self.party = None
|
|
|
|
|
clearing_account = self.payment_group.journal.clearing_account
|
|
|
|
|
if not self.account and clearing_account:
|
|
|
|
|
self.account = clearing_account
|
|
|
|
|
|
2014-09-17 21:54:48 +02:00
|
|
|
@fields.depends('party', 'payment')
|
|
|
|
|
def on_change_party(self):
|
2014-10-29 20:39:19 +01:00
|
|
|
super(StatementLine, self).on_change_party()
|
2014-09-17 21:54:48 +02:00
|
|
|
if self.payment:
|
|
|
|
|
if self.payment.party != self.party:
|
2014-10-29 20:39:19 +01:00
|
|
|
self.payment = None
|
2016-10-12 22:38:11 +02:00
|
|
|
self.payment_group = None
|
2014-09-17 21:54:48 +02:00
|
|
|
|
2016-10-12 22:38:11 +02:00
|
|
|
@fields.depends('account', 'payment', 'payment_group')
|
2014-09-17 21:54:48 +02:00
|
|
|
def on_change_account(self):
|
2014-10-29 20:39:19 +01:00
|
|
|
super(StatementLine, self).on_change_account()
|
2014-09-17 21:54:48 +02:00
|
|
|
if self.payment:
|
|
|
|
|
clearing_account = self.payment.journal.clearing_account
|
2016-10-12 22:38:11 +02:00
|
|
|
elif self.payment_group:
|
|
|
|
|
clearing_account = self.payment_group.journal.clearing_account
|
|
|
|
|
else:
|
|
|
|
|
return
|
|
|
|
|
if self.account != clearing_account:
|
|
|
|
|
self.payment = None
|
2014-09-17 21:54:48 +02:00
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def post_move(cls, lines):
|
|
|
|
|
pool = Pool()
|
|
|
|
|
Move = pool.get('account.move')
|
|
|
|
|
super(StatementLine, cls).post_move(lines)
|
|
|
|
|
Move.post([l.payment.clearing_move for l in lines
|
2018-01-12 12:59:50 +01:00
|
|
|
if l.payment
|
|
|
|
|
and l.payment.clearing_move
|
|
|
|
|
and l.payment.clearing_move.state == 'draft'])
|
2019-01-17 17:34:50 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class StatementRuleLine(metaclass=PoolMeta):
|
|
|
|
|
__name__ = 'account.statement.rule.line'
|
|
|
|
|
|
|
|
|
|
def get_line(self, origin, keywords, **context):
|
|
|
|
|
line = super().get_line(origin, keywords, **context)
|
|
|
|
|
if line:
|
|
|
|
|
line.payment = self._get_payment(origin, keywords)
|
|
|
|
|
if (line.payment and line.party
|
|
|
|
|
and line.payment.party != line.party):
|
|
|
|
|
return
|
|
|
|
|
line.payment_group = self._get_payment_group(origin, keywords)
|
|
|
|
|
return line
|
|
|
|
|
|
|
|
|
|
def _get_payment(self, origin, keywords):
|
|
|
|
|
pool = Pool()
|
|
|
|
|
Payment = pool.get('account.payment')
|
|
|
|
|
if keywords.get('payment'):
|
|
|
|
|
payments = Payment.search([('rec_name', '=', keywords['payment'])])
|
|
|
|
|
if len(payments) == 1:
|
|
|
|
|
payment, = payments
|
|
|
|
|
return payment
|
|
|
|
|
|
|
|
|
|
def _get_payment_group(self, origin, keywords):
|
|
|
|
|
pool = Pool()
|
|
|
|
|
Payment = pool.get('account.payment.group')
|
|
|
|
|
if keywords.get('payment_group'):
|
|
|
|
|
groups, = Payment.search(
|
|
|
|
|
[('rec_name', '=', keywords['payment_group'])])
|
|
|
|
|
if len(groups) == 1:
|
|
|
|
|
group, = groups
|
|
|
|
|
return group
|