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 z?n?eq1XP>p-IM$Z^C;2L3itnbJZAip*Zo0aw2bs8@(s^~*8T9go!%dHcAz2lM;`yp zD=7&xjFV$S&5uDaiScyD?B-i1ze`+CoRtz`Wn+Zl&#s4&}MO{@N!ufrzjG$B79)Y2d3tBk&)TxUTw@QS0TEL_?njX|@vq?Uz(nBFK5Pq7*xj#u*R&i|?7+6# z+|r_n#SW&LXhtheZdah{ZVoqwyT{D>MC3nkFF#N)xLi{p7J1jXlmVeb;cP5?e(=f# zuT7fvjSbjS781v?7{)-X3*?>tq?)Yd)~|1{BDS(pqC zC}~H#WXlkUW*H5CDOo<)#x7%RY)A;ShGhI5s*#cRDA8YgqG(HeKDx+#(ZQ?386dv! zlXCO)w91~Vw4AmOcATuV653fa9R$fyK8ul%rG z-wfS zihugoZyr38Im?Zuh6@RcF~t1anQu7>#lPpb#}4cOA!EM11`%f*07RqOVkmX{p~KJ9 z^zP;K#|)$`^Rb{rnHGH{~>1(fawV0*Z#)}M`m8-?ZJV<+e}s9wE# z)l&az?w^5{)`S(%MRzxdNqrs1n*-=jS^_jqE*5XDrA0+VE`5^*p3CuM<&dZEeCjoz zR;uu_H9ZPZV|fQq`Cyw4nscrVwi!fE6ciMmX$!_hN7uF;jjKG)d2@aC4ropY)8etW=xJvni)8eHi`H$%#zn^WJ5NLc-rqk|u&&4Z6fD_m&JfSI1Bvb?b<*n&sfl0^t z=HnmRl`XrFvMKB%9}>PaA`m-fK6a0(8=qPkWS5bb4=v?XcWi&hRY?O5HdulRi4?fN zlsJ*N-0Qw+Yic@s0(2uy%F@ib;GjXt01Fmx5XbRo6+n|pP(&nodMoap^z{~q ziEeaUT@Mxe3vJSfI6?uLND(CNr=#^W<1b}jzW58bIfyWTDle$mmS(|x-0|2UlX+9k zQ^EX7Nw}?EzVoBfT(-LT|=9N@^hcn-_p&sqG z&*oVs2JSU+N4ZD`FhCAWaS;>|wH2G*Id|?pa#@>tyxX`+4HyIArWDvVrX)2WAOQff z0qyHu&-S@i^MS-+j--!pr4fPBj~_8({~e1bfcl0wI1kaoN>mJL6KUPQm5N7lB(ui1 zE-o%kq)&djzWJ}ob<-GfDlkB;F31j-VHKvQUGQ3sp`CwyGJk_i!y^sD0fqC@$9|jO zOqN!r!8-p==F@ZVP=U$qSpY(gQ0)59P1&t@y?5rvg<}E+GB}26NYPp4f2YFQrQtot5mn3wu_qprZ=>Ig-$ zbW26Ws~IgY>}^5w`vTB(G`PTZaDiGBo5o(tp)qli|NeV( z@H_=R8V39rt5J5YB2Ky?4eJJ#b`_iBe2ot~6%7mLt5t8Vwi^Jy7|jWXqa3amOIoRb zOr}WVFP--DsS`1WpN%~)t3R!arKF^Q$e12KEqU36AWwnCBICpH4XCsfnyrHr>$I$4 z!DpKX$OKLWarN7nv@!uIA+~RNO)l$$w}p(;b>mx8pwYvu;dD_unryX_NhT8*Tj>BTrTTL&!?O+%Rv;b?B??gSzdp?6Uug9{ zd@V08Z$BdI?fpoCS$)t4mg4rT8Q_I}h`0d-vYZ^|dOB*Q^S|xqTV*vIg?@fVFSmMpaw0qtTRbx} z({Pg?#{2`sc9)M5N$*N|4;^t$+QP?#mov zGVC@I*lBVrOU-%2y!7%)fAKjpEFsgQc4{amtiHb95KQEwvf<(3T<9-Zm$xIew#P22 zc2Ix|App^>v6(3L_MCU0d3W##AB0M~3D00EWoKZqsJYT(#@w$Y_H7G22M~ApVFTRHMI_3be)Lkn#0F*V8Pq zc}`Cjy$bE;FJ6H7p=0y#R>`}-m4(0F>%@P|?7fx{=R^uFdISRnZ2W_xQhD{YuR3t< z{6yxu=4~JkeA;|(J6_nv#>Nvs&FuLA&PW^he@t(UwFFE8)|a!R{`E`K`i^ZnyE4$k z;(749Ix|oi$c3QbEJ3b~D_kQsPz~fIUKym($a_7dJ?o+40*OLl^{=&oq$<#Q(yyrp z{J-FAniyAw9tPbe&IhQ|a`DqFTVQGQ&Gq3!C2==4x{6EJwiPZ8zub-iXoUtkJiG{} zPaR&}_fn8_z~(=;5lD-aPWD3z8PZS@AaUiomF!G8I}Mf>e~0g#BelA-5#`cj;O5>N 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

+ + +

Beta License: AGPL-3 OCA/manufacture Translate me on Weblate Try me on Runboat

+

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

+ +
+

Configuration

+

The behavior is resolved with the following precedence (most specific +wins):

+
    +
  1. ProductInventory tab of a product, field Byproduct Auto +Pick.
  2. +
  3. Product category – field Byproduct Auto Pick (cascades up the +category tree).
  4. +
  5. CompanyManufacturing > Configuration > Settings, option +Auto-pick Manually Edited Byproducts.
  6. +
+

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

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

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:

+

yostashiro 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/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

Configuration

-

The behavior is resolved with the following precedence (most specific -wins):

    -
  1. ProductInventory tab of a product, field Byproduct Auto -Pick.
  2. -
  3. Product category – field Byproduct Auto Pick (cascades up the -category tree).
  4. -
  5. CompanyManufacturing > Configuration > Settings, option -Auto-pick Manually Edited Byproducts.
  6. +
  7. Company default – Go to Manufacturing > Configuration > +Settings and tick Auto-pick Manually Edited Byproducts. New +manufacturing orders will inherit this value.
  8. +
  9. 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.

Bug Tracker

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 z?n?eq1XP>p-IM$Z^C;2L3itnbJZAip*Zo0aw2bs8@(s^~*8T9go!%dHcAz2lM;`yp zD=7&xjFV$S&5uDaiScyD?B-i1ze`+CoRtz`Wn+Zl&#s4&}MO{@N!ufrzjG$B79)Y2d3tBk&)TxUTw@QS0TEL_?njX|@vq?Uz(nBFK5Pq7*xj#u*R&i|?7+6# z+|r_n#SW&LXhtheZdah{ZVoqwyT{D>MC3nkFF#N)xLi{p7J1jXlmVeb;cP5?e(=f# zuT7fvjSbjS781v?7{)-X3*?>tq?)Yd)~|1{BDS(pqC zC}~H#WXlkUW*H5CDOo<)#x7%RY)A;ShGhI5s*#cRDA8YgqG(HeKDx+#(ZQ?386dv! zlXCO)w91~Vw4AmOcATuV653fa9R$fyK8ul%rG z-wfS zihugoZyr38Im?Zuh6@RcF~t1anQu7>#lPpb#}4cOA!EM11`%f*07RqOVkmX{p~KJ9 z^zP;K#|)$`^Rb{rnHGH{~>1(fawV0*Z#)}M`m8-?ZJV<+e}s9wE# z)l&az?w^5{)`S(%MRzxdNqrs1n*-=jS^_jqE*5XDrA0+VE`5^*p3CuM<&dZEeCjoz zR;uu_H9ZPZV|fQq`Cyw4nscrVwi!fE6ciMmX$!_hN7uF;jjKG)d2@aC4ropY)8etW=xJvni)8eHi`H$%#zn^WJ5NLc-rqk|u&&4Z6fD_m&JfSI1Bvb?b<*n&sfl0^t z=HnmRl`XrFvMKB%9}>PaA`m-fK6a0(8=qPkWS5bb4=v?XcWi&hRY?O5HdulRi4?fN zlsJ*N-0Qw+Yic@s0(2uy%F@ib;GjXt01Fmx5XbRo6+n|pP(&nodMoap^z{~q ziEeaUT@Mxe3vJSfI6?uLND(CNr=#^W<1b}jzW58bIfyWTDle$mmS(|x-0|2UlX+9k zQ^EX7Nw}?EzVoBfT(-LT|=9N@^hcn-_p&sqG z&*oVs2JSU+N4ZD`FhCAWaS;>|wH2G*Id|?pa#@>tyxX`+4HyIArWDvVrX)2WAOQff z0qyHu&-S@i^MS-+j--!pr4fPBj~_8({~e1bfcl0wI1kaoN>mJL6KUPQm5N7lB(ui1 zE-o%kq)&djzWJ}ob<-GfDlkB;F31j-VHKvQUGQ3sp`CwyGJk_i!y^sD0fqC@$9|jO zOqN!r!8-p==F@ZVP=U$qSpY(gQ0)59P1&t@y?5rvg<}E+GB}26NYPp4f2YFQrQtot5mn3wu_qprZ=>Ig-$ zbW26Ws~IgY>}^5w`vTB(G`PTZaDiGBo5o(tp)qli|NeV( z@H_=R8V39rt5J5YB2Ky?4eJJ#b`_iBe2ot~6%7mLt5t8Vwi^Jy7|jWXqa3amOIoRb zOr}WVFP--DsS`1WpN%~)t3R!arKF^Q$e12KEqU36AWwnCBICpH4XCsfnyrHr>$I$4 z!DpKX$OKLWarN7nv@!uIA+~RNO)l$$w}p(;b>mx8pwYvu;dD_unryX_NhT8*Tj>BTrTTL&!?O+%Rv;b?B??gSzdp?6Uug9{ zd@V08Z$BdI?fpoCS$)t4mg4rT8Q_I}h`0d-vYZ^|dOB*Q^S|xqTV*vIg?@fVFSmMpaw0qtTRbx} z({Pg?#{2`sc9)M5N$*N|4;^t$+QP?#mov zGVC@I*lBVrOU-%2y!7%)fAKjpEFsgQc4{amtiHb95KQEwvf<(3T<9-Zm$xIew#P22 zc2Ix|App^>v6(3L_MCU0d3W##AB0M~3D00EWoKZqsJYT(#@w$Y_H7G22M~ApVFTRHMI_3be)Lkn#0F*V8Pq zc}`Cjy$bE;FJ6H7p=0y#R>`}-m4(0F>%@P|?7fx{=R^uFdISRnZ2W_xQhD{YuR3t< z{6yxu=4~JkeA;|(J6_nv#>Nvs&FuLA&PW^he@t(UwFFE8)|a!R{`E`K`i^ZnyE4$k z;(749Ix|oi$c3QbEJ3b~D_kQsPz~fIUKym($a_7dJ?o+40*OLl^{=&oq$<#Q(yyrp z{J-FAniyAw9tPbe&IhQ|a`DqFTVQGQ&Gq3!C2==4x{6EJwiPZ8zub-iXoUtkJiG{} zPaR&}_fn8_z~(=;5lD-aPWD3z8PZS@AaUiomF!G8I}Mf>e~0g#BelA-5#`cj;O5>N 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 @@

Maintainers

mission is to support the collaborative development of Odoo features and promote its widespread use.

Current maintainers:

-

yostashiro aungkokolin1997

+

kanda999 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/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 - - + + + +