Merge branch 'master' of github.com:webnotes/erpnext
diff --git a/accounts/doctype/journal_voucher/journal_voucher.py b/accounts/doctype/journal_voucher/journal_voucher.py
index 8b54f0f..9b1ca7a 100644
--- a/accounts/doctype/journal_voucher/journal_voucher.py
+++ b/accounts/doctype/journal_voucher/journal_voucher.py
@@ -375,9 +375,9 @@
 		(filters["account"], "%%%s%%" % txt, start, page_len))
 		
 def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
-	return webnotes.conn.sql("""select name, posting_date, user_remark 
+	return webnotes.conn.sql("""select jv.name, jv.posting_date, jv.user_remark 
 		from `tabJournal Voucher` jv, `tabJournal Voucher Detail` jv_detail 
-		where jv_detail.parent = jv.name and jv_detail.account = %s and docstatus = 1 
+		where jv_detail.parent = jv.name and jv_detail.account = %s and jv.docstatus = 1 
 		and jv.%s like %s order by jv.name desc limit %s, %s""" % 
 		("%s", searchfield, "%s", "%s", "%s"), 
 		(filters["account"], "%%%s%%" % txt, start, page_len))
\ No newline at end of file
diff --git a/selling/doctype/lead/lead.txt b/selling/doctype/lead/lead.txt
index ae8c6c4..e162551 100644
--- a/selling/doctype/lead/lead.txt
+++ b/selling/doctype/lead/lead.txt
@@ -2,7 +2,7 @@
  {
   "creation": "2013-01-28 17:07:01", 
   "docstatus": 0, 
-  "modified": "2013-03-26 13:07:11", 
+  "modified": "2013-03-26 14:05:01", 
   "modified_by": "Administrator", 
   "owner": "Administrator"
  }, 
@@ -118,6 +118,18 @@
   "search_index": 0
  }, 
  {
+  "depends_on": "eval:doc.source == 'Customer'", 
+  "description": "Source of th", 
+  "doctype": "DocField", 
+  "fieldname": "customer", 
+  "fieldtype": "Link", 
+  "hidden": 0, 
+  "label": "From Customer", 
+  "oldfieldname": "customer", 
+  "oldfieldtype": "Link", 
+  "options": "Customer"
+ }, 
+ {
   "depends_on": "eval:doc.source == 'Campaign'", 
   "description": "Enter campaign name if the source of lead is campaign.", 
   "doctype": "DocField", 
@@ -145,37 +157,10 @@
  }, 
  {
   "doctype": "DocField", 
-  "fieldname": "sb8", 
+  "fieldname": "contact_info", 
   "fieldtype": "Section Break", 
-  "label": "Lead Details"
- }, 
- {
-  "depends_on": "eval:doc.source == 'Existing Customer'", 
-  "description": "Source of th", 
-  "doctype": "DocField", 
-  "fieldname": "customer", 
-  "fieldtype": "Link", 
-  "hidden": 0, 
-  "label": "From Customer", 
-  "oldfieldname": "customer", 
-  "oldfieldtype": "Link", 
-  "options": "Customer"
- }, 
- {
-  "doctype": "DocField", 
-  "fieldname": "column_break1", 
-  "fieldtype": "Column Break", 
-  "width": "50%"
- }, 
- {
-  "doctype": "DocField", 
-  "fieldname": "type", 
-  "fieldtype": "Select", 
-  "in_filter": 1, 
-  "label": "Lead Type", 
-  "oldfieldname": "type", 
-  "oldfieldtype": "Select", 
-  "options": "\nClient\nChannel Partner\nConsultant"
+  "label": "Contact Info", 
+  "oldfieldtype": "Column Break"
  }, 
  {
   "doctype": "DocField", 
@@ -187,13 +172,6 @@
  }, 
  {
   "doctype": "DocField", 
-  "fieldname": "contact_info", 
-  "fieldtype": "Section Break", 
-  "label": "Contact Info", 
-  "oldfieldtype": "Column Break"
- }, 
- {
-  "doctype": "DocField", 
   "fieldname": "phone", 
   "fieldtype": "Data", 
   "label": "Phone", 
@@ -308,6 +286,16 @@
   "oldfieldtype": "Section Break"
  }, 
  {
+  "doctype": "DocField", 
+  "fieldname": "type", 
+  "fieldtype": "Select", 
+  "in_filter": 1, 
+  "label": "Lead Type", 
+  "oldfieldname": "type", 
+  "oldfieldtype": "Select", 
+  "options": "\nClient\nChannel Partner\nConsultant"
+ }, 
+ {
   "default": "__user", 
   "doctype": "DocField", 
   "fieldname": "lead_owner", 
diff --git a/stock/doctype/item/test_item.py b/stock/doctype/item/test_item.py
index f31f245..dbbeecc 100644
--- a/stock/doctype/item/test_item.py
+++ b/stock/doctype/item/test_item.py
@@ -146,4 +146,23 @@
 		"is_sub_contracted_item": "No",
 		"stock_uom": "_Test UOM"
 	}],
+	[{
+		"doctype": "Item",
+		"item_code": "_Test Serialized Item",
+		"item_name": "_Test Serialized Item",
+		"description": "_Test Serialized Item",
+		"item_group": "_Test Item Group Desktops",
+		"is_stock_item": "Yes",
+		"is_asset_item": "No",
+		"has_batch_no": "No",
+		"has_serial_no": "Yes",
+		"is_purchase_item": "Yes",
+		"is_sales_item": "Yes",
+		"is_service_item": "No",
+		"is_sample_item": "No",
+		"inspection_required": "No",
+		"is_pro_applicable": "No",
+		"is_sub_contracted_item": "No",
+		"stock_uom": "_Test UOM"
+	}],
 ]
\ No newline at end of file
diff --git a/stock/doctype/serial_no/serial_no.py b/stock/doctype/serial_no/serial_no.py
index 00f2de7..5b15977 100644
--- a/stock/doctype/serial_no/serial_no.py
+++ b/stock/doctype/serial_no/serial_no.py
@@ -19,14 +19,11 @@
 
 from webnotes.utils import cint, getdate, nowdate
 import datetime
-
-sql = webnotes.conn.sql
-msgprint = webnotes.msgprint
+from webnotes import msgprint, _
 	
+from controllers.stock_controller import StockController
 
-from utilities.transaction_base import TransactionBase
-
-class DocType(TransactionBase):
+class DocType(StockController):
 	def __init__(self, doc, doclist=[]):
 		self.doc = doc
 		self.doclist = doclist
@@ -54,21 +51,14 @@
 		"""
 			Validate whether serial no is required for this item
 		"""
-		item = sql("select name, has_serial_no from tabItem where name = '%s'" % self.doc.item_code)
+		item = webnotes.conn.sql("select name, has_serial_no from tabItem where name = '%s'" % self.doc.item_code)
 		if not item:
 			msgprint("Item is not exists in the system", raise_exception=1)
 		elif item[0][1] == 'No':
 			msgprint("To proceed please select 'Yes' in 'Has Serial No' in Item master: '%s'" % self.doc.item_code, raise_exception=1)
 			
 
-	# ---------
-	# validate
-	# ---------
 	def validate(self):
-		# import utilities
-		# utilities.validate_status(self.doc.status, ["In Store", "Delivered", 
-		# 	"Not in Use", "Purchase Returned"])
-
 		self.validate_warranty_status()
 		self.validate_amc_status()
 		self.validate_warehouse()
@@ -77,10 +67,12 @@
 	def on_update(self):
 		if self.doc.warehouse and self.doc.status == 'In Store' \
 				and cint(self.doc.sle_exists) == 0 and \
-				not sql("""select name from `tabStock Ledger Entry` where serial_no = %s and 
-				 	ifnull(is_cancelled, 'No') = 'No'""", self.doc.name):
+				not webnotes.conn.sql("""select name from `tabStock Ledger Entry` 
+				where serial_no = %s and ifnull(is_cancelled, 'No') = 'No'""", self.doc.name):
 			self.make_stock_ledger_entry(1)
 			webnotes.conn.set(self.doc, 'sle_exists', 1)
+			
+			self.make_gl_entries()
 
 	def make_stock_ledger_entry(self, qty):
 		from webnotes.model.code import get_obj
@@ -105,15 +97,13 @@
 		get_obj('Stock Ledger').update_stock(values)
 
 
-	# ---------
-	# on trash
-	# ---------
 	def on_trash(self):
 		if self.doc.status == 'Delivered':
 			msgprint("Cannot trash Serial No : %s as it is already Delivered" % (self.doc.name), raise_exception = 1)
 		elif self.doc.status == 'In Store': 
 			webnotes.conn.set(self.doc, 'status', 'Not in Use')
 			self.make_stock_ledger_entry(-1)
+			self.make_gl_entries(cancel=True)
 
 
 	def on_cancel(self):
@@ -121,6 +111,7 @@
 
 	def on_restore(self):
 		self.make_stock_ledger_entry(1)
+		self.make_gl_entries()
 	
 	def on_rename(self, new, old):
 		"""rename serial_no text fields"""
@@ -135,7 +126,16 @@
 					where name=%s""" % (dt[0], '%s', '%s'),
 					('\n'.join(serial_nos), item[0]))
 
+	def make_gl_entries(self, cancel=False):
+		if not cint(webnotes.defaults.get_global_default("auto_inventory_accounting")):
+			return
 				
-				
+		from accounts.general_ledger import make_gl_entries
+		against_stock_account = self.get_company_default("stock_adjustment_account")
+		gl_entries = self.get_gl_entries_for_stock(against_stock_account, self.doc.purchase_rate)
+		
+		for entry in gl_entries:
+			entry["posting_date"] = self.doc.purchase_date
 			
-			
\ No newline at end of file
+		if gl_entries:
+			make_gl_entries(gl_entries, cancel)
\ No newline at end of file
diff --git a/stock/doctype/serial_no/test_serial_no.py b/stock/doctype/serial_no/test_serial_no.py
index ef20de8..fb27aa9 100644
--- a/stock/doctype/serial_no/test_serial_no.py
+++ b/stock/doctype/serial_no/test_serial_no.py
@@ -1,93 +1,102 @@
 # ERPNext - web based ERP (http://erpnext.com)
-# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
-# 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-# 
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
+# For license information, please see license.txt
 
 from __future__ import unicode_literals
-import unittest
-import webnotes
-from webnotes.tests import insert_test_data
-
-company = webnotes.conn.get_default("company")
+import webnotes, unittest
 
 class TestSerialNo(unittest.TestCase):
