odoo-addon-stock-restrict-lot 18.0.1.1.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. odoo/addons/stock_restrict_lot/README.rst +94 -0
  2. odoo/addons/stock_restrict_lot/__init__.py +1 -0
  3. odoo/addons/stock_restrict_lot/__manifest__.py +15 -0
  4. odoo/addons/stock_restrict_lot/i18n/es.po +73 -0
  5. odoo/addons/stock_restrict_lot/i18n/hr.po +78 -0
  6. odoo/addons/stock_restrict_lot/i18n/it.po +77 -0
  7. odoo/addons/stock_restrict_lot/i18n/nl.po +69 -0
  8. odoo/addons/stock_restrict_lot/i18n/nl_NL.po +77 -0
  9. odoo/addons/stock_restrict_lot/i18n/pt.po +69 -0
  10. odoo/addons/stock_restrict_lot/i18n/pt_BR.po +69 -0
  11. odoo/addons/stock_restrict_lot/i18n/stock_restrict_lot.pot +68 -0
  12. odoo/addons/stock_restrict_lot/i18n/tr.po +77 -0
  13. odoo/addons/stock_restrict_lot/models/__init__.py +4 -0
  14. odoo/addons/stock_restrict_lot/models/product_product.py +22 -0
  15. odoo/addons/stock_restrict_lot/models/stock_move.py +160 -0
  16. odoo/addons/stock_restrict_lot/models/stock_picking.py +12 -0
  17. odoo/addons/stock_restrict_lot/models/stock_rule.py +17 -0
  18. odoo/addons/stock_restrict_lot/readme/CONTRIBUTORS.md +3 -0
  19. odoo/addons/stock_restrict_lot/readme/DESCRIPTION.md +4 -0
  20. odoo/addons/stock_restrict_lot/static/description/icon.png +0 -0
  21. odoo/addons/stock_restrict_lot/static/description/index.html +437 -0
  22. odoo/addons/stock_restrict_lot/tests/__init__.py +1 -0
  23. odoo/addons/stock_restrict_lot/tests/test_restrict_lot.py +392 -0
  24. odoo/addons/stock_restrict_lot/views/stock_move_views.xml +41 -0
  25. odoo/addons/stock_restrict_lot/views/stock_picking.xml +34 -0
  26. odoo_addon_stock_restrict_lot-18.0.1.1.0.2.dist-info/METADATA +110 -0
  27. odoo_addon_stock_restrict_lot-18.0.1.1.0.2.dist-info/RECORD +29 -0
  28. odoo_addon_stock_restrict_lot-18.0.1.1.0.2.dist-info/WHEEL +5 -0
  29. odoo_addon_stock_restrict_lot-18.0.1.1.0.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,68 @@
