Merge pull request #3013 from neilLasrado/expense

Expense Claim - 'Total Amount Reimbursed' feild added
diff --git a/.travis.yml b/.travis.yml
index 74cf0d5..598c503 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,11 +18,10 @@
 script:
   - cd ~/frappe-bench
   - bench get-app erpnext $TRAVIS_BUILD_DIR
-  - bench set-default-site test_site
-  - bench frappe --reinstall
-  - bench frappe --build_website
-  - bench frappe --serve_test &
-  - bench frappe --verbose --run_tests
+  - bench use test_site
+  - bench reinstall
+  - bench build-website
+  - bench --verbose run-tests
 
 before_script:
   - mysql -e 'create database test_frappe'
diff --git a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py
index 3361e1b..5d0c20d 100644
--- a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py
+++ b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py
@@ -4,7 +4,7 @@
 from __future__ import unicode_literals
 import frappe
 from frappe import msgprint, _
-from frappe.utils import getdate, add_days, add_years
+from frappe.utils import getdate, add_days, add_years, cstr
 from datetime import timedelta
 
 from frappe.model.document import Document
@@ -48,17 +48,17 @@
 
 @frappe.whitelist()
 def auto_create_fiscal_year():
-	for d in frappe.db.sql("""select name from `tabFiscal Year` where year_end_date =(current_date + 3)"""):
+	for d in frappe.db.sql("""select name from `tabFiscal Year` where year_end_date = date_add(current_date, interval 3 day)"""):
 		try:
 			current_fy = frappe.get_doc("Fiscal Year", d[0])
 
-			new_fy = frappe.copy_doc(current_fy)
+			new_fy = frappe.copy_doc(current_fy, ignore_no_copy=False)
 
 			new_fy.year_start_date = add_days(current_fy.year_end_date, 1)
 			new_fy.year_end_date = add_years(current_fy.year_end_date, 1)
 
-			start_year = new_fy.year_start_date[:4]
-			end_year = new_fy.year_end_date[:4]
+			start_year = cstr(new_fy.year_start_date.year)
+			end_year = cstr(new_fy.year_end_date.year)
 			new_fy.year = start_year if start_year==end_year else (start_year + "-" + end_year)
 
 			new_fy.insert()
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index b3b35f9..ade0d32 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -174,8 +174,12 @@
 			frappe.model.round_floats_in(this.frm.doc, ["base_grand_total", "paid_amount"]);
 			// this will make outstanding amount 0
 			this.frm.set_value("write_off_amount",
-				flt(this.frm.doc.base_grand_total - this.frm.doc.paid_amount, precision("write_off_amount"))
+				flt(this.frm.doc.base_grand_total - this.frm.doc.paid_amount - this.frm.doc.total_advance, precision("write_off_amount"))
 			);
+			this.frm.toggle_enable("write_off_amount", false);
+
+		} else {
+			this.frm.toggle_enable("write_off_amount", true);
 		}
 
 		this.calculate_outstanding_amount(false);
