Merge pull request #5817 from rmehta/neilLasrado-schools

Merge schools, fix setup wizard, update domainify
diff --git a/erpnext/accounts/doctype/asset/depreciation.py b/erpnext/accounts/doctype/asset/depreciation.py
index 6cf09d3..15c155c 100644
--- a/erpnext/accounts/doctype/asset/depreciation.py
+++ b/erpnext/accounts/doctype/asset/depreciation.py
@@ -63,10 +63,10 @@
 			d.db_set("journal_entry", je.name)
 			asset.value_after_depreciation -= d.depreciation_amount
 
-		asset.db_set("value_after_depreciation", asset.value_after_depreciation)
-		asset.set_status()
-		
-		return asset
+	asset.db_set("value_after_depreciation", asset.value_after_depreciation)
+	asset.set_status()
+
+	return asset
 
 def get_depreciation_accounts(asset):
 	fixed_asset_account = accumulated_depreciation_account = depreciation_expense_account = None
diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js
index af46dc0..49cbdd0 100644
--- a/erpnext/accounts/page/pos/pos.js
+++ b/erpnext/accounts/page/pos/pos.js
@@ -678,19 +678,13 @@
 	set_primary_action: function() {
 		var me = this;
 
-		if (this.frm.doc.docstatus==0 && this.frm.doc.outstanding_amount > 0) {
+		if (this.frm.doc.docstatus==0) {
 			this.page.set_primary_action(__("Pay"), function() {
 				me.validate()
 				me.create_invoice();
 				me.make_payment();
 			}, "octicon octicon-credit-card");
-		}else if(this.frm.doc.docstatus == 0 && this.frm.doc.items.length){
-			this.page.set_primary_action(__("Submit"), function() {
-				me.validate()
-				me.create_invoice();
-				me.write_off_amount()
-			})
-		}else if(this.frm.doc.docstatus == 1){
+		}else if(this.frm.doc.docstatus == 1) {
 			this.page.set_primary_action(__("Print"), function() {
 				html = frappe.render(me.print_template, me.frm.doc)
 				me.print_document(html)
diff --git a/erpnext/demo/data/asset.json b/erpnext/demo/data/asset.json
new file mode 100644
index 0000000..b158218
--- /dev/null
+++ b/erpnext/demo/data/asset.json
@@ -0,0 +1,37 @@
+[
+	{
+		"asset_name": "Macbook Pro - 1",
+		"item_code": "Computer",
+		"gross_purchase_amount": 100000
+	},
+	{
+		"asset_name": "Macbook Air - 1",
+		"item_code": "Computer",
+		"gross_purchase_amount": 60000
+	},
+	{
+		"asset_name": "Conferrence Table",
+		"item_code": "Table",
+		"gross_purchase_amount": 30000
+	},
+	{
+		"asset_name": "Lunch Table",
+		"item_code": "Table",
+		"gross_purchase_amount": 20000
+	},
+	{
+		"asset_name": "ERPNext",
+		"item_code": "ERP",
+		"gross_purchase_amount": 100000
+	},
+	{
+		"asset_name": "Chair 1",
+		"item_code": "Chair",
+		"gross_purchase_amount": 10000
+	},
+	{
+		"asset_name": "Chair 2",
+		"item_code": "Chair",
+		"gross_purchase_amount": 10000
+	}
+]
\ No newline at end of file
diff --git a/erpnext/demo/data/asset_category.json b/erpnext/demo/data/asset_category.json
new file mode 100644
index 0000000..54f779d
--- /dev/null
+++ b/erpnext/demo/data/asset_category.json
@@ -0,0 +1,38 @@
+[
+	{
+		"asset_category_name": "Furnitures",
+		"depreciation_method": "Straight Line",
+		"total_number_of_depreciations": 5,
+		"frequency_of_depreciation": 12, 
+		"accounts": [{
+			"company_name": "Wind Power LLC",
+			"fixed_asset_account": "Furnitures and Fixtures - WPL",
+			"accumulated_depreciation_account": "Accumulated Depreciation - WPL",
+			"depreciation_expense_account": "Depreciation - WPL"
+		}]
+	},
+	{
+		"asset_category_name": "Electronic Equipments",
+		"depreciation_method": "Double Declining Balance",
+		"total_number_of_depreciations": 10,
+		"frequency_of_depreciation": 6, 
+		"accounts": [{
+			"company_name": "Wind Power LLC",
+			"fixed_asset_account": "Electronic Equipments - WPL",
+			"accumulated_depreciation_account": "Accumulated Depreciation - WPL",
+			"depreciation_expense_account": "Depreciation - WPL"
+		}]
+	},
+	{
+		"asset_category_name": "Softwares",
+		"depreciation_method": "Straight Line",
+		"total_number_of_depreciations": 10,
+		"frequency_of_depreciation": 12, 
+		"accounts": [{
+			"company_name": "Wind Power LLC",
+			"fixed_asset_account": "Softwares - WPL",
+			"accumulated_depreciation_account": "Accumulated Depreciation - WPL",
+			"depreciation_expense_account": "Depreciation - WPL"
+		}]
+	}
+]
\ No newline at end of file
diff --git a/erpnext/demo/data/item.json b/erpnext/demo/data/item.json
index d8d4584..e208522 100644
--- a/erpnext/demo/data/item.json
+++ b/erpnext/demo/data/item.json
@@ -221,5 +221,59 @@
   "item_code": "Base Plate Un Painted",
   "item_group": "Raw Material",
   "item_name": "Base Plate Un Painted"
+ },
+ {
+  "is_fixed_asset": 1,
+  "asset_category": "Furnitures",
+  "is_stock_item": 0,
+  "description": "Table",
+  "item_code": "Table",
+  "item_name": "Table",
+  "item_group": "Products"
+ },
+ {
+  "is_fixed_asset": 1,
+  "asset_category": "Furnitures",
+  "is_stock_item": 0,
+  "description": "Chair",
+  "item_code": "Chair",
+  "item_name": "Chair",
+  "item_group": "Products"
+ },
+ {
+  "is_fixed_asset": 1,
+  "asset_category": "Electronic Equipments",
+  "is_stock_item": 0,
+  "description": "Computer",
+  "item_code": "Computer",
+  "item_name": "Computer",
+  "item_group": "Products"
+ },
+ {
+  "is_fixed_asset": 1,
+  "asset_category": "Electronic Equipments",
+  "is_stock_item": 0,
+  "description": "Mobile",
+  "item_code": "Mobile",
+  "item_name": "Mobile",
+  "item_group": "Products"
+ },
+ {
+  "is_fixed_asset": 1,
+  "asset_category": "Softwares",
+  "is_stock_item": 0,
+  "description": "ERP",
+  "item_code": "ERP",
+  "item_name": "ERP",
+  "item_group": "All Item Groups"
+ },
+ {
+  "is_fixed_asset": 1,
+  "asset_category": "Softwares",
+  "is_stock_item": 0,
+  "description": "Autocad",
+  "item_code": "Autocad",
+  "item_name": "Autocad",
+  "item_group": "All Item Groups"
  }
 ]
\ No newline at end of file
diff --git a/erpnext/demo/demo.py b/erpnext/demo/demo.py
index 4188432..2435029 100644
--- a/erpnext/demo/demo.py
+++ b/erpnext/demo/demo.py
@@ -4,7 +4,7 @@
 import erpnext
 import frappe.utils
 from erpnext.demo.setup_data import setup_data
-from erpnext.demo.user import hr, sales, purchase, manufacturing, stock, accounts, projects
+from erpnext.demo.user import hr, sales, purchase, manufacturing, stock, accounts, projects, fixed_asset
 
 """
 Make a demo
@@ -53,6 +53,8 @@
 	if not runs_for:
 		runs_for = frappe.utils.date_diff(frappe.utils.nowdate(), current_date)
 		# runs_for = 100
+		
+	fixed_asset.work()
 
 	for i in xrange(runs_for):
 		sys.stdout.write("\rSimulating {0}".format(current_date.strftime("%Y-%m-%d")))
diff --git a/erpnext/demo/setup_data.py b/erpnext/demo/setup_data.py
index 0903482..f5c4eb3 100644
--- a/erpnext/demo/setup_data.py
+++ b/erpnext/demo/setup_data.py
@@ -3,7 +3,7 @@
 import random, json
 from erpnext.demo.domains import data
 import frappe, erpnext
-from frappe.utils import cint, flt, now_datetime, cstr
+from frappe.utils import flt, now_datetime, cstr, nowdate, add_days
 from frappe import _
 
 def setup_data():
@@ -14,8 +14,10 @@
 	setup_holiday_list()
 	setup_customer()
 	setup_supplier()
+	import_json("Asset Category")
 	setup_item()
 	setup_warehouse()
+	setup_asset()
 	import_json('Address')
 	import_json('Contact')
 	setup_workstation()
@@ -66,7 +68,7 @@
 
 def setup_fiscal_year():
 	fiscal_year = None
-	for year in xrange(2014, now_datetime().year + 1, 1):
+	for year in xrange(2010, now_datetime().year + 1, 1):
 		try:
 			fiscal_year = frappe.get_doc({
 				"doctype": "Fiscal Year",
@@ -158,6 +160,20 @@
 	w = frappe.new_doc('Warehouse')
 	w.warehouse_name = 'Supplier'
 	w.insert()
+	
+def setup_asset():
+	assets = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data', 'asset.json')).read())
+	for d in assets:
+		asset = frappe.new_doc('Asset')
+		asset.update(d)
+		asset.purchase_date = add_days(nowdate(), -random.randint(20, 1500))
+		asset.next_depreciation_date = add_days(asset.purchase_date, 30)
+		asset.warehouse = "Stores - WPL"
+		asset.set_missing_values()
+		asset.make_depreciation_schedule()
+		asset.flags.ignore_validate = True
+		asset.save()
+		asset.submit()
 
 def setup_currency_exchange():
 	frappe.get_doc({
diff --git a/erpnext/demo/user/accounts.py b/erpnext/demo/user/accounts.py
index d3df627..e7dceb3 100644
--- a/erpnext/demo/user/accounts.py
+++ b/erpnext/demo/user/accounts.py
@@ -8,11 +8,13 @@
 import random
 from frappe.utils import random_string
 from frappe.desk import query_report
+from erpnext.accounts.doctype.journal_entry.journal_entry import get_payment_entry_against_invoice
+from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
 
 def work():
 	frappe.set_user(frappe.db.get_global('demo_accounts_user'))
 
-	if random.random() < 0.5:
+	if random.random() <= 0.6:
 		from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice
 		report = "Ordered Items to be Billed"
 		for so in list(set([r[0] for r in query_report.run(report)["result"]
@@ -26,7 +28,7 @@
 			si.submit()
 			frappe.db.commit()
 
-	if random.random() < 0.5:
+	if random.random() <= 0.6:
 		from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice
 		report = "Received Items to be Billed"
 		for pr in list(set([r[0] for r in query_report.run(report)["result"]
@@ -38,30 +40,33 @@
 			pi.submit()
 			frappe.db.commit()
 
-	from erpnext.accounts.doctype.journal_entry.journal_entry import get_payment_entry_against_invoice
+	if random.random() < 0.5:
+		make_payment_entries("Sales Invoice", "Accounts Receivable")
 
 	if random.random() < 0.5:
-		report = "Accounts Receivable"
-		for si in list(set([r[3] for r in query_report.run(report,
-		{"report_date": frappe.flags.current_date })["result"]
-		if r[2]=="Sales Invoice"]))[:random.randint(1, 5)]:
-			jv = frappe.get_doc(get_payment_entry_against_invoice("Sales Invoice", si))
-			jv.posting_date = frappe.flags.current_date
-			jv.cheque_no = random_string(6)
-			jv.cheque_date = frappe.flags.current_date
-			jv.insert()
-			jv.submit()
-			frappe.db.commit()
+		make_payment_entries("Purchase Invoice", "Accounts Payable")
 
-	if random.random() < 0.5:
-		report = "Accounts Payable"
-		for pi in list(set([r[3] for r in query_report.run(report,
-			{"report_date": frappe.flags.current_date })["result"]
-				if r[2]=="Purchase Invoice"]))[:random.randint(1, 5)]:
-			jv = frappe.get_doc(get_payment_entry_against_invoice("Purchase Invoice", pi))
-			jv.posting_date = frappe.flags.current_date
-			jv.cheque_no = random_string(6)
-			jv.cheque_date = frappe.flags.current_date
-			jv.insert()
-			jv.submit()
-			frappe.db.commit()
+def make_payment_entries(ref_doctype, report):
+	outstanding_invoices = list(set([r[3] for r in query_report.run(report, 
+	{"report_date": frappe.flags.current_date })["result"] if r[2]==ref_doctype]))
+	
+	# make Payment Entry
+	for inv in outstanding_invoices[:random.randint(1, 2)]:
+		pe = get_payment_entry(ref_doctype, inv)
+		pe.posting_date = frappe.flags.current_date
+		pe.reference_no = random_string(6)
+		pe.reference_date = frappe.flags.current_date
+		pe.insert()
+		pe.submit()
+		frappe.db.commit()
+		outstanding_invoices.remove(inv)
+		
+	# make payment via JV
+	for inv in outstanding_invoices[:1]:
+		jv = frappe.get_doc(get_payment_entry_against_invoice(ref_doctype, inv))
+		jv.posting_date = frappe.flags.current_date
+		jv.cheque_no = random_string(6)
+		jv.cheque_date = frappe.flags.current_date
+		jv.insert()
+		jv.submit()
+		frappe.db.commit()		
\ No newline at end of file
diff --git a/erpnext/demo/user/fixed_asset.py b/erpnext/demo/user/fixed_asset.py
new file mode 100644
index 0000000..bf3199e
--- /dev/null
+++ b/erpnext/demo/user/fixed_asset.py
@@ -0,0 +1,59 @@
+
+# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+
+import frappe
+from frappe.utils.make_random import get_random
+from erpnext.accounts.doctype.asset.asset import make_purchase_invoice, make_sales_invoice
+from erpnext.accounts.doctype.asset.depreciation import post_depreciation_entries, scrap_asset
+
+def work():
+	frappe.set_user(frappe.db.get_global('demo_accounts_user'))
+
+	asset_list = make_asset_purchase_entry()
+
+	if not asset_list:
+		# fixed_asset.work() already run
+		return
+		
+	# post depreciation entries as on today
+	post_depreciation_entries()
+	
+	# scrap a random asset
+	frappe.db.set_value("Company", "Wind Power LLC", "disposal_account", "Gain/Loss on Asset Disposal - WPL")
+	
+	asset = get_random_asset()
+	scrap_asset(asset.name)
+	
+	# Sell a random asset
+	sell_an_asset()	
+
+def make_asset_purchase_entry():
+	asset_list = frappe.get_all("Asset", filters={"purchase_invoice": ["in", ("", None)]}, 
+		fields=["name", "item_code", "gross_purchase_amount", "company", "purchase_date"])
+				
+	# make purchase invoice
+	for asset in asset_list:
+		pi = make_purchase_invoice(asset.name, asset.item_code, asset.gross_purchase_amount, 
+			asset.company, asset.purchase_date)
+		pi.supplier = get_random("Supplier")
+		pi.save()
+		pi.submit()
+		
+	return asset_list
+
+def sell_an_asset():
+	asset = get_random_asset()
+	si = make_sales_invoice(asset.name, asset.item_code, "Wind Power LLC")
+	si.customer = get_random("Customer")
+	si.get("items")[0].rate = asset.value_after_depreciation * 0.8 \
+		if asset.value_after_depreciation else asset.gross_purchase_amount * 0.9
+	si.save()
+	si.submit()
+	
+def get_random_asset():
+	return frappe.db.sql(""" select name, item_code, value_after_depreciation, gross_purchase_amount
+		from `tabAsset` 
+		where docstatus=1 and status not in ("Scrapped", "Sold") order by rand() limit 1""", as_dict=1)[0]
diff --git a/erpnext/demo/user/hr.py b/erpnext/demo/user/hr.py
index bd86507..50f15bb 100644
--- a/erpnext/demo/user/hr.py
+++ b/erpnext/demo/user/hr.py
@@ -124,4 +124,4 @@
 
 def get_random_item():
 	return frappe.db.sql_list(""" select name from `tabItem` where
-		has_variants = 0 order by rand() limit 1""")[0]
+		has_variants=0 and is_stock_item=0 and is_fixed_asset=0 order by rand() limit 1""")[0]
diff --git a/erpnext/demo/user/sales.py b/erpnext/demo/user/sales.py
index 7432ba0..6b36b46 100644
--- a/erpnext/demo/user/sales.py
+++ b/erpnext/demo/user/sales.py
@@ -45,7 +45,7 @@
 
 	add_random_children(b, "items", rows=4, randomize = {
 		"qty": (1, 5),
-		"item_code": ("Item", {"has_variants": "0"})
+		"item_code": ("Item", {"has_variants": "0", "is_fixed_asset": 0})
 	}, unique="item_code")
 
 	b.insert()
@@ -88,7 +88,7 @@
 
 		add_random_children(qtn, "items", rows=3, randomize = {
 			"qty": (1, 5),
-			"item_code": ("Item", {"has_variants": "0"})
+			"item_code": ("Item", {"has_variants": "0", "is_fixed_asset": 0})
 		}, unique="item_code")
 
 		qtn.insert()
diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js
index ebdb535..f816def 100644
--- a/erpnext/projects/doctype/timesheet/timesheet.js
+++ b/erpnext/projects/doctype/timesheet/timesheet.js
@@ -78,15 +78,8 @@
 		var child = locals[cdt][cdn];
 
 		if(frm._setting_hours) return;
-
-		if(flt(child.hours) == 0.0){
-			frappe.model.set_value(cdt, cdn, "hours", moment(child.to_time).diff(moment(child.from_time),
-				"seconds") / 3600);
-		}else{
-			var d = moment(child.to_time);
-			d.add(child.hours, "hours");
-			frappe.model.set_value(cdt, cdn, "from_time", d.format(moment.defaultDatetimeFormat));
-		}
+		frappe.model.set_value(cdt, cdn, "hours", moment(child.to_time).diff(moment(child.from_time),
+			"seconds") / 3600);
 	},
 
 	hours: function(frm, cdt, cdn) {
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index fde33e8..236eb82 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -587,6 +587,8 @@
 				if(data.type == "Cash" && payment_status) {
 					data.amount = total_amount_to_pay;
 					payment_status = false;
+				}else{
+					data.amount = 0.0;
 				}
 			})
 		}
