From 7e7fa4c05d4c26a2f1214e4d1b5724c211f3117f Mon Sep 17 00:00:00 2001
From: kanda999
Date: Wed, 3 Jun 2026 06:14:59 +0000
Subject: [PATCH 1/3] [ADD] mrp_byproduct_auto_pick
---
mrp_byproduct_auto_pick/README.rst | 127 +++++
mrp_byproduct_auto_pick/__init__.py | 1 +
mrp_byproduct_auto_pick/__manifest__.py | 21 +
mrp_byproduct_auto_pick/models/__init__.py | 5 +
.../models/product_category.py | 20 +
.../models/product_template.py | 19 +
mrp_byproduct_auto_pick/models/res_company.py | 16 +
.../models/res_config_settings.py | 13 +
mrp_byproduct_auto_pick/models/stock_move.py | 49 ++
mrp_byproduct_auto_pick/pyproject.toml | 3 +
mrp_byproduct_auto_pick/readme/CONFIGURE.md | 18 +
.../readme/CONTRIBUTORS.md | 2 +
mrp_byproduct_auto_pick/readme/DESCRIPTION.md | 14 +
.../static/description/icon.png | Bin 0 -> 9455 bytes
.../static/description/index.html | 464 ++++++++++++++++++
mrp_byproduct_auto_pick/tests/__init__.py | 1 +
.../tests/test_mrp_byproduct_auto_pick.py | 146 ++++++
.../views/product_category_views.xml | 13 +
.../views/product_views.xml | 19 +
.../views/res_config_settings_views.xml | 18 +
20 files changed, 969 insertions(+)
create mode 100644 mrp_byproduct_auto_pick/README.rst
create mode 100644 mrp_byproduct_auto_pick/__init__.py
create mode 100644 mrp_byproduct_auto_pick/__manifest__.py
create mode 100644 mrp_byproduct_auto_pick/models/__init__.py
create mode 100644 mrp_byproduct_auto_pick/models/product_category.py
create mode 100644 mrp_byproduct_auto_pick/models/product_template.py
create mode 100644 mrp_byproduct_auto_pick/models/res_company.py
create mode 100644 mrp_byproduct_auto_pick/models/res_config_settings.py
create mode 100644 mrp_byproduct_auto_pick/models/stock_move.py
create mode 100644 mrp_byproduct_auto_pick/pyproject.toml
create mode 100644 mrp_byproduct_auto_pick/readme/CONFIGURE.md
create mode 100644 mrp_byproduct_auto_pick/readme/CONTRIBUTORS.md
create mode 100644 mrp_byproduct_auto_pick/readme/DESCRIPTION.md
create mode 100644 mrp_byproduct_auto_pick/static/description/icon.png
create mode 100644 mrp_byproduct_auto_pick/static/description/index.html
create mode 100644 mrp_byproduct_auto_pick/tests/__init__.py
create mode 100644 mrp_byproduct_auto_pick/tests/test_mrp_byproduct_auto_pick.py
create mode 100644 mrp_byproduct_auto_pick/views/product_category_views.xml
create mode 100644 mrp_byproduct_auto_pick/views/product_views.xml
create mode 100644 mrp_byproduct_auto_pick/views/res_config_settings_views.xml
diff --git a/mrp_byproduct_auto_pick/README.rst b/mrp_byproduct_auto_pick/README.rst
new file mode 100644
index 0000000..2a9b4da
--- /dev/null
+++ b/mrp_byproduct_auto_pick/README.rst
@@ -0,0 +1,127 @@
+=======================
+MRP Byproduct Auto Pick
+=======================
+
+..
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! This file is generated by oca-gen-addon-readme !!
+ !! changes will be overwritten. !!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! source digest: sha256:dfcc3449be75e3410a25b67d6cc2215a9fddde1ac736df990144a7b55a651ca7
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
+ :target: https://odoo-community.org/page/development-status
+ :alt: Beta
+.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
+ :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
+ :alt: License: AGPL-3
+.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fmanufacture-lightgray.png?logo=github
+ :target: https://github.com/OCA/manufacture/tree/18.0/mrp_byproduct_auto_pick
+ :alt: OCA/manufacture
+.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
+ :target: https://translation.odoo-community.org/projects/manufacture-18-0/manufacture-18-0-mrp_byproduct_auto_pick
+ :alt: Translate me on Weblate
+.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
+ :target: https://runboat.odoo-community.org/builds?repo=OCA/manufacture&target_branch=18.0
+ :alt: Try me on Runboat
+
+|badge1| |badge2| |badge3| |badge4| |badge5|
+
+In standard Odoo, the quantity of a byproduct on a manufacturing order
+is recomputed from the producing quantity whenever it is (re)evaluated,
+including when *Produce All* fills the producing quantity automatically.
+As a result, a quantity that an operator entered manually on a byproduct
+line is silently reset to the quantity to produce, unless the line
+happens to be marked as picked.
+
+This module lets you opt in, per product, per product category or
+company-wide, to keep the manually entered byproduct quantity: when an
+operator edits the quantity of an eligible byproduct line, the line is
+automatically marked as picked so its value is preserved through
+*Produce All*.
+
+Byproduct lines that are not edited keep the standard behavior and still
+scale with the producing quantity.
+
+**Table of contents**
+
+.. contents::
+ :local:
+
+Configuration
+=============
+
+The behavior is resolved with the following precedence (most specific
+wins):
+
+1. **Product** -- *Inventory* tab of a product, field *Byproduct Auto
+ Pick*.
+2. **Product category** -- field *Byproduct Auto Pick* (cascades up the
+ category tree).
+3. **Company** -- *Manufacturing > Configuration > Settings*, option
+ *Auto-pick Manually Edited Byproducts*.
+
+At product and category level the field has two values, and can also be
+left empty:
+
+- **Empty**: fall back to the next level (category, then company).
+- **Always**: keep the manually entered byproduct quantity.
+- **Never**: reset to the quantity to produce (standard Odoo behavior).
+
+To enable the behavior everywhere, tick the company-wide option and
+leave the product and category fields empty. To enable it only for some
+products, set them (or their category) to *Always*.
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues `_.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us to smash it by providing a detailed and welcomed
+`feedback `_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+-------
+
+* Quartile
+
+Contributors
+------------
+
+- `Quartile `__:
+
+ - Aung Ko Ko Lin
+
+Maintainers
+-----------
+
+This module is maintained by the OCA.
+
+.. image:: https://odoo-community.org/logo.png
+ :alt: Odoo Community Association
+ :target: https://odoo-community.org
+
+OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
+.. |maintainer-yostashiro| image:: https://github.com/yostashiro.png?size=40px
+ :target: https://github.com/yostashiro
+ :alt: yostashiro
+.. |maintainer-aungkokolin1997| image:: https://github.com/aungkokolin1997.png?size=40px
+ :target: https://github.com/aungkokolin1997
+ :alt: aungkokolin1997
+
+Current `maintainers `__:
+
+|maintainer-yostashiro| |maintainer-aungkokolin1997|
+
+This module is part of the `OCA/manufacture `_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/mrp_byproduct_auto_pick/__init__.py b/mrp_byproduct_auto_pick/__init__.py
new file mode 100644
index 0000000..0650744
--- /dev/null
+++ b/mrp_byproduct_auto_pick/__init__.py
@@ -0,0 +1 @@
+from . import models
diff --git a/mrp_byproduct_auto_pick/__manifest__.py b/mrp_byproduct_auto_pick/__manifest__.py
new file mode 100644
index 0000000..fc161ab
--- /dev/null
+++ b/mrp_byproduct_auto_pick/__manifest__.py
@@ -0,0 +1,21 @@
+# Copyright 2026 Quartile (https://www.quartile.co)
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+{
+ "name": "MRP Byproduct Auto Pick",
+ "summary": "Keep manually entered byproduct quantities instead of "
+ "resetting them to the quantity to produce",
+ "version": "18.0.1.0.0",
+ "category": "Manufacturing",
+ "license": "AGPL-3",
+ "author": "Quartile, Odoo Community Association (OCA)",
+ "website": "https://github.com/OCA/manufacture",
+ "depends": ["mrp"],
+ "data": [
+ "views/product_category_views.xml",
+ "views/product_views.xml",
+ "views/res_config_settings_views.xml",
+ ],
+ "maintainers": ["yostashiro", "aungkokolin1997"],
+ "installable": True,
+}
diff --git a/mrp_byproduct_auto_pick/models/__init__.py b/mrp_byproduct_auto_pick/models/__init__.py
new file mode 100644
index 0000000..1d606bf
--- /dev/null
+++ b/mrp_byproduct_auto_pick/models/__init__.py
@@ -0,0 +1,5 @@
+from . import res_company
+from . import res_config_settings
+from . import product_category
+from . import product_template
+from . import stock_move
diff --git a/mrp_byproduct_auto_pick/models/product_category.py b/mrp_byproduct_auto_pick/models/product_category.py
new file mode 100644
index 0000000..0759a4c
--- /dev/null
+++ b/mrp_byproduct_auto_pick/models/product_category.py
@@ -0,0 +1,20 @@
+# Copyright 2026 Quartile (https://www.quartile.co)
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo import fields, models
+
+
+class ProductCategory(models.Model):
+ _inherit = "product.category"
+
+ byproduct_auto_pick = fields.Selection(
+ selection=[
+ ("always", "Always"),
+ ("never", "Never"),
+ ],
+ help="Controls whether a manually entered quantity for products in "
+ "this category, when produced as a byproduct, is kept (marked as "
+ "picked) instead of being reset to the quantity to produce. Leave "
+ "empty to fall back to the parent category, then the company "
+ "setting.",
+ )
diff --git a/mrp_byproduct_auto_pick/models/product_template.py b/mrp_byproduct_auto_pick/models/product_template.py
new file mode 100644
index 0000000..e1e4da3
--- /dev/null
+++ b/mrp_byproduct_auto_pick/models/product_template.py
@@ -0,0 +1,19 @@
+# Copyright 2026 Quartile (https://www.quartile.co)
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo import fields, models
+
+
+class ProductTemplate(models.Model):
+ _inherit = "product.template"
+
+ byproduct_auto_pick = fields.Selection(
+ selection=[
+ ("always", "Always"),
+ ("never", "Never"),
+ ],
+ help="Controls whether a manually entered quantity for this product, "
+ "when produced as a byproduct, is kept (marked as picked) instead of "
+ "being reset to the quantity to produce. Leave empty to fall back to "
+ "the product category, then the company setting.",
+ )
diff --git a/mrp_byproduct_auto_pick/models/res_company.py b/mrp_byproduct_auto_pick/models/res_company.py
new file mode 100644
index 0000000..6aebc0a
--- /dev/null
+++ b/mrp_byproduct_auto_pick/models/res_company.py
@@ -0,0 +1,16 @@
+# Copyright 2026 Quartile (https://www.quartile.co)
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo import fields, models
+
+
+class ResCompany(models.Model):
+ _inherit = "res.company"
+
+ byproduct_auto_pick = fields.Boolean(
+ string="Auto-pick Manually Edited Byproducts",
+ help="When enabled, a manually entered byproduct quantity on a "
+ "manufacturing order is kept (marked as picked) instead of being "
+ "reset to the quantity to produce. This is the company-wide default, "
+ "which can be overridden per product category or per product.",
+ )
diff --git a/mrp_byproduct_auto_pick/models/res_config_settings.py b/mrp_byproduct_auto_pick/models/res_config_settings.py
new file mode 100644
index 0000000..d9d74d9
--- /dev/null
+++ b/mrp_byproduct_auto_pick/models/res_config_settings.py
@@ -0,0 +1,13 @@
+# Copyright 2026 Quartile (https://www.quartile.co)
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo import fields, models
+
+
+class ResConfigSettings(models.TransientModel):
+ _inherit = "res.config.settings"
+
+ byproduct_auto_pick = fields.Boolean(
+ related="company_id.byproduct_auto_pick",
+ readonly=False,
+ )
diff --git a/mrp_byproduct_auto_pick/models/stock_move.py b/mrp_byproduct_auto_pick/models/stock_move.py
new file mode 100644
index 0000000..7f795bb
--- /dev/null
+++ b/mrp_byproduct_auto_pick/models/stock_move.py
@@ -0,0 +1,49 @@
+# Copyright 2026 Quartile (https://www.quartile.co)
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo import models
+from odoo.tools import float_compare
+
+
+class StockMove(models.Model):
+ _inherit = "stock.move"
+
+ def _is_auto_pick_byproduct(self):
+ self.ensure_one()
+ production = self.production_id
+ return bool(production) and self.product_id != production.product_id
+
+ def _should_auto_pick_byproduct(self):
+ self.ensure_one()
+ template = self.product_id.product_tmpl_id
+ if template.byproduct_auto_pick:
+ return template.byproduct_auto_pick == "always"
+ category = template.categ_id
+ while category:
+ if category.byproduct_auto_pick:
+ return category.byproduct_auto_pick == "always"
+ category = category.parent_id
+ return self.company_id.byproduct_auto_pick
+
+ def write(self, vals):
+ # The MO recompute writes byproduct quantities through
+ # `_set_quantity_done` under the `auto_conso` context; we must not
+ # pick those.
+ if self.env.context.get("auto_conso"):
+ return super().write(vals)
+ candidates = self.filtered(
+ lambda move: not move.picked
+ and move._is_auto_pick_byproduct()
+ and move._should_auto_pick_byproduct()
+ )
+ quantity_before = {move.id: move.quantity for move in candidates}
+ res = super().write(vals)
+ candidates.filtered(
+ lambda move: float_compare(
+ move.quantity,
+ quantity_before[move.id],
+ precision_rounding=move.product_uom.rounding,
+ )
+ != 0
+ ).picked = True
+ return res
diff --git a/mrp_byproduct_auto_pick/pyproject.toml b/mrp_byproduct_auto_pick/pyproject.toml
new file mode 100644
index 0000000..4231d0c
--- /dev/null
+++ b/mrp_byproduct_auto_pick/pyproject.toml
@@ -0,0 +1,3 @@
+[build-system]
+requires = ["whool"]
+build-backend = "whool.buildapi"
diff --git a/mrp_byproduct_auto_pick/readme/CONFIGURE.md b/mrp_byproduct_auto_pick/readme/CONFIGURE.md
new file mode 100644
index 0000000..2817193
--- /dev/null
+++ b/mrp_byproduct_auto_pick/readme/CONFIGURE.md
@@ -0,0 +1,18 @@
+The behavior is resolved with the following precedence (most specific wins):
+
+1. **Product** -- *Inventory* tab of a product, field *Byproduct Auto Pick*.
+2. **Product category** -- field *Byproduct Auto Pick* (cascades up the
+ category tree).
+3. **Company** -- *Manufacturing \> Configuration \> Settings*, option
+ *Auto-pick Manually Edited Byproducts*.
+
+At product and category level the field has two values, and can also be left
+empty:
+
+- **Empty**: fall back to the next level (category, then company).
+- **Always**: keep the manually entered byproduct quantity.
+- **Never**: reset to the quantity to produce (standard Odoo behavior).
+
+To enable the behavior everywhere, tick the company-wide option and leave the
+product and category fields empty. To enable it only for some products, set
+them (or their category) to *Always*.
diff --git a/mrp_byproduct_auto_pick/readme/CONTRIBUTORS.md b/mrp_byproduct_auto_pick/readme/CONTRIBUTORS.md
new file mode 100644
index 0000000..faae328
--- /dev/null
+++ b/mrp_byproduct_auto_pick/readme/CONTRIBUTORS.md
@@ -0,0 +1,2 @@
+- [Quartile](https://www.quartile.co):
+ - Aung Ko Ko Lin
diff --git a/mrp_byproduct_auto_pick/readme/DESCRIPTION.md b/mrp_byproduct_auto_pick/readme/DESCRIPTION.md
new file mode 100644
index 0000000..7dccd41
--- /dev/null
+++ b/mrp_byproduct_auto_pick/readme/DESCRIPTION.md
@@ -0,0 +1,14 @@
+In standard Odoo, the quantity of a byproduct on a manufacturing order is
+recomputed from the producing quantity whenever it is (re)evaluated, including
+when *Produce All* fills the producing quantity automatically. As a result, a
+quantity that an operator entered manually on a byproduct line is silently
+reset to the quantity to produce, unless the line happens to be marked as
+picked.
+
+This module lets you opt in, per product, per product category or company-wide,
+to keep the manually entered byproduct quantity: when an operator edits the
+quantity of an eligible byproduct line, the line is automatically marked as
+picked so its value is preserved through *Produce All*.
+
+Byproduct lines that are not edited keep the standard behavior and still scale
+with the producing quantity.
diff --git a/mrp_byproduct_auto_pick/static/description/icon.png b/mrp_byproduct_auto_pick/static/description/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d
GIT binary patch
literal 9455
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
z
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
Xviia!U7SGha1wx#SCgwmn*{w2TRX*I
literal 0
HcmV?d00001
diff --git a/mrp_byproduct_auto_pick/static/description/index.html b/mrp_byproduct_auto_pick/static/description/index.html
new file mode 100644
index 0000000..517465b
--- /dev/null
+++ b/mrp_byproduct_auto_pick/static/description/index.html
@@ -0,0 +1,464 @@
+
+
+
+
+
+MRP Byproduct Auto Pick
+
+
+
+
+
MRP Byproduct Auto Pick
+
+
+

+
In standard Odoo, the quantity of a byproduct on a manufacturing order
+is recomputed from the producing quantity whenever it is (re)evaluated,
+including when Produce All fills the producing quantity automatically.
+As a result, a quantity that an operator entered manually on a byproduct
+line is silently reset to the quantity to produce, unless the line
+happens to be marked as picked.
+
This module lets you opt in, per product, per product category or
+company-wide, to keep the manually entered byproduct quantity: when an
+operator edits the quantity of an eligible byproduct line, the line is
+automatically marked as picked so its value is preserved through
+Produce All.
+
Byproduct lines that are not edited keep the standard behavior and still
+scale with the producing quantity.
+
Table of contents
+
+
+
+
The behavior is resolved with the following precedence (most specific
+wins):
+
+- Product – Inventory tab of a product, field Byproduct Auto
+Pick.
+- Product category – field Byproduct Auto Pick (cascades up the
+category tree).
+- Company – Manufacturing > Configuration > Settings, option
+Auto-pick Manually Edited Byproducts.
+
+
At product and category level the field has two values, and can also be
+left empty:
+
+- Empty: fall back to the next level (category, then company).
+- Always: keep the manually entered byproduct quantity.
+- Never: reset to the quantity to produce (standard Odoo behavior).
+
+
To enable the behavior everywhere, tick the company-wide option and
+leave the product and category fields empty. To enable it only for some
+products, set them (or their category) to Always.
+
+
+
+
Bugs are tracked on GitHub Issues.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us to smash it by providing a detailed and welcomed
+feedback.
+
Do not contact contributors directly about support or help with technical issues.
+
+
+
+
+
+
+
+
This module is maintained by the OCA.
+
+
+
+
OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
Current maintainers:
+

+
This module is part of the OCA/manufacture project on GitHub.
+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
+
+
+
+
+
diff --git a/mrp_byproduct_auto_pick/tests/__init__.py b/mrp_byproduct_auto_pick/tests/__init__.py
new file mode 100644
index 0000000..e7057f7
--- /dev/null
+++ b/mrp_byproduct_auto_pick/tests/__init__.py
@@ -0,0 +1 @@
+from . import test_mrp_byproduct_auto_pick
diff --git a/mrp_byproduct_auto_pick/tests/test_mrp_byproduct_auto_pick.py b/mrp_byproduct_auto_pick/tests/test_mrp_byproduct_auto_pick.py
new file mode 100644
index 0000000..8100827
--- /dev/null
+++ b/mrp_byproduct_auto_pick/tests/test_mrp_byproduct_auto_pick.py
@@ -0,0 +1,146 @@
+# Copyright 2026 Quartile (https://www.quartile.co)
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo import Command
+from odoo.tests import Form, TransactionCase
+
+
+class TestMrpByproductAutoPick(TransactionCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
+ manufacture_route = cls.env.ref("mrp.route_warehouse0_manufacture")
+ cls.finished = cls.env["product.product"].create(
+ {
+ "name": "Finished",
+ "type": "consu",
+ "is_storable": True,
+ "route_ids": [Command.set(manufacture_route.ids)],
+ }
+ )
+ cls.component = cls.env["product.product"].create(
+ {"name": "Component", "type": "consu"}
+ )
+ cls.byproduct = cls.env["product.product"].create(
+ {"name": "Byproduct", "type": "consu", "is_storable": True}
+ )
+ # BoM: 1 finished = 1 component (+) 2 byproduct
+ cls.bom = cls.env["mrp.bom"].create(
+ {
+ "product_tmpl_id": cls.finished.product_tmpl_id.id,
+ "product_qty": 1.0,
+ "type": "normal",
+ "bom_line_ids": [
+ Command.create({"product_id": cls.component.id, "product_qty": 1.0})
+ ],
+ "byproduct_ids": [
+ Command.create({"product_id": cls.byproduct.id, "product_qty": 2.0})
+ ],
+ }
+ )
+
+ def _confirm_mo(self):
+ mo_form = Form(self.env["mrp.production"])
+ mo_form.product_id = self.finished
+ mo_form.bom_id = self.bom
+ mo_form.product_qty = 1.0
+ mo = mo_form.save()
+ mo.action_confirm()
+ return mo
+
+ def _recompute(self, mo):
+ """Reproduce the recompute that 'Produce All' triggers."""
+ mo.qty_producing = 1.0
+ mo._set_qty_producing(False)
+
+ def test_always_preserves_manual_quantity(self):
+ self.byproduct.byproduct_auto_pick = "always"
+ mo = self._confirm_mo()
+ move = mo.move_byproduct_ids
+ self.assertEqual(len(move), 1)
+ move.quantity = 5.0
+ # Editing the byproduct quantity auto-marks the line as picked.
+ self.assertTrue(move.picked)
+ self._recompute(mo)
+ # The manual value survives the recompute.
+ self.assertEqual(move.quantity, 5.0)
+
+ def test_never_reverts_manual_quantity(self):
+ self.byproduct.byproduct_auto_pick = "never"
+ mo = self._confirm_mo()
+ move = mo.move_byproduct_ids
+ move.quantity = 5.0
+ self.assertFalse(move.picked)
+ self._recompute(mo)
+ # Standard behavior: reset to the quantity to produce (2 per unit).
+ self.assertEqual(move.quantity, 2.0)
+
+ def test_tracked_byproduct_pick_on_line_edit(self):
+ # For tracked byproducts the quantity field is read-only; the operator
+ # enters quantities through the move lines (lot numbers) instead, which
+ # the form sends as move_line_ids commands on the move.
+ self.byproduct.write({"tracking": "lot", "byproduct_auto_pick": "always"})
+ mo = self._confirm_mo()
+ move = mo.move_byproduct_ids
+ self.assertFalse(move.picked)
+ line = move.move_line_ids[:1]
+ if line:
+ move.write(
+ {
+ "move_line_ids": [
+ Command.update(
+ line.id, {"quantity": 5.0, "lot_name": "BP-LOT-1"}
+ )
+ ]
+ }
+ )
+ else:
+ move.write(
+ {
+ "move_line_ids": [
+ Command.create(
+ {
+ "product_id": self.byproduct.id,
+ "quantity": 5.0,
+ "lot_name": "BP-LOT-1",
+ "location_id": move.location_id.id,
+ "location_dest_id": move.location_dest_id.id,
+ }
+ )
+ ]
+ }
+ )
+ # Editing the lot line auto-marks the byproduct as picked.
+ self.assertTrue(move.picked)
+ self._recompute(mo)
+ # The manually entered quantity survives the recompute.
+ self.assertEqual(move.quantity, 5.0)
+
+ def test_company_default_applies(self):
+ self.env.company.byproduct_auto_pick = True
+ self.byproduct.byproduct_auto_pick = False
+ mo = self._confirm_mo()
+ move = mo.move_byproduct_ids
+ move.quantity = 5.0
+ self.assertTrue(move.picked)
+ self._recompute(mo)
+ self.assertEqual(move.quantity, 5.0)
+
+ def test_cascade_resolution(self):
+ move = self._confirm_mo().move_byproduct_ids
+ category = self.byproduct.categ_id
+ # Everything inherits, company off -> not auto picked.
+ self.env.company.byproduct_auto_pick = False
+ self.byproduct.byproduct_auto_pick = False
+ category.byproduct_auto_pick = False
+ self.assertFalse(move._should_auto_pick_byproduct())
+ # Company default on.
+ self.env.company.byproduct_auto_pick = True
+ self.assertTrue(move._should_auto_pick_byproduct())
+ # Category 'never' overrides the company default.
+ category.byproduct_auto_pick = "never"
+ self.assertFalse(move._should_auto_pick_byproduct())
+ # Product 'always' overrides the category.
+ self.byproduct.byproduct_auto_pick = "always"
+ self.assertTrue(move._should_auto_pick_byproduct())
diff --git a/mrp_byproduct_auto_pick/views/product_category_views.xml b/mrp_byproduct_auto_pick/views/product_category_views.xml
new file mode 100644
index 0000000..3226ba8
--- /dev/null
+++ b/mrp_byproduct_auto_pick/views/product_category_views.xml
@@ -0,0 +1,13 @@
+
+
+
+ product.category.form.byproduct.auto.pick
+ product.category
+
+
+
+
+
+
+
+
diff --git a/mrp_byproduct_auto_pick/views/product_views.xml b/mrp_byproduct_auto_pick/views/product_views.xml
new file mode 100644
index 0000000..8401186
--- /dev/null
+++ b/mrp_byproduct_auto_pick/views/product_views.xml
@@ -0,0 +1,19 @@
+
+
+
+ product.template.form.byproduct.auto.pick
+ product.template
+
+
+
+
+
+
+
+
+
+
diff --git a/mrp_byproduct_auto_pick/views/res_config_settings_views.xml b/mrp_byproduct_auto_pick/views/res_config_settings_views.xml
new file mode 100644
index 0000000..1caabdd
--- /dev/null
+++ b/mrp_byproduct_auto_pick/views/res_config_settings_views.xml
@@ -0,0 +1,18 @@
+
+
+
+ res.config.settings.form.byproduct.auto.pick
+ res.config.settings
+
+
+
+
+
+
+
+
+
+
From c6f074dcce310ec03c4358c4d6b7ffff766bc76a Mon Sep 17 00:00:00 2001
From: Aungkokolin1997
Date: Fri, 12 Jun 2026 06:39:54 +0000
Subject: [PATCH 2/3] reflect oca changes
---
mrp_byproduct_auto_pick/README.rst | 32 ++++--------
mrp_byproduct_auto_pick/__manifest__.py | 3 +-
mrp_byproduct_auto_pick/models/__init__.py | 3 +-
.../models/mrp_production.py | 22 ++++++++
.../models/product_category.py | 20 -------
.../models/product_template.py | 19 -------
mrp_byproduct_auto_pick/models/res_company.py | 3 +-
mrp_byproduct_auto_pick/models/stock_move.py | 10 +---
mrp_byproduct_auto_pick/readme/CONFIGURE.md | 23 +++-----
mrp_byproduct_auto_pick/readme/DESCRIPTION.md | 9 ++--
.../static/description/index.html | 31 ++++-------
.../tests/test_mrp_byproduct_auto_pick.py | 52 +++++++++----------
.../views/mrp_production_views.xml | 13 +++++
.../views/product_category_views.xml | 13 -----
.../views/product_views.xml | 19 -------
.../views/res_config_settings_views.xml | 3 +-
16 files changed, 96 insertions(+), 179 deletions(-)
create mode 100644 mrp_byproduct_auto_pick/models/mrp_production.py
delete mode 100644 mrp_byproduct_auto_pick/models/product_category.py
delete mode 100644 mrp_byproduct_auto_pick/models/product_template.py
create mode 100644 mrp_byproduct_auto_pick/views/mrp_production_views.xml
delete mode 100644 mrp_byproduct_auto_pick/views/product_category_views.xml
delete mode 100644 mrp_byproduct_auto_pick/views/product_views.xml
diff --git a/mrp_byproduct_auto_pick/README.rst b/mrp_byproduct_auto_pick/README.rst
index 2a9b4da..3c7f241 100644
--- a/mrp_byproduct_auto_pick/README.rst
+++ b/mrp_byproduct_auto_pick/README.rst
@@ -35,9 +35,10 @@ As a result, a quantity that an operator entered manually on a byproduct
line is silently reset to the quantity to produce, unless the line
happens to be marked as picked.
-This module lets you opt in, per product, per product category or
-company-wide, to keep the manually entered byproduct quantity: when an
-operator edits the quantity of an eligible byproduct line, the line is
+This module adds an *Auto-pick Manually Edited Byproducts* option to
+manufacturing orders (defaulted from a company-wide setting) to keep the
+manually entered byproduct quantity: when an operator edits the quantity
+of a byproduct line on an enabled manufacturing order, the line is
automatically marked as picked so its value is preserved through
*Produce All*.
@@ -52,26 +53,13 @@ scale with the producing quantity.
Configuration
=============
-The behavior is resolved with the following precedence (most specific
-wins):
+1. **Company default** -- Go to *Manufacturing > Configuration >
+ Settings* and tick *Auto-pick Manually Edited Byproducts*. New
+ manufacturing orders will inherit this value.
-1. **Product** -- *Inventory* tab of a product, field *Byproduct Auto
- Pick*.
-2. **Product category** -- field *Byproduct Auto Pick* (cascades up the
- category tree).
-3. **Company** -- *Manufacturing > Configuration > Settings*, option
- *Auto-pick Manually Edited Byproducts*.
-
-At product and category level the field has two values, and can also be
-left empty:
-
-- **Empty**: fall back to the next level (category, then company).
-- **Always**: keep the manually entered byproduct quantity.
-- **Never**: reset to the quantity to produce (standard Odoo behavior).
-
-To enable the behavior everywhere, tick the company-wide option and
-leave the product and category fields empty. To enable it only for some
-products, set them (or their category) to *Always*.
+2. **Per manufacturing order** -- The *Auto-pick Manually Edited
+ Byproducts* checkbox on a manufacturing order can be toggled
+ individually, overriding the company default for that order.
Bug Tracker
===========
diff --git a/mrp_byproduct_auto_pick/__manifest__.py b/mrp_byproduct_auto_pick/__manifest__.py
index fc161ab..c12c10c 100644
--- a/mrp_byproduct_auto_pick/__manifest__.py
+++ b/mrp_byproduct_auto_pick/__manifest__.py
@@ -12,8 +12,7 @@
"website": "https://github.com/OCA/manufacture",
"depends": ["mrp"],
"data": [
- "views/product_category_views.xml",
- "views/product_views.xml",
+ "views/mrp_production_views.xml",
"views/res_config_settings_views.xml",
],
"maintainers": ["yostashiro", "aungkokolin1997"],
diff --git a/mrp_byproduct_auto_pick/models/__init__.py b/mrp_byproduct_auto_pick/models/__init__.py
index 1d606bf..ab1f55c 100644
--- a/mrp_byproduct_auto_pick/models/__init__.py
+++ b/mrp_byproduct_auto_pick/models/__init__.py
@@ -1,5 +1,4 @@
+from . import mrp_production
from . import res_company
from . import res_config_settings
-from . import product_category
-from . import product_template
from . import stock_move
diff --git a/mrp_byproduct_auto_pick/models/mrp_production.py b/mrp_byproduct_auto_pick/models/mrp_production.py
new file mode 100644
index 0000000..206dca4
--- /dev/null
+++ b/mrp_byproduct_auto_pick/models/mrp_production.py
@@ -0,0 +1,22 @@
+# Copyright 2026 Quartile (https://www.quartile.co)
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo import api, fields, models
+
+
+class MrpProduction(models.Model):
+ _inherit = "mrp.production"
+
+ byproduct_auto_pick = fields.Boolean(
+ string="Auto-pick Manually Edited Byproducts",
+ compute="_compute_byproduct_auto_pick",
+ store=True,
+ readonly=False,
+ help="When enabled, a manually entered byproduct quantity is kept "
+ "(marked as picked) instead of being reset to the quantity to produce.",
+ )
+
+ @api.depends("company_id")
+ def _compute_byproduct_auto_pick(self):
+ for production in self:
+ production.byproduct_auto_pick = production.company_id.byproduct_auto_pick
diff --git a/mrp_byproduct_auto_pick/models/product_category.py b/mrp_byproduct_auto_pick/models/product_category.py
deleted file mode 100644
index 0759a4c..0000000
--- a/mrp_byproduct_auto_pick/models/product_category.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2026 Quartile (https://www.quartile.co)
-# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
-
-from odoo import fields, models
-
-
-class ProductCategory(models.Model):
- _inherit = "product.category"
-
- byproduct_auto_pick = fields.Selection(
- selection=[
- ("always", "Always"),
- ("never", "Never"),
- ],
- help="Controls whether a manually entered quantity for products in "
- "this category, when produced as a byproduct, is kept (marked as "
- "picked) instead of being reset to the quantity to produce. Leave "
- "empty to fall back to the parent category, then the company "
- "setting.",
- )
diff --git a/mrp_byproduct_auto_pick/models/product_template.py b/mrp_byproduct_auto_pick/models/product_template.py
deleted file mode 100644
index e1e4da3..0000000
--- a/mrp_byproduct_auto_pick/models/product_template.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2026 Quartile (https://www.quartile.co)
-# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
-
-from odoo import fields, models
-
-
-class ProductTemplate(models.Model):
- _inherit = "product.template"
-
- byproduct_auto_pick = fields.Selection(
- selection=[
- ("always", "Always"),
- ("never", "Never"),
- ],
- help="Controls whether a manually entered quantity for this product, "
- "when produced as a byproduct, is kept (marked as picked) instead of "
- "being reset to the quantity to produce. Leave empty to fall back to "
- "the product category, then the company setting.",
- )
diff --git a/mrp_byproduct_auto_pick/models/res_company.py b/mrp_byproduct_auto_pick/models/res_company.py
index 6aebc0a..a61291d 100644
--- a/mrp_byproduct_auto_pick/models/res_company.py
+++ b/mrp_byproduct_auto_pick/models/res_company.py
@@ -11,6 +11,5 @@ class ResCompany(models.Model):
string="Auto-pick Manually Edited Byproducts",
help="When enabled, a manually entered byproduct quantity on a "
"manufacturing order is kept (marked as picked) instead of being "
- "reset to the quantity to produce. This is the company-wide default, "
- "which can be overridden per product category or per product.",
+ "reset to the quantity to produce.",
)
diff --git a/mrp_byproduct_auto_pick/models/stock_move.py b/mrp_byproduct_auto_pick/models/stock_move.py
index 7f795bb..db4c652 100644
--- a/mrp_byproduct_auto_pick/models/stock_move.py
+++ b/mrp_byproduct_auto_pick/models/stock_move.py
@@ -15,15 +15,7 @@ def _is_auto_pick_byproduct(self):
def _should_auto_pick_byproduct(self):
self.ensure_one()
- template = self.product_id.product_tmpl_id
- if template.byproduct_auto_pick:
- return template.byproduct_auto_pick == "always"
- category = template.categ_id
- while category:
- if category.byproduct_auto_pick:
- return category.byproduct_auto_pick == "always"
- category = category.parent_id
- return self.company_id.byproduct_auto_pick
+ return self.production_id.byproduct_auto_pick
def write(self, vals):
# The MO recompute writes byproduct quantities through
diff --git a/mrp_byproduct_auto_pick/readme/CONFIGURE.md b/mrp_byproduct_auto_pick/readme/CONFIGURE.md
index 2817193..bc2e443 100644
--- a/mrp_byproduct_auto_pick/readme/CONFIGURE.md
+++ b/mrp_byproduct_auto_pick/readme/CONFIGURE.md
@@ -1,18 +1,7 @@
-The behavior is resolved with the following precedence (most specific wins):
+1. **Company default** -- Go to *Manufacturing \> Configuration \> Settings*
+ and tick *Auto-pick Manually Edited Byproducts*. New manufacturing orders
+ will inherit this value.
-1. **Product** -- *Inventory* tab of a product, field *Byproduct Auto Pick*.
-2. **Product category** -- field *Byproduct Auto Pick* (cascades up the
- category tree).
-3. **Company** -- *Manufacturing \> Configuration \> Settings*, option
- *Auto-pick Manually Edited Byproducts*.
-
-At product and category level the field has two values, and can also be left
-empty:
-
-- **Empty**: fall back to the next level (category, then company).
-- **Always**: keep the manually entered byproduct quantity.
-- **Never**: reset to the quantity to produce (standard Odoo behavior).
-
-To enable the behavior everywhere, tick the company-wide option and leave the
-product and category fields empty. To enable it only for some products, set
-them (or their category) to *Always*.
+2. **Per manufacturing order** -- The *Auto-pick Manually Edited Byproducts*
+ checkbox on a manufacturing order can be toggled individually, overriding
+ the company default for that order.
diff --git a/mrp_byproduct_auto_pick/readme/DESCRIPTION.md b/mrp_byproduct_auto_pick/readme/DESCRIPTION.md
index 7dccd41..e25bc6b 100644
--- a/mrp_byproduct_auto_pick/readme/DESCRIPTION.md
+++ b/mrp_byproduct_auto_pick/readme/DESCRIPTION.md
@@ -5,10 +5,11 @@ quantity that an operator entered manually on a byproduct line is silently
reset to the quantity to produce, unless the line happens to be marked as
picked.
-This module lets you opt in, per product, per product category or company-wide,
-to keep the manually entered byproduct quantity: when an operator edits the
-quantity of an eligible byproduct line, the line is automatically marked as
-picked so its value is preserved through *Produce All*.
+This module adds an *Auto-pick Manually Edited Byproducts* option to
+manufacturing orders (defaulted from a company-wide setting) to keep the
+manually entered byproduct quantity: when an operator edits the quantity of a
+byproduct line on an enabled manufacturing order, the line is automatically
+marked as picked so its value is preserved through *Produce All*.
Byproduct lines that are not edited keep the standard behavior and still scale
with the producing quantity.
diff --git a/mrp_byproduct_auto_pick/static/description/index.html b/mrp_byproduct_auto_pick/static/description/index.html
index 517465b..009aba8 100644
--- a/mrp_byproduct_auto_pick/static/description/index.html
+++ b/mrp_byproduct_auto_pick/static/description/index.html
@@ -376,9 +376,10 @@ MRP Byproduct Auto Pick
As a result, a quantity that an operator entered manually on a byproduct
line is silently reset to the quantity to produce, unless the line
happens to be marked as picked.
-This module lets you opt in, per product, per product category or
-company-wide, to keep the manually entered byproduct quantity: when an
-operator edits the quantity of an eligible byproduct line, the line is
+
This module adds an Auto-pick Manually Edited Byproducts option to
+manufacturing orders (defaulted from a company-wide setting) to keep the
+manually entered byproduct quantity: when an operator edits the quantity
+of a byproduct line on an enabled manufacturing order, the line is
automatically marked as picked so its value is preserved through
Produce All.
Byproduct lines that are not edited keep the standard behavior and still
@@ -398,26 +399,14 @@
MRP Byproduct Auto Pick
-
The behavior is resolved with the following precedence (most specific
-wins):
-- Product – Inventory tab of a product, field Byproduct Auto
-Pick.
-- Product category – field Byproduct Auto Pick (cascades up the
-category tree).
-- Company – Manufacturing > Configuration > Settings, option
-Auto-pick Manually Edited Byproducts.
+- Company default – Go to Manufacturing > Configuration >
+Settings and tick Auto-pick Manually Edited Byproducts. New
+manufacturing orders will inherit this value.
+- Per manufacturing order – The Auto-pick Manually Edited
+Byproducts checkbox on a manufacturing order can be toggled
+individually, overriding the company default for that order.
-
At product and category level the field has two values, and can also be
-left empty:
-
-- Empty: fall back to the next level (category, then company).
-- Always: keep the manually entered byproduct quantity.
-- Never: reset to the quantity to produce (standard Odoo behavior).
-
-
To enable the behavior everywhere, tick the company-wide option and
-leave the product and category fields empty. To enable it only for some
-products, set them (or their category) to Always.
diff --git a/mrp_byproduct_auto_pick/tests/test_mrp_byproduct_auto_pick.py b/mrp_byproduct_auto_pick/tests/test_mrp_byproduct_auto_pick.py
index 8100827..a993f82 100644
--- a/mrp_byproduct_auto_pick/tests/test_mrp_byproduct_auto_pick.py
+++ b/mrp_byproduct_auto_pick/tests/test_mrp_byproduct_auto_pick.py
@@ -40,12 +40,13 @@ def setUpClass(cls):
}
)
- def _confirm_mo(self):
+ def _confirm_mo(self, byproduct_auto_pick=True):
mo_form = Form(self.env["mrp.production"])
mo_form.product_id = self.finished
mo_form.bom_id = self.bom
mo_form.product_qty = 1.0
mo = mo_form.save()
+ mo.byproduct_auto_pick = byproduct_auto_pick
mo.action_confirm()
return mo
@@ -54,9 +55,8 @@ def _recompute(self, mo):
mo.qty_producing = 1.0
mo._set_qty_producing(False)
- def test_always_preserves_manual_quantity(self):
- self.byproduct.byproduct_auto_pick = "always"
- mo = self._confirm_mo()
+ def test_enabled_preserves_manual_quantity(self):
+ mo = self._confirm_mo(byproduct_auto_pick=True)
move = mo.move_byproduct_ids
self.assertEqual(len(move), 1)
move.quantity = 5.0
@@ -66,9 +66,8 @@ def test_always_preserves_manual_quantity(self):
# The manual value survives the recompute.
self.assertEqual(move.quantity, 5.0)
- def test_never_reverts_manual_quantity(self):
- self.byproduct.byproduct_auto_pick = "never"
- mo = self._confirm_mo()
+ def test_disabled_reverts_manual_quantity(self):
+ mo = self._confirm_mo(byproduct_auto_pick=False)
move = mo.move_byproduct_ids
move.quantity = 5.0
self.assertFalse(move.picked)
@@ -80,8 +79,8 @@ def test_tracked_byproduct_pick_on_line_edit(self):
# For tracked byproducts the quantity field is read-only; the operator
# enters quantities through the move lines (lot numbers) instead, which
# the form sends as move_line_ids commands on the move.
- self.byproduct.write({"tracking": "lot", "byproduct_auto_pick": "always"})
- mo = self._confirm_mo()
+ self.byproduct.write({"tracking": "lot"})
+ mo = self._confirm_mo(byproduct_auto_pick=True)
move = mo.move_byproduct_ids
self.assertFalse(move.picked)
line = move.move_line_ids[:1]
@@ -117,30 +116,27 @@ def test_tracked_byproduct_pick_on_line_edit(self):
# The manually entered quantity survives the recompute.
self.assertEqual(move.quantity, 5.0)
- def test_company_default_applies(self):
+ def test_company_default_propagated(self):
self.env.company.byproduct_auto_pick = True
- self.byproduct.byproduct_auto_pick = False
- mo = self._confirm_mo()
+ mo_form = Form(self.env["mrp.production"])
+ mo_form.product_id = self.finished
+ mo_form.bom_id = self.bom
+ mo_form.product_qty = 1.0
+ mo = mo_form.save()
+ # The computed field should pick up the company value.
+ self.assertTrue(mo.byproduct_auto_pick)
+ mo.action_confirm()
move = mo.move_byproduct_ids
move.quantity = 5.0
self.assertTrue(move.picked)
self._recompute(mo)
self.assertEqual(move.quantity, 5.0)
- def test_cascade_resolution(self):
- move = self._confirm_mo().move_byproduct_ids
- category = self.byproduct.categ_id
- # Everything inherits, company off -> not auto picked.
+ def test_company_default_off(self):
self.env.company.byproduct_auto_pick = False
- self.byproduct.byproduct_auto_pick = False
- category.byproduct_auto_pick = False
- self.assertFalse(move._should_auto_pick_byproduct())
- # Company default on.
- self.env.company.byproduct_auto_pick = True
- self.assertTrue(move._should_auto_pick_byproduct())
- # Category 'never' overrides the company default.
- category.byproduct_auto_pick = "never"
- self.assertFalse(move._should_auto_pick_byproduct())
- # Product 'always' overrides the category.
- self.byproduct.byproduct_auto_pick = "always"
- self.assertTrue(move._should_auto_pick_byproduct())
+ mo_form = Form(self.env["mrp.production"])
+ mo_form.product_id = self.finished
+ mo_form.bom_id = self.bom
+ mo_form.product_qty = 1.0
+ mo = mo_form.save()
+ self.assertFalse(mo.byproduct_auto_pick)
diff --git a/mrp_byproduct_auto_pick/views/mrp_production_views.xml b/mrp_byproduct_auto_pick/views/mrp_production_views.xml
new file mode 100644
index 0000000..c77f964
--- /dev/null
+++ b/mrp_byproduct_auto_pick/views/mrp_production_views.xml
@@ -0,0 +1,13 @@
+
+
+
+ mrp.production.form.byproduct.auto.pick
+ mrp.production
+
+
+
+
+
+
+
+
diff --git a/mrp_byproduct_auto_pick/views/product_category_views.xml b/mrp_byproduct_auto_pick/views/product_category_views.xml
deleted file mode 100644
index 3226ba8..0000000
--- a/mrp_byproduct_auto_pick/views/product_category_views.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
- product.category.form.byproduct.auto.pick
- product.category
-
-
-
-
-
-
-
-
diff --git a/mrp_byproduct_auto_pick/views/product_views.xml b/mrp_byproduct_auto_pick/views/product_views.xml
deleted file mode 100644
index 8401186..0000000
--- a/mrp_byproduct_auto_pick/views/product_views.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
- product.template.form.byproduct.auto.pick
- product.template
-
-
-
-
-
-
-
-
-
-
diff --git a/mrp_byproduct_auto_pick/views/res_config_settings_views.xml b/mrp_byproduct_auto_pick/views/res_config_settings_views.xml
index 1caabdd..4376acb 100644
--- a/mrp_byproduct_auto_pick/views/res_config_settings_views.xml
+++ b/mrp_byproduct_auto_pick/views/res_config_settings_views.xml
@@ -8,7 +8,8 @@
From 35fef5de42bb2514a158d42eada08f1dd107eab8 Mon Sep 17 00:00:00 2001
From: Aungkokolin1997
Date: Mon, 15 Jun 2026 02:17:06 +0000
Subject: [PATCH 3/3] reflect oca changes
---
mrp_byproduct_auto_pick/README.rst | 8 ++++----
mrp_byproduct_auto_pick/__manifest__.py | 2 +-
mrp_byproduct_auto_pick/models/mrp_production.py | 4 ++--
mrp_byproduct_auto_pick/models/res_company.py | 7 +------
.../static/description/icon.png | Bin 9455 -> 0 bytes
.../static/description/index.html | 2 +-
.../views/mrp_production_views.xml | 9 +++++++--
7 files changed, 16 insertions(+), 16 deletions(-)
delete mode 100644 mrp_byproduct_auto_pick/static/description/icon.png
diff --git a/mrp_byproduct_auto_pick/README.rst b/mrp_byproduct_auto_pick/README.rst
index 3c7f241..10810a6 100644
--- a/mrp_byproduct_auto_pick/README.rst
+++ b/mrp_byproduct_auto_pick/README.rst
@@ -99,16 +99,16 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
-.. |maintainer-yostashiro| image:: https://github.com/yostashiro.png?size=40px
- :target: https://github.com/yostashiro
- :alt: yostashiro
+.. |maintainer-kanda999| image:: https://github.com/kanda999.png?size=40px
+ :target: https://github.com/kanda999
+ :alt: kanda999
.. |maintainer-aungkokolin1997| image:: https://github.com/aungkokolin1997.png?size=40px
:target: https://github.com/aungkokolin1997
:alt: aungkokolin1997
Current `maintainers `__:
-|maintainer-yostashiro| |maintainer-aungkokolin1997|
+|maintainer-kanda999| |maintainer-aungkokolin1997|
This module is part of the `OCA/manufacture `_ project on GitHub.
diff --git a/mrp_byproduct_auto_pick/__manifest__.py b/mrp_byproduct_auto_pick/__manifest__.py
index c12c10c..3df14ef 100644
--- a/mrp_byproduct_auto_pick/__manifest__.py
+++ b/mrp_byproduct_auto_pick/__manifest__.py
@@ -15,6 +15,6 @@
"views/mrp_production_views.xml",
"views/res_config_settings_views.xml",
],
- "maintainers": ["yostashiro", "aungkokolin1997"],
+ "maintainers": ["kanda999", "aungkokolin1997"],
"installable": True,
}
diff --git a/mrp_byproduct_auto_pick/models/mrp_production.py b/mrp_byproduct_auto_pick/models/mrp_production.py
index 206dca4..a1a0ac4 100644
--- a/mrp_byproduct_auto_pick/models/mrp_production.py
+++ b/mrp_byproduct_auto_pick/models/mrp_production.py
@@ -12,8 +12,8 @@ class MrpProduction(models.Model):
compute="_compute_byproduct_auto_pick",
store=True,
readonly=False,
- help="When enabled, a manually entered byproduct quantity is kept "
- "(marked as picked) instead of being reset to the quantity to produce.",
+ help="Keep manually entered byproduct quantities on manufacturing "
+ "orders instead of resetting them to the quantity to produce.",
)
@api.depends("company_id")
diff --git a/mrp_byproduct_auto_pick/models/res_company.py b/mrp_byproduct_auto_pick/models/res_company.py
index a61291d..7475154 100644
--- a/mrp_byproduct_auto_pick/models/res_company.py
+++ b/mrp_byproduct_auto_pick/models/res_company.py
@@ -7,9 +7,4 @@
class ResCompany(models.Model):
_inherit = "res.company"
- byproduct_auto_pick = fields.Boolean(
- string="Auto-pick Manually Edited Byproducts",
- help="When enabled, a manually entered byproduct quantity on a "
- "manufacturing order is kept (marked as picked) instead of being "
- "reset to the quantity to produce.",
- )
+ byproduct_auto_pick = fields.Boolean(string="Auto-pick Manually Edited Byproducts")
diff --git a/mrp_byproduct_auto_pick/static/description/icon.png b/mrp_byproduct_auto_pick/static/description/icon.png
deleted file mode 100644
index 3a0328b516c4980e8e44cdb63fd945757ddd132d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 9455
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
z
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
Xviia!U7SGha1wx#SCgwmn*{w2TRX*I
diff --git a/mrp_byproduct_auto_pick/static/description/index.html b/mrp_byproduct_auto_pick/static/description/index.html
index 009aba8..74ffd52 100644
--- a/mrp_byproduct_auto_pick/static/description/index.html
+++ b/mrp_byproduct_auto_pick/static/description/index.html
@@ -443,7 +443,7 @@
mission is to support the collaborative development of Odoo features and
promote its widespread use.
Current maintainers:
-

+

This module is part of the OCA/manufacture project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/mrp_byproduct_auto_pick/views/mrp_production_views.xml b/mrp_byproduct_auto_pick/views/mrp_production_views.xml
index c77f964..ad5b539 100644
--- a/mrp_byproduct_auto_pick/views/mrp_production_views.xml
+++ b/mrp_byproduct_auto_pick/views/mrp_production_views.xml
@@ -5,8 +5,13 @@
mrp.production
-
-
+
+
+
+