[IMP] account_mass_reconcile: Add 'oldest move line' option on reconcile option
parent
2491f49914
commit
957c7e2ccd
|
@ -128,6 +128,9 @@ class MassReconcileBase(models.AbstractModel):
|
|||
def last_date(mlines):
|
||||
return max(mlines, key=itemgetter("date"))
|
||||
|
||||
def oldest_date(mlines):
|
||||
return min(mlines, key=itemgetter("date"))
|
||||
|
||||
def credit(mlines):
|
||||
return [line for line in mlines if line["credit"] > 0]
|
||||
|
||||
|
@ -136,6 +139,8 @@ class MassReconcileBase(models.AbstractModel):
|
|||
|
||||
if based_on == "newest":
|
||||
return last_date(lines)["date"]
|
||||
elif based_on == "oldest":
|
||||
return oldest_date(lines)["date"]
|
||||
elif based_on == "newest_credit":
|
||||
return last_date(credit(lines))["date"]
|
||||
elif based_on == "newest_debit":
|
||||
|
|
|
@ -28,7 +28,11 @@ class MassReconcileOptions(models.AbstractModel):
|
|||
|
||||
@api.model
|
||||
def _get_rec_base_date(self):
|
||||
return [("newest", "Most recent move line"), ("actual", "Today")]
|
||||
return [
|
||||
("newest", "Most recent move line"),
|
||||
("actual", "Today"),
|
||||
("oldest", "Oldest move line"),
|
||||
]
|
||||
|
||||
write_off = fields.Float("Write off allowed", default=0.0)
|
||||
account_lost_id = fields.Many2one("account.account", string="Account Lost")
|
||||
|
|
|
@ -58,7 +58,12 @@ class MassReconcileSimple(models.AbstractModel):
|
|||
return res
|
||||
|
||||
def _simple_order(self, *args, **kwargs):
|
||||
return "ORDER BY account_move_line.%s" % self._key_field
|
||||
ret = "ORDER BY account_move_line.%s" % self._key_field
|
||||
if self.date_base_on == "oldest":
|
||||
ret += ", date"
|
||||
elif self.date_base_on == "newest":
|
||||
ret += ", date desc"
|
||||
return ret
|
||||
|
||||
def _action_rec(self):
|
||||
"""Match only 2 move lines, do not allow partial reconcile"""
|
||||
|
|
|
@ -15,4 +15,7 @@ in order to provide:
|
|||
in this module, the simple reconciliations works
|
||||
on 2 lines (1 debit / 1 credit) and do not allow
|
||||
partial reconciliation, they also match on 1 key,
|
||||
partner or Journal item name.
|
||||
partner or Journal item name. There is also an
|
||||
option for 'most recent move line' or
|
||||
'oldest move line' which is used to choose the
|
||||
move to be reconciled if more than one is found.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# © 2014-2016 Camptocamp SA (Damien Crier)
|
||||
# © 2023 FactorLibre - Aritz Olea <aritz.olea@factorlibre.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from datetime import timedelta
|
||||
|
@ -67,6 +68,124 @@ class TestScenarioReconcile(TestAccountReconciliationCommon):
|
|||
mass_rec.run_reconcile()
|
||||
self.assertEqual("paid", invoice.payment_state)
|
||||
|
||||
def test_scenario_reconcile_newest(self):
|
||||
invoice = self.create_invoice()
|
||||
self.assertEqual("posted", invoice.state)
|
||||
|
||||
receivalble_account_id = invoice.partner_id.property_account_receivable_id.id
|
||||
# create payments
|
||||
payment_old = self.env["account.payment"].create(
|
||||
{
|
||||
"partner_type": "customer",
|
||||
"payment_type": "inbound",
|
||||
"partner_id": invoice.partner_id.id,
|
||||
"destination_account_id": receivalble_account_id,
|
||||
"amount": 50.0,
|
||||
"journal_id": self.bank_journal.id,
|
||||
"date": fields.Date.from_string("2023-10-01"),
|
||||
}
|
||||
)
|
||||
payment_new = self.env["account.payment"].create(
|
||||
{
|
||||
"partner_type": "customer",
|
||||
"payment_type": "inbound",
|
||||
"partner_id": invoice.partner_id.id,
|
||||
"destination_account_id": receivalble_account_id,
|
||||
"amount": 50.0,
|
||||
"journal_id": self.bank_journal.id,
|
||||
"date": fields.Date.from_string("2023-10-20"),
|
||||
}
|
||||
)
|
||||
payment_old.action_post()
|
||||
payment_new.action_post()
|
||||
|
||||
# create the mass reconcile record
|
||||
mass_rec = self.mass_rec_obj.create(
|
||||
{
|
||||
"name": "mass_reconcile_1",
|
||||
"account": invoice.partner_id.property_account_receivable_id.id,
|
||||
"reconcile_method": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"name": "mass.reconcile.simple.partner",
|
||||
"date_base_on": "newest",
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
)
|
||||
# call the automatic reconciliation method
|
||||
mass_rec.run_reconcile()
|
||||
self.assertEqual("paid", invoice.payment_state)
|
||||
self.assertTrue(mass_rec.last_history)
|
||||
payment_new_line = payment_new.move_id.line_ids.filtered(lambda l: l.credit)
|
||||
payment_old_line = payment_old.move_id.line_ids.filtered(lambda l: l.credit)
|
||||
self.assertTrue(payment_new_line in mass_rec.last_history.reconcile_line_ids)
|
||||
self.assertTrue(payment_new_line.reconciled)
|
||||
self.assertFalse(payment_old_line in mass_rec.last_history.reconcile_line_ids)
|
||||
self.assertFalse(payment_old_line.reconciled)
|
||||
|
||||
def test_scenario_reconcile_oldest(self):
|
||||
invoice = self.create_invoice()
|
||||
self.assertEqual("posted", invoice.state)
|
||||
|
||||
receivalble_account_id = invoice.partner_id.property_account_receivable_id.id
|
||||
# create payments
|
||||
payment_old = self.env["account.payment"].create(
|
||||
{
|
||||
"partner_type": "customer",
|
||||
"payment_type": "inbound",
|
||||
"partner_id": invoice.partner_id.id,
|
||||
"destination_account_id": receivalble_account_id,
|
||||
"amount": 50.0,
|
||||
"journal_id": self.bank_journal.id,
|
||||
"date": fields.Date.from_string("2023-10-01"),
|
||||
}
|
||||
)
|
||||
payment_new = self.env["account.payment"].create(
|
||||
{
|
||||
"partner_type": "customer",
|
||||
"payment_type": "inbound",
|
||||
"partner_id": invoice.partner_id.id,
|
||||
"destination_account_id": receivalble_account_id,
|
||||
"amount": 50.0,
|
||||
"journal_id": self.bank_journal.id,
|
||||
"date": fields.Date.from_string("2023-10-20"),
|
||||
}
|
||||
)
|
||||
payment_old.action_post()
|
||||
payment_new.action_post()
|
||||
|
||||
# create the mass reconcile record
|
||||
mass_rec = self.mass_rec_obj.create(
|
||||
{
|
||||
"name": "mass_reconcile_1",
|
||||
"account": invoice.partner_id.property_account_receivable_id.id,
|
||||
"reconcile_method": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"name": "mass.reconcile.simple.partner",
|
||||
"date_base_on": "oldest",
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
)
|
||||
# call the automatic reconciliation method
|
||||
mass_rec.run_reconcile()
|
||||
self.assertEqual("paid", invoice.payment_state)
|
||||
self.assertTrue(mass_rec.last_history)
|
||||
payment_new_line = payment_new.move_id.line_ids.filtered(lambda l: l.credit)
|
||||
payment_old_line = payment_old.move_id.line_ids.filtered(lambda l: l.credit)
|
||||
self.assertFalse(payment_new_line in mass_rec.last_history.reconcile_line_ids)
|
||||
self.assertFalse(payment_new_line.reconciled)
|
||||
self.assertTrue(payment_old_line in mass_rec.last_history.reconcile_line_ids)
|
||||
self.assertTrue(payment_old_line.reconciled)
|
||||
|
||||
def test_scenario_reconcile_currency(self):
|
||||
currency_rate = (
|
||||
self.env["res.currency.rate"]
|
||||
|
|
Loading…
Reference in New Issue