Merge branch 'master' of github.com:webnotes/erpnext into edge
diff --git a/accounts/doctype/pos_setting/pos_setting.txt b/accounts/doctype/pos_setting/pos_setting.txt
index 4e30b57..80cb1ec 100755
--- a/accounts/doctype/pos_setting/pos_setting.txt
+++ b/accounts/doctype/pos_setting/pos_setting.txt
@@ -1,8 +1,8 @@
 [
  {
-  "creation": "2013-03-26 11:03:07", 
+  "creation": "2013-04-30 12:58:25", 
   "docstatus": 0, 
-  "modified": "2013-03-26 12:48:18", 
+  "modified": "2013-05-03 14:36:24", 
   "modified_by": "Administrator", 
   "owner": "Administrator"
  }, 
@@ -40,6 +40,7 @@
   "doctype": "DocField", 
   "fieldname": "user", 
   "fieldtype": "Link", 
+  "in_list_view": 1, 
   "label": "User", 
   "oldfieldname": "user", 
   "oldfieldtype": "Link", 
@@ -99,6 +100,7 @@
   "doctype": "DocField", 
   "fieldname": "company", 
   "fieldtype": "Link", 
+  "in_list_view": 1, 
   "label": "Company", 
   "oldfieldname": "company", 
   "oldfieldtype": "Link", 
@@ -213,12 +215,6 @@
  {
   "create": 1, 
   "doctype": "DocPerm", 
-  "role": "System Manager", 
-  "write": 1
- }, 
- {
-  "create": 1, 
-  "doctype": "DocPerm", 
   "role": "Accounts Manager", 
   "write": 1
  }, 
diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py
index f44a787..87f73c1 100644
--- a/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/accounts/doctype/sales_invoice/sales_invoice.py
@@ -45,7 +45,7 @@
 		
 	def validate(self):
 		super(DocType, self).validate()
-		
+		self.fetch_missing_values()
 		self.validate_posting_time()
 		self.so_dn_required()
 		self.validate_proj_cust()
@@ -137,7 +137,27 @@
 	def on_update_after_submit(self):
 		self.validate_recurring_invoice()
 		self.convert_to_recurring()
-
+		
+	def fetch_missing_values(self):
+		# fetch contact and address details for customer, if they are not mentioned
+		if not (self.doc.contact_person and self.doc.customer_address):
+			for fieldname, val in self.get_default_address_and_contact("customer").items():
+				if not self.doc.fields.get(fieldname) and self.meta.get_field(fieldname):
+					self.doc.fields[fieldname] = val
+					
+		# fetch missing item values
+		for item in self.doclist.get({"parentfield": "entries"}):
+			if item.fields.get("item_code"):
+				ret = get_obj('Sales Common').get_item_details(item.fields, self)
+				for fieldname, value in ret.items():
+					if self.meta.get_field(fieldname, parentfield="entries") and \
+						not item.fields.get(fieldname):
+							item.fields[fieldname] = value
+		
+		# fetch pos details, if they are not fetched
+		if cint(self.doc.is_pos):
+			self.set_pos_fields(for_validate=True)
+			
 	def update_time_log_batch(self, sales_invoice):
 		for d in self.doclist.get({"doctype":"Sales Invoice Item"}):
 			if d.time_log_batch:
@@ -153,60 +173,42 @@
 					webnotes.msgprint(_("Time Log Batch status must be 'Submitted'") + ":" + d.time_log_batch,
 						raise_exception=True)
 
-	def set_pos_fields(self):
+	def set_pos_fields(self, for_validate=False):
 		"""Set retail related fields from pos settings"""
-		pos = self.pos_details
-
-		if pos:
-			val = webnotes.conn.sql("""select name from `tabAccount` 
-				where name = %s and docstatus != 2""", 
-				(cstr(self.doc.customer) + " - " + self.get_company_abbr()))
-
-			val = val and val[0][0] or ''
-			if not val: val = pos[0]['customer_account'] or ''
+		if cint(self.doc.is_pos) != 1:
+			return
+			
+		if self.pos_settings:
+			pos = self.pos_settings[0]
+			
+			self.doc.conversion_rate = flt(pos.conversion_rate)
 			
 			if not self.doc.debit_to:
-				webnotes.conn.set(self.doc,'debit_to',val)
-			
-			lst = ['territory', 'naming_series', 'currency', 'charge', 'letter_head', 'tc_name',
-				'price_list_name', 'company', 'select_print_heading', 'cash_bank_account']
+				self.doc.debit_to = self.doc.customer and webnotes.conn.get_value("Account", {
+					"name": self.doc.customer + " - " + self.get_company_abbr(), 
+					"docstatus": ["!=", 2]
+				}) or pos.customer_account
 				
-			for i in lst:
-				self.doc.fields[i] = pos[0][i] or ''
+			for fieldname in ('territory', 'naming_series', 'currency', 'charge', 'letter_head', 'tc_name',
+				'price_list_name', 'company', 'select_print_heading', 'cash_bank_account'):
+					if (not for_validate) or (for_validate and not self.doc.fields.get(fieldname)):
+						self.doc.fields[fieldname] = pos.get(fieldname)
 
-			self.set_pos_item_values()
-			
-			self.doc.conversion_rate = flt(pos[0]['conversion_rate']) or 0	
+			# set pos values in items
+			for doc in self.doclist.get({"parentfield": "entries"}):
+				if doc.fields.get('item_code'):
+					for fieldname, val in self.apply_pos_settings(doc.fields).items():
+						if (not for_validate) or (for_validate and not self.doc.fields.get(fieldname)):
+							doc.fields[fieldname] = val
 
-			#fetch terms	
-			if self.doc.tc_name:
+			# fetch terms	
+			if self.doc.tc_name and not self.doc.terms:
 				self.get_tc_details()
 			
-			#fetch charges
-			if self.doc.charge:
+			# fetch charges
+			if self.doc.charge and not len(self.doclist.get({"parentfield": "other_charges"})):
 				self.get_other_charges()
 
-
-	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 = self.pos_details
-			
-			for d in getlist(self.doclist,'entries'):
-				# overwrite if mentioned in item
-				item = webnotes.conn.sql("""select default_income_account,
-					default_sales_cost_center, default_warehouse, purchase_account
-					from tabItem where name = %s""", (d.item_code,), as_dict=1)
-				
-				d.income_account = (item and item[0]['default_income_account']) \
-					or (dtl and dtl[0]['income_account']) or d.income_account
-				d.cost_center = (item and item[0]['default_sales_cost_center']) \
-					or (dtl and dtl[0]['cost_center']) or d.cost_center
-				d.warehouse = (item and item[0]['default_warehouse']) \
-					or (dtl and dtl[0]['warehouse']) or d.warehouse
-				d.expense_account = (item and item[0].purchase_account) \
-					or (dtl and dtl[0].expense_account) or d.expense_account
-
 	def get_customer_account(self):
 		"""Get Account Head to which amount needs to be Debited based on Customer"""
 		if not self.doc.company:
@@ -299,60 +301,59 @@
 		args = args and json.loads(args) or {}
 		if args.get('item_code'):
 			ret = get_obj('Sales Common').get_item_details(args, self)
-			return self.get_pos_details(args, ret)
-		else:
-			for doc in self.doclist:
+			
+			if cint(self.doc.is_pos) == 1 and self.pos_settings:
+				ret = self.apply_pos_settings(args, ret)
+			
+			return ret
+		
+		elif cint(self.doc.is_pos) == 1 and self.pos_settings:
+			for doc in self.doclist.get({"parentfield": "entries"}):
 				if doc.fields.get('item_code'):
-					arg = {
-						'item_code':doc.fields.get('item_code'), 	
-						'income_account':doc.fields.get('income_account'), 
-						'cost_center': doc.fields.get('cost_center'), 
-						'warehouse': doc.fields.get('warehouse'),
-						'expense_account': doc.fields.get('expense_account'),
-					}
-
-					ret = self.get_pos_details(arg)
+					ret = self.apply_pos_settings(doc.fields)
 					for r in ret:
 						if not doc.fields.get(r):
 							doc.fields[r] = ret[r]		
 
 	@property
-	def pos_details(self):
-		if not hasattr(self, "_pos_details"):
+	def pos_settings(self):
+		if not hasattr(self, "_pos_settings"):
 			dtl = webnotes.conn.sql("""select * from `tabPOS Setting` where user = %s 
 				and company = %s""", (webnotes.session['user'], self.doc.company), as_dict=1)			 
 			if not dtl:
 				dtl = webnotes.conn.sql("""select * from `tabPOS Setting` 
 					where ifnull(user,'') = '' and company = %s""", self.doc.company, as_dict=1)
-			self._pos_details = dtl
+			self._pos_settings = dtl
 			
-		return self._pos_details
+		return self._pos_settings
 
-	def get_pos_details(self, args, ret = {}):
-		if args['item_code'] and cint(self.doc.is_pos) == 1:
-			dtl = self.pos_details
-
-			item = webnotes.conn.sql("""select default_income_account, default_sales_cost_center, 
-				default_warehouse, purchase_account from tabItem where name = %s""", 
-				args['item_code'], as_dict=1)
-
-			ret['income_account'] = item and item[0].get('default_income_account') \
-				or (dtl and dtl[0].get('income_account') or args.get('income_account'))
-
-			ret['cost_center'] = item and item[0].get('default_sales_cost_center') \
-				or (dtl and dtl[0].get('cost_center') or args.get('cost_center'))
+	def apply_pos_settings(self, args, ret=None):
+		if not ret: ret = {}
+		
+		pos = self.pos_settings[0]
+		
+		item = webnotes.conn.sql("""select default_income_account, default_sales_cost_center, 
+			default_warehouse, purchase_account from tabItem where name = %s""", 
+			args.get('item_code'), as_dict=1)
+		
+		if item:
+			item = item[0]
 			
-			ret['warehouse'] = item and item[0].get('default_warehouse') \
-				or (dtl and dtl[0].get('warehouse') or args.get('warehouse'))
+			ret.update({
+				"income_account": item.get("default_income_account") \
+					or pos.get("income_account") or args.get("income_account"),
+				"cost_center": item.get("default_sales_cost_center") \
+					or pos.get("cost_center") or args.get("cost_center"),
+				"warehouse": item.get("default_warehouse") \
+					or pos.get("warehouse") or args.get("warehouse"),
+				"expense_account": item.get("purchase_account") \
+					or pos.get("expense_account") or args.get("expense_account")
+			})
 			
-			ret['expense_account'] = item and item[0].get('purchase_account') \
-				or (dtl and dtl[0].get('expense_account') or args.get('expense_account'))
-
-			if ret['warehouse']:
-				actual_qty = webnotes.conn.sql("""select actual_qty from `tabBin` 
-					where item_code = %s and warehouse = %s""", 
-					(args['item_code'], ret['warehouse']))
-				ret['actual_qty']= actual_qty and flt(actual_qty[0][0]) or 0
+			if ret.get("warehouse"):
+				ret["actual_qty"] = flt(webnotes.conn.get_value("Bin",
+					{"item_code": args.get("item_code"), "warehouse": args.get("warehouse")},
+					"actual_qty"))
 		return ret
 
 	def get_barcode_details(self, barcode):
diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py
index fd8dc64..b46cdd1 100644
--- a/accounts/doctype/sales_invoice/test_sales_invoice.py
+++ b/accounts/doctype/sales_invoice/test_sales_invoice.py
@@ -90,6 +90,9 @@
 		webnotes.conn.sql("delete from `tabStock Ledger Entry`")
 		webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
 		
+		old_default_company = webnotes.conn.get_default("company")
+		webnotes.conn.set_default("company", "_Test Company")
+		
 		self._insert_purchase_receipt()
 		self._insert_pos_settings()
 		
@@ -106,7 +109,8 @@
 		
 		# check stock ledger entries
 		sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry` 
-			where voucher_type = 'Sales Invoice' and voucher_no = %s""", si.doc.name, as_dict=1)[0]
+			where voucher_type = 'Sales Invoice' and voucher_no = %s""", 
+			si.doc.name, as_dict=1)[0]
 		self.assertTrue(sle)
 		self.assertEquals([sle.item_code, sle.warehouse, sle.actual_qty], 
 			["_Test Item", "_Test Warehouse", -5.0])
@@ -145,6 +149,7 @@
 		self.assertEquals(gl_count[0][0], 16)
 			
 		webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
+		webnotes.conn.set_default("company", old_default_company)
 		
 	def test_sales_invoice_gl_entry_with_aii_no_item_code(self):		
 		webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
@@ -337,7 +342,7 @@
 		# change posting date but keep recuring day to be today
 		si7 = webnotes.bean(copy=base_si.doclist)
 		si7.doc.fields.update({
-			"posting_date": add_to_date(today, days=-3)
+			"posting_date": add_to_date(today, days=-1)
 		})
 		si7.insert()
 		si7.submit()
@@ -345,7 +350,7 @@
 		# setting so that _test function works
 		si7.doc.posting_date = today
 		self._test_recurring_invoice(si7, True)
-			
+
 	def _test_recurring_invoice(self, base_si, first_and_last_day):
 		from webnotes.utils import add_months, get_last_day, getdate
 		from accounts.doctype.sales_invoice.sales_invoice import manage_recurring_invoices
@@ -361,7 +366,8 @@
 			manage_recurring_invoices(next_date=next_date, commit=False)
 			
 			recurred_invoices = webnotes.conn.sql("""select name from `tabSales Invoice`
-				where recurring_id=%s and docstatus=1 order by name desc""", base_si.doc.recurring_id)
+				where recurring_id=%s and docstatus=1 order by name desc""",
+				base_si.doc.recurring_id)
 			
 			self.assertEquals(i+2, len(recurred_invoices))
 			
@@ -395,7 +401,7 @@
 		for i in xrange(count):
 			base_si = _test(i)
 		
-test_dependencies = ["Journal Voucher", "POS Setting"]
+test_dependencies = ["Journal Voucher", "POS Setting", "Contact", "Address"]
 
 test_records = [
 	[
diff --git a/selling/doctype/sales_common/sales_common.py b/selling/doctype/sales_common/sales_common.py
index 7b1528b..78f8422 100644
--- a/selling/doctype/sales_common/sales_common.py
+++ b/selling/doctype/sales_common/sales_common.py
@@ -374,7 +374,7 @@
 			msgprint("Please Enter Appropriate Conversion Rate for Customer's Currency to Base Currency (%s --> %s)" % (obj.doc.currency, default_currency), raise_exception = 1)
 	
 		if (obj.doc.price_list_currency == default_currency and flt(obj.doc.plc_conversion_rate) != 1.00) or not obj.doc.plc_conversion_rate or (obj.doc.price_list_currency != default_currency and flt(obj.doc.plc_conversion_rate) == 1.00):
-			msgprint("Please Enter Appropriate Conversion Rate for Price List Currency to Base Currency ( (%s --> %s)" % (obj.doc.price_list_currency, default_currency), raise_exception = 1)
+			msgprint("Please Enter Appropriate Conversion Rate for Price List Currency to Base Currency (%s --> %s)" % (obj.doc.price_list_currency, default_currency), raise_exception = 1)
 	
 
 
diff --git a/setup/doctype/global_defaults/global_defaults.py b/setup/doctype/global_defaults/global_defaults.py
index 191a47e..dc7f6b4 100644
--- a/setup/doctype/global_defaults/global_defaults.py
+++ b/setup/doctype/global_defaults/global_defaults.py
@@ -21,6 +21,7 @@
 from webnotes.utils import cint
 
 keydict = {
+	# "key in defaults": "key in Global Defaults"
 	"print_style": "print_style",
 	"fiscal_year": "current_fiscal_year",
 	'company': 'default_company',
diff --git a/stock/doctype/stock_entry/test_stock_entry.py b/stock/doctype/stock_entry/test_stock_entry.py
index 7c406f8..c3ce2d7 100644
--- a/stock/doctype/stock_entry/test_stock_entry.py
+++ b/stock/doctype/stock_entry/test_stock_entry.py
@@ -25,6 +25,8 @@
 			where item_code='_Test Item'""")
 			
 		self.assertTrue(mr_name)
+		
+		webnotes.conn.set_default("company", self.old_default_company)
 
 	def test_warehouse_company_validation(self):
 		from stock.doctype.stock_ledger_entry.stock_ledger_entry import InvalidWarehouseCompany
@@ -71,7 +73,7 @@
 		webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
 
 	def test_material_issue_gl_entry(self):
-		webnotes.conn.sql("delete from `tabStock Ledger Entry`")
+		self._clear_stock()
 		webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
 		
 		mr = webnotes.bean(copy=test_records[0])
@@ -111,9 +113,10 @@
 		)
 		
 		webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
+		webnotes.conn.set_default("company", self.old_default_company)
 		
 	def test_material_transfer_gl_entry(self):
-		webnotes.conn.sql("delete from `tabStock Ledger Entry`")
+		self._clear_stock()
 		webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
 
 		mr = webnotes.bean(copy=test_records[0])
@@ -145,6 +148,7 @@
 		self.assertFalse(gl_entries)
 		
 		webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
+		webnotes.conn.set_default("company", self.old_default_company)
 	
 	def check_stock_ledger_entries(self, voucher_type, voucher_no, expected_sle):
 		# check stock ledger entries
@@ -173,6 +177,9 @@
 	def _clear_stock(self):
 		webnotes.conn.sql("delete from `tabStock Ledger Entry`")
 		webnotes.conn.sql("""delete from `tabBin`""")
+		
+		self.old_default_company = webnotes.conn.get_default("company")
+		webnotes.conn.set_default("company", "_Test Company")
 	
 	def _insert_material_receipt(self):
 		self._clear_stock()
@@ -185,6 +192,8 @@
 		se2.insert()
 		se2.submit()
 		
+		webnotes.conn.set_default("company", self.old_default_company)
+		
 	def _get_actual_qty(self):
 		return flt(webnotes.conn.get_value("Bin", {"item_code": "_Test Item", 
 			"warehouse": "_Test Warehouse"}, "actual_qty"))
@@ -463,6 +472,8 @@
 		
 		self.assertEquals(actual_qty_1 - 5, actual_qty_2)
 		
+		webnotes.conn.set_default("company", self.old_default_company)
+		
 		return se, pr.doc.name
 		
 	def test_over_stock_return(self):
@@ -563,6 +574,8 @@
 		
 		self.assertEquals(actual_qty_1 - 5, actual_qty_2)
 		
+		webnotes.conn.set_default("company", self.old_default_company)
+		
 		return se, pr.doc.name
 		
 test_records = [
diff --git a/utilities/doctype/address/test_address.py b/utilities/doctype/address/test_address.py
new file mode 100644
index 0000000..eddd9c7
--- /dev/null
+++ b/utilities/doctype/address/test_address.py
@@ -0,0 +1,14 @@
+test_records = [
+	[{
+		"doctype": "Address",
+		"customer": "_Test Customer",
+		"customer_name": "_Test Customer",
+		"address_type": "Office",
+		"address_title": "_Test Address",
+		"address_line1": "_Test Address Line 1",
+		"city": "_Test City",
+		"country": "India",
+		"phone": "+91 0000000000",
+		"is_primary_address": 1
+	}],
+]
\ No newline at end of file
diff --git a/utilities/transaction_base.py b/utilities/transaction_base.py
index 4b34ba1..5d7d1a8 100644
--- a/utilities/transaction_base.py
+++ b/utilities/transaction_base.py
@@ -22,6 +22,23 @@
 from webnotes.model.controller import DocListController
 
 class TransactionBase(DocListController):
+	def get_default_address_and_contact(self, party_type):
+		"""get a dict of default field values of address and contact for a given party type
+			party_type can be one of: customer, supplier"""
+		ret = {}
+		
+		# {customer: self.doc.fields.get("customer")}
+		args = {party_type: self.doc.fields.get(party_type)}
+		
+		address_text, address_name = self.get_address_text(**args)
+		ret.update({
+			# customer_address
+			(party_type + "_address"): address_name,
+			"address_display": address_text
+		})
+		ret.update(self.get_contact_text(**args))
+		return ret
+	
 	# Get Customer Default Primary Address - first load
 	def get_default_customer_address(self, args=''):
 		address_text, address_name = self.get_address_text(customer=self.doc.customer)
@@ -73,7 +90,7 @@
 			details = webnotes.conn.sql("select name, address_line1, address_line2, city, country, pincode, state, phone, fax from `tabAddress` where %s and docstatus != 2 order by is_shipping_address desc, is_primary_address desc limit 1" % cond, as_dict = 1)
 		else:
 			details = webnotes.conn.sql("select name, address_line1, address_line2, city, country, pincode, state, phone, fax from `tabAddress` where %s and docstatus != 2 order by is_primary_address desc limit 1" % cond, as_dict = 1)
-		
+			
 		extract = lambda x: details and details[0] and details[0].get(x,'') or ''
 		address_fields = [('','address_line1'),('\n','address_line2'),('\n','city'),('\n','state'),(' ','pincode'),('\n','country'),('\nPhone: ','phone'),('\nFax: ', 'fax')]
 		address_display = ''.join([a[0]+extract(a[1]) for a in address_fields if extract(a[1])])