Product Pack

product_pack
REPOSITORY
REPOSITORYOCA/product-pack
GIT
GIThttps://github.com/OCA/product-pack.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/product-pack/tree/19.0/product_pack
VERSION
VERSION 1.1.0
CATEGORY
CATEGORYProduct
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSTecnativa, Odoo Community Association (OCA), ADHOC SA, NaN·tic
MAINTAINERS
MAINTAINERSTecnativa, Odoo Community Association (OCA), ADHOC SA, NaN·tic
COMMITTERS
COMMITTERSVíctor Martínez, OCA-git-bot, oca-ci, jpo, Guido Galetto, mgu
WEBSITE
WEBSITEhttps://github.com/OCA/product-pack
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 19:40:50
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - html_editor
    - uom
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (5)
XML IDNameModelTypeStatus
nan_product_pack_form product.product.pack.form product.product group Inherits product.product_normal_form_view
product_pack_line_form product.pack.line.form product.pack.line form New
product_pack_line_tree product.pack.line.tree product.pack.line list New
product_template_form_view product.template.pack.form product.template div Inherits product.product_template_form_view
product_template_only_form_view product.template.pack.form product.template page Inherits product.product_template_only_form_view
Models touched (4)

New fields (3)
  • parent_product_id Many2one → product.product
    index=True ondelete='cascade' required=True args: 'product.product', 'Parent Product'
  • product_id Many2one → product.product
    index=True ondelete='cascade' required=True args: 'product.product', 'Product'
  • quantity Float
    default=1.0 digits='Product Unit' required=True
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (2)
  • pack_line_ids One2many → product.pack.line
    help='Products that are part of this pack.' args: 'product.pack.line', 'parent_product_id', 'Pack Products'
  • used_in_pack_line_ids One2many → product.pack.line
    help='Packs where product is used.' args: 'product.pack.line', 'product_id', 'Found in packs'
Public methods (2)
  • get_pack_lines(self)
    Returns the content (lines) of the packs. By default, return all the pack_line_ids, but that function can be overloaded to introduce filtering function by date, etc...
  • split_pack_products(self)

New fields (7)
  • pack_component_price Selection
    help="On sale orders or purchase orders:\n* Detailed per component: Detail lines with prices.\n* Totalized in main product: Detail lines merging lines prices on pack (don't show component prices).\n* Ignored: Use product pack price (ignore detail line prices)." args: [('detailed', 'Detailed per component'), ('totalized', 'Totalized in main product'), ('ignored', 'Ignored')]
  • pack_line_ids One2many
    related='product_variant_ids.pack_line_ids'
  • pack_modifiable Boolean
    help='If you check this field yo will be able to edit sale/purchase order line relate to its component'
  • pack_modifiable_invisible Boolean
    compute='_compute_pack_modifiable_invisible' help='Technical field in order to compute the availability of the Pack Modifiable field'
  • pack_ok Boolean
    help='Is a Product Pack?' args: 'Is Pack?'
  • pack_type Selection
    help='On sale orders or purchase orders:\n* Detailed: Display components individually in the sale order.\n* Non Detailed: Do not display components individually in the sale order.' string='Pack Display Type' args: [('detailed', 'Detailed'), ('non_detailed', 'Non Detailed')]
  • used_in_pack_line_ids One2many
    readonly=True related='product_variant_ids.used_in_pack_line_ids'
Public methods (3)
  • onchange_pack_type(self)
    @api.onchange('pack_type', 'pack_component_price')
  • split_pack_products(self)
    Split products and the pack in 2 separate recordsets. :return: [packs, no_packs]
  • write(self, vals)
    We remove from product.product to avoid error.
