Repository: OCA/stock-logistics-workflow
Pull request #1902: [18.0][MIG] stock_product_set: Migration to 18.0
Author: login: victoralmau
Labels: name: needs review
name: approved
name: migration
name: merged 🎉
Created: 2025-03-20T12:05:41Z | Merged: 2025-03-24T07:24:03Z

Migration to 18.0

Please @pilarvargas-tecnativa can you review it?

@Tecnativa TT55553


Diff:
diff --git a/stock_picking_restrict_cancel_printed/README.rst b/stock_picking_restrict_cancel_printed/README.rst
index 7836a86fae99..486388d531ef 100644
--- a/stock_picking_restrict_cancel_printed/README.rst
+++ b/stock_picking_restrict_cancel_printed/README.rst
@@ -28,11 +28,11 @@ Stock Picking - restrict cancelation if printed
 
 |badge1| |badge2| |badge3| |badge4| |badge5|
 
-Display the printed flag on the form view of the transfer.
-Raise an error when canceling a printed stock transfer: `You cannot cancel a transfer that is already printed.`
-The restriction for canceling a printed transfer can be disabled
-with the field `Restrict cancelation if printed` on the transfer type.
-
+Display the printed flag on the form view of the transfer. Raise an
+error when canceling a printed stock transfer: You cannot cancel a
+transfer that is already printed. The restriction for canceling a
+printed transfer can be disabled with the field Restrict cancelation if
+printed on the transfer type.
 
 **Table of contents**
 
@@ -53,19 +53,19 @@ Credits
 =======
 
 Authors
-~~~~~~~
+-------
 
 * Camptocamp
 * BCIM
 
 Contributors
-~~~~~~~~~~~~
+------------
 
-* Telmo Santos <telmo.santos@camptocamp.com>
-* Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
+-  Telmo Santos <telmo.santos@camptocamp.com>
+-  Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
 
 Maintainers
-~~~~~~~~~~~
+-----------
 
 This module is maintained by the OCA.
 
diff --git a/stock_picking_restrict_cancel_printed/readme/CONTRIBUTORS.md b/stock_picking_restrict_cancel_printed/readme/CONTRIBUTORS.md
new file mode 100644
index 000000000000..623114ee9a6b
--- /dev/null
+++ b/stock_picking_restrict_cancel_printed/readme/CONTRIBUTORS.md
@@ -0,0 +1,2 @@
+- Telmo Santos \<<telmo.santos@camptocamp.com>\>
+- Jacques-Etienne Baudoux (BCIM) \<<je@bcim.be>\>
diff --git a/stock_picking_restrict_cancel_printed/readme/CONTRIBUTORS.rst b/stock_picking_restrict_cancel_printed/readme/CONTRIBUTORS.rst
deleted file mode 100644
index 9f18b1b41068..000000000000
--- a/stock_picking_restrict_cancel_printed/readme/CONTRIBUTORS.rst
+++ /dev/null
@@ -1,2 +0,0 @@
-* Telmo Santos <telmo.santos@camptocamp.com>
-* Jacques-Etienne Baudoux (BCIM) <je@bcim.be>
diff --git a/stock_picking_restrict_cancel_printed/readme/DESCRIPTION.md b/stock_picking_restrict_cancel_printed/readme/DESCRIPTION.md
new file mode 100644
index 000000000000..3b8381cf1560
--- /dev/null
+++ b/stock_picking_restrict_cancel_printed/readme/DESCRIPTION.md
@@ -0,0 +1,5 @@
+Display the printed flag on the form view of the transfer. Raise an
+error when canceling a printed stock transfer: You cannot cancel a
+transfer that is already printed. The restriction for canceling a
+printed transfer can be disabled with the field Restrict cancelation if
+printed on the transfer type.
diff --git a/stock_picking_restrict_cancel_printed/readme/DESCRIPTION.rst b/stock_picking_restrict_cancel_printed/readme/DESCRIPTION.rst
deleted file mode 100644
index 589e4b3e5f18..000000000000
--- a/stock_picking_restrict_cancel_printed/readme/DESCRIPTION.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-Display the printed flag on the form view of the transfer.
-Raise an error when canceling a printed stock transfer: `You cannot cancel a transfer that is already printed.`
-The restriction for canceling a printed transfer can be disabled
-with the field `Restrict cancelation if printed` on the transfer type.
-
diff --git a/stock_picking_restrict_cancel_printed/static/description/index.html b/stock_picking_restrict_cancel_printed/static/description/index.html
index 4ec196494da2..5d8d21542acf 100644
--- a/stock_picking_restrict_cancel_printed/static/description/index.html
+++ b/stock_picking_restrict_cancel_printed/static/description/index.html
@@ -370,10 +370,11 @@ <h1 class="title">Stock Picking - restrict cancelation if printed</h1>
 !! source digest: sha256:1e5b100bf5103154e4587a6ca0e636786add3c779e46f4b099e669ca1ab32850
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
 <p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/stock-logistics-workflow/tree/18.0/stock_picking_restrict_cancel_printed"><img alt="OCA/stock-logistics-workflow" src="https://img.shields.io/badge/github-OCA%2Fstock--logistics--workflow-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/stock-logistics-workflow-18-0/stock-logistics-workflow-18-0-stock_picking_restrict_cancel_printed"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-workflow&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