@@ -219,10 +223,8 @@
 
 	if(cint(doc.is_pos) == 1) {
 		hide_field(par_flds);
-		unhide_field('payments_section');
 		cur_frm.fields_dict['items'].grid.set_column_disp(item_flds_normal, false);
 	} else {
-		hide_field('payments_section');
 		for (i in par_flds) {
 			var docfield = frappe.meta.docfield_map[doc.doctype][par_flds[i]];
 			if(!docfield.hidden) unhide_field(par_flds[i]);
@@ -238,6 +240,8 @@
 	if (frappe.boot.sysdefaults.country == 'India') unhide_field(['c_form_applicable', 'c_form_no']);
 	else hide_field(['c_form_applicable', 'c_form_no']);
 
+	this.frm.toggle_enable("write_off_amount", !!!cint(doc.write_off_outstanding_amount_automatically));
+
 	cur_frm.refresh_fields();
 }
 
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
index bb9f08f..11ae3b5 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json
@@ -654,7 +654,7 @@
    "read_only": 0
   }, 
   {
-   "depends_on": "is_pos", 
+   "depends_on": "eval:doc.is_pos===1||(doc.advances && doc.advances.length>0)", 
    "fieldname": "payments_section", 
    "fieldtype": "Section Break", 
    "label": "Payments", 
@@ -664,14 +664,6 @@
   }, 
   {
    "depends_on": "is_pos", 
-   "fieldname": "column_break3", 
-   "fieldtype": "Column Break", 
-   "permlevel": 0, 
-   "read_only": 0, 
-   "width": "50%"
-  }, 
-  {
-   "depends_on": "is_pos", 
    "fieldname": "paid_amount", 
    "fieldtype": "Currency", 
    "label": "Paid Amount", 
@@ -685,6 +677,14 @@
   }, 
   {
    "depends_on": "is_pos", 
+   "fieldname": "column_break3", 
+   "fieldtype": "Column Break", 
+   "permlevel": 0, 
+   "read_only": 0, 
+   "width": "50%"
+  }, 
+  {
+   "depends_on": "is_pos", 
    "fieldname": "cash_bank_account", 
    "fieldtype": "Link", 
    "label": "Cash/Bank Account", 
@@ -696,24 +696,16 @@
    "read_only": 0
   }, 
   {
-   "depends_on": "is_pos", 
+   "depends_on": "grand_total", 
    "fieldname": "column_break4", 
-   "fieldtype": "Column Break", 
+   "fieldtype": "Section Break", 
+   "label": "Write Off", 
    "permlevel": 0, 
    "read_only": 0, 
    "width": "50%"
   }, 
   {
-   "depends_on": "is_pos", 
-   "fieldname": "write_off_outstanding_amount_automatically", 
-   "fieldtype": "Check", 
-   "label": "Write Off Outstanding Amount", 
-   "permlevel": 0, 
-   "print_hide": 1, 
-   "read_only": 0
-  }, 
-  {
-   "depends_on": "is_pos", 
+   "depends_on": "", 
    "fieldname": "write_off_amount", 
    "fieldtype": "Currency", 
    "label": "Write Off Amount", 
@@ -724,7 +716,23 @@
    "read_only": 0
   }, 
   {
-   "depends_on": "is_pos", 
+   "depends_on": "", 
+   "fieldname": "write_off_outstanding_amount_automatically", 
+   "fieldtype": "Check", 
+   "label": "Write Off Outstanding Amount", 
+   "permlevel": 0, 
+   "print_hide": 1, 
+   "read_only": 0
+  }, 
+  {
+   "depends_on": "eval:doc.is_pos===1||(doc.advances && doc.advances.length>0)", 
+   "fieldname": "column_break_74", 
+   "fieldtype": "Column Break", 
+   "permlevel": 0, 
+   "precision": ""
+  }, 
+  {
+   "depends_on": "", 
    "fieldname": "write_off_account", 
    "fieldtype": "Link", 
    "label": "Write Off Account", 
@@ -734,7 +742,7 @@
    "read_only": 0
   }, 
   {
-   "depends_on": "is_pos", 
+   "depends_on": "", 
    "fieldname": "write_off_cost_center", 
    "fieldtype": "Link", 
    "label": "Write Off Cost Center", 
@@ -1246,8 +1254,8 @@
  "icon": "icon-file-text", 
  "idx": 1, 
  "is_submittable": 1, 
- "modified": "2015-03-23 14:46:49.412013", 
- "modified_by": "Administrator", 
+ "modified": "2015-04-02 13:42:22.985078", 
+ "modified_by": "anand@erpnext.com", 
  "module": "Accounts", 
  "name": "Sales Invoice", 
  "owner": "Administrator", 
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 9cb63b2..2a4c331 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -48,10 +48,10 @@
 		self.clear_unallocated_advances("Sales Invoice Advance", "advances")
 		self.validate_advance_jv("advances", "sales_order")
 		self.add_remarks()
+		self.validate_write_off_account()
 
 		if cint(self.is_pos):
 			self.validate_pos()
-			self.validate_write_off_account()
 
 		if cint(self.update_stock):
 			self.validate_item_code()
@@ -453,8 +453,10 @@
 		if gl_entries:
 			from erpnext.accounts.general_ledger import make_gl_entries
 
+			# if POS and amount is written off, there's no outstanding and hence no need to update it
 			update_outstanding = cint(self.is_pos) and self.write_off_account \
 				and 'No' or 'Yes'
+
 			make_gl_entries(gl_entries, cancel=(self.docstatus == 2),
 				update_outstanding=update_outstanding, merge_entries=False)
 
@@ -483,6 +485,8 @@
 
 		self.make_pos_gl_entries(gl_entries)
 
+		self.make_write_off_gl_entry(gl_entries)
+
 		return gl_entries
 
 	def make_customer_gl_entry(self, gl_entries):
@@ -555,29 +559,31 @@
 					"remarks": self.remarks,
 				})
 			)
-			# write off entries, applicable if only pos
-			if self.write_off_account and self.write_off_amount:
-				gl_entries.append(
-					self.get_gl_dict({
-						"account": self.debit_to,
-						"party_type": "Customer",
-						"party": self.customer,
-						"against": self.write_off_account,
-						"credit": self.write_off_amount,
-						"remarks": self.remarks,
-						"against_voucher": self.name,
-						"against_voucher_type": self.doctype,
-					})
-				)
-				gl_entries.append(
-					self.get_gl_dict({
-						"account": self.write_off_account,
-						"against": self.debit_to,
-						"debit": self.write_off_amount,
-						"remarks": self.remarks,
-						"cost_center": self.write_off_cost_center
-					})
-				)
+
+	def make_write_off_gl_entry(self, gl_entries):
+		# write off entries, applicable if only pos
+		if self.write_off_account and self.write_off_amount:
+			gl_entries.append(
+				self.get_gl_dict({
+					"account": self.debit_to,
+					"party_type": "Customer",
+					"party": self.customer,
+					"against": self.write_off_account,
+					"credit": self.write_off_amount,
+					"remarks": self.remarks,
+					"against_voucher": self.name,
+					"against_voucher_type": self.doctype,
+				})
+			)
+			gl_entries.append(
+				self.get_gl_dict({
+					"account": self.write_off_account,
+					"against": self.debit_to,
+					"debit": self.write_off_amount,
+					"remarks": self.remarks,
+					"cost_center": self.write_off_cost_center
+				})
+			)
 
 def get_list_context(context=None):
 	from erpnext.controllers.website_list_for_contact import get_list_context
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index 8b4e6cb..7ea0c66 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -14,6 +14,9 @@
 def get_party_details(party=None, account=None, party_type="Customer", company=None,
 	posting_date=None, price_list=None, currency=None, doctype=None):
 
+	if not party:
+		return {}
+
 	return _get_party_details(party, account, party_type,
 		company, posting_date, price_list, currency, doctype)
 
@@ -161,6 +164,9 @@
 	return due_date
 
 def get_credit_days(party_type, party, company):
+	if not party:
+		return None
+
 	party_group_doctype = "Customer Group" if party_type=="Customer" else "Supplier Type"
 	credit_days, party_group = frappe.db.get_value(party_type, party, ["credit_days", frappe.scrub(party_group_doctype)])
 
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index 9e2d34e..15a6fd1 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -3,6 +3,7 @@
 
 from __future__ import unicode_literals
 import frappe
