Merge branch 'dev' of github.com:webnotes/erpnext into dev
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 82314ca..eb869e5 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -40,18 +40,12 @@
 		self.fname = 'entries'
 
 
-	# Autoname
-	# ---------
 	def autoname(self):
 		self.doc.name = make_autoname(self.doc.naming_series+ '.#####')
 
 
-
-# ********************************* Trigger Functions ******************************
-
-	#Set retail related fields from pos settings
-	#-------------------------------------------------------------------------
 	def set_pos_fields(self):
+		"""Set retail related fields from pos settings"""
 		pos = webnotes.conn.sql("select * from `tabPOS Setting` where ifnull(user,'') = '%s' and company = '%s'" % (session['user'], self.doc.company), as_dict=1)
 		if not pos:
 			pos = webnotes.conn.sql("select * from `tabPOS Setting` where ifnull(user,'') = '' and company = '%s'" % (self.doc.company), as_dict=1)
@@ -79,9 +73,8 @@
 			if self.doc.charge:		self.get_other_charges()
 
 
-	# Set default values related to pos for previously created sales invoice.
-	# -------------------------------------------------------------------------- 
 	def set_pos_item_values(self):
+		"""Set default values related to pos for previously created sales invoice."""
 		if cint(self.doc.is_pos) ==1:
 			dtl = webnotes.conn.sql("select income_account, warehouse, cost_center from `tabPOS Setting` where ifnull(user,'') = '%s' and company = '%s'" % (session['user'], self.doc.company), as_dict=1)
 			if not dtl:
@@ -94,10 +87,8 @@
 				d.warehouse = item and item[0]['default_warehouse'] or dtl and dtl[0]['warehouse'] or d.warehouse
 
 
-			
-	# Get Account Head to which amount needs to be Debited based on Customer
-	# ----------------------------------------------------------------------
 	def get_customer_account(self):
+		"""Get Account Head to which amount needs to be Debited based on Customer"""
 		if not self.doc.company:
 			msgprint("Please select company first and re-select the customer after doing so", raise_exception=1)
 			
@@ -115,10 +106,8 @@
 		return acc_head and {'debit_to' : acc_head} or {}
 
 
-
-	# Set Due Date = Posting Date + Credit Days
-	# -----------------------------------------
 	def get_cust_and_due_date(self):
+		"""Set Due Date = Posting Date + Credit Days"""
 		credit_days = 0
 		if self.doc.debit_to:
 			credit_days = webnotes.conn.sql("select credit_days from `tabAccount` where name='%s' and docstatus != 2" % self.doc.debit_to)
@@ -134,9 +123,8 @@
 			self.doc.customer = webnotes.conn.get_value('Account',self.doc.debit_to,'master_name')
 
 
-	# Pull Details of Delivery Note or Sales Order Selected
-	# ------------------------------------------------------
 	def pull_details(self):
+		"""Pull Details of Delivery Note or Sales Order Selected"""
 		# Delivery Note
 		if self.doc.delivery_note_main:
 			self.validate_prev_docname('delivery note')
@@ -153,14 +141,14 @@
 		ret = self.get_debit_to()
 		self.doc.debit_to = ret.get('debit_to')
 					
-	# onload pull income account
-	# --------------------------
+					
 	def load_default_accounts(self):
 		"""
 			Loads default accounts from items, customer when called from mapper
 		"""
 		self.get_income_account('entries')
 		
+		
 	def get_income_account(self,doctype):		
 		for d in getlist(self.doclist, doctype):			
 			if d.item_code:
@@ -168,8 +156,7 @@
 				d.income_account = item and item[0]['default_income_account'] or ''
 				d.cost_center = item and item[0]['default_sales_cost_center'] or ''				
 
-	# Item Details
-	# -------------
+
 	def get_item_details(self, args=None):
 		import json
 		args = args and json.loads(args) or {}
@@ -215,61 +202,49 @@
 		return get_obj('Sales Common').get_barcode_details(barcode)
 
 
-	# Fetch ref rate from item master as per selected price list
 	def get_adj_percent(self, arg=''):
+		"""Fetch ref rate from item master as per selected price list"""
 		get_obj('Sales Common').get_adj_percent(self)
 
 
-	# Get tax rate if account type is tax
-	# ------------------------------------
 	def get_rate(self,arg):
+		"""Get tax rate if account type is tax"""
 		get_obj('Sales Common').get_rate(arg)
 		
 		
-	# Get Commission rate of Sales Partner
-	# -------------------------------------
 	def get_comm_rate(self, sales_partner):
+		"""Get Commission rate of Sales Partner"""
 		return get_obj('Sales Common').get_comm_rate(sales_partner, self)	
 	
- 
-	# GET TERMS & CONDITIONS
-	# -------------------------------------
+	
 	def get_tc_details(self):
 		return get_obj('Sales Common').get_tc_details(self)
 
-	# Load Default Charges
-	# ----------------------------------------------------------
+
 	def load_default_taxes(self):
 		self.doclist = get_obj('Sales Common').load_default_taxes(self)
 
-	# Get Sales Taxes and Charges Master Details
-	# --------------------------
+
 	def get_other_charges(self):
 		self.doclist = get_obj('Sales Common').get_other_charges(self)
 
-	# Get Advances
-	# -------------
+
 	def get_advances(self):
 		self.doclist = get_obj('GL Control').get_advances(self, self.doc.debit_to, 'Sales Invoice Advance', 'advance_adjustment_details', 'credit')
 
-	#pull project customer
-	#-------------------------
+	
 	def pull_project_customer(self):
 		res = webnotes.conn.sql("select customer from `tabProject` where name = '%s'"%self.doc.project_name)
 		if res:
 			get_obj('DocType Mapper', 'Project-Sales Invoice').dt_map('Project', 'Sales Invoice', self.doc.project_name, self.doc, self.doclist, "[['Project', 'Sales Invoice']]")
 
-# ********************************** Server Utility Functions ******************************
-	
-	# Get Company Abbr.
-	# ------------------
+
 	def get_company_abbr(self):
 		return webnotes.conn.sql("select abbr from tabCompany where name=%s", self.doc.company)[0][0]
 		
-	
-	# Check whether sales order / delivery note items already pulled
-	#----------------------------------------------------------------
+		
 	def validate_prev_docname(self,doctype):
+		"""Check whether sales order / delivery note items already pulled"""
 		for d in getlist(self.doclist, 'entries'): 
 			if doctype == 'delivery note' and self.doc.delivery_note_main == d.delivery_note:
 				msgprint(cstr(self.doc.delivery_note_main) + " delivery note details have already been pulled.")
