Skip to content

Commit

Permalink
[FIX] website_event_booth_sale, website_event_sale: correct price
Browse files Browse the repository at this point in the history
Steps to reproduce:
- Create a price list with different currency and discount with "show price and discount to the customer"
- On the website select this pricelist and register for the event.

Issue:
 The price in the cart is shown in the main currency

Solution:
[website_event_sale] There is an initial issue which when it calls '_compute_price_reduce'. We compare, 'product.lst_price' (in product.currency) and 'product.price' (which has been converted to the pricelist.currency).
In order to compare apples with apples, a conversion is applied to have the 'product.lst_price' in the same currency.

After that, we have kind of a coherent behaviour in the sense that 'ticket.price_reduce' is in the same currency as 'ticket.price'.
Thereafter, a conversion is applied (if the pricelist.currency is different) to get the expected  amount.

The same reasoning is applied to [website_event_booth_sale].

Note: 'list_price' has been changed to 'lst_price' in Booth to have the same logic between Event and Booth

opw-2766997

closes odoo#85640

Signed-off-by: Nicolas Lempereur (nle) <nle@odoo.com>
  • Loading branch information
yosa-odoo committed Jun 9, 2022
1 parent 0530fff commit 7ef09a1
Show file tree
Hide file tree
Showing 11 changed files with 331 additions and 17 deletions.
10 changes: 8 additions & 2 deletions addons/event_booth_sale/models/event_booth_category.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,14 @@ def _compute_price(self):
def _compute_price_reduce(self):
for category in self:
product = category.product_id
list_price = product.list_price + product.price_extra
discount = (list_price - product.price) / list_price if list_price else 0.0
pricelist = self.env['product.pricelist'].browse(self._context.get('pricelist'))
lst_price = product.currency_id._convert(
product.lst_price,
pricelist.currency_id,
self.env.company,
fields.Datetime.now()
)
discount = (lst_price - product.price) / lst_price if lst_price else 0.0
category.price_reduce = (1.0 - discount) * category.price

@api.depends_context('pricelist', 'quantity')
Expand Down
10 changes: 9 additions & 1 deletion addons/event_sale/models/event_ticket.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,19 @@ def _compute_description(self):
if not ticket.description:
ticket.description = False

@api.depends_context('pricelist', 'quantity')
@api.depends('product_id', 'price')
def _compute_price_reduce(self):
for ticket in self:
product = ticket.product_id
discount = (product.lst_price - product.price) / product.lst_price if product.lst_price else 0.0
pricelist = self.env['product.pricelist'].browse(self._context.get('pricelist'))
lst_price = product.currency_id._convert(
product.lst_price,
pricelist.currency_id,
self.env.company,
fields.Datetime.now()
)
discount = (lst_price - product.price) / lst_price if lst_price else 0.0
ticket.price_reduce = (1.0 - discount) * ticket.price

def _init_column(self, column_name):
Expand Down
43 changes: 41 additions & 2 deletions addons/website_event_booth_sale/models/sale_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo import Command
from odoo import models, _
from odoo import fields, models, _


class SaleOrder(models.Model):
Expand Down Expand Up @@ -42,9 +42,48 @@ def _website_product_id_change(self, order_id, product_id, qty=0, **kwargs):
event_booth_registrations_command = new_registrations_commands
values['event_booth_registration_ids'] = event_booth_registrations_command

discount = 0
order = self.env['sale.order'].sudo().browse(order_id)
booth_currency = booths.product_id.currency_id
pricelist_currency = order.pricelist_id.currency_id
price_reduce = sum(booth.booth_category_id.price_reduce for booth in booths)
if booth_currency != pricelist_currency:
price_reduce = booth_currency._convert(
price_reduce,
pricelist_currency,
order.company_id,
order.date_order or fields.Datetime.now()
)
if order.pricelist_id.discount_policy == 'without_discount':
price = sum(booth.booth_category_id.price for booth in booths)
if price != 0:
if booth_currency != pricelist_currency:
price = booth_currency._convert(
price,
pricelist_currency,
order.company_id,
order.date_order or fields.Datetime.now()
)
discount = (price - price_reduce) / price * 100
price_unit = price
if discount < 0:
discount = 0
price_unit = price_reduce
else:
price_unit = price_reduce

