Merge branch 'master' into edge

Conflicts:
	patches/march_2013/p07_update_valuation_rate.py
	patches/patch_list.py
diff --git a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js
index b1cbbdc..1e72010 100644
--- a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js
+++ b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js
@@ -53,16 +53,14 @@
 		var new_val = flt(val)/flt(doc.conversion_rate);
 		return new_val;
 	}
+	
+	function print_hide(fieldname) {
+		var doc_field = wn.meta.get_docfield(doc.doctype, fieldname, doc.name);
+		return doc_field.print_hide;
+	}
+	
 	out ='';
 	if (!doc.print_without_amount) {
-		print_hide_dict = {};
-		for(var i in locals['DocField']) {
-			var doc_field = locals['DocField'][i];
-			if(doc_field.fieldname) {
-				print_hide_dict[doc_field.fieldname] = doc_field.print_hide;
-			}
-		}
-
 		var cl = getchildren('Sales Taxes and Charges',doc.name,'other_charges');
 
 		// outer table  
@@ -71,7 +69,7 @@
 		// main table
 
 		out +='<table class="noborder" style="width:100%">';
-		if(!print_hide_dict['net_total']) {
+		if(!print_hide('net_total')) {
 			out +=make_row('Net Total',convert_rate(doc.net_total),1);
 		}
 
@@ -84,15 +82,15 @@
 		}
 
 		// grand total
-		if(!print_hide_dict['grand_total_export']) {
+		if(!print_hide('grand_total_export')) {
 			out += make_row('Grand Total',doc.grand_total_export,1);
 		}
 		
-		if(!print_hide_dict['rounded_total_export']) {
+		if(!print_hide('rounded_total_export')) {
 			out += make_row('Rounded Total',doc.rounded_total_export,1);
 		}
 
-		if(doc.in_words_export && !print_hide_dict['in_words_export']){
+		if(doc.in_words_export && !print_hide('in_words_export')){
 			out +='</table></td></tr>';
 			out += '<tr><td colspan = "2">';
 			out += '<table><tr><td style="width:25%;"><b>In Words</b></td>'
diff --git a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py
index 953269c..6cd2b4f 100644
--- a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py
+++ b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py
@@ -24,7 +24,7 @@
 
 	def get_rate(self, arg):
 		from webnotes.model.code import get_obj
-		return get_obj('Sales Common').get_rate(arg, self)
+		return get_obj('Sales Common').get_rate(arg)
 
 	def update_other_default_charges(self):
 		webnotes.conn.sql("update `tabSales Taxes and Charges Master` set is_default = 0 where ifnull(is_default,0) = 1 and name != '%s' and company = '%s'" % (self.doc.name, self.doc.company))
diff --git a/patches/april_2013/__init__.py b/patches/april_2013/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/patches/april_2013/__init__.py
diff --git a/patches/april_2013/p01_update_serial_no_valuation_rate.py b/patches/april_2013/p01_update_serial_no_valuation_rate.py
new file mode 100644
index 0000000..2ea0c26
--- /dev/null
+++ b/patches/april_2013/p01_update_serial_no_valuation_rate.py
@@ -0,0 +1,35 @@
+import webnotes
+from webnotes.utils import cstr
+from stock.stock_ledger import update_entries_after
+
+def execute():
+	webnotes.conn.auto_commit_on_many_writes = 1
+	
+	pr_items = webnotes.conn.sql("""select item_code, warehouse, serial_no, valuation_rate, name 
+		from `tabPurchase Receipt Item` where ifnull(serial_no, '') != '' and docstatus = 1""", 
+		as_dict=True)
+		
+	item_warehouse = []
+		
+	for item in pr_items:
+		serial_nos = cstr(item.serial_no).strip().split("\n")
+		serial_nos = map(lambda x: x.strip(), serial_nos)
+
+		if cstr(item.serial_no) != "\n".join(serial_nos):
+			webnotes.conn.sql("""update `tabPurchase Receipt Item` set serial_no = %s 
+				where name = %s""", ("\n".join(serial_nos), item.name))
+			
+			if [item.item_code, item.warehouse] not in item_warehouse:
+				item_warehouse.append([item.item_code, item.warehouse])
+		
+			webnotes.conn.sql("""update `tabSerial No` set purchase_rate = %s 
+				where name in (%s)""" % ('%s', ', '.join(['%s']*len(serial_nos))), 
+				tuple([item.valuation_rate] + serial_nos))
+
+	for d in item_warehouse:
+		try:
+			update_entries_after({"item_code": d[0], "warehouse": d[1] })
+		except:
+			continue
+			
+	webnotes.conn.auto_commit_on_many_writes = 0
\ No newline at end of file
diff --git a/patches/march_2013/p07_update_valuation_rate.py b/patches/march_2013/p07_update_valuation_rate.py
index 794baf3..885fad6 100644
--- a/patches/march_2013/p07_update_valuation_rate.py
+++ b/patches/march_2013/p07_update_valuation_rate.py
@@ -4,12 +4,11 @@
 	webnotes.reload_doc("accounts", "doctype", "purchase_invoice_item")
 	
 	for purchase_invoice in webnotes.conn.sql_list("""select distinct parent 
-		from `tabPurchase Invoice Item` pi_item where docstatus = 1 and ifnull(valuation_rate, 0)=0 
-		and exists(select name from `tabPurchase Invoice` where name = pi_item.parent)"""):
-			pi = webnotes.get_obj("Purchase Invoice", purchase_invoice)
-			pi.calculate_taxes_and_totals()
-			pi.update_raw_material_cost()
-			pi.update_valuation_rate("entries")
-			for item in pi.doclist.get({"parentfield": "entries"}):
-				webnotes.conn.set_value("Purchase Invoice Item", item.name, "valuation_rate",
-					item.valuation_rate)
\ No newline at end of file
+		from `tabPurchase Invoice Item` where docstatus = 1 and ifnull(valuation_rate, 0)=0"""):
+		pi = webnotes.get_obj("Purchase Invoice", purchase_invoice)
+		pi.calculate_taxes_and_totals()
+		pi.update_raw_material_cost()
+		pi.update_valuation_rate("entries")
+		for item in pi.doclist.get({"parentfield": "entries"}):
+			webnotes.conn.sql("""update `tabPurchase Invoice Item` set valuation_rate = %s 
+				where name = %s""", (item.valuation_rate, item.name))
diff --git a/patches/march_2013/p10_update_against_expense_account.py b/patches/march_2013/p10_update_against_expense_account.py
index d1bad5c..3506ac4 100644
--- a/patches/march_2013/p10_update_against_expense_account.py
+++ b/patches/march_2013/p10_update_against_expense_account.py
@@ -5,7 +5,7 @@
 		where docstatus = 1 and ifnull(against_expense_account, '') = ''""")
 		
 	for pi in pi_list:
-	    pi_obj = get_obj("Purchase Invoice", pi[0], with_children=1)
-	    pi_obj.set_against_expense_account()
-	    webnotes.conn.set_value("Purchase Invoice", pi[0], 
-			"against_expense_account", pi_obj.doc.against_expense_account)
\ No newline at end of file
+		pi_obj = get_obj("Purchase Invoice", pi[0], with_children=1)
+		pi_obj.set_against_expense_account()
+		webnotes.conn.sql("""update `tabPurchase Invoice` set against_expense_account = %s 
+			where name = %s""", (pi_obj.doc.against_expense_account, pi[0]))
\ No newline at end of file
diff --git a/patches/patch_list.py b/patches/patch_list.py
index 08d936d..6501821 100644
--- a/patches/patch_list.py
+++ b/patches/patch_list.py
@@ -230,4 +230,5 @@
 	"patches.march_2013.p07_update_valuation_rate",
 	"patches.march_2013.p08_create_aii_accounts",
 	"patches.march_2013.p03_update_buying_amount",
+	"patches.april_2013.p01_update_serial_no_valuation_rate",
 ]
\ No newline at end of file
diff --git a/setup/doctype/item_group/item_group.txt b/setup/doctype/item_group/item_group.txt
index d9c6ffe..a8da12c 100644
--- a/setup/doctype/item_group/item_group.txt
+++ b/setup/doctype/item_group/item_group.txt
@@ -1,8 +1,8 @@
 [
  {
-  "creation": "2013-01-23 20:00:16", 
+  "creation": "2013-03-28 10:35:29", 
   "docstatus": 0, 
-  "modified": "2013-03-20 15:09:28", 
+  "modified": "2013-04-01 12:06:52", 
   "modified_by": "Administrator", 
   "owner": "Administrator"
  }, 
@@ -124,6 +124,7 @@
   "label": "Description"
  }, 
  {
+  "depends_on": "show_in_website", 
   "doctype": "DocField", 
   "fieldname": "item_website_specifications", 
   "fieldtype": "Table", 
@@ -182,20 +183,6 @@
   "print_hide": 1
  }, 
  {
-  "cancel": 1, 
-  "create": 1, 
-  "doctype": "DocPerm", 
-  "role": "System Manager", 
-  "write": 1
- }, 
- {
-  "cancel": 1, 
-  "create": 1, 
-  "doctype": "DocPerm", 
-  "role": "Material Master Manager", 
-  "write": 1
- }, 
- {
   "amend": 0, 
   "cancel": 0, 
   "create": 0, 
@@ -210,5 +197,19 @@
   "doctype": "DocPerm", 
   "role": "Material User", 
   "write": 0
+ }, 
+ {
+  "cancel": 1, 
+  "create": 1, 
+  "doctype": "DocPerm", 
+  "role": "System Manager", 
+  "write": 1
+ }, 
+ {
+  "cancel": 1, 
+  "create": 1, 
+  "doctype": "DocPerm", 
+  "role": "Material Master Manager", 
+  "write": 1
  }
 ]
\ No newline at end of file
diff --git a/setup/page/setup/setup.js b/setup/page/setup/setup.js
index e59a18a..4ab7578 100644
--- a/setup/page/setup/setup.js
+++ b/setup/page/setup/setup.js
@@ -199,6 +199,18 @@
 			},
 		]
 	},
