Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
6c71036
[ADD] sale_product_pack: new module
ernestotejeda Sep 19, 2019
c5be2f1
[UPD] README.rst + [ADD] icon.png
OCA-git-bot Oct 22, 2019
26b8cb2
[UPD] Update sale_product_pack.pot
oca-travis Oct 22, 2019
bf22a20
[IMP] sale_product_pack: add a Roadmap section to the readme
ernestotejeda Oct 22, 2019
aaed3c7
[FIX] sale_product_pack: Unlink pack children lines before
pedrobaeza Dec 4, 2019
a321563
[UPD] Update sale_product_pack.pot
oca-travis Dec 4, 2019
3c9bef5
Update translation files
oca-transbot Dec 4, 2019
5e8a290
Added translation using Weblate (Portuguese)
pedrocs-exo Dec 12, 2019
504930a
[FIX] sale_product_pack: Set price 0 for non detailed components in s…
pedrobaeza Dec 17, 2019
8b2bba3
[UPD] Update sale_product_pack.pot
oca-travis Dec 17, 2019
bb6c4ae
Update translation files
oca-transbot Dec 17, 2019
788b089
Added translation using Weblate (Catalan + Spanish)
CarlesAntoli Dec 27, 2019
54ad49b
Allow to update product_uom_qty after sale is confirmed
hparfr May 12, 2020
526d895
Administrative commits
oca-travis May 12, 2020
02a3675
Add pack_modifiable in the sale order line.
hparfr Mar 18, 2020
e51978a
[UPD] Update sale_product_pack.pot
oca-travis May 26, 2020
f9fff4a
Administrative commits
OCA-git-bot May 26, 2020
da61a65
Added translation using Weblate (French)
ypapouin May 28, 2020
4c7df71
[IMP] sale_product_pack: black, isort, prettier
jjscarafia Jun 7, 2020
6ab5874
[MIG] sale_product_pack: Migration to 13.0
jjscarafia Jun 7, 2020
10d21d3
[MIG] sale_product_pack: Migration to 13.0 (fix order line deleting)
Jul 8, 2020
0eedb78
[UPD] Update sale_product_pack.pot
oca-travis Jul 13, 2020
9b005ea
[UPD] README.rst
OCA-git-bot Jul 13, 2020
1e21981
Update translation files
oca-transbot Aug 16, 2020
d506385
[FIX] sale_product_pack: Missing write result
ypapouin Oct 9, 2020
a7dfe2f
Added translation using Weblate (Dutch)
bosd Dec 13, 2020
1d4524b
Translated using Weblate (Dutch)
bosd Dec 13, 2020
e6da814
[ADD] website_sale_product_pack: New module
chienandalu Jun 18, 2021
ba229f2
[FIX] sale_product_pack: Add pricelist to the sale order to avoid inc…
victoralmau Oct 20, 2021
5916e2f
sale_product_pack 13.0.1.0.2
OCA-git-bot Oct 21, 2021
7b51f05
[IMP] sale_product_pack: black, isort, prettier
dreispt Nov 15, 2021
3e1c90c
[MIG] sale_product_pack: Migration to 14.0
dreispt Nov 15, 2021
0d853df
[UPD] Update sale_product_pack.pot
oca-travis Jan 11, 2022
5eb77bc
[UPD] README.rst
OCA-git-bot Jan 11, 2022
9ad5b6a
[UPD] Update sale_product_pack.pot
oca-travis Jan 14, 2022
b1d06ff
Update translation files
oca-transbot Jan 14, 2022
d304004
Translated using Weblate (Catalan)
Noel000 Feb 28, 2022
8e6cdb5
[14.0][IMP] sale_product_pack: Use multi create for pack lines
rousseldenis Mar 8, 2022
ca8c187
sale_product_pack 14.0.1.0.1
OCA-git-bot Mar 9, 2022
3aabf0e
[14.0][IMP] sale_product_pack: add field in order to get 'do not expa…
rousseldenis Mar 16, 2022
2a52685
[14.0][IMP] sale_product_pack: Use field instead of searches if we ha…
rousseldenis Mar 16, 2022
08152c0
[14.0][IMP] sale_product_pack: Set sequence value in good function
rousseldenis Mar 16, 2022
7d7e31e
[14.0][IMP] sale_product_pack: Add test for multi lines creation
rousseldenis Mar 16, 2022
f297af8
[UPD] Update sale_product_pack.pot
Jun 28, 2022
0f0657a
sale_product_pack 14.0.1.1.0
OCA-git-bot Jun 28, 2022
32b26fa
Update translation files
oca-transbot Jun 28, 2022
27fd4f3
[IMP] Improve tests for sale_product_pack
cvinh Jul 5, 2022
2068b27
sale_product_pack 14.0.1.1.1
OCA-git-bot Jul 8, 2022
f57acba
[MIG] sale_product_pack: Migration to 15.0
nicomacr Jun 2, 2022
74c0283
[UPD] Update sale_product_pack.pot
Nov 30, 2022
64af26d
[UPD] README.rst
OCA-git-bot Nov 30, 2022
36f81ab
[MIG] sale_product_pack: Migration to 16.0
FrancoMaxime Feb 22, 2023
4910fb1
[FIX] sale_product_pack - Recomputes correctly the price of product_p…
FrancoMaxime Mar 2, 2023
b038576
[FIX] sale_product_pack: fix error when creating Down Payment
augusto-weiss Mar 28, 2023
14a9859
[FIX] sale_product_pack: for compatibility with sale_product_pack_ass…
augusto-weiss Apr 6, 2023
6d85dc4
[UPD] Update sale_product_pack.pot
Jun 5, 2023
668f2b6
[UPD] README.rst
OCA-git-bot Jun 5, 2023
17fc2ea
Update translation files
weblate Jun 5, 2023
2076a34
[UPD] README.rst
OCA-git-bot Sep 3, 2023
80b8e98
Translated using Weblate (Spanish)
Ivorra78 Aug 23, 2023
d93eb0a
Added translation using Weblate (Italian)
mymage Nov 8, 2023
17e8cf1
Translated using Weblate (Italian)
mymage Nov 9, 2023
f5a07a1
Translated using Weblate (Italian)
mymage Nov 10, 2023
a337e1e
[IMP] sale_product_pack: add sale demo for each type of pack
ALopez-Adhoc Oct 30, 2023
97ae220
[BOT] post-merge updates
OCA-git-bot Nov 23, 2023
e5fccb6
[IMP] sale_product_pack: pre-commit execution
Nov 30, 2023
a9662f4
[MIG] sale_product_pack: Migration to 17.0
Nov 30, 2023
3fad64a
[UPD] Update sale_product_pack.pot
May 14, 2024
7c19cd5
[BOT] post-merge updates
OCA-git-bot May 14, 2024
144c12b
Update translation files
weblate May 14, 2024
7a2784d
[REF] sale_product_pack: Price computation refactor
May 10, 2024
d215fb3
[FIX] sale_product_pack: Update Price Action
Oct 12, 2023
bff948d
[FIX] sale_product_pack: Respect the order of the lines to be added
victoralmau Oct 21, 2024
9abf075
[IMP] sale_product_pack: Change manifest maintainers
victoralmau Oct 29, 2024
c34d94f
[BOT] post-merge updates
OCA-git-bot Oct 29, 2024
c125a0c
[UPD] Update sale_product_pack.pot
Nov 4, 2024
17952be
[BOT] post-merge updates
OCA-git-bot Nov 4, 2024
d132924
Update translation files
weblate Nov 4, 2024
c65649f
Translated using Weblate (Italian)
mymage Nov 5, 2024
378c33b
[IMP] sale_product_pack: pre-commit execution
ALopez-Adhoc Nov 21, 2024
bc58d85
[MIG] sale_product_pack: Migration to 18.0
ALopez-Adhoc Nov 21, 2024
b7ee0fa
[UPD] Update sale_product_pack.pot
Jan 17, 2025
83e552c
[BOT] post-merge updates
OCA-git-bot Jan 17, 2025
7b3d13b
Update translation files
weblate Jan 17, 2025
9d5e481
[FIX] sale_product_pack: adjust discount formula for detailed packs
lef-adhoc Jan 28, 2025
0a97db5
[BOT] post-merge updates
OCA-git-bot Jan 31, 2025
66aae59
Translated using Weblate (Italian)
mymage Feb 12, 2025
559b3b6
[IMP] sale_product_pack + sale_stock_product_pack: Don't depend on de…
pedrobaeza Jul 16, 2025
4c2973c
[BOT] post-merge updates
OCA-git-bot Jul 17, 2025
4889f06
[MIG] sale_product_pack: Migration to 19.0
apik-mgu Oct 20, 2025
78bb5db
[IMP] product_pack,sale_product_pack: Allow modifiable non-detailed p…
lef-adhoc Nov 13, 2025
2fe595b
Merge branch '19.0' into 19.0-t-58218-lef-dummy
lef-adhoc Dec 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions product_pack/models/product_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ class ProductTemplate(models.Model):
)
pack_modifiable = fields.Boolean(
help="If you check this field yo will be able to edit "
"sale/purchase order line relate to its component",
"sale/purchase order line relate to its component.\n"
"For 'Non Detailed' packs, this will automatically expand the pack "
"into editable detailed lines.",
)
pack_modifiable_invisible = fields.Boolean(
compute="_compute_pack_modifiable_invisible",
Expand All @@ -55,22 +57,23 @@ def _get_pack_modifiable_invisible_depends(self):
@api.depends(lambda self: self._get_pack_modifiable_invisible_depends())
def _compute_pack_modifiable_invisible(self):
"""
The pack modifiable field should be invisible when:
- pack details are not displayed or
- pack component prices are not detailed

The pack modifiable field is visible when:
- Pack Display Type is 'Detailed' and Pack Component Price is
'Detailed per component'
- Pack Display Type is 'Non Detailed'
"""
for product in self:
product.pack_modifiable_invisible = (
product.pack_type != "detailed"
or product.pack_component_price != "detailed"
product.pack_type == "detailed"
and product.pack_component_price != "detailed"
)

@api.onchange("pack_type", "pack_component_price")
def onchange_pack_type(self):
products = self.filtered(
lambda x: x.pack_modifiable
and (x.pack_type != "detailed" or x.pack_component_price != "detailed")
and x.pack_type == "detailed"
and x.pack_component_price != "detailed"
)
for rec in products:
rec.pack_modifiable = False
Expand Down
10 changes: 5 additions & 5 deletions product_pack/tests/test_product_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,18 @@ def test_pack_type(self):
self.pack.pack_modifiable = True
with Form(self.pack.product_tmpl_id) as pack_form:
pack_form.pack_type = "non_detailed"
self.assertFalse(pack_form.pack_modifiable)
self.assertTrue(pack_form.pack_modifiable)

def test_pack_modifiable(self):
# Pack is detailed with component price as detailed
# Pack modifiable invisible should be False
self.assertFalse(self.pack.pack_modifiable_invisible)
# Set the Pack as non detailed
# Pack modifiable invisible should be True
# Pack modifiable invisible should be False
self.pack.pack_type = "non_detailed"
self.assertFalse(self.pack.pack_modifiable_invisible)
# Set the Pack as detailed with component price as totalized
# Pack modifiable invisible should be True
self.assertFalse(self.pack.pack_modifiable_invisible)
self.pack.pack_type = "non_detailed"
self.assertTrue(self.pack.pack_modifiable_invisible)
self.pack.pack_type = "detailed"
self.pack.pack_component_price = "totalized"
self.assertTrue(self.pack.pack_modifiable_invisible)
Expand Down
145 changes: 145 additions & 0 deletions sale_product_pack/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

=================
Sale Product Pack
=================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:d0034cc2b56fe98dabcd701ddded4a3adc81775fbf8857041c8b9ebd13eeb6ad
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |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/license-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%2Fproduct--pack-lightgray.png?logo=github
:target: https://github.com/OCA/product-pack/tree/19.0/sale_product_pack
:alt: OCA/product-pack
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/product-pack-19-0/product-pack-19-0-sale_product_pack
: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/product-pack&target_branch=19.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module adds *Product Pack* functionality to sales orders. You can
choose a *Pack* in *sales order lines* and see different behaviors
depending on "Pack type" and "Pack component price" fields options
selected on this *Pack*.

**Table of contents**

.. contents::
:local:

Usage
=====

To use this module, you need to:

1. Go to *Sales > Products > Products*, create or select a product and
check *Is Pack?*
2. Set "Product type" and "Pack component price" fields in the *Pack*
page.
3. Add the products to be included in it.
4. Go to *Sales > Orders > Quotations* and create a Quotation.
5. Add a product that has checked "Is Pack?"
6. Save data and you will see an specific behavior depending on "Pack
type" and "Pack component price" fields options selected on this
*Pack*. For example, for products that has *Detailed* option selected
in "Pack type" field you will see one *sale order line* per component
that belong to this Pack. (See *Product pack* module README.rst file)

Known issues / Roadmap
======================

- If this module is installed and stock module is installed too, when
you create a Sale order for a *Non detailed* Pack and you confirm it,
a *Stock picking* is not created with the storable components of that
Pack. So, add a new module called *sale_stock_product_pack* that adds
that feature.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/product-pack/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/product-pack/issues/new?body=module:%20sale_product_pack%0Aversion:%2019.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
-------

* NaN·tic
* ADHOC SA
* Tecnativa

Contributors
------------

- `Tecnativa <https://www.tecnativa.com>`__:

- Ernesto Tejeda
- Pedro M. Baeza

- `Akretion <https://akretion.com>`__:

- Raphaël Reverdy

- `Open Source Integrators <https://opensourceintegrators.eu>`__:

- Daniel Reis <dreis@opensourceintegrators.com>

- `Acsone <https://www.acsone.eu/>`__:

- Maxime Franco

- `ADHOC SA <https://www.adhoc.com.ar>`__:

- Bruno Zanotti
- Augusto Weiss
- Nicolas Col

- `Apik <https://apik.cloud/>`__:

- Michel Guiheneuf

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/product-pack <https://github.com/OCA/product-pack/tree/19.0/sale_product_pack>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
2 changes: 2 additions & 0 deletions sale_product_pack/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import models
19 changes: 19 additions & 0 deletions sale_product_pack/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2019 NaN (http://www.nan-tic.com) - Àngel Àlvarez
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
"name": "Sale Product Pack",
"version": "19.0.1.0.0",
"category": "Sales",
"summary": "This module allows you to sell product packs",
"website": "https://github.com/OCA/product-pack",
"author": "NaN·tic, ADHOC SA, Tecnativa, Odoo Community Association (OCA)",
"maintainers": ["victoralmau"],
"license": "AGPL-3",
"depends": ["product_pack", "sale"],
"data": ["security/ir.model.access.csv", "views/product_pack_line_views.xml"],
"demo": [
"demo/product_pack_line_demo.xml",
"demo/sale_pack_demo.xml",
],
"installable": True,
}
23 changes: 23 additions & 0 deletions sale_product_pack/demo/product_pack_line_demo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2019 Tecnativa - Ernesto Tejeda
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo noupdate="1">
<record id="product_pack.pack_cpu_detailed_components_1" model="product.pack.line">
<field name="sale_discount" eval="10.0" />
</record>
<record id="product_pack.pack_cpu_detailed_components_3" model="product.pack.line">
<field name="sale_discount" eval="10.0" />
</record>
<record id="product_pack.pack_cpu_detailed_totalized_1" model="product.pack.line">
<field name="sale_discount" eval="10.0" />
</record>
<record id="product_pack.pack_cpu_detailed_totalized_3" model="product.pack.line">
<field name="sale_discount" eval="10.0" />
</record>
<record id="product_pack.pack_cpu_non_detailed_1" model="product.pack.line">
<field name="sale_discount" eval="10.0" />
</record>
<record id="product_pack.pack_cpu_non_detailed_3" model="product.pack.line">
<field name="sale_discount" eval="10.0" />
</record>
</odoo>
108 changes: 108 additions & 0 deletions sale_product_pack/demo/sale_pack_demo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?xml version='1.0' encoding='utf-8' ?>
<odoo>
<!-- Sale order -->
<record id="portal_sale_order_3" model="sale.order">
<field name="partner_id" ref="base.partner_demo_portal" />
<field name="partner_invoice_id" ref="base.partner_demo_portal" />
<field name="partner_shipping_id" ref="base.partner_demo_portal" />
<field name="user_id" ref="base.user_admin" />
<field name="payment_term_id" ref="account.account_payment_term_30days" />
<field name="team_id" ref="sales_team.team_sales_department" />
<field
name="date_order"
eval="(DateTime.today() - relativedelta(months=1)).strftime('%Y-%m-%d %H:%M')"
/>
<field
name="message_partner_ids"
eval="[(4, ref('base.partner_demo_portal'))]"
/>
</record>

<!-- Sale order lines -->
<!-- Product pack: DETAILED - COMPONENTS -->
<record id="portal_sale_order_line_section_1" model="sale.order.line">
<field name="order_id" ref="portal_sale_order_3" />
<field name="name">Detailed Displayed Components Price</field>
<field name="display_type">line_section</field>
<field name="sequence">1</field>
</record>
<record id="portal_sale_order_line_6" model="sale.order.line">
<field name="order_id" ref="portal_sale_order_3" />
<field
name="product_id"
ref="product_pack.product_pack_cpu_detailed_components"
/>
<field name="sequence">2</field>
</record>
<!-- Product pack: DETAILED - TOTALIZED -->
<record id="portal_sale_order_line_section_2" model="sale.order.line">
<field name="order_id" ref="portal_sale_order_3" />
<field name="name">Detailed Totalized Components Price</field>
<field name="display_type">line_section</field>
<field name="sequence">3</field>
</record>
<record id="portal_sale_order_line_7" model="sale.order.line">
<field name="order_id" ref="portal_sale_order_3" />
<field
name="product_id"
ref="product_pack.product_pack_cpu_detailed_totalized"
/>
<field name="sequence">4</field>
</record>
<!-- Product pack: DETAILED - IGNORED -->
<record id="portal_sale_order_line_section_3" model="sale.order.line">
<field name="order_id" ref="portal_sale_order_3" />
<field name="name">Detailed Ignored Components Price</field>
<field name="display_type">line_section</field>
<field name="sequence">5</field>
</record>
<record id="portal_sale_order_line_8" model="sale.order.line">
<field name="order_id" ref="portal_sale_order_3" />
<field name="product_id" ref="product_pack.product_pack_cpu_detailed_ignored" />
<field name="sequence">6</field>
</record>
<!-- Product pack: NON DETAILED -->
<record id="portal_sale_order_line_section_4" model="sale.order.line">
<field name="order_id" ref="portal_sale_order_3" />
<field name="name">Not Detailed - Totalized Components Price</field>
<field name="display_type">line_section</field>
<field name="sequence">7</field>
</record>
<record id="portal_sale_order_line_9" model="sale.order.line">
<field name="order_id" ref="portal_sale_order_3" />
<field name="product_id" ref="product_pack.product_pack_cpu_non_detailed" />
<field name="sequence">8</field>
</record>
<!-- Components -->
<record id="portal_sale_order_line_section_5" model="sale.order.line">
<field name="order_id" ref="portal_sale_order_3" />
<field name="name">COMPONENTS</field>
<field name="display_type">line_section</field>
<field name="sequence">9</field>
</record>
<record id="portal_sale_order_line_components_1" model="sale.order.line">
<field name="order_id" ref="portal_sale_order_3" />
<field name="product_id" ref="product.product_product_20" />
<field name="sequence">10</field>
</record>

<record id="portal_sale_order_line_components_2" model="sale.order.line">
<field name="order_id" ref="portal_sale_order_3" />
<field name="product_id" ref="product.product_product_16" />
<field name="sequence">11</field>
</record>

<record id="portal_sale_order_components_3" model="sale.order.line">
<field name="order_id" ref="portal_sale_order_3" />
<field name="product_id" ref="product.product_product_24" />
<field name="sequence">12</field>
</record>

<function
model="sale.order"
name="action_confirm"
eval="[[
ref('portal_sale_order_3'),
]]"
/>
</odoo>
Loading