Files
enterprise-addons/sale_subscription/views/sale_subscription_portal_templates.xml

716 lines
47 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="subscription_so_portal_template" inherit_id="sale.sale_order_portal_template">
<a id="o_sale_portal_paynow" position="attributes">
<attribute name="t-elif" add="sale_order.subscription_state != '5_renewed'" separator="and"/>
</a>
<div id="portal_sale_content" position="before">
<div class="alert alert-info text-center" role="alert" t-if="sale_order.subscription_id and sale_order.subscription_state in ['2_renewal', '7_upsell']">
<a class="alert-info alert-link" t-att-href="sale_order.subscription_id.get_portal_url()"><i class="oi oi-arrow-right me-1"/>Back to your subscription</a>
</div>
</div>
<t t-call="payment.state_header" position="attributes">
<attribute name="t-if">sale_order.get_portal_last_transaction().operation != 'validation'</attribute>
</t>
<!-- Need to be present for js -->
<div id="sale_order_sidebar_button" position="inside">
<button role="button" class="mt8 btn btn-primary w-100 d-none" data-bs-toggle="modal" data-bs-target="#wc-modal-change-plan" href="#"
t-if="sale_order.is_subscription and sale_order.plan_id.related_plan_id and sale_order._can_be_edited_on_portal()" id="o_change_plan">
Change Plan
</button>
</div>
<div id="modalaccept" position="after">
<t t-if="sale_order.is_subscription">
<!-- ====== MODAL: Switch Plan ====== -->
<div role="dialog" t-attf-class="modal fade" id="wc-modal-change-plan" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<header class="modal-header">
<h4 class="modal-title">
Change Plan for <span t-field="sale_order.display_name" class="text-primary"/>
</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"/>
</header>
<form method="post" t-attf-action="/my/subscriptions/#{sale_order.id}/change_plan?access_token=#{sale_order.access_token}">
<input class="d-none" name="csrf_token" t-att-value="request.csrf_token()"/>
<main class="modal-body">
<select id="subscription-change-plan-select" class="form-select" name="plan_id">
<option t-att-value="sale_order.plan_id.id" t-out="sale_order.plan_id.name"/>
<t t-foreach="sale_order.plan_id.related_plan_id" t-as="plan">
<option t-att-value="plan.id" t-out="plan.name"/>
</t>
</select>
</main>
<footer class="modal-footer">
<button class="btn btn-primary">Submit</button>
</footer>
</form>
</div>
</div>
</div>
<!-- ====== MODAL: Pause Subscription ====== -->
<div role="dialog" t-attf-class="modal fade" id="wc-modal-pause" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<header class="modal-header">
<h4 class="modal-title">
Pause <span t-field="sale_order.display_name" class="text-primary"/>
</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"/>
</header>
<form method="post" t-attf-action="/my/subscriptions/#{sale_order.id}/pause?access_token=#{sale_order.access_token}">
<input class="d-none" name="csrf_token" t-att-value="request.csrf_token()"/>
<t t-set="modal_start_time" t-value="sale_order.user_pause_start or sale_order.next_invoice_date or sale_order.start_date"/>
<main t-if="modal_start_time" class="modal-body d-flex">
<t t-set="modal_max_pause_time" t-value="modal_start_time + sale_order.plan_id.billing_period"/>
Pause the subscription from<span class="mx-1" t-field="sale_order.next_invoice_date"/> to
<input type="text" id="start" name="until"
class="form-control datetimepicker-input bg-transparent rounded p-0 d-inline w-auto ms-1"
t-att-value="modal_start_time + relativedelta(days=1)"
t-att-data-min-date="modal_start_time + relativedelta(days=1)"
data-widget="datetime-picker" data-widget-type="date"
t-att-data-max-date="modal_max_pause_time" />
</main>
<footer class="modal-footer">
<button class="btn btn-primary">Submit</button>
<span class="btn btn-secondary" data-bs-dismiss="modal">Close</span>
</footer>
</form>
</div>
</div>
</div>
<!-- ====== MODAL: Resume Subscription ====== -->
<div role="dialog" t-attf-class="modal fade" id="wc-modal-resume" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<header class="modal-header">
<h4 class="modal-title">
Resume <span t-field="sale_order.display_name" class="text-primary"/>
</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"/>
</header>
<form method="post" t-attf-action="/my/subscriptions/#{sale_order.id}/resume?access_token=#{sale_order.access_token}">
<input class="d-none" name="csrf_token" t-att-value="request.csrf_token()"/>
<main class="modal-body">
Do you want to resume the subscription today?<br/>
Next invoice date: <t t-if="sale_order.state == 'sale' and next_invoice_date_at_resume" t-out="format_date(next_invoice_date_at_resume)"/>
</main>
<footer class="modal-footer">
<button class="btn btn-primary">Resume</button>
<span class="btn btn-secondary" data-bs-dismiss="modal">Close</span>
</footer>
</form>
</div>
</div>
</div>
</t>
</div>
</template>
<template id="sale_subscription_portal_templates_warnings">
<div class="alert alert-warning pb-0" role="alert">
<p class="fst-italic text-muted">
<t t-if="sale_order.plan_id.user_closable_options == 'at_date'">
You are about to permanently close a subscription that is valid until
&amp;nbsp;<span t-field="sale_order.next_invoice_date"/>.
</t>
<t t-else="">
<t t-set="end_of_period_date" t-value="sale_order.next_invoice_date - relativedelta(days=1)"/>
Your subscription will be closed on the <span t-out="format_date(end_of_period_date)"/>.
</t>
</p>
</div>
</template>
<template id="subscription_portal_template" name="Subscription" inherit_id="sale.sale_order_portal_template" primary="True">
<div id="modalaccept" position="after">
<!-- ====== MODAL: Close Subscription Initialization ====== -->
<div role="dialog" class="modal fade" id="wc-modal-close-init" t-if="display_close" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<header class="modal-header">
<h4 class="modal-title">
Close Subscription <span t-field="sale_order.display_name" class="text-primary"/>
</h4>
</header>
<form method="post" t-attf-action="/my/subscriptions/#{sale_order.id}/close?access_token=#{sale_order.access_token}">
<input class="d-none" name="csrf_token" t-att-value="request.csrf_token()"/>
<main class="modal-body">
<t t-call="sale_subscription.sale_subscription_portal_templates_warnings"/>
<h3>We are sorry to see you go.</h3>
<p>Tell us, why are you leaving?</p>
<t t-if="any(reason.visible_in_portal for reason in close_reasons)">
<div class="mb-3">
<select id="subscription-close-select" class="form-select" name="close_reason_id">
<option value="">Choose a reason...</option>
<t t-foreach="close_reasons" t-as="close_reason">
<t t-if="close_reason.visible_in_portal">
<option t-att-value="close_reason.id" t-att-data-retention="not (close_reason.empty_retention_message or close_reason.retention_button_text == False or close_reason.retention_button_link == False)" t-out="close_reason.name"/>
</t>
</t>
</select>
</div>
</t>
<t t-else="">
<div class="mb-3">
<textarea class="form-control" name="closing_text" style="width: 100%;" rows="4"></textarea>
</div>
</t>
</main>
<footer class="modal-footer">
<div class="tooltip-wrapper" data-tooltip="Choose a closing reason before submitting">
<a role="button" data-bs-toggle="modal" href="#"
data-bs-target="#wc-modal-close-retain"
class="btn btn-primary subscription-close-init-retain d-none">
Submit
</a>
<button t-attf-class="btn btn-primary subscription-close-init-noretain subscription-close-finish
{{ 'disabled' if any(reason.visible_in_portal for reason in close_reasons) else '' }}">
Submit
</button>
</div>
<button type="button" class="btn btn-light" data-bs-dismiss="modal">Discard, I want to stay</button>
</footer>
</form>
</div>
</div>
</div>
<!-- ====== MODAL: Close Subscription Retention ====== -->
<div role="dialog" class="modal fade" id="wc-modal-close-retain" t-if="display_close" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<header class="modal-header">
<h4 class="modal-title">
Close Subscription <span t-field="sale_order.display_name" class="text-primary"/>
</h4>
</header>
<main class="modal-body">
<t t-call="sale_subscription.sale_subscription_portal_templates_warnings"/>
<t t-foreach="close_reasons" t-as="close_reason">
<t t-if="close_reason.visible_in_portal and not (close_reason.empty_retention_message or close_reason.retention_button_text == False or close_reason.retention_button_link == False)">
<div t-att-data-id="close_reason.id" class="subscription-close-message" t-field="close_reason.retention_message"></div>
</t>
</t>
</main>
<footer class="modal-footer">
<t t-foreach="close_reasons" t-as="close_reason">
<t t-if="close_reason.visible_in_portal and not (close_reason.empty_retention_message or close_reason.retention_button_text == False or close_reason.retention_button_link == False)">
<a
t-att-data-id="close_reason.id"
role="button"
t-att-href="close_reason.retention_button_link"
class="btn btn-primary subscription-close-link"
t-field="close_reason.retention_button_text"
></a>
</t>
</t>
<button class="btn btn-light subscription-close-finish">No thanks, close my account</button>
</footer>
</div>
</div>
</div>
</div>
<t t-call="portal.portal_record_sidebar" position="replace">
<t t-call="sale_subscription.subscription_portal_sidebar"/>
</t>
<div id="portal_sale_content" position="before">
<t t-set="upsell_url" t-value="sale_order._get_upsell_portal_url()"/>
<t t-set="renewal_url" t-value="sale_order._get_renewal_portal_url()"/>
<div class="alert alert-warning text-center" role="alert" t-if="upsell_url or renewal_url">
<t t-if="upsell_url and renewal_url">There is a <a t-att-href="upsell_url">quotation</a> and <a t-att-href="renewal_url">renewal</a> quotation existing for this subscription, please confirm them or reject them.</t>
<t t-elif="upsell_url">There is a <a t-att-href="upsell_url" class="alert-link">quotation</a> existing for this subscription, please confirm it or reject it.</t>
<t t-elif="renewal_url">There is a <a t-att-href="renewal_url" class="alert-link">renewal</a> quotation existing for this subscription, please confirm it or reject it.</t>
</div>
<t t-if="sale_order.user_pause_start and sale_order.next_invoice_date &gt; datetime.date.today()">
<div t-if="sale_order.user_pause_start &lt;= datetime.date.today()" class="alert alert-warning text-center">
Your subscription is paused until <span t-field="sale_order.next_invoice_date"/>
</div>
<div t-if="sale_order.user_pause_start &gt; datetime.date.today()" class="alert alert-warning text-center">
Your subscription will be paused from <span t-field="sale_order.user_pause_start"/> until <span t-field="sale_order.next_invoice_date"/>
</div>
</t>
</div>
</template>
<template id="subscription_portal_content" name="Subscription" inherit_id="sale.sale_order_portal_content" primary="True">
<div id="introduction" position="before">
<div class="alert alert-danger text-center" role="alert" t-if="sale_order.subscription_state == '3_progress' and sale_order.next_invoice_date &lt; datetime.date.today()">
Your subscription is expired, will be closed soon.
<a t-if="(providers_sudo or tokens_sudo) and sale_order.amount_total> 0 and display_payment_message" href="#payment_message" class="alert-link">Pay now</a>
<t t-else="">Pay now</t>
</div>
<div class="alert alert-warning"
role="alert"
t-if="sale_order.is_closing">
<span>Your subscription is about to end on the <span t-field="sale_order.end_date"/>.</span>
</div>
</div>
<div id="intro_row" position="replace">
<div id="intro_row" class="d-flex gap-2 align-items-center">
<h2 class="mb-0">
<t t-if="sale_order.is_subscription and sale_order.state == 'sale'">
<t t-out="sale_order.name"/>
</t>
<t t-else="">
<t t-out="sale_order.type_name"/> -
<em t-out="sale_order.name"/>
</t>
</h2>
<span t-if="sale_order.subscription_state in ['3_progress', '4_paused'] and sale_order.next_invoice_date &lt; datetime.date.today()" class="badge rounded-pill text-bg-danger align-middle smaller"><i class="fa fa-fw fa-repeat"/> To Renew</span>
<span
t-elif="sale_order.subscription_state == '3_progress' and not (sale_order.user_pause_start and sale_order.user_pause_start &lt;= datetime.date.today() and sale_order.next_invoice_date &gt; datetime.date.today())"
class="badge rounded-pill text-bg-success align-middle smaller">
<i class="fa fa-fw fa-check"/> In Progress
</span>
<span t-elif="(sale_order.subscription_state == '4_paused') or (sale_order.user_pause_start and sale_order.user_pause_start &lt;= datetime.date.today() and sale_order.next_invoice_date &gt; datetime.date.today())" class="badge rounded-pill text-bg-success align-middle smaller"><i class="fa fa-fw fa-check"/> Paused</span>
<span t-elif="sale_order.subscription_state == '5_renewed'" class="badge rounded-pill text-bg-secondary align-middle smaller"><i class="fa fa-fw fa-check"/> Renewed</span>
<span t-elif="sale_order.subscription_state == '6_churn'" class="badge rounded-pill text-bg-dark align-middle smaller"><i class="fa fa-fw fa-remove"/> Closed</span>
<span
t-if="sale_order.is_closing"
class="badge rounded-pill text-bg-warning align-middle smaller">
<i class="fa fa-fw fa-remove"/> Closing
</span>
</div>
</div>
<span id="sale_info_title" position="replace">
<span id="sale_info_title">
<h5 class="mb-1">
Your Subscription
</h5>
<hr class="mt-1 mb-2"/>
</span>
</span>
<tbody id="sale_info_table" position="replace">
<tbody style="white-space:nowrap">
<tr t-if="sale_order._has_to_be_signed() or sale_order._has_to_be_paid()">
<th class="ps-0 pb-0">Date:</th>
<td class="w-100 pb-0 text-wrap"><span t-field="sale_order.date_order" t-options='{"widget": "date"}'/></td>
</tr>
<tr t-if="sale_order._has_to_be_signed() or sale_order._has_to_be_paid()">
<th class="ps-0 pb-0">Expiration Date:</th>
<td class="w-100 pb-0 text-wrap"><span t-field="sale_order.validity_date" t-options='{"widget": "date"}'/></td>
</tr>
<tr t-if="sale_order.plan_id">
<th class="ps-0 pb-0">Plan:</th>
<td class="w-100 pb-0 text-wrap"><span t-field="sale_order.sudo().plan_id.name"/></td>
<td>
<a role="button" class="link-primary" data-bs-toggle="modal" data-bs-target="#wc-modal-change-plan" href="#"
t-if="sale_order.is_subscription and sale_order.plan_id.related_plan_id and sale_order._can_be_edited_on_portal()">
(Change Plan)
</a>
</td>
</tr>
<tr t-if="sale_order.client_order_ref or sale_order.subscription_id.name">
<th class="ps-0 pb-0">Reference:</th>
<td class="w-100 pb-0"><em t-out="sale_order.client_order_ref or sale_order.subscription_id.name"/></td>
</tr>
<tr t-if="sale_order.start_date">
<th class="ps-0 pb-0">Start Date:</th>
<td class="w-100 pb-0"><span t-field="sale_order.start_date"/></td>
</tr>
<tr t-if="sale_order.end_date">
<th class="ps-0 pb-0">End Date:</th>
<td class="pb-0"><span t-field="sale_order.end_date"/></td>
</tr>
</tbody>
</tbody>
<t t-set='lines_to_report' t-value="sale_order._get_order_lines_to_report()" position="attributes">
<attribute name="t-value">next_billing_details.get('display_lines') if page_name == 'subscription' else sale_order._get_order_lines_to_report()</attribute>
</t>
<!-- ====== Subscription closed ====== -->
<div id="content" position="inside">
<section t-if="display_payment_message and not payment_amount" id="payment_message" class="mt-5">
<div t-if="company_mismatch">
<t t-call="payment.company_mismatch_warning"/>
</div>
<div class="clearfix" t-elif="next_billing_details.get('next_invoice_amount')> 0">
<p id="wc_warning_closed" t-if="sale_order.subscription_state == '6_churn'">
<h3 class="mb-1">Reopen your subscription</h3>
Your subscription is closed.
<t t-if="missing_periods == 1">If you wish to reopen it, you can pay your invoice for the current invoicing period <span t-out="next_billing_details.get('next_invoice_amount')" t-options='{"widget": "monetary", "display_currency": sale_order.currency_id}'/>.</t>
</p>
<h3 t-elif="sale_order.next_invoice_date&lt;=datetime.date.today() or not is_delivery_product" class="mb-1">
Extend Until <span t-out="format_date(sale_order.get_future_next_invoice_date())"/> (<span t-out="next_billing_details.get('next_invoice_amount')" t-options='{"widget": "monetary","display_currency": sale_order.currency_id}'/>)
<br/>
</h3>
<div t-if="sale_order.get_portal_last_transaction().state == 'pending'">
<div class="alert alert-warning m-1 mt-3">
<span>
There is already a pending payment for this subscription.
</span>
</div>
</div>
<div id="payNow" t-if="sale_order.next_invoice_date&lt;=datetime.date.today() or not is_delivery_product">
<div t-if="missing_periods &gt; 1 and sale_order.subscription_state == '6_churn'">
Please contact your sales manager if you want to reopen this subscription.
</div>
<div t-else="">
<hr class="mt-1 mb-2"/>
<t t-call="payment.form">
<t t-set="amount" t-value="next_billing_details.get('next_invoice_amount')"/>
<t t-set="landing_route" t-value="sale_order.get_portal_url()"/>
<t t-set="subscription_anticipate" t-value="True"/>
</t>
</div>
</div>
</div>
</section>
</div>
</template>
<template id="subscription_portal_sidebar">
<t t-call="portal.portal_record_sidebar">
<t t-set="classes" t-value="'col-lg-4 col-xxl-3 d-print-none'"/>
<t t-set="upsell_url" t-value="sale_order._get_upsell_portal_url()"/>
<t t-set="renewal_url" t-value="sale_order._get_renewal_portal_url()"/>
<t t-set="entries">
<div class="d-flex flex-wrap flex-column gap-4">
<div t-if="sale_order.subscription_state != '6_churn'" class="d-flex flex-column gap-2">
<div>
<span class="text-muted">Next Billing</span>
<h2 t-out="next_billing_details.get('next_invoice_amount')" t-options='{"widget": "monetary","display_currency": sale_order.currency_id}'/>
<h6>on <span t-field="sale_order.next_invoice_date"/>
<span t-if="sale_order.next_invoice_date and sale_order.next_invoice_date &lt; datetime.date.today()" class="badge ms-2 rounded-pill text-bg-danger">Overdue</span>
</h6>
</div>
<t t-if="sale_order.subscription_state in ['3_progress', '4_paused']">
<!-- User is logged in as the subscription partner or is a public user. -->
<t t-if="enable_token_management or providers_sudo or tokens_sudo">
<t t-if="sale_order.payment_token_id">
<a t-att-href="token_management_url">
<div class="card mb-2">
<div class="card-body d-flex flex-column flex-lg-row align-items-lg-center gap-3 border-start border-5 border-info">
<div t-field="sale_order.payment_token_id.payment_method_id.image_payment_form" t-options="{'widget': 'image'}"/>
<div>
<b>Payment Method</b>
<div t-out="sale_order.payment_token_id.display_name" class="mt-2"/>
</div>
</div>
</div>
</a>
</t>
<a t-if="next_billing_details.get('next_invoice_amount')>0 and (sale_order.next_invoice_date&lt;=datetime.date.today() or not is_delivery_product)" class="btn btn-primary d-block" href="#payment_message"> Pay Now</a>
</t>
<!-- User is logged in under a partner different than that set on the subscription -->
<button t-elif="not user._is_public()"
title="Managing payment methods requires to be logged in under the customer order."
href="#"
disabled="true"
role="button"
class="btn btn-primary">
Pay Now
</button>
</t>
<a role="button" t-attf-class="btn btn-light d-block {{ 'disabled' if sale_order.next_invoice_date &lt;= datetime.date.today() else '' }}"
data-bs-toggle="modal" data-bs-target="#wc-modal-pause" href="#"
t-if="(sale_order.plan_id.pausable_by_user and (not sale_order.user_pause_start or sale_order.next_invoice_date == datetime.date.today())) and not is_subscription_postpaid">
Pause subscription
</a>
<a role="button" t-attf-class="btn btn-light d-block {{ 'disabled' if sale_order.next_invoice_date &lt; datetime.date.today() else '' }}"
data-bs-toggle="modal" data-bs-target="#wc-modal-resume" href="#"
t-if="(sale_order.plan_id.pausable_by_user and (sale_order.user_pause_start and sale_order.next_invoice_date != datetime.date.today())) and not is_subscription_postpaid">
Resume subscription
</a>
<t
t-set="has_optional_lines"
t-value="bool(
sale_order.order_line.filtered(
lambda l: not l.display_type and l._is_line_optional()
)
)"
/>
<a role="button" class="btn btn-primary" t-att-href="renewal_url"
t-if="sale_order.user_extend and renewal_url">
Renew
</a>
<a role="button" class="btn btn-primary" t-attf-href="/my/subscriptions/{{sale_order.id}}/renewal"
t-elif="sale_order.user_extend and not sale_order._can_be_edited_on_portal()">
Renew
</a>
<t t-if="sale_order.subscription_state != '6_churn'">
<button role="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#wc-modal-change-plan" href="#"
t-if="sale_order.plan_id.related_plan_id and sale_order._can_be_edited_on_portal()" id="o_change_plan">
Change Plan
</button>
<a role="button" class="btn btn-primary"
t-attf-href="{{renewal_url}}&amp;change_plan=true"
t-elif="sale_order.user_extend and sale_order.plan_id.related_plan_id and renewal_url">
Change Plan
</a>
<a role="button" class="btn btn-primary" t-attf-href="/my/subscriptions/{{sale_order.id}}/renewal?change_plan=true"
t-elif="sale_order.user_extend and sale_order.plan_id.related_plan_id">
Change Plan
</a>
<a role="button" class="btn btn-primary" t-att-href="upsell_url"
t-if="sale_order.user_quantity and upsell_url and sale_order.subscription_state in ['3_progress', '4_paused']">
Add Quantity
</a>
<a
role="button"
class="btn btn-primary"
t-attf-href="/my/subscriptions/{{sale_order.id}}/upsell"
t-elif="sale_order.user_quantity
and has_optional_lines
and not sale_order._can_be_edited_on_portal()
and sale_order.subscription_state in ['3_progress', '4_paused']"
>
Add Quantity
</a>
</t>
<a role="button" class="btn btn-light" data-bs-toggle="modal" data-bs-target="#wc-modal-close-init" href="#"
t-if="display_close">
Close Subscription
</a>
<a t-if="payment_amount and sale_order.subscription_state != '5_renewed'" id="o_sale_portal_paynow" role="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modalaccept" href="#">
<i class="fa fa-check"/><t>Pay</t>
</a>
<!-- Download -->
<div class="o_download_pdf d-flex flex-lg-column flex-xl-row flex-wrap gap-2">
<a class="btn btn-light flex-grow-1 o_download_btn" t-att-href="sale_order.get_portal_url(report_type='pdf', download=True)" title="Download"><i class="fa fa-download me-1"/> Download</a>
</div>
</div>
<div t-if="sale_order.user_id">
<h6 class="small text-muted">Subscription Manager:</h6>
<t t-call="portal.portal_my_contact">
<t t-set="_contactAvatar" t-value="image_data_uri(sale_order.user_id.avatar_128)"/>
<t t-set="_contactName" t-value="sale_order.user_id.name"/>
<t t-set="_contactLink" t-value="True"/>
</t>
</div>
<div t-if="sale_order.history_count">
<h6 class="small text-muted">History</h6>
<div class="d-flex flex-column gap-2">
<a t-attf-href="/my/subscriptions?order_id={{sale_order.id}}" title="Orders">Orders</a>
</div>
</div>
<!-- Reopen button if there is an option to reopen the closed subscription -->
<div t-if="(providers_sudo or tokens_sudo) and next_billing_details.get('next_invoice_amount')> 0 and
display_payment_message and sale_order.subscription_state == '6_churn'" class="d-flex flex-wrap flex-column gap-4">
<a class="btn btn-primary d-block" href="#payment_message" role="button">
Reopen
</a>
</div>
</div>
</t>
</t>
</template>
<!-- Modify portal templates -->
<template id="portal_my_home_menu_subscription" name="Portal layout : subscription menu entry" inherit_id="sale.portal_my_home_menu_sale" priority="10">
<li id="portal_breadcrumbs_sale" position="after">
<li t-elif="page_name == 'subscription'" t-attf-class="breadcrumb-item #{'active ' if not sale_order else ''}">
<a t-if="sale_order" t-attf-href="/my/subscriptions?{{ keep_query() }}">Subscriptions</a>
<t t-else="">Subscriptions</t>
</li>
</li>
</template>
<template id="portal_my_home_subscription" name="Subscriptions" customize_show="True" inherit_id="portal.portal_my_home" priority="90">
<xpath expr="//div[hasclass('o_portal_docs')]" position="before">
<t t-set="portal_client_client_enable" t-value="True"/>
</xpath>
<div id="portal_client_category" position="inside">
<t t-call="portal.portal_docs_entry">
<t t-set="icon" t-value="'/sale_subscription/static/src/img/subscription.svg'"/>
<t t-set="title">Subscriptions</t>
<t t-set="text">Manage your subscriptions</t>
<t t-set="url" t-value="'/my/subscriptions'"/>
<t t-set="placeholder_count" t-value="'subscription_count'"/>
</t>
</div>
</template>
<template id="portal_my_subscriptions" name="My Subscriptions">
<t t-call="portal.portal_layout">
<t t-set="breadcrumbs_searchbar" t-value="True"/>
<t t-call="portal.portal_searchbar">
<t t-set="title">Subscriptions</t>
</t>
<t t-if="not subscriptions">
<p class="alert alert-warning">You don't have any subscriptions yet.</p>
</t>
<t t-else="" t-call="portal.portal_table">
<thead>
<tr class="active">
<th class="">Subscription</th>
<th class="text-center">Next Billing Date</th>
<th class="text-center">Recurring Plan</th>
<th class="text-end">Total</th>
<th class="text-center">Status</th>
</tr>
</thead>
<t t-foreach="subscriptions" t-as="sale_order">
<tr>
<td>
<a t-att-href="sale_order.get_portal_url()"><t t-out ="sale_order.display_name"/></a>
</td>
<td class="text-center">
<t t-out ="sale_order.next_invoice_date" t-if="sale_order.subscription_state == '3_progress' and sale_order.next_invoice_date &lt; datetime.date.today()"
class="text-danger"/>
<t t-out ="sale_order.next_invoice_date" t-else=""/>
</td>
<td class="text-center"><t t-out ="sale_order.plan_id.sudo().name"/></td>
<td class="text-end"><span t-out ="sale_order.amount_total" t-options="{'widget': 'monetary', 'display_currency': sale_order.currency_id}"/></td>
<td class="text-center" id="subscription_state">
<t t-if="sale_order.subscription_state == '3_progress' and sale_order.next_invoice_date &lt; datetime.date.today()">
<span class="badge rounded-pill text-bg-danger"><i class="fa fa-fw fa-repeat"/> To Renew</span>
</t>
<t t-elif="sale_order.subscription_state == '2_renewal'">
<span class="badge rounded-pill text-bg-info"> Renewal Quotation </span>
</t>
<t t-elif="sale_order.subscription_state == '3_progress'">
<span class="badge rounded-pill text-bg-success"><i class="fa fa-fw fa-check"/> In Progress</span>
</t>
<t t-elif="sale_order.subscription_state == '4_paused'">
<span class="badge rounded-pill text-bg-success"><i class="fa fa-fw fa-check"/> Paused</span>
</t>
<t t-elif="sale_order.subscription_state == '5_renewed'">
<span class="badge rounded-pill text-bg-secondary"><i class="fa fa-fw fa-check"/> Renewed</span>
</t>
<t t-elif="sale_order.subscription_state == '6_churn'">
<span class="badge rounded-pill text-bg-dark"><i class="fa fa-fw fa-remove"/> Closed</span>
</t>
<t t-elif="sale_order.subscription_state == '7_upsell'">
<span class="badge rounded-pill text-bg-primary"><i class="fa fa-fw fa-check"/> Upsell</span>
</t>
</td>
</tr>
</t>
</t>
</t>
</template>
<!-- Sale order (quotations): display recurrence -->
<template id="sale_order_portal_content_inherit" inherit_id="sale.sale_order_portal_content">
<t t-set="display_discount" position="attributes">
<attribute name="t-value">
True in [bool(line.discount) if sale_order.subscription_state == '7_upsell' else line.discount > 0 for line in sale_order.order_line]
</attribute>
</t>
<tbody id="sale_info_table" position="inside">
<tr t-if="sale_order.subscription_id">
<th class="ps-0 pb-0">Subscription:</th>
<td class="w-100 pb-0 text-wrap"><a t-att-href="sale_order.subscription_id.get_portal_url()"><span t-field="sale_order.subscription_id.name"/></a></td>
</tr>
<tr t-if="sale_order.plan_id">
<th class="ps-0 pb-0">Recurring Plan:</th>
<td class="w-100 pb-0 text-wrap"><span t-field="sale_order.plan_id.sudo().name"/></td>
</tr>
</tbody>
<th id="product_qty_header" position="after">
<th t-if="sale_order.subscription_state == '7_upsell'" class="text-end">
Total Quantity
</th>
</th>
<t t-set="section_name_colspan" position="after">
<t
t-if="sale_order.subscription_state == '7_upsell'"
t-set="section_name_colspan"
t-value="section_name_colspan + 1"
/>
</t>
<td name="td_product_quantity" position="after">
<td t-if="sale_order.subscription_state == '7_upsell'" class="text-end">
<span t-esc="line.upsell_total"/>
<span t-field="line.product_uom_id"/>
</td>
</td>
<div t-field="line.price_unit" position="attributes">
<attribute name="t-if" separator="or" add="sale_order.subscription_state == '7_upsell'"/>
</div>
<strong t-if="line.discount &gt; 0" position="attributes">
<attribute name="t-if" separator="or" add="sale_order.subscription_state == '7_upsell'"/>
</strong>
<div id="intro_row" position="inside">
<div t-if="sale_order.subscription_state == '7_upsell'">
<span class="badge rounded-pill text-bg-primary"><i class="fa fa-fw fa-check"/> Upsell</span>
</div>
</div>
<xpath expr="//div[@id='customer_info']//h5" position="after">
<header class="d-flex justify-content-between align-items-center">
<button t-if="sale_order.subscription_state in ['3_progress', '4_paused'] and multiple_addresses_enabled" data-bs-toggle="modal" data-bs-target="#address_change_modal" class="btn btn-link link-info mb-1" type="object">
Edit
</button>
</header>
</xpath>
<xpath expr="//div[@id='customer_info']//header//button" position="before">
<xpath expr="//div[@id='customer_info']//h5" position="move"/>
</xpath>
<div id="customer_info" position="after">
<!-- MODAL: subscription addresses edition -->
<div t-if="multiple_addresses_enabled" role="dialog" t-attf-class="modal fade" id="address_change_modal" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<header class="modal-header">
<h4 class="modal-title">
Change addresses
</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"/>
</header>
<form method="post" t-attf-action="/my/subscriptions/{{sale_order.id}}/change_address">
<input class="d-none" name="csrf_token" t-att-value="request.csrf_token()"/>
<main class="modal-body">
<div class="mb-3 row">
<label for="subscription-invoicing-address" t-att-class="'col-form-label col-sm-3' if multiple_addresses_enabled else 'col-form-label col-sm-4'">
Invoicing Address
</label>
<div class="col-sm-9">
<!-- We don't allow selecting another delivery address yet. The selection has only one value and it is readonly -->
<select id="subscription-invoicing-address" class="col-sm form-select" name="invoicing_address">
<t t-foreach="invoicing_addresses" t-as="partner">
<option t-att-value="partner['id']" t-out="partner['address']" t-att-selected="partner['id'] == sale_order.partner_invoice_id.id"/>
</t>
</select>
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-3 col-form-label" for="subscription-delivery-address">
Delivery Address
</label>
<div class="col-sm-9 py-2">
<div t-out="partner['address']"/>
<div>
<div class="text-muted">The delivery address can not be changed.</div>
<div class="text-muted">Contact your subscription manager to change it.</div>
</div>
</div>
</div>
<a t-attf-href="/my/addresses" class="link-info"><i class="fa fa-plus"/> Create address</a>
</main>
<footer class="modal-footer d-flex">
<button type="button" class="btn btn-light" data-bs-dismiss="modal" aria-label="Cancel">Cancel</button>
<button class="btn btn-primary">Save</button>
</footer>
</form>
</div>
</div>
</div>
</div>
<xpath expr="//t[@t-set='is_note']" position="after">
<t t-set="is_note" t-value="is_note or line.display_type == 'subscription_discount'"/>
</xpath>
</template>
<template id="sale_order_portal_content_totals_table_inherit" inherit_id="sale.sale_order_portal_content_totals_table">
<t t-set="tax_totals" t-value="sale_order.tax_totals" position="attributes">
<attribute name="t-value">next_billing_details.get('tax_totals') if page_name=='subscription' else sale_order.tax_totals</attribute>
</t>
</template>
<template id="portal_my_orders_inherit" inherit_id="sale.portal_my_orders">
<xpath expr="//t[@t-foreach='orders']/tr/td/a" position="attributes">
<attribute name='t-att-href'>order.with_context(force_sale_url=True).get_portal_url()</attribute>
</xpath>
</template>
</odoo>