+import json
 from frappe.utils import cstr, flt
 from frappe import msgprint, _, throw
 from frappe.model.mapper import get_mapped_doc
@@ -217,6 +218,25 @@
 	def on_update(self):
 		pass
 
+@frappe.whitelist()
+def stop_or_unstop_purchase_orders(names, status):
+	if not frappe.has_permission("Purchase Order", "write"):
+		frappe.throw(_("Not permitted"), frappe.PermissionError)
+
+	names = json.loads(names)
+	for name in names:
+		po = frappe.get_doc("Purchase Order", name)
+		if po.docstatus == 1:
+			if status=="Stopped":
+				if po.status not in ("Stopped", "Cancelled") and (po.per_received < 100 or po.per_billed < 100):
+					po.update_status("Stopped")
+			else:
+				if po.status == "Stopped":
+					po.update_status("Submitted")
+
+	frappe.local.message_log = []
+
+
 def set_missing_values(source, target):
 	target.ignore_pricing_rule = 1
 	target.run_method("set_missing_values")
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order_list.js b/erpnext/buying/doctype/purchase_order/purchase_order_list.js
index 2c28eec..08bf0fe 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order_list.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order_list.js
@@ -3,7 +3,7 @@
 		"supplier_name", "per_received", "per_billed", "status"],
 	get_indicator: function(doc) {
         if(doc.status==="Stopped") {
-			return [__("Stopped"), "red", "status,=,Stopped"];
+			return [__("Stopped"), "darkgrey", "status,=,Stopped"];
 		} else if(flt(doc.per_received) < 100 && doc.status!=="Stopped") {
 			return [__("Not Received"), "orange", "per_received,<,100|status,!=,Stopped"];
 		} else if(flt(doc.per_received) == 100 && flt(doc.per_billed) < 100 && doc.status!=="Stopped") {
@@ -12,5 +12,17 @@
 			return [__("Completed"), "green", "per_received,=,100|per_billed,=,100|status,!=,Stopped"];
 		}
 	},
-	order_by: "per_received asc, modified desc"
+	order_by: "per_received asc, modified desc",
+	onload: function(listview) {
+		var method = "erpnext.buying.doctype.purchase_order.purchase_order.stop_or_unstop_purchase_orders";
+
+		listview.page.add_menu_item(__("Set as Stopped"), function() {
+			listview.call_for_selected_items(method, {"status": "Stopped"});
+		});
+
+		listview.page.add_menu_item(__("Set as Unstopped"), function() {
+			listview.call_for_selected_items(method, {"status": "Submitted"});
+		});
+
+	}
 };
diff --git a/erpnext/crm/doctype/lead/lead.json b/erpnext/crm/doctype/lead/lead.json
index 2f5be34..7a02ff1 100644
--- a/erpnext/crm/doctype/lead/lead.json
+++ b/erpnext/crm/doctype/lead/lead.json
@@ -64,7 +64,7 @@
    "fieldname": "status", 
    "fieldtype": "Select", 
    "in_filter": 1, 
-   "in_list_view": 0, 
+   "in_list_view": 1, 
    "label": "Status", 
    "no_copy": 1, 
    "oldfieldname": "status", 
@@ -332,7 +332,7 @@
  ], 
  "icon": "icon-user", 
  "idx": 1, 
- "modified": "2015-03-18 07:06:34.330943", 
+ "modified": "2015-03-30 21:50:08.852355", 
  "modified_by": "Administrator", 
  "module": "CRM", 
  "name": "Lead", 
@@ -343,7 +343,6 @@
    "cancel": 0, 
    "create": 0, 
    "delete": 0, 
-   "match": "", 
    "permlevel": 1, 
    "read": 1, 
    "report": 1, 
@@ -401,7 +400,6 @@
    "cancel": 0, 
    "create": 0, 
    "delete": 0, 
-   "match": "", 
    "permlevel": 1, 
    "read": 1, 
    "report": 1, 
@@ -414,7 +412,6 @@
    "cancel": 0, 
    "create": 0, 
    "delete": 0, 
-   "match": "", 
    "permlevel": 1, 
    "read": 1, 
    "report": 1, 
diff --git a/erpnext/crm/doctype/lead/lead.py b/erpnext/crm/doctype/lead/lead.py
index 49a4e3d..009cfc2 100644
--- a/erpnext/crm/doctype/lead/lead.py
+++ b/erpnext/crm/doctype/lead/lead.py
@@ -64,7 +64,7 @@
 				self.email_id)
 			if len(email_list) > 1:
 				items = [e[0] for e in email_list if e[0]!=self.name]
-				frappe.throw(_("Email id must be unique, already exists for {0}").format(comma_and(items)))
+				frappe.throw(_("Email id must be unique, already exists for {0}").format(comma_and(items)), frappe.DuplicateEntryError)
 
 	def on_trash(self):
 		frappe.db.sql("""update `tabIssue` set lead='' where lead=%s""",
@@ -124,7 +124,7 @@
 		}}, target_doc)
 
 	return target_doc
-	
+
 @frappe.whitelist()
 def make_quotation(source_name, target_doc=None):
 	target_doc = get_mapped_doc("Lead", source_name,
diff --git a/erpnext/crm/doctype/newsletter/newsletter.py b/erpnext/crm/doctype/newsletter/newsletter.py
index b1a4bd0..f7f42a0 100644
--- a/erpnext/crm/doctype/newsletter/newsletter.py
+++ b/erpnext/crm/doctype/newsletter/newsletter.py
@@ -59,7 +59,7 @@
 			subject = self.subject, message = self.message,
 			reference_doctype = self.doctype, reference_name = self.name,
 			unsubscribe_method = "/api/method/erpnext.crm.doctype.newsletter.newsletter.unsubscribe",
-			unsubscribe_params = {"name": self.name})
+			unsubscribe_params = {"name": self.newsletter_list})
 
 		if not frappe.flags.in_test:
 			frappe.db.auto_commit_on_many_writes = False
@@ -85,9 +85,7 @@
 
 @frappe.whitelist(allow_guest=True)
 def unsubscribe(email, name):
-	from frappe.email.bulk import return_unsubscribed_page
 	from frappe.utils.verified_command import verify_request
-
 	if not verify_request():
 		return
 
@@ -97,8 +95,13 @@
 		subscriber.unsubscribed = 1
 		subscriber.save(ignore_permissions=True)
 
+	frappe.db.commit()
+
 	return_unsubscribed_page(email)
 
+def return_unsubscribed_page(email):
+	frappe.respond_as_web_page(_("Unsubscribed"), _("{0} has been successfully unsubscribed from this list.").format(email))
+
 def create_lead(email_id):
 	"""create a lead if it does not exist"""
 	from email.utils import parseaddr
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index dee46aa..79a3ffe 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -90,8 +90,11 @@
 	]
 }
 
-default_mail_footer = """<div style="padding: 7px; text-align: right;">
-	<a style="color: #888; font-size: 80%;" href="https://erpnext.com">Sent via ERPNext</a></div>"""
+default_mail_footer = """<div style="padding: 7px; margin-top: 7px;">
+	<a style="color: #8D99A6; font-size: 85%; text-decoration: none;" href="https://erpnext.com" target="_blank">
+		Sent via ERPNext
+	</a>
+</div>"""
 
 get_translated_dict = {
 	("page", "setup-wizard"): "frappe.geo.country_info.get_translated_dict",
diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py
index 4ba3e96..5a9bad29 100644
--- a/erpnext/hr/doctype/employee/employee.py
+++ b/erpnext/hr/doctype/employee/employee.py
@@ -131,7 +131,7 @@
 		employee = frappe.db.sql_list("""select name from `tabEmployee` where
 			user_id=%s and status='Active' and name!=%s""", (self.user_id, self.name))
 		if employee:
-			throw(_("User {0} is already assigned to Employee {1}").format(self.user_id, employee[0]))
+			throw(_("User {0} is already assigned to Employee {1}").format(self.user_id, employee[0]), frappe.DuplicateEntryError)
 
 	def validate_employee_leave_approver(self):
 		for l in self.get("leave_approvers")[:]:
diff --git a/erpnext/hr/doctype/job_applicant/job_applicant.py b/erpnext/hr/doctype/job_applicant/job_applicant.py
index eca767a..1bdd8fc 100644
--- a/erpnext/hr/doctype/job_applicant/job_applicant.py
+++ b/erpnext/hr/doctype/job_applicant/job_applicant.py
@@ -7,6 +7,7 @@
 from frappe.model.document import Document
 import frappe
 from frappe import _
+from frappe.utils import comma_and
 
 class JobApplicant(Document):
 	def autoname(self):
@@ -15,5 +16,16 @@
 			frappe.throw(_("Name or Email is mandatory"), frappe.NameError)
 		self.name = " - ".join(keys)
 
+	def validate(self):
+		self.check_email_id_is_unique()
+
+	def check_email_id_is_unique(self):
+		if self.email_id:
+			names = frappe.db.sql_list("""select name from `tabJob Applicant`
+				where email_id=%s and name!=%s""", (self.email_id, self.name))
+
+			if names:
+				frappe.throw(_("Email id must be unique, already exists for {0}").format(comma_and(names)), frappe.DuplicateEntryError)
+
 	def set_sender(self, sender):
 		self.email_id = sender
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py
index 524d11e..ead4b4f 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.py
+++ b/erpnext/manufacturing/doctype/production_order/production_order.py
@@ -56,7 +56,7 @@
 
 	def validate_warehouse(self):
 		from erpnext.stock.utils import validate_warehouse_company
-
+		
 		for w in [self.fg_warehouse, self.wip_warehouse]:
 			validate_warehouse_company(w, self.company)
 
@@ -176,7 +176,7 @@
 
 		operations = frappe.db.sql("""select operation, description, workstation,
 			hour_rate, time_in_mins, operating_cost as "planned_operating_cost", "Pending" as status
-			from `tabBOM Operation` where parent = %s""", self.bom_no, as_dict=1)
+			from `tabBOM Operation` where parent = %s order by idx""", self.bom_no, as_dict=1)
 
 		self.set('operations', operations)
 
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index de51782..14ec93f 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -85,6 +85,7 @@
 erpnext.patches.v4_2.recalculate_bom_cost
 erpnext.patches.v4_2.fix_gl_entries_for_stock_transactions
 erpnext.patches.v4_2.update_requested_and_ordered_qty
+execute:frappe.rename_doc("DocType", "Support Ticket", "Issue", force=True)
 erpnext.patches.v4_4.make_email_accounts
 execute:frappe.delete_doc("DocType", "Contact Control")
 erpnext.patches.v4_2.discount_amount
@@ -94,7 +95,6 @@
 execute:frappe.db.sql("update `tabMaterial Request` set material_request_type = 'Material Transfer' where material_request_type = 'Transfer'")
 execute:frappe.reload_doc('stock', 'doctype', 'item')
 execute:frappe.db.sql("update `tabItem` i set apply_warehouse_wise_reorder_level=1, re_order_level=0, re_order_qty=0 where exists(select name from `tabItem Reorder` where parent=i.name)")
-execute:frappe.rename_doc("DocType", "Support Ticket", "Issue", force=True)
 erpnext.patches.v5_0.set_default_company_in_bom
 erpnext.patches.v5_0.capacity_planning
 execute:frappe.reload_doc('crm', 'doctype', 'lead')
diff --git a/erpnext/patches/v4_4/make_email_accounts.py b/erpnext/patches/v4_4/make_email_accounts.py
index 3ca5fe9..09d1ccb 100644
--- a/erpnext/patches/v4_4/make_email_accounts.py
+++ b/erpnext/patches/v4_4/make_email_accounts.py
@@ -21,7 +21,6 @@
 
 		account.enable_outgoing = 1
 		account.enable_incoming = 0
-		account.is_global = 1
 
 		account.insert()
 
@@ -44,7 +43,7 @@
 			account.set(target_fieldname, support.get(source_fieldname))
 
 		account.enable_outgoing = 0
-		account.is_global = 1
+		account.append_to = "Issue"
 
 		account.insert()
 
@@ -65,7 +64,6 @@
 				account.set(target_fieldname, source.get(source_fieldname))
 
 			account.enable_outgoing = 0
-			account.is_global = 1
 			account.append_to = "Lead" if doctype=="Sales Email Settings" else "Job Applicant"
 
 			account.insert()
diff --git a/erpnext/patches/v5_0/newsletter.py b/erpnext/patches/v5_0/newsletter.py
index 1969c3c..bd95937 100644
--- a/erpnext/patches/v5_0/newsletter.py
+++ b/erpnext/patches/v5_0/newsletter.py
@@ -5,6 +5,7 @@
 import frappe.permissions
 
 def execute():
+	frappe.reload_doc("core", "doctype", "block_module")
 	frappe.reload_doctype("User")
 	frappe.reload_doctype("Lead")
 	frappe.reload_doctype("Contact")
diff --git a/erpnext/patches/v5_0/rename_table_fieldnames.py b/erpnext/patches/v5_0/rename_table_fieldnames.py
index 499ef0c..ca92c28 100644
--- a/erpnext/patches/v5_0/rename_table_fieldnames.py
+++ b/erpnext/patches/v5_0/rename_table_fieldnames.py
@@ -92,21 +92,12 @@
 	"C-Form": [
 		["invoice_details", "invoices"]
 	],
-	"Customize Form": [
-		["customize_form_fields", "fields"]
-	],
-	"Email Alert": [
-		["email_alert_recipients", "recipients"]
-	],
 	"Employee": [
 		["employee_leave_approvers", "leave_approvers"],
 		["educational_qualification_details", "education"],
 		["previous_experience_details", "external_work_history"],
 		["experience_in_company_details", "internal_work_history"]
 	],
-	"Event": [
-		["event_roles", "roles"]
-	],
 	"Expense Claim": [
 		["expense_voucher_details", "expenses"]
 	],
@@ -201,10 +192,6 @@
 	"Time Log Batch": [
 		["time_log_batch_details", "time_logs"]
 	],
-	"Workflow": [
-		["workflow_document_states", "states"],
-		["workflow_transitions", "transitions"]
-	],
 	"Workstation": [
 		["workstation_operation_hours", "working_hours"]
 	],
@@ -241,7 +228,6 @@
 	frappe.reload_doc("stock", "doctype", "item_variant")
 	frappe.reload_doc("accounts", "doctype", "party_account")
 	frappe.reload_doc("accounts", "doctype", "fiscal_year_company")
-	frappe.reload_doc("workflow", "doctype", "workflow")
 
 	#rename table fieldnames
 	for dn in rename_map:
diff --git a/erpnext/patches/v5_0/rename_total_fields.py b/erpnext/patches/v5_0/rename_total_fields.py
index 04b191e..cf95caa 100644
--- a/erpnext/patches/v5_0/rename_total_fields.py
+++ b/erpnext/patches/v5_0/rename_total_fields.py
@@ -41,12 +41,12 @@
 def execute():
 	for doctypes, fields in [[selling_doctypes, selling_renamed_fields], [buying_doctypes, buying_renamed_fields]]:
 		for dt in doctypes:
-			meta = frappe.get_meta(dt)
 			frappe.reload_doc(get_doctype_module(dt), "doctype", scrub(dt))
+			table_columns = frappe.db.get_table_columns(dt)
 			base_net_total = frappe.db.sql("select sum(ifnull({0}, 0)) from `tab{1}`".format(fields[0][1], dt))[0][0]
 			if not base_net_total:
 				for f in fields:
-					if meta.get_field(f[0]):
+					if f[0] in table_columns:
 						rename_field(dt, f[0], f[1])
 
 				# Added new field "total_taxes_and_charges" in buying cycle, updating value
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index a51a495..acd0877 100644
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -85,3 +85,12 @@
 			limit %(start)s, %(page_len)s """ % {'key': searchfield,
 			'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype),
 			'start': start, 'page_len': page_len})
