feat: add borders, ADP Device Code, ADP/Client Portion columns and subtotals to portal view
This commit is contained in:
@@ -8,7 +8,6 @@
|
||||
- Shows client portion in sidebar instead of full order total
|
||||
- Displays ADP claim details (Client Type, Authorizer, Dates, etc.)
|
||||
- Payment amount selector shows client portion
|
||||
- Fixes confirmation text in sign and pay modals
|
||||
-->
|
||||
<odoo>
|
||||
|
||||
@@ -18,13 +17,18 @@
|
||||
<template id="sale_order_portal_sidebar_adp"
|
||||
inherit_id="sale.sale_order_portal_template"
|
||||
name="Fusion: ADP Sidebar Amount">
|
||||
|
||||
<!-- Replace the data attribute with client portion for ADP -->
|
||||
<xpath expr="//div[hasclass('o_portal_sale_sidebar')]" position="attributes">
|
||||
<attribute name="t-att-data-order-amount-total">
|
||||
sale_order.x_fc_client_portion_total if sale_order.x_fc_is_adp_sale and sale_order.x_fc_client_type == 'REG' else sale_order.amount_total
|
||||
</attribute>
|
||||
</xpath>
|
||||
|
||||
<!-- Replace the sidebar title (amount display) -->
|
||||
<xpath expr="//div[hasclass('o_portal_sale_sidebar')]//t[@t-set='title']" position="replace">
|
||||
<t t-set="title">
|
||||
<!-- ADP REG: show client portion -->
|
||||
<t t-if="sale_order.x_fc_is_adp_sale and sale_order.x_fc_client_type == 'REG'">
|
||||
<small class="text-muted d-block">Your Portion</small>
|
||||
<h2 class="mb-0 text-break">
|
||||
@@ -32,10 +36,12 @@
|
||||
t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"/>
|
||||
</h2>
|
||||
</t>
|
||||
<!-- ADP non-REG (100% funded): no payment needed -->
|
||||
<t t-elif="sale_order.x_fc_is_adp_sale and sale_order.x_fc_client_type and sale_order.x_fc_client_type != 'REG'">
|
||||
<small class="text-muted d-block">Fully ADP Funded</small>
|
||||
<h2 class="mb-0 text-break text-success">$ 0.00</h2>
|
||||
</t>
|
||||
<!-- Standard Odoo behavior for non-ADP -->
|
||||
<t t-elif="sale_order._has_to_be_paid() and sale_order.prepayment_percent != 1.0">
|
||||
<h4>Down payment</h4>
|
||||
<h2>
|
||||
@@ -56,6 +62,8 @@
|
||||
<template id="sale_order_portal_content_adp"
|
||||
inherit_id="sale.sale_order_portal_content"
|
||||
name="Fusion: ADP Details on Portal">
|
||||
|
||||
<!-- Add ADP details section after sale_info -->
|
||||
<xpath expr="//div[@id='sale_info']" position="after">
|
||||
<t t-if="sale_order.x_fc_is_adp_sale">
|
||||
<div class="col-12 col-lg-6 mb-4">
|
||||
@@ -65,53 +73,82 @@
|
||||
<tbody style="white-space:nowrap">
|
||||
<tr t-if="sale_order.x_fc_client_type">
|
||||
<th class="ps-0 pb-0">Client Type:</th>
|
||||
<td class="w-100 pb-0 text-wrap"><span t-field="sale_order.x_fc_client_type"/></td>
|
||||
<td class="w-100 pb-0 text-wrap">
|
||||
<span t-field="sale_order.x_fc_client_type"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr t-if="sale_order.x_fc_claim_number">
|
||||
<th class="ps-0 pb-0">Claim Number:</th>
|
||||
<td class="w-100 pb-0 text-wrap"><span t-field="sale_order.x_fc_claim_number"/></td>
|
||||
<td class="w-100 pb-0 text-wrap">
|
||||
<span t-field="sale_order.x_fc_claim_number"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr t-if="sale_order.x_fc_authorizer_id">
|
||||
<th class="ps-0 pb-0">Authorizer:</th>
|
||||
<td class="w-100 pb-0 text-wrap"><span t-field="sale_order.x_fc_authorizer_id"/></td>
|
||||
<td class="w-100 pb-0 text-wrap">
|
||||
<span t-field="sale_order.x_fc_authorizer_id"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr t-if="sale_order.x_fc_client_ref_1">
|
||||
<th class="ps-0 pb-0">Client Ref 1:</th>
|
||||
<td class="w-100 pb-0 text-wrap"><span t-field="sale_order.x_fc_client_ref_1"/></td>
|
||||
<td class="w-100 pb-0 text-wrap">
|
||||
<span t-field="sale_order.x_fc_client_ref_1"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr t-if="sale_order.x_fc_client_ref_2">
|
||||
<th class="ps-0 pb-0">Client Ref 2:</th>
|
||||
<td class="w-100 pb-0 text-wrap"><span t-field="sale_order.x_fc_client_ref_2"/></td>
|
||||
<td class="w-100 pb-0 text-wrap">
|
||||
<span t-field="sale_order.x_fc_client_ref_2"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr t-if="sale_order.x_fc_assessment_end_date">
|
||||
<th class="ps-0 pb-0">Assessment Date:</th>
|
||||
<td class="w-100 pb-0 text-wrap"><span t-field="sale_order.x_fc_assessment_end_date" t-options="{'widget': 'date'}"/></td>
|
||||
<td class="w-100 pb-0 text-wrap">
|
||||
<span t-field="sale_order.x_fc_assessment_end_date"
|
||||
t-options="{'widget': 'date'}"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr t-if="sale_order.x_fc_claim_authorization_date">
|
||||
<th class="ps-0 pb-0">Authorization Date:</th>
|
||||
<td class="w-100 pb-0 text-wrap"><span t-field="sale_order.x_fc_claim_authorization_date" t-options="{'widget': 'date'}"/></td>
|
||||
<td class="w-100 pb-0 text-wrap">
|
||||
<span t-field="sale_order.x_fc_claim_authorization_date"
|
||||
t-options="{'widget': 'date'}"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr t-if="sale_order.x_fc_claim_approval_date">
|
||||
<th class="ps-0 pb-0">Approval Date:</th>
|
||||
<td class="w-100 pb-0 text-wrap"><span t-field="sale_order.x_fc_claim_approval_date" t-options="{'widget': 'date'}"/></td>
|
||||
<td class="w-100 pb-0 text-wrap">
|
||||
<span t-field="sale_order.x_fc_claim_approval_date"
|
||||
t-options="{'widget': 'date'}"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr t-if="sale_order.x_fc_adp_delivery_date">
|
||||
<th class="ps-0 pb-0">Delivery Date:</th>
|
||||
<td class="w-100 pb-0 text-wrap"><span t-field="sale_order.x_fc_adp_delivery_date" t-options="{'widget': 'date'}"/></td>
|
||||
<td class="w-100 pb-0 text-wrap">
|
||||
<span t-field="sale_order.x_fc_adp_delivery_date"
|
||||
t-options="{'widget': 'date'}"/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</t>
|
||||
</xpath>
|
||||
|
||||
<!-- Add funding breakdown before totals -->
|
||||
<xpath expr="//div[@id='total']" position="before">
|
||||
<t t-if="sale_order.x_fc_is_adp_sale and sale_order.x_fc_client_type == 'REG'">
|
||||
<div class="alert alert-info mb-3 py-2">
|
||||
<strong>ADP Assisted Devices Program Order</strong><br/>
|
||||
This order is partially funded through ADP.<br/>
|
||||
<strong>Your portion:</strong>
|
||||
<span t-esc="sale_order.x_fc_client_portion_total" t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"/>
|
||||
<span class="text-muted ms-2">(ADP covers <span t-esc="sale_order.x_fc_adp_portion_total" t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"/>)</span>
|
||||
<span t-esc="sale_order.x_fc_client_portion_total"
|
||||
t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"/>
|
||||
<span class="text-muted ms-2">
|
||||
(ADP covers
|
||||
<span t-esc="sale_order.x_fc_adp_portion_total"
|
||||
t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"/>)
|
||||
</span>
|
||||
</div>
|
||||
</t>
|
||||
<t t-if="sale_order.x_fc_is_adp_sale and sale_order.x_fc_client_type and sale_order.x_fc_client_type != 'REG'">
|
||||
@@ -134,11 +171,25 @@
|
||||
<button name="o_sale_portal_amount_total_button" class="btn btn-light">
|
||||
<t t-if="sale_order.x_fc_is_adp_sale and sale_order.x_fc_client_type == 'REG'">
|
||||
Client Portion <br/>
|
||||
<span t-out="sale_order.x_fc_client_portion_total" t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}" class="fw-bold"/>
|
||||
<span
|
||||
t-out="sale_order.x_fc_client_portion_total"
|
||||
t-options="{
|
||||
'widget': 'monetary',
|
||||
'display_currency': sale_order.currency_id,
|
||||
}"
|
||||
class="fw-bold"
|
||||
/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
Full amount <br/>
|
||||
<span t-out="sale_order.amount_total" t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}" class="fw-bold"/>
|
||||
<span
|
||||
t-out="sale_order.amount_total"
|
||||
t-options="{
|
||||
'widget': 'monetary',
|
||||
'display_currency': sale_order.currency_id,
|
||||
}"
|
||||
class="fw-bold"
|
||||
/>
|
||||
</t>
|
||||
</button>
|
||||
</xpath>
|
||||
@@ -155,31 +206,44 @@
|
||||
<div t-if="sale_order._has_to_be_paid()" class="mb-3">
|
||||
<t t-if="sale_order.x_fc_is_adp_sale and sale_order.x_fc_client_type == 'REG'">
|
||||
By paying
|
||||
<span t-out="sale_order.x_fc_client_portion_total" t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}" class="fw-bold"/>,
|
||||
<span t-out="sale_order.x_fc_client_portion_total"
|
||||
t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"
|
||||
class="fw-bold"/>,
|
||||
you confirm acceptance on behalf of
|
||||
<b t-field="sale_order.partner_id.commercial_partner_id"/>
|
||||
for quotation <b t-field="sale_order.name"/>.
|
||||
This payment covers your client portion. The remaining
|
||||
<span t-out="sale_order.x_fc_adp_portion_total" t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}" class="fw-bold"/>
|
||||
<span t-out="sale_order.x_fc_adp_portion_total"
|
||||
t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"
|
||||
class="fw-bold"/>
|
||||
is funded by ADP.
|
||||
</t>
|
||||
<t t-else="">
|
||||
<span t-if="sale_order.prepayment_percent and sale_order.prepayment_percent != 1.0">
|
||||
<span id="o_sale_portal_use_amount_prepayment">
|
||||
By paying a <u>down payment</u> of
|
||||
<span t-out="amount" t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}" class="fw-bold"/>
|
||||
<t t-if="sale_order._get_prepayment_required_amount() == amount">(<b t-esc="sale_order.prepayment_percent * 100"/>%),</t>
|
||||
<span t-out="amount"
|
||||
t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"
|
||||
class="fw-bold"/>
|
||||
<t t-if="sale_order._get_prepayment_required_amount() == amount">
|
||||
(<b t-esc="sale_order.prepayment_percent * 100"/>%),
|
||||
</t>
|
||||
</span>
|
||||
<span id="o_sale_portal_use_amount_total">By paying,</span>
|
||||
</span>
|
||||
<span t-else="">
|
||||
By paying <span t-out="amount" t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}" class="fw-bold"/>,
|
||||
By paying
|
||||
<span t-out="amount"
|
||||
t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"
|
||||
class="fw-bold"/>,
|
||||
</span>
|
||||
you confirm acceptance on behalf of
|
||||
<b t-field="sale_order.partner_id.commercial_partner_id"/>
|
||||
for the <b data-id="total_amount" t-field="sale_order.amount_total"/> quote.
|
||||
</t>
|
||||
<b t-if="sale_order.payment_term_id" t-field="sale_order.payment_term_id.note" class="o_sale_payment_terms"/>
|
||||
<b t-if="sale_order.payment_term_id"
|
||||
t-field="sale_order.payment_term_id.note"
|
||||
class="o_sale_payment_terms"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
@@ -198,9 +262,11 @@
|
||||
<b t-field="sale_order.partner_id.commercial_partner_id"/>
|
||||
for quotation <b t-field="sale_order.name"/>.
|
||||
Your client portion is
|
||||
<b t-out="sale_order.x_fc_client_portion_total" t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"/>.
|
||||
<b t-out="sale_order.x_fc_client_portion_total"
|
||||
t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"/>.
|
||||
The remaining
|
||||
<span t-out="sale_order.x_fc_adp_portion_total" t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"/>
|
||||
<span t-out="sale_order.x_fc_adp_portion_total"
|
||||
t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"/>
|
||||
is funded by ADP.
|
||||
</t>
|
||||
<t t-elif="sale_order.x_fc_is_adp_sale and sale_order.x_fc_client_type and sale_order.x_fc_client_type != 'REG'">
|
||||
@@ -218,4 +284,161 @@
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
|
||||
<!-- ================================================================
|
||||
6. PORTAL TABLE: ADP table with borders, device code, portions
|
||||
================================================================ -->
|
||||
<template id="sale_order_portal_table_adp"
|
||||
inherit_id="sale.sale_order_portal_content"
|
||||
name="Fusion: ADP Portal Table with Borders and Columns">
|
||||
|
||||
<!-- Hide original table for ADP orders -->
|
||||
<xpath expr="//div[@name='sol_table']" position="attributes">
|
||||
<attribute name="t-if">not sale_order.x_fc_is_adp_sale</attribute>
|
||||
</xpath>
|
||||
|
||||
<!-- Add ADP-specific table after the original -->
|
||||
<xpath expr="//div[@name='sol_table']" position="after">
|
||||
<div t-if="sale_order.x_fc_is_adp_sale" name="sol_table_adp" class="table-responsive">
|
||||
<style>
|
||||
.fc-adp-portal th { font-size: 0.78rem !important; white-space: nowrap; }
|
||||
.fc-adp-portal td { font-size: 0.82rem !important; }
|
||||
.fc-adp-portal .adp-col-bg { background-color: #f5faff; }
|
||||
.fc-adp-portal .client-col-bg { background-color: #fffaf0; }
|
||||
</style>
|
||||
<table class="table table-sm table-bordered fc-adp-portal"
|
||||
id="sales_order_table"
|
||||
t-att-data-order-id="sale_order.id"
|
||||
t-att-data-token="sale_order.access_token">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th class="text-center" style="width: 9%;">ADP Code</th>
|
||||
<th class="text-start" id="product_name_header">Products</th>
|
||||
<th class="text-end" id="product_qty_header">Quantity</th>
|
||||
<th class="text-end d-none d-sm-table-cell" id="product_unit_price_header">Unit Price</th>
|
||||
<th t-if="display_taxes" class="text-end d-none d-md-table-cell">Taxes</th>
|
||||
<th class="text-end" style="background-color: #e3f2fd;">ADP Portion</th>
|
||||
<th class="text-end" style="background-color: #fff3e0;">Client Portion</th>
|
||||
<th class="text-end" id="product_total_header">Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-set="adp_total_cols" t-value="8 - (0 if display_taxes else 1)"/>
|
||||
<t t-foreach="lines_to_report" t-as="line">
|
||||
<t t-if="not line._get_display_grouped_section()">
|
||||
<!-- Section Header -->
|
||||
<tr t-if="line.display_type == 'line_section'" name="tr_section" class="bg-200 fw-bold">
|
||||
<td t-att-colspan="adp_total_cols" name="td_section_line">
|
||||
<span t-field="line.name"/>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Note Line -->
|
||||
<tr t-elif="line.display_type == 'line_note'" name="tr_note" class="fst-italic text-muted">
|
||||
<td t-att-colspan="adp_total_cols" name="td_note_line">
|
||||
<span t-field="line.name"/>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Product Line -->
|
||||
<tr t-elif="not line.display_type" name="tr_product">
|
||||
<td class="text-center">
|
||||
<span t-esc="line.product_id.x_fc_adp_device_code or ''"/>
|
||||
</td>
|
||||
<td name="td_product_name">
|
||||
<span t-field="line.name"/>
|
||||
</td>
|
||||
<td name="td_product_quantity" class="text-end">
|
||||
<div id="quote_qty">
|
||||
<span t-field="line.product_uom_qty"/>
|
||||
<span t-field="line.product_uom_id"/>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-end d-none d-sm-table-cell">
|
||||
<span t-field="line.price_unit"
|
||||
t-options="{'widget': 'monetary', 'display_currency': line.currency_id}"/>
|
||||
</td>
|
||||
<td t-if="display_taxes" class="text-end d-none d-md-table-cell">
|
||||
<span t-out="', '.join(map(lambda x: (x.name), line.tax_ids))"/>
|
||||
</td>
|
||||
<td class="text-end adp-col-bg">
|
||||
<span t-field="line.x_fc_adp_portion"
|
||||
t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"/>
|
||||
</td>
|
||||
<td class="text-end client-col-bg">
|
||||
<span t-field="line.x_fc_client_portion"
|
||||
t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"/>
|
||||
</td>
|
||||
<td t-if="not line.is_downpayment" name="td_product_subtotal" class="text-end">
|
||||
<span t-field="line.price_subtotal"/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<!-- Grouped Section Display -->
|
||||
<tr t-foreach="line._get_grouped_section_summary(display_taxes)"
|
||||
t-as="section_line"
|
||||
name="tr_section_group"
|
||||
class="bg-200 fw-bold">
|
||||
<td/>
|
||||
<td name="td_section_group_name">
|
||||
<span t-field="line.name"/>
|
||||
</td>
|
||||
<td class="text-end text-nowrap"/>
|
||||
<td class="text-end text-nowrap d-none d-sm-table-cell">
|
||||
<span t-out="section_line['price_subtotal']"
|
||||
t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"/>
|
||||
</td>
|
||||
<td t-if="display_taxes" class="text-end d-none d-md-table-cell">
|
||||
<span t-out="', '.join(section_line['tax_labels'])"/>
|
||||
</td>
|
||||
<td class="text-end adp-col-bg"/>
|
||||
<td class="text-end client-col-bg"/>
|
||||
<td name="td_section_group_total" class="text-end">
|
||||
<span t-out="section_line['price_subtotal']"
|
||||
t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
|
||||
<!-- ================================================================
|
||||
7. PORTAL TOTALS: ADP/Client portion subtotals
|
||||
================================================================ -->
|
||||
<template id="sale_order_portal_totals_adp"
|
||||
inherit_id="sale.sale_order_portal_content_totals_table"
|
||||
name="Fusion: ADP Portal Totals">
|
||||
<xpath expr="//table[@name='sale_order_totals_table']" position="before">
|
||||
<t t-if="sale_order.x_fc_is_adp_sale">
|
||||
<table class="table table-sm table-bordered mb-1">
|
||||
<tr style="background-color: #e3f2fd;">
|
||||
<td class="ps-2"><strong>Total ADP Portion</strong></td>
|
||||
<td class="text-end pe-2">
|
||||
<strong>
|
||||
<span t-field="sale_order.x_fc_adp_portion_total"
|
||||
t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"/>
|
||||
</strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="background-color: #fff3e0;">
|
||||
<td class="ps-2"><strong>Total Client Portion</strong></td>
|
||||
<td class="text-end pe-2">
|
||||
<strong>
|
||||
<span t-field="sale_order.x_fc_client_portion_total"
|
||||
t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"/>
|
||||
</strong>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</t>
|
||||
</xpath>
|
||||
<xpath expr="//table[@name='sale_order_totals_table']" position="attributes">
|
||||
<attribute name="t-att-class">'table table-sm' + (' table-bordered' if sale_order.x_fc_is_adp_sale else '')</attribute>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
|
||||
Reference in New Issue
Block a user