Skip to content

Commit 7e699f8

Browse files
[FIX] l10n_ar_currency_update: actualización de moneda.
Ticket: 110979 Cuando la moneda de la compañía es ARS pero el usuario le cambió el nombre por ejemplo a "PES" entonces no se logra hacer la actualización de las tasas de cambio porque no estamos actualizando la moneda de la compañía y odoo lo requiere (por más de que el tipo de cambio sea el mismo todos los días). closes #911 X-original-commit: c76cade Signed-off-by: Julia Elizondo - jue (#l10n) <jue@adhoc.com.ar> Signed-off-by: Pablo Montenegro - pam (#l10n) <pam@adhoc.com.ar>
1 parent 6ff70b8 commit 7e699f8

File tree

2 files changed

+81
-41
lines changed

2 files changed

+81
-41
lines changed

l10n_ar_currency_update/models/res_company.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ def _generate_currency_rates(self, parsed_data):
160160
("company_id", "=", company.id),
161161
]
162162
)
163-
if currency == "ARS":
163+
if currency == company.currency_id.name:
164164
continue
165165
if already_existing_rate:
166166
new_parsed_data.pop(currency)

l10n_ar_currency_update/tests/test_l10n_ar_currency_update.py

Lines changed: 80 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,78 @@
55
import datetime
66
from unittest.mock import patch
77

8-
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
9-
from odoo.tests import tagged
8+
from odoo.tests import TransactionCase, tagged
109

1110

1211
@tagged("post_install", "-at_install")
13-
class TestL10nArCurrencyUpdate(AccountTestInvoicingCommon):
12+
class TestL10nArCurrencyUpdate(TransactionCase):
1413
@classmethod
15-
@AccountTestInvoicingCommon.setup_chart_template("ar_ri")
1614
def setUpClass(cls):
1715
super().setUpClass()
1816
cls.ARS = cls.env.ref("base.ARS")
1917
cls.USD = cls.env.ref("base.USD")
2018
cls.EUR = cls.env.ref("base.EUR")
2119

22-
# Activamos monedas por las dudas
20+
# Activamos monedas
2321
cls.USD.active = True
2422
cls.EUR.active = True
2523
cls.utils_path = "odoo.addons.l10n_ar_currency_update.models.res_company.ResCompany"
2624

2725
def test_ARS(self):
28-
"""When the base currency is ARS"""
29-
msg_error = "Should not be any rate for this currency and company to continue with the test"
30-
self.assertEqual(self.env.company.currency_id, self.ARS)
31-
self.assertEqual(self.ARS.rate, 1.0, msg_error)
32-
self.assertEqual(self.USD.rate, 1.0, msg_error)
33-
self.assertEqual(self.EUR.rate, 1.0, msg_error)
34-
35-
test_date = datetime.date(2024, 9, 24)
26+
"""Cuando se hace la actualización de monedas desde ARCA, siempre tenemos que validar que se actualice la moneda local (ARS) aunque su tipo de cambio sea 1.0 .
27+
Esto es requerido por validaciones de contabilidad en método _generate_currency_rates de src/enterprise/currency_rate_live/models/res_config_settings.py.
28+
Si no actualizamos la moneda local, no se crea ningún registro de tipo de cambio para esa fecha y empresa."""
29+
test_date = datetime.date(2026, 9, 24)
30+
31+
# Clean existing rates for test isolation
32+
self.env["res.currency.rate"].search(
33+
[
34+
("name", "=", test_date),
35+
("company_id", "=", self.env.company.id),
36+
]
37+
).unlink()
38+
39+
# Configure company to use AFIP provider
40+
self.env.company.write(
41+
{
42+
"currency_provider": "afip",
43+
"currency_interval_unit": "daily",
44+
}
45+
)
46+
47+
# Mock data must include base currency for enterprise validation
3648
mocked_res = {
3749
"ARS": (1.0, test_date),
3850
"EUR": (0.0009435361546070796, test_date),
3951
"USD": (0.0010481301358376655, test_date),
4052
}
4153

4254
with patch(f"{self.utils_path}._parse_afip_data", return_value=mocked_res):
43-
self.env.company.update_currency_rates()
55+
self.env.company.with_context(l10n_ar_force_create_rate=True).update_currency_rates()
4456

45-
self.assertEqual(self.ARS.rate, 1.0)
46-
self.assertNotEqual(self.USD.rate, 954.08)
47-
self.assertNotEqual(self.EUR.rate, 1059.8428)
57+
# Base currency WILL have a rate created with rate=1.0 (expected behavior)
58+
base_rate = self.env["res.currency.rate"].search(
59+
[
60+
("currency_id", "=", self.env.company.currency_id.id),
61+
("name", "=", test_date),
62+
("company_id", "=", self.env.company.id),
63+
]
64+
)
65+
self.assertTrue(base_rate, "Base currency should have a rate created")
66+
self.assertEqual(base_rate.rate, 1.0, "Base currency rate should be 1.0")
67+
68+
# Verify other currencies got rates created
69+
for curr_code in mocked_res.keys():
70+
if curr_code != self.env.company.currency_id.name:
71+
if curr := self.env["res.currency"].search([("name", "=", curr_code)]):
72+
rate = self.env["res.currency.rate"].search(
73+
[
74+
("currency_id", "=", curr.id),
75+
("name", "=", test_date),
76+
("company_id", "=", self.env.company.id),
77+
]
78+
)
79+
self.assertTrue(rate, f"{curr_code} should have a rate created")
4880