1
+ # Translation of Odoo Server.
2
+ # This file contains the translation of the following modules:
3
+ # * stock_restrict_lot
4
+ #
5
+ msgid ""
6
+ msgstr ""
7
+ "Project-Id-Version: Odoo Server 18.0\n"
8
+ "Report-Msgid-Bugs-To: \n"
9
+ "Last-Translator: \n"
10
+ "Language-Team: \n"
11
+ "MIME-Version: 1.0\n"
12
+ "Content-Type: text/plain; charset=UTF-8\n"
13
+ "Content-Transfer-Encoding: \n"
14
+ "Plural-Forms: \n"
15
+
16
+ #. module: stock_restrict_lot
17
+ #. odoo-python
18
+ #: code:addons/stock_restrict_lot/models/stock_move.py:0
19
+ msgid ""
20
+ "Inconsistencies between reserved quant and lot restriction on stock move"
21
+ msgstr ""
22
+
23
+ #. module: stock_restrict_lot
24
+ #: model_terms:ir.ui.view,arch_db:stock_restrict_lot.custom_stock_picking_search_view
25
+ msgid "Lot"
26
+ msgstr ""
27
+
28
+ #. module: stock_restrict_lot
29
+ #: model:ir.model,name:stock_restrict_lot.model_product_product
30
+ msgid "Product Variant"
31
+ msgstr ""
32
+
33
+ #. module: stock_restrict_lot
34
+ #: model:ir.model.fields,field_description:stock_restrict_lot.field_stock_move__restrict_lot_id
35
+ #: model:ir.model.fields,field_description:stock_restrict_lot.field_stock_picking__restrict_lot_id
36
+ msgid "Restrict Lot"
37
+ msgstr ""
38
+
39
+ #. module: stock_restrict_lot
40
+ #: model:ir.model,name:stock_restrict_lot.model_stock_move
41
+ msgid "Stock Move"
42
+ msgstr ""
43
+
44
+ #. module: stock_restrict_lot
45
+ #: model:ir.model,name:stock_restrict_lot.model_stock_rule
46
+ msgid "Stock Rule"
47
+ msgstr ""
48
+
49
+ #. module: stock_restrict_lot
50
+ #. odoo-python
51
+ #: code:addons/stock_restrict_lot/models/stock_move.py:0
52
+ msgid ""
53
+ "The lot(s) %(move_line_lot)s being moved is inconsistent with the "
54
+ "restriction on lot %(move_restrict_lot)s set on the move"
55
+ msgstr ""
56
+
57
+ #. module: stock_restrict_lot
58
+ #: model:ir.model,name:stock_restrict_lot.model_stock_picking
59
+ msgid "Transfer"
60
+ msgstr ""
61
+
62
+ #. module: stock_restrict_lot
63
+ #. odoo-python
64
+ #: code:addons/stock_restrict_lot/models/stock_move.py:0
65
+ msgid ""
66
+ "You can't modify the Lot/Serial number because at least one move in the "
67
+ "chain has already been done with another Lot/Serial number."
68
+ msgstr ""
@@ -0,0 +1,77 @@
1
+ # Translation of Odoo Server.
2
+ # This file contains the translation of the following modules:
3
+ # * stock_restrict_lot
4
+ #
5
+ msgid ""
6
+ msgstr ""
7
+ "Project-Id-Version: Odoo Server 18.0\n"
8
+ "Report-Msgid-Bugs-To: \n"
9
+ "PO-Revision-Date: 2026-01-21 16:50+0000\n"
10
+ "Last-Translator: Betül Öğmen <betulo@eska.biz>\n"
11
+ "Language-Team: none\n"
12
+ "Language: tr\n"
13
+ "MIME-Version: 1.0\n"
14
+ "Content-Type: text/plain; charset=UTF-8\n"
15
+ "Content-Transfer-Encoding: \n"
16
+ "Plural-Forms: nplurals=2; plural=n != 1;\n"
17
+ "X-Generator: Weblate 5.15.2\n"
18
+
19
+ #. module: stock_restrict_lot
20
+ #. odoo-python
21
+ #: code:addons/stock_restrict_lot/models/stock_move.py:0
22
+ msgid ""
23
+ "Inconsistencies between reserved quant and lot restriction on stock move"
24
+ msgstr ""
25
+ "Stok hareketinde rezerve miktar ile lot kısıtlanması arasında tutarsızlıklar "
26
+ "bulunuyor"
27
+
28
+ #. module: stock_restrict_lot
29
+ #: model_terms:ir.ui.view,arch_db:stock_restrict_lot.custom_stock_picking_search_view
30
+ msgid "Lot"
31
+ msgstr ""
32
+
33
+ #. module: stock_restrict_lot
34
+ #: model:ir.model,name:stock_restrict_lot.model_product_product
35
+ msgid "Product Variant"
36
+ msgstr "Ürün Varyantı"
37
+
38
+ #. module: stock_restrict_lot
39
+ #: model:ir.model.fields,field_description:stock_restrict_lot.field_stock_move__restrict_lot_id
40
+ #: model:ir.model.fields,field_description:stock_restrict_lot.field_stock_picking__restrict_lot_id
41
+ msgid "Restrict Lot"
42
+ msgstr "Lot Kısıtla"
43
+
44
+ #. module: stock_restrict_lot
45
+ #: model:ir.model,name:stock_restrict_lot.model_stock_move
46
+ msgid "Stock Move"
47
+ msgstr "Stok Hareketi"
48
+
49
+ #. module: stock_restrict_lot
50
+ #: model:ir.model,name:stock_restrict_lot.model_stock_rule
51
+ msgid "Stock Rule"
52
+ msgstr "Stok Kuralı"
53
+
54
+ #. module: stock_restrict_lot
55
+ #. odoo-python
56
+ #: code:addons/stock_restrict_lot/models/stock_move.py:0
57
+ msgid ""
58
+ "The lot(s) %(move_line_lot)s being moved is inconsistent with the "
59
+ "restriction on lot %(move_restrict_lot)s set on the move"
60
+ msgstr ""
61
+ "Taşınan lot(lar) %(move_line_lot), taşıma işleminde belirlenen lot (%"
62
+ "(move_restrict_lot)) üzerindeki kısıtlamayla uyumsuz"
63
+
64
+ #. module: stock_restrict_lot
65
+ #: model:ir.model,name:stock_restrict_lot.model_stock_picking
66
+ msgid "Transfer"
67
+ msgstr ""
68
+
69
+ #. module: stock_restrict_lot
70
+ #. odoo-python
71
+ #: code:addons/stock_restrict_lot/models/stock_move.py:0
72
+ msgid ""
73
+ "You can't modify the Lot/Serial number because at least one move in the "
74
+ "chain has already been done with another Lot/Serial number."
75
+ msgstr ""
76
+ "Parti/Seri numarasını değiştiremezsiniz çünkü zincirdeki işlemlerden en az "
77
+ "biri başka bir Parti/Seri numarasıyla zaten tamamlanmıştır."
@@ -0,0 +1,4 @@
1
+ from . import stock_move
2
+ from . import stock_rule
3
+ from . import stock_picking
4
+ from . import product_product
@@ -0,0 +1,22 @@
1
+ # Copyright 2023 Michael Tietz (MT Software) <mtietz@mt-software.de>
2
+ # License LGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3
+ from odoo import models
4
+
5
+
6
+ class ProductProduct(models.Model):
7
+ _inherit = "product.product"
8
+
9
+ # To be able to get the outgoing and incoming qty by the restrict_lot_id
10
+ # the odoo standard method _compute_quantities_dict is hookable
11
+ # therefore the domain is already here changed
12
+ def _get_domain_locations(self):
13
+ res = super()._get_domain_locations()
14
+ lot_id = self.env.context.get("lot_id")
15
+ if not lot_id:
16
+ return res
17
+
18
+ domain_quant_loc, domain_move_in_loc, domain_move_out_loc = res
19
+ lot_domain = [("restrict_lot_id", "=", lot_id)]
20
+ domain_move_in_loc += lot_domain
21
+ domain_move_out_loc += lot_domain
22
+ return domain_quant_loc, domain_move_in_loc, domain_move_out_loc
@@ -0,0 +1,160 @@
1
+ # License LGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
2
+
3
+ from odoo import api, exceptions, fields, models
4
+ from odoo.exceptions import UserError, ValidationError
5
+ from odoo.tools.misc import OrderedSet
6
+
7
+
8
+ class StockMove(models.Model):
9
+ _inherit = "stock.move"
10
+
11
+ # seems better to not copy this field except when a move is split, because a move
12
+ # can be copied in multiple different occasions and could even be copied with a
13
+ # different product...
14
+ restrict_lot_id = fields.Many2one(
15
+ "stock.lot", string="Restrict Lot", copy=False, index=True
16
+ )
17
+
18
+ def _prepare_procurement_values(self):
19
+ vals = super()._prepare_procurement_values()
20
+ vals["restrict_lot_id"] = self.restrict_lot_id.id
21
+ return vals
22
+
23
+ @api.model
24
+ def _prepare_merge_moves_distinct_fields(self):
25
+ distinct_fields = super()._prepare_merge_moves_distinct_fields()
26
+ distinct_fields.append("restrict_lot_id")
27
+ return distinct_fields
28
+
29
+ def _prepare_move_line_vals(self, quantity=None, reserved_quant=None):
30
+ vals = super()._prepare_move_line_vals(
31
+ quantity=quantity, reserved_quant=reserved_quant
32
+ )
33
+ if self.restrict_lot_id:
34
+ if (
35
+ "lot_id" in vals
36
+ and vals["lot_id"] is not False
37
+ and vals["lot_id"] != self.restrict_lot_id.id
38
+ ):
39
+ raise exceptions.UserError(
40
+ self.env._(
41
+ "Inconsistencies between reserved quant and lot restriction on "
42
+ "stock move"
43
+ )
44
+ )
45
+ vals["lot_id"] = self.restrict_lot_id.id
46
+ return vals
47
+
48
+ def _get_available_quantity(
49
+ self,
50
+ location_id,
51
+ lot_id=None,
52
+ package_id=None,
53
+ owner_id=None,
54
+ strict=False,
55
+ allow_negative=False,
56
+ ):
57
+ self.ensure_one()
58
+ if not lot_id and self.restrict_lot_id:
59
+ lot_id = self.restrict_lot_id
60
+ return super()._get_available_quantity(
61
+ location_id,
62
+ lot_id=lot_id,
63
+ package_id=package_id,
64
+ owner_id=owner_id,
65
+ strict=strict,
66
+ allow_negative=allow_negative,
67
+ )
68
+
69
+ def _update_reserved_quantity(
70
+ self,
71
+ need,
72
+ location_id,
73
+ lot_id=None,
74
+ package_id=None,
75
+ owner_id=None,
76
+ strict=True,
77
+ ):
78
+ self.ensure_one()
79
+ if self.restrict_lot_id:
80
+ lot_id = self.restrict_lot_id
81
+ return super()._update_reserved_quantity(
82
+ need,
83
+ location_id,
84
+ lot_id=lot_id,
85
+ package_id=package_id,
86
+ owner_id=owner_id,
87
+ strict=strict,
88
+ )
89
+
90
+ def _split(self, qty, restrict_partner_id=False):
91
+ vals_list = super()._split(qty, restrict_partner_id=restrict_partner_id)
92
+ if vals_list and self.restrict_lot_id:
93
+ vals_list[0]["restrict_lot_id"] = self.restrict_lot_id.id
94
+ return vals_list
95
+
96
+ def _action_done(self, cancel_backorder=False):
97
+ res = super()._action_done(cancel_backorder=cancel_backorder)
98
+ self._check_lot_consistent_with_restriction()
99
+ return res
100
+
101
+ def _check_lot_consistent_with_restriction(self):
102
+ """
103
+ Check that the lot set on move lines
104
+ is the same as the restricted lot set on the move
105
+ """
106
+ for move in self:
107
+ if not (move.restrict_lot_id and move.move_line_ids):
108
+ continue
109
+ move_line_lot = move.mapped("move_line_ids.lot_id")
110
+ if move.restrict_lot_id != move_line_lot:
111
+ raise UserError(
112
+ self.env._(
113
+ "The lot(s) %(move_line_lot)s being moved is "
114
+ "inconsistent with the restriction on "
115
+ "lot %(move_restrict_lot)s set on the move",
116
+ move_line_lot=", ".join(move_line_lot.mapped("display_name")),
117
+ move_restrict_lot=move.restrict_lot_id.display_name,
118
+ )
119
+ )
120
+
121
+ # Same as _rollup_move_origs but also for "done" moves.
122
+ def _rollup_not_cancelled_move_origs(self, seen=False):
123
+ if not seen:
124
+ seen = OrderedSet()
125
+ unseen = OrderedSet(self.ids) - seen
126
+ if not unseen:
127
+ return seen
128
+ seen.update(unseen)
129
+ self.filtered(lambda m: m.id in unseen).move_orig_ids.filtered(
130
+ lambda sm: sm.state != "cancel"
131
+ )._rollup_not_cancelled_move_origs(seen)
132
+ return seen
133
+
134
+ def write(self, vals):
135
+ if "restrict_lot_id" not in vals:
136
+ return super().write(vals)
137
+ else:
138
+ restrict_lot_id = vals.pop("restrict_lot_id")
139
+ restrict_lot = self.env["stock.lot"].browse(restrict_lot_id)
140
+ chained_move_ids = self._rollup_move_dests()
141
+ chained_move_ids = self._rollup_not_cancelled_move_origs(
142
+ chained_move_ids - self.ids
143
+ )
144
+ chained_moves = self.env["stock.move"].browse(chained_move_ids)
145
+ if any(
146
+ [
147
+ sm.state == "done" and sm.lot_ids and sm.lot_ids != restrict_lot
148
+ for sm in chained_moves
149
+ ]
150
+ ):
151
+ raise ValidationError(
152
+ self.env._(
153
+ "You can't modify the Lot/Serial number "
154
+ "because at least one move in the chain has "
155
+ "already been done with another Lot/Serial number."
156
+ )
157
+ )
158
+ for move in chained_moves:
159
+ super(StockMove, move).write({"restrict_lot_id": restrict_lot_id})
160
+ return super().write(vals)
@@ -0,0 +1,12 @@
1
+ # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
2
+ from odoo import fields, models
3
+
4
+
5
+ class StockPicking(models.Model):
6
+ _inherit = "stock.picking"
7
+
8
+ # this is a technical field, making possible to search a picking by any restrict lot
9
+ # defined on its line, from the web search bar.
10
+ restrict_lot_id = fields.Many2one(
11
+ related="move_ids.restrict_lot_id", string="Restrict Lot"
12
+ )
@@ -0,0 +1,17 @@
1
+ # License LGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
2
+
3
+ from odoo import models
4
+
5
+
6
+ class StockRule(models.Model):
7
+ _inherit = "stock.rule"
8
+
9
+ def _get_custom_move_fields(self):
10
+ fields = super()._get_custom_move_fields()
11
+ fields += ["restrict_lot_id"]
12
+ return fields
13
+
14
+ def _push_prepare_move_copy_values(self, move_to_copy, new_date):
15
+ values = super()._push_prepare_move_copy_values(move_to_copy, new_date)
16
+ values["restrict_lot_id"] = move_to_copy.restrict_lot_id.id
17
+ return values
@@ -0,0 +1,3 @@
1
+ - Florian da Costa \<<florian.dacosta@akretion.com>\>
2
+ - Ruchir Shukla \<<ruchir@bizzappdev.com>\>
3
+ - Stefan Rijnhart \<<stefan@opener.amsterdam>\>
@@ -0,0 +1,4 @@
1
+ This module adds a field to restrict a stock move to a specific lot. It
2
+ propagates it between chained moves. A move with a restrict lot will
3
+ only be able to reserve or transfer products with the specified lot.
4
+ This module serves as a basis for other modules, it has not effect on its own.