+
+
+@frappe.whitelist()
+def set_multiple_status(names, status):
+	names = json.loads(names)
+	for name in names:
+		task = frappe.get_doc("Task", name)
+		task.status = status
+		task.save()
diff --git a/erpnext/projects/doctype/task/task_list.js b/erpnext/projects/doctype/task/task_list.js
index 4406085..9150501 100644
--- a/erpnext/projects/doctype/task/task_list.js
+++ b/erpnext/projects/doctype/task/task_list.js
@@ -1,4 +1,15 @@
 frappe.listview_settings['Task'] = {
 	add_fields: ["project", "status", "priority", "exp_end_date"],
-	filters:[["status","=", "Open"]]
+	onload: function(listview) {
+		var method = "erpnext.projects.doctype.task.task.set_multiple_status";
+
+		listview.page.add_menu_item(__("Set as Open"), function() {
+			listview.call_for_selected_items(method, {"status": "Open"});
+		});
+
+		listview.page.add_menu_item(__("Set as Closed"), function() {
+			listview.call_for_selected_items(method, {"status": "Closed"});
+		});
+	}
+
 };
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index a06f3d7..890f39a 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -3,6 +3,7 @@
 
 from __future__ import unicode_literals
 import frappe
+import json
 import frappe.utils
 from frappe.utils import cstr, flt, getdate, comma_and
 from frappe import _
