Skip to content

Commit d80b348

Browse files
committed
[FIX] pos_self_order: reordered the orderlines in create_order
Steps to reproduce: - Install pos_restaurant - Activate self order to the restaurant you have - Go to the mobile menu and order at least 2 combos - Go to the restaurant orders and select the created order Issue: Combo headers are displayed first, then combo children. Although they are linked correctly, the UI renders them in the order they are read from the database. Headers are created first, then children, as the child must be linked to the header. Now, lines are created in the order received from the frontend, and linkage is done after creation instead of on the fly in the create call. opw-4601833 closes odoo#203770 -co-authored: hyhevic <hyhe@odoo.com> Signed-off-by: David Monnom (moda) <moda@odoo.com>
1 parent 16a2c28 commit d80b348

5 files changed

Lines changed: 106 additions & 36 deletions

File tree

addons/point_of_sale/models/pos_order.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,10 @@ def _link_combo_items(self, order_vals):
167167
line_by_uuid = {line.uuid: line for line in self.lines.filtered_domain([("uuid", "in", [line['uuid'] for line in lines])])}
168168

169169
for line in lines:
170-
if line.get('combo_parent_id'):
171-
line_by_uuid[line['uuid']].combo_parent_id = line_by_uuid[uuid_by_cid[line['combo_parent_id']]]
170+
if not line.get('combo_parent_id'):
171+
continue
172+
idx = line['combo_parent_id'] if isinstance(line['combo_parent_id'], str) else uuid_by_cid[line['combo_parent_id']]
173+
line_by_uuid[line['uuid']].combo_parent_id = line_by_uuid[idx].id
172174

173175
def _process_saved_order(self, draft):
174176
self.ensure_one()

addons/pos_self_order/controllers/orders.py

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# -*- coding: utf-8 -*-
22
import re
33
import uuid
4+
from functools import partial
45
from datetime import timedelta
56
from odoo import http, fields, _
67
from odoo.http import request
@@ -60,36 +61,26 @@ def process_new_order(self, order, access_token, table_identifier, device_type):
6061
posted_order_id = pos_config.env['pos.order'].with_context(from_self=True).create_from_ui([order], draft=True)[0].get('id')
6162

6263
# Process the lines and get their prices computed
63-
lines = self._process_lines(lines, pos_config, posted_order_id, is_take_away)
64+
processed_lines = self._process_lines(lines, pos_config, posted_order_id, is_take_away)
6465

6566
# Compute the order prices
66-
amount_total, amount_untaxed = self._get_order_prices(lines)
67+
amount_total, amount_untaxed = self._get_order_prices(processed_lines)
6768

6869
# Update the order with the computed prices and lines
69-
order = pos_config.env["pos.order"].browse(posted_order_id)
70+
saved_order = pos_config.env["pos.order"].browse(posted_order_id)
71+
saved_lines = pos_config.env['pos.order.line'].with_user(pos_config.self_ordering_default_user_id).create(processed_lines)
7072

71-
classic_lines = []
72-
combo_lines = []
73-
for line in lines:
74-
if line["combo_parent_uuid"]:
75-
combo_lines.append(line)
76-
else:
77-
classic_lines.append(line)
78-
79-
# combo lines must be created after classic_line, as they need the classic line identifier
80-
# use user admin to avoid access rights issues
81-
lines = pos_config.env['pos.order.line'].with_user(pos_config.self_ordering_default_user_id).create(classic_lines)
82-
lines += pos_config.env['pos.order.line'].with_user(pos_config.self_ordering_default_user_id).create(combo_lines)
83-
84-
order.write({
85-
'lines': lines,
73+
saved_order.write({
74+
'lines': saved_lines,
8675
'state': 'paid' if amount_total == 0 else 'draft',
8776
'amount_tax': amount_total - amount_untaxed,
8877
'amount_total': amount_total,
8978
})
9079

91-
order.send_table_count_notification(order.table_id)
92-
return order._export_for_self_order()
80+
order['data']['lines'] = lines
81+
self._process_combo_items(saved_order, order['data'])
82+
saved_order.send_table_count_notification(saved_order.table_id)
83+
return saved_order._export_for_self_order()
9384

9485
@http.route('/pos-self-order/get-orders-taxes', auth='public', type='json', website=True)
9586
def get_order_taxes(self, order, access_token):
@@ -150,9 +141,31 @@ def update_existing_order(self, order, access_token, table_identifier):
150141
'table_stand_number': order.get('table_stand_number'),
151142
})
152143

144+
self._process_combo_items(pos_order, order)
153145
pos_order.send_table_count_notification(pos_order.table_id)
154146
return pos_order._export_for_self_order()
155147

148+
def _process_combo_items(self, order, order_values):
149+
"""
150+
Here we need to process original order dict to add
151+
combo_line_ids and combo_parent_id to the lines
152+
and then call the _link_combo_items method to link
153+
the combo lines together.
154+
"""
155+
combo_lines = []
156+
lines = order_values.get('lines')
157+
for line in lines:
158+
if line.get('child_lines'):
159+
line['combo_line_ids'] = [child_line['uuid'] for child_line in line['child_lines']]
160+
elif line.get('combo_parent_uuid'):
161+
line['combo_parent_id'] = line.get('combo_parent_uuid')
162+
163+
if line.get('combo_line_ids') or line.get('combo_parent_id'):
164+
combo_lines.append([0, 0, line])
165+
166+
order_values['lines'] = combo_lines
167+
order._link_combo_items(order_values)
168+
156169
@http.route('/pos-self-order/remove-order', auth='public', type='json', website=True)
157170
def remove_order(self, access_token, order_id, order_access_token):
158171
pos_config = self._verify_pos_config(access_token)
@@ -221,6 +234,7 @@ def _process_lines(self, lines, pos_config, pos_order_id, take_away=False):
221234
newLines = []
222235
pricelist = pos_config.pricelist_id
223236
sale_price_digits = pos_config.env['decimal.precision'].precision_get('Product Price')
237+
process_line = partial(pos_config.env['pos.order.line']._order_line_fields, session_id=pos_config.current_session_id.id)
224238

