Skip to content

Commit

Permalink
prod_lot_seq: Fix sequence incrementation opening detailed operations
Browse files Browse the repository at this point in the history
When opening the detailed operations view of a stock move, Odoo is calling
stock.production.lot._get_next_serial to set stock.move.next_serial field
anytime the product is tracked by serial and the move is assigned.

If we use this module with product or global policy, the respective sequence
will therefore be called and incremented anytime this view is open, even
if the picking is not creating lots (e.g. delivery orders or internal transfers)

To avoid incrementing the sequence unnecessarily, we only allow to get the next
sequence number the first time this view is opened and if the move has
to create new serial numbers.
Otherwise, we force the value to be set to stock.move.next_serial field to
an empty string if no serial has to be created through this move, or to the
next_serial value assigned on the first opening of the view.
  • Loading branch information
grindtildeath authored and vvrossem committed Mar 20, 2024
1 parent 28db8a2 commit c4fefff
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 12 deletions.
17 changes: 16 additions & 1 deletion product_lot_sequence/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Product Lot Sequence
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:dfe9a2666cd1599203c70fd159399022104a8f2df4808574a961f49e93399cf1
!! source digest: sha256:c497d170778ffa1220e7cd95c340001c2d7caad3c29559a226d0bd3bc9d5d6fb
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
Expand Down Expand Up @@ -73,6 +73,21 @@ To use this module:
* Create new Lot/Serial number
* Select the product and the next number of the product sequence will be automatically proposed

Known issues / Roadmap
======================

* There is an issue with the use of ir.sequence with the newer version of Odoo.

Mostly, when opening the detailed operations of an assigned picking for a product
tracked by serial numbers, Odoo systematically calls `_get_next_serial` even
if there is not any serial number to generate.
Moreover, the widget allowing to generate the serial numbers will not call
the sequence but only increment the number according to the next serial,
potentially leading to a sequence that is not in sync anymore with the created
serial numbers.

cf https://github.com/OCA/product-attribute/issues/1326

Bug Tracker
===========

Expand Down
1 change: 1 addition & 0 deletions product_lot_sequence/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
from . import product
from . import res_config_settings
from . import stock_lot
from . import stock_move
2 changes: 2 additions & 0 deletions product_lot_sequence/models/stock_lot.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ def create(self, vals_list):

@api.model
def _get_next_serial(self, company, product):
if "force_next_serial" in self.env.context:
return self.env.context.get("force_next_serial")
seq_policy = self._get_sequence_policy()
if seq_policy == "product":
seq = product.product_tmpl_id.lot_sequence_id
Expand Down
23 changes: 23 additions & 0 deletions product_lot_sequence/models/stock_move.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2023 Camptocamp SA
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
from odoo import models


class StockMove(models.Model):
_inherit = "stock.move"

def action_show_details(self):
"""Avoid calling and incrementing the sequence if not needed or already done"""
seq_policy = self.env["stock.production.lot"]._get_sequence_policy()
if seq_policy in ("product", "global"):
# If move is not supposed to assign serial pass empty string for next serial
if not self.display_assign_serial:
return super(
StockMove, self.with_context(force_next_serial="")
).action_show_details()
# If the sequence was already called once, avoid calling it another time
elif self.next_serial:
return super(
StockMove, self.with_context(force_next_serial=self.next_serial)
).action_show_details()
return super().action_show_details()
11 changes: 11 additions & 0 deletions product_lot_sequence/readme/ROADMAP.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
* There is an issue with the use of ir.sequence with the newer version of Odoo.

Mostly, when opening the detailed operations of an assigned picking for a product
tracked by serial numbers, Odoo systematically calls `_get_next_serial` even
if there is not any serial number to generate.
Moreover, the widget allowing to generate the serial numbers will not call
the sequence but only increment the number according to the next serial,
potentially leading to a sequence that is not in sync anymore with the created
serial numbers.

