diff --git a/CHANGELOG b/CHANGELOG
index 3fd5710bf7..ed1b73a35f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,4 @@
+* Allow to block payment of line
* Ask payment journal for each currency
* Decrease amount to pay of invoice
* Add group Payment Approval
diff --git a/account.py b/account.py
index 8d4cccd3dd..0ec9557791 100644
--- a/account.py
+++ b/account.py
@@ -44,6 +44,7 @@ class MoveLine:
(None, ''),
] + KINDS, 'Payment Kind'), 'get_payment_kind',
searcher='search_payment_kind')
+ payment_blocked = fields.Boolean('Blocked', readonly=True)
@classmethod
def __setup__(cls):
@@ -52,7 +53,14 @@ class MoveLine:
'pay': {
'invisible': ~Eval('payment_kind').in_(dict(KINDS).keys()),
},
+ 'payment_block': {
+ 'invisible': Eval('payment_blocked', False),
+ },
+ 'payment_unblock': {
+ 'invisible': ~Eval('payment_blocked', False),
+ },
})
+ cls._check_modify_exclude.add('payment_blocked')
@classmethod
def get_payment_amount(cls, lines, name):
@@ -108,6 +116,10 @@ class MoveLine:
def search_payment_kind(cls, name, clause):
return [('account.kind',) + tuple(clause[1:])]
+ @classmethod
+ def default_payment_blocked(cls):
+ return False
+
@classmethod
def copy(cls, lines, default=None):
if default is None:
@@ -122,6 +134,27 @@ class MoveLine:
def pay(cls, lines):
pass
+ @classmethod
+ @ModelView.button
+ def payment_block(cls, lines):
+ pool = Pool()
+ Payment = pool.get('account.payment')
+
+ cls.write(lines, {
+ 'payment_blocked': True,
+ })
+ draft_payments = [p for l in lines for p in l.payments
+ if p.state == 'draft']
+ if draft_payments:
+ Payment.delete(draft_payments)
+
+ @classmethod
+ @ModelView.button
+ def payment_unblock(cls, lines):
+ cls.write(lines, {
+ 'payment_blocked': False,
+ })
+
class PayLineAskJournal(ModelView):
'Pay Line'
@@ -150,6 +183,13 @@ class PayLine(Wizard):
])
pay = StateAction('account_payment.act_payment_form')
+ @classmethod
+ def __setup__(cls):
+ super(PayLine, cls).__setup__()
+ cls._error_messages.update({
+ 'blocked': 'The Line "%(line)s" is blocked.',
+ })
+
def _get_journals(self):
journals = {}
for journal in getattr(self.ask_journal, 'journals', []):
@@ -225,6 +265,11 @@ class PayLine(Wizard):
payments = []
for line in lines:
+ if line.payment_blocked:
+ self.raise_user_warning('blocked:%s' % line,
+ 'blocked', {
+ 'line': line.rec_name,
+ })
payments.append(self.get_payment(line, journals))
Payment.save(payments)
return action, {
diff --git a/account.xml b/account.xml
index 1c18d49683..9b7b1a5895 100644
--- a/account.xml
+++ b/account.xml
@@ -17,6 +17,8 @@ this repository contains the full copyright notices and license terms. -->
+
@@ -82,6 +84,26 @@ this repository contains the full copyright notices and license terms. -->
+
+ payment_block
+
+
+
+
+
+
+
+
+ payment_unblock
+
+
+
+
+
+
+
diff --git a/tests/scenario_account_payment.rst b/tests/scenario_account_payment.rst
index 3e92180df8..61bda8f8de 100644
--- a/tests/scenario_account_payment.rst
+++ b/tests/scenario_account_payment.rst
@@ -106,3 +106,27 @@ Partially fail to pay the remaining::
>>> line.reload()
>>> line.payment_amount
Decimal('30.00')
+
+Pay line and block it after::
+
+ >>> move, = move.duplicate()
+ >>> move.click('post')
+ >>> line, = [l for l in move.lines if l.account == payable]
+ >>> pay_line = Wizard('account.move.line.pay', [line])
+ >>> pay_line.form.journal = payment_journal
+ >>> pay_line.execute('start')
+ >>> len(line.payments)
+ 1
+
+ >>> line.click('payment_block')
+ >>> len(line.payments)
+ 0
+
+Try to pay blocked line::
+
+ >>> pay_line = Wizard('account.move.line.pay', [line])
+ >>> pay_line.form.journal = payment_journal
+ >>> pay_line.execute('start') # doctest: +IGNORE_EXCEPTION_DETAIL
+ Traceback (most recent call last):
+ ...
+ UserWarning: ...
diff --git a/view/move_line_list.xml b/view/move_line_list.xml
index dfb67bb960..848d905a2b 100644
--- a/view/move_line_list.xml
+++ b/view/move_line_list.xml
@@ -13,6 +13,9 @@ this repository contains the full copyright notices and license terms. -->
+
+
+