fix(portal): correct terminology — Sales Orders everywhere (revert Purchase Orders rename)

The customer's Purchase Order is the doc they send US — a separate
artifact, often a PDF attachment on the quote. What lives in our
system is the Sales Order we create in response. Labeling the SO
list as "Purchase Orders" in the customer portal was a wrong-side
mapping.

Reverts and renames in this commit:

- Sidebar item label: "Purchase Orders" → "Sales Orders" (key stays
  odoo_orders; URL still /my/orders). _FP_SIDEBAR_LAYOUT.

- Dashboard KPI tile: "Active POs" → "Active Sales Orders". Link
  hint: "View POs →" → "View orders →". Link target updated to the
  current /my/orders (the legacy /my/purchase_orders still redirects
  but we point at the canonical URL now).

- Dashboard panel: "Recent Purchase Orders" → "Recent Sales Orders".
  Empty state: "No purchase orders yet." → "No sales orders yet."
  View-all link target updated to /my/orders.

- Dashboard docs entries strip: "Purchase Orders" docs entry title
  → "Sales Orders"; URL → /my/orders.

- Removed the three Odoo template rename inherits from
  fp_sale_order_portal.xml (sale.portal_my_home_menu_sale,
  sale.portal_my_orders, sale.sale_order_portal_content). With those
  gone the stock templates emit Odoo's native "Sales Order(s)" and
  "Your Orders" wording on the list page header, breadcrumb, and
  detail page <h2> — which is now the correct terminology.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-05-18 00:30:55 -04:00
parent 4e54ecc32f
commit 25f568f225
3 changed files with 9 additions and 104 deletions

View File

@@ -126,7 +126,7 @@ class FpCustomerPortal(CustomerPortal):
{'type': 'section_label', 'label': 'Activity'},
{'type': 'item', 'key': 'fp_quote_requests', 'label': 'Quote Requests', 'icon': '📄', 'url': '/my/quote_requests'},
{'type': 'item', 'key': 'fp_configurator', 'label': 'Get a Quote', 'icon': '+', 'url': '/my/configurator'},
{'type': 'item', 'key': 'odoo_orders', 'label': 'Purchase Orders', 'icon': '🛒', 'url': '/my/orders'},
{'type': 'item', 'key': 'odoo_orders', 'label': 'Sales Orders', 'icon': '🛒', 'url': '/my/orders'},
{'type': 'item', 'key': 'fp_jobs', 'label': 'Work Orders', 'icon': '⚙️', 'url': '/my/jobs'},
{'type': 'section_label', 'label': 'Documents'},
{'type': 'item', 'key': 'fp_certifications', 'label': 'Certifications', 'icon': '📑', 'url': '/my/certifications'},

View File

@@ -38,9 +38,9 @@
<a href="/my/quote_requests" class="o_fp_kpi_hint o_fp_hint_action">View quotes →</a>
</div>
<div class="o_fp_kpi_tile">
<div class="o_fp_kpi_label">Active POs</div>
<div class="o_fp_kpi_label">Active Sales Orders</div>
<div class="o_fp_kpi_value" t-out="po_count"/>
<a href="/my/purchase_orders" class="o_fp_kpi_hint">View POs →</a>
<a href="/my/orders" class="o_fp_kpi_hint">View orders →</a>
</div>
<div class="o_fp_kpi_tile o_fp_kpi_hero">
<div class="o_fp_kpi_label">In-Flight Jobs</div>
@@ -110,11 +110,11 @@
</t>
</div>
<!-- Purchase Orders -->
<!-- Sales Orders -->
<div class="o_fp_panel">
<div class="o_fp_panel_title">
<span class="o_fp_panel_icon">🛒</span> Recent Purchase Orders
<a href="/my/purchase_orders" class="o_fp_panel_view_all">View all →</a>
<span class="o_fp_panel_icon">🛒</span> Recent Sales Orders
<a href="/my/orders" class="o_fp_panel_view_all">View all →</a>
</div>
<t t-if="recent_pos">
<t t-foreach="recent_pos[:3]" t-as="po">
@@ -125,7 +125,7 @@
</t>
</t>
<t t-else="">
<div class="o_fp_panel_row text-muted">No purchase orders yet.</div>
<div class="o_fp_panel_row text-muted">No sales orders yet.</div>
</t>
</div>
@@ -219,8 +219,8 @@
<t t-set="placeholder_count" t-value="'fp_portal_job_count'"/>
</t>
<t t-call="portal.portal_docs_entry">
<t t-set="title">Purchase Orders</t>
<t t-set="url" t-value="'/my/purchase_orders'"/>
<t t-set="title">Sales Orders</t>
<t t-set="url" t-value="'/my/orders'"/>
<t t-set="placeholder_count" t-value="'fp_purchase_order_count'"/>
</t>
<t t-call="portal.portal_docs_entry">

