Skip to content

Commit

Permalink
[IMP] stock_picking_auto_create_lot
Browse files Browse the repository at this point in the history
  • Loading branch information
AungKoKoLin1997 committed Jun 26, 2024
1 parent e6f3c42 commit 1040f60
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 49 deletions.
36 changes: 5 additions & 31 deletions stock_picking_auto_create_lot/models/stock_move_line.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,13 @@
# Copyright 2020 ACSONE SA/NV
# Copyright 2024 Quartile Limited
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import models
from odoo.fields import first


class StockMoveLine(models.Model):

_inherit = "stock.move.line"

def _get_value_production_lot(self):
res = super()._get_value_production_lot()
if "name" in res and not res["name"]:
del res["name"]
return res

def set_lot_auto(self):
"""
Create lots using create_multi to avoid too much queries
As move lines were created by product or by tracked 'serial'
products, we apply the lot with both different approaches.
"""
values = []
stock_lot_obj = self.env["stock.lot"]
lots_by_product = dict()
for line in self:
# Prepare multi valued lots per line to use multi creation.
values.append(line._get_value_production_lot())
lots = stock_lot_obj.create(values)
for lot in lots:
if lot.product_id.id not in lots_by_product:
lots_by_product[lot.product_id.id] = lot
else:
lots_by_product[lot.product_id.id] += lot
for line in self:
lot = first(lots_by_product[line.product_id.id])
line.lot_id = lot
if lot.product_id.tracking == "serial":
lots_by_product[line.product_id.id] -= lot
def _get_lot_sequence(self):
self.ensure_one()
return self.env["ir.sequence"].next_by_code("stock.lot.serial")
3 changes: 2 additions & 1 deletion stock_picking_auto_create_lot/models/stock_picking.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ def _set_auto_lot(self):
and x.product_id.auto_create_lot
)
)
lines.set_lot_auto()
for line in lines:
line.lot_name = line._get_lot_sequence()

def _action_done(self):
self._set_auto_lot()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ def test_manual_lot(self):
)
self.assertTrue(move.display_assign_serial)
# Assign manual serials
for line in move.move_line_ids:
line.lot_id = self.lot_obj.create(line._get_value_production_lot())
self._assign_manual_serials(move)
self.picking.action_set_quantities_to_reservation()

self.picking.button_validate()
lot = self.env["stock.lot"].search([("product_id", "=", self.product.id)])
Expand All @@ -59,6 +59,9 @@ def test_auto_create_lot(self):
lambda m: m.product_id == self.product_serial_not_auto
)
self.assertTrue(move.display_assign_serial)
# Assign manual serials
self._assign_manual_serials(move)
self.picking.action_set_quantities_to_reservation()

self.picking._action_done()
lot = self.env["stock.lot"].search([("product_id", "=", self.product.id)])
Expand All @@ -75,7 +78,7 @@ def test_auto_create_transfer_lot(self):
lambda m: m.product_id == self.product_serial
)
for line in moves.mapped("move_line_ids"):
self.assertFalse(line.lot_id)
self.assertFalse(line.lot_name)

# Test the exception if manual serials are not filled in
with self.assertRaises(UserError), self.cr.savepoint():
Expand All @@ -85,10 +88,9 @@ def test_auto_create_transfer_lot(self):
moves = self.picking.move_ids.filtered(
lambda m: m.product_id == self.product_serial_not_auto
)

# Assign manual serials
for line in moves.mapped("move_line_ids"):
line.lot_id = self.lot_obj.create(line._get_value_production_lot())
self._assign_manual_serials(moves)
self.picking.action_set_quantities_to_reservation()

self.picking.button_validate()
for line in moves.mapped("move_line_ids"):
Expand Down Expand Up @@ -128,24 +130,19 @@ def test_multi_auto_create_lot(self):

moves = pickings.mapped("move_ids").filtered(
lambda m: m.product_id == self.product_serial
and m.product_id.auto_create_lot
)
for line in moves.mapped("move_line_ids"):
self.assertFalse(line.lot_id)
self.assertFalse(line.lot_name)

pickings._action_done()
for line in moves.mapped("move_line_ids"):
self.assertTrue(line.lot_id)

lot = self.env["stock.lot"].search([("product_id", "=", self.product.id)])
self.assertEqual(len(lot), 1)
# Search for serials
lot = self.env["stock.lot"].search(
[("product_id", "=", self.product_serial.id)]
)
self.assertEqual(len(lot), 6)
self.assertTrue(line.lot_name)

def test_immediate_validate_tracked_move_with_auto_create_lot(self):
# Clear existing moves.
# Clear existing move if not the picking will open backorder wizard because
# when we manually assign lot for serial_not_auto product, other products still
# have 0 done qty.
self.picking.move_ids = False
self._create_move(product=self.product_serial, qty=4.0)
self.picking.action_assign()
Expand All @@ -159,3 +156,25 @@ def test_immediate_validate_tracked_move_with_auto_create_lot(self):
immediate_wizard_form.process()
# Confirm that validation is not blocked, for example, by create-backorder wizard.
self.assertEqual(self.picking.state, "done")

def test_multiple_sml_for_one_stock_move(self):
"""
Create a picking and we receive goods from supplier with different features so we
want different lots by each stock move line.
"""
self._create_picking()
self._create_move(product=self.product, qty=50.0)
self.picking.action_assign()
self.picking.move_line_ids.qty_done = 25.0
# new sml with 25.0 units
self.picking.move_line_ids.copy({"qty_done": 25.0})
self.picking.button_validate()
lots = self.picking.move_line_ids.lot_id
self.assertEqual(len(lots), 2)

def _assign_manual_serials(self, moves):
# Assign manual serials
moves.picking_id._set_auto_lot()
moves.move_line_ids.qty_done = 1.0
for line in moves.move_line_ids:
line.lot_name = self.env["ir.sequence"].next_by_code("stock.lot.serial")

0 comments on commit 1040f60

Please sign in to comment.