cf https://github.com/OCA/product-attribute/issues/1326
37 changes: 26 additions & 11 deletions product_lot_sequence/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ <h1 class="title">Product Lot Sequence</h1>
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:dfe9a2666cd1599203c70fd159399022104a8f2df4808574a961f49e93399cf1
!! source digest: sha256:c497d170778ffa1220e7cd95c340001c2d7caad3c29559a226d0bd3bc9d5d6fb
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/product-attribute/tree/16.0/product_lot_sequence"><img alt="OCA/product-attribute" src="https://img.shields.io/badge/github-OCA%2Fproduct--attribute-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/product-attribute-16-0/product-attribute-16-0-product_lot_sequence"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/product-attribute&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>Adds ability to define a lot sequence from the product which will be proposed upon creating new lots.</p>
Expand All @@ -380,11 +380,12 @@ <h1 class="title">Product Lot Sequence</h1>
</ul>
</li>
<li><a class="reference internal" href="#usage" id="toc-entry-4">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-5">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-6">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-7">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-8">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-9">Maintainers</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="toc-entry-5">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-6">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-7">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-8">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-9">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-10">Maintainers</a></li>
</ul>
</li>
</ul>
Expand Down Expand Up @@ -424,24 +425,38 @@ <h1><a class="toc-backref" href="#toc-entry-4">Usage</a></h1>
<li>Select the product and the next number of the product sequence will be automatically proposed</li>
</ul>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#toc-entry-5">Known issues / Roadmap</a></h1>
<ul class="simple">
<li>There is an issue with the use of ir.sequence with the newer version of Odoo.</li>
</ul>
<p>Mostly, when opening the detailed operations of an assigned picking for a product
tracked by serial numbers, Odoo systematically calls <cite>_get_next_serial</cite> even
if there is not any serial number to generate.
Moreover, the widget allowing to generate the serial numbers will not call
the sequence but only increment the number according to the next serial,
potentially leading to a sequence that is not in sync anymore with the created
serial numbers.</p>
<p>cf <a class="reference external" href="https://github.com/OCA/product-attribute/issues/1326">https://github.com/OCA/product-attribute/issues/1326</a></p>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-5">Bug Tracker</a></h1>
<h1><a class="toc-backref" href="#toc-entry-6">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/product-attribute/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/product-attribute/issues/new?body=module:%20product_lot_sequence%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#toc-entry-6">Credits</a></h1>
<h1><a class="toc-backref" href="#toc-entry-7">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-7">Authors</a></h2>
<h2><a class="toc-backref" href="#toc-entry-8">Authors</a></h2>
<ul class="simple">
<li>ForgeFlow S.L.</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-8">Contributors</a></h2>
<h2><a class="toc-backref" href="#toc-entry-9">Contributors</a></h2>
<ul class="simple">
<li>Adria Gil Sorribes &lt;<a class="reference external" href="mailto:adria.gil&#64;forgeflow.com">adria.gil&#64;forgeflow.com</a>&gt;</li>
<li>Domantas Girdžiūnas &lt;<a class="reference external" href="mailto:domantas&#64;vialaurea.lt">domantas&#64;vialaurea.lt</a>&gt;</li>
Expand All @@ -453,7 +468,7 @@ <h2><a class="toc-backref" href="#toc-entry-8">Contributors</a></h2>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-9">Maintainers</a></h2>
<h2><a class="toc-backref" href="#toc-entry-10">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
Expand Down
49 changes: 49 additions & 0 deletions product_lot_sequence/tests/test_product_lot_sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,22 @@ def setUp(self):
super(TestProductLotSequence, self).setUp()
self.product_product = self.env["product.product"]
self.stock_production_lot = self.env["stock.lot"]
self.receipt_type = self.env.ref("stock.picking_type_in")
self.delivery_type = self.env.ref("stock.picking_type_out")

def _create_picking(self, picking_type, move_vals_list):
picking_form = Form(self.env["stock.picking"])
picking_form.picking_type_id = picking_type
for move_vals in move_vals_list:
with picking_form.move_ids_without_package.new() as move_form:
move_form.product_id = move_vals.get("product_id")
move_form.product_uom_qty = move_vals.get("product_uom_qty", 1.0)
move_form.product_uom = move_vals.get(
"product_uom", self.env.ref("uom.product_uom_unit")
)
picking = picking_form.save()
picking.action_confirm()
return picking

def test_product_sequence(self):
self.assertEqual(self.stock_production_lot._get_sequence_policy(), "product")
Expand Down Expand Up @@ -86,3 +102,36 @@ def test_lot_onchange_product_id_global(self):
lot_form.product_id = product
lot = lot_form.save()
self.assertEqual(lot.name, next_sequence_number)

def test_open_detailed_operations(self):
self.env["ir.config_parameter"].set_param(
"product_lot_sequence.policy", "global"
)
seq = self.env["ir.sequence"].search([("code", "=", "stock.lot.serial")])
first_next_sequence_number = seq.get_next_char(seq.number_next_actual)
product = self.product_product.create(
{"name": "Test global", "tracking": "serial"}
)
delivery_picking = self._create_picking(
self.delivery_type, [{"product_id": product}]
)
delivery_move = delivery_picking.move_lines
self.assertFalse(delivery_move.next_serial)
delivery_move.action_show_details()
self.assertFalse(delivery_move.next_serial)
self.assertEqual(
seq.get_next_char(seq.number_next_actual), first_next_sequence_number
)
receipt_picking = self._create_picking(
self.receipt_type, [{"product_id": product}]
)
receipt_move = receipt_picking.move_lines
self.assertFalse(receipt_move.next_serial)
receipt_move.action_show_details()
self.assertEqual(receipt_move.next_serial, first_next_sequence_number)
new_next_sequence_number = seq.get_next_char(seq.number_next_actual)
self.assertNotEqual(new_next_sequence_number, first_next_sequence_number)
receipt_move.action_show_details()
self.assertEqual(
new_next_sequence_number, seq.get_next_char(seq.number_next_actual)
)

0 comments on commit c4fefff

Please sign in to comment.