From c037dc775e248dfdf4f850b09fbd8898bf1256d1 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 28 Nov 2017 16:11:15 +0530 Subject: [PATCH] Refactor multi pos profile selection in the pos invoice (#11721) --- .../doctype/pos_profile/pos_profile.json | 7 +- .../doctype/pos_profile/pos_profile.py | 108 ++++++----- .../pos_profile_user/pos_profile_user.json | 32 +++- .../pos_profile_user/test_pos_profile_user.js | 23 +++ .../pos_profile_user/test_pos_profile_user.py | 9 + .../doctype/sales_invoice/sales_invoice.js | 23 ++- .../doctype/sales_invoice/sales_invoice.py | 14 +- erpnext/patches.txt | 2 +- .../add_user_to_child_table_in_pos_profile.py | 45 +++-- erpnext/public/js/controllers/transaction.js | 6 +- .../page/point_of_sale/point_of_sale.js | 167 +++++++++--------- erpnext/stock/get_item_details.py | 29 ++- 12 files changed, 302 insertions(+), 163 deletions(-) create mode 100644 erpnext/accounts/doctype/pos_profile_user/test_pos_profile_user.js create mode 100644 erpnext/accounts/doctype/pos_profile_user/test_pos_profile_user.py diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.json b/erpnext/accounts/doctype/pos_profile/pos_profile.json index 2740ef2112..6c09c6e317 100644 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.json +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.json @@ -2,7 +2,7 @@ "allow_copy": 0, "allow_guest_to_view": 0, "allow_import": 0, - "allow_rename": 0, + "allow_rename": 1, "autoname": "field:pos_profile_name", "beta": 0, "creation": "2013-05-24 12:15:51", @@ -315,7 +315,7 @@ "search_index": 0, "set_only_once": 0, "unique": 0 - }, + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -1508,7 +1508,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-10-27 06:45:32.957674", + "modified": "2017-11-24 14:08:09.184226", "modified_by": "Administrator", "module": "Accounts", "name": "POS Profile", @@ -1558,6 +1558,7 @@ "quick_entry": 0, "read_only": 0, "read_only_onload": 0, + "search_fields": "pos_profile_name", "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py index 65b0e7cc7c..c70526cf2c 100644 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.py +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py @@ -4,30 +4,34 @@ from __future__ import unicode_literals import frappe from frappe import msgprint, _ -from frappe.utils import cint +from frappe.utils import cint, now from erpnext.accounts.doctype.sales_invoice.sales_invoice import set_account_for_mode_of_payment from frappe.model.document import Document class POSProfile(Document): def validate(self): - # self.check_for_duplicate() + self.validate_default_profile() self.validate_all_link_fields() self.validate_duplicate_groups() self.check_default_payment() self.validate_customer_territory_group() - def check_for_duplicate(self): - res = frappe.db.sql("""select name, user from `tabPOS Profile` - where ifnull(user, '') = %s and name != %s and company = %s and ifnull(disabled, 0) != 1""", - (self.user, self.name, self.company)) - if res: - if res[0][1]: - msgprint(_("POS Profile {0} already created for user: {1} and company {2}").format(res[0][0], - res[0][1], self.company), raise_exception=1) - else: - msgprint(_("Global POS Profile {0} already created for company {1}").format(res[0][0], - self.company), raise_exception=1) + def validate_default_profile(self): + for row in self.applicable_for_users: + res = frappe.db.sql("""select pf.name + from + `tabPOS Profile User` pfu, `tabPOS Profile` pf + where + pf.name = pfu.parent and pfu.user = %s and pf.name != %s and pf.company = %s + and pfu.default=1""", (row.user, self.name, self.company)) + + if row.default and res: + msgprint(_("Already set default in pos profile {0} for user {1}, kindly disabled default") + .format(res[0][0], row.user), raise_exception=1) + elif not row.default and not res: + msgprint(_("Row {0}: set atleast one default pos profile for user {1}") + .format(row.idx, row.user), raise_exception=1) def validate_all_link_fields(self): accounts = {"Account": [self.income_account, @@ -95,44 +99,58 @@ class POSProfile(Document): def get_series(): return frappe.get_meta("Sales Invoice").get_field("naming_series").options or "" -@frappe.whitelist() -def get_pos_profiles_for_user(user=None): - out = [] - if not user: - user = frappe.session.user +def pos_profile_query(doctype, txt, searchfield, start, page_len, filters): + user = frappe.session['user'] + company = filters.get('company') or frappe.defaults.get_user_default('company') - res = frappe.db.sql(''' - select - parent + args = { + 'user': user, + 'start': start, + 'company': company, + 'page_len': page_len, + 'txt': '%%%s%%' % txt + } + + pos_profile = frappe.db.sql("""select pf.name, pf.pos_profile_name from - `tabPOS Profile User` + `tabPOS Profile` pf, `tabPOS Profile User` pfu where - user = %s - ''', (user), as_dict=1) + pfu.parent = pf.name and pfu.user = %(user)s and pf.company = %(company)s + and (pf.name like %(txt)s or pf.pos_profile_name like %(txt)s) + and pf.disabled = 0 limit %(start)s, %(page_len)s""", args) - if not res: - company = frappe.defaults.get_user_default('company') - res = frappe.db.sql(''' - select - pos_profile_name + if not pos_profile: + del args['user'] + + pos_profile = frappe.db.sql("""select pf.name, pf.pos_profile_name from - `tabPOS Profile` + `tabPOS Profile` pf left join `tabPOS Profile User` pfu + on + pf.name = pfu.parent where - company = %s - ''', (company), as_dict=1) + ifnull(pfu.user, '') = '' and pf.company = %(company)s and + (pf.name like %(txt)s or pf.pos_profile_name like %(txt)s) + and pf.disabled = 0""", args) - out = [r.pos_profile_name for r in res] - - return out - - for r in res: - name = frappe.db.get_value('POS Profile', r.parent, 'pos_profile_name') - out.append(name) - - return out + return pos_profile @frappe.whitelist() -def get_pos_profile(pos_profile_name=None): - if not pos_profile_name: return - name = frappe.db.get_value('POS Profile', { 'pos_profile_name': pos_profile_name }) - return frappe.get_doc('POS Profile', name) +def set_default_profile(pos_profile, company): + modified = now() + user = frappe.session.user + company = frappe.db.escape(company) + + if pos_profile and company: + frappe.db.sql(""" update `tabPOS Profile User` pfu, `tabPOS Profile` pf + set + pfu.default = 0, pf.modified = %s, pf.modified_by = %s + where + pfu.user = %s and pf.name = pfu.parent and pf.company = %s + and pfu.default = 1""", (modified, user, user, company), auto_commit=1) + + frappe.db.sql(""" update `tabPOS Profile User` pfu, `tabPOS Profile` pf + set + pfu.default = 1, pf.modified = %s, pf.modified_by = %s + where + pfu.user = %s and pf.name = pfu.parent and pf.company = %s and pf.name = %s + """, (modified, user, user, company, pos_profile), auto_commit=1) diff --git a/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.json b/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.json index 22c7f722e2..2fb66d227b 100644 --- a/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.json +++ b/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.json @@ -12,6 +12,36 @@ "editable_grid": 1, "engine": "InnoDB", "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "default", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Default", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -54,7 +84,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-10-27 16:46:12.784244", + "modified": "2017-11-23 17:13:16.005475", "modified_by": "Administrator", "module": "Accounts", "name": "POS Profile User", diff --git a/erpnext/accounts/doctype/pos_profile_user/test_pos_profile_user.js b/erpnext/accounts/doctype/pos_profile_user/test_pos_profile_user.js new file mode 100644 index 0000000000..5449ab76a3 --- /dev/null +++ b/erpnext/accounts/doctype/pos_profile_user/test_pos_profile_user.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: POS Profile User", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new POS Profile User + () => frappe.tests.make('POS Profile User', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/accounts/doctype/pos_profile_user/test_pos_profile_user.py b/erpnext/accounts/doctype/pos_profile_user/test_pos_profile_user.py new file mode 100644 index 0000000000..5c69ab1fb8 --- /dev/null +++ b/erpnext/accounts/doctype/pos_profile_user/test_pos_profile_user.py @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt +from __future__ import unicode_literals + +import unittest + +class TestPOSProfileUser(unittest.TestCase): + pass diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index ad52dee973..f4b4c2f586 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -311,6 +311,14 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte }, is_pos: function(frm){ + this.set_pos_data(); + }, + + pos_profile: function() { + this.set_pos_data(); + }, + + set_pos_data: function() { if(this.frm.doc.is_pos) { if(!this.frm.doc.company) { this.frm.set_value("is_pos", 0); @@ -323,7 +331,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte callback: function(r) { if(!r.exc) { if(r.message && r.message.print_format) { - frm.pos_print_format = r.message.print_format; + me.frm.pos_print_format = r.message.print_format; } me.frm.script_manager.trigger("update_stock"); frappe.model.set_default_values(me.frm.doc); @@ -540,6 +548,19 @@ frappe.ui.form.on('Sales Invoice', { } }; }); + + frm.set_query('pos_profile', function(doc) { + if(!doc.company) { + frappe.throw(_('Please set Company')); + } + + return { + query: 'erpnext.accounts.doctype.pos_profile.pos_profile.pos_profile_query', + filters: { + company: doc.company + } + }; + }); }, //When multiple companies are set up. in case company name is changed set default company address company:function(frm){ diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 6a54164ea5..6c862670c9 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -294,21 +294,23 @@ class SalesInvoice(SellingController): return from erpnext.stock.get_item_details import get_pos_profile_item_details, get_pos_profile - pos = get_pos_profile(self.company) + if not self.pos_profile: + pos_profile = get_pos_profile(self.company) or {} + self.pos_profile = pos_profile.get('name') + + pos = {} + if self.pos_profile: + pos = frappe.get_doc('POS Profile', self.pos_profile) if not self.get('payments') and not for_validate: - pos_profile = frappe.get_doc('POS Profile', pos.name) if pos else None - update_multi_mode_option(self, pos_profile) + update_multi_mode_option(self, pos) if not self.account_for_change_amount: self.account_for_change_amount = frappe.db.get_value('Company', self.company, 'default_cash_account') if pos: - self.pos_profile = pos.name if not for_validate and not self.customer: self.customer = pos.customer - self.mode_of_payment = pos.mode_of_payment - # self.set_customer_defaults() if pos.get('account_for_change_amount'): self.account_for_change_amount = pos.get('account_for_change_amount') diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 2c28b9281f..97dec7fa3b 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -449,7 +449,7 @@ erpnext.patches.v8_9.remove_employee_from_salary_structure_parent erpnext.patches.v8_9.delete_gst_doctypes_for_outside_india_accounts erpnext.patches.v8_9.set_default_fields_in_variant_settings erpnext.patches.v8_9.update_billing_gstin_for_indian_account -erpnext.patches.v9_0.add_user_to_child_table_in_pos_profile +erpnext.patches.v9_0.add_user_to_child_table_in_pos_profile #2017-11-28 erpnext.patches.v9_0.set_schedule_date_for_material_request_and_purchase_order erpnext.patches.v9_0.student_admission_childtable_migrate erpnext.patches.v9_0.fix_subscription_next_date #2017-10-23 diff --git a/erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py b/erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py index c150cfa3e2..942f089bce 100644 --- a/erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py +++ b/erpnext/patches/v9_0/add_user_to_child_table_in_pos_profile.py @@ -5,23 +5,34 @@ from __future__ import unicode_literals import frappe def execute(): - doctype = 'POS Profile' - frappe.reload_doc('accounts', 'doctype', doctype) - frappe.reload_doc('accounts', 'doctype', 'pos_profile_user') - frappe.reload_doc('accounts', 'doctype', 'pos_item_group') - frappe.reload_doc('accounts', 'doctype', 'pos_customer_group') + if frappe.db.table_exists("POS Profile User"): + frappe.reload_doc('accounts', 'doctype', 'pos_profile_user') - for doc in frappe.get_all(doctype): - _doc = frappe.get_doc(doctype, doc.name) - user = frappe.db.get_value(doctype, doc.name, 'user') + frappe.db.sql(""" update `tabPOS Profile User`, + (select `tabPOS Profile User`.name from `tabPOS Profile User`, `tabPOS Profile` + where `tabPOS Profile`.name = `tabPOS Profile User`.parent + group by `tabPOS Profile User`.user, `tabPOS Profile`.company) as pfu + set + `tabPOS Profile User`.default = 1 + where `tabPOS Profile User`.name = pfu.name""") + else: + doctype = 'POS Profile' + frappe.reload_doc('accounts', 'doctype', doctype) + frappe.reload_doc('accounts', 'doctype', 'pos_profile_user') + frappe.reload_doc('accounts', 'doctype', 'pos_item_group') + frappe.reload_doc('accounts', 'doctype', 'pos_customer_group') - if not user: continue + for doc in frappe.get_all(doctype): + _doc = frappe.get_doc(doctype, doc.name) + user = frappe.db.get_value(doctype, doc.name, 'user') - _doc.append('applicable_for_users', { - 'user': user - }) - _doc.pos_profile_name = user + ' - ' + _doc.company - _doc.flags.ignore_validate = True - _doc.flags.ignore_mandatory = True - _doc.save() - + if not user: continue + + _doc.append('applicable_for_users', { + 'user': user, + 'default': 1 + }) + _doc.pos_profile_name = user + ' - ' + _doc.company + _doc.flags.ignore_validate = True + _doc.flags.ignore_mandatory = True + _doc.save() \ No newline at end of file diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 9b592fe629..92a788b9d1 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -322,7 +322,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ project: item.project || me.frm.doc.project, qty: item.qty || 1, stock_qty: item.stock_qty, - conversion_factor: item.conversion_factor + conversion_factor: item.conversion_factor, + pos_profile: me.frm.doc.doctype == 'Sales Invoice' ? me.frm.doc.pos_profile : '' } }, @@ -891,7 +892,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ "name": me.frm.doc.name, "is_return": cint(me.frm.doc.is_return), "update_stock": in_list(['Sales Invoice', 'Purchase Invoice'], me.frm.doc.doctype) ? cint(me.frm.doc.update_stock) : 0, - "conversion_factor": me.frm.doc.conversion_factor + "conversion_factor": me.frm.doc.conversion_factor, + "pos_profile": me.frm.doc.doctype == 'Sales Invoice' ? me.frm.doc.pos_profile : '' }; }, 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 b9694344e1..fb3023530d 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.js +++ b/erpnext/selling/page/point_of_sale/point_of_sale.js @@ -50,7 +50,7 @@ erpnext.pos.PointOfSale = class PointOfSale { this.set_online_status(); }, () => this.setup_company(), - () => this.setup_pos_profile(), + () => this.make_new_invoice(), () => { frappe.dom.unfreeze(); @@ -90,7 +90,6 @@ erpnext.pos.PointOfSale = class PointOfSale { this.cart = new POSCart({ frm: this.frm, wrapper: this.wrapper.find('.cart-container'), - pos_profile: this.pos_profile, events: { on_customer_change: (customer) => this.frm.set_value('customer', customer), on_field_change: (item_code, field, value) => { @@ -141,7 +140,7 @@ erpnext.pos.PointOfSale = class PointOfSale { make_items() { this.items = new POSItems({ wrapper: this.wrapper.find('.item-container'), - pos_profile: this.pos_profile, + frm: this.frm, events: { update_cart: (item, field, value) => { if(!this.frm.doc.customer) { @@ -292,68 +291,62 @@ erpnext.pos.PointOfSale = class PointOfSale { }) } - setup_pos_profile() { + change_pos_profile() { return new Promise((resolve) => { - - const load_default = () => { - this.pos_profile = { - company: this.company, - currency: frappe.defaults.get_default('currency'), - selling_price_list: frappe.defaults.get_default('selling_price_list') - }; - resolve(); - } - - const on_submit = ({ pos_profile }) => { - this.get_pos_profile_doc(pos_profile) - .then(doc => { - this.pos_profile = doc; - if (!this.pos_profile) { - load_default(); - } - resolve(); - }); - } - - frappe.call({ - method: 'erpnext.accounts.doctype.pos_profile.pos_profile.get_pos_profiles_for_user' - }).then((r) => { - if (r && r.message) { - const pos_profiles = r.message.filter(a => a); - - if (pos_profiles.length === 0) { - load_default(); - } else if(pos_profiles.length === 1) { - // load profile directly - on_submit({pos_profile: pos_profiles[0]}); - } else { - // ask prompt - frappe.prompt( - [{ fieldtype: 'Select', label: 'POS Profile', options: pos_profiles }], - on_submit, - __('Select POS Profile') - ); - } - } else { - frappe.dom.unfreeze(); - frappe.throw(__("POS Profile is required to use Point-of-Sale")); + const on_submit = ({ pos_profile, set_as_default }) => { + if (pos_profile) { + this.frm.doc.pos_profile = pos_profile; } - }); + + if (set_as_default) { + frappe.call({ + method: "erpnext.accounts.doctype.pos_profile.pos_profile.set_default_profile", + args: { + 'pos_profile': pos_profile, + 'company': this.frm.doc.company + } + }).then(() => { + this.on_change_pos_profile(); + }); + } else { + this.on_change_pos_profile(); + } + } + + frappe.prompt(this.get_promopt_fields(), + on_submit, + __('Select POS Profile') + ); }); } - get_pos_profile_doc(pos_profile_name) { - return new Promise(resolve => { - frappe.call({ - method: 'erpnext.accounts.doctype.pos_profile.pos_profile.get_pos_profile', - args: { - pos_profile_name - }, - callback: (r) => { - resolve(r.message); + on_change_pos_profile() { + this.set_pos_profile_data() + .then(() => { + this.reset_cart(); + if (this.items) { + this.items.reset_items(); } }); - }); + } + + get_promopt_fields() { + return [{ + fieldtype: 'Link', + label: __('POS Profile'), + options: 'POS Profile', + get_query: () => { + return { + query: 'erpnext.accounts.doctype.pos_profile.pos_profile.pos_profile_query', + filters: { + company: this.frm.doc.company + } + }; + } + }, { + fieldtype: 'Check', + label: __('Set as default') + }]; } setup_company() { @@ -378,9 +371,7 @@ erpnext.pos.PointOfSale = class PointOfSale { .then(() => this.set_pos_profile_data()) .then(() => { if (this.cart) { - this.cart.frm = this.frm; - this.cart.reset(); - this.items.reset_search_field(); + this.reset_cart(); } else { this.make_items(); this.make_cart(); @@ -391,29 +382,32 @@ erpnext.pos.PointOfSale = class PointOfSale { ]); } + reset_cart() { + this.cart.frm = this.frm; + this.cart.reset(); + this.items.reset_search_field(); + } + make_sales_invoice_frm() { const doctype = 'Sales Invoice'; return new Promise(resolve => { if (this.frm) { - this.frm = get_frm(this.pos_profile, this.frm); + this.frm = get_frm(this.frm); resolve(); } else { frappe.model.with_doctype(doctype, () => { - this.frm = get_frm(this.pos_profile); + this.frm = get_frm(); resolve(); }); } }); - function get_frm(pos_profile, _frm) { + function get_frm(_frm) { const page = $('
'); const frm = _frm || new _f.Frm(doctype, page, false); const name = frappe.model.make_new_doc_and_get_name(doctype, true); frm.refresh(name); frm.doc.items = []; - if(!frm.doc.company) { - frm.set_value('company', pos_profile.company); - } frm.doc.is_pos = 1; return frm; } @@ -426,6 +420,10 @@ erpnext.pos.PointOfSale = class PointOfSale { method: "set_missing_values", }).then((r) => { if(!r.exc) { + if (!this.frm.doc.pos_profile) { + frappe.dom.unfreeze(); + frappe.throw(__("POS Profile is required to use Point-of-Sale")); + } this.frm.script_manager.trigger("update_stock"); frappe.model.set_default_values(this.frm.doc); this.frm.cscript.calculate_taxes_and_totals(); @@ -433,8 +431,8 @@ erpnext.pos.PointOfSale = class PointOfSale { } resolve(); - }) - }) + }); + }); } prepare_menu() { @@ -458,6 +456,10 @@ erpnext.pos.PointOfSale = class PointOfSale { this.page.add_menu_item(__('POS Settings'), function() { frappe.set_route('Form', 'POS Settings'); }); + + this.page.add_menu_item(__('Change POS Profile'), function() { + me.change_pos_profile(); + }); } set_form_action() { @@ -478,12 +480,11 @@ erpnext.pos.PointOfSale = class PointOfSale { }; class POSCart { - constructor({frm, wrapper, pos_profile, events}) { + constructor({frm, wrapper, events}) { this.frm = frm; this.item_data = {}; this.wrapper = wrapper; this.events = events; - this.pos_profile = pos_profile; this.make(); this.bind_events(); } @@ -549,7 +550,7 @@ class POSCart { this.wrapper.find('.grand-total-value').text( format_currency(this.frm.doc.grand_total, this.frm.currency)); - const customer = this.frm.doc.customer || this.pos_profile.customer; + const customer = this.frm.doc.customer; this.customer_field.set_value(customer); } @@ -637,7 +638,6 @@ class POSCart { } make_customer_field() { - let customer = this.frm.doc.customer || this.pos_profile['customer']; this.customer_field = frappe.ui.form.make_control({ df: { fieldtype: 'Link', @@ -653,9 +653,7 @@ class POSCart { render_input: true }); - if (customer) { - this.customer_field.set_value(customer); - } + this.customer_field.set_value(this.frm.doc.customer); } make_numpad() { @@ -920,19 +918,22 @@ class POSCart { } class POSItems { - constructor({wrapper, pos_profile, events}) { + constructor({wrapper, frm, events}) { this.wrapper = wrapper; - this.pos_profile = pos_profile; + this.frm = frm; this.items = {}; this.events = events; - this.currency = this.pos_profile.currency; + this.currency = this.frm.doc.currency; this.make_dom(); this.make_fields(); this.init_clusterize(); this.bind_events(); + this.load_items_data(); + } + load_items_data() { // bootstrap with 20 items this.get_items() .then(({ items }) => { @@ -942,6 +943,12 @@ class POSItems { }); } + reset_items() { + this.wrapper.find('.pos-items').empty(); + this.init_clusterize(); + this.load_items_data(); + } + make_dom() { this.wrapper.html(`
@@ -1165,7 +1172,7 @@ class POSItems { args: { start, page_length, - 'price_list': this.pos_profile.selling_price_list, + 'price_list': this.frm.doc.selling_price_list, item_group, search_value } diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 15b903eecd..63c76bc2b5 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -394,7 +394,7 @@ def get_pos_profile_item_details(company, args, pos_profile=None): res = frappe._dict() if not pos_profile: - pos_profile = get_pos_profile(company) + pos_profile = get_pos_profile(company, args.get('pos_profile')) if pos_profile: for fieldname in ("income_account", "cost_center", "warehouse", "expense_account"): @@ -408,17 +408,32 @@ def get_pos_profile_item_details(company, args, pos_profile=None): return res @frappe.whitelist() -def get_pos_profile(company): - pos_profile = frappe.db.sql("""select * from `tabPOS Profile` where user = %s - and company = %s and ifnull(disabled,0) != 1""", (frappe.session['user'], company), as_dict=1) +def get_pos_profile(company, pos_profile=None, user=None): + if pos_profile: + return frappe.get_doc('POS Profile', pos_profile) + + if not user: + user = frappe.session['user'] + + pos_profile = frappe.db.sql("""select pf.* + from + `tabPOS Profile` pf, `tabPOS Profile User` pfu + where + pfu.parent = pf.name and pfu.user = %s and pf.company = %s + and pf.disabled = 0 and pfu.default=1""", (user, company), as_dict=1) if not pos_profile: - pos_profile = frappe.db.sql("""select * from `tabPOS Profile` - where ifnull(user,'') = '' and company = %s and ifnull(disabled,0) != 1""", company, as_dict=1) + pos_profile = frappe.db.sql("""select pf.* + from + `tabPOS Profile` pf left join `tabPOS Profile User` pfu + on + pf.name = pfu.parent + where + ifnull(pfu.user, '') = '' and pf.company = %s + and pf.disabled = 0""", (company), as_dict=1) return pos_profile and pos_profile[0] or None - def get_serial_nos_by_fifo(args): if frappe.db.get_single_value("Stock Settings", "automatically_set_serial_nos_based_on_fifo"): return "\n".join(frappe.db.sql_list("""select name from `tabSerial No`