folder rename

This commit is contained in:
gsinghpal
2026-04-16 20:53:53 -04:00
parent 3f3ddcbab4
commit 7c7ef06057
634 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo>
<!-- ===== Coating Configuration List View ===== -->
<record id="view_fp_coating_config_list" model="ir.ui.view">
<field name="name">fp.coating.config.list</field>
<field name="model">fp.coating.config</field>
<field name="arch" type="xml">
<list string="Coating Configurations" decoration-muted="not active">
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="process_type_id"/>
<field name="phosphorus_level"/>
<field name="thickness_min"/>
<field name="thickness_max"/>
<field name="spec_reference"/>
<field name="certification_level"/>
<field name="active" widget="boolean_toggle"/>
</list>
</field>
</record>
<!-- ===== Coating Configuration Form View ===== -->
<record id="view_fp_coating_config_form" model="ir.ui.view">
<field name="name">fp.coating.config.form</field>
<field name="model">fp.coating.config</field>
<field name="arch" type="xml">
<form string="Coating Configuration">
<sheet>
<widget name="web_ribbon" title="Archived" bg_color="text-bg-danger" invisible="active"/>
<div class="oe_title">
<label for="name"/>
<h1><field name="name" placeholder="e.g. EN Mid-Phos AMS 2404"/></h1>
</div>
<group>
<group>
<field name="process_type_id"/>
<field name="recipe_id"/>
<field name="phosphorus_level"/>
<field name="certification_level"/>
<field name="sequence"/>
</group>
<group>
<field name="thickness_min"/>
<field name="thickness_max"/>
<field name="thickness_uom"/>
<field name="spec_reference"/>
</group>
</group>
<notebook>
<page string="Treatments" name="treatments">
<group>
<group string="Pre-Treatments">
<field name="pre_treatment_ids" widget="many2many_tags" nolabel="1"/>
</group>
<group string="Post-Treatments">
<field name="post_treatment_ids" widget="many2many_tags" nolabel="1"/>
</group>
</group>
</page>
<page string="Description" name="description">
<field name="description" placeholder="Detailed description of this coating configuration..."/>
</page>
</notebook>
<group>
<field name="active" widget="boolean_toggle"/>
</group>
</sheet>
</form>
</field>
</record>
<!-- ===== Coating Configuration Search View ===== -->
<record id="view_fp_coating_config_search" model="ir.ui.view">
<field name="name">fp.coating.config.search</field>
<field name="model">fp.coating.config</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="process_type_id"/>
<field name="spec_reference"/>
<separator/>
<filter string="Commercial" name="commercial" domain="[('certification_level','=','commercial')]"/>
<filter string="Mil-Spec" name="mil_spec" domain="[('certification_level','=','mil_spec')]"/>
<filter string="Nadcap" name="nadcap" domain="[('certification_level','=','nadcap')]"/>
<filter string="Nuclear" name="nuclear" domain="[('certification_level','=','nuclear')]"/>
<separator/>
<filter string="Low Phosphorus" name="low_phos" domain="[('phosphorus_level','=','low_phos')]"/>
<filter string="Mid Phosphorus" name="mid_phos" domain="[('phosphorus_level','=','mid_phos')]"/>
<filter string="High Phosphorus" name="high_phos" domain="[('phosphorus_level','=','high_phos')]"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
<group>
<filter string="Process Type" name="group_process_type" context="{'group_by':'process_type_id'}"/>
<filter string="Certification Level" name="group_cert_level" context="{'group_by':'certification_level'}"/>
</group>
</search>
</field>
</record>
<!-- ===== Window Action ===== -->
<record id="action_fp_coating_config" model="ir.actions.act_window">
<field name="name">Coating Configurations</field>
<field name="res_model">fp.coating.config</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_fp_coating_config_search"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No coating configurations defined yet
</p>
<p>
Define coating setups with process type, phosphorus level,
thickness range, spec reference, and required treatments.
</p>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo>
<!-- ===== Window actions (must be defined before menus reference them) ===== -->
<record id="action_fp_customers" model="ir.actions.act_window">
<field name="name">Customers</field>
<field name="res_model">res.partner</field>
<field name="view_mode">list,form,kanban</field>
<field name="domain">[('customer_rank', '>', 0)]</field>
<field name="context">{'default_customer_rank': 1}</field>
</record>
<!-- ===== SALES submenu under Fusion Plating root ===== -->
<menuitem id="menu_fp_sales"
name="Sales"
parent="fusion_plating.menu_fp_root"
sequence="5"
groups="group_fp_estimator,fusion_plating.group_fusion_plating_supervisor"/>
<menuitem id="menu_fp_quotations"
name="Quotations"
parent="menu_fp_sales"
action="action_fp_quotations"
sequence="10"/>
<menuitem id="menu_fp_sale_orders"
name="Sale Orders"
parent="menu_fp_sales"
action="action_fp_sale_orders"
sequence="20"/>
<menuitem id="menu_fp_customers"
name="Customers"
parent="menu_fp_sales"
action="action_fp_customers"
sequence="30"/>
<menuitem id="menu_fp_part_catalog"
name="Part Catalog"
parent="menu_fp_sales"
action="action_fp_part_catalog"
sequence="40"/>
<!-- ===== CONFIGURATOR submenu ===== -->
<menuitem id="menu_fp_configurator"
name="Configurator"
parent="fusion_plating.menu_fp_root"
sequence="8"
groups="group_fp_estimator"/>
<menuitem id="menu_fp_new_quote"
name="New Quote"
parent="menu_fp_configurator"
action="action_fp_quote_configurator"
sequence="10"/>
<menuitem id="menu_fp_coating_configs"
name="Coating Configurations"
parent="menu_fp_configurator"
action="action_fp_coating_config"
sequence="20"/>
<menuitem id="menu_fp_pricing_rules"
name="Pricing Rules"
parent="menu_fp_configurator"
action="action_fp_pricing_rule"
sequence="30"/>
<menuitem id="menu_fp_treatments"
name="Treatments"
parent="menu_fp_configurator"
action="action_fp_treatment"
sequence="40"/>
</odoo>

