[pos][minor] fixed sales_invoice.js for pos view
diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py
index bfea0bb..0538323 100644
--- a/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -261,13 +261,11 @@
 			if d.purchase_order:
 				submitted = sql("select name from `tabPurchase Order` where docstatus = 1 and name = '%s'" % d.purchase_order)
 				if not submitted:
-					msgprint("Purchase Order : "+ cstr(d.purchase_order) +" is not submitted")
-					raise Exception , "Validation Error."
+					webnotes.throw("Purchase Order : "+ cstr(d.purchase_order) +" is not submitted")
 			if d.purchase_receipt:
 				submitted = sql("select name from `tabPurchase Receipt` where docstatus = 1 and name = '%s'" % d.purchase_receipt)
 				if not submitted:
-					msgprint("Purchase Receipt : "+ cstr(d.purchase_receipt) +" is not submitted")
-					raise Exception , "Validation Error."
+					webnotes.throw("Purchase Receipt : "+ cstr(d.purchase_receipt) +" is not submitted")
 					
 					
 	def update_against_document_in_jv(self):
diff --git a/accounts/doctype/sales_invoice/pos.js b/accounts/doctype/sales_invoice/pos.js
index 1c21fbe..0bae8a3 100644
--- a/accounts/doctype/sales_invoice/pos.js
+++ b/accounts/doctype/sales_invoice/pos.js
@@ -16,7 +16,7 @@
 				<div class="col-sm-6">\
 					<div class="pos-bill">\
 						<div class="item-cart">\
-							<table class="table table-condensed table-hover" id="cart"  style="table-layout: fixed;">\
+							<table class="table table-condensed table-hover" id="cart" style="table-layout: fixed;">\
 								<thead>\
 									<tr>\
 										<th style="width: 50%">Item</th>\
@@ -160,13 +160,10 @@
 			parent: this.wrapper.find(".barcode-area")
 		});
 		this.barcode.make_input();
