Attached products in sales

sale_attached_product
REPOSITORY
REPOSITORYOCA/sale-workflow
GIT
GIThttps://github.com/OCA/sale-workflow.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/sale-workflow/tree/17.0/sale_attached_product
VERSION
VERSION 1.0.0
CATEGORY
CATEGORYSale
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSTecnativa, Odoo Community Association (OCA)
MAINTAINERS
MAINTAINERSTecnativa, Odoo Community Association (OCA)
COMMITTERS
COMMITTERSRuchir Shukla, Weblate, OCA-git-bot, oca-ci
WEBSITE
WEBSITEhttps://github.com/OCA/sale-workflow
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 19:20:05
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - sale
    - sales_team
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - account_payment
    - account
    - onboarding
    - product
    - uom
    - analytic
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - digest
    - resource
    - payment
    - utm
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION
This module allows to define a set of products which will be added
automatically to the sales order whenever that product is present on it.

Code Analysis

Views touched (1)
XML IDNameModelTypeStatus
product_template_form_view product.template xpath Inherits product.product_template_form_view
Models touched (4)

New fields (1)
  • attached_product_ids Many2many → product.product
    comodel_name='product.product' help="Similar to optional products, although they're added automatically to thesale order and optionally removed when the main product goes away." relation='product_attached_rel' string='Attached Products'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • recompute_attached_products(self)
    Recurrent method for recomputing attached lines. Always done in these three steps: 1. A cleanup of orphaned attached lines or attached lines that doesn't match their parent attached products anymore. 2. Creating new attached lines from lines which don't have them. 3. Updating existing attached lines. Mainly for quantity
  • write(self, vals)

New fields (3)
  • attached_from_line_id Many2one → sale.order.line
    comodel_name='sale.order.line'
  • attached_line_ids One2many → sale.order.line
    comodel_name='sale.order.line' inverse_name='attached_from_line_id'
  • is_attached_line Boolean
    help='Flag products that are attached to their main counterpart'
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
  • write(self, vals)
REPOSITORY
REPOSITORYOCA/sale-workflow
GIT
GIThttps://github.com/OCA/sale-workflow.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/sale-workflow/tree/16.0/sale_attached_product
VERSION
VERSION 1.0.0
CATEGORY
CATEGORYSale
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSTecnativa, Odoo Community Association (OCA)
MAINTAINERS
MAINTAINERSTecnativa, Odoo Community Association (OCA)
COMMITTERS
COMMITTERSWeblate, OCA-git-bot, oca-ci, Christopher Ormaza
WEBSITE
WEBSITEhttps://github.com/OCA/sale-workflow
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:53:45
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - sale
    - sales_team
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - account_payment
    - account
    - product
    - uom
    - analytic
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - digest
    - resource
    - payment
    - utm
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (1)
XML IDNameModelTypeStatus
product_template_form_view product.template xpath Inherits product.product_template_form_view
Models touched (4)

New fields (1)
  • attached_product_ids Many2many → product.product
    comodel_name='product.product' help="Similar to optional products, although they're added automatically to thesale order and optionally removed when the main product goes away." relation='product_attached_rel' string='Attached Products'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • recompute_attached_products(self)
    Recurrent method for recomputing attached lines. Always done in these three steps: 1. A cleanup of orphaned attached lines or attached lines that doesn't match their parent attached products anymore. 2. Creating new attached lines from lines which don't have them. 3. Updating existing attached lines. Mainly for quantity
  • write(self, vals)

New fields (3)
  • attached_from_line_id Many2one → sale.order.line
    comodel_name='sale.order.line'
  • attached_line_ids One2many → sale.order.line
    comodel_name='sale.order.line' inverse_name='attached_from_line_id'
  • is_attached_line Boolean
    help='Flag products that are attached to their main counterpart'
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
  • write(self, vals)
