From 089c8cda4697f0ab73f6d849840725da66f1848b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Cmithan=20G=C3=BCldemir?= Date: Tue, 4 Feb 2025 08:36:25 +0300 Subject: [PATCH] [MIG] altinkaya_stock_lot --- altinkaya_stock_lot/__init__.py | 4 + altinkaya_stock_lot/__manifest__.py | 10 +-- .../i18n/altinkaya_stock_lot.pot | 48 +++++++++++ altinkaya_stock_lot/i18n/tr.po | 48 +++++++++++ altinkaya_stock_lot/models/__init__.py | 5 ++ altinkaya_stock_lot/models/stock_inventory.py | 11 --- .../models/stock_inventory_line.py | 44 ---------- altinkaya_stock_lot/models/stock_lot.py | 28 ++++++ altinkaya_stock_lot/models/stock_move_line.py | 15 ++-- altinkaya_stock_lot/models/stock_picking.py | 45 ---------- altinkaya_stock_lot/models/stock_quant.py | 28 ++++++ .../static/description/icon.png | Bin 0 -> 27359 bytes altinkaya_stock_lot/wizards/__init__.py | 3 + .../wizards/mrp_product_produce.py | 80 ++++++++++-------- .../wizards/mrp_product_produce_view.xml | 8 +- 15 files changed, 223 insertions(+), 154 deletions(-) create mode 100644 altinkaya_stock_lot/__init__.py create mode 100644 altinkaya_stock_lot/i18n/altinkaya_stock_lot.pot create mode 100644 altinkaya_stock_lot/i18n/tr.po create mode 100644 altinkaya_stock_lot/models/__init__.py delete mode 100644 altinkaya_stock_lot/models/stock_inventory.py delete mode 100644 altinkaya_stock_lot/models/stock_inventory_line.py create mode 100644 altinkaya_stock_lot/models/stock_lot.py delete mode 100644 altinkaya_stock_lot/models/stock_picking.py create mode 100644 altinkaya_stock_lot/models/stock_quant.py create mode 100644 altinkaya_stock_lot/static/description/icon.png create mode 100644 altinkaya_stock_lot/wizards/__init__.py diff --git a/altinkaya_stock_lot/__init__.py b/altinkaya_stock_lot/__init__.py new file mode 100644 index 000000000..6fa69c9cb --- /dev/null +++ b/altinkaya_stock_lot/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2022 Yiğit Budak (https://github.com/yibudak) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from . import models +# from . import wizards diff --git a/altinkaya_stock_lot/__manifest__.py b/altinkaya_stock_lot/__manifest__.py index b2bfceb2e..586f9f0bd 100644 --- a/altinkaya_stock_lot/__manifest__.py +++ b/altinkaya_stock_lot/__manifest__.py @@ -1,18 +1,18 @@ -# Copyright 2022 Yiğit Budak (https://github.com/yibudak) +# Copyright 2025 Yiğit Budak, Ümithan Güldemir (https://github.com/yibudak) (https://github.com/umithan-guldemir) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { "name": "Altinkaya Stock Lot Extensions", "summary": "Adds custom fields to stock.production.lot", - "version": "13.0.1.0.0", + "version": "16.0.1.0.0", "category": "stock", "website": "https://github.com/yibudak", - "author": "Yiğit Budak", + "author": "Yiğit Budak, Ümithan Güldemir", "license": "AGPL-3", "application": False, "installable": True, - "depends": ["stock", "mrp"], + "depends": ["stock", "mrp", "stock_inventory"], "data": [ - "wizards/mrp_product_produce_view.xml", + # "wizards/mrp_product_produce_view.xml", ], } diff --git a/altinkaya_stock_lot/i18n/altinkaya_stock_lot.pot b/altinkaya_stock_lot/i18n/altinkaya_stock_lot.pot new file mode 100644 index 000000000..cc93dbc7d --- /dev/null +++ b/altinkaya_stock_lot/i18n/altinkaya_stock_lot.pot @@ -0,0 +1,48 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * altinkaya_stock_lot +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-12-28 08:07+0000\n" +"PO-Revision-Date: 2022-12-28 08:07+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: altinkaya_stock_lot +#: model:ir.model,name:altinkaya_stock_lot.model_stock_production_lot +msgid "Lot/Serial" +msgstr "" + +#. module: altinkaya_stock_lot +#: model:ir.model.fields,field_description:altinkaya_stock_lot.field_stock_production_lot__name +msgid "Lot/Serial Number" +msgstr "" + +#. module: altinkaya_stock_lot +#: model:ir.model,name:altinkaya_stock_lot.model_mrp_product_produce +msgid "Record Production" +msgstr "" + +#. module: altinkaya_stock_lot +#: model:ir.model,name:altinkaya_stock_lot.model_stock_picking +msgid "Transfer" +msgstr "" + +#. module: altinkaya_stock_lot +#: model:ir.model.fields,help:altinkaya_stock_lot.field_stock_production_lot__name +msgid "Unique Lot/Serial Number" +msgstr "" + +#. module: altinkaya_stock_lot +#: code:addons/altinkaya_stock_lot/wizards/mrp_product_produce.py:16 +#, python-format +msgid "You have to select a product." +msgstr "" + diff --git a/altinkaya_stock_lot/i18n/tr.po b/altinkaya_stock_lot/i18n/tr.po new file mode 100644 index 000000000..a6dabd830 --- /dev/null +++ b/altinkaya_stock_lot/i18n/tr.po @@ -0,0 +1,48 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * altinkaya_stock_lot +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-12-28 08:07+0000\n" +"PO-Revision-Date: 2022-12-28 08:07+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: altinkaya_stock_lot +#: model:ir.model,name:altinkaya_stock_lot.model_stock_production_lot +msgid "Lot/Serial" +msgstr "Lot/Seri" + +#. module: altinkaya_stock_lot +#: model:ir.model.fields,field_description:altinkaya_stock_lot.field_stock_production_lot__name +msgid "Lot/Serial Number" +msgstr "Lot/Seri Numarası" + +#. module: altinkaya_stock_lot +#: model:ir.model,name:altinkaya_stock_lot.model_mrp_product_produce +msgid "Record Production" +msgstr "Üretimi Kaydını İşle" + +#. module: altinkaya_stock_lot +#: model:ir.model,name:altinkaya_stock_lot.model_stock_picking +msgid "Transfer" +msgstr "Transfer" + +#. module: altinkaya_stock_lot +#: model:ir.model.fields,help:altinkaya_stock_lot.field_stock_production_lot__name +msgid "Unique Lot/Serial Number" +msgstr "Benzersiz Lot / Seri Numarası" + +#. module: altinkaya_stock_lot +#: code:addons/altinkaya_stock_lot/wizards/mrp_product_produce.py:16 +#, python-format +msgid "You have to select a product." +msgstr "Üretilecek bir ürün seçmelisiniz." + diff --git a/altinkaya_stock_lot/models/__init__.py b/altinkaya_stock_lot/models/__init__.py new file mode 100644 index 000000000..aeb5521cf --- /dev/null +++ b/altinkaya_stock_lot/models/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2022 Yiğit Budak (https://github.com/yibudak) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from . import stock_lot +from . import stock_move_line +# from . import stock_quant diff --git a/altinkaya_stock_lot/models/stock_inventory.py b/altinkaya_stock_lot/models/stock_inventory.py deleted file mode 100644 index 384a869ce..000000000 --- a/altinkaya_stock_lot/models/stock_inventory.py +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright 2022 Yiğit Budak (https://github.com/yibudak) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) -from odoo import models, api - - -class StockInventory(models.Model): - _inherit = "stock.inventory" - - - def action_validate(self): - return super(StockInventory, self).action_validate() diff --git a/altinkaya_stock_lot/models/stock_inventory_line.py b/altinkaya_stock_lot/models/stock_inventory_line.py deleted file mode 100644 index 1856f7286..000000000 --- a/altinkaya_stock_lot/models/stock_inventory_line.py +++ /dev/null @@ -1,44 +0,0 @@ -from odoo import api, models - - -class InventoryLine(models.Model): - _inherit = "stock.inventory.line" - - - def _create_missing_lot(self): - """EXPERIMENTAL: Create a lot for the move line if it is missing.""" - for rec in self: - if rec.product_id.tracking != "none" and not rec.prod_lot_id: - # yigit: When working with negative quantities, any lot without quant - # is causing issues, try to search quant and link it to lot - related_quant = rec.env["stock.quant"].search( - [ - ("product_id", "=", rec.product_id.id), - ("location_id", "=", rec.inventory_location_id.id), - ("quantity", "=", rec.product_qty), - ("lot_id", "=", False), - ], - limit=1, - ) - prod_lot_id = self.env["stock.production.lot"].create( - { - "product_id": rec.product_id.id, - "ref": rec.inventory_id.name or "", - "product_qty": rec.product_qty, - "quant_ids": [(6, 0, related_quant.ids)], - } - ) - rec.prod_lot_id = prod_lot_id.id - return True - - @api.model - def create(self, vals): - res = super(InventoryLine, self).create(vals) - res._create_missing_lot() - return res - - @api.model - def write(self, vals): - res = super(InventoryLine, self).write(vals) - self._create_missing_lot() - return res diff --git a/altinkaya_stock_lot/models/stock_lot.py b/altinkaya_stock_lot/models/stock_lot.py new file mode 100644 index 000000000..9c0e83e74 --- /dev/null +++ b/altinkaya_stock_lot/models/stock_lot.py @@ -0,0 +1,28 @@ +# Copyright 2022 Yiğit Budak (https://github.com/yibudak) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) +import random + +from odoo import fields, models + + +class StockProductionLot(models.Model): + _inherit = "stock.lot" + + def _compute_lot_name(self): + """Generates a random lot number. Overrides the default method. + We excluded some characters from the random string to avoid confusion.""" + while True: + unique = "".join( + random.choice("ABCDEFGHJKLMNPRSTUVXYZ123456789") for i in range(5) + ) + if not self.search([("name", "=", unique)], limit=1): + break + return unique + + name = fields.Char( + "Lot/Serial Number", + default=_compute_lot_name, + required=True, + readonly=True, + help="Unique Lot/Serial Number", + ) diff --git a/altinkaya_stock_lot/models/stock_move_line.py b/altinkaya_stock_lot/models/stock_move_line.py index 4093da447..8fb87de49 100644 --- a/altinkaya_stock_lot/models/stock_move_line.py +++ b/altinkaya_stock_lot/models/stock_move_line.py @@ -1,30 +1,29 @@ # Copyright 2022 Yiğit Budak (https://github.com/yibudak) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) -from odoo import models, api +from odoo import api, models class StockMoveLine(models.Model): _inherit = "stock.move.line" - def _create_missing_lot(self): - """EXPERIMENTAL: Create a lot for the move line if it is missing.""" + """Create a lot for the move line if it is missing.""" for rec in self: if rec.product_id.tracking != "none" and not rec.lot_id: - lot_id = self.env["stock.production.lot"].create( - {"product_id": rec.product_id.id, "ref": rec.move_id.name or ""} + lot_id = self.env["stock.lot"].create( + {"product_id": rec.product_id.id, "ref": rec.move_id.reference or ""} ) rec.lot_id = lot_id.id return True @api.model - def create(self, vals): - res = super(StockMoveLine, self).create(vals) + def create(self, vals_list): + res = super().create(vals_list) res._create_missing_lot() return res @api.model def write(self, vals): - res = super(StockMoveLine, self).write(vals) + res = super().write(vals) self._create_missing_lot() return res diff --git a/altinkaya_stock_lot/models/stock_picking.py b/altinkaya_stock_lot/models/stock_picking.py deleted file mode 100644 index 5c7298002..000000000 --- a/altinkaya_stock_lot/models/stock_picking.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright 2022 Yiğit Budak (https://github.com/yibudak) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) -from odoo import models, api -from odoo.tools import float_compare, float_is_zero - - -class StockPickin(models.Model): - _inherit = "stock.picking" - - # - # def button_validate(self): - # """Overridden to create lot_id for move_lines automatically""" - # picking_type = self.picking_type_id - # precision_digits = self.env["decimal.precision"].precision_get( - # "Product Unit of Measure" - # ) - # no_quantities_done = all( - # float_is_zero(move_line.qty_done, precision_digits=precision_digits) - # for move_line in self.move_line_ids.filtered( - # lambda m: m.state not in ("done", "cancel") - # ) - # ) - # if picking_type.use_create_lots or picking_type.use_existing_lots: - # lines_to_check = self.move_line_ids - # if not no_quantities_done: - # lines_to_check = lines_to_check.filtered( - # lambda ml: float_compare( - # ml.qty_done, - # 0, - # precision_rounding=ml.product_uom_id.rounding, - # ) - # ) - # for line in lines_to_check: - # product = line.product_id - # if product and product.tracking != "none": - # if not line.lot_name and not line.lot_id: - # vals = { - # "product_id": product.id, - # "ref": self.origin or "", - # } - # created_lot = line.lot_id.create(vals) - # line.write( - # {"lot_id": created_lot.id, "lot_name": created_lot.name} - # ) - # return super(StockPickin, self).button_validate() diff --git a/altinkaya_stock_lot/models/stock_quant.py b/altinkaya_stock_lot/models/stock_quant.py new file mode 100644 index 000000000..5e7a37b64 --- /dev/null +++ b/altinkaya_stock_lot/models/stock_quant.py @@ -0,0 +1,28 @@ +from odoo import api, models + + +class StockQuant(models.Model): + _inherit = "stock.quant" + + def _create_missing_lot(self, vals_list): + """EXPERIMENTAL: Create a lot for the move line if it is missing.""" + for vals in vals_list: + if not vals.get("lot_id") and vals.get("product_id") and (vals.get("quantity") or vals.get("inventory_quantity")): + product_id = self.env["product.product"].browse(vals["product_id"]) + if product_id.tracking != "none": + lot_id = self.env["stock.lot"].create( + { + "product_id": product_id.id, + "ref": vals.get("stock_inventory_ids") or "", #todo: find a better ref + "product_qty": vals.get("quantity") or vals.get("inventory_quantity"), + } + ) + vals["lot_id"] = lot_id.id + + + @api.model_create_multi + def create(self, vals_list): + self._create_missing_lot(vals_list) + res = super().create(vals_list) + + return res diff --git a/altinkaya_stock_lot/static/description/icon.png b/altinkaya_stock_lot/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e21c8907074c68d278a30072e5bb675679bae61a GIT binary patch literal 27359 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

&?4J#DStRliVo!Q7_;ys@ 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 D(^nMl literal 0 HcmV?d00001 diff --git a/altinkaya_stock_lot/wizards/__init__.py b/altinkaya_stock_lot/wizards/__init__.py new file mode 100644 index 000000000..2f8570c2e --- /dev/null +++ b/altinkaya_stock_lot/wizards/__init__.py @@ -0,0 +1,3 @@ +# Copyright 2022 Yiğit Budak (https://github.com/yibudak) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) +from . import mrp_product_produce \ No newline at end of file diff --git a/altinkaya_stock_lot/wizards/mrp_product_produce.py b/altinkaya_stock_lot/wizards/mrp_product_produce.py index febc70b51..73f14fd7a 100644 --- a/altinkaya_stock_lot/wizards/mrp_product_produce.py +++ b/altinkaya_stock_lot/wizards/mrp_product_produce.py @@ -1,14 +1,13 @@ -# Copyright 2022 Yiğit Budak (https://github.com/yibudak) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) -from odoo import models, fields, api, _ -from odoo.exceptions import UserError -from odoo.tools import float_is_zero +# # Copyright 2025 Yiğit Budak, Ümithan Güldemir (https://github.com/yibudak) (https://github.com/umithan-guldemir) +# # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) +# from odoo import models, fields, api, _ +# from odoo.exceptions import UserError +# from odoo.tools import float_is_zero -class MrpProductProduce(models.TransientModel): - _inherit = "mrp.product.produce" +# class MrpProductProduce(models.TransientModel): +# _inherit = "mrp.production" - def do_produce(self): """Override do_produce method on MRP to generate lot_id automatically""" if any( @@ -18,47 +17,54 @@ def do_produce(self): and not float_is_zero( x.qty_done, precision_rounding=x.product_uom_id.rounding ) - for x in self.produce_line_ids + for x in self.finished_move_line_ids ] ): raise UserError(_("Some products are tracked by lots but no lot is set.")) if self.product_tracking != "none" and not self.lot_id: # If lot created within label printing wizard, use it - if self.production_id.lot_id_to_create: - self.lot_id = self.production_id.lot_id_to_create + if self.lot_producing_id: + self.lot_id = self.lot_producing_id else: vals = { "product_id": self.product_id.id, - "ref": self.production_id.origin or "", + "ref": self.origin or "", } self.lot_id = self.lot_id.create(vals) - return super(MrpProductProduce, self).do_produce() + return self.do_produce() - @api.onchange("product_qty") - def _onchange_product_qty(self): - """Override _onchange_product_qty method on MRP to remove duplicate - rows caused by split procurement rules""" - res = super(MrpProductProduce, self)._onchange_product_qty() - for line in self.produce_line_ids.filtered(lambda p: not p.lot_id): - real_line = self.produce_line_ids.filtered( - lambda x: x.qty_to_consume == line.qty_to_consume - and x.product_id == line.product_id - and x.lot_id - ) - if real_line: - self.produce_line_ids -= line - return res +# @api.onchange("product_qty") +# def _onchange_product_qty(self): +# """Override _onchange_product_qty method on MRP to remove duplicate +# rows caused by split procurement rules""" +# res = self._onchange_product_qty() +# for line in self.finished_move_line_ids.filtered(lambda p: not p.lot_id): +# real_line = self.finished_move_line_ids.filtered( +# lambda x: x.reserved_qty == line.reserved_qty +# and x.product_id == line.product_id +# and x.lot_id +# ) +# if real_line: +# self.finished_move_line_ids -= line +# return res -class MrpProductProduceLine(models.TransientModel): - _inherit = "mrp.product.produce.line" +# class MrpProductProduceLine(models.TransientModel): +# _inherit = "mrp.production.backorder.line" - # We've added this field to prevent selection of a lot that is not in the - # raw materials location of the production order. - location_src_id = fields.Many2one( - "stock.location", - "Raw Materials Location", - related="raw_product_produce_id.production_id.location_src_id", - readonly=True, - ) +# # We've added this field to prevent selection of a lot that is not in the +# # raw materials location of the production order. +# production_id = fields.Many2one( +# "mrp.production", +# "Production Order", +# required=True, +# ondelete="cascade", +# index=True, +# ) +# location_src_id = fields.Many2one( +# "stock.location", +# "Raw Materials Location", +# related="production_id.location_src_id", +# readonly=True, +# ) diff --git a/altinkaya_stock_lot/wizards/mrp_product_produce_view.xml b/altinkaya_stock_lot/wizards/mrp_product_produce_view.xml index 6a8248860..5d414bc73 100644 --- a/altinkaya_stock_lot/wizards/mrp_product_produce_view.xml +++ b/altinkaya_stock_lot/wizards/mrp_product_produce_view.xml @@ -1,4 +1,4 @@ - +