Merge pull request #6969 from rohitwaghchaure/pos_syncing_issue_and_enhancement

User can able to add multiple item group, customer group in the POS profile.
diff --git a/erpnext/accounts/doctype/pos_customer_group/__init__.py b/erpnext/accounts/doctype/pos_customer_group/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_customer_group/__init__.py
diff --git a/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.json b/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.json
new file mode 100644
index 0000000..4f6a675
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.json
@@ -0,0 +1,66 @@
+{
+ "allow_copy": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "beta": 0, 
+ "creation": "2016-11-16 15:27:16.413449", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "customer_group", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 1, 
+   "label": "Customer Group", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Customer Group", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }
+ ], 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "in_dialog": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 1, 
+ "max_attachments": 0, 
+ "modified": "2016-11-16 15:27:25.730507", 
+ "modified_by": "Administrator", 
+ "module": "Accounts", 
+ "name": "POS Customer Group", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.py b/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.py
new file mode 100644
index 0000000..85c1c9f
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_customer_group/pos_customer_group.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class POSCustomerGroup(Document):
+	pass
diff --git a/erpnext/accounts/doctype/pos_item_group/__init__.py b/erpnext/accounts/doctype/pos_item_group/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_item_group/__init__.py
diff --git a/erpnext/accounts/doctype/pos_item_group/pos_item_group.json b/erpnext/accounts/doctype/pos_item_group/pos_item_group.json
new file mode 100644
index 0000000..b278765
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_item_group/pos_item_group.json
@@ -0,0 +1,66 @@
+{
+ "allow_copy": 0, 
+ "allow_import": 0, 
+ "allow_rename": 0, 
+ "beta": 0, 
+ "creation": "2016-11-16 15:26:47.706713", 
+ "custom": 0, 
+ "docstatus": 0, 
+ "doctype": "DocType", 
+ "document_type": "", 
+ "editable_grid": 1, 
+ "engine": "InnoDB", 
+ "fields": [
+  {
+   "allow_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "item_group", 
+   "fieldtype": "Link", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 1, 
+   "label": "Item Group", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "Item Group", 
+   "permlevel": 0, 
+   "precision": "", 
+   "print_hide": 0, 
+   "print_hide_if_no_value": 0, 
+   "read_only": 0, 
+   "remember_last_selected_value": 0, 
+   "report_hide": 0, 
+   "reqd": 1, 
+   "search_index": 0, 
+   "set_only_once": 0, 
+   "unique": 0
+  }
+ ], 
+ "hide_heading": 0, 
+ "hide_toolbar": 0, 
+ "idx": 0, 
+ "image_view": 0, 
+ "in_create": 0, 
+ "in_dialog": 0, 
+ "is_submittable": 0, 
+ "issingle": 0, 
+ "istable": 1, 
+ "max_attachments": 0, 
+ "modified": "2016-11-16 15:27:32.263630", 
+ "modified_by": "Administrator", 
+ "module": "Accounts", 
+ "name": "POS Item Group", 
+ "name_case": "", 
+ "owner": "Administrator", 
+ "permissions": [], 
+ "quick_entry": 1, 
+ "read_only": 0, 
+ "read_only_onload": 0, 
+ "sort_field": "modified", 
+ "sort_order": "DESC", 
+ "track_seen": 0
+}
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/pos_item_group/pos_item_group.py b/erpnext/accounts/doctype/pos_item_group/pos_item_group.py
new file mode 100644
index 0000000..ceaa57b
--- /dev/null
+++ b/erpnext/accounts/doctype/pos_item_group/pos_item_group.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe
+from frappe.model.document import Document
+
+class POSItemGroup(Document):
+	pass
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.js b/erpnext/accounts/doctype/pos_profile/pos_profile.js
index c1aa0c3..bbbab73 100755
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.js
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.js
@@ -26,6 +26,30 @@
 	});
 });
 
