chore(plating): de-dash shipped code + intake-neutral customer emails

Replace em-dashes and en-dashes with hyphens across 789 shipped source
files (py/xml/js/scss) so the delivered module reads as human-written;
em-dashes had become a recognizable AI-generated tell. Internal .md dev
notes are excluded. The WO-sticker mojibake strippers keep their dash
search targets (now written — / –). No logic changes: comments
and display strings only; validated with py_compile + lxml parse.

Rewrite the 7 customer notification emails to be intake-neutral
(ship-in / drop-off / pickup) and repair-aware, and fix the Shipped
email documents line (packing slip vs bill of lading; certificate only
when issued). Subjects use a hyphen separator.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-06-05 00:16:19 -04:00
parent c9eb61ee0c
commit 8c76a16366
789 changed files with 4692 additions and 4692 deletions

View File

@@ -1,13 +1,13 @@
# -*- coding: utf-8 -*-
# E2E persona walk order entry from start to finish.
# E2E persona walk - order entry from start to finish.
#
# Personas:
# Sarah Customer Service Rep
# Mike Receiver
# Carlos Plating Operator
# Lisa QC Inspector
# Tom Shipper
# Jane Accounting
# Sarah - Customer Service Rep
# Mike - Receiver
# Carlos - Plating Operator
# Lisa - QC Inspector
# Tom - Shipper
# Jane - Accounting
#
# This script fills every visible-to-operator field per step, walks the
# workflow with no shortcuts, asserts the data is sane after each phase,
@@ -40,7 +40,7 @@ def e2e(env):
findings = []
# ----- pick a real partner with a recipe-able product -----
section('SETUP pick a customer + a part already in the catalog')
section('SETUP - pick a customer + a part already in the catalog')
Partner = env['res.partner']
Part = env['fp.part.catalog']
Coating = env['fp.coating.config']
@@ -59,11 +59,11 @@ def e2e(env):
step('Sarah', f'Part: {part.part_number or part.name} rev {part.revision or "?"} (id={part.id})')
step('Sarah', f'Coating: {coating.display_name if coating else "NONE"} (id={coating.id if coating else 0})')
if not coating:
findings.append('No fp.coating.config found in DB cannot create realistic SO')
findings.append('No fp.coating.config found in DB - cannot create realistic SO')
return findings
# ----- Sarah builds a sale order -----
section('PHASE 1 Sarah (CSR) creates the sale order')
section('PHASE 1 - Sarah (CSR) creates the sale order')
SO = env['sale.order']
SOL = env['sale.order.line']
so_vals = {
@@ -79,13 +79,13 @@ def e2e(env):
'x_fc_delivery_method': 'shipping_partner',
'x_fc_rush_order': False,
'x_fc_is_blanket_order': False,
'x_fc_internal_note': 'E2E test SO full persona walk.',
'x_fc_internal_note': 'E2E test SO - full persona walk.',
'x_fc_external_note': 'Standard plating per spec.',
}
so = SO.create(so_vals)
step('Sarah', f'Created SO {so.name} (id={so.id})')
# add a line fill the part / coating / treatment fields
# add a line - fill the part / coating / treatment fields
product = env['product.product'].search([('sale_ok', '=', True)], limit=1)
if not product:
findings.append('No saleable product available for SO line')
@@ -94,7 +94,7 @@ def e2e(env):
'order_id': so.id,
'product_id': product.id,
'product_uom_qty': 25,
'name': f'{part.part_number or part.name} Plating per coating spec',
'name': f'{part.part_number or part.name} - Plating per coating spec',
'x_fc_part_catalog_id': part.id,
'x_fc_coating_config_id': coating.id,
'x_fc_internal_description': 'Process via standard recipe; bake ASAP.',
@@ -103,7 +103,7 @@ def e2e(env):
line = SOL.create(line_vals)
step('Sarah', f'Added line: {line.product_uom_qty} × {line.name[:40]}')
# confirm does account hold block?
# confirm - does account hold block?
if partner.x_fc_account_hold:
find('Sarah', 'Customer is on account hold; SO confirm should block (or warn)')
try:
@@ -129,7 +129,7 @@ def e2e(env):
find('Sarah', 'NO fp.receiving auto-created on SO confirm! Receiver has nothing to track.')
findings.append('SO confirm did not auto-spawn fp.receiving')
if jobs and not portal_jobs:
find('Sarah', 'fp.job exists but no portal.job mirror customer can\'t track on portal.')
find('Sarah', 'fp.job exists but no portal.job mirror - customer can\'t track on portal.')
findings.append('Portal job mirror missing post-confirm')
# smart-button visibility check
@@ -140,7 +140,7 @@ def e2e(env):
f'NCRs visible? {so.fp_qc_ncr_count_so > 0} (count={so.fp_qc_ncr_count_so})')
# ----- Mike receives parts -----
section('PHASE 2 Mike (Receiver) processes inbound parts')
section('PHASE 2 - Mike (Receiver) processes inbound parts')
receiving = receivings[:1]
if not receiving:
receiving = Receiving.create({
@@ -148,7 +148,7 @@ def e2e(env):
'expected_qty': 25,
})
step('Mike', f'Manually created receiving {receiving.name} (auto-create did not fire)')
find('Mike', 'Had to manually create receiving auto-create from SO confirm is missing')
find('Mike', 'Had to manually create receiving - auto-create from SO confirm is missing')
findings.append('Auto-receiving on SO confirm not wired')
else:
step('Mike', f'Found auto-created receiving {receiving.name} (state={receiving.state})')
@@ -199,17 +199,17 @@ def e2e(env):
racks = Inspection.search([('sale_order_id', '=', so.id)])
step('Mike', f'Racking inspections for this SO: {len(racks)}')
if not racks:
find('Mike', 'Racking inspection NOT auto-created racking crew has nothing to walk.')
find('Mike', 'Racking inspection NOT auto-created - racking crew has nothing to walk.')
findings.append('No racking inspection auto-created post-confirm')
# ----- Carlos works the plating job -----
section('PHASE 3 Carlos (Operator) walks the plating job')
section('PHASE 3 - Carlos (Operator) walks the plating job')
if not jobs:
fail('Carlos', 'No job to work SO confirm did not spawn one. Skipping phase.')
fail('Carlos', 'No job to work - SO confirm did not spawn one. Skipping phase.')
else:
job = jobs[0]
step('Carlos', f'Job {job.name}: state={job.state}, qty={job.qty}, deadline={job.date_deadline}')
step('Carlos', f'Steps: {len(job.step_ids)} recipe={job.recipe_id.name or "(none)"}')
step('Carlos', f'Steps: {len(job.step_ids)} - recipe={job.recipe_id.name or "(none)"}')
if not job.step_ids:
find('Carlos', f'Job has zero steps! Recipe not assigned or not generated. Recipe field: {job.recipe_id}')
findings.append('Job confirmed with zero steps')
@@ -244,7 +244,7 @@ def e2e(env):
done_count = len(job.step_ids.filtered(lambda st: st.state == 'done'))
step('Carlos', f'Walked {done_count}/{len(job.step_ids)} steps to done')
# try to mark job done should hit QC gate if customer requires QC
# try to mark job done - should hit QC gate if customer requires QC
wants_qc = 'x_fc_requires_qc' in partner._fields and partner.x_fc_requires_qc
step('Carlos', f'Customer requires QC? {wants_qc}')
try:
@@ -258,7 +258,7 @@ def e2e(env):
findings.append(f'button_mark_done: {e}')
# ----- Lisa runs QC -----
section('PHASE 4 Lisa (QC) walks the checklist (if any)')
section('PHASE 4 - Lisa (QC) walks the checklist (if any)')
QC = env['fusion.plating.quality.check']
qcs = QC.search([('job_id', 'in', jobs.ids)]) if jobs else QC.browse()
step('Lisa', f'QC checks for this job: {len(qcs)}')
@@ -292,7 +292,7 @@ def e2e(env):
findings.append(f'Job blocked post-QC: {e}')
# ----- Tom ships -----
section('PHASE 5 Tom (Shipper) prepares the delivery')
section('PHASE 5 - Tom (Shipper) prepares the delivery')
Delivery = env['fusion.plating.delivery']
deliveries = Delivery.search([
'|', ('job_ref', 'in', jobs.mapped('name') if jobs else []),
@@ -325,14 +325,14 @@ def e2e(env):
findings.append('Certificate auto-create missing')
# ----- Jane invoices -----
section('PHASE 6 Jane (Accounting) creates and posts invoice')
section('PHASE 6 - Jane (Accounting) creates and posts invoice')
invoices_before = env['account.move'].search_count([
('invoice_origin', '=', so.name),
])
try:
if so.invoice_status == 'to invoice':
inv_action = so._create_invoices()
step('Jane', f'Invoiced {invoices_before}{env["account.move"].search_count([("invoice_origin","=",so.name)])} moves')
step('Jane', f'Invoiced - {invoices_before}{env["account.move"].search_count([("invoice_origin","=",so.name)])} moves')
else:
step('Jane', f'invoice_status={so.invoice_status} (nothing to invoice)')
except Exception as e:
@@ -340,7 +340,7 @@ def e2e(env):
findings.append(f'invoice creation: {e}')
# ----- common-sense edge case sweeps -----
section('PHASE 7 common-sense edge case sweeps')
section('PHASE 7 - common-sense edge case sweeps')
# smart-button results: do they actually return non-empty data?
section_name = ' smart-button result probes'
@@ -381,7 +381,7 @@ def e2e(env):
for i, f in enumerate(findings, 1):
print(f' {i}. {f}')
else:
print(' ✅ No findings workflow is clean end-to-end.')
print(' ✅ No findings - workflow is clean end-to-end.')
env.cr.commit()
return findings