Merge branch 'v4.x.x'
This commit is contained in:
		
						commit
						397a2bf1d0
					
				| @ -1,2 +1,2 @@ | ||||
| from __future__ import unicode_literals | ||||
| __version__ = '4.25.2' | ||||
| __version__ = '4.25.3' | ||||
|  | ||||
| @ -6,6 +6,7 @@ import frappe | ||||
| import frappe.defaults | ||||
| from frappe.utils import flt | ||||
| from erpnext.accounts.utils import get_balance_on | ||||
| from erpnext.accounts.report.financial_statements import sort_root_accounts | ||||
| 
 | ||||
| @frappe.whitelist() | ||||
| def get_companies(): | ||||
| @ -21,12 +22,15 @@ def get_children(): | ||||
| 	# root | ||||
| 	if args['parent'] in ("Accounts", "Cost Centers"): | ||||
| 		acc = frappe.db.sql(""" select  | ||||
| 			name as value, if(group_or_ledger='Group', 1, 0) as expandable | ||||
| 			name as value, if(group_or_ledger='Group', 1, 0) as expandable, root_type, report_type | ||||
| 			from `tab%s` | ||||
| 			where ifnull(parent_%s,'') = '' | ||||
| 			and `company` = %s	and docstatus<2  | ||||
| 			order by name""" % (ctype, ctype.lower().replace(' ','_'), '%s'), | ||||
| 				company, as_dict=1) | ||||
| 				 | ||||
| 		if args["parent"]=="Accounts": | ||||
| 			sort_root_accounts(acc) | ||||
| 	else:	 | ||||
| 		# other | ||||
| 		acc = frappe.db.sql("""select  | ||||
|  | ||||
| @ -186,7 +186,10 @@ def filter_accounts(accounts, depth=10): | ||||
| 	filtered_accounts = [] | ||||
| 	def add_to_list(parent, level): | ||||
| 		if level < depth: | ||||
| 			for child in (parent_children_map.get(parent) or []): | ||||
| 			children = parent_children_map.get(parent) or [] | ||||
| 			if parent == None: | ||||
| 				sort_root_accounts(children) | ||||
| 			for child in children: | ||||
| 				child.indent = level | ||||
| 				filtered_accounts.append(child) | ||||
| 				add_to_list(child.name, level + 1) | ||||
| @ -202,6 +205,22 @@ def filter_accounts(accounts, depth=10): | ||||
| 	add_to_list(None, 0) | ||||
| 
 | ||||
| 	return filtered_accounts, accounts_by_name | ||||
| 	 | ||||
| def sort_root_accounts(roots): | ||||
| 	"""Sort root types as Asset, Liability, Equity, Income, Expense""" | ||||
| 
 | ||||
| 	def compare_roots(a, b): | ||||
| 		if a.report_type != b.report_type and a.report_type == "Balance Sheet": | ||||
| 			return -1 | ||||
| 		if a.root_type != b.root_type and a.root_type == "Asset": | ||||
| 			return -1 | ||||
| 		if a.root_type == "Liability" and b.root_type == "Equity": | ||||
| 			return -1 | ||||
| 		if a.root_type == "Income" and b.root_type == "Expense": | ||||
| 			return -1 | ||||
| 		return 1 | ||||
| 
 | ||||
| 	roots.sort(compare_roots) | ||||
| 
 | ||||
| def get_gl_entries(company, from_date, to_date, root_lft, root_rgt, ignore_closing_entries=False): | ||||
| 	"""Returns a dict like { "account": [gl entries], ... }""" | ||||
|  | ||||
| @ -123,7 +123,8 @@ def accumulate_values_into_parents(accounts, accounts_by_name): | ||||
| def prepare_data(accounts, filters, total_row): | ||||
| 	show_zero_values = cint(filters.show_zero_values) | ||||
| 	data = [] | ||||
| 	for i, d in enumerate(accounts): | ||||
| 	accounts_with_zero_value = [] | ||||
| 	for d in accounts: | ||||
| 		has_value = False | ||||
| 		row = { | ||||
| 			"account_name": d.account_name, | ||||
| @ -140,9 +141,14 @@ def prepare_data(accounts, filters, total_row): | ||||
| 			row[key] = d.get(key, 0.0) | ||||
| 			if row[key]: | ||||
| 				has_value = True | ||||
| 
 | ||||
| 		if has_value or show_zero_values: | ||||
| 		 | ||||
| 		if show_zero_values: | ||||
| 			data.append(row) | ||||
| 		else: | ||||
| 			if not has_value: | ||||
| 				accounts_with_zero_value.append(d.name) | ||||
| 			elif d.parent_account not in accounts_with_zero_value: | ||||
| 				data.append(row) | ||||
| 
 | ||||
| 	data.extend([{},total_row]) | ||||
| 
 | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| 
 | ||||
| from __future__ import unicode_literals | ||||
| import frappe | ||||
| from frappe.utils import flt | ||||
| from frappe.utils import flt, cstr | ||||
| from frappe import _ | ||||
| 
 | ||||
| from erpnext.stock.doctype.item.item import get_last_purchase_details | ||||
| @ -64,7 +64,7 @@ class PurchaseCommon(BuyingController): | ||||
| 							= d.rate = item_last_purchase_rate | ||||
| 
 | ||||
| 	def validate_for_items(self, obj): | ||||
| 		check_list, chk_dupl_itm=[],[] | ||||
| 		items = [] | ||||
| 		for d in obj.get(obj.fname): | ||||
| 			# validation for valid qty | ||||
| 			if flt(d.qty) < 0 or (d.parenttype != 'Purchase Receipt' and not flt(d.qty)): | ||||
| @ -96,30 +96,10 @@ class PurchaseCommon(BuyingController): | ||||
| 				if item[0][1] != 'Yes' and item[0][2] != 'Yes': | ||||
| 					frappe.throw(_("{0} must be a Purchased or Sub-Contracted Item in row {1}").format(d.item_code, d.idx)) | ||||
| 
 | ||||
| 			# list criteria that should not repeat if item is stock item | ||||
| 			e = [getattr(d, "schedule_date", None), d.item_code, d.description, d.warehouse, d.uom, | ||||
| 				d.meta.get_field('prevdoc_docname') and d.prevdoc_docname or d.meta.get_field('sales_order_no') and d.sales_order_no or '', | ||||
| 				d.meta.get_field('prevdoc_detail_docname') and d.prevdoc_detail_docname or '', | ||||
| 				d.meta.get_field('batch_no') and d.batch_no or ''] | ||||
| 
 | ||||
| 			# if is not stock item | ||||
| 			f = [getattr(d, "schedule_date", None), d.item_code, d.description] | ||||
| 
 | ||||
| 			ch = frappe.db.sql("""select is_stock_item from `tabItem` where name = %s""", d.item_code) | ||||
| 
 | ||||
| 			if ch and ch[0][0] == 'Yes': | ||||
| 				# check for same items | ||||
| 				if e in check_list: | ||||
| 					frappe.throw(_("Item {0} has been entered multiple times with same description or date or warehouse").format(d.item_code)) | ||||
| 				else: | ||||
| 					check_list.append(e) | ||||
| 
 | ||||
| 			elif ch and ch[0][0] == 'No': | ||||
| 				# check for same items | ||||
| 				if f in chk_dupl_itm: | ||||
| 					frappe.throw(_("Item {0} has been entered multiple times with same description or date").format(d.item_code)) | ||||
| 				else: | ||||
| 					chk_dupl_itm.append(f) | ||||
| 			items.append(cstr(d.item_code)) | ||||
| 			if items and len(items) != len(set(items)): | ||||
| 				frappe.msgprint(_("Warning: Same item has been entered multiple times.")) | ||||
| 			 | ||||
| 
 | ||||
| 	def check_for_stopped_status(self, doctype, docname): | ||||
| 		stopped = frappe.db.sql("""select name from `tab%s` where name = %s and | ||||
|  | ||||
| @ -5,7 +5,7 @@ app_publisher = "Web Notes Technologies Pvt. Ltd. and Contributors" | ||||
| app_description = "Open Source Enterprise Resource Planning for Small and Midsized Organizations" | ||||
| app_icon = "icon-th" | ||||
| app_color = "#e74c3c" | ||||
| app_version = "4.25.2" | ||||
| app_version = "4.25.3" | ||||
| 
 | ||||
| error_report_email = "support@erpnext.com" | ||||
| 
 | ||||
|  | ||||
| @ -254,8 +254,10 @@ class ProductionPlanningTool(Document): | ||||
| 					ifnull(sum(ifnull(fb.qty, 0)/ifnull(bom.quantity, 1)), 0) as qty, | ||||
| 					fb.description, fb.stock_uom, it.min_order_qty | ||||
| 					from `tabBOM Explosion Item` fb, `tabBOM` bom, `tabItem` it | ||||
| 					where bom.name = fb.parent and it.name = fb.item_code and ifnull(it.is_pro_applicable, 'No') = 'No' | ||||
| 					where bom.name = fb.parent and it.name = fb.item_code  | ||||
| 					and ifnull(it.is_pro_applicable, 'No') = 'No' | ||||
| 					and ifnull(it.is_sub_contracted_item, 'No') = 'No' | ||||
| 					and ifnull(it.is_stock_item, 'No') = 'Yes' | ||||
| 					and fb.docstatus<2 and bom.name=%s | ||||
| 					group by item_code, stock_uom""", bom, as_dict=1): | ||||
| 						bom_wise_item_details.setdefault(d.item_code, d) | ||||
| @ -268,6 +270,7 @@ class ProductionPlanningTool(Document): | ||||
| 					from `tabBOM Item` bom_item, `tabBOM` bom, tabItem item | ||||
| 					where bom.name = bom_item.parent and bom.name = %s and bom_item.docstatus < 2 | ||||
| 					and bom_item.item_code = item.name | ||||
| 					and ifnull(item.is_stock_item, 'No') = 'Yes' | ||||
| 					group by item_code""", bom, as_dict=1): | ||||
| 						bom_wise_item_details.setdefault(d.item_code, d) | ||||
| 
 | ||||
