Merge branch 'develop' of https://github.com/frappe/erpnext into loan_top_up_fixes
This commit is contained in:
		
						commit
						a2249e013d
					
				| @ -302,10 +302,10 @@ | ||||
|    "fieldname": "warehouse", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Warehouse", | ||||
|    "mandatory_depends_on": "update_stock", | ||||
|    "oldfieldname": "warehouse", | ||||
|    "oldfieldtype": "Link", | ||||
|    "options": "Warehouse", | ||||
|    "reqd": 1 | ||||
|    "options": "Warehouse" | ||||
|   }, | ||||
|   { | ||||
|    "default": "0", | ||||
| @ -350,4 +350,4 @@ | ||||
|  ], | ||||
|  "sort_field": "modified", | ||||
|  "sort_order": "DESC" | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -1619,22 +1619,23 @@ def update_multi_mode_option(doc, pos_profile): | ||||
| 
 | ||||
| 	for pos_payment_method in pos_profile.get('payments'): | ||||
| 		pos_payment_method = pos_payment_method.as_dict() | ||||
| 		 | ||||
| 
 | ||||
| 		payment_mode = get_mode_of_payment_info(pos_payment_method.mode_of_payment, doc.company) | ||||
| 		payment_mode[0].default = pos_payment_method.default | ||||
| 		append_payment(payment_mode[0]) | ||||
| 		if payment_mode: | ||||
| 			payment_mode[0].default = pos_payment_method.default | ||||
| 			append_payment(payment_mode[0]) | ||||
| 
 | ||||
| def get_all_mode_of_payments(doc): | ||||
| 	return frappe.db.sql(""" | ||||
| 		select mpa.default_account, mpa.parent, mp.type as type  | ||||
| 		from `tabMode of Payment Account` mpa,`tabMode of Payment` mp  | ||||
| 		select mpa.default_account, mpa.parent, mp.type as type | ||||
| 		from `tabMode of Payment Account` mpa,`tabMode of Payment` mp | ||||
| 		where mpa.parent = mp.name and mpa.company = %(company)s and mp.enabled = 1""", | ||||
| 	{'company': doc.company}, as_dict=1) | ||||
| 
 | ||||
| def get_mode_of_payment_info(mode_of_payment, company): | ||||
| 	return frappe.db.sql(""" | ||||
| 		select mpa.default_account, mpa.parent, mp.type as type  | ||||
| 		from `tabMode of Payment Account` mpa,`tabMode of Payment` mp  | ||||
| 		select mpa.default_account, mpa.parent, mp.type as type | ||||
| 		from `tabMode of Payment Account` mpa,`tabMode of Payment` mp | ||||
| 		where mpa.parent = mp.name and mpa.company = %s and mp.enabled = 1 and mp.name = %s""", | ||||
| 	(company, mode_of_payment), as_dict=1) | ||||
| 
 | ||||
|  | ||||
| @ -206,10 +206,19 @@ class TestSalesInvoice(unittest.TestCase): | ||||
| 			"rate": 14, | ||||
| 			'included_in_print_rate': 1 | ||||
| 		}) | ||||
| 		si.append("taxes", { | ||||
| 			"charge_type": "On Item Quantity", | ||||
| 			"account_head": "_Test Account Education Cess - _TC", | ||||
| 			"cost_center": "_Test Cost Center - _TC", | ||||
| 			"description": "CESS", | ||||
| 			"rate": 5, | ||||
| 			'included_in_print_rate': 1 | ||||
| 		}) | ||||
| 		si.insert() | ||||
| 
 | ||||
| 		# with inclusive tax | ||||
| 		self.assertEqual(si.net_total, 4385.96) | ||||
| 		self.assertEqual(si.items[0].net_amount, 3947.368421052631) | ||||
| 		self.assertEqual(si.net_total, 3947.37) | ||||
| 		self.assertEqual(si.grand_total, 5000) | ||||
| 
 | ||||
| 		si.reload() | ||||
| @ -222,8 +231,8 @@ class TestSalesInvoice(unittest.TestCase): | ||||
| 		si.save() | ||||
| 
 | ||||
| 		# with inclusive tax and additional discount | ||||
| 		self.assertEqual(si.net_total, 4285.96) | ||||
| 		self.assertEqual(si.grand_total, 4885.99) | ||||
| 		self.assertEqual(si.net_total, 3847.37) | ||||
| 		self.assertEqual(si.grand_total, 4886) | ||||
| 
 | ||||
| 		si.reload() | ||||
| 
 | ||||
| @ -235,7 +244,7 @@ class TestSalesInvoice(unittest.TestCase): | ||||
| 		si.save() | ||||
| 
 | ||||
| 		# with inclusive tax and additional discount | ||||
| 		self.assertEqual(si.net_total, 4298.25) | ||||
| 		self.assertEqual(si.net_total, 3859.65) | ||||
| 		self.assertEqual(si.grand_total, 4900.00) | ||||
| 
 | ||||
| 	def test_sales_invoice_discount_amount(self): | ||||
|  | ||||
| @ -11,7 +11,7 @@ from erpnext.assets.doctype.asset_maintenance.asset_maintenance import calculate | ||||
| 
 | ||||
| class AssetMaintenanceLog(Document): | ||||
| 	def validate(self): | ||||
| 		if getdate(self.due_date) < getdate(nowdate()): | ||||
| 		if getdate(self.due_date) < getdate(nowdate()) and self.maintenance_status not in ["Completed", "Cancelled"]: | ||||
| 			self.maintenance_status = "Overdue" | ||||
| 
 | ||||