@@ -238,6 +239,24 @@
 	return list_context
 
 @frappe.whitelist()
+def stop_or_unstop_sales_orders(names, status):
+	if not frappe.has_permission("Sales Order", "write"):
+		frappe.throw(_("Not permitted"), frappe.PermissionError)
+
+	names = json.loads(names)
+	for name in names:
+		so = frappe.get_doc("Sales Order", name)
+		if so.docstatus == 1:
+			if status=="Stop":
+				if so.status not in ("Stopped", "Cancelled") and (so.per_delivered < 100 or so.per_billed < 100):
+					so.stop_sales_order()
+			else:
+				if so.status == "Stopped":
+					so.unstop_sales_order()
+
+	frappe.local.message_log = []
+
+@frappe.whitelist()
 def make_material_request(source_name, target_doc=None):
 	def postprocess(source, doc):
 		doc.material_request_type = "Purchase"
diff --git a/erpnext/selling/doctype/sales_order/sales_order_list.js b/erpnext/selling/doctype/sales_order/sales_order_list.js
index 702c300..085d0e8 100644
--- a/erpnext/selling/doctype/sales_order/sales_order_list.js
+++ b/erpnext/selling/doctype/sales_order/sales_order_list.js
@@ -3,7 +3,7 @@
 		"status"],
 	get_indicator: function(doc) {
         if(doc.status==="Stopped") {
-			return [__("Stopped"), "red", "status,=,Stopped"];
+			return [__("Stopped"), "darkgrey", "status,=,Stopped"];
         } else if(flt(doc.per_delivered) < 100 && frappe.datetime.get_diff(doc.delivery_date) < 0) {
 			return [__("Overdue"), "red", "per_delivered,<,100|delivery_date,<,Today|status,!=,Stopped"];
 		} else if(flt(doc.per_delivered) < 100 && doc.status!=="Stopped") {
@@ -14,5 +14,17 @@
 			return [__("Completed"), "green", "per_delivered,=,100|per_billed,=,100|status,!=,Stopped"];
 		}
 	},
-	order_by: "per_delivered asc, modified desc"
+	order_by: "per_delivered asc, modified desc",
+	onload: function(listview) {
+		var method = "erpnext.selling.doctype.sales_order.sales_order.stop_or_unstop_sales_orders";
+
+		listview.page.add_menu_item(__("Set as Stopped"), function() {
+			listview.call_for_selected_items(method, {"status": "Stop"});
+		});
+
+		listview.page.add_menu_item(__("Set as Unstopped"), function() {
+			listview.call_for_selected_items(method, {"status": "Unstop"});
+		});
+
+	}
 };