+frappe.ui.form.on("POS Profile", {
+	setup: function(frm) {
+		frm.trigger("get_query_for_groups")
+	},
+
+	get_query_for_groups: function(frm) {
+		frm.fields_dict['item_groups'].grid.get_field('item_group').get_query = function(frm, cdt, cdn) {
+			return{
+				filters: {
+					'is_group': 0
+				}
+			}
+		}
+
+		frm.fields_dict['customer_groups'].grid.get_field('customer_group').get_query = function(frm, cdt, cdn) {
+			return{
+				filters: {
+					'is_group': 0
+				}
+			}
+		}
+	}
+})
+
 // Income Account
 // --------------------------------
 cur_frm.fields_dict['income_account'].get_query = function(doc,cdt,cdn) {
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.json b/erpnext/accounts/doctype/pos_profile/pos_profile.json
index f450121..e6cfd74 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.json
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.json
@@ -380,6 +380,114 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
+   "fieldname": "section_break_14", 
+   "fieldtype": "Section Break", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "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_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "item_groups", 
+   "fieldtype": "Table", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Item Groups", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "POS Item Group", 
+   "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_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "column_break_16", 
+   "fieldtype": "Column Break", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "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_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
+   "fieldname": "customer_groups", 
+   "fieldtype": "Table", 
+   "hidden": 0, 
+   "ignore_user_permissions": 0, 
+   "ignore_xss_filter": 0, 
+   "in_filter": 0, 
+   "in_list_view": 0, 
+   "label": "Customer Groups", 
+   "length": 0, 
+   "no_copy": 0, 
+   "options": "POS Customer Group", 
+   "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_on_submit": 0, 
+   "bold": 0, 
+   "collapsible": 0, 
+   "columns": 0, 
    "fieldname": "section_break_16", 
    "fieldtype": "Section Break", 
    "hidden": 0, 
@@ -548,34 +656,6 @@
    "bold": 0, 
    "collapsible": 0, 
    "columns": 0, 
-   "fieldname": "customer_group", 
-   "fieldtype": "Link", 
-   "hidden": 0, 
-   "ignore_user_permissions": 0, 
-   "ignore_xss_filter": 0, 
-   "in_filter": 0, 
-   "in_list_view": 0, 
-   "label": "Customer Group", 
-   "length": 0, 
-   "no_copy": 0, 
-   "options": "Customer Group", 
-   "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_on_submit": 0, 
-   "bold": 0, 
-   "collapsible": 0, 
-   "columns": 0, 
    "description": "", 
    "fieldname": "territory", 
    "fieldtype": "Link", 
@@ -951,8 +1031,8 @@
  "issingle": 0, 
  "istable": 0, 
  "max_attachments": 0, 
- "modified": "2016-11-03 15:53:33.820428", 
- "modified_by": "Administrator", 
+ "modified": "2016-11-17 00:20:51.377850", 
+ "modified_by": "rohit@erpnext.com", 
  "module": "Accounts", 
  "name": "POS Profile", 
  "owner": "Administrator", 
diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py
index 5f4d5bc..ef497bf 100644
--- a/erpnext/accounts/doctype/pos_profile/pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py
@@ -13,6 +13,7 @@
 	def validate(self):
 		self.check_for_duplicate()
 		self.validate_all_link_fields()
+		self.validate_duplicate_groups()
 
 	def check_for_duplicate(self):
 		res = frappe.db.sql("""select name, user from `tabPOS Profile`
@@ -37,6 +38,16 @@
 						"company": self.company, "name": link_dn}):
 					frappe.throw(_("{0} does not belong to Company {1}").format(link_dn, self.company))
 
+	def validate_duplicate_groups(self):
+		item_groups = [d.item_group for d in self.item_groups]
+		customer_groups = [d.customer_group for d in self.customer_groups]
+
+		if len(item_groups) != len(set(item_groups)):
+			frappe.throw(_("Duplicate item group found in the item group table"), title = "Duplicate Item Group")
+
+		if len(customer_groups) != len(set(customer_groups)):
+			frappe.throw(_("Duplicate customer group found in the cutomer group table"), title = "Duplicate Customer Group")
+
 	def before_save(self):
 		set_account_for_mode_of_payment(self)
 
diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
index 62274a3..9c6a114 100644
--- a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
+++ b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py
@@ -5,8 +5,47 @@
 
 import frappe
 import unittest
-
-# test_records = frappe.get_test_records('POS Profile')
+from erpnext.stock.get_item_details import get_pos_profile
+from erpnext.accounts.doctype.sales_invoice.pos import get_items_list, get_customers_list
 
 class TestPOSProfile(unittest.TestCase):
-	pass
+	def test_pos_profile(self):
+		make_pos_profile()
+
+		pos_profile = get_pos_profile("_Test Company") or {}
+		if pos_profile:
+			doc = frappe.get_doc("POS Profile", pos_profile.get("name"))
+			doc.append('item_groups', {'item_group': '_Test Item Group'})
+			doc.append('customer_groups', {'customer_group': '_Test Customer Group'})
+			doc.save()
+
+			items = get_items_list(doc)
+			customers = get_customers_list(doc)
+
+			products_count = frappe.db.sql(""" select count(name) from tabItem where item_group = '_Test Item Group'""", as_list=1)
+			customers_count = frappe.db.sql(""" select count(name) from tabCustomer where customer_group = '_Test Customer Group'""")
+
+			self.assertEquals(len(items), products_count[0][0])
+			self.assertEquals(len(customers), customers_count[0][0])
+
+		frappe.db.sql("delete from `tabPOS Profile`")
+
+def make_pos_profile():
+	pos_profile = frappe.get_doc({
+		"company": "_Test Company",
+		"cost_center": "_Test Cost Center - _TC",
+		"currency": "INR",
+		"doctype": "POS Profile",
+		"expense_account": "_Test Account Cost for Goods Sold - _TC",
+		"income_account": "Sales - _TC",
+		"name": "_Test POS Profile",
+		"naming_series": "_T-POS Profile-",
+		"selling_price_list": "_Test Price List",
+		"territory": "_Test Territory",
+		"warehouse": "_Test Warehouse - _TC",
+		"write_off_account": "_Test Write Off - _TC",
+		"write_off_cost_center": "_Test Write Off Cost Center - _TC"
+	})
+
+	if not frappe.db.exists("POS Profile", "_Test POS Profile"):
+		pos_profile.insert()
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py
index 1d1a122..e5c86dc 100644
--- a/erpnext/accounts/doctype/sales_invoice/pos.py
+++ b/erpnext/accounts/doctype/sales_invoice/pos.py
@@ -30,10 +30,16 @@
 	return {
 		'doc': doc,
 		'default_customer': pos_profile.get('customer'),
-		'items': get_items(doc, pos_profile),
-		'customers': get_customers(pos_profile, doc, company_data.default_currency),
-		'pricing_rules': get_pricing_rules(doc),
+		'items': get_items_list(pos_profile),
+		'customers': get_customers_list(pos_profile),
+		'serial_no_data': get_serial_no_data(pos_profile, doc.company),
+		'batch_no_data': get_batch_no_data(),
+		'tax_data': get_item_tax_data(),
+		'price_list_data': get_price_list_data(doc.selling_price_list),
+		'bin_data': get_bin_data(pos_profile),
+		'pricing_rules': get_pricing_rule_data(doc),
 		'print_template': print_template,
+		'pos_profile': pos_profile,
 		'meta': {
 			'invoice': frappe.get_meta('Sales Invoice'),
 			'items': frappe.get_meta('Sales Invoice Item'),
@@ -104,63 +110,116 @@
 	for tax in taxes:
 		doc.append('taxes', tax)
 
-def get_items(doc, pos_profile):
-	item_list = []
-	for item in frappe.get_all("Item", fields=["*"], filters={'disabled': 0, 'has_variants': 0, 'is_sales_item': 1}):
-		item_doc = frappe.get_doc('Item', item.name)
-		if item_doc.taxes:
-			item.taxes = json.dumps(dict(([d.tax_type, d.tax_rate] for d in
-						item_doc.get("taxes"))))
+def get_items_list(pos_profile):
+	cond = "1=1"
+	item_groups = []
+	if pos_profile.get('item_groups'):
+		# Get items based on the item groups defined in the POS profile
 
-		item.price_list_rate = frappe.db.get_value('Item Price', {'item_code': item.name,
-									'price_list': doc.selling_price_list}, 'price_list_rate') or 0
-		item.default_warehouse = pos_profile.get('warehouse') or \
-			get_item_warehouse_for_company(doc.company, item.default_warehouse) or None
-		item.expense_account = pos_profile.get('expense_account') or item.expense_account
-		item.income_account = pos_profile.get('income_account') or item_doc.income_account
-		item.cost_center = pos_profile.get('cost_center') or item_doc.selling_cost_center
-		item.actual_qty = frappe.db.get_value('Bin', {'item_code': item.name,
-								'warehouse': item.default_warehouse}, 'actual_qty') or 0
-		item.serial_nos = get_serial_nos(item, pos_profile, doc.company)
-		item.batch_nos = frappe.db.sql_list("""select name from `tabBatch` where ifnull(expiry_date, '4000-10-10') > curdate()
-			and item = %(item_code)s""", {'item_code': item.item_code})
+		cond = "item_group in (%s)"%(', '.join(['%s']*len(pos_profile.get('item_groups'))))
+		item_groups = [d.item_group for d in pos_profile.get('item_groups')]
 
-		item_list.append(item)
+	return frappe.db.sql(""" 
+		select
+			name, item_code, item_name, description, item_group, expense_account, has_batch_no,
+			has_serial_no, expense_account, selling_cost_center, stock_uom, image, default_warehouse
+		from
+			tabItem
+		where
+			disabled = 0 and has_variants = 0 and is_sales_item = 1 and {cond}
+		""".format(cond=cond), tuple(item_groups), as_dict=1)
 
-	return item_list
+def get_customers_list(pos_profile):
+	cond = "1=1"
+	customer_groups = []
+	if pos_profile.get('customer_groups'):
+		# Get customers based on the customer groups defined in the POS profile
 
-def get_item_warehouse_for_company(company, warehouse):
-	if frappe.db.get_value('Warehouse', warehouse, 'company') != company:
-		warehouse = None
-	return warehouse
+		cond = "customer_group in (%s)"%(', '.join(['%s']*len(pos_profile.get('customer_groups'))))
+		customer_groups = [d.customer_group for d in pos_profile.get('customer_groups')]
 
-def get_serial_nos(item, pos_profile, company):
+	return frappe.db.sql(""" select name, customer_name, customer_group,
+		territory from tabCustomer where disabled = 0
+		and {cond}""".format(cond=cond), tuple(customer_groups), as_dict=1) or {}
+
+def get_serial_no_data(pos_profile, company):
+	# get itemwise serial no data
+	# example {'Nokia Lumia 1020': {'SN0001': 'Pune'}}
+	# where Nokia Lumia 1020 is item code, SN0001 is serial no and Pune is warehouse
+
 	cond = "1=1"
 	if pos_profile.get('update_stock') and pos_profile.get('warehouse'):
 		cond = "warehouse = '{0}'".format(pos_profile.get('warehouse'))
 
-	serial_nos = frappe.db.sql("""select name, warehouse from `tabSerial No` where {0}
-				and item_code = %(item_code)s and company = %(company)s
-				""".format(cond), {'item_code': item.item_code, 'company': company}, as_dict=1)
+	serial_nos = frappe.db.sql("""select name, warehouse, item_code from `tabSerial No` where {0}
+				and company = %(company)s """.format(cond), {'company': company}, as_dict=1)
 
-	serial_no_list = {}
-	for serial_no in serial_nos:
-		serial_no_list[serial_no.name] = serial_no.warehouse
+	itemwise_serial_no = {}
+	for sn in serial_nos:
+		if sn.item_code not in itemwise_serial_no:
+			itemwise_serial_no.setdefault(sn.item_code, {})
+		itemwise_serial_no[sn.item_code][sn.name] = sn.warehouse
 
-	return serial_no_list
+	return itemwise_serial_no
 
-def get_customers(pos_profile, doc, company_currency):
-	filters = {'disabled': 0}
-	customer_list = []
-	customers = frappe.get_all("Customer", fields=["*"], filters = filters)
+def get_batch_no_data():
+	# get itemwise batch no data
+	# exmaple: {'LED-GRE': [Batch001, Batch002]}
+	# where LED-GRE is item code, SN0001 is serial no and Pune is warehouse
 
-	for customer in customers:
-		customer_currency = get_party_account_currency('Customer', customer.name, doc.company) or doc.currency
-		if customer_currency == doc.currency or customer_currency == company_currency:
-			customer_list.append(customer)
-	return customer_list
+	itemwise_batch = {}
+	batches = frappe.db.sql("""select name, item from `tabBatch`
+		where ifnull(expiry_date, '4000-10-10') >= curdate()""", as_dict=1)
 
-def get_pricing_rules(doc):
+	for batch in batches:
+		if batch.item not in itemwise_batch:
+			itemwise_batch.setdefault(batch.item, [])
+		itemwise_batch[batch.item].append(batch.name)
+
+	return itemwise_batch
+
+def get_item_tax_data():
+	# get default tax of an item
+	# example: {'Consulting Services': {'Excise 12 - TS': '12.000'}}
+
+	itemwise_tax = {}
+	taxes = frappe.db.sql(""" select parent, tax_type, tax_rate from `tabItem Tax`""", as_dict=1)
+
+	for tax in taxes:
+		if tax.parent not in itemwise_tax:
+			itemwise_tax.setdefault(tax.parent, {})
+		itemwise_tax[tax.parent][tax.tax_type] = tax.tax_rate
+
+	return itemwise_tax
+
+def get_price_list_data(selling_price_list):
+	itemwise_price_list = {}
+	price_lists = frappe.db.sql("""Select ifnull(price_list_rate, 0) as price_list_rate,
+		item_code from `tabItem Price` ip where price_list = %(price_list)s""",
+		{'price_list': selling_price_list}, as_dict=1)
+
+	for item in price_lists:
+		itemwise_price_list[item.item_code] = item.price_list_rate
+
+	return itemwise_price_list
+
+def get_bin_data(pos_profile):
+	itemwise_bin_data = {}
+	cond = "1=1"
+	if pos_profile.get('warehouse'):
+		cond = "warehouse = '{0}'".format(pos_profile.get('warehouse'))
+
+	bin_data = frappe.db.sql(""" select item_code, warehouse, actual_qty from `tabBin`
+		where actual_qty > 0 and {cond}""".format(cond=cond), as_dict=1)
+
+	for bins in bin_data:
+		if bins.item_code not in itemwise_bin_data:
+			itemwise_bin_data.setdefault(bins.item_code, {})
+		itemwise_bin_data[bins.item_code][bins.warehouse] = bins.actual_qty
+
+	return itemwise_bin_data
+
+def get_pricing_rule_data(doc):
 	pricing_rules = ""
 	if doc.ignore_pricing_rule == 0:
 		pricing_rules = frappe.db.sql(""" Select * from `tabPricing Rule` where docstatus < 2
diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
index 511eeaa..c4f275a 100644
--- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -7,6 +7,7 @@
 from frappe.utils import nowdate, add_days, flt, nowdate
 from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
 from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
+from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
 from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
 from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency
 from erpnext.stock.doctype.serial_no.serial_no import SerialNoWarehouseError
@@ -467,7 +468,7 @@
 
 	def test_pos_gl_entry_with_perpetual_inventory(self):
 		set_perpetual_inventory()
-		self.make_pos_profile()
+		make_pos_profile()
 
 		self._insert_purchase_receipt()
 		pos = copy.deepcopy(test_records[1])
@@ -486,7 +487,7 @@
 
 	def test_pos_change_amount(self):
 		set_perpetual_inventory()
-		self.make_pos_profile()
+		make_pos_profile()
 
 		self._insert_purchase_receipt()
 		pos = copy.deepcopy(test_records[1])
@@ -508,7 +509,7 @@
 
 		set_perpetual_inventory()
 
-		self.make_pos_profile()
+		make_pos_profile()
 		self._insert_purchase_receipt()
 
 		pos = copy.deepcopy(test_records[1])
@@ -572,26 +573,6 @@
 
 		frappe.db.sql("delete from `tabPOS Profile`")
 
-	def make_pos_profile(self):
-		pos_profile = frappe.get_doc({
-			"company": "_Test Company",
-			"cost_center": "_Test Cost Center - _TC",
-			"currency": "INR",
-			"doctype": "POS Profile",
-			"expense_account": "_Test Account Cost for Goods Sold - _TC",
-			"income_account": "Sales - _TC",
-			"name": "_Test POS Profile",
-			"naming_series": "_T-POS Profile-",
-			"selling_price_list": "_Test Price List",
-			"territory": "_Test Territory",
-			"warehouse": "_Test Warehouse - _TC",
-			"write_off_account": "_Test Write Off - _TC",
-			"write_off_cost_center": "_Test Write Off Cost Center - _TC"
-		})
-
-		if not frappe.db.exists("POS Profile", "_Test POS Profile"):
-			pos_profile.insert()
-			
 	def test_sales_invoice_gl_entry_with_perpetual_inventory_no_item_code(self):
 		set_perpetual_inventory()
 
diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js
index 32e9b3a..26bf3ea 100644
--- a/erpnext/accounts/page/pos/pos.js
+++ b/erpnext/accounts/page/pos/pos.js
@@ -25,7 +25,6 @@
 		this.set_indicator();
 		this.onload();
 		this.make_menu_list();
-		this.set_interval_for_si_sync();
 		this.si_docs = this.get_doc_from_localstorage();
 	},
 
@@ -73,8 +72,6 @@
 		this.get_data_from_server(function(){
 			me.create_new();
 		});
-
-		this.check_internet_connection();
 	},
 
 	make_menu_list: function(){
@@ -204,13 +201,10 @@
 			freeze: true,
 			freeze_message: __("Master data syncing, it might take some time"),
 			callback: function(r){
-				window.items = r.message.items;
-				window.customers = r.message.customers;
-				window.pricing_rules = r.message.pricing_rules;
-				window.meta = r.message.meta;
-				window.print_template = r.message.print_template;
-				me.default_customer = r.message.default_customer || null;
+				me.init_master_data(r)
 				localStorage.setItem('doc', JSON.stringify(r.message.doc));
+				me.set_interval_for_si_sync();
+				me.check_internet_connection();
 				if(callback){
 					callback();
 				}
@@ -218,6 +212,22 @@
 		})
 	},
 
