86 lines
5.2 KiB
Markdown
86 lines
5.2 KiB
Markdown
# Multi-Company Product, Category & BOM Sync
|
|
|
|
This Odoo 19 module automatically shares and synchronizes company-dependent product, product category, and Bill of Materials (BOM / recipe) settings from a parent company to all active branch (descendant) companies recursively.
|
|
|
|
## Overview
|
|
|
|
In Odoo, standard product templates (`product.template`) and product categories (`product.category`) are globally accessible if their `company_id` is set to `False` (empty). However, accounting, taxes, location routing, and manufacturing recipes remain company-dependent:
|
|
**Accounting Accounts**: Stored as `jsonb` fields on the model in Odoo 19, mapping company IDs directly to account record IDs.
|
|
**Taxes & Routes**: Many-to-many relationships where each company must map its own specific records.
|
|
**Bill of Materials (BOM)**: Explicitly linked to a company, requiring child branches to duplicate manufacturing structures if they wish to produce locally.
|
|
|
|
This module automates the propagation of these settings and structures down the company hierarchy, minimizing manual configuration errors across multiple branch companies.
|
|
|
|
## Features
|
|
|
|
### 🏢 Recursive Multi-Company Synchronization
|
|
Propagates all settings down the active company's branch hierarchy recursively using Odoo's fast `'child_of'` operator.
|
|
|
|
### 🧮 Product Category Sync (`product.category`)
|
|
Synchronizes the following fields from the parent category to branch categories:
|
|
**Inventory Valuation**: Periodic or Automated (`property_valuation`)
|
|
**Costing Method**: Standard, Average (AVCO), or FIFO (`property_cost_method`)
|
|
**Income Account** (`property_account_income_categ_id`)
|
|
**Expense Account** (`property_account_expense_categ_id`)
|
|
**Price Difference Account** (`property_price_difference_account_id`)
|
|
**Stock Production Cost Account** (`property_stock_account_production_cost_id`)
|
|
**Stock Valuation Account** (`property_stock_valuation_account_id`)
|
|
**Note**: `account_stock_variation_id` (Stock Variation Account) in Odoo 19 is a global field (`company_dependent=False`) and is shared automatically without additional sync code.
|
|
**Valuation Journal Excluded**: The Stock Journal (`property_stock_journal`) is completely excluded from the sync to remain branch-company specific.
|
|
|
|
### 📦 Product Template Sync (`product.template`)
|
|
Synchronizes the following fields from the parent product template to branch templates:
|
|
**Income Account** (`property_account_income_id`)
|
|
**Expense Account** (`property_account_expense_id`)
|
|
**Price Difference Account** (`property_price_difference_account_id`)
|
|
**Stock Inventory Location** (`property_stock_inventory`)
|
|
**Stock Production Location** (`property_stock_production`)
|
|
**Customer Taxes** (`taxes_id`) & **Vendor Taxes** (`supplier_taxes_id`)
|
|
**Logistics Routes** (`route_ids`)
|
|
**Note**: Many-to-Many taxes and routes updates are performed safely to prevent standard Odoo writes from clearing the mappings of other unrelated branch companies.
|
|
**Cost Price Excluded**: Cost price (`standard_price`) is excluded from synchronization to allow branch-specific costing.
|
|
|
|
### 🔨 Bill of Materials (BOM) Sync (`mrp.bom`)
|
|
Synchronizes manufacturing recipes and component lines recursively:
|
|
**Recipe Structures**: Replicates `mrp.bom` records and their ingredient lines (`mrp.bom.line`) to branch companies.
|
|
**Parent Tracking**: Automatically maps and tracks branch records to their parent via a custom field (`parent_bom_id`) complete with cascade deletion.
|
|
**Hierarchical Company Matching**: Implements custom compatibility matching that respects Odoo's multi-company visibility. BOMs are replicated if the main product template and all ingredient component products are either global or belong to a parent/ancestor company of the branch.
|
|
|
|
### 🔄 Intelligent Branch Counterpart Matching
|
|
When mapping a parent company record to a child company:
|
|
**Accounts**: Matches by account `code`.
|
|
**Taxes**: Matches by tax `name`, `type_tax_use`, `amount`, and `amount_type`.
|
|
**Routes**: Matches by route `name`.
|
|
**Locations**: Matches by `complete_name` first, then by `name`.
|
|
**Universal Fallback**: If no specific branch-company counterpart exists, the sync falls back to preserving the parent record value for the branch.
|
|
|
|
## Installation
|
|
|
|
1. Copy the `multicompany_product_sync` folder to your custom addons directory.
|
|
2. Restart your Odoo server.
|
|
3. Activate the developer mode in Odoo.
|
|
4. Go to **Apps** -> **Update Apps List**.
|
|
5. Search for `Multi-Company Product & Category Settings Sync` and click **Activate**.
|
|
|
|
## Technical Details
|
|
|
|
### Infinite Loop Prevention
|
|
All synchronization logic utilizes context variables (e.g., `skip_company_dependent_sync=True`) when executing writes on branch companies, ensuring that child company updates do not trigger redundant and infinite synchronization loops.
|
|
|
|
### Context-Independent Parent Matching
|
|
To ensure correct execution inside background crons, UI switches, and CLI shell scripts, the parent/source company is derived dynamically from each record's own `company_id` field instead of defaulting to `self.env.company`.
|
|
|
|
### Directory Structure
|
|
```
|
|
multicompany_product_sync/
|
|
├── __init__.py
|
|
├── __manifest__.py
|
|
├── README.md
|
|
├── .gitignore
|
|
└── models/
|
|
├── __init__.py
|
|
├── product_category.py
|
|
├── product_template.py
|
|
└── mrp_bom.py
|
|
```
|