From 33466c6ecdb07bfd8966946ace58f7dedbf78b93 Mon Sep 17 00:00:00 2001 From: Joseph Caburnay Date: Fri, 7 Apr 2023 11:52:17 +0000 Subject: [PATCH] [FIX] point_of_sale: properly call the 'post_closing_cash_details' method 2 issues 1. Activate cash control by making sure there is a cash payment method. There is traceback when closing session. - This is because the method call to post_closing_cash_details is not properly sent. 2. Install pos_restaurant, keep the cash payment method. Steps: - Create a new order. - Add item and go back to floor. (This will create a draft order in the backend.) - Try closing the session. - It should fail but it should not call `update_closing_control_state_session`. - BUG: Because `update_closing_control_state_session` is called, the session state changed and the user can't do "continue selling" because the button in the pos.session kanban is now "close". It should be "continue selling". Solution: 1. Make sure the orm.call is provided the correct params. 2. Access `cashControl` from the component which is equivalent to env.pos.config.cash_control. This commit fixes the listed issues. closes odoo/odoo#118226 X-original-commit: 6541633e4e79e2ef6c6099982bb21e5993f5d1df Signed-off-by: Heinz Robin (rhe) --- .../static/src/js/Popups/ClosePosPopup.js | 9 ++- .../static/tests/tours/ReceiptScreen.tour.js | 45 +++++++++++-- .../tours/helpers/ProductScreenTourMethods.js | 65 +++++++++++++++---- addons/point_of_sale/tests/test_frontend.py | 4 ++ 4 files changed, 98 insertions(+), 25 deletions(-) diff --git a/addons/point_of_sale/static/src/js/Popups/ClosePosPopup.js b/addons/point_of_sale/static/src/js/Popups/ClosePosPopup.js index bfb8d07be21..b7c548fc18e 100644 --- a/addons/point_of_sale/static/src/js/Popups/ClosePosPopup.js +++ b/addons/point_of_sale/static/src/js/Popups/ClosePosPopup.js @@ -131,14 +131,13 @@ export class ClosePosPopup extends AbstractAwaitablePopup { if (!this.closeSessionClicked) { this.closeSessionClicked = true; - if (this.pos.globalState.config.cashControl) { + if (this.cashControl) { const response = await this.orm.call( "pos.session", - "post_closing_cash_details"[this.pos.globalState.pos_session.id], + "post_closing_cash_details", + [this.pos.globalState.pos_session.id], { - counted_cash: this.pos.globalState.config.cashControl - ? this.state.payments[this.defaultCashDetails.id].counted - : 0, + counted_cash: this.state.payments[this.defaultCashDetails.id].counted, } ); diff --git a/addons/point_of_sale/static/tests/tours/ReceiptScreen.tour.js b/addons/point_of_sale/static/tests/tours/ReceiptScreen.tour.js index 6cb5ac0e4da..c151edad310 100644 --- a/addons/point_of_sale/static/tests/tours/ReceiptScreen.tour.js +++ b/addons/point_of_sale/static/tests/tours/ReceiptScreen.tour.js @@ -3,6 +3,7 @@ import { ProductScreen } from "@point_of_sale/../tests/tours/helpers/ProductScreenTourMethods"; import { ReceiptScreen } from "@point_of_sale/../tests/tours/helpers/ReceiptScreenTourMethods"; import { PaymentScreen } from "@point_of_sale/../tests/tours/helpers/PaymentScreenTourMethods"; +import { Chrome } from "@point_of_sale/../tests/tours/helpers/ChromeTourMethods"; import { NumberPopup } from "@point_of_sale/../tests/tours/helpers/NumberPopupTourMethods"; import { getSteps, startSteps } from "@point_of_sale/../tests/tours/helpers/utils"; import { registry } from "@web/core/registry"; @@ -64,18 +65,48 @@ PaymentScreen.do.clickPaymentMethod("Bank"); PaymentScreen.do.clickValidate(); ReceiptScreen.check.customerNoteIsThere("Test customer note"); -registry.category("web_tour.tours").add("ReceiptScreenTour", { test: true, url: "/pos/ui", steps: getSteps() }); +registry + .category("web_tour.tours") + .add("ReceiptScreenTour", { test: true, url: "/pos/ui", steps: getSteps() }); startSteps(); ProductScreen.do.clickHomeCategory(); -ProductScreen.exec.addOrderline('Test Product', '1'); +ProductScreen.exec.addOrderline("Test Product", "1"); ProductScreen.do.clickPricelistButton(); -ProductScreen.do.selectPriceList('special_pricelist'); -ProductScreen.check.discountOriginalPriceIs('7.0'); +ProductScreen.do.selectPriceList("special_pricelist"); +ProductScreen.check.discountOriginalPriceIs("7.0"); ProductScreen.do.clickPayButton(); -PaymentScreen.do.clickPaymentMethod('Cash'); +PaymentScreen.do.clickPaymentMethod("Cash"); PaymentScreen.do.clickValidate(); -ReceiptScreen.check.discountAmountIs('0.7'); +ReceiptScreen.check.discountAmountIs("0.7"); -registry.category("web_tour.tours").add("ReceiptScreenDiscountWithPricelistTour", { test: true, url: "/pos/ui", steps: getSteps() }); \ No newline at end of file +registry.category("web_tour.tours").add("ReceiptScreenDiscountWithPricelistTour", { + test: true, + url: "/pos/ui", + steps: getSteps(), +}); + +startSteps(); + +ProductScreen.do.confirmOpeningPopup(); +ProductScreen.exec.addOrderline("Desk Pad", "5", "5"); +ProductScreen.check.selectedOrderlineHas("Desk Pad", "5"); +ProductScreen.do.clickPayButton(); +PaymentScreen.do.clickPaymentMethod("Cash"); +PaymentScreen.check.validateButtonIsHighlighted(true); +PaymentScreen.do.clickValidate(); +ReceiptScreen.check.receiptIsThere(); +ReceiptScreen.do.clickNextOrder(); +ProductScreen.check.isShown(); +// Close the session +Chrome.do.clickMenuButton(); +ProductScreen.do.clickCloseButton(); +ProductScreen.do.closeWithCashAmount("25"); +ProductScreen.check.cashDifferenceIs("0.00"); +ProductScreen.do.clickCloseSession(); +ProductScreen.check.lastClosingCashIs("25.00"); + +registry + .category("web_tour.tours") + .add("OrderPaidInCash", { test: true, url: "/pos/ui", steps: getSteps() }); diff --git a/addons/point_of_sale/static/tests/tours/helpers/ProductScreenTourMethods.js b/addons/point_of_sale/static/tests/tours/helpers/ProductScreenTourMethods.js index 90e59d4cfcb..8e07735b089 100644 --- a/addons/point_of_sale/static/tests/tours/helpers/ProductScreenTourMethods.js +++ b/addons/point_of_sale/static/tests/tours/helpers/ProductScreenTourMethods.js @@ -145,24 +145,46 @@ class Do { enterOpeningAmount(amount) { return [ { - content: 'enter opening amount', - trigger: '.cash-input-sub-section > .pos-input', - run: 'text ' + amount, + content: "enter opening amount", + trigger: ".cash-input-sub-section > .pos-input", + run: "text " + amount, }, ]; } changeFiscalPosition(name) { return [ { - content: 'click fiscal position button', - trigger: '.o_fiscal_position_button', + content: "click fiscal position button", + trigger: ".o_fiscal_position_button", }, { - content: 'fiscal position screen is shown', + content: "fiscal position screen is shown", trigger: `.selection-item:contains("${name}")`, }, ]; } + clickCloseButton() { + return [ + { + trigger: ".header-button", + }, + ]; + } + closeWithCashAmount(val) { + return [ + { + trigger: ".pos-input", + run: `text ${val}`, + }, + ]; + } + clickCloseSession() { + return [ + { + trigger: "footer .button:contains('Close Session')", + }, + ]; + } } class Check { @@ -259,20 +281,20 @@ class Check { checkSecondCashClosingDetailsLineAmount(amount, sign) { return [ { - content: 'Open menu', - trigger: '.menu-button', + content: "Open menu", + trigger: ".menu-button", }, { - content: 'Click close session button', - trigger: '.header-button', + content: "Click close session button", + trigger: ".header-button", }, { - content: 'Check closing details', + content: "Check closing details", trigger: `.cash-overview tr:nth-child(2) td:contains("${amount}")`, run: () => {}, // it's a check }, { - content: 'Check closing details', + content: "Check closing details", trigger: `.cash-overview tr:nth-child(2) .cash-sign:contains("${sign}")`, run: () => {}, // it's a check }, @@ -281,7 +303,7 @@ class Check { noDiscountApplied(originalPrice) { return [ { - content: 'no discount is applied', + content: "no discount is applied", trigger: `.info:not(:contains(${originalPrice}))`, }, ]; @@ -295,6 +317,23 @@ class Check { }, ]; } + cashDifferenceIs(val) { + return [ + { + trigger: `.payment-methods-overview tr td:nth-child(4):contains(${val})`, + isCheck: true, + }, + ]; + } + // Temporarily put it here. It should be in the utility methods for the backend views. + lastClosingCashIs(val) { + return [ + { + trigger: `[name=last_session_closing_cash]:contains(${val})`, + isCheck: true, + }, + ]; + } } class Execute { diff --git a/addons/point_of_sale/tests/test_frontend.py b/addons/point_of_sale/tests/test_frontend.py index 9eb5e6449b2..5948d983ca4 100644 --- a/addons/point_of_sale/tests/test_frontend.py +++ b/addons/point_of_sale/tests/test_frontend.py @@ -690,6 +690,10 @@ class TestUi(TestPointOfSaleHttpCommon): self.assertEqual(len(pos_session.statement_line_ids), 1) self.assertEqual(pos_session.statement_line_ids[0].amount, -10) + def test_cash_payments_should_reflect_on_next_opening(self): + self.main_pos_config.open_ui() + self.start_tour("/pos/ui?config_id=%d" % self.main_pos_config.id, 'OrderPaidInCash', login="accountman") + def test_fiscal_position_no_tax(self): #create a tax of 15% with price included tax = self.env['account.tax'].create({