4981
def test_currency_rate_with_rate_perc(self):
5082
"""Check that the rate percentage is applied only to company 1 when both sync from ARCA"""
@@ -53,8 +85,15 @@ def test_currency_rate_with_rate_perc(self):
5385
rate_perc = 0.03
5486
test_date = datetime.date.today()
5587

56-
# Create a second Argentine company
88+
# Create two fresh Argentine companies to avoid currency change issues
5789
ar_country = self.env.ref("base.ar")
90+
company_1 = self.env["res.company"].create(
91+
{
92+
"name": "Test Argentine Company 1",
93+
"country_id": ar_country.id,
94+
"currency_id": self.ARS.id,
95+
}
96+
)
5897
company_2 = self.env["res.company"].create(
5998
{
6099
"name": "Test Argentine Company 2",
@@ -63,49 +102,49 @@ def test_currency_rate_with_rate_perc(self):
63102
}
64103
)
65104

66-
# Configure the first company (self.env.company) with currency provider AND rate_perc
67-
self.env.company.write(
105+
# Configure company_1 with currency provider AND rate_perc
106+
company_1.write(
68107
{
69108
"currency_provider": "afip",
70109
"rate_perc": rate_perc,
71110
"currency_interval_unit": "daily",
72111
}
73112
)
74113

75-
# Configure the second company with currency provider but WITHOUT rate_perc
114+
# Configure company_2 with currency provider but WITHOUT rate_perc
76115
company_2.write(
77116
{
78117
"currency_provider": "afip",
79118
"currency_interval_unit": "daily",
119+
"rate_perc": 0.0, # Explicitly no markup
80120
}
81121
)
82122

83123
# Clean up previous rates for both companies
84-
existing_rates = self.env["res.currency.rate"].search(
124+
self.env["res.currency.rate"].search(
85125
[
86126
("currency_id", "=", self.USD.id),
87127
("name", "=", test_date),
88-
("company_id", "in", [self.env.company.id, company_2.id]),
128+
("company_id", "in", [company_1.id, company_2.id]),
89129
]
90-
)
91-
existing_rates.unlink()
130+
).unlink()
92131

93132
# Prepare mock data for AFIP
94133
mocked_res = {
95-
"ARS": (1.0, test_date),
134+
"ARS": (1.0, test_date), # Base currency for both companies
96135
"USD": (1.0 / base_arca_rate, test_date),
97136
}
98137

99138
# Execute test logic with patch - call update_currency_rates on both companies
100139
with patch(f"{self.utils_path}._parse_afip_data", return_value=mocked_res):
101-
(self.env.company | company_2).update_currency_rates()
140+
(company_1 | company_2).with_context(l10n_ar_force_create_rate=True).update_currency_rates()
102141

103142
# Validate rate creation for company 1 (WITH percentage rate_perc)
104143
rate_record_company_1 = self.env["res.currency.rate"].search(
105144
[
106145
("currency_id", "=", self.USD.id),
107146
("name", "=", test_date),
108-
("company_id", "=", self.env.company.id),
147+
("company_id", "=", company_1.id),
109148
]
110149
)
111150

@@ -115,15 +154,16 @@ def test_currency_rate_with_rate_perc(self):
115154
)
116155

117156
# Verify markup was applied correctly for company 1
118-
# The inverse rate (ARS per USD unit) should be base_arca_rate * (1 + rate_perc)
119-
inverse_rate_company_1 = 1 / rate_record_company_1.rate
120-
expected_inverse_rate_company_1 = base_arca_rate * (1 + rate_perc)
157+
# In Odoo, rate field = 1 / (ARS per USD)
158+
# With markup: ARS_per_USD = base_arca_rate * (1 + rate_perc)
159+
# So rate field = 1 / (base_arca_rate * (1 + rate_perc))
160+
expected_rate_with_markup = 1.0 / (base_arca_rate * (1 + rate_perc))
121161

122162
self.assertAlmostEqual(
123-
inverse_rate_company_1,
124-
expected_inverse_rate_company_1,
125-
places=2,
126-
msg="The inverse rate value (ARS per unit) with markup is incorrect for company 1.",
163+
rate_record_company_1.rate,
164+
expected_rate_with_markup,
165+
places=6,
166+
msg="The rate with markup is incorrect for company 1.",
127167
)
128168

129169
# Validate rate creation for company 2 (WITHOUT rate_perc)
@@ -141,13 +181,13 @@ def test_currency_rate_with_rate_perc(self):
141181
)
142182

143183
# Verify NO markup was applied for company 2 (base ARCA rate)
144-
inverse_rate_company_2 = 1 / rate_record_company_2.rate
184+
expected_rate_no_markup = 1.0 / base_arca_rate
145185

146186
self.assertAlmostEqual(
147-
inverse_rate_company_2,
148-
base_arca_rate,
149-
places=2,
150-
msg="The inverse rate value (ARS per unit) should be the base ARCA rate for company 2 (no markup).",
187+
rate_record_company_2.rate,
188+
expected_rate_no_markup,
189+
places=6,
190+
msg="The rate should be the base ARCA rate for company 2 (no markup).",
151191
)
152192

153193
# Verify that the rates are different between companies

0 commit comments

Comments
 (0)