Merge 9c0bfd0418
into eec5655c15
commit
a752bd86b4
|
@ -158,9 +158,20 @@ class MassReconcileBase(models.AbstractModel):
|
||||||
currency = same_curr and lines[0].currency_id or lines[0].company_id.currency_id
|
currency = same_curr and lines[0].currency_id or lines[0].company_id.currency_id
|
||||||
journal = self.journal_id
|
journal = self.journal_id
|
||||||
partners = lines.mapped("partner_id")
|
partners = lines.mapped("partner_id")
|
||||||
|
|
||||||
|
# Adjust amount_currency to match the sign of the company's residual (amount)
|
||||||
|
if same_curr:
|
||||||
|
if amount != 0:
|
||||||
|
sign = 1 if amount > 0 else -1
|
||||||
|
adjusted_amount_curr = abs(amount_curr) * sign
|
||||||
|
else:
|
||||||
|
adjusted_amount_curr = 0.0
|
||||||
|
else:
|
||||||
|
adjusted_amount_curr = amount
|
||||||
|
|
||||||
write_off_vals = {
|
write_off_vals = {
|
||||||
"name": _("Automatic writeoff"),
|
"name": _("Automatic writeoff"),
|
||||||
"amount_currency": same_curr and amount_curr or amount,
|
"amount_currency": adjusted_amount_curr if same_curr else amount,
|
||||||
"debit": amount > 0.0 and amount or 0.0,
|
"debit": amount > 0.0 and amount or 0.0,
|
||||||
"credit": amount < 0.0 and -amount or 0.0,
|
"credit": amount < 0.0 and -amount or 0.0,
|
||||||
"partner_id": len(partners) == 1 and partners.id or False,
|
"partner_id": len(partners) == 1 and partners.id or False,
|
||||||
|
|
|
@ -451,3 +451,129 @@ class TestScenarioReconcile(AccountTestInvoicingCommon):
|
||||||
)
|
)
|
||||||
self.assertEqual(len(writeoff_line), 1)
|
self.assertEqual(len(writeoff_line), 1)
|
||||||
self.assertEqual(writeoff_line.date, fields.Date.today())
|
self.assertEqual(writeoff_line.date, fields.Date.today())
|
||||||
|
|
||||||
|
def test_reconcile_with_writeoff_currency_opposite_signs(self):
|
||||||
|
"""Test write-off when company and foreign residuals have opposite signs."""
|
||||||
|
self.env.ref("base.group_multi_currency").users |= self.env.user
|
||||||
|
self.company.currency_id = self.env.ref("base.EUR")
|
||||||
|
usd = self.env.ref("base.USD")
|
||||||
|
usd.active = True
|
||||||
|
|
||||||
|
inv_date = fields.Date.today() - timedelta(days=10)
|
||||||
|
pay_date = fields.Date.today() - timedelta(days=1)
|
||||||
|
|
||||||
|
# Create currency rates
|
||||||
|
self.env["res.currency.rate"].create(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": inv_date,
|
||||||
|
"currency_id": usd.id,
|
||||||
|
"rate": 1.2,
|
||||||
|
"company_id": self.company.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": pay_date,
|
||||||
|
"rate": 1.25,
|
||||||
|
"currency_id": usd.id,
|
||||||
|
"company_id": self.company.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": fields.Date.today(),
|
||||||
|
"rate": 1.25,
|
||||||
|
"currency_id": usd.id,
|
||||||
|
"company_id": self.company.id,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create invoice and payment with opposing residual signs
|
||||||
|
common_ref = "INV-PAY-OPPOSITE-SIGNS"
|
||||||
|
invoice = self.init_invoice(
|
||||||
|
move_type="out_invoice",
|
||||||
|
partner=self.partner_a,
|
||||||
|
currency=usd,
|
||||||
|
amounts=[100],
|
||||||
|
invoice_date=inv_date,
|
||||||
|
post=True,
|
||||||
|
)
|
||||||
|
invoice.ref = common_ref
|
||||||
|
|
||||||
|
payment = self.env["account.payment"].create(
|
||||||
|
{
|
||||||
|
"partner_type": "customer",
|
||||||
|
"payment_type": "inbound",
|
||||||
|
"partner_id": self.partner_a.id,
|
||||||
|
"destination_account_id": self.company_data[
|
||||||
|
"default_account_receivable"
|
||||||
|
].id,
|
||||||
|
"amount": 100.10,
|
||||||
|
"currency_id": usd.id,
|
||||||
|
"journal_id": self.bank_journal.id,
|
||||||
|
"date": pay_date,
|
||||||
|
"ref": common_ref,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
payment.action_post()
|
||||||
|
|
||||||
|
# Create and run mass reconciliation
|
||||||
|
mass_rec = self.mass_rec_obj.create(
|
||||||
|
{
|
||||||
|
"name": "mass_reconcile_currency_writeoff_opposite",
|
||||||
|
"account": self.company_data["default_account_receivable"].id,
|
||||||
|
"reconcile_method": [
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": "mass.reconcile.advanced.ref",
|
||||||
|
"account_lost_id": self.company_data[
|
||||||
|
"default_account_expense"
|
||||||
|
].id,
|
||||||
|
"account_profit_id": self.company_data[
|
||||||
|
"default_account_revenue"
|
||||||
|
].id,
|
||||||
|
"journal_id": self.company_data["default_journal_misc"].id,
|
||||||
|
"write_off": 3.50,
|
||||||
|
"date_base_on": "newest",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
existing_moves = self.env["account.move"].search(
|
||||||
|
[("journal_id", "=", self.company_data["default_journal_misc"].id)]
|
||||||
|
)
|
||||||
|
mass_rec.run_reconcile()
|
||||||
|
|
||||||
|
# Validate write-off move
|
||||||
|
writeoff_move = self.env["account.move"].search(
|
||||||
|
[
|
||||||
|
("journal_id", "=", self.company_data["default_journal_misc"].id),
|
||||||
|
("id", "not in", existing_moves.ids),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
len(writeoff_move), 1, "Exactly one write-off move should exist"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
writeoff_move.currency_id, usd, "USD should be the write-off currency"
|
||||||
|
)
|
||||||
|
|
||||||
|
pl_line = writeoff_move.line_ids.filtered(
|
||||||
|
lambda ml: ml.account_id == self.company_data["default_account_expense"]
|
||||||
|
)
|
||||||
|
receivable_line = writeoff_move.line_ids.filtered(
|
||||||
|
lambda ml: ml.account_id == self.company_data["default_account_receivable"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check amounts (0.10 USD residual, 3.25 EUR residual)
|
||||||
|
self.assertAlmostEqual(pl_line.debit, 3.25, 2, "Expense line debit (EUR)")
|
||||||
|
self.assertAlmostEqual(
|
||||||
|
pl_line.amount_currency, 0.10, 2, "Expense line USD amount"
|
||||||
|
)
|
||||||
|
self.assertAlmostEqual(
|
||||||
|
receivable_line.credit, 3.25, 2, "Receivable line credit (EUR)"
|
||||||
|
)
|
||||||
|
self.assertAlmostEqual(
|
||||||
|
receivable_line.amount_currency, -0.10, 2, "Receivable line USD amount"
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue