Merge branch 'master' of github.com:webnotes/erpnext
diff --git a/home/page/dashboard/dashboard.js b/home/page/dashboard/dashboard.js
index c5dd361..15e7cf3 100644
--- a/home/page/dashboard/dashboard.js
+++ b/home/page/dashboard/dashboard.js
@@ -10,12 +10,12 @@
 
 	pscript.dashboard_settings = {
 		company: sys_defaults.company,
-		start: dateutil.obj_to_str(dateutil.add_days(new Date(), -60)),
+		start: dateutil.obj_to_str(dateutil.add_days(new Date(), -180)),
 		end: dateutil.obj_to_str(new Date()),
-		interval: 7
+		interval: 30
 	}
 	
-	var ph = new PageHeader($('.dashboard .header').get(0), 'Dashboards');
+	var ph = new PageHeader($('.dashboard .header').get(0), 'Dashboard');
 	var db = new Dashboard();
 
 	ph.add_button('Settings', db.show_settings);
@@ -46,17 +46,19 @@
 				// give an id!
 				var cell = $td(t,ridx,cidx);
 				var title = $a(cell, 'div', 'dashboard-title', '', data[i][0].title);
-				var parent = $a(cell, 'div', 'dashboard-graph')
+				var parent = $a(cell, 'div', 'dashboard-graph');
+				if(data[i][0].comment);
+					var comment = $a(cell, 'div', 'comment', '', data[i][0].comment)
 				
 				parent.id = '_dashboard' + ridx + '-' + cidx;
 				
 				// render graph
-				me.render_graph(parent.id, data[i][1]);
+				me.render_graph(parent.id, data[i][1], data[i][0].fillColor);
 				cidx++;
 			}
 		},
 		
-		render_graph: function(parent, values) {
+		render_graph: function(parent, values, fillColor) {
 			var vl = [];
 			$.each(values, function(i,v) { 
 				vl.push([dateutil.str_to_user(v[0]), v[1]]);
@@ -84,7 +86,8 @@
 						pad: 1.05,
 						tickOptions: {formatString: '%d'}
 					}
-				}
+				},
+				seriesColors: [fillColor]
 			});
 		},
 		
diff --git a/home/page/dashboard/dashboard.py b/home/page/dashboard/dashboard.py
index 2c76b15..9ead6d6 100644
--- a/home/page/dashboard/dashboard.py
+++ b/home/page/dashboard/dashboard.py
@@ -2,58 +2,63 @@
 	{
 		'type': 'account',
 		'account': 'Income',
-		'title': 'Income'
+		'title': 'Income',
+		'fillColor': '#90EE90'
 	},
 	
 	{
 		'type': 'account',
 		'account': 'Expenses',
-		'title': 'Expenses'
+		'title': 'Expenses',
+		'fillColor': '#90EE90'
 	},
 
 	{
-		'type': 'from_company',
-		'account': 'receivables_group',
-		'title': 'Receivables'
+		'type': 'receivables',
+		'title': 'Receivables',
+		'fillColor': '#FFE4B5'
 	},
 
 	{
-		'type': 'from_company',
-		'account': 'payables_group',
-		'title': 'Payables'
+		'type': 'payables',
+		'title': 'Payables',
+		'fillColor': '#FFE4B5'
 	},
 
 	{
-		'type': 'cash',
-		'debit_or_credit': 'Debit',
-		'title': 'Cash Inflow'
+		'type': 'collection',
+		'title': 'Collection',
+		'comment':'This info comes from the accounts your have marked as "Bank or Cash"',
+		'fillColor': '#DDA0DD'
 	},
 
 	{
-		'type': 'cash',
-		'debit_or_credit': 'Credit',
-		'title': 'Cash Outflow'
+		'type': 'payments',
+		'title': 'Payments',
+		'comment':'This info comes from the accounts your have marked as "Bank or Cash"',
+		'fillColor': '#DDA0DD'
 	},
 
 	{
 		'type': 'creation',
 		'doctype': 'Quotation',
-		'title': 'New Quotations'
+		'title': 'New Quotations',
+		'fillColor': '#ADD8E6'
 	},
 	
 	{
 		'type': 'creation',
 		'doctype': 'Sales Order',
-		'title': 'New Orders'
+		'title': 'New Orders',
+		'fillColor': '#ADD8E6'
 	}
 ]
 