else:
price_unit = price_reduce

if order.pricelist_id and order.partner_id:
order_line = order._cart_find_product_line(booths.product_id.id)
if order_line:
price_unit = self.env['account.tax']._fix_tax_included_price_company(price_unit, booths.product_id.taxes_id, order_line[0].tax_id, self.company_id)

values.update(
event_id=booths.event_id.id,
price_unit=sum(booth.booth_category_id.price_reduce for booth in booths),
discount=discount,
price_unit=price_unit,
name=booths._get_booth_multiline_description,
)

Expand Down
1 change: 1 addition & 0 deletions addons/website_event_booth_sale/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from . import test_event_booth_sale
from . import test_website_event_booth_sale_pricelist
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo.addons.event_booth_sale.tests.common import TestEventBoothSaleCommon
from odoo.addons.website_event_sale.tests.common import TestWebsiteEventSaleCommon
from odoo.addons.website_sale.controllers.main import WebsiteSale
from odoo.addons.website.tools import MockRequest
from odoo.tests import tagged


@tagged('post_install', '-at_install')
class TestWebsiteBoothPriceList(TestEventBoothSaleCommon, TestWebsiteEventSaleCommon):

@classmethod
def setUpClass(cls):
super(TestWebsiteBoothPriceList, cls).setUpClass()

cls.WebsiteSaleController = WebsiteSale()
cls.booth_1 = cls.env['event.booth'].create({
'booth_category_id': cls.event_booth_category_1.id,
'event_id': cls.event_0.id,
'name': 'Test Booth 1',
})

cls.booth_2 = cls.env['event.booth'].create({
'booth_category_id': cls.event_booth_category_1.id,
'event_id': cls.event_0.id,
'name': 'Test Booth 2',
})

def test_pricelist_different_currency(self):
so_line = self.env['sale.order.line'].create({
'event_booth_category_id': self.event_booth_category_1.id,
'event_booth_pending_ids': (self.booth_1 + self.booth_2).ids,
'event_id': self.event_0.id,
'order_id': self.so.id,
'product_id': self.event_booth_product.id,
})
# set pricelist to 0 - currency: company
self.pricelist.write({
'currency_id': self.new_company.currency_id.id,
'discount_policy': 'with_discount',
'item_ids': [(5, 0, 0), (0, 0, {
'applied_on': '3_global',
'compute_price': 'percentage',
'percent_price': 0,
})],
'name': 'With Discount Included',
})
with MockRequest(self.env, sale_order_id=self.so.id, website=self.current_website):
self.WebsiteSaleController.pricelist('With Discount Included')
self.so._cart_update(line_id=so_line.id, product_id=self.event_booth_product.id, set_qty=1)
self.assertEqual(so_line.price_reduce, 40)

# set pricelist to 10% - without discount
self.pricelist.write({
'currency_id': self.currency_test.id,
'discount_policy': 'without_discount',
'item_ids': [(5, 0, 0), (0, 0, {
'applied_on': '3_global',
'compute_price': 'percentage',
'percent_price': 10,
})],
'name': 'Without Discount Included',
})
with MockRequest(self.env, sale_order_id=self.so.id, website=self.current_website):
self.WebsiteSaleController.pricelist('Without Discount Included')
self.so._cart_update(line_id=so_line.id, product_id=self.event_booth_product.id, set_qty=1)
self.assertEqual(so_line.price_reduce, 360, 'Incorrect amount based on the pricelist and its currency.')

