[IMP] {website_}event_sale: add pricelist picker
Purpose ======= As an Event seller, I might not use the /shop page because I do not sell goods, only tickets. That being said, I do this in multi-currency for example, and need visitors to be able to pick the relevant pricelists. Specifications ============ Adding the price currency on the event ticket so that users will know which currency is used. Adding a pricelist picker on the website event front-end and on the ticket registration page to allow the user to display the prices depending on a selected pricelist. Task-3081384 closes odoo/odoo#106980 Signed-off-by: Stéphane Debauche (std) <std@odoo.com>
This commit is contained in:
@@ -20,6 +20,7 @@ class EventTemplateTicket(models.Model):
|
||||
product_id = fields.Many2one(
|
||||
'product.product', string='Product', required=True,
|
||||
domain=[("detailed_type", "=", "event")], default=_default_product_id)
|
||||
currency_id = fields.Many2one(related="product_id.currency_id", string="Currency")
|
||||
price = fields.Float(
|
||||
string='Price', compute='_compute_price',
|
||||
digits='Product Price', readonly=False, store=True)
|
||||
|
||||
@@ -46,7 +46,8 @@
|
||||
<field name="product_id" context="{'default_detailed_type': 'event'}"/>
|
||||
</field>
|
||||
<field name="description" position="after">
|
||||
<field name="price"/>
|
||||
<field name="currency_id" invisible="1"/>
|
||||
<field name="price" widget="monetary" options="{'currency_field': 'currency_id'}"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -150,7 +150,7 @@ class TestEventPerformance(EventPerformanceCase):
|
||||
has_social = 'social_menu' in self.env['event.event'] # otherwise view may crash in enterprise
|
||||
|
||||
# type and website
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=445): # tef 400 / com 406
|
||||
with freeze_time(self.reference_now), self.assertQueryCount(event_user=450): # tef 402 / com 408
|
||||
self.env.cr._now = self.reference_now # force create_date to check schedulers
|
||||
# Require for `website_menu` to be visible
|
||||
# <div name="event_menu_configuration" groups="base.group_no_one">
|
||||
@@ -453,7 +453,7 @@ class TestOnlineEventPerformance(EventPerformanceCase, UtilPerf):
|
||||
# website customer data
|
||||
with freeze_time(self.reference_now):
|
||||
self.authenticate('user_eventmanager', 'user_eventmanager')
|
||||
with self.assertQueryCount(default=39): # tef 38
|
||||
with self.assertQueryCount(default=42): # tef 41
|
||||
self._test_url_open('/event')
|
||||
|
||||
@warmup
|
||||
@@ -461,7 +461,7 @@ class TestOnlineEventPerformance(EventPerformanceCase, UtilPerf):
|
||||
# website customer data
|
||||
with freeze_time(self.reference_now):
|
||||
self.authenticate(None, None)
|
||||
with self.assertQueryCount(default=28):
|
||||
with self.assertQueryCount(default=38):
|
||||
self._test_url_open('/event')
|
||||
|
||||
# @warmup
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
<field name="name" placeholder="e.g. "Conference for Architects"" string="Event Name"/>
|
||||
<field name="address_id" context="{'show_address': 1}" options='{"always_reload": True}'/>
|
||||
<label for="date_begin" string="Start → End"/>
|
||||
<div class="o_row w-100">
|
||||
<field name="date_begin" widget="daterange" nolabel="1" options="{'related_end_date': 'date_end'}"/>
|
||||
<div class="d-flex flex-column flex-sm-row align-items-baseline w-100">
|
||||
<field name="date_begin" style="width: 17ch" widget="daterange" nolabel="1" options="{'related_end_date': 'date_end'}"/>
|
||||
<i class="fa fa-long-arrow-right mx-2" aria-label="Arrow icon" title="Arrow"/>
|
||||
<field name="date_end" widget="daterange" nolabel="1" options="{'related_start_date': 'date_begin'}"/>
|
||||
<field name="date_end" style="width: 17ch" widget="daterange" nolabel="1" options="{'related_start_date': 'date_begin'}"/>
|
||||
</div>
|
||||
</group>
|
||||
</form>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<nav class="navbar navbar-light border-top shadow-sm d-print-none">
|
||||
<div class="container">
|
||||
<div class="d-flex flex-column flex-sm-row justify-content-between w-100">
|
||||
<span class="navbar-brand h4 my-0 me-auto">Events</span>
|
||||
<span class="navbar-brand h4 my-0 me-auto pe-sm-4">Events</span>
|
||||
<ul class="o_wevent_index_topbar_filters nav">
|
||||
<t t-foreach="categories" t-as="category">
|
||||
<li t-if="category.is_published and category.tag_ids and any(tag.color for tag in category.tag_ids)" class="nav-item dropdown me-2 my-1">
|
||||
|
||||
@@ -22,6 +22,10 @@ Sell event tickets through eCommerce app.
|
||||
'web.assets_tests': [
|
||||
'website_event_sale/static/tests/**/*',
|
||||
],
|
||||
'web.assets_frontend': [
|
||||
'website_event_sale/static/src/scss/*.scss',
|
||||
'website_event_sale/static/src/js/*.js',
|
||||
],
|
||||
},
|
||||
'license': 'LGPL-3',
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import publicWidget from 'web.public.widget';
|
||||
|
||||
publicWidget.registry.ticketDetailsWidget.include({
|
||||
/**
|
||||
* Overriding the method to toggle the tickets registration
|
||||
* pricelist dropdown visibility on ticket details click
|
||||
*/
|
||||
_onTicketDetailsClick: function(ev) {
|
||||
this._super(...arguments);
|
||||
if (this.foldedByDefault){
|
||||
$(ev.currentTarget).siblings('#o_wevent_tickets_pricelist').toggleClass('collapse');
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
#o_wevent_tickets .o_pricelist_dropdown {
|
||||
.dropdown-toggle {
|
||||
color: $gray-600; // text-muted
|
||||
font-style: italic;
|
||||
}
|
||||
.dropdown-toggle:focus {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.dropdown-toggle:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.dropdown-item {
|
||||
font-size: small;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,16 @@
|
||||
<odoo>
|
||||
|
||||
<template id="registration_template" inherit_id="website_event.registration_template">
|
||||
<!-- Change pricelist -->
|
||||
<xpath expr="//div[hasclass('o_wevent_price_range')]" position="after">
|
||||
<div id="o_wevent_tickets_pricelist" class="collapse show">
|
||||
<t t-set="website_sale_pricelists" t-value="website.get_pricelist_available(show_visible=True)" />
|
||||
<t t-set="hasPricelistDropdown" t-value="website_sale_pricelists and len(website_sale_pricelists)>1"/>
|
||||
<t t-call="website_sale.pricelist_list">
|
||||
<t t-set="_classes" t-valuef="d-none d-lg-inline p-0 ms-2 my-1"/>
|
||||
</t>
|
||||
</div>
|
||||
</xpath>
|
||||
<!-- Add price information on tickets (multi tickets, aka in collapse) -->
|
||||
<xpath expr="//div[hasclass('o_wevent_registration_multi_select')]" position="inside">
|
||||
<t t-if="ticket.price">
|
||||
@@ -20,13 +30,16 @@
|
||||
<span t-else="" class="fw-bold text-uppercase">Free</span>
|
||||
</xpath>
|
||||
<xpath expr="//div[hasclass('o_wevent_price_range')]" position="inside">
|
||||
<t t-if="event.event_ticket_ids[-1].price_reduce > 0">
|
||||
<t t-set="all_prices" t-value="event.event_ticket_ids.mapped('price_reduce')"/>
|
||||
<t t-set="lowest_price" t-value="min(all_prices)"/>
|
||||
<t t-set="highest_price" t-value="max(all_prices)"/>
|
||||
<t t-if="highest_price > 0">
|
||||
<span class="text-dark">
|
||||
From
|
||||
<span t-out="event.event_ticket_ids[0].price_reduce" t-options="{'widget': 'monetary', 'from_currency': event.company_id.sudo().currency_id, 'display_currency': website.pricelist_id.currency_id}"/>
|
||||
<t t-if="event.event_ticket_ids[-1].price_reduce != event.event_ticket_ids[0].price_reduce">
|
||||
<span t-out="lowest_price" t-options="{'widget': 'monetary', 'from_currency': event.company_id.sudo().currency_id, 'display_currency': website.pricelist_id.currency_id}"/>
|
||||
<t t-if="lowest_price != highest_price">
|
||||
to
|
||||
<span t-out="event.event_ticket_ids[-1].price_reduce" t-options="{'widget': 'monetary', 'from_currency': event.company_id.sudo().currency_id, 'display_currency': website.pricelist_id.currency_id}"/>
|
||||
<span t-out="highest_price" t-options="{'widget': 'monetary', 'from_currency': event.company_id.sudo().currency_id, 'display_currency': website.pricelist_id.currency_id}"/>
|
||||
</t>
|
||||
</span>
|
||||
</t>
|
||||
@@ -65,4 +78,10 @@
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="fold_register_details" inherit_id="website_event.fold_register_details" name="Fold ticket details">
|
||||
<xpath expr="//div[@id='o_wevent_tickets_pricelist']" position="attributes">
|
||||
<attribute name="class">collapse</attribute>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="index_topbar" inherit_id="website_event.index_topbar">
|
||||
<xpath expr="//ul[hasclass('o_wevent_index_topbar_filters')]" position="inside">
|
||||
<t t-set="website_sale_pricelists" t-value="website.get_pricelist_available(show_visible=True)" />
|
||||
<t t-set="hasPricelistDropdown" t-value="website_sale_pricelists and len(website_sale_pricelists)>1"/>
|
||||
<t t-call="website_sale.pricelist_list">
|
||||
<t t-set="_classes" t-valuef="d-none d-lg-inline me-2 my-1"/>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<!-- If the sale order line concerns an event, we want the "product" link to point to the event itself and not to the product on the ecommerce -->
|
||||
<template id="cart_line_product_link_inherit_website_event_sale" inherit_id="website_sale.cart_line_product_link" name="Event Shopping Cart Line Product Link">
|
||||
<xpath expr="//a" position="attributes">
|
||||
|
||||
Reference in New Issue
Block a user