Skip to content

Commit 0dd8411

Browse files
[IMP] stock_secondary_unit: assign secondary_uom_id when generate or import serials/lots
1 parent e6be5bd commit 0dd8411

File tree

5 files changed

+180
-33
lines changed

5 files changed

+180
-33
lines changed

stock_secondary_unit/README.rst

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
.. image:: https://odoo-community.org/readme-banner-image
2-
:target: https://odoo-community.org/get-involved?utm_source=readme
3-
:alt: Odoo Community Association
4-
51
====================
62
Stock Secondary Unit
73
====================
@@ -17,7 +13,7 @@ Stock Secondary Unit
1713
.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
1814
:target: https://odoo-community.org/page/development-status
1915
:alt: Production/Stable
20-
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
16+
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
2117
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
2218
:alt: License: AGPL-3
2319
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github
@@ -52,6 +48,14 @@ To use this module you need to:
5248
5. Push button 'On hand' and set quantities in stock for this product.
5349
6. Go to product list and you can see the secondary unit value.
5450

51+
Known issues / Roadmap
52+
======================
53+
54+
When generating or importing serials/lots, the default secondary unit
55+
for move lines is taken from the first matching stock move that has a
56+
secondary UoM. It is assumed that the same product will not use
57+
different secondary units within the same picking.
58+
5559
Bug Tracker
5660
===========
5761

@@ -73,15 +77,15 @@ Authors
7377
Contributors
7478
------------
7579

76-
- `Tecnativa <https://www.tecnativa.com>`__
80+
- `Tecnativa <https://www.tecnativa.com>`__
7781

78-
- Carlos Dauden
79-
- Sergio Teruel
80-
- Carlos Roca
82+
- Carlos Dauden
83+
- Sergio Teruel
84+
- Carlos Roca
8185

82-
- Kitti Upariphutthiphong <kittiu@ecosoft.co.th>
83-
- Pimolnat Suntian <pimolnats@ecosoft.co.th>
84-
- Alan Ramos <alan.ramos@jarsa.com.mx>
86+
- Kitti Upariphutthiphong <kittiu@ecosoft.co.th>
87+
- Pimolnat Suntian <pimolnats@ecosoft.co.th>
88+
- Alan Ramos <alan.ramos@jarsa.com.mx>
8589

8690
Maintainers
8791
-----------

stock_secondary_unit/models/stock_move.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,38 @@ def _recompute_state(self):
4242
move.onchange_product_uom_for_secondary()
4343
return res
4444

45+
@api.model
46+
def action_generate_lot_line_vals(self, context, mode, first_lot, count, lot_text):
47+
vals_list = super().action_generate_lot_line_vals(
48+
context, mode, first_lot, count, lot_text
49+
)
50+
product_id = context.get("default_product_id")
51+
picking_id = context.get("default_picking_id")
52+
move = self.env["stock.move"].search(
53+
[
54+
("picking_id", "=", picking_id),
55+
("product_id", "=", product_id),
56+
("secondary_uom_id", "!=", False),
57+
],
58+
limit=1,
59+
)
60+
if not move:
61+
return vals_list
62+
if move.secondary_uom_id.dependency_type == "independent":
63+
return vals_list
64+
# Assume same uom with move and move line when it is generated
65+
factor = move._get_factor_line()
66+
for vals in vals_list:
67+
qty = self._calc_secondary_uom_qty(
68+
factor, vals["quantity"], move.secondary_uom_id
69+
)
70+
vals["secondary_uom_qty"] = qty
71+
vals["secondary_uom_id"] = {
72+
"id": move.secondary_uom_id.id,
73+
"display_name": move.secondary_uom_id.display_name,
74+
}
75+
return vals_list
76+
4577

4678
class StockMoveLine(models.Model):
4779
_inherit = ["stock.move.line", "product.secondary.unit.mixin"]
@@ -52,6 +84,16 @@ class StockMoveLine(models.Model):
5284
store=True, readonly=False, compute="_compute_quantity", precompute=True
5385
)
5486

87+
@api.model
88+
def default_get(self, fields_list):
89+
res = super().default_get(fields_list)
90+
move_id = self.env.context.get("default_move_id") or res.get("move_id")
91+
if move_id and not res.get("secondary_uom_id"):
92+
move = self.env["stock.move"].browse(move_id)
93+
if move.secondary_uom_id:
94+
res["secondary_uom_id"] = move.secondary_uom_id.id
95+
return res
96+
5597
@api.model_create_multi
5698
def create(self, vals_list):
5799
for vals in vals_list:
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
When generating or importing serials/lots, the default secondary unit for move
2+
lines is taken from the first matching stock move that has a secondary UoM.
3+
It is assumed that the same product will not use different secondary units
4+
within the same picking.

stock_secondary_unit/static/description/index.html

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
55
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
6-
<title>README.rst</title>
6+
<title>Stock Secondary Unit</title>
77
<style type="text/css">
88