# set pricelist to 10% - with discount
self.pricelist.write({
'discount_policy': 'with_discount',
'name': 'With Discount Included',
})
with MockRequest(self.env, sale_order_id=self.so.id, website=self.current_website):
self.WebsiteSaleController.pricelist('With Discount Included')
self.so._cart_update(line_id=so_line.id, product_id=self.event_booth_product.id, set_qty=1)
self.assertEqual(so_line.price_reduce, 360, 'Incorrect amount based on the pricelist and its currency.')
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@
<template id="event_booth_registration" inherit_id="website_event_booth.event_booth_registration">
<xpath expr="//h5[@name='booth_category_name']" position="after">
<t t-if="booth_category.price">
<t t-if="(booth_category.price-website.get_current_pricelist().currency_id._convert(booth_category.price_reduce, event.company_id.sudo().currency_id, event.company_id, datetime.date.today())) &gt; 1 and website.get_current_pricelist().discount_policy == 'without_discount'">
<del class="text-danger mr-1"
t-field="booth_category.price"
t-options="{'widget': 'monetary', 'from_currency': event.company_id.sudo().currency_id, 'display_currency': website.get_current_pricelist().currency_id}"/>
</t>
<span t-field="booth_category.price_reduce" class="font-weight-normal text-muted"
t-options="{'widget': 'monetary', 'display_currency': website.pricelist_id.currency_id}"
t-options="{'widget': 'monetary', 'from_currency': event.company_id.sudo().currency_id, 'display_currency': website.pricelist_id.currency_id}"
groups="account.group_show_line_subtotals_tax_excluded"/>
<span t-field="booth_category.price_reduce_taxinc" class="font-weight-normal text-muted"
t-options="{'widget': 'monetary', 'display_currency': website.pricelist_id.currency_id}"
t-options="{'widget': 'monetary', 'from_currency': event.company_id.sudo().currency_id, 'display_currency': website.pricelist_id.currency_id}"
groups="account.group_show_line_subtotals_tax_included"/>
</t>
<span t-else="" class="font-weight-normal text-muted">Free</span>
Expand Down
44 changes: 40 additions & 4 deletions addons/website_event_sale/models/sale_order.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-

from odoo import api, models, _
from odoo import api, fields, models, _
from odoo.exceptions import UserError
from odoo.osv import expression

Expand Down Expand Up @@ -40,11 +40,47 @@ def _website_product_id_change(self, order_id, product_id, qty=0, **kwargs):
values['product_id'] = ticket.product_id.id
values['event_id'] = ticket.event_id.id
values['event_ticket_id'] = ticket.id
discount = 0
ticket_currency = ticket.product_id.currency_id
pricelist_currency = order.pricelist_id.currency_id
price_reduce = ticket.price_reduce
if ticket_currency != pricelist_currency:
price_reduce = ticket_currency._convert(
price_reduce,
pricelist_currency,
order.company_id,
order.date_order or fields.Datetime.now()
)
if order.pricelist_id.discount_policy == 'without_discount':
values['price_unit'] = ticket.price
price = ticket.price
if price != 0:
if ticket_currency != pricelist_currency:
price = ticket_currency._convert(
price,
pricelist_currency,
order.company_id,
order.date_order or fields.Datetime.now()
)
discount = (price - price_reduce) / price * 100
price_unit = price
if discount < 0:
discount = 0
price_unit = price_reduce
else:
price_unit = price_reduce
else:
values['price_unit'] = ticket.price_reduce
values['name'] = ticket._get_ticket_multiline_description()
price_unit = price_reduce

if order.pricelist_id and order.partner_id:
order_line = order._cart_find_product_line(ticket.product_id.id)
if order_line:
price_unit = self.env['account.tax']._fix_tax_included_price_company(price_unit, ticket.product_id.taxes_id, order_line[0].tax_id, self.company_id)

values.update(
discount=discount,
name=ticket._get_ticket_multiline_description(),
price_unit=price_unit,
)

# avoid writing related values that end up locking the product record
values.pop('event_ok', None)
Expand Down
2 changes: 2 additions & 0 deletions addons/website_event_sale/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from . import common
from . import test_frontend_buy_tickets
from . import test_website_event_sale_pricelist
61 changes: 61 additions & 0 deletions addons/website_event_sale/tests/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from datetime import timedelta

from odoo.fields import Datetime
from odoo.tests.common import TransactionCase


class TestWebsiteEventSaleCommon(TransactionCase):

@classmethod
def setUpClass(cls):
super(TestWebsiteEventSaleCommon, cls).setUpClass()

cls.product_event = cls.env['product.product'].create({
'base_unit_price': 100,
'detailed_type': 'event',
'name': 'Event Registration No Company Assigned',
})

