fix(reports+configurator): clean description, recipe propagation, uppercase rendering

H1 — Recipe propagation hardening for multi-part orders. The G3 onchange
fires when material_process changes, but a newly-added line (especially
via inline part create) sometimes didn't pick up the recipe before
confirm. In action_create_order, just BEFORE building so_vals, force
line.process_variant_id = wizard.material_process if the line is missing
one. Also added the same fallback inside the so_vals dict so the SO line
always carries the right recipe even if the wizard line missed it.

H2 — Strip 'spec - PART Rev X (xN)' header from customer-facing
description. Per user feedback, the customer-facing reports (SO
confirmation, Invoice, CoC, packing slip, BoL) should show ONLY the
typed description + thickness in the Description column. The legacy
header that prepended part metadata to line.name duplicated info from
the Part Number column. Wizard now writes ONLY the customer description
to line.name; the Part Number column owns the part-rev-name display.

H3 — Uppercase customer-facing description in reports. The shared
customer_line_description macro now wraps the description, serial,
and thickness in text-transform: uppercase divs. All reports that use
the macro (SO confirmation, Invoice, CoC, packing slip, BoL) get the
caps treatment automatically. Non-part lines (freight, rush fees)
keep their natural casing.

Manually cleaned up DOD-00154/SO-30062:
- Backfilled line 682 with the header recipe (ENP ALUM BASIC HP)
- Stripped the legacy 'No spec - PART Rev (xN)' header from both
  lines' names; descriptions now read 'THIS IS TEST SPECIFICATIONS...'
  and 'THIS IS BLB ABLA BOLL' cleanly.
This commit is contained in:
gsinghpal
2026-05-27 00:24:27 -04:00
parent 1d0d4afdbf
commit 18072c9c60
2 changed files with 45 additions and 36 deletions

View File

@@ -752,24 +752,25 @@ class FpDirectOrderWizard(models.Model):
part = line._get_or_bump_revision()
resolved_parts[line.id] = part
# Build the line header. Specification is optional; when
# missing, drop it from the header rather than printing
# "False - PartName Rev A". Same defensive treatment for
# part identifier and revision — `%s` on a False/NULL field
# used to print the literal string "False".
spec = getattr(line, 'customer_spec_id', False)
spec_label = (spec.display_name if spec else '') or _('No spec')
# Prefer part_number (set on every saved part); fall back to
# name; skip the segment entirely if both are missing.
part_label = part.part_number or part.name or ''
rev_suffix = (' Rev %s' % part.revision) if part.revision else ''
header = '%s - %s%s (x%d)' % (
spec_label,
part_label or _('Unspecified part'),
rev_suffix,
line.quantity,
)
# 2026-05-27 — drop the legacy "spec - PART Rev (xN)" header
# entirely from the customer-facing line name. Per user
# request, customer-facing reports (SO confirmation, invoice,
# CoC, packing slip, BoL) should show ONLY:
# - the customer-typed description (line.line_description)
# - the thickness range (rendered on its own line)
# The part number / revision / serial show in the dedicated
# Part Number column. The header was duplicating that info
# in the Description column.
extended = (line.line_description or '').strip()
line_desc = (header + '\n\n' + extended) if extended else header
line_desc = extended or (part.part_number or '')
# G3 robustness (2026-05-27): make sure the line's process
# variant carries the order-level recipe if no per-line
# override exists. Belt-and-braces with the onchange/create
# propagation — catches the multi-part case where a new
# part's line never received the order recipe.
if not line.process_variant_id and self.material_process:
line.process_variant_id = self.material_process.id
if line.description_template_id:
line.description_template_id._register_usage()
@@ -792,7 +793,13 @@ class FpDirectOrderWizard(models.Model):
'x_fc_start_at_node_id': line.start_at_node_id.id or False,
'x_fc_is_one_off': line.is_one_off,
'x_fc_quote_id': line.quote_id.id or False,
'x_fc_process_variant_id': line.process_variant_id.id or False,
# Recipe propagation (G3) — line's process_variant_id, falling
# back to the order-level material_process recipe so multi-part
# orders still get the header recipe on every line.
'x_fc_process_variant_id': (
line.process_variant_id.id
or (self.material_process.id if self.material_process else False)
),
'x_fc_save_as_default_process': line.save_as_default_process,
# Sub 5 / Phase 1 — carry serial M2M to the SO line.
# x_fc_serial_id is back-compat alias and auto-resolves