99
/*
@@ -360,38 +360,34 @@
360360
</style>
361361
</head>
362362
<body>
363-
<div class="document">
363+
<div class="document" id="stock-secondary-unit">
364+
<h1 class="title">Stock Secondary Unit</h1>
364365

365-
366-
<a class="reference external image-reference" href="https://odoo-community.org/get-involved?utm_source=readme">
367-
<img alt="Odoo Community Association" src="https://odoo-community.org/readme-banner-image" />
368-
</a>
369-
<div class="section" id="stock-secondary-unit">
370-
<h1>Stock Secondary Unit</h1>
371366
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
372367
!! This file is generated by oca-gen-addon-readme !!
373368
!! changes will be overwritten. !!
374369
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
375370
!! source digest: sha256:74d27f6a71ab6acf126e480ea7dcfdc84c09d7269ff765dd075e960ecf101647
376371
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
377-
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Production/Stable" src="https://img.shields.io/badge/maturity-Production%2FStable-green.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/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/stock-logistics-warehouse/tree/18.0/stock_secondary_unit"><img alt="OCA/stock-logistics-warehouse" src="https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/stock-logistics-warehouse-18-0/stock-logistics-warehouse-18-0-stock_secondary_unit"><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/stock-logistics-warehouse&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
372+
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Production/Stable" src="https://img.shields.io/badge/maturity-Production%2FStable-green.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/stock-logistics-warehouse/tree/18.0/stock_secondary_unit"><img alt="OCA/stock-logistics-warehouse" src="https://img.shields.io/badge/github-OCA%2Fstock--logistics--warehouse-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/stock-logistics-warehouse-18-0/stock-logistics-warehouse-18-0-stock_secondary_unit"><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/stock-logistics-warehouse&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
378373
<p>This module extends the functionality of stock module to allow define
379374
other units with their conversion factor.</p>
380375
<p><strong>Table of contents</strong></p>
381376
<div class="contents local topic" id="contents">
382377
<ul class="simple">
383378
<li><a class="reference internal" href="#usage" id="toc-entry-1">Usage</a></li>
384-
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-2">Bug Tracker</a></li>
385-
<li><a class="reference internal" href="#credits" id="toc-entry-3">Credits</a><ul>
386-
<li><a class="reference internal" href="#authors" id="toc-entry-4">Authors</a></li>
387-
<li><a class="reference internal" href="#contributors" id="toc-entry-5">Contributors</a></li>
388-
<li><a class="reference internal" href="#maintainers" id="toc-entry-6">Maintainers</a></li>
379+
<li><a class="reference internal" href="#known-issues-roadmap" id="toc-entry-2">Known issues / Roadmap</a></li>
380+
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
381+
<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
382+
<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
383+
<li><a class="reference internal" href="#contributors" id="toc-entry-6">Contributors</a></li>
384+
<li><a class="reference internal" href="#maintainers" id="toc-entry-7">Maintainers</a></li>
389385
</ul>
390386
</li>
391387
</ul>
392388
</div>
393389
<div class="section" id="usage">
394-
<h2><a class="toc-backref" href="#toc-entry-1">Usage</a></h2>
390+
<h1><a class="toc-backref" href="#toc-entry-1">Usage</a></h1>
395391
<p>To use this module you need to:</p>
396392
<ol class="arabic simple">
397393
<li>Go to a <em>Product &gt; General Information tab</em>.</li>
@@ -402,24 +398,31 @@ <h2><a class="toc-backref" href="#toc-entry-1">Usage</a></h2>
402398
<li>Go to product list and you can see the secondary unit value.</li>
403399
</ol>
404400
</div>
401+
<div class="section" id="known-issues-roadmap">
402+
<h1><a class="toc-backref" href="#toc-entry-2">Known issues / Roadmap</a></h1>
403+
<p>When generating or importing serials/lots, the default secondary unit
404+
for move lines is taken from the first matching stock move that has a
405+
secondary UoM. It is assumed that the same product will not use
406+
different secondary units within the same picking.</p>
407+
</div>
405408
<div class="section" id="bug-tracker">
406-
<h2><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h2>
409+
<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
407410
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/issues">GitHub Issues</a>.
408411
In case of trouble, please check there if your issue has already been reported.
409412
If you spotted it first, help us to smash it by providing a detailed and welcomed
410413
<a class="reference external" href="https://github.com/OCA/stock-logistics-warehouse/issues/new?body=module:%20stock_secondary_unit%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
411414
<p>Do not contact contributors directly about support or help with technical issues.</p>
412415
</div>
413416
<div class="section" id="credits">
414-
<h2><a class="toc-backref" href="#toc-entry-3">Credits</a></h2>
417+
<h1><a class="toc-backref" href="#toc-entry-4">Credits</a></h1>
415418
<div class="section" id="authors">
416-
<h3><a class="toc-backref" href="#toc-entry-4">Authors</a></h3>
419+
<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
417420
<ul class="simple">
418421
<li>Tecnativa</li>
419422
</ul>
420423
</div>
421424
<div class="section" id="contributors">
422-
<h3><a class="toc-backref" href="#toc-entry-5">Contributors</a></h3>
425+
<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
423426
<ul class="simple">
424427
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a><ul>
425428
<li>Carlos Dauden</li>
@@ -433,7 +436,7 @@ <h3><a class="toc-backref" href="#toc-entry-5">Contributors</a></h3>
433436
</ul>
434437
</div>
435438
<div class="section" id="maintainers">
436-
<h3><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h3>
439+
<h2><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h2>
437440
<p>This module is maintained by the OCA.</p>
438441
<a class="reference external image-reference" href="https://odoo-community.org">
439442
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
@@ -446,6 +449,5 @@ <h3><a class="toc-backref" href="#toc-entry-6">Maintainers</a></h3>
446449
</div>
447450
</div>
448451
</div>
449-
</div>
450452
</body>
451453
</html>

stock_secondary_unit/tests/test_stock_secondary_unit.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,25 @@ def setUpClass(cls):
3333
cls.attribute_value_black = ProductAttributeValue.create(
3434
{"name": "test_black", "attribute_id": cls.attribute_color.id}
3535
)
36+
cls.serial_product = cls.env["product.product"].create(
37+
{
38+
"name": "Serial Product",
39+
"uom_id": cls.product_uom_unit.id,
40+
"type": "consu",
41+
"is_storable": True,
42+
"tracking": "serial",
43+
"secondary_uom_ids": [
44+
Command.create(
45+
{
46+
"code": "A",
47+
"name": "Double",
48+
"uom_id": cls.product_uom_unit.id,
49+
"factor": 2,
50+
},
51+
)
52+
],
53+
}
54+
)
3655
cls.product_template = cls.env["product.template"].create(
3756
{
3857
"name": "test",
@@ -225,3 +244,79 @@ def test_secondary_unit_merge_move_same_uom(self):
225244
picking.action_confirm()
226245
self.assertEqual(len(picking.move_ids), 1)
227246
self.assertEqual(picking.move_ids.secondary_uom_qty, 2)
247+
248+
def test_action_generate_lot_line_vals(self):
249+
picking = self.env["stock.picking"].create(
250+
{
251+
"location_id": self.location_supplier.id,
252+
"location_dest_id": self.location_stock.id,
253+
"picking_type_id": self.picking_type_in.id,
254+
}
255+
)
256+
move = self.env["stock.move"].create(
257+
{
258+
"name": "Test Move",
259+
"product_id": self.serial_product.id,
260+
"product_uom_qty": 2.0,
261+
"picking_id": picking.id,
262+
"location_id": self.location_supplier.id,
263+
"location_dest_id": self.location_stock.id,
264+
"secondary_uom_id": self.serial_product.secondary_uom_ids[0].id,
265+
}
266+
)
267+
# Import serials
268+
vals = self.env["stock.move"].action_generate_lot_line_vals(
269+
{
270+
"default_tracking": "serial",
271+
"default_product_id": move.product_id.id,
272+
"default_picking_id": picking.id,
273+
"default_location_dest_id": self.location_stock.id,
274+
},
275+
"import",
276+
"",
277+
0,
278+
"001\n002",
279+
)
280+
self.assertEqual(len(vals), 2)
281+
self.assertEqual(vals[0]["lot_name"], "001")
282+
self.assertEqual(
283+
vals[0]["secondary_uom_id"]["id"],
284+
self.serial_product.secondary_uom_ids[0].id,
285+
)
286+
self.assertEqual(vals[0]["quantity"], 1)
287+
self.assertEqual(vals[0]["secondary_uom_qty"], 0.5)
288+
self.assertEqual(vals[1]["lot_name"], "002")
289+
self.assertEqual(
290+
vals[1]["secondary_uom_id"]["id"],
291+
self.serial_product.secondary_uom_ids[0].id,
292+
)
293+
self.assertEqual(vals[1]["quantity"], 1)
294+
self.assertEqual(vals[1]["secondary_uom_qty"], 0.5)
295+
# Generate serials
296+
vals = self.env["stock.move"].action_generate_lot_line_vals(
297+
{
298+
"default_tracking": "serial",
299+
"default_product_id": move.product_id.id,
300+
"default_picking_id": picking.id,
301+
"default_location_dest_id": self.location_stock.id,
302+
},
303+
"generate",
304+
"001",
305+
2,
306+
False,
307+
)
308+
self.assertEqual(len(vals), 2)
309+
self.assertEqual(vals[0]["lot_name"], "001")
310+
self.assertEqual(
311+
vals[0]["secondary_uom_id"]["id"],
312+
self.serial_product.secondary_uom_ids[0].id,
313+
)
314+
self.assertEqual(vals[0]["quantity"], 1)
315+
self.assertEqual(vals[0]["secondary_uom_qty"], 0.5)
316+
self.assertEqual(vals[1]["lot_name"], "002")
317+
self.assertEqual(
318+
vals[1]["secondary_uom_id"]["id"],
319+
self.serial_product.secondary_uom_ids[0].id,
320+
)
321+
self.assertEqual(vals[1]["quantity"], 1)
322+
self.assertEqual(vals[1]["secondary_uom_qty"], 0.5)

0 commit comments

Comments
 (0)