From 168762c838ad46f5304bcd15ec9b11d9a5d005f4 Mon Sep 17 00:00:00 2001 From: "Adrien Guilliams (adgu)" Date: Thu, 23 Feb 2023 10:04:38 +0000 Subject: [PATCH] [IMP] pos, pos_restaurant: adaptation of change of quantity for orderlines In the previous state of the point_of_sale module, when the l10n_fr_pos_cert module was used, we were too restrictive leading to an unusable flow by some clients. We adapt the modules here so that the FR module is more usable by the clients while still respecting the law. closes odoo/odoo#113754 Signed-off-by: Heinz Robin (rhe) --- addons/point_of_sale/models/pos_order.py | 1 + .../js/Screens/ProductScreen/ProductScreen.js | 29 ++++++++++--------- addons/point_of_sale/static/src/js/models.js | 28 +++++++++++++++++- .../static/src/js/Screens/TicketScreen.js | 18 ++++++------ .../static/tests/tours/TicketScreen.tour.js | 2 +- 5 files changed, 53 insertions(+), 25 deletions(-) diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py index 711fcd03a3f..eba93a1c99c 100644 --- a/addons/point_of_sale/models/pos_order.py +++ b/addons/point_of_sale/models/pos_order.py @@ -1285,6 +1285,7 @@ class PosOrderLine(models.Model): if line and 'tax_ids' not in line[2]: product = self.env['product.product'].browse(line[2]['product_id']) line[2]['tax_ids'] = [(6, 0, [x.id for x in product.taxes_id])] + # Clean up fields sent by the JS line = [ line[0], line[1], {k: v for k, v in line[2].items() if k in self.env['pos.order.line']._fields} diff --git a/addons/point_of_sale/static/src/js/Screens/ProductScreen/ProductScreen.js b/addons/point_of_sale/static/src/js/Screens/ProductScreen/ProductScreen.js index 57f0d852e23..62bdfb4d2af 100644 --- a/addons/point_of_sale/static/src/js/Screens/ProductScreen/ProductScreen.js +++ b/addons/point_of_sale/static/src/js/Screens/ProductScreen/ProductScreen.js @@ -208,22 +208,23 @@ export class ProductScreen extends ControlButtonsMixin(Component) { const order = this.env.pos.get_order(); const selectedLine = this.env.pos.get_order().get_selected_orderline(); const currentQuantity = selectedLine.get_quantity(); - if ( - selectedLine.is_last_line() && - currentQuantity === 1 && - newQuantity < currentQuantity - ) { + if (newQuantity >= currentQuantity) { selectedLine.set_quantity(newQuantity); - } else if (newQuantity >= currentQuantity) { - selectedLine.set_quantity(newQuantity); - } else { - const newLine = selectedLine.clone(); - const decreasedQuantity = currentQuantity - newQuantity; - newLine.order = order; - - newLine.set_quantity(-decreasedQuantity, true); - order.add_orderline(newLine); + return; } + if (newQuantity >= selectedLine.saved_quantity) { + if (newQuantity == 0) { + order.remove_orderline(selectedLine) + } + selectedLine.set_quantity(newQuantity) + return; + } + const newLine = selectedLine.clone(); + const decreasedQuantity = selectedLine.saved_quantity - newQuantity; + newLine.order = order; + newLine.set_quantity(-decreasedQuantity, true); + selectedLine.set_quantity(selectedLine.saved_quantity); + order.add_orderline(newLine); } } async onClickPay() { diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index 893abdec2a8..ad37eca3349 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -395,10 +395,13 @@ export class PosGlobalState extends PosModel { this.ordersToUpdateSet.delete(order); } if (order.server_id && !order.finalized) { - this.db.set_order_to_remove_from_server(order); + this.setOrderToRemove(order); } } } + setOrderToRemove(order) { + this.db.set_order_to_remove_from_server(order); + } /** * Return the current cashier (in this case, the user) @@ -439,6 +442,10 @@ export class PosGlobalState extends PosModel { if (this.isOpenOrderShareable()) { this.sendDraftToServer(); } + if (this.selectedOrder) { + this.selectedOrder.firstDraft = false; + this.selectedOrder.updateSavedQuantity(); + } const order = this.createReactiveOrder(); this.orders.add(order); this.selectedOrder = order; @@ -629,6 +636,7 @@ export class PosGlobalState extends PosModel { } // important to throw error here and let the rendering component handle the error console.warn("Failed to remove orders:", removedOrdersIds); + this._postRemoveFromServer(removedOrdersIds); throw error; } } @@ -899,6 +907,10 @@ export class PosGlobalState extends PosModel { // change the current order set_order(order, options) { + if (this.selectedOrder) { + this.selectedOrder.firstDraft = false; + this.selectedOrder.updateSavedQuantity(); + } this.selectedOrder = order; } @@ -1914,6 +1926,7 @@ export class Orderline extends PosModel { this.full_product_name = options.description || ""; this.id = orderline_id++; this.customerNote = this.customerNote || ""; + this.saved_quantity = 0; if (options.price) { this.set_unit_price(options.price); @@ -1946,6 +1959,7 @@ export class Orderline extends PosModel { this.set_customer_note(json.customer_note); this.refunded_qty = json.refunded_qty; this.refunded_orderline_id = json.refunded_orderline_id; + this.saved_quantity = json.qty; } clone() { var orderline = new Orderline( @@ -2056,6 +2070,9 @@ export class Orderline extends PosModel { get_price_extra() { return this.price_extra; } + updateSavedQuantity() { + this.saved_quantity = this.quantity; + } // sets the quantity of the product. The quantity will be rounded according to the // product's unity of measure properties. Quantities greater than zero will not get // rounded to zero @@ -2797,6 +2814,7 @@ export class Order extends PosModel { this.cashier = this.pos.get_cashier(); this.finalized = false; // if true, cannot be modified. this.shippingDate = null; + this.firstDraft = true; this.partner = null; @@ -2863,6 +2881,7 @@ export class Order extends PosModel { this.validation_date = json.creation_date; this.server_id = json.server_id ? json.server_id : false; this.user_id = json.user_id; + this.firstDraft = false; if (json.fiscal_position_id) { var fiscal_position = _.find(this.pos.fiscal_positions, function (fp) { @@ -3147,6 +3166,9 @@ export class Order extends PosModel { zero_pad(this.sequence_number, 4) ); } + updateSavedQuantity() { + this.orderlines.forEach((line) => line.updateSavedQuantity()); + } get_name() { return this.name; } @@ -3303,6 +3325,10 @@ export class Order extends PosModel { this.select_orderline(this.get_last_orderline()); } + isFirstDraft(){ + return this.firstDraft; + } + fix_tax_included_price(line) { line.set_unit_price(line.compute_fixed_price(line.price)); } diff --git a/addons/pos_restaurant/static/src/js/Screens/TicketScreen.js b/addons/pos_restaurant/static/src/js/Screens/TicketScreen.js index 1340044a69c..7dca365734a 100644 --- a/addons/pos_restaurant/static/src/js/Screens/TicketScreen.js +++ b/addons/pos_restaurant/static/src/js/Screens/TicketScreen.js @@ -78,19 +78,19 @@ patch(TicketScreen.prototype, "pos_restaurant.TicketScreen", { } }, //@override - async onDeleteOrder() { - await this._super(...arguments); + async onDeleteOrder(order) { + const _super = this._super; if (this.env.pos.config.iface_floorplan) { + this.env.pos.setOrderToRemove(order); if (!this.env.pos.table) { - this.env.pos._removeOrdersFromServer(); - } - const orderList = this.env.pos.table - ? this.env.pos.getTableOrders(this.env.pos.table.id) - : this.env.pos.orders; - if (orderList.length == 0) { - this.pos.showScreen("FloorScreen"); + try { + await this.env.pos._removeOrdersFromServer(); + } catch (error) { + throw error; + } } } + await _super(...arguments); }, async setTip(order, serverId, amount) { try { diff --git a/addons/pos_restaurant/static/tests/tours/TicketScreen.tour.js b/addons/pos_restaurant/static/tests/tours/TicketScreen.tour.js index 583426b4f46..e78d59dacc6 100644 --- a/addons/pos_restaurant/static/tests/tours/TicketScreen.tour.js +++ b/addons/pos_restaurant/static/tests/tours/TicketScreen.tour.js @@ -21,7 +21,7 @@ ProductScreen.check.isShown(); Chrome.do.clickTicketButton(); TicketScreen.check.nthRowContains(2, "-0001"); TicketScreen.do.deleteOrder("-0001"); -FloorScreen.check.isShown(); +TicketScreen.do.clickDiscard(); // Create 2 items in a table. From floorscreen, delete 1 item. Then select the other item. // Correct order and screen should be displayed and the BackToFloorButton is shown.