-
 class DashboardWidget:
 	def __init__(self, company, start, end, interval):
-		import webnotes
 		from webnotes.utils import getdate
 		from webnotes.model.code import get_obj
+		import webnotes
 		
 		self.company = company
 		self.abbr = webnotes.conn.get_value('Company', company, 'abbr')
@@ -61,17 +66,20 @@
 		self.end = getdate(end)
 		
 		self.interval = interval
-		self.fiscal_year = webnotes.conn.sql("""
-			select name from `tabFiscal Year` 
-			where year_start_date <= %s and
-			DATE_ADD(year_start_date, INTERVAL 1 YEAR) >= %s
-			""", (start, start))[0][0]
+
 		self.glc = get_obj('GL Control')
 		self.cash_accounts = [d[0] for d in webnotes.conn.sql("""
 			select name from tabAccount 
 			where account_type='Bank or Cash'
 			and company = %s and docstatus = 0 
 			""", company)]
+			
+		self.receivables_group = webnotes.conn.get_value('Company', company,'receivables_group')
+		self.payables_group = webnotes.conn.get_value('Company', company,'payables_group')
+		
+		# list of bank and cash accounts
+		self.bc_list = [s[0] for s in webnotes.conn.sql("select name from tabAccount where account_type='Bank or Cash'")]
+
 		
 	def timeline(self):
 		"""
@@ -99,11 +107,12 @@
 		"""
 			Generate the dasboard
 		"""
+		from webnotes.utils import flt
 		tl = self.timeline()
 		self.out = []
 		
 		for i in range(len(tl)-1):
-			self.out.append([tl[i+1].strftime('%Y-%m-%d'), self.value(opts, tl[i], tl[i+1]) or 0])
+			self.out.append([tl[i+1].strftime('%Y-%m-%d'), flt(self.value(opts, tl[i], tl[i+1])) or 0])
 			
 		return self.out
 
@@ -125,8 +134,19 @@
 			print acc
 			raise e
 		
-		return self.glc.get_as_on_balance(acc, self.fiscal_year, start, debit_or_credit, lft, rgt)
+		return self.glc.get_as_on_balance(acc, self.get_fiscal_year(start), start, debit_or_credit, lft, rgt)
 
+	def get_fiscal_year(self, dt):
+		"""
+			get fiscal year from date
+		"""
+		import webnotes
+		return webnotes.conn.sql("""
+			select name from `tabFiscal Year` 
+			where year_start_date <= %s and
+			DATE_ADD(year_start_date, INTERVAL 1 YEAR) >= %s
+			""", (dt, dt))[0][0]
+			
 	def get_creation_trend(self, doctype, start, end):
 		"""
 			Get creation # of creations in period
@@ -158,6 +178,26 @@
 		
 		return debit_or_credit=='Credit' and float(ret[1]-ret[0]) or float(ret[0]-ret[1])
 