225239
combo_line_ids = [line['combo_line_id'] for line in lines if line.get('combo_line_id')]
226240
combo_lines = pos_config.env['pos.combo.line'].search([('id', 'in', combo_line_ids)])
@@ -246,6 +260,7 @@ def _process_lines(self, lines, pos_config, pos_order_id, take_away=False):
246260
children = [l for l in lines if l.get('combo_parent_uuid') == line.get('uuid')]
247261
pos_combo_lines = combo_lines.browse([child.get('combo_line_id') for child in children])
248262

263+
newLines.append({})
249264
if len(children) > 0:
250265
original_total = sum(pos_combo_lines.mapped("combo_id.base_price"))
251266
remaining_total = lst_price
@@ -293,7 +308,7 @@ def _process_lines(self, lines, pos_config, pos_order_id, take_away=False):
293308
taxes_after_fp = fiscal_pos.map_tax(product.taxes_id) if fiscal_pos else product.taxes_id
294309
pdetails = taxes_after_fp.compute_all(price_unit_fp, pos_config.currency_id, line_qty, product)
295310

296-
newLines.append({
311+
newLine = {
297312
'price_unit': price_unit_fp,
298313
'price_subtotal': pdetails.get('total_excluded'),
299314
'price_subtotal_incl': pdetails.get('total_included'),
@@ -310,10 +325,12 @@ def _process_lines(self, lines, pos_config, pos_order_id, take_away=False):
310325
'combo_parent_uuid': line.get('combo_parent_uuid'),
311326
'combo_id': line.get('combo_id'),
312327
'price_extra': price_extra
313-
})
328+
}
329+
newLines[len(newLines) - 1 - len(children)] = newLine
314330
appended_uuid.append(line.get('uuid'))
315331

316-
return newLines
332+
sanatized_lines = [process_line([0, 0, line])[2] for line in newLines]
333+
return sanatized_lines
317334

318335
def _get_order_prices(self, lines):
319336
amount_untaxed = sum([line.get('price_subtotal') for line in lines])

addons/pos_self_order/models/pos_order.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,6 @@ class PosOrderLine(models.Model):
1313
combo_line_ids = fields.One2many('pos.order.line', 'combo_parent_id', string='Combo Lines')
1414
combo_id = fields.Many2one('pos.combo', string='Combo line reference')
1515

16-
@api.model_create_multi
17-
def create(self, vals_list):
18-
for vals in vals_list:
19-
if (vals.get('combo_parent_uuid')):
20-
vals.update([
21-
('combo_parent_id', self.search([('uuid', '=', vals.get('combo_parent_uuid'))]).id)
22-
])
23-
if 'combo_parent_uuid' in vals:
24-
del vals['combo_parent_uuid']
25-
return super().create(vals_list)
26-
2716
def write(self, vals):
2817
if (vals.get('combo_parent_uuid')):
2918
vals.update([

addons/pos_self_order/static/tests/tours/test_self_order_combo.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,44 @@ registry.category("web_tour.tours").add("self_combo_selector", {
5050
Utils.checkIsNoBtn("Order Now"),
5151
],
5252
});
53+
54+
registry.category("web_tour.tours").add("test_self_order_combo_correct_order", {
55+
steps: () =>
56+
[
57+
Utils.clickBtn("Order Now"),
58+
ProductPage.clickProduct("Office Combo"),
59+
...ProductPage.setupCombo([
60+
{
61+
product: "Combo Product 1",
62+
attributes: [],
63+
},
64+
{
65+
product: "Combo Product 5",
66+
attributes: [],
67+
},
68+
{
69+
product: "Combo Product 8",
70+
attributes: [],
71+
},
72+
]),
73+
ProductPage.clickProduct("Office Combo"),
74+
...ProductPage.setupCombo([
75+
{
76+
product: "Combo Product 2",
77+
attributes: [],
78+
},
79+
{
80+
product: "Combo Product 5",
81+
attributes: [],
82+
},
83+
{
84+
product: "Combo Product 8",
85+
attributes: [],
86+
},
87+
]),
88+
Utils.clickBtn("Order"),
89+
Utils.clickBtn("Pay"),
90+
Utils.clickBtn("Ok"),
91+
Utils.checkIsNoBtn("Order Now"),
92+
].flat(),
93+
});

addons/pos_self_order/tests/test_self_order_combo.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,24 @@ def test_self_order_combo(self):
2929
self_route = self.pos_config._get_self_order_route()
3030

3131
self.start_tour(self_route, "self_combo_selector")
32+
33+
def test_self_order_combo_correct_order(self):
34+
setup_pos_combo_items(self)
35+
self.pos_config.with_user(self.pos_user).open_ui()
36+
self_route = self.pos_config._get_self_order_route()
37+
self.start_tour(self_route, "test_self_order_combo_correct_order")
38+
39+
pos_order = self.env['pos.order'].search([], order="id desc", limit=1)
40+
order_lines = pos_order._export_for_ui(pos_order)['lines']
41+
42+
def check_combo_products_order(lines):
43+
combo_header_id = None
44+
for line in lines:
45+
if len(line[2]['combo_line_ids']):
46+
combo_header_id = line[2]['id']
47+
else:
48+
if line[2]['combo_parent_id'] != combo_header_id:
49+
return False
50+
return True
51+
52+
self.assertTrue(check_combo_products_order(order_lines))

0 commit comments

Comments
 (0)