diff --git a/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py b/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py
index 3360ddb..2b88a50 100644
--- a/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py
+++ b/erpnext/selling/report/customer_acquisition_and_loyalty/customer_acquisition_and_loyalty.py
@@ -18,11 +18,11 @@
 		company_condition = ' and company=%(company)s'
 
 	for si in frappe.db.sql("""select posting_date, customer, base_grand_total from `tabSales Invoice`
-		where docstatus=1 and posting_date <= %(to_date)s 
-		{company_condition} order by posting_date""".format(company_condition=company_condition), 
+		where docstatus=1 and posting_date <= %(to_date)s
+		{company_condition} order by posting_date""".format(company_condition=company_condition),
 		filters, as_dict=1):
-				
-		key = si.posting_date[:7]
+
+		key = si.posting_date.strftime("%Y-%m-%d")
 		if not si.customer in customers:
 			new_customers_in.setdefault(key, [0, 0.0])
 			new_customers_in[key][0] += 1
@@ -32,14 +32,14 @@
 			repeat_customers_in.setdefault(key, [0, 0.0])
 			repeat_customers_in[key][0] += 1
 			repeat_customers_in[key][1] += si.base_grand_total
-			
+
 	# time series
 	from_year, from_month, temp = filters.get("from_date").split("-")
 	to_year, to_month, temp = filters.get("to_date").split("-")
-	
+
 	from_year, from_month, to_year, to_month = \
 		cint(from_year), cint(from_month), cint(to_year), cint(to_month)
-	
+
 	out = []
 	for year in xrange(from_year, to_year+1):
 		for month in xrange(from_month if year==from_year else 1, (to_month+1) if year==to_year else 13):
@@ -48,19 +48,18 @@
 			new = new_customers_in.get(key, [0,0.0])
 			repeat = repeat_customers_in.get(key, [0,0.0])
 
-			out.append([year, calendar.month_name[month], 
+			out.append([year, calendar.month_name[month],
 				new[0], repeat[0], new[0] + repeat[0],
 				new[1], repeat[1], new[1] + repeat[1]])
-					
+
 	return [
-		_("Year"), _("Month"), 
-		_("New Customers") + ":Int", 
-		_("Repeat Customers") + ":Int", 
+		_("Year"), _("Month"),
+		_("New Customers") + ":Int",
+		_("Repeat Customers") + ":Int",
 		_("Total") + ":Int",
-		_("New Customer Revenue") + ":Currency:150", 
-		_("Repeat Customer Revenue") + ":Currency:150", 
+		_("New Customer Revenue") + ":Currency:150",
+		_("Repeat Customer Revenue") + ":Currency:150",
 		_("Total Revenue") + ":Currency:150"
 	], out
-		
-		
-		
\ No newline at end of file
+
+
diff --git a/erpnext/setup/doctype/sales_person/sales_person.py b/erpnext/setup/doctype/sales_person/sales_person.py
index 9098aae..5f70b23 100644
--- a/erpnext/setup/doctype/sales_person/sales_person.py
+++ b/erpnext/setup/doctype/sales_person/sales_person.py
@@ -27,7 +27,7 @@
 				frappe.throw(_("User ID not set for Employee {0}").format(self.employee))
 			else:
 				return frappe.db.get_value("User", user, "email") or user
-	
+
 	def validate_employee_id(self):
 		if frappe.db.exists({"doctype": "Sales Person","employee": self.employee}):
-			frappe.throw("Another sales person with the same employee id exists.")
+			frappe.throw("Another sales person with the same employee id exists.", frappe.DuplicateEntryError)
diff --git a/erpnext/setup/page/setup_wizard/emails/email-1.md b/erpnext/setup/page/setup_wizard/emails/email-1.md
new file mode 100644
index 0000000..56ad94f
--- /dev/null
+++ b/erpnext/setup/page/setup_wizard/emails/email-1.md
@@ -0,0 +1,15 @@
+Dear {{ fullname }},
+
+If you aren't a pro, setting me up, is not an easy job. Here are some tips:
+
+1. Try and make dummy cycles: Run your dummy quotes, invoices, payments, deliveries in the system so that you can get familiar with what I can do for you.
+1. Data Import Tool: You can import bulk data into me using the data import tool: via Setup > Data > Data Import Tool
+1. Help me make more friends: Add more users via Setup > Users and Permissions > User
+
+If you need help or are stuck, [head to the user forum](https://discuss.frappe.io) or [read my manual](https://manual.erpnext.com).
+
+Best of luck!
+
+Your ERPNext Account\*
+
+\* This is an automated messaged sent by your ERPNext installation to keep you motivated. You will receive one more such message in another 3 days.
diff --git a/erpnext/setup/page/setup_wizard/emails/email-2.md b/erpnext/setup/page/setup_wizard/emails/email-2.md
new file mode 100644
index 0000000..f2b5d6a
--- /dev/null
+++ b/erpnext/setup/page/setup_wizard/emails/email-2.md
@@ -0,0 +1,16 @@
+Dear {{ fullname }},
+
+Hey, how's it going?
+
+If you still need some help, there is a large community out there to help you. Some places you can start:
+
+1. [Ask your questions in the user forum](https://discuss.frappe.io)
+1. [Buy support from the ERPNext Team](https://erpnext.com/pricing)
+1. [Connect with a Service Provider](https://community.erpnext.com/service-providers)
+1. [Hangout on the community chat (gitter.im)](https://gitter.im/frappe/erpnext)
+
+Thanks!
+
+Your ERPNext Account\*
+
+\* That's it from me. Have fun!
diff --git a/erpnext/setup/page/setup_wizard/install_fixtures.py b/erpnext/setup/page/setup_wizard/install_fixtures.py
index 32fb6a5..6f3f9e1 100644
--- a/erpnext/setup/page/setup_wizard/install_fixtures.py
+++ b/erpnext/setup/page/setup_wizard/install_fixtures.py
@@ -179,4 +179,3 @@
 				pass
 			else:
 				raise
-
diff --git a/erpnext/setup/page/setup_wizard/setup_wizard.js b/erpnext/setup/page/setup_wizard/setup_wizard.js
index ef39b03..eb47e4a 100644
--- a/erpnext/setup/page/setup_wizard/setup_wizard.js
+++ b/erpnext/setup/page/setup_wizard/setup_wizard.js
@@ -50,7 +50,7 @@
 		this.slides = this.slides;
 		this.slide_dict = {};
 		this.welcomed = true;
-		frappe.set_route(this.page_name, "0");
+		frappe.set_route("setup-wizard/0");
 	},
 	make: function() {
 		this.parent = $('<div class="setup-wizard-wrapper">').appendTo(this.parent);
@@ -565,10 +565,12 @@
 							placeholder:__("A Product or Service")},
 						{fieldtype:"Select", label:__("Group"), fieldname:"item_group_" + i,
 							options:[__("Products"), __("Services"),
-								__("Raw Material"), __("Consumable"), __("Sub Assemblies")]},
+								__("Raw Material"), __("Consumable"), __("Sub Assemblies")],
+							"default": __("Products")},
 						{fieldtype:"Select", fieldname:"item_uom_" + i, label:__("UOM"),
 							options:[__("Unit"), __("Nos"), __("Box"), __("Pair"), __("Kg"), __("Set"),
-								__("Hour"), __("Minute")]},
+								__("Hour"), __("Minute")],
+							"default": __("Unit")},
 						{fieldtype: "Check", fieldname: "is_sales_item_" + i, label:__("We sell this Item"), default: 1},
 						{fieldtype: "Check", fieldname: "is_purchase_item_" + i, label:__("We buy this Item")},
 						{fieldtype:"Column Break"},
diff --git a/erpnext/setup/page/setup_wizard/setup_wizard.py b/erpnext/setup/page/setup_wizard/setup_wizard.py
index 4df21b5..11f3269 100644
--- a/erpnext/setup/page/setup_wizard/setup_wizard.py
+++ b/erpnext/setup/page/setup_wizard/setup_wizard.py
@@ -11,8 +11,9 @@
 	get_lang_dict, send_translations, get_language_from_code)
 from frappe.geo.country_info import get_country_info
 from frappe.utils.nestedset import get_root_of
-from default_website import website_maker
+from .default_website import website_maker
 import install_fixtures
+from .welcome_emails import setup_welcome_emails
 
 @frappe.whitelist()
 def setup_account(args=None):
@@ -73,8 +74,12 @@
 		website_maker(args.company_name.strip(), args.company_tagline, args.name)
 		create_logo(args)
 
+		frappe.db.commit()
+
 		login_as_first_user(args)
 
+		setup_welcome_emails()
+
 		frappe.db.commit()
 
 		frappe.clear_cache()
diff --git a/erpnext/setup/page/setup_wizard/welcome_emails.py b/erpnext/setup/page/setup_wizard/welcome_emails.py
new file mode 100644
index 0000000..03a9717
--- /dev/null
+++ b/erpnext/setup/page/setup_wizard/welcome_emails.py
@@ -0,0 +1,20 @@
+# 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 import add_days, nowdate, get_fullname
+import markdown2
+
+def setup_welcome_emails():
+	for email in (
+		{"fname": "email-1.md", "subject": "Setting up ERPNext", "after": 1},
+		{"fname": "email-2.md", "subject": "Getting ERPNext Help", "after": 3},
+	):
+		content = frappe.get_template("setup/page/setup_wizard/emails/" \
+			+ email["fname"]).render({"fullname": get_fullname()})
+
+		frappe.sendmail(recipients = frappe.session.user, subject = email["subject"],
+			sender = "hello@erpnext.com",
+			content=markdown2.markdown(content), as_bulk = True,
+			send_after= add_days(nowdate(), email["after"]))
diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py
index 4f456fe..45f5ccc 100644
--- a/erpnext/stock/report/stock_balance/stock_balance.py
+++ b/erpnext/stock/report/stock_balance/stock_balance.py
@@ -4,7 +4,7 @@
 from __future__ import unicode_literals
 import frappe
 from frappe import _
-from frappe.utils import flt
+from frappe.utils import flt, getdate
 
 def execute(filters=None):
 	if not filters: filters = {}
@@ -88,11 +88,11 @@
 			qty_diff = flt(d.actual_qty)
 
 		value_diff = flt(d.stock_value_difference)
-
-		if d.posting_date < filters["from_date"]:
+		
+		if d.posting_date < getdate(filters["from_date"]):
 			qty_dict.opening_qty += qty_diff
 			qty_dict.opening_val += value_diff
-		elif d.posting_date >= filters["from_date"] and d.posting_date <= filters["to_date"]:
+		elif d.posting_date >= getdate(filters["from_date"]) and d.posting_date <= getdate(filters["to_date"]):
 			qty_dict.val_rate = d.valuation_rate
 			if qty_diff > 0:
 				qty_dict.in_qty += qty_diff
diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js
new file mode 100644
index 0000000..f92e4e6
--- /dev/null
+++ b/erpnext/support/doctype/issue/issue.js
@@ -0,0 +1,15 @@
+frappe.ui.form.on("Issue", {
+	"refresh": function(frm) {
+		if(frm.doc.status==="Open") {
+			frm.add_custom_button("Close", function() {
+				frm.set_value("status", "Closed");
+				frm.save();
+			});
+		} else {
+			frm.add_custom_button("Reopen", function() {
+				frm.set_value("status", "Open");
+				frm.save();
+			});
+		}
+	}
+});
diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py
index 841d905..dc6809f 100644
--- a/erpnext/support/doctype/issue/issue.py
+++ b/erpnext/support/doctype/issue/issue.py
@@ -3,6 +3,7 @@
 
 from __future__ import unicode_literals
 import frappe
+import json
 from frappe import _
 
 from frappe.model.document import Document
@@ -75,3 +76,9 @@
 	frappe.db.sql("""update `tabIssue` set status = 'Closed'
 		where status = 'Replied'
 		and date_sub(curdate(),interval 15 Day) > modified""")
+
+@frappe.whitelist()
+def set_multiple_status(names, status):
+	names = json.loads(names)
+	for name in names:
+		set_status(name, status)
diff --git a/erpnext/support/doctype/issue/issue_list.js b/erpnext/support/doctype/issue/issue_list.js
index 02fd40c..7198b0c 100644
--- a/erpnext/support/doctype/issue/issue_list.js
+++ b/erpnext/support/doctype/issue/issue_list.js
@@ -1,3 +1,14 @@
 frappe.listview_settings['Issue'] = {
-	colwidths: {"subject": 6}
+	colwidths: {"subject": 6},
+	onload: function(listview) {
+		var method = "erpnext.support.doctype.issue.issue.set_multiple_status";
+
+		listview.page.add_menu_item(__("Set as Open"), function() {
+			listview.call_for_selected_items(method, {"status": "Open"});
+		});
+
+		listview.page.add_menu_item(__("Set as Closed"), function() {
+			listview.call_for_selected_items(method, {"status": "Closed"});
+		});
+	}
 }
diff --git a/erpnext/utilities/doctype/note/note.py b/erpnext/utilities/doctype/note/note.py
index 757684c..d81363c 100644
--- a/erpnext/utilities/doctype/note/note.py
+++ b/erpnext/utilities/doctype/note/note.py
@@ -24,10 +24,7 @@
 	if user == "Administrator":
 		return ""
 
-	return """(`tabNote`.public=1 or `tabNote`.owner="{user}" or exists (
-		select name from `tabNote User`
-			where `tabNote User`.parent=`tabNote`.name
-			and `tabNote User`.user="{user}"))""".format(user=frappe.db.escape(user))
+	return "`tabNote`.public=1"
 
 def has_permission(doc, ptype, user):
 	if doc.public == 1 or user == "Administrator":