148 lines
6.3 KiB
Python
148 lines
6.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
from odoo import api, fields, models
|
|
|
|
class ProductTemplate(models.Model):
|
|
_inherit = 'product.template'
|
|
|
|
def _get_counterpart_record(self, record, target_company):
|
|
"""Helper to find counterpart record in target company, fallback to parent if not found."""
|
|
if not record:
|
|
return record.browse()
|
|
|
|
has_company_ids = 'company_ids' in record._fields
|
|
has_company_id = 'company_id' in record._fields
|
|
|
|
if has_company_ids and target_company in record.company_ids:
|
|
return record
|
|
if has_company_id and record.company_id and record.company_id.id == target_company.id:
|
|
return record
|
|
if not has_company_ids and not has_company_id:
|
|
return record
|
|
if has_company_id and not record.company_id:
|
|
return record
|
|
|
|
model_name = record._name
|
|
domain = []
|
|
if has_company_ids:
|
|
domain.append(('company_ids', 'in', [target_company.id]))
|
|
else:
|
|
domain.append(('company_id', '=', target_company.id))
|
|
|
|
if model_name == 'account.account':
|
|
domain.append(('code', '=', record.code))
|
|
elif model_name == 'account.journal':
|
|
domain.append(('code', '=', record.code))
|
|
elif model_name == 'stock.location':
|
|
match = self.env['stock.location'].search([
|
|
('company_id', '=', target_company.id),
|
|
('complete_name', '=', record.complete_name)
|
|
], limit=1)
|
|
if match:
|
|
return match
|
|
domain.append(('name', '=', record.name))
|
|
elif model_name == 'account.tax':
|
|
domain.extend([
|
|
('name', '=', record.name),
|
|
('type_tax_use', '=', record.type_tax_use),
|
|
('amount', '=', record.amount),
|
|
('amount_type', '=', record.amount_type)
|
|
])
|
|
elif model_name == 'stock.route':
|
|
domain.append(('name', '=', record.name))
|
|
else:
|
|
if 'name' in record._fields:
|
|
domain.append(('name', '=', record.name))
|
|
else:
|
|
return record
|
|
|
|
match = self.env[model_name].search(domain, limit=1)
|
|
if not match:
|
|
return record
|
|
return match
|
|
|
|
def _sync_to_branch_companies(self, sync_taxes=True, sync_m2o=True):
|
|
"""Replicate product template settings to all active branch companies recursively."""
|
|
if self.env.context.get('skip_company_dependent_sync'):
|
|
return
|
|
|
|
current_company = self.env.company
|
|
branch_companies = self.env['res.company'].search([('id', 'child_of', current_company.id)]) - current_company
|
|
if not branch_companies:
|
|
return
|
|
|
|
for product in self:
|
|
for branch in branch_companies:
|
|
# 1. Sync company-dependent many2one fields (accounts, locations)
|
|
if sync_m2o:
|
|
vals_to_write = {}
|
|
m2o_fields = [
|
|
'property_account_income_id',
|
|
'property_account_expense_id',
|
|
'property_price_difference_account_id',
|
|
'property_stock_inventory',
|
|
'property_stock_production'
|
|
]
|
|
for field in m2o_fields:
|
|
val = product.with_company(current_company)[field]
|
|
if val:
|
|
counterpart = product._get_counterpart_record(val, branch)
|
|
vals_to_write[field] = counterpart.id if counterpart else False
|
|
else:
|
|
vals_to_write[field] = False
|
|
|
|
if vals_to_write:
|
|
product.with_company(branch).with_context(skip_company_dependent_sync=True).write(vals_to_write)
|
|
|
|
# 2. Sync many2many fields (taxes, routes) safely preserving other companies' values
|
|
if sync_taxes:
|
|
m2m_fields = ['taxes_id', 'supplier_taxes_id', 'route_ids']
|
|
for field in m2m_fields:
|
|
all_records = product[field]
|
|
|
|
# Filter active/parent company records
|
|
current_records = all_records.filtered(
|
|
lambda r: 'company_id' in r._fields and r.company_id == current_company
|
|
)
|
|
# Filter target branch company records
|
|
branch_records = all_records.filtered(
|
|
lambda r: 'company_id' in r._fields and r.company_id == branch
|
|
)
|
|
# Filter records belonging to other companies
|
|
other_records = all_records - current_records - branch_records
|
|
|
|
counterparts = self.env[all_records._name]
|
|
for r in current_records:
|
|
match = product._get_counterpart_record(r, branch)
|
|
if match:
|
|
counterparts |= match
|
|
|
|
final_records = other_records | current_records | counterparts
|
|
product.with_context(skip_company_dependent_sync=True).write({
|
|
field: [(6, 0, final_records.ids)]
|
|
})
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals_list):
|
|
products = super().create(vals_list)
|
|
products._sync_to_branch_companies()
|
|
return products
|
|
|
|
def write(self, vals):
|
|
res = super().write(vals)
|
|
|
|
m2o_fields = [
|
|
'property_account_income_id',
|
|
'property_account_expense_id',
|
|
'property_price_difference_account_id',
|
|
'property_stock_inventory',
|
|
'property_stock_production'
|
|
]
|
|
m2m_fields = ['taxes_id', 'supplier_taxes_id', 'route_ids']
|
|
|
|
sync_taxes = any(f in vals for f in m2m_fields)
|
|
sync_m2o = any(f in vals for f in m2o_fields)
|
|
|
|
if sync_taxes or sync_m2o:
|
|
self._sync_to_branch_companies(sync_taxes=sync_taxes, sync_m2o=sync_m2o)
|
|
return res
|