odoo-addon-account-reconcile-oca 16.0.2.1.2__py3-none-any.whl → 16.0.2.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- odoo/addons/account_reconcile_oca/README.rst +1 -1
- odoo/addons/account_reconcile_oca/__manifest__.py +1 -1
- odoo/addons/account_reconcile_oca/i18n/es.po +2 -2
- odoo/addons/account_reconcile_oca/models/account_account_reconcile.py +5 -1
- odoo/addons/account_reconcile_oca/models/account_bank_statement_line.py +196 -26
- odoo/addons/account_reconcile_oca/models/account_reconcile_abstract.py +39 -14
- odoo/addons/account_reconcile_oca/static/description/index.html +1 -1
- odoo/addons/account_reconcile_oca/static/src/js/widgets/reconcile_data_widget.esm.js +12 -0
- odoo/addons/account_reconcile_oca/static/src/xml/reconcile.xml +12 -1
- odoo/addons/account_reconcile_oca/tests/test_bank_account_reconcile.py +139 -39
- {odoo_addon_account_reconcile_oca-16.0.2.1.2.dist-info → odoo_addon_account_reconcile_oca-16.0.2.2.0.dist-info}/METADATA +2 -2
- {odoo_addon_account_reconcile_oca-16.0.2.1.2.dist-info → odoo_addon_account_reconcile_oca-16.0.2.2.0.dist-info}/RECORD +14 -14
- {odoo_addon_account_reconcile_oca-16.0.2.1.2.dist-info → odoo_addon_account_reconcile_oca-16.0.2.2.0.dist-info}/WHEEL +0 -0
- {odoo_addon_account_reconcile_oca-16.0.2.1.2.dist-info → odoo_addon_account_reconcile_oca-16.0.2.2.0.dist-info}/top_level.txt +0 -0
@@ -7,7 +7,7 @@ Account Reconcile Oca
|
|
7
7
|
!! This file is generated by oca-gen-addon-readme !!
|
8
8
|
!! changes will be overwritten. !!
|
9
9
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
10
|
-
!! source digest: sha256:
|
10
|
+
!! source digest: sha256:aadf7b4e5870025e66812a15fbb3b6afbacbea02bbcf7e4e9a19a530b166af07
|
11
11
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
12
12
|
|
13
13
|
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
@@ -5,7 +5,7 @@
|
|
5
5
|
"name": "Account Reconcile Oca",
|
6
6
|
"summary": """
|
7
7
|
Reconcile addons for Odoo CE accounting""",
|
8
|
-
"version": "16.0.2.
|
8
|
+
"version": "16.0.2.2.0",
|
9
9
|
"license": "AGPL-3",
|
10
10
|
"author": "CreuBlanca,Dixmit,Odoo Community Association (OCA)",
|
11
11
|
"maintainers": ["etobella"],
|
@@ -6,7 +6,7 @@ msgid ""
|
|
6
6
|
msgstr ""
|
7
7
|
"Project-Id-Version: Odoo Server 16.0\n"
|
8
8
|
"Report-Msgid-Bugs-To: \n"
|
9
|
-
"PO-Revision-Date: 2024-12-
|
9
|
+
"PO-Revision-Date: 2024-12-20 13:06+0000\n"
|
10
10
|
"Last-Translator: Víctor Martínez <victor.martinez@tecnativa.com>\n"
|
11
11
|
"Language-Team: none\n"
|
12
12
|
"Language: es\n"
|
@@ -583,7 +583,7 @@ msgstr "Conciliado"
|
|
583
583
|
#. module: account_reconcile_oca
|
584
584
|
#: model_terms:ir.ui.view,arch_db:account_reconcile_oca.bank_statement_line_form_reconcile_view
|
585
585
|
msgid "Reset reconciliation"
|
586
|
-
msgstr "Restablecer
|
586
|
+
msgstr "Restablecer conciliación"
|
587
587
|
|
588
588
|
#. module: account_reconcile_oca
|
589
589
|
#. odoo-python
|
@@ -164,7 +164,11 @@ class AccountAccountReconcile(models.Model):
|
|
164
164
|
for line_id in counterparts:
|
165
165
|
max_amount = amount if line_id == counterparts[-1] else 0
|
166
166
|
lines = self._get_reconcile_line(
|
167
|
-
self.env["account.move.line"].browse(line_id),
|
167
|
+
self.env["account.move.line"].browse(line_id),
|
168
|
+
"other",
|
169
|
+
is_counterpart=True,
|
170
|
+
max_amount=max_amount,
|
171
|
+
move=True,
|
168
172
|
)
|
169
173
|
new_data["data"] += lines
|
170
174
|
amount += sum(line["amount"] for line in lines)
|
@@ -8,6 +8,7 @@ from dateutil.relativedelta import relativedelta
|
|
8
8
|
|
9
9
|
from odoo import Command, _, api, fields, models
|
10
10
|
from odoo.exceptions import UserError
|
11
|
+
from odoo.fields import first
|
11
12
|
from odoo.tools import float_is_zero
|
12
13
|
|
13
14
|
|
@@ -194,6 +195,18 @@ class AccountBankStatementLine(models.Model):
|
|
194
195
|
)._default_reconcile_data()
|
195
196
|
self.can_reconcile = self.reconcile_data_info.get("can_reconcile", False)
|
196
197
|
|
198
|
+
def _get_amount_currency(self, line, dest_curr):
|
199
|
+
if line["line_currency_id"] == dest_curr.id:
|
200
|
+
amount = line["currency_amount"]
|
201
|
+
else:
|
202
|
+
amount = self.company_id.currency_id._convert(
|
203
|
+
line["amount"],
|
204
|
+
dest_curr,
|
205
|
+
self.company_id,
|
206
|
+
self.date,
|
207
|
+
)
|
208
|
+
return amount
|
209
|
+
|
197
210
|
@api.onchange("add_account_move_line_id")
|
198
211
|
def _onchange_add_account_move_line_id(self):
|
199
212
|
if self.add_account_move_line_id:
|
@@ -201,9 +214,10 @@ class AccountBankStatementLine(models.Model):
|
|
201
214
|
new_data = []
|
202
215
|
is_new_line = True
|
203
216
|
pending_amount = 0.0
|
217
|
+
currency = self._get_reconcile_currency()
|
204
218
|
for line in data:
|
205
219
|
if line["kind"] != "suspense":
|
206
|
-
pending_amount += line
|
220
|
+
pending_amount += self._get_amount_currency(line, currency)
|
207
221
|
if self.add_account_move_line_id.id in line.get(
|
208
222
|
"counterpart_line_ids", []
|
209
223
|
):
|
@@ -212,7 +226,11 @@ class AccountBankStatementLine(models.Model):
|
|
212
226
|
new_data.append(line)
|
213
227
|
if is_new_line:
|
214
228
|
reconcile_auxiliary_id, lines = self._get_reconcile_line(
|
215
|
-
self.add_account_move_line_id,
|
229
|
+
self.add_account_move_line_id,
|
230
|
+
"other",
|
231
|
+
is_counterpart=True,
|
232
|
+
max_amount=currency.round(pending_amount),
|
233
|
+
move=True,
|
216
234
|
)
|
217
235
|
new_data += lines
|
218
236
|
self.reconcile_data_info = self._recompute_suspense_line(
|
@@ -226,9 +244,11 @@ class AccountBankStatementLine(models.Model):
|
|
226
244
|
def _recompute_suspense_line(self, data, reconcile_auxiliary_id, manual_reference):
|
227
245
|
can_reconcile = True
|
228
246
|
total_amount = 0
|
247
|
+
currency_amount = 0
|
229
248
|
new_data = []
|
230
249
|
suspense_line = False
|
231
250
|
counterparts = []
|
251
|
+
suspense_currency = self.foreign_currency_id or self.currency_id
|
232
252
|
for line in data:
|
233
253
|
if line.get("counterpart_line_ids"):
|
234
254
|
counterparts += line["counterpart_line_ids"]
|
@@ -240,10 +260,29 @@ class AccountBankStatementLine(models.Model):
|
|
240
260
|
if line["kind"] != "suspense":
|
241
261
|
new_data.append(line)
|
242
262
|
total_amount += line["amount"]
|
263
|
+
if not line.get("is_exchange_counterpart"):
|
264
|
+
# case of statement line with foreign_currency
|
265
|
+
if (
|
266
|
+
line["kind"] == "liquidity"
|
267
|
+
and line["line_currency_id"] != suspense_currency.id
|
268
|
+
):
|
269
|
+
currency_amount += self.amount_currency
|
270
|
+
elif (
|
271
|
+
line.get("currency_amount")
|
272
|
+
and line.get("line_currency_id") == suspense_currency.id
|
273
|
+
):
|
274
|
+
currency_amount += line.get("currency_amount")
|
275
|
+
else:
|
276
|
+
currency_amount += self.company_id.currency_id._convert(
|
277
|
+
line["amount"],
|
278
|
+
suspense_currency,
|
279
|
+
self.company_id,
|
280
|
+
self.date,
|
281
|
+
)
|
243
282
|
else:
|
244
283
|
suspense_line = line
|
245
284
|
if not float_is_zero(
|
246
|
-
total_amount, precision_digits=self.currency_id.decimal_places
|
285
|
+
total_amount, precision_digits=self.company_id.currency_id.decimal_places
|
247
286
|
):
|
248
287
|
can_reconcile = False
|
249
288
|
if suspense_line:
|
@@ -252,9 +291,11 @@ class AccountBankStatementLine(models.Model):
|
|
252
291
|
"amount": -total_amount,
|
253
292
|
"credit": total_amount if total_amount > 0 else 0.0,
|
254
293
|
"debit": -total_amount if total_amount < 0 else 0.0,
|
294
|
+
"currency_amount": -currency_amount,
|
255
295
|
}
|
256
296
|
)
|
257
297
|
else:
|
298
|
+
|
258
299
|
suspense_line = {
|
259
300
|
"reference": "reconcile_auxiliary;%s" % reconcile_auxiliary_id,
|
260
301
|
"id": False,
|
@@ -269,8 +310,8 @@ class AccountBankStatementLine(models.Model):
|
|
269
310
|
"debit": -total_amount if total_amount < 0 else 0.0,
|
270
311
|
"kind": "suspense",
|
271
312
|
"currency_id": self.company_id.currency_id.id,
|
272
|
-
"line_currency_id":
|
273
|
-
"currency_amount": -
|
313
|
+
"line_currency_id": suspense_currency.id,
|
314
|
+
"currency_amount": -currency_amount,
|
274
315
|
}
|
275
316
|
reconcile_auxiliary_id += 1
|
276
317
|
new_data.append(suspense_line)
|
@@ -291,7 +332,9 @@ class AccountBankStatementLine(models.Model):
|
|
291
332
|
or self.manual_account_id.id != line["account_id"][0]
|
292
333
|
or self.manual_name != line["name"]
|
293
334
|
or (
|
294
|
-
self.manual_partner_id
|
335
|
+
self.manual_partner_id
|
336
|
+
and self.manual_partner_id.name_get()[0]
|
337
|
+
or [False, False]
|
295
338
|
)
|
296
339
|
!= line.get("partner_id")
|
297
340
|
or self.analytic_distribution != line.get("analytic_distribution", False)
|
@@ -372,7 +415,11 @@ class AccountBankStatementLine(models.Model):
|
|
372
415
|
|
373
416
|
@api.onchange("manual_amount_in_currency")
|
374
417
|
def _onchange_manual_amount_in_currency(self):
|
375
|
-
if
|
418
|
+
if (
|
419
|
+
self.manual_line_id.exists()
|
420
|
+
and self.manual_line_id
|
421
|
+
and self.manual_kind != "liquidity"
|
422
|
+
):
|
376
423
|
self.manual_amount = self.manual_in_currency_id._convert(
|
377
424
|
self.manual_amount_in_currency,
|
378
425
|
self.company_id.currency_id,
|
@@ -382,7 +429,7 @@ class AccountBankStatementLine(models.Model):
|
|
382
429
|
self._onchange_manual_reconcile_vals()
|
383
430
|
|
384
431
|
def _get_manual_reconcile_vals(self):
|
385
|
-
|
432
|
+
vals = {
|
386
433
|
"name": self.manual_name,
|
387
434
|
"partner_id": self.manual_partner_id
|
388
435
|
and self.manual_partner_id.name_get()[0]
|
@@ -395,6 +442,18 @@ class AccountBankStatementLine(models.Model):
|
|
395
442
|
"debit": self.manual_amount if self.manual_amount > 0 else 0.0,
|
396
443
|
"analytic_distribution": self.analytic_distribution,
|
397
444
|
}
|
445
|
+
if self.manual_line_id:
|
446
|
+
vals.update(
|
447
|
+
{
|
448
|
+
"currency_amount": self.manual_line_id.currency_id._convert(
|
449
|
+
self.manual_amount,
|
450
|
+
self.manual_in_currency_id,
|
451
|
+
self.company_id,
|
452
|
+
self.manual_line_id.date,
|
453
|
+
),
|
454
|
+
}
|
455
|
+
)
|
456
|
+
return vals
|
398
457
|
|
399
458
|
@api.onchange(
|
400
459
|
"manual_account_id",
|
@@ -529,7 +588,10 @@ class AccountBankStatementLine(models.Model):
|
|
529
588
|
reconcile_auxiliary_id = 1
|
530
589
|
for line in liquidity_lines:
|
531
590
|
reconcile_auxiliary_id, lines = self._get_reconcile_line(
|
532
|
-
line,
|
591
|
+
line,
|
592
|
+
"liquidity",
|
593
|
+
reconcile_auxiliary_id=reconcile_auxiliary_id,
|
594
|
+
move=True,
|
533
595
|
)
|
534
596
|
data += lines
|
535
597
|
if not from_unreconcile:
|
@@ -555,6 +617,7 @@ class AccountBankStatementLine(models.Model):
|
|
555
617
|
self.manual_reference,
|
556
618
|
)
|
557
619
|
elif res and res.get("amls"):
|
620
|
+
# TODO should be signed in currency get_reconcile_currency
|
558
621
|
amount = self.amount_total_signed
|
559
622
|
for line in res.get("amls", []):
|
560
623
|
reconcile_auxiliary_id, line_data = self._get_reconcile_line(
|
@@ -574,16 +637,87 @@ class AccountBankStatementLine(models.Model):
|
|
574
637
|
self.manual_reference,
|
575
638
|
)
|
576
639
|
for line in other_lines:
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
640
|
+
partial_lines = self._all_partials_lines(line) if from_unreconcile else []
|
641
|
+
if partial_lines:
|
642
|
+
for reconciled_line in (
|
643
|
+
partial_lines.debit_move_id + partial_lines.credit_move_id - line
|
644
|
+
):
|
645
|
+
if (
|
646
|
+
reconciled_line.move_id.journal_id
|
647
|
+
== self.company_id.currency_exchange_journal_id
|
648
|
+
):
|
649
|
+
reconcile_auxiliary_id, lines = self._get_reconcile_line(
|
650
|
+
reconciled_line.move_id.line_ids - reconciled_line,
|
651
|
+
"other",
|
652
|
+
from_unreconcile=False,
|
653
|
+
move=True,
|
654
|
+
)
|
655
|
+
data += lines
|
656
|
+
continue
|
657
|
+
partial = partial_lines.filtered(
|
658
|
+
lambda r: r.debit_move_id == reconciled_line
|
659
|
+
or r.credit_move_id == reconciled_line
|
660
|
+
)
|
661
|
+
partial_amount = sum(
|
662
|
+
partial.filtered(
|
663
|
+
lambda r: r.credit_move_id == reconciled_line
|
664
|
+
).mapped("amount")
|
665
|
+
) - sum(
|
666
|
+
partial.filtered(
|
667
|
+
lambda r: r.debit_move_id == reconciled_line
|
668
|
+
).mapped("amount")
|
669
|
+
)
|
670
|
+
reconcile_auxiliary_id, lines = self._get_reconcile_line(
|
671
|
+
reconciled_line,
|
672
|
+
"other",
|
673
|
+
from_unreconcile={
|
674
|
+
"amount": partial_amount,
|
675
|
+
"credit": partial_amount > 0 and partial_amount,
|
676
|
+
"debit": partial_amount < 0 and -partial_amount,
|
677
|
+
"currency_amount": sum(
|
678
|
+
partial.filtered(
|
679
|
+
lambda r: r.credit_move_id == reconciled_line
|
680
|
+
).mapped("credit_amount_currency")
|
681
|
+
)
|
682
|
+
- sum(
|
683
|
+
partial.filtered(
|
684
|
+
lambda r: r.debit_move_id == reconciled_line
|
685
|
+
).mapped("debit_amount_currency")
|
686
|
+
),
|
687
|
+
},
|
688
|
+
move=True,
|
689
|
+
)
|
690
|
+
data += lines
|
691
|
+
else:
|
692
|
+
reconcile_auxiliary_id, lines = self._get_reconcile_line(
|
693
|
+
line, "other", from_unreconcile=False
|
694
|
+
)
|
695
|
+
data += lines
|
696
|
+
|
581
697
|
return self._recompute_suspense_line(
|
582
698
|
data,
|
583
699
|
reconcile_auxiliary_id,
|
584
700
|
self.manual_reference,
|
585
701
|
)
|
586
702
|
|
703
|
+
def _all_partials_lines(self, lines):
|
704
|
+
reconciliation_lines = lines.filtered(
|
705
|
+
lambda x: x.account_id.reconcile
|
706
|
+
or x.account_id.account_type in ("asset_cash", "liability_credit_card")
|
707
|
+
)
|
708
|
+
current_lines = reconciliation_lines
|
709
|
+
current_partials = self.env["account.partial.reconcile"]
|
710
|
+
partials = self.env["account.partial.reconcile"]
|
711
|
+
while current_lines:
|
712
|
+
current_partials = (
|
713
|
+
current_lines.matched_debit_ids + current_lines.matched_credit_ids
|
714
|
+
) - current_partials
|
715
|
+
current_lines = (
|
716
|
+
current_partials.debit_move_id + current_partials.credit_move_id
|
717
|
+
) - current_lines
|
718
|
+
partials += current_partials
|
719
|
+
return partials
|
720
|
+
|
587
721
|
def clean_reconcile(self):
|
588
722
|
self.reconcile_data_info = self._default_reconcile_data()
|
589
723
|
self.can_reconcile = self.reconcile_data_info.get("can_reconcile", False)
|
@@ -737,12 +871,13 @@ class AccountBankStatementLine(models.Model):
|
|
737
871
|
to_reverse._reverse_moves(default_values_list, cancel=True)
|
738
872
|
|
739
873
|
def _reconcile_move_line_vals(self, line, move_id=False):
|
740
|
-
|
874
|
+
vals = {
|
741
875
|
"move_id": move_id or self.move_id.id,
|
742
876
|
"account_id": line["account_id"][0],
|
743
877
|
"partner_id": line.get("partner_id") and line["partner_id"][0],
|
744
878
|
"credit": line["credit"],
|
745
879
|
"debit": line["debit"],
|
880
|
+
"currency_id": line.get("line_currency_id", self.company_id.currency_id.id),
|
746
881
|
"tax_ids": line.get("tax_ids", []),
|
747
882
|
"tax_tag_ids": line.get("tax_tag_ids", []),
|
748
883
|
"group_tax_id": line.get("group_tax_id"),
|
@@ -751,6 +886,11 @@ class AccountBankStatementLine(models.Model):
|
|
751
886
|
"name": line.get("name"),
|
752
887
|
"reconcile_model_id": line.get("reconcile_model_id"),
|
753
888
|
}
|
889
|
+
if line.get("line_currency_id") and line["currency_id"] != line.get(
|
890
|
+
"line_currency_id"
|
891
|
+
):
|
892
|
+
vals["amount_currency"] = line["currency_amount"]
|
893
|
+
return vals
|
754
894
|
|
755
895
|
@api.model_create_multi
|
756
896
|
def create(self, mvals):
|
@@ -770,7 +910,9 @@ class AccountBankStatementLine(models.Model):
|
|
770
910
|
data = []
|
771
911
|
for line in liquidity_lines:
|
772
912
|
reconcile_auxiliary_id, lines = record._get_reconcile_line(
|
773
|
-
line,
|
913
|
+
line,
|
914
|
+
"liquidity",
|
915
|
+
move=True,
|
774
916
|
)
|
775
917
|
data += lines
|
776
918
|
reconcile_auxiliary_id = 1
|
@@ -782,10 +924,10 @@ class AccountBankStatementLine(models.Model):
|
|
782
924
|
self.manual_reference,
|
783
925
|
)
|
784
926
|
elif res.get("amls"):
|
785
|
-
amount = self.amount
|
927
|
+
amount = self.amount_currency or self.amount
|
786
928
|
for line in res.get("amls", []):
|
787
929
|
reconcile_auxiliary_id, line_datas = record._get_reconcile_line(
|
788
|
-
line, "other", is_counterpart=True, max_amount=amount
|
930
|
+
line, "other", is_counterpart=True, max_amount=amount, move=True
|
789
931
|
)
|
790
932
|
amount -= sum(line_data.get("amount") for line_data in line_datas)
|
791
933
|
data += line_datas
|
@@ -847,6 +989,7 @@ class AccountBankStatementLine(models.Model):
|
|
847
989
|
is_counterpart=True,
|
848
990
|
reconcile_auxiliary_id=reconcile_auxiliary_id,
|
849
991
|
max_amount=original_amount,
|
992
|
+
move=True,
|
850
993
|
)
|
851
994
|
new_data += lines
|
852
995
|
new_data.append(
|
@@ -894,6 +1037,7 @@ class AccountBankStatementLine(models.Model):
|
|
894
1037
|
max_amount=False,
|
895
1038
|
from_unreconcile=False,
|
896
1039
|
reconcile_auxiliary_id=False,
|
1040
|
+
move=False,
|
897
1041
|
):
|
898
1042
|
new_vals = super()._get_reconcile_line(
|
899
1043
|
line,
|
@@ -901,29 +1045,48 @@ class AccountBankStatementLine(models.Model):
|
|
901
1045
|
is_counterpart=is_counterpart,
|
902
1046
|
max_amount=max_amount,
|
903
1047
|
from_unreconcile=from_unreconcile,
|
1048
|
+
move=move,
|
904
1049
|
)
|
905
1050
|
rates = []
|
906
1051
|
for vals in new_vals:
|
1052
|
+
rate = False
|
907
1053
|
if vals["partner_id"] is False:
|
908
1054
|
vals["partner_id"] = (False, self.partner_name)
|
909
|
-
|
910
|
-
|
911
|
-
|
1055
|
+
if vals.get("kind") not in ("suspense", "liquidity"):
|
1056
|
+
reconcile_auxiliary_id, rate = self._compute_exchange_rate(
|
1057
|
+
vals, line, reconcile_auxiliary_id
|
1058
|
+
)
|
912
1059
|
if rate:
|
913
1060
|
rates.append(rate)
|
914
1061
|
new_vals += rates
|
915
1062
|
return reconcile_auxiliary_id, new_vals
|
916
1063
|
|
917
1064
|
def _get_exchange_rate_amount(self, amount, currency_amount, currency, line):
|
918
|
-
|
919
|
-
|
1065
|
+
if self.foreign_currency_id == currency:
|
1066
|
+
# take real rate of statement line to compute the exchange rate gain/loss
|
1067
|
+
real_rate = self.amount / self.amount_currency
|
1068
|
+
to_amount_journal_currency = currency_amount * real_rate
|
1069
|
+
to_amount_company_currency = self.currency_id._convert(
|
1070
|
+
to_amount_journal_currency,
|
1071
|
+
self.company_id.currency_id,
|
1072
|
+
self.company_id,
|
1073
|
+
self.date,
|
1074
|
+
)
|
1075
|
+
to_amount = self.company_id.currency_id.round(to_amount_company_currency)
|
1076
|
+
elif self.currency_id == currency and not self.foreign_currency_id:
|
1077
|
+
liquidity_lines, _suspense_lines, _other_lines = self._seek_for_lines()
|
1078
|
+
real_rate = (
|
1079
|
+
first(liquidity_lines).balance / first(liquidity_lines).amount_currency
|
1080
|
+
)
|
1081
|
+
to_amount = self.company_id.currency_id.round(currency_amount * real_rate)
|
1082
|
+
else:
|
1083
|
+
to_amount = currency._convert(
|
920
1084
|
currency_amount,
|
921
1085
|
self.company_id.currency_id,
|
922
1086
|
self.company_id,
|
923
1087
|
self.date,
|
924
1088
|
)
|
925
|
-
|
926
|
-
)
|
1089
|
+
return self.company_id.currency_id.round(to_amount - amount)
|
927
1090
|
|
928
1091
|
def _compute_exchange_rate(
|
929
1092
|
self,
|
@@ -962,8 +1125,8 @@ class AccountBankStatementLine(models.Model):
|
|
962
1125
|
"debit": amount if amount > 0 else 0.0,
|
963
1126
|
"kind": "other",
|
964
1127
|
"currency_id": self.company_id.currency_id.id,
|
965
|
-
"line_currency_id":
|
966
|
-
"currency_amount":
|
1128
|
+
"line_currency_id": currency.id,
|
1129
|
+
"currency_amount": 0,
|
967
1130
|
}
|
968
1131
|
reconcile_auxiliary_id += 1
|
969
1132
|
return reconcile_auxiliary_id, data
|
@@ -989,3 +1152,10 @@ class AccountBankStatementLine(models.Model):
|
|
989
1152
|
"split_line_id": self.id,
|
990
1153
|
}
|
991
1154
|
return action
|
1155
|
+
|
1156
|
+
def _get_reconcile_currency(self):
|
1157
|
+
return (
|
1158
|
+
self.foreign_currency_id
|
1159
|
+
or self.journal_id.currency_id
|
1160
|
+
or self.company_id.currency_id
|
1161
|
+
)
|
@@ -33,24 +33,46 @@ class AccountReconcileAbstract(models.AbstractModel):
|
|
33
33
|
related="company_id.currency_id", string="Company Currency"
|
34
34
|
)
|
35
35
|
|
36
|
+
def _get_reconcile_currency(self):
|
37
|
+
return self.currency_id or self.company_id._currency_id
|
38
|
+
|
36
39
|
def _get_reconcile_line(
|
37
|
-
self,
|
40
|
+
self,
|
41
|
+
line,
|
42
|
+
kind,
|
43
|
+
is_counterpart=False,
|
44
|
+
max_amount=False,
|
45
|
+
from_unreconcile=False,
|
46
|
+
move=False,
|
38
47
|
):
|
39
48
|
date = self.date if "date" in self._fields else line.date
|
40
49
|
original_amount = amount = net_amount = line.debit - line.credit
|
50
|
+
line_currency = line.currency_id
|
41
51
|
if is_counterpart:
|
42
52
|
currency_amount = -line.amount_residual_currency or line.amount_residual
|
43
53
|
amount = -line.amount_residual
|
44
|
-
currency = line.currency_id or
|
54
|
+
currency = line.currency_id or line.company_id.currency_id
|
45
55
|
original_amount = net_amount = -line.amount_residual
|
46
56
|
if max_amount:
|
47
|
-
|
48
|
-
|
49
|
-
|
57
|
+
dest_currency = self._get_reconcile_currency()
|
58
|
+
if currency == dest_currency:
|
59
|
+
real_currency_amount = currency_amount
|
60
|
+
elif self.company_id.currency_id == dest_currency:
|
61
|
+
real_currency_amount = amount
|
62
|
+
else:
|
63
|
+
real_currency_amount = self.company_id.currency_id._convert(
|
64
|
+
amount,
|
65
|
+
dest_currency,
|
66
|
+
self.company_id,
|
67
|
+
date,
|
68
|
+
)
|
50
69
|
if (
|
51
|
-
-
|
52
|
-
or -
|
70
|
+
-real_currency_amount > max_amount > 0
|
71
|
+
or -real_currency_amount < max_amount < 0
|
53
72
|
):
|
73
|
+
currency_max_amount = self._get_reconcile_currency()._convert(
|
74
|
+
max_amount, currency, self.company_id, date
|
75
|
+
)
|
54
76
|
amount = currency_max_amount
|
55
77
|
net_amount = -max_amount
|
56
78
|
currency_amount = -amount
|
@@ -61,8 +83,11 @@ class AccountReconcileAbstract(models.AbstractModel):
|
|
61
83
|
date,
|
62
84
|
)
|
63
85
|
else:
|
64
|
-
currency_amount =
|
86
|
+
currency_amount = self.amount_currency or self.amount
|
87
|
+
line_currency = self._get_reconcile_currency()
|
65
88
|
vals = {
|
89
|
+
"move_id": move and line.move_id.id,
|
90
|
+
"move": move and line.move_id.name,
|
66
91
|
"reference": "account.move.line;%s" % line.id,
|
67
92
|
"id": line.id,
|
68
93
|
"account_id": line.account_id.name_get()[0],
|
@@ -74,7 +99,7 @@ class AccountReconcileAbstract(models.AbstractModel):
|
|
74
99
|
"amount": amount,
|
75
100
|
"net_amount": amount - net_amount,
|
76
101
|
"currency_id": self.company_id.currency_id.id,
|
77
|
-
"line_currency_id":
|
102
|
+
"line_currency_id": line_currency.id,
|
78
103
|
"currency_amount": currency_amount,
|
79
104
|
"analytic_distribution": line.analytic_distribution,
|
80
105
|
"kind": kind,
|
@@ -82,11 +107,11 @@ class AccountReconcileAbstract(models.AbstractModel):
|
|
82
107
|
if from_unreconcile:
|
83
108
|
vals.update(
|
84
109
|
{
|
85
|
-
"
|
86
|
-
"
|
87
|
-
|
88
|
-
|
89
|
-
|
110
|
+
"credit": vals["debit"] and from_unreconcile["debit"],
|
111
|
+
"debit": vals["credit"] and from_unreconcile["credit"],
|
112
|
+
"amount": from_unreconcile["amount"],
|
113
|
+
"net_amount": from_unreconcile["amount"],
|
114
|
+
"currency_amount": from_unreconcile["currency_amount"],
|
90
115
|
}
|
91
116
|
)
|
92
117
|
if not float_is_zero(
|
@@ -367,7 +367,7 @@ ul.auto-toc {
|
|
367
367
|
!! This file is generated by oca-gen-addon-readme !!
|
368
368
|
!! changes will be overwritten. !!
|
369
369
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
370
|
-
!! source digest: sha256:
|
370
|
+
!! source digest: sha256:aadf7b4e5870025e66812a15fbb3b6afbacbea02bbcf7e4e9a19a530b166af07
|
371
371
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
372
372
|
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/account-reconcile/tree/16.0/account_reconcile_oca"><img alt="OCA/account-reconcile" src="https://img.shields.io/badge/github-OCA%2Faccount--reconcile-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/account-reconcile-16-0/account-reconcile-16-0-account_reconcile_oca"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/account-reconcile&target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
|
373
373
|
<p>This addon allows to reconcile bank statements and account marked as <cite>reconcile</cite>.</p>
|
@@ -3,12 +3,15 @@
|
|
3
3
|
import fieldUtils from "web.field_utils";
|
4
4
|
import {registry} from "@web/core/registry";
|
5
5
|
import session from "web.session";
|
6
|
+
import {useService} from "@web/core/utils/hooks";
|
6
7
|
|
7
8
|
const {Component} = owl;
|
8
9
|
|
9
10
|
export class AccountReconcileDataWidget extends Component {
|
10
11
|
setup() {
|
11
12
|
super.setup(...arguments);
|
13
|
+
this.orm = useService("orm");
|
14
|
+
this.action = useService("action");
|
12
15
|
this.foreignCurrency =
|
13
16
|
this.props &&
|
14
17
|
this.props.record &&
|
@@ -83,6 +86,15 @@ export class AccountReconcileDataWidget extends Component {
|
|
83
86
|
});
|
84
87
|
this.env.bus.trigger("RECONCILE_PAGE_NAVIGATE", triggerEv);
|
85
88
|
}
|
89
|
+
async openMove(ev, moveId) {
|
90
|
+
ev.preventDefault();
|
91
|
+
ev.stopPropagation();
|
92
|
+
console.log(moveId);
|
93
|
+
const action = await this.orm.call("account.move", "get_formview_action", [
|
94
|
+
[moveId],
|
95
|
+
]);
|
96
|
+
this.action.doAction(action);
|
97
|
+
}
|
86
98
|
}
|
87
99
|
AccountReconcileDataWidget.template = "account_reconcile_oca.ReconcileDataWidget";
|
88
100
|
|
@@ -116,7 +116,18 @@
|
|
116
116
|
t-on-click="(ev) => this.selectReconcileLine(ev, reconcile_line)"
|
117
117
|
t-att-class="'o_reconcile_widget_line ' + reconcile_line.kind + (props.record.data.manual_reference == reconcile_line.reference ? ' selected ' : ' ')"
|
118
118
|
>
|
119
|
-
<td
|
119
|
+
<td>
|
120
|
+
<div t-esc="reconcile_line.account_id[1]" />
|
121
|
+
<div t-if="reconcile_line.move_id">
|
122
|
+
<a
|
123
|
+
t-att-href="'/web#id=' + reconcile_line.move_id + '&view_type=form&model=account.move'"
|
124
|
+
class="o_form_uri"
|
125
|
+
t-on-click="(ev) => this.openMove(ev, reconcile_line.move_id)"
|
126
|
+
>
|
127
|
+
<small t-esc="reconcile_line.move" />
|
128
|
+
</a>
|
129
|
+
</div>
|
130
|
+
</td>
|
120
131
|
<td>
|
121
132
|
<span
|
122
133
|
t-esc="reconcile_line.partner_id[1]"
|
@@ -84,7 +84,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
84
84
|
inv1 = self.create_invoice(currency_id=self.currency_usd_id, invoice_amount=100)
|
85
85
|
bank_stmt = self.acc_bank_stmt_model.create(
|
86
86
|
{
|
87
|
-
"company_id": self.env.ref("base.main_company").id,
|
88
87
|
"journal_id": self.bank_journal_euro.id,
|
89
88
|
"date": time.strftime("%Y-07-15"),
|
90
89
|
"name": "test",
|
@@ -112,6 +111,42 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
112
111
|
self.assertFalse(f.add_account_move_line_id)
|
113
112
|
self.assertTrue(f.can_reconcile)
|
114
113
|
|
114
|
+
def test_manual_line_with_currency(self):
|
115
|
+
bank_stmt = self.acc_bank_stmt_model.create(
|
116
|
+
{
|
117
|
+
"journal_id": self.bank_journal_euro.id,
|
118
|
+
"date": time.strftime("%Y-07-15"),
|
119
|
+
"name": "test",
|
120
|
+
}
|
121
|
+
)
|
122
|
+
bank_stmt_line = self.acc_bank_stmt_line_model.create(
|
123
|
+
{
|
124
|
+
"name": "testLine",
|
125
|
+
"journal_id": self.bank_journal_euro.id,
|
126
|
+
"statement_id": bank_stmt.id,
|
127
|
+
"amount": 50,
|
128
|
+
"amount_currency": 100,
|
129
|
+
"foreign_currency_id": self.currency_usd_id,
|
130
|
+
"date": time.strftime("%Y-07-15"),
|
131
|
+
}
|
132
|
+
)
|
133
|
+
receivable_acc = self.company_data["default_account_receivable"]
|
134
|
+
with Form(
|
135
|
+
bank_stmt_line,
|
136
|
+
view="account_reconcile_oca.bank_statement_line_form_reconcile_view",
|
137
|
+
) as f:
|
138
|
+
self.assertFalse(f.can_reconcile)
|
139
|
+
f.manual_reference = "reconcile_auxiliary;1"
|
140
|
+
f.manual_account_id = receivable_acc
|
141
|
+
self.assertTrue(f.can_reconcile)
|
142
|
+
bank_stmt_line.reconcile_bank_line()
|
143
|
+
receivable_line = bank_stmt_line.line_ids.filtered(
|
144
|
+
lambda line: line.account_id == receivable_acc
|
145
|
+
)
|
146
|
+
self.assertEqual(receivable_line.currency_id.id, self.currency_usd_id)
|
147
|
+
self.assertEqual(receivable_line.amount_currency, -100)
|
148
|
+
self.assertEqual(receivable_line.balance, -50)
|
149
|
+
|
115
150
|
def test_reconcile_invoice_reconcile_full(self):
|
116
151
|
"""
|
117
152
|
We want to test the reconcile widget for bank statements on invoices.
|
@@ -123,7 +158,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
123
158
|
)
|
124
159
|
bank_stmt = self.acc_bank_stmt_model.create(
|
125
160
|
{
|
126
|
-
"company_id": self.env.ref("base.main_company").id,
|
127
161
|
"journal_id": self.bank_journal_euro.id,
|
128
162
|
"date": time.strftime("%Y-07-15"),
|
129
163
|
"name": "test",
|
@@ -172,7 +206,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
172
206
|
)
|
173
207
|
bank_stmt = self.acc_bank_stmt_model.create(
|
174
208
|
{
|
175
|
-
"company_id": self.env.ref("base.main_company").id,
|
176
209
|
"journal_id": self.bank_journal_euro.id,
|
177
210
|
"date": time.strftime("%Y-07-15"),
|
178
211
|
"name": "test",
|
@@ -235,7 +268,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
235
268
|
)
|
236
269
|
bank_stmt = self.acc_bank_stmt_model.create(
|
237
270
|
{
|
238
|
-
"company_id": self.env.ref("base.main_company").id,
|
239
271
|
"journal_id": self.bank_journal_euro.id,
|
240
272
|
"date": time.strftime("%Y-07-15"),
|
241
273
|
"name": "test",
|
@@ -299,7 +331,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
299
331
|
)
|
300
332
|
bank_stmt = self.acc_bank_stmt_model.create(
|
301
333
|
{
|
302
|
-
"company_id": self.env.ref("base.main_company").id,
|
303
334
|
"journal_id": self.bank_journal_euro.id,
|
304
335
|
"date": time.strftime("%Y-07-15"),
|
305
336
|
"name": "test",
|
@@ -353,7 +384,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
353
384
|
"""
|
354
385
|
bank_stmt = self.acc_bank_stmt_model.create(
|
355
386
|
{
|
356
|
-
"company_id": self.env.ref("base.main_company").id,
|
357
387
|
"journal_id": self.bank_journal_euro.id,
|
358
388
|
"date": time.strftime("%Y-07-15"),
|
359
389
|
"name": "test",
|
@@ -397,7 +427,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
397
427
|
)
|
398
428
|
bank_stmt = self.acc_bank_stmt_model.create(
|
399
429
|
{
|
400
|
-
"company_id": self.env.ref("base.main_company").id,
|
401
430
|
"journal_id": self.bank_journal_euro.id,
|
402
431
|
"date": time.strftime("%Y-07-15"),
|
403
432
|
"name": "test",
|
@@ -452,7 +481,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
452
481
|
)
|
453
482
|
bank_stmt = self.acc_bank_stmt_model.create(
|
454
483
|
{
|
455
|
-
"company_id": self.env.ref("base.main_company").id,
|
456
484
|
"journal_id": self.bank_journal_euro.id,
|
457
485
|
"date": time.strftime("%Y-07-15"),
|
458
486
|
"name": "test",
|
@@ -512,7 +540,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
512
540
|
|
513
541
|
bank_stmt = self.acc_bank_stmt_model.create(
|
514
542
|
{
|
515
|
-
"company_id": self.env.ref("base.main_company").id,
|
516
543
|
"journal_id": self.bank_journal_euro.id,
|
517
544
|
"date": time.strftime("%Y-07-15"),
|
518
545
|
"name": "test",
|
@@ -542,7 +569,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
542
569
|
)
|
543
570
|
bank_stmt = self.acc_bank_stmt_model.create(
|
544
571
|
{
|
545
|
-
"company_id": self.env.ref("base.main_company").id,
|
546
572
|
"journal_id": self.bank_journal_euro.id,
|
547
573
|
"date": time.strftime("%Y-07-15"),
|
548
574
|
"name": "test",
|
@@ -600,7 +626,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
600
626
|
)
|
601
627
|
bank_stmt = self.acc_bank_stmt_model.create(
|
602
628
|
{
|
603
|
-
"company_id": self.env.ref("base.main_company").id,
|
604
629
|
"journal_id": self.bank_journal_euro.id,
|
605
630
|
"date": time.strftime("%Y-07-15"),
|
606
631
|
"name": "test",
|
@@ -642,7 +667,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
642
667
|
"""
|
643
668
|
bank_stmt = self.acc_bank_stmt_model.create(
|
644
669
|
{
|
645
|
-
"company_id": self.env.ref("base.main_company").id,
|
646
670
|
"journal_id": self.bank_journal_euro.id,
|
647
671
|
"date": time.strftime("%Y-07-15"),
|
648
672
|
"name": "test",
|
@@ -677,7 +701,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
677
701
|
)
|
678
702
|
bank_stmt = self.acc_bank_stmt_model.create(
|
679
703
|
{
|
680
|
-
"company_id": self.env.ref("base.main_company").id,
|
681
704
|
"journal_id": self.bank_journal_euro.id,
|
682
705
|
"date": time.strftime("%Y-07-15"),
|
683
706
|
"name": "test",
|
@@ -715,7 +738,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
715
738
|
)
|
716
739
|
bank_stmt = self.acc_bank_stmt_model.create(
|
717
740
|
{
|
718
|
-
"company_id": self.env.ref("base.main_company").id,
|
719
741
|
"journal_id": self.bank_journal_euro.id,
|
720
742
|
"date": time.strftime("%Y-07-15"),
|
721
743
|
"name": "test",
|
@@ -756,7 +778,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
756
778
|
)
|
757
779
|
bank_stmt = self.acc_bank_stmt_model.create(
|
758
780
|
{
|
759
|
-
"company_id": self.env.ref("base.main_company").id,
|
760
781
|
"journal_id": self.bank_journal_euro.id,
|
761
782
|
"date": time.strftime("%Y-07-15"),
|
762
783
|
"name": "test",
|
@@ -797,7 +818,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
797
818
|
)
|
798
819
|
bank_stmt = self.acc_bank_stmt_model.create(
|
799
820
|
{
|
800
|
-
"company_id": self.env.ref("base.main_company").id,
|
801
821
|
"journal_id": self.bank_journal_euro.id,
|
802
822
|
"date": time.strftime("%Y-07-15"),
|
803
823
|
"name": "test",
|
@@ -833,7 +853,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
833
853
|
"""
|
834
854
|
bank_stmt = self.acc_bank_stmt_model.create(
|
835
855
|
{
|
836
|
-
"company_id": self.env.ref("base.main_company").id,
|
837
856
|
"journal_id": self.bank_journal_euro.id,
|
838
857
|
"date": time.strftime("%Y-07-15"),
|
839
858
|
"name": "test",
|
@@ -884,7 +903,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
884
903
|
"""
|
885
904
|
bank_stmt = self.acc_bank_stmt_model.create(
|
886
905
|
{
|
887
|
-
"company_id": self.env.ref("base.main_company").id,
|
888
906
|
"journal_id": self.bank_journal_euro.id,
|
889
907
|
"date": time.strftime("%Y-07-15"),
|
890
908
|
"name": "test",
|
@@ -927,7 +945,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
927
945
|
|
928
946
|
bank_stmt = self.acc_bank_stmt_model.create(
|
929
947
|
{
|
930
|
-
"company_id": self.env.ref("base.main_company").id,
|
931
948
|
"journal_id": self.bank_journal_euro.id,
|
932
949
|
"date": time.strftime("%Y-07-15"),
|
933
950
|
"name": "test",
|
@@ -991,7 +1008,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
991
1008
|
|
992
1009
|
bank_stmt = self.acc_bank_stmt_model.create(
|
993
1010
|
{
|
994
|
-
"company_id": self.env.ref("base.main_company").id,
|
995
1011
|
"journal_id": self.bank_journal_euro.id,
|
996
1012
|
"date": time.strftime("%Y-07-15"),
|
997
1013
|
"name": "test",
|
@@ -1025,7 +1041,6 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
1025
1041
|
inv1 = self.create_invoice(currency_id=self.currency_usd_id, invoice_amount=100)
|
1026
1042
|
bank_stmt = self.acc_bank_stmt_model.create(
|
1027
1043
|
{
|
1028
|
-
"company_id": self.env.ref("base.main_company").id,
|
1029
1044
|
"journal_id": self.bank_journal_usd.id,
|
1030
1045
|
"date": time.strftime("%Y-07-15"),
|
1031
1046
|
"name": "test",
|
@@ -1064,30 +1079,51 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
1064
1079
|
)
|
1065
1080
|
|
1066
1081
|
def test_journal_foreign_currency_change(self):
|
1082
|
+
cny = self.env.ref("base.CNY")
|
1083
|
+
cny.write({"active": True})
|
1084
|
+
cny_journal = self.env["account.journal"].create(
|
1085
|
+
{
|
1086
|
+
"name": "Bank CNY",
|
1087
|
+
"type": "bank",
|
1088
|
+
"currency_id": cny.id,
|
1089
|
+
}
|
1090
|
+
)
|
1067
1091
|
self.env["res.currency.rate"].create(
|
1068
1092
|
{
|
1069
|
-
"
|
1070
|
-
"
|
1071
|
-
"
|
1093
|
+
"name": time.strftime("%Y-09-10"),
|
1094
|
+
"currency_id": cny.id,
|
1095
|
+
"inverse_company_rate": 0.125989013758,
|
1096
|
+
}
|
1097
|
+
)
|
1098
|
+
self.env["res.currency.rate"].create(
|
1099
|
+
{
|
1100
|
+
"name": time.strftime("%Y-09-09"),
|
1101
|
+
"currency_id": cny.id,
|
1102
|
+
"inverse_company_rate": 0.126225969731,
|
1072
1103
|
}
|
1073
1104
|
)
|
1074
1105
|
bank_stmt = self.acc_bank_stmt_model.create(
|
1075
1106
|
{
|
1076
|
-
"
|
1077
|
-
"
|
1078
|
-
"date": time.strftime("%Y-07-15"),
|
1107
|
+
"journal_id": cny_journal.id,
|
1108
|
+
"date": time.strftime("%Y-09-10"),
|
1079
1109
|
"name": "test",
|
1080
1110
|
}
|
1081
1111
|
)
|
1082
1112
|
bank_stmt_line = self.acc_bank_stmt_line_model.create(
|
1083
1113
|
{
|
1084
1114
|
"name": "testLine",
|
1085
|
-
"journal_id":
|
1115
|
+
"journal_id": cny_journal.id,
|
1086
1116
|
"statement_id": bank_stmt.id,
|
1087
|
-
"amount":
|
1088
|
-
"date": time.strftime("%Y-
|
1117
|
+
"amount": 259200,
|
1118
|
+
"date": time.strftime("%Y-09-10"),
|
1089
1119
|
}
|
1090
1120
|
)
|
1121
|
+
inv1 = self._create_invoice(
|
1122
|
+
currency_id=cny.id,
|
1123
|
+
invoice_amount=259200,
|
1124
|
+
date_invoice=time.strftime("%Y-09-09"),
|
1125
|
+
auto_validate=True,
|
1126
|
+
)
|
1091
1127
|
with Form(
|
1092
1128
|
bank_stmt_line,
|
1093
1129
|
view="account_reconcile_oca.bank_statement_line_form_reconcile_view",
|
@@ -1095,8 +1131,26 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
1095
1131
|
line = f.reconcile_data_info["data"][0]
|
1096
1132
|
self.assertEqual(
|
1097
1133
|
line["currency_amount"],
|
1098
|
-
|
1134
|
+
259200,
|
1135
|
+
)
|
1136
|
+
f.add_account_move_line_id = inv1.line_ids.filtered(
|
1137
|
+
lambda l: l.account_id.account_type == "asset_receivable"
|
1099
1138
|
)
|
1139
|
+
self.assertTrue(f.can_reconcile)
|
1140
|
+
self.assertEqual(len(bank_stmt_line.reconcile_data_info["data"]), 3)
|
1141
|
+
exchange_line = bank_stmt_line.reconcile_data_info["data"][-1]
|
1142
|
+
self.assertEqual(exchange_line["amount"], 61.42)
|
1143
|
+
bank_stmt_line.reconcile_bank_line()
|
1144
|
+
self.assertEqual(inv1.payment_state, "paid")
|
1145
|
+
|
1146
|
+
def test_invoice_foreign_currency_change(self):
|
1147
|
+
self.env["res.currency.rate"].create(
|
1148
|
+
{
|
1149
|
+
"currency_id": self.env.ref("base.EUR").id,
|
1150
|
+
"name": time.strftime("%Y-07-14"),
|
1151
|
+
"rate": 1.15,
|
1152
|
+
}
|
1153
|
+
)
|
1100
1154
|
self.env["res.currency.rate"].create(
|
1101
1155
|
{
|
1102
1156
|
"currency_id": self.env.ref("base.EUR").id,
|
@@ -1104,6 +1158,28 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
1104
1158
|
"rate": 1.2,
|
1105
1159
|
}
|
1106
1160
|
)
|
1161
|
+
inv1 = self._create_invoice(
|
1162
|
+
currency_id=self.currency_usd_id,
|
1163
|
+
invoice_amount=100,
|
1164
|
+
date_invoice="2021-07-14",
|
1165
|
+
auto_validate=True,
|
1166
|
+
)
|
1167
|
+
bank_stmt = self.acc_bank_stmt_model.create(
|
1168
|
+
{
|
1169
|
+
"journal_id": self.bank_journal_usd.id,
|
1170
|
+
"date": time.strftime("%Y-07-15"),
|
1171
|
+
"name": "test",
|
1172
|
+
}
|
1173
|
+
)
|
1174
|
+
bank_stmt_line = self.acc_bank_stmt_line_model.create(
|
1175
|
+
{
|
1176
|
+
"name": "testLine",
|
1177
|
+
"journal_id": self.bank_journal_usd.id,
|
1178
|
+
"statement_id": bank_stmt.id,
|
1179
|
+
"amount": 100,
|
1180
|
+
"date": time.strftime("%Y-07-15"),
|
1181
|
+
}
|
1182
|
+
)
|
1107
1183
|
with Form(
|
1108
1184
|
bank_stmt_line,
|
1109
1185
|
view="account_reconcile_oca.bank_statement_line_form_reconcile_view",
|
@@ -1113,18 +1189,27 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
1113
1189
|
line["currency_amount"],
|
1114
1190
|
100,
|
1115
1191
|
)
|
1192
|
+
f.add_account_move_line_id = inv1.line_ids.filtered(
|
1193
|
+
lambda l: l.account_id.account_type == "asset_receivable"
|
1194
|
+
)
|
1195
|
+
self.assertFalse(f.add_account_move_line_id)
|
1196
|
+
self.assertTrue(f.can_reconcile)
|
1197
|
+
self.assertEqual(3, len(f.reconcile_data_info["data"]))
|
1116
1198
|
|
1117
|
-
def
|
1199
|
+
def test_invoice_foreign_currency_late_change_of_rate(self):
|
1200
|
+
# Test we can reconcile lines in foreign currency even if the rate was updated
|
1201
|
+
# late in odoo, meaning the statement line was created and the rate was updated
|
1202
|
+
# in odoo after that.
|
1118
1203
|
self.env["res.currency.rate"].create(
|
1119
1204
|
{
|
1120
|
-
"currency_id": self.env.ref("base.
|
1205
|
+
"currency_id": self.env.ref("base.USD").id,
|
1121
1206
|
"name": time.strftime("%Y-07-14"),
|
1122
1207
|
"rate": 1.15,
|
1123
1208
|
}
|
1124
1209
|
)
|
1125
1210
|
self.env["res.currency.rate"].create(
|
1126
1211
|
{
|
1127
|
-
"currency_id": self.env.ref("base.
|
1212
|
+
"currency_id": self.env.ref("base.USD").id,
|
1128
1213
|
"name": time.strftime("%Y-07-15"),
|
1129
1214
|
"rate": 1.2,
|
1130
1215
|
}
|
@@ -1132,12 +1217,11 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
1132
1217
|
inv1 = self._create_invoice(
|
1133
1218
|
currency_id=self.currency_usd_id,
|
1134
1219
|
invoice_amount=100,
|
1135
|
-
date_invoice="
|
1220
|
+
date_invoice=time.strftime("%Y-07-14"),
|
1136
1221
|
auto_validate=True,
|
1137
1222
|
)
|
1138
1223
|
bank_stmt = self.acc_bank_stmt_model.create(
|
1139
1224
|
{
|
1140
|
-
"company_id": self.env.ref("base.main_company").id,
|
1141
1225
|
"journal_id": self.bank_journal_usd.id,
|
1142
1226
|
"date": time.strftime("%Y-07-15"),
|
1143
1227
|
"name": "test",
|
@@ -1149,7 +1233,16 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
1149
1233
|
"journal_id": self.bank_journal_usd.id,
|
1150
1234
|
"statement_id": bank_stmt.id,
|
1151
1235
|
"amount": 100,
|
1152
|
-
"date": time.strftime("%Y-07-
|
1236
|
+
"date": time.strftime("%Y-07-16"),
|
1237
|
+
}
|
1238
|
+
)
|
1239
|
+
# rate of 07-16 is create after the statement line, meaning the rate of the
|
1240
|
+
# statement line is the one of the 07-15
|
1241
|
+
self.env["res.currency.rate"].create(
|
1242
|
+
{
|
1243
|
+
"currency_id": self.env.ref("base.USD").id,
|
1244
|
+
"name": time.strftime("%Y-07-16"),
|
1245
|
+
"rate": 1.25,
|
1153
1246
|
}
|
1154
1247
|
)
|
1155
1248
|
with Form(
|
@@ -1161,9 +1254,16 @@ class TestReconciliationWidget(TestAccountReconciliationCommon):
|
|
1161
1254
|
line["currency_amount"],
|
1162
1255
|
100,
|
1163
1256
|
)
|
1257
|
+
self.assertEqual(
|
1258
|
+
line["amount"],
|
1259
|
+
83.33,
|
1260
|
+
)
|
1261
|
+
f.manual_reference = "account.move.line;%s" % line["id"]
|
1262
|
+
# simulate click on statement line, check amount does not recompute
|
1263
|
+
self.assertEqual(f.manual_amount, 83.33)
|
1164
1264
|
f.add_account_move_line_id = inv1.line_ids.filtered(
|
1165
1265
|
lambda l: l.account_id.account_type == "asset_receivable"
|
1166
1266
|
)
|
1167
|
-
self.assertFalse(f.add_account_move_line_id)
|
1168
|
-
self.assertTrue(f.can_reconcile)
|
1169
1267
|
self.assertEqual(3, len(f.reconcile_data_info["data"]))
|
1268
|
+
self.assertTrue(f.can_reconcile)
|
1269
|
+
self.assertEqual(f.reconcile_data_info["data"][-1]["amount"], 3.63)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: odoo-addon-account_reconcile_oca
|
3
|
-
Version: 16.0.2.
|
3
|
+
Version: 16.0.2.2.0
|
4
4
|
Summary: Reconcile addons for Odoo CE accounting
|
5
5
|
Home-page: https://github.com/OCA/account-reconcile
|
6
6
|
Author: CreuBlanca,Dixmit,Odoo Community Association (OCA)
|
@@ -23,7 +23,7 @@ Account Reconcile Oca
|
|
23
23
|
!! This file is generated by oca-gen-addon-readme !!
|
24
24
|
!! changes will be overwritten. !!
|
25
25
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
26
|
-
!! source digest: sha256:
|
26
|
+
!! source digest: sha256:aadf7b4e5870025e66812a15fbb3b6afbacbea02bbcf7e4e9a19a530b166af07
|
27
27
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
28
28
|
|
29
29
|
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
@@ -1,11 +1,11 @@
|
|
1
|
-
odoo/addons/account_reconcile_oca/README.rst,sha256=
|
1
|
+
odoo/addons/account_reconcile_oca/README.rst,sha256=1dCJECaC1IcDfbbjwf_Dj1cAnTUfF1A5kweF82X3C_4,3709
|
2
2
|
odoo/addons/account_reconcile_oca/__init__.py,sha256=vqRYeBgCVZMpZhYvILSxVsNLC9V7zDnvxMnKU8RQP94,55
|
3
|
-
odoo/addons/account_reconcile_oca/__manifest__.py,sha256=
|
3
|
+
odoo/addons/account_reconcile_oca/__manifest__.py,sha256=LKWjqgwvZDqLFH2ReH-sxbtm8d0lYEKR8HqYB7R-VgY,1826
|
4
4
|
odoo/addons/account_reconcile_oca/hooks.py,sha256=l2-vYiPh-Wu_4Hi3GvfoUmc527S-Jozb07-DbP6LzDA,187
|
5
5
|
odoo/addons/account_reconcile_oca/demo/demo.xml,sha256=6k0uK-H1aBiyogVNhQMQfFGL5zUfUGV2M-sSV6LHeUs,204
|
6
6
|
odoo/addons/account_reconcile_oca/i18n/account_reconcile_oca.pot,sha256=UOXZfULkd2lLxY1q6OJb-D4C8KqXV1U-7eG_52CP5lU,26737
|
7
7
|
odoo/addons/account_reconcile_oca/i18n/ca.po,sha256=V2CvS0DOFF6a4Icr-0sFYJEgYp2XKAQBiM9toi67ID8,28745
|
8
|
-
odoo/addons/account_reconcile_oca/i18n/es.po,sha256=
|
8
|
+
odoo/addons/account_reconcile_oca/i18n/es.po,sha256=ayMNseb6fTxDtwUbYHU7PH69alTXtyKcftEqhKT3phM,29360
|
9
9
|
odoo/addons/account_reconcile_oca/i18n/fr.po,sha256=Insh_trMpG5e1E5-QQ6qreIlDyHNohJeNn4cF9SFhuA,29811
|
10
10
|
odoo/addons/account_reconcile_oca/i18n/hr.po,sha256=lNsev7ujXBBUT0N1gd3Bv2O7K3uzogQ86jbqT6UG4CM,28174
|
11
11
|
odoo/addons/account_reconcile_oca/i18n/it.po,sha256=X_U3jXzdqKSMEZQJPD7QfkGE8wItoP2rOuRF85sfgTA,29527
|
@@ -16,12 +16,12 @@ odoo/addons/account_reconcile_oca/i18n/sv.po,sha256=aHozw_7rtEPrdtsgiz0gVu78gPX_
|
|
16
16
|
odoo/addons/account_reconcile_oca/i18n/tr.po,sha256=h26NnXK18YlnqdnekoerWgp22TdwjacB0suUJnQqmy8,29290
|
17
17
|
odoo/addons/account_reconcile_oca/migrations/16.0.1.2.0/pre-migration.py,sha256=Z_OLx-fclggJUAtYpepXRAAc68AizrIN6MWtl4zp0Qw,642
|
18
18
|
odoo/addons/account_reconcile_oca/models/__init__.py,sha256=28wbZjUZa30uHQY10BMJtKQ_BqJgwLQMQvB9uv0H_fY,282
|
19
|
-
odoo/addons/account_reconcile_oca/models/account_account_reconcile.py,sha256=
|
19
|
+
odoo/addons/account_reconcile_oca/models/account_account_reconcile.py,sha256=XGTsmZSUVyxp4XAjE2Q7f6nNAdONUOQS6GrCKI0pG7g,6882
|
20
20
|
odoo/addons/account_reconcile_oca/models/account_bank_statement.py,sha256=CFqlLLtmTqmt5yH3v_pkUfkZezSb1nEhBTu2J5gCjxM,1034
|
21
|
-
odoo/addons/account_reconcile_oca/models/account_bank_statement_line.py,sha256=
|
21
|
+
odoo/addons/account_reconcile_oca/models/account_bank_statement_line.py,sha256=GXjiZ89otoRCF-wZe9j6f1uPAMVgAegeb4zCyZlrexU,46903
|
22
22
|
odoo/addons/account_reconcile_oca/models/account_journal.py,sha256=8vluuQ0q0rGmVnJWyaSOAhTD0WZQuawKNqhUCEEYRvo,1306
|
23
23
|
odoo/addons/account_reconcile_oca/models/account_move_line.py,sha256=yLNHitduzhS5ShrWWw31S5zirIadFsG8ga1gtXehRTc,1213
|
24
|
-
odoo/addons/account_reconcile_oca/models/account_reconcile_abstract.py,sha256=
|
24
|
+
odoo/addons/account_reconcile_oca/models/account_reconcile_abstract.py,sha256=Q4TRiGluDU_t-oXfgEeNh9FbLqBoEDvAT0SH_5jIJ7U,4944
|
25
25
|
odoo/addons/account_reconcile_oca/models/res_company.py,sha256=IaSLPwHJZre5RYPVW8V6mnSoxltS_w0GUN1Ev-cfcB4,354
|
26
26
|
odoo/addons/account_reconcile_oca/models/res_config_settings.py,sha256=AuenxX0UfqYWWP-QvtB0irSf_JuWVh4a9QylPfl-Lxc,325
|
27
27
|
odoo/addons/account_reconcile_oca/readme/CONTRIBUTORS.rst,sha256=GAYxzAZEN5wTBewMNx4PD2y_QoI-dzpokacQ9NnaEso,16
|
@@ -30,7 +30,7 @@ odoo/addons/account_reconcile_oca/readme/ROADMAP.rst,sha256=MlQ8cFQmu5MzBoFW2WP_
|
|
30
30
|
odoo/addons/account_reconcile_oca/readme/USAGE.rst,sha256=npPsx_C8T-JuCEJiTK4V44_5Io1j4ltO831T3yHFuCs,396
|
31
31
|
odoo/addons/account_reconcile_oca/security/ir.model.access.csv,sha256=XfN2EKOoChlEDonVd5DtodVAQyRbShiJ8nrXx6EwNmM,339
|
32
32
|
odoo/addons/account_reconcile_oca/static/description/icon.png,sha256=6xBPJauaFOF0KDHfHgQopSc28kKvxMaeoQFQWZtfZDo,9455
|
33
|
-
odoo/addons/account_reconcile_oca/static/description/index.html,sha256=
|
33
|
+
odoo/addons/account_reconcile_oca/static/description/index.html,sha256=22cu8HmJ_WLzsK8e7Ek9LuNGcXNWFTy0w39ojI-WInU,13829
|
34
34
|
odoo/addons/account_reconcile_oca/static/src/js/reconcile/reconcile_controller.esm.js,sha256=Q_WFfEwl2q0Nr6cugeIt0ziVTZ7oFxM7UdcPzFP6FEs,4856
|
35
35
|
odoo/addons/account_reconcile_oca/static/src/js/reconcile/reconcile_kanban_record.esm.js,sha256=ewNK1VQgFZWccTiyJMKYkOG6KtbHHVnI2pdNy9kjkig,467
|
36
36
|
odoo/addons/account_reconcile_oca/static/src/js/reconcile/reconcile_renderer.esm.js,sha256=jm7p1yKiSw7oz32IZ_uwjFOMMz77sxicv-zPomVVt4U,2157
|
@@ -45,14 +45,14 @@ odoo/addons/account_reconcile_oca/static/src/js/reconcile_move_line/reconcile_mo
|
|
45
45
|
odoo/addons/account_reconcile_oca/static/src/js/reconcile_move_line/reconcile_move_line_renderer.esm.js,sha256=UhOEnNAeVyXR4v4c4kMTne6Rw9_y3IOXWo-jUn7Kx-Q,594
|
46
46
|
odoo/addons/account_reconcile_oca/static/src/js/reconcile_move_line/reconcile_move_line_view.esm.js,sha256=TFHNQB-A2wyBlfUHXpqKBt_-ICY0pbO90n4ao9dCVBI,510
|
47
47
|
odoo/addons/account_reconcile_oca/static/src/js/widgets/reconcile_chatter_field.esm.js,sha256=9vYBd7Nr-csZujbLx6VmdZOZ7T4JTtqrM7w4slrWzIw,541
|
48
|
-
odoo/addons/account_reconcile_oca/static/src/js/widgets/reconcile_data_widget.esm.js,sha256=
|
48
|
+
odoo/addons/account_reconcile_oca/static/src/js/widgets/reconcile_data_widget.esm.js,sha256=gP5XuA9D6KrHf_PPop1FoUVNAh88lV1L50FVjY6LB2k,3595
|
49
49
|
odoo/addons/account_reconcile_oca/static/src/js/widgets/reconcile_move_line_widget.esm.js,sha256=s_GHeElGkhsa2nQvd0eKxXdrsMPL2g0YfPC-REyUqew,1604
|
50
50
|
odoo/addons/account_reconcile_oca/static/src/js/widgets/selection_badge_uncheck.esm.js,sha256=zH2cqAerAF4cYDQMyMYTeFKoPIo1v_UmeFyPiwAz8tM,943
|
51
51
|
odoo/addons/account_reconcile_oca/static/src/scss/reconcile.scss,sha256=cQoernconYYErBp0nkOQOPeDq1NGDP9kds5r_q1nrk0,2809
|
52
|
-
odoo/addons/account_reconcile_oca/static/src/xml/reconcile.xml,sha256=
|
52
|
+
odoo/addons/account_reconcile_oca/static/src/xml/reconcile.xml,sha256=0ohTUpO2Jpo4Je-tsq2HCYMoRRukAz5kWlan_sWXgts,9327
|
53
53
|
odoo/addons/account_reconcile_oca/tests/__init__.py,sha256=8JhP4auByShS8Z_Ik5dShMuWdh1kBlYP_DLI4Ku8XWA,79
|
54
54
|
odoo/addons/account_reconcile_oca/tests/test_account_reconcile.py,sha256=opQs4FgChPdphc25Jzs07TuYxoVGBCj6IAPueMLNkH0,10576
|
55
|
-
odoo/addons/account_reconcile_oca/tests/test_bank_account_reconcile.py,sha256=
|
55
|
+
odoo/addons/account_reconcile_oca/tests/test_bank_account_reconcile.py,sha256=qsGtpSIeX1j-6I10NrquZ6rO-8KIBN8YG9bh4cSChmo,48412
|
56
56
|
odoo/addons/account_reconcile_oca/views/account_account.xml,sha256=Z6S9dDF2CnaSl8CYw69dxJiuVznJZzZX2BrhaDeMP3c,916
|
57
57
|
odoo/addons/account_reconcile_oca/views/account_account_reconcile.xml,sha256=yGOV7nOj5dVwp09ItOIfvNiBQrO_FpAC36gcnjI98JE,7066
|
58
58
|
odoo/addons/account_reconcile_oca/views/account_bank_statement.xml,sha256=e8ojLqYeZaMdTj-F0QdmFST4ICAlaKV66SJPkHXCdEU,2473
|
@@ -61,7 +61,7 @@ odoo/addons/account_reconcile_oca/views/account_journal.xml,sha256=WQGxMPgl4Um-I
|
|
61
61
|
odoo/addons/account_reconcile_oca/views/account_move.xml,sha256=qMXpycJJfaztyToulMmLY1NF2UDL2lcZM-m1tTiAoRY,995
|
62
62
|
odoo/addons/account_reconcile_oca/views/account_move_line.xml,sha256=BfObEwM6vXHMtxOFMOGDdCPOWO4ybz3w1_fm4_ufqM0,5274
|
63
63
|
odoo/addons/account_reconcile_oca/views/res_config_settings.xml,sha256=hL06Z_0Eg96LU6ta7VHRaheUDehJ6tVexBjU6X52Vng,1412
|
64
|
-
odoo_addon_account_reconcile_oca-16.0.2.
|
65
|
-
odoo_addon_account_reconcile_oca-16.0.2.
|
66
|
-
odoo_addon_account_reconcile_oca-16.0.2.
|
67
|
-
odoo_addon_account_reconcile_oca-16.0.2.
|
64
|
+
odoo_addon_account_reconcile_oca-16.0.2.2.0.dist-info/METADATA,sha256=pa9S0So2qSue2eCWjzzAB15Jv7XI4kciZ7x5lcEPKkw,4322
|
65
|
+
odoo_addon_account_reconcile_oca-16.0.2.2.0.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
66
|
+
odoo_addon_account_reconcile_oca-16.0.2.2.0.dist-info/top_level.txt,sha256=qBj40grFkGOfDZ2WDSw3y1RnDlgG0u8rP8pvGNdbz4w,5
|
67
|
+
odoo_addon_account_reconcile_oca-16.0.2.2.0.dist-info/RECORD,,
|
File without changes
|