feat(configurator): SO-line template picker + dual descriptions + onchange (Sub 2 Task 15)

Surfaces the per-part description template on the SO line list alongside
a hidden-by-default internal description column. Picking a template
fires an onchange that copies `customer_facing_description` into Odoo's
standard `name` (customer-visible) and `internal_description` into
x_fc_internal_description (shop-floor / WO only). Estimator can edit
either field after the template is applied.

The template picker's domain filters by the line's part, and the field
stays hidden until a part is chosen — avoids showing every global
template when the line is blank.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-04-21 22:49:49 -04:00
parent d1c855698a
commit a659eba8f5
2 changed files with 25 additions and 1 deletions

View File

@@ -3,7 +3,7 @@
# License OPL-1 (Odoo Proprietary License v1.0)
# Part of the Fusion Plating product family.
from odoo import fields, models
from odoo import api, fields, models
class SaleOrderLine(models.Model):
@@ -66,6 +66,22 @@ class SaleOrderLine(models.Model):
'preserved for audit. Useful when a part is cancelled mid-order.',
)
@api.onchange('x_fc_description_template_id')
def _onchange_description_template(self):
"""When estimator picks a template, auto-fill both descriptions.
The customer-facing text goes into `name` (Odoo's line description,
prints on customer docs). The internal text goes into
x_fc_internal_description (prints on WO / traveler only).
Estimator can edit either field after the template is applied.
"""
if self.x_fc_description_template_id:
tpl = self.x_fc_description_template_id
if tpl.customer_facing_description:
self.name = tpl.customer_facing_description
if tpl.internal_description:
self.x_fc_internal_description = tpl.internal_description
def action_archive_line(self):
self.write({'x_fc_archived': True})
return True

View File

@@ -179,6 +179,14 @@
</xpath>
<xpath expr="//field[@name='order_line']/list/field[@name='product_uom_qty']" position="before">
<field name="x_fc_part_catalog_id" optional="show"/>
<field name="x_fc_description_template_id"
domain="[('part_catalog_id', '=', x_fc_part_catalog_id)]"
options="{'no_create': True}"
invisible="not x_fc_part_catalog_id"
optional="show"/>
<field name="x_fc_internal_description"
placeholder="Shop-floor workflow instructions (prints on WO / traveler)"
optional="hide"/>
<field name="x_fc_coating_config_id" optional="show"/>
<field name="x_fc_treatment_ids" widget="many2many_tags" optional="hide"/>
<field name="x_fc_part_deadline" optional="hide"/>