fix(portal): 5 hotfixes - /my route, button sizing, clickable cards, state sync, SO doc

1. /my now serves the FP dashboard (stock Odoo home was leaking
   through because parent route declared ['/my', '/my/home'] but my
   override only listed /my/home).
2. Button padding bumped to .5rem 1rem + font 1rem so o_fp_btn matches
   Odoo's standard Bootstrap button rhythm. Ghost button drops its
   custom padding override.
3. .o_fp_job_card on /my/home + /my/jobs is now an <a> wrapping the
   whole card area — full row is the click target, not just the WO
   number. Inner <a> on job.name dropped to avoid nested anchors;
   focus-visible outline added for keyboard nav.
4. fp.job.write() now mirrors state -> fp.portal.job.state via new
   _FP_JOB_STATE_TO_PORTAL_STATE map (confirmed->received,
   in_progress->in_progress, done->ready_to_ship). Fixes the bug where
   completed backend jobs left the portal stuck on 'in_progress'.
   'on_hold' and 'cancelled' intentionally not mirrored — manager
   choice what to surface.
5. Sales Order Confirmation now surfaces in the 'From You' group on
   the job detail page, pulled via job.x_fc_job_id.sale_order_id ->
   /report/pdf/sale.report_saleorder/<id>. Falls back to the upload
   placeholder when no SO is linked.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-05-17 03:13:00 -04:00
parent edcc325483
commit 28220f0732
7 changed files with 159 additions and 38 deletions

View File

@@ -67,12 +67,10 @@
<t t-if="recent_jobs">
<t t-foreach="recent_jobs[:3]" t-as="job">
<div class="o_fp_job_card">
<a t-att-href="'/my/jobs/%s' % job.id" class="o_fp_job_card">
<div class="o_fp_job_header">
<div>
<a t-att-href="'/my/jobs/%s' % job.id"
class="o_fp_job_ref text-decoration-none"
t-out="job.name"/>
<span class="o_fp_job_ref" t-out="job.name"/>
<span class="o_fp_job_meta">
<t t-if="job.quantity"><t t-out="job.quantity"/> units</t>
<t t-if="job.target_ship_date"> · ETA <span t-field="job.target_ship_date" t-options='{"widget": "date"}'/></t>
@@ -102,20 +100,16 @@
<!-- Doc chips: CoC + tracking (V1) -->
<div class="o_fp_job_docs">
<t t-if="job.coc_attachment_id">
<t t-call="fusion_plating_portal.fp_portal_doc_chip">
<t t-set="doc" t-value="{'icon': '📑', 'label': 'CoC', 'url': '/my/jobs/%s/coc' % job.id}"/>
</t>
<span class="o_fp_doc_chip">📑 CoC</span>
</t>
<t t-else="">
<t t-call="fusion_plating_portal.fp_portal_doc_chip">
<t t-set="doc" t-value="{'icon': '📑', 'label': 'CoC', 'pending': True}"/>
</t>
<span class="o_fp_doc_chip o_fp_doc_chip_pending">📑 CoC · pending</span>
</t>
<t t-if="job.tracking_ref">
<span class="o_fp_doc_chip">📦 <span t-out="job.tracking_ref"/></span>
</t>
</div>
</div>
</a>
</t>
<t t-if="job_count > 3">

View File

@@ -436,12 +436,10 @@
<t t-if="jobs">
<div class="o_fp_dashboard">
<t t-foreach="jobs" t-as="job">
<div class="o_fp_job_card">
<a t-att-href="'/my/jobs/%s' % job.id" class="o_fp_job_card">
<div class="o_fp_job_header">
<div>
<a t-att-href="'/my/jobs/%s' % job.id"
class="o_fp_job_ref text-decoration-none"
t-out="job.name"/>
<span class="o_fp_job_ref" t-out="job.name"/>
<span class="o_fp_job_meta">
<t t-if="job.quantity"><t t-out="job.quantity"/> units</t>
<t t-if="job.target_ship_date"> · ETA <span t-field="job.target_ship_date" t-options='{"widget": "date"}'/></t>
@@ -465,7 +463,7 @@
]"/>
<t t-set="active_state" t-value="'warn' if job.state == 'quality_check' else 'normal'"/>
<t t-call="fusion_plating_portal.fp_portal_stepper"/>
</div>
</a>
</t>
</div>
</t>