diff --git a/erpnext/public/js/payment/payments.js b/erpnext/public/js/payment/payments.js
index 9464f50..90766e9 100644
--- a/erpnext/public/js/payment/payments.js
+++ b/erpnext/public/js/payment/payments.js
@@ -58,11 +58,6 @@
 					currency: me.frm.doc.currency,
 					type: data.type
 				})).appendTo(multimode_payments)
-
-				if (data.type == 'Cash' && me.frm.doc.outstanding_amount > 0) {
-					me.idx = data.idx;
-					me.set_outstanding_amount();
-				}
 			})
 		}else{
 			$("<p>No payment mode selected in pos profile</p>").appendTo(multimode_payments)
@@ -157,7 +152,7 @@
 				data.amount = flt(me.selected_mode.val(), 2)
 			}
 		})
-		this.calculate_outstanding_amount();
+		this.calculate_outstanding_amount(false);
 		this.show_amounts();
 	},
 	
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index fa6dd3c..03f2ee1 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -344,10 +344,9 @@
 	def raise_exceptions(self):
 		deficiency = min(e["diff"] for e in self.exceptions)
 
-
-
 		if ((self.exceptions[0]["voucher_type"], self.exceptions[0]["voucher_no"]) in
 			frappe.local.flags.currently_saving):
+
 			msg = _("{0} units of {1} needed in {2} to complete this transaction.").format(
 				abs(deficiency), frappe.get_desk_link('Item', self.item_code),
 				frappe.get_desk_link('Warehouse', self.warehouse))