@@ -279,7 +254,6 @@
 				raise Exception , "Validation Error. Sales order details have already been pulled."
 
 
-	#-----------------------------------------------------------------
 	def update_against_document_in_jv(self):
 		"""
 			Links invoice and advance voucher:
@@ -308,11 +282,8 @@
 			get_obj('GL Control').reconcile_against_document(lst)
 	
 	
-	# ------------------------------------------------------------------------
 	def validate_customer(self):
-		"""
-			Validate customer name with SO and DN
-		"""
+		"""	Validate customer name with SO and DN"""
 		for d in getlist(self.doclist,'entries'):
 			dt = d.delivery_note and 'Delivery Note' or d.sales_order and 'Sales Order' or ''
 			if dt:
@@ -322,9 +293,8 @@
 					msgprint("Customer %s does not match with customer of %s: %s." %(self.doc.customer, dt, dt_no), raise_exception=1)
 			
 
-	# Validates Debit To Account and Customer Matches
-	# ------------------------------------------------
-	def validate_debit_to_acc(self):
+	def validate_customer_account(self):
+		"""Validates Debit To Account and Customer Matches"""
 		if self.doc.customer and self.doc.debit_to and not cint(self.doc.is_pos):
 			acc_head = webnotes.conn.sql("select master_name from `tabAccount` where name = %s and docstatus != 2", self.doc.debit_to)
 			
@@ -334,11 +304,6 @@
 					and Master Name in account master." %(self.doc.debit_to, self.doc.customer,self.doc.company), raise_exception=1)
 
 
-	# Validate Debit To Account
-	# 1. Account Exists
-	# 2. Is a Debit Account
-	# 3. Is a PL Account
-	# ---------------------------
 	def validate_debit_acc(self):
 		acc = webnotes.conn.sql("select debit_or_credit, is_pl_account from tabAccount where name = '%s' and docstatus != 2" % self.doc.debit_to)
 		if not acc:
@@ -352,9 +317,8 @@
 			raise Exception
 
 
-	# Validate Fixed Asset Account and whether Income Account Entered Exists
-	# -----------------------------------------------------------------------
 	def validate_fixed_asset_account(self):
+		"""Validate Fixed Asset Account and whether Income Account Entered Exists"""
 		for d in getlist(self.doclist,'entries'):
 			item = webnotes.conn.sql("select name,is_asset_item,is_sales_item 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)
 			acc =	webnotes.conn.sql("select account_type from `tabAccount` where name = '%s' and docstatus != 2" % d.income_account)
@@ -366,22 +330,16 @@
 				raise Exception
 
 
-
-	# Set totals in words
-	#--------------------
 	def set_in_words(self):
 		dcc = TransactionBase().get_company_currency(self.doc.company)
 		self.doc.in_words = get_obj('Sales Common').get_total_in_words(dcc, self.doc.rounded_total)
 		self.doc.in_words_export = get_obj('Sales Common').get_total_in_words(self.doc.currency, self.doc.rounded_total_export)
 
-	# Clear Advances
-	# --------------
+
 	def clear_advances(self):
 		get_obj('GL Control').clear_advances(self, 'Sales Invoice Advance','advance_adjustment_details')
 
 
-	# set aging date
-	#-------------------
 	def set_aging_date(self):
 		if self.doc.is_opening != 'Yes':
 			self.doc.aging_date = self.doc.posting_date
@@ -390,20 +348,21 @@
 			raise Exception
 			
 
-	# Set against account for debit to account
-	#------------------------------------------
 	def set_against_income_account(self):
+		"""Set against account for debit to account"""
 		against_acc = []
 		for d in getlist(self.doclist, 'entries'):
 			if d.income_account not in against_acc:
 				against_acc.append(d.income_account)
 		self.doc.against_income_account = ','.join(against_acc)
 
+
 	def add_remarks(self):
 		if not self.doc.remarks: self.doc.remarks = 'No Remarks'
 
-	#check in manage account if sales order / delivery note required or not.
+
 	def so_dn_required(self):
+		"""check in manage account if sales order / delivery note required or not."""
 		dict = {'Sales Order':'so_required','Delivery Note':'dn_required'}
 		for i in dict:	
 			res = webnotes.conn.sql("select value from `tabSingles` where doctype = 'Global Defaults' and field = '%s'"%dict[i])
@@ -413,9 +372,9 @@
 						msgprint("%s No. required against item %s"%(i,d.item_code))
 						raise Exception
 
-	#check for does customer belong to same project as entered..
-	#-------------------------------------------------------------------------------------------------
+
 	def validate_proj_cust(self):
+		"""check for does customer belong to same project as entered.."""
 		if self.doc.project_name and self.doc.customer:
 			res = webnotes.conn.sql("select name from `tabProject` where name = '%s' and (customer = '%s' or ifnull(customer,'')='')"%(self.doc.project_name, self.doc.customer))
 			if not res:
@@ -431,20 +390,13 @@
 			raise Exception
 
 
-	# ********* UPDATE CURRENT STOCK *****************************
-	def update_current_stock(self):
-		for d in getlist(self.doclist, 'entries'):
-			bin = webnotes.conn.sql("select actual_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1)
-			d.actual_qty = bin and flt(bin[0]['actual_qty']) or 0
-
 	def validate_item_code(self):
 		for d in getlist(self.doclist, 'entries'):
 			if not d.item_code:
 				msgprint("Please enter Item Code at line no : %s to update stock for POS or remove check from Update Stock in Basic Info Tab." % (d.idx))
 				raise Exception
 
-	# Validate Write Off Account
-	# -------------------------------
+
 	def validate_write_off_account(self):
 		if flt(self.doc.write_off_amount) and not self.doc.write_off_account:
 			msgprint("Please enter Write Off Account", raise_exception=1)
@@ -457,12 +409,22 @@
 					and parent = %s""", (self.doc.amended_from,	self.doc.c_form_no))
 
 			webnotes.conn.set(self.doc, 'c_form_no', '')
+			
+
+	def update_current_stock(self):
+		for d in getlist(self.doclist, 'entries'):
+			if d.item_code and d.warehouse:
+				bin = webnotes.conn.sql("select actual_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1)
+				d.actual_qty = bin and flt(bin[0]['actual_qty']) or 0
+
+		for d in getlist(self.doclist, 'packing_details'):
+			bin = sql("select actual_qty, projected_qty from `tabBin` where item_code =	%s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1)
+			d.actual_qty = bin and flt(bin[0]['actual_qty']) or 0
+			d.projected_qty = bin and flt(bin[0]['projected_qty']) or 0
 	 
-	# VALIDATE
-	# ====================================================================================
+	
 	def validate(self):
 		self.so_dn_required()
-		#self.dn_required()
 		self.validate_proj_cust()
 		sales_com_obj = get_obj('Sales Common')
 		sales_com_obj.check_stop_sales_order(self)
@@ -472,7 +434,7 @@
 		sales_com_obj.get_allocated_sum(self)	# this is to verify that the allocated % of sales persons is 100%
 		sales_com_obj.validate_fiscal_year(self.doc.fiscal_year,self.doc.posting_date,'Posting Date')
 		self.validate_customer()
-		self.validate_debit_to_acc()
+		self.validate_customer_account()
 		self.validate_debit_acc()
 		self.validate_fixed_asset_account()
 		self.add_remarks()
@@ -480,7 +442,9 @@
 			self.validate_pos()
 			self.validate_write_off_account()
 			if cint(self.doc.update_stock):
-				get_obj('Stock Ledger').validate_serial_no(self, 'entries')
+				sl = get_obj('Stock Ledger')
+				sl.validate_serial_no(self, 'entries')
+				sl.validate_serial_no(self, 'packing_details')
 				self.validate_item_code()
 				self.update_current_stock()
 		self.set_in_words()
@@ -488,14 +452,62 @@
 			self.doc.is_opening = 'No'
 		self.set_aging_date()
 		self.clear_advances()
-		# Set against account
 		self.set_against_income_account()
 		self.validate_c_form()
 
+
+	def get_warehouse(self):
+		w = webnotes.conn.sql("select warehouse from `tabPOS Setting` where ifnull(user,'') = '%s' and company = '%s'" % (session['user'], self.doc.company))
+		w = w and w[0][0] or ''
+		if not w:
+			ps = webnotes.conn.sql("select name, warehouse from `tabPOS Setting` where ifnull(user,'') = '' and company = '%s'" % self.doc.company)
+			if not ps:
+				msgprint("To make POS entry, please create POS Setting from Accounts --> POS Setting page and refresh the system.")
+				raise Exception
+			elif not ps[0][1]:
+				msgprint("Please enter warehouse in POS Setting")
+			else:
+				w = ps[0][1]
+		return w
+
+	
+	def make_packing_list(self):
+		get_obj('Sales Common').make_packing_list(self,'entries')
+		sl = get_obj('Stock Ledger')
+		sl.scrub_serial_nos(self)
+		sl.scrub_serial_nos(self, 'packing_details')
+
+
+	def on_update(self):
+		# Set default warehouse from pos setting
+		if cint(self.doc.is_pos) == 1:
+			if cint(self.doc.update_stock) == 1:
+				w = self.get_warehouse()
+				if w:
+					for d in getlist(self.doclist, 'entries'):
+						if not d.warehouse:
+							d.warehouse = cstr(w)
+							
+				self.make_packing_list()
+			else:
+				self.doclist = self.doc.clear_table(self.doclist, 'packing_details')
+
+			if flt(self.doc.paid_amount) == 0:
+				if self.doc.cash_bank_account: 
+					webnotes.conn.set(self.doc, 'paid_amount', 
+						(flt(self.doc.grand_total) - flt(self.doc.write_off_amount)))
+				else:
+					# show message that the amount is not paid
+					webnotes.conn.set(self.doc,'paid_amount',0)
+					webnotes.msgprint("Note: Payment Entry will not be created since 'Cash/Bank Account' was not specified.")
+
+		else:
+			self.doclist = self.doc.clear_table(self.doclist, 'packing_details')
+			webnotes.conn.set(self.doc,'paid_amount',0)
+
+		webnotes.conn.set(self.doc,'outstanding_amount',flt(self.doc.grand_total) - flt(self.doc.total_advance) - flt(self.doc.paid_amount) - flt(self.doc.write_off_amount))
+
 		
-# *************************************************** ON SUBMIT **********************************************
-	# Check Ref Document's docstatus
-	# -------------------------------
 	def check_prev_docstatus(self):
 		for d in getlist(self.doclist,'entries'):
 			if d.sales_order:
@@ -511,56 +523,45 @@
 					raise Exception , "Validation Error."
 
 
-	#Set Actual Qty based on item code and warehouse
-	#------------------------------------------------------
-	def set_actual_qty(self):
-		for d in getlist(self.doclist, 'entries'):
-			if d.item_code and d.warehouse:
-				actual_qty = webnotes.conn.sql("select actual_qty from `tabBin` where item_code = '%s' and warehouse = '%s'" % (d.item_code, d.warehouse))
-				d.actual_qty = actual_qty and flt(actual_qty[0][0]) or 0
-
-
-
-	# ********************** Make Stock Entry ************************************
 	def make_sl_entry(self, d, wh, qty, in_value, update_stock):
-		st_uom = webnotes.conn.sql("select stock_uom from `tabItem` where name = '%s'"%d.item_code)
+		st_uom = webnotes.conn.sql("select stock_uom from `tabItem` where name = '%s'"%d['item_code'])
 		self.values.append({
-			'item_code'					 : d.item_code,
+			'item_code'					 : d['item_code'],
 			'warehouse'					 : wh,
 			'transaction_date'			: getdate(self.doc.modified).strftime('%Y-%m-%d'),
 			'posting_date'				: self.doc.posting_date,
 			'posting_time'				: self.doc.posting_time,
 			'voucher_type'				: 'Sales Invoice',
 			'voucher_no'					: cstr(self.doc.name),
-			'voucher_detail_no'	 : cstr(d.name), 
+			'voucher_detail_no'	 : cstr(d['name']), 
 			'actual_qty'					: qty, 
 			'stock_uom'					 : st_uom and st_uom[0][0] or '',
 			'incoming_rate'			 : in_value,
 			'company'						 : self.doc.company,
 			'fiscal_year'				 : self.doc.fiscal_year,
 			'is_cancelled'				: (update_stock==1) and 'No' or 'Yes',
-			'batch_no'						: cstr(d.batch_no),
-			'serial_no'					 : d.serial_no
-		})		
+			'batch_no'						: cstr(d['batch_no']),
+			'serial_no'					 : d['serial_no']
+		})	
 			
 
-	# UPDATE STOCK LEDGER
-	# ---------------------------------------------------------------------------
-	def update_stock_ledger(self, update_stock, clear = 0):
+	def update_stock_ledger(self, update_stock):
 		self.values = []
-		for d in getlist(self.doclist, 'entries'):
-			stock_item = webnotes.conn.sql("SELECT is_stock_item, is_sample_item FROM tabItem where name = '%s'"%(d.item_code), as_dict = 1) # stock ledger will be updated only if it is a stock item
+		items = get_obj('Sales Common').get_item_list(self)
+		for d in items:
+			stock_item = webnotes.conn.sql("SELECT is_stock_item, is_sample_item \
+				FROM tabItem where name = '%s'"%(d['item_code']), as_dict = 1)
 			if stock_item[0]['is_stock_item'] == "Yes":
+				if not d['warehouse']:
+					msgprint("Message: Please enter Warehouse for item %s as it is stock item." \
+						% d['item_code'], raise_exception=1)
+
 				# Reduce actual qty from warehouse
-				self.make_sl_entry( d, d.warehouse, - flt(d.qty) , 0, update_stock)
-		get_obj('Stock Ledger', 'Stock Ledger').update_stock(self.values, self.doc.amended_from and 'Yes' or 'No')
-
-
-	#-------------------POS Stock Updatation Part----------------------------------------------
-	def pos_update_stock(self):
-		self.update_stock_ledger(update_stock = 1)
+				self.make_sl_entry( d, d['warehouse'], - flt(d['qty']) , 0, update_stock)
+				
+		get_obj('Stock Ledger', 'Stock Ledger').update_stock(self.values)
 	
-	# ********** Get Actual Qty of item in warehouse selected *************
+
 	def get_actual_qty(self,args):
 		args = eval(args)
 		actual_qty = webnotes.conn.sql("select actual_qty from `tabBin` where item_code = '%s' and warehouse = '%s'" % (args['item_code'], args['warehouse']), as_dict=1)
@@ -569,23 +570,39 @@
 		}
 		return ret
 
-	# Make GL Entries
-	# -------------------------
+
 	def make_gl_entries(self, is_cancel=0):
 		mapper = self.doc.is_pos and self.doc.write_off_account and 'POS with write off' or self.doc.is_pos and not self.doc.write_off_account and 'POS' or ''
 		update_outstanding = self.doc.is_pos and self.doc.write_off_account and 'No' or 'Yes'
 		get_obj(dt='GL Control').make_gl_entries(self.doc, self.doclist,cancel = is_cancel, use_mapper = mapper, update_outstanding = update_outstanding, merge_entries = cint(self.doc.is_pos) != 1 and 1 or 0)
 		
 
-	# On Submit
-	# ---------
+	def update_c_form(self):
+		"""Update amended id in C-form"""
+		if self.doc.c_form_no and self.doc.amended_from:
+			webnotes.conn.sql("""update `tabC-Form Invoice Detail` set invoice_no = %s,
+					invoice_date = %s, territory = %s, net_total = %s,
+					grand_total = %s where invoice_no = %s and parent = %s""", (self.doc.name, self.doc.amended_from, self.doc.c_form_no))
+
+
+	def check_next_docstatus(self):
+		submit_jv = webnotes.conn.sql("select t1.name from `tabJournal Voucher` t1,`tabJournal Voucher Detail` t2 where t1.name = t2.parent and t2.against_invoice = '%s' and t1.docstatus = 1" % (self.doc.name))
+		if submit_jv:
+			msgprint("Journal Voucher : " + cstr(submit_jv[0][0]) + " has been created against " + cstr(self.doc.doctype) + ". So " + cstr(self.doc.doctype) + " cannot be Cancelled.")
+			raise Exception, "Validation Error."
+
+
 	def on_submit(self):
 		if cint(self.doc.is_pos) == 1:
 			if cint(self.doc.update_stock) == 1:
 				sl_obj = get_obj("Stock Ledger")
 				sl_obj.validate_serial_no_warehouse(self, 'entries')
+				sl_obj.validate_serial_no_warehouse(self, 'packing_details')
+				
 				sl_obj.update_serial_record(self, 'entries', is_submit = 1, is_incoming = 0)
-				self.pos_update_stock()
+				sl_obj.update_serial_record(self, 'packing_details', is_submit = 1, is_incoming = 0)
+				
+				self.update_stock_ledger(update_stock=1)
 		else:
 			self.check_prev_docstatus()
 			get_obj("Sales Common").update_prevdoc_detail(1,self)
@@ -603,31 +620,13 @@
 		self.update_c_form()
 
 
-	def update_c_form(self):
-		"""Update amended id in C-form"""
-		if self.doc.c_form_no and self.doc.amended_from:
-			webnotes.conn.sql("""update `tabC-Form Invoice Detail` set invoice_no = %s,
-					invoice_date = %s, territory = %s, net_total = %s,
-					grand_total = %s where invoice_no = %s and parent = %s""", (self.doc.name, self.doc.amended_from, self.doc.c_form_no))
-	
-
-			
-# *************************************************** ON CANCEL **********************************************
-	# Check Next Document's docstatus
-	# --------------------------------
-	def check_next_docstatus(self):
-		submit_jv = webnotes.conn.sql("select t1.name from `tabJournal Voucher` t1,`tabJournal Voucher Detail` t2 where t1.name = t2.parent and t2.against_invoice = '%s' and t1.docstatus = 1" % (self.doc.name))
-		if submit_jv:
-			msgprint("Journal Voucher : " + cstr(submit_jv[0][0]) + " has been created against " + cstr(self.doc.doctype) + ". So " + cstr(self.doc.doctype) + " cannot be Cancelled.")
-			raise Exception, "Validation Error."
-
-
-	# On Cancel
-	# ----------
 	def on_cancel(self):
 		if cint(self.doc.is_pos) == 1:
 			if cint(self.doc.update_stock) == 1:
-				get_obj('Stock Ledger').update_serial_record(self, 'entries', is_submit = 0, is_incoming = 0)
+				sl = get_obj('Stock Ledger')
+				sl.update_serial_record(self, 'entries', is_submit = 0, is_incoming = 0)
+				sl.update_serial_record(self, 'packing_details', is_submit = 0, is_incoming = 0)
+				
 				self.update_stock_ledger(update_stock = -1)
 		else:
 			sales_com_obj = get_obj(dt = 'Sales Common')
@@ -636,51 +635,6 @@
 			sales_com_obj.update_prevdoc_detail(0,self)
 
 		self.make_gl_entries(is_cancel=1)
