[fix] [conflict]
diff --git a/controllers/selling_controller.py b/controllers/selling_controller.py
index 0215dbd..61bd032 100644
--- a/controllers/selling_controller.py
+++ b/controllers/selling_controller.py
@@ -358,4 +358,4 @@
 				webnotes.throw(_("Item is neither Sales nor Service Item") + ": " + d.item_code)
 			if d.income_account and not item.default_income_account:
 				webnotes.conn.set_value("Item", d.item_code, "default_income_account", 
-					d.income_account)
\ No newline at end of file
+					d.income_account)
diff --git a/selling/doctype/quotation/quotation.py b/selling/doctype/quotation/quotation.py
index cf82407..dbc496b 100644
--- a/selling/doctype/quotation/quotation.py
+++ b/selling/doctype/quotation/quotation.py
@@ -59,9 +59,37 @@
 		self.validate_for_items()
 		self.validate_uom_is_integer("stock_uom", "qty")
 
+<<<<<<< HEAD
 	def update_opportunity(self):
 		for opportunity in self.doclist.get_distinct_values("prevdoc_docname"):
 			webnotes.bean("Opportunity", opportunity).get_controller().set_status(update=True)
+=======
+		sales_com_obj = get_obj('Sales Common')
+		sales_com_obj.check_active_sales_items(self)
+		sales_com_obj.validate_max_discount(self,'quotation_details')
+
+	def on_update(self):
+		# Set Quotation Status
+		webnotes.conn.set(self.doc, 'status', 'Draft')
+	
+	#update enquiry
+	#------------------
+	def update_enquiry(self, flag):
+		prevdoc=''
+		for d in getlist(self.doclist, 'quotation_details'):
+			if d.prevdoc_docname:
+				prevdoc = d.prevdoc_docname
+		
+		if prevdoc:
+			if flag == 'submit': #on submit
+				sql("update `tabOpportunity` set status = 'Quotation Sent' where name = %s", prevdoc)
+			elif flag == 'cancel': #on cancel
+				sql("update `tabOpportunity` set status = 'Open' where name = %s", prevdoc)
+			elif flag == 'order lost': #order lost
+				sql("update `tabOpportunity` set status = 'Opportunity Lost' where name=%s", prevdoc)
+			elif flag == 'order confirm': #order confirm
+				sql("update `tabOpportunity` set status='Order Confirmed' where name=%s", prevdoc)
+>>>>>>> 8f72d9f679fca88be7710e31b6cfa66defcde81a
 	
 	# declare as order lost
 	#-------------------------
