fix(audit-trail): 3 production bugs found via end-to-end Anodize battle test
Battle-tested complete workflow on entech: ABC Manufacturing + Anodize recipe (id=136) cloned to part-variant (id=1775) → SO S00276 confirmed → fp.job 1234 with 17 steps → recorded 56 measurement values exercising all 13 input types (incl. all 4 new types) → CoC chronological report renders 69KB with all values incl. photo thumbnails. Bugs found and fixed: 1. fp.process.node.input_ids missing copy=True — when a master recipe was cloned per-part (the standard variant pattern), the operator prompts on each step did NOT get copied to the variant. Result: jobs built from variants ran with zero prompts even though the master had them. Fixed: input_ids now copy=True so cloning auto-duplicates. 2. CoC chronological template read dest.input_ids where dest is fp.job.step. Steps don't carry input_ids — that field lives on the recipe node. Result: AttributeError aborted the entire CoC render. Fixed: walk via dest.recipe_node_id.input_ids; preserves the existing collect=True filter. 3. CoC chronological template used hasattr() in a t-value expression. QWeb's expression engine doesn't expose Python builtins, raised KeyError: 'hasattr'. Fixed: use 'collect' in i._fields instead. Also enhanced photo rendering in CoC: was just "[Attachment]" placeholder; now renders an actual <img> thumbnail (max 80px tall) plus the filename. Battle-test script saved to fusion_plating/scripts/bt_e2e_anodize_v2.py for re-runs / regression testing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -95,7 +95,10 @@
|
||||
<t t-foreach="moves" t-as="mv">
|
||||
<t t-set="dest" t-value="mv.to_step_id"/>
|
||||
<t t-set="tank_code" t-value="(mv.to_tank_id and mv.to_tank_id.code) or (dest and dest.tank_id and dest.tank_id.code) or ''"/>
|
||||
<t t-set="captured" t-value="(dest and dest.input_ids.filtered(lambda i: (i.kind or 'step_input') == 'step_input' and (not hasattr(i, 'collect') or i.collect)).sorted('sequence')) or []"/>
|
||||
<!-- Sub 12d — input_ids lives on recipe_node, not job.step.
|
||||
Walk via recipe_node_id; filter to step_input + collect=True. -->
|
||||
<t t-set="recipe_node" t-value="(dest and dest.recipe_node_id) or False"/>
|
||||
<t t-set="captured" t-value="(recipe_node and recipe_node.input_ids.filtered(lambda i: (i.kind or 'step_input') == 'step_input' and (i.collect if 'collect' in i._fields else True)).sorted('sequence')) or []"/>
|
||||
|
||||
<h3>
|
||||
<span t-esc="(dest and dest.name) or '—'"/>
|
||||
@@ -184,7 +187,13 @@
|
||||
<strong t-esc="actual_str"/>
|
||||
</t>
|
||||
<t t-elif="cv and cv.value_attachment_id">
|
||||
<span style="font-size: 7.5pt; color: #555;">[Attachment]</span>
|
||||
<!-- Photo: render as a thumbnail (height-capped); fall back to filename. -->
|
||||
<img t-att-src="'/web/image/%s' % cv.value_attachment_id.id"
|
||||
style="max-height: 80px; max-width: 160px; border: 1px solid #ccc;"
|
||||
t-att-alt="cv.value_attachment_id.name"/>
|
||||
<div style="font-size: 7.5pt; color: #555;">
|
||||
<span t-esc="cv.value_attachment_id.name"/>
|
||||
</div>
|
||||
</t>
|
||||
</td>
|
||||
<td>
|
||||
|
||||
Reference in New Issue
Block a user