Odoo18-Base/addons/website_sale/views/templates.xml
2025-01-06 10:57:38 +07:00

3364 lines
198 KiB
XML

<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="header_cart_link" name="Header Cart Link">
<t t-nocache="The number of products is dynamic, this rendering cannot be cached."
t-nocache-_icon="_icon"
t-nocache-_text="_text"
t-nocache-_badge="_badge"
t-nocache-_badge_class="_badge_class"
t-nocache-_icon_wrap_class="_icon_wrap_class"
t-nocache-_text_class="_text_class"
t-nocache-_item_class="_item_class"
t-nocache-_link_class="_link_class">
<t t-set="website_sale_cart_quantity" t-value="request.session['website_sale_cart_quantity'] if 'website_sale_cart_quantity' in request.session else website.sale_get_order().cart_quantity or 0"/>
<t t-set="show_cart" t-value="website.has_ecommerce_access()"/>
<li t-attf-class="#{_item_class} divider d-none"/> <!-- Make sure the cart and related menus are not folded (see autohideMenu) -->
<li t-attf-class="o_wsale_my_cart #{not show_cart and 'd-none'} #{_item_class}">
<a href="/shop/cart" t-attf-class="#{_link_class}" aria-label="eCommerce cart">
<div t-attf-class="#{_icon_wrap_class}">
<i t-if="_icon" class="fa fa-shopping-cart fa-stack"/>
<sup t-attf-class="my_cart_quantity badge bg-primary #{_badge_class} #{'d-none' if (website_sale_cart_quantity == 0) else ''}" t-esc="website_sale_cart_quantity" t-att-data-order-id="request.session.get('sale_order_id', '')"/>
</div>
<span t-if="_text" t-attf-class="#{_text_class}">My Cart</span>
</a>
</li>
</t>
</template>
<template id="header_hide_empty_cart_link" inherit_id="website_sale.header_cart_link" name="Header Hide Empty Cart link" active="False">
<xpath expr="//t[@t-set='show_cart']" position="after">
<t t-set="show_cart" t-value="website_sale_cart_quantity" />
</xpath>
</template>
<template id="template_header_mobile" inherit_id="website.template_header_mobile">
<xpath expr="//ul[hasclass('o_header_mobile_buttons_wrap')]//li" position="before">
<t t-call="website_sale.header_cart_link">
<t t-set="_icon" t-value="True"/>
<t t-set="_link_class" t-value="'o_navlink_background_hover btn position-relative rounded-circle border-0 p-1 text-reset'"/>
<t t-set="_badge_class" t-value="'position-absolute top-0 end-0 mt-n1 me-n1 rounded-pill'"/>
</t>
</xpath>
</template>
<template id="template_header_default" inherit_id="website.template_header_default">
<xpath expr="//t[@t-call='website.placeholder_header_search_box']" position="before">
<t t-call="website_sale.header_cart_link">
<t t-set="_icon" t-value="True"/>
<t t-set="_link_class" t-value="'o_navlink_background btn position-relative rounded-circle p-1 text-center text-reset'"/>
<t t-set="_badge_class" t-value="'position-absolute top-0 end-0 mt-n1 me-n1 rounded-pill'"/>
</t>
</xpath>
</template>
<template id="template_header_hamburger" inherit_id="website.template_header_hamburger">
<xpath expr="//t[@t-call='portal.placeholder_user_sign_in']" position="before">
<t t-call="website_sale.header_cart_link">
<t t-set="_icon" t-value="True"/>
<t t-set="_link_class" t-value="'o_navlink_background_hover btn position-relative rounded-pill p-1 text-reset'"/>
<t t-set="_badge_class" t-value="'position-absolute top-0 end-0 mt-n1 me-n1 rounded'"/>
</t>
</xpath>
</template>
<template id="template_header_stretch" inherit_id="website.template_header_stretch">
<xpath expr="//t[@t-call='website.placeholder_header_social_links']" position="before">
<t t-call="website_sale.header_cart_link">
<t t-set="_icon" t-value="True"/>
<t t-set="_item_class" t-value="'border-start o_border_contrast'"/>
<t t-set="_link_class" t-value="'o_navlink_background_hover btn position-relative d-flex align-items-center h-100 rounded-0 p-2 text-reset'"/>
<t t-set="_badge_class" t-value="'rounded'"/>
</t>
</xpath>
</template>
<template id="template_header_vertical" inherit_id="website.template_header_vertical">
<xpath expr="//t[@t-call='portal.placeholder_user_sign_in']" position="before">
<t t-call="website_sale.header_cart_link">
<t t-set="_icon" t-value="True"/>
<t t-set="_link_class" t-value="'o_navlink_background btn position-relative rounded-circle p-1 text-reset'"/>
<t t-set="_badge_class" t-value="'position-absolute top-0 end-0 mt-n1 me-n1 rounded-pill'"/>
</t>
</xpath>
</template>
<template id="template_header_search" inherit_id="website.template_header_search">
<xpath expr="//t[@t-call='portal.placeholder_user_sign_in']" position="before">
<t t-call="website_sale.header_cart_link">
<t t-set="_text" t-value="True"/>
<t t-set="_item_class" t-value="'border-start o_border_contrast'"/>
<t t-set="_link_class" t-value="'o_navlink_background_hover btn btn-sm d-flex align-items-center gap-1 h-100 rounded-0 p-2 text-reset'"/>
<t t-set="_badge_class" t-value="'rounded'"/>
</t>
</xpath>
</template>
<template id="template_header_sales_one" inherit_id="website.template_header_sales_one">
<xpath expr="//t[@t-call='portal.user_dropdown']" position="before">
<t t-call="website_sale.header_cart_link">
<t t-set="_icon" t-value="True"/>
<t t-set="_link_class" t-value="'btn position-relative rounded-circle p-1 text-reset o_navlink_background'"/>
<t t-set="_badge_class" t-value="'position-absolute top-0 end-0 mt-n1 me-n1 rounded-pill'"/>
</t>
</xpath>
</template>
<template id="template_header_sales_two" inherit_id="website.template_header_sales_two">
<xpath expr="//t[@t-call='portal.placeholder_user_sign_in']" position="before">
<t t-call="website_sale.header_cart_link">
<t t-set="_icon" t-value="True"/>
<t t-set="_text" t-value="True"/>
<t t-set="_icon_wrap_class" t-value="'position-relative me-2 rounded-circle border p-2 bg-o-color-3 o_border_contrast'"/>
<t t-set="_link_class" t-value="'btn d-flex align-items-center fw-bold text-reset o_navlink_background_hover'"/>
<t t-set="_badge_class" t-value="'position-absolute top-0 end-0 mt-n1 me-n1 rounded-pill'"/>
<t t-set="_text_class" t-value="'small'"/>
</t>
</xpath>
</template>
<template id="template_header_sales_three" inherit_id="website.template_header_sales_three">
<xpath expr="//t[@t-call='website.placeholder_header_language_selector']" position="before">
<t t-call="website_sale.header_cart_link">
<t t-set="_text" t-value="True"/>
<t t-set="_item_class" t-value="'position-relative'"/>
<t t-set="_link_class" t-value="'nav-link d-flex flex-row-reverse align-items-center text-uppercase fw-bold'"/>
<t t-set="_icon_wrap_class" t-value="'d-contains'"/>
<t t-set="_badge_class" t-value="'top-0 d-block ms-2'"/>
</t>
</xpath>
</template>
<template id="template_header_sales_four" inherit_id="website.template_header_sales_four">
<xpath expr="//t[@t-call='website.placeholder_header_call_to_action']" position="before">
<t t-call="website_sale.header_cart_link">
<t t-set="_icon" t-value="True"/>
<t t-set="_link_class" t-value="'o_navlink_background_hover btn position-relative rounded-pill p-1 text-reset'"/>
<t t-set="_badge_class" t-value="'position-absolute top-0 end-0 mt-n1 me-n1 rounded-pill'"/>
</t>
</xpath>
</template>
<template id="template_header_sidebar" inherit_id="website.template_header_sidebar">
<xpath expr="//t[@t-call='website.placeholder_header_brand']" position="after">
<div class="d-flex ms-auto mb-0">
<t t-call="website_sale.header_cart_link">
<t t-set="_icon" t-value="True"/>
<t t-set="_link_class" t-value="'o_navlink_background_hover btn position-relative p-1 rounded-circle text-reset'"/>
<t t-set="_badge_class" t-value="'position-absolute top-0 end-0 rounded-pill mt-n1 me-n1'"/>
</t>
</div>
</xpath>
</template>
<template id="template_header_boxed" inherit_id="website.template_header_boxed">
<xpath expr="//t[@t-call='website.placeholder_header_search_box']" position="before">
<t t-call="website_sale.header_cart_link">
<t t-set="_icon" t-value="True"/>
<t t-set="_link_class" t-value="'o_navlink_background btn position-relative rounded-circle p-1 text-center text-reset'"/>
<t t-set="_badge_class" t-value="'position-absolute top-0 end-0 mt-n1 me-n1 rounded-pill'"/>
</t>
</xpath>
</template>
<!-- Search Bar input-group template -->
<template id="search" name="Search Box" active="True">
<t t-call="website.website_search_box_input">
<t t-set="_form_classes" t-valuef="o_wsale_products_searchbar_form me-auto flex-grow-1 {{_form_classes}}"/>
<t t-set="_submit_classes" t-valuef="btn btn-{{navClass}}"/>
<t t-set="_input_classes" t-valuef="border-0 text-bg-{{navClass}}"/>
<t t-set="search_type" t-valuef="products"/>
<t t-set="action" t-value="keep('/shop'+ ('/category/'+slug(category)) if category else None, search=0) or '/shop'"/>
<t t-set="display_image" t-valuef="true"/>
<t t-set="display_description" t-valuef="true"/>
<t t-set="display_extra_link" t-valuef="true"/>
<t t-set="display_detail" t-valuef="true"/>
<t t-if="attrib_values">
<t t-foreach="attrib_values" t-as="a">
<input type="hidden" name="attribute_value" t-att-value="'%s-%s' % (a[0], a[1])" />
</t>
</t>
</t>
</template>
<template id="products_item" name="Products item">
<form action="/shop/cart/update" method="post" class="oe_product_cart h-100 d-flex"
t-att-data-publish="product.website_published and 'on' or 'off'"
itemscope="itemscope" itemtype="http://schema.org/Product">
<t t-set="product_href" t-value="keep(product.website_url, page=(pager['page']['num'] if pager['page']['num']&gt;1 else None)) + selected_attributes_hash" />
<t t-set="image_type" t-value="product._get_suitable_image_size(ppr, td_product['x'], td_product['y'])"/>
<div class="oe_product_image position-relative flex-grow-0 overflow-hidden">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" t-nocache="The csrf token must always be up to date."/>
<a
t-att-href="product_href"
class="oe_product_image_link d-block position-relative"
itemprop="url"
contenteditable="false"
>
<t t-set="image_holder" t-value="product._get_image_holder()"/>
<span t-field="image_holder.image_1920"
t-options="{'widget': 'image', 'preview_image': image_type, 'itemprop': 'image', 'class': 'h-100 w-100 position-absolute'}"
class="oe_product_image_img_wrapper d-flex h-100 justify-content-center align-items-center position-absolute"/>
<t t-set="bg_color" t-value="td_product['ribbon'].bg_color"/>
<t t-set="text_color" t-value="td_product['ribbon'].text_color"/>
<t t-set="bg_class" t-value="td_product['ribbon']._get_position_class()"/>
<span
t-attf-class="o_ribbon o_not_editable #{bg_class}"
t-attf-style="#{text_color and ('color: %s;' % text_color)} #{bg_color and 'background-color:' + bg_color}"
t-out="td_product['ribbon'].name or ''"
/>
</a>
</div>
<div class="o_wsale_product_information position-relative d-flex flex-column flex-grow-1 flex-shrink-1">
<div class="o_wsale_product_information_text">
<h6 class="o_wsale_products_item_title mb-2 text-break">
<a class="text-primary text-decoration-none text-primary-emphasis" itemprop="name" t-att-href="product_href" t-att-content="product.name" t-field="product.name" />
<a t-if="not product.website_published" role="button" t-att-href="product_href" class="btn btn-sm btn-danger" title="This product is unpublished.">
Unpublished
</a>
</h6>
</div>
<div class="o_wsale_product_sub d-flex justify-content-between align-items-end gap-2 flex-wrap">
<t t-set="template_price_vals" t-value="get_product_prices(product)"/>
<div class="o_wsale_product_btn d-flex gap-2"/>
<div class="product_price" itemprop="offers" itemscope="itemscope" itemtype="http://schema.org/Offer">
<span class="h6 mb-0"
t-if="template_price_vals['price_reduce'] or not website.prevent_zero_price_sale"
t-out="template_price_vals['price_reduce']"
t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"/>
<span class="h6 mb-0" t-elif="any(ptav.price_extra for ptav in product.attribute_line_ids.product_template_value_ids)">&amp;nbsp;</span>
<span class="h6 mb-0" t-else="" t-field="website.prevent_zero_price_sale_text"/>
<t t-if="'base_price' in template_price_vals and (template_price_vals['base_price'] &gt; template_price_vals['price_reduce']) and (template_price_vals['price_reduce'] or not website.prevent_zero_price_sale)">
<del t-attf-class="text-muted me-1 h6 mb-0" style="white-space: nowrap;">
<em class="small" t-esc="template_price_vals['base_price']" t-options="{'widget': 'monetary', 'display_currency': website.currency_id}" />
</del>
</t>
<span itemprop="price" style="display:none;" t-esc="template_price_vals['price_reduce']" />
<span itemprop="priceCurrency" style="display:none;" t-esc="website.currency_id.name" />
</div>
</div>
</div>
</form>
</template>
<template id="products_description" inherit_id="website_sale.products_item" active="False" name="Product Description">
<xpath expr="//form" position="attributes">
<attribute name="class" add="oe_product_cart_has_description" separator=" "/>
</xpath>
<xpath expr="//*[hasclass('o_wsale_products_item_title')]" position="after">
<div class="oe_subdescription mb-2 text-muted small" contenteditable="false">
<div itemprop="description" t-field="product.description_sale"/>
</div>
</xpath>
</template>
<template id="products_add_to_cart" inherit_id="website_sale.products_item" active="False" name="Add to Cart">
<xpath expr="//div[hasclass('o_wsale_product_btn')]" position="inside">
<t t-set="product_variant_id" t-value="product._get_first_possible_variant_id()"/>
<input name="product_id" t-att-value="product_variant_id" type="hidden"/>
<input name="product_template_id" t-att-value="product.id" type="hidden"/>
<t t-if="product_variant_id and template_price_vals['price_reduce'] or not website.prevent_zero_price_sale">
<a
t-if="product._website_show_quick_add()"
href="#"
role="button"
class="btn btn-light a-submit"
aria-label="Shopping cart"
title="Shopping cart"
>
<span class="fa fa-shopping-cart"/>
</a>
</t>
</xpath>
</template>
<template id="pricelist_list" name="Pricelists Dropdown">
<t t-set="website_sale_pricelists" t-value="website_sale_pricelists or website.get_pricelist_available(show_visible=True)" />
<t t-set="hasPricelistDropdown" t-value="hasPricelistDropdown or (website_sale_pricelists and len(website_sale_pricelists)&gt;1)"/>
<t t-set="pricelist" t-value="website.pricelist_id"/>
<div t-attf-class="o_pricelist_dropdown dropdown #{_classes if hasPricelistDropdown else 'd-none'}">
<t t-cache="pricelist,website_sale_pricelists,navClass">
<a role="button" href="#" t-attf-class="dropdown-toggle btn btn-{{navClass}}" data-bs-toggle="dropdown">
<t t-esc="pricelist and pricelist.name or ' - '" />
</a>
<div class="dropdown-menu" role="menu">
<t t-foreach="website_sale_pricelists" t-as="pl">
<a role="menuitem" t-att-href="'/shop/change_pricelist/%s' % pl.id" class="dropdown-item">
<span class="switcher_pricelist small" t-att-data-pl_id="pl.id" t-esc="pl.name"/>
</a>
</t>
</div>
</t>
</div>
</template>
<template id="products_breadcrumb" name="Products Breadcrumb">
<ol t-if="category" t-attf-class="breadcrumb #{_classes}">
<li class="breadcrumb-item">
<a href="/shop">Products</a>
</li>
<t t-foreach="category.parents_and_self" t-as="cat">
<li t-if="cat == category" class="breadcrumb-item">
<span class="d-inline-block" t-field="cat.name"/>
</li>
<li t-else="" class="breadcrumb-item">
<a t-att-href="keep('/shop/category/%s' % slug(cat), category=0)" t-field="cat.name"/>
</li>
</t>
</ol>
</template>
<!-- /shop product listing -->
<template id="products" name="Products">
<t t-call="website.layout">
<t t-set="additional_title" t-value="category.name"/>
<t t-set="grid_block_name">Grid</t>
<t t-set="product_block_name">Product</t>
<!-- Qweb variable defining the class suffix for navbar items.
Change accordingly to the derired visual result (eg. `primary`, `dark`...)-->
<t t-set="navClass" t-valuef="light"/>
<!-- Check for active options: the stored value may be used in sub-templates too -->
<t t-set="opt_wsale_categories" t-value="is_view_active('website_sale.products_categories')"/>
<t t-set="opt_wsale_attributes" t-value="is_view_active('website_sale.products_attributes')"/>
<t t-set="opt_wsale_filter_price" t-value="is_view_active('website_sale.filter_products_price')"/>
<t t-set="opt_wsale_filter_tags" t-value="is_view_active('website_sale.filter_products_tags')"/>
<t t-set="opt_wsale_categories_top" t-value="is_view_active('website_sale.products_categories_top')"/>
<t t-set="opt_wsale_attributes_top" t-value="is_view_active('website_sale.products_attributes_top')"/>
<t t-set="website_sale_pricelists" t-value="website.get_pricelist_available(show_visible=True)" />
<t t-set="website_sale_sortable" t-value="website._get_product_sort_mapping()"/>
<t t-set="hasLeftColumn" t-value="opt_wsale_categories or opt_wsale_attributes"/>
<t t-set="isFilteringByPrice" t-if="opt_wsale_filter_price" t-value="float_round(available_min_price, 2) != float_round(min_price, 2) or float_round(available_max_price, 2) != float_round(max_price, 2)"/>
<t t-set="hasPricelistDropdown" t-value="website_sale_pricelists and len(website_sale_pricelists)&gt;1"/>
<t t-set="isSortingBy" t-value="[sort for sort in website_sale_sortable if sort[0]==request.params.get('order', '')]"/>
<div id="wrap" class="js_sale o_wsale_products_page">
<div class="oe_structure oe_empty oe_structure_not_nearest" id="oe_structure_website_sale_products_1"/>
<div class="container oe_website_sale pt-2">
<div class="row o_wsale_products_main_row align-items-start flex-nowrap">
<aside t-if="hasLeftColumn" id="products_grid_before" class="d-none d-lg-block position-sticky col-3 px-3 clearfix">
<div class="o_wsale_products_grid_before_rail vh-100 ms-n2 mt-n2 pt-2 p-lg-2 pb-lg-5 ps-2 overflow-y-scroll">
<t
t-set="is_sidebar_collapsible"
t-value="is_view_active('website_sale.products_categories_list_collapsible')"
/>
<div
t-if="opt_wsale_categories"
t-att-class="'products_categories'
+ (' accordion accordion-flush' if is_sidebar_collapsible else ' mb-3')"
>
<t t-call="website_sale.products_categories_list"/>
</div>
<div
t-attf-class="products_attributes_filters d-empty-none {{opt_wsale_categories and 'border-top'}}"
/>
<t
t-if="opt_wsale_filter_price and opt_wsale_attributes"
t-call="website_sale.filter_products_price"
>
<t
t-set="_classes"
t-valuef="{{is_sidebar_collapsible and 'accordion accordion-flush'}} {{is_sidebar_collapsible and (opt_wsale_categories or len(attributes) > 0) and 'border-top'}}"
/>
</t>
</div>
</aside>
<div id="products_grid"
t-attf-class="#{'o_wsale_layout_list' if layout_mode == 'list' else ''} {{'col-lg-9' if hasLeftColumn else 'col-12'}}">
<t t-call="website_sale.products_breadcrumb">
<t t-set="_classes" t-valuef="d-none d-lg-flex w-100 p-0 small"/>
</t>
<h1 t-if="category">
<t t-esc="category.name"/>
</h1>
<t t-if="category">
<t t-set='editor_msg'>
Drag building blocks here to customize the header for
"<t t-esc='category.name'/>" category.
</t>
<div class="mb16"
id="category_header"
t-att-data-editor-message="editor_msg"
t-field="category.website_description"/>
</t>
<t t-if="opt_wsale_categories_top"
t-call="website_sale.filmstrip_categories"/>
<div class="products_header btn-toolbar flex-nowrap align-items-center justify-content-between gap-3 mb-3">
<t t-if="is_view_active('website_sale.search')" t-call="website_sale.search">
<t t-set="search" t-value="original_search or search"/>
<t t-set="_form_classes" t-valuef="d-lg-inline {{'d-inline' if not category else 'd-none'}}"/>
</t>
<t t-call="website_sale.pricelist_list">
<t t-set="_classes" t-valuef="d-none d-lg-inline"/>
</t>
<t t-if="is_view_active('website_sale.sort')" t-call="website_sale.sort">
<t t-set="_classes" t-valuef="d-none me-auto d-lg-inline-block"/>
</t>
<div t-if="category" class="d-flex align-items-center d-lg-none me-auto">
<t t-if="not category.parent_id" t-set="backUrl" t-valuef="/shop"/>
<t t-else="" t-set="backUrl" t-value="keep('/shop/category/' + slug(category.parent_id), category=0)"/>
<a t-attf-class="btn btn-{{navClass}} me-2" t-att-href="category.parent_id and keep('/shop/category/' + slug(category.parent_id), category=0) or '/shop'">
<i class="fa fa-angle-left"/>
</a>
<h4 t-out="category.name" class="mb-0 me-auto"/>
</div>
<t t-if="is_view_active('website_sale.add_grid_or_list_option')" t-call="website_sale.add_grid_or_list_option">
<t t-set="_classes" t-valuef="d-flex"/>
</t>
<button t-if="is_view_active('website_sale.sort') or opt_wsale_categories or opt_wsale_attributes or opt_wsale_attributes_top"
t-attf-class="btn btn-{{navClass}} position-relative {{not opt_wsale_attributes_top and 'd-lg-none'}}"
data-bs-toggle="offcanvas"
data-bs-target="#o_wsale_offcanvas">
<i class="fa fa-sliders"/>
<span t-if="isFilteringByPrice or attrib_set or tags" t-attf-class="position-absolute top-0 start-100 translate-middle border border-{{navClass}} rounded-circle bg-danger p-1"><span class="visually-hidden">filters active</span></span>
</button>
</div>
<div t-if="original_search and products" class="alert alert-warning mt8">
No results found for '<span t-esc="original_search"/>'. Showing results for '<span t-esc="search"/>'.
</div>
<div t-if="products" class="o_wsale_products_grid_table_wrapper pt-3 pt-lg-0">
<t t-set="grid_md_allow_custom_cols" t-value="hasLeftColumn"/>
<t t-set="grid_md_use_3col"
t-value="not hasLeftColumn and ppr == 4"/>
<section
id="o_wsale_products_grid"
t-attf-class="o_wsale_products_grid_table grid {{grid_md_allow_custom_cols and 'o_wsale_products_grid_table_md'}}"
t-attf-style="--o-wsale-products-grid-gap: {{gap}}; --o-wsale-ppr: {{ppr}}; --o-wsale-ppg: {{ppg}}"
t-att-data-ppg="ppg"
t-att-data-ppr="ppr"
t-att-data-default-sort="website.shop_default_sort"
t-att-data-name="grid_block_name"
>
<t t-foreach="bins" t-as="tr_product">
<t t-foreach="tr_product" t-as="td_product">
<t t-if="td_product">
<t t-set="col_height" t-value="td_product['y']"/>
<t t-set="col_width"
t-value="12 // ppr * td_product['x']"/>
<t t-set="col_class_lg"
t-value="'g-col-lg-' + str(col_width)"/>
<t t-set="col_class_md"
t-value="grid_md_allow_custom_cols and ('g-col-md-' + str(col_width)) or grid_md_use_3col and 'g-col-md-4' or 'g-col-md-6'"/>
<t t-set="col_is_stretched"
t-value="(td_product['x'] &gt;= td_product['y'] * 2)"/>
<t t-set="col_is_custom_portrait"
t-value="not col_is_stretched and (col_height &gt; td_product['x'])"/>
<div
t-attf-class="oe_product {{col_is_custom_portrait and 'oe_product_custom_portrait'}} g-col-6 {{col_class_md}} {{col_class_lg}} {{col_is_stretched and 'oe_product_size_stretch'}}"
t-attf-style="--o-wsale-products-grid-product-col-height: {{col_height}};"
t-att-data-ribbon-id="td_product['ribbon'].id"
t-att-data-colspan="td_product['x'] != 1 and td_product['x']"
t-att-data-rowspan="td_product['y'] != 1 and td_product['y']"
t-att-data-name="product_block_name"
>
<div t-attf-class="o_wsale_product_grid_wrapper position-relative h-100 o_wsale_product_grid_wrapper_#{td_product['x']}_#{td_product['y']}">
<t t-call="website_sale.products_item">
<t t-set="product"
t-value="td_product['product']"/>
</t>
</div>
</div>
</t>
</t>
</t>
</section>
</div>
<div t-else="" class="text-center text-muted mt128 mb256">
<t t-if="not search">
<h3 class="mt8">No product defined</h3>
<p t-if="category">No product defined in this category.</p>
</t>
<t t-else="">
<h3 class="mt8">No results</h3>
<p>No results for "<strong t-esc='search'/>"<t t-if="category"> in category "<strong t-esc="category.display_name"/>"</t>.</p>
</t>
<p t-ignore="true" groups="sales_team.group_sale_manager">Click <i>'New'</i> in the top-right corner to create your first product.</p>
</div>
<div class="products_pager d-flex justify-content-center pt-5 pb-3">
<t t-call="website.pager"/>
</div>
<t t-if="category">
<t t-set='footer_editor_message'>
Drag building blocks here to customize the footer for
"<t t-esc='category.name'/>" category.
</t>
<div
class="mb16"
id="category_footer"
t-att-data-editor-message="footer_editor_message"
t-field="category.website_footer"
/>
</t>
</div>
</div>
<t t-call="website_sale.o_wsale_offcanvas"/>
</div>
<div class="oe_structure oe_empty oe_structure_not_nearest" id="oe_structure_website_sale_products_2"/>
</div>
</t>
</template>
<!-- (Option) Products: Enable "Card" or "Thumbnails" designs -->
<template id="products_design_card" name="Card Design" inherit_id="website_sale.products" active="False">
<xpath expr="//section[@id='o_wsale_products_grid']" position="attributes">
<attribute name="t-attf-class" add="o_wsale_design_cards" separator=" "/>
</xpath>
</template>
<template id="products_design_thumbs" name="Thumbnails Design" inherit_id="website_sale.products" active="False">
<xpath expr="//section[@id='o_wsale_products_grid']" position="attributes">
<attribute name="t-attf-class" add="o_wsale_design_thumbs" separator=" "/>
</xpath>
</template>
<template id="products_design_grid" name="Grid Design" inherit_id="website_sale.products" active="False">
<xpath expr="//section[@id='o_wsale_products_grid']" position="attributes">
<attribute name="t-attf-class" add="o_wsale_design_grid" separator=" "/>
</xpath>
</template>
<!-- (Options) Products: Define products' default image ratio -->
<template id="products_thumb_4_3" name="thumb_4_3" inherit_id="website_sale.products" active="False">
<xpath expr="//section[@id='o_wsale_products_grid']" position="attributes">
<attribute name="t-attf-class" add="o_wsale_context_thumb_4_3" separator=" "/>
</xpath>
</template>
<template id="products_thumb_4_5" name="thumb_4_5" inherit_id="website_sale.products" active="False">
<xpath expr="//section[@id='o_wsale_products_grid']" position="attributes">
<attribute name="t-attf-class" add="o_wsale_context_thumb_4_5" separator=" "/>
</xpath>
</template>
<template id="products_thumb_2_3" name="thumb_2_3" inherit_id="website_sale.products" active="False">
<xpath expr="//section[@id='o_wsale_products_grid']" position="attributes">
<attribute name="t-attf-class" add="o_wsale_context_thumb_2_3" separator=" "/>
</xpath>
</template>
<!-- (Option) Products: Define products' images filling mode -->
<template id="products_thumb_cover" name="thumb_cover" inherit_id="website_sale.products" active="True">
<xpath expr="//section[@id='o_wsale_products_grid']" position="attributes">
<attribute name="t-attf-class" add="o_wsale_context_thumb_cover" separator=" "/>
</xpath>
</template>
<template id="website_sale.sort" name="Sort-by Template">
<div t-attf-class="o_sortby_dropdown dropdown dropdown_sorty_by {{_classes}}">
<a role="button" href="#" t-attf-class="dropdown-toggle btn btn-{{navClass}}" data-bs-toggle="dropdown">
<small class="d-none d-lg-inline text-muted">Sort By:</small>
<span class="d-none d-lg-inline">
<t t-if="isSortingBy" t-out="isSortingBy[0][1]"/>
<span t-else="1" t-field="website.shop_default_sort"/>
</span>
<i class="fa fa-sort-amount-asc d-lg-none"/>
</a>
<div class="dropdown-menu dropdown-menu-end" role="menu">
<t t-foreach="website_sale_sortable" t-as="sortby">
<a role="menuitem" rel="noindex,nofollow" t-att-href="keep('/shop', order=sortby[0])" class="dropdown-item">
<span t-out="sortby[1]"/>
</a>
</t>
</div>
</div>
</template>
<template id="website_sale.add_grid_or_list_option" active="True" name="Grid or List button">
<t t-set="_activeClasses" t-translation="off">active</t>
<div t-attf-class="o_wsale_apply_layout btn-group {{_classes}}" t-att-data-active-classes="_activeClasses">
<input type="radio" class="btn-check" name="wsale_products_layout" id="o_wsale_apply_grid" t-att-checked="'checked' if layout_mode != 'list' else None" value="grid"/>
<label t-attf-class="btn btn-{{navClass}} #{_activeClasses if layout_mode != 'list' else None} o_wsale_apply_grid" title="Grid" for="o_wsale_apply_grid">
<i class="fa fa-th-large"/>
</label>
<input type="radio" class="btn-check" name="wsale_products_layout" id="o_wsale_apply_list" t-att-checked="'checked' if layout_mode == 'list' else None" value="list"/>
<label t-attf-class="btn btn-{{navClass}} #{_activeClasses if layout_mode == 'list' else None} o_wsale_apply_list" title="List" for="o_wsale_apply_list">
<i class="oi oi-view-list"/>
</label>
</div>
</template>
<template id="website_sale.products_categories" active="False" name="Categories in Left Side "/>
<template id="website_sale.products_categories_top" active="True" name="Categories in top-nav"/>
<template id="website_sale.products_attributes_top" active="False" name="Attributes in top-nav"/>
<template id="o_wsale_offcanvas_color_attribute" name="Color type attribute in filter">
<t t-foreach="a.value_ids" t-as="v">
<t t-set="img_style"
t-value="'background:url(/web/image/product.attribute.value/%s/image); background-size:cover;' % v.id if v.image else ''"
/>
<t t-set="color_style"
t-value="'background: ' + str(v.html_color or v.name if not v.is_custom else '')"
/>
<label t-attf-style="#{img_style or color_style}"
t-attf-class="css_attribute_color mb-1 #{'active' if v.id in attrib_set else ''}"
>
<input type="checkbox"
name="attribute_value"
t-att-value="'%s-%s' % (a.id, v.id)"
t-att-checked="'checked' if v.id in attrib_set else None"
t-att-title="v.name"
/>
</label>
</t>
</template>
<!-- OffCanvas Nav -->
<template id="website_sale.o_wsale_offcanvas" name="Offcanvas">
<aside id="o_wsale_offcanvas"
class="o_website_offcanvas offcanvas offcanvas-end p-0">
<div class="offcanvas-header justify-content-end">
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"/>
</div>
<div t-if="category" class="offcanvas-body d-lg-none flex-grow-0 overflow-visible">
<t t-call="website_sale.search">
<t t-set="search" t-value="original_search or search"/>
<t t-set="_s_searchbar_autocomplete_classes" t-valuef="bg-primary"> </t>
</t>
</div>
<div id="o_wsale_offcanvas_content" class="accordion accordion-flush flex-grow-1 overflow-auto">
<div class="d-block d-lg-none accordion-item" t-if="hasPricelistDropdown">
<h2 id="o_wsale_offcanvas_orderby_header" class="accordion-header mb-0">
<button class="o_wsale_offcanvas_title accordion-button rounded-0 collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target="#o_wsale_offcanvas_pricelist"
aria-expanded="false"
aria-controls="o_wsale_offcanvas_pricelist">
<b>Pricelist</b>
</button>
</h2>
<t t-set="curr_pl" t-value="website.pricelist_id"/>
<div id="o_wsale_offcanvas_pricelist"
class="accordion-collapse collapse"
aria-labelledby="o_wsale_offcanvas_orderby_header">
<div class="accordion-body pt-0">
<div class="list-group list-group-flush">
<a t-foreach="website_sale_pricelists" t-as="pl"
role="menuitem"
rel="noindex,nofollow"
t-att-href="'/shop/change_pricelist/%s' % pl.id"
class="list-group-item border-0 ps-0 pb-0"
>
<div class="form-check d-inline-block">
<input type="radio"
t-attf-onclick="location.href='/shop/change_pricelist/#{pl.id}';"
class="form-check-input o_not_editable"
name="wsale_pricelist_radios_offcanvas"
t-att-checked="curr_pl == pl">
<label class="form-check-label fw-normal" t-out="pl.name"/>
</input>
</div>
</a>
</div>
</div>
</div>
</div>
<div t-if="is_view_active('website_sale.sort')" class="accordion-item">
<t t-if="isSortingBy" t-set="isSortingBy" t-value="isSortingBy[0][1]"/>
<t t-else="" t-set="isSortingBy" t-value="website.shop_default_sort"/>
<h2 id="o_wsale_offcanvas_orderby_header" class="accordion-header mb-0">
<button class="o_wsale_offcanvas_title accordion-button rounded-0 collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target="#o_wsale_offcanvas_orderby"
aria-expanded="false"
aria-controls="o_wsale_offcanvas_orderby">
<b>Sort By</b>
</button>
</h2>
<div id="o_wsale_offcanvas_orderby"
class="accordion-collapse collapse"
aria-labelledby="o_wsale_offcanvas_orderby_header">
<div class="accordion-body pt-0">
<div class="list-group list-group-flush">
<a t-foreach="website_sale_sortable" t-as="sortby"
role="menuitem"
rel="noindex,nofollow"
t-att-href="keep('/shop', order=sortby[0])"
class="list-group-item border-0 ps-0 pb-0">
<div class="form-check d-inline-block">
<input type="radio"
t-attf-onclick="location.href='#{keep('/shop', order=sortby[0])}';"
class="form-check-input o_not_editable"
name="wsale_sortby_radios_offcanvas"
t-att-checked="isSortingBy and isSortingBy == sortby[1]">
<label class="form-check-label fw-normal" t-out="sortby[1]"/>
</input>
</div>
</a>
</div>
</div>
</div>
</div>
<div t-if="opt_wsale_categories"
class="accordion-item">
<h2 id="o_wsale_offcanvas_categories_header" class="accordion-header mb-0">
<button class="o_wsale_offcanvas_title accordion-button rounded-0 collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target="#o_wsale_offcanvas_categories"
aria-expanded="false"
aria-controls="o_wsale_offcanvas_categories">
<b>Categories</b>
</button>
</h2>
<div id="o_wsale_offcanvas_categories"
class="accordion-collapse collapse"
aria-labelledby="o_wsale_offcanvas_categories_header">
<div class="accordion-body pt-0">
<t t-call="website_sale.products_categories_list">
<t t-set="isOffcanvas" t-value="true"/>
<t t-set="_titleClasses" t-valuef="d-none"/>
<t t-set="_radioGroup" t-valuef="_offcanvas"/>
</t>
</div>
</div>
</div>
<form t-if="opt_wsale_attributes or opt_wsale_attributes_top"
t-attf-class="js_attributes accordion accordion-flush d-flex flex-column {{len(attributes) > 0 and 'border-bottom'}}"
method="get">
<input t-if="category" type="hidden" name="category" t-att-value="category.id"/>
<input type="hidden" name="search" t-att-value="search"/>
<t t-foreach="attributes" t-as="a">
<t t-cache="a,attrib_set">
<t t-set="_status" t-value="'inactive'"/>
<t t-foreach="a.value_ids" t-as="v" t-if="v.id in attrib_set" t-set="_status" t-value="'active'"/>
<div t-if="a.value_ids and len(a.value_ids) &gt; 1"
t-attf-class="accordion-item border-top-0 {{(_status == 'active') and 'order-1' or 'order-2'}}">
<h2 class="accordion-header mb-0" t-attf-id="o_wsale_offcanvas_attribute_{{a.id}}_header">
<button t-attf-class="o_wsale_offcanvas_title accordion-button rounded-0 {{ not attrib_values and 'collapsed'}}"
type="button"
t-att-data-status="_status"
data-bs-toggle="collapse"
t-attf-data-bs-target="#o_wsale_offcanvas_attribute_{{a.id}}"
t-att-aria-expanded="_status == 'active' and 'True' or 'False'"
t-attf-aria-controls="o_wsale_offcanvas_attribute_{{a.id}}">
<b t-out="a.name"/>
</button>
</h2>
<div t-attf-id="o_wsale_offcanvas_attribute_{{a.id}}"
t-attf-class="accordion-collapse collapse {{ (_status == 'active') and 'show'}}"
t-att-aria-expanded="(_status == 'active') and 'True' or 'False'"
t-attf-aria-labelledby="o_wsale_offcanvas_attribute_{{a.id}}_header">
<div class="accordion-body pt-0">
<div t-if="a.display_type == 'color'" class="pt-1 pb-3">
<t t-call="website_sale.o_wsale_offcanvas_color_attribute"/>
</div>
<div t-elif="a.display_type in ('radio', 'pills', 'select')"
class="list-group list-group-flush">
<div t-foreach="a.value_ids" t-as="v" class="list-group-item border-0 ps-0 pb-0">
<div class="form-check mb-1">
<input type="checkbox"
name="attribute_value"
class="form-check-input"
t-att-id="'%s-%s' % (a.id,v.id)"
t-att-value="'%s-%s' % (a.id,v.id)"
t-att-checked="'checked' if v.id in attrib_set else None"/>
<label class="form-check-label fw-normal" t-att-for="'%s-%s' % (a.id,v.id)" t-field="v.name"/>
</div>
</div>
</div>
</div>
</div>
</div>
</t>
</t>
<t t-if="opt_wsale_filter_tags and (opt_wsale_attributes or opt_wsale_attributes_top)">
<t t-set="_status" t-value="'inactive'"/>
<t t-foreach="all_tags" t-as="v" t-if="v.id in tags" t-set="_status" t-value="'active'"/>
<div t-if="all_tags">
<h2 class="accordion-header mb-0" t-attf-id="o_wsale_offcanvas_tags_header">
<button t-attf-class="o_wsale_offcanvas_title accordion-button border-top rounded-0 {{ not tags and 'collapsed'}}"
type="button"
t-att-data-status="_status"
data-bs-toggle="collapse"
t-attf-data-bs-target="#o_wsale_offcanvas_tags"
t-att-aria-expanded="_status == 'active' and 'True' or 'False'"
t-attf-aria-controls="o_wsale_offcanvas_tags"
>
<b>Tags</b>
</button>
</h2>
<div t-attf-id="o_wsale_offcanvas_tags"
t-attf-class="accordion-collapse collapse {{ (_status == 'active') and 'show'}}"
t-att-aria-expanded="(_status == 'active') and 'True' or 'False'"
t-attf-aria-labelledby="o_wsale_offcanvas_tags_header"
>
<div class="accordion-body pt-0">
<div class="list-group list-group-flush">
<t t-call="website_sale.filter_products_tags_list">
<t t-set="all_tags" t-value="all_tags"/>
</t>
</div>
</div>
</div>
</div>
</t>
</form>
<t t-if="opt_wsale_filter_price and (opt_wsale_attributes or opt_wsale_attributes_top)"
t-call="website_sale.filter_products_price">
<t
t-set="_classes"
t-valuef="o_wsale_offcanvas_title accordion accordion-flush px-4"
/>
<t t-set="_classes_title" t-valuef="ms-n1 pt-3 pb-2"/>
<t t-set="isOffcanvas" t-value="True"/>
</t>
</div>
<div class="offcanvas-body d-flex justify-content-between flex-grow-0 border-top overflow-hidden">
<a t-attf-class="btn btn-{{navClass}} d-flex py-1 mb-2 {{(not attrib_values and not isFilteringByPrice and not tags) and 'disabled' }}"
t-att-aria-disabled="(not attrib_values and not isFilteringByPrice and not tags) and 'true' or 'false'"
href="/shop"
title="Clear Filters">
Clear Filters
</a>
</div>
</aside>
</template>
<!-- Top-Nav Categories -->
<template id="website_sale.filmstrip_categories" name="Categories Filmstrip">
<t t-if="category.id">
<t t-set="entries" t-value="not search and category.child_id or category.child_id.filtered(lambda c: category.id in search_categories_ids)"/>
<t t-if="not entries">
<t t-set="parent" t-value="category.parent_id"/>
<t t-set="entries" t-value="not search and parent.child_id or parent.child_id.filtered(lambda c: parent.id in search_categories_ids)"/>
</t>
</t>
<t t-else="">
<t t-set="entries" t-value="categories"/>
</t>
<div t-if="entries" class="o_wsale_filmstip_container d-flex align-items-stretch mb-2 overflow-hidden">
<div class="o_wsale_filmstip_wrapper pb-1 overflow-auto">
<ul class="o_wsale_filmstip d-flex align-items-stretch mb-0 list-unstyled overflow-visible">
<t t-if="category.parent_id" t-set="backUrl" t-value="keep('/shop/category/' + slug(category.parent_id), category=0)"/>
<t t-else="" t-set="backUrl" t-value="'/shop'"/>
<li
t-foreach="entries"
t-as="c"
t-attf-class="d-flex {{'pe-3' if not c_last else ''}}"
>
<a
t-att-href="keep('/shop/category/' + slug(c), category=0)"
class="text-decoration-none"
draggable="false"
>
<input
type="radio"
t-attf-name="wsale_categories_top_radios_{{parentCategoryId}}"
class="btn-check pe-none"
t-att-id="c.id"
t-att-value="c.id"
t-att-checked="'true' if c.id == category.id else None"/>
<div
t-att-class="'d-flex align-items-center h-100 btn btn-'
+ navClass
+ (c.image_128 and ' ps-2 pe-3' or ' px-4')
+ (c.id == category.id and ' border-primary' or '')"
>
<div
t-if="c.image_128"
t-attf-style="background-image:url('data:image/png;base64,
#{c.image_128}')"
class="o_image_40_cover oe_img_bg o_bg_img_center
flex-shrink-0 rounded-3 me-3"
t-att-alt="c.name "/>
<span class="text-nowrap" t-field="c.name"/>
</div>
</a>
</li>
</ul>
</div>
</div>
</template>
<!-- Add to cart button-->
<template id="categories_recursive" name="Category list">
<li class="nav-item mb-1">
<t t-call="website_sale.categorie_link"/>
<ul t-if="c.child_id" class="nav flex-column nav-hierarchy mt-1 ps-3">
<t t-foreach="c.child_id" t-as="c">
<t t-if="not search or c.id in search_categories_ids">
<t t-call="website_sale.categories_recursive" />
</t>
</t>
</ul>
</li>
</template>
<template id="categorie_link" name="Category Link">
<a
t-att-href="keep('/shop/category/' + slug(c), category=0)"
t-attf-class="{{c.id == category.id and 'text-decoration-underline'}} p-0"
t-field="c.name"
/>
</template>
<template id="website_sale.products_categories_list" active="True" name="eCommerce Categories">
<!--
We must keep `t-attf-class` attr. for both following divs to work correctly with
products_categories_list_collapsible and option_collapse_products_categories
-->
<div t-attf-class="d-contents">
<h6 t-attf-class="o_categories_collapse_title {{_titleClasses}}"><b>Categories</b></h6>
<div name="wsale_products_categories_list" t-attf-class="wsale_products_categories_list">
<ul class="nav d-flex flex-column mb-3">
<li class="nav-item mb-1">
<a
t-att-href="keep('/shop', category=0)"
t-attf-class="{{not category and 'text-decoration-underline'}} p-0"
>
All Products
</a>
</li>
<t t-foreach="categories" t-as="c">
<t t-call="website_sale.categories_recursive"/>
</t>
</ul>
</div>
</div>
</template>
<template
id="website_sale.products_categories_list_collapsible"
inherit_id="website_sale.products_categories_list"
name="Collapsed eCommerce Categories"
>
<xpath expr="//div" position="attributes">
<attribute
name="t-attf-class"
add="{{not isOffcanvas and 'accordion-item'}}"
remove="d-contents"
separator=" "
/>
</xpath>
<xpath expr="//h6" position="attributes">
<attribute name="t-attf-class" add="accordion-header" separator=" "/>
</xpath>
<xpath expr="//h6//b" position="replace">
<button
class="accordion-button px-0 bg-transparent shadow-none"
type="button"
data-bs-toggle="collapse"
t-attf-data-bs-target="#o_wsale_categories"
t-attf-aria-controls="o_wsale_categories"
aria-expanded="true"
>
<b>Categories</b>
</button>
</xpath>
<xpath expr="//div//div" position="attributes">
<attribute
name="t-attf-id"
add="{{not isOffcanvas and 'o_wsale_categories'}}"
separator=" "
/>
<attribute
name="t-attf-class"
add="{{not isOffcanvas and 'accordion-collapse collapse show'}}"
separator=" "
/>
</xpath>
</template>
<template id="option_collapse_categories_recursive" name="Collapse Category Recursive">
<t t-set="children" t-value="not search and c.child_id or c.child_id.filtered(lambda c: c.id in search_categories_ids)"/>
<t t-if="children">
<t t-set="isOpen" t-value="c.id in category.parents_and_self.ids"/>
<li class="nav-item">
<div class="accordion-header d-flex mb-1">
<t t-call="website_sale.categorie_link"/>
<button t-attf-id="o_wsale_cat_accordion_title_{{c.id}}"
t-attf-class="o_categories_recursive_button accordion-button p-0 ms-3 {{not isOpen and 'collapsed'}} w-auto flex-grow-1 bg-transparent shadow-none"
t-attf-data-bs-target="#o_wsale_cat_accordion_{{c.id}}"
t-att-aria-expanded="isOpen and 'true' or 'false'"
t-attf-aria-controls="o_wsale_cat_accordion_{{c.id}}"
data-bs-toggle="collapse"
type="button"/>
</div>
<ul t-attf-id="o_wsale_cat_accordion_{{c.id}}"
t-attf-class="accordion-collapse list-unstyled ps-2 collapse {{isOpen and 'show'}}"
t-attf-aria-labelledby="o_wsale_cat_accordion_title_{{c.id}}">
<t t-set="parentCategoryId" t-value="c.id"/>
<t t-if="isOffcanvas" t-set="parentCategoryId" t-valuef="offcanvas_{{c.id}}"/>
<t t-foreach="children" t-as="c">
<t t-call="website_sale.option_collapse_categories_recursive"/>
</t>
</ul>
</li>
</t>
<li t-else="" class="nav-item mb-1">
<t t-if="isOffcanvas" t-set="parentCategoryId" t-valuef="offcanvas"/>
<div class="d-flex flex-wrap justify-content-between align-items-center">
<t t-call="website_sale.categorie_link"/>
</div>
</li>
</template>
<template id="option_collapse_products_categories" name="Collapsible Category List" inherit_id="website_sale.products_categories_list" active="False">
<xpath expr="//t[@t-call='website_sale.categories_recursive']" position="attributes">
<attribute name="t-call">website_sale.option_collapse_categories_recursive</attribute>
</xpath>
</template>
<template id="products_attributes" inherit_id="website_sale.products" active="True" name="Attributes &amp; Variants filters">
<xpath expr="//div[contains(@t-attf-class, 'products_attributes_filters')]" position="inside">
<div t-if="attributes or all_tags" id="wsale_products_attributes_collapse"
class=" position-relative">
<form class="js_attributes position-relative mb-2" method="get">
<input t-if="category" type="hidden" name="category" t-att-value="category.id" />
<input type="hidden" name="search" t-att-value="search" />
<input type="hidden" name="order" t-att-value="order"/>
<div
t-if="attrib_values or tags"
class="accordion-item rounded-0 border-top-0 py-3"
>
<a
t-att-href="keep('/shop' + ('/category/' + slug(category)) if category else None, attribute_value=0, tags=0)"
t-attf-class="btn btn-{{navClass}} d-flex align-items-center py-1"
title="Clear Filters"
>
<small class="mx-auto"><b>Clear Filters</b></small>
<i class="oi oi-close" role="presentation"/>
</a>
</div>
<t t-foreach="attributes" t-as="a">
<t t-cache="a,attrib_set">
<div class="accordion-item nav-item mb-1 rounded-0" t-if="a.value_ids and len(a.value_ids) &gt; 1">
<h6 class="mb-3">
<b class="d-none d-lg-block" t-field="a.name"/>
</h6>
<div t-attf-id="o_products_attributes_{{a.id}}" class="">
<t t-if="a.display_type == 'select'">
<select class="form-select css_attribute_select mb-2" name="attribute_value">
<option value="" selected="true">All <t t-out="a.name"/></option>
<t t-foreach="a.value_ids" t-as="v">
<option t-att-value="'%s-%s' % (a.id,v.id)" t-esc="v.name" t-att-selected="v.id in attrib_set" />
</t>
</select>
</t>
<div t-elif="a.display_type == 'color'" class="mb-3">
<t t-call="website_sale.o_wsale_offcanvas_color_attribute"/>
</div>
<div t-elif="a.display_type in ('radio', 'pills', 'multi')" class="flex-column mb-3">
<t t-foreach="a.value_ids" t-as="v">
<div class="form-check mb-1">
<input type="checkbox"
name="attribute_value"
class="form-check-input"
t-att-id="'%s-%s' % (a.id,v.id)"
t-att-value="'%s-%s' % (a.id,v.id)"
t-att-checked="'checked' if v.id in attrib_set else None"/>
<label class="form-check-label fw-normal" t-att-for="'%s-%s' % (a.id,v.id)" t-field="v.name"/>
</div>
</t>
</div>
</div>
</div>
</t>
</t>
<t t-if="opt_wsale_filter_tags and opt_wsale_attributes"
t-call="website_sale.filter_products_tags"
>
<t t-set="all_tags" t-value="all_tags"/>
</t>
</form>
</div>
</xpath>
</template>
<template
id="products_attributes_collapsible"
name="Collapsed Attributes &amp; Variants filters"
inherit_id="website_sale.products_attributes"
>
<xpath expr="//form" position="attributes">
<attribute
name="class"
add="wsale_accordion_collapsible accordion accordion-flush"
remove="mb-2"
separator=" "
/>
</xpath>
<xpath expr="//div[hasclass('accordion-item')]//h6" position="replace">
<h6 class="accordion-header">
<button
class="accordion-button px-0 bg-transparent shadow-none"
type="button"
data-bs-toggle="collapse"
t-attf-data-bs-target="#o_products_attributes_{{a.id}}"
t-attf-aria-controls="o_products_attributes_{{a.id}}"
aria-expanded="true"
>
<b t-field="a.name"/>
</button>
</h6>
</xpath>
<xpath expr="//div[@t-attf-id='o_products_attributes_{{a.id}}']" position="attributes">
<attribute name="class" add="accordion-collapse collapse show" separator=" "/>
<attribute name="data-bs-parent" add="wsale_products_attributes_collapse"/>
</xpath>
<xpath expr="//select" position="attributes">
<attribute name="class" add="mb-3" remove="mb-2" separator=" "/>
</xpath>
<xpath expr="//div[hasclass('flex-column')]" position="attributes">
<attribute name="class" add="mb-3" separator=" "/>
</xpath>
</template>
<template id="filter_products_price" name="Filter by Prices">
<t t-set="is_disabled" t-value="available_min_price == available_max_price"/>
<div
id="o_wsale_price_range_option"
t-attf-class="position-relative {{_classes}} {{is_disabled and 'opacity-75 pe-none user-select-none'}}"
>
<t t-if="is_sidebar_collapsible">
<div class="accordion-item">
<h6 class="accordion-header">
<button
class="accordion-button px-0 bg-transparent shadow-none"
type="button"
data-bs-toggle="collapse"
t-attf-data-bs-target="#o_wsale_price_range_option_inner"
t-attf-aria-controls="o_wsale_price_range_option_inner"
aria-expanded="true"
>
<b>Price Range</b>
</button>
</h6>
<div
id="o_wsale_price_range_option_inner"
class="accordion-collapse collapse show"
>
<input
type="range"
multiple="multiple"
t-attf-class="form-range range-with-input {{_classes_input}}"
t-att-data-currency="website.currency_id.symbol"
t-att-data-currency-position="website.currency_id.position"
t-att-step="website.currency_id.rounding"
t-att-min="'%f' % (available_min_price)"
t-att-max="'%f' % (available_max_price)"
t-att-value="'%f,%f' % (min_price, max_price)"
/>
</div>
</div>
</t>
<t t-else="">
<label t-attf-class="h6 m-0 {{_classes_title}}">
<b>Price Range</b>
</label>
<input
type="range"
multiple="multiple"
t-attf-class="form-range range-with-input {{_classes_input}}"
t-att-data-currency="website.currency_id.symbol"
t-att-data-currency-position="website.currency_id.position"
t-att-step="website.currency_id.rounding"
t-att-min="'%f' % (available_min_price)"
t-att-max="'%f' % (available_max_price)"
t-att-value="'%f,%f' % (min_price, max_price)"
/>
</t>
</div>
</template>
<template id="filter_products_tags" name="Filter by Tags" active="True">
<div t-if="all_tags">
<h6 class="mb-3">
<b>Tags</b>
</h6>
<div class="flex-column mb-3">
<t t-call="website_sale.filter_products_tags_list">
<t t-set="all_tags" t-value="all_tags"/>
</t>
</div>
</div>
</template>
<template id="filter_products_tags_list">
<t t-foreach="all_tags" t-as="tag" class="list-group-item border-0 ps-0 pb-0">
<div class="form-check mb-1">
<input type="checkbox"
name="tags"
class="form-check-input"
t-attf-id="tag_#{tag.id}"
t-att-value="tag.id"
t-att-checked="'checked' if tag.id in tags else None"
/>
<label class="form-check-label fw-normal" t-attf-for="tag_#{tag.id}" t-field="tag.name"/>
</div>
</t>
</template>
<template id="products_list_view" inherit_id="website_sale.products" active="False" name="List View (by default)">
<xpath expr="//div[@id='products_grid']" position="after">
<!-- Nothing to do, this view is only meant to allow the server -->
<!-- to know if the list view layout should be used -->
</xpath>
</template>
<!-- /shop/product page -->
<template id="base_unit_price" name="Product Base unit price">
(<span class="o_base_unit_price" t-esc="combination_info['base_unit_price']" t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"/>
/ <span class="oe_custom_base_unit" t-field="product.base_unit_name"/>)
</template>
<template id="product" name="Product" track="1">
<!-- Qweb variable defining the class suffix for navbar items.
Change accordingly to the derired visual result (eg. `primary`, `dark`...)-->
<t t-set="navClass" t-valuef="light"/>
<t t-set="combination_info" t-value="product._get_combination_info()"/>
<t t-set="product_variant" t-value="product.env['product.product'].browse(combination_info['product_id'])"/>
<t t-call="website.layout">
<t t-set="additional_title" t-value="product.name" />
<div itemscope="itemscope" itemtype="http://schema.org/Product" id="wrap" class="js_sale o_wsale_product_page">
<t t-set="editor_message">DROP BUILDING BLOCKS HERE TO MAKE THEM AVAILABLE ACROSS ALL PRODUCTS</t>
<div class="oe_structure oe_empty oe_structure_not_nearest" id="oe_structure_website_sale_product_1" t-att-data-editor-message="editor_message"/>
<section id="product_detail"
t-attf-class="oe_website_sale container my-3 my-lg-4 #{'discount'
if combination_info['has_discounted_price'] else ''}"
t-att-data-view-track="view_track and '1' or '0'"
t-att-data-product-tracking-info="'product_tracking_info' in combination_info and json.dumps(combination_info['product_tracking_info'])"
>
<div class="row align-items-center">
<div class="col d-flex align-items-center order-1 order-lg-0">
<ol class="o_wsale_breadcrumb breadcrumb p-0 mb-4 m-lg-0">
<li class="o_not_editable breadcrumb-item d-none d-lg-inline-block">
<a t-att-href="keep(category=0, attribute_value=0, tags=0)">
<i class="oi oi-chevron-left d-lg-none me-1" role="presentation"/>All Products
</a>
</li>
<li
t-nocache="The category does not have to be cached, as the product can be accessed via different paths."
t-if="category"
class="breadcrumb-item"
>
<a
class="py-2 py-lg-0"
t-att-href="keep('/shop/category/%s' % slug(category), category=0, attribute_value=0, tags=0)"
>
<i class="oi oi-chevron-left d-lg-none me-1" role="presentation"/><t t-out="category.name"/>
</a>
</li>
<li t-else="" class="o_not_editable breadcrumb-item d-lg-none">
<a
class="py-2 py-lg-0"
t-att-href="keep(category=0, attribute_value=0, tags=0)"
>
<i class="oi oi-chevron-left me-1" role="presentation"/>All Products
</a>
</li>
<li class="breadcrumb-item d-none d-lg-inline-block active">
<span t-field="product.name" />
</li>
</ol>
</div>
<div class="col-lg-4 d-flex align-items-center">
<div class="d-flex justify-content-between w-100">
<t t-if="is_view_active('website_sale.search')" t-call="website_sale.search">
<t t-set="search" t-value="False"/>
<t t-set="_form_classes" t-valuef="mb-4 mb-lg-0"/>
<t t-set="_classes" t-value="'me-sm-2'"/>
</t>
<t t-call="website_sale.pricelist_list">
<t t-set="_classes" t-valuef="d-lg-inline ms-2"/>
</t>
</div>
</div>
</div>
<div class="row" id="product_detail_main" data-name="Product Page"
t-att-data-image_width="website.product_page_image_width"
t-att-data-image_layout="website.product_page_image_layout">
<t t-set="image_cols" t-value="website._get_product_page_proportions()"/>
<div
t-attf-class="col-lg-#{image_cols[0]} mt-lg-4 o_wsale_product_images position-relative"
t-if="website.product_page_image_width != 'none'"
t-att-data-image-amount="len(product_variant._get_images() if product_variant else product._get_images())"
>
<t t-call="website_sale.shop_product_images"/>
</div>
<div t-attf-class="col-lg-#{image_cols[1]} mt-md-4" id="product_details">
<t t-set="base_url" t-value="website.get_base_url()"/>
<h1 itemprop="name" t-field="product.name">Product Name</h1>
<span itemprop="url" style="display:none;" t-esc="base_url + product.website_url"/>
<span itemprop="image" style="display:none;" t-esc="base_url + website.image_url(product, 'image_1920')" />
<t t-if="is_view_active('website_sale.product_comment')">
<a href="#o_product_page_reviews" class="o_product_page_reviews_link text-decoration-none">
<t t-call="portal_rating.rating_widget_stars_static">
<t t-set="rating_avg" t-value="product.rating_avg"/>
<t t-set="trans_text_plural">%s reviews</t>
<t t-set="trans_text_singular">%s review</t>
<t t-set="rating_count" t-value="(trans_text_plural if product.rating_count > 1 else trans_text_singular) % product.rating_count"/>
</t>
</a>
</t>
<div t-field="product.description_ecommerce" class="oe_structure"
placeholder="A detailed, formatted description to promote your product on this page. Use '/' to discover more features."/>
<form t-if="product._is_add_to_cart_possible()" action="/shop/cart/update" method="POST">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" t-nocache="The csrf token must always be up to date."/>
<div class="js_product js_main_product mb-3">
<div>
<t t-call="website_sale.product_price"/>
<small t-if="'base_unit_price' in combination_info"
class="ms-1 text-muted o_base_unit_price_wrapper d-none" groups="website_sale.group_show_uom_price">
<t t-call='website_sale.base_unit_price'/>
</small>
</div>
<t t-placeholder="select">
<input type="hidden" class="product_id" name="product_id" t-att-value="product_variant.id" />
<input type="hidden" class="product_template_id" name="product_template_id" t-att-value="product.id" />
<input t-if="product.public_categ_ids.ids" type="hidden" class="product_category_id" name="product_category_id" t-att-value="product.public_categ_ids.ids[0]" />
<t t-call="website_sale.variants">
<t t-set="ul_class" t-valuef="flex-column" />
<t t-set="parent_combination" t-value="None" />
<t t-set="combination" t-value="combination_info['combination']"/>
</t>
</t>
<p t-if="True" class="css_not_available_msg alert alert-warning">This combination does not exist.</p>
<div id="o_wsale_cta_wrapper" class="d-flex flex-wrap align-items-center">
<t t-set="hasQuantities" t-value="false"/>
<t t-set="hasBuyNow" t-value="false"/>
<!-- TODO: remove line below in master -->
<t t-set="ctaSizeBig" t-value="not hasQuantities or not hasBuyNow"/>
<div id="add_to_cart_wrap" t-attf-class="{{'d-none' if combination_info['prevent_zero_price_sale'] else 'd-inline-flex'}} align-items-center mb-2 me-auto">
<a data-animation-selector=".o_wsale_product_images" role="button" id="add_to_cart" t-attf-class="btn btn-primary js_check_product a-submit flex-grow-1" href="#">
<i class="fa fa-shopping-cart me-2"/>
Add to cart
</a>
</div>
<div id="product_option_block" class="d-flex flex-wrap w-100"/>
</div>
<t
t-if="is_view_active('website_sale.product_tags')"
t-call="website_sale.product_tags"
>
<t
t-set="all_product_tags"
t-value="product_variant.all_product_tag_ids"
/>
</t>
</div>
</form>
<p t-elif="not product.active" class="alert alert-warning">
This product is no longer available.
</p>
<p t-else="" class="alert alert-warning">
This product has no valid combination.
</p>
<t t-call="website_sale.product_accordion"/>
<div
id="contact_us_wrapper"
t-attf-class="{{'d-flex' if combination_info['prevent_zero_price_sale'] else 'd-none'}} oe_structure oe_structure_solo #{_div_classes}"
>
<section
class="s_text_block"
data-snippet="s_text_block"
data-name="Text"
>
<div class="container">
<a
t-att-href="website.contact_us_button_url"
class="btn btn-primary btn_cta"
>
Contact Us
</a>
</div>
</section>
</div>
<div
t-if="not is_view_active('website_sale_comparison.accordion_specs_item')"
id="product_attributes_simple"
>
<t t-set="single_value_attributes" t-value="product.valid_product_template_attribute_line_ids._prepare_single_value_for_display()"/>
<table t-attf-class="table table-sm text-muted {{'' if single_value_attributes else 'd-none'}}">
<t t-foreach="single_value_attributes" t-as="attribute">
<tr>
<td>
<span t-field="attribute.name"/>:
<t t-foreach="single_value_attributes[attribute]" t-as="ptal">
<span t-field="ptal.product_template_value_ids._only_active().name"/><t t-if="not ptal_last">, </t>
</t>
</td>
</tr>
</t>
</table>
</div>
<t t-set="product_documents" t-value="product.sudo().product_document_ids.filtered(lambda doc: doc.shown_on_product_page)"/>
<div id="product_documents" class="my-2" t-if="product_documents">
<h5>Documents</h5>
<t t-foreach="product_documents" t-as="document_sudo">
<t t-set="attachment_sudo" t-value="document_sudo.ir_attachment_id"/>
<t t-set="target" t-value="attachment_sudo.type == 'url' and '_blank' or '_self'"/>
<t t-set="icon" t-value="attachment_sudo.type == 'url' and 'fa-link' or 'fa-download'"/>
<div>
<a t-att-href="'/shop/' + slug(product) + '/document/' + str(document_sudo.id)" t-att-target="target">
<i t-att-class="'fa ' + icon"/>
<t t-out="attachment_sudo.name"/>
</a>
</div>
</t>
</div>
<div
id="o_product_terms_and_share"
class="d-flex justify-content-between flex-column flex-md-row align-items-md-end gap-3 mb-3"
/>
</div>
</div>
</section>
<div itemprop="description" t-field="product.website_description" class="oe_structure oe_empty mt16" id="product_full_description"/>
<div class="oe_structure oe_empty oe_structure_not_nearest mt16" id="oe_structure_website_sale_product_2" t-att-data-editor-message="editor_message"/>
</div>
</t>
</template>
<template id="product_accordion" name="Accordion On Product Page">
<div
t-if="is_view_active('website_sale_comparison.accordion_specs_item')
or is_view_active('website_sale.accordion_more_information')"
id="product_accordion"
class="o_accordion_not_initialized accordion accordion-flush my-4"
>
<div
t-if="is_view_active('website_sale.accordion_more_information')"
id="more_information_accordion_item"
class="accordion-item"
/>
</div>
</template>
<template
id="accordion_more_information"
name="More Information Accordion Item"
inherit_id="website_sale.product_accordion"
active="False"
>
<xpath expr="//div[@id='more_information_accordion_item']" position="inside">
<div class="accordion-header my-0 h6">
<button
class="accordion-button collapsed fw-medium"
type="button"
data-bs-toggle="collapse"
data-bs-target="#customizable_item"
aria-expanded="false"
aria-controls="customizable_item"
>
More Information
</button>
</div>
<div
id="customizable_item"
class="accordion-collapse collapse"
data-bs-parent="#product_accordion"
>
<div class="accordion-body pt-0">
<p>This content will be shared across all product pages.</p>
</div>
</div>
</xpath>
</template>
<template id="product_tags" name="Product Tags" active="True">
<div class="o_product_tags o_field_tags d-flex flex-wrap align-items-center gap-2 mb-2 mt-1">
<t t-foreach="all_product_tags" t-as="tag">
<t t-if="tag.visible_on_ecommerce">
<span t-if="tag.image"
class="order-0"
t-field="tag.image"
t-options="{'widget': 'image', 'class': 'o_product_tag_img rounded'}"
/>
<span t-else="" class="position-relative order-1 py-1 px-2">
<span class="position-absolute top-0 start-0 w-100 h-100 rounded"
t-attf-style="background-color: #{tag.color}; opacity: .2;"
/>
<span class="text-nowrap small"
t-attf-style="color: #{tag.color}"
t-field="tag.name"
/>
</span>
</t>
</t>
</div>
</template>
<template id="alternative_products" name="Alternative Products" inherit_id="website_sale.product" active="True">
<div itemprop="description" position="after">
<div class="oe_structure oe_structure_solo oe_unremovable oe_unmovable" id="oe_structure_website_sale_recommended_products" t-ignore="true" t-if="product.alternative_product_ids">
<section data-snippet="s_dynamic_snippet_products"
class="oe_unmovable oe_unremovable s_dynamic_snippet_products o_wsale_alternative_products s_dynamic pt32 pb32 o_colored_level s_product_product_borderless_1"
data-name="Alternative Products" style="background-image: none;" t-att-data-filter-id="product._get_alternative_product_filter()"
data-template-key="website_sale.dynamic_filter_template_product_product_borderless_1" data-product-category-id="all" data-number-of-elements="4"
data-number-of-elements-small-devices="1" data-number-of-records="16" data-carousel-interval="5000" data-bs-original-title="" title="">
<div class="container o_not_editable">
<div class="css_non_editable_mode_hidden">
<div class="missing_option_warning alert alert-info rounded-0 fade show d-none d-print-none o_default_snippet_text">
Your Dynamic Snippet will be displayed here...
This message is displayed because youy did not provide both a filter and a template to use.
</div>
</div>
<div class="dynamic_snippet_template"></div>
</div>
</section>
</div>
</div>
</template>
<template id="product_custom_text" inherit_id="website_sale.product" customize_show="True" active="True" name="Terms and Conditions" priority="21">
<xpath expr="//div[@id='o_product_terms_and_share']" position="inside">
<p class="text-muted mb-0">
<a href="/terms" class="text-muted"><u>Terms and Conditions</u></a><br/>
30-day money-back guarantee<br/>
Shipping: 2-3 Business Days
</p>
</xpath>
</template>
<template id="product_share_buttons" inherit_id="website_sale.product" active="True" name="Share Buttons" priority="22">
<xpath expr="//div[@id='o_product_terms_and_share']" position="inside">
<div
data-snippet="s_share"
data-name="Share"
class="s_share text-start o_no_link_popover"
>
<h4 class="s_share_title d-none o_default_snippet_text">Share</h4>
<a
href="https://www.facebook.com/sharer/sharer.php?u={url}"
target="_blank"
aria-label="Facebook"
class="s_share_facebook"
>
<i class="fa fa-facebook rounded shadow-sm"/>
</a>
<a
href="https://twitter.com/intent/tweet?text={title}&amp;url={url}"
target="_blank"
aria-label="X"
class="s_share_twitter"
>
<i class="fa fa-twitter rounded shadow-sm"/>
</a>
<a
href="https://www.linkedin.com/sharing/share-offsite/?url={url}"
target="_blank"
aria-label="LinkedIn"
class="s_share_linkedin"
>
<i class="fa fa-linkedin rounded shadow-sm"/>
</a>
<a
href="https://wa.me/?text={title}"
target="_blank"
aria-label="WhatsApp"
class="s_share_whatsapp"
>
<i class="fa fa-whatsapp rounded shadow-sm"/>
</a>
<a
href="https://pinterest.com/pin/create/button/?url={url}&amp;media={media}&amp;description={title}"
target="_blank"
aria-label="Pinterest"
class="s_share_pinterest"
>
<i class="fa fa-pinterest rounded shadow-sm"/>
</a>
<a
href="mailto:?body={url}&amp;subject={title}"
aria-label="Email"
class="s_share_email"
>
<i class="fa fa-envelope rounded shadow-sm"/>
</a>
</div>
</xpath>
</template>
<!-- Product options: Zoom -->
<template inherit_id='website_sale.product' id="product_picture_magnify_hover" name="Automatic Image Zoom">
<xpath expr='//div[hasclass("o_wsale_product_page")]' position='attributes'>
<attribute name="data-ecom-zoom-auto">1</attribute>
<attribute name="class" separator=" " add="ecom-zoomable zoomodoo-next" />
</xpath>
</template>
<template inherit_id='website_sale.product' id="product_picture_magnify_click" active="False" name="Image Zoom On Click">
<xpath expr='//div[hasclass("o_wsale_product_page")]' position='attributes'>
<attribute name="data-ecom-zoom-click">1</attribute>
<attribute name="class" separator=" " add="ecom-zoomable zoomodoo-next" />
</xpath>
</template>
<template inherit_id='website_sale.product' id="product_picture_magnify_both" active="False" name="Automatic Image Zoom And On Click">
<xpath expr='//div[hasclass("o_wsale_product_page")]' position='attributes'>
<attribute name="data-ecom-zoom-auto">1</attribute>
<attribute name="data-ecom-zoom-click">1</attribute>
<attribute name="class" separator=" " add="ecom-zoomable zoomodoo-next" />
</xpath>
</template>
<!-- Product options: OpenChatter -->
<template id="product_comment" inherit_id="website_sale.product" active="False" name="Discussion and Rating" priority="15">
<xpath expr="//div[@t-field='product.website_description']" position="after">
<div class="o_shop_discussion_rating" data-anchor='true'>
<section id="o_product_page_reviews" class="container pt32 pb32" data-anchor='true'>
<a class="o_product_page_reviews_title d-flex justify-content-between text-decoration-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#o_product_page_reviews_content" aria-expanded="false" aria-controls="o_product_page_reviews_content">
<h3 class="mb32">Customer Reviews</h3>
<i class="fa align-self-start"/>
</a>
<div id="o_product_page_reviews_content" class="collapse">
<t t-call="portal.message_thread">
<t t-set="object" t-value="product"/>
<t t-set="display_rating" t-value="True"/>
<t t-set="message_per_page" t-value="5"/>
<t t-set="two_columns" t-value="true"/>
</t>
</div>
</section>
</div>
</xpath>
</template>
<template id="product_quantity" inherit_id="website_sale.product" name="Select Quantity">
<xpath expr="//t[@t-set='hasQuantities']" position="attributes">
<attribute name="t-value" remove="false" add="true" separator=" "/>
</xpath>
<div id="add_to_cart_wrap" position="before">
<div t-attf-class="css_quantity input-group {{'d-none' if combination_info['prevent_zero_price_sale'] else 'd-inline-flex'}} me-2 mb-2 align-middle" contenteditable="false">
<a t-attf-href="#" class="btn btn-link js_add_cart_json" aria-label="Remove one" title="Remove one">
<i class="fa fa-minus"/>
</a>
<input type="text" class="form-control quantity text-center" data-min="1" name="add_qty" t-att-value="1"/>
<a t-attf-href="#" class="btn btn-link float_left js_add_cart_json" aria-label="Add one" title="Add one">
<i class="fa fa-plus"/>
</a>
</div>
</div>
</template>
<template id="product_buy_now" inherit_id="website_sale.product" active="False" name="Buy Now Button">
<xpath expr="//t[@t-set='hasBuyNow']" position="attributes">
<attribute name="t-value" remove="false" add="true" separator=" "/>
</xpath>
<xpath expr="//a[@id='add_to_cart']" position="after">
<a role="button" class="btn btn-outline-primary o_we_buy_now ms-1" href="#">
<i class="fa fa-bolt me-2"/>
Buy now
</a>
</xpath>
</template>
<template id="website_sale.tax_indication" active="False">
<span t-if="website.show_line_subtotals_tax_selection == 'tax_excluded'" class="h6 text-muted">
Tax Excluded
</span>
<span t-else="" class="h6 text-muted">
Tax Included
</span>
</template>
<template id="product_price">
<div itemprop="offers" itemscope="itemscope" itemtype="http://schema.org/Offer" t-attf-class="product_price mt-2 mb-3 {{'d-none' if combination_info['prevent_zero_price_sale'] else 'd-inline-block'}}">
<h3 class="css_editable_mode_hidden">
<span class="oe_price"
style="white-space: nowrap;"
t-out="combination_info['price']"
t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"/>
<span itemprop="price" style="display:none;" t-out="combination_info['price']"/>
<span itemprop="priceCurrency" style="display:none;" t-esc="website.currency_id.name"/>
<span t-attf-class="text-muted oe_default_price ms-1 h5 {{'' if combination_info['has_discounted_price'] and not combination_info['compare_list_price'] else 'd-none'}}"
style="text-decoration: line-through; white-space: nowrap;"
t-esc="combination_info['list_price']"
t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"
itemprop="listPrice"
/>
<t t-if="is_view_active('website_sale.tax_indication')" t-call="website_sale.tax_indication"/>
<del t-if="combination_info['compare_list_price'] and (combination_info['compare_list_price'] &gt; combination_info['price'])"
class="text-muted ms-1 h5 oe_compare_list_price">
<bdi dir="inherit">
<span t-esc="combination_info['compare_list_price']"
groups="website_sale.group_product_price_comparison"
t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"/>
</bdi>
</del>
</h3>
<h3 class="css_non_editable_mode_hidden decimal_precision" t-att-data-precision="str(website.currency_id.decimal_places)">
<span t-field="product.list_price"
t-options="{'widget': 'monetary', 'display_currency': product.currency_id}"/>
<t t-if="is_view_active('website_sale.tax_indication')" t-call="website_sale.tax_indication"/>
<del t-if="combination_info['compare_list_price'] and (combination_info['compare_list_price'] &gt; combination_info['price'])">
<bdi dir="inherit">
<span t-field="product.compare_list_price"
groups="website_sale.group_product_price_comparison"
t-options="{'widget': 'monetary', 'display_currency': product.currency_id}"/>
</bdi>
</del>
</h3>
</div>
<div id="product_unavailable" t-attf-class="{{'d-flex' if combination_info['prevent_zero_price_sale'] else 'd-none'}}">
<h3 class="fst-italic" t-field="website.prevent_zero_price_sale_text"/>
</div>
</template>
<template id="product_variants" inherit_id="website_sale.product" active="False" name="List View of Variants">
<xpath expr="//t[@t-placeholder='select']" position="replace">
<!--
Using this setting with dynamic variants is not supported.
Indeed the variants that have yet to exist will not show on the
list and will never be selectable to be created...
We also don't use the feature with no_variant because these
attributes have to be selected manually.
Finally we don't use the feature with is_custom values because
they need to be set by the user.
-->
<t t-if="not product.has_dynamic_attributes() and not product._has_no_variant_attributes() and not product._has_is_custom_values()">
<t t-set="attribute_exclusions" t-value="product._get_attribute_exclusions()"/>
<t t-set="filtered_sorted_variants" t-value="product._get_possible_variants_sorted()"/>
<ul class="d-none js_add_cart_variants mb-0" t-att-data-attribute_exclusions="json.dumps(attribute_exclusions)"/>
<input type="hidden" class="product_template_id" name="product_template_id" t-att-value="product.id"/>
<input type="hidden" t-if="len(filtered_sorted_variants) == 1" class="product_id" name="product_id" t-att-value="filtered_sorted_variants[0].id"/>
<t t-if="len(filtered_sorted_variants) &gt; 1">
<t t-set="template_combination_info" t-value="product._get_combination_info(only_template=True)"/>
<div class="mb-4">
<div t-foreach="filtered_sorted_variants" t-as="variant_id" class="form-check mb-1">
<t t-set="combination_info" t-value="variant_id._get_combination_info_variant()"/>
<input type="radio"
name="product_id"
class="form-check-input product_id js_product_change"
t-att-checked="'checked' if variant_id_index == 0 else None"
t-attf-id="radio_variant_#{variant_id.id}"
t-att-value="variant_id.id"
t-att-data-price="combination_info['price']"
t-att-data-combination="variant_id.product_template_attribute_value_ids.ids"/>
<label t-attf-for="radio_variant_#{variant_id.id}" label-default="label-default" class="form-check-label fw-normal">
<span t-out="combination_info['display_name']"/>
<t t-set="diff_price" t-value="website.currency_id.compare_amounts(combination_info['price'], template_combination_info['price'])"/>
<span t-attf-class="badge text-bg-{{navClass}} border" t-if="diff_price != 0">
<span class="sign_badge_price_extra" t-out="diff_price > 0 and '+' or '-'"/>
<span t-out="abs(combination_info['price'] - template_combination_info['price'])"
t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"
class="text-muted fst-italic"/>
</span>
</label>
</div>
</div>
</t>
</t>
<t t-else="">$0</t>
</xpath>
</template>
<template id="wizard_checkout" name="Wizard Checkout">
<t t-call="website.step_wizard">
<t t-set="wizard_step" t-value="website._get_checkout_steps()"/>
</t>
</template>
<!-- /shop/extra_info route -->
<template id="extra_info" name="Checkout Extra Info" active="False">
<t t-call="website_sale.checkout_layout">
<t t-set="show_navigation_button" t-value="False"/>
<t t-set="redirect" t-valuef="/shop/extra_info"/>
<t t-set="oe_structure">
<!-- This is the drag-and-drop area for website building blocs at the end of each
checkout page. This is append at the of the page in `checkout_layout`. The
templates created in the database to store blocs are hooked using XPath on the
`oe_struture` element ID. Therefore, we can't use dynamic IDs (like with
t-att-id) and each template needs to define a div element. -->
<div class="oe_structure" id="oe_structure_website_sale_extra_info_1"/>
</t>
<h3 class="mb-4">Extra info</h3>
<section class="s_website_form" data-vcss="001" data-snippet="s_website_form">
<div class="container">
<form action="/website/form/" method="post" enctype="multipart/form-data" class="o_mark_required s_website_form_no_recaptcha" data-mark="*" data-force_action="shop.sale.order" data-model_name="sale.order" data-success-mode="redirect" data-success-page="/shop/payment" hide-change-model="true">
<div class="s_website_form_rows s_col_no_bgcolor row">
<div class="s_website_form_field col-12 py-2 mb-0" data-type="char" data-name="Field">
<div class="s_col_no_resize s_col_no_bgcolor row">
<label class="s_website_form_label col-form-label col-sm-auto" style="width: 200px" for="sale1">
<span class="s_website_form_label_content">Your Reference</span>
</label>
<div class="col-sm">
<input id="sale1" type="text" class="s_website_form_input form-control" name="client_order_ref"/>
</div>
</div>
</div>
<div class="s_website_form_field s_website_form_custom col-12 py-2 mb-0" data-type="text" data-name="Field">
<div class="s_col_no_resize s_col_no_bgcolor row">
<label class="s_website_form_label col-form-label col-sm-auto" style="width: 200px" for="sale2">
<span class="s_website_form_label_content">Give us your feedback</span>
</label>
<div class="col-sm">
<textarea id="sale2" class="s_website_form_input form-control" name="Give us your feedback" />
</div>
</div>
</div>
<div class="s_website_form_field s_website_form_custom col-12 py-2 mb-0" data-type="binary" data-name="Field">
<div class="s_col_no_resize s_col_no_bgcolor row">
<label class="s_website_form_label col-form-label col-sm-auto" style="width: 200px" for="sale3">
<span class="s_website_form_label_content">Upload a document</span>
</label>
<div class="col-sm">
<input id="sale3" type="file" class="s_website_form_input form-control" name="a_document" />
</div>
</div>
</div>
<div class="s_website_form_submit s_website_form_no_submit_option d-flex flex-column flex-lg-row align-items-lg-center pt-4">
<a role="button"
name="website_sale_main_button"
class="s_website_form_send btn btn-primary order-lg-3 w-100 w-lg-auto ms-lg-auto"
href="/shop/confirm_order">
Continue checkout
<i class="fa fa-angle-right ms-2 fw-light"/>
</a>
<div class="position-relative d-flex d-lg-none w-100 justify-content-center align-items-center my-2 opacity-75">
<hr class="w-100"/>
<span class="px-3">or</span>
<hr class="w-100"/>
</div>
<a href="/shop/checkout" class="text-center">
<i class="fa fa-angle-left me-2 fw-light"/>
Return to shipping
</a>
<span id="s_website_form_result"/>
</div>
</div>
</form>
</div>
</section>
</t>
</template>
<!-- Encapsulate the content in a `a` tag with a link to the product page. Override this
template to change or remove the product link. Called in `website_sale.cart_lines`. -->
<template id="cart_line_product_link" name="Shopping Cart Line Product Link">
<a t-att-href="line.product_id.website_url">
<t t-out="0"/>
</a>
</template>
<!-- This template displays all the lines following the first one on the description of the sale
order line, with a muted style. For typical products this content will be the product
description_sale. Called in `website_sale.cart_lines`. -->
<template id="cart_line_description_following_lines" name="Shopping Cart Line Description Following Lines">
<t t-set="description_lines" t-value="line.get_description_following_lines()"/>
<div t-if="description_lines" t-attf-class="text-muted {{div_class}} small">
<t t-foreach="description_lines" t-as="name_line">
<span t-if="name_line" class="d-block" t-out="name_line"/>
</t>
</div>
</template>
<!-- Lines that show items in the cart. Called in `website_sale.cart`. -->
<template id="cart_lines" name="Shopping Cart Lines">
<div t-if="not website_sale_order or not website_sale_order.website_order_line" class="js_cart_lines alert alert-info">
Your cart is empty!
</div>
<t t-if='website_sale_order'>
<div t-if='website_sale_order._get_shop_warning(clear=False)' class="alert alert-warning js_cart_lines" role="alert">
<strong>Warning!</strong> <t t-esc='website_sale_order._get_shop_warning()'/>
</div>
</t>
<div id="cart_products"
t-if="website_sale_order and website_sale_order.website_order_line"
class="js_cart_lines d-flex flex-column mb32">
<t t-set="show_qty" t-value="is_view_active('website_sale.product_quantity')"/>
<div t-foreach="website_sale_order.website_order_line"
t-as="line"
t-attf-class="o_cart_product d-flex align-items-stretch gap-3 #{line.linked_line_id and 'optional_product info'} #{not line_last and 'border-bottom pb-4'} #{line_index &gt; 0 and 'pt-4'}"
t-attf-data-product-id="#{line.product_id and line.product_id.id}">
<t t-if="line.product_id">
<div style="width: 64px">
<!--
Unsellable lines can have unpublished products, but portal users have no
access to unpublished product images. To ensure product images are
always shown for unsellable lines, we use the raw image data as src
(which doesn't require access, unlike the image URL).
-->
<img
t-if="line._is_not_sellable_line() and line.product_id.image_128"
t-att-src="image_data_uri(line.product_id.image_128)"
class="o_image_64_max img rounded"
t-att-alt="line.name_short"
/>
<div
t-elif="line.product_id.image_128"
t-field="line.product_id.image_128"
t-options="{
'widget': 'image',
'qweb_img_responsive': False,
'class': 'o_image_64_max rounded',
}"
/>
</div>
<div class="flex-grow-1">
<t t-call="website_sale.cart_line_product_link">
<h6 t-field="line.name_short" class="d-inline align-top h6 fw-bold"/>
</t>
<t t-call="website_sale.cart_line_description_following_lines">
<t t-set="div_class" t-value="''"/>
</t>
<div name="o_wsale_cart_line_button_container">
<a href='#'
class="js_delete_product d-none d-md-inline-block small"
aria-label="Remove from cart"
title="Remove from cart">Remove</a>
<button class="js_delete_product btn btn-light d-inline-block d-md-none"
title="remove">
<i class="fa fa-trash-o"/>
</button>
</div>
<t t-if="line.product_type == 'combo'">
<div
t-foreach="line.linked_line_ids"
t-as="combo_item_line"
t-attf-class="{{'' if combo_item_line_last else 'pb-2'}}"
>
<t t-call="website_sale.cart_combo_item_line"/>
</div>
</t>
</div>
<div class="d-flex flex-column align-items-end">
<div t-attf-class="css_quantity input-group mb-2"
name="website_sale_cart_line_quantity">
<t t-if="not line._is_not_sellable_line()">
<t t-if="show_qty">
<a href="#"
class="js_add_cart_json btn btn-link d-inline-block border-end-0"
aria-label="Remove one"
title="Remove one">
<i class="position-relative z-1 fa fa-minus"/>
</a>
<input type="text"
class="js_quantity quantity form-control border-start-0 border-end-0"
t-att-data-line-id="line.id"
t-att-data-product-id="line.product_id.id"
t-att-value="line._get_displayed_quantity()"/>
<t t-if="line._get_shop_warning(clear=False)">
<a href="#" class="btn btn-link">
<i class='fa fa-warning text-warning'
t-att-title="line._get_shop_warning()"
role="img"
aria-label="Warning"/>
</a>
</t>
<a t-else=""
href="#"
class="js_add_cart_json d-inline-block float_left btn btn-link border-start-0"
aria-label="Add one"
title="Add one">
<i class="fa fa-plus position-relative z-1"/>
</a>
</t>
<t t-else="">
<input type="hidden"
class="js_quantity form-control quantity"
t-att-data-line-id="line.id"
t-att-data-product-id="line.product_id.id"
t-att-value="line._get_displayed_quantity()"/>
</t>
</t>
<t t-else="">
<span class="w-100 text-muted" t-esc="int(line.product_uom_qty)"/>
<input type="hidden"
class="js_quantity quantity form-control"
t-att-data-line-id="line.id"
t-att-data-product-id="line.product_id.id"
t-att-value="line._get_displayed_quantity()"/>
</t>
</div>
<div class="mb-0 h6 fw-bold text-end" name="website_sale_cart_line_price">
<t t-if="line.discount">
<del t-attf-class="#{'text-muted mr8'}"
style="white-space: nowrap;"
t-out="line._get_displayed_unit_price() * line.product_uom_qty"
t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"/>
</t>
<t t-set="product_price" t-value="line._get_cart_display_price()"/>
<t t-call="website_sale.cart_product_price"/>
<small t-if="not line._is_not_sellable_line() and line.product_id.base_unit_price"
class="cart_product_base_unit_price d-block text-muted"
groups="website_sale.group_show_uom_price">
<t t-call='website_sale.base_unit_price'>
<t t-set='product' t-value='line.product_id'/>
<t t-set='combination_info'
t-value="{'base_unit_price': product._get_base_unit_price(product_price/line.product_uom_qty)}"/>
</t>
</small>
</div>
</div>
</t>
</div>
</div>
</template>
<template id="cart_combo_item_line">
<div class="d-flex align-items-center">
<div t-field="combo_item_line.product_id.image_128"
t-options="{
'widget': 'image',
'qweb_img_responsive': False,
'class': 'o_image_64_max rounded',
}"
/>
<div class="ms-3">
<a t-att-href="combo_item_line.product_id.website_url">
<h6 class="d-inline align-top h6 fw-bold">
<span t-out="combo_item_line._get_displayed_quantity()"/>
x
<span t-out="combo_item_line.name_short"/>
</h6>
</a>
<t
t-set="description_lines"
t-value="combo_item_line.get_description_following_lines()"
/>
<div t-if="description_lines" t-attf-class="text-muted d-none d-md-block small">
<t t-foreach="description_lines" t-as="description_line">
<span class="d-block" t-if="description_line" t-out="description_line"/>
</t>
</div>
</div>
</div>
</template>
<template id="cart_product_price">
<span
t-out="product_price"
style="white-space: nowrap;"
t-options="{'widget': 'monetary', 'display_currency': website_sale_order.currency_id}"
/>
</template>
<!-- /shop/cart route -->
<template id="cart" name="Shopping Cart">
<t t-call="website_sale.checkout_layout">
<t t-set="show_shorter_cart_summary" t-value="True"/>
<t t-set="show_footer" t-value="True"/>
<t t-set="oe_structure">
<!-- This is the drag-and-drop area for website building blocs at the end of each
checkout page. This is append at the of the page in `checkout_layout`. The
templates created in the database to store blocs are hooked using XPath on the
`oe_struture` element ID. Therefore, we can't use dynamic IDs (like with
t-att-id) and each template needs to define a div element. -->
<div class="oe_structure" id="oe_structure_website_sale_cart_2"/>
</t>
<div class="col">
<h3 class="mb-4">Order overview</h3>
<div t-if="abandoned_proceed or access_token" class="alert alert-info mt8 mb8" role="alert"> <!-- abandoned cart choices -->
<t t-if="abandoned_proceed">
<p>Your previous cart has already been completed.</p>
<p t-if="website_sale_order">Please proceed your current cart.</p>
</t>
<t t-if="access_token">
<p>This is your current cart.</p>
<p>
<strong>
<a t-attf-href="/shop/cart/?access_token=#{access_token}&amp;revive=squash">Click here</a>
</strong> if you want to restore your previous cart. Your current cart will be replaced with your previous cart.
</p>
<p>
<strong>
<a t-attf-href="/shop/cart/?access_token=#{access_token}&amp;revive=merge">Click here</a>
</strong> if you want to merge your previous cart into current cart.
</p>
</t>
</div>
<t t-call="website_sale.cart_lines"/>
<div class="clearfix" />
<div class="oe_structure" id="oe_structure_website_sale_cart_1"/>
</div>
</t>
</template>
<!-- Deactivatable through the website editor. -->
<template id="suggested_products_list" inherit_id="website_sale.cart_lines" name="Accessory Products in my cart">
<xpath expr="//div[@id='cart_products']" position="inside">
<h5 t-attf-class="mt32 mb-3" t-if="suggested_products">Suggested accessories</h5>
<div t-if="suggested_products"
id="suggested_products"
class="d-flex flex-column align-items-stretch mb32">
<div t-foreach="suggested_products"
t-as="product"
t-attf-class="d-flex gap-3 #{not product_last and 'border-bottom pb-4'} #{product_index &gt; 0 and 'pt-4'}"
t-att-data-publish="product.website_published and 'on' or 'off'">
<div style="width: 64px">
<a t-att-href="product.website_url">
<span t-field="product.image_128" t-options="{'widget': 'image', 'qweb_img_responsive': False, 'class': 'o_image_64_max rounded'}"/>
</a>
</div>
<div class="o_cart_suggested_product_name flex-grow-1">
<div>
<a t-att-href="product.website_url">
<strong t-out="product.with_context(display_default_code=False).display_name"/>
</a>
</div>
<div class="d-none d-md-block text-muted" t-field="product.description_sale"/>
</div>
<div class="d-flex flex-column align-items-end">
<input class="js_quantity" name="product_id" t-att-data-product-id="product.id" type="hidden"/>
<a role="button"
class="js_add_suggested_products btn btn-md btn-outline-primary text-nowrap">
<span class="d-md-none fa fa-shopping-cart"/>
<span class="d-none d-md-inline">Add to cart</span>
</a>
<div class="mb-0 h-6 fw-bold text-end d-flex"
name="website_sale_suggested_product_price">
<t t-set="combination_info"
t-value="product._get_combination_info_variant()"/>
<del t-attf-class="text-muted mr8 {{'' if combination_info['has_discounted_price'] else 'd-none'}}"
t-esc="combination_info['list_price']"
t-options="{'widget': 'monetary', 'display_currency': website.currency_id}"
style="white-space: nowrap;"/>
<span t-esc="combination_info['price']"
t-options="{'widget': 'monetary','display_currency': website.currency_id}"
style="white-space: nowrap;"/>
</div>
</div>
</div>
</div>
</xpath>
</template>
<!-- Called in `website_sale.reduction_code`. -->
<template id='coupon_form' name='Coupon form'>
<!-- Checkout context:
- redirect: The route to redirect to when a customer enters a coupon; default: `None`.
- website_sale_order: The current order.
-->
<form t-attf-action="/shop/pricelist#{redirect and '?r=' + redirect or ''}"
method="post" name="coupon_code">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" t-nocache="The csrf token must always be up to date."/>
<div class="input-group w-100 my-2">
<input name="promo" class="form-control" type="text" placeholder="Discount code..." t-att-value="website_sale_order.pricelist_id.code or None"/>
<a href="#" role="button" class="btn btn-secondary a-submit ps-2">Apply</a>
</div>
</form>
<t t-if="request.params.get('code_not_available')" name="code_not_available">
<div class="alert alert-danger text-start" role="alert">This promo code is not available.</div>
</t>
</template>
<!-- Called in `website_sale.checkout_layout`. -->
<template id="navigation_buttons" name="Navigation buttons">
<!-- Layout customization parameters:
- _cta_classes: CSS classes to append on the primary navigation button; default `None`.
- _form_send_navigation: Whether the primary button serves as a submit button for a
form; default `None`.
- hide_payment_button: Whether the payment button should be hidden; default: False.
-->
<!-- Checkout context:
- website_sale_order: The current order.
- xmlid: The id of the xml templated rendered by the controller.
-->
<t t-set="step_specific_values" t-value="website._get_checkout_steps(xmlid)"/>
<div t-attf-class="#{_container_classes} d-flex #{_form_send_navigation and 'flex-column flex-lg-row align-items-lg-center' or 'flex-column'} mb-5 mb-lg-0 pt-4">
<t t-if="website_sale_order and website_sale_order.website_order_line">
<t t-if="xmlid == 'website_sale.payment'">
<div t-if="not errors and not website_sale_order.amount_total"
name="o_website_sale_free_cart">
<form name="o_wsale_confirm_order"
class="d-flex flex-column"
target="_self"
action="/shop/payment/validate"
method="post">
<input type="hidden"
name="csrf_token"
t-att-value="request.csrf_token()"
t-nocache="The csrf token must always be up to date."/>
<t t-if="not hide_payment_button" t-call="payment.submit_button">
<t t-set="submit_button_label">Confirm Order</t>
</t>
</form>
</div>
<t t-elif="not hide_payment_button" t-call="payment.submit_button"/>
</t>
<t t-else="">
<a role="button" name="website_sale_main_button"
t-attf-class="#{_cta_classes} btn btn-primary #{not website_sale_order._is_cart_ready() and 'disabled'} #{_form_send_navigation and 'order-lg-3 w-100 w-lg-auto ms-lg-auto' or 'w-100'}"
t-att-href="step_specific_values['main_button_href']">
<t t-out="step_specific_values['main_button']"/>
<i class="fa fa-angle-right ms-2 fw-light"/>
</a>
</t>
</t>
<div t-if="not hide_payment_button" t-attf-class="position-relative #{_form_send_navigation and 'd-flex d-lg-none' or 'd-flex'} w-100 justify-content-center align-items-center my-2 opacity-75">
<hr class="w-100"/>
<span class="px-3">or</span>
<hr class="w-100"/>
</div>
<a t-att-href="step_specific_values['back_button_href']" class="text-center">
<i class="fa fa-angle-left me-2 fw-light"/>
<t t-out="step_specific_values['back_button']"/>
</a>
</div>
</template>
<!-- /shop/checkout route -->
<template id="checkout">
<t t-call="website_sale.checkout_layout">
<t t-set="additional_title">Shop - Checkout</t>
<t t-set="redirect" t-valuef="/shop/checkout"/>
<t t-set="same_shipping" t-value="bool(order.partner_shipping_id==order.partner_invoice_id or only_services)" />
<div id="shop_checkout">
<t t-if="order._has_deliverable_products()">
<t t-call="website_sale.delivery_address_row">
<t t-set="addresses" t-value="delivery_addresses"/>
</t>
<t t-call="website_sale.delivery_form">
<t t-set="selected_dm_id" t-value="order.carrier_id.id"/>
</t>
</t>
<t t-call="website_sale.billing_address_row">
<t t-set="addresses" t-value="billing_addresses"/>
</t>
</div>
</t>
</template>
<template id="delivery_address_row">
<div id="delivery_address_row" class="mb-4">
<h4 class="text-uppercase small fs-6 fw-bold">Delivery address</h4>
<t groups="account.group_delivery_invoice_address">
<t t-call="website_sale.address_row">
<t t-set="is_invoice" t-value="False"/>
<t t-set="addresses" t-value="delivery_addresses"/>
<t t-set="selected_address" t-value="order.partner_shipping_id"/>
</t>
</t>
</div>
</template>
<template id="billing_address_row">
<div id="billing_address_row">
<h4 class="text-uppercase small fs-6 fw-bold mt-3">Billing address</h4>
<t t-set="has_delivery" t-value="order._has_deliverable_products()"/>
<div t-if="has_delivery" class="form-check form-switch mt-2 mb-3">
<label id="use_delivery_as_billing_label">
<input
type="checkbox"
id="use_delivery_as_billing"
class="form-check-input"
t-att-checked="use_delivery_as_billing"
/> Same as delivery address
</label>
</div>
<div
id="billing_container"
t-attf-class="{{'d-none' if use_delivery_as_billing and has_delivery else ''}}"
>
<t t-call="website_sale.address_row">
<t t-set="is_invoice" t-value="True"/>
<t t-set="addresses" t-value="billing_addresses"/>
<t t-set="selected_address" t-value="order.partner_invoice_id"/>
</t>
</div>
</div>
</template>
<template id="address_row">
<div t-att-class="('all_billing' if is_invoice else 'all_delivery')
+ ' row row-cols-md-2 row-cols-lg-3 g-3 flex-nowrap flex-md-wrap'"
>
<div t-foreach="addresses" t-as="addr" class="one_kanban col-md">
<t t-call="website_sale.address_kanban">
<t t-set="contact" t-value="addr"/>
<t t-set="selected" t-value="addr == selected_address"/>
</t>
</div>
<div
t-if="is_invoice or not order.website_id.is_public_user()" class="one_kanban col-md"
>
<!-- We don't allow public users to have multiple delivery addresses. -->
<t t-if="is_invoice">
<t t-set="new_address_href" t-valuef="/shop/address?address_type=billing"/>
</t>
<t t-else="">
<t
t-set="new_address_href"
t-valuef="/shop/address?address_type=delivery&amp;use_delivery_as_billing={{use_delivery_as_billing}}"
/>
</t>
<a
role="button"
t-att-href="new_address_href"
t-att-data-address-type="is_invoice and 'billing' or 'delivery'"
class="o_wsale_add_address d-flex align-items-center justify-content-center h-100 px-4 border rounded mx-auto no-decoration"
>
<i class="fa fa-plus me-md-2"/>
<span class="d-none d-md-inline">Add address</span>
</a>
</div>
</div>
</template>
<!-- Card view of addresses. Called in `website_sale.checkout`. -->
<template id="address_kanban" name="Kanban address">
<t t-set="address_type" t-value="is_invoice and 'billing' or 'delivery'"/>
<div
name="address_card"
t-attf-class="card position-relative h-100 #{selected and 'bg-primary border border-primary' or 'js_change_address'}"
t-att-data-address-type="address_type"
t-att-data-partner-id="contact.id"
>
<div class="card-body d-flex flex-column align-items-start">
<t t-esc="contact" t-options="dict(widget='contact', fields=['name', 'address'], no_marker=True)"/>
<t t-if="contact._can_be_edited_by_current_customer(website_sale_order, address_type)">
<t t-set="new_address_href" t-value="'/shop/address?address_type=' + address_type"/>
<a
t-att-href="new_address_href + '&amp;partner_id=' + str(contact.id)"
class="js_edit_address btn btn-link p-0 mt-auto"
role="button"
title="Edit this address"
aria-label="Edit this address">
<i class="fa fa-pencil me-1"/>Edit
</a>
</t>
</div>
</div>
</template>
<!-- /shop/address route -->
<template id="website_sale.address" name="Address Management">
<t t-set="no_footer" t-value="1"/>
<t t-call="website.layout">
<div id="wrap">
<div class="oe_website_sale o_wsale_address_fill container py-2">
<div class="row">
<div class="col-12">
<t t-call="website_sale.wizard_checkout"/>
</div>
</div>
<div class="row">
<div class="oe_cart col-12 col-lg-8">
<div>
<t t-if="not is_anonymous_cart">
<t t-if="use_delivery_as_billing">
<h3 class="mb-3">Your address</h3>
</t>
<t t-elif="address_type == 'delivery'">
<h3 class="mb-3">Delivery address</h3>
</t>
<t t-else="">
<h3 class="mb-3">Billing address</h3>
</t>
</t>
<div
t-if="use_delivery_as_billing and not only_services"
class="alert alert-warning"
role="alert"
groups="account.group_delivery_invoice_address"
>
<h4 class="alert-heading">Be aware!</h4>
<p>
You are editing your <b>delivery and billing</b> addresses
at the same time!<br/>
If you want to modify your billing address, create a
<a href="/shop/address?address_type=billing">new address</a>.
</p>
</div>
<div id="errors"/> <!-- for js -->
<form
action="/shop/address/submit"
method="post"
class="checkout_autoformat"
t-att-data-company-country-code="res_company.country_id.code"
>
<t t-if="is_anonymous_cart">
<div id="div_email_public" t-attf-class="col-lg-12">
<label class="col-form-label" for="o_email">Email</label>
<div
t-if="website.account_on_checkout != 'disabled'"
class="align-items-center float-end"
style="margin-top: -11px"
>
<span>Already have an account?</span>
<a
role="button"
href='/web/login?redirect=/shop/checkout'
class="btn btn-primary"
>
Sign in
</a>
</div>
<input
id="o_email"
type="email"
name="email"
class="form-control"
t-att-value="partner_sudo.email"
/>
</div>
<h4 class="mb-1 mt-5">Fill in your address</h4>
</t>
<div class="row">
<div id="div_name" class="col-lg-12 mb-2">
<label class="col-form-label" for="o_name">Full name</label>
<input
id="o_name"
type="text"
name="name"
t-att-value="partner_sudo.name"
class="form-control"
/>
</div>
<div class="w-100"/>
<div
t-if="not is_anonymous_cart"
id="div_email"
class="col-lg-6 mb-2"
>
<label class="col-form-label" for="o_email">Email</label>
<input
id="o_email"
type="email"
name="email"
t-att-value="partner_sudo.email"
class="form-control"
/>
</div>
<div id="div_phone" class="col-lg-6 mb-2">
<label class="col-form-label" for="o_phone">Phone</label>
<input
id="o_phone"
type="tel"
name="phone"
t-att-value="partner_sudo.phone"
class="form-control"
/>
</div>
<t t-if="website._display_partner_b2b_fields()">
<div class="w-100"/>
<t t-if="show_vat">
<t t-set="vat_warning" t-value="partner_sudo.vat and not can_edit_vat"/>
<div id="company_name_div" class="col-lg-6 mb-2">
<label
class="col-form-label fw-normal label-optional"
for="o_company_name"
>
Company Name
</label>
<input
id="o_company_name"
type="text"
name="company_name"
t-att-value="partner_sudo.commercial_company_name"
t-att-readonly="'1' if vat_warning else None"
class="form-control"
/>
<small t-if="vat_warning" class="form-text text-muted d-block d-lg-none">
Changing company name is not allowed once document(s) have been issued for your account. Please contact us directly for this operation.
</small>
</div>
<div id="div_vat" class="col-lg-6 mb-2">
<label class="col-form-label fw-normal label-optional" for="o_vat">
<t t-out="vat_label"/>
</label>
<input
type="text"
id="o_vat"
name="vat"
t-att-value="partner_sudo.vat"
t-att-readonly="'1' if vat_warning else None"
class="form-control"
/>
<small t-if="vat_warning" class="form-text text-muted d-block d-lg-none">
Changing VAT number is not allowed once document(s) have been issued for your account. Please contact us directly for this operation.
</small>
</div>
<div t-if="vat_warning" class="col-12 d-none d-lg-block mb-1">
<small class="form-text text-muted">
Changing company name or VAT number is not allowed once document(s) have been issued for your account. Please contact us directly for this operation.
</small>
</div>
</t>
</t>
<div id="div_street" class="col-lg-12 mb-2">
<label class="col-form-label" for="o_street">Street and Number</label>
<input id="o_street" type="text" name="street" class="form-control" t-att-value="partner_sudo.street"/>
</div>
<div id="div_street2" class="col-lg-12 mb-2">
<label class="col-form-label label-optional" for="o_street2">Apartment, suite, etc.</label>
<input id="o_street2" type="text" name="street2" class="form-control" t-att-value="partner_sudo.street2" />
</div>
<div class="w-100"/>
<t t-if="zip_before_city">
<div id="div_zip" class="col-md-4 mb-2">
<label class="col-form-label label-optional" for="o_zip">Zip Code</label>
<input id="o_zip" type="text" name="zip" class="form-control" t-att-value="partner_sudo.zip"/>
</div>
</t>
<div id="div_city" class="col-md-8 mb-2">
<label class="col-form-label" for="o_city">City</label>
<input id="o_city" type="text" name="city" class="form-control" t-att-value="partner_sudo.city"/>
</div>
<t t-if="not zip_before_city">
<div id="div_zip" class="col-md-4 mb-2">
<label class="col-form-label label-optional" for="o_zip">Zip Code</label>
<input id="o_zip" type="text" name="zip" class="form-control" t-att-value="partner_sudo.zip"/>
</div>
</t>
<div class="w-100"/>
<div id="div_country" class="col-lg-6 mb-2">
<label class="col-form-label" for="o_country_id">Country</label>
<select id="o_country_id" name="country_id" class="form-select">
<option value="">Country...</option>
<t t-foreach="countries" t-as="c">
<option t-att-value="c.id" t-att-selected="c.id == country.id" t-att-code="c.code">
<t t-esc="c.name" />
</option>
</t>
</select>
</div>
<div id="div_state" class="col-lg-6 mb-2"
t-att-style="not country_states and 'display: none'">
<label class="col-form-label" for="o_state_id">State / Province</label>
<select id="o_state_id" name="state_id" class="form-select">
<option value="">State / Province...</option>
<t t-foreach="country_states" t-as="s">
<option t-att-value="s.id" t-att-selected="s.id == state_id">
<t t-esc="s.name" />
</option>
</t>
</select>
</div>
</div>
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" t-nocache="The csrf token must always be up to date."/>
<input type="hidden" name="address_type" t-att-value="address_type"/>
<input
type="hidden"
name="use_delivery_as_billing"
t-att-value="use_delivery_as_billing"
/>
<t t-if="partner_id">
<input type="hidden" name="partner_id" t-att-value="partner_id"/>
</t>
<t t-if="callback">
<input type="hidden" name="callback" t-att-value="callback"/>
</t>
<!-- Example -->
<input type="hidden" name="required_fields" t-att-value="'name,country_id'"/>
<div class="d-flex flex-column flex-md-row align-items-center justify-content-between mt32 mb32">
<a role="button" t-att-href="discard_url" class="btn btn-outline-secondary w-100 w-md-auto order-md-1 order-3">
<i class="fw-light fa fa-angle-left me-2"/>Discard
</a>
<div class="position-relative w-100 d-flex d-md-none justify-content-center align-items-center order-2 my-2 opacity-75">
<hr class="w-100"/>
<span class="px-3">or</span>
<hr class="w-100"/>
</div>
<button id="save_address" class="btn btn-primary w-100 w-md-auto order-1 order-md-3">
<t t-if="is_anonymous_cart">
Continue checkout
</t>
<t t-else="">
Save address
</t>
<i class="fw-light fa fa-angle-right ms-2"/>
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</t>
</template>
<!-- Deactivatable through the website editor. -->
<template id="address_b2b" inherit_id="website_sale.address" name="Show b2b fields" />
<!-- Called in `website_sale.payment`. -->
<template id="address_on_payment" name="Address on payment">
<div class="card">
<div class="card-body" id="delivery_and_billing">
<a class="float-end no-decoration" href="/shop/checkout"><i class="fa fa-pencil me-1"/>Edit</a>
<t
t-set="use_delivery_as_billing"
t-value="order.partner_invoice_id == order.partner_shipping_id and not order.pickup_location_data"
/>
<div t-if="not use_delivery_as_billing and order._has_deliverable_products()" groups="account.group_delivery_invoice_address">
<t t-if="order.pickup_location_data">
<b>Deliver to pickup point: </b>
<t t-out="order.pickup_location_data.get('name', '') + ', ' + order.pickup_location_data.get('street', '') + ' ' + order.pickup_location_data.get('zip_code', '') + ' ' + order.pickup_location_data.get('city','')"/>
</t>
<t t-else="">
<b>Delivery: </b>
<span
t-out="order.partner_shipping_id"
t-options="dict(widget='contact', fields=['address'], no_marker=True, separator=', ')"
class="address-inline"
/>
</t>
</div>
<div>
<b><t t-if="use_delivery_as_billing and not only_services">Delivery &amp; </t>Billing: </b>
<span t-esc="order.partner_invoice_id" t-options="dict(widget='contact', fields=['address'], no_marker=True, separator=', ')" class="address-inline"/>
</div>
</div>
</div>
</template>
<!-- /shop/payment route -->
<template id="payment" name="Payment">
<t t-call="website_sale.checkout_layout">
<t t-set="additional_title">Shop - Select Payment Method</t>
<t t-set='redirect' t-valuef="/shop/payment"/>
<t t-set="oe_structure">
<!-- This is the drag-and-drop area for website building blocs at the end of each
checkout page. This is append at the of the page in `checkout_layout`. The
templates created in the database to store blocs are hooked using XPath on the
`oe_struture` element ID. Therefore, we can't use dynamic IDs (like with
t-att-id) and each template needs to define a div element. -->
<div class="oe_structure" id="oe_structure_website_sale_payment_2"/>
</t>
<div class="col-12" t-if="errors">
<t t-set="hide_payment_button" t-value="True"/>
<t t-foreach="errors" t-as="error">
<div class="alert alert-danger" t-if="error" role="alert">
<h4>
<t t-esc="error[0]" />
</h4>
<t t-esc="error[1]" />
</div>
</t>
</div>
<h3 class="mb-4">Confirm order</h3>
<div id="address_on_payment" class="mb-4">
<t t-call="website_sale.address_on_payment"/>
</div>
<div class="oe_structure clearfix mt-3" id="oe_structure_website_sale_payment_1"/>
<div t-if="not errors and website_sale_order.amount_total" name="website_sale_non_free_cart">
<div id="payment_method" class="o_not_editable mt-4">
<t t-call="payment.form"/>
</div>
<t t-if="not (payment_methods_sudo or tokens_sudo)" t-set="hide_payment_button" t-value="True"/>
</div>
</t>
</template>
<!-- Activatable through the website editor. -->
<template id="accept_terms_and_conditions"
inherit_id="navigation_buttons"
name="Accept Terms &amp; Conditions"
active="False">
<xpath expr="//div[@name='o_website_sale_free_cart']" position="before">
<div name="website_sale_terms_and_conditions_checkbox" class="form-check mb-2">
<input type="checkbox" id="website_sale_tc_checkbox" class="form-check-input"/>
<label for="website_sale_tc_checkbox" class="form-check-label">
I agree to the <a target="_BLANK" href="/terms">terms &amp; conditions</a>
</label>
</div>
</xpath>
</template>
<!-- Template of the checkout pages. Should be called in every page of the checkout flow. -->
<template id="checkout_layout" name="Checkout layout page">
<!-- Layout customization parameters:
- show_footer: Whether to show the website footer; default: `False`.
- show_navigation_button: Whether to show the navigation buttons; default: `True`.
- show_wizard_checkout: Whether to show the wizard checkout; default: `True`.
- show_shorter_cart_summary: Whether to show the shorter cart_summary (without items
summary and with express checkout buttons) or the full;
default: `None`.
- oe_structure: The structure element to append at the bottom of the page;
default: `None`.
-->
<!-- Checkout context (non exhaustive):
- redirect: The route to redirect to when a customer enters a coupon; default: `None`.
- website_sale_order: The current order.
-->
<t t-call="website.layout">
<t t-set="no_footer" t-value="True if show_footer is None else not show_footer"/>
<t t-set="show_navigation_button" t-value="True if show_navigation_button is None else show_navigation_button"/>
<t t-set="show_wizard_checkout" t-value="True if show_wizard_checkout is None else show_wizard_checkout"/>
<div id="wrap">
<div class="oe_website_sale o_website_sale_checkout container py-2">
<div t-attf-class="row #{show_navigation_button and 'position-relative'} #{not show_wizard_checkout and 'mt32'} mb32">
<div t-if="show_wizard_checkout" class="col-12">
<t t-call="website_sale.wizard_checkout"/>
</div>
<div t-if="show_shorter_cart_summary"
class="offset-xl-1 col-lg-5 col-xl-4 order-2"
id="o_cart_summary">
<div class="o_total_card card sticky-lg-top"
t-if="website_sale_order and website_sale_order.website_order_line">
<div class="card-body p-0 p-lg-4">
<t t-call="website_sale.total"/>
<t
t-if="website.account_on_checkout != 'mandatory' or
not website.is_public_user()"
t-call="payment.express_checkout"
/>
<t t-call="website_sale.navigation_buttons"/>
</div>
</div>
</div>
<div t-else=""
class="o_wsale_accordion accordion sticky-lg-top offset-xl-1 col-12 col-lg-5 col-xl-4 order-lg-2 rounded"
id="o_wsale_total_accordion">
<div class="o_total_card sticky-lg-top">
<div id="o_wsale_total_accordion_item" class="accordion-item p-lg-4 border-0">
<div class="accordion-header d-block align-items-center mb-4">
<button class="accordion-button px-0 collapsed"
data-bs-toggle="collapse"
data-bs-target="#o_wsale_accordion_item"
aria-expanded="false"
aria-controls="o_wsale_accordion_item">
<div class="d-flex flex-wrap">
<b class="w-100">Order summary</b>
<span t-out="str(website_sale_order.cart_quantity)"/>
&amp;nbsp;item(s)&amp;nbsp;-&amp;nbsp;
<span id="amount_total_summary"
class="monetary_field ms-1"
t-field="website_sale_order.amount_total"
t-options='{"widget": "monetary", "display_currency": website_sale_order.currency_id}'/>
</div>
</button>
</div>
<div name="cart_summary_info" t-if="not website_sale_order or not website_sale_order.website_order_line" class="alert alert-info">
Your cart is empty!
</div>
<div id="o_wsale_accordion_item"
class="accordion-collapse collapse mb-4 mb-lg-0"
data-bs-parent="#o_wsale_total_accordion">
<div t-att-class="len(website_sale_order.website_order_line) &gt; 3 and 'o_wsale_scrollable_table mt-n4 me-n4 pt-4 pe-4'">
<table t-if="website_sale_order and website_sale_order.website_order_line"
class="table accordion-body mb-0"
id="cart_products">
<tbody>
<tr t-foreach="website_sale_order.website_order_line" t-as="line" t-att-class="line_last and 'border-transparent'">
<t t-set="o_cart_sum_padding_top"
t-value="'pt-3' if line_size &gt; 1 and not line_first else 'pt-0'"/>
<td t-if="not line.product_id" colspan="2"/>
<t t-else="">
<td t-attf-class="td-img ps-0 #{o_cart_sum_padding_top}">
<span t-if="line._is_not_sellable_line() and line.product_id.image_128">
<img t-att-src="image_data_uri(line.product_id.image_128)" class="o_image_64_max img rounded" t-att-alt="line.name_short"/>
</span>
<span t-else=""
t-field="line.product_id.image_128"
t-options="{'widget': 'image', 'qweb_img_responsive': False, 'class': 'o_image_64_max rounded'}"
/>
</td>
<td t-attf-class="#{o_cart_sum_padding_top} td-product_name td-qty w-100"
name='website_sale_cart_summary_product_name'>
<h6>
<t t-out="int(line.product_uom_qty)" />
<t t-if="line._get_shop_warning(clear=False)">
<i class="fa fa-warning text-warning"
role="img"
t-att-title="line._get_shop_warning()"
aria-label="Warning"/>
</t>
x
<t t-out="line.name_short"/>
</h6>
</td>
</t>
<td t-attf-class="#{o_cart_sum_padding_top} td-price pe-0 text-end"
name="website_sale_cart_summary_line_price">
<t t-call="website_sale.cart_product_price">
<t
t-set="product_price"
t-value="line._get_cart_display_price()"
/>
</t>
</td>
</tr>
</tbody>
</table>
</div>
<t t-if='website_sale_order'>
<t t-set='warning' t-value='website_sale_order._get_shop_warning(clear=False)' />
<div t-if='warning' class="alert alert-warning" role="alert">
<strong>Warning!</strong> <t t-esc='website_sale_order._get_shop_warning()'/>
</div>
</t>
</div>
<t t-call="website_sale.total">
<t t-set="_cart_total_classes" t-valuef="border-top pt-3"/>
</t>
<div t-if="show_navigation_button" class="o_cta_navigation_container position-absolute position-lg-static start-0 bottom-0 col-12">
<t t-call="website_sale.navigation_buttons"/>
</div>
</div>
</div>
</div>
<div t-attf-class="oe_cart col-12 col-lg-7">
<t t-out="0"/>
</div>
<!-- This div serves as an anchor for the navigation buttons on the mobile
view. -->
<div t-if="not show_shorter_cart_summary and show_navigation_button"
class="o_cta_navigation_placeholder d-block d-none d-lg-none order-lg-4"/>
</div>
</div>
<!-- This is the drag-and-drop area for website building blocs at the end of each
checkout page. The templates created in the database to store blocs are hooked
using XPath on the `oe_struture` element ID. Therefore, we can't use dynamic
IDs (like with t-att-id) and each template needs to define a div element. -->
<t t-out="oe_structure"/>
</div>
</t>
</template>
<!-- /shop/confirmation route -->
<template id="confirmation">
<t t-call="website_sale.checkout_layout">
<t t-set="show_wizard_checkout" t-value="False"/>
<t t-set="show_navigation_button" t-value="False"/>
<t t-set="show_footer" t-value="True"/>
<t t-set="additional_title">Shop - Confirmed</t>
<t t-set="hide_promotions" t-value="True"/>
<t t-set="oe_structure">
<!-- This is the drag-and-drop area for website building blocs at the end of each
checkout page. This is append at the of the page in `checkout_layout`. The
templates created in the database to store blocs are hooked using XPath on the
`oe_struture` element ID. Therefore, we can't use dynamic IDs (like with
t-att-id) and each template needs to define a div element. -->
<div class="oe_structure" id="oe_structure_website_sale_confirmation_3"/>
</t>
<t t-set="tx_sudo" t-value="order.get_portal_last_transaction()"/>
<div t-if="tx_sudo.state in ['pending', 'done']" class="d-flex justify-content-between align-items-center">
<h3>Thank you for your order.</h3>
<a role="button" class="d-none d-md-inline-block btn btn-primary ms-auto" href="/shop/print" target="_blank" aria-label="Print" title="Print"><i class="fa fa-print me-2"></i>Print</a>
</div>
<t t-if="tx_sudo.state == 'done'">
<div class="mb-4">
<h5>
<em>
<span>Order</span>
<span t-field="order.name" />
<t t-if="order.state == 'sale'">
<i class="fa fa-check-circle ms-1"/>
</t>
</em>
</h5>
</div>
</t>
<t t-if="request.env['res.users']._get_signup_invitation_scope() == 'b2c' and request.website.is_public_user()">
<p class="alert alert-info mt-3" role="status">
<a role="button" t-att-href="order.partner_id.signup_prepare() and order.partner_id.with_context(relative_url=True)._get_signup_url()" class="btn btn-primary">Sign Up</a>
to follow your order.
</p>
</t>
<div class="oe_structure clearfix mt-3" id="oe_structure_website_sale_confirmation_1"/>
<h4 class="text-start mt-3">Payment Information</h4>
<table class="table">
<tbody>
<tr>
<td colspan="2" class="ps-0">
<t t-esc="tx_sudo.provider_id.name" />
</td>
<td class="text-end pe-0" width="100">
<strong>Total:</strong>
</td>
<td class="text-end pe-0" width="100">
<strong t-field="tx_sudo.amount" t-options="{'widget': 'monetary', 'display_currency': order.currency_id}" />
</td>
</tr>
</tbody>
</table>
<t t-call="website_sale.payment_confirmation_status"/>
<div class="card mt-3">
<div class="card-body">
<t t-set="same_shipping" t-value="bool(order.partner_shipping_id == order.partner_invoice_id or only_services)" />
<div><b>Billing <t t-if="same_shipping and not only_services"> &amp; Delivery</t>: </b><span t-esc='order.partner_invoice_id' t-options="dict(widget='contact', fields=['address'], no_marker=True, separator=', ')" class="address-inline"/></div>
<div t-if="not same_shipping and not only_services" groups="account.group_delivery_invoice_address"><b>Delivery: </b><span t-esc='order.partner_shipping_id' t-options="dict(widget='contact', fields=['address'], no_marker=True, separator=', ')" class="address-inline"/></div>
</div>
</div>
<div class="oe_structure mt-3" id="oe_structure_website_sale_confirmation_2"/>
<input t-if='website.plausible_shared_key' type='hidden' class='js_plausible_push' data-event-name='Shop' t-attf-data-event-params='{"CTA": "Order Confirmed", "amount": "#{"%3s-%3s" % (max(0, round(website_sale_order.amount_total/100)*100 - 50), round(website_sale_order.amount_total/100)*100 + 50)}"}' />
</t>
</template>
<!-- Called in `website_sale.checkout_layout`. -->
<template id="total">
<div id="cart_total" t-if="website_sale_order and website_sale_order.website_order_line" t-att-class="_cart_total_classes">
<table class="table mb-0">
<tr
t-if="website_sale_order._has_deliverable_products() and website_sale_order.carrier_id"
id="order_delivery"
>
<td
class="ps-0 pt-0 pb-2 border-0 text-muted"
colspan="2"
title="Delivery will be updated after choosing a new delivery method"
>
Delivery
</td>
<td class="text-end pe-0 pt-0 pb-2 border-0">
<span
t-out="website_sale_order.amount_delivery"
class="monetary_field"
style="white-space: nowrap;"
t-options="{'widget': 'monetary', 'display_currency': website_sale_order.currency_id}"
/>
</td>
</tr>
<tr id="order_total_untaxed">
<td id="cart_total_subtotal"
class="border-0 pb-2 ps-0 pt-0 text-start text-muted"
colspan="2">
Subtotal
</td>
<td class="text-end border-0 pb-2 pe-0 pt-0">
<span t-field="website_sale_order.amount_untaxed"
class="monetary_field"
style="white-space: nowrap;"
t-options="{'widget': 'monetary', 'display_currency': website_sale_order.currency_id}"/>
</td>
</tr>
<tr id="order_total_taxes">
<td colspan="2" class="text-muted border-0 ps-0 pt-0 pb-3">Taxes</td>
<td class="text-end border-0 pe-0 pt-0 pb-3">
<span t-field="website_sale_order.amount_tax"
class="monetary_field"
style="white-space: nowrap;"
t-options="{'widget': 'monetary', 'display_currency': website_sale_order.currency_id}"/>
</td>
</tr>
<tr id="order_total" class="border-top">
<td colspan="2" class="border-0 ps-0 pt-3"><strong>Total</strong></td>
<td class="text-end border-0 px-0 pt-3">
<strong t-field="website_sale_order.amount_total"
class="monetary_field text-end p-0"
t-options="{'widget': 'monetary', 'display_currency': website_sale_order.currency_id}"/>
</td>
</tr>
</table>
</div>
</template>
<!-- Deactivatable through the website editor. -->
<template id="reduction_code" inherit_id="website_sale.total" name="Promo Code">
<!-- Checkout context:
- hide_promotions: Whether to hide promotion input; default: `None`.
- redirect: The route to redirect to when a customer enters a coupon; default: `None`.
- website_sale_order: The current order.
-->
<xpath expr="//div[@id='cart_total']//table/tr[last()]" position="after">
<tr t-if="not hide_promotions">
<td colspan="3" class="text-end text-xl-end border-0 p-0">
<span>
<t t-set="force_coupon" t-value="website_sale_order.pricelist_id.code"/>
<div t-if="not force_coupon" class="coupon_form">
<t t-call="website_sale.coupon_form"/>
</div>
</span>
</td>
</tr>
</xpath>
</template>
<!-- Called in `website_sale.confirmation`. -->
<template id="payment_confirmation_status">
<div class="oe_website_sale_tx_status mt-3" t-att-data-order-id="order.id" t-att-data-order-tracking-info="json.dumps(order_tracking_info)">
<t t-set="tx_sudo" t-value="order.get_portal_last_transaction()"/>
<div t-attf-class="card #{
(tx_sudo.state == 'pending' and 'bg-info') or
(tx_sudo.state == 'done' and order.amount_total == tx_sudo.amount and 'alert-success') or
(tx_sudo.state == 'done' and order.amount_total != tx_sudo.amount and 'bg-warning') or
(tx_sudo.state == 'authorized' and 'alert-success') or
'bg-danger'}">
<div class="card-header">
<a role="button" groups="base.group_system" class="btn btn-sm btn-link text-white float-end" target="_blank" aria-label="Edit" title="Edit"
t-attf-href="/odoo/action-payment.action_payment_provider/{{tx_sudo.provider_id.id}}">
<i class="fa fa-pencil"></i>
</a>
<t t-if="tx_sudo.state == 'pending'">
<t t-out="tx_sudo.provider_id.sudo().pending_msg"/>
</t>
<t t-if="tx_sudo.state == 'done'">
<span t-if='tx_sudo.provider_id.sudo().done_msg' t-out="tx_sudo.provider_id.sudo().done_msg"/>
</t>
<t t-if="tx_sudo.state == 'done' and order.amount_total != tx_sudo.amount">
<span>Unfortunately your order can not be confirmed as the amount of your payment does not match the amount of your cart.
Please contact the responsible of the shop for more information.</span>
</t>
<t t-if="tx_sudo.state == 'cancel'">
<t t-out="tx_sudo.provider_id.sudo().cancel_msg"/>
</t>
<t t-if="tx_sudo.state == 'authorized'">
<t t-if="tx_sudo.provider_id.sudo().auth_msg" t-out="tx_sudo.provider_id.sudo().auth_msg"/>
<span t-else="">Your payment has been authorized.</span>
</t>
<t t-if="tx_sudo.state == 'error'">
<span t-esc="tx_sudo.state_message"/>
</t>
</div>
<t t-if="tx_sudo.provider_code == 'custom'">
<div t-if="order.reference" class="card-body">
<b>Communication: </b><span t-esc='order.reference'/>
</div>
<div t-if="tx_sudo.provider_id.sudo().qr_code">
<t t-set="qr_code" t-value="tx_sudo.company_id.partner_id.bank_ids[:1].build_qr_code_base64(order.amount_total,tx_sudo.reference, None, tx_sudo.currency_id, tx_sudo.partner_id)"/>
<div class="card-body" t-if="qr_code">
<h3>Or scan me with your banking app.</h3>
<img class="border border-dark rounded" t-att-src="qr_code"/>
</div>
</div>
</t>
</div>
</div>
</template>
<template id="website_sale.brand_promotion" inherit_id="website.brand_promotion">
<xpath expr="//t[@t-call='web.brand_promotion_message']" position="replace">
<t t-call="web.brand_promotion_message">
<t t-set="_message">
The #1 <a target="_blank" href="http://www.odoo.com/app/ecommerce?utm_source=db&amp;utm_medium=website">Open Source eCommerce</a>
</t>
<t t-set="_utm_medium" t-valuef="website"/>
</t>
</xpath>
</template>
<template id="sale_order_portal_content_inherit_website_sale" name="Orders Followup Products Links" inherit_id="sale.sale_order_portal_content">
<xpath expr="//section[@id='details']//div[hasclass('table-responsive')]" position="attributes">
<attribute name="class" remove="table-responsive" separator=" "/>
</xpath>
<xpath expr="//section[@id='details']//td[@id='product_name']/*" position="replace">
<a t-if="line.product_id.website_published" t-att-href="line.product_id.website_url" class="d-block text-wrap" style="max-width: 35vw">
<span t-field="line.name" />
</a>
<t t-if="not line.product_id.website_published">
<span t-field="line.name" class="d-block text-wrap" style="max-width: 35vw"/>
</t>
</xpath>
</template>
<!-- Product page images -->
<template id="website_sale.shop_product_images" name="Shop Product Images">
<t t-set="product_images" t-value="product_variant._get_images() if product_variant else product._get_images()"/>
<t t-set="ribbon" t-value="product_variant.sudo().variant_ribbon_id or product.sudo().website_ribbon_id"/>
<t t-set="bg_color" t-value="ribbon['bg_color'] or ''"/>
<t t-set="text_color" t-value="ribbon['text_color']"/>
<t t-set="bg_class" t-value="ribbon._get_position_class()"/>
<t t-call="website_sale.shop_product_#{website.product_page_image_layout}"/>
</template>
<template id="website_sale.shop_product_image">
<div t-if="product_image._name == 'product.image' and product_image.embed_code" t-att-class="image_classes + ' ratio ratio-16x9'">
<t t-out="product_image.embed_code"/>
</div>
<div
t-elif="len(product_images) == 1 and website.product_page_image_layout != 'grid'"
class="position-relative d-inline-flex overflow-hidden m-auto w-100"
>
<span t-attf-class="o_ribbon #{ribbon._get_position_class()} z-1"
t-attf-style="#{text_color and ('color: %s; ' % text_color)}#{bg_color and 'background-color:' + bg_color}"
t-out="ribbon['name'] or ''"
/>
<div
t-field="product_image.image_1920"
name="o_img_with_max_suggested_width"
class="d-flex align-items-start justify-content-center w-100 oe_unmovable"
t-options="{
'widget': 'image',
'preview_image': 'image_1024',
'class': 'oe_unmovable product_detail_img w-100',
'alt-field': 'name',
'zoom': product_image.can_image_1024_be_zoomed and 'image_1920',
}"
/>
</div>
<div
t-else=""
t-field="product_image.image_1920"
t-att-class="image_classes + ' oe_unmovable'"
t-options="{
'widget': 'image',
'preview_image': 'image_1024',
'class': 'oe_unmovable product_detail_img w-100 mh-100',
'alt-field': 'name',
'zoom': product_image.can_image_1024_be_zoomed and 'image_1920',
}"
/>
</template>
<!-- Product page images: Carousel -->
<template id="website_sale.shop_product_carousel" name="Shop Product Carousel">
<t t-set="product_carousel_block_name">Product Carousel</t>
<div
id="o-carousel-product"
t-attf-class="#{len(product_images) > 1 and 'o_carousel_not_single'} carousel slide position-sticky mb-3 overflow-hidden"
data-bs-ride="true"
t-att-data-name="product_carousel_block_name"
>
<div
class="o_carousel_product_outer carousel-outer position-relative d-flex align-items-center w-100 overflow-hidden"
>
<span t-if="len(product_images) > 1"
t-attf-class="o_ribbon #{ribbon._get_position_class()} z-1"
t-attf-style="#{text_color and ('color: %s; ' % text_color)}#{bg_color and 'background-color:' + bg_color}"
t-out="ribbon['name'] or ''"
/>
<div class="carousel-inner h-100">
<t t-set="image_classes" t-value="'d-flex align-items-center justify-content-center h-100'"/>
<t t-foreach="product_images" t-as="product_image">
<div t-attf-class="carousel-item h-100 text-center#{' active' if product_image_first else ''}">
<t t-call="website_sale.shop_product_image"/>
</div>
</t>
</div>
<t t-if="len(product_images) > 1">
<a class="carousel-control-prev" href="#o-carousel-product" role="button" data-bs-slide="prev">
<i
class="oi oi-chevron-left oe_unmovable border bg-white text-900"
role="img"
aria-label="Previous"
title="Previous"
/>
</a>
<a class="carousel-control-next" href="#o-carousel-product" role="button" data-bs-slide="next">
<i
class="oi oi-chevron-right oe_unmovable border bg-white text-900"
role="img"
aria-label="Next"
title="Next"
/>
</a>
</t>
</div>
</div>
</template>
<template
id="products_carousel_4x3"
name="carousel_img_ratio_4x3"
inherit_id="website_sale.shop_product_carousel"
active="False"
>
<xpath expr="//div[hasclass('o_carousel_product_outer')]" position="attributes">
<attribute name="class" add="o_wsale_carousel_ratio_4x3" separator=" "/>
</xpath>
</template>
<template
id="products_carousel_4x5"
name="carousel_img_ratio_4x5"
inherit_id="website_sale.shop_product_carousel"
active="False"
>
<xpath expr="//div[hasclass('o_carousel_product_outer')]" position="attributes">
<attribute name="class" add="o_wsale_carousel_ratio_4x5" separator=" "/>
</xpath>
</template>
<template
id="products_carousel_16x9"
name="carousel_img_ratio_16x9"
inherit_id="website_sale.shop_product_carousel"
active="False"
>
<xpath expr="//div[hasclass('o_carousel_product_outer')]" position="attributes">
<attribute name="class" add="o_wsale_carousel_ratio_16x9" separator=" "/>
</xpath>
</template>
<template
id="products_carousel_21x9"
name="carousel_img_ratio_21x9"
inherit_id="website_sale.shop_product_carousel"
active="False"
>
<xpath expr="//div[hasclass('o_carousel_product_outer')]" position="attributes">
<attribute name="class" add="o_wsale_carousel_ratio_21x9" separator=" "/>
</xpath>
</template>
<template id="carousel_product_indicators_bottom" inherit_id="website_sale.shop_product_carousel" name="Carousel Product Indicators Bottom">
<xpath expr="//div[hasclass('o_carousel_product_outer')]" position="after">
<t t-call="website_sale.carousel_product_indicators">
<t t-set="indicators_div_class" t-value="'pt-2 overflow-hidden'"/>
</t>
</xpath>
</template>
<template id="carousel_product_indicators_left" inherit_id="website_sale.shop_product_carousel" name="Carousel Product Indicators Left" active="False">
<xpath expr="//div[hasclass('o_carousel_product_outer')]" position="before">
<t t-call="website_sale.carousel_product_indicators">
<t t-set="indicators_list_class" t-value="'d-flex d-lg-block pe-2'"/>
</t>
</xpath>
<xpath expr="//div[@id='o-carousel-product']" position="attributes">
<attribute name="t-attf-class" add="o_carousel_product_left_indicators d-flex" separator=" "/>
</xpath>
</template>
<template id="carousel_product_indicators" name="Carousel Product">
<div
t-if="len(product_images) > 1"
t-ignore="True"
t-attf-class="o_carousel_product_indicators {{indicators_div_class}}"
>
<ol
t-att-class="'carousel-indicators '
+ (indicators_list_class or '')
+ ('justify-content-center ' if website.product_page_image_width == '100_pc' else '')
+ ' position-static pt-2 pt-lg-0 mx-auto my-0'"
>
<li
t-foreach="product_images" t-as="product_image"
t-attf-class="align-top position-relative {{'active' if product_image_first else ''}}"
data-bs-target="#o-carousel-product"
t-att-data-bs-slide-to="str(product_image_index)"
>
<div
t-field="product_image.image_128"
t-options="{'widget': 'image', 'qweb_img_responsive': False, 'class': 'o_image_64_cover', 'alt-field': 'name'}"
/>
<i
t-if="product_image._name == 'product.image' and product_image.embed_code"
class="fa fa-2x fa-play-circle o_product_video_thumb bg-black-50 text-center"
/>
</li>
</ol>
</div>
</template>
<!-- Product page images: Grid -->
<template id="website_sale.shop_product_grid" name="Shop Product Grid">
<div
id="o-grid-product"
class="mb-3"
data-name="Product Grid"
t-att-data-image_spacing="website.product_page_image_spacing"
t-att-data-grid_columns="website.product_page_grid_columns"
>
<div class="container position-relative overflow-hidden">
<span t-attf-class="o_ribbon #{ribbon._get_position_class()}"
t-attf-style="#{text_color and ('color: %s; ' % text_color)}#{bg_color and 'background-color:' + bg_color}"
t-out="ribbon['name'] or ''"
/>
<!-- One row for every two images -->
<t t-set="image_classes" t-value="'w-100'"/>
<div class="row">
<t t-foreach="website.product_page_grid_columns" t-as="col_idx">
<t t-set="col_feed_counter" t-value="0"/>
<div
t-if="col_idx_index &lt; len(product_images)"
class="col o_wsale_product_page_grid_column d-flex flex-column px-0"
>
<t t-foreach="len(product_images)" t-as="image_idx">
<t
t-set="product_image"
t-value="image_idx &lt; len(product_images) and product_images[image_idx] or False"
/>
<t
t-set="image_classes"
t-value="website._get_product_page_grid_image_spacing_classes()"
/>
<t
t-if="product_image and col_idx == col_feed_counter"
t-call="website_sale.shop_product_image"
/>
<t t-if="col_feed_counter == (website.product_page_grid_columns - 1)">
<t t-set="col_feed_counter" t-value="0"/>
</t>
<t t-else="">
<t t-set="col_feed_counter" t-value="col_feed_counter + 1"/>
</t>
</t>
</div>
</t>
</div>
</div>
</div>
</template>
<template id="ecom_show_extra_fields" inherit_id="website_sale.product" active="True" name="Show Extra Fields">
<xpath expr="//div[@id='product_details']" position="inside">
<t t-if="any([product[field.name] for field in website.shop_extra_field_ids])">
<hr/>
<p class="text-muted">
<t t-foreach='website.shop_extra_field_ids' t-as='field' t-if='product[field.name]'>
<b><t t-esc='field.label'/>: </b>
<t t-if='field.field_id.ttype != "binary"'>
<span t-esc='product[field.name]' t-options="{'widget': field.field_id.ttype}"/>
</t>
<t t-else=''>
<a target='_blank' t-attf-href='/web/content/product.template/#{product.id}/#{field.name}?download=1'>
<i class='fa fa-file'></i>
</a>
</t>
<br/>
</t>
</p>
</t>
</xpath>
</template>
<template id="add_to_cart_redirect" inherit_id="website.layout" name="Cart Redirection" priority="1">
<xpath expr="//html" position="before">
<t t-set="html_data" t-value="dict(html_data, **{'data-add2cart-redirect': '1' if website.add_to_cart_action == 'stay' else '0' if website.add_to_cart_action == 'go_to_cart' else '2'})"/>
</xpath>
</template>
<template id="product_category_extra_link" name="Product Category Extra Link">
<button class="btn btn-link btn-sm pe-0" disabled="disabled">
<t t-if="len(categories) == 1">Category:</t>
<t t-else="">Categories:</t>
</button>
<t t-foreach="categories" t-as="category">
<button class="btn btn-link btn-sm p-0 text-wrap" t-out="category.name"
t-attf-onclick="location.href='/shop/category/#{slug(category)}';return false;"/>
</t>
</template>
<template id="sale_order_re_order_btn" inherit_id="sale.sale_order_portal_template" name="Sale Order Order Again">
<xpath expr="//t[@t-set='entries']/div/div/div[hasclass('o_download_pdf')]" position="before">
<t t-if="request.website.enabled_portal_reorder_button and sale_order.with_user(request.env.user).sudo()._is_reorder_allowed()">
<button class="btn btn-primary o_wsale_reorder_button" t-att-data-sale-order-id="sale_order.id">
<i class="fa fa-rotate-right me-1"/>
Order Again
</button>
</t>
</xpath>
</template>
</odoo>