+	def get_bank_amt(self, debit_or_credit, master_type, start, end):
+		"""
+			Get collection (reduction in receivables over a period)
+		"""
+		import webnotes
+
+		reg = '('+'|'.join(self.bc_list) + ')'
+
+		return webnotes.conn.sql("""
+		select sum(t1.%s)
+		from `tabGL Entry` t1, tabAccount t2
+		where t1.account = t2.name
+		and t2.master_type='%s'
+		and t1.%s > 0
+		and t1.against REGEXP '%s'
+		and ifnull(t1.is_cancelled, 'No')='No'
+		and t1.posting_date between '%s' and '%s'
+		""" % (debit_or_credit, master_type, debit_or_credit, reg, start, end))[0][0]
+
+
 	def value(self, opts, start, end):
 		"""
 			Value of the series on a particular date
@@ -170,17 +210,17 @@
 
 			return self.get_account_amt(opts['account'], start, end, debit_or_credit)
 		
-		elif opts['type']=='from_company':
-			acc = webnotes.conn.get_value('Company', self.company, \
-				opts['account'].split('.')[-1])
+		elif opts['type']=='receivables':
+			return self.get_account_balance(self.receivables_group, end)[2]
 			
-			return self.get_account_balance(acc, start)[2]
-						
-		elif opts['type']=='cash':
-			if opts['debit_or_credit']=='Credit':
-				return sum([self.get_account_amt(acc, start, end, opts['debit_or_credit']) for acc in self.cash_accounts]) or 0
-			elif opts['debit_or_credit']=='Debit':
-				return sum([self.get_account_amt(acc, start, end, opts['debit_or_credit']) for acc in self.cash_accounts]) or 0
+		elif opts['type']=='payables':
+			return self.get_account_balance(self.payables_group, end)[2]
+
+		elif opts['type']=='collection':
+			return self.get_bank_amt('credit', 'Customer', start, end)
+
+		elif opts['type']=='payments':
+			return self.get_bank_amt('debit', 'Supplier', start, end)
 			
 		elif opts['type']=='creation':
 			return self.get_creation_trend(opts['doctype'], start, end)
diff --git a/home/page/event_updates/event_updates.js b/home/page/event_updates/event_updates.js
index 1574f53..9aa3da2 100644
--- a/home/page/event_updates/event_updates.js
+++ b/home/page/event_updates/event_updates.js
@@ -25,12 +25,7 @@
 	
 	wrapper.banner_area = $a(wrapper.head, 'div');
 
-	wrapper.setup_wizard_area = $a(wrapper.body, 'div', 'setup-wizard')
-
-	wrapper.system_message_area = $a(wrapper.body, 'div', '', 
-		{marginBottom:'16px', padding:'8px', backgroundColor:'#FFD', border:'1px dashed #AA6', display:'none'})
-	
-	
+	wrapper.setup_wizard_area = $a(wrapper.body, 'div', 'setup-wizard');	
 }
 
 // ==================================
@@ -436,8 +431,8 @@
 	// head
 
 	$a(this.head,'h1','', {display:'inline'}, 'Home'); 
-	$a(this.head,'span','link_type', {marginLeft:'7px'}, '[?]', function() {
-		msgprint('<b>What appears here?</b> This is where you get updates of everything you are allowed to access and generates an update')
+	$a(this.head,'span','link_type', {marginLeft:'7px'}, 'help', function() {
+		msgprint('<b>What appears here?</b> This is where you get updates of everything you are permitted to follow')
 	})
 
 	// refresh
@@ -445,6 +440,11 @@
 		{cursor:'pointer', marginLeft:'7px', fontSize:'11px'}, 'refresh',
 		function() { me.run(); }
 	);
+	
+	if(has_common(user_roles, ['System Manager','Accounts Manager'])) {
+		$btn(this.head, 'Dashboard', function() {loadpage('dashboard'); }, {marginLeft:'7px'})
+		
+	}
 }
 
 FeedList.prototype.run = function() {
@@ -594,14 +594,15 @@
 	
 	this.render = function(r) {
 		this.wrapper.innerHTML = '';
-		this.span = $a(this.wrapper, 'span', 'home-status-link')
+		this.span = $a(this.wrapper, 'span', 'link_type', {fontWeight:'bold'});
 		this.span.onclick = function() { loadpage('My Company')	}
 		
 		if(r.unread_messages) {
-			this.span.innerHTML = '<span class="home-status-unread">' + r.unread_messages + '</span> unread message' + (cint(r.unread_messages) > 1 ? 's' : '');
+			this.span.innerHTML = '<span class="home-status-unread">' + r.unread_messages + '</span> unread';
 		} else {
-			this.span.innerHTML = 'No unread messages.';
+			this.span.innerHTML = 'Team / Messages';			
 		}
+		
 	}
 }
 
@@ -613,11 +614,7 @@
 	$c_page('home', 'event_updates', 'get_status_details', user,
 		function(r,rt) { 
 			home_status_bar.render(r.message);
-			
-			// system_messages
-			if(r.message.system_message)
-				pscript.show_system_message(wrapper, r.message.system_message);
-							
+										
 			// render online users
 			pscript.online_users_obj.render(r.message.online_users);
 			pscript.online_users = r.message.online_users;
@@ -630,24 +627,6 @@
 	);	
 }
 
-// show system message
-// -------------------
-pscript.show_system_message = function(wrapper, msg) {
-	$ds(wrapper.system_message_area);
-	var txt = $a(wrapper.system_message_area, 'div', '', {lineHeight:'1.6em'});
-	txt.innerHTML = msg;
-	
-	var span = $ln($a(wrapper.system_message_area, 'div', '', {textAlign:'right'}), 'Dismiss'.bold(), 
-		function(me) { 
-			me.set_working();
-			$c_obj('Home Control', 'dismiss_message', '', function(r,rt) { 
-				me.done_working(); 
-				$(wrapper.system_message_area).slideUp(); 
-			});
-		}, {fontSize:'11px'}
-	)
-}
-
 // complete my company registration
 // --------------------------------
 pscript.complete_registration = function()
diff --git a/home/page/event_updates/event_updates.py b/home/page/event_updates/event_updates.py
index 85a121b..1134273 100644
--- a/home/page/event_updates/event_updates.py
+++ b/home/page/event_updates/event_updates.py
@@ -28,18 +28,11 @@
 		
 	online = get_online_users()
 			
-	# system messages
-	msg_id = webnotes.conn.get_global('system_message_id')
-	msg = ''
-				
-	if msg_id and msg_id != webnotes.conn.get_global('system_message_id', webnotes.session['user']):
-		msg = webnotes.conn.get_global('system_message')
-			
+	# system messages			
 	ret = {
 		'user_count': len(online) or 0, 
 		'unread_messages': get_unread_messages(),
 		'online_users': online or [],
-		'system_message':msg,
 		'is_trial': webnotes.conn.get_global('is_trial'),
 		'days_to_expiry': (webnotes.conn.get_global('days_to_expiry') or '0'),
 		'setup_status': get_setup_status()
@@ -56,9 +49,20 @@
 	percent = 20
 	ret = []
 	
-	header = webnotes.conn.get_value('Control Panel', None, 'client_name') or ''
-	if header.startswith('<div style="padding:4px; font-size:20px;">'\
-		+webnotes.conn.get_value('Control Panel', None, 'company_name')):
+	def is_header_set():
+		header = webnotes.conn.get_value('Control Panel', None, 'client_name') or ''
+
+		if header.startswith('<div style="padding:4px; font-size:20px;">'\
+			+webnotes.conn.get_value('Control Panel', None, 'company_name')):
+			return False
+			
+		elif 'Banner Comes Here' in header:
+			return False
+			
+		else:
+			return True
+	
+	if not is_header_set():
 		ret.append('<a href="#!Form/Personalize/Personalize">Upload your company banner</a>')
 	else:
 		percent += 20
diff --git a/home/page/my_company/my_company.js b/home/page/my_company/my_company.js
index c2a55ea..9da7e9b 100644
--- a/home/page/my_company/my_company.js
+++ b/home/page/my_company/my_company.js
@@ -657,7 +657,7 @@
 	}
 
 	var st = (!det.docstatus ? {fontWeight: 'bold'} : null);
-	this.msg = $a(this.comment, 'span', 'social', st, ': ' + det.creation);
+	this.msg = $a(this.comment, 'span', 'social', st, ': ' + det.comment);
 
 	if(det.full_name==user) {
 		$y(this.wrapper, {backgroundColor: '#D9D9F3'});
diff --git a/knowledge_base/doctype/question/question.py b/knowledge_base/doctype/question/question.py
new file mode 100644
index 0000000..5ddee6a
--- /dev/null
+++ b/knowledge_base/doctype/question/question.py
@@ -0,0 +1,8 @@
+class DocType:
+	def __init__(self, d, dl):
+		self.doc, self.doclist = d, dl
+		
+	def on_trash(self):
+		import webnotes
+		webnotes.conn.sql("delete from tabAnswer where question=%s", self.doc.name)
+		
\ No newline at end of file
diff --git a/knowledge_base/page/kb_common/kb_common.js b/knowledge_base/page/kb_common/kb_common.js
index 1826f05..3e17b6f 100644
--- a/knowledge_base/page/kb_common/kb_common.js
+++ b/knowledge_base/page/kb_common/kb_common.js
@@ -19,12 +19,25 @@
 		this.line1.innerHTML = repl('By %(name)s | %(when)s', {
 			name: wn.utils.full_name(this.det.first_name, this.det.last_name),
 			when: wn.datetime.comment_when(this.det.modified)
-		})
+		});
+		
+		// allow system manager to delete questions / answers
+		if(has_common(user_roles, ['Administrator', 'System Manager'])) {
+			this.line1.innerHTML += ' | '
+			$ln(this.line1, 'delete', me.del);
+		}
 	}
 
 	this.make_vote = function() {
 		new KBPoints(this.line2, this.det.points, this.det._users_voted, this.doctype, this.det.name, this.det.owner);
-		
+	}
+	
+	this.del = function() {
+		this.innerHTML = 'deleting...'; this.disabled = 1;
+		$c_page('knowledge_base', 'questions', 'delete', {dt:me.doctype, dn:me.det.name}, function(r,rt) {
+			// reload the list
+			kb.list.run()
+		});
 	}
 	
 	this.make_tags = function() {
diff --git a/knowledge_base/page/question_view/question_view.js b/knowledge_base/page/question_view/question_view.js
index ed11efc..422fb30 100644
--- a/knowledge_base/page/question_view/question_view.js
+++ b/knowledge_base/page/question_view/question_view.js
@@ -128,7 +128,7 @@
 			as_dict: 1,
 			no_results_message: 'No answers yet, be the first one to answer!',
 			render_row: function(body, data) {
-				new KBAnswer(body, data)
+				new KBAnswer(body, data, me)
 			},
 			get_query: function() {
 				return repl("SELECT t1.name, t1.owner, t1.answer, t1.points, t1._users_voted, t2.first_name, "
@@ -150,7 +150,7 @@
 // answer
 // by xxx | on xxx
 // points yyy
-KBAnswer = function(body, data) {
+KBAnswer = function(body, data, ans_list) {
 	body.className = 'qv-answer';
 	new EditableText({
 		parent: body,
@@ -169,7 +169,7 @@
 		det: data,
 		with_tags: 0,
 		doctype: 'Answer'
-	}, null)
+	}, ans_list)
 	
 }
 
diff --git a/knowledge_base/page/questions/questions.py b/knowledge_base/page/questions/questions.py
index cbb6a25..5f8b209 100644
--- a/knowledge_base/page/questions/questions.py
+++ b/knowledge_base/page/questions/questions.py
@@ -35,3 +35,11 @@
 		(p, cstr(res[1]) + ',' + webnotes.user.name, args['dn']))
 	
 	return p
+
+def delete(arg):
+	"""
+		delete a question or answer (called from kb toolbar)
+	"""
+	args = load_json(arg)
+	from webnotes.model import delete_doc
+	delete_doc(args['dt'], args['dn'])
\ No newline at end of file
diff --git a/patches/patch.py b/patches/patch.py
index fbfdf2e..2b7be9c 100644
--- a/patches/patch.py
+++ b/patches/patch.py
@@ -1,7 +1,8 @@
 # REMEMBER to update this
 # ========================
 
-last_patch = 349
+last_patch = 350
+
 #-------------------------------------------
 
 def execute(patch_no):
@@ -268,4 +269,6 @@
 		# reload profile with new fields for security
 		delete_doc('DocType', 'Profile')
 		reload_doc('core', 'doctype', 'profile')
-		
+	elif patch_no == 350:
+		reload_doc('stock', 'doctype', 'delivery_note_detail')
+		reload_doc('stock', 'doctype', 'item_customer_detail')