mirror of
https://github.com/OCA/bank-payment.git
synced 2025-02-02 10:37:31 +02:00
@@ -199,7 +199,7 @@ class TestSCT(common.HttpCase):
|
||||
debtor_acc_xpath[0].text,
|
||||
self.payment_order.company_partner_bank_id.sanitized_acc_number)
|
||||
self.payment_order.generated2uploaded()
|
||||
self.assertEqual(self.payment_order.state, 'uploaded')
|
||||
self.assertEqual(self.payment_order.state, 'done')
|
||||
for inv in [invoice1, invoice2, invoice3, invoice4, invoice5]:
|
||||
self.assertEqual(inv.state, 'paid')
|
||||
return
|
||||
@@ -276,7 +276,7 @@ class TestSCT(common.HttpCase):
|
||||
debtor_acc_xpath[0].text,
|
||||
self.payment_order.company_partner_bank_id.sanitized_acc_number)
|
||||
self.payment_order.generated2uploaded()
|
||||
self.assertEqual(self.payment_order.state, 'uploaded')
|
||||
self.assertEqual(self.payment_order.state, 'done')
|
||||
for inv in [invoice1, invoice2]:
|
||||
self.assertEqual(inv.state, 'paid')
|
||||
return
|
||||
|
||||
@@ -209,7 +209,7 @@ class TestSDD(common.HttpCase):
|
||||
debtor_acc_xpath[0].text,
|
||||
payment_order.company_partner_bank_id.sanitized_acc_number)
|
||||
payment_order.generated2uploaded()
|
||||
self.assertEqual(payment_order.state, 'uploaded')
|
||||
self.assertEqual(payment_order.state, 'done')
|
||||
for inv in [invoice1, invoice2]:
|
||||
self.assertEqual(inv.state, 'paid')
|
||||
self.assertEqual(self.mandate2.recurrent_sequence_type, 'recurring')
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
{
|
||||
'name': 'Account Payment Order',
|
||||
'version': '12.0.1.6.3',
|
||||
'version': '12.0.2.0.0',
|
||||
'license': 'AGPL-3',
|
||||
'author': "ACSONE SA/NV, "
|
||||
"Therp BV, "
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copyright 2021 Hunki Enterprises BV
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from openupgradelib import openupgrade
|
||||
|
||||
|
||||
@openupgrade.migrate()
|
||||
def migrate(env, version):
|
||||
for order in env['account.payment.order'].search([
|
||||
('state', '=', 'uploaded'),
|
||||
]):
|
||||
if order._all_lines_reconciled():
|
||||
order.action_done()
|
||||
@@ -148,3 +148,37 @@ class AccountMoveLine(models.Model):
|
||||
)
|
||||
result.update(arch=arch, fields=fields)
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def reconcile(self, writeoff_acc_id=False, writeoff_journal_id=False):
|
||||
""" Set payment orders with fully reconciled lines to done """
|
||||
result = super().reconcile(
|
||||
writeoff_acc_id=writeoff_acc_id,
|
||||
writeoff_journal_id=writeoff_journal_id,
|
||||
)
|
||||
if not self.env.context.get('account_payment_order_defer_close'):
|
||||
self.filtered('full_reconcile_id')._close_payment_orders()
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def _close_payment_orders(self):
|
||||
"""
|
||||
Set payment orders linked to move lines in self to done if all
|
||||
of them are reconciled
|
||||
"""
|
||||
for order in self._find_payment_orders():
|
||||
if order.state != 'done' and order._all_lines_reconciled():
|
||||
order.action_done()
|
||||
|
||||
@api.multi
|
||||
def _find_payment_orders(self):
|
||||
"""
|
||||
Return all payment orders linked (directly by payment_line_ids
|
||||
or indirectly by reconciliation with a transfer account) to self
|
||||
"""
|
||||
return self.mapped(
|
||||
'move_id.line_ids.bank_payment_line_id.order_id'
|
||||
) | self.mapped(
|
||||
'full_reconcile_id.reconciled_line_ids.move_id.line_ids.'
|
||||
'bank_payment_line_id.order_id'
|
||||
)
|
||||
|
||||
@@ -114,7 +114,7 @@ class AccountPaymentOrder(models.Model):
|
||||
@api.multi
|
||||
def unlink(self):
|
||||
for order in self:
|
||||
if order.state == 'uploaded':
|
||||
if order.state in ('uploaded', 'done'):
|
||||
raise UserError(_(
|
||||
"You cannot delete an uploaded payment order. You can "
|
||||
"cancel it in order to do so."))
|
||||
@@ -359,13 +359,13 @@ class AccountPaymentOrder(models.Model):
|
||||
|
||||
@api.multi
|
||||
def generated2uploaded(self):
|
||||
for order in self:
|
||||
if order.payment_mode_id.generate_move:
|
||||
order.generate_move()
|
||||
self.write({
|
||||
'state': 'uploaded',
|
||||
'date_uploaded': fields.Date.context_today(self),
|
||||
})
|
||||
for order in self:
|
||||
if order.payment_mode_id.generate_move:
|
||||
order.generate_move()
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
@@ -514,3 +514,18 @@ class AccountPaymentOrder(models.Model):
|
||||
trfmoves = self._prepare_trf_moves()
|
||||
for hashcode, blines in trfmoves.items():
|
||||
self._create_reconcile_move(hashcode, blines)
|
||||
|
||||
@api.multi
|
||||
def _all_lines_reconciled(self):
|
||||
"""
|
||||
Return true if all payment lines' counterpart lines are reconciled too
|
||||
Also return true if the counterpart account cannot be reconciled
|
||||
"""
|
||||
self.ensure_one()
|
||||
move_lines = self.env['account.move.line'].search([(
|
||||
'bank_payment_line_id', 'in', self.mapped('bank_line_ids').ids
|
||||
)]).mapped('move_id.line_ids')
|
||||
return bool(move_lines) and all(
|
||||
move_line.reconciled for move_line in move_lines
|
||||
if move_line.account_id.reconcile
|
||||
)
|
||||
|
||||
@@ -163,7 +163,7 @@ class BankPaymentLine(models.Model):
|
||||
def unlink(self):
|
||||
for line in self:
|
||||
order_state = line.order_id.state
|
||||
if order_state == 'uploaded':
|
||||
if order_state in ('uploaded', 'done'):
|
||||
raise UserError(_(
|
||||
'Cannot delete a payment order line whose payment order is'
|
||||
' in state \'%s\'. You need to cancel it first.')
|
||||
|
||||
@@ -109,7 +109,7 @@ class TestPaymentOrderInbound(TestPaymentOrderInboundBase):
|
||||
payment_order.open2generated()
|
||||
payment_order.generated2uploaded()
|
||||
|
||||
self.assertEqual(payment_order.state, 'uploaded')
|
||||
self.assertEqual(payment_order.state, 'done')
|
||||
with self.assertRaises(UserError):
|
||||
payment_order.unlink()
|
||||
|
||||
|
||||
@@ -145,6 +145,7 @@ class TestPaymentOrderOutbound(SavepointCase):
|
||||
order.generated2uploaded()
|
||||
order.action_done()
|
||||
self.assertEqual(order.state, 'done')
|
||||
return order
|
||||
|
||||
def test_cancel_payment_order(self):
|
||||
# Open invoice
|
||||
@@ -176,7 +177,7 @@ class TestPaymentOrderOutbound(SavepointCase):
|
||||
payment_order.open2generated()
|
||||
payment_order.generated2uploaded()
|
||||
|
||||
self.assertEqual(payment_order.state, 'uploaded')
|
||||
self.assertEqual(payment_order.state, 'done')
|
||||
with self.assertRaises(UserError):
|
||||
payment_order.unlink()
|
||||
|
||||
@@ -201,3 +202,57 @@ class TestPaymentOrderOutbound(SavepointCase):
|
||||
with self.assertRaises(ValidationError):
|
||||
outbound_order.date_scheduled = date.today() - timedelta(
|
||||
days=1)
|
||||
|
||||
def test_reconciliation_full(self):
|
||||
self.mode.write({
|
||||
'bank_account_link': 'fixed',
|
||||
'default_date_prefered': 'fixed',
|
||||
'fixed_journal_id': self.bank_journal.id,
|
||||
})
|
||||
self.bank_journal.default_debit_account_id.reconcile = True
|
||||
|
||||
order_full = self.order_creation('fixed')
|
||||
order_full.write({'state': 'uploaded'})
|
||||
self.reconcile_order_lines(order_full)
|
||||
self.assertEqual(order_full.state, 'done')
|
||||
|
||||
def test_reconciliation_partial(self):
|
||||
self.mode.write({
|
||||
'bank_account_link': 'fixed',
|
||||
'default_date_prefered': 'fixed',
|
||||
'fixed_journal_id': self.bank_journal.id,
|
||||
})
|
||||
self.bank_journal.default_debit_account_id.reconcile = True
|
||||
|
||||
order_partial = self.order_creation('fixed')
|
||||
order_partial.write({'state': 'uploaded'})
|
||||
self.reconcile_order_lines(order_partial, .9)
|
||||
self.assertEqual(order_partial.state, 'uploaded')
|
||||
|
||||
def reconcile_order_lines(self, order, factor=1):
|
||||
to_reconcile = self.env['account.move.line'].search([
|
||||
('bank_payment_line_id', 'in', order.mapped('bank_line_ids').ids)
|
||||
]).mapped('move_id.line_ids').filtered(lambda x: not x.reconciled)
|
||||
for move_line in to_reconcile[:]:
|
||||
move = self.env['account.move'].create({
|
||||
'name': 'payment',
|
||||
'date': move_line.date,
|
||||
'journal_id': self.bank_journal.id,
|
||||
'line_ids': [
|
||||
(0, 0, dict(
|
||||
credit=move_line.credit * factor,
|
||||
debit=move_line.debit * factor,
|
||||
account_id=move_line.account_id.id,
|
||||
)),
|
||||
(0, 0, dict(
|
||||
credit=move_line.debit * factor,
|
||||
debit=move_line.credit * factor,
|
||||
account_id=move_line.account_id.id,
|
||||
)),
|
||||
],
|
||||
})
|
||||
to_reconcile += move.line_ids.filtered(
|
||||
lambda x: x.credit != move_line.credit
|
||||
)
|
||||
to_reconcile.reconcile()
|
||||
return to_reconcile
|
||||
|
||||
@@ -21,8 +21,11 @@
|
||||
string="Back to Draft" />
|
||||
<button name="action_cancel" type="object" states="draft,open,generated"
|
||||
string="Cancel Payments"/>
|
||||
<button name="action_done_cancel" type="object" states="uploaded"
|
||||
<button name="action_done_cancel" type="object" states="uploaded,done"
|
||||
string="Cancel Payments"/>
|
||||
<button name="action_done" type="object" states="uploaded"
|
||||
string="Set Done"
|
||||
/>
|
||||
<field name="state" widget="statusbar"/>
|
||||
</header>
|
||||
<sheet>
|
||||
|
||||
Reference in New Issue
Block a user