Skip to content

Commit

Permalink
[FIX] account_reconcile_oca : Fix multi currency management
Browse files Browse the repository at this point in the history
Fix the case of payment with a foreign currency set on bank statement line

improve tests around multi-currency
  • Loading branch information
florian-dacosta authored and etobella committed Oct 1, 2024
1 parent c24ec5b commit 0553397
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 98 deletions.
108 changes: 65 additions & 43 deletions account_reconcile_oca/models/account_bank_statement_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,23 +194,29 @@ def _onchange_manual_model_id(self):
)._default_reconcile_data()
self.can_reconcile = self.reconcile_data_info.get("can_reconcile", False)

def _get_amount_currency(self, line, dest_curr):
if line["line_currency_id"] == dest_curr.id:
amount = line["currency_amount"]
else:
amount = self.company_id.currency_id._convert(

Check warning on line 201 in account_reconcile_oca/models/account_bank_statement_line.py

View check run for this annotation

Codecov / codecov/patch

account_reconcile_oca/models/account_bank_statement_line.py#L201

Added line #L201 was not covered by tests
line["amount"],
dest_curr,
self.company_id,
self.date,
)
return amount

@api.onchange("add_account_move_line_id")
def _onchange_add_account_move_line_id(self):
if self.add_account_move_line_id:
data = self.reconcile_data_info["data"]
new_data = []
is_new_line = True
pending_amount = 0.0
currency = self._get_reconcile_currency()
for line in data:
if line["kind"] != "suspense":
pending_amount += currency._convert(
line["currency_amount"],
self.env["res.currency"].browse(
line.get("line_currency_id", currency.id)
),
self.company_id,
self.date,
pending_amount += self._get_amount_currency(
line, self._get_reconcile_currency()
)
if self.add_account_move_line_id.id in line.get(
"counterpart_line_ids", []
Expand Down Expand Up @@ -242,6 +248,7 @@ def _recompute_suspense_line(self, data, reconcile_auxiliary_id, manual_referenc
new_data = []
suspense_line = False
counterparts = []
suspense_currency = self.foreign_currency_id or self.currency_id
for line in data:
if line.get("counterpart_line_ids"):
counterparts += line["counterpart_line_ids"]
Expand All @@ -253,24 +260,25 @@ def _recompute_suspense_line(self, data, reconcile_auxiliary_id, manual_referenc
if line["kind"] != "suspense":
new_data.append(line)
total_amount += line["amount"]
if line.get("currency_amount"):
currency_amount += (
self.env["res.currency"]
.browse(line["line_currency_id"])
._convert(
line["currency_amount"],
self._get_reconcile_currency(),
if not line.get("is_exchange_counterpart"):
# case of statement line with foreign_currency
if (
line["kind"] == "liquidity"
and line["line_currency_id"] != suspense_currency.id
):
currency_amount += self.amount_currency

Check warning on line 269 in account_reconcile_oca/models/account_bank_statement_line.py

View check run for this annotation

Codecov / codecov/patch

account_reconcile_oca/models/account_bank_statement_line.py#L269

Added line #L269 was not covered by tests
elif (
line.get("currency_amount")
and line.get("line_currency_id") == suspense_currency.id
):
currency_amount += line.get("currency_amount")
else:
currency_amount += self.company_id.currency_id._convert(

Check warning on line 276 in account_reconcile_oca/models/account_bank_statement_line.py

View check run for this annotation

Codecov / codecov/patch

account_reconcile_oca/models/account_bank_statement_line.py#L276

Added line #L276 was not covered by tests
line["amount"],
suspense_currency,
self.company_id,
self.date,
)
)
else:
currency_amount += self.company_id.currency_id._convert(
line["amount"],
self._get_reconcile_currency(),
self.company_id,
self.date,
)
else:
suspense_line = line
if not float_is_zero(
Expand All @@ -283,6 +291,7 @@ def _recompute_suspense_line(self, data, reconcile_auxiliary_id, manual_referenc
"amount": -total_amount,
"credit": total_amount if total_amount > 0 else 0.0,
"debit": -total_amount if total_amount < 0 else 0.0,
"currency_amount": -currency_amount,
}
)
else:
Expand All @@ -301,7 +310,7 @@ def _recompute_suspense_line(self, data, reconcile_auxiliary_id, manual_referenc
"debit": -total_amount if total_amount < 0 else 0.0,
"kind": "suspense",
"currency_id": self.company_id.currency_id.id,
"line_currency_id": self.currency_id.id,
"line_currency_id": suspense_currency.id,
"currency_amount": -currency_amount,
}
reconcile_auxiliary_id += 1
Expand All @@ -323,7 +332,9 @@ def _check_line_changed(self, line):
or self.manual_account_id.id != line["account_id"][0]
or self.manual_name != line["name"]
or (
self.manual_partner_id and self.manual_partner_id.name_get()[0] or False
self.manual_partner_id
and self.manual_partner_id.name_get()[0]
or [False, False]
)
!= line.get("partner_id")
)
Expand Down Expand Up @@ -409,7 +420,7 @@ def _onchange_manual_amount_in_currency(self):
if self.manual_line_id.exists() and self.manual_line_id:
self.manual_amount = self.manual_in_currency_id._convert(
self.manual_amount_in_currency,
self._get_reconcile_currency(),
self.company_id.currency_id,
self.company_id,
self.manual_line_id.date,
)
Expand All @@ -429,6 +440,10 @@ def _onchange_manual_reconcile_vals(self):
for line in data:
if line["reference"] == self.manual_reference:
if self._check_line_changed(line):
if line["line_currency_id"] == self.company_id.currency_id.id:
currency_amount = self.manual_amount
else:
currency_amount = self.manual_amount_in_currency
line.update(
{
"name": self.manual_name,
Expand All @@ -446,13 +461,7 @@ def _onchange_manual_reconcile_vals(self):
if self.manual_amount > 0
else 0.0,
"analytic_distribution": self.analytic_distribution,
"currency_amount": self._get_reconcile_currency()._convert(
self.manual_amount,
self.manual_in_currency_id
or self._get_reconcile_currency(),
self.company_id,
line["date"],
),
"currency_amount": currency_amount,
"kind": line["kind"]
if line["kind"] != "suspense"
else "other",
Expand Down Expand Up @@ -588,6 +597,7 @@ def _default_reconcile_data(self, from_unreconcile=False):
self.manual_reference,
)
elif res and res.get("amls"):
# TODO should be signed in currency get_reconcile_currency
amount = self.amount_total_signed
for line in res.get("amls", []):
reconcile_auxiliary_id, line_data = self._get_reconcile_line(
Expand Down Expand Up @@ -891,7 +901,7 @@ def create(self, mvals):
self.manual_reference,
)
elif res.get("amls"):
amount = self.amount
amount = self.amount_currency or self.amount
for line in res.get("amls", []):
reconcile_auxiliary_id, line_datas = record._get_reconcile_line(
line, "other", is_counterpart=True, max_amount=amount, move=True
Expand Down Expand Up @@ -1016,26 +1026,38 @@ def _get_reconcile_line(
)
rates = []
for vals in new_vals:
rate = False
if vals["partner_id"] is False:
vals["partner_id"] = (False, self.partner_name)
reconcile_auxiliary_id, rate = self._compute_exchange_rate(
vals, line, reconcile_auxiliary_id
)
if vals.get("kind") not in ("suspense", "liquidity"):
reconcile_auxiliary_id, rate = self._compute_exchange_rate(
vals, line, reconcile_auxiliary_id
)
if rate:
rates.append(rate)
new_vals += rates
return reconcile_auxiliary_id, new_vals

def _get_exchange_rate_amount(self, amount, currency_amount, currency, line):
return (
currency._convert(
if self.foreign_currency_id:
# take real rate of statement line to compute the exchange rate gain/loss
real_rate = self.amount / self.amount_currency
to_amount_journal_currency = currency_amount * real_rate
to_amount_company_currency = self.currency_id._convert(
to_amount_journal_currency,
self.company_id.currency_id,
self.company_id,
self.date,
)
to_amount = self.company_id.currency_id.round(to_amount_company_currency)
else:
to_amount = currency._convert(
currency_amount,
self.company_id.currency_id,
self.company_id,
self.date,
)
- amount
)
return self.company_id.currency_id.round(to_amount - amount)

def _compute_exchange_rate(
self,
Expand Down Expand Up @@ -1104,7 +1126,7 @@ def add_statement(self):

def _get_reconcile_currency(self):
return (
self.currency_id
self.foreign_currency_id
or self.journal_id.currency_id
or self.company_id._currency_id
or self.company_id.currency_id
)
24 changes: 16 additions & 8 deletions account_reconcile_oca/models/account_reconcile_abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,25 @@ def _get_reconcile_line(
):
date = self.date if "date" in self._fields else line.date
original_amount = amount = net_amount = line.debit - line.credit
line_currency = line.currency_id
if is_counterpart:
currency_amount = -line.amount_residual_currency or line.amount_residual
amount = -line.amount_residual
currency = line.currency_id or line.company_id.currency_id
original_amount = net_amount = -line.amount_residual
if max_amount:
real_currency_amount = currency._convert(
currency_amount,
self._get_reconcile_currency(),
self.company_id,
date,
)
dest_currency = self._get_reconcile_currency()
if currency == dest_currency:
real_currency_amount = currency_amount
elif self.company_id.currency_id == dest_currency:
real_currency_amount = amount

Check warning on line 61 in account_reconcile_oca/models/account_reconcile_abstract.py

View check run for this annotation

Codecov / codecov/patch

account_reconcile_oca/models/account_reconcile_abstract.py#L61

Added line #L61 was not covered by tests
else:
real_currency_amount = self.company_id.currency_id._convert(

Check warning on line 63 in account_reconcile_oca/models/account_reconcile_abstract.py

View check run for this annotation

Codecov / codecov/patch

account_reconcile_oca/models/account_reconcile_abstract.py#L63

Added line #L63 was not covered by tests
amount,
dest_currency,
self.company_id,
date,
)
if (
-real_currency_amount > max_amount > 0
or -real_currency_amount < max_amount < 0
Expand All @@ -76,7 +83,8 @@ def _get_reconcile_line(
date,
)
else:
currency_amount = line.amount_currency
currency_amount = self.amount_currency or self.amount
line_currency = self._get_reconcile_currency()
vals = {
"move_id": move and line.move_id.id,
"move": move and line.move_id.name,
Expand All @@ -91,7 +99,7 @@ def _get_reconcile_line(
"amount": amount,
"net_amount": amount - net_amount,
"currency_id": self.company_id.currency_id.id,
"line_currency_id": line.currency_id.id,
"line_currency_id": line_currency.id,
"currency_amount": currency_amount,
"analytic_distribution": line.analytic_distribution,
"kind": kind,
Expand Down
Loading

0 comments on commit 0553397

Please sign in to comment.