feat: Add account asset to migration list and introduce a new script for cloning BOMs, product category COA, and POS payment method configurations.
This commit is contained in:
parent
861ba677e4
commit
cbbc43e6ec
118
clone_extra_data.py
Normal file
118
clone_extra_data.py
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
def clone_extra_data(env):
|
||||||
|
source_name = 'Kedai Kipas 58 Rungkut'
|
||||||
|
target_name = 'Kedai Kipas 58 Tenggilis'
|
||||||
|
|
||||||
|
source_company = env['res.company'].search([('name', 'ilike', source_name)], limit=1)
|
||||||
|
target_company = env['res.company'].search([('name', 'ilike', target_name)], limit=1)
|
||||||
|
|
||||||
|
if not source_company or not target_company:
|
||||||
|
print(f"Could not find one or both companies: '{source_name}', '{target_name}'")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"\n--- 1. Cloning Product BOMs ---")
|
||||||
|
boms = env['mrp.bom'].search([('company_id', '=', source_company.id)])
|
||||||
|
count_bom = 0
|
||||||
|
for bom in boms:
|
||||||
|
# Check if already exists in target (same product template & name-ish?)
|
||||||
|
# Let's match by product_tmpl_id
|
||||||
|
existing = env['mrp.bom'].search([
|
||||||
|
('product_tmpl_id', '=', bom.product_tmpl_id.id),
|
||||||
|
('company_id', '=', target_company.id)
|
||||||
|
], limit=1)
|
||||||
|
|
||||||
|
if existing:
|
||||||
|
print(f" -> BOM for '{bom.product_tmpl_id.name}' already exists in {target_company.name}. Skipping.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
with env.cr.savepoint():
|
||||||
|
new_bom = bom.copy({'company_id': target_company.id})
|
||||||
|
print(f" -> Cloned BOM for '{bom.product_tmpl_id.name}'")
|
||||||
|
count_bom += 1
|
||||||
|
except Exception as e:
|
||||||
|
print(f" -> Failed to clone BOM '{bom.product_tmpl_id.name}': {e}")
|
||||||
|
|
||||||
|
print(f"\n--- 2. Copying Product Category COA Setup ---")
|
||||||
|
categories = env['product.category'].with_company(source_company.id).search([])
|
||||||
|
count_categ = 0
|
||||||
|
for categ in categories:
|
||||||
|
# We need to read properties from source, and write to target
|
||||||
|
income_acc = categ.property_account_income_categ_id
|
||||||
|
expense_acc = categ.property_account_expense_categ_id
|
||||||
|
stock_val_acc = getattr(categ, 'property_stock_valuation_account_id', False)
|
||||||
|
stock_in_acc = getattr(categ, 'property_stock_account_input_categ_id', False)
|
||||||
|
stock_out_acc = getattr(categ, 'property_stock_account_output_categ_id', False)
|
||||||
|
stock_journal = getattr(categ, 'property_stock_journal', False)
|
||||||
|
|
||||||
|
vals = {}
|
||||||
|
if income_acc: vals['property_account_income_categ_id'] = income_acc.id
|
||||||
|
if expense_acc: vals['property_account_expense_categ_id'] = expense_acc.id
|
||||||
|
if stock_val_acc: vals['property_stock_valuation_account_id'] = stock_val_acc.id
|
||||||
|
if stock_in_acc: vals['property_stock_account_input_categ_id'] = stock_in_acc.id
|
||||||
|
if stock_out_acc: vals['property_stock_account_output_categ_id'] = stock_out_acc.id
|
||||||
|
|
||||||
|
# for journal it is tricky - the source journal might belong to Rungkut!
|
||||||
|
if stock_journal:
|
||||||
|
# check if it is explicitly rungkut's journal
|
||||||
|
if stock_journal.company_id.id == source_company.id:
|
||||||
|
# find equivalent for tenggilis
|
||||||
|
t_journal = env['account.journal'].search([
|
||||||
|
('name', '=', stock_journal.name),
|
||||||
|
('company_id', '=', target_company.id)
|
||||||
|
], limit=1)
|
||||||
|
if t_journal: vals['property_stock_journal'] = t_journal.id
|
||||||
|
else:
|
||||||
|
vals['property_stock_journal'] = stock_journal.id
|
||||||
|
|
||||||
|
if vals:
|
||||||
|
# switch to target company context so properties are saved for target
|
||||||
|
categ.with_company(target_company.id).write(vals)
|
||||||
|
count_categ += 1
|
||||||
|
print(f" -> Copied Accounting properties for {count_categ} product categories.")
|
||||||
|
|
||||||
|
|
||||||
|
print(f"\n--- 3. Fixing POS Payment Methods COA and Journals ---")
|
||||||
|
methods = env['pos.payment.method'].search([('company_id', '=', target_company.id)])
|
||||||
|
count_pm = 0
|
||||||
|
for method in methods:
|
||||||
|
# get original
|
||||||
|
orig_method = env['pos.payment.method'].search([
|
||||||
|
('name', '=', method.name),
|
||||||
|
('company_id', '=', source_company.id)
|
||||||
|
], limit=1)
|
||||||
|
|
||||||
|
if not orig_method:
|
||||||
|
continue
|
||||||
|
|
||||||
|
vals = {}
|
||||||
|
# Journals
|
||||||
|
orig_journal = orig_method.journal_id
|
||||||
|
if orig_journal:
|
||||||
|
if orig_journal.company_id.id == source_company.id:
|
||||||
|
t_j = env['account.journal'].search([
|
||||||
|
('name', '=', orig_journal.name),
|
||||||
|
('company_id', '=', target_company.id)
|
||||||
|
], limit=1)
|
||||||
|
vals['journal_id'] = t_j.id if t_j else False
|
||||||
|
else:
|
||||||
|
vals['journal_id'] = orig_journal.id
|
||||||
|
|
||||||
|
# Custom Accounting fields (like income/discount accounts if they exist)
|
||||||
|
if hasattr(orig_method, 'income_account_id') and orig_method.income_account_id:
|
||||||
|
vals['income_account_id'] = orig_method.income_account_id.id
|
||||||
|
if hasattr(orig_method, 'discount_account_id') and orig_method.discount_account_id:
|
||||||
|
vals['discount_account_id'] = orig_method.discount_account_id.id
|
||||||
|
|
||||||
|
if vals:
|
||||||
|
method.write(vals)
|
||||||
|
count_pm += 1
|
||||||
|
print(f" -> Re-linked Journal & Accounts for Payment Method '{method.name}'")
|
||||||
|
|
||||||
|
print(f"\nCommitting changes...")
|
||||||
|
env.cr.commit()
|
||||||
|
print("Done!")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
clone_extra_data(env)
|
||||||
@ -25,6 +25,8 @@ def migrate_to_branch(env):
|
|||||||
'pos_order_line',
|
'pos_order_line',
|
||||||
'pos_payment',
|
'pos_payment',
|
||||||
'pos_payment_method',
|
'pos_payment_method',
|
||||||
|
# Accounting / Assets
|
||||||
|
'account_asset',
|
||||||
|
|
||||||
# Shop Floor / Inventory
|
# Shop Floor / Inventory
|
||||||
'stock_warehouse',
|
'stock_warehouse',
|
||||||
|
|||||||
@ -25,7 +25,7 @@ def migrate_to_branch(env):
|
|||||||
'stock_warehouse', 'stock_location', 'stock_picking_type', 'stock_picking', 'stock_move', 'stock_move_line',
|
'stock_warehouse', 'stock_location', 'stock_picking_type', 'stock_picking', 'stock_move', 'stock_move_line',
|
||||||
'stock_quant', 'stock_valuation_layer', 'stock_scrap', 'stock_inventory', 'stock_rule', 'stock_route', 'stock_putaway_rule',
|
'stock_quant', 'stock_valuation_layer', 'stock_scrap', 'stock_inventory', 'stock_rule', 'stock_route', 'stock_putaway_rule',
|
||||||
'mrp_production', 'mrp_workorder', 'mrp_workcenter', 'mrp_routing_workcenter', 'mrp_bom', 'mrp_bom_line', 'mrp_unbuild', 'mrp_consumption_warning',
|
'mrp_production', 'mrp_workorder', 'mrp_workcenter', 'mrp_routing_workcenter', 'mrp_bom', 'mrp_bom_line', 'mrp_unbuild', 'mrp_consumption_warning',
|
||||||
'account_journal', 'account_move', 'account_move_line', 'account_payment', 'account_bank_statement', 'account_bank_statement_line', 'account_partial_reconcile', 'account_payment_term',
|
'account_journal', 'account_move', 'account_move_line', 'account_payment', 'account_bank_statement', 'account_bank_statement_line', 'account_partial_reconcile', 'account_payment_term', 'account_asset',
|
||||||
'sale_order', 'sale_order_line', 'purchase_order', 'purchase_order_line', 'purchase_requisition', 'purchase_requisition_line',
|
'sale_order', 'sale_order_line', 'purchase_order', 'purchase_order_line', 'purchase_requisition', 'purchase_requisition_line',
|
||||||
'hr_employee', 'hr_contract', 'hr_attendance', 'hr_payslip', 'hr_expense', 'hr_expense_sheet',
|
'hr_employee', 'hr_contract', 'hr_attendance', 'hr_payslip', 'hr_expense', 'hr_expense_sheet',
|
||||||
'product_pricelist', 'ir_sequence'
|
'product_pricelist', 'ir_sequence'
|
||||||
@ -346,6 +346,112 @@ def fix_all_mismatched_journals(env):
|
|||||||
env.cr.commit()
|
env.cr.commit()
|
||||||
|
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 7. CLONE EXTRA DATA (BOM, CATEGORY COA, PM ACCOUNTS)
|
||||||
|
# ==========================================
|
||||||
|
def clone_extra_data(env):
|
||||||
|
print("\n==========================================")
|
||||||
|
print("7. CLONING BOMs, CATEGORY COA & PM ACCOUNTS")
|
||||||
|
print("==========================================")
|
||||||
|
source_name = 'Kedai Kipas 58 Rungkut'
|
||||||
|
target_name = 'Kedai Kipas 58 Tenggilis'
|
||||||
|
|
||||||
|
source_company = env['res.company'].search([('name', 'ilike', source_name)], limit=1)
|
||||||
|
target_company = env['res.company'].search([('name', 'ilike', target_name)], limit=1)
|
||||||
|
|
||||||
|
if not source_company or not target_company:
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"--- 1. Cloning Product BOMs ---")
|
||||||
|
boms = env['mrp.bom'].search([('company_id', '=', source_company.id)])
|
||||||
|
count_bom = 0
|
||||||
|
for bom in boms:
|
||||||
|
existing = env['mrp.bom'].search([
|
||||||
|
('product_tmpl_id', '=', bom.product_tmpl_id.id),
|
||||||
|
('company_id', '=', target_company.id)
|
||||||
|
], limit=1)
|
||||||
|
|
||||||
|
if existing:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
with env.cr.savepoint():
|
||||||
|
bom.copy({'company_id': target_company.id})
|
||||||
|
count_bom += 1
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
print(f" -> Cloned {count_bom} BOMs")
|
||||||
|
|
||||||
|
print(f"\n--- 2. Copying Product Category COA Setup ---")
|
||||||
|
categories = env['product.category'].with_company(source_company.id).search([])
|
||||||
|
count_categ = 0
|
||||||
|
for categ in categories:
|
||||||
|
income_acc = categ.property_account_income_categ_id
|
||||||
|
expense_acc = categ.property_account_expense_categ_id
|
||||||
|
stock_val_acc = getattr(categ, 'property_stock_valuation_account_id', False)
|
||||||
|
stock_in_acc = getattr(categ, 'property_stock_account_input_categ_id', False)
|
||||||
|
stock_out_acc = getattr(categ, 'property_stock_account_output_categ_id', False)
|
||||||
|
stock_journal = getattr(categ, 'property_stock_journal', False)
|
||||||
|
|
||||||
|
vals = {}
|
||||||
|
if income_acc: vals['property_account_income_categ_id'] = income_acc.id
|
||||||
|
if expense_acc: vals['property_account_expense_categ_id'] = expense_acc.id
|
||||||
|
if stock_val_acc: vals['property_stock_valuation_account_id'] = stock_val_acc.id
|
||||||
|
if stock_in_acc: vals['property_stock_account_input_categ_id'] = stock_in_acc.id
|
||||||
|
if stock_out_acc: vals['property_stock_account_output_categ_id'] = stock_out_acc.id
|
||||||
|
|
||||||
|
if stock_journal:
|
||||||
|
if stock_journal.company_id.id == source_company.id:
|
||||||
|
t_journal = env['account.journal'].search([
|
||||||
|
('name', '=', stock_journal.name),
|
||||||
|
('company_id', '=', target_company.id)
|
||||||
|
], limit=1)
|
||||||
|
if t_journal: vals['property_stock_journal'] = t_journal.id
|
||||||
|
else:
|
||||||
|
vals['property_stock_journal'] = stock_journal.id
|
||||||
|
|
||||||
|
if vals:
|
||||||
|
categ.with_company(target_company.id).write(vals)
|
||||||
|
count_categ += 1
|
||||||
|
print(f" -> Copied Accounting properties for {count_categ} product categories.")
|
||||||
|
|
||||||
|
print(f"\n--- 3. Fixing POS Payment Methods COA and Journals ---")
|
||||||
|
methods = env['pos.payment.method'].search([('company_id', '=', target_company.id)])
|
||||||
|
count_pm = 0
|
||||||
|
for method in methods:
|
||||||
|
orig_method = env['pos.payment.method'].search([
|
||||||
|
('name', '=', method.name),
|
||||||
|
('company_id', '=', source_company.id)
|
||||||
|
], limit=1)
|
||||||
|
|
||||||
|
if not orig_method:
|
||||||
|
continue
|
||||||
|
|
||||||
|
vals = {}
|
||||||
|
orig_journal = orig_method.journal_id
|
||||||
|
if orig_journal:
|
||||||
|
if orig_journal.company_id.id == source_company.id:
|
||||||
|
t_j = env['account.journal'].search([
|
||||||
|
('name', '=', orig_journal.name),
|
||||||
|
('company_id', '=', target_company.id)
|
||||||
|
], limit=1)
|
||||||
|
vals['journal_id'] = t_j.id if t_j else False
|
||||||
|
else:
|
||||||
|
vals['journal_id'] = orig_journal.id
|
||||||
|
|
||||||
|
if hasattr(orig_method, 'income_account_id') and orig_method.income_account_id:
|
||||||
|
vals['income_account_id'] = orig_method.income_account_id.id
|
||||||
|
if hasattr(orig_method, 'discount_account_id') and orig_method.discount_account_id:
|
||||||
|
vals['discount_account_id'] = orig_method.discount_account_id.id
|
||||||
|
|
||||||
|
if vals:
|
||||||
|
method.write(vals)
|
||||||
|
count_pm += 1
|
||||||
|
print(f" -> Re-linked Journal & Accounts for {count_pm} Payment Methods")
|
||||||
|
|
||||||
|
env.cr.commit()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
try:
|
||||||
print("Starting full migration and cloning process...")
|
print("Starting full migration and cloning process...")
|
||||||
@ -355,6 +461,7 @@ if __name__ == '__main__':
|
|||||||
clone_rounding_and_pricelist(env)
|
clone_rounding_and_pricelist(env)
|
||||||
fix_company_journals(env)
|
fix_company_journals(env)
|
||||||
fix_all_mismatched_journals(env)
|
fix_all_mismatched_journals(env)
|
||||||
|
clone_extra_data(env)
|
||||||
print("\n*** ALL MIGRATIONS COMPLETED SUCCESSFULLY! ***")
|
print("\n*** ALL MIGRATIONS COMPLETED SUCCESSFULLY! ***")
|
||||||
except NameError:
|
except NameError:
|
||||||
print("Please run this script using Odoo shell:")
|
print("Please run this script using Odoo shell:")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user