REPOSITORY
REPOSITORYOCA/product-pack
GIT
GIThttps://github.com/OCA/product-pack.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/product-pack/tree/18.0/product_pack
VERSION
VERSION 1.1.0
CATEGORY
CATEGORYProduct
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSTecnativa, Odoo Community Association (OCA), ADHOC SA, NaN·tic
MAINTAINERS
MAINTAINERSTecnativa, Odoo Community Association (OCA), ADHOC SA, NaN·tic
COMMITTERS
COMMITTERSPedro M. Baeza, Víctor Martínez, Weblate, OCA-git-bot, oca-ci, Alexis Lopez
WEBSITE
WEBSITEhttps://github.com/OCA/product-pack
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 19:30:17
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - html_editor
    - uom
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (5)
XML IDNameModelTypeStatus
nan_product_pack_form product.product.pack.form product.product group Inherits product.product_normal_form_view
product_pack_line_form product.pack.line.form product.pack.line form New
product_pack_line_tree product.pack.line.tree product.pack.line list New
product_template_form_view product.template.pack.form product.template div Inherits product.product_template_form_view
product_template_only_form_view product.template.pack.form product.template page Inherits product.product_template_only_form_view
Models touched (4)

New fields (3)
  • parent_product_id Many2one → product.product
    index=True ondelete='cascade' required=True args: 'product.product', 'Parent Product'
  • product_id Many2one → product.product
    index=True ondelete='cascade' required=True args: 'product.product', 'Product'
  • quantity Float
    default=1.0 digits='Product UoS' required=True
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (2)
  • pack_line_ids One2many → product.pack.line
    help='Products that are part of this pack.' args: 'product.pack.line', 'parent_product_id', 'Pack Products'
  • used_in_pack_line_ids One2many → product.pack.line
    help='Packs where product is used.' args: 'product.pack.line', 'product_id', 'Found in packs'
Public methods (2)
  • get_pack_lines(self)
    Returns the content (lines) of the packs. By default, return all the pack_line_ids, but that function can be overloaded to introduce filtering function by date, etc...
  • split_pack_products(self)

New fields (7)
  • pack_component_price Selection
    help="On sale orders or purchase orders:\n* Detailed per component: Detail lines with prices.\n* Totalized in main product: Detail lines merging lines prices on pack (don't show component prices).\n* Ignored: Use product pack price (ignore detail line prices)." args: [('detailed', 'Detailed per component'), ('totalized', 'Totalized in main product'), ('ignored', 'Ignored')]
  • pack_line_ids One2many
    related='product_variant_ids.pack_line_ids'
  • pack_modifiable Boolean
    help='If you check this field yo will be able to edit sale/purchase order line relate to its component'
  • pack_modifiable_invisible Boolean
    compute='_compute_pack_modifiable_invisible' help='Technical field in order to compute the availability of the Pack Modifiable field'
  • pack_ok Boolean
    help='Is a Product Pack?' args: 'Is Pack?'
  • pack_type Selection
    help='On sale orders or purchase orders:\n* Detailed: Display components individually in the sale order.\n* Non Detailed: Do not display components individually in the sale order.' string='Pack Display Type' args: [('detailed', 'Detailed'), ('non_detailed', 'Non Detailed')]
  • used_in_pack_line_ids One2many
    readonly=True related='product_variant_ids.used_in_pack_line_ids'
Public methods (3)
  • onchange_pack_type(self)
    @api.onchange('pack_type', 'pack_component_price')
  • split_pack_products(self)
    Split products and the pack in 2 separate recordsets. :return: [packs, no_packs]
  • write(self, vals)
    We remove from product.product to avoid error.
REPOSITORY
REPOSITORYOCA/product-pack
GIT
GIThttps://github.com/OCA/product-pack.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/product-pack/tree/17.0/product_pack
VERSION
VERSION 2.0.1
CATEGORY
CATEGORYProduct
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSTecnativa, Odoo Community Association (OCA), ADHOC SA, NaN·tic
MAINTAINERS
MAINTAINERSTecnativa, Odoo Community Association (OCA), ADHOC SA, NaN·tic
COMMITTERS
COMMITTERSBruno Zanotti, Weblate, OCA-git-bot, oca-ci, mav-adhoc
WEBSITE
WEBSITEhttps://github.com/OCA/product-pack
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 19:20:10
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (5)
XML IDNameModelTypeStatus
nan_product_pack_form product.product.pack.form product.product group Inherits product.product_normal_form_view
product_pack_line_form product.pack.line.form product.pack.line form New
product_pack_line_tree product.pack.line.tree product.pack.line tree New
product_template_form_view product.template.pack.form product.template div Inherits product.product_template_form_view
product_template_only_form_view product.template.pack.form product.template page Inherits product.product_template_only_form_view
Models touched (4)

