# Copyright 2022 Moduon # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). import logging from odoo import api, fields, models _logger = logging.getLogger(__name__) ADDON = "account_journal_general_sequence" class AccountMove(models.Model): _inherit = "account.move" _sql_constraints = [ ( "entry_number_unique", "UNIQUE(entry_number, journal_id)", "Entry number must be unique per journal.", ), ] entry_number = fields.Char( index=True, readonly=True, store=True, compute="_compute_entry_number", help="Automatic numbering, based on journal configuration.", ) @api.depends("state") def _compute_entry_number(self): """Assign an entry number when posting.""" # Skip if installing module, for performance reasons if self.env.context.get("module") == ADDON: module = self.env["ir.module.module"].search([("name", "=", ADDON)]) if module.state == "to install": _logger.info( "Skipping entry number generation at install for %s.", self, ) return canceled = self.filtered_domain( [("state", "=", "cancel"), ("entry_number", "!=", False)] ) canceled.entry_number = False if canceled: no_gap_seqs = canceled.mapped( "journal_id.entry_number_sequence_id" ).filtered_domain([("implementation", "=", "no_gap")]) if no_gap_seqs: _logger.warning( "Emptied entry_number for %r after cancellation. " "This created gaps on %r.", canceled, no_gap_seqs, ) chosen = self.filtered_domain( [("state", "=", "posted"), ("entry_number", "=", False)] ) # Cache all the new numbers to avoid wasting recomputations, caused by # searches done by _next() in the loop below chosen_map = {} for move in chosen.sorted( lambda one: (one.date or "", one.name or "", one.id or 0) ): chosen_map[move.id] = move.journal_id.entry_number_sequence_id._next( move.date ) # Write all the new numbers in the chosen moves for move_id, new_number in chosen_map.items(): self.browse(move_id).entry_number = new_number if chosen: _logger.info("Added entry_number to %d account moves", len(chosen)) _logger.debug("Added entry_number to %r", chosen)