|  | ||||
| @ -9,19 +9,20 @@ from frappe.utils import flt, cint | ||||
| def execute(filters=None): | ||||
| 	if not filters: filters = {} | ||||
| 
 | ||||
| 	float_precision = cint(frappe.db.get_default("float_precision")) or 3 | ||||
| 	 | ||||
| 	columns = get_columns(filters) | ||||
| 	item_map = get_item_details(filters) | ||||
| 	iwb_map = get_item_warehouse_batch_map(filters) | ||||
| 	iwb_map = get_item_warehouse_batch_map(filters, float_precision) | ||||
| 
 | ||||
| 	data = [] | ||||
| 	for item in sorted(iwb_map): | ||||
| 		for wh in sorted(iwb_map[item]): | ||||
| 			for batch in sorted(iwb_map[item][wh]): | ||||
| 				qty_dict = iwb_map[item][wh][batch] | ||||
| 				data.append([item, item_map[item]["item_name"], | ||||
| 					item_map[item]["description"], wh, batch, | ||||
| 					qty_dict.opening_qty, qty_dict.in_qty, | ||||
| 					qty_dict.out_qty, qty_dict.bal_qty | ||||
| 				data.append([item, item_map[item]["item_name"], item_map[item]["description"], wh, batch, | ||||
| 					flt(qty_dict.opening_qty, float_precision), flt(qty_dict.in_qty, float_precision), | ||||
| 					flt(qty_dict.out_qty, float_precision), flt(qty_dict.bal_qty, float_precision) | ||||
| 				]) | ||||
| 
 | ||||
| 	return columns, data | ||||
| @ -56,8 +57,7 @@ def get_stock_ledger_entries(filters): | ||||
| 		where docstatus < 2 %s order by item_code, warehouse""" % | ||||
| 		conditions, as_dict=1) | ||||
| 
 | ||||
| def get_item_warehouse_batch_map(filters): | ||||
| 	float_precision = cint(frappe.db.get_default("float_precision")) or 3 | ||||
| def get_item_warehouse_batch_map(filters, float_precision): | ||||
| 	sle = get_stock_ledger_entries(filters) | ||||
| 	iwb_map = {} | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user