[capacity planning] automatically plan Time Logs from Production Order
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.json b/erpnext/accounts/doctype/journal_entry/journal_entry.json
index 12d0bab..7c1273d 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.json
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.json
@@ -17,7 +17,7 @@
    "fieldname": "voucher_type", 
    "fieldtype": "Select", 
    "in_filter": 1, 
-   "in_list_view": 1, 
+   "in_list_view": 0, 
    "label": "Voucher Type", 
    "oldfieldname": "voucher_type", 
    "oldfieldtype": "Select", 
@@ -289,7 +289,7 @@
   }, 
   {
    "default": "No", 
-   "description": "Considered as Opening Balance", 
+   "description": "", 
    "fieldname": "is_opening", 
    "fieldtype": "Select", 
    "in_filter": 1, 
@@ -303,10 +303,10 @@
    "search_index": 1
   }, 
   {
-   "description": "Actual Posting Date", 
+   "description": "", 
    "fieldname": "aging_date", 
    "fieldtype": "Date", 
-   "label": "Aging Date", 
+   "label": "Ageing Date", 
    "no_copy": 0, 
    "oldfieldname": "aging_date", 
    "oldfieldtype": "Date", 
@@ -356,6 +356,33 @@
    "permlevel": 0
   }, 
   {
+   "allow_on_submit": 1, 
+   "fieldname": "select_print_heading", 
+   "fieldtype": "Link", 
+   "label": "Print Heading", 
+   "no_copy": 1, 
+   "oldfieldname": "select_print_heading", 
+   "oldfieldtype": "Link", 
+   "options": "Print Heading", 
+   "permlevel": 0, 
+   "print_hide": 1, 
+   "read_only": 0, 
+   "report_hide": 1
+  }, 
+  {
+   "fieldname": "amended_from", 
+   "fieldtype": "Link", 
+   "ignore_user_permissions": 1, 
+   "label": "Amended From", 
+   "no_copy": 1, 
+   "oldfieldname": "amended_from", 
+   "oldfieldtype": "Link", 
+   "options": "Journal Entry", 
+   "permlevel": 0, 
+   "print_hide": 1, 
+   "read_only": 1
+  }, 
+  {
    "fieldname": "column_break3", 
    "fieldtype": "Column Break", 
    "oldfieldtype": "Column Break", 
@@ -427,37 +454,18 @@
    "search_index": 1
   }, 
   {
-   "allow_on_submit": 1, 
-   "fieldname": "select_print_heading", 
-   "fieldtype": "Link", 
-   "label": "Print Heading", 
-   "no_copy": 1, 
-   "oldfieldname": "select_print_heading", 
-   "oldfieldtype": "Link", 
-   "options": "Print Heading", 
+   "fieldname": "title", 
+   "fieldtype": "Data", 
+   "hidden": 1, 
+   "label": "Title", 
    "permlevel": 0, 
-   "print_hide": 1, 
-   "read_only": 0, 
-   "report_hide": 1
-  }, 
-  {
-   "fieldname": "amended_from", 
-   "fieldtype": "Link", 
-   "ignore_user_permissions": 1, 
-   "label": "Amended From", 
-   "no_copy": 1, 
-   "oldfieldname": "amended_from", 
-   "oldfieldtype": "Link", 
-   "options": "Journal Entry", 
-   "permlevel": 0, 
-   "print_hide": 1, 
-   "read_only": 1
+   "precision": ""
   }
  ], 
  "icon": "icon-file-text", 
  "idx": 1, 
  "is_submittable": 1, 
- "modified": "2015-02-20 05:07:15.435166", 
+ "modified": "2015-02-23 04:46:05.569476", 
  "modified_by": "Administrator", 
  "module": "Accounts", 
  "name": "Journal Entry", 
@@ -514,5 +522,5 @@
  "search_fields": "voucher_type,posting_date, due_date, cheque_no", 
  "sort_field": "modified", 
  "sort_order": "DESC", 
- "title_field": "voucher_type"
+ "title_field": "title"
 }
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index 66e4854..a0a5a86 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -40,6 +40,7 @@
 		self.validate_expense_claim()
 		self.validate_credit_debit_note()
 		self.validate_empty_accounts_table()
+		self.set_title()
 
 	def on_submit(self):
 		self.check_credit_limit()
@@ -47,6 +48,9 @@
 		self.update_advance_paid()
 		self.update_expense_claim()
 
+	def set_title(self):
+		self.title = self.pay_to_recd_from or self.accounts[0].account
+
 	def update_advance_paid(self):
 		advance_paid = frappe._dict()
 		for d in self.get("accounts"):
