This commit is contained in:
gsinghpal
2026-04-29 03:35:33 -04:00
parent 6ac6d24da6
commit a2fe1fcbcc
61 changed files with 4655 additions and 667 deletions

View File

@@ -13,6 +13,30 @@ from odoo import fields, models
class AccountMoveLine(models.Model):
_inherit = 'account.move.line'
def fp_customer_description(self):
"""Strip the "[code] product_name" prefix from line.name.
Mirror of sale.order.line.fp_customer_description so the shared
customer_line_description QWeb macro renders cleanly on invoice
PDFs too.
"""
self.ensure_one()
name = (self.name or '').strip()
if not self.product_id or not name:
return name
code = self.product_id.default_code or ''
pname = self.product_id.name or ''
prefixes = []
if code and pname:
prefixes.append(f'[{code}] {pname}')
if pname:
prefixes.append(pname)
for prefix in prefixes:
if name.startswith(prefix):
tail = name[len(prefix):]
return tail.lstrip(' \t\r\n-—–:').strip()
return name
x_fc_part_catalog_id = fields.Many2one(
'fp.part.catalog',
string='Part',

View File

@@ -25,9 +25,26 @@ class FpCoatingThickness(models.Model):
ondelete='cascade',
)
value = fields.Float(
string='Nominal',
digits=(10, 4),
required=True,
help='Target thickness value (magnitude only; UoM in the next field).',
help='Target / nominal thickness value (the number printed on the cert). '
'Magnitude only — UoM lives in the next field.',
)
# Hitting an exact thickness on plated parts is impossible — the spec
# is always "X mils ± tolerance" or a min/max range. These fields
# capture the acceptance band so QC can mark a reading pass/fail
# against real customer specs (e.g. AMS-2404 Class 4 = 0.001"0.0015").
# Both optional: leave blank for legacy single-value entries.
value_min = fields.Float(
string='Min',
digits=(10, 4),
help='Lower acceptance bound. Readings below this fail QC.',
)
value_max = fields.Float(
string='Max',
digits=(10, 4),
help='Upper acceptance bound. Readings above this fail QC.',
)
uom = fields.Selection(
[('mils', 'mils (0.001 in)'),
@@ -44,7 +61,7 @@ class FpCoatingThickness(models.Model):
store=True,
)
@api.depends('value', 'uom')
@api.depends('value', 'value_min', 'value_max', 'uom')
def _compute_display_name(self):
uom_labels = dict(self._fields['uom'].selection)
for rec in self:
@@ -52,7 +69,22 @@ class FpCoatingThickness(models.Model):
# Strip the bracketed clarification for a tighter dropdown row.
if ' (' in label:
label = label.split(' (')[0]
if rec.value:
# Range overrides single value when both bounds are set —
# operators see the real spec, not a phantom-precise nominal.
if rec.value_min and rec.value_max:
rec.display_name = (
f'{rec.value_min:g}{rec.value_max:g} {label}'.strip()
)
elif rec.value:
rec.display_name = f'{rec.value:g} {label}'.strip()
else:
rec.display_name = label
@api.constrains('value_min', 'value_max')
def _check_range(self):
for rec in self:
if rec.value_min and rec.value_max and rec.value_min > rec.value_max:
from odoo.exceptions import ValidationError
raise ValidationError(_(
'Thickness Min (%(mn)s) cannot exceed Max (%(mx)s).'
) % {'mn': rec.value_min, 'mx': rec.value_max})

View File

@@ -10,6 +10,36 @@ from odoo.exceptions import ValidationError
class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'
def fp_customer_description(self):
"""Return line.name with the leading "[code] product_name" stripped.
Odoo's _compute_name re-prepends the product code + name on save,
polluting customer-facing PDFs with internal-product noise like
"[FP-SERVICE] Plating Service". This helper peels that prefix
off so the QWeb macros print only what the estimator actually
typed for the customer to see. Same logic mirrored on
account.move.line for invoice rendering.
"""
self.ensure_one()
name = (self.name or '').strip()
if not self.product_id or not name:
return name
code = self.product_id.default_code or ''
pname = self.product_id.name or ''
# Try the bracketed form first ("[CODE] Name"), then bare name.
# Whichever matches gets stripped along with any trailing
# newline / dash / em-dash separator.
prefixes = []
if code and pname:
prefixes.append(f'[{code}] {pname}')
if pname:
prefixes.append(pname)
for prefix in prefixes:
if name.startswith(prefix):
tail = name[len(prefix):]
return tail.lstrip(' \t\r\n-—–:').strip()
return name
x_fc_part_catalog_id = fields.Many2one(
'fp.part.catalog', string='Part',
)