View File

@@ -95,99 +95,4 @@
</template>
<!-- ================================================================== -->
<!-- Breadcrumbs: rename "Sales Orders" → "Purchase Orders" on -->
<!-- confirmed-order pages, and "Sales Order SOXXXX" → "Purchase -->
<!-- Order SOXXXX" in the detail breadcrumb active item. -->
<!-- -->
<!-- The stock template (sale.portal_my_home_menu_sale) has two -->
<!-- adjacent <li> elements inside a t-elif chain: -->
<!-- • t-if → Quotations list crumb (state=sent/cancel) -->
<!-- • t-elif → Sales Orders list crumb (confirmed orders) -->
<!-- followed by a third <li t-if="sale_order"> that shows the -->
<!-- document name with a <span t-field="sale_order.type_name"/>. -->
<!-- -->
<!-- We replace only the confirmed-order <li t-elif> (sales-orders -->
<!-- list link) and the detail <li> (document name prefix). The -->
<!-- Quotations branch is left intact — our portal doesn't expose -->
<!-- /my/quotes from the sidebar, but we don't need to break it. -->
<!-- ================================================================== -->
<template id="fp_portal_breadcrumbs_purchase_order_rename"
inherit_id="sale.portal_my_home_menu_sale"
priority="30">
<!-- Replace the "Sales Orders" list-link breadcrumb item -->
<xpath expr="//li[@t-elif and contains(., 'Sales Orders')]" position="replace">
<li t-elif="page_name == 'order' or sale_order and sale_order.state not in ('sent', 'cancel')"
t-attf-class="breadcrumb-item #{'active ' if not sale_order else ''}">
<a t-if="sale_order" t-attf-href="/my/orders?{{ keep_query() }}">Purchase Orders</a>
<t t-else="">Purchase Orders</t>
</li>
</xpath>
<!-- Replace the detail breadcrumb item: "Sales Order SO-XXXXX" →
"Purchase Order SO-XXXXX". The original uses t-field="sale_order.type_name"
which returns "Sales Order" or "Quotation" at runtime. We hard-code
"Purchase Order" for the confirmed-order case (only this crumb fires
for state not in sent/cancel, so quotation pages are unaffected). -->
<xpath expr="//li[@t-if='sale_order' and hasclass('breadcrumb-item')]" position="replace">
<li t-if="sale_order" class="breadcrumb-item active">
<t t-if="sale_order.state in ('sent', 'cancel')">
<t t-out="sale_order.type_name"/>
</t>
<t t-else="">Purchase Order</t>
<t t-out="' ' + sale_order.name"/>
</li>
</xpath>
</template>
<!-- ================================================================== -->
<!-- /my/orders list page: rename "Your Orders" title and -->
<!-- "Sales Order #" column header -->
<!-- ================================================================== -->
<template id="fp_portal_my_orders_rename"
inherit_id="sale.portal_my_orders"
priority="30">
<!-- Rename the page title from "Your Orders" to "Purchase Orders" -->
<xpath expr="//t[@t-call='portal.portal_searchbar']" position="replace">
<t t-call="portal.portal_searchbar">
<t t-set="title">Purchase Orders</t>
</t>
</xpath>
<!-- Rename "Sales Order #" column header -->
<xpath expr="//span[@class='d-none d-md-inline'][contains(text(), 'Sales Order #')]" position="replace">
<span class="d-none d-md-inline">Purchase Order #</span>
</xpath>
</template>
<!-- ================================================================== -->
<!-- Detail page heading: "Sales Order - SO-XXXXX" → -->
<!-- "Purchase Order - SO-XXXXX" -->
<!-- -->
<!-- sale.sale_order_portal_content renders the <h2> with -->
<!-- <t t-out="sale_order.type_name"/> which evaluates to "Sales Order" -->
<!-- for confirmed orders and "Quotation" for draft/sent. We replace -->
<!-- the entire <h2> to hard-code "Purchase Order" for confirmed -->
<!-- orders and preserve "Quotation" for others. -->
<!-- ================================================================== -->
<template id="fp_sale_order_portal_content_rename"
inherit_id="sale.sale_order_portal_content"
priority="30">
<xpath expr="//div[@id='intro_row']/h2" position="replace">
<h2>
<t t-if="sale_order.state in ('sale', 'cancel', 'done')">Purchase Order</t>
<t t-else="" t-out="sale_order.type_name"/>
-
<em t-out="sale_order.name"/>
</h2>
</xpath>
</template>
</odoo>