Files
Odoo-Modules/fusion_plating/fusion_plating_jobs/views/fp_certificate_views.xml
gsinghpal 8831176ec4 feat(certificates): Fischerscope thickness-report upload wizard
Operators now drop a .docx or .pdf Fischerscope XDAL 600 export
on the cert form's Thickness Report tab. The wizard parses the
readings, calibration std, operator + date metadata, and the
embedded microscope image, then shows them for review before
recording on fp.certificate.

  Operator         Wizard               Certificate
  ─────────────────────────────────────────────────────────────
  Click "Upload    Parse .docx /        - thickness_reading_ids
   Thickness         .pdf →               written (3 rows)
   Report"         Show 3 readings      - x_fc_local_thickness
  Pick file        + metadata             _pdf attached (original
  Click Parse      Click Save             file)
                                        - microscope image as
                                          ir.attachment on cert
                                        - chatter post
  ─────────────────────────────────────────────────────────────

When parse can't find readings (unrecognised format), wizard falls
through to manual state — operator can still save, file lands on
the cert as-is for the existing CoC page-2 merge logic.

Closes the gap in the S19 enforcement: x_fc_send_thickness_report
customers blocked at action_issue until the file is on file. Now
they have a parseable upload UX, not just a bare Binary field.

Architecture
- fischerscope_parser.py: pure-Python lib, branches on extension,
  python-docx + PyPDF2 already on entech (no new deps). Regex
  extraction returns {readings, metadata, image, errors}.
- fp.thickness.upload.wizard: TransientModel with upload/review/
  manual states. Lazy-imports parser at action_parse time to dodge
  Python 3.11 partial-init relative-import error.
- 27 tests (TestFischerscopeParser 9 + TestThicknessUploadWizard 8
  + the rehoused TestActionIssueGates 10) — all green on entech.

Same metadata copies onto every reading row, microscope image
attaches once at cert level (decisions 2026-05-19).

Drive-by fixes uncovered while running tests on entech:
- fp.certificate.action_issue: guard rec.company_id access with
  field-existence check. Lazy-fill-signer branch crashed when
  certified_by_id was unset on certs that don't carry a company_id
  field. Pre-existing bug that never fired in production because
  jobs auto-fill certified_by_id before reaching this branch.
- test_action_issue_gates: set x_fc_send_thickness_report=False on
  the test partner. Field defaults to True so every cert in this
  class hit the thickness gate; tests were never able to verify
  the other gates in isolation.
- Tests directory missing test_action_issue_gates.py on entech.
  Synced; turns out the 2026-05-18 "changes" commit added the file
  locally but the deploy script never copied tests/.

Module: fusion_plating_certificates 19.0.6.4.0 → 19.0.7.0.0

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 01:05:16 -04:00