-		this.barcode.$input.on("keypress", function() {
-			setTimeout(function() { me.barcode_timeout(); }, 1000);
+		this.barcode.$input.on("change", function() {
+			setTimeout(me.add_item_thru_barcode(), 1000);
 		});
 	},
-	barcode_timeout: function() {
-		me.add_item_thru_barcode();
-	},
 	make_item_list: function() {
 		var me = this;
 		wn.call({
@@ -181,12 +178,13 @@
 				me.wrapper.find(".item-list").empty();
 				$.each(r.message, function(index, obj) {
 					if (obj.image)
-						image = '<img src="' + obj.image + '" class="img-responsive" style="border: 1px solid #eee;">';
+						image = '<img src="' + obj.image + '" class="img-responsive" \
+								style="border:1px solid #eee;height:140px;width:122px;">';
 					else
 						image = '<div class="missing-image"><i class="icon-camera"></i></div>';
 
 					$(repl('<div class="col-xs-3 pos-item" data-item_code="%(item_code)s">\
-								%(item_image)s\
+								<div>%(item_image)s</div>\
 								<div class="small">%(item_code)s</div>\
 								<div class="small">%(item_name)s</div>\
 								<div class="small">%(item_price)s</div>\
@@ -332,7 +330,6 @@
 	},
 	add_item_thru_barcode: function() {
 		var me = this;
-		clearTimeout();
 		wn.call({
 			method: 'accounts.doctype.sales_invoice.pos.get_item_from_barcode',
 			args: {barcode: this.barcode.$input.val()},
@@ -363,6 +360,7 @@
 		$.each(child, function(i, d) {
 			for (var i in selected_items) {
 				if (d.item_code == selected_items[i]) {
+					// cur_frm.fields_dict["entries"].grid.grid_rows[d.idx].remove();
 					wn.model.clear_doc(d.doctype, d.name);
 				}
 			}
@@ -401,6 +399,7 @@
 						"total_amount": $(".grand-total").text()
 					});
 					dialog.show();
+					cur_frm.pos.barcode.$input.focus();
 					
 					dialog.get_input("total_amount").attr("disabled", "disabled");
 					
diff --git a/accounts/doctype/sales_invoice/sales_invoice.js b/accounts/doctype/sales_invoice/sales_invoice.js
index e2eeeac..85550c4 100644
--- a/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/accounts/doctype/sales_invoice/sales_invoice.js
@@ -93,14 +93,13 @@
 						}
 					});
 				});
-			
-			if (cint(sys_defaults.fs_pos_view)===1)
-				cur_frm.cscript.pos_btn();
-				
 		} else {
 			// hide shown pos for submitted records
 			if(cur_frm.pos_active) cur_frm.cscript.toggle_pos(false);
 		}
+
+		if(cint(sys_defaults.fs_pos_view)===1)
+			cur_frm.cscript.pos_btn();
 	},
 
 	pos_btn: function() {
@@ -123,6 +122,9 @@
 	},
 
 	toggle_pos: function(show) {
+		// if(cint(sys_defaults.fs_pos_view)===0) return;
+		// if(!(this.frm.doc.is_pos && this.frm.doc.docstatus===0)) return;
+		
 		if (!this.frm.doc.selling_price_list)
 			msgprint(wn._("Please select Price List"))
 		else {
diff --git a/config.json b/config.json
index c9d1aa7..5412b01 100644
--- a/config.json
+++ b/config.json
@@ -1,4 +1,5 @@
 {
+	"app_name": "ERPNext",
 	"modules": {
 		"Selling": {
 			"link": "selling-home",
diff --git a/selling/doctype/sales_common/sales_common.js b/selling/doctype/sales_common/sales_common.js
index dea94b8..5c0c96a 100644
--- a/selling/doctype/sales_common/sales_common.js
+++ b/selling/doctype/sales_common/sales_common.js
@@ -95,7 +95,7 @@
 						return{
 							query : "selling.doctype.sales_common.sales_common.get_batch_no",
 							filters: {
-								'item': item.item_code,
+								'item_code': item.item_code,
 								'posting_date': me.frm.doc.posting_date
 							}
 						}
diff --git a/selling/doctype/sales_common/sales_common.py b/selling/doctype/sales_common/sales_common.py
index 3c43c1e..baa8850 100644
--- a/selling/doctype/sales_common/sales_common.py
+++ b/selling/doctype/sales_common/sales_common.py
@@ -340,7 +340,7 @@
 					and batch_no like '%(txt)s' 
 					and exists(select * from `tabBatch` 
 							where name = sle.batch_no 
-								and expiry_date >= '%(posting_date)s' 
+								and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s') 
 								and docstatus != 2) 
 					%(mcond)s
 				group by batch_no having sum(actual_qty) > 0 
@@ -353,11 +353,11 @@
 		return webnotes.conn.sql("""select name from tabBatch 
 				where docstatus != 2 
 					and item = '%(item_code)s' 
-					and expiry_date >= '%(posting_date)s' 
+					and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s')
 					and name like '%(txt)s' 
 					%(mcond)s 
 				order by name desc 
 				limit %(start)s, %(page_len)s""" % {'item_code': filters['item_code'], 
 				'posting_date': filters['posting_date'], 'txt': "%%%s%%" % txt, 
 				'mcond':get_match_cond(doctype, searchfield),'start': start, 
-				'page_len': page_len})
\ No newline at end of file
+				'page_len': page_len})
diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py
index a9bb7a2..8e3ed70 100644
--- a/selling/doctype/sales_order/sales_order.py
+++ b/selling/doctype/sales_order/sales_order.py
@@ -126,8 +126,9 @@
 		self.validate_mandatory()
 		self.validate_proj_cust()
 		self.validate_po()
-		self.validate_uom_is_integer("stock_uom", "qty")		
+		self.validate_uom_is_integer("stock_uom", "qty")
 		self.validate_for_items()
+		self.validate_warehouse_user()
 		sales_com_obj = get_obj(dt = 'Sales Common')
 		sales_com_obj.check_active_sales_items(self)
 		sales_com_obj.check_conversion_rate(self)
@@ -147,6 +148,16 @@
 		if not self.doc.billing_status: self.doc.billing_status = 'Not Billed'
 		if not self.doc.delivery_status: self.doc.delivery_status = 'Not Delivered'
 		
+		
+	def validate_warehouse_user(self):
+		from stock.utils import validate_warehouse_user
+		
+		warehouses = list(set([d.reserved_warehouse for d in 
+			self.doclist.get({"doctype": self.tname}) if d.reserved_warehouse]))
+				
+		for w in warehouses:
+			validate_warehouse_user(w)
+		
 	def validate_with_previous_doc(self):
 		super(DocType, self).validate_with_previous_doc(self.tname, {
 			"Quotation": {
diff --git a/selling/doctype/sales_order/test_sales_order.py b/selling/doctype/sales_order/test_sales_order.py
index 9fd16e8..7b72271 100644
--- a/selling/doctype/sales_order/test_sales_order.py
+++ b/selling/doctype/sales_order/test_sales_order.py
@@ -272,6 +272,29 @@
 		self.check_reserved_qty(sbom_test_records[0][2]["item_code"], 
 			so.doclist[1].reserved_warehouse, 20.0)
 
+	def test_warehouse_user(self):
+		webnotes.session.user = "test@example.com"
+
+		webnotes.bean("Profile", "test@example.com").get_controller()\
+			.add_roles("Sales User", "Sales Manager", "Material User", "Material Manager")
+			
+		webnotes.bean("Profile", "test2@example.com").get_controller()\
+			.add_roles("Sales User", "Sales Manager", "Material User", "Material Manager")
+
+
+		from stock.utils import UserNotAllowedForWarehouse
+		so = webnotes.bean(copy = test_records[0])
+		so.doc.company = "_Test Company 1"
+		so.doc.conversion_rate = 0.02
+		so.doc.plc_conversion_rate = 0.02
+		so.doclist[1].reserved_warehouse = "_Test Warehouse 2 - _TC1"
+		self.assertRaises(UserNotAllowedForWarehouse, so.insert)
+
+		webnotes.session.user = "test2@example.com"
+		so.insert()
+
+		webnotes.session.user = "Administrator"
+
 test_dependencies = ["Sales BOM"]
 	
 test_records = [
diff --git a/stock/doctype/purchase_receipt/purchase_receipt_list.js b/stock/doctype/purchase_receipt/purchase_receipt_list.js
deleted file mode 100644
index bc0c9f6..0000000
--- a/stock/doctype/purchase_receipt/purchase_receipt_list.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
-// License: GNU General Public License v3. See license.txt
-
-// render
-wn.listview_settings['Purchase Receipt'] = {
-	add_fields: ["group_concat(`tabPurchase Receipt Item`.prevdoc_docname) \
-		as purchase_order_no"],
-	add_columns: [{"content":"purchase_order_no", width:"30%"}],
-	group_by: "`tabPurchase Receipt`.name",
-	prepare_data: function(data) {
-		if(data.purchase_order_no) {
-			data.purchase_order_no = $.unique(data.purchase_order_no.split(","));
-			var po_list = [];
-			$.each(data.purchase_order_no, function(i, v){
-				if(po_list.indexOf(v)==-1) po_list.push(
-					repl("<a href=\"#Form/Purchase Order/%(name)s\">%(name)s</a>",
-					{name: v}));
-			});
-			data.purchase_order_no = po_list.join(", ");
-		}
-	}	
-};
diff --git a/stock/doctype/stock_entry/test_stock_entry.py b/stock/doctype/stock_entry/test_stock_entry.py
index f33cfa3..b9b3230 100644
--- a/stock/doctype/stock_entry/test_stock_entry.py
+++ b/stock/doctype/stock_entry/test_stock_entry.py
@@ -41,11 +41,42 @@
 		webnotes.conn.set_default("company", self.old_default_company)
 
 	def test_warehouse_company_validation(self):
+		webnotes.session.user = "test2@example.com"
+		webnotes.bean("Profile", "test2@example.com").get_controller()\
+			.add_roles("Sales User", "Sales Manager", "Material User", "Material Manager")
+
 		from stock.doctype.stock_ledger_entry.stock_ledger_entry import InvalidWarehouseCompany
 		st1 = webnotes.bean(copy=test_records[0])
 		st1.doclist[1].t_warehouse="_Test Warehouse 2 - _TC1"
 		st1.insert()
 		self.assertRaises(InvalidWarehouseCompany, st1.submit)
+		
+		webnotes.session.user = "Administrator"
+
+	def test_warehouse_user(self):
+		from stock.utils import UserNotAllowedForWarehouse
+
+		webnotes.session.user = "test@example.com"
+		webnotes.bean("Profile", "test@example.com").get_controller()\
+			.add_roles("Sales User", "Sales Manager", "Material User", "Material Manager")
+
+		webnotes.bean("Profile", "test2@example.com").get_controller()\
+			.add_roles("Sales User", "Sales Manager", "Material User", "Material Manager")
+
+		st1 = webnotes.bean(copy=test_records[0])
+		st1.doc.company = "_Test Company 1"
+		st1.doclist[1].t_warehouse="_Test Warehouse 2 - _TC1"
+		st1.insert()
+		self.assertRaises(UserNotAllowedForWarehouse, st1.submit)
+
+		webnotes.session.user = "test2@example.com"
+		st1 = webnotes.bean(copy=test_records[0])
+		st1.doc.company = "_Test Company 1"
+		st1.doclist[1].t_warehouse="_Test Warehouse 2 - _TC1"
+		st1.insert()
+		st1.submit()
+		
+		webnotes.session.user = "Administrator"
 
 	def test_material_receipt_gl_entry(self):
 		webnotes.conn.sql("delete from `tabStock Ledger Entry`")
diff --git a/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
index 71d426f..58fc828 100644
--- a/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
+++ b/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
@@ -25,12 +25,14 @@
 		self.doclist = doclist
 
 	def validate(self):
+		from stock.utils import validate_warehouse_user
 		if not hasattr(webnotes, "new_stock_ledger_entries"):
 			webnotes.new_stock_ledger_entries = []
+			
 		webnotes.new_stock_ledger_entries.append(self.doc)
 		self.validate_mandatory()
 		self.validate_item()
-		self.validate_warehouse_user()
+		validate_warehouse_user(self.doc.warehouse)
 		self.validate_warehouse_company()
 		self.actual_amt_check()
 		self.check_stock_frozen_date()
@@ -52,16 +54,6 @@
 
 			self.doc.fields.pop('batch_bal')
 			 
-	def validate_warehouse_user(self):
-		if webnotes.session.user=="Administrator":
-			return
-		warehouse_users = [p[0] for p in webnotes.conn.sql("""select user from `tabWarehouse User`
-			where parent=%s""", self.doc.warehouse)]
-			
-		if warehouse_users and not webnotes.session.user in warehouse_users:
-			webnotes.msgprint(_("User not allowed entry in the Warehouse") \
-				+ ": " + webnotes.session.user + " / " + self.doc.warehouse, raise_exception = 1)
-
 	def validate_warehouse_company(self):
 		warehouse_company = webnotes.conn.get_value("Warehouse", self.doc.warehouse, "company")
 		if warehouse_company and warehouse_company != self.doc.company:
diff --git a/stock/doctype/warehouse/test_warehouse.py b/stock/doctype/warehouse/test_warehouse.py
index 4e47d56..ed72562 100644
--- a/stock/doctype/warehouse/test_warehouse.py
+++ b/stock/doctype/warehouse/test_warehouse.py
@@ -16,5 +16,9 @@
 		"doctype": "Warehouse",
 		"warehouse_name": "_Test Warehouse 2",
 		"company": "_Test Company 1"
+	}, {
+		"doctype": "Warehouse User",
+		"parentfield": "warehouse_users",
+		"user": "test2@example.com"
 	}]	
 ]
diff --git a/stock/utils.py b/stock/utils.py
index 5376342..f04b663 100644
--- a/stock/utils.py
+++ b/stock/utils.py
@@ -8,6 +8,8 @@
 from webnotes.defaults import get_global_default
 from webnotes.utils.email_lib import sendmail
 
+class UserNotAllowedForWarehouse(webnotes.ValidationError): pass
+
 def validate_end_of_life(item_code, end_of_life=None, verbose=1):
 	if not end_of_life:
 		end_of_life = webnotes.conn.get_value("Item", item_code, "end_of_life")
@@ -152,6 +154,16 @@
 				wlist.append([w])
 	return wlist
 
+def validate_warehouse_user(warehouse):
+	if webnotes.session.user=="Administrator":
+		return
+	warehouse_users = [p[0] for p in webnotes.conn.sql("""select user from `tabWarehouse User`
+		where parent=%s""", warehouse)]
+				
+	if warehouse_users and not (webnotes.session.user in warehouse_users):
+		webnotes.throw(_("Not allowed entry in Warehouse") \
+			+ ": " + warehouse, UserNotAllowedForWarehouse)
+
 def get_buying_amount(item_code, voucher_type, voucher_no, voucher_detail_no, 
 		stock_ledger_entries, item_sales_bom=None):
 	if item_sales_bom and item_sales_bom.get(item_code):
diff --git a/utilities/demo/__init__.py b/utilities/demo/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/utilities/demo/__init__.py
diff --git a/utilities/demo/demo-login.css b/utilities/demo/demo-login.css
new file mode 100644
index 0000000..f3464a3
--- /dev/null
+++ b/utilities/demo/demo-login.css
@@ -0,0 +1,3 @@
+body, #container, .outer {
+	background-color: #888 !important;
+}
\ No newline at end of file
diff --git a/utilities/demo/demo-login.html b/utilities/demo/demo-login.html
new file mode 100644
index 0000000..ef24678
--- /dev/null
+++ b/utilities/demo/demo-login.html
@@ -0,0 +1,25 @@
+<div class="container">
+	<div class="row" style="margin-top: 100px;">
+		<div class="col-sm-offset-3 col-sm-6">
+			<div class="panel panel-default">
+				<div class="panel-heading">
+					Start ERPNext Demo
+				</div>
+				<div class="panel-body">
+					<p>
+					<input id="lead-email" type="email"
+						class="form-control" placeholder="Your Email Id">
+					</p>
+					<p>
+						<button type="submit" id="login_btn" 
+							class="btn btn-primary btn-large">Launch Demo</button>
+					</p>
+					<hr>
+					<p class="text-muted small">Some functionality is disabled for the demo app. The demo data will be cleared regulary. To start your own ERPNext Trial, <a href="https://erpnext.com/pricing-and-signup">click here</a></p>
+				</div>
+			</div>
+		</div>
+	</div>
+	<div class="row">
+	</div>
+</div>
diff --git a/utilities/demo/demo-login.js b/utilities/demo/demo-login.js
new file mode 100644
index 0000000..229d169
--- /dev/null
+++ b/utilities/demo/demo-login.js
@@ -0,0 +1,27 @@
+$(document).ready(function() {
+    $(".navbar, footer, .banner, #user-tools").toggle(false);
+    
+    $("#login_btn").click(function() {
+        var me = this;
+        $(this).html("Logging In...").attr("disabled", "disabled");
+        wn.call({
+            "method": "login",
+            args: {
+                usr: "demo@erpnext.com",
+                pwd: "demo",
+                lead_email: $("#lead-email").val(),
+            },
+            callback: function(r) {
+                $(me).attr("disabled", false);
+                if(r.exc) {
+                    alert("Error, please contact support@erpnext.com");
+                } else {
+                    console.log("Logged In");
+                    window.location.href = "app.html";
+                }
+            }
+        })
+        return false;
+    })
+    .attr("disabled", false);
+})
\ No newline at end of file
diff --git a/utilities/demo/demo_control_panel.py b/utilities/demo/demo_control_panel.py
new file mode 100644
index 0000000..c70913e
--- /dev/null
+++ b/utilities/demo/demo_control_panel.py
@@ -0,0 +1,13 @@
+
+  def on_login(self):
+    from webnotes.utils import validate_email_add
+	import conf
+	if hasattr(conf, "demo_notify_url"):
+      if webnotes.form_dict.lead_email and validate_email_add(webnotes.form_dict.lead_email):
+        import requests
+        response = requests.post(conf.demo_notify_url, data={
+          "cmd":"website.helpers.contact.send_message",
+          "subject":"Logged into Demo",
+          "sender": webnotes.form_dict.lead_email,
+          "message": "via demo.erpnext.com"
+        })
diff --git a/utilities/demo_docs/Address.csv b/utilities/demo/demo_docs/Address.csv
similarity index 100%
rename from utilities/demo_docs/Address.csv
rename to utilities/demo/demo_docs/Address.csv
diff --git a/utilities/demo_docs/BOM.csv b/utilities/demo/demo_docs/BOM.csv
similarity index 100%
rename from utilities/demo_docs/BOM.csv
rename to utilities/demo/demo_docs/BOM.csv
diff --git a/utilities/demo_docs/Contact.csv b/utilities/demo/demo_docs/Contact.csv
similarity index 100%
rename from utilities/demo_docs/Contact.csv
rename to utilities/demo/demo_docs/Contact.csv
diff --git a/utilities/demo_docs/Customer.csv b/utilities/demo/demo_docs/Customer.csv
similarity index 100%
rename from utilities/demo_docs/Customer.csv
rename to utilities/demo/demo_docs/Customer.csv
diff --git a/utilities/demo_docs/Employee.csv b/utilities/demo/demo_docs/Employee.csv
similarity index 100%
rename from utilities/demo_docs/Employee.csv
rename to utilities/demo/demo_docs/Employee.csv
diff --git a/utilities/demo_docs/Fiscal_Year.csv b/utilities/demo/demo_docs/Fiscal_Year.csv
similarity index 100%
rename from utilities/demo_docs/Fiscal_Year.csv
rename to utilities/demo/demo_docs/Fiscal_Year.csv
diff --git a/utilities/demo_docs/Item.csv b/utilities/demo/demo_docs/Item.csv
similarity index 100%
rename from utilities/demo_docs/Item.csv
rename to utilities/demo/demo_docs/Item.csv
diff --git a/utilities/demo_docs/Item_Price.csv b/utilities/demo/demo_docs/Item_Price.csv
similarity index 100%
rename from utilities/demo_docs/Item_Price.csv
rename to utilities/demo/demo_docs/Item_Price.csv
diff --git a/utilities/demo_docs/Lead.csv b/utilities/demo/demo_docs/Lead.csv
similarity index 100%
rename from utilities/demo_docs/Lead.csv
rename to utilities/demo/demo_docs/Lead.csv
diff --git a/utilities/demo_docs/Profile.csv b/utilities/demo/demo_docs/Profile.csv
similarity index 100%
rename from utilities/demo_docs/Profile.csv
rename to utilities/demo/demo_docs/Profile.csv
diff --git a/utilities/demo_docs/Salary_Structure.csv b/utilities/demo/demo_docs/Salary_Structure.csv
similarity index 100%
rename from utilities/demo_docs/Salary_Structure.csv
rename to utilities/demo/demo_docs/Salary_Structure.csv
diff --git a/utilities/demo_docs/Stock Reconcilation Template.csv b/utilities/demo/demo_docs/Stock Reconcilation Template.csv
similarity index 100%
rename from utilities/demo_docs/Stock Reconcilation Template.csv
rename to utilities/demo/demo_docs/Stock Reconcilation Template.csv
diff --git a/utilities/demo_docs/Supplier.csv b/utilities/demo/demo_docs/Supplier.csv
similarity index 100%
rename from utilities/demo_docs/Supplier.csv
rename to utilities/demo/demo_docs/Supplier.csv
diff --git a/utilities/demo_docs/bearing-block.png b/utilities/demo/demo_docs/bearing-block.png
similarity index 100%
rename from utilities/demo_docs/bearing-block.png
rename to utilities/demo/demo_docs/bearing-block.png
Binary files differ
diff --git a/utilities/demo_docs/wind-turbine.png b/utilities/demo/demo_docs/wind-turbine.png
similarity index 100%
rename from utilities/demo_docs/wind-turbine.png
rename to utilities/demo/demo_docs/wind-turbine.png
Binary files differ
diff --git a/utilities/make_demo.py b/utilities/demo/make_demo.py
similarity index 92%
rename from utilities/make_demo.py
rename to utilities/demo/make_demo.py
index 2884144..3d7d648 100644
--- a/utilities/make_demo.py
+++ b/utilities/demo/make_demo.py
@@ -19,9 +19,9 @@
 country = "United States"
 currency = "USD"
 time_zone = "America/New York"
-start_date = '2010-01-01'
+start_date = '2013-01-01'
 bank_name = "Citibank"
-runs_for = 20
+runs_for = None
 prob = {
 	"default": { "make": 0.6, "qty": (1,5) },
 	"Sales Order": { "make": 0.4, "qty": (1,3) },
@@ -50,21 +50,24 @@
 	# make_opening_accounts()
 
 def simulate():
-	current_date = None
-	for i in xrange(runs_for):
-		if not current_date:
-			# get last stock ledger posting date or use default
-			last_posting = webnotes.conn.sql("""select max(posting_date) from `tabStock Ledger Entry`""")
-			if last_posting[0][0]:
-				current_date = webnotes.utils.add_days(last_posting[0][0], 1)
-			else:
-				current_date = webnotes.utils.getdate(start_date)
-		else:
-			current_date = webnotes.utils.add_days(current_date, 1)
-		
+	global runs_for
+	current_date = webnotes.utils.getdate(start_date)
+	
+	# continue?
+	last_posting = webnotes.conn.sql("""select max(posting_date) from `tabStock Ledger Entry`""")
+	if last_posting[0][0]:
+		current_date = webnotes.utils.add_days(last_posting[0][0], 1)
+
+	# run till today
+	if not runs_for:
+		runs_for = webnotes.utils.date_diff(webnotes.utils.nowdate(), current_date)
+	
+	for i in xrange(runs_for):		
 		print current_date.strftime("%Y-%m-%d")
+		webnotes.utils.current_date = current_date
 		
 		if current_date.weekday() in (5, 6):
+			current_date = webnotes.utils.add_days(current_date, 1)
 			continue
 
 		run_sales(current_date)
@@ -72,6 +75,8 @@
 		run_manufacturing(current_date)
 		run_stock(current_date)
 		run_accounts(current_date)
+
+		current_date = webnotes.utils.add_days(current_date, 1)
 		
 def run_sales(current_date):
 	if can_make("Quotation"):
@@ -136,7 +141,7 @@
 		for po in list(set([r[0] for r in query_report.run(report)["result"] if r[0]!="Total"]))[:how_many("Purchase Receipt")]:
 			pr = webnotes.bean(make_purchase_receipt(po))
 			pr.doc.posting_date = current_date
-			pr.doc.fiscal_year = "2010"
+			pr.doc.fiscal_year = "2013"
 			pr.insert()
 			pr.submit()
 			webnotes.conn.commit()
@@ -150,7 +155,7 @@
 		for so in list(set([r[0] for r in query_report.run(report)["result"] if r[0]!="Total"]))[:how_many("Delivery Note")]:
 			dn = webnotes.bean(make_delivery_note(so))
 			dn.doc.posting_date = current_date
-			dn.doc.fiscal_year = "2010"
+			dn.doc.fiscal_year = "2013"
 			dn.insert()
 			try:
 				dn.submit()
@@ -173,7 +178,7 @@
 			mr = webnotes.new_bean("Material Request")
 			mr.doc.material_request_type = "Purchase"
 			mr.doc.transaction_date = current_date
-			mr.doc.fiscal_year = "2010"
+			mr.doc.fiscal_year = "2013"
 			mr.doclist.append({
 				"doctype": "Material Request Item",
 				"parentfield": "indent_details",
@@ -192,7 +197,7 @@
 			if row[0] != "Total":
 				sq = webnotes.bean(make_supplier_quotation(row[0]))
 				sq.doc.transaction_date = current_date
-				sq.doc.fiscal_year = "2010"
+				sq.doc.fiscal_year = "2013"
 				sq.insert()
 				sq.submit()
 				webnotes.conn.commit()
@@ -205,7 +210,7 @@
 			if row[0] != "Total":
 				po = webnotes.bean(make_purchase_order(row[0]))
 				po.doc.transaction_date = current_date
-				po.doc.fiscal_year = "2010"
+				po.doc.fiscal_year = "2013"
 				po.insert()
 				po.submit()
 				webnotes.conn.commit()
@@ -261,11 +266,11 @@
 	from stock.stock_ledger import NegativeStockError
 	from stock.doctype.stock_entry.stock_entry import IncorrectValuationRateError, DuplicateEntryForProductionOrderError
 
-	st = webnotes.bean(make_stock_entry(pro_id, purpose))
-	st.doc.posting_date = current_date
-	st.doc.fiscal_year = "2010"
-	st.doc.expense_adjustment_account = "Stock in Hand - WP"
 	try:
+		st = webnotes.bean(make_stock_entry(pro_id, purpose))
+		st.doc.posting_date = current_date
+		st.doc.fiscal_year = "2013"
+		st.doc.expense_adjustment_account = "Stock in Hand - WP"
 		st.insert()
 		webnotes.conn.commit()
 		st.submit()
@@ -273,7 +278,7 @@
 	except NegativeStockError: pass
 	except IncorrectValuationRateError: pass
 	except DuplicateEntryForProductionOrderError: pass
-
+	
 def make_quotation(current_date):
 	b = webnotes.bean([{
 		"creation": current_date,
@@ -282,7 +287,7 @@
 		"customer": get_random("Customer"),
 		"order_type": "Sales",
 		"transaction_date": current_date,
-		"fiscal_year": "2010"
+		"fiscal_year": "2013"
 	}])
 	
 	add_random_children(b, {
@@ -349,8 +354,9 @@
 def install():
 	print "Creating Fresh Database..."
 	from webnotes.install_lib.install import Installer
+	import conf
 	inst = Installer('root')
-	inst.import_from_db("demo", verbose = 1)
+	inst.import_from_db(conf.demo_db_name, verbose = 1)
 
 def complete_setup():
 	print "Complete Setup..."
@@ -392,6 +398,7 @@
 	}).insert()
 	
 	webnotes.set_value("Company", company, "default_bank_account", ba.doc.name)
+	webnotes.conn.commit()
 
 def import_data(dt, submit=False):
 	if not isinstance(dt, (tuple, list)):
@@ -399,7 +406,7 @@
 	
 	for doctype in dt:
 		print "Importing", doctype.replace("_", " "), "..."
-		webnotes.form_dict = {}
+		webnotes.form_dict = webnotes._dict()
 		if submit:
 			webnotes.form_dict["params"] = json.dumps({"_submit": 1})
 		webnotes.uploaded_file = os.path.join(os.path.dirname(__file__), "demo_docs", doctype+".csv")
diff --git a/utilities/demo/make_erpnext_demo.py b/utilities/demo/make_erpnext_demo.py
new file mode 100644
index 0000000..31dc400
--- /dev/null
+++ b/utilities/demo/make_erpnext_demo.py
@@ -0,0 +1,117 @@
+if __name__=="__main__":
+	import sys
+	sys.path.extend([".", "lib", "app"])
+
+import webnotes, os
+
+def make_demo_app():
+	import utilities.demo.make_demo
+	utilities.demo.make_demo.make(reset=True)
+
+def make_demo_user():
+	roles = ["Accounts Manager", "Analytics", "Expense Approver", "Accounts User", 
+		"Leave Approver", "Blogger", "Customer", "Sales Manager", "Employee", "Support Manager", 
+		"HR Manager", "HR User", "Maintenance Manager", "Maintenance User", "Material Manager", 
+		"Material Master Manager", "Material User", "Partner", "Manufacturing Manager", 
+		"Manufacturing User", "Projects User", "Purchase Manager", "Purchase Master Manager", 
+		"Purchase User", "Quality Manager", "Report Manager", "Sales Master Manager", 
+		"Sales User", "Supplier", "Support Team"]
+		
+	def add_roles(bean):
+		for role in roles:
+			p.doclist.append({
+				"doctype": "UserRole",
+				"parentfield": "user_roles",
+				"role": role
+			})
+	
+	# make demo user
+	if webnotes.conn.exists("Profile", "demo@erpnext.com"):
+		webnotes.delete_doc("Profile", "demo@erpnext.com")
+
+	p = webnotes.new_bean("Profile")
+	p.doc.email = "demo@erpnext.com"
+	p.doc.first_name = "Demo"
+	p.doc.last_name = "User"
+	p.doc.enabled = 1
+	p.doc.user_type = "ERPNext Demo"
+	p.doc.send_invite_email = 0
+	p.doc.new_password = "demo"
+	p.insert()
+	add_roles(p)
+	p.save()
+	
+	# make system manager user
+	if webnotes.conn.exists("Profile", "admin@erpnext.com"):
+		webnotes.delete_doc("Profile", "admin@erpnext.com")
+	
+	p = webnotes.new_bean("Profile")
+	p.doc.email = "admin@erpnext.com"
+	p.doc.first_name = "Admin"
+	p.doc.last_name = "User"
+	p.doc.enabled = 1
+	p.doc.user_type = "System User"
+	p.doc.send_invite_email = 0
+	p.doc.new_password = "admin010123"
+	p.insert()
+	roles.append("System Manager")
+	add_roles(p)
+	p.save()
+	
+	# only read for newsletter
+	webnotes.conn.sql("""update `tabDocPerm` set `write`=0, `create`=0, `cancel`=0
+		where parent='Newsletter'""")
+	webnotes.conn.sql("""update `tabDocPerm` set `write`=0, `create`=0, `cancel`=0
+		where parent='Profile' and role='All'""")
+	
+	webnotes.conn.commit()
+
+def make_demo_login_page():
+	webnotes.conn.set_value("Website Settings", None, "home_page", "")
+
+	webnotes.conn.sql("""delete from `tabWeb Page` where name='demo-login'""")
+	p = webnotes.new_bean("Web Page")
+	p.doc.title = "Demo Login"
+	p.doc.published = 1
+	p.doc.description = "ERPNext Demo Login"
+
+	with open(os.path.join(os.path.dirname(__file__), "demo-login.html"), "r") as dfile:
+		p.doc.main_section = dfile.read()
+
+	p.doc.insert_code = 1
+	with open(os.path.join(os.path.dirname(__file__), "demo-login.js"), "r") as dfile:
+		p.doc.javascript = dfile.read()
+
+	p.doc.insert_style = 1
+	with open(os.path.join(os.path.dirname(__file__), "demo-login.css"), "r") as dfile:
+		p.doc.css = dfile.read()
+		
+	p.insert()
+	
+	webnotes.conn.set_value("Website Settings", None, "home_page", "demo-login")
+	webnotes.conn.set_value("Website Settings", None, "disable_signup", 1)
+	
+	webnotes.conn.commit()
+
+def make_demo_on_login_script():
+	webnotes.conn.sql("""delete from `tabCustom Script` where dt='Control Panel'""")
+	s = webnotes.new_bean("Custom Script")
+	s.doc.dt = "Control Panel"
+	s.doc.script_type = "Server"
+	with open(os.path.join(os.path.dirname(__file__), "demo_control_panel.py"), "r") as dfile:
+		s.doc.script = dfile.read()
+	s.insert()
+	
+	cp = webnotes.bean("Control Panel")
+	cp.doc.custom_startup_code = """wn.ui.toolbar.show_banner('You are using ERPNext Demo. To start your own ERPNext Trial, <a href="https://erpnext.com/pricing-and-signup" target="_blank">click here</a>')"""
+	cp.save()
+
+	webnotes.conn.commit()
+
+if __name__=="__main__":
+	# webnotes.connect()
+	webnotes.mute_emails = 1
+	make_demo_app()
+	make_demo_user()
+	make_demo_login_page()
+	make_demo_on_login_script()
\ No newline at end of file
diff --git a/utilities/transaction_base.py b/utilities/transaction_base.py
index d2bffcf..aace0cb 100644
--- a/utilities/transaction_base.py
+++ b/utilities/transaction_base.py
@@ -55,6 +55,8 @@
 		return self._party_type_and_name
 			
 	def get_customer_defaults(self):
+		if not self.doc.customer: return {}
+		
 		out = self.get_default_address_and_contact("customer")
 
 		customer = webnotes.doc("Customer", self.doc.customer)
diff --git a/website/doctype/website_settings/website_settings.js b/website/doctype/website_settings/website_settings.js
index 0d0dab6..21b55be 100644
--- a/website/doctype/website_settings/website_settings.js
+++ b/website/doctype/website_settings/website_settings.js
@@ -4,6 +4,14 @@
 // update parent select
 
 $.extend(cur_frm.cscript, {
+	refresh: function(doc) {
+		cur_frm.add_custom_button("Auto Build Website", function() {
+			cur_frm.call({
+				doc: cur_frm.doc,
+				method: "make_website"
+			})
+		}, 'icon-magic')
+	},
 	onload_post_render: function(doc) {
 		this.set_parent_label_options();
 	},
diff --git a/website/doctype/website_settings/website_settings.py b/website/doctype/website_settings/website_settings.py
index 3b27c7c..5d6c874 100644
--- a/website/doctype/website_settings/website_settings.py
+++ b/website/doctype/website_settings/website_settings.py
@@ -13,6 +13,26 @@
 		self.set_home_page()
 		self.validate_top_bar_items()
 		self.validate_footer_items()
+		
+	def make_website(self):
+		# set item pages
+		for name in webnotes.conn.sql_list("""select name from tabItem where 
+			ifnull(show_in_website, 0)=0 and is_sales_item ='Yes' """):
+			webnotes.msgprint("Setting 'Show in Website' for:" + name)
+			item = webnotes.bean("Item", name)
+			item.doc.show_in_website = 1
+			item.doc.website_warehouse = item.doc.default_warehouse
+			item.doc.website_image = item.doc.image
+			item.save()
+		
+		# set item group pages
+		for name in webnotes.conn.sql_list("""select name from `tabItem Group` where 
+			ifnull(show_in_website, 0)=0 and exists (select name from tabItem where 
+				ifnull(show_in_website, 0)=1)"""):
+			webnotes.msgprint("Setting 'Show in Website' for:" + name)
+			item_group = webnotes.bean("Item Group", name)
+			item_group.doc.show_in_website = 1
+			item_group.save()
 			
 	def validate_top_bar_items(self):
 		"""validate url in top bar items"""