From 963419e82edc0c056658e7b3595d2ca56a5c0849 Mon Sep 17 00:00:00 2001 From: Carlos Dauden Date: Thu, 17 Oct 2024 23:52:27 +0200 Subject: [PATCH] [IMP] account_invoice_report_grouped_by_picking: Refactor code to simplify and remove OrderedDict From Python 3.7 dictionaries maintain the insertion order, so OrderedDict is unnecessary and adds overhead. --- .../models/account_move.py | 70 +++++++++---------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/account_invoice_report_grouped_by_picking/models/account_move.py b/account_invoice_report_grouped_by_picking/models/account_move.py index e75e66e2c..3e2ac376f 100644 --- a/account_invoice_report_grouped_by_picking/models/account_move.py +++ b/account_invoice_report_grouped_by_picking/models/account_move.py @@ -3,7 +3,6 @@ # Copyright 2018-2019 Tecnativa - Pedro M. Baeza # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import datetime -from collections import OrderedDict from odoo import api, models from odoo.tools import float_round @@ -15,7 +14,7 @@ class AccountMove(models.Model): @api.model def _sort_grouped_lines(self, lines_dic): min_date = datetime.datetime.min - dictionary = sorted( + return sorted( lines_dic, key=lambda x: ( ( @@ -25,30 +24,28 @@ def _sort_grouped_lines(self, lines_dic): ) ), ) - return dictionary def _get_signed_quantity_done(self, invoice_line, move, sign): """Hook method. Usage example: account_invoice_report_grouped_by_picking_sale_mrp module """ - qty = 0 if move.location_id.usage == "customer": - qty = -move.quantity_done * sign + return -move.quantity_done * sign elif move.location_dest_id.usage == "customer": - qty = move.quantity_done * sign - return qty + return move.quantity_done * sign + return 0 def _process_section_note_lines_grouped( self, previous_section, previous_note, lines_dic, pick_order=None ): - key_section = (pick_order, previous_section) if pick_order else previous_section - if previous_section and key_section not in lines_dic: - lines_dic[key_section] = 0.0 - key_note = (pick_order, previous_note) if pick_order else previous_note - if previous_note and key_note not in lines_dic: - lines_dic[key_note] = 0.0 + """Processes section and note lines, grouping them by order.""" + for line in [previous_section, previous_note]: + if line: + key = (pick_order, line) if pick_order else line + lines_dic.setdefault(key, 0.0) def _get_grouped_by_picking_sorted_lines(self): + """Sorts the invoice lines to be grouped by picking.""" return self.invoice_line_ids.sorted( lambda ln: (-ln.sequence, ln.date, ln.move_name, -ln.id), reverse=True ) @@ -57,9 +54,11 @@ def lines_grouped_by_picking(self): """This prepares a data structure for printing the invoice report grouped by pickings.""" self.ensure_one() - picking_dict = OrderedDict() - lines_dict = OrderedDict() + picking_dict = {} + lines_dict = {} picking_obj = self.env["stock.picking"] + + # Determine the sign based on the move type # Not change sign if the credit note has been created from reverse move option # and it has the same pickings related than the reversed invoice instead of sale # order invoicing process after picking reverse transfer @@ -79,19 +78,12 @@ def lines_grouped_by_picking(self): last_section_notes = [] sorted_lines = self._get_grouped_by_picking_sorted_lines() for line in sorted_lines: - if line.display_type == "line_section": - previous_section = line - last_section_notes.append( - { - "picking": picking_obj, - "line": line, - "qty": 0.0, - "is_last_section_notes": True, - } - ) - continue - if line.display_type == "line_note": - previous_note = line + # Process section or note lines + if line.display_type in ["line_section", "line_note"]: + if line.display_type == "line_section": + previous_section = line + else: + previous_note = line last_section_notes.append( { "picking": picking_obj, @@ -101,34 +93,40 @@ def lines_grouped_by_picking(self): } ) continue + + # Reset sections and notes when encountering a regular line last_section_notes = [] has_returned_qty = False remaining_qty = line.quantity + + # Process moves related to the line for move in line.move_line_ids: key = (move.picking_id, line) self._process_section_note_lines_grouped( previous_section, previous_note, picking_dict, move.picking_id ) picking_dict.setdefault(key, 0) - if move.location_id.usage == "customer": - has_returned_qty = True qty = self._get_signed_quantity_done(line, move, sign) picking_dict[key] += qty remaining_qty -= qty + if move.location_id.usage == "customer": + has_returned_qty = True + + # Process sale order lines without moves if not line.move_line_ids and line.sale_line_ids: for so_line in line.sale_line_ids: - if so_dict.get(so_line.order_id): - key = (so_dict[so_line.order_id], line) + picking = so_dict.get(so_line.order_id) + if picking: + key = (picking, line) self._process_section_note_lines_grouped( - previous_section, - previous_note, - picking_dict, - so_dict[so_line.order_id], + previous_section, previous_note, picking_dict, picking ) picking_dict.setdefault(key, 0) qty = so_line.product_uom_qty picking_dict[key] += qty remaining_qty -= qty + + # Process lines without moves or sale orders elif not line.move_line_ids and not line.sale_line_ids: key = (picking_obj, line) self._process_section_note_lines_grouped(