odoo-addon-account-reconcile-oca 17.0.1.5.3__py3-none-any.whl → 17.0.1.5.5__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.
Files changed (18) hide show
  1. odoo/addons/account_reconcile_oca/README.rst +1 -1
  2. odoo/addons/account_reconcile_oca/__manifest__.py +1 -1
  3. odoo/addons/account_reconcile_oca/i18n/account_reconcile_oca.pot +7 -0
  4. odoo/addons/account_reconcile_oca/i18n/es.po +8 -1
  5. odoo/addons/account_reconcile_oca/models/account_account_reconcile.py +21 -9
  6. odoo/addons/account_reconcile_oca/models/account_bank_statement_line.py +331 -52
  7. odoo/addons/account_reconcile_oca/models/account_reconcile_abstract.py +42 -14
  8. odoo/addons/account_reconcile_oca/static/description/index.html +1 -1
  9. odoo/addons/account_reconcile_oca/static/src/js/reconcile_move_line/reconcile_move_line_controller.esm.js +9 -0
  10. odoo/addons/account_reconcile_oca/static/src/js/reconcile_move_line/reconcile_move_line_view.esm.js +1 -0
  11. odoo/addons/account_reconcile_oca/static/src/js/widgets/reconcile_data_widget.esm.js +12 -0
  12. odoo/addons/account_reconcile_oca/static/src/js/widgets/reconcile_move_line_widget.esm.js +2 -1
  13. odoo/addons/account_reconcile_oca/static/src/xml/reconcile.xml +15 -1
  14. odoo/addons/account_reconcile_oca/tests/test_bank_account_reconcile.py +214 -47
  15. {odoo_addon_account_reconcile_oca-17.0.1.5.3.dist-info → odoo_addon_account_reconcile_oca-17.0.1.5.5.dist-info}/METADATA +2 -2
  16. {odoo_addon_account_reconcile_oca-17.0.1.5.3.dist-info → odoo_addon_account_reconcile_oca-17.0.1.5.5.dist-info}/RECORD +18 -18
  17. {odoo_addon_account_reconcile_oca-17.0.1.5.3.dist-info → odoo_addon_account_reconcile_oca-17.0.1.5.5.dist-info}/WHEEL +0 -0
  18. {odoo_addon_account_reconcile_oca-17.0.1.5.3.dist-info → odoo_addon_account_reconcile_oca-17.0.1.5.5.dist-info}/top_level.txt +0 -0
@@ -8,7 +8,8 @@ from dateutil.relativedelta import relativedelta
8
8
 
9
9
  from odoo import Command, _, api, fields, models, tools
10
10
  from odoo.exceptions import UserError
11
- from odoo.tools import float_is_zero
11
+ from odoo.fields import first
12
+ from odoo.tools import float_compare, float_is_zero
12
13
 
13
14
 
14
15
  class AccountBankStatementLine(models.Model):
@@ -178,41 +179,63 @@ class AccountBankStatementLine(models.Model):
178
179
  )._default_reconcile_data()
179
180
  self.can_reconcile = self.reconcile_data_info.get("can_reconcile", False)
180
181
 
182
+ def _get_amount_currency(self, line, dest_curr):
183
+ if line["line_currency_id"] == dest_curr.id:
184
+ amount = line["currency_amount"]
185
+ else:
186
+ amount = self.company_id.currency_id._convert(
187
+ line["amount"],
188
+ dest_curr,
189
+ self.company_id,
190
+ self.date,
191
+ )
192
+ return amount
193
+
181
194
  @api.onchange("add_account_move_line_id")
182
195
  def _onchange_add_account_move_line_id(self):
183
196
  if self.add_account_move_line_id:
184
- data = self.reconcile_data_info["data"]
185
- new_data = []
186
- is_new_line = True
187
- pending_amount = 0.0
188
- for line in data:
189
- if line["kind"] != "suspense":
190
- pending_amount += line["amount"]
191
- if self.add_account_move_line_id.id in line.get(
192
- "counterpart_line_ids", []
193
- ):
194
- is_new_line = False
195
- else:
197
+ self._add_account_move_line(self.add_account_move_line_id)
198
+ self.add_account_move_line_id = False
199
+
200
+ def _add_account_move_line(self, move_line, keep_current=False):
201
+ data = self.reconcile_data_info["data"]
202
+ new_data = []
203
+ is_new_line = True
204
+ pending_amount = 0.0
205
+ currency = self._get_reconcile_currency()
206
+ for line in data:
207
+ if line["kind"] != "suspense":
208
+ pending_amount += self._get_amount_currency(line, currency)
209
+ if move_line.id in line.get("counterpart_line_ids", []):
210
+ is_new_line = False
211
+ if keep_current:
196
212
  new_data.append(line)
197
- if is_new_line:
198
- reconcile_auxiliary_id, lines = self._get_reconcile_line(
199
- self.add_account_move_line_id, "other", True, pending_amount
200
- )
201
- new_data += lines
202
- self.reconcile_data_info = self._recompute_suspense_line(
203
- new_data,
204
- self.reconcile_data_info["reconcile_auxiliary_id"],
205
- self.manual_reference,
213
+ else:
214
+ new_data.append(line)
215
+ if is_new_line:
216
+ reconcile_auxiliary_id, lines = self._get_reconcile_line(
217
+ move_line,
218
+ "other",
219
+ is_counterpart=True,
220
+ max_amount=currency.round(pending_amount),
221
+ move=True,
206
222
  )
207
- self.can_reconcile = self.reconcile_data_info.get("can_reconcile", False)
208
- self.add_account_move_line_id = False
223
+ new_data += lines
224
+ self.reconcile_data_info = self._recompute_suspense_line(
225
+ new_data,
226
+ self.reconcile_data_info["reconcile_auxiliary_id"],
227
+ self.manual_reference,
228
+ )
229
+ self.can_reconcile = self.reconcile_data_info.get("can_reconcile", False)
209
230
 
210
231
  def _recompute_suspense_line(self, data, reconcile_auxiliary_id, manual_reference):
211
232
  can_reconcile = True
212
233
  total_amount = 0
234
+ currency_amount = 0
213
235
  new_data = []
214
236
  suspense_line = False
215
237
  counterparts = []
238
+ suspense_currency = self.foreign_currency_id or self.currency_id
216
239
  for line in data:
217
240
  if line.get("counterpart_line_ids"):
218
241
  counterparts += line["counterpart_line_ids"]
@@ -224,10 +247,29 @@ class AccountBankStatementLine(models.Model):
224
247
  if line["kind"] != "suspense":
225
248
  new_data.append(line)
226
249
  total_amount += line["amount"]
250
+ if not line.get("is_exchange_counterpart"):
251
+ # case of statement line with foreign_currency
252
+ if (
253
+ line["kind"] == "liquidity"
254
+ and line["line_currency_id"] != suspense_currency.id
255
+ ):
256
+ currency_amount += self.amount_currency
257
+ elif (
258
+ line.get("currency_amount")
259
+ and line.get("line_currency_id") == suspense_currency.id
260
+ ):
261
+ currency_amount += line.get("currency_amount")
262
+ else:
263
+ currency_amount += self.company_id.currency_id._convert(
264
+ line["amount"],
265
+ suspense_currency,
266
+ self.company_id,
267
+ self.date,
268
+ )
227
269
  else:
228
270
  suspense_line = line
229
271
  if not float_is_zero(
230
- total_amount, precision_digits=self.currency_id.decimal_places
272
+ total_amount, precision_digits=self.company_id.currency_id.decimal_places
231
273
  ):
232
274
  can_reconcile = False
233
275
  if suspense_line:
@@ -236,6 +278,7 @@ class AccountBankStatementLine(models.Model):
236
278
  "amount": -total_amount,
237
279
  "credit": total_amount if total_amount > 0 else 0.0,
238
280
  "debit": -total_amount if total_amount < 0 else 0.0,
281
+ "currency_amount": -currency_amount,
239
282
  }
240
283
  )
241
284
  else:
@@ -261,8 +304,8 @@ class AccountBankStatementLine(models.Model):
261
304
  "debit": -total_amount if total_amount < 0 else 0.0,
262
305
  "kind": "suspense",