-
-	# Get Warehouse
-	def get_warehouse(self):
-		w = webnotes.conn.sql("select warehouse from `tabPOS Setting` where ifnull(user,'') = '%s' and company = '%s'" % (session['user'], self.doc.company))
-		w = w and w[0][0] or ''
-		if not w:
-			ps = webnotes.conn.sql("select name, warehouse from `tabPOS Setting` where ifnull(user,'') = '' and company = '%s'" % self.doc.company)
-			if not ps:
-				msgprint("To make POS entry, please create POS Setting from Setup --> Accounts --> POS Setting and refresh the system.")
-				raise Exception
-			elif not ps[0][1]:
-				msgprint("Please enter warehouse in POS Setting")
-			else:
-				w = ps[0][1]
-		return w
-
-	# on update
-	def on_update(self):
-		# Set default warehouse from pos setting
-		#----------------------------------------
-		if cint(self.doc.is_pos) == 1:
-			self.set_actual_qty()
-			w = self.get_warehouse()
-			if w:
-				for d in getlist(self.doclist, 'entries'):
-					if not d.warehouse:
-						d.warehouse = cstr(w)
-
-			if flt(self.doc.paid_amount) == 0:
-				if self.doc.cash_bank_account: 
-					webnotes.conn.set(self.doc, 'paid_amount', 
-						(flt(self.doc.grand_total) - flt(self.doc.write_off_amount)))
-				else:
-					# show message that the amount is not paid
-					webnotes.conn.set(self.doc,'paid_amount',0)
-					webnotes.msgprint("Note: Payment Entry not created since 'Cash/Bank Account' was not specified.")
-
-		else:
-			webnotes.conn.set(self.doc,'paid_amount',0)
-
-		webnotes.conn.set(self.doc,'outstanding_amount',flt(self.doc.grand_total) - flt(self.doc.total_advance) - flt(self.doc.paid_amount) - flt(self.doc.write_off_amount))
-
-	#-------------------------------------------------------------------------------------
-	def on_update_after_submit(self):
-		self.convert_into_recurring()
 		
 
 	def convert_into_recurring(self):
@@ -717,3 +671,7 @@
 		next_date = next_date.strftime("%Y-%m-%d")
 
 		webnotes.conn.set(self.doc, 'next_date', next_date)
+
+
+	def on_update_after_submit(self):
+		self.convert_into_recurring()
\ No newline at end of file
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.txt b/erpnext/accounts/doctype/sales_invoice/sales_invoice.txt
index 969a7dc..a2b341f 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.txt
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.txt
@@ -3,9 +3,9 @@
 
 	# These values are common in all dictionaries
 	{
-		'creation': '2012-06-11 12:09:54',
+		'creation': '2012-07-05 11:04:09',
 		'docstatus': 0,
-		'modified': '2012-06-17 21:37:40',
+		'modified': '2012-07-11 12:19:49',
 		'modified_by': u'Administrator',
 		'owner': u'Administrator'
 	},
@@ -353,6 +353,16 @@
 	# DocField
 	{
 		'doctype': u'DocField',
+		'fieldname': u'sales_bom_help',
+		'fieldtype': u'HTML',
+		'label': u'Sales BOM Help',
+		'permlevel': 0,
+		'print_hide': 1
+	},
+
+	# DocField
+	{
+		'doctype': u'DocField',
 		'fieldname': u'section_break0',
 		'fieldtype': u'Section Break',
 		'options': u'Simple',
@@ -1346,6 +1356,27 @@
 	# DocField
 	{
 		'doctype': u'DocField',
+		'fieldname': u'packing_list',
+		'fieldtype': u'Section Break',
+		'label': u'Packing List',
+		'permlevel': 0,
+		'print_hide': 1
+	},
+
+	# DocField
+	{
+		'doctype': u'DocField',
+		'fieldname': u'packing_details',
+		'fieldtype': u'Table',
+		'label': u'Packing Details',
+		'options': u'Delivery Note Packing Item',
+		'permlevel': 0,
+		'print_hide': 1
+	},
+
+	# DocField
+	{
+		'doctype': u'DocField',
 		'fieldname': u'sales_team_section_break',
 		'fieldtype': u'Section Break',
 		'label': u'Sales Team',
diff --git a/erpnext/production/doctype/bom/bom.py b/erpnext/production/doctype/bom/bom.py
index 81297b4..bc166ce 100644
--- a/erpnext/production/doctype/bom/bom.py
+++ b/erpnext/production/doctype/bom/bom.py
@@ -106,7 +106,6 @@
 		return ret_item
 
 
-
 	def get_rm_rate(self, arg):
 		"""	Get raw material rate as per selected method, if bom exists takes bom cost """
 
@@ -293,7 +292,6 @@
 		self.validate_main_item()
 		self.validate_operations()
 		self.validate_materials()
-		self.validate_operations()
 
 
 
@@ -353,8 +351,6 @@
 			})
 
 
-
-
 	# Get Current Flat BOM Items
 	# -----------------------------
 	def get_current_flat_bom_items(self):
diff --git a/erpnext/selling/doctype/sales_common/sales_common.js b/erpnext/selling/doctype/sales_common/sales_common.js
index c852230..bf80d8f 100644
--- a/erpnext/selling/doctype/sales_common/sales_common.js
+++ b/erpnext/selling/doctype/sales_common/sales_common.js
@@ -127,10 +127,34 @@
 	cur_frm.cscript.base_currency = base_curr;
 	set_dynamic_label_par(doc, cdt, cdn, base_curr);
 	set_dynamic_label_child(doc, cdt, cdn, base_curr);
+	set_sales_bom_help(doc);
 
 	if (callback) callback(doc, cdt, cdn);
 }
 
+// Help for Sales BOM items
+var set_sales_bom_help = function(doc) {
+	if (getchildren('Delivery Note Packing Item', doc.name, 'packing_details').length) {
+		$(cur_frm.fields_dict.packing_list.row.wrapper).toggle(true);
+		
+		if (inList(['Delivery Note', 'Sales Invoice'], doc.doctype)) {
+			help_msg = "<div class='help-box'> \
+				For 'Sales BOM' items, warehouse, serial no and batch no \
+				will be considered from the 'Packing List' table. \
+				If warehouse and batch no are same for all packing items for any 'Sales BOM' item, \
+				those values can be entered in the main item table, values will be copied to 'Packing List' table. \
+			</div>";
+			get_field(doc.doctype, 'sales_bom_help', doc.name).options = help_msg;
+		} 
+	} else {
+		$(cur_frm.fields_dict.packing_list.row.wrapper).toggle(false);
+		if (inList(['Delivery Note', 'Sales Invoice'], doc.doctype)) {
+			get_field(doc.doctype, 'sales_bom_help', doc.name).options = '';
+		}
+	}
+	refresh_field('sales_bom_help');
+}
+
 
 // hide / unhide price list currency based on availability of price list in customer's currency
 //---------------------------------------------------------------------------------------------------
