This commit is contained in:
gsinghpal
2026-05-30 20:59:59 -04:00
parent 55da42e91f
commit 5c1f60b3b8
17 changed files with 147 additions and 56 deletions

View File

@@ -5,7 +5,7 @@
{
'name': 'Fusion Plating — Configurator',
'version': '19.0.23.6.0',
'version': '19.0.22.10.0',
'category': 'Manufacturing/Plating',
'summary': 'Quotation configurator with part catalog, coating configs, and formula-based pricing engine.',
'description': """
@@ -44,7 +44,6 @@ Provides:
'views/fp_part_catalog_views.xml',
'views/fp_process_node_part_scoped_views.xml',
'views/fp_pricing_rule_views.xml',
'views/fp_additional_charge_type_views.xml',
'views/fp_quote_configurator_views.xml',
'views/sale_order_views.xml',
'views/res_partner_views.xml',
@@ -60,7 +59,6 @@ Provides:
'views/fp_configurator_menu.xml',
'views/fp_so_job_sort_views.xml',
'data/fp_sale_description_template_data.xml',
'data/fp_additional_charge_type_data.xml',
],
'assets': {
'web.assets_backend': [

View File

@@ -233,10 +233,6 @@
<span><strong>OPEN</strong> open the part record</span>
</div>
<div class="mb-2 d-flex align-items-center gap-2">
<field name="is_lot_order" widget="boolean_toggle"/>
<span><strong>Lot Order</strong> — price each line as a flat lot total (qty preserved for production)</span>
</div>
<div class="mb-2 d-flex gap-2">
<button name="action_add_from_prior_so"
type="object"
@@ -290,17 +286,10 @@
width="120px"/>
<field name="internal_description" string="Internal Notes" optional="show"/>
<field name="quantity" string="Qty" width="55px"/>
<field name="lot_total"
string="Lot Total"
widget="monetary"
options="{'currency_field': 'currency_id'}"
column_invisible="not parent.is_lot_order"
width="90px"/>
<field name="unit_price"
string="Price"
widget="monetary"
options="{'currency_field': 'currency_id'}"
readonly="parent.is_lot_order"
width="80px"/>
<field name="line_subtotal"
string="Subtotal"
@@ -318,6 +307,12 @@
options="{'no_quick_create': True}"
invisible="not part_catalog_id"
optional="hide"/>
<field name="tax_ids"
string="Tax"
widget="many2many_tags"
options="{'no_create': True}"
optional="hide"
width="110px"/>
<field name="currency_id" column_invisible="1"/>
</list>
</field>
@@ -346,7 +341,6 @@
<div class="o_fp_xpr_footer_right">
<div class="o_fp_xpr_card o_fp_xpr_totals">
<div class="o_fp_xpr_totals_head">Order Summary</div>
<div class="o_fp_xpr_total_row">
<span class="o_fp_xpr_total_label">Subtotal</span>
<field name="total_subtotal"
@@ -355,29 +349,19 @@
readonly="1" nolabel="1"/>
</div>
<div class="o_fp_xpr_total_row">
<div class="o_fp_xpr_total_label">
<span>Additional Charge</span>
<field name="charge_type_id" nolabel="1"
placeholder="Type..."
options="{'no_open': True}"/>
</div>
<field name="charge_amount"
widget="monetary"
options="{'currency_field': 'currency_id'}"
nolabel="1"/>
</div>
<div class="o_fp_xpr_total_row">
<div class="o_fp_xpr_total_label">
<span>Tax</span>
<field name="tax_id" nolabel="1"
placeholder="Tax type..."
options="{'no_create': True}"/>
</div>
<span class="o_fp_xpr_total_label">Tax</span>
<field name="total_tax"
widget="monetary"
options="{'currency_field': 'currency_id'}"
readonly="1" nolabel="1"/>
</div>
<div class="o_fp_xpr_total_row">
<span class="o_fp_xpr_total_label">Tooling Charge</span>
<field name="tooling_charge"
widget="monetary"
options="{'currency_field': 'currency_id'}"
nolabel="1"/>
</div>
<div class="o_fp_xpr_total_row">
<span class="o_fp_xpr_total_label">Total Lines</span>
<field name="total_line_count" readonly="1" nolabel="1"/>

View File

@@ -165,6 +165,40 @@ class FpDirectOrderWizard(models.Model):
"""Default pricelist = company's default. Re-resolved on partner pick."""
return self.env.company.partner_id.property_product_pricelist.id or False
@api.model
def _fp_default_terms_and_conditions(self):
"""Seed Terms & Conditions from the Accounting default — same source
as the standard sale.order.note field.
Respects the `account.use_invoice_terms` system parameter (toggled
from Settings → Invoicing → Default Terms & Conditions). Strips HTML
tags defensively since Odoo's rich-text editor sometimes leaks
markup into the plain `invoice_terms` field; the wizard field is
Text and must not store raw markup.
"""
ICP = self.env['ir.config_parameter'].sudo()
if not ICP.get_param('account.use_invoice_terms'):
return False
company = self.env.company
raw = (
(company.invoice_terms or '').strip()
or (getattr(company, 'invoice_terms_html', False) or '').strip()
)
if not raw:
return False
# Defensive HTML strip — works whether the source was clean plain
# text, a real html field, or a "plain" field polluted by the
# rich-text editor (entech case 2026-05-27).
if '<' in raw and '>' in raw:
try:
from lxml import html as lxml_html
raw = lxml_html.fromstring(raw).text_content().strip()
except Exception:
# Last-ditch regex fallback — no lxml, malformed html, etc.
import re
raw = re.sub(r'<[^>]+>', '', raw).strip()
return raw or False
# ---- Express Orders: auto-apply order recipe to all lines ----
@api.onchange('material_process')
def _onchange_material_process_apply_to_lines(self):
@@ -273,9 +307,10 @@ class FpDirectOrderWizard(models.Model):
# so the existing data preserves its customer-facing semantic.
terms_and_conditions = fields.Text(
string='Terms & Conditions',
default=lambda self: self._fp_default_terms_and_conditions(),
help='Customer-facing terms — prints on quote / SO / invoice. '
'Seeded from res.company.invoice_terms_html with partner-level '
'override via res.partner.invoice_terms.',
'Seeded from the Accounting default terms '
'(Settings → Invoicing → Default Terms & Conditions).',
)
internal_notes = fields.Text(
string='Order-Level Internal Notes',