Refactor multi pos profile selection in the pos invoice (#11721)

diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.json b/erpnext/accounts/doctype/pos_profile/pos_profile.json
index 2740ef2..6c09c6e 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 65b0e7c..c70526c 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 @@
 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 22c7f72..2fb66d2 100644
--- a/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.json
+++ b/erpnext/accounts/doctype/pos_profile_user/pos_profile_user.json
@@ -18,6 +18,36 @@
    "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, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "user", 
    "fieldtype": "Link", 
    "hidden": 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 0000000..5449ab7
--- /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 0000000..5c69ab1
--- /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 ad52dee..f4b4c2f 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -311,6 +311,14 @@
 	},
 
 	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 @@
 					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 @@
 				}
 			};
 		});
+
+		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 6a54164..6c86267 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -294,21 +294,23 @@
 			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 2c28b92..97dec7f 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -449,7 +449,7 @@
 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 c150cfa..942f089 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 @@
 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 9b592fe..92a788b 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -322,7 +322,8 @@
 							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 @@
 			"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 b969434..fb30235 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 @@
 				this.set_online_status();
 			},
 			() => this.setup_company(),
-			() => this.setup_pos_profile(),
+
 			() => this.make_new_invoice(),
 			() => {
 				frappe.dom.unfreeze();
@@ -90,7 +90,6 @@
 		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 @@
 	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 @@
 		})
 	}
 
-	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 @@
 					.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 @@
 		]);
 	}
 
+	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 = $('<div>');
 			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 @@
 				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 @@
 				}
 
 				resolve();
-			})
-		})
+			});
+		});
 	}
 
 	prepare_menu() {
@@ -458,6 +456,10 @@
 		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 @@
 };
 
 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 @@
 		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 @@
 	}
 
 	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 @@
 			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 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 @@
 			});
 	}
 
+	reset_items() {
+		this.wrapper.find('.pos-items').empty();
+		this.init_clusterize();
+		this.load_items_data();
+	}
+
 	make_dom() {
 		this.wrapper.html(`
 			<div class="fields">
@@ -1165,7 +1172,7 @@
 				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 15b903e..63c76bc 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -394,7 +394,7 @@
 	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 @@
 	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`