REPOSITORY
REPOSITORYOCA/sale-workflow
GIT
GIThttps://github.com/OCA/sale-workflow.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/sale-workflow/tree/15.0/sale_attached_product
VERSION
VERSION 1.0.0
CATEGORY
CATEGORYSale
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSTecnativa, Odoo Community Association (OCA)
MAINTAINERS
MAINTAINERSTecnativa, Odoo Community Association (OCA)
COMMITTERS
COMMITTERSWeblate, OCA-git-bot, oca-ci, Luis Ernesto García Medina
WEBSITE
WEBSITEhttps://github.com/OCA/sale-workflow
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:46:33
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - sale
    - sales_team
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - payment
    - account
    - product
    - uom
    - analytic
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - digest
    - resource
    - utm
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (1)
XML IDNameModelTypeStatus
product_template_form_view product.template xpath Inherits product.product_template_form_view
Models touched (4)

New fields (1)
  • attached_product_ids Many2many → product.product
    comodel_name='product.product' help="Similar to optional products, although they're added automatically to thesale order and optionally removed when the main product goes away." relation='product_attached_rel' string='Attached Products'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • recompute_attached_products(self)
    Recurrent method for recomputing attached lines. Always done in these three steps: 1. A cleanup of orphaned attached lines or attached lines that doesn't match their parent attached products anymore. 2. Creating new attached lines from lines which don't have them. 3. Updating existing attached lines. Mainly for quantity
  • write(self, vals)

New fields (3)
  • attached_from_line_id Many2one → sale.order.line
    comodel_name='sale.order.line'
  • attached_line_ids One2many → sale.order.line
    comodel_name='sale.order.line' inverse_name='attached_from_line_id'
  • is_attached_line Boolean
    help='Flag products that are attached to their main counterpart'
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
  • write(self, vals)
REPOSITORY
REPOSITORYOCA/sale-workflow
GIT
GIThttps://github.com/OCA/sale-workflow.git
GIT FOLDER
GIT FOLDERhttps://github.com/OCA/sale-workflow/tree/13.0/sale_attached_product
VERSION
VERSION 1.0.0
CATEGORY
CATEGORYSale
LICENSE
LICENSEAGPL-3
APPLICATION
APPLICATIONNo
AUTO-INSTALLABLE
AUTO-INSTALLABLENo
AUTHORS
AUTHORSTecnativa, Odoo Community Association (OCA)
MAINTAINERS
MAINTAINERSTecnativa, Odoo Community Association (OCA)
COMMITTERS
COMMITTERSdavid, OCA-git-bot, oca-ci
WEBSITE
WEBSITEhttps://github.com/OCA/sale-workflow
LAST TRACKING UPDATE
LAST TRACKING UPDATE2026-07-06 00:34:12
ODOO DEPENDENCIES
ODOO DEPENDENCIES odoo/odoo:
    - sale
    - sales_team
    - base
    - mail
    - base_setup
    - web
    - bus
    - web_tour
    - payment
    - account
    - product
    - uom
    - analytic
    - portal
    - web_editor
    - http_routing
    - auth_signup
    - digest
    - resource
    - utm
PYTHON DEPENDENCIES
PYTHON DEPENDENCIES Not have
SYSTEM DEPENDENCIES
SYSTEM DEPENDENCIES Not have
DESCRIPTION
DESCRIPTION

Code Analysis

Views touched (1)
XML IDNameModelTypeStatus
product_template_form_view product.template xpath Inherits product.product_template_form_view
Models touched (4)

New fields (1)
  • attached_product_ids Many2many → product.product
    comodel_name='product.product' help="Similar to optional products, although they're added automatically to thesale order and optionally removed when the main product goes away." relation='product_attached_rel' string='Attached Products'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • recompute_attached_products(self)
    Recurrent method for recomputing attached lines. Always done in these three steps: 1. A cleanup of orphaned attached lines or attached lines that doesn't match their parent attached products anymore. 2. Creating new attached lines from lines which don't have them. 3. Updating existing attached lines. Mainly for quantity
  • write(self, vals)

New fields (3)
  • attached_from_line_id Many2one → sale.order.line
    comodel_name='sale.order.line'
  • attached_line_ids One2many → sale.order.line
    comodel_name='sale.order.line' inverse_name='attached_from_line_id'
  • is_attached_line Boolean
    help='Flag products that are attached to their main counterpart'
Public methods (3)
  • create(self, vals_list)
    @api.model_create_multi
  • unlink(self)
  • write(self, vals)