From 56704c19d6f40b0a7b647966fd972703d0b9b8d0 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 23 Aug 2017 17:58:42 +0200 Subject: [PATCH] [FIX] account: iteration different under ordereddict mutation Did you know that if you iterate on an OrderedDict in Python 2 and add to the dict during iteration, the new items will be iterated? No? Me neither. And did you know that that does not work in Python 3 likely because OrderedDict's implementation details changed? Why the fuck would anyone do that and thus why would we care you ask? WELL WE FUCKING DO IT TURNS OUT and that breaks test_partial_reconcile_currencies on Python 3... Fix it, try to make it more obvious that we're doing weird crap instead of abusing OrderedDict in ways it was never meant to be used. --- addons/account/models/account_move.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index 34a18555049..6139f36bb19 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -1722,17 +1722,20 @@ class AccountPartialReconcile(models.Model): return self #check if the reconcilation is full #first, gather all journal items involved in the reconciliation just created - partial_rec_set = OrderedDict.fromkeys([x for x in self]) aml_set = aml_to_balance = self.env['account.move.line'] total_debit = 0 total_credit = 0 total_amount_currency = 0 #make sure that all partial reconciliations share the same secondary currency otherwise it's not #possible to compute the exchange difference entry and it has to be done manually. - currency = list(partial_rec_set)[0].currency_id + currency = self[0].currency_id maxdate = '0000-00-00' - for partial_rec in partial_rec_set: + seen = set() + todo = set(self) + while todo: + partial_rec = todo.pop() + seen.add(partial_rec) if partial_rec.currency_id != currency: #no exchange rate entry will be created currency = None @@ -1751,13 +1754,15 @@ class AccountPartialReconcile(models.Model): #currency is recorded on the partial rec and in order to check if the reconciliation is total, we need to convert the #aml.balance in that foreign currency total_amount_currency += aml.company_id.currency_id.with_context(date=aml.date).compute(aml.balance, partial_rec.currency_id) + for x in aml.matched_debit_ids | aml.matched_credit_ids: - partial_rec_set[x] = None - partial_rec_ids = [x.id for x in partial_rec_set] + if x not in seen: + todo.add(x) + + partial_rec_ids = [x.id for x in seen] aml_ids = aml_set.ids #then, if the total debit and credit are equal, or the total amount in currency is 0, the reconciliation is full digits_rounding_precision = aml_set[0].company_id.currency_id.rounding - if (currency and float_is_zero(total_amount_currency, precision_rounding=currency.rounding)) or float_compare(total_debit, total_credit, precision_rounding=digits_rounding_precision) == 0: exchange_move_id = False exchange_partial_rec_id = False