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.
- odoo/addons/stock_restrict_lot/README.rst +94 -0
- odoo/addons/stock_restrict_lot/__init__.py +1 -0
- odoo/addons/stock_restrict_lot/__manifest__.py +15 -0
- odoo/addons/stock_restrict_lot/i18n/es.po +73 -0
- odoo/addons/stock_restrict_lot/i18n/hr.po +78 -0
- odoo/addons/stock_restrict_lot/i18n/it.po +77 -0
- odoo/addons/stock_restrict_lot/i18n/nl.po +69 -0
- odoo/addons/stock_restrict_lot/i18n/nl_NL.po +77 -0
- odoo/addons/stock_restrict_lot/i18n/pt.po +69 -0
- odoo/addons/stock_restrict_lot/i18n/pt_BR.po +69 -0
- odoo/addons/stock_restrict_lot/i18n/stock_restrict_lot.pot +68 -0
- odoo/addons/stock_restrict_lot/i18n/tr.po +77 -0
- odoo/addons/stock_restrict_lot/models/__init__.py +4 -0
- odoo/addons/stock_restrict_lot/models/product_product.py +22 -0
- odoo/addons/stock_restrict_lot/models/stock_move.py +160 -0
- odoo/addons/stock_restrict_lot/models/stock_picking.py +12 -0
- odoo/addons/stock_restrict_lot/models/stock_rule.py +17 -0
- odoo/addons/stock_restrict_lot/readme/CONTRIBUTORS.md +3 -0
- odoo/addons/stock_restrict_lot/readme/DESCRIPTION.md +4 -0
- odoo/addons/stock_restrict_lot/static/description/icon.png +0 -0
- odoo/addons/stock_restrict_lot/static/description/index.html +437 -0
- odoo/addons/stock_restrict_lot/tests/__init__.py +1 -0
- odoo/addons/stock_restrict_lot/tests/test_restrict_lot.py +392 -0
- odoo/addons/stock_restrict_lot/views/stock_move_views.xml +41 -0
- odoo/addons/stock_restrict_lot/views/stock_picking.xml +34 -0
- odoo_addon_stock_restrict_lot-18.0.1.1.0.2.dist-info/METADATA +110 -0
- odoo_addon_stock_restrict_lot-18.0.1.1.0.2.dist-info/RECORD +29 -0
- odoo_addon_stock_restrict_lot-18.0.1.1.0.2.dist-info/WHEEL +5 -0
- 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,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,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.
|
|
Binary file
|