Merge PR #860 into 12.0

Signed-off-by pedrobaeza
This commit is contained in:
OCA-git-bot
2021-10-11 13:58:16 +00:00
10 changed files with 132 additions and 12 deletions

View File

@@ -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

View File

@@ -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')

View File

@@ -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, "

View File

@@ -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()

View File

@@ -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'
)

View File

@@ -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
)

View File

@@ -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.')

View File

@@ -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()

View File

@@ -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

View File

@@ -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>