From 4e7d8138876cdaa4f8fc225fb4eb2bc8316503fd Mon Sep 17 00:00:00 2001 From: jbw Date: Wed, 17 Nov 2021 14:33:15 +0000 Subject: [PATCH] Cherry pick of 673a66f5b81b36b2eef21153e2471f8d52bbf147 failed stdout: stderr: 17:35:39.225044 git.c:344 trace: built-in: git cherry-pick 673a66f5b81b36b2eef21153e2471f8d52bbf147 error: could not apply 673a66f5b81... [FIX] account: remove unused variables hint: after resolving the conflicts, mark the corrected paths hint: with 'git add ' or 'git rm ' hint: and commit the result with 'git commit' ---------- status: closes odoo/odoo#79971 Related: odoo/enterprise#22324 Signed-off-by: Olivier Colson --- addons/account/models/account_move.py | 49 ++++++++++++++++--- .../tests/test_account_move_reconcile.py | 1 + addons/point_of_sale/models/account_move.py | 10 ++++ 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index dc6a90caf7782..817f25c35adc6 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -2331,10 +2331,6 @@ def compute_tax_repartition_lines_mapping(move_vals): # invoice_repartition_line => refund_repartition_line mapping = {} - # Do nothing if the move is not a credit note. - if move_vals['move_type'] not in ('out_refund', 'in_refund'): - return mapping - for line_command in move_vals.get('line_ids', []): line_vals = line_command[2] # (0, 0, {...}) @@ -2352,9 +2348,33 @@ def compute_tax_repartition_lines_mapping(move_vals): mapping[inv_rep_line] = ref_rep_line return mapping + def invert_tags_if_needed(repartition_line, tags): + tax_type = repartition_line.tax_id.type_tax_use + tags_need_inversion = self._tax_tags_need_inversion( + self, + ( + (tax_type == 'purchase' and line_vals['credit'] > 0) or + (tax_type == 'sale' and line_vals['debit'] > 0) + ), + tax_type) + if tags_need_inversion: + return self.env['account.move.line']._revert_signed_tags(tags) + return tags + move_vals = self.with_context(include_business_fields=True).copy_data(default=default_values)[0] - tax_repartition_lines_mapping = compute_tax_repartition_lines_mapping(move_vals) + is_refund = False + if move_vals['move_type'] in ('out_refund', 'in_refund'): + is_refund = True + elif move_vals['move_type'] == 'entry': + base_lines = self.line_ids.filtered(lambda line: line.tax_ids) + tax_type = set(base_lines.tax_ids.mapped('type_tax_use')) + if tax_type == {'sale'} and sum(base_lines.mapped('debit')) == 0: + is_refund = True + elif tax_type == {'purchase'} and sum(base_lines.mapped('credit')) == 0: + is_refund = True + + tax_repartition_lines_mapping = compute_tax_repartition_lines_mapping(move_vals) if is_refund else {} for line_command in move_vals.get('line_ids', []): line_vals = line_command[2] # (0, 0, {...}) @@ -2369,7 +2389,7 @@ def compute_tax_repartition_lines_mapping(move_vals): 'credit': balance < 0.0 and -balance or 0.0, }) - if move_vals['move_type'] not in ('out_refund', 'in_refund'): + if not is_refund: continue # ==== Map tax repartition lines ==== @@ -2396,6 +2416,7 @@ def compute_tax_repartition_lines_mapping(move_vals): subsequent_taxes = self.env['account.tax'].browse(line_vals['tax_ids'][0][2]) tags += subsequent_taxes.refund_repartition_line_ids.filtered(lambda x: x.repartition_type == 'base').tag_ids + tags = invert_tags_if_needed(refund_repartition_line, tags) line_vals.update({ 'tax_repartition_line_id': refund_repartition_line.id, 'account_id': account_id, @@ -2410,7 +2431,11 @@ def compute_tax_repartition_lines_mapping(move_vals): refund_repartition_lines = invoice_repartition_lines\ .mapped(lambda line: tax_repartition_lines_mapping[line]) - line_vals['tax_tag_ids'] = [(6, 0, refund_repartition_lines.mapped('tag_ids').ids)] + tag_ids = [] + for refund_repartition_line in refund_repartition_lines: + tag_ids += invert_tags_if_needed(refund_repartition_line, refund_repartition_line.tag_ids).ids + + line_vals['tax_tag_ids'] = [(6, 0, tag_ids)] return move_vals def _reverse_moves(self, default_values_list=None, cancel=False): @@ -3867,7 +3892,7 @@ def _compute_tax_audit(self): # Cash basis entries are always treated as misc operations, applying the tag sign directly to the balance type_multiplicator = 1 else: - type_multiplicator = (record.journal_id.type == 'sale' and -1 or 1) * (self._get_refund_tax_audit_condition(record) and -1 or 1) + type_multiplicator = (record.journal_id.type == 'sale' and self._get_not_entry_condition(record) and -1 or 1) * (self._get_refund_tax_audit_condition(record) and -1 or 1) tag_amount = type_multiplicator * (tag.tax_negate and -1 or 1) * record.balance @@ -3883,6 +3908,14 @@ def _compute_tax_audit(self): record.tax_audit = audit_str + def _get_not_entry_condition(self, aml): + """ + Returns the condition to exclude entry move types to avoid their tax_audit value + to be revesed if they are from type entry. + This function is overridden in pos. + """ + return aml.move_id.move_type != 'entry' + def _get_refund_tax_audit_condition(self, aml): """ Returns the condition to be used for the provided move line to tell whether or not it comes from a refund operation. diff --git a/addons/account/tests/test_account_move_reconcile.py b/addons/account/tests/test_account_move_reconcile.py index 140d97d0fc6b6..39e337e643d68 100644 --- a/addons/account/tests/test_account_move_reconcile.py +++ b/addons/account/tests/test_account_move_reconcile.py @@ -1945,6 +1945,7 @@ def test_reconcile_cash_basis_exchange_difference_transfer_account_check_entries def test_reconcile_cash_basis_revert(self): ''' Ensure the cash basis journal entry can be reverted. ''' self.cash_basis_transfer_account.reconcile = True + self.cash_basis_tax_a_third_amount.cash_basis_transition_account_id = self.tax_account_1 invoice_move = self.env['account.move'].create({ 'move_type': 'entry', diff --git a/addons/point_of_sale/models/account_move.py b/addons/point_of_sale/models/account_move.py index 8bd57452e007c..f9cd288edd8e6 100644 --- a/addons/point_of_sale/models/account_move.py +++ b/addons/point_of_sale/models/account_move.py @@ -41,6 +41,16 @@ def _stock_account_get_anglo_saxon_price_unit(self): price_unit = order._get_pos_anglo_saxon_price_unit(self.product_id, self.move_id.partner_id.id, self.quantity) return price_unit + def _get_not_entry_condition(self, aml): + # Overridden so that sale entry moves created par POS still have their amount inverted + # in _compute_tax_audit() + rslt = super()._get_not_entry_condition(aml) + + sessions_count = self.env['pos.session'].search_count([('move_id', '=', aml.move_id.id)]) + pos_orders_count = self.env['pos.order'].search_count([('account_move', '=', aml.move_id.id)]) + + return rslt or (sessions_count + pos_orders_count) + def _get_refund_tax_audit_condition(self, aml): # Overridden so that the returns can be detected as credit notes by the tax audit computation rslt = super()._get_refund_tax_audit_condition(aml)