diff options
| author | Sébastien Theys <seb@odoo.com> | 2018-08-14 16:00:38 +0200 |
|---|---|---|
| committer | Sébastien Theys <seb@odoo.com> | 2018-08-14 16:51:16 +0200 |
| commit | fd3febf7d7899412d36d1e2263e7a466398cd336 (patch) | |
| tree | 438a1c9e0020929dad7731f8844f5d683e999228 | |
| parent | c99eb1b8fb48eef80300aae90c08b54d28e093a7 (diff) | |
[IMP] various: add event and ticket name on sale order and invoice line
In event_sale it is possible to have one product representing several tickets. But before this commit, on the sale order and invoice the client only saw the name of the product and didn't know which event/ticket they subscribed to.
The goal of this commit is to overwrite that behavior whenever a sale order or invoice line is related to an event ticket, to show the ticket name and event name instead of the product name.
Technically, the following changes have been done:
----------------------------------------
* various: add a method to compute a default name for a SaleOrderLine, based on its product
I added the method because the code to compute the name was duplicated in several places. This will make it more consistent.
Moreover this gives the option for modules to override the method to define a custom name as necessary.
----------------------------------------
* event_sale: compute a consistent description for a SaleOrderLine based on an EventTicket
The description will be the same whether the sale order comes from the front end or the back end. It takes into account the customer language.
The default description will be computed as follow:
1. The ticket name should be the first line of the product description on the SO.
2. The event name should be the second line of the product description on the SO.
To compute the ticket multi-line description we decided to ignore entirely the product name and the product description_sale because they are considered to be replaced by the ticket name and event name.
We also ignore them because the work-flow of creating a new event does not lead to filling them correctly, as the product is created through the event interface.
----------------------------------------
* event_sale: improve sale order line and event registration views
It was possible to select a ticket related to a product before an event was selected.
This is typically the case for tickets defined in an event_type but not in an event.
The ticket field is now hidden until both the product and the event have been selected.
This way we are sure the selected ticket will belong to an event and not an event_type.
We reset the ticket on event change because we don't want the user to be able to select a ticket belonging to the wrong event.
We also improve here the comments of the related on-change methods.
----------------------------------------
* website_event_sale: update views to show ticket name and event name
The standard behavior was to show the product name in several places instead of the sale order line description.
However, for event tickets, we don't want to show the product name, but the ticket name and event name instead.
----------------------------------------
* website_event_sale: add ticket on confirmation page
The ticket name was missing from the registration confirmation page (shown when the ticket is free and/or the user paid with a direct method). This is now fixed.
----------------------------------------
Task: 1837987
PR: 25819
| -rw-r--r-- | addons/event/views/event_views.xml | 2 | ||||
| -rw-r--r-- | addons/event_sale/models/event.py | 28 | ||||
| -rw-r--r-- | addons/event_sale/models/sale_order.py | 39 | ||||
| -rw-r--r-- | addons/event_sale/tests/test_event_sale.py | 9 | ||||
| -rw-r--r-- | addons/event_sale/views/event_views.xml | 10 | ||||
| -rw-r--r-- | addons/event_sale/views/sale_order_views.xml | 24 | ||||
| -rw-r--r-- | addons/product/models/product.py | 10 | ||||
| -rw-r--r-- | addons/sale/models/sale.py | 14 | ||||
| -rw-r--r-- | addons/sale_management/models/sale_order.py | 4 | ||||
| -rw-r--r-- | addons/website_event/models/event.py | 7 | ||||
| -rw-r--r-- | addons/website_event_sale/models/sale_order.py | 17 | ||||
| -rw-r--r-- | addons/website_event_sale/views/event_templates.xml | 43 | ||||
| -rw-r--r-- | addons/website_sale/models/sale_order.py | 18 | ||||
| -rw-r--r-- | addons/website_sale/views/templates.xml | 48 |
14 files changed, 231 insertions, 42 deletions
diff --git a/addons/event/views/event_views.xml b/addons/event/views/event_views.xml index ffc04deca47..1977634b90a 100644 --- a/addons/event/views/event_views.xml +++ b/addons/event/views/event_views.xml @@ -468,7 +468,7 @@ <field name="email"/> </group> <group string="Event Information" name="event"> - <field name="event_id" attrs="{'readonly': [('state', '!=', 'draft')]}"/> + <field name="event_id" attrs="{'readonly': [('state', '!=', 'draft')]}" options="{'no_open': True, 'no_create': True}"/> <field name="date_open" groups="base.group_no_one"/> <field name="date_closed" groups="base.group_no_one"/> </group> diff --git a/addons/event_sale/models/event.py b/addons/event_sale/models/event.py index 1f9a7ed53b0..0ab88b3be85 100644 --- a/addons/event_sale/models/event.py +++ b/addons/event_sale/models/event.py @@ -160,17 +160,43 @@ class EventTicket(models.Model): def _onchange_product_id(self): self.price = self.product_id.list_price or 0 + def get_ticket_multiline_description_sale(self): + """ Compute a multiline description of this ticket, in the context of sales. + It will often be used as the default description of a sales order line referencing this ticket. + + 1. the first line is the ticket name + 2. the second line is the event name (if it exists, which should be the case with a normal workflow) or the product name (if it exists) + + We decided to ignore entirely the product name and the product description_sale because they are considered to be replaced by the ticket name and event name. + -> the workflow of creating a new event also does not lead to filling them correctly, as the product is created through the event interface + """ + + name = self.display_name + + if self.event_id: + name += '\n' + self.event_id.display_name + elif self.product_id: + name += '\n' + self.product_id.display_name + + return name + class EventRegistration(models.Model): _inherit = 'event.registration' - event_ticket_id = fields.Many2one('event.event.ticket', string='Event Ticket') + event_ticket_id = fields.Many2one('event.event.ticket', string='Event Ticket', readonly=True, states={'draft': [('readonly', False)]}) # in addition to origin generic fields, add real relational fields to correctly # handle attendees linked to sales orders and their lines # TDE FIXME: maybe add an onchange on sale_order_id + origin sale_order_id = fields.Many2one('sale.order', string='Source Sales Order', ondelete='cascade') sale_order_line_id = fields.Many2one('sale.order.line', string='Sales Order Line', ondelete='cascade') + @api.onchange('event_id') + def _onchange_event_id(self): + # We reset the ticket when keeping it would lead to an inconstitent state. + if self.event_ticket_id and (not self.event_id or self.event_id != self.event_ticket_id.event_id): + self.event_ticket_id = None + @api.multi @api.constrains('event_ticket_id', 'state') def _check_ticket_seats_limit(self): diff --git a/addons/event_sale/models/sale_order.py b/addons/event_sale/models/sale_order.py index a4601ac5f76..c41a6218f10 100644 --- a/addons/event_sale/models/sale_order.py +++ b/addons/event_sale/models/sale_order.py @@ -28,14 +28,6 @@ class SaleOrderLine(models.Model): event_ok = fields.Boolean(related='product_id.event_ok', readonly=True) @api.multi - def _prepare_invoice_line(self, qty): - self.ensure_one() - res = super(SaleOrderLine, self)._prepare_invoice_line(qty) - if self.event_id: - res['name'] = '%s: %s' % (res.get('name', ''), self.event_id.name) - return res - - @api.multi def _update_registrations(self, confirm=True, cancel_to_draft=False, registration_data=None): """ Create or update registrations linked to a sales order line. A sale order line has a product_uom_qty attribute that will be the number of @@ -60,9 +52,40 @@ class SaleOrderLine(models.Model): Registration._prepare_attendee_values(registration)) return True + @api.onchange('product_id') + def _onchange_product_id(self): + # We reset the event when keeping it would lead to an inconstitent state. + # We need to do it this way because the only relation between the product and the event is through the corresponding tickets. + if self.event_id and (not self.product_id or self.product_id.id not in self.event_id.mapped('event_ticket_ids.product_id.id')): + self.event_id = None + + @api.onchange('event_id') + def _onchange_event_id(self): + # We reset the ticket when keeping it would lead to an inconstitent state. + if self.event_ticket_id and (not self.event_id or self.event_id != self.event_ticket_id.event_id): + self.event_ticket_id = None + @api.onchange('event_ticket_id') def _onchange_event_ticket_id(self): company = self.event_id.company_id or self.env.user.company_id currency = company.currency_id self.price_unit = currency._convert( self.event_ticket_id.price, self.order_id.currency_id, self.order_id.company_id, self.order_id.date_order or fields.Date.today()) + + # we call this to force update the default name + self.product_id_change() + + def get_sale_order_line_multiline_description_sale(self, product): + """ We override this method because we decided that: + The default description of a sales order line containing a ticket must be different than the default description when no ticket is present. + So in that case we use the description computed from the ticket, instead of the description computed from the product. + We need this override to be defined here in sales order line (and not in product) because here is the only place where the event_ticket_id is referenced. + """ + if self.event_ticket_id: + ticket = self.event_ticket_id.with_context( + lang=self.order_id.partner_id.lang, + ) + + return ticket.get_ticket_multiline_description_sale() + else: + return super(SaleOrderLine, self).get_sale_order_line_multiline_description_sale(product) diff --git a/addons/event_sale/tests/test_event_sale.py b/addons/event_sale/tests/test_event_sale.py index d73a1cfcb7e..8f17f322780 100644 --- a/addons/event_sale/tests/test_event_sale.py +++ b/addons/event_sale/tests/test_event_sale.py @@ -25,6 +25,12 @@ class EventSaleTest(common.TransactionCase): 'date_begin': '2012-01-01 18:05:15' }) + ticket = self.env['event.event.ticket'].create({ + 'name': 'test_ticket', + 'product_id': product.id, + 'event_id': event.id, + }) + # I create a sales order self.sale_order = self.env['sale.order'].create({ 'partner_id': self.env.ref('base.res_partner_2').id, @@ -40,7 +46,8 @@ class EventSaleTest(common.TransactionCase): 'product_uom_qty': 8.0, 'order_id': self.sale_order.id, 'name': 'sales order line', - 'event_id': event.id + 'event_id': event.id, + 'event_ticket_id': ticket.id, }) # In the event registration I add some attendee detail lines. i choose event product diff --git a/addons/event_sale/views/event_views.xml b/addons/event_sale/views/event_views.xml index e8498e562e1..778bd166cb3 100644 --- a/addons/event_sale/views/event_views.xml +++ b/addons/event_sale/views/event_views.xml @@ -29,7 +29,15 @@ <field name="inherit_id" ref="event.view_event_registration_form" /> <field name="arch" type="xml"> <field name="event_id" position="after"> - <field name="event_ticket_id" domain="[('event_id', '=', event_id)]"/> + <field + name="event_ticket_id" + domain="[ + ('event_id', '=', event_id), + '|', ('seats_availability', '=', 'unlimited'), ('seats_available', '>', 0) + ]" + attrs="{'invisible': [('event_id', '=', False)]}" + options="{'no_open': True, 'no_create': True}" + /> </field> <group name="event" position="after"> <group string="Origin"> diff --git a/addons/event_sale/views/sale_order_views.xml b/addons/event_sale/views/sale_order_views.xml index 3d2b8530947..712da75ffd8 100644 --- a/addons/event_sale/views/sale_order_views.xml +++ b/addons/event_sale/views/sale_order_views.xml @@ -6,8 +6,28 @@ <field name="inherit_id" ref="sale.view_order_form" /> <field name="arch" type="xml"> <xpath expr="//field[@name='order_line']//form//field[@name='product_id']" position="after"> - <field name="event_id" domain="[('event_ticket_ids.product_id','=', product_id),('date_end','>=',time.strftime('%Y-%m-%d 00:00:00'))]" attrs="{'invisible': [('event_ok', '=', False)],'required': [('event_ok', '!=', False)]}"/> - <field name="event_ticket_id" domain="[('event_id', '=', event_id), ('product_id','=',product_id), '|', ('seats_availability', '=', 'unlimited'), ('seats_available', '>', 0)]" attrs="{'invisible': [('event_ok', '=', False)], 'required': [('event_ok', '!=', False)]}"/> + <field + name="event_id" + domain="[ + ('event_ticket_ids.product_id','=', product_id), + ('date_end','>=',time.strftime('%Y-%m-%d 00:00:00')) + ]" + attrs="{'invisible': [('event_ok', '=', False)], 'required': [('event_ok', '!=', False)]}" + options="{'no_open': True, 'no_create': True}" + /> + <field + name="event_ticket_id" + domain="[ + ('event_id', '=', event_id), + ('product_id','=',product_id), + '|', ('seats_availability', '=', 'unlimited'), ('seats_available', '>', 0) + ]" + attrs="{ + 'invisible': ['|', ('event_ok', '=', False), ('event_id', '=', False)], + 'required': [('event_ok', '!=', False), ('event_id', '!=', False)], + }" + options="{'no_open': True, 'no_create': True}" + /> <field name="event_ok" invisible="1"/> </xpath> <xpath expr="//field[@name='order_line']//tree//field[@name='product_id']" position="after"> diff --git a/addons/product/models/product.py b/addons/product/models/product.py index a42b37cf5e7..ccda4b32511 100644 --- a/addons/product/models/product.py +++ b/addons/product/models/product.py @@ -572,6 +572,16 @@ class ProductProduct(models.Model): ) return super(ProductProduct, self).get_empty_list_help(help) + def get_product_multiline_description_sale(self): + """ Compute a multiline description of this product, in the context of sales + (do not use for purchases or other display reasons that don't intend to use "description_sale"). + It will often be used as the default description of a sale order line referencing this product. + """ + name = self.display_name + if self.description_sale: + name += '\n' + self.description_sale + return name + class ProductPackaging(models.Model): _name = "product.packaging" diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py index cdae56697db..3a66cc1a1f4 100644 --- a/addons/sale/models/sale.py +++ b/addons/sale/models/sale.py @@ -1343,10 +1343,7 @@ class SaleOrderLine(models.Model): self.product_id = False return result - name = product.name_get()[0][1] - if product.description_sale: - name += '\n' + product.description_sale - vals['name'] = name + vals.update(name=self.get_sale_order_line_multiline_description_sale(product)) self._compute_tax_id() @@ -1486,3 +1483,12 @@ class SaleOrderLine(models.Model): def _is_delivery(self): self.ensure_one() return False + + def get_sale_order_line_multiline_description_sale(self, product): + """ Compute a default multiline description for this sales order line. + This method exists so it can be overridden in other modules to change how the default name is computed. + In general only the product is used to compute the name, and this method would not be necessary (we could directly override the method in product). + BUT in event_sale we need to know specifically the sales order line as well as the product to generate the name: + the product is not sufficient because we also need to know the event_id and the event_ticket_id (both which belong to the sale order line). + """ + return product.get_product_multiline_description_sale() diff --git a/addons/sale_management/models/sale_order.py b/addons/sale_management/models/sale_order.py index f2481bc7fc5..b8a8d3ad8e8 100644 --- a/addons/sale_management/models/sale_order.py +++ b/addons/sale_management/models/sale_order.py @@ -238,9 +238,7 @@ class SaleOrderOption(models.Model): return product = self.product_id.with_context(lang=self.order_id.partner_id.lang) self.price_unit = product.list_price - self.name = product.name - if product.description_sale: - self.name += '\n' + product.description_sale + self.name = product.get_product_multiline_description_sale() self.uom_id = self.uom_id or product.uom_id pricelist = self.order_id.pricelist_id if pricelist and product: diff --git a/addons/website_event/models/event.py b/addons/website_event/models/event.py index ae07f798939..e4e10667dfc 100644 --- a/addons/website_event/models/event.py +++ b/addons/website_event/models/event.py @@ -4,12 +4,9 @@ import logging import pytz import werkzeug -from datetime import datetime - from odoo import api, fields, models, _ from odoo.addons.http_routing.models.ir_http import slug from odoo.exceptions import UserError -from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT _logger = logging.getLogger(__name__) @@ -162,8 +159,8 @@ class Event(models.Model): return result def _get_event_resource_urls(self, attendees): - url_date_start = datetime.strptime(self.date_begin, DEFAULT_SERVER_DATETIME_FORMAT).strftime('%Y%m%dT%H%M%SZ') - url_date_stop = datetime.strptime(self.date_end, DEFAULT_SERVER_DATETIME_FORMAT).strftime('%Y%m%dT%H%M%SZ') + url_date_start = self.date_begin.strftime('%Y%m%dT%H%M%SZ') + url_date_stop = self.date_end.strftime('%Y%m%dT%H%M%SZ') params = { 'action': 'TEMPLATE', 'text': self.name, diff --git a/addons/website_event_sale/models/sale_order.py b/addons/website_event_sale/models/sale_order.py index 3cf2d253182..097ce0adbaf 100644 --- a/addons/website_event_sale/models/sale_order.py +++ b/addons/website_event_sale/models/sale_order.py @@ -42,7 +42,7 @@ class SaleOrder(models.Model): values['event_id'] = ticket.event_id.id values['event_ticket_id'] = ticket.id values['price_unit'] = ticket.price_reduce or ticket.price - values['name'] = "%s\n%s" % (ticket.event_id.display_name, ticket.name) + values['name'] = ticket.get_ticket_multiline_description_sale() # avoid writing related values that end up locking the product record values.pop('event_ok', None) @@ -96,3 +96,18 @@ class SaleOrder(models.Model): # add in return values the registrations, to display them on website (or not) values['attendee_ids'] = self.env['event.registration'].search([('sale_order_line_id', '=', line.id), ('state', '!=', 'cancel')]).ids return values + + +class SaleOrderLine(models.Model): + _inherit = "sale.order.line" + + @api.multi + @api.depends('product_id.display_name', 'event_ticket_id.display_name') + def _compute_name_short(self): + """ If the sale order line concerns a ticket, we don't want the product name, but the ticket name instead. + """ + super(SaleOrderLine, self)._compute_name_short() + + for record in self: + if record.event_ticket_id: + record.name_short = record.event_ticket_id.display_name diff --git a/addons/website_event_sale/views/event_templates.xml b/addons/website_event_sale/views/event_templates.xml index 4be278f9620..bccf05ad8be 100644 --- a/addons/website_event_sale/views/event_templates.xml +++ b/addons/website_event_sale/views/event_templates.xml @@ -84,15 +84,54 @@ </xpath> </template> -<template id="cart" inherit_id="website_sale.cart_lines" name="Hide product reduction for event tickets"> - <xpath expr="//td[hasclass('td-product_name')]/div/a" position="attributes"> +<!-- 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"> <attribute name="t-attf-href"/> <attribute name="t-att-href"> line.event_id and ('/event/%s/register' % slug(line.event_id)) or ('/shop/product/%s' % slug(line.product_id.product_tmpl_id)) </attribute> </xpath> +</template> + +<!-- If the sale order line concerns an event, we want to show an additional line with the event name even on small screens --> +<template id="cart_lines_inherit_website_event_sale" inherit_id="website_sale.cart_lines" name="Event Shopping Cart Lines"> + <xpath expr="//t[@t-call='website_sale.cart_line_description_following_lines']/t[@t-set='div_class']" position="after"> + <t t-if="line.event_id"> + <t t-set="div_class" t-value="''"/> + </t> + </xpath> +</template> + +<!-- If the sale order line concerns an event, we want to show an additional line with the event name --> +<template id="cart_popover_inherit_website_event_sale" inherit_id="website_sale.cart_popover" name="Event Cart Popover"> + <xpath expr="//t[@t-call='website_sale.cart_line_product_link']" position="after"> + <t t-if="line.event_id" t-call="website_sale.cart_line_description_following_lines"/> + </xpath> +</template> + +<!-- If the sale order line concerns an event, we want to show an additional line with the event name --> +<template id="cart_summary_inherit_website_event_sale" inherit_id="website_sale.cart_summary" name="Event Cart right column"> + <xpath expr="//td[hasclass('td-product_name')]/div/strong" position="after"> + <t t-if="line.event_id" t-call="website_sale.cart_line_description_following_lines"/> + </xpath> +</template> + +<template id="cart_lines_inherit_website_event_sale" inherit_id="website_sale.cart_lines" name="Hide product reduction for event tickets"> <xpath expr="//del" position="attributes"> <attribute name="t-attf-class" separator=" " add="#{line.event_id and 'd-none' or ''}"/> </xpath> </template> + +<!-- Add the ticket name on the registration complete page. --> +<template id="registration_complete_inherit_website_event_sale" inherit_id="website_event.registration_complete" name="Sale Registration Completed"> + <xpath expr="//thead/tr/th[1]" position="after"> + <th>Ticket</th> + </xpath> + <xpath expr="//tbody/t/tr/td[1]" position="after"> + <td><i class="fa fa-ticket"></i> <t t-if='attendee.event_ticket_id'><t t-esc="attendee.event_ticket_id.name"/></t><t t-if='not attendee.event_ticket_id'>N/A</t></td> + </xpath> +</template> + </odoo> + diff --git a/addons/website_sale/models/sale_order.py b/addons/website_sale/models/sale_order.py index a48436c1433..8d8fd395045 100644 --- a/addons/website_sale/models/sale_order.py +++ b/addons/website_sale/models/sale_order.py @@ -239,3 +239,21 @@ class SaleOrder(models.Model): self.modified(['create_date']) if self.env.recompute and self.env.context.get('recompute', True): self.recompute() + + +class SaleOrderLine(models.Model): + _inherit = "sale.order.line" + + name_short = fields.Char(compute="_compute_name_short") + + @api.multi + @api.depends('product_id.display_name') + def _compute_name_short(self): + """ Compute a short name for this sale order line, to be used on the website where we don't have much space. + To keep it short, instead of using the first line of the description, we take the product name without the internal reference. + """ + for record in self: + record.name_short = record.product_id.with_context(display_default_code=False).display_name + + def get_description_following_lines(self): + return self.name.splitlines()[1:] diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml index 20a4c211015..1d5010bc412 100644 --- a/addons/website_sale/views/templates.xml +++ b/addons/website_sale/views/templates.xml @@ -817,6 +817,24 @@ </xpath> </template> + <!-- We use this template where we want to give the user a link to the product of a sale order line. --> + <template id="cart_line_product_link" name="Shopping Cart Line Product Link"> + <a t-attf-href="/shop/product/#{ slug(line.product_id.product_tmpl_id) }"> + <t t-raw="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. --> + <template id="cart_line_description_following_lines" name="Shopping Cart Line Description Following Lines"> + <div t-if="line.get_description_following_lines()" t-attf-class="text-muted {{div_class}} small"> + <t t-foreach="line.get_description_following_lines()" t-as="name_line"> + <span><t t-esc="name_line"/></span> + <br t-if="not name_line_last" /> + </t> + </div> + </template> + + <!-- This template is the one at the "Review order" step (the first one) on the checkout workflow. --> <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! @@ -840,15 +858,13 @@ </td> <td t-if="line.product_id.product_tmpl_id" class='td-product_name'> <div> - <a t-attf-href="/shop/product/#{ slug(line.product_id.product_tmpl_id) }"> - <strong t-esc="line.product_id.with_context(display_default_code=False).display_name" /> - </a> - </div> - <div class="text-muted d-none d-md-block small"> - <t t-foreach="line.name.splitlines()[1:]" t-as="name_line"> - <span><t t-esc="name_line"/></span><br/> + <t t-call="website_sale.cart_line_product_link"> + <strong t-field="line.name_short" /> </t> </div> + <t t-call="website_sale.cart_line_description_following_lines"> + <t t-set="div_class" t-value="'d-none d-md-block'"/> + </t> </td> <td class="text-center td-qty"> <div class="css_quantity input-group oe_website_spinner"> @@ -943,6 +959,7 @@ </t> </template> + <!-- this template is the one when we mouse over "My Cart" on the top right --> <template id="cart_popover" name="Cart Popover"> <div t-if="not website_sale_order or not website_sale_order.website_order_line" class="alert alert-info"> Your cart is empty! @@ -954,10 +971,11 @@ <span t-field="line.product_id.image_small" t-options="{'widget': 'image', 'class': 'rounded'}" /> </div> <div class="col-9"> - <a t-attf-href="/shop/product/#{ slug(line.product_id.product_tmpl_id) }"> - <span t-esc="line.product_id.with_context(display_default_code=False).display_name" class="h6" /> - </a> - <br /> + <div> + <t t-call="website_sale.cart_line_product_link"> + <span class="h6" t-esc="line.name_short" /> + </t> + </div> <small>Qty: <t t-esc="int(line.product_uom_qty) == line.product_uom_qty and int(line.product_uom_qty) or line.product_uom_qty" /></small> </div> </div> @@ -1388,6 +1406,10 @@ </div> </template> + <!-- This template is the one present on the right during the payment process. + Here it is important to not show too much information to the user, because we want him to pay! + We shouldn't display link to products or long descriptions. + --> <template id="cart_summary" name="Cart right column"> <div class="card"> <div class="card-body p-xl-0"> @@ -1416,9 +1438,9 @@ </td> <td class='td-product_name' t-if="line.product_id.product_tmpl_id"> <div> - <strong t-field="line.product_id.with_context(display_default_code=False).display_name" /> + <strong t-field="line.name_short" /> </div> - </td> + </td> <td class='td-qty'> <div t-esc="line.product_uom_qty" /> </td> |