@@ -442,16 +446,16 @@
 				if d.debit > pending_amount:
 					frappe.throw(_("Row No {0}: Amount cannot be greater than Pending Amount against Expense Claim {1}. \
 						Pending Amount is {2}".format(d.idx, d.against_expense_claim, pending_amount)))
-						
+
 	def validate_credit_debit_note(self):
 		count = frappe.db.exists({
 			"doctype": "Journal Entry",
 			"stock_entry":self.stock_entry,
-			"docstatus":1	
+			"docstatus":1
 		})
 		if count:
 			frappe.throw(_("{0} already made against stock entry {1}".format(self.voucher_type, self.stock_entry)))
-			
+
 	def validate_empty_accounts_table(self):
 		if not self.get('accounts'):
 			frappe.throw("Accounts table cannot be blank.")
@@ -462,11 +466,17 @@
 	if mode_of_payment:
 		account = get_bank_cash_account(mode_of_payment, company)
 		if account.get("bank_cash_account"):
-			account.update({"balance": get_balance_on(account.get("cash_bank_account"))})
+			account.update({"balance": get_balance_on(account.get("bank_cash_account"))})
 			return account
 
-	account = frappe.db.get_value("Company", company, \
-		voucher_type=="Bank Voucher" and "default_bank_account" or "default_cash_account")
+	if voucher_type=="Bank Entry":
+		account = frappe.db.get_value("Company", company, "default_bank_account")
+		if not account:
+			account = frappe.db.get_value("Account", {"company": company, "account_type": "Bank"})
+	elif voucher_type=="Cash Entry":
+		account = frappe.db.get_value("Company", company, "default_cash_account")
+		if not account:
+			account = frappe.db.get_value("Account", {"company": company, "account_type": "Cash"})
 
 	if account:
 		return {
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry_list.js b/erpnext/accounts/doctype/journal_entry/journal_entry_list.js
index 101793c..48d6115 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry_list.js
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry_list.js
@@ -1,3 +1,12 @@
 frappe.listview_settings['Journal Entry'] = {
-	add_fields: ["voucher_type", "posting_date", "total_debit", "company", "user_remark"]
+	add_fields: ["voucher_type", "posting_date", "total_debit", "company", "user_remark"],
+	get_indicator: function(doc) {
+		if(doc.docstatus==0) {
+			return [__("Draft", "red", "docstatus,=,0")]
+		} else if(doc.docstatus==2) {
+			return [__("Cancelled", "grey", "docstatus,=,2")]
+		} else {
+			return [__(doc.voucher_type), "blue", "voucher_type,=," + doc.voucher_type]
+		}
+	}
 };
diff --git a/erpnext/config/manufacturing.py b/erpnext/config/manufacturing.py
index 6c915b7..bd258fb 100644
--- a/erpnext/config/manufacturing.py
+++ b/erpnext/config/manufacturing.py
@@ -19,6 +19,11 @@
 				},
 				{
 					"type": "doctype",
+					"name": "Time Log",
+					"description": _("Time Logs for manufacturing."),
+				},
+				{
+					"type": "doctype",
 					"name": "Item",
 					"description": _("All Products or Services."),
 				},
diff --git a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json
index be5d5fc..1fa949d 100644
--- a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json
+++ b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json
@@ -34,11 +34,10 @@
   }, 
   {
    "default": "30", 
-   "description": "Delay in start time of production order operations if automatically make time logs is used.\n(in mins)", 
-   "fieldname": "operations_start_delay", 
-   "fieldtype": "Float", 
-   "in_list_view": 1, 
-   "label": "Operations Start Delay", 
+   "description": "Try planning operations for X days in advance.", 
+   "fieldname": "capacity_planning_for_days", 
+   "fieldtype": "Data", 
+   "label": "Capacity Planning For (Days)", 
    "permlevel": 0, 
    "precision": ""
   }
@@ -51,7 +50,7 @@
  "is_submittable": 0, 
  "issingle": 1, 
  "istable": 0, 
- "modified": "2015-02-05 05:11:41.192126", 
+ "modified": "2015-02-23 09:05:58.927098", 
  "modified_by": "Administrator", 
  "module": "Manufacturing", 
  "name": "Manufacturing Settings", 
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.js b/erpnext/manufacturing/doctype/production_order/production_order.js
index 1febb74..48fe7a0 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.js
+++ b/erpnext/manufacturing/doctype/production_order/production_order.js
@@ -85,6 +85,14 @@
 				frm.add_custom_button(__('Unstop'), cur_frm.cscript['Unstop Production Order'],
 				"icon-check", "btn-default");
 			}
