mirror of
https://gitlab.com/flectra-hq/flectra.git
synced 2026-10-24 23:17:39 -05:00
[PATCH] Upstream patch - 01052022
This commit is contained in:
1 parent
6e0a013fee
commit
ec3e63c643
18 files changed
+309
-27
No files matched your search
@@ -621,7 +621,11 @@ class AccountPaymentRegister(models.TransientModel):
|
||||
to which a payment will be created (see '_get_batches').
|
||||
:param edit_mode: Is the wizard in edition mode.
|
||||
"""
|
||||
domain = [('account_internal_type', 'in', ('receivable', 'payable')), ('reconciled', '=', False)]
|
||||
domain = [
|
||||
('parent_state', '=', 'posted'),
|
||||
('account_internal_type', 'in', ('receivable', 'payable')),
|
||||
('reconciled', '=', False),
|
||||
]
|
||||
for vals in to_process:
|
||||
payment_lines = vals['payment'].line_ids.filtered_domain(domain)
|
||||
lines = vals['to_reconcile']
|
||||
|
||||
@@ -37,7 +37,7 @@ class MailTemplate(models.Model):
|
||||
isr_pdf = base64.b64encode(isr_pdf)
|
||||
new_attachments.append((isr_report_name, isr_pdf))
|
||||
|
||||
if record.partner_bank_id._eligible_for_qr_code('ch_qr', record.partner_id, record.currency_id):
|
||||
if record.move_type == 'out_invoice' and record.partner_bank_id._eligible_for_qr_code('ch_qr', record.partner_id, record.currency_id):
|
||||
# We add an attachment containing the QR-bill
|
||||
qr_report_name = 'QR-bill-' + inv_print_name + '.pdf'
|
||||
qr_pdf = self.env.ref('l10n_ch.l10n_ch_qr_report')._render_qweb_pdf(record.ids)[0]
|
||||
|
||||
@@ -206,7 +206,7 @@ class ReportBomStructure(models.AbstractModel):
|
||||
else:
|
||||
prod_qty = line.product_qty * factor / bom.product_qty
|
||||
company = bom.company_id or self.env.company
|
||||
not_rounded_price = line.product_id.uom_id._compute_price(line.product_id.with_context(force_comany=company.id).standard_price, line.product_uom_id) * prod_qty
|
||||
not_rounded_price = line.product_id.uom_id._compute_price(line.product_id.with_company(company).standard_price, line.product_uom_id) * prod_qty
|
||||
price += company.currency_id.round(not_rounded_price)
|
||||
return price
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ class ProductAttribute(models.Model):
|
||||
@api.depends('attribute_line_ids.active', 'attribute_line_ids.product_tmpl_id')
|
||||
def _compute_products(self):
|
||||
for pa in self:
|
||||
pa.product_tmpl_ids = pa.attribute_line_ids.product_tmpl_id
|
||||
pa.with_context(active_test=False).product_tmpl_ids = pa.attribute_line_ids.product_tmpl_id
|
||||
|
||||
def _without_no_variant_attributes(self):
|
||||
return self.filtered(lambda pa: pa.create_variant != 'no_variant')
|
||||
|
||||
@@ -465,7 +465,6 @@ class ProductTemplate(models.Model):
|
||||
|
||||
Product = self.env['product.product']
|
||||
templates = self.browse([])
|
||||
domain_no_variant = [('product_variant_ids', '=', False)]
|
||||
while True:
|
||||
domain = templates and [('product_tmpl_id', 'not in', templates.ids)] or []
|
||||
args = args if args is not None else []
|
||||
@@ -480,13 +479,7 @@ class ProductTemplate(models.Model):
|
||||
If this happens, an infinite loop will occur."""
|
||||
break
|
||||
templates |= new_templates
|
||||
current_round_templates = self.browse([])
|
||||
if not products:
|
||||
domain_template = args + domain_no_variant + (templates and [('id', 'not in', templates.ids)] or [])
|
||||
template_ids = super(ProductTemplate, self)._name_search(name=name, args=domain_template, operator=operator, limit=limit, name_get_uid=name_get_uid)
|
||||
current_round_templates |= self.browse(template_ids)
|
||||
templates |= current_round_templates
|
||||
if (not products and not current_round_templates) or (limit and (len(templates) > limit)):
|
||||
if (not products) or (limit and (len(templates) > limit)):
|
||||
break
|
||||
|
||||
searched_ids = set(templates.ids)
|
||||
@@ -494,10 +487,16 @@ class ProductTemplate(models.Model):
|
||||
# we need to add the base _name_search to the results
|
||||
# FIXME awa: this is really not performant at all but after discussing with the team
|
||||
# we don't see another way to do it
|
||||
tmpl_without_variant_ids = []
|
||||
if not limit or len(searched_ids) < limit:
|
||||
tmpl_without_variant_ids = self.env['product.template'].search(
|
||||
[('id', 'not in', self.env['product.template']._search([('product_variant_ids.active', '=', True)]))]
|
||||
)
|
||||
if tmpl_without_variant_ids:
|
||||
domain = expression.AND([args or [], [('id', 'in', tmpl_without_variant_ids.ids)]])
|
||||
searched_ids |= set(super(ProductTemplate, self)._name_search(
|
||||
name,
|
||||
args=args,
|
||||
args=domain,
|
||||
operator=operator,
|
||||
limit=limit,
|
||||
name_get_uid=name_get_uid))
|
||||
|
||||
@@ -22,3 +22,8 @@ class TestName(TransactionCase):
|
||||
display_name = self.product.with_context(display_default_code=False).display_name
|
||||
self.assertEqual(display_name, self.product_name,
|
||||
"Code should not be preprended to the name as context should prevent it.")
|
||||
|
||||
def test_default_code_and_negative_operator(self):
|
||||
res = self.env['product.template'].name_search(name='PTN', operator='not ilike')
|
||||
res_ids = [r[0] for r in res]
|
||||
self.assertNotIn(self.product.id, res_ids)
|
||||
@@ -665,3 +665,34 @@ class TestProductAttributeValueConfig(TestProductAttributeValueCommon):
|
||||
'name': '32 GB',
|
||||
'attribute_id': self.ram_attribute.id,
|
||||
})
|
||||
|
||||
def test_inactive_related_product_update(self):
|
||||
"""
|
||||
Create a product and give it a product attribute then archive it, delete the product attribute,
|
||||
unarchive the product and check that the product is not related to the product attribute.
|
||||
"""
|
||||
product_attribut = self.env['product.attribute'].create({
|
||||
'name': 'PA',
|
||||
'sequence': 1,
|
||||
'create_variant': 'no_variant',
|
||||
})
|
||||
a1 = self.env['product.attribute.value'].create({
|
||||
'name': 'pa_value',
|
||||
'attribute_id': product_attribut.id,
|
||||
'sequence': 1,
|
||||
})
|
||||
product = self.env['product.template'].create({
|
||||
'name': 'P1',
|
||||
'type': 'product',
|
||||
'attribute_line_ids': [(0, 0, {
|
||||
'attribute_id': product_attribut.id,
|
||||
'value_ids': [(6, 0, [a1.id])],
|
||||
})]
|
||||
})
|
||||
self.assertTrue(product_attribut.is_used_on_products, 'The product attribute must have an associated product')
|
||||
product.action_archive()
|
||||
self.assertFalse(product.active, 'The product should be archived.')
|
||||
product.write({'attribute_line_ids': [[5, 0, 0]]})
|
||||
product.action_unarchive()
|
||||
self.assertTrue(product.active, 'The product should be unarchived.')
|
||||
self.assertFalse(product_attribut.is_used_on_products, 'The product attribute must not have an associated product')
|
||||
@@ -132,6 +132,9 @@ class SaleOrder(models.Model):
|
||||
else:
|
||||
return fixed_amount
|
||||
|
||||
def _get_coupon_program_domain(self):
|
||||
return []
|
||||
|
||||
def _get_cheapest_line(self):
|
||||
# Unit prices tax included
|
||||
return min(self.order_line.filtered(lambda x: not x.is_reward_line and x.price_reduce > 0), key=lambda x: x['price_reduce'])
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from flectra import api, fields, models, _
|
||||
from flectra.exceptions import UserError
|
||||
from flectra.osv import expression
|
||||
|
||||
|
||||
class SaleCouponApplyCode(models.TransientModel):
|
||||
@@ -24,7 +25,9 @@ class SaleCouponApplyCode(models.TransientModel):
|
||||
|
||||
def apply_coupon(self, order, coupon_code):
|
||||
error_status = {}
|
||||
program = self.env['coupon.program'].search([('promo_code', '=', coupon_code)])
|
||||
program_domain = order._get_coupon_program_domain()
|
||||
program_domain = expression.AND([program_domain, [('promo_code', '=', coupon_code)]])
|
||||
program = self.env['coupon.program'].search(program_domain)
|
||||
if program:
|
||||
error_status = program._check_promo_code(order, coupon_code)
|
||||
if not error_status:
|
||||
|
||||
@@ -409,8 +409,9 @@ class StockWarehouseOrderpoint(models.Model):
|
||||
orderpoints = self.env['stock.warehouse.orderpoint'].with_user(SUPERUSER_ID).create(orderpoint_values_list)
|
||||
for orderpoint in orderpoints:
|
||||
orderpoint_wh = orderpoint.location_id.get_warehouse()
|
||||
orderpoint.route_id = next((r for r in orderpoint.product_id.route_ids if not r.supplied_wh_id or r.supplied_wh_id == orderpoint_wh), None) \
|
||||
or orderpoint._set_default_route_id()
|
||||
orderpoint.route_id = next((r for r in orderpoint.product_id.route_ids if not r.supplied_wh_id or r.supplied_wh_id == orderpoint_wh), orderpoint.route_id)
|
||||
if not orderpoint.route_id:
|
||||
orderpoint._set_default_route_id()
|
||||
return action
|
||||
|
||||
@api.model
|
||||
|
||||
@@ -115,3 +115,63 @@ class TestVirtualAvailable(TestStockCommon):
|
||||
('id', 'in', product.ids),
|
||||
])
|
||||
self.assertEqual(product, result)
|
||||
|
||||
def test_search_product_template(self):
|
||||
"""
|
||||
Suppose a variant V01 that can not be deleted because it is used by a
|
||||
lot [1]. Then, the variant's template T is changed: we add a dynamic
|
||||
attribute. Because of [1], V01 is archived. This test ensures that
|
||||
`name_search` still finds T.
|
||||
Then, we create a new variant V02 of T. This test also ensures that
|
||||
calling `name_search` with a negative operator will exclude T from the
|
||||
result.
|
||||
"""
|
||||
template = self.env['product.template'].create({
|
||||
'name': 'Super Product',
|
||||
})
|
||||
product01 = template.product_variant_id
|
||||
|
||||
self.env['stock.production.lot'].create({
|
||||
'name': 'lot1',
|
||||
'product_id': product01.id,
|
||||
'company_id': self.env.company.id,
|
||||
})
|
||||
|
||||
product_attribute = self.env['product.attribute'].create({
|
||||
'name': 'PA',
|
||||
'create_variant': 'dynamic'
|
||||
})
|
||||
|
||||
self.env['product.attribute.value'].create([{
|
||||
'name': 'PAV' + str(i),
|
||||
'attribute_id': product_attribute.id
|
||||
} for i in range(2)])
|
||||
|
||||
tmpl_attr_lines = self.env['product.template.attribute.line'].create({
|
||||
'attribute_id': product_attribute.id,
|
||||
'product_tmpl_id': product01.product_tmpl_id.id,
|
||||
'value_ids': [(6, 0, product_attribute.value_ids.ids)],
|
||||
})
|
||||
|
||||
self.assertFalse(product01.active)
|
||||
self.assertTrue(template.active)
|
||||
self.assertFalse(template.product_variant_ids)
|
||||
|
||||
res = self.env['product.template'].name_search(name='super', operator='ilike')
|
||||
res_ids = [r[0] for r in res]
|
||||
self.assertIn(template.id, res_ids)
|
||||
|
||||
product02 = self.env['product.product'].create({
|
||||
'default_code': '123',
|
||||
'product_tmpl_id': template.id,
|
||||
'product_template_attribute_value_ids': [(6, 0, tmpl_attr_lines.product_template_value_ids[0].ids)]
|
||||
})
|
||||
|
||||
self.assertFalse(product01.active)
|
||||
self.assertTrue(product02.active)
|
||||
self.assertTrue(template)
|
||||
self.assertEqual(template.product_variant_ids, product02)
|
||||
|
||||
res = self.env['product.template'].name_search(name='123', operator='not ilike')
|
||||
res_ids = [r[0] for r in res]
|
||||
self.assertNotIn(template.id, res_ids)
|
||||
@@ -156,9 +156,11 @@ class ProductProduct(models.Model):
|
||||
:rtype: dict
|
||||
"""
|
||||
self.ensure_one()
|
||||
company_id = self.env.context.get('force_company', self.env.company.id)
|
||||
company = self.env['res.company'].browse(company_id)
|
||||
vals = {
|
||||
'product_id': self.id,
|
||||
'value': unit_cost * quantity,
|
||||
'value': company.currency_id.round(unit_cost * quantity),
|
||||
'unit_cost': unit_cost,
|
||||
'quantity': quantity,
|
||||
}
|
||||
@@ -175,11 +177,14 @@ class ProductProduct(models.Model):
|
||||
:rtype: dict
|
||||
"""
|
||||
self.ensure_one()
|
||||
company_id = self.env.context.get('force_company', self.env.company.id)
|
||||
company = self.env['res.company'].browse(company_id)
|
||||
currency = company.currency_id
|
||||
# Quantity is negative for out valuation layers.
|
||||
quantity = -1 * quantity
|
||||
vals = {
|
||||
'product_id': self.id,
|
||||
'value': quantity * self.standard_price,
|
||||
'value': currency.round(quantity * self.standard_price),
|
||||
'unit_cost': self.standard_price,
|
||||
'quantity': quantity,
|
||||
}
|
||||
@@ -188,7 +193,6 @@ class ProductProduct(models.Model):
|
||||
vals['remaining_qty'] = fifo_vals.get('remaining_qty')
|
||||
# In case of AVCO, fix rounding issue of standard price when needed.
|
||||
if self.cost_method == 'average':
|
||||
currency = self.env.company.currency_id
|
||||
rounding_error = currency.round(self.standard_price * self.quantity_svl - self.value_svl)
|
||||
if rounding_error:
|
||||
# If it is bigger than the (smallest number of the currency * quantity) / 2,
|
||||
|
||||
@@ -29,19 +29,21 @@ class TestStockValuationCommon(SavepointCase):
|
||||
# Counter automatically incremented by `_make_in_move` and `_make_out_move`.
|
||||
self.days = 0
|
||||
|
||||
def _make_in_move(self, product, quantity, unit_cost=None, create_picking=False):
|
||||
def _make_in_move(self, product, quantity, unit_cost=None, create_picking=False, loc_dest=None, pick_type=None):
|
||||
""" Helper to create and validate a receipt move.
|
||||
"""
|
||||
unit_cost = unit_cost or product.standard_price
|
||||
loc_dest = loc_dest or self.stock_location
|
||||
pick_type = pick_type or self.picking_type_in
|
||||
in_move = self.env['stock.move'].create({
|
||||
'name': 'in %s units @ %s per unit' % (str(quantity), str(unit_cost)),
|
||||
'product_id': product.id,
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'location_dest_id': loc_dest.id,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': quantity,
|
||||
'price_unit': unit_cost,
|
||||
'picking_type_id': self.picking_type_in.id,
|
||||
'picking_type_id': pick_type.id,
|
||||
})
|
||||
|
||||
if create_picking:
|
||||
@@ -60,17 +62,19 @@ class TestStockValuationCommon(SavepointCase):
|
||||
self.days += 1
|
||||
return in_move.with_context(svl=True)
|
||||
|
||||
def _make_out_move(self, product, quantity, force_assign=None, create_picking=False):
|
||||
def _make_out_move(self, product, quantity, force_assign=None, create_picking=False, loc_src=None, pick_type=None):
|
||||
""" Helper to create and validate a delivery move.
|
||||
"""
|
||||
loc_src = loc_src or self.stock_location
|
||||
pick_type = pick_type or self.picking_type_out
|
||||
out_move = self.env['stock.move'].create({
|
||||
'name': 'out %s units' % str(quantity),
|
||||
'product_id': product.id,
|
||||
'location_id': self.stock_location.id,
|
||||
'location_id': loc_src.id,
|
||||
'location_dest_id': self.customer_location.id,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': quantity,
|
||||
'picking_type_id': self.picking_type_out.id,
|
||||
'picking_type_id': pick_type.id,
|
||||
})
|
||||
|
||||
if create_picking:
|
||||
@@ -299,6 +303,30 @@ class TestStockValuationStandard(TestStockValuationCommon):
|
||||
self.assertTrue(product2.stock_valuation_layer_ids)
|
||||
self.assertFalse(product1.stock_valuation_layer_ids)
|
||||
|
||||
def test_currency_precision_and_standard_svl_value(self):
|
||||
currency = self.env['res.currency'].create({
|
||||
'name': 'Flectra',
|
||||
'symbol': 'O',
|
||||
'rounding': 1,
|
||||
})
|
||||
new_company = self.env['res.company'].create({
|
||||
'name': 'Super Company',
|
||||
'currency_id': currency.id,
|
||||
})
|
||||
|
||||
old_company = self.env.user.company_id
|
||||
try:
|
||||
self.env.user.company_id = new_company
|
||||
warehouse = self.env['stock.warehouse'].search([('company_id', '=', new_company.id)])
|
||||
product = self.product1.with_company(new_company)
|
||||
product.standard_price = 3
|
||||
|
||||
self._make_in_move(product, 0.5, loc_dest=warehouse.lot_stock_id, pick_type=warehouse.in_type_id)
|
||||
self._make_out_move(product, 0.5, loc_src=warehouse.lot_stock_id, pick_type=warehouse.out_type_id)
|
||||
|
||||
self.assertEqual(product.value_svl, 0.0)
|
||||
finally:
|
||||
self.env.user.company_id = old_company
|
||||
|
||||
class TestStockValuationAVCO(TestStockValuationCommon):
|
||||
def setUp(self):
|
||||
@@ -704,6 +732,31 @@ class TestStockValuationFIFO(TestStockValuationCommon):
|
||||
self.assertEqual(self.product1.value_svl, 20)
|
||||
self.assertEqual(self.product1.quantity_svl, 10)
|
||||
|
||||
def test_currency_precision_and_fifo_svl_value(self):
|
||||
currency = self.env['res.currency'].create({
|
||||
'name': 'Flectra',
|
||||
'symbol': 'O',
|
||||
'rounding': 1,
|
||||
})
|
||||
new_company = self.env['res.company'].create({
|
||||
'name': 'Super Company',
|
||||
'currency_id': currency.id,
|
||||
})
|
||||
|
||||
old_company = self.env.user.company_id
|
||||
try:
|
||||
self.env.user.company_id = new_company
|
||||
product = self.product1.with_company(new_company)
|
||||
product.product_tmpl_id.categ_id.property_cost_method = 'fifo'
|
||||
warehouse = self.env['stock.warehouse'].search([('company_id', '=', new_company.id)])
|
||||
|
||||
self._make_in_move(product, 0.5, loc_dest=warehouse.lot_stock_id, pick_type=warehouse.in_type_id, unit_cost=3)
|
||||
self._make_out_move(product, 0.5, loc_src=warehouse.lot_stock_id, pick_type=warehouse.out_type_id)
|
||||
|
||||
self.assertEqual(product.value_svl, 0.0)
|
||||
finally:
|
||||
self.env.user.company_id = old_company
|
||||
|
||||
|
||||
class TestStockValuationChangeCostMethod(TestStockValuationCommon):
|
||||
def test_standard_to_fifo_1(self):
|
||||
|
||||
@@ -81,13 +81,14 @@ class SaleOrder(models.Model):
|
||||
|
||||
# case: buying tickets for a sold out ticket
|
||||
values = {}
|
||||
if ticket and ticket.seats_limited and ticket.seats_available <= 0:
|
||||
increased_quantity = new_qty > old_qty
|
||||
if ticket and ticket.seats_limited and ticket.seats_available <= 0 and increased_quantity:
|
||||
values['warning'] = _('Sorry, The %(ticket)s tickets for the %(event)s event are sold out.') % {
|
||||
'ticket': ticket.name,
|
||||
'event': ticket.event_id.name}
|
||||
new_qty, set_qty, add_qty = 0, 0, -old_qty
|
||||
# case: buying tickets, too much attendees
|
||||
elif ticket and ticket.seats_limited and new_qty > ticket.seats_available:
|
||||
elif ticket and ticket.seats_limited and new_qty > ticket.seats_available and increased_quantity:
|
||||
values['warning'] = _('Sorry, only %(remaining_seats)d seats are still available for the %(ticket)s ticket for the %(event)s event.') % {
|
||||
'remaining_seats': ticket.seats_available,
|
||||
'ticket': ticket.name,
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
flectra.define('website_event_sale.tour.last_ticket', function (require) {
|
||||
'use strict';
|
||||
|
||||
var tour = require('web_tour.tour');
|
||||
|
||||
tour.register('event_buy_last_ticket', {
|
||||
test: true,
|
||||
url: '/event',
|
||||
},[{
|
||||
content: "Open the Last ticket test event page",
|
||||
trigger: '.o_wevent_events_list a:contains("Last ticket test")',
|
||||
},
|
||||
{
|
||||
content: "Show available Tickets",
|
||||
trigger: '.btn-primary:contains("Register")',
|
||||
},
|
||||
{
|
||||
content: "Select 2 units of `VIP` ticket type",
|
||||
extra_trigger: '#wrap:not(:has(a[href*="/event"]:contains("Last ticket test")))',
|
||||
trigger: 'select:eq(0)',
|
||||
run: 'text 2',
|
||||
},
|
||||
{
|
||||
content: "Click on `Order Now` button",
|
||||
extra_trigger: 'select:eq(0):has(option:contains(2):propSelected)',
|
||||
trigger: '.a-submit:contains("Register")',
|
||||
},
|
||||
{
|
||||
content: "Fill attendees details",
|
||||
trigger: 'form[id="attendee_registration"] .btn:contains("Continue")',
|
||||
run: function () {
|
||||
$("input[name='1-name']").val("Att1");
|
||||
$("input[name='1-phone']").val("111 111");
|
||||
$("input[name='1-email']").val("att1@example.com");
|
||||
$("input[name='2-name']").val("Att2");
|
||||
$("input[name='2-phone']").val("222 222");
|
||||
$("input[name='2-email']").val("att2@example.com");
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "Validate attendees details",
|
||||
extra_trigger: "input[name='1-name'], input[name='2-name']",
|
||||
trigger: 'button:contains("Continue")',
|
||||
},
|
||||
{
|
||||
content: "Fill address",
|
||||
trigger: 'form.checkout_autoformat',
|
||||
run: function () {
|
||||
$("input[name='name']").val("test1");
|
||||
$("input[name='email']").val("test@example.com");
|
||||
$("input[name='phone']").val("111 111");
|
||||
$("input[name='street']").val("street test 1");
|
||||
$("input[name='city']").val("testCity");
|
||||
$("input[name='zip']").val("123");
|
||||
$('#country_id option:eq(1)').attr('selected', true);
|
||||
},
|
||||
},
|
||||
{
|
||||
content: "Validate address",
|
||||
trigger: '.btn-primary:contains("Next")',
|
||||
},
|
||||
{
|
||||
// if the seats_available checking logic is not correct,
|
||||
// the shopping cart will be cleared when selling the last ticket
|
||||
// the tour test will be failed here
|
||||
content: "Select `Wire Transfer` payment method",
|
||||
trigger: '#payment_method label:contains("Wire Transfer")',
|
||||
},
|
||||
// following steps are based on the website_sale_buy.js
|
||||
{
|
||||
content: "Pay",
|
||||
//Either there are multiple payment methods, and one is checked, either there is only one, and therefore there are no radio inputs
|
||||
extra_trigger: '#payment_method label:contains("Wire Transfer") input:checked,#payment_method:not(:has("input:radio:visible"))',
|
||||
trigger: 'button[id="o_payment_form_pay"]:visible',
|
||||
},
|
||||
{
|
||||
content: "payment finish",
|
||||
trigger: '.oe_website_sale:contains("Please make a payment to:")',
|
||||
// Leave /shop/confirmation to prevent RPC loop to /shop/payment/get_status.
|
||||
// The RPC could be handled in python while the tour is killed (and the session), leading to crashes
|
||||
run: function () {
|
||||
window.location.href = '/contactus'; // Redirect in JS to avoid the RPC loop (20x1sec)
|
||||
},
|
||||
timeout: 30000,
|
||||
},
|
||||
{
|
||||
content: "wait page loaded",
|
||||
trigger: 'h1:contains("Contact us")',
|
||||
run: function () {}, // it's a check
|
||||
},
|
||||
]);
|
||||
});
|
||||
@@ -37,8 +37,27 @@ class TestUi(HttpCaseWithUserDemo):
|
||||
'price': 1500.0,
|
||||
}])
|
||||
|
||||
self.event_3 = self.env['event.event'].create({
|
||||
'name': 'Last ticket test',
|
||||
'user_id': self.env.ref('base.user_admin').id,
|
||||
'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'),
|
||||
'website_published': True,
|
||||
})
|
||||
|
||||
self.env['event.event.ticket'].create([{
|
||||
'name': 'VIP',
|
||||
'event_id': self.event_3.id,
|
||||
'product_id': self.env.ref('event_sale.product_product_event').id,
|
||||
'end_sale_date': (Datetime.today() + timedelta(90)).strftime('%Y-%m-%d'),
|
||||
'price': 1500.0,
|
||||
'seats_max': 2,
|
||||
}])
|
||||
|
||||
|
||||
# flush event to ensure having tickets available in the tests
|
||||
self.event_2.flush()
|
||||
self.event_3.flush()
|
||||
|
||||
(self.env.ref('base.partner_admin') + self.partner_demo).write({
|
||||
'street': '215 Vine St',
|
||||
@@ -66,4 +85,7 @@ class TestUi(HttpCaseWithUserDemo):
|
||||
def test_demo(self):
|
||||
self.start_tour("/", 'event_buy_tickets', login="demo")
|
||||
|
||||
def test_buy_last_ticket(self):
|
||||
self.start_tour("/", 'event_buy_last_ticket')
|
||||
|
||||
# TO DO - add public test with new address when convert to web.tour format.
|
||||
@@ -4,6 +4,7 @@
|
||||
<template id="assets_tests" inherit_id="web.assets_tests" name="Website Event Sale Assets Tests">
|
||||
<xpath expr="." position="inside">
|
||||
<script type="text/javascript" src="/website_event_sale/static/tests/tours/website_event_sale.js"></script>
|
||||
<script type="text/javascript" src="/website_event_sale/static/tests/tours/website_event_sale_last_ticket.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -64,6 +64,9 @@ class SaleOrder(models.Model):
|
||||
request.session.pop('error_promo_code')
|
||||
return error
|
||||
|
||||
def _get_coupon_program_domain(self):
|
||||
return [('website_id', 'in', [False, self.website_id.id])]
|
||||
|
||||
def _cart_update(self, product_id=None, line_id=None, add_qty=0, set_qty=0, **kwargs):
|
||||
res = super(SaleOrder, self)._cart_update(product_id=product_id, line_id=line_id, add_qty=add_qty, set_qty=set_qty, **kwargs)
|
||||
self.recompute_coupon_lines()
|
||||
|
||||
Reference in new issue
Block a user