Warn when cancelling, grouping, rescheduling or delegating move line with payment

This commit is contained in:
Cédric Krier
2023-09-08 20:52:32 +02:00
parent 8cf114cc27
commit 42c9ffb209
6 changed files with 251 additions and 0 deletions
+12
View File
@@ -97,9 +97,21 @@ class GroupLineError(UserError):
pass
class GroupLineWarning(UserWarning):
pass
class RescheduleLineError(UserError):
pass
class RescheduleLineWarning(UserWarning):
pass
class DelegateLineError(UserError):
pass
class DelegateLineWarning(UserWarning):
pass
+1
View File
@@ -1,3 +1,4 @@
* Warn when cancelling, grouping, rescheduling or delegating move line with payment
* Mark Payment as succeeded or failed when imported in statement
* Add pay buttons on invoice lines to pay
+4
View File
@@ -34,6 +34,10 @@ def register():
payment.ProcessPayment,
account.CreateDirectDebit,
account.PayLine,
account.MoveCancel,
account.MoveLineGroup,
account.MoveLineReschedule,
account.MoveLineDelegate,
party.Replace,
party.Erase,
module='account_payment', type_='wizard')
+101
View File
@@ -12,6 +12,9 @@ from sql.functions import Abs
from trytond.i18n import gettext
from trytond.model import ModelSQL, ModelView, fields
from trytond.modules.account.exceptions import (
CancelWarning, DelegateLineWarning, GroupLineWarning,
RescheduleLineWarning)
from trytond.modules.company.model import CompanyValueMixin
from trytond.modules.currency.fields import Monetary
from trytond.pool import Pool, PoolMeta
@@ -487,6 +490,104 @@ class ConfigurationPaymentGroupSequence(ModelSQL, CompanyValueMixin):
return None
class MoveCancel(metaclass=PoolMeta):
__name__ = 'account.move.cancel'
def transition_cancel(self):
pool = Pool()
Warning = pool.get('res.user.warning')
moves_w_payments = []
for move in self.records:
for line in move.lines:
if any(p.state != 'failed' for p in line.payments):
moves_w_payments.append(move)
break
if moves_w_payments:
names = ', '.join(
m.rec_name for m in moves_w_payments[:5])
if len(moves_w_payments) > 5:
names += '...'
key = Warning.format('cancel_payments', moves_w_payments)
if Warning.check(key):
raise CancelWarning(
key, gettext(
'account_payment.msg_move_cancel_payments',
moves=names))
return super().transition_cancel()
class MoveLineGroup(metaclass=PoolMeta):
__name__ = 'account.move.line.group'
def do_group(self, action):
pool = Pool()
Warning = pool.get('res.user.warning')
lines_w_payments = []
for line in self.records:
if any(p.state != 'failed' for p in line.payments):
lines_w_payments.append(line)
if lines_w_payments:
names = ', '.join(
m.rec_name for m in lines_w_payments[:5])
if len(lines_w_payments) > 5:
names += '...'
key = Warning.format('group_payments', lines_w_payments)
if Warning.check(key):
raise GroupLineWarning(
key, gettext(
'account_payment.msg_move_line_group_payments',
lines=names))
return super().do_group(action)
class MoveLineReschedule(metaclass=PoolMeta):
__name__ = 'account.move.line.reschedule'
def do_reschedule(self, action):
pool = Pool()
Warning = pool.get('res.user.warning')
lines_w_payments = []
for line in self.records:
if any(p.state != 'failed' for p in line.payments):
lines_w_payments.append(line)
if lines_w_payments:
names = ', '.join(
m.rec_name for m in lines_w_payments[:5])
if len(lines_w_payments) > 5:
names += '...'
key = Warning.format('reschedule_payments', lines_w_payments)
if Warning.check(key):
raise RescheduleLineWarning(
key, gettext(
'account_payment.msg_move_line_reschedule_payments',
lines=names))
return super().do_reschedule(action)
class MoveLineDelegate(metaclass=PoolMeta):
__name__ = 'account.move.line.delegate'
def do_delegate(self, action):
pool = Pool()
Warning = pool.get('res.user.warning')
lines_w_payments = []
for line in self.records:
if any(p.state != 'failed' for p in line.payments):
lines_w_payments.append(line)
if lines_w_payments:
names = ', '.join(
m.rec_name for m in lines_w_payments[:5])
if len(lines_w_payments) > 5:
names += '...'
key = Warning.format('delegate_payments', lines_w_payments)
if Warning.check(key):
raise DelegateLineWarning(
key, gettext(
'account_payment.msg_move_line_delegate_payments',
lines=names))
return super().do_delegate(action)
class Invoice(metaclass=PoolMeta):
__name__ = 'account.invoice'
+12
View File
@@ -18,5 +18,17 @@ this repository contains the full copyright notices and license terms. -->
<record model="ir.message" id="msg_pay_line_group">
<field name="text">The lines "%(names)s" for %(party)s could be grouped with the line "%(line)s".</field>
</record>
<record model="ir.message" id="msg_move_cancel_payments">
<field name="text">The moves "%(moves)s" contain lines with payments, you may want to cancel them before cancelling.</field>
</record>
<record model="ir.message" id="msg_move_line_group_payments">
<field name="text">The lines "%(lines)s" have payments, you may want to cancel them before grouping.</field>
</record>
<record model="ir.message" id="msg_move_line_reschedule_payments">
<field name="text">The lines "%(lines)s" have payments, you may want to cancel them before rescheduling.</field>
</record>
<record model="ir.message" id="msg_move_line_delegate_payments">
<field name="text">The lines "%(lines)s" have payments, you may want to cancel them before delegating.</field>
</record>
</data>
</tryton>
@@ -0,0 +1,121 @@
=================================
Account Payment Warnings Scenario
=================================
Imports::
>>> from decimal import Decimal
>>> import datetime as dt
>>> from proteus import Model, Wizard
>>> from trytond.tests.tools import activate_modules
>>> from trytond.modules.company.tests.tools import (
... create_company, get_company)
>>> from trytond.modules.account.tests.tools import (
... create_fiscalyear, create_chart, get_accounts)
>>> today = dt.date.today()
Activate modules::
>>> config = activate_modules('account_payment')
>>> Journal = Model.get('account.journal')
>>> Move = Model.get('account.move')
>>> Party = Model.get('party.party')
>>> Payment = Model.get('account.payment')
>>> PaymentJournal = Model.get('account.payment.journal')
Create company::
>>> _ = create_company()
>>> company = get_company()
Create fiscal year::
>>> fiscalyear = create_fiscalyear(company)
>>> fiscalyear.click('create_period')
Create chart of accounts::
>>> _ = create_chart(company)
>>> accounts = get_accounts(company)
>>> expense_journal, = Journal.find([('code', '=', 'EXP')])
Create payment journal::
>>> payment_journal = PaymentJournal(
... name="Manual", process_method='manual')
>>> payment_journal.save()
Create parties::
>>> supplier = Party(name="Supplier")
>>> supplier.save()
>>> supplier2 = Party(name="Supplier 2")
>>> supplier2.save()
Create receivable moves::
>>> move = Move()
>>> move.journal = expense_journal
>>> line = move.lines.new(
... account=accounts['payable'], party=supplier, maturity_date=today,
... credit=Decimal('100.00'))
>>> line = move.lines.new(
... account=accounts['expense'],
... debit=Decimal('100.00'))
>>> move.click('post')
>>> move.state
'posted'
>>> move2, = move.duplicate()
>>> move2.click('post')
Pay line::
>>> line, = [l for l in move.lines if l.account == accounts['payable']]
>>> pay_line = Wizard('account.move.line.pay', [line])
>>> pay_line.form.date = today
>>> pay_line.execute('next_')
>>> pay_line.execute('next_')
>>> payment, = Payment.find()
Try to cancel move::
>>> cancel_move = Wizard('account.move.cancel', [move])
>>> cancel_move.execute('cancel') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
CancelWarning: ...
Try to group lines::
>>> line2, = [l for l in move2.lines if l.account == accounts['payable']]
>>> group_line = Wizard('account.move.line.group', [line, line2])
>>> group_line.execute('group') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
GroupLineWarning: ...
Try to reschedule line::
>>> reschedule_line = Wizard('account.move.line.reschedule', [line])
>>> reschedule_line.form.start_date = today
>>> reschedule_line.form.frequency = 'monthly'
>>> reschedule_line.form.interval = 1
>>> reschedule_line.form.amount = Decimal('50.00')
>>> reschedule_line.execute('preview')
>>> reschedule_line.execute('reschedule') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
RescheduleLineWarning: ...
Try to delegate line::
>>> delegate_line = Wizard('account.move.line.delegate', [line])
>>> delegate_line.form.party = supplier2
>>> delegate_line.execute('delegate') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
DelegateLineWarning: ...