diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 90395e22b6b..806955d6e7c 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -280,6 +280,7 @@ standard_portal_menu_items = [ sounds = [ {"name": "incoming-call", "src": "/assets/erpnext/sounds/incoming-call.mp3", "volume": 0.2}, {"name": "call-disconnect", "src": "/assets/erpnext/sounds/call-disconnect.mp3", "volume": 0.2}, + {"name": "numpad-touch", "src": "/assets/erpnext/sounds/numpad-touch.mp3", "volume": 0.8}, ] has_upload_permission = {"Employee": "erpnext.setup.doctype.employee.employee.has_upload_permission"} diff --git a/erpnext/public/scss/point-of-sale.scss b/erpnext/public/scss/point-of-sale.scss index d4cc7094e55..f007bec5e8b 100644 --- a/erpnext/public/scss/point-of-sale.scss +++ b/erpnext/public/scss/point-of-sale.scss @@ -882,27 +882,6 @@ overflow: hidden; text-overflow: ellipsis; } - - > .cash-shortcuts { - display: none; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: var(--margin-sm); - font-size: var(--text-sm); - text-align: center; - - > .shortcut { - @extend .pointer-no-select; - border-radius: var(--border-radius-sm); - background-color: var(--control-bg); - font-weight: 500; - padding: var(--padding-xs) var(--padding-sm); - transition: all 0.15s ease-in-out; - - &:hover { - background-color: var(--control-bg); - } - } - } } > .loyalty-card { diff --git a/erpnext/public/sounds/numpad-touch.mp3 b/erpnext/public/sounds/numpad-touch.mp3 new file mode 100644 index 00000000000..97fbb32ffa9 Binary files /dev/null and b/erpnext/public/sounds/numpad-touch.mp3 differ diff --git a/erpnext/selling/page/point_of_sale/pos_payment.js b/erpnext/selling/page/point_of_sale/pos_payment.js index 5c38171fa6b..1ea6edbd43d 100644 --- a/erpnext/selling/page/point_of_sale/pos_payment.js +++ b/erpnext/selling/page/point_of_sale/pos_payment.js @@ -130,7 +130,7 @@ erpnext.PointOfSale.Payment = class { [1, 2, 3], [4, 5, 6], [7, 8, 9], - [".", 0, "Delete"], + ["+/-", 0, "Delete"], ], }); @@ -141,13 +141,33 @@ erpnext.PointOfSale.Payment = class { const button_value = $btn.attr("data-button-value"); highlight_numpad_btn($btn); - this.numpad_value = - button_value === "delete" ? this.numpad_value.slice(0, -1) : this.numpad_value + button_value; - this.selected_mode.$input.get(0).focus(); - this.selected_mode.set_value(this.numpad_value); + if (!this.selected_mode) { + frappe.show_alert({ + message: __("Select a Payment Method."), + indicator: "yellow", + }); + return; + } + + const precision = 10 ** frappe.sys_defaults.currency_precision; + this.numpad_value = "0"; + if (this.selected_mode.get_value()) { + this.numpad_value = (this.selected_mode.get_value() * precision).toFixed(0).toString(); + } + + if (button_value === "delete") { + this.numpad_value = this.numpad_value.slice(0, -1); + } else if (button_value === "+/-") { + this.numpad_value = `${this.numpad_value * -1}`; + } else { + this.numpad_value = this.numpad_value + button_value; + } + + this.selected_mode.set_value(this.numpad_value / precision); function highlight_numpad_btn($btn) { $btn.addClass("shadow-base-inner bg-selected"); + frappe.utils.play_sound("numpad-touch", true); setTimeout(() => { $btn.removeClass("shadow-base-inner bg-selected"); }, 100); @@ -162,22 +182,17 @@ erpnext.PointOfSale.Payment = class { // if clicked element doesn't have .mode-of-payment class then return if (!$(e.target).is(mode_clicked)) return; - const scrollLeft = - mode_clicked.offset().left - me.$payment_modes.offset().left + me.$payment_modes.scrollLeft(); - me.$payment_modes.animate({ scrollLeft }); - const mode = mode_clicked.attr("data-mode"); // hide all control fields and shortcuts $(`.mode-of-payment-control`).css("display", "none"); - $(`.cash-shortcuts`).css("display", "none"); me.$payment_modes.find(`.pay-amount`).css("display", "inline"); me.$payment_modes.find(`.loyalty-amount-name`).css("display", "none"); // remove highlight from all mode-of-payments $(".mode-of-payment").removeClass("border-primary"); - if (mode_clicked.hasClass("border-primary")) { + if (me.selected_mode?._label === me[`${mode}_control`]?._label) { // clicked one is selected then unselect it mode_clicked.removeClass("border-primary"); me.selected_mode = ""; @@ -185,12 +200,10 @@ erpnext.PointOfSale.Payment = class { // clicked one is not selected then select it mode_clicked.addClass("border-primary"); mode_clicked.find(".mode-of-payment-control").css("display", "flex"); - mode_clicked.find(".cash-shortcuts").css("display", "grid"); me.$payment_modes.find(`.${mode}-amount`).css("display", "none"); me.$payment_modes.find(`.${mode}-name`).css("display", "inline"); me.selected_mode = me[`${mode}_control`]; - me.selected_mode && me.selected_mode.$input.get(0).focus(); me.auto_set_remaining_amount(); } }); @@ -296,11 +309,6 @@ erpnext.PointOfSale.Payment = class { bind_paid_amount_event(frm) { this.update_totals_section(frm.doc); - - // need to re calculate cash shortcuts after discount is applied - const is_cash_shortcuts_invisible = !this.$payment_modes.find(".cash-shortcuts").is(":visible"); - this.attach_cash_shortcuts(frm.doc); - !is_cash_shortcuts_invisible && this.$payment_modes.find(".cash-shortcuts").css("display", "grid"); this.render_payment_mode_dom(); } @@ -457,8 +465,7 @@ erpnext.PointOfSale.Payment = class { .map((p, i) => { const mode = this.sanitize_mode_of_payment(p.mode_of_payment); const payment_type = p.type; - const margin = i % 2 === 0 ? "pr-2" : "pl-2"; - const amount = p.amount > 0 ? format_currency(p.amount, currency) : ""; + const amount = p.amount !== 0 ? format_currency(p.amount, currency) : ""; return `