-<p>Display the printed flag on the form view of the transfer.
-Raise an error when canceling a printed stock transfer: <cite>You cannot cancel a transfer that is already printed.</cite>
-The restriction for canceling a printed transfer can be disabled
-with the field <cite>Restrict cancelation if printed</cite> on the transfer type.</p>
+<p>Display the printed flag on the form view of the transfer. Raise an
+error when canceling a printed stock transfer: You cannot cancel a
+transfer that is already printed. The restriction for canceling a
+printed transfer can be disabled with the field Restrict cancelation if
+printed on the transfer type.</p>
 <p><strong>Table of contents</strong></p>
 <div class="contents local topic" id="contents">
 <ul class="simple">
diff --git a/stock_product_set/README.rst b/stock_product_set/README.rst
new file mode 100644
index 000000000000..6202db33c54b
--- /dev/null
+++ b/stock_product_set/README.rst
@@ -0,0 +1,103 @@
+============================
+Add product sets in pickings
+============================
+
+.. 
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   !! This file is generated by oca-gen-addon-readme !!
+   !! changes will be overwritten.                   !!
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+   !! source digest: sha256:2022e5b24dd98b41b8501ec05bea9d51debc2f521125f3d9c78cf27d1e81571a
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+.. |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%2Fstock--logistics--workflow-lightgray.png?logo=github
+    :target: https://github.com/OCA/stock-logistics-workflow/tree/18.0/stock_product_set
+    :alt: OCA/stock-logistics-workflow
+.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
+    :target: https://translation.odoo-community.org/projects/stock-logistics-workflow-18-0/stock-logistics-workflow-18-0-stock_product_set
+    :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/stock-logistics-workflow&target_branch=18.0
+    :alt: Try me on Runboat
+
+|badge1| |badge2| |badge3| |badge4| |badge5|
+
+This module allows to use product sets in planned transfer pickings.
+
+**Table of contents**
+
+.. contents::
+   :local:
+
+Usage
+=====
+
+#. Go to *Inventory -> Delivery orders* and create new 'Planned
+transfer' (an option available by clicking on the 3 dots in the upper
+right-hand corner). #. Go to *Add set* button and select some product
+set and click on the *Add set* button. #. Lines for each product of the
+set have been created in the *Stock Info* tab.
+
+Known issues / Roadmap
+======================
+
+-  The dependency sale_product_set must be changed to product_set in
+   v16.
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues <https://github.com/OCA/stock-logistics-workflow/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 <https://github.com/OCA/stock-logistics-workflow/issues/new?body=module:%20stock_product_set%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+-------
+
+* Tecnativa
+
+Contributors
+------------
+
+-  `Tecnativa <https://www.tecnativa.com>`__:
+
+   -  Víctor Martínez
+   -  Pedro M. Baeza
+   -  Pilar Vargas
+
+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-victoralmau| image:: https://github.com/victoralmau.png?size=40px
+    :target: https://github.com/victoralmau
+    :alt: victoralmau
+
+Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
+
+|maintainer-victoralmau| 
+
+This module is part of the `OCA/stock-logistics-workflow <https://github.com/OCA/stock-logistics-workflow/tree/18.0/stock_product_set>`_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/stock_product_set/__init__.py b/stock_product_set/__init__.py
new file mode 100644
index 000000000000..9b4296142f47
--- /dev/null
+++ b/stock_product_set/__init__.py
@@ -0,0 +1,2 @@
+from . import models
+from . import wizard
diff --git a/stock_product_set/__manifest__.py b/stock_product_set/__manifest__.py
new file mode 100644
index 000000000000..9e8efc266143
--- /dev/null
+++ b/stock_product_set/__manifest__.py
@@ -0,0 +1,18 @@
+# Copyright 2023-2024 Tecnativa - Víctor Martínez
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+{
+    "name": "Add product sets in pickings",
+    "version": "18.0.1.0.0",
+    "category": "Warehouse",
+    "website": "https://github.com/OCA/stock-logistics-workflow",
+    "author": "Tecnativa, Odoo Community Association (OCA)",
+    "license": "AGPL-3",
+    "depends": ["stock", "product_set"],
+    "installable": True,
+    "data": [
+        "security/ir.model.access.csv",
+        "wizard/stock_product_set_wizard_view.xml",
+        "views/stock_picking_views.xml",
+    ],
+    "maintainers": ["victoralmau"],
+}
diff --git a/stock_product_set/i18n/es.po b/stock_product_set/i18n/es.po
new file mode 100644
index 000000000000..7006f397443c
--- /dev/null
+++ b/stock_product_set/i18n/es.po
@@ -0,0 +1,111 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# 	* stock_product_set
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 15.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2023-12-22 10:00+0000\n"
+"PO-Revision-Date: 2023-12-22 11:02+0100\n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"Language: es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: \n"
+"X-Generator: Poedit 3.0.1\n"
+
+#. module: stock_product_set
+#: model:ir.actions.act_window,name:stock_product_set.act_open_wizard_product_set_add_from_picking
+msgid "Add a set in a picking"
+msgstr "Añadir conjunto en un albarán"
+
+#. module: stock_product_set
+#: model_terms:ir.ui.view,arch_db:stock_product_set.product_set_add_from_picking_form_view
+#: model_terms:ir.ui.view,arch_db:stock_product_set.view_picking_form
+msgid "Add set"
+msgstr "Añadir conjunto"
+
+#. module: stock_product_set
+#: model_terms:ir.ui.view,arch_db:stock_product_set.product_set_add_from_picking_form_view
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__partner_id
+msgid "Contact"
+msgstr "Contacto"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__create_date
+msgid "Created on"
+msgstr "Creado el"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__display_name
+msgid "Display Name"
+msgstr "Nombre a mostrar"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__id
+msgid "ID"
+msgstr "ID"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard____last_update
+msgid "Last Modified on"
+msgstr "Última modificación el"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__write_uid
+msgid "Last Updated by"
+msgstr "Ultima actualización por"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__write_date
+msgid "Last Updated on"
+msgstr "Fecha modificación"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__picking_id
+msgid "Picking"
+msgstr "Albarán"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__product_set_id
+msgid "Product set"
+msgstr "Línea de conjunto de productos"
+
+#. module: stock_product_set
+#: model:ir.model,name:stock_product_set.model_product_set_line
+msgid "Product set line"
+msgstr "Línea de conjunto de productos"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__product_set_line_ids
+msgid "Product set lines"
+msgstr "Línea de conjunto de productos"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__quantity
+msgid "Quantity"
+msgstr "Cantidad"
+
+#. module: stock_product_set
+#. odoo-python
+#: code:addons/stock_product_set/wizard/stock_product_set_wizard.py:0
+#, python-format
+msgid "This set of products is restricted for this user."
+msgstr ""
+
+#. module: stock_product_set
+#: model:ir.model,name:stock_product_set.model_stock_product_set_wizard
+msgid "Wizard model to add product set into a picking form"
+msgstr ""
diff --git a/stock_product_set/i18n/it.po b/stock_product_set/i18n/it.po
new file mode 100644
index 000000000000..bc611295ecba
--- /dev/null
+++ b/stock_product_set/i18n/it.po
@@ -0,0 +1,111 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# 	* stock_product_set
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 16.0\n"
+"Report-Msgid-Bugs-To: \n"
+"PO-Revision-Date: 2024-03-19 15:37+0000\n"
+"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
+"Language-Team: none\n"
+"Language: it\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.17\n"
+
+#. module: stock_product_set
+#: model:ir.actions.act_window,name:stock_product_set.act_open_wizard_product_set_add_from_picking
+msgid "Add a set in a picking"
+msgstr "Aggiungere un set nel prelievo"
+
+#. module: stock_product_set
+#: model_terms:ir.ui.view,arch_db:stock_product_set.product_set_add_from_picking_form_view
+#: model_terms:ir.ui.view,arch_db:stock_product_set.view_picking_form
+msgid "Add set"
+msgstr "Aggiungi set"
+
+#. module: stock_product_set
+#: model_terms:ir.ui.view,arch_db:stock_product_set.product_set_add_from_picking_form_view
+msgid "Cancel"
+msgstr "Annulla"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__partner_id
+msgid "Contact"
+msgstr "Contatto"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__create_uid
+msgid "Created by"
+msgstr "Creato da"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__create_date
+msgid "Created on"
+msgstr "Creato il"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__display_name
+msgid "Display Name"
+msgstr "Nome visualizzato"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__id
+msgid "ID"
+msgstr "ID"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard____last_update
+msgid "Last Modified on"
+msgstr "Ultima modifica il"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__write_uid
+msgid "Last Updated by"
+msgstr "Ultimo aggiornamento di"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__write_date
+msgid "Last Updated on"
+msgstr "Ultimo aggiornamento il"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__picking_id
+msgid "Picking"
+msgstr "Prelievo"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__product_set_id
+msgid "Product set"
+msgstr "Set prodotto"
+
+#. module: stock_product_set
+#: model:ir.model,name:stock_product_set.model_product_set_line
+msgid "Product set line"
+msgstr "Riga set prodotto"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__product_set_line_ids
+msgid "Product set lines"
+msgstr "Righe set prodotto"
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__quantity
+msgid "Quantity"
+msgstr "Quantità"
+
+#. module: stock_product_set
+#. odoo-python
+#: code:addons/stock_product_set/wizard/stock_product_set_wizard.py:0
+#, python-format
+msgid "This set of products is restricted for this user."
+msgstr "Questo set di prodotti è limitato per questo utente."
+
+#. module: stock_product_set
+#: model:ir.model,name:stock_product_set.model_stock_product_set_wizard
+msgid "Wizard model to add product set into a picking form"
+msgstr ""
+"Modello procedura guidata per aggiugere un set prodotto in un modulo prelievo"
diff --git a/stock_product_set/i18n/stock_product_set.pot b/stock_product_set/i18n/stock_product_set.pot
new file mode 100644
index 000000000000..b04e0c932da2
--- /dev/null
+++ b/stock_product_set/i18n/stock_product_set.pot
@@ -0,0 +1,107 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# 	* stock_product_set
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 16.0\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: stock_product_set
+#: model:ir.actions.act_window,name:stock_product_set.act_open_wizard_product_set_add_from_picking
+msgid "Add a set in a picking"
+msgstr ""
+
+#. module: stock_product_set
+#: model_terms:ir.ui.view,arch_db:stock_product_set.product_set_add_from_picking_form_view
+#: model_terms:ir.ui.view,arch_db:stock_product_set.view_picking_form
+msgid "Add set"
+msgstr ""
+
+#. module: stock_product_set
+#: model_terms:ir.ui.view,arch_db:stock_product_set.product_set_add_from_picking_form_view
+msgid "Cancel"
+msgstr ""
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__partner_id
+msgid "Contact"
+msgstr ""
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__create_uid
+msgid "Created by"
+msgstr ""
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__create_date
+msgid "Created on"
+msgstr ""
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__id
+msgid "ID"
+msgstr ""
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__write_uid
+msgid "Last Updated by"
+msgstr ""
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__write_date
+msgid "Last Updated on"
+msgstr ""
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__picking_id
+msgid "Picking"
+msgstr ""
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__product_set_id
+msgid "Product set"
+msgstr ""
+
+#. module: stock_product_set
+#: model:ir.model,name:stock_product_set.model_product_set_line
+msgid "Product set line"
+msgstr ""
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__product_set_line_ids
+msgid "Product set lines"
+msgstr ""
+
+#. module: stock_product_set
+#: model:ir.model.fields,field_description:stock_product_set.field_stock_product_set_wizard__quantity
+msgid "Quantity"
+msgstr ""
+
+#. module: stock_product_set
+#. odoo-python
+#: code:addons/stock_product_set/wizard/stock_product_set_wizard.py:0
+#, python-format
+msgid "This set of products is restricted for this user."
+msgstr ""
+
+#. module: stock_product_set
+#: model:ir.model,name:stock_product_set.model_stock_product_set_wizard
+msgid "Wizard model to add product set into a picking form"
+msgstr ""
diff --git a/stock_product_set/models/__init__.py b/stock_product_set/models/__init__.py
new file mode 100644
index 000000000000..40f6d2a3b4aa
--- /dev/null
+++ b/stock_product_set/models/__init__.py
@@ -0,0 +1,3 @@
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import product_set_line
diff --git a/stock_product_set/models/product_set_line.py b/stock_product_set/models/product_set_line.py
new file mode 100644
index 000000000000..e2520bb5ba5c
--- /dev/null
+++ b/stock_product_set/models/product_set_line.py
@@ -0,0 +1,32 @@
+# Copyright 2023-2024 Tecnativa - Víctor Martínez
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
+from odoo import models
+
+
+class ProductSetLine(models.Model):
+    _inherit = "product.set.line"
+
+    def prepare_picking_stock_move_values(self, picking, quantity):
+        self.ensure_one()
+        product = self.product_id.with_context(
+            lang=picking.partner_id.lang or self.env.user.lang
+        )
+        # Inspired in the _prepare_stock_move_vals() method of purchase_stock
+        return {
+            # truncate to 2000 to avoid triggering index limit error
+            "name": (self.product_id.display_name or "")[:2000],
+            "product_id": self.product_id.id,
+            "location_id": picking.location_id.id,
+            "location_dest_id": picking.location_dest_id.id,
+            "picking_id": picking.id,
+            "partner_id": picking.partner_id.id,
+            "state": "draft",
+            "company_id": picking.company_id.id,
+            "picking_type_id": picking.picking_type_id.id,
+            "group_id": picking.group_id.id,
+            "description_picking": product.description_pickingin,
+            "warehouse_id": picking.picking_type_id.warehouse_id.id,
+            "product_uom_qty": self.quantity * quantity,
+            "product_uom": self.product_id.uom_id.id,
+            "sequence": self.sequence,
+        }
diff --git a/stock_product_set/pyproject.toml b/stock_product_set/pyproject.toml
new file mode 100644
index 000000000000..4231d0cccb3d
--- /dev/null
+++ b/stock_product_set/pyproject.toml
@@ -0,0 +1,3 @@
+[build-system]
+requires = ["whool"]
+build-backend = "whool.buildapi"
diff --git a/stock_product_set/readme/CONTRIBUTORS.md b/stock_product_set/readme/CONTRIBUTORS.md
new file mode 100644
index 000000000000..7f438edf95dc
--- /dev/null
+++ b/stock_product_set/readme/CONTRIBUTORS.md
@@ -0,0 +1,4 @@
+- [Tecnativa](https://www.tecnativa.com):
+  - Víctor Martínez
+  - Pedro M. Baeza
+  - Pilar Vargas
diff --git a/stock_product_set/readme/DESCRIPTION.md b/stock_product_set/readme/DESCRIPTION.md
new file mode 100644
index 000000000000..8e63dd13400d
--- /dev/null
+++ b/stock_product_set/readme/DESCRIPTION.md
@@ -0,0 +1 @@
+This module allows to use product sets in planned transfer pickings.
diff --git a/stock_product_set/readme/ROADMAP.md b/stock_product_set/readme/ROADMAP.md
new file mode 100644
index 000000000000..472e82b7a0dc
--- /dev/null
+++ b/stock_product_set/readme/ROADMAP.md
@@ -0,0 +1 @@
+- The dependency sale_product_set must be changed to product_set in v16.
diff --git a/stock_product_set/readme/USAGE.md b/stock_product_set/readme/USAGE.md
new file mode 100644
index 000000000000..5b9bc4fa4636
--- /dev/null
+++ b/stock_product_set/readme/USAGE.md
@@ -0,0 +1,5 @@
+#\. Go to *Inventory -\> Delivery orders* and create new 'Planned
+transfer' (an option available by clicking on the 3 dots in the upper
+right-hand corner). \#. Go to *Add set* button and select some product
+set and click on the *Add set* button. \#. Lines for each product of the
+set have been created in the *Stock Info* tab.
diff --git a/stock_product_set/security/ir.model.access.csv b/stock_product_set/security/ir.model.access.csv
new file mode 100644
index 000000000000..defede3c884c
--- /dev/null
+++ b/stock_product_set/security/ir.model.access.csv
@@ -0,0 +1,2 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+stock_product_set.access_stock_product_set_wizard,access_stock_product_set_wizard,stock_product_set.model_stock_product_set_wizard,stock.group_stock_user,1,1,1,1
diff --git a/stock_product_set/static/description/icon.png b/stock_product_set/static/description/icon.png
new file mode 100644
index 000000000000..3a0328b516c4
Binary files /dev/null and b/stock_product_set/static/description/icon.png differ
diff --git a/stock_product_set/static/description/index.html b/stock_product_set/static/description/index.html
new file mode 100644
index 000000000000..888dfebe8890
--- /dev/null
+++ b/stock_product_set/static/description/index.html
@@ -0,0 +1,447 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
+<title>Add product sets in pickings</title>
+<style type="text/css">
+
+/*
+:Author: David Goodger (goodger@python.org)
+:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
+:Copyright: This stylesheet has been placed in the public domain.
+
+Default cascading style sheet for the HTML output of Docutils.
+Despite the name, some widely supported CSS2 features are used.
+
+See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
+customize this style sheet.
+*/
+
+/* used to remove borders from tables and images */
+.borderless, table.borderless td, table.borderless th {
+  border: 0 }
+
+table.borderless td, table.borderless th {
+  /* Override padding for "table.docutils td" with "! important".
+     The right padding separates the table cells. */
+  padding: 0 0.5em 0 0 ! important }
+
+.first {
+  /* Override more specific margin styles with "! important". */
+  margin-top: 0 ! important }
+
+.last, .with-subtitle {
+  margin-bottom: 0 ! important }
+
+.hidden {
+  display: none }
+
+.subscript {
+  vertical-align: sub;
+  font-size: smaller }
+
+.superscript {
+  vertical-align: super;
+  font-size: smaller }
+
+a.toc-backref {
+  text-decoration: none ;
+  color: black }
+
+blockquote.epigraph {
+  margin: 2em 5em ; }
+
+dl.docutils dd {
+  margin-bottom: 0.5em }
+
+object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
+  overflow: hidden;
+}
+
+/* Uncomment (and remove this text!) to get bold-faced definition list terms
+dl.docutils dt {
+  font-weight: bold }
+*/
+
+div.abstract {
+  margin: 2em 5em }
+
+div.abstract p.topic-title {
+  font-weight: bold ;
+  text-align: center }
+
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning {
+  margin: 2em ;
+  border: medium outset ;
+  padding: 1em }
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+  font-weight: bold ;
+  font-family: sans-serif }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title, .code .error {
+  color: red ;
+  font-weight: bold ;
+  font-family: sans-serif }
+
+/* Uncomment (and remove this text!) to get reduced vertical space in
+   compound paragraphs.
+div.compound .compound-first, div.compound .compound-middle {
+  margin-bottom: 0.5em }
+
+div.compound .compound-last, div.compound .compound-middle {
+  margin-top: 0.5em }
+*/
+
+div.dedication {
+  margin: 2em 5em ;
+  text-align: center ;
+  font-style: italic }
+
+div.dedication p.topic-title {
+  font-weight: bold ;
+  font-style: normal }
+
+div.figure {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+div.footer, div.header {
+  clear: both;
+  font-size: smaller }
+
+div.line-block {
+  display: block ;
+  margin-top: 1em ;
+  margin-bottom: 1em }
+
+div.line-block div.line-block {
+  margin-top: 0 ;
+  margin-bottom: 0 ;
+  margin-left: 1.5em }
+
+div.sidebar {
+  margin: 0 0 0.5em 1em ;
+  border: medium outset ;
+  padding: 1em ;
+  background-color: #ffffee ;
+  width: 40% ;
+  float: right ;
+  clear: right }
+
+div.sidebar p.rubric {
+  font-family: sans-serif ;
+  font-size: medium }
+
+div.system-messages {
+  margin: 5em }
+
+div.system-messages h1 {
+  color: red }
+
+div.system-message {
+  border: medium outset ;
+  padding: 1em }
+
+div.system-message p.system-message-title {
+  color: red ;
+  font-weight: bold }
+
+div.topic {
+  margin: 2em }
+
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
+  margin-top: 0.4em }
+
+h1.title {
+  text-align: center }
+
+h2.subtitle {
+  text-align: center }
+
+hr.docutils {
+  width: 75% }
+
+img.align-left, .figure.align-left, object.align-left, table.align-left {
+  clear: left ;
+  float: left ;
+  margin-right: 1em }
+
+img.align-right, .figure.align-right, object.align-right, table.align-right {
+  clear: right ;
+  float: right ;
+  margin-left: 1em }
+
+img.align-center, .figure.align-center, object.align-center {
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+table.align-center {
+  margin-left: auto;
+  margin-right: auto;
+}
+
+.align-left {
+  text-align: left }
+
+.align-center {
+  clear: both ;
+  text-align: center }
+
+.align-right {
+  text-align: right }
+
+/* reset inner alignment in figures */
+div.align-right {
+  text-align: inherit }
+
+/* div.align-center * { */
+/*   text-align: left } */
+
+.align-top    {
+  vertical-align: top }
+
+.align-middle {
+  vertical-align: middle }
+
+.align-bottom {
+  vertical-align: bottom }
+
+ol.simple, ul.simple {
+  margin-bottom: 1em }
+
+ol.arabic {
+  list-style: decimal }
+
+ol.loweralpha {
+  list-style: lower-alpha }
+
+ol.upperalpha {
+  list-style: upper-alpha }
+
+ol.lowerroman {
+  list-style: lower-roman }
+
+ol.upperroman {
+  list-style: upper-roman }
+
+p.attribution {
+  text-align: right ;
+  margin-left: 50% }
+
+p.caption {
+  font-style: italic }
+
+p.credits {
+  font-style: italic ;
+  font-size: smaller }
+
+p.label {
+  white-space: nowrap }
+
+p.rubric {
+  font-weight: bold ;
+  font-size: larger ;
+  color: maroon ;
+  text-align: center }
+
+p.sidebar-title {
+  font-family: sans-serif ;
+  font-weight: bold ;
+  font-size: larger }
+
+p.sidebar-subtitle {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+p.topic-title {
+  font-weight: bold }
+
+pre.address {
+  margin-bottom: 0 ;
+  margin-top: 0 ;
+  font: inherit }
+
+pre.literal-block, pre.doctest-block, pre.math, pre.code {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+pre.code .ln { color: gray; } /* line numbers */
+pre.code, code { background-color: #eeeeee }
+pre.code .comment, code .comment { color: #5C6576 }
+pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
+pre.code .literal.string, code .literal.string { color: #0C5404 }
+pre.code .name.builtin, code .name.builtin { color: #352B84 }
+pre.code .deleted, code .deleted { background-color: #DEB0A1}
+pre.code .inserted, code .inserted { background-color: #A3D289}
+
+span.classifier {
+  font-family: sans-serif ;
+  font-style: oblique }
+
+span.classifier-delimiter {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+span.interpreted {
+  font-family: sans-serif }
+
+span.option {
+  white-space: nowrap }
+
+span.pre {
+  white-space: pre }
+
+span.problematic, pre.problematic {
+  color: red }
+
+span.section-subtitle {
+  /* font-size relative to parent (h1..h6 element) */
+  font-size: 80% }
+
+table.citation {
+  border-left: solid 1px gray;
+  margin-left: 1px }
+
+table.docinfo {
+  margin: 2em 4em }
+
+table.docutils {
+  margin-top: 0.5em ;
+  margin-bottom: 0.5em }
+
+table.footnote {
+  border-left: solid 1px black;
+  margin-left: 1px }
+
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th {
+  padding-left: 0.5em ;
+  padding-right: 0.5em ;
+  vertical-align: top }
+
+table.docutils th.field-name, table.docinfo th.docinfo-name {
+  font-weight: bold ;
+  text-align: left ;
+  white-space: nowrap ;
+  padding-left: 0 }
+
+/* "booktabs" style (no vertical lines) */
+table.docutils.booktabs {
+  border: 0px;
+  border-top: 2px solid;
+  border-bottom: 2px solid;
+  border-collapse: collapse;
+}
+table.docutils.booktabs * {
+  border: 0px;
+}
+table.docutils.booktabs th {
+  border-bottom: thin solid;
+  text-align: left;
+}
+
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
+  font-size: 100% }
+
+ul.auto-toc {
+  list-style-type: none }
+
+</style>
+</head>
+<body>
+<div class="document" id="add-product-sets-in-pickings">
+<h1 class="title">Add product sets in pickings</h1>
+
+<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!! This file is generated by oca-gen-addon-readme !!
+!! changes will be overwritten.                   !!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!! source digest: sha256:2022e5b24dd98b41b8501ec05bea9d51debc2f521125f3d9c78cf27d1e81571a
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
+<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/stock-logistics-workflow/tree/18.0/stock_product_set"><img alt="OCA/stock-logistics-workflow" src="https://img.shields.io/badge/github-OCA%2Fstock--logistics--workflow-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/stock-logistics-workflow-18-0/stock-logistics-workflow-18-0-stock_product_set"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/stock-logistics-workflow&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
+<p>This module allows to use product sets in planned transfer pickings.</p>
+<p><strong>Table of contents</strong></p>
+<div class="contents local topic" id="contents">
+<ul class="simple">
+<li><a class="reference internal" href="#usage" id="toc-entry-1">Usage</a></li>
+<li><a class="reference internal" href="#known-issues-roadmap" id="toc-entry-2">Known issues / Roadmap</a></li>
+<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
+<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
+<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
+<li><a class="reference internal" href="#contributors" id="toc-entry-6">Contributors</a></li>
+<li><a class="reference internal" href="#maintainers" id="toc-entry-7">Maintainers</a></li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="usage">
+<h1><a class="toc-backref" href="#toc-entry-1">Usage</a></h1>
+<p>#. Go to <em>Inventory -&gt; Delivery orders</em> and create new ‘Planned
+transfer’ (an option available by clicking on the 3 dots in the upper
+right-hand corner). #. Go to <em>Add set</em> button and select some product
+set and click on the <em>Add set</em> button. #. Lines for each product of the
+set have been created in the <em>Stock Info</em> tab.</p>
+</div>
+<div class="section" id="known-issues-roadmap">
+<h1><a class="toc-backref" href="#toc-entry-2">Known issues / Roadmap</a></h1>
+<ul class="simple">
+<li>The dependency sale_product_set must be changed to product_set in
+v16.</li>
+</ul>
+</div>
+<div class="section" id="bug-tracker">
+<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
+<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/stock-logistics-workflow/issues">GitHub Issues</a>.
+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
+<a class="reference external" href="https://github.com/OCA/stock-logistics-workflow/issues/new?body=module:%20stock_product_set%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
+<p>Do not contact contributors directly about support or help with technical issues.</p>
+</div>
+<div class="section" id="credits">
+<h1><a class="toc-backref" href="#toc-entry-4">Credits</a></h1>
+<div class="section" id="authors">
+<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
+<ul class="simple">
+<li>Tecnativa</li>
+</ul>
+</div>
+<div class="section" id="contributors">
+<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
+<ul class="simple">
+<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul>
+<li>Víctor Martínez</li>
+<li>Pedro M. Baeza</li>
+<li>Pilar Vargas</li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="maintainers">
+<h2><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h2>
+<p>This module is maintained by the OCA.</p>
+<a class="reference external image-reference" href="https://odoo-community.org">
+<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
+</a>
+<p>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.</p>
+<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
+<p><a class="reference external image-reference" href="https://github.com/victoralmau"><img alt="victoralmau" src="https://github.com/victoralmau.png?size=40px" /></a></p>
+<p>This module is part of the <a class="reference external" href="https://github.com/OCA/stock-logistics-workflow/tree/18.0/stock_product_set">OCA/stock-logistics-workflow</a> project on GitHub.</p>
+<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
+</div>
+</div>
+</div>
+</body>
+</html>
diff --git a/stock_product_set/tests/__init__.py b/stock_product_set/tests/__init__.py
new file mode 100644
index 000000000000..cd8b8f67976c
--- /dev/null
+++ b/stock_product_set/tests/__init__.py
@@ -0,0 +1,4 @@
+# Copyright 2023 Tecnativa - Víctor Martínez
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import test_stock_product_set
diff --git a/stock_product_set/tests/test_stock_product_set.py b/stock_product_set/tests/test_stock_product_set.py
new file mode 100644
index 000000000000..7c4d4cec94da
--- /dev/null
+++ b/stock_product_set/tests/test_stock_product_set.py
@@ -0,0 +1,56 @@
+# Copyright 2023-2025 Tecnativa - Víctor Martínez
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+from odoo.tests import Form, new_test_user
+from odoo.tests.common import users
+
+from odoo.addons.base.tests.common import BaseCommon
+
+
+class TestStockProductSet(BaseCommon):
+    @classmethod
+    def setUpClass(cls):
+        super().setUpClass()
+        cls.product_a = cls.env["product.product"].create(
+            {"name": "Test product A", "type": "consu", "is_storable": True}
+        )
+        cls.product_b = cls.env["product.product"].create(
+            {"name": "Test product B", "type": "consu", "is_storable": True}
+        )
+        cls.product_set = cls.env["product.set"].create(
+            {
+                "name": "Test product set",
+                "set_line_ids": [
+                    (0, 0, {"product_id": cls.product_a.id, "quantity": 2}),
+                    (0, 0, {"product_id": cls.product_b.id, "quantity": 1}),
+                ],
+            }
+        )
+        cls.picking_type_internal = cls.env.ref("stock.picking_type_internal")
+        cls.picking_type_internal.default_location_dest_id = cls.env.ref(
+            "stock.stock_location_components"
+        )
+        new_test_user(cls.env, login="test-stock-user", groups="stock.group_stock_user")
+
+    @users("test-stock-user")
+    def test_wizard_product_set_add_1(self):
+        picking_form = Form(
+            self.env["stock.picking"].with_context(
+                default_picking_type_id=self.picking_type_internal.id
+            )
+        )
+        picking = picking_form.save()
+        wizard_form = Form(
+            self.env["stock.product.set.wizard"].with_context(
+                default_picking_id=picking.id
+            )
+        )
+        wizard_form.product_set_id = self.product_set
+        wizard = wizard_form.save()
+        wizard.add_set()
+        self.assertEqual(len(picking.move_ids_without_package), 2)
+        products = picking.move_ids_without_package.mapped("product_id")
+        self.assertIn(self.product_a, products)
+        self.assertIn(self.product_b, products)
+        self.assertEqual(
+            sum(picking.move_ids_without_package.mapped("product_uom_qty")), 3
+        )
diff --git a/stock_product_set/views/stock_picking_views.xml b/stock_product_set/views/stock_picking_views.xml
new file mode 100644
index 000000000000..e511befb0dc2
--- /dev/null
+++ b/stock_product_set/views/stock_picking_views.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<odoo>
+    <record id="view_picking_form" model="ir.ui.view">
+        <field name="name">stock.picking.form</field>
+        <field name="model">stock.picking</field>
+        <field name="inherit_id" ref="stock.view_picking_form" />
+        <field name="arch" type="xml">
+            <xpath expr="//header" position="inside">
+                <button
+                    class="btn-primary"
+                    type="action"
+                    name="%(act_open_wizard_product_set_add_from_picking)d"
+                    icon="fa-cubes"
+                    invisible="state!='draft'"
+                    string="Add set"
+                />
+            </xpath>
+        </field>
+    </record>
+</odoo>
diff --git a/stock_product_set/wizard/__init__.py b/stock_product_set/wizard/__init__.py
new file mode 100644
index 000000000000..df16d2139a0e
--- /dev/null
+++ b/stock_product_set/wizard/__init__.py
@@ -0,0 +1 @@
+from . import stock_product_set_wizard
diff --git a/stock_product_set/wizard/stock_product_set_wizard.py b/stock_product_set/wizard/stock_product_set_wizard.py
new file mode 100644
index 000000000000..64fa33267cf8
--- /dev/null
+++ b/stock_product_set/wizard/stock_product_set_wizard.py
@@ -0,0 +1,61 @@
+# Copyright 2023-2024 Tecnativa - Víctor Martínez
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
+from odoo import _, exceptions, fields, models
+
+
+class StockProductSetWizard(models.TransientModel):
+    _inherit = "product.set.wizard"
+    _name = "stock.product.set.wizard"
+    _description = "Wizard model to add product set into a picking form"
+
+    picking_id = fields.Many2one(
+        comodel_name="stock.picking",
+        string="Picking",
+        required=True,
+        default=lambda self: self.env.context.get("active_id")
+        if self.env.context.get("active_model") == "stock.picking"
+        else None,
+        ondelete="cascade",
+    )
+    partner_id = fields.Many2one(related="picking_id.partner_id", ondelete="cascade")
+
+    def _compute_product_set_line_ids(self):
+        res = super()._compute_product_set_line_ids()
+        for rec in self:
+            rec.product_set_line_ids = rec.product_set_id.set_line_ids.filtered(
+                "product_id"
+            )
+        return res
+
+    def _prepare_stock_moves(self):
+        moves = []
+        for _seq, set_line in enumerate(self._get_lines(), start=1):
+            values = self.prepare_stock_move_data(set_line)
+            moves.append((0, 0, values))
+        return moves
+
+    def prepare_stock_move_data(self, set_line):
+        self.ensure_one()
+        return set_line.prepare_picking_stock_move_values(
+            self.picking_id, self.quantity
+        )
+
+    def _check_partner(self):
+        res = super()._check_partner()
+        if (
+            self.product_set_id.partner_id
+            and self.partner_id != self.product_set_id.partner_id
+        ):
+            raise exceptions.ValidationError(
+                _("This set of products is restricted for this user.")
+            )
+        return res
+
+    def add_set(self):
+        res = super().add_set()
+        if not self.picking_id:
+            return res
+        moves = self._prepare_stock_moves()
+        if moves:
+            self.picking_id.write({"move_ids_without_package": moves})
+        return moves
diff --git a/stock_product_set/wizard/stock_product_set_wizard_view.xml b/stock_product_set/wizard/stock_product_set_wizard_view.xml
new file mode 100644
index 000000000000..a5f0e1d56ee8
--- /dev/null
+++ b/stock_product_set/wizard/stock_product_set_wizard_view.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<odoo>
+    <record id="product_set_add_from_picking_form_view" model="ir.ui.view">
+        <field name="name">stock.product.set.form</field>
+        <field name="model">stock.product.set.wizard</field>
+        <field name="arch" type="xml">
+            <form>
+                <group name="main" colspan="4">
+                    <field
+                        name="picking_id"
+                        invisible="context.get('default_picking_id')"
+                    />
+                    <field name="partner_id" invisible="1" />
+                    <field
+                        name="product_set_id"
+                        domain="['|',('partner_id', '=', False),('partner_id', '=', partner_id)]"
+                    />
+                    <field name="quantity" />
+                </group>
+                <group name="lines">
+                    <field
+                        name="product_set_line_ids"
+                        nolabel="1"
+                        colspan="2"
+                        domain="[('product_set_id', '=', product_set_id)]"
+                    >
+                        <list>
+                            <field
+                                name="product_id"
+                                options="{'no_open': True, 'no_create': True}"
+                            />
+                        </list>
+                    </field>
+                </group>
+                <footer>
+                    <button
+                        name="add_set"
+                        string="Add set"
+                        type="object"
+                        class="oe_highlight"
+                    />
+                    <button special="cancel" string="Cancel" class="oe_link" />
+                </footer>
+            </form>
+        </field>
+    </record>
+    <record
+        id="act_open_wizard_product_set_add_from_picking"
+        model="ir.actions.act_window"
+    >
+        <field name="name">Add a set in a picking</field>
+        <field name="res_model">stock.product.set.wizard</field>
+        <field name="view_mode">form</field>
+        <field name="view_id" ref="product_set_add_from_picking_form_view" />
+        <field name="domain">[]</field>
+        <field name="context">{'default_picking_id': active_id}</field>
+        <field name="target">new</field>
+    </record>
+</odoo>


Reviews:
user: login: pilarvargas-tecnativa
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T07:56:13Z
user: login: victoralmau
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-21T15:59:00Z
user: login: rousseldenis
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-21T16:32:00Z
user: login: pilarvargas-tecnativa
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-24T06:13:52Z

Review comments:
diff_hunk: @@ -11,7 +11,7 @@
                     type="action"
                     name="%(act_open_wizard_product_set_add_from_picking)d"
                     icon="fa-cubes"
-                    attrs="{'invisible': ['|', ('state', '!=', 'draft'), ('immediate_transfer', '=', True)]}"
path: stock_product_set/views/stock_picking_views.xml
user: login: pilarvargas-tecnativa
body: The field immediate_transfer has disappeared?
created_at: 2025-03-21T07:56:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -11,7 +11,7 @@
                     type="action"
                     name="%(act_open_wizard_product_set_add_from_picking)d"
                     icon="fa-cubes"
-                    attrs="{'invisible': ['|', ('state', '!=', 'draft'), ('immediate_transfer', '=', True)]}"
path: stock_product_set/views/stock_picking_views.xml
user: login: victoralmau
body: Yes, it is actually removed already in 17.0.: https://github.com/OCA/OpenUpgrade/blob/857b65680f0033e2df07497d74e69c2ebb25d28a/openupgrade_scripts/scripts/stock/17.0.1.1/upgrade_analysis_work.txt#L64
created_at: 2025-03-21T15:59:00Z
author_association: MEMBER

PR comments:
user: login: OCA-git-bot
created_at: 2025-03-20T12:05:46Z
body: Hi @jbaudoux,
some modules you are maintaining are being modified, check this out!
author_association: CONTRIBUTOR
user: login: rousseldenis
created_at: 2025-03-21T16:31:06Z
body: /ocabot migration stock_product_set
author_association: CONTRIBUTOR
user: login: pedrobaeza
created_at: 2025-03-24T07:17:20Z
body: /ocabot merge nobump
author_association: MEMBER
user: login: OCA-git-bot
created_at: 2025-03-24T07:17:27Z
body: Hey, thanks for contributing! Proceeding to merge this for you.
Prepared branch [18.0-ocabot-merge-pr-1902-by-pedrobaeza-bump-nobump](https://github.com/OCA/stock-logistics-workflow/commits/18.0-ocabot-merge-pr-1902-by-pedrobaeza-bump-nobump), awaiting test results.
author_association: CONTRIBUTOR
user: login: OCA-git-bot
created_at: 2025-03-24T07:24:03Z
body: Congratulations, your PR was merged at eb287bb023a87f0e9d02c99babd5d49b69800c03. Thanks a lot for contributing to OCA. ❤️
author_association: CONTRIBUTOR