New fields (3)
  • parent_product_id Many2one → product.product
    index=True ondelete='cascade' required=True args: 'product.product', 'Parent Product'
  • product_id Many2one → product.product
    index=True ondelete='cascade' required=True args: 'product.product', 'Product'
  • quantity Float
    default=1.0 digits='Product UoS' required=True
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (2)
  • pack_line_ids One2many → product.pack.line
    help='Products that are part of this pack.' args: 'product.pack.line', 'parent_product_id', 'Pack Products'
  • used_in_pack_line_ids One2many → product.pack.line
    help='Packs where product is used.' args: 'product.pack.line', 'product_id', 'Found in packs'
Public methods (2)
  • get_pack_lines(self)
    Returns the content (lines) of the packs. By default, return all the pack_line_ids, but that function can be overloaded to introduce filtering function by date, etc...
  • split_pack_products(self)

New fields (7)
  • pack_component_price Selection
    help="On sale orders or purchase orders:\n* Detailed per component: Detail lines with prices.\n* Totalized in main product: Detail lines merging lines prices on pack (don't show component prices).\n* Ignored: Use product pack price (ignore detail line prices)." args: [('detailed', 'Detailed per component'), ('totalized', 'Totalized in main product'), ('ignored', 'Ignored')]
  • pack_line_ids One2many
    related='product_variant_ids.pack_line_ids'
  • pack_modifiable Boolean
    help='If you check this field yo will be able to edit sale/purchase order line relate to its component'
  • pack_modifiable_invisible Boolean
    compute='_compute_pack_modifiable_invisible' help='Technical field in order to compute the availability of the Pack Modifiable field'
  • pack_ok Boolean
    help='Is a Product Pack?' args: 'Is Pack?'
  • pack_type Selection
    help='On sale orders or purchase orders:\n* Detailed: Display components individually in the sale order.\n* Non Detailed: Do not display components individually in the sale order.' string='Pack Display Type' args: [('detailed', 'Detailed'), ('non_detailed', 'Non Detailed')]
  • used_in_pack_line_ids One2many
    readonly=True related='product_variant_ids.used_in_pack_line_ids'
Public methods (3)
  • onchange_pack_type(self)
    @api.onchange('pack_type', 'pack_component_price')
  • split_pack_products(self)
    Split products and the pack in 2 separate recordsets. :return: [packs, no_packs]
  • write(self, vals)
    We remove from product.product to avoid error.
REPOSITORY
REPOSITORYOCA/product-pack
GIT
GIThttps://github.com/OCA/product-pack.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/product-pack/tree/16.0/product_pack
VERSION
VERSION 1.1.0
CATEGORY
CATEGORYProduct
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSTecnativa, Odoo Community Association (OCA), ADHOC SA, NaN·tic
MAINTAINERS
MAINTAINERSTecnativa, Odoo Community Association (OCA), ADHOC SA, NaN·tic
COMMITTERS
COMMITTERSWeblate, OCA-git-bot, Maxime Franco, oca-ci, Christian-RB, docker-odoo
WEBSITE
WEBSITEhttps://github.com/OCA/product-pack
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:53:56
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (5)
XML IDNameModelTypeStatus
nan_product_pack_form product.product.pack.form product.product group Inherits product.product_normal_form_view
product_pack_line_form product.pack.line.form product.pack.line form New
product_pack_line_tree product.pack.line.tree product.pack.line tree New
product_template_form_view product.template.pack.form product.template div Inherits product.product_template_form_view
product_template_only_form_view product.template.pack.form product.template page Inherits product.product_template_only_form_view
Models touched (3)

New fields (3)
  • parent_product_id Many2one → product.product
    index=True ondelete='cascade' required=True args: 'product.product', 'Parent Product'
  • product_id Many2one → product.product
    index=True ondelete='cascade' required=True args: 'product.product', 'Product'
  • quantity Float
    default=1.0 digits='Product UoS' required=True
Public methods (1)
  • get_price(self)

New fields (2)
  • pack_line_ids One2many → product.pack.line
    help='Products that are part of this pack.' args: 'product.pack.line', 'parent_product_id', 'Pack Products'
  • used_in_pack_line_ids One2many → product.pack.line
    help='Packs where product is used.' args: 'product.pack.line', 'product_id', 'Found in packs'
