Warn when cancelling, grouping, rescheduling or delegating move line with payment
This commit is contained in:
@@ -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,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
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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: ...
|
||||
Reference in New Issue
Block a user