Files
Odoo-Modules/fusion_plating/fusion_plating_configurator/__init__.py

129 lines
4.5 KiB
Python

# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
# Part of the Fusion Plating product family.
from . import controllers
from . import models
from . import wizard
from . import tests
def _backfill_currency(env):
"""Fill missing currency_id on existing money-holding records.
Older demo data and manually-created rows were persisted before the
`required=True` was added, so some records sit with currency_id=NULL
and Monetary fields render without a $ symbol. This runs on module
install/upgrade and pins them to the company's currency.
"""
company_currency = env.company.currency_id.id
if not company_currency:
return
for model_name in (
'fp.pricing.rule',
'fp.quote.configurator',
):
Model = env.get(model_name)
if Model is None:
continue
Model.search([('currency_id', '=', False)]).write(
{'currency_id': company_currency}
)
def _backfill_cloned_process_names(env):
"""Append " — <part_number> Rev <revision>" to every existing part-
cloned process ROOT whose name doesn't already carry the suffix.
Feedback on 2026-04-23: the Process tab on the part form was
showing a bare template name ("General Processing"), so users
couldn't tell at a glance that the clone belonged to THIS part.
The clone logic now adds the suffix automatically; this backfill
brings older clones up to the same format without forcing
users to re-compose (which would wipe their edits).
Idempotent: checks for a literal "" separator before rewriting.
"""
Node = env['fusion.plating.process.node']
roots = Node.search([
('node_type', '=', 'recipe'),
('part_catalog_id', '!=', False),
('parent_id', '=', False),
])
renamed = 0
for root in roots:
part = root.part_catalog_id
if not part:
continue
if '' in (root.name or ''):
continue # Already has a suffix — leave alone.
suffix_bits = []
if part.part_number:
suffix_bits.append(part.part_number)
if part.revision:
# `revision` sometimes already carries a "Rev " prefix
# (e.g. "Rev 2") — don't double up.
rev = part.revision.strip()
if not rev.lower().startswith('rev'):
rev = 'Rev %s' % rev
suffix_bits.append(rev)
if not suffix_bits:
continue
root.name = '%s%s' % (root.name or '', ' '.join(suffix_bits))
renamed += 1
def _backfill_part_material_id(env):
"""Pin existing parts AND quote configurators to a row in the
shared material library.
Pre-Sub-12d, both models only had a `substrate_material` Selection.
This sets `material_id` on every record that doesn't yet have one,
matching by substrate_material → seed material XML id. Idempotent.
"""
Part = env['fp.part.catalog']
Material = env['fp.part.material']
if Part is None or Material is None:
return
# Map legacy Selection key → seed XML id (the generic per-category entry).
xmlid_by_key = {
'aluminium': 'fusion_plating_configurator.fp_material_aluminium',
'steel': 'fusion_plating_configurator.fp_material_steel',
'stainless': 'fusion_plating_configurator.fp_material_stainless',
'copper': 'fusion_plating_configurator.fp_material_copper',
'titanium': 'fusion_plating_configurator.fp_material_titanium',
'other': 'fusion_plating_configurator.fp_material_other',
}
cache = {}
for key, xmlid in xmlid_by_key.items():
rec = env.ref(xmlid, raise_if_not_found=False)
if rec:
cache[key] = rec.id
if not cache:
return
# Parts
for part in Part.search([('material_id', '=', False)]):
mid = cache.get(part.substrate_material)
if mid:
part.material_id = mid
# Quote configurators (same Selection key → same library)
Quote = env['fp.quote.configurator']
if Quote is not None:
for q in Quote.search([('material_id', '=', False)]):
mid = cache.get(q.substrate_material)
if mid:
q.material_id = mid
def post_init_hook(env):
_backfill_currency(env)
_backfill_cloned_process_names(env)
_backfill_part_material_id(env)
def post_upgrade_hook(env):
_backfill_currency(env)
_backfill_cloned_process_names(env)
_backfill_part_material_id(env)