Public methods (3)
  • get_pack_lines(self)
    Returns the content (lines) of the packs. By default, return all the pack_line_ids, but that function can be overloaded to introduce filtering function by date, etc...
  • price_compute(self, price_type, uom=False, currency=False, company=False, date=False)
  • split_pack_products(self)

New fields (7)
  • pack_component_price Selection
    help="On sale orders or purchase orders:\n* Detailed per component: Detail lines with prices.\n* Totalized in main product: Detail lines merging lines prices on pack (don't show component prices).\n* Ignored: Use product pack price (ignore detail line prices)." args: [('detailed', 'Detailed per component'), ('totalized', 'Totalized in main product'), ('ignored', 'Ignored')]
  • pack_line_ids One2many
    related='product_variant_ids.pack_line_ids'
  • pack_modifiable Boolean
    help='If you check this field yo will be able to edit sale/purchase order line relate to its component'
  • pack_modifiable_invisible Boolean
    compute='_compute_pack_modifiable_invisible' help='Technical field in order to compute the availability of the Pack Modifiable field'
  • pack_ok Boolean
    help='Is a Product Pack?' args: 'Is Pack?'
  • pack_type Selection
    help='On sale orders or purchase orders:\n* Detailed: Display components individually in the sale order.\n* Non Detailed: Do not display components individually in the sale order.' string='Pack Display Type' args: [('detailed', 'Detailed'), ('non_detailed', 'Non Detailed')]
  • used_in_pack_line_ids One2many
    readonly=True related='product_variant_ids.used_in_pack_line_ids'
Public methods (3)
  • onchange_pack_type(self)
    @api.onchange('pack_type', 'pack_component_price')
  • split_pack_products(self)
    Split products and the pack in 2 separate recordsets. :return: [packs, no_packs]
  • write(self, vals)
    We remove from product.product to avoid error.
REPOSITORY
REPOSITORYOCA/product-pack
GIT
GIThttps://github.com/OCA/product-pack.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/product-pack/tree/15.0/product_pack
VERSION
VERSION 1.0.1
CATEGORY
CATEGORYProduct
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSTecnativa, Odoo Community Association (OCA), ADHOC SA, NaN·tic
MAINTAINERS
MAINTAINERSTecnativa, Odoo Community Association (OCA), ADHOC SA, NaN·tic
COMMITTERS
COMMITTERSPedro M. Baeza, manu, Weblate, OCA-git-bot, oca-ci
WEBSITE
WEBSITEhttps://github.com/OCA/product-pack
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:46:41
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (5)
XML IDNameModelTypeStatus
nan_product_pack_form product.product.pack.form product.product group Inherits product.product_normal_form_view
product_pack_line_form product.pack.line.form product.pack.line form New
product_pack_line_tree product.pack.line.tree product.pack.line tree New
product_template_form_view product.template.pack.form product.template div Inherits product.product_template_form_view
product_template_only_form_view product.template.pack.form product.template page Inherits product.product_template_only_form_view
Models touched (4)

New fields (3)
  • parent_product_id Many2one → product.product
    index=True ondelete='cascade' required=True args: 'product.product', 'Parent Product'
  • product_id Many2one → product.product
    index=True ondelete='cascade' required=True args: 'product.product', 'Product'
  • quantity Float
    default=1.0 digits='Product UoS' required=True
Public methods (1)
  • get_price(self)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (2)
  • pack_line_ids One2many → product.pack.line
    help='Products that are part of this pack.' args: 'product.pack.line', 'parent_product_id', 'Pack Products'
  • used_in_pack_line_ids One2many → product.pack.line
    help='Packs where product is used.' args: 'product.pack.line', 'product_id', 'Found in packs'
Public methods (3)
  • get_pack_lines(self)
    Returns the content (lines) of the packs. By default, return all the pack_line_ids, but that function can be overloaded to introduce filtering function by date, etc...
  • price_compute(self, price_type, uom=False, currency=False, company=False)
  • split_pack_products(self)

