From 0406238506b0f582d244670c890ea9242d0c5b45 Mon Sep 17 00:00:00 2001 From: bvisible Date: Fri, 15 Sep 2023 12:50:23 +0200 Subject: [PATCH] add categories in pos and allow stripe cancel --- .../page/point_of_sale/point_of_sale.py | 47 +++++++ .../page/point_of_sale/pos_item_selector.js | 117 +++++++++++++++++- .../page/point_of_sale/stripe_terminal.js | 20 ++- 3 files changed, 180 insertions(+), 4 deletions(-) diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py index 9f1b087009b5..8e8b6f097727 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.py +++ b/erpnext/selling/page/point_of_sale/point_of_sale.py @@ -369,3 +369,50 @@ def get_pos_profile_data(pos_profile): pos_profile.customer_groups = _customer_groups_with_children return pos_profile + +#//// +@frappe.whitelist() +def has_items(item_group, pos_profile): + warehouse, hide_unavailable_items, company = frappe.db.get_value( #//// + "POS Profile", pos_profile, ["warehouse", "hide_unavailable_items", "company"] #//// + ) + + if not frappe.db.exists("Item Group", item_group): + item_group = get_root_of("Item Group") + + condition = get_item_group_condition(pos_profile) + + lft, rgt = frappe.db.get_value("Item Group", item_group, ["lft", "rgt"]) + + bin_join_selection, bin_join_condition = "", "" + if hide_unavailable_items: + bin_join_selection = ", `tabBin` bin" + bin_join_condition = ( + "AND bin.warehouse = %(warehouse)s AND bin.item_code = item.name AND bin.actual_qty > 0" + ) + + item_count = frappe.db.sql( + """ + SELECT COUNT(item.name) + FROM + `tabItem` item {bin_join_selection} + WHERE + item.disabled = 0 + AND item.has_variants = 0 + AND item.is_sales_item = 1 + AND item.is_fixed_asset = 0 + AND item.item_group in (SELECT name FROM `tabItem Group` WHERE lft >= {lft} AND rgt <= {rgt}) + {condition} + {bin_join_condition} + """.format( + lft=cint(lft), + rgt=cint(rgt), + condition=condition, + bin_join_selection=bin_join_selection, + bin_join_condition=bin_join_condition, + ), + {"warehouse": warehouse} + ) + + return {'count': item_count[0][0]} +#//// diff --git a/erpnext/selling/page/point_of_sale/pos_item_selector.js b/erpnext/selling/page/point_of_sale/pos_item_selector.js index 602192cc9c5c..8b0b3d2e9cb9 100644 --- a/erpnext/selling/page/point_of_sale/pos_item_selector.js +++ b/erpnext/selling/page/point_of_sale/pos_item_selector.js @@ -9,18 +9,22 @@ erpnext.PointOfSale.ItemSelector = class { this.hide_images = settings.hide_images; this.auto_add_item = settings.auto_add_item_to_cart; - this.inti_component(); + this.init_component(); } - inti_component() { + init_component() { this.prepare_dom(); this.make_search_bar(); this.load_items_data(); + this.load_item_groups_data(); //// Ajoutez ceci après avoir chargé les articles this.bind_events(); + this.bind_item_group_events(); //// Ajoutez ceci après avoir lié les événements this.attach_shortcuts(); } prepare_dom() { + //// added
+ //// added
this.wrapper.append( `
@@ -28,12 +32,16 @@ erpnext.PointOfSale.ItemSelector = class {
+
+
` ); this.$component = this.wrapper.find('.items-selector'); this.$items_container = this.$component.find('.items-container'); + this.$item_group_container = this.$component.find('.item-group-container'); //// + this.$parent_item_group_container = this.$component.find('.parent-item-group-container'); //// } async load_items_data() { @@ -407,4 +415,109 @@ erpnext.PointOfSale.ItemSelector = class { this.set_search_value(''); this.$component.css('display', show ? 'flex': 'none'); } + + //// + async load_item_groups_data() { + let res = []; + let res_all = []; + let res_childs = []; + let res_parent = []; + let res_all_parents = []; + if(!this.item_group) { + res_childs = await frappe.db.get_list("Item Group", {filters: {'parent_item_group': 'Tous les Groupes d\'Articles'}, fields: ["name", "parent_item_group", "pos_color"]}); + let pos_profile_doc = await frappe.db.get_doc("POS Profile", this.pos_profile); + if (pos_profile_doc && pos_profile_doc.item_groups) { + let itemGroupNames = pos_profile_doc.item_groups.map(entry => entry.item_group); + + res_childs = res_childs.filter(itemGroupName => !itemGroupNames.includes(itemGroupName)); + } + } else { + let group_data = await frappe.db.get_value("Item Group", this.item_group, "group_tree") + if(group_data.message.group_tree) { + let split_group = group_data.message.group_tree.split(">"); + for (let group of split_group) { + let parent = await frappe.db.get_list("Item Group", { + filters: {'item_group_name': group}, + fields: ["name", "parent_item_group", "pos_color"] + }); + res_all_parents = res_all_parents.concat(parent); + } + } + res_childs = await frappe.db.get_list("Item Group", {filters: {'parent_item_group': this.item_group}, fields: ["name", "parent_item_group", "pos_color"]}); + } + this.item_groups = res_all_parents; + await this.render_parent_item_group_list(this.item_groups); + this.item_groups = res_childs; + await this.render_item_group_list(this.item_groups); + } + + async render_item_group_list(item_groups) { + const item_group_container = this.$component.find('.item-group-container'); + item_group_container.html(''); + + for (let item_group of item_groups) { + let r = await frappe.call({ + method: "erpnext.selling.page.point_of_sale.point_of_sale.has_items", + args: { item_group: item_group.name, pos_profile: this.pos_profile }, + }) + + if(r.message && r.message.count > 0) { + const item_group_html = this.get_item_group_html(item_group); + item_group_container.append(item_group_html); + } + } + } + + async render_parent_item_group_list(item_groups) { + const item_group_container = this.$component.find('.parent-item-group-container'); + item_group_container.html(''); + + for (let item_group of item_groups) { + let r = await frappe.call({ + method: "erpnext.selling.page.point_of_sale.point_of_sale.has_items", + args: { item_group: item_group.name, pos_profile: this.pos_profile }, + }) + + if(r.message && r.message.count > 0) { + const item_group_html = this.get_item_group_html(item_group); + item_group_container.append(item_group_html); + } + } + } + + get_item_group_html(item_group) { + let bgColor = item_group.pos_color ? `background-color: ${item_group.pos_color};` : ''; + return ( + `
+ ${item_group.name} +
` + ); + } + + bind_item_group_events() { + const me = this; + this.$item_group_container.on("click", ".item-group-wrapper", function(){ + const $item_group = $(this); + const item_group_name = unescape($item_group.attr('data-item-group-name')); + + // Vous pouvez filtrer les articles par catégorie ici + // Par exemple : + me.filter_items_by_item_group(item_group_name, me); + }); + this.$parent_item_group_container.on("click", ".item-group-wrapper", function(){ + const $item_group = $(this); + const item_group_name = unescape($item_group.attr('data-item-group-name')); + + // Vous pouvez filtrer les articles par catégorie ici + // Par exemple : + me.filter_items_by_item_group(item_group_name); + }); + } + + filter_items_by_item_group(item_group_name) { + this.item_group = item_group_name; + !this.item_group && (this.item_group = this.parent_item_group); + this.filter_items(); + this.load_item_groups_data(); + } }; diff --git a/erpnext/selling/page/point_of_sale/stripe_terminal.js b/erpnext/selling/page/point_of_sale/stripe_terminal.js index 651b8d3d964a..6b8117956d9d 100644 --- a/erpnext/selling/page/point_of_sale/stripe_terminal.js +++ b/erpnext/selling/page/point_of_sale/stripe_terminal.js @@ -39,7 +39,7 @@ erpnext.PointOfSale.StripeTerminal = function(){ function show_loading_modal(title, message) { loading_dialog = new frappe.ui.Dialog({ - title: title, + title: __(title), fields: [{ label: '', fieldname: 'show_dialog', @@ -52,6 +52,12 @@ erpnext.PointOfSale.StripeTerminal = function(){ html += ''; loading_dialog.fields_dict.show_dialog.$wrapper.html(html); loading_dialog.show(); + if(title == 'Collecting Payments') { + loading_dialog.set_primary_action(__('Cancel'), function () { + loading_dialog.hide(); + terminal.clearReaderDisplay(); + }); + } } function unexpectedDisconnect() { @@ -261,7 +267,17 @@ erpnext.PointOfSale.StripeTerminal = function(){ function create_payment(payment, is_online){ show_loading_modal('Collecting Payments', 'Please Wait
Collecting Payments'); - frappe.dom.freeze(); + loading_dialog.$wrapper.attr('id', 'myUniqueModalId'); + loading_dialog.$wrapper.find('.btn-modal-close').hide() + + $(document).on('shown.bs.modal', '#myUniqueModalId', function() { + $(this).data('bs.modal')._config.backdrop = 'static'; + $(this).data('bs.modal')._config.keyboard = false; + }); + $(document).on('hidden.bs.modal', '#myUniqueModalId', function() { + $(this).removeAttr('id'); + }); + //frappe.dom.freeze(); frappe.call({ method: "pasigono.pasigono.api.payment_intent_creation", freeze: true,