View File

@@ -0,0 +1,214 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo>
<!-- ===== Part Catalog List View ===== -->
<record id="view_fp_part_catalog_list" model="ir.ui.view">
<field name="name">fp.part.catalog.list</field>
<field name="model">fp.part.catalog</field>
<field name="arch" type="xml">
<list string="Part Catalog" decoration-muted="not active">
<field name="partner_id"/>
<field name="part_number"/>
<field name="revision"/>
<field name="substrate_material"/>
<field name="surface_area"/>
<field name="complexity"/>
<field name="active" widget="boolean_toggle"/>
</list>
</field>
</record>
<!-- ===== Part Catalog Form View ===== -->
<record id="view_fp_part_catalog_form" model="ir.ui.view">
<field name="name">fp.part.catalog.form</field>
<field name="model">fp.part.catalog</field>
<field name="arch" type="xml">
<form string="Part Catalog">
<header>
<button name="action_create_revision"
string="Create New Revision"
type="object"
class="btn-secondary"
icon="fa-code-fork"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button name="action_view_sale_orders"
type="object"
class="oe_stat_button"
icon="fa-file-text-o"
invisible="sale_order_count == 0">
<field name="sale_order_count" widget="statinfo" string="Sale Orders"/>
</button>
<button name="action_view_configurators"
type="object"
class="oe_stat_button"
icon="fa-sliders"
invisible="configurator_count == 0">
<field name="configurator_count" widget="statinfo" string="Quotes"/>
</button>
</div>
<widget name="web_ribbon" title="Archived" bg_color="text-bg-danger" invisible="active"/>
<widget name="web_ribbon" title="Superseded" bg_color="text-bg-warning" invisible="is_latest_revision"/>
<div class="oe_title">
<label for="name"/>
<h1><field name="name" placeholder="e.g. Valve Body Housing"/></h1>
<field name="part_number" placeholder="Customer part number (e.g. VS-R392007E01)"/>
</div>
<group>
<group>
<field name="partner_id"/>
<field name="revision"/>
<field name="revision_number"/>
<field name="substrate_material"/>
<field name="geometry_source"/>
<field name="is_latest_revision" invisible="1"/>
<field name="parent_part_id" invisible="not parent_part_id"/>
</group>
<group>
<label for="surface_area"/>
<div class="d-flex align-items-center gap-2">
<field name="surface_area" class="oe_inline"/>
<button name="action_calculate_surface_area" type="object"
string="Calculate from 3D Model"
class="btn-link" icon="fa-calculator"
invisible="not model_attachment_id"/>
</div>
<field name="surface_area_uom"/>
<field name="masking_area_sqin"/>
<field name="effective_area_sqin" readonly="1"/>
<field name="weight"/>
<field name="material_weight_kg" readonly="1"/>
</group>
</group>
<!-- Auto-extracted geometry from 3D model -->
<group string="3D Model Analysis"
invisible="not volume_mm3 and not bbox_summary_in and hole_count == 0">
<group>
<field name="bbox_summary_in" readonly="1"/>
<field name="volume_mm3" readonly="1"/>
<field name="bbox_length_mm" invisible="1"/>
<field name="bbox_width_mm" invisible="1"/>
<field name="bbox_height_mm" invisible="1"/>
</group>
<group>
<field name="hole_count" readonly="1"/>
<field name="hole_summary" readonly="1" invisible="not hole_summary"/>
<field name="is_manifold" widget="boolean_toggle" readonly="1"/>
</group>
<div class="alert alert-warning mb-0"
colspan="2"
invisible="is_manifold or not model_attachment_id">
<i class="fa fa-exclamation-triangle me-1"/>
<strong>Geometry warning:</strong> 3D model is not watertight (manifold).
This often indicates open shells or invalid surfaces. Review before quoting.
</div>
</group>
<notebook>
<page string="Dimensions &amp; Complexity" name="dimensions">
<group>
<group>
<field name="dimensions_length"/>
<field name="dimensions_width"/>
<field name="dimensions_height"/>
</group>
<group>
<field name="complexity"/>
<field name="masking_zones"/>
<field name="has_blind_holes"/>
<field name="has_recesses"/>
<field name="has_threads"/>
</group>
</group>
<group>
<field name="masking_description" placeholder="e.g. Mask threaded holes, mask bore ID"/>
</group>
</page>
<page string="Attachments" name="attachments">
<group>
<field name="model_attachment_id"/>
<field name="drawing_attachment_ids" widget="fp_pdf_preview_binary"/>
</group>
<div invisible="not model_attachment_id" class="mt-3">
<field name="model_attachment_id" widget="fp_3d_preview" nolabel="1"/>
</div>
</page>
<page string="Revision History" name="revisions"
invisible="not parent_part_id and not revision_ids">
<field name="revision_ids" mode="list">
<list default_order="revision_number desc">
<field name="revision_number" string="Rev #"/>
<field name="revision"/>
<field name="revision_note"/>
<field name="revision_date"/>
<field name="surface_area"/>
<field name="model_attachment_id" string="3D Model"/>
<field name="is_latest_revision" widget="boolean_toggle"/>
</list>
</field>
</page>
<page string="Notes" name="notes">
<field name="notes" placeholder="Additional notes about this part..."/>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<!-- ===== Part Catalog Search View ===== -->
<record id="view_fp_part_catalog_search" model="ir.ui.view">
<field name="name">fp.part.catalog.search</field>
<field name="model">fp.part.catalog</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="part_number"/>
<field name="partner_id"/>
<separator/>
<filter string="Aluminium" name="material_aluminium" domain="[('substrate_material','=','aluminium')]"/>
<filter string="Steel" name="material_steel" domain="[('substrate_material','=','steel')]"/>
<filter string="Stainless Steel" name="material_stainless" domain="[('substrate_material','=','stainless')]"/>
<filter string="Copper" name="material_copper" domain="[('substrate_material','=','copper')]"/>
<filter string="Titanium" name="material_titanium" domain="[('substrate_material','=','titanium')]"/>
<filter string="Other" name="material_other" domain="[('substrate_material','=','other')]"/>
<separator/>
<filter string="Simple" name="complexity_simple" domain="[('complexity','=','simple')]"/>
<filter string="Moderate" name="complexity_moderate" domain="[('complexity','=','moderate')]"/>
<filter string="Complex" name="complexity_complex" domain="[('complexity','=','complex')]"/>
<filter string="Very Complex" name="complexity_very_complex" domain="[('complexity','=','very_complex')]"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
<group>
<filter string="Customer" name="group_partner" context="{'group_by':'partner_id'}"/>
<filter string="Material" name="group_material" context="{'group_by':'substrate_material'}"/>
<filter string="Complexity" name="group_complexity" context="{'group_by':'complexity'}"/>
</group>
</search>
</field>
</record>
<!-- ===== Window Action ===== -->
<record id="action_fp_part_catalog" model="ir.actions.act_window">
<field name="name">Part Catalog</field>
<field name="res_model">fp.part.catalog</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_fp_part_catalog_search"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No parts in the catalog yet
</p>
<p>
Add customer parts with geometry, material, and complexity data
for instant re-quoting on repeat orders.
</p>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo>
<!-- ===== Pricing Rule List View ===== -->
<record id="view_fp_pricing_rule_list" model="ir.ui.view">
<field name="name">fp.pricing.rule.list</field>
<field name="model">fp.pricing.rule</field>
<field name="arch" type="xml">
<list string="Pricing Rules" decoration-muted="not active">
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="coating_config_id"/>
<field name="substrate_material"/>
<field name="certification_level"/>
<field name="pricing_method"/>
<field name="currency_id" column_invisible="1"/>
<field name="base_rate"/>
<field name="minimum_charge"/>
<field name="active" widget="boolean_toggle"/>
</list>
</field>
</record>
<!-- ===== Pricing Rule Form View ===== -->
<record id="view_fp_pricing_rule_form" model="ir.ui.view">
<field name="name">fp.pricing.rule.form</field>
<field name="model">fp.pricing.rule</field>
<field name="arch" type="xml">
<form string="Pricing Rule">
<sheet>
<widget name="web_ribbon" title="Archived" bg_color="text-bg-danger" invisible="active"/>
<div class="oe_title">
<label for="name"/>
<h1><field name="name" placeholder="e.g. EN Mid-Phos Aluminium — Commercial"/></h1>
</div>
<group string="Filters">
<group>
<field name="coating_config_id"/>
<field name="substrate_material"/>
<field name="certification_level"/>
</group>
<group>
<div class="text-muted" colspan="2">
Leave filter fields blank to create a global rule
that matches any configuration.
</div>
</group>
</group>
<group string="Pricing">
<group>
<field name="pricing_method"/>
<field name="currency_id" invisible="1"/>
<field name="base_rate"/>
<field name="thickness_factor"/>
</group>
<group>
<field name="masking_rate_per_zone"/>
<field name="setup_fee"/>
<field name="minimum_charge"/>
<field name="rush_surcharge_percent"/>
</group>
</group>
<notebook>
<page string="Complexity Surcharges" name="surcharges">
<field name="complexity_surcharge_ids">
<list editable="bottom">
<field name="complexity"/>
<field name="surcharge_percent"/>
</list>
</field>
</page>
<page string="Notes" name="notes">
<field name="notes" placeholder="Internal notes about this pricing rule..."/>
</page>
</notebook>
<group>
<field name="sequence"/>
<field name="active" widget="boolean_toggle"/>
</group>
</sheet>
</form>
</field>
</record>
<!-- ===== Pricing Rule Search View ===== -->
<record id="view_fp_pricing_rule_search" model="ir.ui.view">
<field name="name">fp.pricing.rule.search</field>
<field name="model">fp.pricing.rule</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="coating_config_id"/>
<separator/>
<filter string="Per Square Inch" name="per_sqin" domain="[('pricing_method','=','per_sqin')]"/>
<filter string="Per Square Foot" name="per_sqft" domain="[('pricing_method','=','per_sqft')]"/>
<filter string="Per Piece" name="per_piece" domain="[('pricing_method','=','per_piece')]"/>
<filter string="Flat Rate" name="flat_rate" domain="[('pricing_method','=','flat_rate')]"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
<group>
<filter string="Coating Config" name="group_coating_config" context="{'group_by':'coating_config_id'}"/>
<filter string="Pricing Method" name="group_pricing_method" context="{'group_by':'pricing_method'}"/>
</group>
</search>
</field>
</record>
<!-- ===== Window Action ===== -->
<record id="action_fp_pricing_rule" model="ir.actions.act_window">
<field name="name">Pricing Rules</field>
<field name="res_model">fp.pricing.rule</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_fp_pricing_rule_search"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No pricing rules defined yet
</p>
<p>
Define formula-based pricing rules matched by coating
configuration, substrate material, and certification level.
The first matching rule (by sequence) wins.
</p>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,326 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo>
<!-- ===== Configurator Form View ===== -->
<record id="view_fp_quote_configurator_form" model="ir.ui.view">
<field name="name">fp.quote.configurator.form</field>
<field name="model">fp.quote.configurator</field>
<field name="arch" type="xml">
<form string="Quote Configurator">
<header>
<button name="action_create_quotation"
string="Create Quotation"
type="object"
class="btn-primary"
confirm="This will create a Sale Order from this configurator session. Continue?"
invisible="state != 'draft'"/>
<button name="action_recalculate_price"
string="Recalculate"
type="object"
class="btn-secondary"/>
<button name="action_save_to_catalog"
string="Save to Catalog"
type="object"
class="btn-secondary"
confirm="This will overwrite the part catalog's geometry, substrate, masking area, and complexity with values from this quote. Continue?"
invisible="not part_catalog_id"/>
<button name="action_cancel"
string="Cancel"
type="object"
invisible="state == 'cancelled'"/>
<button name="action_reset_draft"
string="Reset to Draft"
type="object"
invisible="state == 'draft'"/>
<field name="state" widget="statusbar" statusbar_visible="draft,confirmed,cancelled"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button name="action_view_sale_order"
type="object"
class="oe_stat_button"
icon="fa-file-text-o"
invisible="not sale_order_id">
<field name="sale_order_id" widget="statinfo" string="Sale Order"/>
</button>
<button name="action_view_part_catalog"
type="object"
class="oe_stat_button"
icon="fa-cube"
invisible="not part_catalog_id">
<field name="part_catalog_id" widget="statinfo" string="Part"/>
</button>
<button name="action_view_drawings"
type="object"
class="oe_stat_button"
icon="fa-file-pdf-o"
invisible="drawing_count == 0">
<field name="drawing_count" widget="statinfo" string="Drawings"/>
</button>
<button name="action_view_rfq"
type="object"
class="oe_stat_button"
icon="fa-envelope-o"
invisible="not rfq_attachment_id">
<div class="o_stat_info">
<span class="o_stat_value">1</span>
<span class="o_stat_text">RFQ</span>
</div>
</button>
<button name="action_view_po"
type="object"
class="oe_stat_button"
icon="fa-file-o"
invisible="not po_attachment_id">
<div class="o_stat_info">
<span class="o_stat_value">1</span>
<span class="o_stat_text">PO</span>
</div>
</button>
</div>
<div class="oe_title">
<h1>
<field name="name" readonly="1"/>
</h1>
</div>
<!-- Main layout: 3/4 fields (left) + 1/4 3D preview (right) -->
<div class="o_fp_cfg_layout">
<!-- LEFT COLUMN: all fields -->
<div class="o_fp_cfg_fields">
<group>
<group string="Customer &amp; Part">
<field name="partner_id"/>
<field name="part_catalog_id"/>
<field name="coating_config_id"/>
<!-- 3D File: upload before, filename + clear button after -->
<field name="upload_3d_file" filename="upload_3d_filename"
invisible="state != 'draft' or model_attachment_id"
string="Attach 3D File"/>
<field name="upload_3d_filename" invisible="1"/>
<field name="model_attachment_id"
string="3D Model"
invisible="not model_attachment_id"
readonly="state != 'draft'"/>
<!-- Drawing: upload before, filename + clear button after -->
<field name="upload_drawing" filename="upload_drawing_filename"
invisible="state != 'draft' or drawing_count > 0"
string="Attach Drawing"/>
<field name="upload_drawing_filename" invisible="1"/>
<field name="first_drawing_id"
string="Drawing"
invisible="drawing_count == 0"
readonly="state != 'draft'"/>
<field name="drawing_count" invisible="1"/>
</group>
<group string="RFQ / PO Documents">
<field name="upload_rfq_file"
filename="upload_rfq_filename"
invisible="state != 'draft' or rfq_attachment_id"
string="Attach RFQ"/>
<field name="upload_rfq_filename" invisible="1"/>
<field name="rfq_attachment_id"
invisible="not rfq_attachment_id"
readonly="state != 'draft'"/>
<field name="upload_po_file"
filename="upload_po_filename"
invisible="state != 'draft' or po_attachment_id"
string="Attach PO"/>
<field name="upload_po_filename" invisible="1"/>
<field name="po_attachment_id"
invisible="not po_attachment_id"
readonly="state != 'draft'"/>
<field name="po_number_preliminary"
string="PO Number"
readonly="state != 'draft'"/>
<separator string="Quantity &amp; Options"/>
<field name="quantity"/>
<field name="batch_size"/>
<field name="complexity"/>
<field name="rush_order"/>
</group>
</group>
<group>
<group string="Geometry">
<field name="surface_area"/>
<field name="surface_area_uom"/>
<field name="masking_area_sqin"
string="Masking Area (sq in)"/>
<field name="effective_area_sqin"
string="Effective Plating Area"
readonly="1"/>
<field name="thickness_requested"/>
<field name="substrate_material"/>
<field name="masking_zones"/>
<field name="turnaround_days"/>
</group>
<group string="Auto from 3D"
invisible="not part_catalog_id">
<field name="bbox_summary_in"
string="Dimensions"
readonly="1"/>
<field name="material_weight_kg"
string="Weight (kg)"
readonly="1"/>
<field name="hole_count"
string="Holes"
readonly="1"/>
<field name="hole_summary"
readonly="1"
invisible="not hole_summary"/>
<field name="is_manifold"
widget="boolean_toggle"
readonly="1"/>
</group>
</group>
<div class="alert alert-warning"
invisible="is_manifold or not part_catalog_id or not hole_count">
<i class="fa fa-exclamation-triangle me-1"/>
<strong>Warning:</strong> 3D model is not watertight.
Surface area calculation may be inaccurate. Review the file before quoting.
</div>
<group>
<group string="Delivery &amp; Fees">
<field name="delivery_method"/>
<field name="shipping_fee"/>
<field name="delivery_fee"/>
<field name="currency_id" invisible="1"/>
</group>
</group>
<separator string="Pricing"/>
<group>
<group>
<field name="calculated_price" widget="monetary" readonly="1"
class="fw-bold fs-4"/>
</group>
<group>
<field name="estimator_override_price" widget="monetary"/>
</group>
</group>
<group>
<field name="price_breakdown_html" readonly="1" nolabel="1" colspan="2"/>
</group>
</div>
<!-- RIGHT COLUMN: 3D preview + Drawings preview (sticky) -->
<div class="o_fp_cfg_preview"
invisible="not model_attachment_id and drawing_count == 0">
<!-- 3D viewer -->
<div invisible="not model_attachment_id">
<field name="model_attachment_id" widget="fp_3d_preview" nolabel="1"/>
<div class="text-center mt-2">
<button name="action_open_3d_fullscreen"
string="Full Screen"
type="object"
class="btn btn-sm btn-outline-primary"
icon="fa-expand"/>
</div>
</div>
<!-- Drawings preview (custom OWL widget — fixed height, full screen button) -->
<div invisible="drawing_count == 0" class="mt-3">
<span class="o_form_label fw-bold text-muted small d-block mb-1">Drawing Preview</span>
<field name="first_drawing_id"
widget="fp_pdf_inline_preview"
nolabel="1"
readonly="1"/>
<!-- Multi-drawing list shown only when more than one -->
<div invisible="drawing_count &lt; 2" class="mt-2">
<span class="o_form_label fw-bold text-muted small d-block mb-1">All Drawings</span>
<field name="drawing_attachment_ids"
widget="fp_pdf_preview_binary"
nolabel="1"
readonly="1"/>
</div>
</div>
</div>
</div>
<notebook>
<page string="Sale Order" name="sale_order">
<group>
<field name="sale_order_id" readonly="1"/>
</group>
</page>
<page string="Notes" name="notes">
<field name="notes" placeholder="Internal notes about this quote..."/>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<!-- ===== Configurator List View ===== -->
<record id="view_fp_quote_configurator_list" model="ir.ui.view">
<field name="name">fp.quote.configurator.list</field>
<field name="model">fp.quote.configurator</field>
<field name="arch" type="xml">
<list string="Quote Configurators"
decoration-info="state == 'draft'"
decoration-muted="state == 'cancelled'"
default_order="create_date desc">
<field name="create_date" string="Date"/>
<field name="name"/>
<field name="partner_id"/>
<field name="coating_config_id"/>
<field name="surface_area"/>
<field name="quantity"/>
<field name="currency_id" column_invisible="1"/>
<field name="calculated_price"/>
<field name="estimator_override_price" string="Final Price"/>
<field name="state" widget="badge"
decoration-success="state == 'confirmed'"
decoration-info="state == 'draft'"
decoration-danger="state == 'cancelled'"/>
</list>
</field>
</record>
<!-- ===== Configurator Search View ===== -->
<record id="view_fp_quote_configurator_search" model="ir.ui.view">
<field name="name">fp.quote.configurator.search</field>
<field name="model">fp.quote.configurator</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="partner_id"/>
<field name="coating_config_id"/>
<separator/>
<filter string="Draft" name="draft" domain="[('state', '=', 'draft')]"/>
<filter string="Confirmed" name="confirmed" domain="[('state', '=', 'confirmed')]"/>
<filter string="Cancelled" name="cancelled" domain="[('state', '=', 'cancelled')]"/>
<group>
<filter string="Customer" name="group_customer" context="{'group_by': 'partner_id'}"/>
<filter string="Coating Config" name="group_coating" context="{'group_by': 'coating_config_id'}"/>
<filter string="Status" name="group_state" context="{'group_by': 'state'}"/>
</group>
</search>
</field>
</record>
<!-- ===== Window Action ===== -->
<record id="action_fp_quote_configurator" model="ir.actions.act_window">
<field name="name">Quote Configurator</field>
<field name="res_model">fp.quote.configurator</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_fp_quote_configurator_search"/>
<field name="context">{}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new quote configurator session
</p>
<p>
Select a customer and coating configuration, enter part geometry,
and the pricing engine will calculate a quote. The estimator can
override the calculated price before creating a sale order.
</p>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo>
<!-- ===== Treatment List View ===== -->
<record id="view_fp_treatment_list" model="ir.ui.view">
<field name="name">fp.treatment.list</field>
<field name="model">fp.treatment</field>
<field name="arch" type="xml">
<list string="Treatments">
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="treatment_type"/>
<field name="default_duration_minutes"/>
<field name="currency_id" column_invisible="1"/>
<field name="default_cost"/>
<field name="active" widget="boolean_toggle"/>
</list>
</field>
</record>
<!-- ===== Treatment Form View ===== -->
<record id="view_fp_treatment_form" model="ir.ui.view">
<field name="name">fp.treatment.form</field>
<field name="model">fp.treatment</field>
<field name="arch" type="xml">
<form string="Treatment">
<sheet>
<widget name="web_ribbon" title="Archived" bg_color="text-bg-danger" invisible="active"/>
<div class="oe_title">
<label for="name"/>
<h1><field name="name" placeholder="e.g. Bead Blast"/></h1>
</div>
<group>
<group>
<field name="treatment_type"/>
<field name="sequence"/>
</group>
<group>
<field name="default_duration_minutes"/>
<field name="currency_id" invisible="1"/>
<field name="default_cost"/>
</group>
</group>
<group>
<field name="description" placeholder="Description of this treatment step..."/>
</group>
<group>
<field name="active" widget="boolean_toggle"/>
</group>
</sheet>
</form>
</field>
</record>
<!-- ===== Treatment Search View ===== -->
<record id="view_fp_treatment_search" model="ir.ui.view">
<field name="name">fp.treatment.search</field>
<field name="model">fp.treatment</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<separator/>
<filter string="Pre-Treatment" name="pre" domain="[('treatment_type','=','pre')]"/>
<filter string="Post-Treatment" name="post" domain="[('treatment_type','=','post')]"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active','=',False)]"/>
<group>
<filter string="Type" name="group_type" context="{'group_by':'treatment_type'}"/>
</group>
</search>
</field>
</record>
<!-- ===== Window Action ===== -->
<record id="action_fp_treatment" model="ir.actions.act_window">
<field name="name">Treatments</field>
<field name="res_model">fp.treatment</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_fp_treatment_search"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No treatments defined yet
</p>
<p>
Add pre-treatment steps (bead blast, zincate, acid etch) and
post-treatment steps (bake, passivate, chromate seal).
</p>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_partner_form_fp_parts" model="ir.ui.view">
<field name="name">res.partner.form.fp.parts</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='button_box']" position="inside">
<button name="action_view_parts"
type="object"
class="oe_stat_button"
icon="fa-cube"
invisible="x_fc_part_count == 0">
<field name="x_fc_part_count" widget="statinfo" string="Parts"/>
</button>
</xpath>
<xpath expr="//page[@name='sales_purchases']" position="after">
<page string="Part Library" name="part_library">
<field name="x_fc_part_catalog_ids" mode="list"
domain="[('is_latest_revision', '=', True)]">
<list default_order="name" >
<field name="part_number"/>
<field name="name"/>
<field name="revision"/>
<field name="revision_number" string="Rev #"/>
<field name="substrate_material"/>
<field name="surface_area"/>
<field name="surface_area_uom" string="UoM"/>
<field name="complexity"/>
<field name="model_attachment_id" string="3D Model"/>
</list>
</field>
</page>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2026 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
Part of the Fusion Plating product family.
-->
<odoo>
<!-- ===== Inherit SO Form — add Plating tab ===== -->
<record id="view_sale_order_form_fp" model="ir.ui.view">
<field name="name">sale.order.form.fp.configurator</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//div[hasclass('oe_button_box')]" position="inside">
<button name="action_view_rfq"
type="object"
class="oe_stat_button"
icon="fa-envelope-o"
invisible="not x_fc_rfq_attachment_id">
<div class="o_stat_info">
<span class="o_stat_value">1</span>
<span class="o_stat_text">RFQ</span>
</div>
</button>
<button name="action_view_po"
type="object"
class="oe_stat_button"
icon="fa-file-o"
invisible="not x_fc_po_attachment_id">
<div class="o_stat_info">
<span class="o_stat_value">1</span>
<span class="o_stat_text">PO</span>
</div>
</button>
</xpath>
<xpath expr="//notebook" position="inside">
<page string="Plating" name="plating_tab">
<group>
<group string="Part &amp; Coating">
<field name="x_fc_configurator_id" readonly="1"/>
<field name="x_fc_part_catalog_id"/>
<field name="x_fc_coating_config_id"/>
</group>
<group string="RFQ / PO">
<field name="x_fc_po_number"/>
<field name="upload_rfq_file"
filename="upload_rfq_filename"
invisible="x_fc_rfq_attachment_id"
string="Attach RFQ"/>
<field name="upload_rfq_filename" invisible="1"/>
<field name="x_fc_rfq_attachment_id"
invisible="not x_fc_rfq_attachment_id"/>
<field name="upload_po_file"
filename="upload_po_filename"
invisible="x_fc_po_attachment_id"
string="Attach PO"/>
<field name="upload_po_filename" invisible="1"/>
<field name="x_fc_po_attachment_id"
invisible="not x_fc_po_attachment_id"/>
<field name="x_fc_po_received"/>
<field name="x_fc_po_override"
groups="fusion_plating.group_fusion_plating_manager"/>
<field name="x_fc_po_override_reason"
invisible="not x_fc_po_override"/>
</group>
</group>
<group>
<group string="Invoicing">
<field name="x_fc_invoice_strategy"/>
<field name="x_fc_deposit_percent"
invisible="x_fc_invoice_strategy != 'deposit'"/>
</group>
<group string="Delivery">
<field name="x_fc_rush_order"/>
<field name="x_fc_delivery_method"/>
<field name="x_fc_receiving_status"/><!-- Will become computed when fusion_plating_receiving is installed -->
</group>
</group>
</page>
</xpath>
</field>
</record>
<!-- ===== Custom SO List View for Fusion Plating ===== -->
<record id="view_sale_order_list_fp" model="ir.ui.view">
<field name="name">sale.order.list.fp</field>
<field name="model">sale.order</field>
<field name="arch" type="xml">
<list string="Sale Orders" decoration-info="state == 'draft'"
decoration-muted="state == 'cancel'">
<field name="name"/>
<field name="partner_id"/>
<field name="x_fc_po_number"/>
<field name="x_fc_part_catalog_id" optional="show"/>
<field name="x_fc_coating_config_id" optional="show"/>
<field name="amount_total" sum="Total"/>
<field name="x_fc_receiving_status" widget="badge"
decoration-warning="x_fc_receiving_status == 'not_received'"
decoration-success="x_fc_receiving_status in ('received','inspected')"/>
<field name="x_fc_delivery_method" optional="show"/>
<field name="state" widget="badge"/>
</list>
</field>
</record>
<!-- ===== Window Action — Quotations (for Fusion Plating menu) ===== -->
<record id="action_fp_quotations" model="ir.actions.act_window">
<field name="name">Quotations</field>
<field name="res_model">sale.order</field>
<field name="view_mode">list,form,kanban</field>
<field name="domain">[('state', 'in', ('draft', 'sent'))]</field>
<field name="view_ids" eval="[(5, 0, 0),
(0, 0, {'view_mode': 'list', 'view_id': ref('view_sale_order_list_fp')})]"/>
<field name="context">{'default_x_fc_delivery_method': 'shipping_partner'}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new quotation
</p>
</field>
</record>
<!-- ===== Window Action — Confirmed Sale Orders ===== -->
<record id="action_fp_sale_orders" model="ir.actions.act_window">
<field name="name">Sale Orders</field>
<field name="res_model">sale.order</field>
<field name="view_mode">list,form,kanban</field>
<field name="domain">[('state', 'in', ('sale', 'done'))]</field>
<field name="view_ids" eval="[(5, 0, 0),
(0, 0, {'view_mode': 'list', 'view_id': ref('view_sale_order_list_fp')})]"/>
</record>
</odoo>