New fields (7)
  • pack_component_price Selection
    help="On sale orders or purchase orders:\n* Detailed per component: Detail lines with prices.\n* Totalized in main product: Detail lines merging lines prices on pack (don't show component prices).\n* Ignored: Use product pack price (ignore detail line prices)." args: [('detailed', 'Detailed per component'), ('totalized', 'Totalized in main product'), ('ignored', 'Ignored')]
  • pack_line_ids One2many
    related='product_variant_ids.pack_line_ids'
  • pack_modifiable Boolean
    help='If you check this field yo will be able to edit sale/purchase order line relate to its component'
  • pack_modifiable_invisible Boolean
    compute='_compute_pack_modifiable_invisible' help='Technical field in order to compute the availability of the Pack Modifiable field'
  • pack_ok Boolean
    help='Is a Product Pack?' args: 'Is Pack?'
  • pack_type Selection
    help='On sale orders or purchase orders:\n* Detailed: Display components individually in the sale order.\n* Non Detailed: Do not display components individually in the sale order.' string='Pack Display Type' args: [('detailed', 'Detailed'), ('non_detailed', 'Non Detailed')]
  • used_in_pack_line_ids One2many
    readonly=True related='product_variant_ids.used_in_pack_line_ids'
Public methods (3)
  • onchange_pack_type(self)
    @api.onchange('pack_type', 'pack_component_price')
  • split_pack_products(self)
    Split products and the pack in 2 separate recordsets. :return: [packs, no_packs]
  • write(self, vals)
    We remove from product.product to avoid error.
REPOSITORY
REPOSITORYOCA/product-pack
GIT
GIThttps://github.com/OCA/product-pack.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/product-pack/tree/14.0/product_pack
VERSION
VERSION 1.1.2
CATEGORY
CATEGORYProduct
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSTecnativa, Odoo Community Association (OCA), ADHOC SA, NaN·tic
MAINTAINERS
MAINTAINERSTecnativa, Odoo Community Association (OCA), ADHOC SA, NaN·tic
COMMITTERS
COMMITTERSPedro M. Baeza, Denis Roussel, Pierre Verkest, OCA Transbot, oca-travis, Weblate, OCA-git-bot, oca-ci, Usdoo Wedoo
WEBSITE
WEBSITEhttps://github.com/OCA/product-pack
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:41:10
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (5)
XML IDNameModelTypeStatus
nan_product_pack_form product.product.pack.form product.product group Inherits product.product_normal_form_view
product_pack_line_form product.pack.line.form product.pack.line form New
product_pack_line_tree product.pack.line.tree product.pack.line tree New
product_template_form_view product.template.pack.form product.template div Inherits product.product_template_form_view
product_template_only_form_view product.template.pack.form product.template page Inherits product.product_template_only_form_view
Models touched (4)

New fields (3)
  • parent_product_id Many2one → product.product
    index=True ondelete='cascade' required=True args: 'product.product', 'Parent Product'
  • product_id Many2one → product.product
    index=True ondelete='cascade' required=True args: 'product.product', 'Product'
  • quantity Float
    default=1.0 digits='Product UoS' required=True
Public methods (1)
  • get_price(self)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (2)
  • pack_line_ids One2many → product.pack.line
    help='Products that are part of this pack.' args: 'product.pack.line', 'parent_product_id', 'Pack Products'
  • used_in_pack_line_ids One2many → product.pack.line
    help='Packs where product is used.' args: 'product.pack.line', 'product_id', 'Found in packs'
Public methods (3)
  • get_pack_lines(self)
    Returns the content (lines) of the packs. By default, return all the pack_line_ids, but that function can be overloaded to introduce filtering function by date, etc...
  • price_compute(self, price_type, uom=False, currency=False, company=False)
  • split_pack_products(self)

