Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[16][FIX] account_reconcile_oca : Fix multi currency management #1

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 43 additions & 32 deletions account_reconcile_oca/models/account_bank_statement_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,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
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The suspense currency should always be the foreign_currency if set (at least it is the case on enterprise)

for line in data:
if line.get("counterpart_line_ids"):
counterparts += line["counterpart_line_ids"]
Expand All @@ -244,24 +245,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
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(
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 @@ -274,6 +276,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 @@ -292,7 +295,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 @@ -314,7 +317,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 @@ -400,7 +405,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 Down Expand Up @@ -437,13 +442,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": self.manual_amount_in_currency,
"kind": line["kind"]
if line["kind"] != "suspense"
else "other",
Expand Down Expand Up @@ -1007,26 +1006,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
)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case of payment with a foreign currency, the real rate, applied by the bank can't be the Odoo one.
So, Odoo tries to create a exchange line even before reconciliation. I don't think it make sense, so we avoid this logic for liquidity/suspense line.

I believe that before starting reconciliation, we always should have 1 liquidity line and one suspense line, not a third line which would make a mess during reconciliation.

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)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case of a foreign currency, we want to take the real rate (the one applied by the bank) instead of the one defined in Odoo. So we by pass the currency._convert in this case.

else:
to_amount = currency._convert(
currency_amount,
self.company_id.currency_id,
self.company_id,
self.date,
)
- amount
)
return to_amount - amount

def _compute_exchange_rate(
self,
Expand Down