From c70bbacd347a1e83082a49f3b1f7614e30823448 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Tue, 29 Aug 2017 15:27:17 +0530 Subject: [PATCH] Add online, offline option, fix search --- .../doctype/pos_settings/pos_settings.json | 11 +-- .../doctype/pos_settings/pos_settings.py | 8 +- erpnext/accounts/page/pos/pos.js | 12 ++- .../page/point_of_sale/point_of_sale.js | 78 ++++++++++++------- .../page/point_of_sale/point_of_sale.py | 11 +++ 5 files changed, 80 insertions(+), 40 deletions(-) diff --git a/erpnext/accounts/doctype/pos_settings/pos_settings.json b/erpnext/accounts/doctype/pos_settings/pos_settings.json index ab3976e1ba7..cdd1865b758 100644 --- a/erpnext/accounts/doctype/pos_settings/pos_settings.json +++ b/erpnext/accounts/doctype/pos_settings/pos_settings.json @@ -18,8 +18,9 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "type_of_pos", - "fieldtype": "Select", + "default": "0", + "fieldname": "is_online", + "fieldtype": "Check", "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -27,10 +28,10 @@ "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, - "label": "Type of POS", + "label": "Online", "length": 0, "no_copy": 0, - "options": "Online\nOffline", + "options": "", "permlevel": 0, "precision": "", "print_hide": 0, @@ -54,7 +55,7 @@ "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2017-08-28 16:46:41.732676", + "modified": "2017-08-29 14:34:36.166049", "modified_by": "Administrator", "module": "Accounts", "name": "POS Settings", diff --git a/erpnext/accounts/doctype/pos_settings/pos_settings.py b/erpnext/accounts/doctype/pos_settings/pos_settings.py index 4a71775a706..c978a4e9ad9 100644 --- a/erpnext/accounts/doctype/pos_settings/pos_settings.py +++ b/erpnext/accounts/doctype/pos_settings/pos_settings.py @@ -7,10 +7,4 @@ import frappe from frappe.model.document import Document class POSSettings(Document): - def validate(self): - link = 'point-of-sale' if self.type_of_pos == 'Online' else 'pos' - desktop_icon = frappe.db.get_value('Desktop Icon', {'module_name': 'POS'}, 'name') - if desktop_icon: - doc = frappe.get_doc('Desktop Icon', desktop_icon) - doc.link = link - doc.save() \ No newline at end of file + pass \ No newline at end of file diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index 599372411a0..3d5d5f4d907 100644 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -8,8 +8,16 @@ frappe.pages['pos'].on_page_load = function (wrapper) { single_column: true }); - wrapper.pos = new erpnext.pos.PointOfSale(wrapper); - cur_pos = wrapper.pos; + frappe.db.get_value('POS Settings', {name: 'POS Settings'}, 'is_online', (r) => { + if (r && r.is_online && !cint(r.is_online)) { + // offline + wrapper.pos = new erpnext.pos.PointOfSale(wrapper); + cur_pos = wrapper.pos; + } else { + // online + frappe.set_route('point-of-sale'); + } + }); } frappe.pages['pos'].refresh = function (wrapper) { diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.js b/erpnext/selling/page/point_of_sale/point_of_sale.js index cc1e3f164d2..b523a4952cb 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.js +++ b/erpnext/selling/page/point_of_sale/point_of_sale.js @@ -7,8 +7,16 @@ frappe.pages['point-of-sale'].on_page_load = function(wrapper) { single_column: true }); - wrapper.pos = new PointOfSale(wrapper); - window.cur_pos = wrapper.pos; + frappe.db.get_value('POS Settings', {name: 'POS Settings'}, 'is_online', (r) => { + if (r && r.is_online && cint(r.is_online)) { + // online + wrapper.pos = new PointOfSale(wrapper); + window.cur_pos = wrapper.pos; + } else { + // offline + frappe.set_route('pos'); + } + }); }; class PointOfSale { @@ -117,16 +125,12 @@ class PointOfSale { wrapper: this.wrapper.find('.item-container'), pos_profile: this.pos_profile, events: { - item_click: (item_code) => { + update_cart: (item, field, value) => { if(!this.frm.doc.customer) { frappe.throw(__('Please select a customer')); } - - this.update_item_in_cart(item_code, 'qty', '+1'); + this.update_item_in_cart(item, field, value); this.cart && this.cart.unselect_all(); - }, - update_cart: (item, field, value) => { - this.update_item_in_cart(item, field, value) } } }); @@ -146,7 +150,7 @@ class PointOfSale { } if(field === 'qty' && (item.serial_no || item.batch_no)) { - this.select_batch_and_serial_no(item) + this.select_batch_and_serial_no(item); } else { this.update_item_in_frm(item, field, value) .then(() => { @@ -257,6 +261,13 @@ class PointOfSale { } }).then(r => { this.pos_profile = r.message; + + if (!this.pos_profile) { + this.pos_profile = { + currency: frappe.defaults.get_default('currency'), + selling_price_list: frappe.defaults.get_default('selling_price_list') + }; + } }); } @@ -307,9 +318,9 @@ class PointOfSale { this.page.clear_menu(); // for mobile - this.page.add_menu_item(__("Pay"), function () { - // - }).addClass('visible-xs'); + // this.page.add_menu_item(__("Pay"), function () { + // + // }).addClass('visible-xs'); this.page.add_menu_item(__("Form View"), function () { var doc = frappe.model.sync(me.frm.doc); @@ -319,6 +330,10 @@ class PointOfSale { this.page.add_menu_item(__("POS Profile"), function () { frappe.set_route('List', 'POS Profile'); }); + + this.page.add_menu_item(__('POS Settings'), function() { + frappe.set_route('Form', 'POS Settings'); + }); } set_form_action() { @@ -740,8 +755,7 @@ class POSItems { this.pos_profile = pos_profile; this.items = {}; this.events = events; - this.currency = this.pos_profile.currency || - frappe.defaults.get_default('currency'); + this.currency = this.pos_profile.currency; this.make_dom(); this.make_fields(); @@ -751,10 +765,11 @@ class POSItems { // bootstrap with 20 items this.get_items() - .then((items, serial_no) => { + .then(({ items }) => { + this.all_items = items; this.items = items; - }) - .then(() => this.render_items()); + this.render_items(items); + }); } make_dom() { @@ -795,8 +810,11 @@ class POSItems { }); this.search_field.$input.on('input', (e) => { - const search_term = e.target.value; - this.filter_items({ search_term }); + clearTimeout(this.last_search); + this.last_search = setTimeout(() => { + const search_term = e.target.value; + this.filter_items({ search_term }); + }, 300); }); this.item_group_field = frappe.ui.form.make_control({ @@ -861,18 +879,26 @@ class POSItems { this.render_items(items); return; } + } else { + return this.render_items(this.all_items); } this.get_items({search_value: search_term, item_group }) - .then((items) => { + .then(({ items, serial_no, batch_no }) => { if (search_term) { this.search_index[search_term] = items; } this.render_items(items); - if(this.serial_no) { + if(serial_no) { this.events.update_cart(items[0].item_code, - 'serial_no', this.serial_no); + 'serial_no', serial_no); + this.search_field.set_value(''); + } + if(batch_no) { + this.events.update_cart(items[0].item_code, + 'batch_no', serial_no); + this.search_field.set_value(''); } }); } @@ -882,7 +908,7 @@ class POSItems { this.wrapper.on('click', '.pos-item-wrapper', function(e) { const $item = $(this); const item_code = $item.attr('data-item-code'); - me.events.item_click.apply(null, [item_code]); + me.events.update_cart(item_code, 'qty', '+1'); }); } @@ -944,10 +970,10 @@ class POSItems { search_value } }).then(r => { - const { items, serial_no } = r.message; + // const { items, serial_no, batch_no } = r.message; - this.serial_no = serial_no || ""; - res(items); + // this.serial_no = serial_no || ""; + res(r.message); }); }); } 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 d34fc544e92..4e2b1b1343d 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.py +++ b/erpnext/selling/page/point_of_sale/point_of_sale.py @@ -15,6 +15,7 @@ from erpnext.controllers.accounts_controller import get_taxes_and_charges def get_items(start, page_length, price_list, item_group, search_value=""): condition = "" serial_no = "" + batch_no = "" item_code = search_value if search_value: @@ -23,6 +24,11 @@ def get_items(start, page_length, price_list, item_group, search_value=""): if serial_no_data: serial_no, item_code = serial_no_data + if not serial_no: + batch_no_data = frappe.db.get_value('Batch', search_value, ['name', 'item']) + if batch_no_data: + batch_no, item_code = batch_no_data + lft, rgt = frappe.db.get_value('Item Group', item_group, ['lft', 'rgt']) # locate function is used to sort by closest match from the beginning of the value res = frappe.db.sql("""select i.name as item_code, i.item_name, i.image as item_image, @@ -52,6 +58,11 @@ def get_items(start, page_length, price_list, item_group, search_value=""): 'serial_no': serial_no }) + if batch_no: + res.update({ + 'batch_no': batch_no + }) + return res @frappe.whitelist()