New fields (7)
  • pack_component_price Selection
    help="On sale orders or purchase orders:\n* Detailed per component: Detail lines with prices.\n* Totalized in main product: Detail lines merging lines prices on pack (don't show component prices).\n* Ignored: Use product pack price (ignore detail line prices)." args: [('detailed', 'Detailed per component'), ('totalized', 'Totalized in main product'), ('ignored', 'Ignored')], 'Pack component price'
  • pack_line_ids One2many
    related='product_variant_ids.pack_line_ids'
  • pack_modifiable Boolean
    help='If you check this field yo will be able to edit sale/purchase order line relate to its component'
  • pack_modifiable_invisible Boolean
    compute='_compute_pack_modifiable_invisible' help='Technical field in order to compute the availability of the Pack Modifiable field'
  • pack_ok Boolean
    help='Is a Product Pack?' args: 'Is Pack?'
  • pack_type Selection
    help='On sale orders or purchase orders:\n* Detailed: Display components individually in the sale order.\n* Non Detailed: Do not display components individually in the sale order.' string='Pack Display Type' args: [('detailed', 'Detailed'), ('non_detailed', 'Non Detailed')]
  • used_in_pack_line_ids One2many
    readonly=True related='product_variant_ids.used_in_pack_line_ids'
Public methods (3)
  • onchange_pack_type(self)
    @api.onchange('pack_type', 'pack_component_price')
  • split_pack_products(self)
    Split products and the pack in 2 separate recordsets. :return: [packs, no_packs]
  • write(self, vals)
    We remove from product.product to avoid error.
REPOSITORY
REPOSITORYOCA/product-pack
GIT
GIThttps://github.com/OCA/product-pack.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/product-pack/tree/13.0/product_pack
VERSION
VERSION 1.0.4
CATEGORY
CATEGORYProduct
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSTecnativa, Odoo Community Association (OCA), ADHOC SA, NaN·tic
MAINTAINERS
MAINTAINERSTecnativa, Odoo Community Association (OCA), ADHOC SA, NaN·tic
COMMITTERS
COMMITTERSPedro M. Baeza, david, OCA Transbot, Nicolás Mac Rouillon, Juan Jose Scarafia, oca-travis, Weblate, OCA-git-bot, oca-ci
WEBSITE
WEBSITEhttps://github.com/OCA/product-pack
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:34:19
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - product
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (5)
XML IDNameModelTypeStatus
nan_product_pack_form product.product.pack.form product.product group Inherits product.product_normal_form_view
product_pack_line_form product.pack.line.form product.pack.line form New
product_pack_line_tree product.pack.line.tree product.pack.line tree New
product_template_form_view product.template.pack.form product.template div Inherits product.product_template_form_view
product_template_only_form_view product.template.pack.form product.template page Inherits product.product_template_only_form_view
Models touched (4)

New fields (3)
  • parent_product_id Many2one → product.product
    index=True ondelete='cascade' required=True args: 'product.product', 'Parent Product'
  • product_id Many2one → product.product
    index=True ondelete='cascade' required=True args: 'product.product', 'Product'
  • quantity Float
    default=1.0 digits='Product UoS' required=True
Public methods (1)
  • get_price(self)

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (2)
  • pack_line_ids One2many → product.pack.line
    help='Products that are part of this pack.' args: 'product.pack.line', 'parent_product_id', 'Pack Products'
  • used_in_pack_line_ids One2many → product.pack.line
    help='Packs where product is used.' args: 'product.pack.line', 'product_id', 'Found in packs'
Public methods (3)
  • get_pack_lines(self)
    Returns the content (lines) of the packs. By default, return all the pack_line_ids, but that function can be overloaded to introduce filtering function by date, etc...
  • price_compute(self, price_type, uom=False, currency=False, company=False)
  • split_pack_products(self)

New fields (6)
  • pack_component_price Selection
    help="On sale orders or purchase orders:\n* Detailed per component: Detail lines with prices.\n* Totalized in main product: Detail lines merging lines prices on pack (don't show component prices).\n* Ignored: Use product pack price (ignore detail line prices)." args: [('detailed', 'Detailed per component'), ('totalized', 'Totalized in main product'), ('ignored', 'Ignored')], 'Pack component price'
  • pack_line_ids One2many
    related='product_variant_ids.pack_line_ids'
  • pack_modifiable Boolean
    help='If you check this field yo will be able to edit sale/purchase order line relate to its component'
  • pack_ok Boolean
    help='Is a Product Pack?' args: 'Is Pack?'
  • pack_type Selection
    help='On sale orders or purchase orders:\n* Detailed: Display components individually in the sale order.\n* Non Detailed: Do not display components individually in the sale order.' args: [('detailed', 'Detailed'), ('non_detailed', 'Non Detailed')], 'Pack Type'
  • used_in_pack_line_ids One2many
    readonly=True related='product_variant_ids.used_in_pack_line_ids'