diff --git a/selling/doctype/sales_common/sales_common.py b/selling/doctype/sales_common/sales_common.py
new file mode 100644
index 0000000..ad626da
--- /dev/null
+++ b/selling/doctype/sales_common/sales_common.py
@@ -0,0 +1,348 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import webnotes
+
+from webnotes.utils import cint, cstr, flt
+from webnotes.model.doc import addchild
+from webnotes.model.bean import getlist
+from webnotes.model.code import get_obj
+from webnotes import msgprint, _
+from setup.utils import get_company_currency
+
+get_value = webnotes.conn.get_value
+
+from utilities.transaction_base import TransactionBase
+
+class DocType(TransactionBase):
+	def __init__(self,d,dl):
+		self.doc, self.doclist = d, dl
+
+
+	def get_contact_details(self, obj = '', primary = 0):
+		cond = " and contact_name = '"+cstr(obj.doc.contact_person)+"'"
+		if primary: cond = " and is_primary_contact = 'Yes'"
+		contact = webnotes.conn.sql("select contact_name, contact_no, email_id, contact_address from `tabContact` where customer = '%s' and docstatus != 2 %s" %(obj.doc.customer, cond), as_dict = 1)
+		if not contact:
+			return
+		c = contact[0]
+		obj.doc.contact_person = c['contact_name'] or ''
+		obj.doc.contact_no = c['contact_no'] or ''
+		obj.doc.email_id = c['email_id'] or ''
+		obj.doc.customer_mobile_no = c['contact_no'] or ''
+		if c['contact_address']:
+			obj.doc.customer_address = c['contact_address']
+
+	def get_invoice_details(self, obj = ''):
+		if obj.doc.company:
+			acc_head = webnotes.conn.sql("select name from `tabAccount` where name = '%s' and docstatus != 2" % (cstr(obj.doc.customer) + " - " + webnotes.conn.get_value('Company', obj.doc.company, 'abbr')))
+			obj.doc.debit_to = acc_head and acc_head[0][0] or ''
+			
+	def get_tax_details(self, item_code, obj):
+		import json
+		tax = webnotes.conn.sql("select tax_type, tax_rate from `tabItem Tax` where parent = %s" , item_code)
+		t = {}
+		for x in tax: t[x[0]] = flt(x[1])
+		ret = {
+			'item_tax_rate'		:	tax and json.dumps(t) or ''
+		}
+		return ret
+
+	def get_serial_details(self, serial_no, obj):
+		import json
+		item = webnotes.conn.sql("select item_code, make, label,brand, description from `tabSerial No` where name = '%s' and docstatus != 2" %(serial_no), as_dict=1)
+		tax = webnotes.conn.sql("select tax_type, tax_rate from `tabItem Tax` where parent = %s" , item[0]['item_code'])
+		t = {}
+		for x in tax: t[x[0]] = flt(x[1])
+		ret = {
+			'item_code'				: item and item[0]['item_code'] or '',
+			'make'						 : item and item[0]['make'] or '',
+			'label'						: item and item[0]['label'] or '',
+			'brand'						: item and item[0]['brand'] or '',
+			'description'			: item and item[0]['description'] or '',
+			'item_tax_rate'		: json.dumps(t)
+		}
+		return ret
+		
+	# To verify whether rate entered in details table does not exceed max discount %
+	# =======================================================================================
+	def validate_max_discount(self,obj, detail_table):
+		for d in getlist(obj.doclist, detail_table):
+			discount = webnotes.conn.sql("select max_discount from tabItem where name = '%s'" %(d.item_code),as_dict = 1)
+			if discount and discount[0]['max_discount'] and (flt(d.adj_rate)>flt(discount[0]['max_discount'])):
+				msgprint("You cannot give more than " + cstr(discount[0]['max_discount']) + " % discount on Item Code : "+cstr(d.item_code))
+				raise Exception
+			
+	# Get Tax rate if account type is TAX
+	# =========================================================================
+	def get_rate(self, arg):
+		arg = eval(arg)
+		rate = webnotes.conn.sql("select account_type, tax_rate from `tabAccount` where name = '%s' and docstatus != 2" %(arg['account_head']), as_dict=1)
+		ret = {'rate' : 0}
+		if arg['charge_type'] == 'Actual' and rate[0]['account_type'] == 'Tax':
+			msgprint("You cannot select ACCOUNT HEAD of type TAX as your CHARGE TYPE is 'ACTUAL'")
+			ret = {
+				'account_head'	:	''
+			}
+		elif rate[0]['account_type'] in ['Tax', 'Chargeable'] and not arg['charge_type'] == 'Actual':
+			ret = {
+				'rate'	:	rate and flt(rate[0]['tax_rate']) or 0
+			}
+		return ret
+
+
+	def get_item_list(self, obj, is_stopped=0):
+		"""get item list"""
+		il = []
+		for d in getlist(obj.doclist, obj.fname):
+			reserved_warehouse = ""
+			reserved_qty_for_main_item = 0
+			
+			if obj.doc.doctype == "Sales Order":
+				if (webnotes.conn.get_value("Item", d.item_code, "is_stock_item") == 'Yes' or 
+					self.has_sales_bom(d.item_code)) and not d.reserved_warehouse:
+						webnotes.throw(_("Please enter Reserved Warehouse for item ") + 
+							d.item_code + _(" as it is stock Item or packing item"))
+				reserved_warehouse = d.reserved_warehouse
+				if flt(d.qty) > flt(d.delivered_qty):
+					reserved_qty_for_main_item = flt(d.qty) - flt(d.delivered_qty)
+				
+			if obj.doc.doctype == "Delivery Note" and d.prevdoc_doctype == 'Sales Order':
+				# 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
+				
+				already_delivered_qty = self.get_already_delivered_qty(obj.doc.name, 
+					d.prevdoc_docname, d.prevdoc_detail_docname)
+				so_qty, reserved_warehouse = self.get_so_qty_and_warehouse(d.prevdoc_detail_docname)
+				
+				if already_delivered_qty + d.qty > so_qty:
+					reserved_qty_for_main_item = -(so_qty - already_delivered_qty)
+				else:
+					reserved_qty_for_main_item = -flt(d.qty)
+
+			if self.has_sales_bom(d.item_code):
+				for p in getlist(obj.doclist, 'packing_details'):
+					if p.parent_detail_docname == d.name and p.parent_item == d.item_code:
+						# the packing details table's qty is already multiplied with parent's qty
+						il.append(webnotes._dict({
+							'warehouse': p.warehouse,
+							'reserved_warehouse': reserved_warehouse,
+							'item_code': p.item_code,
+							'qty': flt(p.qty),
+							'reserved_qty': (flt(p.qty)/flt(d.qty)) * reserved_qty_for_main_item,
+							'uom': p.uom,
+							'batch_no': cstr(p.batch_no).strip(),
+							'serial_no': cstr(p.serial_no).strip(),
+							'name': d.name
+						}))
+			else:
+				il.append(webnotes._dict({
+					'warehouse': d.warehouse,
+					'reserved_warehouse': reserved_warehouse,
+					'item_code': d.item_code,
+					'qty': d.qty,
+					'reserved_qty': reserved_qty_for_main_item,
+					'uom': d.stock_uom,
+					'batch_no': cstr(d.batch_no).strip(),
+					'serial_no': cstr(d.serial_no).strip(),
+					'name': d.name
+				}))
+		return il
+
+	def get_already_delivered_qty(self, dn, so, so_detail):
+		qty = webnotes.conn.sql("""select sum(qty) from `tabDelivery Note Item` 
+			where prevdoc_detail_docname = %s and docstatus = 1 
+			and prevdoc_doctype = 'Sales Order' and prevdoc_docname = %s 
+			and parent != %s""", (so_detail, so, dn))
+		return qty and flt(qty[0][0]) or 0.0
+
+	def get_so_qty_and_warehouse(self, so_detail):
+		so_item = webnotes.conn.sql("""select qty, reserved_warehouse from `tabSales Order Item`
+			where name = %s and docstatus = 1""", so_detail, as_dict=1)
+		so_qty = so_item and flt(so_item[0]["qty"]) or 0.0
+		so_warehouse = so_item and so_item[0]["reserved_warehouse"] or ""
+		return so_qty, so_warehouse
+
+	def has_sales_bom(self, item_code):
+		return webnotes.conn.sql("select name from `tabSales BOM` where new_item_code=%s and docstatus != 2", item_code)
+	
+	def get_sales_bom_items(self, item_code):
+		return webnotes.conn.sql("""select t1.item_code, t1.qty, t1.uom 
+			from `tabSales BOM Item` t1, `tabSales BOM` t2 
+			where t2.new_item_code=%s and t1.parent = t2.name""", item_code, as_dict=1)
+
+	def get_packing_item_details(self, item):
+		return webnotes.conn.sql("select item_name, description, stock_uom from `tabItem` where name = %s", item, as_dict = 1)[0]
+
+	def get_bin_qty(self, item, warehouse):
+		det = webnotes.conn.sql("select actual_qty, projected_qty from `tabBin` where item_code = '%s' and warehouse = '%s'" % (item, warehouse), as_dict = 1)
+		return det and det[0] or ''
+
+	def update_packing_list_item(self,obj, packing_item_code, qty, warehouse, line):
+		bin = self.get_bin_qty(packing_item_code, warehouse)
+		item = self.get_packing_item_details(packing_item_code)
+
+		# check if exists
+		exists = 0
+		for d in getlist(obj.doclist, 'packing_details'):
+			if d.parent_item == line.item_code and d.item_code == packing_item_code and d.parent_detail_docname == line.name:
+				pi, exists = d, 1
+				break
+
+		if not exists:
+			pi = addchild(obj.doc, 'packing_details', 'Delivery Note Packing Item', 
+				obj.doclist)
+
+		pi.parent_item = line.item_code
+		pi.item_code = packing_item_code
+		pi.item_name = item['item_name']
+		pi.parent_detail_docname = line.name
+		pi.description = item['description']
+		pi.uom = item['stock_uom']
+		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.prevdoc_doctype = line.prevdoc_doctype
+		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
+		
+		# saved, since this function is called on_update of delivery note
+		pi.save()
+		
+		self.packing_list_idx += 1
+
+
+	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):
+			warehouse = fname == "sales_order_details" and d.reserved_warehouse or d.warehouse
+			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)
+
+				if [d.item_code, d.name] not in parent_items:
+					parent_items.append([d.item_code, d.name])
+				
+		obj.doclist = self.cleanup_packing_list(obj, parent_items)
+		
+		return obj.doclist
+		
+	def cleanup_packing_list(self, obj, parent_items):
+		"""Remove all those child items which are no longer present in main item table"""
+		delete_list = []
+		for d in getlist(obj.doclist, 'packing_details'):
+			if [d.parent_item, d.parent_detail_docname] not in parent_items:
+				# mark for deletion from doclist
+				delete_list.append(d.name)
+
+		if not delete_list:
+			return obj.doclist
+		
+		# delete from doclist
+		obj.doclist = webnotes.doclist(filter(lambda d: d.name not in delete_list, obj.doclist))
+		
+		# delete from db
+		webnotes.conn.sql("""\
+			delete from `tabDelivery Note Packing Item`
+			where name in (%s)"""
+			% (", ".join(["%s"] * len(delete_list))),
+			tuple(delete_list))
+			
+		return obj.doclist
+		
+
+	def get_month(self,date):
+		"""Get month based on date (required in sales person and sales partner)"""
+		month_list = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
+		month_idx = cint(cstr(date).split('-')[1])-1
+		return month_list[month_idx]
+		
+		
+	# **** Check for Stop SO as no transactions can be made against Stopped SO. Need to unstop it. ***
+	def check_stop_sales_order(self,obj):
+		for d in getlist(obj.doclist,obj.fname):
+			ref_doc_name = ''
+			if d.fields.has_key('prevdoc_docname') and d.prevdoc_docname and d.prevdoc_doctype == 'Sales Order':
+				ref_doc_name = d.prevdoc_docname
+			elif d.fields.has_key('sales_order') and d.sales_order and not d.delivery_note:
+				ref_doc_name = d.sales_order
+			if ref_doc_name:
+				so_status = webnotes.conn.sql("select status from `tabSales Order` where name = %s",ref_doc_name)
+				so_status = so_status and so_status[0][0] or ''
+				if so_status == 'Stopped':
+					msgprint("You cannot do any transaction against Sales Order : '%s' as it is Stopped." %(ref_doc_name))
+					raise Exception
+
+	def check_active_sales_items(self,obj):
+		for d in getlist(obj.doclist, obj.fname):
+			if d.item_code:
+				item = webnotes.conn.sql("""select docstatus, is_sales_item, 
+					is_service_item, default_income_account from tabItem where name = %s""", 
+					d.item_code, as_dict=True)[0]
+				if item.is_sales_item == 'No' and item.is_service_item == 'No':
+					msgprint("Item : '%s' is neither Sales nor Service Item" % (d.item_code))
+					raise Exception
+				if d.income_account and not item.default_income_account:
+					webnotes.conn.set_value("Item", d.item_code, "default_income_account", d.income_account)
+
+
+	def check_credit(self,obj,grand_total):
+		acc_head = webnotes.conn.sql("select name from `tabAccount` where company = '%s' and master_name = '%s'"%(obj.doc.company, obj.doc.customer))
+		if acc_head:
+			tot_outstanding = 0
+			dbcr = webnotes.conn.sql("""select sum(debit), sum(credit) from `tabGL Entry` 
+				where account = %s""", acc_head[0][0])
+			if dbcr:
+				tot_outstanding = flt(dbcr[0][0])-flt(dbcr[0][1])
+
+			exact_outstanding = flt(tot_outstanding) + flt(grand_total)
+			get_obj('Account',acc_head[0][0]).check_credit_limit(acc_head[0][0], obj.doc.company, exact_outstanding)
+
+	def get_prevdoc_date(self, obj):
+		for d in getlist(obj.doclist, obj.fname):
+			if d.prevdoc_doctype and d.prevdoc_docname:
+				if d.prevdoc_doctype in ["Sales Invoice", "Delivery Note"]:
+					date_field = "posting_date"
+				else:
+					date_field = "transaction_date"
+					
+				d.prevdoc_date = webnotes.conn.get_value(d.prevdoc_doctype, 
+					d.prevdoc_docname, date_field)
+
+def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
+	from controllers.queries import get_match_cond
+
+	if filters.has_key('warehouse'):
+		return webnotes.conn.sql("""select batch_no from `tabStock Ledger Entry` sle 
+				where item_code = '%(item_code)s' 
+					and warehouse = '%(warehouse)s' 
+					and batch_no like '%(txt)s' 
+					and exists(select * from `tabBatch` 
+							where name = sle.batch_no 
+								and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s') 
+								and docstatus != 2) 
+					%(mcond)s
+				group by batch_no having sum(actual_qty) > 0 
+				order by batch_no desc 
+				limit %(start)s, %(page_len)s """ % {'item_code': filters['item_code'], 
+					'warehouse': filters['warehouse'], 'posting_date': filters['posting_date'], 
+					'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype, searchfield), 
+					'start': start, 'page_len': page_len})
+	else:
+		return webnotes.conn.sql("""select name from tabBatch 
+				where docstatus != 2 
+					and item = '%(item_code)s' 
+					and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s')
+					and name like '%(txt)s' 
+					%(mcond)s 
+				order by name desc 
+				limit %(start)s, %(page_len)s""" % {'item_code': filters['item_code'], 
+				'posting_date': filters['posting_date'], 'txt': "%%%s%%" % txt, 
+				'mcond':get_match_cond(doctype, searchfield),'start': start, 
+				'page_len': page_len})
diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py
index a9ab827..7bad121 100644
--- a/selling/doctype/sales_order/sales_order.py
+++ b/selling/doctype/sales_order/sales_order.py
@@ -110,10 +110,10 @@
 		self.validate_uom_is_integer("stock_uom", "qty")
 		self.validate_for_items()
 		self.validate_warehouse()