| 		if self.maintenance_status == "Completed" and not self.completion_date: | ||||
|  | ||||
| @ -1,14 +1,15 @@ | ||||
| frappe.listview_settings['Asset Maintenance Log'] = { | ||||
| 	add_fields: ["maintenance_status"], | ||||
| 	has_indicator_for_draft: 1, | ||||
| 	get_indicator: function(doc) { | ||||
| 		if(doc.maintenance_status=="Pending") { | ||||
| 			return [__("Pending"), "orange"]; | ||||
| 		} else if(doc.maintenance_status=="Completed") { | ||||
| 			return [__("Completed"), "green"]; | ||||
| 		} else if(doc.maintenance_status=="Cancelled") { | ||||
| 			return [__("Cancelled"), "red"]; | ||||
| 		} else if(doc.maintenance_status=="Overdue") { | ||||
| 			return [__("Overdue"), "red"]; | ||||
| 		if (doc.maintenance_status=="Planned") { | ||||
| 			return [__(doc.maintenance_status), "orange", "status,=," + doc.maintenance_status]; | ||||
| 		} else if (doc.maintenance_status=="Completed") { | ||||
| 			return [__(doc.maintenance_status), "green", "status,=," + doc.maintenance_status]; | ||||
| 		} else if (doc.maintenance_status=="Cancelled") { | ||||
| 			return [__(doc.maintenance_status), "red", "status,=," + doc.maintenance_status]; | ||||
| 		} else if (doc.maintenance_status=="Overdue") { | ||||
| 			return [__(doc.maintenance_status), "red", "status,=," + doc.maintenance_status]; | ||||
| 		} | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| @ -94,7 +94,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend( | ||||
| 				if(this.frm.doc.status !== 'Closed' && flt(this.frm.doc.per_received) < 100 && flt(this.frm.doc.per_billed) < 100) { | ||||
| 					this.frm.add_custom_button(__('Update Items'), () => { | ||||
| 						erpnext.utils.update_child_items({ | ||||
| 							frm: frm, | ||||
| 							frm: this.frm, | ||||
| 							child_docname: "items", | ||||
| 							child_doctype: "Purchase Order Detail", | ||||
| 							cannot_add_row: false, | ||||
|  | ||||
| @ -985,7 +985,7 @@ def validate_inclusive_tax(tax, doc): | ||||
| 			# all rows about the reffered tax should be inclusive | ||||
| 			_on_previous_row_error("1 - %d" % (tax.row_id,)) | ||||
| 		elif tax.get("category") == "Valuation": | ||||
| 			frappe.throw(_("Valuation type charges can not marked as Inclusive")) | ||||
| 			frappe.throw(_("Valuation type charges can not be marked as Inclusive")) | ||||
| 
 | ||||
| 
 | ||||
| def set_balance_in_account_currency(gl_dict, account_currency=None, conversion_rate=None, company_currency=None): | ||||
|  | ||||
| @ -161,8 +161,9 @@ class calculate_taxes_and_totals(object): | ||||
| 		for item in self.doc.get("items"): | ||||
| 			item_tax_map = self._load_item_tax_rate(item.item_tax_rate) | ||||
| 			cumulated_tax_fraction = 0 | ||||
| 			total_inclusive_tax_amount_per_qty = 0 | ||||
| 			for i, tax in enumerate(self.doc.get("taxes")): | ||||
| 				tax.tax_fraction_for_current_item = self.get_current_tax_fraction(tax, item_tax_map) | ||||
| 				tax.tax_fraction_for_current_item, inclusive_tax_amount_per_qty = self.get_current_tax_fraction(tax, item_tax_map) | ||||
| 
 | ||||
| 				if i==0: | ||||
| 					tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item | ||||
| @ -172,9 +173,12 @@ class calculate_taxes_and_totals(object): | ||||
| 						+ tax.tax_fraction_for_current_item | ||||
| 
 | ||||
| 				cumulated_tax_fraction += tax.tax_fraction_for_current_item | ||||
| 				total_inclusive_tax_amount_per_qty += inclusive_tax_amount_per_qty * flt(item.qty) | ||||
| 
 | ||||
| 			if cumulated_tax_fraction and not self.discount_amount_applied and item.qty: | ||||
| 				item.net_amount = flt(item.amount / (1 + cumulated_tax_fraction)) | ||||
| 			if not self.discount_amount_applied and item.qty and (cumulated_tax_fraction or total_inclusive_tax_amount_per_qty): | ||||
| 				amount = flt(item.amount) - total_inclusive_tax_amount_per_qty | ||||
| 
 | ||||
| 				item.net_amount = flt(amount / (1 + cumulated_tax_fraction)) | ||||
| 				item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate")) | ||||
| 				item.discount_percentage = flt(item.discount_percentage, | ||||
| 					item.precision("discount_percentage")) | ||||
| @ -190,6 +194,7 @@ class calculate_taxes_and_totals(object): | ||||
| 			from tax inclusive amount | ||||
| 		""" | ||||
| 		current_tax_fraction = 0 | ||||
| 		inclusive_tax_amount_per_qty = 0 | ||||
| 
 | ||||
| 		if cint(tax.included_in_print_rate): | ||||
| 			tax_rate = self._get_tax_rate(tax, item_tax_map) | ||||
| @ -204,10 +209,15 @@ class calculate_taxes_and_totals(object): | ||||
| 			elif tax.charge_type == "On Previous Row Total": | ||||
| 				current_tax_fraction = (tax_rate / 100.0) * \ | ||||
| 					self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_fraction_for_current_item | ||||
| 			 | ||||
| 			elif tax.charge_type == "On Item Quantity": | ||||
| 				inclusive_tax_amount_per_qty = flt(tax_rate) | ||||
| 
 | ||||
| 		if getattr(tax, "add_deduct_tax", None): | ||||
| 			current_tax_fraction *= -1.0 if (tax.add_deduct_tax == "Deduct") else 1.0 | ||||
| 		return current_tax_fraction | ||||
| 		if getattr(tax, "add_deduct_tax", None) and tax.add_deduct_tax == "Deduct": | ||||
| 			current_tax_fraction *= -1.0 | ||||
| 			inclusive_tax_amount_per_qty *= -1.0 | ||||
| 
 | ||||
| 		return current_tax_fraction, inclusive_tax_amount_per_qty | ||||
| 
 | ||||
| 	def _get_tax_rate(self, tax, item_tax_map): | ||||
| 		if tax.account_head in item_tax_map: | ||||
| @ -321,7 +331,7 @@ class calculate_taxes_and_totals(object): | ||||
| 			current_tax_amount = (tax_rate / 100.0) * \ | ||||
| 				self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_for_current_item | ||||
| 		elif tax.charge_type == "On Item Quantity": | ||||
| 			current_tax_amount = tax_rate * item.stock_qty | ||||
| 			current_tax_amount = tax_rate * item.qty | ||||
| 
 | ||||
| 		self.set_item_wise_tax(item, tax, tax_rate, current_tax_amount) | ||||
| 
 | ||||
| @ -472,7 +482,7 @@ class calculate_taxes_and_totals(object): | ||||
| 			actual_taxes_dict = {} | ||||
| 
 | ||||
| 			for tax in self.doc.get("taxes"): | ||||
| 				if tax.charge_type == "Actual": | ||||
| 				if tax.charge_type in ["Actual", "On Item Quantity"]: | ||||
| 					tax_amount = self.get_tax_amount_if_for_valuation_or_deduction(tax.tax_amount, tax) | ||||
| 					actual_taxes_dict.setdefault(tax.idx, tax_amount) | ||||
| 				elif tax.row_id in actual_taxes_dict: | ||||
|  | ||||
| @ -50,9 +50,9 @@ | ||||
|   "contact_email", | ||||
|   "contact_mobile", | ||||
|   "more_info", | ||||
|   "company", | ||||
|   "campaign", | ||||
|   "column_break1", | ||||
|   "company", | ||||
|   "transaction_date", | ||||
|   "amended_from", | ||||
|   "lost_reasons" | ||||
| @ -344,7 +344,7 @@ | ||||
|    "collapsible": 1, | ||||
|    "fieldname": "more_info", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "Source", | ||||
|    "label": "More Information", | ||||
|    "oldfieldtype": "Section Break", | ||||
|    "options": "fa fa-file-text" | ||||
|   }, | ||||
| @ -411,7 +411,7 @@ | ||||
|    "fieldname": "lost_reasons", | ||||
|    "fieldtype": "Table MultiSelect", | ||||
|    "label": "Lost Reasons", | ||||
|    "options": "Lost Reason Detail", | ||||
|    "options": "Opportunity Lost Reason Detail", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
| @ -424,7 +424,7 @@ | ||||
|  "icon": "fa fa-info-sign", | ||||
|  "idx": 195, | ||||
|  "links": [], | ||||
|  "modified": "2020-08-11 14:49:13.496297", | ||||
|  "modified": "2020-08-11 17:34:35.066961", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "CRM", | ||||
|  "name": "Opportunity", | ||||
|  | ||||
| @ -0,0 +1,31 @@ | ||||
| { | ||||
|  "actions": [], | ||||
|  "creation": "2020-07-16 16:11:39.830389", | ||||
|  "doctype": "DocType", | ||||
|  "editable_grid": 1, | ||||
|  "engine": "InnoDB", | ||||
|  "field_order": [ | ||||
|   "lost_reason" | ||||
|  ], | ||||
|  "fields": [ | ||||
|   { | ||||
|    "fieldname": "lost_reason", | ||||
|    "fieldtype": "Link", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Opportunity Lost Reason", | ||||
|    "options": "Opportunity Lost Reason" | ||||
|   } | ||||
|  ], | ||||
|  "istable": 1, | ||||
|  "links": [], | ||||
|  "modified": "2020-07-26 17:58:26.313242", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "CRM", | ||||
|  "name": "Opportunity Lost Reason Detail", | ||||
|  "owner": "Administrator", | ||||
|  "permissions": [], | ||||
|  "quick_entry": 1, | ||||
|  "sort_field": "modified", | ||||
|  "sort_order": "DESC", | ||||
|  "track_changes": 1 | ||||
| } | ||||
| @ -0,0 +1,10 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors | ||||
| # For license information, please see license.txt | ||||
| 
 | ||||
| from __future__ import unicode_literals | ||||
| # import frappe | ||||
| from frappe.model.document import Document | ||||
| 
 | ||||
| class OpportunityLostReasonDetail(Document): | ||||
| 	pass | ||||
| @ -78,7 +78,7 @@ | ||||
|  "idx": 0, | ||||
|  "is_standard": 1, | ||||
|  "label": "HR", | ||||
|  "modified": "2020-06-16 19:20:50.976045", | ||||
|  "modified": "2020-08-11 17:04:38.655417", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "HR", | ||||
|  "name": "HR", | ||||
| @ -88,7 +88,7 @@ | ||||
|  "pin_to_top": 0, | ||||
|  "shortcuts": [ | ||||
|   { | ||||
|    "color": "#9deca2", | ||||
|    "color": "#cef6d1", | ||||
|    "format": "{} Active", | ||||
|    "label": "Employee", | ||||
|    "link_to": "Employee", | ||||
| @ -96,18 +96,19 @@ | ||||
|    "type": "DocType" | ||||
|   }, | ||||
|   { | ||||
|    "label": "Attendance", | ||||
|    "link_to": "Attendance", | ||||
|    "stats_filter": "", | ||||
|    "type": "DocType" | ||||
|   }, | ||||
|   { | ||||
|    "color": "#ffe8cd", | ||||
|    "format": "{} Open", | ||||
|    "label": "Leave Application", | ||||
|    "link_to": "Leave Application", | ||||
|    "stats_filter": "{\"status\":\"Open\"}", | ||||
|    "type": "DocType" | ||||
|   }, | ||||
|   { | ||||
|    "label": "Attendance", | ||||
|    "link_to": "Attendance", | ||||
|    "stats_filter": "", | ||||
|    "type": "DocType" | ||||
|   }, | ||||
|   { | ||||
|    "label": "Job Applicant", | ||||
|    "link_to": "Job Applicant", | ||||
|  | ||||
| @ -5,20 +5,23 @@ cur_frm.add_fetch('employee','employee_name','employee_name'); | ||||
| 
 | ||||
| frappe.ui.form.on("Leave Allocation", { | ||||
| 	onload: function(frm) { | ||||
| 		// Ignore cancellation of doctype on cancel all.
 | ||||
| 		frm.ignore_doctypes_on_cancel_all = ["Leave Ledger Entry"]; | ||||
| 
 | ||||
| 		if(!frm.doc.from_date) frm.set_value("from_date", frappe.datetime.get_today()); | ||||
| 
 | ||||
| 		frm.set_query("employee", function() { | ||||
| 			return { | ||||
| 				query: "erpnext.controllers.queries.employee_query" | ||||
| 			} | ||||
| 			}; | ||||
| 		}); | ||||
| 		frm.set_query("leave_type", function() { | ||||
| 			return { | ||||
| 				filters: { | ||||
| 					is_lwp: 0 | ||||
| 				} | ||||
| 			} | ||||
| 		}) | ||||
| 			}; | ||||
| 		}); | ||||
| 	}, | ||||
| 
 | ||||
| 	refresh: function(frm) { | ||||
|  | ||||
| @ -19,6 +19,10 @@ frappe.ui.form.on("Leave Application", { | ||||
| 		frm.set_query("employee", erpnext.queries.employee); | ||||
| 	}, | ||||
| 	onload: function(frm) { | ||||
| 
 | ||||
| 		// Ignore cancellation of doctype on cancel all.
 | ||||
| 		frm.ignore_doctypes_on_cancel_all = ["Leave Ledger Entry"]; | ||||
| 
 | ||||
| 		if (!frm.doc.posting_date) { | ||||
| 			frm.set_value("posting_date", frappe.datetime.get_today()); | ||||
| 		} | ||||
|  | ||||
| @ -2,6 +2,10 @@ | ||||
| // For license information, please see license.txt
 | ||||
| 
 | ||||
| frappe.ui.form.on('Leave Encashment', { | ||||
| 	onload: function(frm) { | ||||
| 		// Ignore cancellation of doctype on cancel all.
 | ||||
| 		frm.ignore_doctypes_on_cancel_all = ["Leave Ledger Entry"]; | ||||
| 	}, | ||||
| 	setup: function(frm) { | ||||
| 		frm.set_query("leave_type", function() { | ||||
| 			return { | ||||
| @ -33,7 +37,7 @@ frappe.ui.form.on('Leave Encashment', { | ||||
| 				doc: frm.doc, | ||||
| 				callback: function(r) { | ||||
| 					frm.refresh_fields(); | ||||
| 					} | ||||
| 				} | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @ -16,14 +16,16 @@ from six import string_types | ||||
| 
 | ||||
| class LoanApplication(Document): | ||||
| 	def validate(self): | ||||
| 
 | ||||
| 		validate_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount, | ||||
| 			self.repayment_periods, self.is_term_loan) | ||||
| 
 | ||||
| 		self.validate_loan_type() | ||||
| 		self.set_pledge_amount() | ||||
| 		self.set_loan_amount() | ||||
| 		self.validate_loan_amount() | ||||
| 
 | ||||
| 		if self.is_term_loan: | ||||
| 			validate_repayment_method(self.repayment_method, self.loan_amount, self.repayment_amount, | ||||
| 				self.repayment_periods, self.is_term_loan) | ||||
| 
 | ||||
| 		self.validate_loan_type() | ||||
| 
 | ||||
| 		self.get_repayment_details() | ||||
| 		self.check_sanctioned_amount_limit() | ||||
| 
 | ||||
| @ -106,7 +108,7 @@ class LoanApplication(Document): | ||||
| 		if self.is_secured_loan and self.proposed_pledges: | ||||
| 			self.maximum_loan_amount = 0 | ||||
| 			for security in self.proposed_pledges: | ||||
| 				self.maximum_loan_amount += security.post_haircut_amount | ||||
| 				self.maximum_loan_amount += flt(security.post_haircut_amount) | ||||
| 
 | ||||
| 		if not self.loan_amount and self.is_secured_loan and self.proposed_pledges: | ||||
| 			self.loan_amount = self.maximum_loan_amount | ||||
|  | ||||
| @ -718,3 +718,6 @@ erpnext.patches.v13_0.delete_report_requested_items_to_order | ||||
| erpnext.patches.v12_0.update_item_tax_template_company | ||||
| erpnext.patches.v13_0.move_branch_code_to_bank_account | ||||
| erpnext.patches.v13_0.healthcare_lab_module_rename_doctypes | ||||
| erpnext.patches.v13_0.stock_entry_enhancements | ||||
| erpnext.patches.v12_0.update_state_code_for_daman_and_diu | ||||
| erpnext.patches.v12_0.rename_lost_reason_detail | ||||
|  | ||||
							
								
								
									
										17
									
								
								erpnext/patches/v12_0/rename_lost_reason_detail.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								erpnext/patches/v12_0/rename_lost_reason_detail.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| from __future__ import unicode_literals | ||||
| import frappe | ||||
| 
 | ||||
| def execute(): | ||||
|     if frappe.db.exists("DocType", "Lost Reason Detail"): | ||||
|         frappe.reload_doc("crm", "doctype", "opportunity_lost_reason_detail") | ||||
|         frappe.reload_doc("setup", "doctype", "quotation_lost_reason_detail") | ||||
| 
 | ||||
|         frappe.db.sql("""INSERT INTO `tabOpportunity Lost Reason Detail` SELECT * FROM `tabLost Reason Detail` WHERE `parenttype` = 'Opportunity'""") | ||||
| 
 | ||||
|         frappe.db.sql("""INSERT INTO `tabQuotation Lost Reason Detail` SELECT * FROM `tabLost Reason Detail` WHERE `parenttype` = 'Quotation'""") | ||||
| 
 | ||||
|         frappe.db.sql("""INSERT INTO `tabQuotation Lost Reason` (`name`, `creation`, `modified`, `modified_by`, `owner`, `docstatus`, `parent`, `parentfield`, `parenttype`, `idx`, `_comments`, `_assign`, `_user_tags`, `_liked_by`, `order_lost_reason`)  | ||||
|             SELECT o.`name`, o.`creation`, o.`modified`, o.`modified_by`, o.`owner`, o.`docstatus`, o.`parent`, o.`parentfield`, o.`parenttype`, o.`idx`, o.`_comments`, o.`_assign`, o.`_user_tags`, o.`_liked_by`, o.`lost_reason`  | ||||
|             FROM `tabOpportunity Lost Reason` o LEFT JOIN `tabQuotation Lost Reason` q ON q.name = o.name WHERE q.name IS NULL""") | ||||
|          | ||||
|         frappe.delete_doc("DocType", "Lost Reason Detail") | ||||
| @ -19,7 +19,7 @@ def create_stock_entry_types(): | ||||
| 
 | ||||
| 	for purpose in ["Material Issue", "Material Receipt", "Material Transfer", | ||||
| 		"Material Transfer for Manufacture", "Material Consumption for Manufacture", "Manufacture", | ||||
| 		"Repack", "Send to Subcontractor", "Send to Warehouse", "Receive at Warehouse"]: | ||||
| 		"Repack", "Send to Subcontractor"]: | ||||
| 
 | ||||
| 		ste_type = frappe.get_doc({ | ||||
| 			'doctype': 'Stock Entry Type', | ||||
|  | ||||
							
								
								
									
										22
									
								
								erpnext/patches/v12_0/update_state_code_for_daman_and_diu.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								erpnext/patches/v12_0/update_state_code_for_daman_and_diu.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| import frappe | ||||
| from erpnext.regional.india import states | ||||
| 
 | ||||
| def execute(): | ||||
| 
 | ||||
| 	company = frappe.get_all('Company', filters = {'country': 'India'}) | ||||
| 	if not company: | ||||
| 		return | ||||
| 
 | ||||
| 	# Update options in gst_state custom field | ||||
| 	gst_state = frappe.get_doc('Custom Field', 'Address-gst_state') | ||||
| 	gst_state.options = '\n'.join(states) | ||||
| 	gst_state.save() | ||||
| 
 | ||||
| 	# Update gst_state and state code in existing address | ||||
| 	frappe.db.sql(""" | ||||
| 		UPDATE `tabAddress` | ||||
| 		SET | ||||
| 			gst_state = 'Dadra and Nagar Haveli and Daman and Diu', | ||||
| 			gst_state_number = 26 | ||||
| 		WHERE gst_state = 'Daman and Diu' | ||||
| 	""") | ||||
							
								
								
									
										27
									
								
								erpnext/patches/v13_0/stock_entry_enhancements.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								erpnext/patches/v13_0/stock_entry_enhancements.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| # Copyright(c) 2020, Frappe Technologies Pvt.Ltd.and Contributors | ||||
| # License: GNU General Public License v3.See license.txt | ||||
| 
 | ||||
| from __future__ import unicode_literals | ||||
| import frappe | ||||
| 
 | ||||
| def execute(): | ||||
|     frappe.reload_doc("stock", "doctype", "stock_entry") | ||||
|     if frappe.db.has_column("Stock Entry", "add_to_transit"): | ||||
|         frappe.db.sql(""" | ||||
|             UPDATE `tabStock Entry` SET  | ||||
|             stock_entry_type = 'Material Transfer', | ||||
|             purpose = 'Material Transfer', | ||||
|             add_to_transit = 1 WHERE stock_entry_type = 'Send to Warehouse' | ||||
|             """) | ||||
| 
 | ||||
|         frappe.db.sql("""UPDATE `tabStock Entry` SET  | ||||
|             stock_entry_type = 'Material Transfer', | ||||
|             purpose = 'Material Transfer' | ||||
|             WHERE stock_entry_type = 'Receive at Warehouse' | ||||
|             """) | ||||
|          | ||||
|         frappe.reload_doc("stock", "doctype", "warehouse_type") | ||||
|         if not frappe.db.exists('Warehouse Type', 'Transit'): | ||||
|             doc = frappe.new_doc('Warehouse Type') | ||||
|             doc.name = 'Transit' | ||||
|             doc.insert() | ||||
| @ -8,7 +8,7 @@ | ||||
|   { | ||||
|    "hidden": 0, | ||||
|    "label": "Taxation", | ||||
|    "links": "[\n    {\n        \"label\": \"Payroll Period\",\n        \"name\": \"Payroll Period\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Income Tax Slab\",\n        \"name\": \"Income Tax Slab\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Declaration\",\n        \"name\": \"Employee Tax Exemption Declaration\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Proof Submission\",\n        \"name\": \"Employee Tax Exemption Proof Submission\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Category\",\n        \"name\": \"Employee Tax Exemption Category\",\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Sub Category\",\n        \"name\": \"Employee Tax Exemption Sub Category\",\n        \"type\": \"doctype\"\n        \n    }\n]" | ||||
|    "links": "[\n    {\n        \"label\": \"Payroll Period\",\n        \"name\": \"Payroll Period\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Income Tax Slab\",\n        \"name\": \"Income Tax Slab\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Other Income\",\n        \"name\": \"Employee Other Income\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Declaration\",\n        \"name\": \"Employee Tax Exemption Declaration\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Proof Submission\",\n        \"name\": \"Employee Tax Exemption Proof Submission\",\n        \"onboard\": 1,\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Category\",\n        \"name\": \"Employee Tax Exemption Category\",\n        \"type\": \"doctype\"\n        \n    },\n    {\n        \"label\": \"Employee Tax Exemption Sub Category\",\n        \"name\": \"Employee Tax Exemption Sub Category\",\n        \"type\": \"doctype\"\n        \n    }\n]" | ||||
|   }, | ||||
|   { | ||||
|    "hidden": 0, | ||||
| @ -38,7 +38,7 @@ | ||||
|  "idx": 0, | ||||
|  "is_standard": 1, | ||||
|  "label": "Payroll", | ||||
|  "modified": "2020-06-19 12:23:06.034046", | ||||
|  "modified": "2020-08-10 19:38:45.976209", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Payroll", | ||||
|  "name": "Payroll", | ||||
|  | ||||
| @ -94,13 +94,6 @@ frappe.ui.form.on("Timesheet", { | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	company: function(frm) { | ||||
| 		frappe.db.get_value('Company', { 'company_name' : frm.doc.company }, 'standard_working_hours') | ||||
| 			.then(({ message }) => { | ||||
| 				(frappe.working_hours = message.standard_working_hours || 0); | ||||
| 			}); | ||||
| 	}, | ||||
| 
 | ||||
| 	make_invoice: function(frm) { | ||||
| 		let dialog = new frappe.ui.Dialog({ | ||||
| 			title: __("Select Item (optional)"), | ||||
|  | ||||
| @ -163,9 +163,11 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ | ||||
| 		$.each(me.frm.doc["items"] || [], function(n, item) { | ||||
| 			var item_tax_map = me._load_item_tax_rate(item.item_tax_rate); | ||||
| 			var cumulated_tax_fraction = 0.0; | ||||
| 
 | ||||
| 			var total_inclusive_tax_amount_per_qty = 0; | ||||
| 			$.each(me.frm.doc["taxes"] || [], function(i, tax) { | ||||
| 				tax.tax_fraction_for_current_item = me.get_current_tax_fraction(tax, item_tax_map); | ||||
| 				var current_tax_fraction = me.get_current_tax_fraction(tax, item_tax_map); | ||||
| 				tax.tax_fraction_for_current_item = current_tax_fraction[0]; | ||||
| 				var inclusive_tax_amount_per_qty = current_tax_fraction[1]; | ||||
| 
 | ||||
| 				if(i==0) { | ||||
| 					tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item; | ||||
| @ -176,10 +178,12 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ | ||||
| 				} | ||||
| 
 | ||||
| 				cumulated_tax_fraction += tax.tax_fraction_for_current_item; | ||||
| 				total_inclusive_tax_amount_per_qty += inclusive_tax_amount_per_qty * flt(item.qty); | ||||
| 			}); | ||||
| 
 | ||||
| 			if(cumulated_tax_fraction && !me.discount_amount_applied) { | ||||
| 				item.net_amount = flt(item.amount / (1 + cumulated_tax_fraction)); | ||||
| 			if(!me.discount_amount_applied && item.qty && (total_inclusive_tax_amount_per_qty || cumulated_tax_fraction)) { | ||||
| 				var amount = flt(item.amount) - total_inclusive_tax_amount_per_qty; | ||||
| 				item.net_amount = flt(amount / (1 + cumulated_tax_fraction)); | ||||
| 				item.net_rate = item.qty ? flt(item.net_amount / item.qty, precision("net_rate", item)) : 0; | ||||
| 
 | ||||
| 				me.set_in_company_currency(item, ["net_rate", "net_amount"]); | ||||
| @ -191,6 +195,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ | ||||
| 		// Get tax fraction for calculating tax exclusive amount
 | ||||
| 		// from tax inclusive amount
 | ||||
| 		var current_tax_fraction = 0.0; | ||||
| 		var inclusive_tax_amount_per_qty = 0; | ||||
| 
 | ||||
| 		if(cint(tax.included_in_print_rate)) { | ||||
| 			var tax_rate = this._get_tax_rate(tax, item_tax_map); | ||||
| @ -205,13 +210,16 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ | ||||
| 			} else if(tax.charge_type == "On Previous Row Total") { | ||||
| 				current_tax_fraction = (tax_rate / 100.0) * | ||||
| 					this.frm.doc["taxes"][cint(tax.row_id) - 1].grand_total_fraction_for_current_item; | ||||
| 			} else if (tax.charge_type == "On Item Quantity") { | ||||
| 				inclusive_tax_amount_per_qty = flt(tax_rate); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if(tax.add_deduct_tax) { | ||||
| 			current_tax_fraction *= (tax.add_deduct_tax == "Deduct") ? -1.0 : 1.0; | ||||
| 		if(tax.add_deduct_tax && tax.add_deduct_tax == "Deduct") { | ||||
| 			current_tax_fraction *= -1; | ||||
| 			inclusive_tax_amount_per_qty *= -1; | ||||
| 		} | ||||
| 		return current_tax_fraction; | ||||
| 		return [current_tax_fraction, inclusive_tax_amount_per_qty]; | ||||
| 	}, | ||||
| 
 | ||||
| 	_get_tax_rate: function(tax, item_tax_map) { | ||||
| @ -360,8 +368,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ | ||||
| 		} else if(tax.charge_type == "On Previous Row Total") { | ||||
| 			current_tax_amount = (tax_rate / 100.0) * | ||||
| 				this.frm.doc["taxes"][cint(tax.row_id) - 1].grand_total_for_current_item; | ||||
| 		} else if (tax.charge_type == "On Item Quantity") { | ||||
| 			current_tax_amount = tax_rate * item.qty; | ||||
| 		} | ||||
| 
 | ||||
| 		this.set_item_wise_tax(item, tax, tax_rate, current_tax_amount); | ||||
| 
 | ||||
| 		return current_tax_amount; | ||||
| @ -573,7 +582,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ | ||||
| 			var actual_taxes_dict = {}; | ||||
| 
 | ||||
| 			$.each(this.frm.doc["taxes"] || [], function(i, tax) { | ||||
| 				if (tax.charge_type == "Actual") { | ||||
| 				if (in_list(["Actual", "On Item Quantity"], tax.charge_type)) { | ||||
| 					var tax_amount = (tax.category == "Valuation") ? 0.0 : tax.tax_amount; | ||||
| 					tax_amount *= (tax.add_deduct_tax == "Deduct") ? -1.0 : 1.0; | ||||
| 					actual_taxes_dict[tax.idx] = tax_amount; | ||||
| @ -586,7 +595,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ | ||||
| 			$.each(actual_taxes_dict, function(key, value) { | ||||
| 				if (value) total_actual_tax += value; | ||||
| 			}); | ||||
| 
 | ||||
| 			 | ||||
| 			return flt(this.frm.doc.grand_total - total_actual_tax, precision("grand_total")); | ||||
| 		} | ||||
| 	}, | ||||
|  | ||||
| @ -10,8 +10,7 @@ states = [ | ||||
|  'Bihar', | ||||
|  'Chandigarh', | ||||
|  'Chhattisgarh', | ||||
|  'Dadra and Nagar Haveli', | ||||
|  'Daman and Diu', | ||||
|  'Dadra and Nagar Haveli and Daman and Diu', | ||||
|  'Delhi', | ||||
|  'Goa', | ||||
|  'Gujarat', | ||||
| @ -50,8 +49,7 @@ state_numbers = { | ||||
|  "Bihar": "10", | ||||
|  "Chandigarh": "04", | ||||
|  "Chhattisgarh": "22", | ||||
|  "Dadra and Nagar Haveli": "26", | ||||
|  "Daman and Diu": "25", | ||||
|  "Dadra and Nagar Haveli and Daman and Diu": "26", | ||||
|  "Delhi": "07", | ||||
|  "Goa": "30", | ||||
|  "Gujarat": "24", | ||||
|  | ||||
| @ -134,15 +134,10 @@ | ||||
|   "state_code": "DL", | ||||
|   "state_name": "Delhi" | ||||
|  }, | ||||
|  { | ||||
|   "state_number": "25", | ||||
|   "state_code": "DD", | ||||
|   "state_name": "Daman and Diu" | ||||
|  }, | ||||
|  { | ||||
|   "state_number": "26", | ||||
|   "state_code": "DN", | ||||
|   "state_name": "Dadra and Nagar Haveli" | ||||
|   "state_name": "Dadra and Nagar Haveli and Daman and Diu" | ||||
|  }, | ||||
|  { | ||||
|   "state_number": "22", | ||||
|  | ||||
| @ -184,6 +184,14 @@ class Customer(TransactionBase): | ||||
| 	def validate_credit_limit_on_change(self): | ||||
| 		if self.get("__islocal") or not self.credit_limits: | ||||
| 			return | ||||
| 		 | ||||
| 		past_credit_limits = [d.credit_limit | ||||
| 			for d in frappe.db.get_all("Customer Credit Limit", filters={'parent': self.name}, fields=["credit_limit"], order_by="company")] | ||||
| 		 | ||||
| 		current_credit_limits = [d.credit_limit for d in sorted(self.credit_limits, key=lambda k: k.company)] | ||||
| 
 | ||||
| 		if past_credit_limits == current_credit_limits: | ||||
| 			return | ||||
| 
 | ||||
| 		company_record = [] | ||||
| 		for limit in self.credit_limits: | ||||
|  | ||||
| @ -923,7 +923,7 @@ | ||||
|    "fieldname": "lost_reasons", | ||||
|    "fieldtype": "Table MultiSelect", | ||||
|    "label": "Lost Reasons", | ||||
|    "options": "Lost Reason Detail", | ||||
|    "options": "Quotation Lost Reason Detail", | ||||
|    "read_only": 1 | ||||
|   } | ||||
|  ], | ||||
| @ -932,7 +932,7 @@ | ||||
|  "is_submittable": 1, | ||||
|  "links": [], | ||||
|  "max_attachments": 1, | ||||
|  "modified": "2020-07-18 04:59:09.960118", | ||||
|  "modified": "2020-07-26 17:46:19.951223", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Selling", | ||||
|  "name": "Quotation", | ||||
|  | ||||
| @ -68,7 +68,7 @@ class Quotation(SellingController): | ||||
| 
 | ||||
| 	def declare_enquiry_lost(self, lost_reasons_list, detailed_reason=None): | ||||
| 		if not self.has_sales_order(): | ||||
| 			get_lost_reasons = frappe.get_list('Opportunity Lost Reason', | ||||
| 			get_lost_reasons = frappe.get_list('Quotation Lost Reason', | ||||
| 			fields = ["name"]) | ||||
| 			lost_reasons_lst = [reason.get('name') for reason in get_lost_reasons] | ||||
| 			frappe.db.set(self, 'status', 'Lost') | ||||
|  | ||||
| @ -494,13 +494,18 @@ frappe.ui.form.on(cur_frm.doctype, { | ||||
| 		var dialog = new frappe.ui.Dialog({ | ||||
| 			title: __("Set as Lost"), | ||||
| 			fields: [ | ||||
| 				{"fieldtype": "Table MultiSelect", | ||||
| 				"label": __("Lost Reasons"), | ||||
| 				"fieldname": "lost_reason", | ||||
| 				"options": "Lost Reason Detail", | ||||
| 				"reqd": 1}, | ||||
| 
 | ||||
| 				{"fieldtype": "Text", "label": __("Detailed Reason"), "fieldname": "detailed_reason"}, | ||||
| 				{ | ||||
| 					"fieldtype": "Table MultiSelect", | ||||
| 					"label": __("Lost Reasons"), | ||||
| 					"fieldname": "lost_reason", | ||||
| 					"options": frm.doctype === 'Opportunity' ? 'Opportunity Lost Reason Detail': 'Quotation Lost Reason Detail', | ||||
| 					"reqd": 1 | ||||
| 				}, | ||||
| 				{ | ||||
| 					"fieldtype": "Text", | ||||
| 					"label": __("Detailed Reason"), | ||||
| 					"fieldname": "detailed_reason" | ||||
| 				}, | ||||
| 			], | ||||
| 			primary_action: function() { | ||||
| 				var values = dialog.get_values(); | ||||
|  | ||||
| @ -34,6 +34,16 @@ frappe.ui.form.on("Company", { | ||||
| 		frm.set_query("default_buying_terms", function() { | ||||
| 			return { filters: { buying: 1 } }; | ||||
| 		}); | ||||
| 
 | ||||
| 		frm.set_query("default_in_transit_warehouse", function() { | ||||
| 			return { | ||||
| 				filters:{ | ||||
| 					'warehouse_type' : 'Transit', | ||||
| 					'is_group': 0, | ||||
| 					'company': frm.doc.company | ||||
| 				} | ||||
| 			}; | ||||
| 		}); | ||||
| 	}, | ||||
| 
 | ||||
| 	company_name: function(frm) { | ||||
|  | ||||
| @ -25,6 +25,7 @@ | ||||
|   "default_selling_terms", | ||||
|   "default_buying_terms", | ||||
|   "default_warehouse_for_sales_return", | ||||
|   "default_in_transit_warehouse", | ||||
|   "column_break_10", | ||||
|   "country", | ||||
|   "create_chart_of_accounts_based_on", | ||||
| @ -733,6 +734,12 @@ | ||||
|    "fieldname": "enable_perpetual_inventory_for_non_stock_items", | ||||
|    "fieldtype": "Check", | ||||
|    "label": "Enable Perpetual Inventory For Non Stock Items" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "default_in_transit_warehouse", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Default In Transit Warehouse", | ||||
|    "options": "Warehouse" | ||||
|   } | ||||
|  ], | ||||
|  "icon": "fa fa-building", | ||||
| @ -740,7 +747,7 @@ | ||||
|  "image_field": "company_logo", | ||||
|  "is_tree": 1, | ||||
|  "links": [], | ||||
|  "modified": "2020-06-24 12:45:31.462195", | ||||
|  "modified": "2020-08-06 00:38:08.311216", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Setup", | ||||
|  "name": "Company", | ||||
|  | ||||
| @ -140,7 +140,8 @@ class Company(NestedSet): | ||||
| 			{"warehouse_name": _("All Warehouses"), "is_group": 1}, | ||||
| 			{"warehouse_name": _("Stores"), "is_group": 0}, | ||||
| 			{"warehouse_name": _("Work In Progress"), "is_group": 0}, | ||||
| 			{"warehouse_name": _("Finished Goods"), "is_group": 0}]: | ||||
| 			{"warehouse_name": _("Finished Goods"), "is_group": 0}, | ||||
| 			{"warehouse_name": _("Goods In Transit"), "is_group": 0, "warehouse_type": "Transit"}]: | ||||
| 
 | ||||
| 			if not frappe.db.exists("Warehouse", "{0} - {1}".format(wh_detail["warehouse_name"], self.abbr)): | ||||
| 				warehouse = frappe.get_doc({ | ||||
| @ -149,7 +150,8 @@ class Company(NestedSet): | ||||
| 					"is_group": wh_detail["is_group"], | ||||
| 					"company": self.name, | ||||
| 					"parent_warehouse": "{0} - {1}".format(_("All Warehouses"), self.abbr) \ | ||||
| 						if not wh_detail["is_group"] else "" | ||||
| 						if not wh_detail["is_group"] else "", | ||||
| 					"warehouse_type" : wh_detail["warehouse_type"] if "warehouse_type" in wh_detail else None | ||||
| 				}) | ||||
| 				warehouse.flags.ignore_permissions = True | ||||
| 				warehouse.flags.ignore_mandatory = True | ||||
|  | ||||
| @ -0,0 +1,31 @@ | ||||
| { | ||||
|  "actions": [], | ||||
|  "creation": "2020-07-14 09:21:44.057724", | ||||
|  "doctype": "DocType", | ||||
|  "editable_grid": 1, | ||||
|  "engine": "InnoDB", | ||||
|  "field_order": [ | ||||
|   "lost_reason" | ||||
|  ], | ||||
|  "fields": [ | ||||
|   { | ||||
|    "fieldname": "lost_reason", | ||||
|    "fieldtype": "Link", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Quotation Lost Reason", | ||||
|    "options": "Quotation Lost Reason" | ||||
|   } | ||||
|  ], | ||||
|  "istable": 1, | ||||
|  "links": [], | ||||
|  "modified": "2020-07-26 17:58:56.373775", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Setup", | ||||
|  "name": "Quotation Lost Reason Detail", | ||||
|  "owner": "Administrator", | ||||
|  "permissions": [], | ||||
|  "quick_entry": 1, | ||||
|  "sort_field": "modified", | ||||
|  "sort_order": "DESC", | ||||
|  "track_changes": 1 | ||||
| } | ||||
| @ -0,0 +1,10 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors | ||||
| # For license information, please see license.txt | ||||
| 
 | ||||
| from __future__ import unicode_literals | ||||
| # import frappe | ||||
| from frappe.model.document import Document | ||||
| 
 | ||||
| class QuotationLostReasonDetail(Document): | ||||
| 	pass | ||||
| @ -95,8 +95,6 @@ def install(country=None): | ||||
| 		{'doctype': 'Stock Entry Type', 'name': 'Send to Subcontractor', 'purpose': 'Send to Subcontractor'}, | ||||
| 		{'doctype': 'Stock Entry Type', 'name': 'Material Transfer for Manufacture', 'purpose': 'Material Transfer for Manufacture'}, | ||||
| 		{'doctype': 'Stock Entry Type', 'name': 'Material Consumption for Manufacture', 'purpose': 'Material Consumption for Manufacture'}, | ||||
| 		{'doctype': 'Stock Entry Type', 'name': 'Send to Warehouse', 'purpose': 'Send to Warehouse'}, | ||||
| 		{'doctype': 'Stock Entry Type', 'name': 'Receive at Warehouse', 'purpose': 'Receive at Warehouse'}, | ||||
| 
 | ||||
| 		# Designation | ||||
| 		{'doctype': 'Designation', 'designation_name': _('CEO')}, | ||||
| @ -244,7 +242,10 @@ def install(country=None): | ||||
| 		{"doctype": "Sales Stage", "stage_name": _("Identifying Decision Makers")}, | ||||
| 		{"doctype": "Sales Stage", "stage_name": _("Perception Analysis")}, | ||||
| 		{"doctype": "Sales Stage", "stage_name": _("Proposal/Price Quote")}, | ||||
| 		{"doctype": "Sales Stage", "stage_name": _("Negotiation/Review")} | ||||
| 		{"doctype": "Sales Stage", "stage_name": _("Negotiation/Review")}, | ||||
| 
 | ||||
| 		# Warehouse Type | ||||
| 		{'doctype': 'Warehouse Type', 'name': 'Transit'}, | ||||
| 	] | ||||
| 
 | ||||
| 	from erpnext.setup.setup_wizard.data.industry_type import get_industry_types | ||||
|  | ||||
| @ -123,6 +123,7 @@ | ||||
|   "weightage", | ||||
|   "slideshow", | ||||
|   "website_image", | ||||
|   "website_image_alt", | ||||
|   "thumbnail", | ||||
|   "cb72", | ||||
|   "website_warehouse", | ||||
| @ -1054,15 +1055,21 @@ | ||||
|    "fieldtype": "Data", | ||||
|    "label": "Default Manufacturer Part No", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "website_image_alt", | ||||
|    "fieldtype": "Data", | ||||
|    "label": "Image Description" | ||||
|   } | ||||
|  ], | ||||
|  "has_web_view": 1, | ||||
|  "icon": "fa fa-tag", | ||||
|  "idx": 2, | ||||
|  "image_field": "image", | ||||
|  "index_web_pages_for_search": 1, | ||||
|  "links": [], | ||||
|  "max_attachments": 1, | ||||
|  "modified": "2020-07-31 21:21:10.956453", | ||||
|  "modified": "2020-08-07 14:24:58.384992", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Stock", | ||||
|  "name": "Item", | ||||
| @ -1124,4 +1131,4 @@ | ||||
|  "sort_order": "DESC", | ||||
|  "title_field": "item_name", | ||||
|  "track_changes": 1 | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -343,7 +343,7 @@ class Item(WebsiteGenerator): | ||||
| 			if variant: | ||||
| 				context.variant = frappe.get_doc("Item", variant) | ||||
| 
 | ||||
| 				for fieldname in ("website_image", "web_long_description", "description", | ||||
| 				for fieldname in ("website_image", "website_image_alt", "web_long_description", "description", | ||||
| 										"website_specifications"): | ||||
| 					if context.variant.get(fieldname): | ||||
| 						value = context.variant.get(fieldname) | ||||
|  | ||||
| @ -11,6 +11,7 @@ | ||||
|   "naming_series", | ||||
|   "title", | ||||
|   "material_request_type", | ||||
|   "transfer_status", | ||||
|   "customer", | ||||
|   "column_break_2", | ||||
|   "schedule_date", | ||||
| @ -303,13 +304,22 @@ | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Set From Warehouse", | ||||
|    "options": "Warehouse" | ||||
|   }, | ||||
|   { | ||||
|    "allow_on_submit": 1, | ||||
|    "depends_on": "eval:doc.add_to_transit == 1", | ||||
|    "fieldname": "transfer_status", | ||||
|    "fieldtype": "Select", | ||||
|    "label": "Transfer Status", | ||||
|    "options": "\nNot Started\nIn Transit\nCompleted", | ||||
|    "read_only": 1 | ||||
|   } | ||||
|  ], | ||||
|  "icon": "fa fa-ticket", | ||||
|  "idx": 70, | ||||
|  "is_submittable": 1, | ||||
|  "links": [], | ||||
|  "modified": "2020-05-01 20:21:09.990867", | ||||
|  "modified": "2020-08-10 13:27:54.891058", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Stock", | ||||
|  "name": "Material Request", | ||||
|  | ||||
| @ -1,8 +1,16 @@ | ||||
| frappe.listview_settings['Material Request'] = { | ||||
| 	add_fields: ["material_request_type", "status", "per_ordered", "per_received"], | ||||
| 	add_fields: ["material_request_type", "status", "per_ordered", "per_received", "transfer_status"], | ||||
| 	get_indicator: function(doc) { | ||||
| 		if(doc.status=="Stopped") { | ||||
| 			return [__("Stopped"), "red", "status,=,Stopped"]; | ||||
| 		} else if(doc.transfer_status && doc.docstatus != 2) { | ||||
| 			if (doc.transfer_status == "Not Started") { | ||||
| 				return [__("Not Started"), "orange"]; | ||||
| 			} else if (doc.transfer_status == "In Transit") { | ||||
| 				return [__("In Transit"), "yellow"]; | ||||
| 			} else if (doc.transfer_status == "Completed") { | ||||
| 				return [__("Completed"), "green"]; | ||||
| 			} | ||||
| 		} else if(doc.docstatus==1 && flt(doc.per_ordered, 2) == 0) { | ||||
| 			return [__("Pending"), "orange", "per_ordered,=,0"]; | ||||
| 		}  else if(doc.docstatus==1 && flt(doc.per_ordered, 2) < 100) { | ||||
|  | ||||
| @ -19,7 +19,6 @@ frappe.ui.form.on('Stock Entry', { | ||||
| 				filters: [ | ||||
| 					['Stock Entry', 'docstatus', '=', 1], | ||||
| 					['Stock Entry', 'per_transferred', '<','100'], | ||||
| 					['Stock Entry', 'purpose', '=', 'Send to Warehouse'] | ||||
| 				] | ||||
| 			} | ||||
| 		}); | ||||
| @ -171,9 +170,9 @@ frappe.ui.form.on('Stock Entry', { | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (frm.doc.docstatus === 1 && frm.doc.purpose == 'Send to Warehouse') { | ||||
| 			if (frm.doc.per_transferred < 100) { | ||||
| 				frm.add_custom_button(__('Receive at Warehouse Entry'), function() { | ||||
| 		if (frm.doc.docstatus === 1) { | ||||
| 			if (frm.doc.add_to_transit && frm.doc.purpose=='Material Transfer' && frm.doc.per_transferred < 100) { | ||||
| 				frm.add_custom_button('End Transit', function() { | ||||
| 					frappe.model.open_mapped_doc({ | ||||
| 						method: "erpnext.stock.doctype.stock_entry.stock_entry.make_stock_in_entry", | ||||
| 						frm: frm | ||||
| @ -266,6 +265,7 @@ frappe.ui.form.on('Stock Entry', { | ||||
| 	stock_entry_type: function(frm){ | ||||
| 		frm.remove_custom_button('Bill of Materials', "Get items from"); | ||||
| 		frm.events.show_bom_custom_button(frm); | ||||
| 		frm.trigger('add_to_transit'); | ||||
| 	}, | ||||
| 
 | ||||
| 	purpose: function(frm) { | ||||
| @ -532,6 +532,26 @@ frappe.ui.form.on('Stock Entry', { | ||||
| 
 | ||||
| 	target_warehouse_address: function(frm) { | ||||
| 		erpnext.utils.get_address_display(frm, 'target_warehouse_address', 'target_address_display', false); | ||||
| 	}, | ||||
| 
 | ||||
| 	add_to_transit: function(frm) { | ||||
| 		if(frm.doc.add_to_transit && frm.doc.purpose=='Material Transfer') { | ||||
| 			frm.set_value('stock_entry_type', 'Material Transfer'); | ||||
| 			frm.fields_dict.to_warehouse.get_query = function() { | ||||
| 				return { | ||||
| 					filters:{ | ||||
| 						'warehouse_type' : 'Transit', | ||||
| 						'is_group': 0, | ||||
| 						'company': frm.doc.company | ||||
| 					} | ||||
| 				}; | ||||
| 			}; | ||||
| 			frappe.db.get_value('Company', frm.doc.company, 'default_in_transit_warehouse', (r) => { | ||||
| 				if (r.default_in_transit_warehouse) { | ||||
| 					frm.set_value('to_warehouse', r.default_in_transit_warehouse); | ||||
| 				} | ||||
| 			}); | ||||
| 		} | ||||
| 	} | ||||
| }) | ||||
| 
 | ||||
| @ -754,6 +774,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ | ||||
| 		} | ||||
| 		erpnext.hide_company(); | ||||
| 		erpnext.utils.add_item(this.frm); | ||||
| 		this.frm.trigger('add_to_transit'); | ||||
| 	}, | ||||
| 
 | ||||
| 	scan_barcode: function() { | ||||
| @ -919,8 +940,6 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ | ||||
| 			doc.purpose!='Material Issue'); | ||||
| 
 | ||||
| 		this.frm.fields_dict["items"].grid.set_column_disp("additional_cost", doc.purpose!='Material Issue'); | ||||
| 		this.frm.toggle_reqd("outgoing_stock_entry", | ||||
| 			doc.purpose == 'Receive at Warehouse' ? 1: 0); | ||||
| 	}, | ||||
| 
 | ||||
| 	supplier: function(doc) { | ||||
|  | ||||
| @ -13,6 +13,7 @@ | ||||
|   "stock_entry_type", | ||||
|   "outgoing_stock_entry", | ||||
|   "purpose", | ||||
|   "add_to_transit", | ||||
|   "work_order", | ||||
|   "purchase_order", | ||||
|   "delivery_note_no", | ||||
| @ -116,11 +117,12 @@ | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "depends_on": "eval:doc.purpose == 'Receive at Warehouse'", | ||||
|    "depends_on": "eval:doc.purpose == 'Material Transfer'", | ||||
|    "fieldname": "outgoing_stock_entry", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Stock Entry (Outward GIT)", | ||||
|    "options": "Stock Entry" | ||||
|    "options": "Stock Entry", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "bold": 1, | ||||
| @ -132,7 +134,7 @@ | ||||
|    "label": "Purpose", | ||||
|    "oldfieldname": "purpose", | ||||
|    "oldfieldtype": "Select", | ||||
|    "options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor\nSend to Warehouse\nReceive at Warehouse", | ||||
|    "options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
| @ -630,13 +632,21 @@ | ||||
|   { | ||||
|    "fieldname": "print_settings_col_break", | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "default": "0", | ||||
|    "depends_on": "eval: doc.purpose=='Material Transfer' && !doc.outgoing_stock_entry", | ||||
|    "fieldname": "add_to_transit", | ||||
|    "fieldtype": "Check", | ||||
|    "label": "Add to Transit", | ||||
|    "no_copy": 1 | ||||
|   } | ||||
|  ], | ||||
|  "icon": "fa fa-file-text", | ||||
|  "idx": 1, | ||||
|  "is_submittable": 1, | ||||
|  "links": [], | ||||
|  "modified": "2020-04-23 12:56:52.881752", | ||||
|  "modified": "2020-08-11 19:10:07.954981", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Stock", | ||||
|  "name": "Stock Entry", | ||||
|  | ||||
| @ -96,6 +96,11 @@ class StockEntry(StockController): | ||||
| 		self.update_quality_inspection() | ||||
| 		if self.work_order and self.purpose == "Manufacture": | ||||
| 			self.update_so_in_serial_number() | ||||
| 		 | ||||
| 		if self.purpose == 'Material Transfer' and self.add_to_transit: | ||||
| 			self.set_material_request_transfer_status('In Transit') | ||||
| 		if self.purpose == 'Material Transfer' and self.outgoing_stock_entry: | ||||
| 			self.set_material_request_transfer_status('Completed') | ||||
| 
 | ||||
| 	def on_cancel(self): | ||||
| 
 | ||||
| @ -116,6 +121,11 @@ class StockEntry(StockController): | ||||
| 		self.update_quality_inspection() | ||||
| 		self.delete_auto_created_batches() | ||||
| 
 | ||||
| 		if self.purpose == 'Material Transfer' and self.add_to_transit: | ||||
| 			self.set_material_request_transfer_status('Not Started') | ||||
| 		if self.purpose == 'Material Transfer' and self.outgoing_stock_entry: | ||||
| 			self.set_material_request_transfer_status('In Transit') | ||||
| 
 | ||||
| 	def set_job_card_data(self): | ||||
| 		if self.job_card and not self.work_order: | ||||
| 			data = frappe.db.get_value('Job Card', | ||||
| @ -133,7 +143,7 @@ class StockEntry(StockController): | ||||
| 	def validate_purpose(self): | ||||
| 		valid_purposes = ["Material Issue", "Material Receipt", "Material Transfer", | ||||
| 			"Material Transfer for Manufacture", "Manufacture", "Repack", "Send to Subcontractor", | ||||
| 			"Material Consumption for Manufacture", "Send to Warehouse", "Receive at Warehouse"] | ||||
| 			"Material Consumption for Manufacture"] | ||||
| 
 | ||||
| 		if self.purpose not in valid_purposes: | ||||
| 			frappe.throw(_("Purpose must be one of {0}").format(comma_or(valid_purposes))) | ||||
| @ -199,7 +209,8 @@ class StockEntry(StockController): | ||||
| 						item.set(f, item_details.get(f)) | ||||
| 
 | ||||
| 			if not item.transfer_qty and item.qty: | ||||
| 				item.transfer_qty = item.qty * item.conversion_factor | ||||
| 				item.transfer_qty = flt(flt(item.qty) * flt(item.conversion_factor), | ||||
| 				self.precision("transfer_qty", item)) | ||||
| 
 | ||||
| 			if (self.purpose in ("Material Transfer", "Material Transfer for Manufacture") | ||||
| 				and not item.serial_no | ||||
| @ -258,10 +269,10 @@ class StockEntry(StockController): | ||||
| 		"""perform various (sometimes conditional) validations on warehouse""" | ||||
| 
 | ||||
| 		source_mandatory = ["Material Issue", "Material Transfer", "Send to Subcontractor", "Material Transfer for Manufacture", | ||||
| 			"Material Consumption for Manufacture", "Send to Warehouse", "Receive at Warehouse"] | ||||
| 			"Material Consumption for Manufacture"] | ||||
| 
 | ||||
| 		target_mandatory = ["Material Receipt", "Material Transfer", "Send to Subcontractor", | ||||
| 			"Material Transfer for Manufacture", "Send to Warehouse", "Receive at Warehouse"] | ||||
| 			"Material Transfer for Manufacture"] | ||||
| 
 | ||||
| 		validate_for_manufacture = any([d.bom_no for d in self.get("items")]) | ||||
| 
 | ||||
| @ -809,7 +820,7 @@ class StockEntry(StockController): | ||||
| 	def set_items_for_stock_in(self): | ||||
| 		self.items = [] | ||||
| 
 | ||||
| 		if self.outgoing_stock_entry and self.purpose == 'Receive at Warehouse': | ||||
| 		if self.outgoing_stock_entry and self.purpose == 'Material Transfer': | ||||
| 			doc = frappe.get_doc('Stock Entry', self.outgoing_stock_entry) | ||||
| 
 | ||||
| 			if doc.per_transferred == 100: | ||||
| @ -1210,13 +1221,25 @@ class StockEntry(StockController): | ||||
| 
 | ||||
| 	def validate_with_material_request(self): | ||||
| 		for item in self.get("items"): | ||||
| 			if item.material_request: | ||||
| 			material_request = item.material_request or None | ||||
| 			material_request_item = item.material_request_item or None | ||||
| 			if self.purpose == 'Material Transfer' and self.outgoing_stock_entry: | ||||
| 				parent_se = frappe.get_value("Stock Entry Detail", item.ste_detail, ['material_request','material_request_item'],as_dict=True) | ||||
| 				if parent_se: | ||||
| 					material_request = parent_se.material_request | ||||
| 					material_request_item = parent_se.material_request_item | ||||
| 
 | ||||
| 			if material_request: | ||||
| 				mreq_item = frappe.db.get_value("Material Request Item", | ||||
| 					{"name": item.material_request_item, "parent": item.material_request}, | ||||
| 					{"name": material_request_item, "parent": material_request}, | ||||
| 					["item_code", "warehouse", "idx"], as_dict=True) | ||||
| 				if mreq_item.item_code != item.item_code or \ | ||||
| 				mreq_item.warehouse != (item.s_warehouse if self.purpose== "Material Issue" else item.t_warehouse): | ||||
| 					frappe.throw(_("Item or Warehouse for row {0} does not match Material Request").format(item.idx), | ||||
| 				if mreq_item.item_code != item.item_code: | ||||
| 					frappe.throw(_("Item for row {0} does not match Material Request").format(item.idx), | ||||
| 						frappe.MappingMismatchError) | ||||
| 				elif self.purpose == "Material Transfer" and self.add_to_transit: | ||||
| 					continue | ||||
| 				elif mreq_item.warehouse != (item.s_warehouse if self.purpose == "Material Issue" else item.t_warehouse): | ||||
| 					frappe.throw(_("Warehouse for row {0} does not match Material Request").format(item.idx), | ||||
| 						frappe.MappingMismatchError) | ||||
| 
 | ||||
| 	def validate_batch(self): | ||||
| @ -1284,7 +1307,7 @@ class StockEntry(StockController): | ||||
| 						 to fullfill Sales Order {2}.").format(item.item_code, sr, sales_order)) | ||||
| 
 | ||||
| 	def update_transferred_qty(self): | ||||
| 		if self.purpose == 'Receive at Warehouse': | ||||
| 		if self.purpose == 'Material Transfer' and self.outgoing_stock_entry: | ||||
| 			stock_entries = {} | ||||
| 			stock_entries_child_list = [] | ||||
| 			for d in self.items: | ||||
| @ -1342,6 +1365,20 @@ class StockEntry(StockController): | ||||
| 						'reference_type': reference_type, | ||||
| 						'reference_name': reference_name | ||||
| 					}) | ||||
| 	def set_material_request_transfer_status(self, status): | ||||
| 		material_requests = [] | ||||
| 		if self.outgoing_stock_entry: | ||||
| 			parent_se = frappe.get_value("Stock Entry", self.outgoing_stock_entry, 'add_to_transit') | ||||
| 
 | ||||
| 		for item in self.items:  | ||||
| 			material_request = item.material_request or None | ||||
| 			if self.purpose == "Material Transfer" and material_request not in material_requests: | ||||
| 				if self.outgoing_stock_entry and parent_se: | ||||
| 					material_request = frappe.get_value("Stock Entry Detail", item.ste_detail, 'material_request') | ||||
| 
 | ||||
| 			if material_request and material_request not in material_requests: | ||||
| 				material_requests.append(material_request) | ||||
| 				frappe.db.set_value('Material Request', material_request, 'transfer_status', status) | ||||
| 
 | ||||
| @frappe.whitelist() | ||||
| def move_sample_to_retention_warehouse(company, items): | ||||
| @ -1381,12 +1418,19 @@ def move_sample_to_retention_warehouse(company, items): | ||||
| 
 | ||||
| @frappe.whitelist() | ||||
| def make_stock_in_entry(source_name, target_doc=None): | ||||
| 
 | ||||
| 	def set_missing_values(source, target): | ||||
| 		target.purpose = 'Receive at Warehouse' | ||||
| 		target.set_stock_entry_type() | ||||
| 
 | ||||
| 	def update_item(source_doc, target_doc, source_parent): | ||||
| 		target_doc.t_warehouse = '' | ||||
| 
 | ||||
| 		if source_doc.material_request_item and source_doc.material_request : | ||||
| 			add_to_transit = frappe.db.get_value('Stock Entry', source_name, 'add_to_transit') | ||||
| 			if add_to_transit: | ||||
| 				warehouse = frappe.get_value('Material Request Item', source_doc.material_request_item, 'warehouse') | ||||
| 				target_doc.t_warehouse = warehouse | ||||
| 		 | ||||
| 		target_doc.s_warehouse = source_doc.t_warehouse | ||||
| 		target_doc.qty = source_doc.qty - source_doc.transferred_qty | ||||
| 
 | ||||
|  | ||||
| @ -737,34 +737,6 @@ class TestStockEntry(unittest.TestCase): | ||||
| 		self.assertEqual(se.get("items")[0].allow_zero_valuation_rate, 1) | ||||
| 		self.assertEqual(se.get("items")[0].amount, 0) | ||||
| 
 | ||||
| 	def test_goods_in_transit(self): | ||||
| 		from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse | ||||
| 		warehouse = "_Test Warehouse FG 1 - _TC" | ||||
| 
 | ||||
| 		if not frappe.db.exists('Warehouse', warehouse): | ||||
| 			create_warehouse("_Test Warehouse FG 1") | ||||
| 
 | ||||
| 		outward_entry = make_stock_entry(item_code="_Test Item", | ||||
| 			purpose="Send to Warehouse", | ||||
| 			source="_Test Warehouse - _TC", | ||||
| 			target="_Test Warehouse 1 - _TC", qty=50, basic_rate=100) | ||||
| 
 | ||||
| 		inward_entry1 = make_stock_in_entry(outward_entry.name) | ||||
| 		inward_entry1.items[0].t_warehouse = warehouse | ||||
| 		inward_entry1.items[0].qty = 25 | ||||
| 		inward_entry1.submit() | ||||
| 
 | ||||
| 		doc = frappe.get_doc('Stock Entry', outward_entry.name) | ||||
| 		self.assertEqual(doc.per_transferred, 50) | ||||
| 
 | ||||
| 		inward_entry2 = make_stock_in_entry(outward_entry.name) | ||||
| 		inward_entry2.items[0].t_warehouse = warehouse | ||||
| 		inward_entry2.items[0].qty = 25 | ||||
| 		inward_entry2.submit() | ||||
| 
 | ||||
| 		doc = frappe.get_doc('Stock Entry', outward_entry.name) | ||||
| 		self.assertEqual(doc.per_transferred, 100) | ||||
| 
 | ||||
| 	def test_gle_for_opening_stock_entry(self): | ||||
| 		mr = make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company="_Test Company with perpetual inventory",qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1", is_opening="Yes", do_not_save=True) | ||||
| 
 | ||||
|  | ||||
| @ -1,156 +1,83 @@ | ||||
| { | ||||
|  "allow_copy": 0, | ||||
|  "allow_events_in_timeline": 0, | ||||
|  "allow_guest_to_view": 0, | ||||
|  "allow_import": 0, | ||||
|  "allow_rename": 0, | ||||
|  "actions": [], | ||||
|  "autoname": "Prompt", | ||||
|  "beta": 0, | ||||
|  "creation": "2019-03-13 16:23:46.636769", | ||||
|  "custom": 0, | ||||
|  "docstatus": 0, | ||||
|  "doctype": "DocType", | ||||
|  "document_type": "", | ||||
|  "editable_grid": 1, | ||||
|  "engine": "InnoDB", | ||||
|  "field_order": [ | ||||
|   "purpose" | ||||
|  ], | ||||
|  "fields": [ | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "default": "Material Issue", | ||||
|    "fetch_if_empty": 0, | ||||
|    "fieldname": "purpose", | ||||
|    "fieldtype": "Select", | ||||
|    "hidden": 0, | ||||
|    "ignore_user_permissions": 0, | ||||
|    "ignore_xss_filter": 0, | ||||
|    "in_filter": 0, | ||||
|    "in_global_search": 0, | ||||
|    "in_list_view": 1, | ||||
|    "in_standard_filter": 0, | ||||
|    "label": "Purpose", | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "options": "\nMaterial Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor\nSend to Warehouse\nReceive at Warehouse", | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 0, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "options": "\nMaterial Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor", | ||||
|    "reqd": 1, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 1, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "set_only_once": 1 | ||||
|   } | ||||
|  ], | ||||
|  "has_web_view": 0, | ||||
|  "hide_heading": 0, | ||||
|  "hide_toolbar": 0, | ||||
|  "idx": 0, | ||||
|  "image_view": 0, | ||||
|  "in_create": 0, | ||||
|  "is_submittable": 0, | ||||
|  "issingle": 0, | ||||
|  "istable": 0, | ||||
|  "max_attachments": 0, | ||||
|  "modified": "2019-03-26 12:02:42.144377", | ||||
|  "links": [], | ||||
|  "modified": "2020-08-10 23:24:37.160817", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Stock", | ||||
|  "name": "Stock Entry Type", | ||||
|  "name_case": "", | ||||
|  "owner": "Administrator", | ||||
|  "permissions": [ | ||||
|   { | ||||
|    "amend": 0, | ||||
|    "cancel": 0, | ||||
|    "create": 1, | ||||
|    "delete": 1, | ||||
|    "email": 1, | ||||
|    "export": 1, | ||||
|    "if_owner": 0, | ||||
|    "import": 0, | ||||
|    "permlevel": 0, | ||||
|    "print": 1, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "role": "System Manager", | ||||
|    "set_user_permissions": 0, | ||||
|    "share": 1, | ||||
|    "submit": 0, | ||||
|    "write": 1 | ||||
|   }, | ||||
|   { | ||||
|    "amend": 0, | ||||
|    "cancel": 0, | ||||
|    "create": 1, | ||||
|    "delete": 1, | ||||
|    "email": 1, | ||||
|    "export": 1, | ||||
|    "if_owner": 0, | ||||
|    "import": 0, | ||||
|    "permlevel": 0, | ||||
|    "print": 1, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "role": "Manufacturing Manager", | ||||
|    "set_user_permissions": 0, | ||||
|    "share": 1, | ||||
|    "submit": 0, | ||||
|    "write": 1 | ||||
|   }, | ||||
|   { | ||||
|    "amend": 0, | ||||
|    "cancel": 0, | ||||
|    "create": 1, | ||||
|    "delete": 1, | ||||
|    "email": 1, | ||||
|    "export": 1, | ||||
|    "if_owner": 0, | ||||
|    "import": 0, | ||||
|    "permlevel": 0, | ||||
|    "print": 1, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "role": "Stock Manager", | ||||
|    "set_user_permissions": 0, | ||||
|    "share": 1, | ||||
|    "submit": 0, | ||||
|    "write": 1 | ||||
|   }, | ||||
|   { | ||||
|    "amend": 0, | ||||
|    "cancel": 0, | ||||
|    "create": 1, | ||||
|    "delete": 1, | ||||
|    "email": 1, | ||||
|    "export": 1, | ||||
|    "if_owner": 0, | ||||
|    "import": 0, | ||||
|    "permlevel": 0, | ||||
|    "print": 1, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "role": "Stock User", | ||||
|    "set_user_permissions": 0, | ||||
|    "share": 1, | ||||
|    "submit": 0, | ||||
|    "write": 1 | ||||
|   } | ||||
|  ], | ||||
|  "quick_entry": 1, | ||||
|  "read_only": 0, | ||||
|  "read_only_onload": 0, | ||||
|  "show_name_in_global_search": 0, | ||||
|  "sort_field": "modified", | ||||
|  "sort_order": "ASC", | ||||
|  "track_changes": 1, | ||||
|  "track_seen": 0, | ||||
|  "track_views": 0 | ||||
|  "track_changes": 1 | ||||
| } | ||||
| @ -23,7 +23,7 @@ | ||||
| 	}) | ||||
| </script> | ||||
| {% else %} | ||||
| {{ product_image(website_image or image or 'no-image.jpg') }} | ||||
| {{ product_image(website_image or image or 'no-image.jpg', alt=website_image_alt or item_name) }} | ||||
| {% endif %} | ||||
| 
 | ||||
| <!-- Simple image preview --> | ||||
|  | ||||
| @ -7,9 +7,9 @@ | ||||
| </div> | ||||
| {% endmacro %} | ||||
| 
 | ||||
| {% macro product_image(website_image, css_class="") %} | ||||
| {% macro product_image(website_image, css_class="", alt="") %} | ||||
|     <div class="border text-center rounded h-100 {{ css_class }}" style="overflow: hidden;"> | ||||
| 		<img itemprop="image" class="website-image h-100 w-100" src="{{ frappe.utils.quoted(website_image or 'no-image.jpg') | abs_url }}"> | ||||
| 		<img itemprop="image" class="website-image h-100 w-100" alt="{{ alt }}" src="{{ frappe.utils.quoted(website_image or 'no-image.jpg') | abs_url }}"> | ||||
|     </div> | ||||
| {% endmacro %} | ||||
| 
 | ||||
|  | ||||
| @ -9,6 +9,33 @@ | ||||
| 			<p class="hero-subtitle">{{ greeting_subtitle }}</p> | ||||
| 			{% endif %} | ||||
| 		</div> | ||||
| 		<div class="search-container"> | ||||
| 			<div class="website-search" id="search-container"> | ||||
| 				<div class="dropdown"> | ||||
| 					<div class="search-icon"> | ||||
| 						<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" | ||||
| 							fill="none" | ||||
| 							stroke="currentColor" stroke-width="2" stroke-linecap="round" | ||||
| 							stroke-linejoin="round" | ||||
| 							class="feather feather-search"> | ||||
| 							<circle cx="11" cy="11" r="8"></circle> | ||||
| 							<line x1="21" y1="21" x2="16.65" y2="16.65"></line> | ||||
| 						</svg> | ||||
| 					</div> | ||||
| 					<input type="search" class="form-control" placeholder="Search the docs (Press ? to focus)" /> | ||||
| 					<div class="overflow-hidden shadow dropdown-menu w-100"> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 			<button class="navbar-toggler" type="button" | ||||
| 				data-toggle="collapse" | ||||
| 				data-target="#navbarSupportedContent" | ||||
| 				aria-controls="navbarSupportedContent" | ||||
| 				aria-expanded="false" | ||||
| 				aria-label="Toggle navigation"> | ||||
| 				<span class="navbar-toggler-icon"></span> | ||||
| 			</button> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </section> | ||||
| 
 | ||||
| @ -54,5 +81,21 @@ | ||||
| 	</div> | ||||
| </section> | ||||
| {% endif %} | ||||
| {% endblock %} | ||||
| 
 | ||||
| {% endblock %} | ||||
| {%- block script -%} | ||||
| <script> | ||||
| 	frappe.ready(() => { | ||||
| 		frappe.setup_search('#search-container', 'kb'); | ||||
| 	}); | ||||
| </script> | ||||
| {%- endblock -%} | ||||
| 
 | ||||
| {%- block style -%} | ||||
| <style> | ||||
| 	.search-container { | ||||
| 		margin-top: 1.2rem; | ||||
| 		max-width: 500px; | ||||
| 	}	 | ||||
| </style> | ||||
| {%- endblock -%} | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user