263
306
  "currency_id": self.company_id.currency_id.id,
264
- "line_currency_id": self.company_id.currency_id.id,
265
- "currency_amount": -total_amount,
307
+ "line_currency_id": suspense_currency.id,
308
+ "currency_amount": -currency_amount,
266
309
  }
267
310
  reconcile_auxiliary_id += 1
268
311
  new_data.append(suspense_line)
@@ -282,11 +325,37 @@ class AccountBankStatementLine(models.Model):
282
325
  )
283
326
  or self.manual_account_id.id != line["account_id"][0]
284
327
  or self.manual_name != line["name"]
285
- or (self.manual_partner_id and self.manual_partner_id.display_name or False)
328
+ or (
329
+ self.manual_partner_id
330
+ and [self.manual_partner_id.id, self.manual_partner_id.display_name]
331
+ or [False, False]
332
+ )
286
333
  != line.get("partner_id")
287
334
  or self.analytic_distribution != line.get("analytic_distribution", False)
288
335
  )
289
336
 
337
+ def _check_reconcile_data_changed(self):
338
+ self.ensure_one()
339
+ data = self.reconcile_data_info.get("data", [])
340
+ liquidity_lines, _suspense_lines, _other_lines = self._seek_for_lines()
341
+ move_amount_cur = sum(liquidity_lines.mapped("amount_currency"))
342
+ move_credit = sum(liquidity_lines.mapped("credit"))
343
+ move_debit = sum(liquidity_lines.mapped("debit"))
344
+ stmt_amount_curr = stmt_debit = stmt_credit = 0.0
345
+ for line_data in data:
346
+ if line_data["kind"] != "liquidity":
347
+ continue
348
+ stmt_amount_curr += line_data["currency_amount"]
349
+ stmt_debit += line_data["debit"]
350
+ stmt_credit += line_data["credit"]
351
+ prec = self.currency_id.rounding
352
+ return (
353
+ float_compare(move_amount_cur, move_amount_cur, precision_rounding=prec)
354
+ != 0
355
+ or float_compare(move_credit, stmt_credit, precision_rounding=prec) != 0
356
+ or float_compare(move_debit, stmt_debit, precision_rounding=prec) != 0
357
+ )
358
+
290
359
  def _get_manual_delete_vals(self):