+	{
+		title: wn._("Update Manager"),
+		icon: "icon-magnet",
+		right: true,
+		items: [
+			{
+				"page":"update-manager",
+				label: wn._("Update This Application"),
+				"description":wn._("Apply latest updates and patches to this app")
+			},
+		]
+	},
 ]
 
 pscript['onload_Setup'] = function(wrapper) {
diff --git a/stock/doctype/landed_cost_wizard/landed_cost_wizard.py b/stock/doctype/landed_cost_wizard/landed_cost_wizard.py
index 1fb7b9a..e5fd12c 100644
--- a/stock/doctype/landed_cost_wizard/landed_cost_wizard.py
+++ b/stock/doctype/landed_cost_wizard/landed_cost_wizard.py
@@ -212,7 +212,8 @@
 				if flt(d.qty):
 					d.valuation_rate = (flt(d.purchase_rate) + (flt(d.rm_supp_cost)/flt(d.qty)) + (flt(d.item_tax_amount)/flt(d.qty))) / flt(d.conversion_factor)
 					d.save()
-					self.update_serial_no(d.serial_no, d.valuation_rate)
+					if d.serial_no:
+						self.update_serial_no(d.serial_no, d.valuation_rate)
 				sql("update `tabStock Ledger Entry` set incoming_rate = '%s' where voucher_detail_no = '%s'"%(flt(d.valuation_rate), d.name))
 				
 				res = sql("""select item_code, warehouse, posting_date, posting_time 
@@ -226,10 +227,10 @@
 	
 	def update_serial_no(self, sr_no, rate):
 		""" update valuation rate in serial no"""
-		sr_no = cstr(sr_no).split('\n')
-		for d in sr_no:
-			sql("update `tabSerial No` set purchase_rate = %s where name = %s", (rate, d))
-
+		sr_no = map(lambda x: x.strip(), cstr(sr_no).split('\n'))
+		
+		webnotes.conn.sql("""update `tabSerial No` set purchase_rate = %s where name in (%s)""" % 
+			('%s', ', '.join(['%s']*len(sr_no))), tuple([rate] + sr_no))
 				
 	def update_landed_cost(self):
 		""" 
diff --git a/stock/doctype/stock_ledger/stock_ledger.py b/stock/doctype/stock_ledger/stock_ledger.py
index fcb4a54..469c94b 100644
--- a/stock/doctype/stock_ledger/stock_ledger.py
+++ b/stock/doctype/stock_ledger/stock_ledger.py
@@ -38,10 +38,10 @@
 		
 		for d in getlist(obj.doclist, table_name):
 			if d.serial_no:
-				d.serial_no = cstr(d.serial_no).strip().replace(',', '\n')
+				serial_nos = cstr(d.serial_no).strip().replace(',', '\n').split('\n')
+				d.serial_no = "\n".join(map(lambda x: x.strip(), serial_nos))
 				d.save()
 
-
 	def validate_serial_no_warehouse(self, obj, fname):
 		for d in getlist(obj.doclist, fname):
 			wh = d.warehouse or d.s_warehouse
@@ -84,6 +84,7 @@
 		item_details = webnotes.conn.sql("""select item_group, warranty_period 
 			from `tabItem` where name = '%s' and (ifnull(end_of_life,'')='' or 
 			end_of_life = '0000-00-00' or end_of_life > now()) """ %(d.item_code), as_dict=1)
+		webnotes.errprint([d.item_code, d.valuation_rate])
 		
 		s.purchase_document_type	=	obj.doc.doctype
 		s.purchase_document_no		=	obj.doc.name
diff --git a/website/templates/html/product_in_list.html b/website/templates/html/product_in_list.html
index 97de596..bc62607 100644
--- a/website/templates/html/product_in_list.html
+++ b/website/templates/html/product_in_list.html
@@ -1,10 +1,12 @@
 <div class="span3">
 	<div style="height: 120px; overflow: hidden;">
-		{% if website_image %}
+		<a href="{{ page_name }}">
+		{%- if website_image -%}
 		<img class="product-image" style="width: 80%; margin: auto;" src="{{ website_image }}">
-		{% else %}
+		{%- else -%}
 		{% include 'html/product_missing_image.html' %}
-		{% endif %}
+		{%- endif -%}
+		</a>
 	</div>
 	<div style="height: 100px; overflow: hidden; font-size: 80%;">
 		<h4 style="margin-bottom: 2px;"><a href="{{ page_name }}">{{ item_name }}</a></h4>