+
+			// opertions
+			if ((doc.operations || []).length) {
+				frm.add_custom_button(__('Show Time Logs'), function() {
+					frappe.route_options = {"production_order": frm.doc.name};
+					frappe.set_route("List", "Time Log");
+				});
+			}
 		}
 
 	},
@@ -191,6 +199,11 @@
 		});
 	},
 
+	show_time_logs: function(doc, doctype, name) {
+		frappe.route_options = {"operation_id": name};
+		frappe.set_route("List", "Time Log");
+	},
+
 	make_time_log: function(doc, cdt, cdn){
 		var child = locals[cdt][cdn]
 		frappe.call({
@@ -209,16 +222,7 @@
 				frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
 			}
 		});
-	},
-
-	auto_time_log: function(doc){
-		frappe.call({
-			method:"erpnext.manufacturing.doctype.production_order.production_order.auto_make_time_log",
-			args: {
-				"production_order_id": doc.name
-			}
-		});
-	},
+	}
 });
 
 cur_frm.cscript['Stop Production Order'] = function() {
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.json b/erpnext/manufacturing/doctype/production_order/production_order.json
index ae66c5e..089fd38 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.json
+++ b/erpnext/manufacturing/doctype/production_order/production_order.json
@@ -271,15 +271,6 @@
    "read_only": 1
   }, 
   {
-   "allow_on_submit": 1, 
-   "depends_on": "eval:doc.docstatus==1", 
-   "fieldname": "auto_time_log", 
-   "fieldtype": "Button", 
-   "label": "Automatically Make Time logs", 
-   "permlevel": 0, 
-   "precision": ""
-  }, 
-  {
    "fieldname": "more_info", 
    "fieldtype": "Section Break", 
    "label": "More Info", 
@@ -360,7 +351,7 @@
  "idx": 1, 
  "in_create": 0, 
  "is_submittable": 1, 
- "modified": "2015-02-20 05:04:13.881343", 
+ "modified": "2015-02-23 07:42:05.639225", 
  "modified_by": "Administrator", 
  "module": "Manufacturing", 
  "name": "Production Order", 
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py
index 9226178..607f913 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.py
+++ b/erpnext/manufacturing/doctype/production_order/production_order.py
@@ -4,14 +4,19 @@
 from __future__ import unicode_literals
 import frappe, json
 
-from frappe.utils import flt, nowdate, cstr, get_datetime, getdate
+from frappe.utils import flt, nowdate, get_datetime, getdate, date_diff, time_diff_in_seconds
 from frappe import _
 from frappe.model.document import Document
 from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
 from dateutil.relativedelta import relativedelta
+from dateutil.parser import parse
 
 class OverProductionError(frappe.ValidationError): pass
 class StockOverProductionError(frappe.ValidationError): pass
+class OperationTooLongError(frappe.ValidationError): pass
+
+from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError, NotInWorkingHoursError
+from erpnext.projects.doctype.time_log.time_log import OverlapError
 
 form_grid_templates = {
 	"operations": "templates/form_grid/production_order_grid.html"
@@ -141,6 +146,7 @@
 		if not self.fg_warehouse:
 			frappe.throw(_("For Warehouse is required before Submit"))
 		frappe.db.set(self,'status', 'Submitted')
+		self.make_time_logs()
 		self.update_planned_qty(self.qty)
 
 
@@ -204,6 +210,58 @@
 
 		return self.holidays[holiday_list]
 
+	def make_time_logs(self):
+		time_logs = []
+
+		plan_days = frappe.db.get_single_value("Manufacturing Settings", "capacity_planning_for_days") or 30
+
+		for d in self.operations:
+			time_log = make_time_log(self.name, d.operation, d.planned_start_time, d.planned_end_time,
+				flt(self.qty) - flt(d.completed_qty), self.project_name, d.workstation)
+
+			self.check_operation_fits_in_working_hours(d)
+
+			original_start_time = time_log.from_time
+			while True:
+				try:
+					time_log.save()
+					break
+				except WorkstationHolidayError:
+					time_log.move_to_next_day()
+				except NotInWorkingHoursError:
+					time_log.move_to_next_working_slot()
+				except OverlapError:
+					time_log.move_to_next_non_overlapping_slot()
+
+				# reset end time
+				time_log.to_time = get_datetime(time_log.from_time) + relativedelta(minutes=d.time_in_mins)
+
+				if date_diff(time_log.from_time, original_start_time) > plan_days:
+					frappe.msgprint(_("Unable to find Time Slot in the next {0} days for Operation {1}").format(plan_days, d.operation))
+					break
+
+				print time_log.as_json()
+
+			if time_log.name:
+				time_logs.append(time_log.name)
+
+		if time_logs:
+			frappe.msgprint(_("Time Logs created:") + "\n" + "\n".join(time_logs))
+
+
+	def check_operation_fits_in_working_hours(self, d):
+		"""Raises expection if operation is longer than working hours in the given workstation."""
+		operation_length = time_diff_in_seconds(d.planned_end_time, d.planned_start_time)
+
+		workstation = frappe.get_doc("Workstation", d.workstation)
+		for working_hour in workstation.working_hours:
+			slot_length = (parse(working_hour.end_time) - parse(working_hour.start_time)).total_seconds()
+			if slot_length >= operation_length:
+				return
+
+		frappe.throw(_("Operation {0} longer than any available working hours in workstation {1}, break down the operation into multiple operations").format(d.operation, d.workstation),
+			OperationTooLongError)
+
 	def update_operation_status(self):
 		for d in self.get("operations"):
 			if not d.completed_qty:
@@ -293,13 +351,14 @@
 	return data
 
 @frappe.whitelist()
-def make_time_log(name, operation, from_time, to_time, qty=None,  project=None, workstation=None):
+def make_time_log(name, operation, from_time, to_time, qty=None,  project=None, workstation=None, operation_id=None):
 	time_log =  frappe.new_doc("Time Log")
 	time_log.time_log_for = 'Manufacturing'
 	time_log.from_time = from_time
 	time_log.to_time = to_time
 	time_log.production_order = name
 	time_log.project = project
+	time_log.operation_id = operation_id
 	time_log.operation= operation
 	time_log.workstation= workstation
 	time_log.activity_type= "Manufacturing"
@@ -307,20 +366,3 @@
 	if from_time and to_time :
 		time_log.calculate_total_hours()
 	return time_log
-
-@frappe.whitelist()
-def auto_make_time_log(production_order_id):
-	if frappe.db.get_value("Time Log", filters={"production_order": production_order_id, "docstatus":1}):
-		frappe.throw(_("Time logs already exists against this Production Order"))
-
-	time_logs = []
-	prod_order = frappe.get_doc("Production Order", production_order_id)
-
-	for d in prod_order.operations:
-		operation = cstr(d.idx) + ". " + d.operation
-		time_log = make_time_log(prod_order.name, operation, d.planned_start_time, d.planned_end_time,
-			flt(prod_order.qty) - flt(d.completed_qty), prod_order.project_name, d.workstation)
-		time_log.save()
-		time_logs.append(time_log.name)
-	if time_logs:
-		frappe.msgprint(_("Time Logs created:") + "\n" + "\n".join(time_logs))
diff --git a/erpnext/manufacturing/doctype/production_order_operation/production_order_operation.json b/erpnext/manufacturing/doctype/production_order_operation/production_order_operation.json
index 071e941..2fe6c32 100644
--- a/erpnext/manufacturing/doctype/production_order_operation/production_order_operation.json
+++ b/erpnext/manufacturing/doctype/production_order_operation/production_order_operation.json
@@ -40,7 +40,7 @@
   }, 
   {
    "allow_on_submit": 0, 
-   "fieldname": "opn_description", 
+   "fieldname": "description", 
    "fieldtype": "Text", 
    "hidden": 0, 
    "ignore_user_permissions": 0, 
@@ -125,6 +125,15 @@
    "unique": 0
   }, 
   {
+   "allow_on_submit": 1, 
+   "depends_on": "eval:(doc.docstatus==1 && doc.status!=\"Completed\")", 
+   "fieldname": "show_time_logs", 
+   "fieldtype": "Button", 
+   "label": "Show Time Logs", 
+   "permlevel": 0, 
+   "precision": ""
+  }, 
+  {
    "fieldname": "estimated_time_and_cost", 
    "fieldtype": "Section Break", 
    "label": "Estimated Time and Cost", 
@@ -266,7 +275,6 @@
    "read_only": 1
   }, 
   {
-   "allow_on_submit": 1, 
    "depends_on": "eval:(doc.docstatus==1 && doc.status!=\"Completed\")", 
    "fieldname": "make_time_log", 
    "fieldtype": "Button", 
@@ -282,7 +290,7 @@
  "is_submittable": 0, 
  "issingle": 0, 
  "istable": 1, 
- "modified": "2015-02-20 05:08:36.612612", 
+ "modified": "2015-02-23 07:55:19.368919", 
  "modified_by": "Administrator", 
  "module": "Manufacturing", 
  "name": "Production Order Operation", 
diff --git a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py
index 6eddb3f..f365733 100644
--- a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py
+++ b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py
@@ -8,6 +8,7 @@
 from frappe import msgprint, _
 
 from frappe.model.document import Document
+from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
 
 class ProductionPlanningTool(Document):
 	def __init__(self, arg1, arg2=None):
@@ -156,20 +157,10 @@
 	def validate_data(self):
 		self.validate_company()
 		for d in self.get('items'):
-			self.validate_bom_no(d)
+			validate_bom_no(d.item_code, d.bom_no)
 			if not flt(d.planned_qty):
 				frappe.throw(_("Please enter Planned Qty for Item {0} at row {1}").format(d.item_code, d.idx))
 
-	def validate_bom_no(self, d):
-		if not d.bom_no:
-			frappe.throw(_("Please enter BOM for Item {0} at row {1}").format(d.item_code, d.idx))
-		else:
-			bom = frappe.db.sql("""select name from `tabBOM` where name = %s and item = %s
-				and docstatus = 1 and is_active = 1""",
-				(d.bom_no, d.item_code), as_dict = 1)
-			if not bom:
-				frappe.throw(_("Incorrect or Inactive BOM {0} for Item {1} at row {2}").format(d.bom_no, d.item_code, d.idx))
-
 	def raise_production_order(self):
 		"""It will raise production order (Draft) for all distinct FG items"""
 		self.validate_data()
@@ -218,7 +209,7 @@
 		for key in items:
 			pro = frappe.new_doc("Production Order")
 			pro.update(items[key])
-		
+
 			pro.planned_start_date = now()
 			pro.set_production_order_operations()
 
diff --git a/erpnext/manufacturing/doctype/workstation/workstation.json b/erpnext/manufacturing/doctype/workstation/workstation.json
index e4cda3d..b65560c 100644
--- a/erpnext/manufacturing/doctype/workstation/workstation.json
+++ b/erpnext/manufacturing/doctype/workstation/workstation.json
@@ -10,7 +10,7 @@
   {
    "fieldname": "description_and_warehouse", 
    "fieldtype": "Section Break", 
-   "label": "Description and Warehouse", 
+   "label": "", 
    "permlevel": 0, 
    "precision": ""
   }, 
@@ -70,7 +70,7 @@
   {
    "description": "per hour", 
    "fieldname": "hour_rate_electricity", 
-   "fieldtype": "Float", 
+   "fieldtype": "Currency", 
    "label": "Electricity Cost", 
    "oldfieldname": "hour_rate_electricity", 
    "oldfieldtype": "Currency", 
@@ -79,7 +79,7 @@
   {
    "description": "per hour", 
    "fieldname": "hour_rate_consumable", 
-   "fieldtype": "Float", 
+   "fieldtype": "Currency", 
    "label": "Consumable Cost", 
    "oldfieldname": "hour_rate_consumable", 
    "oldfieldtype": "Currency", 
@@ -94,7 +94,7 @@
   {
    "description": "per hour", 
    "fieldname": "hour_rate_rent", 
-   "fieldtype": "Float", 
+   "fieldtype": "Currency", 
    "label": "Rent Cost", 
    "oldfieldname": "hour_rate_rent", 
    "oldfieldtype": "Currency", 
@@ -103,7 +103,7 @@
   {
    "description": "Wages per hour", 
    "fieldname": "hour_rate_labour", 
-   "fieldtype": "Float", 
+   "fieldtype": "Currency", 
    "label": "Wages", 
    "oldfieldname": "hour_rate_labour", 
    "oldfieldtype": "Currency", 
@@ -113,7 +113,7 @@
   {
    "description": "per hour", 
    "fieldname": "hour_rate", 
-   "fieldtype": "Float", 
+   "fieldtype": "Currency", 
    "label": "Net Hour Rate", 
    "oldfieldname": "hour_rate", 
    "oldfieldtype": "Currency", 
@@ -123,7 +123,7 @@
   {
    "fieldname": "working_hours_section", 
    "fieldtype": "Section Break", 
-   "label": "Wroking Hours", 
+   "label": "Working Hours", 
    "permlevel": 0, 
    "precision": ""
   }, 
@@ -133,12 +133,13 @@
    "label": "Working Hours", 
    "options": "Workstation Working Hour", 
    "permlevel": 0, 
-   "precision": ""
+   "precision": "", 
+   "reqd": 1
   }
  ], 
  "icon": "icon-wrench", 
  "idx": 1, 
- "modified": "2015-02-05 05:13:38.580439", 
+ "modified": "2015-02-23 09:43:35.903827", 
  "modified_by": "Administrator", 
  "module": "Manufacturing", 
  "name": "Workstation", 
diff --git a/erpnext/manufacturing/doctype/workstation/workstation.py b/erpnext/manufacturing/doctype/workstation/workstation.py
index 00f7ee6..d345e26 100644
--- a/erpnext/manufacturing/doctype/workstation/workstation.py
+++ b/erpnext/manufacturing/doctype/workstation/workstation.py
@@ -10,7 +10,7 @@
 from frappe.model.document import Document
 
 class WorkstationHolidayError(frappe.ValidationError): pass
-class WorkstationIsClosedError(frappe.ValidationError): pass
+class NotInWorkingHoursError(frappe.ValidationError): pass
 class OverlapError(frappe.ValidationError): pass
 
 class Workstation(Document):
@@ -31,6 +31,7 @@
 		self.update_bom_operation()
 
 	def validate_overlap_for_operation_timings(self):
+		"""Check if there is no overlap in setting Workstation Operating Hours"""
 		for d in self.get("working_hours"):
 			existing = frappe.db.sql_list("""select idx from `tabWorkstation Working Hour`
 				where parent = %s and name != %s
@@ -49,7 +50,7 @@
 
 def check_if_within_operating_hours(workstation, from_datetime, to_datetime):
 	if not is_within_operating_hours(workstation, from_datetime, to_datetime):
-		frappe.throw(_("Time Log timings outside workstation operating hours"), WorkstationIsClosedError)
+		frappe.throw(_("Time Log timings outside workstation operating hours"), NotInWorkingHoursError)
 
 	if not cint(frappe.db.get_value("Manufacturing Settings", "None", "allow_production_on_holidays")):
 		check_workstation_for_holiday(workstation, from_datetime, to_datetime)
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index c3e5dfa..05b92b1 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -123,3 +123,4 @@
 erpnext.patches.v5_0.convert_stock_reconciliation
 erpnext.patches.v5_0.update_projects
 erpnext.patches.v5_0.item_patches
+erpnext.patches.v5_0.update_journal_entry_title
diff --git a/erpnext/patches/v5_0/update_journal_entry_title.py b/erpnext/patches/v5_0/update_journal_entry_title.py
new file mode 100644
index 0000000..59e6f41
--- /dev/null
+++ b/erpnext/patches/v5_0/update_journal_entry_title.py
@@ -0,0 +1,7 @@
+import frappe
+
+def execute():
+	frappe.db.sql("""update `tabJournal Entry` set title =
+		if(ifnull(pay_to_recd_from, "")!="", pay_to_recd_from,
+			(select account from `tabJournal Entry Account`
+				where parent=`tabJournal Entry`.name and idx=1 limit 1))""")
diff --git a/erpnext/projects/doctype/project/project_list.js b/erpnext/projects/doctype/project/project_list.js
index e440de8..8281c7d 100644
--- a/erpnext/projects/doctype/project/project_list.js
+++ b/erpnext/projects/doctype/project/project_list.js
@@ -1,6 +1,5 @@
 frappe.listview_settings['Project'] = {
-	add_fields: ["status", "priority", "is_active", "percent_complete",
-		"percent_milestones_completed", "completion_date"],
+	add_fields: ["status", "priority", "is_active", "percent_complete", "completion_date"],
 	filters:[["status","=", "Open"]],
 	get_indicator: function(doc) {
 		if(doc.status=="Open" && doc.percent_complete) {
diff --git a/erpnext/projects/doctype/time_log/time_log.js b/erpnext/projects/doctype/time_log/time_log.js
index 8172650..5f7e846 100644
--- a/erpnext/projects/doctype/time_log/time_log.js
+++ b/erpnext/projects/doctype/time_log/time_log.js
@@ -10,6 +10,14 @@
 	}
 });
 
+frappe.ui.form.on("Time Log", "refresh", function(frm) {
+	// set default user if created
+	if (frm.doc.__islocal && !frm.doc.user) {
+		frm.set_value("user", user);
+	}
+});
+
+
 // set to time if hours is updated
 frappe.ui.form.on("Time Log", "hours", function(frm) {
 	if(!frm.doc.from_time) {
diff --git a/erpnext/projects/doctype/time_log/time_log.json b/erpnext/projects/doctype/time_log/time_log.json
index bc68805..603efe3 100644
--- a/erpnext/projects/doctype/time_log/time_log.json
+++ b/erpnext/projects/doctype/time_log/time_log.json
@@ -51,6 +51,14 @@
    "read_only": 0
   }, 
   {
+   "fieldname": "user", 
+   "fieldtype": "Link", 
+   "label": "User", 
+   "options": "User", 
+   "permlevel": 0, 
+   "precision": ""
+  }, 
+  {
    "fieldname": "column_break_3", 
    "fieldtype": "Column Break", 
    "permlevel": 0, 
@@ -121,6 +129,15 @@
    "precision": ""
   }, 
   {
+   "fieldname": "operation_id", 
+   "fieldtype": "Data", 
+   "label": "Operation ID", 
+   "options": "", 
+   "permlevel": 0, 
+   "precision": "", 
+   "read_only": 1
+  }, 
+  {
    "fieldname": "column_break_14", 
    "fieldtype": "Column Break", 
    "permlevel": 0, 
@@ -213,7 +230,7 @@
  "icon": "icon-time", 
  "idx": 1, 
  "is_submittable": 1, 
- "modified": "2015-02-19 04:16:33.756377", 
+ "modified": "2015-02-23 08:00:48.195775", 
  "modified_by": "Administrator", 
  "module": "Projects", 
  "name": "Time Log", 
diff --git a/erpnext/projects/doctype/time_log/time_log.py b/erpnext/projects/doctype/time_log/time_log.py
index 33855af..3adf879 100644
--- a/erpnext/projects/doctype/time_log/time_log.py
+++ b/erpnext/projects/doctype/time_log/time_log.py
@@ -6,7 +6,9 @@
 from __future__ import unicode_literals
 import frappe, json
 from frappe import _
-from frappe.utils import cstr, comma_and, flt
+from frappe.utils import cstr, flt, add_days, get_datetime, get_time
+from dateutil.relativedelta import relativedelta
+from dateutil.parser import parse
 
 class OverlapError(frappe.ValidationError): pass
 class OverProductionError(frappe.ValidationError): pass
@@ -52,24 +54,35 @@
 			self.status="Billed"
 
 	def validate_overlap(self):
-		"""Checks if 'Time Log' entries overlap each other. """
-		existing = frappe.db.sql_list("""select name from `tabTime Log` where owner=%s and
+		"""Checks if 'Time Log' entries overlap for a user, workstation. """
+		self.validate_overlap_for("user")
+		self.validate_overlap_for("workstation")
+
+	def validate_overlap_for(self, fieldname):
+		existing = self.get_overlap_for(fieldname)
+		if existing:
+			frappe.throw(_("This Time Log conflicts with {0} for {1}").format(existing.name,
+				self.meta.get_label(fieldname)), OverlapError)
+
+	def get_overlap_for(self, fieldname):
+		if not self.get(fieldname):
+			return
+		existing = frappe.db.sql("""select name, from_time, to_time from `tabTime Log` where `{0}`=%s and
 			(
 				(from_time between %s and %s) or
 				(to_time between %s and %s) or
 				(%s between from_time and to_time))
 			and name!=%s
 			and ifnull(task, "")=%s
-			and docstatus < 2""",
-			(self.owner, self.from_time, self.to_time, self.from_time,
+			and docstatus < 2""".format(fieldname),
+			(self.get(fieldname), self.from_time, self.to_time, self.from_time,
 				self.to_time, self.from_time, self.name or "No Name",
-				cstr(self.task)))
+				cstr(self.task)), as_dict=True)
 
-		if existing:
-			frappe.throw(_("This Time Log conflicts with {0}").format(comma_and(existing)), OverlapError)
+		return existing[0] if existing else None
 
 	def validate_timings(self):
-		if self.to_time < self.from_time:
+		if get_datetime(self.to_time) < get_datetime(self.from_time):
 			frappe.throw(_("From Time cannot be greater than To Time"))
 
 	def calculate_total_hours(self):
@@ -97,7 +110,7 @@
 		"""Updates `start_date`, `end_date`, `status` for operation in Production Order."""
 
 		if self.time_log_for=="Manufacturing" and self.operation:
-			operation = self.operation.split('. ',1)
+			operation = self.operation
 
 			dates = self.get_operation_start_end_time()
 			tl = self.get_all_time_logs()
@@ -122,6 +135,31 @@
 				where production_order = %s and operation = %s and docstatus=1""",
 				(self.production_order, self.operation), as_dict=1)[0]
 
+	def move_to_next_day(self):
+		"""Move start and end time one day forward"""
+		self.from_time = add_days(self.from_time, 1)
+
+	def move_to_next_working_slot(self):
+		"""Move to next working slot from workstation"""
+		workstation = frappe.get_doc("Workstation", self.workstation)
+		slot_found = False
+		for working_hour in workstation.working_hours:
+			if get_datetime(self.from_time).time() < get_time(working_hour.start_time):
+				self.from_time = self.from_time.split()[0] + " " + working_hour.start_time
+				slot_found = True
+				break
+
+		if not slot_found:
+			# later than last time
+			self.from_time = self.from_time.split()[0] + workstation.working_hours[0].start_time
+			self.move_to_next_day()
+
+	def move_to_next_non_overlapping_slot(self):
+		"""If in overlap, set start as the end point of the overlapping time log"""
+		overlapping = self.get_overlap_for("workstation")
+		if overlapping:
+			self.from_time = parse(overlapping.to_time) + relativedelta(minutes=10)
+
 	def get_all_time_logs(self):
 		"""Returns 'Actual Operating Time'. """
 		return frappe.db.sql("""select
diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json
index 9083ead..83f7a84 100644
--- a/erpnext/stock/doctype/item/item.json
+++ b/erpnext/stock/doctype/item/item.json
@@ -166,6 +166,7 @@
    "search_index": 0
   }, 
   {
+   "depends_on": "eval:!!!doc.variant_of", 
    "fieldname": "variants_section", 
    "fieldtype": "Section Break", 
    "label": "Variants", 
@@ -702,7 +703,7 @@
    "fieldtype": "Link", 
    "ignore_user_permissions": 1, 
    "label": "Default BOM", 
-   "no_copy": 1, 
+   "no_copy": 0, 
    "oldfieldname": "default_bom", 
    "oldfieldtype": "Link", 
    "options": "BOM", 
@@ -874,7 +875,7 @@
  "icon": "icon-tag", 
  "idx": 1, 
  "max_attachments": 1, 
- "modified": "2015-02-22 23:59:37.956424", 
+ "modified": "2015-02-23 06:12:13.359646", 
  "modified_by": "Administrator", 
  "module": "Stock", 
  "name": "Item", 
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index aa338ec..5eb6a9b 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -187,6 +187,7 @@
 			frappe.msgprint(_("Item Variants {0} deleted").format(", ".join(deleted)))
 
 	def get_variant_item_codes(self):
+		"""Get all possible suffixes for variants"""
 		if not self.variants:
 			return []
 
@@ -234,7 +235,7 @@
 		from frappe.model import no_value_fields
 		for field in self.meta.fields:
 			if field.fieldtype not in no_value_fields and (insert or not field.no_copy)\
-				and field.fieldname != "item_code":
+				and field.fieldname not in ("item_code", "item_name"):
 				if variant.get(field.fieldname) != template.get(field.fieldname):
 					variant.set(field.fieldname, template.get(field.fieldname))
 					variant.__dirty = True
@@ -245,7 +246,10 @@
 			template.get_variant_item_codes()
 
 		for attr in template.variant_attributes[variant.item_code]:
-			variant.description += "\n" + attr[0] + ": " + attr[1]
+			variant.description += "<p>" + attr[0] + ": " + attr[1] + "</p>"
+
+		variant.item_name = self.item_name + variant.item_code[len(self.name):]
+
 		variant.variant_of = template.name
 		variant.has_variants = 0
 		variant.show_in_website = 0
@@ -292,7 +296,7 @@
 		if self.default_bom:
 			bom_item = frappe.db.get_value("BOM", self.default_bom, "item")
 			if bom_item not in (self.name, self.variant_of):
-				frappe.throw(_("Default BOM must be for this item or its template"))
+				frappe.throw(_("Default BOM ({0}) must be active for this item or its template").format(bom_item))
 
 		if self.is_purchase_item != "Yes":
 			bom_mat = frappe.db.sql("""select distinct t1.parent
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 54e7192..4e229cb 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -179,13 +179,13 @@
 			self.production_order = None
 
 	def check_if_operations_completed(self):
+		"""Check if Time Logs are completed against before manufacturing to capture operating costs."""
 		prod_order = frappe.get_doc("Production Order", self.production_order)
-		if prod_order.actual_operating_cost:
-			for d in prod_order.get("operations"):
-				total_completed_qty = flt(self.fg_completed_qty) + flt(prod_order.produced_qty)
-				if total_completed_qty > flt(d.completed_qty):
-					frappe.throw(_("Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Production Order # {3}. Please update operation status via Time Logs")
-						.format(d.idx, d.operation, total_completed_qty, self.production_order))
+		for d in prod_order.get("operations"):
+			total_completed_qty = flt(self.fg_completed_qty) + flt(prod_order.produced_qty)
+			if total_completed_qty > flt(d.completed_qty):
+				frappe.throw(_("Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Production Order # {3}. Please update operation status via Time Logs")
+					.format(d.idx, d.operation, total_completed_qty, self.production_order))
 
 	def check_duplicate_entry_for_production_order(self):
 		other_ste = [t[0] for t in frappe.db.get_values("Stock Entry",  {
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 29897ef..d7ace2f 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -124,6 +124,9 @@
 		elif item.is_sales_item != "Yes":
 			throw(_("Item {0} must be a Sales Item").format(item.name))
 
+		if cint(item.has_variants):
+			throw(_("Item {0} is a template, please select one of its variants").format(item.name))
+
 	elif args.transaction_type == "buying" and args.parenttype != "Material Request":
 		# validate if purchase item or subcontracted item
 		if item.is_purchase_item != "Yes":