-				
+
 		from stock.doctype.packed_item.packed_item import make_packing_list
 		self.doclist = make_packing_list(self,'sales_order_details')
-		
+
 		self.validate_with_previous_doc()
 				
 		if not self.doc.status:
@@ -417,4 +417,4 @@
 			}
 		}, target_doclist)
 	
-		return [d.fields for d in doclist]
\ No newline at end of file
+		return [d.fields for d in doclist]
diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py
index 8d325f4..4c8068a 100644
--- a/stock/doctype/delivery_note/delivery_note.py
+++ b/stock/doctype/delivery_note/delivery_note.py
@@ -69,11 +69,8 @@
 		self.check_stop_sales_order("against_sales_order")
 		self.validate_for_items()
 		self.validate_warehouse()
-		self.validate_uom_is_integer("stock_uom", "qty")		
-
-		# Set actual qty for each item in selected warehouse
-		self.update_current_stock()
-		
+		self.validate_uom_is_integer("stock_uom", "qty")
+		self.update_current_stock()		
 		self.validate_with_previous_doc()
 		
 		self.doc.status = 'Draft'
diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py
index 0e05a88..665486f 100644
--- a/stock/doctype/stock_entry/stock_entry.py
+++ b/stock/doctype/stock_entry/stock_entry.py
@@ -366,7 +366,6 @@
 					
 	def get_item_details(self, arg):
 		arg = json.loads(arg)
-
 		item = webnotes.conn.sql("""select stock_uom, description, item_name, 
 			purchase_account, cost_center from `tabItem` 
 			where name = %s and (ifnull(end_of_life,'')='' or end_of_life ='0000-00-00'