cls.event = cls.env['event.event'].create({
'date_begin': (Datetime.today() + timedelta(days=5)).strftime('%Y-%m-%d 07:00:00'),
'date_end': (Datetime.today() + timedelta(days=5)).strftime('%Y-%m-%d 16:30:00'),
'name': 'Pycon',
'user_id': cls.env.ref('base.user_admin').id,
'website_published': True,
})
cls.ticket = cls.env['event.event.ticket'].create([{
'event_id': cls.event.id,
'name': 'Standard',
'product_id': cls.product_event.id,
'price': 100,
}])
cls.currency_test = cls.env['res.currency'].create({
'name': 'eventX',
'rate': 10,
'rounding': 0.01,
'symbol': 'EX',
})
cls.partner = cls.env['res.partner'].create({'name': 'test'})
cls.new_company = cls.env['res.company'].create({
'currency_id': cls.env.ref('base.EUR').id,
'name': 'Great Company EUR',
'partner_id': cls.partner.id,
})
cls.env['res.currency.rate'].create({
'company_id': cls.new_company.id,
'currency_id': cls.currency_test.id,
'name': '2022-01-01',
'rate': 10,
})

cls.current_website = cls.env['website'].get_current_website()
cls.pricelist = cls.current_website.get_current_pricelist()

cls.so = cls.env['sale.order'].create({
'company_id': cls.new_company.id,
'partner_id': cls.partner.id,
'pricelist_id': cls.pricelist.id,
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo.addons.website_sale.controllers.main import WebsiteSale
from odoo.addons.website.tools import MockRequest
from odoo.addons.website_event_sale.tests.common import TestWebsiteEventSaleCommon
from odoo.tests import tagged


@tagged('post_install', '-at_install')
class TestWebsiteEventPriceList(TestWebsiteEventSaleCommon):

@classmethod
def setUpClass(cls):
super(TestWebsiteEventPriceList, cls).setUpClass()

cls.WebsiteSaleController = WebsiteSale()

def test_pricelist_different_currency(self):

so_line = self.env['sale.order.line'].create({
'event_id': self.event.id,
'event_ticket_id': self.ticket.id,
'name': self.event.name,
'order_id': self.so.id,
'product_id': self.ticket.product_id.id,
'product_uom_qty': 1,
})
# set pricelist to 0 - currency: company
self.pricelist.write({
'currency_id': self.new_company.currency_id.id,
'discount_policy': 'with_discount',
'item_ids': [(5, 0, 0), (0, 0, {
'applied_on': '3_global',
'compute_price': 'percentage',
'percent_price': 0,
})],
'name': 'With Discount Included',
})
with MockRequest(self.env, sale_order_id=self.so.id, website=self.current_website):
self.WebsiteSaleController.pricelist('With Discount Included')
self.so._cart_update(line_id=so_line.id, product_id=self.ticket.product_id.id, set_qty=1)
self.assertEqual(so_line.price_reduce, 100)

# set pricelist to 10% - without discount
self.pricelist.write({
'currency_id': self.currency_test.id,
'discount_policy': 'without_discount',
'item_ids': [(5, 0, 0), (0, 0, {
'applied_on': '3_global',
'compute_price': 'percentage',
'percent_price': 10,
})],
'name': 'Without Discount Included',
})
with MockRequest(self.env, sale_order_id=self.so.id, website=self.current_website):
self.WebsiteSaleController.pricelist('Without Discount Included')
self.so._cart_update(line_id=so_line.id, product_id=self.ticket.product_id.id, set_qty=1)
self.assertEqual(so_line.price_reduce, 900, 'Incorrect amount based on the pricelist and its currency.')

# set pricelist to 10% - with discount
self.pricelist.write({
'discount_policy': 'with_discount',
'name': 'With Discount Included',
})
with MockRequest(self.env, sale_order_id=self.so.id, website=self.current_website):
self.WebsiteSaleController.pricelist('With Discount Included')
self.so._cart_update(line_id=so_line.id, product_id=self.ticket.product_id.id, set_qty=1)
self.assertEqual(so_line.price_reduce, 900, 'Incorrect amount based on the pricelist and its currency.')
Loading

0 comments on commit 7ef09a1

Please sign in to comment.