diff --git a/erpnext/selling/doctype/sales_common/sales_common.py b/erpnext/selling/doctype/sales_common/sales_common.py
index 74963fb..a658209 100644
--- a/erpnext/selling/doctype/sales_common/sales_common.py
+++ b/erpnext/selling/doctype/sales_common/sales_common.py
@@ -385,7 +385,7 @@
 		return ret
 
 
-	def get_item_list(self, obj, is_stopped):
+	def get_item_list(self, obj, is_stopped=0):
 		"""get item list"""
 		il = []
 		for d in getlist(obj.doclist,obj.fname):
@@ -394,7 +394,7 @@
 			if is_stopped:
 				qty = flt(d.qty) > flt(d.delivered_qty) and flt(flt(d.qty) - flt(d.delivered_qty)) or 0
 				
-			if d.prevdoc_doctype == 'Sales Order':			
+			if d.prevdoc_doctype == 'Sales Order':
 				# used in delivery note to reduce reserved_qty 
 				# Eg.: if SO qty is 10 and there is tolerance of 20%, then it will allow DN of 12.
 				# But in this case reserved qty should only be reduced by 10 and not 12.
@@ -413,7 +413,7 @@
 					if p.parent_detail_docname == d.name:
 						# the packing details table's qty is already multiplied with parent's qty
 						il.append({
-							'warehouse': d.warehouse,
+							'warehouse': p.warehouse,
 							'reserved_warehouse': reserved_wh,
 							'item_code': p.item_code,
 							'qty': flt(p.qty),
@@ -496,23 +496,21 @@
 		pi.qty = flt(qty)
 		pi.actual_qty = bin and flt(bin['actual_qty']) or 0
 		pi.projected_qty = bin and flt(bin['projected_qty']) or 0
-		pi.warehouse = warehouse
 		pi.prevdoc_doctype = line.prevdoc_doctype
-		if packing_item_code == line.item_code:
-			pi.serial_no = cstr(line.serial_no)
+		if not pi.warehouse:
+			pi.warehouse = warehouse
+		if not pi.batch_no:
 			pi.batch_no = cstr(line.batch_no)
 		pi.idx = self.packing_list_idx
 		
-		# has to be saved, since this function is called on_update of delivery note
+		# saved, since this function is called on_update of delivery note
 		pi.save()
 		
 		self.packing_list_idx += 1
 
 
-	# ------------------
-	# make packing list from sales bom if exists or directly copy item with balance
-	# ------------------ 
 	def make_packing_list(self, obj, fname):
+		"""make packing list for sales bom item"""
 		self.packing_list_idx = 0
 		parent_items = []
 		for d in getlist(obj.doclist, fname):
@@ -520,10 +518,9 @@
 			if self.has_sales_bom(d.item_code):
 				for i in self.get_sales_bom_items(d.item_code):
 					self.update_packing_list_item(obj, i['item_code'], flt(i['qty'])*flt(d.qty), warehouse, d)
-			else:
-				self.update_packing_list_item(obj, d.item_code, d.qty, warehouse, d)
-			if [d.item_code, d.name] not in parent_items:
-				parent_items.append([d.item_code, d.name])
+
+				if [d.item_code, d.name] not in parent_items:
+					parent_items.append([d.item_code, d.name])
 				
 		self.cleanup_packing_list(obj, parent_items)
 		
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index ad95cf1..490051b 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -197,51 +197,6 @@
 		get_obj('DocType Mapper', 'Sales Order-Delivery Note', with_children = 1).validate_reference_value(self, self.doc.name)
 
 
-	def validate_prevdoc_details(self):
-		for d in getlist(self.doclist,'delivery_note_details'):
-			prevdoc = d.prevdoc_doctype
-			prevdoc_docname = d.prevdoc_docname
-
-			if prevdoc_docname and prevdoc:
-				# Validates Transaction Date of DN and previous doc (i.e. SO , PO, PR)
-				trans_date = sql("select posting_date from `tab%s` where name = '%s'" %(prevdoc,prevdoc_docname))[0][0]
-				if trans_date and getdate(self.doc.posting_date) < (trans_date):
-					msgprint("Your Posting Date cannot be before "+cstr(prevdoc)+" Date.")
-					raise Exception
-				# Validates DN and previous doc details
-				get_name = sql("select name from `tab%s` where name = '%s'" % (prevdoc, prevdoc_docname))
-				name = get_name and get_name[0][0] or ''
-				if name:	#check for incorrect docname
-					if prevdoc == 'Sales Order':
-						dt = sql("select company, docstatus, customer, currency, sales_partner from `tab%s` where name = '%s'" % (prevdoc, name))
-						cust_name = dt and dt[0][2] or ''
-						if cust_name != self.doc.customer:
-							msgprint(cstr(prevdoc) + ": " + cstr(prevdoc_docname) + " customer :" + cstr(cust_name) + " does not match with customer : " + cstr(self.doc.customer) + " of current document.")
-							raise Exception, "Validation Error. "
-						sal_partner = dt and dt[0][4] or ''
-						if sal_partner != self.doc.sales_partner:
-							msgprint(cstr(prevdoc) + ": " + cstr(prevdoc_docname) + " sales partner name :" + cstr(sal_partner) + " does not match with sales partner name : " + cstr(self.doc.sales_partner_name) + " of current document.")
-							raise Exception, "Validation Error. "
-					else:
-						dt = sql("select company, docstatus, supplier, currency from `tab%s` where name = '%s'" % (prevdoc, name))
-						supp_name = dt and dt[0][2] or ''
-						company_name = dt and dt[0][0] or ''
-						docstatus = dt and dt[0][1] or 0
-						currency = dt and dt[0][3] or ''
-						if (currency != self.doc.currency):
-							msgprint(cstr(prevdoc) + ": " + cstr(prevdoc_docname) + " currency : "+ cstr(currency) + "does not match with Currency: " + cstr(self.doc.currency) + "of current document")
-							raise Exception, "Validation Error."
-						if (company_name != self.doc.company):
-							msgprint(cstr(prevdoc) + ": " + cstr(prevdoc_docname) + " does not belong to the Company: " + cstr(self.doc.company_name))
-							raise Exception, "Validation Error."
-						if (docstatus != 1):
-							msgprint(cstr(prevdoc) + ": " + cstr(prevdoc_docname) + " is not Submitted Document.")
-							raise Exception, "Validation Error."
-				else:
-					msgprint(cstr(prevdoc) + ": " + cstr(prevdoc_docname) + " is not a valid " + cstr(prevdoc))
-					raise Exception, "Validation Error."
-
-
 	def validate_for_items(self):
 		check_list, chk_dupl_itm = [], []
 		for d in getlist(self.doclist,'delivery_note_details'):
@@ -292,11 +247,22 @@
 		set(self.doc, 'message', 'Items against your Order #%s have been delivered. Delivery #%s: ' % (self.doc.po_no, self.doc.name))
 		# Check for Approving Authority
 		get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, self.doc.company, self.doc.grand_total, self)
+		
+		# validate serial no for item table (non-sales-bom item) and packing list (sales-bom item)
 		sl_obj = get_obj("Stock Ledger")
+		sl_obj.validate_serial_no(self, 'delivery_note_details')
+		sl_obj.validate_serial_no_warehouse(self, 'delivery_note_details')
 		sl_obj.validate_serial_no(self, 'packing_details')
 		sl_obj.validate_serial_no_warehouse(self, 'packing_details')
+		
+		# update delivery details in serial no
+		sl_obj.update_serial_record(self, 'delivery_note_details', is_submit = 1, is_incoming = 0)
 		sl_obj.update_serial_record(self, 'packing_details', is_submit = 1, is_incoming = 0)
+		
+		# update delivered qty in sales order
 		get_obj("Sales Common").update_prevdoc_detail(1,self)
+		
+		# create stock ledger entry
 		self.update_stock_ledger(update_stock = 1)
 
 		self.credit_limit()
@@ -332,10 +298,14 @@
 		sales_com_obj = get_obj(dt = 'Sales Common')
 		sales_com_obj.check_stop_sales_order(self)
 		self.check_next_docstatus()
-		get_obj('Stock Ledger').update_serial_record(self, 'packing_details', is_submit = 0, is_incoming = 0)
+		
+		# remove delivery details from serial no
+		sl = get_obj('Stock Ledger')		
+		sl.update_serial_record(self, 'delivery_note_details', is_submit = 0, is_incoming = 0)
+		sl.update_serial_record(self, 'packing_details', is_submit = 0, is_incoming = 0)
+		
 		sales_com_obj.update_prevdoc_detail(0,self)
 		self.update_stock_ledger(update_stock = -1)
-		# :::::: set DN status :::::::
 		set(self.doc, 'status', 'Cancelled')
 		self.cancel_packing_slips()
 
@@ -435,7 +405,8 @@
 
 	def on_update(self):
 		get_obj('Sales Common').make_packing_list(self,'delivery_note_details')
-		self.set_actual_qty()
-		get_obj('Stock Ledger').scrub_serial_nos(self)
+		sl = get_obj('Stock Ledger')
+		sl.scrub_serial_nos(self)
+		sl.scrub_serial_nos(self, 'packing_details')
 
 
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.txt b/erpnext/stock/doctype/delivery_note/delivery_note.txt
index 7db9513..a0c2df0 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.txt
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.txt
@@ -3,9 +3,9 @@
 
 	# These values are common in all dictionaries
 	{
-		'creation': '2012-05-15 12:15:05',
+		'creation': '2012-06-11 12:10:09',
 		'docstatus': 0,
-		'modified': '2012-05-18 18:06:26',
+		'modified': '2012-07-11 11:56:53',
 		'modified_by': u'Administrator',
 		'owner': u'Administrator'
 	},
@@ -72,26 +72,14 @@
 
 	# DocPerm
 	{
-		'amend': 1,
-		'cancel': 1,
-		'create': 1,
+		'amend': 0,
+		'cancel': 0,
+		'create': 0,
 		'doctype': u'DocPerm',
-		'permlevel': 0,
-		'role': u'Sales User',
-		'submit': 1,
-		'write': 1
-	},
-
-	# DocPerm
-	{
-		'amend': 1,
-		'cancel': 1,
-		'create': 1,
-		'doctype': u'DocPerm',
-		'permlevel': 0,
-		'role': u'Material Master Manager',
-		'submit': 1,
-		'write': 1
+		'permlevel': 1,
+		'role': u'Material User',
+		'submit': 0,
+		'write': 0
 	},
 
 	# DocPerm
@@ -108,16 +96,72 @@
 
 	# DocPerm
 	{
+		'amend': 0,
+		'cancel': 0,
+		'create': 0,
 		'doctype': u'DocPerm',
 		'permlevel': 1,
-		'role': u'All'
+		'role': u'Material Manager',
+		'submit': 0,
+		'write': 0
+	},
+
+	# DocPerm
+	{
+		'amend': 1,
+		'cancel': 1,
+		'create': 1,
+		'doctype': u'DocPerm',
+		'permlevel': 0,
+		'role': u'Sales User',
+		'submit': 1,
+		'write': 1
+	},
+
+	# DocPerm
+	{
+		'amend': 0,
+		'cancel': 0,
+		'create': 0,
+		'doctype': u'DocPerm',
+		'permlevel': 1,
+		'role': u'Sales User',
+		'submit': 0,
+		'write': 0
+	},
+
+	# DocPerm
+	{
+		'cancel': 0,
+		'create': 0,
+		'doctype': u'DocPerm',
+		'permlevel': 0,
+		'role': u'Accounts User',
+		'submit': 0,
+		'write': 0
+	},
+
+	# DocPerm
+	{
+		'doctype': u'DocPerm',
+		'permlevel': 1,
+		'role': u'Accounts User'
+	},
+
+	# DocPerm
+	{
+		'doctype': u'DocPerm',
+		'match': u'customer_name',
+		'permlevel': 0,
+		'role': u'Customer'
 	},
 
 	# DocPerm
 	{
 		'doctype': u'DocPerm',
 		'permlevel': 2,
-		'role': u'All'
+		'role': u'All',
+		'write': 1
 	},
 
 	# DocField
@@ -340,6 +384,7 @@
 	# DocField
 	{
 		'allow_on_submit': 1,
+		'colour': u'White:FFF',
 		'doctype': u'DocField',
 		'fieldname': u'delivery_note_details',
 		'fieldtype': u'Table',
@@ -355,6 +400,16 @@
 	# DocField
 	{
 		'doctype': u'DocField',
+		'fieldname': u'sales_bom_help',
+		'fieldtype': u'HTML',
+		'label': u'Sales BOM Help',
+		'permlevel': 0,
+		'print_hide': 1
+	},
+
+	# DocField
+	{
+		'doctype': u'DocField',
 		'fieldname': u'section_break0',
 		'fieldtype': u'Section Break',
 		'options': u'Simple',
diff --git a/erpnext/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.txt b/erpnext/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.txt
index 51001fc..db512c6 100644
--- a/erpnext/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.txt
+++ b/erpnext/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.txt
@@ -3,9 +3,9 @@
 
 	# These values are common in all dictionaries
 	{
-		'creation': '2012-04-13 11:56:35',
+		'creation': '2012-06-11 12:10:10',
 		'docstatus': 0,
-		'modified': '2012-05-09 12:55:23',
+		'modified': '2012-07-10 12:05:31',
 		'modified_by': u'Administrator',
 		'owner': u'Administrator'
 	},
@@ -111,7 +111,7 @@
 		'oldfieldname': u'warehouse',
 		'oldfieldtype': u'Link',
 		'options': u'Warehouse',
-		'permlevel': 1
+		'permlevel': 0
 	},
 
 	# DocField
diff --git a/erpnext/stock/doctype/stock_ledger/stock_ledger.py b/erpnext/stock/doctype/stock_ledger/stock_ledger.py
index 0cb4b96..42ad6f6 100644
--- a/erpnext/stock/doctype/stock_ledger/stock_ledger.py
+++ b/erpnext/stock/doctype/stock_ledger/stock_ledger.py
@@ -51,19 +51,16 @@
 		self.doclist = doclist
 
 
-	# -----------------
-	# scrub serial nos
-	# -----------------
-	def scrub_serial_nos(self, obj):
-		for d in getlist(obj.doclist, obj.fname):
+	def scrub_serial_nos(self, obj, table_name = ''):
+		if not table_name:
+			table_name = obj.fname
+		
+		for d in getlist(obj.doclist, table_name):
 			if d.serial_no:
 				d.serial_no = d.serial_no.replace(',', '\n')
 				d.save()
 
 
-	# -----------------------------
-	# validate serial no warehouse
-	# -----------------------------
 	def validate_serial_no_warehouse(self, obj, fname):
 		for d in getlist(obj.doclist, fname):
 			wh = d.warehouse or d.s_warehouse
@@ -80,10 +77,8 @@
 						msgprint("Serial No : %s for Item : %s doesn't exists in Warehouse : %s" % (s, d.item_code, wh), raise_exception = 1)
 
 
-	# ------------------------------------
-	# check whether serial no is required
-	# ------------------------------------
 	def validate_serial_no(self, obj, fname):
+		"""check whether serial no is required"""
 		for d in getlist(obj.doclist, fname):
 			is_stock_item = get_value('Item', d.item_code, 'is_stock_item')
 			ar_required = get_value('Item', d.item_code, 'has_serial_no')
@@ -101,18 +96,10 @@
 				msgprint("Rejected serial no is mandatory for rejected qty of item: "+ d.item_code, raise_exception = 1)
 				
 				
-
-
-
-	# -------------------
-	# get serial no list
-	# -------------------
 	def get_sr_no_list(self, sr_nos, qty = 0, item_code = ''):
 		return get_sr_no_list(sr_nos, qty, item_code)
 
-	# ---------------------
-	# set serial no values
-	# ---------------------
+
 	def set_pur_serial_no_values(self, obj, serial_no, d, s, new_rec):
 		item_details = 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)
@@ -143,9 +130,6 @@
 		s.save(new_rec)
 
 
-	# ----------------------------------
-	# update serial no purchase details
-	# ----------------------------------
 	def update_serial_purchase_details(self, obj, d, serial_no, is_submit, purpose = ''):
 		exists = sql("select name, status, docstatus from `tabSerial No` where name = '%s'" % (serial_no))
 		if is_submit:
@@ -168,9 +152,6 @@
 				sql("update `tabSerial No` set docstatus = 2, status = 'Not in Use', purchase_document_type = '', purchase_document_no = '', purchase_date = null, purchase_rate = 0, supplier = null, supplier_name = '', supplier_address = '', warehouse = '' where name = '%s'" % serial_no)
 
 
-	# -------------------------------
-	# check whether serial no exists
-	# -------------------------------
 	def check_serial_no_exists(self, serial_no, item_code):
 		chk = sql("select name, status, docstatus, item_code from `tabSerial No` where name = %s", (serial_no), as_dict=1)
 		if not chk:
@@ -182,9 +163,7 @@
 		elif chk and chk[0]['status'] == 'Delivered':
 			msgprint("Serial No: %s of Item : %s is already delivered." % (serial_no, item_code), raise_exception = 1)
 
-	# ---------------------
-	# set serial no values
-	# ---------------------
+
 	def set_delivery_serial_no_values(self, obj, serial_no):
 		s = Document('Serial No', serial_no)
 		s.delivery_document_type =	 obj.doc.doctype
@@ -203,9 +182,6 @@
 		s.save()
 
 
-	# ----------------------------------
-	# update serial no delivery details
-	# ----------------------------------
 	def update_serial_delivery_details(self, obj, d, serial_no, is_submit):
 		if is_submit:
 			self.check_serial_no_exists(serial_no, d.item_code)
@@ -214,9 +190,6 @@
 			sql("update `tabSerial No` set docstatus = 0, status = 'In Store', delivery_document_type = '', delivery_document_no = '', delivery_date = null, customer = null, customer_name = '', delivery_address = '', territory = null where name = '%s'" % (serial_no))
 
 
-	# ---------------------
-	# update serial record
-	# ---------------------
 	def update_serial_record(self, obj, fname, is_submit = 1, is_incoming = 0):
 		import datetime
 		for d in getlist(obj.doclist, fname):
@@ -235,11 +208,6 @@
 					self.update_serial_purchase_details(obj, d, a, is_submit)
 				
 				
-
-
-	# -------------
-	# update stock
-	# -------------
 	def update_stock(self, values, is_amended = 'No'):
 		for v in values:
 			sle_id, serial_nos = '', ''
@@ -261,9 +229,6 @@
 				v["posting_date"], sle_id, v["posting_time"], '', v["is_cancelled"],v["voucher_type"],v["voucher_no"], is_amended)
 
 
-	# -----------
-	# make entry
-	# -----------
 	def make_entry(self, args):
 		sle = Document(doctype = 'Stock Ledger Entry')
 		for k in args.keys():