[fix] [minor] perpetual inventory: account for each warehouse
This commit is contained in:
		
							parent
							
								
									87eb4b99a8
								
							
						
					
					
						commit
						7a75e10a61
					
				| @ -32,10 +32,10 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) { | ||||
| 	} else { | ||||
| 		// credit days and type if customer or supplier
 | ||||
| 		cur_frm.set_intro(null); | ||||
| 		cur_frm.toggle_display(['credit_days', 'credit_limit', 'master_name'],  | ||||
| 			in_list(['Customer', 'Supplier'], doc.master_type)); | ||||
| 		cur_frm.toggle_display(['credit_days', 'credit_limit'], in_list(['Customer', 'Supplier'],  | ||||
| 			doc.master_type)); | ||||
| 		 | ||||
| 		// hide tax_rate
 | ||||
| 		cur_frm.cscript.master_type(doc, cdt, cdn); | ||||
| 		cur_frm.cscript.account_type(doc, cdt, cdn); | ||||
| 
 | ||||
| 		// show / hide convert buttons
 | ||||
| @ -44,7 +44,10 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) { | ||||
| } | ||||
| 
 | ||||
| cur_frm.cscript.master_type = function(doc, cdt, cdn) { | ||||
| 	cur_frm.toggle_display(['credit_days', 'credit_limit', 'master_name'],  | ||||
| 	cur_frm.toggle_display(['credit_days', 'credit_limit'], in_list(['Customer', 'Supplier'],  | ||||
| 		doc.master_type)); | ||||
| 		 | ||||
| 	cur_frm.toggle_display('master_name', doc.account_type=='Warehouse' ||  | ||||
| 		in_list(['Customer', 'Supplier'], doc.master_type)); | ||||
| } | ||||
| 
 | ||||
| @ -58,10 +61,10 @@ cur_frm.add_fetch('parent_account', 'is_pl_account', 'is_pl_account'); | ||||
| // -----------------------------------------
 | ||||
| cur_frm.cscript.account_type = function(doc, cdt, cdn) { | ||||
| 	if(doc.group_or_ledger=='Ledger') { | ||||
| 		cur_frm.toggle_display(['tax_rate'],  | ||||
| 			doc.account_type == 'Tax'); | ||||
| 		cur_frm.toggle_display(['master_type', 'master_name'],  | ||||
| 			cstr(doc.account_type)=='');		 | ||||
| 		cur_frm.toggle_display(['tax_rate'], doc.account_type == 'Tax'); | ||||
| 		cur_frm.toggle_display('master_type', cstr(doc.account_type)==''); | ||||
| 		cur_frm.toggle_display('master_name', doc.account_type=='Warehouse' ||  | ||||
| 			in_list(['Customer', 'Supplier'], doc.master_type)); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @ -109,11 +112,15 @@ cur_frm.cscript.convert_to_group = function(doc, cdt, cdn) { | ||||
| } | ||||
| 
 | ||||
| cur_frm.fields_dict['master_name'].get_query = function(doc) { | ||||
| 	if (doc.master_type) { | ||||
| 	if (doc.master_type || doc.account_type=="Warehouse") { | ||||
| 		var dt = doc.master_type || "Warehouse"; | ||||
| 		return { | ||||
| 			doctype: doc.master_type, | ||||
| 			doctype: dt, | ||||
| 			query: "accounts.doctype.account.account.get_master_name", | ||||
| 			filters: {	"master_type": doc.master_type } | ||||
| 			filters: { | ||||
| 				"master_type": dt, | ||||
| 				"company": doc.company | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -4,7 +4,7 @@ | ||||
| from __future__ import unicode_literals | ||||
| import webnotes | ||||
| 
 | ||||
| from webnotes.utils import flt, fmt_money | ||||
| from webnotes.utils import flt, fmt_money, cstr, cint | ||||
| from webnotes import msgprint, _ | ||||
| 
 | ||||
| sql = webnotes.conn.sql | ||||
| @ -16,13 +16,25 @@ class DocType: | ||||
| 		self.nsm_parent_field = 'parent_account' | ||||
| 
 | ||||
| 	def autoname(self): | ||||
| 		"""Append abbreviation to company on naming""" | ||||
| 		self.doc.name = self.doc.account_name.strip() + ' - ' + \ | ||||
| 			webnotes.conn.get_value("Company", self.doc.company, "abbr") | ||||
| 
 | ||||
| 	def get_address(self): | ||||
| 		address = webnotes.conn.get_value(self.doc.master_type, self.doc.master_name, "address") | ||||
| 		return {'address': address} | ||||
| 		return { | ||||
| 			'address': webnotes.conn.get_value(self.doc.master_type,  | ||||
| 				self.doc.master_name, "address") | ||||
| 		} | ||||
| 		 | ||||
| 	def validate(self):  | ||||
| 		self.validate_master_name() | ||||
| 		self.validate_parent() | ||||
| 		self.validate_duplicate_account() | ||||
| 		self.validate_root_details() | ||||
| 		self.validate_mandatory() | ||||
| 		self.validate_warehouse_account() | ||||
| 	 | ||||
| 		if not self.doc.parent_account: | ||||
| 			self.doc.parent_account = '' | ||||
| 		 | ||||
| 	def validate_master_name(self): | ||||
| 		"""Remind to add master name""" | ||||
| @ -110,15 +122,25 @@ class DocType: | ||||
| 		if not self.doc.is_pl_account: | ||||
| 			msgprint("Is PL Account field is mandatory", raise_exception=1) | ||||
| 			 | ||||
| 	def validate(self):  | ||||
| 		self.validate_master_name() | ||||
| 		self.validate_parent() | ||||
| 		self.validate_duplicate_account() | ||||
| 		self.validate_root_details() | ||||
| 		self.validate_mandatory() | ||||
| 	def validate_warehouse_account(self): | ||||
| 		if not cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")): | ||||
| 			return | ||||
| 			 | ||||
| 		if self.doc.account_type == "Warehouse": | ||||
| 			old_warehouse = cstr(webnotes.conn.get_value("Account", self.doc.name, "master_name")) | ||||
| 			if old_warehouse != cstr(self.doc.master_name): | ||||
| 				if old_warehouse: | ||||
| 					self.validate_warehouse(old_warehouse) | ||||
| 				if self.doc.master_name: | ||||
| 					self.validate_warehouse(self.doc.master_name) | ||||
| 				else: | ||||
| 					webnotes.throw(_("Master Name is mandatory if account type is Warehouse")) | ||||
| 		 | ||||
| 	def validate_warehouse(self, warehouse): | ||||
| 		if webnotes.conn.get_value("Stock Ledger Entry", {"warehouse": warehouse}): | ||||
| 			webnotes.throw(_("Stock transactions exist against warehouse ") + warehouse +  | ||||
| 				_(" .You can not assign / modify / remove Master Name")) | ||||
| 
 | ||||
| 		if not self.doc.parent_account: | ||||
| 			self.doc.parent_account = '' | ||||
| 
 | ||||
| 	def update_nsm_model(self): | ||||
| 		"""update lft, rgt indices for nested set model""" | ||||
| @ -198,9 +220,11 @@ class DocType: | ||||
| 		return " - ".join(parts) | ||||
| 
 | ||||
| def get_master_name(doctype, txt, searchfield, start, page_len, filters): | ||||
| 	return webnotes.conn.sql("""select name from `tab%s` where %s like %s  | ||||
| 	conditions = (" and company='%s'"% filters["company"]) if doctype == "Warehouse" else "" | ||||
| 		 | ||||
| 	return webnotes.conn.sql("""select name from `tab%s` where %s like %s %s | ||||
| 		order by name limit %s, %s""" % | ||||
| 		(filters["master_type"], searchfield, "%s", "%s", "%s"),  | ||||
| 		(filters["master_type"], searchfield, "%s", conditions, "%s", "%s"),  | ||||
| 		("%%%s%%" % txt, start, page_len), as_list=1) | ||||
| 		 | ||||
| def get_parent_account(doctype, txt, searchfield, start, page_len, filters): | ||||
|  | ||||
| @ -2,7 +2,7 @@ | ||||
|  { | ||||
|   "creation": "2013-01-30 12:49:46",  | ||||
|   "docstatus": 0,  | ||||
|   "modified": "2013-07-05 14:23:30",  | ||||
|   "modified": "2013-09-16 12:21:10",  | ||||
|   "modified_by": "Administrator",  | ||||
|   "owner": "Administrator" | ||||
|  },  | ||||
| @ -162,7 +162,7 @@ | ||||
|   "label": "Account Type",  | ||||
|   "oldfieldname": "account_type",  | ||||
|   "oldfieldtype": "Select",  | ||||
|   "options": "\nFixed Asset Account\nBank or Cash\nExpense Account\nTax\nIncome Account\nChargeable",  | ||||
|   "options": "\nFixed Asset Account\nBank or Cash\nExpense Account\nTax\nIncome Account\nChargeable\nWarehouse",  | ||||
|   "permlevel": 0,  | ||||
|   "search_index": 0 | ||||
|  },  | ||||
|  | ||||
| @ -13,5 +13,9 @@ class DocType: | ||||
| 		self.doc, self.doclist = d, dl | ||||
| 
 | ||||
| 	def on_update(self): | ||||
| 		for key in ["auto_accounting_for_stock"]: | ||||
| 			webnotes.conn.set_default(key, self.doc.fields.get(key, '')) | ||||
| 		webnotes.conn.set_default("auto_accounting_for_stock", self.doc.auto_accounting_for_stock) | ||||
| 		 | ||||
| 		if self.doc.auto_accounting_for_stock: | ||||
| 			for wh in webnotes.conn.sql("select name from `tabWarehouse`"): | ||||
| 				wh_bean = webnotes.bean("Warehouse", wh[0]) | ||||
| 				wh_bean.save() | ||||
| @ -2,7 +2,7 @@ | ||||
|  { | ||||
|   "creation": "2013-06-24 15:49:57",  | ||||
|   "docstatus": 0,  | ||||
|   "modified": "2013-08-28 18:55:43",  | ||||
|   "modified": "2013-09-16 14:24:39",  | ||||
|   "modified_by": "Administrator",  | ||||
|   "owner": "Administrator" | ||||
|  },  | ||||
| @ -44,7 +44,7 @@ | ||||
|   "doctype": "DocField",  | ||||
|   "fieldname": "auto_accounting_for_stock",  | ||||
|   "fieldtype": "Check",  | ||||
|   "label": "Make Accounting Entry For Every Stock Entry" | ||||
|   "label": "Make Accounting Entry For Every Stock Movement" | ||||
|  },  | ||||
|  { | ||||
|   "description": "Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.",  | ||||
|  | ||||
| @ -192,8 +192,6 @@ class DocType(SellingController): | ||||
| 		pos = get_pos_settings(self.doc.company) | ||||
| 			 | ||||
| 		if pos: | ||||
| 			self.doc.conversion_rate = flt(pos.conversion_rate) | ||||
| 			 | ||||
| 			if not for_validate: | ||||
| 				self.doc.customer = pos.customer | ||||
| 				self.set_customer_defaults() | ||||
|  | ||||
| @ -6,10 +6,12 @@ import unittest, json | ||||
| from webnotes.utils import flt, cint | ||||
| from webnotes.model.bean import DocstatusTransitionError, TimestampMismatchError | ||||
| from accounts.utils import get_stock_and_account_difference | ||||
| from stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory | ||||
| 
 | ||||
| class TestSalesInvoice(unittest.TestCase): | ||||
| 	def make(self): | ||||
| 		w = webnotes.bean(copy=test_records[0]) | ||||
| 		w.doc.is_pos = 0 | ||||
| 		w.insert() | ||||
| 		w.submit() | ||||
| 		return w | ||||
| @ -93,7 +95,6 @@ class TestSalesInvoice(unittest.TestCase): | ||||
| 		si.doclist[1].ref_rate = 1 | ||||
| 		si.doclist[2].export_rate = 3 | ||||
| 		si.doclist[2].ref_rate = 3 | ||||
| 		si.run_method("calculate_taxes_and_totals") | ||||
| 		si.insert() | ||||
| 		 | ||||
| 		expected_values = { | ||||
| @ -259,6 +260,7 @@ class TestSalesInvoice(unittest.TestCase): | ||||
| 		 | ||||
| 	def test_payment(self): | ||||
| 		w = self.make() | ||||
| 		 | ||||
| 		from accounts.doctype.journal_voucher.test_journal_voucher \ | ||||
| 			import test_records as jv_test_records | ||||
| 			 | ||||
| @ -298,8 +300,8 @@ class TestSalesInvoice(unittest.TestCase): | ||||
| 			"Batched for Billing") | ||||
| 			 | ||||
| 	def test_sales_invoice_gl_entry_without_aii(self): | ||||
| 		webnotes.defaults.set_global_default("auto_accounting_for_stock", 0) | ||||
| 		self.clear_stock_account_balance() | ||||
| 		set_perpetual_inventory(0) | ||||
| 		si = webnotes.bean(copy=test_records[1]) | ||||
| 		si.insert() | ||||
| 		si.submit() | ||||
| @ -331,10 +333,8 @@ class TestSalesInvoice(unittest.TestCase): | ||||
| 		self.assertFalse(gle) | ||||
| 		 | ||||
| 	def test_pos_gl_entry_with_aii(self): | ||||
| 		webnotes.conn.sql("delete from `tabStock Ledger Entry`") | ||||
| 		webnotes.conn.sql("delete from `tabGL Entry`") | ||||
| 		webnotes.conn.sql("delete from `tabBin`") | ||||
| 		webnotes.defaults.set_global_default("auto_accounting_for_stock", 1) | ||||
| 		self.clear_stock_account_balance() | ||||
| 		set_perpetual_inventory() | ||||
| 		 | ||||
| 		self._insert_purchase_receipt() | ||||
| 		self._insert_pos_settings() | ||||
| @ -359,18 +359,19 @@ class TestSalesInvoice(unittest.TestCase): | ||||
| 			["_Test Item", "_Test Warehouse - _TC", -1.0]) | ||||
| 		 | ||||
| 		# check gl entries | ||||
| 		 | ||||
| 		gl_entries = webnotes.conn.sql("""select account, debit, credit | ||||
| 			from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s | ||||
| 			order by account asc, debit asc""", si.doc.name, as_dict=1) | ||||
| 		self.assertTrue(gl_entries) | ||||
| 		 | ||||
| 		stock_in_hand = webnotes.conn.get_value("Account", {"master_name": "_Test Warehouse - _TC"}) | ||||
| 				 | ||||
| 		expected_gl_entries = sorted([ | ||||
| 			[si.doc.debit_to, 630.0, 0.0], | ||||
| 			[pos[1]["income_account"], 0.0, 500.0], | ||||
| 			[pos[2]["account_head"], 0.0, 80.0], | ||||
| 			[pos[3]["account_head"], 0.0, 50.0], | ||||
| 			["_Test Account Stock In Hand - _TC", 0.0, 75.0], | ||||
| 			[stock_in_hand, 0.0, 75.0], | ||||
| 			[pos[1]["expense_account"], 75.0, 0.0], | ||||
| 			[si.doc.debit_to, 0.0, 600.0], | ||||
| 			["_Test Account Bank Account - _TC", 600.0, 0.0] | ||||
| @ -389,12 +390,13 @@ class TestSalesInvoice(unittest.TestCase): | ||||
| 		 | ||||
| 		self.assertFalse(gle) | ||||
| 		 | ||||
| 		self.assertFalse(get_stock_and_account_difference(["_Test Account Stock In Hand - _TC"])) | ||||
| 		self.assertFalse(get_stock_and_account_difference([stock_in_hand])) | ||||
| 		 | ||||
| 		webnotes.defaults.set_global_default("auto_accounting_for_stock", 0) | ||||
| 		set_perpetual_inventory(0) | ||||
| 		 | ||||
| 	def test_sales_invoice_gl_entry_with_aii_no_item_code(self):	 | ||||
| 		webnotes.defaults.set_global_default("auto_accounting_for_stock", 1) | ||||
| 		self.clear_stock_account_balance() | ||||
| 		set_perpetual_inventory() | ||||
| 				 | ||||
| 		si_copy = webnotes.copy_doclist(test_records[1]) | ||||
| 		si_copy[1]["item_code"] = None | ||||
| @ -418,11 +420,11 @@ class TestSalesInvoice(unittest.TestCase): | ||||
| 			self.assertEquals(expected_values[i][1], gle.debit) | ||||
| 			self.assertEquals(expected_values[i][2], gle.credit) | ||||
| 		 | ||||
| 		webnotes.defaults.set_global_default("auto_accounting_for_stock", 0) | ||||
| 		set_perpetual_inventory(0) | ||||
| 	 | ||||
| 	def test_sales_invoice_gl_entry_with_aii_non_stock_item(self): | ||||
| 		webnotes.defaults.set_global_default("auto_accounting_for_stock", 1) | ||||
| 		 | ||||
| 		self.clear_stock_account_balance() | ||||
| 		set_perpetual_inventory() | ||||
| 		si_copy = webnotes.copy_doclist(test_records[1]) | ||||
| 		si_copy[1]["item_code"] = "_Test Non Stock Item" | ||||
| 		si = webnotes.bean(si_copy) | ||||
| @ -445,7 +447,7 @@ class TestSalesInvoice(unittest.TestCase): | ||||
| 			self.assertEquals(expected_values[i][1], gle.debit) | ||||
| 			self.assertEquals(expected_values[i][2], gle.credit) | ||||
| 				 | ||||
| 		webnotes.defaults.set_global_default("auto_accounting_for_stock", 0) | ||||
| 		set_perpetual_inventory(0) | ||||
| 		 | ||||
| 	def _insert_purchase_receipt(self): | ||||
| 		from stock.doctype.purchase_receipt.test_purchase_receipt import test_records \ | ||||
|  | ||||
| @ -5,7 +5,7 @@ from __future__ import unicode_literals | ||||
| import webnotes | ||||
| from webnotes import _, msgprint | ||||
| from webnotes.utils import flt, cint, today, cstr | ||||
| from setup.utils import get_company_currency, get_price_list_currency | ||||
| from setup.utils import get_company_currency | ||||
| from accounts.utils import get_fiscal_year, validate_fiscal_year | ||||
| from utilities.transaction_base import TransactionBase, validate_conversion_rate | ||||
| import json | ||||
| @ -13,7 +13,6 @@ import json | ||||
| class AccountsController(TransactionBase): | ||||
| 	def validate(self): | ||||
| 		self.set_missing_values(for_validate=True) | ||||
| 		 | ||||
| 		self.validate_date_with_fiscal_year() | ||||
| 		if self.meta.get_field("currency"): | ||||
| 			self.calculate_taxes_and_totals() | ||||
| @ -54,34 +53,36 @@ class AccountsController(TransactionBase): | ||||
| 							self.doc.doctype + _(" can not be made."), raise_exception=1) | ||||
| 			 | ||||
| 	def set_price_list_currency(self, buying_or_selling): | ||||
| 		if self.meta.get_field("currency"): | ||||
| 			company_currency = get_company_currency(self.doc.company) | ||||
| 		fieldname = buying_or_selling.lower() + "_price_list" | ||||
| 		# TODO - change this, since price list now has only one currency allowed | ||||
| 		if self.meta.get_field(fieldname) and self.doc.fields.get(fieldname) and \ | ||||
| 			not self.doc.price_list_currency: | ||||
| 				self.doc.fields.update(get_price_list_currency(self.doc.fields.get(fieldname))) | ||||
| 			 | ||||
| 				if self.doc.price_list_currency: | ||||
| 					if not self.doc.plc_conversion_rate: | ||||
| 			# price list part | ||||
| 			fieldname = "selling_price_list" if buying_or_selling.lower() == "selling" \ | ||||
| 				else "buying_price_list" | ||||
| 			if self.meta.get_field(fieldname) and self.doc.fields.get(fieldname): | ||||
| 				if not self.doc.price_list_currency: | ||||
| 					self.doc.price_list_currency = webnotes.conn.get_value("Price List", | ||||
| 						self.doc.fields.get(fieldame), "currency") | ||||
| 				 | ||||
| 				if self.doc.price_list_currency == company_currency: | ||||
| 					self.doc.plc_conversion_rate = 1.0 | ||||
| 						else: | ||||
| 							exchange = self.doc.price_list_currency + "-" + company_currency | ||||
| 							self.doc.plc_conversion_rate = flt(webnotes.conn.get_value("Currency Exchange", | ||||
| 								exchange, "exchange_rate")) | ||||
| 				elif not self.doc.plc_conversion_rate: | ||||
| 					self.doc.plc_conversion_rate = self.get_exchange_rate( | ||||
| 						self.doc.price_list_currency, company_currency) | ||||
| 			 | ||||
| 			# currency | ||||
| 			if not self.doc.currency: | ||||
| 				self.doc.currency = self.doc.price_list_currency | ||||
| 				self.doc.conversion_rate = self.doc.plc_conversion_rate | ||||
| 			elif self.doc.currency == company_currency: | ||||
| 				self.doc.conversion_rate = 1.0 | ||||
| 			elif not self.doc.conversion_rate: | ||||
| 				self.doc.conversion_rate = self.get_exchange_rate(self.doc.currency, | ||||
| 					company_currency) | ||||
| 
 | ||||
| 		if self.meta.get_field("currency"): | ||||
| 			if self.doc.currency and self.doc.currency != company_currency: | ||||
| 				if not self.doc.conversion_rate: | ||||
| 					exchange = self.doc.currency + "-" + company_currency | ||||
| 					self.doc.conversion_rate = flt(webnotes.conn.get_value("Currency Exchange", | ||||
| 						exchange, "exchange_rate")) | ||||
| 			else: | ||||
| 				self.doc.conversion_rate = 1 | ||||
| 	def get_exchange_rate(self, from_currency, to_currency): | ||||
| 		exchange = "%s-%s" % (from_currency, to_currency) | ||||
| 		return flt(webnotes.conn.get_value("Currency Exchange", exchange, "exchange_rate")) | ||||
| 
 | ||||
| 	def set_missing_item_details(self, get_item_details): | ||||
| 		"""set missing item values""" | ||||
|  | ||||
| @ -31,12 +31,12 @@ class StockController(AccountsController): | ||||
| 			default_cost_center) | ||||
| 		 | ||||
| 		gl_list = [] | ||||
| 		warehouse_with_no_account = [] | ||||
| 		for detail in voucher_details: | ||||
| 			sle_list = stock_ledger.get(detail.name) | ||||
| 			if sle_list: | ||||
| 				for sle in sle_list: | ||||
| 					if warehouse_account.get(sle.warehouse): | ||||
| 						 | ||||
| 						# from warehouse account | ||||
| 						gl_list.append(self.get_gl_dict({ | ||||
| 							"account": warehouse_account[sle.warehouse], | ||||
| @ -54,6 +54,12 @@ class StockController(AccountsController): | ||||
| 							"remarks": self.doc.remarks or "Accounting Entry for Stock", | ||||
| 							"credit": sle.stock_value_difference | ||||
| 						})) | ||||
| 					elif sle.warehouse not in warehouse_with_no_account: | ||||
| 						warehouse_with_no_account.append(sle.warehouse) | ||||
| 						 | ||||
| 		if warehouse_with_no_account:				 | ||||
| 			msgprint(_("No accounting entries for following warehouses") + ": \n" +  | ||||
| 				"\n".join(warehouse_with_no_account)) | ||||
| 		 | ||||
| 		return process_gl_map(gl_list) | ||||
| 			 | ||||
| @ -80,9 +86,11 @@ class StockController(AccountsController): | ||||
| 		return stock_ledger | ||||
| 		 | ||||
| 	def get_warehouse_account(self): | ||||
| 		warehouse_account = dict(webnotes.conn.sql("""select name, account from `tabWarehouse` | ||||
| 			where ifnull(account, '') != ''""")) | ||||
| 		for d in webnotes.conn.sql("select name from tabWarehouse"): | ||||
| 			webnotes.bean("Warehouse", d[0]).save() | ||||
| 
 | ||||
| 		warehouse_account = dict(webnotes.conn.sql("""select master_name, name from tabAccount  | ||||
| 			where account_type = 'Warehouse' and ifnull(master_name, '') != ''""")) | ||||
| 		return warehouse_account | ||||
| 		 | ||||
| 	def update_gl_entries_after(self): | ||||
|  | ||||
| @ -68,9 +68,9 @@ class DocType(TransactionBase): | ||||
| 				ac_bean.ignore_permissions = True | ||||
| 				ac_bean.insert() | ||||
| 				 | ||||
| 				msgprint("Account Head: %s created" % ac_bean.doc.name) | ||||
| 				msgprint(_("Account Head") + ": " + ac_bean.doc.name + _(" created")) | ||||
| 		else : | ||||
| 			msgprint("Please Select Company under which you want to create account head") | ||||
| 			msgprint(_("Please Select Company under which you want to create account head")) | ||||
| 
 | ||||
| 	def update_credit_days_limit(self): | ||||
| 		webnotes.conn.sql("""update tabAccount set credit_days = %s, credit_limit = %s  | ||||
|  | ||||
| @ -59,14 +59,12 @@ class DocType: | ||||
| 
 | ||||
| 	def create_default_warehouses(self): | ||||
| 		for whname in ("Stores", "Work In Progress", "Finished Goods"): | ||||
| 			wh = { | ||||
| 			webnotes.bean({ | ||||
| 				"doctype":"Warehouse", | ||||
| 				"warehouse_name": whname, | ||||
| 				"company": self.doc.name, | ||||
| 			} | ||||
| 			wh.update({"account": "Stock In Hand - " + self.doc.abbr}) | ||||
| 				 | ||||
| 			webnotes.bean(wh).insert() | ||||
| 				"create_account_under": "Stock Assets - " + self.doc.abbr | ||||
| 			}).insert() | ||||
| 			 | ||||
| 	def create_default_web_page(self): | ||||
| 		if not webnotes.conn.get_value("Website Settings", None, "home_page"): | ||||
| @ -116,7 +114,6 @@ class DocType: | ||||
| 					['Securities and Deposits','Current Assets','Group','No','','Debit',self.doc.name,''], | ||||
| 						['Earnest Money','Securities and Deposits','Ledger','No','','Debit',self.doc.name,''], | ||||
| 					['Stock Assets','Current Assets','Group','No','','Debit',self.doc.name,''], | ||||
| 						['Stock In Hand','Stock Assets','Ledger','No','','Debit',self.doc.name,''], | ||||
| 					['Tax Assets','Current Assets','Group','No','','Debit',self.doc.name,''], | ||||
| 				['Fixed Assets','Application of Funds (Assets)','Group','No','','Debit',self.doc.name,''], | ||||
| 					['Capital Equipments','Fixed Assets','Ledger','No','Fixed Asset Account','Debit',self.doc.name,''], | ||||
| @ -289,9 +286,6 @@ class DocType: | ||||
| 		""" | ||||
| 		rec = webnotes.conn.sql("SELECT name from `tabGL Entry` where company = %s", self.doc.name) | ||||
| 		if not rec: | ||||
| 			# delete gl entry | ||||
| 			webnotes.conn.sql("delete from `tabGL Entry` where company = %s", self.doc.name) | ||||
| 
 | ||||
| 			#delete tabAccount | ||||
| 			webnotes.conn.sql("delete from `tabAccount` where company = %s order by lft desc, rgt desc", self.doc.name) | ||||
| 			 | ||||
| @ -300,6 +294,9 @@ class DocType: | ||||
| 			#delete cost center | ||||
| 			webnotes.conn.sql("delete from `tabCost Center` WHERE company = %s order by lft desc, rgt desc", self.doc.name) | ||||
| 			 | ||||
| 		if not webnotes.conn.get_value("Stock Ledger Entry", {"company": self.doc.name}): | ||||
| 			webnotes.conn.sql("""delete from `tabWarehouse` where company=%s""", self.doc.name) | ||||
| 			 | ||||
| 		webnotes.defaults.clear_default("company", value=self.doc.name) | ||||
| 			 | ||||
| 		webnotes.conn.sql("""update `tabSingles` set value="" | ||||
|  | ||||
| @ -7,7 +7,7 @@ import unittest | ||||
| import webnotes | ||||
| import webnotes.defaults | ||||
| from webnotes.utils import cint | ||||
| from stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries, test_records as pr_test_records | ||||
| from stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries, set_perpetual_inventory, test_records as pr_test_records | ||||
| 
 | ||||
| class TestDeliveryNote(unittest.TestCase): | ||||
| 	def _insert_purchase_receipt(self, item_code=None): | ||||
| @ -41,7 +41,7 @@ class TestDeliveryNote(unittest.TestCase): | ||||
| 	 | ||||
| 	def test_delivery_note_no_gl_entry(self): | ||||
| 		self.clear_stock_account_balance() | ||||
| 		webnotes.defaults.set_global_default("auto_accounting_for_stock", 0) | ||||
| 		set_perpetual_inventory(0) | ||||
| 		self.assertEqual(cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")), 0) | ||||
| 		 | ||||
| 		self._insert_purchase_receipt() | ||||
| @ -65,8 +65,7 @@ class TestDeliveryNote(unittest.TestCase): | ||||
| 		 | ||||
| 	def test_delivery_note_gl_entry(self): | ||||
| 		self.clear_stock_account_balance() | ||||
| 		 | ||||
| 		webnotes.defaults.set_global_default("auto_accounting_for_stock", 1) | ||||
| 		set_perpetual_inventory() | ||||
| 		self.assertEqual(cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")), 1) | ||||
| 		webnotes.conn.set_value("Item", "_Test Item", "valuation_method", "FIFO") | ||||
| 		 | ||||
| @ -76,8 +75,8 @@ class TestDeliveryNote(unittest.TestCase): | ||||
| 		dn.doclist[1].expense_account = "Cost of Goods Sold - _TC" | ||||
| 		dn.doclist[1].cost_center = "Main - _TC" | ||||
| 
 | ||||
| 		stock_in_hand_account = webnotes.conn.get_value("Warehouse", dn.doclist[1].warehouse,  | ||||
| 			"account") | ||||
| 		stock_in_hand_account = webnotes.conn.get_value("Account",  | ||||
| 			{"master_name": dn.doclist[1].warehouse}) | ||||
| 		 | ||||
| 		from accounts.utils import get_balance_on | ||||
| 		prev_bal = get_balance_on(stock_in_hand_account, dn.doc.posting_date) | ||||
| @ -118,12 +117,11 @@ class TestDeliveryNote(unittest.TestCase): | ||||
| 					 | ||||
| 		dn.cancel() | ||||
| 		self.assertFalse(get_gl_entries("Delivery Note", dn.doc.name)) | ||||
| 		 | ||||
| 		webnotes.defaults.set_global_default("auto_accounting_for_stock", 0) | ||||
| 		set_perpetual_inventory(0) | ||||
| 			 | ||||
| 	def test_delivery_note_gl_entry_packing_item(self): | ||||
| 		self.clear_stock_account_balance() | ||||
| 		webnotes.defaults.set_global_default("auto_accounting_for_stock", 1) | ||||
| 		set_perpetual_inventory() | ||||
| 		 | ||||
| 		self._insert_purchase_receipt() | ||||
| 		self._insert_purchase_receipt("_Test Item Home Desktop 100") | ||||
| @ -132,8 +130,8 @@ class TestDeliveryNote(unittest.TestCase): | ||||
| 		dn.doclist[1].item_code = "_Test Sales BOM Item" | ||||
| 		dn.doclist[1].qty = 1 | ||||
| 	 | ||||
| 		stock_in_hand_account = webnotes.conn.get_value("Warehouse", dn.doclist[1].warehouse,  | ||||
| 			"account") | ||||
| 		stock_in_hand_account = webnotes.conn.get_value("Account",  | ||||
| 			{"master_name": dn.doclist[1].warehouse}) | ||||
| 		 | ||||
| 		from accounts.utils import get_balance_on | ||||
| 		prev_bal = get_balance_on(stock_in_hand_account, dn.doc.posting_date) | ||||
| @ -158,7 +156,7 @@ class TestDeliveryNote(unittest.TestCase): | ||||
| 		dn.cancel() | ||||
| 		self.assertFalse(get_gl_entries("Delivery Note", dn.doc.name)) | ||||
| 		 | ||||
| 		webnotes.defaults.set_global_default("auto_accounting_for_stock", 0) | ||||
| 		set_perpetual_inventory(0) | ||||
| 		 | ||||
| 	def test_serialized(self): | ||||
| 		from stock.doctype.stock_entry.test_stock_entry import make_serialized_item | ||||
|  | ||||
| @ -12,8 +12,8 @@ from accounts.utils import get_stock_and_account_difference | ||||
| 
 | ||||
| class TestPurchaseReceipt(unittest.TestCase): | ||||
| 	def test_make_purchase_invoice(self): | ||||
| 		webnotes.defaults.set_global_default("auto_accounting_for_stock", 0) | ||||
| 		self._clear_stock_account_balance() | ||||
| 		set_perpetual_inventory(0) | ||||
| 		from stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice | ||||
| 
 | ||||
| 		pr = webnotes.bean(copy=test_records[0]).insert() | ||||
| @ -33,8 +33,8 @@ class TestPurchaseReceipt(unittest.TestCase): | ||||
| 		self.assertRaises(webnotes.ValidationError, webnotes.bean(pi).submit) | ||||
| 		 | ||||
| 	def test_purchase_receipt_no_gl_entry(self): | ||||
| 		webnotes.defaults.set_global_default("auto_accounting_for_stock", 0) | ||||
| 		self._clear_stock_account_balance() | ||||
| 		set_perpetual_inventory(0) | ||||
| 		pr = webnotes.bean(copy=test_records[0]) | ||||
| 		pr.insert() | ||||
| 		pr.submit() | ||||
| @ -53,11 +53,11 @@ class TestPurchaseReceipt(unittest.TestCase): | ||||
| 		self.assertFalse(get_gl_entries("Purchase Receipt", pr.doc.name)) | ||||
| 		 | ||||
| 	def test_purchase_receipt_gl_entry(self): | ||||
| 		webnotes.defaults.set_global_default("auto_accounting_for_stock", 1) | ||||
| 		self.assertEqual(cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")), 1) | ||||
| 		 | ||||
| 		self._clear_stock_account_balance() | ||||
| 		 | ||||
| 		set_perpetual_inventory() | ||||
| 		self.assertEqual(cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")), 1) | ||||
| 		 | ||||
| 		pr = webnotes.bean(copy=test_records[0]) | ||||
| 		pr.insert() | ||||
| 		pr.submit() | ||||
| @ -66,10 +66,10 @@ class TestPurchaseReceipt(unittest.TestCase): | ||||
| 		 | ||||
| 		self.assertTrue(gl_entries) | ||||
| 		 | ||||
| 		stock_in_hand_account = webnotes.conn.get_value("Warehouse", pr.doclist[1].warehouse,  | ||||
| 			"account")		 | ||||
| 		fixed_asset_account = webnotes.conn.get_value("Warehouse", pr.doclist[2].warehouse,  | ||||
| 			"account") | ||||
| 		stock_in_hand_account = webnotes.conn.get_value("Account",  | ||||
| 			{"master_name": pr.doclist[1].warehouse})		 | ||||
| 		fixed_asset_account = webnotes.conn.get_value("Account",  | ||||
| 			{"master_name": pr.doclist[2].warehouse}) | ||||
| 		 | ||||
| 		expected_values = { | ||||
| 			stock_in_hand_account: [375.0, 0.0], | ||||
| @ -84,7 +84,7 @@ class TestPurchaseReceipt(unittest.TestCase): | ||||
| 		pr.cancel() | ||||
| 		self.assertFalse(get_gl_entries("Purchase Receipt", pr.doc.name)) | ||||
| 		 | ||||
| 		webnotes.defaults.set_global_default("auto_accounting_for_stock", 0) | ||||
| 		set_perpetual_inventory(0) | ||||
| 		 | ||||
| 	def _clear_stock_account_balance(self): | ||||
| 		webnotes.conn.sql("delete from `tabStock Ledger Entry`") | ||||
| @ -123,6 +123,10 @@ def get_gl_entries(voucher_type, voucher_no): | ||||
| 		from `tabGL Entry` where voucher_type=%s and voucher_no=%s | ||||
| 		order by account desc""", (voucher_type, voucher_no), as_dict=1) | ||||
| 		 | ||||
| def set_perpetual_inventory(enable=1): | ||||
| 	accounts_settings = webnotes.bean("Accounts Settings") | ||||
| 	accounts_settings.doc.auto_accounting_for_stock = enable | ||||
| 	accounts_settings.save() | ||||
| 	 | ||||
| 		 | ||||
| test_dependencies = ["BOM"] | ||||
|  | ||||
| @ -6,18 +6,18 @@ test_records = [ | ||||
| 		"doctype": "Warehouse", | ||||
| 		"warehouse_name": "_Test Warehouse", | ||||
| 		"company": "_Test Company",  | ||||
| 		"account": "_Test Account Stock In Hand - _TC" | ||||
| 		"create_account_under": "Stock Assets - _TC" | ||||
| 	}], | ||||
| 	[{ | ||||
| 		"doctype": "Warehouse", | ||||
| 		"warehouse_name": "_Test Warehouse 1", | ||||
| 		"company": "_Test Company", | ||||
| 		"account": "_Test Account Fixed Assets - _TC" | ||||
| 		"create_account_under": "Fixed Assets - _TC" | ||||
| 	}], | ||||
| 	[{ | ||||
| 		"doctype": "Warehouse", | ||||
| 		"warehouse_name": "_Test Warehouse 2", | ||||
| 		"account": "_Test Account Stock In Hand - _TC1", | ||||
| 		"create_account_under": "Stock Assets - _TC", | ||||
| 		"company": "_Test Company 1" | ||||
| 	}, { | ||||
| 		"doctype": "Warehouse User", | ||||
|  | ||||
| @ -17,12 +17,12 @@ cur_frm.cscript.merge = function(doc, cdt, cdn) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| cur_frm.set_query("account", function() { | ||||
| cur_frm.set_query("create_account_under", function() { | ||||
| 	return { | ||||
| 		filters: { | ||||
| 			"company": cur_frm.doc.company, | ||||
| 			"debit_or_credit": "Debit", | ||||
| 			'group_or_ledger': "Ledger" | ||||
| 			'group_or_ledger': "Group" | ||||
| 		} | ||||
| 	} | ||||
| }) | ||||
|  | ||||
| @ -6,7 +6,7 @@ import webnotes | ||||
| 
 | ||||
| from webnotes.utils import cint, flt, validate_email_add | ||||
| from webnotes.model.code import get_obj | ||||
| from webnotes import msgprint | ||||
| from webnotes import msgprint, _ | ||||
| 
 | ||||
| sql = webnotes.conn.sql | ||||
| 
 | ||||
| @ -24,20 +24,46 @@ class DocType: | ||||
| 		if self.doc.email_id and not validate_email_add(self.doc.email_id): | ||||
| 				msgprint("Please enter valid Email Id", raise_exception=1) | ||||
| 		 | ||||
| 		self.account_mandatory() | ||||
| 		self.validate_parent_account() | ||||
| 				 | ||||
| 	def account_mandatory(self): | ||||
| 	def on_update(self): | ||||
| 		self.create_account_head() | ||||
| 						 | ||||
| 	def create_account_head(self): | ||||
| 		if cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")): | ||||
| 			sle_exists = webnotes.conn.get_value("Stock Ledger Entry", {"warehouse": self.doc.name}) | ||||
| 			if not self.doc.account and (self.doc.__islocal or not sle_exists): | ||||
| 				webnotes.throw(_("Asset/Expense Account mandatory")) | ||||
| 			if not webnotes.conn.get_value("Account", {"account_type": "Warehouse",  | ||||
| 					"master_name": self.doc.name}): | ||||
| 				if self.doc.__islocal or not webnotes.conn.get_value("Stock Ledger Entry",  | ||||
| 						{"warehouse": self.doc.name}): | ||||
| 					ac_bean = webnotes.bean({ | ||||
| 						"doctype": "Account", | ||||
| 						'account_name': self.doc.warehouse_name,  | ||||
| 						'parent_account': self.doc.create_account_under,  | ||||
| 						'group_or_ledger':'Ledger',  | ||||
| 						'company':self.doc.company,  | ||||
| 						"account_type": "Warehouse", | ||||
| 						"master_name": self.doc.name, | ||||
| 						"freeze_account": "No" | ||||
| 					}) | ||||
| 					ac_bean.ignore_permissions = True | ||||
| 					ac_bean.insert() | ||||
| 					 | ||||
| 			if not self.doc.__islocal and sle_exists: | ||||
| 				old_account = webnotes.conn.get_value("Warehouse", self.doc.name, "account") | ||||
| 				if old_account != self.doc.account: | ||||
| 					webnotes.throw(_("Account can not be changed/assigned/removed as \ | ||||
| 						stock transactions exist for this warehouse")) | ||||
| 					msgprint(_("Account Head") + ": " + ac_bean.doc.name + _(" created")) | ||||
| 	 | ||||
| 	def validate_parent_account(self): | ||||
| 		if cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")) and \ | ||||
| 			not self.doc.create_account_under: | ||||
| 				parent_account = webnotes.conn.get_value("Account",  | ||||
| 					{"account_name": "Stock Assets", "company": self.doc.company}) | ||||
| 				if parent_account: | ||||
| 					self.doc.create_account_under = parent_account | ||||
| 				else: | ||||
| 					webnotes.throw(_("Please enter account group under which account \ | ||||
| 						for warehouse ") + self.doc.name +_(" will be created")) | ||||
| 			 | ||||
| 	def on_rename(self, new, old): | ||||
| 		webnotes.conn.set_value("Account", {"account_type": "Warehouse", "master_name": old},  | ||||
| 			"master_name", new) | ||||
| 
 | ||||
| 	def merge_warehouses(self): | ||||
| 		webnotes.conn.auto_commit_on_many_writes = 1 | ||||
| @ -52,6 +78,15 @@ class DocType: | ||||
| 		link_fields = rename_doc.get_link_fields('Warehouse') | ||||
| 		rename_doc.update_link_field_values(link_fields, self.doc.name, self.doc.merge_with) | ||||
| 		 | ||||
| 		account_link_fields = rename_doc.get_link_fields('Account') | ||||
| 		old_warehouse_account = webnotes.conn.get_value("Account", {"master_name": self.doc.name}) | ||||
| 		new_warehouse_account = webnotes.conn.get_value("Account",  | ||||
| 			{"master_name": self.doc.merge_with}) | ||||
| 		rename_doc.update_link_field_values(account_link_fields, old_warehouse_account,  | ||||
| 			new_warehouse_account) | ||||
| 			 | ||||
| 		webnotes.conn.delete_doc("Account", old_warehouse_account) | ||||
| 		 | ||||
| 		for item_code in items: | ||||
| 			self.repost(item_code[0], self.doc.merge_with) | ||||
| 			 | ||||
| @ -160,6 +195,11 @@ class DocType: | ||||
| 			else: | ||||
| 				sql("delete from `tabBin` where name = %s", d['name']) | ||||
| 				 | ||||
| 		warehouse_account = webnotes.conn.get_value("Account",  | ||||
| 			{"account_type": "Warehosue", "master_name": self.doc.name}) | ||||
| 		if warehouse_account: | ||||
| 			webnotes.delete_doc("Account", warehouse_account) | ||||
| 				 | ||||
| 		# delete cancelled sle | ||||
| 		if sql("""select name from `tabStock Ledger Entry` where warehouse = %s""", self.doc.name): | ||||
| 			msgprint("""Warehosue can not be deleted as stock ledger entry  | ||||
|  | ||||
| @ -2,7 +2,7 @@ | ||||
|  { | ||||
|   "creation": "2013-03-07 18:50:32",  | ||||
|   "docstatus": 0,  | ||||
|   "modified": "2013-08-01 15:27:49",  | ||||
|   "modified": "2013-09-16 10:45:49",  | ||||
|   "modified_by": "Administrator",  | ||||
|   "owner": "Administrator" | ||||
|  },  | ||||
| @ -28,9 +28,9 @@ | ||||
|   "parent": "Warehouse",  | ||||
|   "parentfield": "permissions",  | ||||
|   "parenttype": "DocType",  | ||||
|   "permlevel": 0,  | ||||
|   "read": 1,  | ||||
|   "report": 1,  | ||||
|   "submit": 0 | ||||
|   "report": 1 | ||||
|  },  | ||||
|  { | ||||
|   "doctype": "DocType",  | ||||
| @ -71,11 +71,12 @@ | ||||
|   "search_index": 1 | ||||
|  },  | ||||
|  { | ||||
|   "description": "This account will be used for perpetual accounting for inventory e.g. Stock-in-Hand, Fixed Asset Account etc",  | ||||
|   "depends_on": "eval:sys_defaults.auto_accounting_for_stock",  | ||||
|   "description": "Account for the warehouse (Perpetual Inventory) will be created under this Account.",  | ||||
|   "doctype": "DocField",  | ||||
|   "fieldname": "account",  | ||||
|   "fieldname": "create_account_under",  | ||||
|   "fieldtype": "Link",  | ||||
|   "label": "Account",  | ||||
|   "label": "Create Account Under",  | ||||
|   "options": "Account",  | ||||
|   "permlevel": 0 | ||||
|  },  | ||||
| @ -231,16 +232,8 @@ | ||||
|   "cancel": 1,  | ||||
|   "create": 1,  | ||||
|   "doctype": "DocPerm",  | ||||
|   "permlevel": 0,  | ||||
|   "role": "Material Master Manager",  | ||||
|   "write": 1 | ||||
|  },  | ||||
|  { | ||||
|   "cancel": 1,  | ||||
|   "create": 1,  | ||||
|   "doctype": "DocPerm",  | ||||
|   "permlevel": 0,  | ||||
|   "role": "System Manager",  | ||||
|   "submit": 0,  | ||||
|   "write": 1 | ||||
|  },  | ||||
|  { | ||||
| @ -248,26 +241,20 @@ | ||||
|   "cancel": 0,  | ||||
|   "create": 0,  | ||||
|   "doctype": "DocPerm",  | ||||
|   "permlevel": 0,  | ||||
|   "role": "Material Manager",  | ||||
|   "write": 0 | ||||
|  },  | ||||
|  { | ||||
|   "amend": 0,  | ||||
|   "cancel": 0,  | ||||
|   "create": 0,  | ||||
|   "doctype": "DocPerm",  | ||||
|   "permlevel": 0,  | ||||
|   "role": "Material User",  | ||||
|   "submit": 0,  | ||||
|   "write": 0 | ||||
|  },  | ||||
|  { | ||||
|   "amend": 0,  | ||||
|   "cancel": 0,  | ||||
|   "create": 0,  | ||||
|   "doctype": "DocPerm",  | ||||
|   "permlevel": 2,  | ||||
|   "role": "System Manager",  | ||||
|   "write": 1 | ||||
|   "role": "Sales User" | ||||
|  },  | ||||
|  { | ||||
|   "doctype": "DocPerm",  | ||||
|   "role": "Purchase User" | ||||
|  },  | ||||
|  { | ||||
|   "doctype": "DocPerm",  | ||||
|   "role": "Accounts User" | ||||
|  } | ||||
| ] | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user