291
360
  return {
292
361
  "manual_reference": False,
@@ -362,7 +431,11 @@ class AccountBankStatementLine(models.Model):
362
431
 
363
432
  @api.onchange("manual_amount_in_currency")
364
433
  def _onchange_manual_amount_in_currency(self):
365
- if self.manual_line_id.exists() and self.manual_line_id:
434
+ if (
435
+ self.manual_line_id.exists()
436
+ and self.manual_line_id
437
+ and self.manual_kind != "liquidity"
438
+ ):
366
439
  self.manual_amount = self.manual_in_currency_id._convert(
367
440
  self.manual_amount_in_currency,
368
441
  self.company_id.currency_id,
@@ -372,7 +445,7 @@ class AccountBankStatementLine(models.Model):
372
445
  self._onchange_manual_reconcile_vals()
373
446
 
374
447
  def _get_manual_reconcile_vals(self):
375
- return {
448
+ vals = {
376
449
  "name": self.manual_name,
377
450
  "partner_id": (
378
451
  self.manual_partner_id
@@ -390,6 +463,19 @@ class AccountBankStatementLine(models.Model):
390
463
  "debit": self.manual_amount if self.manual_amount > 0 else 0.0,
391
464
  "analytic_distribution": self.analytic_distribution,
392
465
  }
466
+ liquidity_lines, _suspense_lines, _other_lines = self._seek_for_lines()
467
+ if self.manual_line_id and self.manual_line_id.id not in liquidity_lines.ids:
468
+ vals.update(
469
+ {
470
+ "currency_amount": self.manual_currency_id._convert(
471
+ self.manual_amount,
472
+ self.manual_in_currency_id,
473
+ self.company_id,
474
+ self.manual_line_id.date,
475
+ ),
476
+ }
477
+ )
478
+ return vals
393
479
 
394
480
  @api.onchange(
395
481
  "manual_account_id",
@@ -472,6 +558,8 @@ class AccountBankStatementLine(models.Model):
472
558
  def _reconcile_data_by_model(self, data, reconcile_model, reconcile_auxiliary_id):
473
559
  new_data = []
474
560
  liquidity_amount = 0.0
561
+ currency = self._get_reconcile_currency()
562
+ currency_amount = False
475
563
  for line_data in data:
476
564
  if line_data["kind"] == "suspense":
477
565
  continue
@@ -484,8 +572,18 @@ class AccountBankStatementLine(models.Model):
484
572
  new_line = line.copy()
485
573
  amount = line.get("balance")
486
574
  if self.foreign_currency_id:
487
- amount = self.foreign_currency_id.compute(
488
- amount, self.journal_id.currency_id or self.company_currency_id
575
+ amount = self.foreign_currency_id._convert(
576
+ amount,
577
+ self.journal_id.currency_id or self.company_currency_id,
578
+ self.company_id,
579
+ self.date,
580
+ )
581
+ if currency != self.company_id.currency_id:
582
+ currency_amount = self.company_id.currency_id._convert(
583
+ amount,
584
+ currency,
585
+ self.company_id,
586
+ self.date,
489
587
  )
490
588
  new_line.update(
491
589
  {
@@ -502,9 +600,9 @@ class AccountBankStatementLine(models.Model):
502
600
  .display_name,
503
601
  ],
504
602
  "date": fields.Date.to_string(self.date),
505
- "line_currency_id": self.company_id.currency_id.id,
603
+ "line_currency_id": currency.id,
506
604
  "currency_id": self.company_id.currency_id.id,
507
- "currency_amount": amount,
605
+ "currency_amount": currency_amount or amount,
508
606
  "name": line.get("name") or self.payment_ref,
509
607
  }
510
608
  )
@@ -525,7 +623,10 @@ class AccountBankStatementLine(models.Model):
525
623
  reconcile_auxiliary_id = 1
526
624
  for line in liquidity_lines:
527
625
  reconcile_auxiliary_id, lines = self._get_reconcile_line(
528
- line, "liquidity", reconcile_auxiliary_id=reconcile_auxiliary_id
626
+ line,
627
+ "liquidity",
628
+ reconcile_auxiliary_id=reconcile_auxiliary_id,
629
+ move=True,
529
630
  )
530
631
  data += lines
531
632
  if not from_unreconcile:
@@ -551,6 +652,7 @@ class AccountBankStatementLine(models.Model):
551
652
  self.manual_reference,
552
653
  )
553
654
  elif res and res.get("amls"):
655
+ # TODO should be signed in currency get_reconcile_currency
554
656
  amount = self.amount_total_signed
555
657
  for line in res.get("amls", []):
556
658
  reconcile_auxiliary_id, line_data = self._get_reconcile_line(
@@ -570,16 +672,89 @@ class AccountBankStatementLine(models.Model):
570
672
  self.manual_reference,
571
673
  )
572
674
  for line in other_lines:
573
- reconcile_auxiliary_id, lines = self._get_reconcile_line(
574
- line, "other", from_unreconcile=from_unreconcile
575
- )
576
- data += lines
675
+ partial_lines = self._all_partials_lines(line) if from_unreconcile else []
676
+ if partial_lines:
677
+ for reconciled_line in (
678
+ partial_lines.debit_move_id + partial_lines.credit_move_id - line
679
+ ):
680
+ if (
681
+ reconciled_line.move_id.journal_id
682
+ == self.company_id.currency_exchange_journal_id
683
+ ):
684
+ reconcile_auxiliary_id, lines = self._get_reconcile_line(
685
+ reconciled_line.move_id.line_ids - reconciled_line,
686
+ "other",
687
+ from_unreconcile=False,
688
+ move=True,
689
+ )
690
+ data += lines
691
+ continue
692
+ partial = partial_lines.filtered(
693
+ lambda r, line=reconciled_line: r.debit_move_id == line
694
+ or r.credit_move_id == line
695
+ )
696
+ partial_amount = sum(
697
+ partial.filtered(
698
+ lambda r, line=reconciled_line: r.credit_move_id == line
699
+ ).mapped("amount")
700
+ ) - sum(
701
+ partial.filtered(
702
+ lambda r, line=reconciled_line: r.debit_move_id == line
703
+ ).mapped("amount")
704
+ )
705
+ reconcile_auxiliary_id, lines = self._get_reconcile_line(
706
+ reconciled_line,
707
+ "other",
708
+ from_unreconcile={
709
+ "amount": partial_amount,
710
+ "credit": partial_amount > 0 and partial_amount,
711
+ "debit": partial_amount < 0 and -partial_amount,
712
+ "currency_amount": sum(
713
+ partial.filtered(
714
+ lambda r, line=reconciled_line: r.credit_move_id
715
+ == line
716
+ ).mapped("credit_amount_currency")
717
+ )
718
+ - sum(
719
+ partial.filtered(
720
+ lambda r, line=reconciled_line: r.debit_move_id
721
+ == line
722
+ ).mapped("debit_amount_currency")
723
+ ),
724
+ },
725
+ move=True,
726
+ )
727
+ data += lines
728
+ else:
729
+ reconcile_auxiliary_id, lines = self._get_reconcile_line(
730
+ line, "other", from_unreconcile=False
731
+ )
732
+ data += lines
733
+
577
734
  return self._recompute_suspense_line(
578
735
  data,
579
736
  reconcile_auxiliary_id,
580
737
  self.manual_reference,
581
738
  )
582
739
 
740
+ def _all_partials_lines(self, lines):
741
+ reconciliation_lines = lines.filtered(
742
+ lambda x: x.account_id.reconcile
743
+ or x.account_id.account_type in ("asset_cash", "liability_credit_card")
744
+ )
745
+ current_lines = reconciliation_lines
746
+ current_partials = self.env["account.partial.reconcile"]
747
+ partials = self.env["account.partial.reconcile"]
748
+ while current_lines:
749
+ current_partials = (
750
+ current_lines.matched_debit_ids + current_lines.matched_credit_ids
751
+ ) - current_partials
752
+ current_lines = (
753
+ current_partials.debit_move_id + current_partials.credit_move_id
754
+ ) - current_lines
755
+ partials += current_partials
756
+ return partials
757
+
583
758
  def clean_reconcile(self):
584
759
  self.reconcile_data_info = self._default_reconcile_data()
585
760
  self.can_reconcile = self.reconcile_data_info.get("can_reconcile", False)
@@ -734,12 +909,13 @@ class AccountBankStatementLine(models.Model):
734
909
  to_reverse._reverse_moves(default_values_list, cancel=True)
735
910
 
736
911
  def _reconcile_move_line_vals(self, line, move_id=False):
737
- return {
912
+ vals = {
738
913
  "move_id": move_id or self.move_id.id,
739
914
  "account_id": line["account_id"][0],
740
915
  "partner_id": line.get("partner_id") and line["partner_id"][0],
741
916
  "credit": line["credit"],
742
917
  "debit": line["debit"],
918
+ "currency_id": line.get("line_currency_id", self.company_id.currency_id.id),
743
919
  "tax_ids": line.get("tax_ids", []),
744
920
  "tax_tag_ids": line.get("tax_tag_ids", []),
745
921
  "group_tax_id": line.get("group_tax_id"),
@@ -748,6 +924,11 @@ class AccountBankStatementLine(models.Model):
748
924
  "name": line.get("name"),
749
925
  "reconcile_model_id": line.get("reconcile_model_id"),
750
926
  }
927
+ if line.get("line_currency_id") and line["currency_id"] != line.get(
928
+ "line_currency_id"
929
+ ):
930
+ vals["amount_currency"] = line["currency_amount"]
931
+ return vals
751
932
 
752
933
  @api.model_create_multi
753
934
  def create(self, mvals):
@@ -771,7 +952,9 @@ class AccountBankStatementLine(models.Model):
771
952
  data = []
772
953
  for line in liquidity_lines:
773
954
  reconcile_auxiliary_id, lines = record._get_reconcile_line(
774
- line, "liquidity"
955
+ line,
956
+ "liquidity",
957
+ move=True,
775
958
  )
776
959
  data += lines
777
960
  reconcile_auxiliary_id = 1
@@ -783,10 +966,10 @@ class AccountBankStatementLine(models.Model):
783
966
  self.manual_reference,
784
967
  )
785
968
  elif res.get("amls"):
786
- amount = self.amount
969
+ amount = self.amount_currency or self.amount
787
970
  for line in res.get("amls", []):
788
971
  reconcile_auxiliary_id, line_datas = record._get_reconcile_line(
789
- line, "other", is_counterpart=True, max_amount=amount
972
+ line, "other", is_counterpart=True, max_amount=amount, move=True
790
973
  )
791
974
  amount -= sum(line_data.get("amount") for line_data in line_datas)
792
975
  data += line_datas
@@ -802,6 +985,67 @@ class AccountBankStatementLine(models.Model):
802
985
  )(self._prepare_reconcile_line_data(data["data"]))
803
986
  return result
804
987
 
988
+ def _synchronize_to_moves(self, changed_fields):
989
+ """We want to avoid to change stuff (mainly amounts ) in accounting entries
990
+ when some changes happen in the reconciliation widget. The only change
991
+ (among the fields triggering the synchronization) possible from the
992
+ reconciliation widget is the partner_id field.
993
+
994
+ So, in case of change on partner_id field we do not call super but make
995
+ only the required change (relative to partner) on accounting entries.
996
+
997
+ And if something else changes, we then re-define reconcile_data_info to
998
+ make the data consistent (for example, if debit/credit has changed by
999
+ applying a different rate or even if there was a correction on statement
1000
+ line amount).
1001
+ """
1002
+ if self._context.get("skip_account_move_synchronization"):
1003
+ return
1004
+ if "partner_id" in changed_fields and not any(
1005
+ field_name in changed_fields
1006
+ for field_name in (
1007
+ "payment_ref",
1008
+ "amount",
1009
+ "amount_currency",
1010
+ "foreign_currency_id",
1011
+ "currency_id",
1012
+ )
1013
+ ):
1014
+ for st_line in self.with_context(skip_account_move_synchronization=True):
1015
+ (
1016
+ liquidity_lines,
1017
+ suspense_lines,
1018
+ _other_lines,
1019
+ ) = st_line._seek_for_lines()
1020
+ line_vals = {"partner_id": st_line.partner_id}
1021
+ line_ids_commands = [(1, liquidity_lines.id, line_vals)]
1022
+ if suspense_lines:
1023
+ line_ids_commands.append((1, suspense_lines.id, line_vals))
1024
+ st_line_vals = {"line_ids": line_ids_commands}
1025
+ if st_line.move_id.partner_id != st_line.partner_id:
1026
+ st_line_vals["partner_id"] = st_line.partner_id.id
1027
+ st_line.move_id.write(st_line_vals)
1028
+ else:
1029
+ super()._synchronize_to_moves(changed_fields=changed_fields)
1030
+
1031
+ if not any(
1032
+ field_name in changed_fields
1033
+ for field_name in (
1034
+ "payment_ref",
1035
+ "amount",
1036
+ "amount_currency",
1037
+ "foreign_currency_id",
1038
+ "currency_id",
1039
+ "partner_id",
1040
+ )
1041
+ ):
1042
+ return
1043
+ # reset reconcile_data_info if amounts are not consistent anymore with the
1044
+ # amounts of the accounting entries
1045
+ for st_line in self:
1046
+ if st_line._check_reconcile_data_changed():
1047
+ st_line.reconcile_data_info = st_line._default_reconcile_data()
1048
+
805
1049
  def _prepare_reconcile_line_data(self, lines):
806
1050
  new_lines = []
807
1051
  reverse_lines = {}
@@ -848,6 +1092,7 @@ class AccountBankStatementLine(models.Model):
848
1092
  is_counterpart=True,
849
1093
  reconcile_auxiliary_id=reconcile_auxiliary_id,
850
1094
  max_amount=original_amount,
1095
+ move=True,
851
1096
  )
852
1097
  new_data += lines
853
1098
  new_data.append(
@@ -895,6 +1140,7 @@ class AccountBankStatementLine(models.Model):
895
1140
  max_amount=False,
896
1141
  from_unreconcile=False,
897
1142
  reconcile_auxiliary_id=False,
1143
+ move=False,
898
1144
  ):
899
1145
  new_vals = super()._get_reconcile_line(
900
1146
  line,
@@ -902,29 +1148,48 @@ class AccountBankStatementLine(models.Model):
902
1148
  is_counterpart=is_counterpart,
903
1149
  max_amount=max_amount,
904
1150
  from_unreconcile=from_unreconcile,
1151
+ move=move,
905
1152
  )
906
1153
  rates = []
907
1154
  for vals in new_vals:
1155
+ rate = False
908
1156
  if vals["partner_id"] is False:
909
1157
  vals["partner_id"] = (False, self.partner_name)
910
- reconcile_auxiliary_id, rate = self._compute_exchange_rate(
911
- vals, line, reconcile_auxiliary_id
912
- )
1158
+ if vals.get("kind") not in ("suspense", "liquidity"):
1159
+ reconcile_auxiliary_id, rate = self._compute_exchange_rate(
1160
+ vals, line, reconcile_auxiliary_id
1161
+ )
913
1162
  if rate:
914
1163
  rates.append(rate)
915
1164
  new_vals += rates
916
1165
  return reconcile_auxiliary_id, new_vals
917
1166
 
918
1167
  def _get_exchange_rate_amount(self, amount, currency_amount, currency, line):
919
- return (
920
- currency._convert(
1168
+ if self.foreign_currency_id == currency:
1169
+ # take real rate of statement line to compute the exchange rate gain/loss
1170
+ real_rate = self.amount / self.amount_currency
1171
+ to_amount_journal_currency = currency_amount * real_rate
1172
+ to_amount_company_currency = self.currency_id._convert(
1173
+ to_amount_journal_currency,
1174
+ self.company_id.currency_id,
1175
+ self.company_id,
1176
+ self.date,
1177
+ )
1178
+ to_amount = self.company_id.currency_id.round(to_amount_company_currency)
1179
+ elif self.currency_id == currency and not self.foreign_currency_id:
1180
+ liquidity_lines, _suspense_lines, _other_lines = self._seek_for_lines()
1181
+ real_rate = (
1182
+ first(liquidity_lines).balance / first(liquidity_lines).amount_currency
1183
+ )
1184
+ to_amount = self.company_id.currency_id.round(currency_amount * real_rate)
1185
+ else:
1186
+ to_amount = currency._convert(
921
1187
  currency_amount,
922
1188
  self.company_id.currency_id,
923
1189
  self.company_id,
924
1190
  self.date,
925
1191
  )
926
- - amount
927
- )
1192
+ return self.company_id.currency_id.round(to_amount - amount)
928
1193
 
929
1194
  def _compute_exchange_rate(
930
1195
  self,
@@ -963,8 +1228,8 @@ class AccountBankStatementLine(models.Model):
963
1228
  "debit": amount if amount > 0 else 0.0,
964
1229
  "kind": "other",
965
1230
  "currency_id": self.company_id.currency_id.id,
966
- "line_currency_id": self.company_id.currency_id.id,
967
- "currency_amount": amount,
1231
+ "line_currency_id": currency.id,
1232
+ "currency_amount": 0,
968
1233
  }
969
1234
  reconcile_auxiliary_id += 1
970
1235
  return reconcile_auxiliary_id, data
@@ -991,3 +1256,17 @@ class AccountBankStatementLine(models.Model):
991
1256
  "split_line_id": self.id,
992
1257
  }
993
1258
  return action
1259
+
1260
+ def _get_reconcile_currency(self):
1261
+ return (
1262
+ self.foreign_currency_id
1263
+ or self.journal_id.currency_id
1264
+ or self.company_id.currency_id
1265
+ )
1266
+
1267
+ def add_multiple_lines(self, domain):
1268
+ res = super().add_multiple_lines(domain)
1269
+ lines = self.env["account.move.line"].search(domain)
1270
+ for line in lines:
1271
+ self._add_account_move_line(line, keep_current=True)
1272
+ return res