509 lines
20 KiB
Python
509 lines
20 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo.addons.event_sale.tests.common import TestEventSaleCommon
|
|
from odoo.addons.mail.tests.common import mail_new_test_user
|
|
from odoo.exceptions import ValidationError
|
|
from odoo.tests import tagged
|
|
from odoo.tests.common import users
|
|
|
|
|
|
@tagged('event_flow')
|
|
class TestEventSale(TestEventSaleCommon):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super(TestEventSale, cls).setUpClass()
|
|
|
|
product = cls.env['product.product'].create({
|
|
'name': 'Event',
|
|
'detailed_type': 'event',
|
|
})
|
|
|
|
cls.user_salesperson = mail_new_test_user(cls.env, login='user_salesman', groups='sales_team.group_sale_salesman')
|
|
|
|
cls.ticket = cls.env['event.event.ticket'].create({
|
|
'name': 'First Ticket',
|
|
'product_id': cls.event_product.id,
|
|
'seats_max': 30,
|
|
'event_id': cls.event_0.id,
|
|
})
|
|
|
|
cls.event_0.write({
|
|
'event_ticket_ids': [
|
|
(6, 0, cls.ticket.ids),
|
|
(0, 0, {
|
|
'name': 'Second Ticket',
|
|
'product_id': cls.event_product.id,
|
|
})
|
|
],
|
|
})
|
|
|
|
cls.sale_order = cls.env['sale.order'].create({
|
|
'partner_id': cls.env['res.partner'].create({'name': 'Test Partner'}).id,
|
|
'note': 'Invoice after delivery',
|
|
'payment_term_id': cls.env.ref('account.account_payment_term_end_following_month').id
|
|
})
|
|
|
|
# In the sales order I add some sales order lines. i choose event product
|
|
cls.env['sale.order.line'].create({
|
|
'product_id': product.id,
|
|
'price_unit': 190.50,
|
|
'order_id': cls.sale_order.id,
|
|
'event_id': cls.event_0.id,
|
|
'event_ticket_id': cls.ticket.id,
|
|
})
|
|
|
|
cls.register_person = cls.env['registration.editor'].create({
|
|
'sale_order_id': cls.sale_order.id,
|
|
'event_registration_ids': [(0, 0, {
|
|
'event_id': cls.event_0.id,
|
|
'name': 'Administrator',
|
|
'email': 'abc@example.com',
|
|
'sale_order_line_id': cls.sale_order.order_line.id,
|
|
})],
|
|
})
|
|
|
|
# make a SO for a customer, selling some tickets
|
|
cls.customer_so = cls.env['sale.order'].with_user(cls.user_sales_salesman).create({
|
|
'partner_id': cls.event_customer.id,
|
|
})
|
|
|
|
cls.env['account.tax.group'].create(
|
|
{'name': 'Test Account Tax Group', 'company_id': cls.env.company.id}
|
|
)
|
|
|
|
@users('user_sales_salesman')
|
|
def test_adjusted_quantity_in_sale_order(self):
|
|
""" This test ensures that when reducing the quantity of tickets for an event, we will cancel the
|
|
registrations for those tickets too.
|
|
"""
|
|
customer_so = self.customer_so.with_user(self.env.user)
|
|
ticket = self.event_0.event_ticket_ids[0]
|
|
|
|
customer_so.write({
|
|
'order_line': [
|
|
(0, 0, {
|
|
'event_id': self.event_0.id,
|
|
'event_ticket_id': ticket.id,
|
|
'product_id': ticket.product_id.id,
|
|
'product_uom_qty': 3,
|
|
'price_unit': 10,
|
|
})
|
|
]
|
|
})
|
|
|
|
editor = self.env['registration.editor'].with_context({'default_sale_order_id': customer_so.id}).create({})
|
|
editor.action_make_registration()
|
|
|
|
registration_to_cancel = self.event_0.registration_ids[0]
|
|
registration_to_cancel.action_cancel()
|
|
|
|
registrations = self.env['event.registration'].search([('sale_order_id', '=', customer_so.id)])
|
|
|
|
expected_states = ['draft', 'draft', 'cancel']
|
|
actual_states = registrations.sorted('id').mapped('state')
|
|
|
|
self.assertListEqual(actual_states, expected_states, "One of the registrations should be cancelled.")
|
|
|
|
@users('user_sales_salesman')
|
|
def test_event_crm_sale(self):
|
|
TICKET1_COUNT, TICKET2_COUNT = 3, 1
|
|
customer_so = self.customer_so.with_user(self.env.user)
|
|
ticket1 = self.event_0.event_ticket_ids[0]
|
|
ticket2 = self.event_0.event_ticket_ids[1]
|
|
|
|
# PREPARE SO DATA
|
|
# ------------------------------------------------------------
|
|
|
|
# adding some tickets to SO
|
|
customer_so.write({
|
|
'order_line': [
|
|
(0, 0, {
|
|
'event_id': self.event_0.id,
|
|
'event_ticket_id': ticket1.id,
|
|
'product_id': ticket1.product_id.id,
|
|
'product_uom_qty': TICKET1_COUNT,
|
|
'price_unit': 10,
|
|
}), (0, 0, {
|
|
'event_id': self.event_0.id,
|
|
'event_ticket_id': ticket2.id,
|
|
'product_id': ticket2.product_id.id,
|
|
'product_uom_qty': TICKET2_COUNT,
|
|
'price_unit': 50,
|
|
})
|
|
]
|
|
})
|
|
ticket1_line = customer_so.order_line.filtered(lambda line: line.event_ticket_id == ticket1)
|
|
ticket2_line = customer_so.order_line.filtered(lambda line: line.event_ticket_id == ticket2)
|
|
self.assertEqual(customer_so.amount_untaxed, TICKET1_COUNT * 10 + TICKET2_COUNT * 50)
|
|
|
|
# one existing registration for first ticket
|
|
ticket1_reg1 = self.env['event.registration'].create({
|
|
'event_id': self.event_0.id,
|
|
'event_ticket_id': ticket1.id,
|
|
'partner_id': self.event_customer2.id,
|
|
'sale_order_id': customer_so.id,
|
|
'sale_order_line_id': ticket1_line.id,
|
|
})
|
|
self.assertEqual(ticket1_reg1.partner_id, self.event_customer)
|
|
for field in ['name', 'email', 'phone']:
|
|
self.assertEqual(ticket1_reg1[field], self.event_customer[field])
|
|
|
|
# EVENT REGISTRATION EDITOR
|
|
# ------------------------------------------------------------
|
|
|
|
# use event registration editor to create missing lines and update details
|
|
editor = self.env['registration.editor'].with_context({
|
|
'default_sale_order_id': customer_so.id
|
|
}).create({})
|
|
self.assertEqual(len(editor.event_registration_ids), TICKET1_COUNT + TICKET2_COUNT)
|
|
self.assertEqual(editor.sale_order_id, customer_so)
|
|
self.assertEqual(editor.event_registration_ids.sale_order_line_id, ticket1_line | ticket2_line)
|
|
|
|
# check line linked to existing registration (ticket1_reg1)
|
|
ticket1_editor_reg1 = editor.event_registration_ids.filtered(lambda line: line.registration_id)
|
|
for field in ['name', 'email', 'phone']:
|
|
self.assertEqual(ticket1_editor_reg1[field], ticket1_reg1[field])
|
|
|
|
# check new lines
|
|
ticket1_editor_other = editor.event_registration_ids.filtered(lambda line: not line.registration_id and line.event_ticket_id == ticket1)
|
|
self.assertEqual(len(ticket1_editor_other), 2)
|
|
ticket2_editor_other = editor.event_registration_ids.filtered(lambda line: not line.registration_id and line.event_ticket_id == ticket2)
|
|
self.assertEqual(len(ticket2_editor_other), 1)
|
|
|
|
# update lines in editor and save them
|
|
ticket1_editor_other[0].write({
|
|
'name': 'ManualEntry1',
|
|
'email': 'manual.email.1@test.example.com',
|
|
'phone': '+32456111111',
|
|
})
|
|
ticket1_editor_other[1].write({
|
|
'name': 'ManualEntry2',
|
|
'email': 'manual.email.2@test.example.com',
|
|
})
|
|
|
|
editor.action_make_registration()
|
|
|
|
# check editor correctly created new registrations with information coming from it or SO as fallback
|
|
self.assertEqual(len(self.event_0.registration_ids), TICKET1_COUNT + TICKET2_COUNT)
|
|
new_registrations = self.event_0.registration_ids - ticket1_reg1
|
|
self.assertEqual(new_registrations.sale_order_id, customer_so)
|
|
ticket1_new_reg = new_registrations.filtered(lambda reg: reg.event_ticket_id == ticket1)
|
|
ticket2_new_reg = new_registrations.filtered(lambda reg: reg.event_ticket_id == ticket2)
|
|
self.assertEqual(len(ticket1_new_reg), 2)
|
|
self.assertEqual(len(ticket2_new_reg), 1)
|
|
self.assertEqual(
|
|
set(ticket1_new_reg.mapped('name')),
|
|
set(['ManualEntry1', 'ManualEntry2'])
|
|
)
|
|
self.assertEqual(
|
|
set(ticket1_new_reg.mapped('email')),
|
|
set(['manual.email.1@test.example.com', 'manual.email.2@test.example.com'])
|
|
)
|
|
self.assertEqual(
|
|
set(ticket1_new_reg.mapped('phone')),
|
|
set(['+32456111111', self.event_customer._phone_format(fname='phone')])
|
|
)
|
|
for field in ['name', 'email']:
|
|
self.assertEqual(ticket2_new_reg[field], self.event_customer[field])
|
|
self.assertEqual(ticket2_new_reg['phone'], self.event_customer._phone_format(fname='phone'))
|
|
|
|
# ADDING MANUAL LINES ON SO
|
|
# ------------------------------------------------------------
|
|
|
|
ticket2_line.write({'product_uom_qty': 3})
|
|
|
|
# Whenever the quantity is modified the price is recomputed in function of the ticket,
|
|
# so we reapply the wanted price.
|
|
ticket2_line.write({'price_unit': 50})
|
|
|
|
editor_action = customer_so.action_confirm()
|
|
self.assertEqual(customer_so.state, 'sale')
|
|
self.assertEqual(customer_so.amount_untaxed, TICKET1_COUNT * 10 + (TICKET2_COUNT + 2) * 50)
|
|
|
|
# check confirm of SO correctly created new registrations with information coming from SO
|
|
self.assertEqual(len(self.event_0.registration_ids), 6) # 3 for each ticket now
|
|
new_registrations = self.event_0.registration_ids - (ticket1_reg1 | ticket1_new_reg | ticket2_new_reg)
|
|
self.assertEqual(new_registrations.event_ticket_id, ticket2)
|
|
self.assertEqual(new_registrations.partner_id, self.customer_so.partner_id)
|
|
|
|
self.assertEqual(editor_action['type'], 'ir.actions.act_window')
|
|
self.assertEqual(editor_action['res_model'], 'registration.editor')
|
|
|
|
@users('user_sales_salesman')
|
|
def test_event_sale_free_confirm(self):
|
|
"""Check that free registrations are immediately
|
|
confirmed if the seats are available.
|
|
"""
|
|
TICKET_COUNT = 3
|
|
customer_so = self.customer_so.with_user(self.env.user)
|
|
ticket = self.event_0.event_ticket_ids[0]
|
|
|
|
# Limiting seats
|
|
self.event_0.write({
|
|
"seats_limited": True,
|
|
"seats_max": 5
|
|
})
|
|
|
|
customer_so.write({
|
|
'order_line': [
|
|
(0, 0, {
|
|
'event_id': self.event_0.id,
|
|
'event_ticket_id': ticket.id,
|
|
'product_id': ticket.product_id.id,
|
|
'product_uom_qty': TICKET_COUNT,
|
|
'price_unit': 0,
|
|
})
|
|
]
|
|
})
|
|
|
|
editor = self.env['registration.editor'].with_context({
|
|
'default_sale_order_id': customer_so.id
|
|
}).create({})
|
|
|
|
editor.action_make_registration()
|
|
self.assertEqual(len(self.event_0.registration_ids), TICKET_COUNT)
|
|
self.assertTrue(all(reg.state == "open" for reg in self.event_0.registration_ids))
|
|
|
|
@users('user_sales_salesman')
|
|
def test_event_sale_free_full_event_no_confirm(self):
|
|
"""Check that even free registrations are not confirmed if there are not
|
|
enough seats available for the event.
|
|
"""
|
|
TICKET_COUNT = 3
|
|
customer_so = self.customer_so.with_user(self.env.user)
|
|
ticket = self.event_0.event_ticket_ids[0]
|
|
|
|
# Limiting event seats
|
|
self.event_0.write({
|
|
"seats_limited": True,
|
|
"seats_max": 2
|
|
})
|
|
|
|
# adding too many tickets to SO in two different lines
|
|
customer_so.write({
|
|
'order_line': [
|
|
(0, 0, {
|
|
'event_id': self.event_0.id,
|
|
'event_ticket_id': ticket.id,
|
|
'product_id': ticket.product_id.id,
|
|
'product_uom_qty': TICKET_COUNT - 1,
|
|
'price_unit': 0,
|
|
}),
|
|
(0, 0, {
|
|
'event_id': self.event_0.id,
|
|
'event_ticket_id': ticket.id,
|
|
'product_id': ticket.product_id.id,
|
|
'product_uom_qty': 1,
|
|
'price_unit': 0,
|
|
})
|
|
]
|
|
})
|
|
|
|
# Confirming the SO will raise an error if there is not enough seats
|
|
with self.assertRaises(ValidationError):
|
|
customer_so.action_confirm()
|
|
|
|
editor = self.env['registration.editor'].with_context({
|
|
'default_sale_order_id': customer_so.id
|
|
}).create({})
|
|
|
|
with self.assertRaises(ValidationError):
|
|
editor.action_make_registration()
|
|
|
|
@users('user_sales_salesman')
|
|
def test_event_sale_free_full_ticket_no_confirm(self):
|
|
"""Check that even free registrations are not confirmed if there are not enough
|
|
seats available for the requested tickets.
|
|
"""
|
|
TICKET_COUNT = 3
|
|
customer_so = self.customer_so.with_user(self.env.user)
|
|
ticket = self.event_0.event_ticket_ids[0]
|
|
|
|
# Limiting ticket seats
|
|
ticket.write({
|
|
"seats_limited": True,
|
|
"seats_max": 2,
|
|
})
|
|
# adding too many tickets to SO in two different lines
|
|
customer_so.write({
|
|
'order_line': [
|
|
(0, 0, {
|
|
'event_id': self.event_0.id,
|
|
'event_ticket_id': ticket.id,
|
|
'product_id': ticket.product_id.id,
|
|
'product_uom_qty': TICKET_COUNT - 1,
|
|
'price_unit': 0,
|
|
}),
|
|
(0, 0, {
|
|
'event_id': self.event_0.id,
|
|
'event_ticket_id': ticket.id,
|
|
'product_id': ticket.product_id.id,
|
|
'product_uom_qty': 1,
|
|
'price_unit': 0,
|
|
})
|
|
]
|
|
})
|
|
|
|
# Confirming the SO will raise an error if there is not enough seats
|
|
with self.assertRaises(ValidationError):
|
|
customer_so.action_confirm()
|
|
|
|
editor = self.env['registration.editor'].with_context({
|
|
'default_sale_order_id': customer_so.id
|
|
}).create({})
|
|
|
|
with self.assertRaises(ValidationError):
|
|
editor.action_make_registration()
|
|
|
|
def test_ticket_price_with_currency_conversion(self):
|
|
def _prepare_currency(self, currency_name):
|
|
currency = self.env['res.currency'].with_context(active_test=False).search(
|
|
[('name', '=', currency_name)]
|
|
)
|
|
currency.action_unarchive()
|
|
return currency
|
|
|
|
currency_VEF = _prepare_currency(self, 'VEF')
|
|
currency_USD = _prepare_currency(self, 'USD')
|
|
|
|
company_test = self.env['res.company'].create({
|
|
'name': 'TestCompany',
|
|
'country_id': self.env.ref('base.be').id,
|
|
'currency_id': currency_USD.id,
|
|
})
|
|
self.env.user.company_ids += company_test
|
|
self.env.user.company_id = company_test
|
|
|
|
pricelist_USD = self.env['product.pricelist'].create({
|
|
'name': 'pricelist_USD',
|
|
'currency_id': currency_USD.id,
|
|
})
|
|
pricelist_VEF = self.env['product.pricelist'].create({
|
|
'name': 'pricelist_VEF',
|
|
'currency_id': currency_VEF.id,
|
|
})
|
|
|
|
event_product = self.env['product.template'].create({
|
|
'name': 'Event Product',
|
|
'list_price': 10.0,
|
|
'taxes_id': False,
|
|
})
|
|
|
|
event = self.env['event.event'].create({
|
|
'name': 'New Event',
|
|
'date_begin': '2020-02-02',
|
|
'date_end': '2020-04-04',
|
|
})
|
|
event_ticket = self.env['event.event.ticket'].create({
|
|
'name': 'VIP',
|
|
'price': 1000.0,
|
|
'event_id': event.id,
|
|
'product_id': event_product.product_variant_id.id,
|
|
})
|
|
|
|
so = self.env['sale.order'].create({
|
|
'partner_id': self.env.user.partner_id.id,
|
|
'pricelist_id': pricelist_USD.id,
|
|
})
|
|
self.env['sale.order.line'].create({
|
|
'product_id': event_product.product_variant_id.id,
|
|
'order_id': so.id,
|
|
'event_id': event.id,
|
|
'event_ticket_id': event_ticket.id,
|
|
})
|
|
self.assertEqual(so.amount_total, event_ticket.price)
|
|
|
|
so.pricelist_id = pricelist_VEF
|
|
so.action_update_prices()
|
|
|
|
self.assertAlmostEqual(
|
|
so.amount_total,
|
|
currency_USD._convert(
|
|
event_ticket.price, currency_VEF, self.env.user.company_id, so.date_order
|
|
),
|
|
delta=1,
|
|
)
|
|
|
|
def test_ticket_price_with_pricelist_and_tax(self):
|
|
self.env.user.partner_id.country_id = False
|
|
pricelist = self.env['product.pricelist'].create({'name': 'Base Pricelist'})
|
|
|
|
tax = self.env['account.tax'].create({
|
|
'name': "Tax 10",
|
|
'amount': 10,
|
|
})
|
|
|
|
event_product = self.env['product.template'].create({
|
|
'name': 'Event Product',
|
|
'list_price': 10.0,
|
|
})
|
|
|
|
event_product.taxes_id = tax
|
|
|
|
event = self.env['event.event'].create({
|
|
'name': 'New Event',
|
|
'date_begin': '2020-02-02',
|
|
'date_end': '2020-04-04',
|
|
})
|
|
event_ticket = self.env['event.event.ticket'].create({
|
|
'name': 'VIP',
|
|
'price': 1000.0,
|
|
'event_id': event.id,
|
|
'product_id': event_product.product_variant_id.id,
|
|
})
|
|
|
|
pricelist.item_ids = self.env['product.pricelist.item'].create({
|
|
'applied_on': "1_product",
|
|
'base': "list_price",
|
|
'compute_price': "fixed",
|
|
'fixed_price': 6.0,
|
|
'product_tmpl_id': event_product.id,
|
|
})
|
|
|
|
pricelist.discount_policy = 'without_discount'
|
|
|
|
so = self.env['sale.order'].create({
|
|
'partner_id': self.env.user.partner_id.id,
|
|
'pricelist_id': pricelist.id,
|
|
})
|
|
sol = self.env['sale.order.line'].create({
|
|
'product_id': event_product.product_variant_id.id,
|
|
'order_id': so.id,
|
|
'event_id': event.id,
|
|
'event_ticket_id': event_ticket.id,
|
|
})
|
|
self.assertEqual(so.amount_total, 660.0, "Ticket is $1000 but the event product is on a pricelist 10 -> 6. So, $600 + a 10% tax.")
|
|
|
|
@users('user_salesman')
|
|
def test_unlink_so(self):
|
|
""" This test ensures that when deleting a sale order, if the latter is linked to an event registration,
|
|
it is also deleted """
|
|
event = self.env['event.event'].browse(self.event_0.ids)
|
|
self.register_person.action_make_registration()
|
|
self.assertEqual(len(event.registration_ids), 1)
|
|
self.sale_order.unlink()
|
|
self.assertEqual(len(event.registration_ids), 0)
|
|
|
|
@users('user_salesman')
|
|
def test_unlink_soline(self):
|
|
""" This test ensures that when deleting a sale order line, if the latter is linked to an event registration,
|
|
it is also deleted """
|
|
event = self.env['event.event'].browse(self.event_0.ids)
|
|
self.register_person.action_make_registration()
|
|
self.assertEqual(len(event.registration_ids), 1)
|
|
self.sale_order.order_line.unlink()
|
|
self.assertEqual(len(event.registration_ids), 0)
|
|
|
|
@users('user_salesman')
|
|
def test_cancel_so(self):
|
|
""" This test ensures that when canceling a sale order, if the latter is linked to an event registration,
|
|
it is also cancelled """
|
|
event = self.env['event.event'].browse(self.event_0.ids)
|
|
self.register_person.action_make_registration()
|
|
self.assertEqual(len(event.registration_ids), 1)
|
|
self.sale_order._action_cancel()
|
|
self.assertEqual(len(event.registration_ids), 1)
|
|
self.assertEqual(event.registration_ids.state, 'cancel')
|