+	init_master_data: function(r){
+		var me = this;
+		this.meta = r.message.meta;
+		this.item_data = r.message.items;
+		this.customers = r.message.customers;
+		this.serial_no_data = r.message.serial_no_data;
+		this.batch_no_data = r.message.batch_no_data;
+		this.tax_data = r.message.tax_data;
+		this.price_list_data = r.message.price_list_data;
+		this.bin_data = r.message.bin_data;
+		this.pricing_rules = r.message.pricing_rules;
+		this.print_template = r.message.print_template;
+		this.pos_profile_data = r.message.pos_profile;
+		this.default_customer = r.message.default_customer || null;
+	},
+
 	save_previous_entry : function(){
 		if(this.frm.doc.items.length > 0){
 			this.create_invoice()
@@ -233,20 +243,19 @@
 	},
 
 	load_data: function(load_doc){
-		this.items = window.items;
-		this.customers = window.customers;
-		this.pricing_rules = window.pricing_rules;
+		var me = this;
 
+		this.items = this.item_data;
 		if(load_doc) {
 			this.frm.doc =  JSON.parse(localStorage.getItem('doc'));
 		}
 
-		$.each(window.meta, function(i, data){
+		$.each(this.meta, function(i, data){
 			frappe.meta.sync(data)
 		})
 
 		this.print_template = frappe.render_template("print_template",
-			{content: window.print_template, title:"POS",
+			{content: this.print_template, title:"POS",
 			base_url: frappe.urllib.get_base_url(), print_css: frappe.boot.print_css})
 	},
 
@@ -387,12 +396,12 @@
 		var $wrap = me.wrapper.find(".item-list");
 		me.wrapper.find(".item-list").empty();
 
-		if (this.items) {
+		if (this.items.length > 0) {
 			$.each(this.items, function(index, obj) {
 				if(index < 30){
 					$(frappe.render_template("pos_item", {
 						item_code: obj.name,
-						item_price: format_currency(obj.price_list_rate, me.frm.doc.currency),
+						item_price: format_currency(me.price_list_data[obj.name], me.frm.doc.currency),
 						item_name: obj.name===obj.item_name ? "" : obj.item_name,
 						item_image: obj.image ? "url('" + obj.image + "')" : null,
 						color: frappe.get_palette(obj.item_name),
@@ -400,6 +409,8 @@
 					})).tooltip().appendTo($wrap);
 				}
 			});
+		} else {
+			$("<h4>Searching record not found.</h4>").appendTo($wrap)
 		}
 
 		if(this.items.length == 1
@@ -426,7 +437,7 @@
 		this.item_batch_no = {};
 
 		if(item_code){
-			return $.grep(window.items, function(item){
+			return $.grep(this.item_data, function(item){
 				if(item.item_code == item_code ){
 					return true
 				}
@@ -439,14 +450,15 @@
 		search_status = true
 
 		if(key){
-			return $.grep(window.items, function(item){
+			return $.grep(this.item_data, function(item){
 				if(search_status){
-					if(in_list(item.batch_nos, me.search.$input.val())){
+					if(in_list(me.batch_no_data[item.item_code], me.search.$input.val())){
 						search_status = false;
 						return me.item_batch_no[item.item_code] = me.search.$input.val()
-					} else if(in_list(Object.keys(item.serial_nos), me.search.$input.val())) {
+					} else if( me.serial_no_data[item.item_code]
+						&& in_list(Object.keys(me.serial_no_data[item.item_code]), me.search.$input.val())) {
 						search_status = false;
-						me.item_serial_no[item.item_code] = [me.search.$input.val(), item.serial_nos[me.search.$input.val()]]
+						me.item_serial_no[item.item_code] = [me.search.$input.val(), me.serial_no_data[item.item_code][me.search.$input.val()]]
 						return true
 					} else if(item.barcode == me.search.$input.val()) {
 						search_status = false;
@@ -458,7 +470,7 @@
 				}
 			})
 		}else{
-			return window.items;
+			return this.item_data;
 		}
 	},
 
@@ -611,18 +623,18 @@
 		this.child.description = this.items[0].description;
 		this.child.qty = 1;
 		this.child.item_group = this.items[0].item_group;
-		this.child.cost_center = this.items[0].cost_center;
-		this.child.income_account = this.items[0].income_account;
+		this.child.cost_center = this.pos_profile_data['cost_center'] || this.items[0].cost_center;
+		this.child.income_account = this.pos_profile_data['income_account'] || this.items[0].income_account;
 		this.child.warehouse = (this.item_serial_no[this.child.item_code]
-			? this.item_serial_no[this.child.item_code][1] : this.items[0].default_warehouse);
-		this.child.price_list_rate = flt(this.items[0].price_list_rate, 9) / flt(this.frm.doc.conversion_rate, 9);
-		this.child.rate = flt(this.items[0].price_list_rate, 9) / flt(this.frm.doc.conversion_rate, 9);
-		this.child.actual_qty = this.items[0].actual_qty;
+			? this.item_serial_no[this.child.item_code][1] : (this.pos_profile_data['warehouse'] || this.items[0].default_warehouse) );
+		this.child.price_list_rate = flt(this.price_list_data[this.child.item_code], 9) / flt(this.frm.doc.conversion_rate, 9);
+		this.child.rate = flt(this.price_list_data[this.child.item_code], 9) / flt(this.frm.doc.conversion_rate, 9);
+		this.child.actual_qty = me.get_actual_qty(this.items[0]);
 		this.child.amount = flt(this.child.qty) * flt(this.child.rate);
 		this.child.batch_no = this.item_batch_no[this.child.item_code];
 		this.child.serial_no = (this.item_serial_no[this.child.item_code]
 			? this.item_serial_no[this.child.item_code][0] : '');
-		this.child.item_tax_rate = this.items[0].taxes;
+		this.child.item_tax_rate = JSON.stringify(this.tax_data[this.child.item_code]);
 	},
 
 	update_paid_amount_status: function(update_paid_amount){
@@ -668,7 +680,7 @@
 				item_code: d.item_code,
 				item_name: (d.item_name===d.item_code || !d.item_name) ? "" : ("<br>" + d.item_name),
 				qty: d.qty,
-				actual_qty: d.actual_qty,
+				actual_qty: me.actual_qty,
 				projected_qty: d.projected_qty,
 				rate: format_number(d.rate, me.frm.doc.currency),
 				amount: format_currency(d.amount, me.frm.doc.currency)
@@ -1064,8 +1076,18 @@
 	},
 
 	validate_warehouse: function(){
-		if(!this.items[0].default_warehouse){
+		if(!this.items[0].default_warehouse && !this.pos_profile_data['warehouse']){
 			frappe.throw(__("Default warehouse is required for selected item"))
 		}
+	},
+
+	get_actual_qty: function(item) {
+		this.actual_qty = 0.0;
+		var warehouse = this.pos_profile_data['warehouse'] || item.default_warehouse;
+		if(warehouse && this.bin_data[item.item_code]) {
+			this.actual_qty = this.bin_data[item.item_code][warehouse] || 0;
+		}
+
+		return this.actual_qty
 	}
 })
\ No newline at end of file