151 lines
8.0 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ============================================================ -->
<!-- S19 — Surface Fischerscope thickness PDF on the cert form -->
<!-- ============================================================ -->
<!-- Without this extension the operator has no way to know, -->
<!-- before clicking Issue, whether the QC's Fischerscope PDF -->
<!-- will be appended to the CoC. After Issue, no indicator that -->
<!-- the merged PDF actually contains it. This extension fixes -->
<!-- both gaps with a banner + smart button + clickable file. -->
<record id="fp_certificate_view_form_jobs"
model="ir.ui.view">
<field name="name">fp.certificate.form.inherit.jobs</field>
<field name="model">fp.certificate</field>
<field name="inherit_id"
ref="fusion_plating_certificates.fp_certificate_view_form"/>
<field name="arch" type="xml">
<!-- 1. Smart button: linked Plating Job, and a separate -->
<!-- smart button for the Fischerscope-source QC. -->
<xpath expr="//div[@name='button_box']" position="inside">
<button name="action_open_job"
type="object"
class="oe_stat_button"
icon="fa-cogs"
invisible="not x_fc_job_id">
<field name="x_fc_job_id" widget="statinfo"
string="Work Order"/>
</button>
<button name="action_view_thickness_qc"
type="object"
class="oe_stat_button"
icon="fa-microscope"
invisible="not x_fc_thickness_qc_id">
<div class="o_field_widget o_stat_info">
<span class="o_stat_text">
<field name="x_fc_thickness_status" widget="badge"
decoration-info="x_fc_thickness_status == 'pending'"
decoration-success="x_fc_thickness_status == 'merged'"/>
</span>
<span class="o_stat_text">Fischerscope</span>
</div>
</button>
</xpath>
<!-- 2. Banner row above the title — explicit, can't miss. -->
<!-- Three states with distinct alert classes. -->
<xpath expr="//sheet/div[@class='oe_title']" position="before">
<div class="alert alert-info" role="alert"
invisible="x_fc_thickness_status != 'pending'">
<i class="fa fa-info-circle" title="Info"
aria-label="Info"/>
<strong> Fischerscope thickness PDF is on file.</strong>
It will be automatically appended as page&#160;2 of
the CoC when you click <strong>Issue</strong>.
</div>
<div class="alert alert-success" role="alert"
invisible="x_fc_thickness_status != 'merged'">
<i class="fa fa-check-circle" title="Merged"
aria-label="Merged"/>
<strong> Fischerscope thickness report merged.</strong>
The issued CoC PDF includes the Fischerscope report
as page&#160;2 — open the Certificate&#160;PDF tab to verify.
</div>
<div class="alert alert-warning" role="alert"
invisible="state != 'draft' or x_fc_thickness_status != 'none' or not partner_id"
style="margin-top:0;">
<i class="fa fa-exclamation-triangle" title="Warning"
aria-label="Warning"/>
<strong> No Fischerscope PDF available.</strong>
Drop the PDF into the <em>Thickness Report
(Fischerscope)</em> tab below, or upload it on the
linked QC check, before issuing. Thickness Report
certs cannot issue without thickness data.
</div>
</xpath>
<!-- 3. Add a Thickness Report tab right next to the -->
<!-- Certificate PDF tab so operator can preview the -->
<!-- Fischerscope file before merging into the cert. -->
<xpath expr="//notebook/page[@name='pdf']" position="after">
<page string="Thickness Report (Fischerscope)"
name="thickness_pdf">
<group>
<field name="x_fc_thickness_status" widget="badge"
readonly="1"
decoration-muted="x_fc_thickness_status == 'none'"
decoration-info="x_fc_thickness_status == 'pending'"
decoration-success="x_fc_thickness_status == 'merged'"/>
<field name="x_fc_thickness_qc_id" readonly="1"
invisible="not x_fc_thickness_qc_id"/>
<field name="x_fc_thickness_pdf_id" readonly="1"
widget="many2one_binary"
invisible="not x_fc_thickness_pdf_id"/>
</group>
<separator string="Upload Fischerscope Report"/>
<div class="oe_button_box">
<button name="%(fusion_plating_certificates.action_fp_thickness_upload_wizard)d"
type="action"
class="btn-primary"
string="Upload Thickness Report"
context="{'default_certificate_id': id}"
invisible="state != 'draft'"/>
</div>
<div class="text-muted">
<p>
Drop the <code>.docx</code> or <code>.pdf</code>
file straight from the Fischerscope&#160;XDAL&#160;600.
The wizard reads the readings, calibration set,
and operator info, lets you review them, and
attaches the original file to this certificate.
</p>
</div>
<separator string="Attached File"
invisible="not x_fc_local_thickness_pdf"/>
<group invisible="not x_fc_local_thickness_pdf">
<field name="x_fc_local_thickness_pdf"
filename="x_fc_local_thickness_pdf_filename"
readonly="1"/>
<field name="x_fc_local_thickness_pdf_filename"
invisible="1"/>
</group>
<div class="text-muted"
invisible="x_fc_thickness_status != 'none'">
<p>
No Fischerscope thickness PDF has been
uploaded yet. The CoC will be issued without
an appended thickness report. Either drop the
PDF into the upload field above, OR upload it
on the linked QC check and re-open this cert.
</p>
</div>
<div class="text-muted"
invisible="x_fc_thickness_status != 'pending'">
<p>
<i class="fa fa-arrow-up" title="Action"
aria-label="Action"/>
Click <strong>Issue</strong> in the header
and the Fischerscope PDF will be merged into
page&#160;2 of the CoC.
</p>
</div>
</page>
</xpath>
</field>
</record>
</odoo>