-	def setUp(self):
-		webnotes.conn.begin()
-		self.insert_test_data()
-
-	def tearDown(self):
-		# print "Message Log:", "\n--\n".join(webnotes.message_log)
-		# print "Debug Log:", "\n--\n".join(webnotes.debug_log)
-		webnotes.conn.rollback()
+	def test_aii_gl_entries_for_serial_no_in_store(self):
+		webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
 		
-	def test_serialized_stock_entry(self):
-		data = [["2012-01-01", "01:00", "10001", 400, 400],
-			["2012-01-01", "03:00", "10002", 500, 700],
-			["2012-01-01", "04:00", "10003", 700, 700],
-			["2012-01-01", "05:00", "10004", 1200, 800],
-			["2012-01-01", "05:00", "10005", 800, 800],
-			["2012-01-01", "02:00", "10006", 1200, 800],
-			["2012-01-01", "06:00", "10007", 1500, 900]]
-		for d in data:
-			webnotes.bean([{
-				"doctype": "Serial No",
-				"item_code": "Nebula 8",
-				"warehouse": "Default Warehouse", 
-				"status": "In Store",
-				"sle_exists": 0,
-				"purchase_date": d[0],
-				"purchase_time": d[1],
-				"serial_no": d[2],
-				"purchase_rate": d[3],
-				"company": company,
-			}]).insert()
+		sr = webnotes.bean(copy=test_records[0])
+		sr.doc.serial_no = "_Test Serial No 1"
+		sr.insert()
+		
+		stock_in_hand_account = webnotes.conn.get_value("Company", "_Test Company", 
+			"stock_in_hand_account")
+		against_stock_account = webnotes.conn.get_value("Company", "_Test Company", 
+			"stock_adjustment_account")
+		
+		# check stock ledger entries
+		sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry` 
+			where voucher_type = 'Serial No' and voucher_no = %s""", sr.doc.name, as_dict=1)[0]
+		self.assertTrue(sle)
+		self.assertEquals([sle.item_code, sle.warehouse, sle.actual_qty], 
+			["_Test Serialized Item", "_Test Warehouse", 1.0])
 			
-		for d in data:
-			res = webnotes.conn.sql("""select valuation_rate from `tabStock Ledger Entry`
-				where posting_date=%s and posting_time=%s and actual_qty=1 and serial_no=%s""",
-				(d[0], d[1], d[2]))
-			self.assertEquals(res[0][0], d[4])
+		# check gl entries
+		gl_entries = webnotes.conn.sql("""select account, debit, credit
+			from `tabGL Entry` where voucher_type='Serial No' and voucher_no=%s
+			order by account desc""", sr.doc.name, as_dict=1)
+		self.assertTrue(gl_entries)
 		
-		print "deleted"
-		webnotes.delete_doc("Serial No", "10002")
+		expected_values = [
+			[stock_in_hand_account, 1000.0, 0.0],
+			[against_stock_account, 0.0, 1000.0]
+		]
 		
-		test_data = [["10001", 400, 400],
-			["10003", 700, 766.666667],
-			["10004", 1200, 875],
-			["10005", 800, 860],
-			["10006", 1200, 800],
-			["10007", 1500, 966.666667]]
+		for i, gle in enumerate(gl_entries):
+			self.assertEquals(expected_values[i][0], gle.account)
+			self.assertEquals(expected_values[i][1], gle.debit)
+			self.assertEquals(expected_values[i][2], gle.credit)
 		
-		for d in test_data:
-			res = webnotes.conn.sql("""select valuation_rate from `tabStock Ledger Entry`
-				where actual_qty=1 and serial_no=%s""", (d[0],))
-			self.assertEquals(res[0][0], d[2])
+		sr.load_from_db()
+		self.assertEquals(sr.doc.sle_exists, 1)
+		
+		# save again	
+		sr.save()
+		gl_entries = webnotes.conn.sql("""select account, debit, credit
+			from `tabGL Entry` where voucher_type='Serial No' and voucher_no=%s
+			order by account desc""", sr.doc.name, as_dict=1)
+		
+		for i, gle in enumerate(gl_entries):
+			self.assertEquals(expected_values[i][0], gle.account)
+			self.assertEquals(expected_values[i][1], gle.debit)
+			self.assertEquals(expected_values[i][2], gle.credit)
+			
+		# trash/cancel
+		sr.submit()
+		sr.cancel()
+		
+		gl_count = webnotes.conn.sql("""select count(name) from `tabGL Entry` 
+			where voucher_type='Serial No' and voucher_no=%s and ifnull(is_cancelled, 'No') = 'Yes' 
+			order by account asc, name asc""", sr.doc.name)
+		
+		self.assertEquals(gl_count[0][0], 4)
+		
+		webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
+		
+		
+	def test_aii_gl_entries_for_serial_no_delivered(self):
+		webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
+		
+		sr = webnotes.bean(copy=test_records[0])
+		sr.doc.serial_no = "_Test Serial No 2"
+		sr.doc.status = "Delivered"
+		sr.insert()
+		
+		gl_entries = webnotes.conn.sql("""select account, debit, credit
+			from `tabGL Entry` where voucher_type='Serial No' and voucher_no=%s
+			order by account desc""", sr.doc.name, as_dict=1)
+		self.assertFalse(gl_entries)
+		
+		webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
 	
-	def insert_test_data(self):
-		# create default warehouse
-		if not webnotes.conn.exists("Warehouse", "Default Warehouse"):
-			webnotes.insert({"doctype": "Warehouse", 
-				"warehouse_name": "Default Warehouse",
-				"warehouse_type": "Stores"})
-
-		# create UOM: Nos.
-		if not webnotes.conn.exists("UOM", "Nos"):
-			webnotes.insert({"doctype": "UOM", "uom_name": "Nos"})
-			
-		# create item groups and items
-		insert_test_data("Item Group", 
-			sort_fn=lambda ig: (ig[0].get('parent_item_group'), ig[0].get('name')))
-		
-		insert_test_data("Item")
\ No newline at end of file
+	
+test_records = [
+	[
+		{
+			"company": "_Test Company", 
+			"doctype": "Serial No", 
+			"serial_no": "_Test Serial No", 
+			"status": "In Store",
+			"item_code": "_Test Serialized Item", 
+			"item_group": "_Test Item Group", 
+			"warehouse": "_Test Warehouse",
+			"purchase_rate": 1000.0, 
+			"purchase_time": "11:37:39", 
+			"purchase_date": "2013-02-26",
+			'fiscal_year': "_Test Fiscal Year 2013"
+		}
+	]
+]
\ No newline at end of file