Public methods (3)
  • onchange_pack_type(self)
    @api.onchange('pack_type', 'pack_component_price')
  • split_pack_products(self)
    Split products and the pack in 2 separate recordsets. :return: [packs, no_packs]
  • write(self, vals)
    We remove from product.product to avoid error.
REPOSITORY
REPOSITORYOCA/product-pack
GIT
GIThttps://github.com/OCA/product-pack.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/product-pack/tree/12.0/product_pack
VERSION
VERSION 1.0.2
CATEGORY
CATEGORYProduct
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSTecnativa, Odoo Community Association (OCA), ADHOC SA, NaN·tic
MAINTAINERS
MAINTAINERSTecnativa, Odoo Community Association (OCA), ADHOC SA, NaN·tic
COMMITTERS
COMMITTERSPedro M. Baeza, GitHub, OCA Transbot, Nicolás Mac Rouillon, oca-travis, Weblate, OCA-git-bot, ernesto, Miguel Poyatos
WEBSITE
WEBSITEhttps://github.com/OCA/product-pack
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:29:24
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - product
    - base
    - decimal_precision
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - uom
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (5)
XML IDNameModelTypeStatus
nan_product_pack_form product.product.pack.form product.product group Inherits product.product_normal_form_view
product_pack_line_form product.pack.line.form product.pack.line form New
product_pack_line_tree product.pack.line.tree product.pack.line tree New
product_template_form_view product.template.pack.form product.template div Inherits product.product_template_form_view
product_template_only_form_view product.template.pack.form product.template page Inherits product.product_template_only_form_view
Models touched (3)

New fields (3)
  • parent_product_id Many2one → product.product
    index=True ondelete='cascade' required=True args: 'product.product', 'Parent Product'
  • product_id Many2one → product.product
    index=True ondelete='cascade' required=True args: 'product.product', 'Product'
  • quantity Float
    default=1.0 digits=dp.get_precision('Product UoS') required=True
Public methods (1)
  • get_price(self)
    @api.multi

New fields (2)
  • pack_line_ids One2many → product.pack.line
    help='Products that are part of this pack.' args: 'product.pack.line', 'parent_product_id', 'Pack Products'
  • used_in_pack_line_ids One2many → product.pack.line
    help='Packs where product is used.' args: 'product.pack.line', 'product_id', 'Found in packs'
Public methods (4)
  • get_pack_lines(self)
    @api.multi
    Returns the content (lines) of the packs. By default, return all the pack_line_ids, but that function can be overloaded to introduce filtering function by date, etc...
  • onchange_pack_type(self)
    @api.onchange('pack_type', 'pack_component_price')
  • price_compute(self, price_type, uom=False, currency=False, company=False)
    @api.multi
  • split_pack_products(self)
    @api.multi
    Split products and the pack in 2 separate recordsets. :return: [packs, no_packs]

New fields (6)
  • pack_component_price Selection
    help="On sale orders or purchase orders:\n* Detailed per component: Detail lines with prices.\n* Totalized in main product: Detail lines merging lines prices on pack (don't show component prices).\n* Ignored: Use product pack price (ignore detail line prices)." args: [('detailed', 'Detailed per component'), ('totalized', 'Totalized in main product'), ('ignored', 'Ignored')], 'Pack component price'
  • pack_line_ids One2many
    related='product_variant_ids.pack_line_ids'
  • pack_modifiable Boolean
    help='If you check this field yo will be able to edit sale/purchase order line relate to its component'
  • pack_ok Boolean
    help='Is a Product Pack?' args: 'Is Pack?'
  • pack_type Selection
    help='On sale orders or purchase orders:\n* Detailed: Display components individually in the sale order.\n* Non Detailed: Do not display components individually in the sale order.' args: [('detailed', 'Detailed'), ('non_detailed', 'Non Detailed')], 'Pack Type'
  • used_in_pack_line_ids One2many
    readonly=True related='product_variant_ids.used_in_pack_line_ids'
Public methods (2)
  • onchange_pack_type(self)
    @api.onchange('pack_type', 'pack_component_price')
  • write(self, vals)
    @api.multi
    We remove from product.product to avoid error.