Merge branch 'develop' into scheduling-ui-rewrite
This commit is contained in:
		
						commit
						ccd9b38463
					
				| @ -19,6 +19,11 @@ def get(chart_name = None, chart = None, no_cache = None, from_date = None, to_d | ||||
| 	else: | ||||
| 		chart = frappe._dict(frappe.parse_json(chart)) | ||||
| 	timespan = chart.timespan | ||||
| 
 | ||||
| 	if chart.timespan == 'Select Date Range': | ||||
| 		from_date = chart.from_date | ||||
| 		to_date = chart.to_date | ||||
| 
 | ||||
| 	timegrain = chart.time_interval | ||||
| 	filters = frappe.parse_json(chart.filters_json) | ||||
| 
 | ||||
|  | ||||
| @ -174,6 +174,8 @@ def make_gl_entries(doc, credit_account, debit_account, against, | ||||
| 	# GL Entry for crediting the amount in the deferred expense | ||||
| 	from erpnext.accounts.general_ledger import make_gl_entries | ||||
| 
 | ||||
| 	if amount == 0: return | ||||
| 
 | ||||
| 	gl_entries = [] | ||||
| 	gl_entries.append( | ||||
| 		doc.get_gl_dict({ | ||||
|  | ||||
| @ -24,6 +24,11 @@ class AccountingDimension(Document): | ||||
| 			msg = _("Not allowed to create accounting dimension for {0}").format(self.document_type) | ||||
| 			frappe.throw(msg) | ||||
| 
 | ||||
| 		exists = frappe.db.get_value("Accounting Dimension", {'document_type': self.document_type}, ['name']) | ||||
| 
 | ||||
| 		if exists and self.is_new(): | ||||
| 			frappe.throw("Document Type already used as a dimension") | ||||
| 
 | ||||
| 	def after_insert(self): | ||||
| 		if frappe.flags.in_test: | ||||
| 			make_dimension_in_accounting_doctypes(doc=self) | ||||
| @ -60,7 +65,8 @@ def make_dimension_in_accounting_doctypes(doc): | ||||
| 			"label": doc.label, | ||||
| 			"fieldtype": "Link", | ||||
| 			"options": doc.document_type, | ||||
| 			"insert_after": insert_after_field | ||||
| 			"insert_after": insert_after_field, | ||||
| 			"owner": "Administrator" | ||||
| 		} | ||||
| 
 | ||||
| 		if doctype == "Budget": | ||||
|  | ||||
| @ -15,8 +15,8 @@ class AccountsSettings(Document): | ||||
| 		frappe.clear_cache() | ||||
| 
 | ||||
| 	def validate(self): | ||||
| 		for f in ["add_taxes_from_item_tax_template"]: | ||||
| 			frappe.db.set_default(f, self.get(f, "")) | ||||
| 		frappe.db.set_default("add_taxes_from_item_tax_template", | ||||
| 			self.get("add_taxes_from_item_tax_template", 0)) | ||||
| 
 | ||||
| 		self.validate_stale_days() | ||||
| 		self.enable_payment_schedule_in_print() | ||||
|  | ||||
| @ -570,7 +570,7 @@ $.extend(erpnext.journal_entry, { | ||||
| 				}, | ||||
| 				{fieldtype: "Date", fieldname: "posting_date", label: __("Date"), reqd: 1, | ||||
| 					default: frm.doc.posting_date}, | ||||
| 				{fieldtype: "Small Text", fieldname: "user_remark", label: __("User Remark"), reqd: 1}, | ||||
| 				{fieldtype: "Small Text", fieldname: "user_remark", label: __("User Remark")}, | ||||
| 				{fieldtype: "Select", fieldname: "naming_series", label: __("Series"), reqd: 1, | ||||
| 					options: naming_series_options, default: naming_series_default}, | ||||
| 			] | ||||
|  | ||||
| @ -32,8 +32,10 @@ class OpeningInvoiceCreationTool(Document): | ||||
| 				}) | ||||
| 				invoices_summary.update({company: _summary}) | ||||
| 
 | ||||
| 				paid_amount.append(invoice.paid_amount) | ||||
| 				outstanding_amount.append(invoice.outstanding_amount) | ||||
| 				if invoice.paid_amount: | ||||
| 					paid_amount.append(invoice.paid_amount) | ||||
| 				if invoice.outstanding_amount: | ||||
| 					outstanding_amount.append(invoice.outstanding_amount) | ||||
| 
 | ||||
| 			if paid_amount or outstanding_amount: | ||||
| 				max_count.update({ | ||||
|  | ||||
| @ -554,7 +554,7 @@ frappe.ui.form.on('Payment Entry', { | ||||
| 			frappe.flags.allocate_payment_amount = true; | ||||
| 			frm.events.validate_filters_data(frm, filters); | ||||
| 			frm.events.get_outstanding_documents(frm, filters); | ||||
| 		}, __("Filters"), __("Get Outstanding Invoices")); | ||||
| 		}, __("Filters"), __("Get Outstanding Documents")); | ||||
| 	}, | ||||
| 
 | ||||
| 	validate_filters_data: function(frm, filters) { | ||||
|  | ||||
| @ -62,6 +62,7 @@ | ||||
|   "dimension_col_break", | ||||
|   "cost_center", | ||||
|   "section_break_12", | ||||
|   "status", | ||||
|   "remarks", | ||||
|   "column_break_16", | ||||
|   "letter_head", | ||||
| @ -563,10 +564,18 @@ | ||||
|   { | ||||
|    "fieldname": "dimension_col_break", | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "default": "Draft", | ||||
|    "fieldname": "status", | ||||
|    "fieldtype": "Select", | ||||
|    "label": "Status", | ||||
|    "options": "\nDraft\nSubmitted\nCancelled", | ||||
|    "read_only": 1 | ||||
|   } | ||||
|  ], | ||||
|  "is_submittable": 1, | ||||
|  "modified": "2019-05-27 15:53:21.108857", | ||||
|  "modified": "2019-11-06 12:59:43.151721", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Accounts", | ||||
|  "name": "Payment Entry", | ||||
|  | ||||
| @ -61,6 +61,7 @@ class PaymentEntry(AccountsController): | ||||
| 		self.validate_duplicate_entry() | ||||
| 		self.validate_allocated_amount() | ||||
| 		self.ensure_supplier_is_not_blocked() | ||||
| 		self.set_status() | ||||
| 
 | ||||
| 	def on_submit(self): | ||||
| 		self.setup_party_account_field() | ||||
| @ -70,6 +71,7 @@ class PaymentEntry(AccountsController): | ||||
| 		self.update_outstanding_amounts() | ||||
| 		self.update_advance_paid() | ||||
| 		self.update_expense_claim() | ||||
| 		self.set_status() | ||||
| 
 | ||||
| 
 | ||||
| 	def on_cancel(self): | ||||
| @ -79,6 +81,7 @@ class PaymentEntry(AccountsController): | ||||
| 		self.update_advance_paid() | ||||
| 		self.update_expense_claim() | ||||
| 		self.delink_advance_entry_references() | ||||
| 		self.set_status() | ||||
| 
 | ||||
| 	def update_outstanding_amounts(self): | ||||
| 		self.set_missing_ref_details(force=True) | ||||
| @ -275,6 +278,14 @@ class PaymentEntry(AccountsController): | ||||
| 						frappe.throw(_("Against Journal Entry {0} does not have any unmatched {1} entry") | ||||
| 							.format(d.reference_name, dr_or_cr)) | ||||
| 
 | ||||
| 	def set_status(self): | ||||
| 		if self.docstatus == 2: | ||||
| 			self.status = 'Cancelled' | ||||
| 		elif self.docstatus == 1: | ||||
| 			self.status = 'Submitted' | ||||
| 		else: | ||||
| 			self.status = 'Draft' | ||||
| 
 | ||||
| 	def set_amounts(self): | ||||
| 		self.set_amounts_in_company_currency() | ||||
| 		self.set_total_allocated_amount() | ||||
|  | ||||
| @ -90,7 +90,8 @@ class PaymentReconciliation(Document): | ||||
| 			FROM `tab{doc}`, `tabGL Entry` | ||||
| 			WHERE | ||||
| 				(`tab{doc}`.name = `tabGL Entry`.against_voucher or `tab{doc}`.name = `tabGL Entry`.voucher_no) | ||||
| 				and `tab{doc}`.is_return = 1 and `tabGL Entry`.against_voucher_type = %(voucher_type)s | ||||
| 				and `tab{doc}`.is_return = 1 and `tab{doc}`.return_against IS NULL | ||||
| 				and `tabGL Entry`.against_voucher_type = %(voucher_type)s | ||||
| 				and `tab{doc}`.docstatus = 1 and `tabGL Entry`.party = %(party)s | ||||
| 				and `tabGL Entry`.party_type = %(party_type)s and `tabGL Entry`.account = %(account)s | ||||
| 			GROUP BY `tab{doc}`.name | ||||
|  | ||||
| @ -18,13 +18,14 @@ from erpnext.accounts.general_ledger import make_gl_entries, merge_similar_entri | ||||
| from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt | ||||
| from erpnext.buying.utils import check_on_hold_or_closed_status | ||||
| from erpnext.accounts.general_ledger import get_round_off_account_and_cost_center | ||||
| from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_disabled | ||||
| from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_enabled | ||||
| from frappe.model.mapper import get_mapped_doc | ||||
| from six import iteritems | ||||
| from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_party, update_linked_doc,\ | ||||
| 	unlink_inter_company_doc | ||||
| from erpnext.accounts.doctype.tax_withholding_category.tax_withholding_category import get_party_tax_withholding_details | ||||
| from erpnext.accounts.deferred_revenue import validate_service_stop_date | ||||
| from erpnext.stock.doctype.purchase_receipt.purchase_receipt import get_item_account_wise_additional_cost | ||||
| 
 | ||||
| form_grid_templates = { | ||||
| 	"items": "templates/form_grid/item_grid.html" | ||||
| @ -225,6 +226,8 @@ class PurchaseInvoice(BuyingController): | ||||
| 			# in case of auto inventory accounting, | ||||
| 			# expense account is always "Stock Received But Not Billed" for a stock item | ||||
| 			# except epening entry, drop-ship entry and fixed asset items | ||||
| 			if item.item_code: | ||||
| 				asset_category = frappe.get_cached_value("Item", item.item_code, "asset_category") | ||||
| 
 | ||||
| 			if auto_accounting_for_stock and item.item_code in stock_items \ | ||||
| 				and self.is_opening == 'No' and not item.is_fixed_asset \ | ||||
| @ -235,7 +238,8 @@ class PurchaseInvoice(BuyingController): | ||||
| 					item.expense_account = warehouse_account[item.warehouse]["account"] | ||||
| 				else: | ||||
| 					item.expense_account = stock_not_billed_account | ||||
| 			elif item.is_fixed_asset and is_cwip_accounting_disabled(): | ||||
| 
 | ||||
| 			elif item.is_fixed_asset and not is_cwip_accounting_enabled(self.company, asset_category): | ||||
| 				if not item.asset: | ||||
| 					frappe.throw(_("Row {0}: asset is required for item {1}") | ||||
| 						.format(item.idx, item.item_code)) | ||||
| @ -391,7 +395,8 @@ class PurchaseInvoice(BuyingController): | ||||
| 
 | ||||
| 		self.make_supplier_gl_entry(gl_entries) | ||||
| 		self.make_item_gl_entries(gl_entries) | ||||
| 		if not is_cwip_accounting_disabled(): | ||||
| 
 | ||||
| 		if self.check_asset_cwip_enabled(): | ||||
| 			self.get_asset_gl_entry(gl_entries) | ||||
| 
 | ||||
| 		self.make_tax_gl_entries(gl_entries) | ||||
| @ -404,6 +409,15 @@ class PurchaseInvoice(BuyingController): | ||||
| 
 | ||||
| 		return gl_entries | ||||
| 
 | ||||
| 	def check_asset_cwip_enabled(self): | ||||
| 		# Check if there exists any item with cwip accounting enabled in it's asset category | ||||
| 		for item in self.get("items"): | ||||
| 			if item.item_code and item.is_fixed_asset: | ||||
| 				asset_category = frappe.get_cached_value("Item", item.item_code, "asset_category") | ||||
| 				if is_cwip_accounting_enabled(self.company, asset_category): | ||||
| 					return 1 | ||||
| 		return 0 | ||||
| 
 | ||||
| 	def make_supplier_gl_entry(self, gl_entries): | ||||
| 		# Checked both rounding_adjustment and rounded_total | ||||
| 		# because rounded_total had value even before introcution of posting GLE based on rounded total | ||||
| @ -436,6 +450,8 @@ class PurchaseInvoice(BuyingController): | ||||
| 		if self.update_stock and self.auto_accounting_for_stock: | ||||
| 			warehouse_account = get_warehouse_account_map(self.company) | ||||
| 
 | ||||
| 		landed_cost_entries = get_item_account_wise_additional_cost(self.name) | ||||
| 
 | ||||
| 		voucher_wise_stock_value = {} | ||||
| 		if self.update_stock: | ||||
| 			for d in frappe.get_all('Stock Ledger Entry', | ||||
| @ -445,6 +461,8 @@ class PurchaseInvoice(BuyingController): | ||||
| 		for item in self.get("items"): | ||||
| 			if flt(item.base_net_amount): | ||||
| 				account_currency = get_account_currency(item.expense_account) | ||||
| 				if item.item_code: | ||||
| 					asset_category = frappe.get_cached_value("Item", item.item_code, "asset_category") | ||||
| 
 | ||||
| 				if self.update_stock and self.auto_accounting_for_stock and item.item_code in stock_items: | ||||
| 					# warehouse account | ||||
| @ -463,15 +481,16 @@ class PurchaseInvoice(BuyingController): | ||||
| 					) | ||||
| 
 | ||||
| 					# Amount added through landed-cost-voucher | ||||
| 					if flt(item.landed_cost_voucher_amount): | ||||
| 						gl_entries.append(self.get_gl_dict({ | ||||
| 							"account": expenses_included_in_valuation, | ||||
| 							"against": item.expense_account, | ||||
| 							"cost_center": item.cost_center, | ||||
| 							"remarks": self.get("remarks") or _("Accounting Entry for Stock"), | ||||
| 							"credit": flt(item.landed_cost_voucher_amount), | ||||
| 							"project": item.project | ||||
| 						}, item=item)) | ||||
| 					if landed_cost_entries: | ||||
| 						for account, amount in iteritems(landed_cost_entries[(item.item_code, item.name)]): | ||||
| 							gl_entries.append(self.get_gl_dict({ | ||||
| 								"account": account, | ||||
| 								"against": item.expense_account, | ||||
| 								"cost_center": item.cost_center, | ||||
| 								"remarks": self.get("remarks") or _("Accounting Entry for Stock"), | ||||
| 								"credit": flt(amount), | ||||
| 								"project": item.project | ||||
| 							}, item=item)) | ||||
| 
 | ||||
| 					# sub-contracting warehouse | ||||
| 					if flt(item.rm_supp_cost): | ||||
| @ -486,8 +505,9 @@ class PurchaseInvoice(BuyingController): | ||||
| 							"remarks": self.get("remarks") or _("Accounting Entry for Stock"), | ||||
| 							"credit": flt(item.rm_supp_cost) | ||||
| 						}, warehouse_account[self.supplier_warehouse]["account_currency"], item=item)) | ||||
| 				elif not item.is_fixed_asset or (item.is_fixed_asset and is_cwip_accounting_disabled()): | ||||
| 
 | ||||
| 				elif not item.is_fixed_asset or (item.is_fixed_asset and not is_cwip_accounting_enabled(self.company, | ||||
| 					asset_category)): | ||||
| 					expense_account = (item.expense_account | ||||
| 						if (not item.enable_deferred_expense or self.is_return) else item.deferred_expense_account) | ||||
| 
 | ||||
| @ -528,7 +548,10 @@ class PurchaseInvoice(BuyingController): | ||||
| 
 | ||||
| 	def get_asset_gl_entry(self, gl_entries): | ||||
| 		for item in self.get("items"): | ||||
| 			if item.is_fixed_asset: | ||||
| 			if item.item_code and item.is_fixed_asset : | ||||
| 				asset_category = frappe.get_cached_value("Item", item.item_code, "asset_category") | ||||
| 
 | ||||
| 			if item.is_fixed_asset and is_cwip_accounting_enabled(self.company, asset_category) : | ||||
| 				eiiav_account = self.get_company_default("expenses_included_in_asset_valuation") | ||||
| 
 | ||||
| 				asset_amount = flt(item.net_amount) + flt(item.item_tax_amount/self.conversion_rate) | ||||
|  | ||||
| @ -6,8 +6,8 @@ frappe.listview_settings['Purchase Invoice'] = { | ||||
| 	add_fields: ["supplier", "supplier_name", "base_grand_total", "outstanding_amount", "due_date", "company", | ||||
| 		"currency", "is_return", "release_date", "on_hold"], | ||||
| 	get_indicator: function(doc) { | ||||
| 		if(flt(doc.outstanding_amount) < 0 && doc.docstatus == 1) { | ||||
| 			return [__("Debit Note Issued"), "darkgrey", "outstanding_amount,<,0"] | ||||
| 		if( (flt(doc.outstanding_amount) <= 0) && doc.docstatus == 1 &&  doc.status == 'Debit Note Issued') { | ||||
| 			return [__("Debit Note Issued"), "darkgrey", "outstanding_amount,<=,0"]; | ||||
| 		} else if(flt(doc.outstanding_amount) > 0 && doc.docstatus==1) { | ||||
| 			if(cint(doc.on_hold) && !doc.release_date) { | ||||
| 				return [__("On Hold"), "darkgrey"]; | ||||
|  | ||||
| @ -1230,7 +1230,8 @@ class SalesInvoice(SellingController): | ||||
| 					self.status = "Unpaid and Discounted" | ||||
| 				elif flt(self.outstanding_amount) > 0 and getdate(self.due_date) >= getdate(nowdate()): | ||||
| 					self.status = "Unpaid" | ||||
| 				elif flt(self.outstanding_amount) < 0 and self.is_return==0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}): | ||||
| 				#Check if outstanding amount is 0 due to credit note issued against invoice | ||||
| 				elif flt(self.outstanding_amount) <= 0 and self.is_return == 0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}): | ||||
| 					self.status = "Credit Note Issued" | ||||
| 				elif self.is_return == 1: | ||||
| 					self.status = "Return" | ||||
|  | ||||
| @ -21,6 +21,8 @@ frappe.ui.form.on('Share Transfer', { | ||||
| 				erpnext.share_transfer.make_jv(frm); | ||||
| 			}); | ||||
| 		} | ||||
| 
 | ||||
| 		frm.toggle_reqd("asset_account", frm.doc.transfer_type != "Transfer"); | ||||
| 	}, | ||||
| 	no_of_shares: (frm) => { | ||||
| 		if (frm.doc.rate != undefined || frm.doc.rate != null){ | ||||
| @ -56,6 +58,10 @@ frappe.ui.form.on('Share Transfer', { | ||||
| 				}; | ||||
| 			}); | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	transfer_type: function(frm) { | ||||
| 		frm.toggle_reqd("asset_account", frm.doc.transfer_type != "Transfer"); | ||||
| 	} | ||||
| }); | ||||
| 
 | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -168,14 +168,20 @@ def validate_account_for_perpetual_inventory(gl_map): | ||||
| 					StockValueAndAccountBalanceOutOfSync) | ||||
| 
 | ||||
| def validate_cwip_accounts(gl_map): | ||||
| 	if not cint(frappe.db.get_value("Asset Settings", None, "disable_cwip_accounting")) \ | ||||
| 		and gl_map[0].voucher_type == "Journal Entry": | ||||
| 	cwip_enabled = cint(frappe.get_cached_value("Company", | ||||
| 		gl_map[0].company, "enable_cwip_accounting")) | ||||
| 
 | ||||
| 	if not cwip_enabled: | ||||
| 		cwip_enabled = any([cint(ac.enable_cwip_accounting) for ac in frappe.db.get_all("Asset Category","enable_cwip_accounting")]) | ||||
| 
 | ||||
| 	if cwip_enabled and gl_map[0].voucher_type == "Journal Entry": | ||||
| 			cwip_accounts = [d[0] for d in frappe.db.sql("""select name from tabAccount | ||||
| 				where account_type = 'Capital Work in Progress' and is_group=0""")] | ||||
| 
 | ||||
| 			for entry in gl_map: | ||||
| 				if entry.account in cwip_accounts: | ||||
| 					frappe.throw(_("Account: <b>{0}</b> is capital Work in progress and can not be updated by Journal Entry").format(entry.account)) | ||||
| 					frappe.throw( | ||||
| 						_("Account: <b>{0}</b> is capital Work in progress and can not be updated by Journal Entry").format(entry.account)) | ||||
| 
 | ||||
| def round_off_debit_credit(gl_map): | ||||
| 	precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"), | ||||
|  | ||||
| @ -139,15 +139,11 @@ erpnext.accounts.bankTransactionUpload = class bankTransactionUpload { | ||||
| 	} | ||||
| 
 | ||||
| 	make() { | ||||
| 		const me = this; | ||||
| 		frappe.upload.make({ | ||||
| 			args: { | ||||
| 				method: 'erpnext.accounts.doctype.bank_transaction.bank_transaction_upload.upload_bank_statement', | ||||
| 				allow_multiple: 0 | ||||
| 			}, | ||||
| 			no_socketio: true, | ||||
| 			sample_url: "e.g. http://example.com/somefile.csv", | ||||
| 			callback: function(attachment, r) { | ||||
| 		const me = this;	 | ||||
| 		new frappe.ui.FileUploader({ | ||||
| 			method: 'erpnext.accounts.doctype.bank_transaction.bank_transaction_upload.upload_bank_statement', | ||||
| 			allow_multiple: 0, | ||||
| 			on_success: function(attachment, r) { | ||||
| 				if (!r.exc && r.message) { | ||||
| 					me.data = r.message; | ||||
| 					me.setup_transactions_dom(); | ||||
| @ -533,9 +529,16 @@ erpnext.accounts.ReconciliationRow = class ReconciliationRow { | ||||
| 			frappe.db.get_doc(dt, event.value) | ||||
| 			.then(doc => { | ||||
| 				let displayed_docs = [] | ||||
| 				let payment = [] | ||||
| 				if (dt === "Payment Entry") { | ||||
| 					payment.currency = doc.payment_type == "Receive" ? doc.paid_to_account_currency : doc.paid_from_account_currency; | ||||
| 					payment.doctype = dt | ||||
| 					payment.posting_date = doc.posting_date; | ||||
| 					payment.party = doc.party; | ||||
| 					payment.reference_no = doc.reference_no; | ||||
| 					payment.reference_date = doc.reference_date; | ||||
| 					payment.paid_amount = doc.paid_amount; | ||||
| 					payment.name = doc.name; | ||||
| 					displayed_docs.push(payment); | ||||
| 				} else if (dt === "Journal Entry") { | ||||
| 					doc.accounts.forEach(payment => { | ||||
| @ -568,11 +571,11 @@ erpnext.accounts.ReconciliationRow = class ReconciliationRow { | ||||
| 
 | ||||
| 				const details_wrapper = me.dialog.fields_dict.payment_details.$wrapper; | ||||
| 				details_wrapper.append(frappe.render_template("linked_payment_header")); | ||||
| 				displayed_docs.forEach(values => { | ||||
| 					details_wrapper.append(frappe.render_template("linked_payment_row", values)); | ||||
| 				displayed_docs.forEach(payment => { | ||||
| 					details_wrapper.append(frappe.render_template("linked_payment_row", payment)); | ||||
| 				}) | ||||
| 			}) | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -79,13 +79,20 @@ frappe.query_reports["Accounts Receivable"] = { | ||||
| 			"options": "Customer", | ||||
| 			on_change: () => { | ||||
| 				var customer = frappe.query_report.get_filter_value('customer'); | ||||
| 				var company = frappe.query_report.get_filter_value('company'); | ||||
| 				if (customer) { | ||||
| 					frappe.db.get_value('Customer', customer, ["tax_id", "customer_name", "credit_limit", "payment_terms"], function(value) { | ||||
| 					frappe.db.get_value('Customer', customer, ["tax_id", "customer_name", "payment_terms"], function(value) { | ||||
| 						frappe.query_report.set_filter_value('tax_id', value["tax_id"]); | ||||
| 						frappe.query_report.set_filter_value('customer_name', value["customer_name"]); | ||||
| 						frappe.query_report.set_filter_value('credit_limit', value["credit_limit"]); | ||||
| 						frappe.query_report.set_filter_value('payment_terms', value["payment_terms"]); | ||||
| 					}); | ||||
| 
 | ||||
| 					frappe.db.get_value('Customer Credit Limit', {'parent': customer, 'company': company},  | ||||
| 						["credit_limit"], function(value) { | ||||
| 						if (value) { | ||||
| 							frappe.query_report.set_filter_value('credit_limit', value["credit_limit"]); | ||||
| 						} | ||||
| 					}, "Customer"); | ||||
| 				} else { | ||||
| 					frappe.query_report.set_filter_value('tax_id', ""); | ||||
| 					frappe.query_report.set_filter_value('customer_name', ""); | ||||
|  | ||||
| @ -76,8 +76,7 @@ def get_data(filters): | ||||
| 	accumulate_values_into_parents(accounts, accounts_by_name) | ||||
| 
 | ||||
| 	data = prepare_data(accounts, filters, total_row, parent_children_map, company_currency) | ||||
| 	data = filter_out_zero_value_rows(data, parent_children_map, | ||||
| 		show_zero_values=filters.get("show_zero_values")) | ||||
| 	data = filter_out_zero_value_rows(data, parent_children_map, show_zero_values=filters.get("show_zero_values")) | ||||
| 
 | ||||
| 	return data | ||||
| 
 | ||||
| @ -187,33 +186,11 @@ def calculate_values(accounts, gl_entries_by_account, opening_balances, filters, | ||||
| 
 | ||||
| 		d["closing_debit"] = d["opening_debit"] + d["debit"] | ||||
| 		d["closing_credit"] = d["opening_credit"] + d["credit"] | ||||
| 		total_row["debit"] += d["debit"] | ||||
| 		total_row["credit"] += d["credit"] | ||||
| 
 | ||||
| 		if d["root_type"] == "Asset" or d["root_type"] == "Equity" or d["root_type"] == "Expense": | ||||
| 			d["opening_debit"] -= d["opening_credit"] | ||||
| 			d["closing_debit"] -= d["closing_credit"] | ||||
| 		prepare_opening_closing(d) | ||||
| 
 | ||||
| 			# For opening | ||||
| 			check_opening_closing_has_negative_value(d, "opening_debit", "opening_credit") | ||||
| 
 | ||||
| 			# For closing | ||||
| 			check_opening_closing_has_negative_value(d, "closing_debit", "closing_credit") | ||||
| 
 | ||||
| 		if d["root_type"] == "Liability" or d["root_type"] == "Income": | ||||
| 			d["opening_credit"] -= d["opening_debit"] | ||||
| 			d["closing_credit"] -= d["closing_debit"] | ||||
| 
 | ||||
| 			# For opening | ||||
| 			check_opening_closing_has_negative_value(d, "opening_credit", "opening_debit") | ||||
| 
 | ||||
| 			# For closing | ||||
| 			check_opening_closing_has_negative_value(d, "closing_credit", "closing_debit") | ||||
| 
 | ||||
| 		total_row["opening_debit"] += d["opening_debit"] | ||||
| 		total_row["closing_debit"] += d["closing_debit"] | ||||
| 		total_row["opening_credit"] += d["opening_credit"] | ||||
| 		total_row["closing_credit"] += d["closing_credit"] | ||||
| 		for field in value_fields: | ||||
| 			total_row[field] += d[field] | ||||
| 
 | ||||
| 	return total_row | ||||
| 
 | ||||
| @ -227,6 +204,10 @@ def prepare_data(accounts, filters, total_row, parent_children_map, company_curr | ||||
| 	data = [] | ||||
| 
 | ||||
| 	for d in accounts: | ||||
| 		# Prepare opening closing for group account | ||||
| 		if parent_children_map.get(d.account): | ||||
| 			prepare_opening_closing(d) | ||||
| 
 | ||||
| 		has_value = False | ||||
| 		row = { | ||||
| 			"account": d.name, | ||||
| @ -313,11 +294,16 @@ def get_columns(): | ||||
| 		} | ||||
| 	] | ||||
| 
 | ||||
| def check_opening_closing_has_negative_value(d, dr_or_cr, switch_to_column): | ||||
| 	# If opening debit has negetive value then move it to opening credit and vice versa. | ||||
| def prepare_opening_closing(row): | ||||
| 	dr_or_cr = "debit" if row["root_type"] in ["Asset", "Equity", "Expense"] else "credit" | ||||
| 	reverse_dr_or_cr = "credit" if dr_or_cr == "debit" else "debit" | ||||
| 
 | ||||
| 	if d[dr_or_cr] < 0: | ||||
| 		d[switch_to_column] = abs(d[dr_or_cr]) | ||||
| 		d[dr_or_cr] = 0.0 | ||||
| 	else: | ||||
| 		d[switch_to_column] = 0.0 | ||||
| 	for col_type in ["opening", "closing"]: | ||||
| 		valid_col = col_type + "_" + dr_or_cr | ||||
| 		reverse_col = col_type + "_" + reverse_dr_or_cr | ||||
| 		row[valid_col] -= row[reverse_col] | ||||
| 		if row[valid_col] < 0: | ||||
| 			row[reverse_col] = abs(row[valid_col]) | ||||
| 			row[valid_col] = 0.0 | ||||
| 		else: | ||||
| 			row[reverse_col] = 0.0 | ||||
| @ -203,7 +203,7 @@ frappe.ui.form.on('Asset', { | ||||
| 	}, | ||||
| 
 | ||||
| 	opening_accumulated_depreciation: function(frm) { | ||||
| 		erpnext.asset.set_accululated_depreciation(frm); | ||||
| 		erpnext.asset.set_accumulated_depreciation(frm); | ||||
| 	}, | ||||
| 
 | ||||
| 	make_schedules_editable: function(frm) { | ||||
| @ -282,17 +282,6 @@ frappe.ui.form.on('Asset', { | ||||
| 	}, | ||||
| 
 | ||||
| 	calculate_depreciation: function(frm) { | ||||
| 		frappe.db.get_value("Asset Settings", {'name':"Asset Settings"}, 'schedule_based_on_fiscal_year', (data) => { | ||||
| 			if (data.schedule_based_on_fiscal_year == 1) { | ||||
| 				frm.set_df_property("depreciation_method", "options", "\nStraight Line\nManual"); | ||||
| 				frm.toggle_reqd("available_for_use_date", true); | ||||
| 				frm.toggle_display("frequency_of_depreciation", false); | ||||
| 				frappe.db.get_value("Fiscal Year", {'name': frappe.sys_defaults.fiscal_year}, "year_end_date", (data) => { | ||||
| 					frm.set_value("next_depreciation_date", data.year_end_date); | ||||
| 				}) | ||||
| 			} | ||||
| 		}) | ||||
| 
 | ||||
| 		frm.toggle_reqd("finance_books", frm.doc.calculate_depreciation); | ||||
| 	}, | ||||
| 
 | ||||
| @ -371,12 +360,12 @@ frappe.ui.form.on('Depreciation Schedule', { | ||||
| 	}, | ||||
| 
 | ||||
| 	depreciation_amount: function(frm, cdt, cdn) { | ||||
| 		erpnext.asset.set_accululated_depreciation(frm); | ||||
| 		erpnext.asset.set_accumulated_depreciation(frm); | ||||
| 	} | ||||
| 
 | ||||
| }) | ||||
| 
 | ||||
| erpnext.asset.set_accululated_depreciation = function(frm) { | ||||
| erpnext.asset.set_accumulated_depreciation = function(frm) { | ||||
| 	if(frm.doc.depreciation_method != "Manual") return; | ||||
| 
 | ||||
| 	var accumulated_depreciation = flt(frm.doc.opening_accumulated_depreciation); | ||||
|  | ||||
| @ -1,497 +1,499 @@ | ||||
| { | ||||
|    "allow_import": 1, | ||||
|    "allow_rename": 1, | ||||
|    "autoname": "naming_series:", | ||||
|    "creation": "2016-03-01 17:01:27.920130", | ||||
|    "doctype": "DocType", | ||||
|    "document_type": "Document", | ||||
|    "field_order": [ | ||||
|     "naming_series", | ||||
|     "asset_name", | ||||
|     "item_code", | ||||
|     "item_name", | ||||
|     "asset_category", | ||||
|     "asset_owner", | ||||
|     "asset_owner_company", | ||||
|     "supplier", | ||||
|     "customer", | ||||
|     "image", | ||||
|     "column_break_3", | ||||
|     "company", | ||||
|     "location", | ||||
|     "custodian", | ||||
|     "department", | ||||
|     "purchase_date", | ||||
|     "disposal_date", | ||||
|     "journal_entry_for_scrap", | ||||
|     "accounting_dimensions_section", | ||||
|     "cost_center", | ||||
|     "dimension_col_break", | ||||
|     "section_break_5", | ||||
|     "gross_purchase_amount", | ||||
|     "available_for_use_date", | ||||
|     "column_break_18", | ||||
|     "calculate_depreciation", | ||||
|     "is_existing_asset", | ||||
|     "opening_accumulated_depreciation", | ||||
|     "number_of_depreciations_booked", | ||||
|     "section_break_23", | ||||
|     "finance_books", | ||||
|     "section_break_33", | ||||
|     "depreciation_method", | ||||
|     "value_after_depreciation", | ||||
|     "total_number_of_depreciations", | ||||
|     "column_break_24", | ||||
|     "frequency_of_depreciation", | ||||
|     "next_depreciation_date", | ||||
|     "section_break_14", | ||||
|     "schedules", | ||||
|     "insurance_details", | ||||
|     "policy_number", | ||||
|     "insurer", | ||||
|     "insured_value", | ||||
|     "column_break_48", | ||||
|     "insurance_start_date", | ||||
|     "insurance_end_date", | ||||
|     "comprehensive_insurance", | ||||
|     "section_break_31", | ||||
|     "maintenance_required", | ||||
|     "other_details", | ||||
|     "status", | ||||
|     "booked_fixed_asset", | ||||
|     "column_break_51", | ||||
|     "purchase_receipt", | ||||
|     "purchase_receipt_amount", | ||||
|     "purchase_invoice", | ||||
|     "default_finance_book", | ||||
|     "amended_from" | ||||
|    ], | ||||
|    "fields": [ | ||||
|     { | ||||
|      "fieldname": "naming_series", | ||||
|      "fieldtype": "Select", | ||||
|      "label": "Naming Series", | ||||
|      "options": "ACC-ASS-.YYYY.-" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "asset_name", | ||||
|      "fieldtype": "Data", | ||||
|      "in_list_view": 1, | ||||
|      "label": "Asset Name", | ||||
|      "reqd": 1 | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "item_code", | ||||
|      "fieldtype": "Link", | ||||
|      "in_standard_filter": 1, | ||||
|      "label": "Item Code", | ||||
|      "options": "Item", | ||||
|      "reqd": 1 | ||||
|     }, | ||||
|     { | ||||
|      "fetch_from": "item_code.item_name", | ||||
|      "fieldname": "item_name", | ||||
|      "fieldtype": "Read Only", | ||||
|      "label": "Item Name" | ||||
|     }, | ||||
|     { | ||||
|      "fetch_from": "item_code.asset_category", | ||||
|      "fieldname": "asset_category", | ||||
|      "fieldtype": "Link", | ||||
|      "in_global_search": 1, | ||||
|      "in_list_view": 1, | ||||
|      "in_standard_filter": 1, | ||||
|      "label": "Asset Category", | ||||
|      "options": "Asset Category", | ||||
|      "read_only": 1 | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "asset_owner", | ||||
|      "fieldtype": "Select", | ||||
|      "label": "Asset Owner", | ||||
|      "options": "\nCompany\nSupplier\nCustomer" | ||||
|     }, | ||||
|     { | ||||
|      "depends_on": "eval:doc.asset_owner == \"Company\"", | ||||
|      "fieldname": "asset_owner_company", | ||||
|      "fieldtype": "Link", | ||||
|      "label": "Asset Owner Company", | ||||
|      "options": "Company" | ||||
|     }, | ||||
|     { | ||||
|      "depends_on": "eval:doc.asset_owner == \"Supplier\"", | ||||
|      "fieldname": "supplier", | ||||
|      "fieldtype": "Link", | ||||
|      "label": "Supplier", | ||||
|      "options": "Supplier" | ||||
|     }, | ||||
|     { | ||||
|      "depends_on": "eval:doc.asset_owner == \"Customer\"", | ||||
|      "fieldname": "customer", | ||||
|      "fieldtype": "Link", | ||||
|      "label": "Customer", | ||||
|      "options": "Customer" | ||||
|     }, | ||||
|     { | ||||
|      "allow_on_submit": 1, | ||||
|      "fieldname": "image", | ||||
|      "fieldtype": "Attach Image", | ||||
|      "hidden": 1, | ||||
|      "label": "Image", | ||||
|      "no_copy": 1, | ||||
|      "print_hide": 1 | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "column_break_3", | ||||
|      "fieldtype": "Column Break" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "company", | ||||
|      "fieldtype": "Link", | ||||
|      "label": "Company", | ||||
|      "options": "Company", | ||||
|      "remember_last_selected_value": 1, | ||||
|      "reqd": 1 | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "location", | ||||
|      "fieldtype": "Link", | ||||
|      "in_list_view": 1, | ||||
|      "label": "Location", | ||||
|      "options": "Location", | ||||
|      "reqd": 1 | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "custodian", | ||||
|      "fieldtype": "Link", | ||||
|      "ignore_user_permissions": 1, | ||||
|      "label": "Custodian", | ||||
|      "options": "Employee" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "cost_center", | ||||
|      "fieldtype": "Link", | ||||
|      "label": "Cost Center", | ||||
|      "options": "Cost Center" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "department", | ||||
|      "fieldtype": "Link", | ||||
|      "label": "Department", | ||||
|      "options": "Department" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "purchase_date", | ||||
|      "fieldtype": "Date", | ||||
|      "label": "Purchase Date", | ||||
|      "reqd": 1 | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "disposal_date", | ||||
|      "fieldtype": "Date", | ||||
|      "label": "Disposal Date", | ||||
|      "read_only": 1 | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "journal_entry_for_scrap", | ||||
|      "fieldtype": "Link", | ||||
|      "label": "Journal Entry for Scrap", | ||||
|      "no_copy": 1, | ||||
|      "options": "Journal Entry", | ||||
|      "print_hide": 1, | ||||
|      "read_only": 1 | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "section_break_5", | ||||
|      "fieldtype": "Section Break" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "gross_purchase_amount", | ||||
|      "fieldtype": "Currency", | ||||
|      "label": "Gross Purchase Amount", | ||||
|      "options": "Company:company:default_currency", | ||||
|      "reqd": 1 | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "available_for_use_date", | ||||
|      "fieldtype": "Date", | ||||
|      "label": "Available-for-use Date" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "column_break_18", | ||||
|      "fieldtype": "Column Break" | ||||
|     }, | ||||
|     { | ||||
|      "default": "0", | ||||
|      "fieldname": "calculate_depreciation", | ||||
|      "fieldtype": "Check", | ||||
|      "label": "Calculate Depreciation" | ||||
|     }, | ||||
|     { | ||||
|      "default": "0", | ||||
|      "fieldname": "is_existing_asset", | ||||
|      "fieldtype": "Check", | ||||
|      "label": "Is Existing Asset" | ||||
|     }, | ||||
|     { | ||||
|      "depends_on": "is_existing_asset", | ||||
|      "fieldname": "opening_accumulated_depreciation", | ||||
|      "fieldtype": "Currency", | ||||
|      "label": "Opening Accumulated Depreciation", | ||||
|      "no_copy": 1, | ||||
|      "options": "Company:company:default_currency" | ||||
|     }, | ||||
|     { | ||||
|      "depends_on": "eval:(doc.is_existing_asset && doc.opening_accumulated_depreciation)", | ||||
|      "fieldname": "number_of_depreciations_booked", | ||||
|      "fieldtype": "Int", | ||||
|      "label": "Number of Depreciations Booked", | ||||
|      "no_copy": 1 | ||||
|     }, | ||||
|     { | ||||
|      "depends_on": "calculate_depreciation", | ||||
|      "fieldname": "section_break_23", | ||||
|      "fieldtype": "Section Break", | ||||
|      "label": "Depreciation" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "finance_books", | ||||
|      "fieldtype": "Table", | ||||
|      "label": "Finance Books", | ||||
|      "options": "Asset Finance Book" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "section_break_33", | ||||
|      "fieldtype": "Section Break", | ||||
|      "hidden": 1 | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "depreciation_method", | ||||
|      "fieldtype": "Select", | ||||
|      "label": "Depreciation Method", | ||||
|      "options": "\nStraight Line\nDouble Declining Balance\nManual" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "value_after_depreciation", | ||||
|      "fieldtype": "Currency", | ||||
|      "hidden": 1, | ||||
|      "label": "Value After Depreciation", | ||||
|      "options": "Company:company:default_currency", | ||||
|      "read_only": 1 | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "total_number_of_depreciations", | ||||
|      "fieldtype": "Int", | ||||
|      "label": "Total Number of Depreciations" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "column_break_24", | ||||
|      "fieldtype": "Column Break" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "frequency_of_depreciation", | ||||
|      "fieldtype": "Int", | ||||
|      "label": "Frequency of Depreciation (Months)" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "next_depreciation_date", | ||||
|      "fieldtype": "Date", | ||||
|      "label": "Next Depreciation Date", | ||||
|      "no_copy": 1 | ||||
|     }, | ||||
|     { | ||||
|      "depends_on": "calculate_depreciation", | ||||
|      "fieldname": "section_break_14", | ||||
|      "fieldtype": "Section Break", | ||||
|      "label": "Depreciation Schedule" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "schedules", | ||||
|      "fieldtype": "Table", | ||||
|      "label": "Depreciation Schedules", | ||||
|      "no_copy": 1, | ||||
|      "options": "Depreciation Schedule" | ||||
|     }, | ||||
|     { | ||||
|      "collapsible": 1, | ||||
|      "fieldname": "insurance_details", | ||||
|      "fieldtype": "Section Break", | ||||
|      "label": "Insurance details" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "policy_number", | ||||
|      "fieldtype": "Data", | ||||
|      "label": "Policy number" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "insurer", | ||||
|      "fieldtype": "Data", | ||||
|      "label": "Insurer" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "insured_value", | ||||
|      "fieldtype": "Data", | ||||
|      "label": "Insured value" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "column_break_48", | ||||
|      "fieldtype": "Column Break" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "insurance_start_date", | ||||
|      "fieldtype": "Date", | ||||
|      "label": "Insurance Start Date" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "insurance_end_date", | ||||
|      "fieldtype": "Date", | ||||
|      "label": "Insurance End Date" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "comprehensive_insurance", | ||||
|      "fieldtype": "Data", | ||||
|      "label": "Comprehensive Insurance" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "section_break_31", | ||||
|      "fieldtype": "Section Break", | ||||
|      "label": "Maintenance" | ||||
|     }, | ||||
|     { | ||||
|      "allow_on_submit": 1, | ||||
|      "default": "0", | ||||
|      "description": "Check if Asset requires Preventive Maintenance or Calibration", | ||||
|      "fieldname": "maintenance_required", | ||||
|      "fieldtype": "Check", | ||||
|      "label": "Maintenance Required" | ||||
|     }, | ||||
|     { | ||||
|      "collapsible": 1, | ||||
|      "fieldname": "other_details", | ||||
|      "fieldtype": "Section Break", | ||||
|      "label": "Other Details" | ||||
|     }, | ||||
|     { | ||||
|      "allow_on_submit": 1, | ||||
|      "default": "Draft", | ||||
|      "fieldname": "status", | ||||
|      "fieldtype": "Select", | ||||
|      "in_list_view": 1, | ||||
|      "in_standard_filter": 1, | ||||
|      "label": "Status", | ||||
|      "no_copy": 1, | ||||
|      "options": "Draft\nSubmitted\nPartially Depreciated\nFully Depreciated\nSold\nScrapped\nIn Maintenance\nOut of Order\nIssue\nReceipt", | ||||
|      "read_only": 1 | ||||
|     }, | ||||
|     { | ||||
|      "default": "0", | ||||
|      "fieldname": "booked_fixed_asset", | ||||
|      "fieldtype": "Check", | ||||
|      "label": "Booked Fixed Asset", | ||||
|      "no_copy": 1, | ||||
|      "read_only": 1 | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "column_break_51", | ||||
|      "fieldtype": "Column Break" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "purchase_receipt", | ||||
|      "fieldtype": "Link", | ||||
|      "label": "Purchase Receipt", | ||||
|      "no_copy": 1, | ||||
|      "options": "Purchase Receipt", | ||||
|      "print_hide": 1, | ||||
|      "read_only": 1 | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "purchase_receipt_amount", | ||||
|      "fieldtype": "Currency", | ||||
|      "hidden": 1, | ||||
|      "label": "Purchase Receipt Amount", | ||||
|      "no_copy": 1, | ||||
|      "print_hide": 1, | ||||
|      "read_only": 1 | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "purchase_invoice", | ||||
|      "fieldtype": "Link", | ||||
|      "label": "Purchase Invoice", | ||||
|      "no_copy": 1, | ||||
|      "options": "Purchase Invoice", | ||||
|      "read_only": 1 | ||||
|     }, | ||||
|     { | ||||
|      "fetch_from": "company.default_finance_book", | ||||
|      "fieldname": "default_finance_book", | ||||
|      "fieldtype": "Link", | ||||
|      "hidden": 1, | ||||
|      "label": "Default Finance Book", | ||||
|      "options": "Finance Book", | ||||
|      "read_only": 1 | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "amended_from", | ||||
|      "fieldtype": "Link", | ||||
|      "label": "Amended From", | ||||
|      "no_copy": 1, | ||||
|      "options": "Asset", | ||||
|      "print_hide": 1, | ||||
|      "read_only": 1 | ||||
|     }, | ||||
|     { | ||||
|      "collapsible": 1, | ||||
|      "fieldname": "accounting_dimensions_section", | ||||
|      "fieldtype": "Section Break", | ||||
|      "label": "Accounting Dimensions" | ||||
|     }, | ||||
|     { | ||||
|      "fieldname": "dimension_col_break", | ||||
|      "fieldtype": "Column Break" | ||||
|     } | ||||
|    ], | ||||
|    "idx": 72, | ||||
|    "image_field": "image", | ||||
|    "is_submittable": 1, | ||||
|    "modified": "2019-05-25 22:26:19.786201", | ||||
|    "modified_by": "Administrator", | ||||
|    "module": "Assets", | ||||
|    "name": "Asset", | ||||
|    "owner": "Administrator", | ||||
|    "permissions": [ | ||||
|     { | ||||
|      "amend": 1, | ||||
|      "cancel": 1, | ||||
|      "create": 1, | ||||
|      "delete": 1, | ||||
|      "email": 1, | ||||
|      "export": 1, | ||||
|      "import": 1, | ||||
|      "print": 1, | ||||
|      "read": 1, | ||||
|      "report": 1, | ||||
|      "role": "Accounts User", | ||||
|      "share": 1, | ||||
|      "submit": 1, | ||||
|      "write": 1 | ||||
|     }, | ||||
|     { | ||||
|      "cancel": 1, | ||||
|      "create": 1, | ||||
|      "delete": 1, | ||||
|      "email": 1, | ||||
|      "export": 1, | ||||
|      "print": 1, | ||||
|      "read": 1, | ||||
|      "report": 1, | ||||
|      "role": "Quality Manager", | ||||
|      "share": 1, | ||||
|      "submit": 1, | ||||
|      "write": 1 | ||||
|     } | ||||
|    ], | ||||
|    "show_name_in_global_search": 1, | ||||
|    "sort_field": "modified", | ||||
|    "sort_order": "DESC", | ||||
|    "title_field": "asset_name" | ||||
|   } | ||||
|  "allow_import": 1, | ||||
|  "allow_rename": 1, | ||||
|  "autoname": "naming_series:", | ||||
|  "creation": "2016-03-01 17:01:27.920130", | ||||
|  "doctype": "DocType", | ||||
|  "document_type": "Document", | ||||
|  "engine": "InnoDB", | ||||
|  "field_order": [ | ||||
|   "naming_series", | ||||
|   "asset_name", | ||||
|   "item_code", | ||||
|   "item_name", | ||||
|   "asset_category", | ||||
|   "asset_owner", | ||||
|   "asset_owner_company", | ||||
|   "supplier", | ||||
|   "customer", | ||||
|   "image", | ||||
|   "column_break_3", | ||||
|   "company", | ||||
|   "location", | ||||
|   "custodian", | ||||
|   "department", | ||||
|   "purchase_date", | ||||
|   "disposal_date", | ||||
|   "journal_entry_for_scrap", | ||||
|   "accounting_dimensions_section", | ||||
|   "cost_center", | ||||
|   "dimension_col_break", | ||||
|   "section_break_5", | ||||
|   "gross_purchase_amount", | ||||
|   "available_for_use_date", | ||||
|   "column_break_18", | ||||
|   "calculate_depreciation", | ||||
|   "is_existing_asset", | ||||
|   "opening_accumulated_depreciation", | ||||
|   "number_of_depreciations_booked", | ||||
|   "section_break_23", | ||||
|   "finance_books", | ||||
|   "section_break_33", | ||||
|   "depreciation_method", | ||||
|   "value_after_depreciation", | ||||
|   "total_number_of_depreciations", | ||||
|   "column_break_24", | ||||
|   "frequency_of_depreciation", | ||||
|   "next_depreciation_date", | ||||
|   "section_break_14", | ||||
|   "schedules", | ||||
|   "insurance_details", | ||||
|   "policy_number", | ||||
|   "insurer", | ||||
|   "insured_value", | ||||
|   "column_break_48", | ||||
|   "insurance_start_date", | ||||
|   "insurance_end_date", | ||||
|   "comprehensive_insurance", | ||||
|   "section_break_31", | ||||
|   "maintenance_required", | ||||
|   "other_details", | ||||
|   "status", | ||||
|   "booked_fixed_asset", | ||||
|   "column_break_51", | ||||
|   "purchase_receipt", | ||||
|   "purchase_receipt_amount", | ||||
|   "purchase_invoice", | ||||
|   "default_finance_book", | ||||
|   "amended_from" | ||||
|  ], | ||||
|  "fields": [ | ||||
|   { | ||||
|    "fieldname": "naming_series", | ||||
|    "fieldtype": "Select", | ||||
|    "label": "Naming Series", | ||||
|    "options": "ACC-ASS-.YYYY.-" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "asset_name", | ||||
|    "fieldtype": "Data", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Asset Name", | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "item_code", | ||||
|    "fieldtype": "Link", | ||||
|    "in_standard_filter": 1, | ||||
|    "label": "Item Code", | ||||
|    "options": "Item", | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fetch_from": "item_code.item_name", | ||||
|    "fieldname": "item_name", | ||||
|    "fieldtype": "Read Only", | ||||
|    "label": "Item Name" | ||||
|   }, | ||||
|   { | ||||
|    "fetch_from": "item_code.asset_category", | ||||
|    "fieldname": "asset_category", | ||||
|    "fieldtype": "Link", | ||||
|    "in_global_search": 1, | ||||
|    "in_list_view": 1, | ||||
|    "in_standard_filter": 1, | ||||
|    "label": "Asset Category", | ||||
|    "options": "Asset Category", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "asset_owner", | ||||
|    "fieldtype": "Select", | ||||
|    "label": "Asset Owner", | ||||
|    "options": "\nCompany\nSupplier\nCustomer" | ||||
|   }, | ||||
|   { | ||||
|    "depends_on": "eval:doc.asset_owner == \"Company\"", | ||||
|    "fieldname": "asset_owner_company", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Asset Owner Company", | ||||
|    "options": "Company" | ||||
|   }, | ||||
|   { | ||||
|    "depends_on": "eval:doc.asset_owner == \"Supplier\"", | ||||
|    "fieldname": "supplier", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Supplier", | ||||
|    "options": "Supplier" | ||||
|   }, | ||||
|   { | ||||
|    "depends_on": "eval:doc.asset_owner == \"Customer\"", | ||||
|    "fieldname": "customer", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Customer", | ||||
|    "options": "Customer" | ||||
|   }, | ||||
|   { | ||||
|    "allow_on_submit": 1, | ||||
|    "fieldname": "image", | ||||
|    "fieldtype": "Attach Image", | ||||
|    "hidden": 1, | ||||
|    "label": "Image", | ||||
|    "no_copy": 1, | ||||
|    "print_hide": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "column_break_3", | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "company", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Company", | ||||
|    "options": "Company", | ||||
|    "remember_last_selected_value": 1, | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "location", | ||||
|    "fieldtype": "Link", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Location", | ||||
|    "options": "Location", | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "custodian", | ||||
|    "fieldtype": "Link", | ||||
|    "ignore_user_permissions": 1, | ||||
|    "label": "Custodian", | ||||
|    "options": "Employee" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "cost_center", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Cost Center", | ||||
|    "options": "Cost Center" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "department", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Department", | ||||
|    "options": "Department" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "purchase_date", | ||||
|    "fieldtype": "Date", | ||||
|    "label": "Purchase Date", | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "disposal_date", | ||||
|    "fieldtype": "Date", | ||||
|    "label": "Disposal Date", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "journal_entry_for_scrap", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Journal Entry for Scrap", | ||||
|    "no_copy": 1, | ||||
|    "options": "Journal Entry", | ||||
|    "print_hide": 1, | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "section_break_5", | ||||
|    "fieldtype": "Section Break" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "gross_purchase_amount", | ||||
|    "fieldtype": "Currency", | ||||
|    "label": "Gross Purchase Amount", | ||||
|    "options": "Company:company:default_currency", | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "available_for_use_date", | ||||
|    "fieldtype": "Date", | ||||
|    "label": "Available-for-use Date", | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "column_break_18", | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "default": "0", | ||||
|    "fieldname": "calculate_depreciation", | ||||
|    "fieldtype": "Check", | ||||
|    "label": "Calculate Depreciation" | ||||
|   }, | ||||
|   { | ||||
|    "default": "0", | ||||
|    "fieldname": "is_existing_asset", | ||||
|    "fieldtype": "Check", | ||||
|    "label": "Is Existing Asset" | ||||
|   }, | ||||
|   { | ||||
|    "depends_on": "is_existing_asset", | ||||
|    "fieldname": "opening_accumulated_depreciation", | ||||
|    "fieldtype": "Currency", | ||||
|    "label": "Opening Accumulated Depreciation", | ||||
|    "no_copy": 1, | ||||
|    "options": "Company:company:default_currency" | ||||
|   }, | ||||
|   { | ||||
|    "depends_on": "eval:(doc.is_existing_asset && doc.opening_accumulated_depreciation)", | ||||
|    "fieldname": "number_of_depreciations_booked", | ||||
|    "fieldtype": "Int", | ||||
|    "label": "Number of Depreciations Booked", | ||||
|    "no_copy": 1 | ||||
|   }, | ||||
|   { | ||||
|    "depends_on": "calculate_depreciation", | ||||
|    "fieldname": "section_break_23", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "Depreciation" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "finance_books", | ||||
|    "fieldtype": "Table", | ||||
|    "label": "Finance Books", | ||||
|    "options": "Asset Finance Book" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "section_break_33", | ||||
|    "fieldtype": "Section Break", | ||||
|    "hidden": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "depreciation_method", | ||||
|    "fieldtype": "Select", | ||||
|    "label": "Depreciation Method", | ||||
|    "options": "\nStraight Line\nDouble Declining Balance\nManual" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "value_after_depreciation", | ||||
|    "fieldtype": "Currency", | ||||
|    "hidden": 1, | ||||
|    "label": "Value After Depreciation", | ||||
|    "options": "Company:company:default_currency", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "total_number_of_depreciations", | ||||
|    "fieldtype": "Int", | ||||
|    "label": "Total Number of Depreciations" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "column_break_24", | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "frequency_of_depreciation", | ||||
|    "fieldtype": "Int", | ||||
|    "label": "Frequency of Depreciation (Months)" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "next_depreciation_date", | ||||
|    "fieldtype": "Date", | ||||
|    "label": "Next Depreciation Date", | ||||
|    "no_copy": 1 | ||||
|   }, | ||||
|   { | ||||
|    "depends_on": "calculate_depreciation", | ||||
|    "fieldname": "section_break_14", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "Depreciation Schedule" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "schedules", | ||||
|    "fieldtype": "Table", | ||||
|    "label": "Depreciation Schedules", | ||||
|    "no_copy": 1, | ||||
|    "options": "Depreciation Schedule" | ||||
|   }, | ||||
|   { | ||||
|    "collapsible": 1, | ||||
|    "fieldname": "insurance_details", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "Insurance details" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "policy_number", | ||||
|    "fieldtype": "Data", | ||||
|    "label": "Policy number" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "insurer", | ||||
|    "fieldtype": "Data", | ||||
|    "label": "Insurer" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "insured_value", | ||||
|    "fieldtype": "Data", | ||||
|    "label": "Insured value" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "column_break_48", | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "insurance_start_date", | ||||
|    "fieldtype": "Date", | ||||
|    "label": "Insurance Start Date" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "insurance_end_date", | ||||
|    "fieldtype": "Date", | ||||
|    "label": "Insurance End Date" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "comprehensive_insurance", | ||||
|    "fieldtype": "Data", | ||||
|    "label": "Comprehensive Insurance" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "section_break_31", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "Maintenance" | ||||
|   }, | ||||
|   { | ||||
|    "allow_on_submit": 1, | ||||
|    "default": "0", | ||||
|    "description": "Check if Asset requires Preventive Maintenance or Calibration", | ||||
|    "fieldname": "maintenance_required", | ||||
|    "fieldtype": "Check", | ||||
|    "label": "Maintenance Required" | ||||
|   }, | ||||
|   { | ||||
|    "collapsible": 1, | ||||
|    "fieldname": "other_details", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "Other Details" | ||||
|   }, | ||||
|   { | ||||
|    "allow_on_submit": 1, | ||||
|    "default": "Draft", | ||||
|    "fieldname": "status", | ||||
|    "fieldtype": "Select", | ||||
|    "in_list_view": 1, | ||||
|    "in_standard_filter": 1, | ||||
|    "label": "Status", | ||||
|    "no_copy": 1, | ||||
|    "options": "Draft\nSubmitted\nPartially Depreciated\nFully Depreciated\nSold\nScrapped\nIn Maintenance\nOut of Order\nIssue\nReceipt", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "default": "0", | ||||
|    "fieldname": "booked_fixed_asset", | ||||
|    "fieldtype": "Check", | ||||
|    "label": "Booked Fixed Asset", | ||||
|    "no_copy": 1, | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "column_break_51", | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "purchase_receipt", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Purchase Receipt", | ||||
|    "no_copy": 1, | ||||
|    "options": "Purchase Receipt", | ||||
|    "print_hide": 1, | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "purchase_receipt_amount", | ||||
|    "fieldtype": "Currency", | ||||
|    "hidden": 1, | ||||
|    "label": "Purchase Receipt Amount", | ||||
|    "no_copy": 1, | ||||
|    "print_hide": 1, | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "purchase_invoice", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Purchase Invoice", | ||||
|    "no_copy": 1, | ||||
|    "options": "Purchase Invoice", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fetch_from": "company.default_finance_book", | ||||
|    "fieldname": "default_finance_book", | ||||
|    "fieldtype": "Link", | ||||
|    "hidden": 1, | ||||
|    "label": "Default Finance Book", | ||||
|    "options": "Finance Book", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "amended_from", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Amended From", | ||||
|    "no_copy": 1, | ||||
|    "options": "Asset", | ||||
|    "print_hide": 1, | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "collapsible": 1, | ||||
|    "fieldname": "accounting_dimensions_section", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "Accounting Dimensions" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "dimension_col_break", | ||||
|    "fieldtype": "Column Break" | ||||
|   } | ||||
|  ], | ||||
|  "idx": 72, | ||||
|  "image_field": "image", | ||||
|  "is_submittable": 1, | ||||
|  "modified": "2019-10-07 15:34:30.976208", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Assets", | ||||
|  "name": "Asset", | ||||
|  "owner": "Administrator", | ||||
|  "permissions": [ | ||||
|   { | ||||
|    "amend": 1, | ||||
|    "cancel": 1, | ||||
|    "create": 1, | ||||
|    "delete": 1, | ||||
|    "email": 1, | ||||
|    "export": 1, | ||||
|    "import": 1, | ||||
|    "print": 1, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "role": "Accounts User", | ||||
|    "share": 1, | ||||
|    "submit": 1, | ||||
|    "write": 1 | ||||
|   }, | ||||
|   { | ||||
|    "cancel": 1, | ||||
|    "create": 1, | ||||
|    "delete": 1, | ||||
|    "email": 1, | ||||
|    "export": 1, | ||||
|    "print": 1, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "role": "Quality Manager", | ||||
|    "share": 1, | ||||
|    "submit": 1, | ||||
|    "write": 1 | ||||
|   } | ||||
|  ], | ||||
|  "show_name_in_global_search": 1, | ||||
|  "sort_field": "modified", | ||||
|  "sort_order": "DESC", | ||||
|  "title_field": "asset_name" | ||||
| } | ||||
| @ -30,7 +30,8 @@ class Asset(AccountsController): | ||||
| 		self.validate_in_use_date() | ||||
| 		self.set_status() | ||||
| 		self.update_stock_movement() | ||||
| 		if not self.booked_fixed_asset and not is_cwip_accounting_disabled(): | ||||
| 		if not self.booked_fixed_asset and is_cwip_accounting_enabled(self.company, | ||||
| 			self.asset_category): | ||||
| 			self.make_gl_entries() | ||||
| 
 | ||||
| 	def on_cancel(self): | ||||
| @ -76,10 +77,13 @@ class Asset(AccountsController): | ||||
| 			self.set('finance_books', finance_books) | ||||
| 
 | ||||
| 	def validate_asset_values(self): | ||||
| 		if not self.asset_category: | ||||
| 			self.asset_category = frappe.get_cached_value("Item", self.item_code, "asset_category") | ||||
| 
 | ||||
| 		if not flt(self.gross_purchase_amount): | ||||
| 			frappe.throw(_("Gross Purchase Amount is mandatory"), frappe.MandatoryError) | ||||
| 
 | ||||
| 		if not is_cwip_accounting_disabled(): | ||||
| 		if is_cwip_accounting_enabled(self.company, self.asset_category): | ||||
| 			if not self.is_existing_asset and not (self.purchase_receipt or self.purchase_invoice): | ||||
| 				frappe.throw(_("Please create purchase receipt or purchase invoice for the item {0}"). | ||||
| 					format(self.item_code)) | ||||
| @ -424,7 +428,7 @@ def update_maintenance_status(): | ||||
| 			asset.set_status('Out of Order') | ||||
| 
 | ||||
| def make_post_gl_entry(): | ||||
| 	if is_cwip_accounting_disabled(): | ||||
| 	if not is_cwip_accounting_enabled(self.company, self.asset_category): | ||||
| 		return | ||||
| 
 | ||||
| 	assets = frappe.db.sql_list(""" select name from `tabAsset` | ||||
| @ -574,8 +578,13 @@ def make_journal_entry(asset_name): | ||||
| 
 | ||||
| 	return je | ||||
| 
 | ||||
| def is_cwip_accounting_disabled(): | ||||
| 	return cint(frappe.db.get_single_value("Asset Settings", "disable_cwip_accounting")) | ||||
| def is_cwip_accounting_enabled(company, asset_category=None): | ||||
| 	enable_cwip_in_company = cint(frappe.db.get_value("Company", company, "enable_cwip_accounting")) | ||||
| 
 | ||||
| 	if enable_cwip_in_company or not asset_category: | ||||
| 		return enable_cwip_in_company | ||||
| 
 | ||||
| 	return cint(frappe.db.get_value("Asset Category", asset_category, "enable_cwip_accounting")) | ||||
| 
 | ||||
| def get_pro_rata_amt(row, depreciation_amount, from_date, to_date): | ||||
| 	days = date_diff(to_date, from_date) | ||||
| @ -587,4 +596,4 @@ def get_total_days(date, frequency): | ||||
| 	period_start_date = add_months(date, | ||||
| 		cint(frequency) * -1) | ||||
| 
 | ||||
| 	return date_diff(date, period_start_date) | ||||
| 	return date_diff(date, period_start_date) | ||||
|  | ||||
| @ -14,7 +14,6 @@ from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchas | ||||
| class TestAsset(unittest.TestCase): | ||||
| 	def setUp(self): | ||||
| 		set_depreciation_settings_in_company() | ||||
| 		remove_prorated_depreciation_schedule() | ||||
| 		create_asset_data() | ||||
| 		frappe.db.sql("delete from `tabTax Rule`") | ||||
| 
 | ||||
| @ -70,11 +69,13 @@ class TestAsset(unittest.TestCase): | ||||
| 			{"voucher_type": "Purchase Invoice", "voucher_no": pi.name})) | ||||
| 
 | ||||
| 	def test_is_fixed_asset_set(self): | ||||
| 		asset = create_asset(is_existing_asset = 1) | ||||
| 		doc = frappe.new_doc('Purchase Invoice') | ||||
| 		doc.supplier = '_Test Supplier' | ||||
| 		doc.append('items', { | ||||
| 			'item_code': 'Macbook Pro', | ||||
| 			'qty': 1 | ||||
| 			'qty': 1, | ||||
| 			'asset': asset.name | ||||
| 		}) | ||||
| 
 | ||||
| 		doc.set_missing_values() | ||||
| @ -200,7 +201,6 @@ class TestAsset(unittest.TestCase): | ||||
| 		self.assertEqual(schedules, expected_schedules) | ||||
| 
 | ||||
| 	def test_schedule_for_prorated_straight_line_method(self): | ||||
| 		set_prorated_depreciation_schedule() | ||||
| 		pr = make_purchase_receipt(item_code="Macbook Pro", | ||||
| 			qty=1, rate=100000.0, location="Test Location") | ||||
| 
 | ||||
| @ -233,8 +233,6 @@ class TestAsset(unittest.TestCase): | ||||
| 
 | ||||
| 		self.assertEqual(schedules, expected_schedules) | ||||
| 
 | ||||
| 		remove_prorated_depreciation_schedule() | ||||
| 
 | ||||
| 	def test_depreciation(self): | ||||
| 		pr = make_purchase_receipt(item_code="Macbook Pro", | ||||
| 			qty=1, rate=100000.0, location="Test Location") | ||||
| @ -487,6 +485,8 @@ class TestAsset(unittest.TestCase): | ||||
| 		from erpnext.stock.doctype.purchase_receipt.purchase_receipt import ( | ||||
| 			make_purchase_invoice as make_purchase_invoice_from_pr) | ||||
| 
 | ||||
| 		#frappe.db.set_value("Asset Category","Computers","enable_cwip_accounting", 1) | ||||
| 
 | ||||
| 		pr = make_purchase_receipt(item_code="Macbook Pro", | ||||
| 			qty=1, rate=5000, do_not_submit=True, location="Test Location") | ||||
| 
 | ||||
| @ -565,6 +565,7 @@ class TestAsset(unittest.TestCase): | ||||
| 			where voucher_type='Asset' and voucher_no = %s | ||||
| 			order by account""", asset_doc.name) | ||||
| 
 | ||||
| 
 | ||||
| 		self.assertEqual(gle, expected_gle) | ||||
| 
 | ||||
| 	def test_expense_head(self): | ||||
| @ -575,7 +576,6 @@ class TestAsset(unittest.TestCase): | ||||
| 
 | ||||
| 		self.assertEquals('Asset Received But Not Billed - _TC', doc.items[0].expense_account) | ||||
| 
 | ||||
| 
 | ||||
| def create_asset_data(): | ||||
| 	if not frappe.db.exists("Asset Category", "Computers"): | ||||
| 		create_asset_category() | ||||
| @ -596,15 +596,15 @@ def create_asset(**args): | ||||
| 
 | ||||
| 	asset = frappe.get_doc({ | ||||
| 		"doctype": "Asset", | ||||
| 		"asset_name": "Macbook Pro 1", | ||||
| 		"asset_name": args.asset_name or "Macbook Pro 1", | ||||
| 		"asset_category": "Computers", | ||||
| 		"item_code": "Macbook Pro", | ||||
| 		"company": "_Test Company", | ||||
| 		"item_code": args.item_code or "Macbook Pro", | ||||
| 		"company": args.company or"_Test Company", | ||||
| 		"purchase_date": "2015-01-01", | ||||
| 		"calculate_depreciation": 0, | ||||
| 		"gross_purchase_amount": 100000, | ||||
| 		"expected_value_after_useful_life": 10000, | ||||
| 		"warehouse": "_Test Warehouse - _TC", | ||||
| 		"warehouse": args.warehouse or "_Test Warehouse - _TC", | ||||
| 		"available_for_use_date": "2020-06-06", | ||||
| 		"location": "Test Location", | ||||
| 		"asset_owner": "Company", | ||||
| @ -616,6 +616,9 @@ def create_asset(**args): | ||||
| 	except frappe.DuplicateEntryError: | ||||
| 		pass | ||||
| 
 | ||||
| 	if args.submit: | ||||
| 		asset.submit() | ||||
| 
 | ||||
| 	return asset | ||||
| 
 | ||||
| def create_asset_category(): | ||||
| @ -623,6 +626,7 @@ def create_asset_category(): | ||||
| 	asset_category.asset_category_name = "Computers" | ||||
| 	asset_category.total_number_of_depreciations = 3 | ||||
| 	asset_category.frequency_of_depreciation = 3 | ||||
| 	asset_category.enable_cwip_accounting = 1 | ||||
| 	asset_category.append("accounts", { | ||||
| 		"company_name": "_Test Company", | ||||
| 		"fixed_asset_account": "_Test Fixed Asset - _TC", | ||||
| @ -656,19 +660,4 @@ def set_depreciation_settings_in_company(): | ||||
| 	company.save() | ||||
| 
 | ||||
| 	# Enable booking asset depreciation entry automatically | ||||
| 	frappe.db.set_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically", 1) | ||||
| 
 | ||||
| def remove_prorated_depreciation_schedule(): | ||||
| 	asset_settings = frappe.get_doc("Asset Settings", "Asset Settings") | ||||
| 	asset_settings.schedule_based_on_fiscal_year = 0 | ||||
| 	asset_settings.save() | ||||
| 
 | ||||
| 	frappe.db.commit() | ||||
| 
 | ||||
| def set_prorated_depreciation_schedule(): | ||||
| 	asset_settings = frappe.get_doc("Asset Settings", "Asset Settings") | ||||
| 	asset_settings.schedule_based_on_fiscal_year = 1 | ||||
| 	asset_settings.number_of_days_in_fiscal_year = 360 | ||||
| 	asset_settings.save() | ||||
| 
 | ||||
| 	frappe.db.commit() | ||||
| 	frappe.db.set_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically", 1) | ||||
| @ -1,284 +1,115 @@ | ||||
| { | ||||
|  "allow_copy": 0,  | ||||
|  "allow_guest_to_view": 0,  | ||||
|  "allow_import": 1,  | ||||
|  "allow_rename": 1,  | ||||
|  "autoname": "field:asset_category_name",  | ||||
|  "beta": 0,  | ||||
|  "creation": "2016-03-01 17:41:39.778765",  | ||||
|  "custom": 0,  | ||||
|  "docstatus": 0,  | ||||
|  "doctype": "DocType",  | ||||
|  "document_type": "Document",  | ||||
|  "editable_grid": 0,  | ||||
|  "engine": "InnoDB",  | ||||
|  "allow_import": 1, | ||||
|  "allow_rename": 1, | ||||
|  "autoname": "field:asset_category_name", | ||||
|  "creation": "2016-03-01 17:41:39.778765", | ||||
|  "doctype": "DocType", | ||||
|  "document_type": "Document", | ||||
|  "engine": "InnoDB", | ||||
|  "field_order": [ | ||||
|   "asset_category_name", | ||||
|   "column_break_3", | ||||
|   "depreciation_options", | ||||
|   "enable_cwip_accounting", | ||||
|   "finance_book_detail", | ||||
|   "finance_books", | ||||
|   "section_break_2", | ||||
|   "accounts" | ||||
|  ], | ||||
|  "fields": [ | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fieldname": "asset_category_name",  | ||||
|    "fieldtype": "Data",  | ||||
|    "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": "Asset Category Name",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 0,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 1,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "unique": 0 | ||||
|   },  | ||||
|    "fieldname": "asset_category_name", | ||||
|    "fieldtype": "Data", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Asset Category Name", | ||||
|    "reqd": 1, | ||||
|    "unique": 1 | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fieldname": "column_break_3",  | ||||
|    "fieldtype": "Column Break",  | ||||
|    "hidden": 0,  | ||||
|    "ignore_user_permissions": 0,  | ||||
|    "ignore_xss_filter": 0,  | ||||
|    "in_filter": 0,  | ||||
|    "in_global_search": 0,  | ||||
|    "in_list_view": 0,  | ||||
|    "in_standard_filter": 0,  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 0,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 0,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "unique": 0 | ||||
|   },  | ||||
|    "fieldname": "column_break_3", | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fieldname": "finance_book_detail",  | ||||
|    "fieldtype": "Section Break",  | ||||
|    "hidden": 0,  | ||||
|    "ignore_user_permissions": 0,  | ||||
|    "ignore_xss_filter": 0,  | ||||
|    "in_filter": 0,  | ||||
|    "in_global_search": 0,  | ||||
|    "in_list_view": 0,  | ||||
|    "in_standard_filter": 0,  | ||||
|    "label": "Finance Book Detail",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 0,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 0,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "unique": 0 | ||||
|   },  | ||||
|    "fieldname": "finance_book_detail", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "Finance Book Detail" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fieldname": "finance_books",  | ||||
|    "fieldtype": "Table",  | ||||
|    "hidden": 0,  | ||||
|    "ignore_user_permissions": 0,  | ||||
|    "ignore_xss_filter": 0,  | ||||
|    "in_filter": 0,  | ||||
|    "in_global_search": 0,  | ||||
|    "in_list_view": 0,  | ||||
|    "in_standard_filter": 0,  | ||||
|    "label": "Finance Books",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "options": "Asset Finance Book",  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 0,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 0,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "unique": 0 | ||||
|   },  | ||||
|    "fieldname": "finance_books", | ||||
|    "fieldtype": "Table", | ||||
|    "label": "Finance Books", | ||||
|    "options": "Asset Finance Book" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fieldname": "section_break_2",  | ||||
|    "fieldtype": "Section Break",  | ||||
|    "hidden": 0,  | ||||
|    "ignore_user_permissions": 0,  | ||||
|    "ignore_xss_filter": 0,  | ||||
|    "in_filter": 0,  | ||||
|    "in_global_search": 0,  | ||||
|    "in_list_view": 0,  | ||||
|    "in_standard_filter": 0,  | ||||
|    "label": "Accounts",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 0,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 0,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "unique": 0 | ||||
|   },  | ||||
|    "fieldname": "section_break_2", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "Accounts" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fieldname": "accounts",  | ||||
|    "fieldtype": "Table",  | ||||
|    "hidden": 0,  | ||||
|    "ignore_user_permissions": 0,  | ||||
|    "ignore_xss_filter": 0,  | ||||
|    "in_filter": 0,  | ||||
|    "in_global_search": 0,  | ||||
|    "in_list_view": 0,  | ||||
|    "in_standard_filter": 0,  | ||||
|    "label": "Accounts",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "options": "Asset Category Account",  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 0,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 1,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "unique": 0 | ||||
|    "fieldname": "accounts", | ||||
|    "fieldtype": "Table", | ||||
|    "label": "Accounts", | ||||
|    "options": "Asset Category Account", | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "depreciation_options", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "Depreciation Options" | ||||
|   }, | ||||
|   { | ||||
|    "default": "0", | ||||
|    "fieldname": "enable_cwip_accounting", | ||||
|    "fieldtype": "Check", | ||||
|    "label": "Enable Capital Work in Progress Accounting" | ||||
|   } | ||||
|  ],  | ||||
|  "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": "2018-05-12 14:56:04.116425",  | ||||
|  "modified_by": "Administrator",  | ||||
|  "module": "Assets",  | ||||
|  "name": "Asset Category",  | ||||
|  "name_case": "",  | ||||
|  "owner": "Administrator",  | ||||
|  ], | ||||
|  "modified": "2019-10-11 12:19:59.759136", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Assets", | ||||
|  "name": "Asset Category", | ||||
|  "owner": "Administrator", | ||||
|  "permissions": [ | ||||
|   { | ||||
|    "amend": 0,  | ||||
|    "apply_user_permissions": 0,  | ||||
|    "cancel": 0,  | ||||
|    "create": 1,  | ||||
|    "delete": 1,  | ||||
|    "email": 1,  | ||||
|    "export": 1,  | ||||
|    "if_owner": 0,  | ||||
|    "import": 1,  | ||||
|    "permlevel": 0,  | ||||
|    "print": 1,  | ||||
|    "read": 1,  | ||||
|    "report": 1,  | ||||
|    "role": "Accounts User",  | ||||
|    "set_user_permissions": 0,  | ||||
|    "share": 1,  | ||||
|    "submit": 0,  | ||||
|    "create": 1, | ||||
|    "delete": 1, | ||||
|    "email": 1, | ||||
|    "export": 1, | ||||
|    "import": 1, | ||||
|    "print": 1, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "role": "Accounts User", | ||||
|    "share": 1, | ||||
|    "write": 1 | ||||
|   },  | ||||
|   }, | ||||
|   { | ||||
|    "amend": 0,  | ||||
|    "apply_user_permissions": 0,  | ||||
|    "cancel": 0,  | ||||
|    "create": 1,  | ||||
|    "delete": 1,  | ||||
|    "email": 1,  | ||||
|    "export": 1,  | ||||
|    "if_owner": 0,  | ||||
|    "import": 1,  | ||||
|    "permlevel": 0,  | ||||
|    "print": 1,  | ||||
|    "read": 1,  | ||||
|    "report": 1,  | ||||
|    "role": "Accounts Manager",  | ||||
|    "set_user_permissions": 0,  | ||||
|    "share": 1,  | ||||
|    "submit": 0,  | ||||
|    "create": 1, | ||||
|    "delete": 1, | ||||
|    "email": 1, | ||||
|    "export": 1, | ||||
|    "import": 1, | ||||
|    "print": 1, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "role": "Accounts Manager", | ||||
|    "share": 1, | ||||
|    "write": 1 | ||||
|   },  | ||||
|   }, | ||||
|   { | ||||
|    "amend": 0,  | ||||
|    "apply_user_permissions": 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": "Quality Manager",  | ||||
|    "set_user_permissions": 0,  | ||||
|    "share": 1,  | ||||
|    "submit": 0,  | ||||
|    "create": 1, | ||||
|    "delete": 1, | ||||
|    "email": 1, | ||||
|    "export": 1, | ||||
|    "print": 1, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "role": "Quality Manager", | ||||
|    "share": 1, | ||||
|    "write": 1 | ||||
|   } | ||||
|  ],  | ||||
|  "quick_entry": 0,  | ||||
|  "read_only": 0,  | ||||
|  "read_only_onload": 0,  | ||||
|  "show_name_in_global_search": 1,  | ||||
|  "sort_field": "modified",  | ||||
|  "sort_order": "DESC",  | ||||
|  "track_changes": 0,  | ||||
|  "track_seen": 0 | ||||
|  ], | ||||
|  "show_name_in_global_search": 1, | ||||
|  "sort_field": "modified", | ||||
|  "sort_order": "DESC" | ||||
| } | ||||
| @ -10,11 +10,24 @@ from frappe.model.document import Document | ||||
| 
 | ||||
| class AssetCategory(Document): | ||||
| 	def validate(self): | ||||
| 		self.validate_finance_books() | ||||
| 		self.validate_enable_cwip_accounting() | ||||
| 
 | ||||
| 	def validate_finance_books(self): | ||||
| 		for d in self.finance_books: | ||||
| 			for field in ("Total Number of Depreciations", "Frequency of Depreciation"): | ||||
| 				if cint(d.get(frappe.scrub(field)))<1: | ||||
| 					frappe.throw(_("Row {0}: {1} must be greater than 0").format(d.idx, field), frappe.MandatoryError) | ||||
| 
 | ||||
| 	def validate_enable_cwip_accounting(self): | ||||
| 		if self.enable_cwip_accounting : | ||||
| 			for d in self.accounts: | ||||
| 				cwip = frappe.db.get_value("Company",d.company_name,"enable_cwip_accounting") | ||||
| 				if cwip: | ||||
| 					frappe.throw(_ | ||||
| 						("CWIP is enabled globally in Company {1}. To enable it in Asset Category, first disable it in {1} ").format( | ||||
| 							frappe.bold(d.idx), frappe.bold(d.company_name))) | ||||
| 
 | ||||
| @frappe.whitelist() | ||||
| def get_asset_category_account(asset, fieldname, account=None, asset_category = None, company = None): | ||||
| 	if not asset_category and company: | ||||
|  | ||||
| @ -1,5 +0,0 @@ | ||||
| // Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
 | ||||
| // For license information, please see license.txt
 | ||||
| 
 | ||||
| frappe.ui.form.on('Asset Settings', { | ||||
| }); | ||||
| @ -1,148 +0,0 @@ | ||||
| { | ||||
|  "allow_copy": 0,  | ||||
|  "allow_events_in_timeline": 0,  | ||||
|  "allow_guest_to_view": 0,  | ||||
|  "allow_import": 0,  | ||||
|  "allow_rename": 0,  | ||||
|  "beta": 0,  | ||||
|  "creation": "2018-01-03 10:30:32.983381",  | ||||
|  "custom": 0,  | ||||
|  "docstatus": 0,  | ||||
|  "doctype": "DocType",  | ||||
|  "document_type": "",  | ||||
|  "editable_grid": 1,  | ||||
|  "engine": "InnoDB",  | ||||
|  "fields": [ | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_in_quick_entry": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fetch_if_empty": 0,  | ||||
|    "fieldname": "depreciation_options",  | ||||
|    "fieldtype": "Section Break",  | ||||
|    "hidden": 0,  | ||||
|    "ignore_user_permissions": 0,  | ||||
|    "ignore_xss_filter": 0,  | ||||
|    "in_filter": 0,  | ||||
|    "in_global_search": 0,  | ||||
|    "in_list_view": 0,  | ||||
|    "in_standard_filter": 0,  | ||||
|    "label": "Depreciation Options",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 0,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 0,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "translatable": 0,  | ||||
|    "unique": 0 | ||||
|   },  | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_in_quick_entry": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fetch_if_empty": 0,  | ||||
|    "fieldname": "disable_cwip_accounting",  | ||||
|    "fieldtype": "Check",  | ||||
|    "hidden": 0,  | ||||
|    "ignore_user_permissions": 0,  | ||||
|    "ignore_xss_filter": 0,  | ||||
|    "in_filter": 0,  | ||||
|    "in_global_search": 0,  | ||||
|    "in_list_view": 0,  | ||||
|    "in_standard_filter": 0,  | ||||
|    "label": "Disable CWIP Accounting",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 0,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 0,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "translatable": 0,  | ||||
|    "unique": 0 | ||||
|   } | ||||
|  ],  | ||||
|  "has_web_view": 0,  | ||||
|  "hide_heading": 0,  | ||||
|  "hide_toolbar": 0,  | ||||
|  "idx": 0,  | ||||
|  "image_view": 0,  | ||||
|  "in_create": 0,  | ||||
|  "is_submittable": 0,  | ||||
|  "issingle": 1,  | ||||
|  "istable": 0,  | ||||
|  "max_attachments": 0,  | ||||
|  "modified": "2019-05-26 18:31:19.930563",  | ||||
|  "modified_by": "Administrator",  | ||||
|  "module": "Assets",  | ||||
|  "name": "Asset Settings",  | ||||
|  "name_case": "",  | ||||
|  "owner": "Administrator",  | ||||
|  "permissions": [ | ||||
|   { | ||||
|    "amend": 0,  | ||||
|    "cancel": 0,  | ||||
|    "create": 1,  | ||||
|    "delete": 1,  | ||||
|    "email": 1,  | ||||
|    "export": 0,  | ||||
|    "if_owner": 0,  | ||||
|    "import": 0,  | ||||
|    "permlevel": 0,  | ||||
|    "print": 1,  | ||||
|    "read": 1,  | ||||
|    "report": 0,  | ||||
|    "role": "System Manager",  | ||||
|    "set_user_permissions": 0,  | ||||
|    "share": 1,  | ||||
|    "submit": 0,  | ||||
|    "write": 1 | ||||
|   },  | ||||
|   { | ||||
|    "amend": 0,  | ||||
|    "cancel": 0,  | ||||
|    "create": 1,  | ||||
|    "delete": 1,  | ||||
|    "email": 1,  | ||||
|    "export": 0,  | ||||
|    "if_owner": 0,  | ||||
|    "import": 0,  | ||||
|    "permlevel": 0,  | ||||
|    "print": 1,  | ||||
|    "read": 1,  | ||||
|    "report": 0,  | ||||
|    "role": "Accounts Manager",  | ||||
|    "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": "DESC",  | ||||
|  "track_changes": 1,  | ||||
|  "track_seen": 0,  | ||||
|  "track_views": 0 | ||||
| } | ||||
| @ -1,9 +0,0 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors | ||||
| # For license information, please see license.txt | ||||
| 
 | ||||
| from __future__ import unicode_literals | ||||
| from frappe.model.document import Document | ||||
| 
 | ||||
| class AssetSettings(Document): | ||||
| 	pass | ||||
| @ -1,23 +0,0 @@ | ||||
| /* eslint-disable */ | ||||
| // rename this file from _test_[name] to test_[name] to activate
 | ||||
| // and remove above this line
 | ||||
| 
 | ||||
| QUnit.test("test: Asset Settings", function (assert) { | ||||
| 	let done = assert.async(); | ||||
| 
 | ||||
| 	// number of asserts
 | ||||
| 	assert.expect(1); | ||||
| 
 | ||||
| 	frappe.run_serially([ | ||||
| 		// insert a new Asset Settings
 | ||||
| 		() => frappe.tests.make('Asset Settings', [ | ||||
| 			// values to be set
 | ||||
| 			{key: 'value'} | ||||
| 		]), | ||||
| 		() => { | ||||
| 			assert.equal(cur_frm.doc.key, 'value'); | ||||
| 		}, | ||||
| 		() => done() | ||||
| 	]); | ||||
| 
 | ||||
| }); | ||||
| @ -1,9 +0,0 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| # Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors | ||||
| # See license.txt | ||||
| from __future__ import unicode_literals | ||||
| 
 | ||||
| import unittest | ||||
| 
 | ||||
| class TestAssetSettings(unittest.TestCase): | ||||
| 	pass | ||||
| @ -21,10 +21,6 @@ def get_data(): | ||||
| 					"name": "Asset Category", | ||||
| 					"onboard": 1, | ||||
| 				}, | ||||
| 				{ | ||||
| 					"type": "doctype", | ||||
| 					"name": "Asset Settings", | ||||
| 				}, | ||||
| 				{ | ||||
| 					"type": "doctype", | ||||
| 					"name": "Asset Movement", | ||||
|  | ||||
| @ -1193,8 +1193,9 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil | ||||
| 			frappe.throw(_("Cannot set quantity less than received quantity")) | ||||
| 
 | ||||
| 		child_item.qty = flt(d.get("qty")) | ||||
| 		precision = child_item.precision("rate") or 2 | ||||
| 
 | ||||
| 		if flt(child_item.billed_amt) > (flt(d.get("rate")) * flt(d.get("qty"))): | ||||
| 		if flt(child_item.billed_amt, precision) > flt(flt(d.get("rate")) * flt(d.get("qty")), precision): | ||||
| 			frappe.throw(_("Row #{0}: Cannot set Rate if amount is greater than billed amount for Item {1}.") | ||||
| 						 .format(child_item.idx, child_item.item_code)) | ||||
| 		else: | ||||
|  | ||||
| @ -49,7 +49,8 @@ status_map = { | ||||
| 		["Submitted", "eval:self.docstatus==1"], | ||||
| 		["Paid", "eval:self.outstanding_amount==0 and self.docstatus==1"], | ||||
| 		["Return", "eval:self.is_return==1 and self.docstatus==1"], | ||||
| 		["Debit Note Issued", "eval:self.outstanding_amount < 0 and self.docstatus==1"], | ||||
| 		["Debit Note Issued", | ||||
| 		 "eval:self.outstanding_amount <= 0 and self.docstatus==1 and self.is_return==0 and get_value('Purchase Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1})"], | ||||
| 		["Unpaid", "eval:self.outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.docstatus==1"], | ||||
| 		["Overdue", "eval:self.outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.docstatus==1"], | ||||
| 		["Cancelled", "eval:self.docstatus==2"], | ||||
| @ -118,7 +119,6 @@ class StatusUpdater(Document): | ||||
| 
 | ||||
| 		if self.doctype in status_map: | ||||
| 			_status = self.status | ||||
| 
 | ||||
| 			if status and update: | ||||
| 				self.db_set("status", status) | ||||
| 
 | ||||
|  | ||||
| @ -52,7 +52,8 @@ | ||||
|    "fieldtype": "Select", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Email Campaign For ", | ||||
|    "options": "\nLead\nContact" | ||||
|    "options": "\nLead\nContact", | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "recipient", | ||||
| @ -69,7 +70,7 @@ | ||||
|    "options": "User" | ||||
|   } | ||||
|  ], | ||||
|  "modified": "2019-07-12 13:47:37.261213", | ||||
|  "modified": "2019-11-11 17:18:47.342839", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "CRM", | ||||
|  "name": "Email Campaign", | ||||
|  | ||||
| @ -73,13 +73,13 @@ def send_mail(entry, email_campaign): | ||||
| 
 | ||||
| 	email_template = frappe.get_doc("Email Template", entry.get("email_template")) | ||||
| 	sender = frappe.db.get_value("User", email_campaign.get("sender"), 'email') | ||||
| 
 | ||||
| 	context = {"doc": frappe.get_doc(email_campaign.email_campaign_for, email_campaign.recipient)} | ||||
| 	# send mail and link communication to document | ||||
| 	comm = make( | ||||
| 		doctype = "Email Campaign", | ||||
| 		name = email_campaign.name, | ||||
| 		subject = email_template.get("subject"), | ||||
| 		content = email_template.get("response"), | ||||
| 		content = frappe.render_template(email_template.get("response"), context), | ||||
| 		sender = sender, | ||||
| 		recipients = recipient, | ||||
| 		communication_medium = "Email", | ||||
|  | ||||
| @ -11,6 +11,7 @@ | ||||
|   "validate_batch", | ||||
|   "validate_course", | ||||
|   "academic_term_reqd", | ||||
|   "user_creation_skip", | ||||
|   "section_break_7", | ||||
|   "instructor_created_by", | ||||
|   "web_academy_settings_section", | ||||
| @ -91,6 +92,13 @@ | ||||
|    "fieldname": "enable_lms", | ||||
|    "fieldtype": "Check", | ||||
|    "label": "Enable LMS" | ||||
|   }, | ||||
|   { | ||||
|    "default": "0", | ||||
|    "description": "By default, a new User is created for every new Student. If enabled, no new User will be created when a new Student is created.", | ||||
|    "fieldname": "user_creation_skip", | ||||
|    "fieldtype": "Check", | ||||
|    "label": "Skip User creation for new Student" | ||||
|   } | ||||
|  ], | ||||
|  "issingle": 1, | ||||
| @ -133,4 +141,4 @@ | ||||
|  "sort_field": "modified", | ||||
|  "sort_order": "DESC", | ||||
|  "track_changes": 1 | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -40,7 +40,8 @@ class Student(Document): | ||||
| 			frappe.throw(_("Student {0} exist against student applicant {1}").format(student[0][0], self.student_applicant)) | ||||
| 
 | ||||
| 	def after_insert(self): | ||||
| 		self.create_student_user() | ||||
| 		if not frappe.get_single('Education Settings').user_creation_skip: | ||||
| 			self.create_student_user() | ||||
| 
 | ||||
| 	def create_student_user(self): | ||||
| 		"""Create a website user for student creation if not already exists""" | ||||
|  | ||||
| @ -1,10 +1,8 @@ | ||||
| 
 | ||||
| from __future__ import unicode_literals | ||||
| import frappe, base64, hashlib, hmac, json | ||||
| import datetime | ||||
| from frappe import _ | ||||
| 
 | ||||
| 
 | ||||
| def verify_request(): | ||||
| 	woocommerce_settings = frappe.get_doc("Woocommerce Settings") | ||||
| 	sig = base64.b64encode( | ||||
| @ -30,191 +28,149 @@ def order(*args, **kwargs): | ||||
| 		frappe.log_error(error_message, "WooCommerce Error") | ||||
| 		raise | ||||
| 
 | ||||
| 
 | ||||
| def _order(*args, **kwargs): | ||||
| 	woocommerce_settings = frappe.get_doc("Woocommerce Settings") | ||||
| 	if frappe.flags.woocomm_test_order_data: | ||||
| 		fd = frappe.flags.woocomm_test_order_data | ||||
| 		order = frappe.flags.woocomm_test_order_data | ||||
| 		event = "created" | ||||
| 
 | ||||
| 	elif frappe.request and frappe.request.data: | ||||
| 		verify_request() | ||||
| 		fd = json.loads(frappe.request.data) | ||||
| 		try: | ||||
| 			order = json.loads(frappe.request.data) | ||||
| 		except ValueError: | ||||
| 			#woocommerce returns 'webhook_id=value' for the first request which is not JSON | ||||
| 			order = frappe.request.data | ||||
| 		event = frappe.get_request_header("X-Wc-Webhook-Event") | ||||
| 
 | ||||
| 	else: | ||||
| 		return "success" | ||||
| 
 | ||||
| 	if event == "created": | ||||
| 		raw_billing_data = fd.get("billing") | ||||
| 		customer_woo_com_email = raw_billing_data.get("email") | ||||
| 
 | ||||
| 		if frappe.get_value("Customer",{"woocommerce_email": customer_woo_com_email}): | ||||
| 			# Edit | ||||
| 			link_customer_and_address(raw_billing_data,1) | ||||
| 		else: | ||||
| 			# Create | ||||
| 			link_customer_and_address(raw_billing_data,0) | ||||
| 
 | ||||
| 
 | ||||
| 		items_list = fd.get("line_items") | ||||
| 		for item in items_list: | ||||
| 
 | ||||
| 			item_woo_com_id = item.get("product_id") | ||||
| 
 | ||||
| 			if frappe.get_value("Item",{"woocommerce_id": item_woo_com_id}): | ||||
| 				#Edit | ||||
| 				link_item(item,1) | ||||
| 			else: | ||||
| 				link_item(item,0) | ||||
| 
 | ||||
| 
 | ||||
| 		raw_billing_data = order.get("billing") | ||||
| 		customer_name = raw_billing_data.get("first_name") + " " + raw_billing_data.get("last_name") | ||||
| 		link_customer_and_address(raw_billing_data, customer_name) | ||||
| 		link_items(order.get("line_items"), woocommerce_settings) | ||||
| 		create_sales_order(order, woocommerce_settings, customer_name) | ||||
| 
 | ||||
| 		new_sales_order = frappe.new_doc("Sales Order") | ||||
| 		new_sales_order.customer = customer_name | ||||
| 
 | ||||
| 		created_date = fd.get("date_created").split("T") | ||||
| 		new_sales_order.transaction_date = created_date[0] | ||||
| 
 | ||||
| 		new_sales_order.po_no = fd.get("id") | ||||
| 		new_sales_order.woocommerce_id = fd.get("id") | ||||
| 		new_sales_order.naming_series = woocommerce_settings.sales_order_series or "SO-WOO-" | ||||
| 
 | ||||
| 		placed_order_date = created_date[0] | ||||
| 		raw_date = datetime.datetime.strptime(placed_order_date, "%Y-%m-%d") | ||||
| 		raw_delivery_date = frappe.utils.add_to_date(raw_date,days = 7) | ||||
| 		order_delivery_date_str = raw_delivery_date.strftime('%Y-%m-%d') | ||||
| 		order_delivery_date = str(order_delivery_date_str) | ||||
| 
 | ||||
| 		new_sales_order.delivery_date = order_delivery_date | ||||
| 		default_set_company = frappe.get_doc("Global Defaults") | ||||
| 		company = raw_billing_data.get("company") or default_set_company.default_company | ||||
| 		found_company = frappe.get_doc("Company",{"name":company}) | ||||
| 		company_abbr = found_company.abbr | ||||
| 
 | ||||
| 		new_sales_order.company = company | ||||
| 
 | ||||
| 		for item in items_list: | ||||
| 			woocomm_item_id = item.get("product_id") | ||||
| 			found_item = frappe.get_doc("Item",{"woocommerce_id": woocomm_item_id}) | ||||
| 
 | ||||
| 			ordered_items_tax = item.get("total_tax") | ||||
| 
 | ||||
| 			new_sales_order.append("items",{ | ||||
| 				"item_code": found_item.item_code, | ||||
| 				"item_name": found_item.item_name, | ||||
| 				"description": found_item.item_name, | ||||
| 				"delivery_date":order_delivery_date, | ||||
| 				"uom": woocommerce_settings.uom or _("Nos"), | ||||
| 				"qty": item.get("quantity"), | ||||
| 				"rate": item.get("price"), | ||||
| 				"warehouse": woocommerce_settings.warehouse or "Stores" + " - " + company_abbr | ||||
| 				}) | ||||
| 
 | ||||
| 			add_tax_details(new_sales_order,ordered_items_tax,"Ordered Item tax",0) | ||||
| 
 | ||||
| 		# shipping_details = fd.get("shipping_lines") # used for detailed order | ||||
| 		shipping_total = fd.get("shipping_total") | ||||
| 		shipping_tax = fd.get("shipping_tax") | ||||
| 
 | ||||
| 		add_tax_details(new_sales_order,shipping_tax,"Shipping Tax",1) | ||||
| 		add_tax_details(new_sales_order,shipping_total,"Shipping Total",1) | ||||
| 
 | ||||
| 		new_sales_order.submit() | ||||
| 
 | ||||
| 		frappe.db.commit() | ||||
| 
 | ||||
| def link_customer_and_address(raw_billing_data,customer_status): | ||||
| 
 | ||||
| 	if customer_status == 0: | ||||
| 		# create | ||||
| def link_customer_and_address(raw_billing_data, customer_name): | ||||
| 	customer_woo_com_email = raw_billing_data.get("email") | ||||
| 	customer_exists = frappe.get_value("Customer", {"woocommerce_email": customer_woo_com_email}) | ||||
| 	if not customer_exists: | ||||
| 		# Create Customer | ||||
| 		customer = frappe.new_doc("Customer") | ||||
| 		address = frappe.new_doc("Address") | ||||
| 
 | ||||
| 	if customer_status == 1: | ||||
| 		# Edit | ||||
| 		customer_woo_com_email = raw_billing_data.get("email") | ||||
| 		customer = frappe.get_doc("Customer",{"woocommerce_email": customer_woo_com_email}) | ||||
| 	else: | ||||
| 		# Edit Customer | ||||
| 		customer = frappe.get_doc("Customer", {"woocommerce_email": customer_woo_com_email}) | ||||
| 		old_name = customer.customer_name | ||||
| 
 | ||||
| 	full_name = str(raw_billing_data.get("first_name"))+ " "+str(raw_billing_data.get("last_name")) | ||||
| 	customer.customer_name = full_name | ||||
| 	customer.woocommerce_email = str(raw_billing_data.get("email")) | ||||
| 	customer.save() | ||||
| 	frappe.db.commit() | ||||
| 	customer.customer_name = customer_name | ||||
| 	customer.woocommerce_email = customer_woo_com_email | ||||
| 	customer.flags.ignore_mandatory = True | ||||
| 	customer.save()  | ||||
| 
 | ||||
| 	if customer_status == 1: | ||||
| 		frappe.rename_doc("Customer", old_name, full_name) | ||||
| 		address = frappe.get_doc("Address",{"woocommerce_email":customer_woo_com_email}) | ||||
| 		customer = frappe.get_doc("Customer",{"woocommerce_email": customer_woo_com_email}) | ||||
| 	if customer_exists: | ||||
| 		frappe.rename_doc("Customer", old_name, customer_name) | ||||
| 		address = frappe.get_doc("Address", {"woocommerce_email": customer_woo_com_email}) | ||||
| 	else: | ||||
| 		address = frappe.new_doc("Address") | ||||
| 
 | ||||
| 	address.address_line1 = raw_billing_data.get("address_1", "Not Provided") | ||||
| 	address.address_line2 = raw_billing_data.get("address_2", "Not Provided") | ||||
| 	address.city = raw_billing_data.get("city", "Not Provided") | ||||
| 	address.woocommerce_email = str(raw_billing_data.get("email")) | ||||
| 	address.address_type = "Shipping" | ||||
| 	address.country = frappe.get_value("Country", filters={"code":raw_billing_data.get("country", "IN").lower()}) | ||||
| 	address.state =  raw_billing_data.get("state") | ||||
| 	address.pincode =  str(raw_billing_data.get("postcode")) | ||||
| 	address.phone = str(raw_billing_data.get("phone")) | ||||
| 	address.email_id = str(raw_billing_data.get("email")) | ||||
| 
 | ||||
| 	address.woocommerce_email = customer_woo_com_email | ||||
| 	address.address_type = "Billing" | ||||
| 	address.country = frappe.get_value("Country", {"code": raw_billing_data.get("country", "IN").lower()}) | ||||
| 	address.state = raw_billing_data.get("state") | ||||
| 	address.pincode = raw_billing_data.get("postcode") | ||||
| 	address.phone = raw_billing_data.get("phone") | ||||
| 	address.email_id = customer_woo_com_email | ||||
| 	address.append("links", { | ||||
| 		"link_doctype": "Customer", | ||||
| 		"link_name": customer.customer_name | ||||
| 	}) | ||||
| 	address.flags.ignore_mandatory = True | ||||
| 	address = address.save() | ||||
| 
 | ||||
| 	address.save() | ||||
| 	frappe.db.commit() | ||||
| 
 | ||||
| 	if customer_status == 1: | ||||
| 
 | ||||
| 		address = frappe.get_doc("Address",{"woocommerce_email":customer_woo_com_email}) | ||||
| 	if customer_exists: | ||||
| 		old_address_title = address.name | ||||
| 		new_address_title = customer.customer_name+"-billing" | ||||
| 		new_address_title = customer.customer_name + "-billing" | ||||
| 		address.address_title = customer.customer_name | ||||
| 		address.save() | ||||
| 
 | ||||
| 		frappe.rename_doc("Address",old_address_title,new_address_title) | ||||
| 		frappe.rename_doc("Address", old_address_title, new_address_title) | ||||
| 
 | ||||
| 	frappe.db.commit() | ||||
| 
 | ||||
| def link_item(item_data,item_status): | ||||
| 	woocommerce_settings = frappe.get_doc("Woocommerce Settings") | ||||
| 
 | ||||
| 	if item_status == 0: | ||||
| 		#Create Item | ||||
| 		item = frappe.new_doc("Item") | ||||
| 
 | ||||
| 	if item_status == 1: | ||||
| 		#Edit Item | ||||
| def link_items(items_list, woocommerce_settings): | ||||
| 	for item_data in items_list: | ||||
| 		item_woo_com_id = item_data.get("product_id") | ||||
| 		item = frappe.get_doc("Item",{"woocommerce_id": item_woo_com_id}) | ||||
| 
 | ||||
| 	item.item_name = str(item_data.get("name")) | ||||
| 	item.item_code = "woocommerce - " + str(item_data.get("product_id")) | ||||
| 	item.woocommerce_id = str(item_data.get("product_id")) | ||||
| 	item.item_group = _("WooCommerce Products") | ||||
| 	item.stock_uom = woocommerce_settings.uom or _("Nos") | ||||
| 	item.save() | ||||
| 		if frappe.get_value("Item", {"woocommerce_id": item_woo_com_id}): | ||||
| 			#Edit Item | ||||
| 			item = frappe.get_doc("Item", {"woocommerce_id": item_woo_com_id}) | ||||
| 		else: | ||||
| 			#Create Item | ||||
| 			item = frappe.new_doc("Item") | ||||
| 	 | ||||
| 		item.item_name = item_data.get("name") | ||||
| 		item.item_code = _("woocommerce - {0}").format(item_data.get("product_id")) | ||||
| 		item.woocommerce_id = item_data.get("product_id") | ||||
| 		item.item_group = _("WooCommerce Products") | ||||
| 		item.stock_uom = woocommerce_settings.uom or _("Nos") | ||||
| 		item.flags.ignore_mandatory = True | ||||
| 		item.save() | ||||
| 
 | ||||
| def create_sales_order(order, woocommerce_settings, customer_name):	 | ||||
| 	new_sales_order = frappe.new_doc("Sales Order") | ||||
| 	new_sales_order.customer = customer_name | ||||
| 
 | ||||
| 	new_sales_order.po_no = new_sales_order.woocommerce_id = order.get("id") | ||||
| 	new_sales_order.naming_series = woocommerce_settings.sales_order_series or "SO-WOO-" | ||||
| 
 | ||||
| 	created_date = order.get("date_created").split("T") | ||||
| 	new_sales_order.transaction_date = created_date[0] | ||||
| 	delivery_after = woocommerce_settings.delivery_after_days or 7 | ||||
| 	new_sales_order.delivery_date = frappe.utils.add_days(created_date[0], delivery_after) | ||||
| 
 | ||||
| 	new_sales_order.company = woocommerce_settings.company | ||||
| 
 | ||||
| 	set_items_in_sales_order(new_sales_order, woocommerce_settings, order) | ||||
| 	new_sales_order.flags.ignore_mandatory = True | ||||
| 	new_sales_order.insert() | ||||
| 	new_sales_order.submit() | ||||
| 
 | ||||
| 	frappe.db.commit() | ||||
| 
 | ||||
| def add_tax_details(sales_order,price,desc,status): | ||||
| def set_items_in_sales_order(new_sales_order, woocommerce_settings, order): | ||||
| 	company_abbr = frappe.db.get_value('Company', woocommerce_settings.company, 'abbr') | ||||
| 
 | ||||
| 	woocommerce_settings = frappe.get_doc("Woocommerce Settings") | ||||
| 	for item in order.get("line_items"): | ||||
| 		woocomm_item_id = item.get("product_id") | ||||
| 		found_item = frappe.get_doc("Item", {"woocommerce_id": woocomm_item_id}) | ||||
| 
 | ||||
| 	if status == 0: | ||||
| 		# Product taxes | ||||
| 		account_head_type = woocommerce_settings.tax_account | ||||
| 		ordered_items_tax = item.get("total_tax") | ||||
| 
 | ||||
| 	if status == 1: | ||||
| 		# Shipping taxes | ||||
| 		account_head_type = woocommerce_settings.f_n_f_account | ||||
| 		new_sales_order.append("items",{ | ||||
| 			"item_code": found_item.item_code, | ||||
| 			"item_name": found_item.item_name, | ||||
| 			"description": found_item.item_name, | ||||
| 			"delivery_date": new_sales_order.delivery_date, | ||||
| 			"uom": woocommerce_settings.uom or _("Nos"), | ||||
| 			"qty": item.get("quantity"), | ||||
| 			"rate": item.get("price"), | ||||
| 			"warehouse": woocommerce_settings.warehouse or _("Stores - {0}").format(company_abbr) | ||||
| 			}) | ||||
| 
 | ||||
| 	sales_order.append("taxes",{ | ||||
| 							"charge_type":"Actual", | ||||
| 							"account_head": account_head_type, | ||||
| 							"tax_amount": price, | ||||
| 							"description": desc | ||||
| 							}) | ||||
| 		add_tax_details(new_sales_order, ordered_items_tax, "Ordered Item tax", woocommerce_settings.tax_account) | ||||
| 
 | ||||
| 	# shipping_details = order.get("shipping_lines") # used for detailed order | ||||
| 
 | ||||
| 	add_tax_details(new_sales_order, order.get("shipping_tax"), "Shipping Tax", woocommerce_settings.f_n_f_account) | ||||
| 	add_tax_details(new_sales_order, order.get("shipping_total"), "Shipping Total", woocommerce_settings.f_n_f_account) | ||||
| 			 | ||||
| def add_tax_details(sales_order, price, desc, tax_account_head): | ||||
| 	sales_order.append("taxes", { | ||||
| 		"charge_type":"Actual", | ||||
| 		"account_head": tax_account_head, | ||||
| 		"tax_amount": price, | ||||
| 		"description": desc | ||||
| 	}) | ||||
|  | ||||
| @ -50,7 +50,7 @@ class ShopifySettings(Document): | ||||
| 		deleted_webhooks = [] | ||||
| 
 | ||||
| 		for d in self.webhooks: | ||||
| 			url = get_shopify_url('admin/api/2019-04/webhooks.json'.format(d.webhook_id), self) | ||||
| 			url = get_shopify_url('admin/api/2019-04/webhooks/{0}.json'.format(d.webhook_id), self) | ||||
| 			try: | ||||
| 				res = session.delete(url, headers=get_header(self)) | ||||
| 				res.raise_for_status() | ||||
|  | ||||
| @ -1,694 +1,175 @@ | ||||
| { | ||||
|  "allow_copy": 0, | ||||
|  "allow_events_in_timeline": 0, | ||||
|  "allow_guest_to_view": 0, | ||||
|  "allow_import": 0, | ||||
|  "allow_rename": 0, | ||||
|  "beta": 0, | ||||
|  "creation": "2018-02-12 15:10:05.495713", | ||||
|  "custom": 0, | ||||
|  "docstatus": 0, | ||||
|  "doctype": "DocType", | ||||
|  "document_type": "", | ||||
|  "editable_grid": 1, | ||||
|  "engine": "InnoDB", | ||||
|  "field_order": [ | ||||
|   "enable_sync", | ||||
|   "sb_00", | ||||
|   "woocommerce_server_url", | ||||
|   "secret", | ||||
|   "cb_00", | ||||
|   "api_consumer_key", | ||||
|   "api_consumer_secret", | ||||
|   "sb_accounting_details", | ||||
|   "tax_account", | ||||
|   "column_break_10", | ||||
|   "f_n_f_account", | ||||
|   "defaults_section", | ||||
|   "creation_user", | ||||
|   "warehouse", | ||||
|   "sales_order_series", | ||||
|   "column_break_14", | ||||
|   "company", | ||||
|   "delivery_after_days", | ||||
|   "uom", | ||||
|   "endpoints", | ||||
|   "endpoint" | ||||
|  ], | ||||
|  "fields": [ | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "fetch_if_empty": 0, | ||||
|    "default": "0", | ||||
|    "fieldname": "enable_sync", | ||||
|    "fieldtype": "Check", | ||||
|    "hidden": 0, | ||||
|    "ignore_user_permissions": 0, | ||||
|    "ignore_xss_filter": 0, | ||||
|    "in_filter": 0, | ||||
|    "in_global_search": 0, | ||||
|    "in_list_view": 0, | ||||
|    "in_standard_filter": 0, | ||||
|    "label": "Enable Sync", | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 0, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 0, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "label": "Enable Sync" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "fetch_if_empty": 0, | ||||
|    "fieldname": "sb_00", | ||||
|    "fieldtype": "Section Break", | ||||
|    "hidden": 0, | ||||
|    "ignore_user_permissions": 0, | ||||
|    "ignore_xss_filter": 0, | ||||
|    "in_filter": 0, | ||||
|    "in_global_search": 0, | ||||
|    "in_list_view": 0, | ||||
|    "in_standard_filter": 0, | ||||
|    "label": "", | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 0, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 0, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "fieldtype": "Section Break" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "fetch_if_empty": 0, | ||||
|    "fieldname": "woocommerce_server_url", | ||||
|    "fieldtype": "Data", | ||||
|    "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": "Woocommerce Server URL", | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 0, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 0, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "label": "Woocommerce Server URL" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "fetch_if_empty": 0, | ||||
|    "fieldname": "secret", | ||||
|    "fieldtype": "Code", | ||||
|    "hidden": 0, | ||||
|    "ignore_user_permissions": 0, | ||||
|    "ignore_xss_filter": 0, | ||||
|    "in_filter": 0, | ||||
|    "in_global_search": 0, | ||||
|    "in_list_view": 0, | ||||
|    "in_standard_filter": 0, | ||||
|    "label": "Secret", | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 1, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 0, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "fetch_if_empty": 0, | ||||
|    "fieldname": "cb_00", | ||||
|    "fieldtype": "Column Break", | ||||
|    "hidden": 0, | ||||
|    "ignore_user_permissions": 0, | ||||
|    "ignore_xss_filter": 0, | ||||
|    "in_filter": 0, | ||||
|    "in_global_search": 0, | ||||
|    "in_list_view": 0, | ||||
|    "in_standard_filter": 0, | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 0, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 0, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "fetch_if_empty": 0, | ||||
|    "fieldname": "api_consumer_key", | ||||
|    "fieldtype": "Data", | ||||
|    "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": "API consumer key", | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 0, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 0, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "label": "API consumer key" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "fetch_if_empty": 0, | ||||
|    "fieldname": "api_consumer_secret", | ||||
|    "fieldtype": "Data", | ||||
|    "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": "API consumer secret", | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 0, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 0, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "label": "API consumer secret" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "fetch_if_empty": 0, | ||||
|    "fieldname": "sb_accounting_details", | ||||
|    "fieldtype": "Section Break", | ||||
|    "hidden": 0, | ||||
|    "ignore_user_permissions": 0, | ||||
|    "ignore_xss_filter": 0, | ||||
|    "in_filter": 0, | ||||
|    "in_global_search": 0, | ||||
|    "in_list_view": 0, | ||||
|    "in_standard_filter": 0, | ||||
|    "label": "Accounting Details", | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 0, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 0, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "label": "Accounting Details" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "fetch_if_empty": 0, | ||||
|    "fieldname": "tax_account", | ||||
|    "fieldtype": "Link", | ||||
|    "hidden": 0, | ||||
|    "ignore_user_permissions": 0, | ||||
|    "ignore_xss_filter": 0, | ||||
|    "in_filter": 0, | ||||
|    "in_global_search": 0, | ||||
|    "in_list_view": 0, | ||||
|    "in_standard_filter": 0, | ||||
|    "label": "Tax Account", | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "options": "Account", | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 0, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 1, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "fetch_if_empty": 0, | ||||
|    "fieldname": "column_break_10", | ||||
|    "fieldtype": "Column Break", | ||||
|    "hidden": 0, | ||||
|    "ignore_user_permissions": 0, | ||||
|    "ignore_xss_filter": 0, | ||||
|    "in_filter": 0, | ||||
|    "in_global_search": 0, | ||||
|    "in_list_view": 0, | ||||
|    "in_standard_filter": 0, | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 0, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 0, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "fetch_if_empty": 0, | ||||
|    "fieldname": "f_n_f_account", | ||||
|    "fieldtype": "Link", | ||||
|    "hidden": 0, | ||||
|    "ignore_user_permissions": 0, | ||||
|    "ignore_xss_filter": 0, | ||||
|    "in_filter": 0, | ||||
|    "in_global_search": 0, | ||||
|    "in_list_view": 0, | ||||
|    "in_standard_filter": 0, | ||||
|    "label": "Freight and Forwarding Account", | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "options": "Account", | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 0, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 1, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "fetch_if_empty": 0, | ||||
|    "fieldname": "defaults_section", | ||||
|    "fieldtype": "Section Break", | ||||
|    "hidden": 0, | ||||
|    "ignore_user_permissions": 0, | ||||
|    "ignore_xss_filter": 0, | ||||
|    "in_filter": 0, | ||||
|    "in_global_search": 0, | ||||
|    "in_list_view": 0, | ||||
|    "in_standard_filter": 0, | ||||
|    "label": "Defaults", | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 0, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 0, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "label": "Defaults" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "description": "The user that will be used to create Customers, Items and Sales Orders. This user should have the relevant permissions.", | ||||
|    "fetch_if_empty": 0, | ||||
|    "fieldname": "creation_user", | ||||
|    "fieldtype": "Link", | ||||
|    "hidden": 0, | ||||
|    "ignore_user_permissions": 0, | ||||
|    "ignore_xss_filter": 0, | ||||
|    "in_filter": 0, | ||||
|    "in_global_search": 0, | ||||
|    "in_list_view": 0, | ||||
|    "in_standard_filter": 0, | ||||
|    "label": "Creation User", | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "options": "User", | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 0, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 1, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "description": "This warehouse will be used to create Sale Orders. The fallback warehouse is \"Stores\".", | ||||
|    "fetch_if_empty": 0, | ||||
|    "description": "This warehouse will be used to create Sales Orders. The fallback warehouse is \"Stores\".", | ||||
|    "fieldname": "warehouse", | ||||
|    "fieldtype": "Link", | ||||
|    "hidden": 0, | ||||
|    "ignore_user_permissions": 0, | ||||
|    "ignore_xss_filter": 0, | ||||
|    "in_filter": 0, | ||||
|    "in_global_search": 0, | ||||
|    "in_list_view": 0, | ||||
|    "in_standard_filter": 0, | ||||
|    "label": "Warehouse", | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "options": "Warehouse", | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 0, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 0, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "options": "Warehouse" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "fetch_if_empty": 0, | ||||
|    "fieldname": "column_break_14", | ||||
|    "fieldtype": "Column Break", | ||||
|    "hidden": 0, | ||||
|    "ignore_user_permissions": 0, | ||||
|    "ignore_xss_filter": 0, | ||||
|    "in_filter": 0, | ||||
|    "in_global_search": 0, | ||||
|    "in_list_view": 0, | ||||
|    "in_standard_filter": 0, | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 0, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 0, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "description": "The fallback series is \"SO-WOO-\".", | ||||
|    "fetch_if_empty": 0, | ||||
|    "fieldname": "sales_order_series", | ||||
|    "fieldtype": "Select", | ||||
|    "hidden": 0, | ||||
|    "ignore_user_permissions": 0, | ||||
|    "ignore_xss_filter": 0, | ||||
|    "in_filter": 0, | ||||
|    "in_global_search": 0, | ||||
|    "in_list_view": 0, | ||||
|    "in_standard_filter": 0, | ||||
|    "label": "Sales Order Series", | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 0, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 0, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "label": "Sales Order Series" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "description": "This is the default UOM used for items and Sales orders. The fallback UOM is \"Nos\".", | ||||
|    "fetch_if_empty": 0, | ||||
|    "fieldname": "uom", | ||||
|    "fieldtype": "Link", | ||||
|    "hidden": 0, | ||||
|    "ignore_user_permissions": 0, | ||||
|    "ignore_xss_filter": 0, | ||||
|    "in_filter": 0, | ||||
|    "in_global_search": 0, | ||||
|    "in_list_view": 0, | ||||
|    "in_standard_filter": 0, | ||||
|    "label": "UOM", | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "options": "UOM", | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 0, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 0, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "options": "UOM" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "fetch_if_empty": 0, | ||||
|    "fieldname": "endpoints", | ||||
|    "fieldtype": "Section Break", | ||||
|    "hidden": 0, | ||||
|    "ignore_user_permissions": 0, | ||||
|    "ignore_xss_filter": 0, | ||||
|    "in_filter": 0, | ||||
|    "in_global_search": 0, | ||||
|    "in_list_view": 0, | ||||
|    "in_standard_filter": 0, | ||||
|    "label": "Endpoints", | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 0, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 0, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "label": "Endpoints" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0, | ||||
|    "allow_in_quick_entry": 0, | ||||
|    "allow_on_submit": 0, | ||||
|    "bold": 0, | ||||
|    "collapsible": 0, | ||||
|    "columns": 0, | ||||
|    "fetch_if_empty": 0, | ||||
|    "fieldname": "endpoint", | ||||
|    "fieldtype": "Code", | ||||
|    "hidden": 0, | ||||
|    "ignore_user_permissions": 0, | ||||
|    "ignore_xss_filter": 0, | ||||
|    "in_filter": 0, | ||||
|    "in_global_search": 0, | ||||
|    "in_list_view": 0, | ||||
|    "in_standard_filter": 0, | ||||
|    "label": "Endpoint", | ||||
|    "length": 0, | ||||
|    "no_copy": 0, | ||||
|    "permlevel": 0, | ||||
|    "precision": "", | ||||
|    "print_hide": 0, | ||||
|    "print_hide_if_no_value": 0, | ||||
|    "read_only": 1, | ||||
|    "remember_last_selected_value": 0, | ||||
|    "report_hide": 0, | ||||
|    "reqd": 0, | ||||
|    "search_index": 0, | ||||
|    "set_only_once": 0, | ||||
|    "translatable": 0, | ||||
|    "unique": 0 | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "description": "This company will be used to create Sales Orders.", | ||||
|    "fieldname": "company", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Company", | ||||
|    "options": "Company", | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "description": "This is the default offset (days) for the Delivery Date in Sales Orders. The fallback offset is 7 days from the order placement date.", | ||||
|    "fieldname": "delivery_after_days", | ||||
|    "fieldtype": "Int", | ||||
|    "label": "Delivery After (Days)" | ||||
|   } | ||||
|  ], | ||||
|  "has_web_view": 0, | ||||
|  "hide_toolbar": 0, | ||||
|  "idx": 0, | ||||
|  "in_create": 0, | ||||
|  "is_submittable": 0, | ||||
|  "issingle": 1, | ||||
|  "istable": 0, | ||||
|  "max_attachments": 0, | ||||
|  "menu_index": 0, | ||||
|  "modified": "2019-04-08 17:04:16.720696", | ||||
|  "modified": "2019-11-04 00:45:21.232096", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "ERPNext Integrations", | ||||
|  "name": "Woocommerce Settings", | ||||
|  "name_case": "", | ||||
|  "owner": "Administrator", | ||||
|  "permissions": [ | ||||
|   { | ||||
|    "amend": 0, | ||||
|    "cancel": 0, | ||||
|    "create": 1, | ||||
|    "delete": 0, | ||||
|    "email": 1, | ||||
|    "export": 0, | ||||
|    "if_owner": 0, | ||||
|    "import": 0, | ||||
|    "permlevel": 0, | ||||
|    "print": 1, | ||||
|    "read": 1, | ||||
|    "report": 0, | ||||
|    "role": "System Manager", | ||||
|    "set_user_permissions": 0, | ||||
|    "share": 1, | ||||
|    "submit": 0, | ||||
|    "write": 1 | ||||
|   } | ||||
|  ], | ||||
|  "quick_entry": 1, | ||||
|  "read_only": 0, | ||||
|  "show_name_in_global_search": 0, | ||||
|  "sort_field": "modified", | ||||
|  "sort_order": "DESC", | ||||
|  "track_changes": 1, | ||||
|  "track_seen": 0, | ||||
|  "track_views": 0 | ||||
|  "track_changes": 1 | ||||
| } | ||||
| @ -8,6 +8,7 @@ from frappe import _ | ||||
| from frappe.utils.nestedset import get_root_of | ||||
| from frappe.model.document import Document | ||||
| from six.moves.urllib.parse import urlparse | ||||
| from frappe.custom.doctype.custom_field.custom_field import create_custom_field | ||||
| 
 | ||||
| class WoocommerceSettings(Document): | ||||
| 	def validate(self): | ||||
| @ -17,75 +18,21 @@ class WoocommerceSettings(Document): | ||||
| 
 | ||||
| 	def create_delete_custom_fields(self): | ||||
| 		if self.enable_sync: | ||||
| 			custom_fields = {} | ||||
| 			# create | ||||
| 			create_custom_field_id_and_check_status = False | ||||
| 			create_custom_field_email_check = False | ||||
| 			names = ["Customer-woocommerce_id","Sales Order-woocommerce_id","Item-woocommerce_id","Address-woocommerce_id"] | ||||
| 			names_check_box = ["Customer-woocommerce_check","Sales Order-woocommerce_check","Item-woocommerce_check","Address-woocommerce_check"] | ||||
| 			email_names = ["Customer-woocommerce_email","Address-woocommerce_email"] | ||||
| 			for doctype in ["Customer", "Sales Order", "Item", "Address"]: | ||||
| 				df = dict(fieldname='woocommerce_id', label='Woocommerce ID', fieldtype='Data', read_only=1, print_hide=1) | ||||
| 				create_custom_field(doctype, df) | ||||
| 
 | ||||
| 			for i in zip(names,names_check_box): | ||||
| 
 | ||||
| 				if not frappe.get_value("Custom Field",{"name":i[0]}) or not frappe.get_value("Custom Field",{"name":i[1]}): | ||||
| 					create_custom_field_id_and_check_status = True | ||||
| 					break | ||||
| 
 | ||||
| 
 | ||||
| 			if create_custom_field_id_and_check_status: | ||||
| 				names = ["Customer","Sales Order","Item","Address"] | ||||
| 				for name in names: | ||||
| 					custom = frappe.new_doc("Custom Field") | ||||
| 					custom.dt = name | ||||
| 					custom.label = "woocommerce_id" | ||||
| 					custom.read_only = 1 | ||||
| 					custom.save() | ||||
| 
 | ||||
| 					custom = frappe.new_doc("Custom Field") | ||||
| 					custom.dt = name | ||||
| 					custom.label = "woocommerce_check" | ||||
| 					custom.fieldtype = "Check" | ||||
| 					custom.read_only = 1 | ||||
| 					custom.save() | ||||
| 
 | ||||
| 			for i in email_names: | ||||
| 
 | ||||
| 				if not frappe.get_value("Custom Field",{"name":i}): | ||||
| 					create_custom_field_email_check = True | ||||
| 					break; | ||||
| 
 | ||||
| 			if create_custom_field_email_check: | ||||
| 				names = ["Customer","Address"] | ||||
| 				for name in names: | ||||
| 					custom = frappe.new_doc("Custom Field") | ||||
| 					custom.dt = name | ||||
| 					custom.label = "woocommerce_email" | ||||
| 					custom.read_only = 1 | ||||
| 					custom.save() | ||||
| 
 | ||||
| 			if not frappe.get_value("Item Group",{"name": _("WooCommerce Products")}): | ||||
| 			for doctype in ["Customer", "Address"]: | ||||
| 				df = dict(fieldname='woocommerce_email', label='Woocommerce Email', fieldtype='Data', read_only=1, print_hide=1) | ||||
| 				create_custom_field(doctype, df) | ||||
| 			 | ||||
| 			if not frappe.get_value("Item Group", {"name": _("WooCommerce Products")}): | ||||
| 				item_group = frappe.new_doc("Item Group") | ||||
| 				item_group.item_group_name = _("WooCommerce Products") | ||||
| 				item_group.parent_item_group = get_root_of("Item Group") | ||||
| 				item_group.save() | ||||
| 
 | ||||
| 
 | ||||
| 		elif not self.enable_sync: | ||||
| 			# delete | ||||
| 			names = ["Customer-woocommerce_id","Sales Order-woocommerce_id","Item-woocommerce_id","Address-woocommerce_id"] | ||||
| 			names_check_box = ["Customer-woocommerce_check","Sales Order-woocommerce_check","Item-woocommerce_check","Address-woocommerce_check"] | ||||
| 			email_names = ["Customer-woocommerce_email","Address-woocommerce_email"] | ||||
| 			for name in names: | ||||
| 				frappe.delete_doc("Custom Field",name) | ||||
| 
 | ||||
| 			for name in names_check_box: | ||||
| 				frappe.delete_doc("Custom Field",name) | ||||
| 
 | ||||
| 			for name in email_names: | ||||
| 				frappe.delete_doc("Custom Field",name) | ||||
| 
 | ||||
| 			frappe.delete_doc("Item Group", _("WooCommerce Products")) | ||||
| 
 | ||||
| 		frappe.db.commit() | ||||
| 				item_group.insert() | ||||
| 
 | ||||
| 	def validate_settings(self): | ||||
| 		if self.enable_sync: | ||||
|  | ||||
| @ -235,17 +235,16 @@ doc_events = { | ||||
| 	("Sales Taxes and Charges Template", 'Price List'): { | ||||
| 		"on_update": "erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings.validate_cart_settings" | ||||
| 	}, | ||||
| 
 | ||||
| 	"Website Settings": { | ||||
| 		"validate": "erpnext.portal.doctype.products_settings.products_settings.home_page_is_products" | ||||
| 	}, | ||||
| 	"Sales Invoice": { | ||||
| 		"on_submit": ["erpnext.regional.france.utils.create_transaction_log", "erpnext.regional.italy.utils.sales_invoice_on_submit"], | ||||
| 		"on_submit": ["erpnext.regional.create_transaction_log", "erpnext.regional.italy.utils.sales_invoice_on_submit"], | ||||
| 		"on_cancel": "erpnext.regional.italy.utils.sales_invoice_on_cancel", | ||||
| 		"on_trash": "erpnext.regional.check_deletion_permission" | ||||
| 	}, | ||||
| 	"Payment Entry": { | ||||
| 		"on_submit": ["erpnext.regional.france.utils.create_transaction_log", "erpnext.accounts.doctype.payment_request.payment_request.make_status_as_paid"], | ||||
| 		"on_submit": ["erpnext.regional.create_transaction_log", "erpnext.accounts.doctype.payment_request.payment_request.make_status_as_paid"], | ||||
| 		"on_trash": "erpnext.regional.check_deletion_permission" | ||||
| 	}, | ||||
| 	'Address': { | ||||
|  | ||||
| @ -167,10 +167,11 @@ class Employee(NestedSet): | ||||
| 	def validate_status(self): | ||||
| 		if self.status == 'Left': | ||||
| 			reports_to = frappe.db.get_all('Employee', | ||||
| 				filters={'reports_to': self.name} | ||||
| 				filters={'reports_to': self.name, 'status': "Active"}, | ||||
| 				fields=['name','employee_name'] | ||||
| 			) | ||||
| 			if reports_to: | ||||
| 				link_to_employees = [frappe.utils.get_link_to_form('Employee', employee.name) for employee in reports_to] | ||||
| 				link_to_employees = [frappe.utils.get_link_to_form('Employee', employee.name, label=employee.employee_name) for employee in reports_to] | ||||
| 				throw(_("Employee status cannot be set to 'Left' as following employees are currently reporting to this employee: ") | ||||
| 					+ ', '.join(link_to_employees), EmployeeLeftValidationError) | ||||
| 			if not self.relieving_date: | ||||
|  | ||||
| @ -21,7 +21,7 @@ def get_data(): | ||||
| 			}, | ||||
| 			{ | ||||
| 				'label': _('Expense'), | ||||
| 				'items': ['Expense Claim', 'Travel Request'] | ||||
| 				'items': ['Expense Claim', 'Travel Request', 'Employee Advance'] | ||||
| 			}, | ||||
| 			{ | ||||
| 				'label': _('Benefit'), | ||||
|  | ||||
| @ -1,435 +1,436 @@ | ||||
| { | ||||
|   "allow_import": 1, | ||||
|   "autoname": "naming_series:", | ||||
|   "creation": "2013-01-10 16:34:14", | ||||
|   "doctype": "DocType", | ||||
|   "document_type": "Setup", | ||||
|   "engine": "InnoDB", | ||||
|   "field_order": [ | ||||
|    "naming_series", | ||||
|    "employee", | ||||
|    "employee_name", | ||||
|    "department", | ||||
|    "column_break_5", | ||||
|    "expense_approver", | ||||
|    "approval_status", | ||||
|    "is_paid", | ||||
|    "expense_details", | ||||
|    "expenses", | ||||
|    "sb1", | ||||
|    "taxes", | ||||
|    "transactions_section", | ||||
|    "total_sanctioned_amount", | ||||
|    "total_taxes_and_charges", | ||||
|    "total_advance_amount", | ||||
|    "column_break_17", | ||||
|    "grand_total", | ||||
|    "total_claimed_amount", | ||||
|    "total_amount_reimbursed", | ||||
|    "section_break_16", | ||||
|    "posting_date", | ||||
|    "vehicle_log", | ||||
|    "task", | ||||
|    "cb1", | ||||
|    "remark", | ||||
|    "title", | ||||
|    "email_id", | ||||
|    "accounting_details", | ||||
|    "company", | ||||
|    "mode_of_payment", | ||||
|    "clearance_date", | ||||
|    "column_break_24", | ||||
|    "payable_account", | ||||
|    "accounting_dimensions_section", | ||||
|    "project", | ||||
|    "dimension_col_break", | ||||
|    "cost_center", | ||||
|    "more_details", | ||||
|    "status", | ||||
|    "amended_from", | ||||
|    "advance_payments", | ||||
|    "advances" | ||||
|   ], | ||||
|   "fields": [ | ||||
|    { | ||||
|     "fieldname": "naming_series", | ||||
|     "fieldtype": "Select", | ||||
|     "label": "Series", | ||||
|     "no_copy": 1, | ||||
|     "options": "HR-EXP-.YYYY.-", | ||||
|     "print_hide": 1, | ||||
|     "reqd": 1, | ||||
|     "set_only_once": 1 | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "employee", | ||||
|     "fieldtype": "Link", | ||||
|     "in_global_search": 1, | ||||
|     "label": "From Employee", | ||||
|     "oldfieldname": "employee", | ||||
|     "oldfieldtype": "Link", | ||||
|     "options": "Employee", | ||||
|     "reqd": 1, | ||||
|     "search_index": 1 | ||||
|    }, | ||||
|    { | ||||
|     "fetch_from": "employee.employee_name", | ||||
|     "fieldname": "employee_name", | ||||
|     "fieldtype": "Data", | ||||
|     "in_global_search": 1, | ||||
|     "label": "Employee Name", | ||||
|     "oldfieldname": "employee_name", | ||||
|     "oldfieldtype": "Data", | ||||
|     "read_only": 1, | ||||
|     "width": "150px" | ||||
|    }, | ||||
|    { | ||||
|     "fetch_from": "employee.department", | ||||
|     "fieldname": "department", | ||||
|     "fieldtype": "Link", | ||||
|     "label": "Department", | ||||
|     "options": "Department", | ||||
|     "read_only": 1 | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "column_break_5", | ||||
|     "fieldtype": "Column Break" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "expense_approver", | ||||
|     "fieldtype": "Link", | ||||
|     "label": "Expense Approver", | ||||
|     "options": "User" | ||||
|    }, | ||||
|    { | ||||
|     "default": "Draft", | ||||
|     "fieldname": "approval_status", | ||||
|     "fieldtype": "Select", | ||||
|     "label": "Approval Status", | ||||
|     "no_copy": 1, | ||||
|     "options": "Draft\nApproved\nRejected", | ||||
|     "search_index": 1 | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "total_claimed_amount", | ||||
|     "fieldtype": "Currency", | ||||
|     "in_list_view": 1, | ||||
|     "label": "Total Claimed Amount", | ||||
|     "no_copy": 1, | ||||
|     "oldfieldname": "total_claimed_amount", | ||||
|     "oldfieldtype": "Currency", | ||||
|     "options": "Company:company:default_currency", | ||||
|     "read_only": 1, | ||||
|     "width": "160px" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "total_sanctioned_amount", | ||||
|     "fieldtype": "Currency", | ||||
|     "label": "Total Sanctioned Amount", | ||||
|     "no_copy": 1, | ||||
|     "oldfieldname": "total_sanctioned_amount", | ||||
|     "oldfieldtype": "Currency", | ||||
|     "options": "Company:company:default_currency", | ||||
|     "read_only": 1, | ||||
|     "width": "160px" | ||||
|    }, | ||||
|    { | ||||
|     "default": "0", | ||||
|     "depends_on": "eval:(doc.docstatus==0 || doc.is_paid)", | ||||
|     "fieldname": "is_paid", | ||||
|     "fieldtype": "Check", | ||||
|     "label": "Is Paid" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "expense_details", | ||||
|     "fieldtype": "Section Break", | ||||
|     "oldfieldtype": "Section Break" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "expenses", | ||||
|     "fieldtype": "Table", | ||||
|     "label": "Expenses", | ||||
|     "oldfieldname": "expense_voucher_details", | ||||
|     "oldfieldtype": "Table", | ||||
|     "options": "Expense Claim Detail", | ||||
|     "reqd": 1 | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "sb1", | ||||
|     "fieldtype": "Section Break", | ||||
|     "options": "Simple" | ||||
|    }, | ||||
|    { | ||||
|     "default": "Today", | ||||
|     "fieldname": "posting_date", | ||||
|     "fieldtype": "Date", | ||||
|     "label": "Posting Date", | ||||
|     "oldfieldname": "posting_date", | ||||
|     "oldfieldtype": "Date", | ||||
|     "reqd": 1 | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "vehicle_log", | ||||
|     "fieldtype": "Link", | ||||
|     "label": "Vehicle Log", | ||||
|     "options": "Vehicle Log", | ||||
|     "read_only": 1 | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "project", | ||||
|     "fieldtype": "Link", | ||||
|     "label": "Project", | ||||
|     "options": "Project" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "task", | ||||
|     "fieldtype": "Link", | ||||
|     "label": "Task", | ||||
|     "options": "Task", | ||||
|     "remember_last_selected_value": 1 | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "cb1", | ||||
|     "fieldtype": "Column Break" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "total_amount_reimbursed", | ||||
|     "fieldtype": "Currency", | ||||
|     "in_list_view": 1, | ||||
|     "label": "Total Amount Reimbursed", | ||||
|     "no_copy": 1, | ||||
|     "options": "Company:company:default_currency", | ||||
|     "read_only": 1 | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "remark", | ||||
|     "fieldtype": "Small Text", | ||||
|     "label": "Remark", | ||||
|     "no_copy": 1, | ||||
|     "oldfieldname": "remark", | ||||
|     "oldfieldtype": "Small Text" | ||||
|    }, | ||||
|    { | ||||
|     "allow_on_submit": 1, | ||||
|     "default": "{employee_name}", | ||||
|     "fieldname": "title", | ||||
|     "fieldtype": "Data", | ||||
|     "hidden": 1, | ||||
|     "label": "Title", | ||||
|     "no_copy": 1 | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "email_id", | ||||
|     "fieldtype": "Data", | ||||
|     "hidden": 1, | ||||
|     "label": "Employees Email Id", | ||||
|     "oldfieldname": "email_id", | ||||
|     "oldfieldtype": "Data", | ||||
|     "print_hide": 1 | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "accounting_details", | ||||
|     "fieldtype": "Section Break", | ||||
|     "label": "Accounting Details" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "company", | ||||
|     "fieldtype": "Link", | ||||
|     "label": "Company", | ||||
|     "oldfieldname": "company", | ||||
|     "oldfieldtype": "Link", | ||||
|     "options": "Company", | ||||
|     "remember_last_selected_value": 1, | ||||
|     "reqd": 1 | ||||
|    }, | ||||
|    { | ||||
|     "depends_on": "is_paid", | ||||
|     "fieldname": "mode_of_payment", | ||||
|     "fieldtype": "Link", | ||||
|     "label": "Mode of Payment", | ||||
|     "options": "Mode of Payment" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "clearance_date", | ||||
|     "fieldtype": "Date", | ||||
|     "label": "Clearance Date" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "column_break_24", | ||||
|     "fieldtype": "Column Break" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "payable_account", | ||||
|     "fieldtype": "Link", | ||||
|     "label": "Payable Account", | ||||
|     "options": "Account" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "cost_center", | ||||
|     "fieldtype": "Link", | ||||
|     "label": "Cost Center", | ||||
|     "options": "Cost Center" | ||||
|    }, | ||||
|    { | ||||
|     "collapsible": 1, | ||||
|     "fieldname": "more_details", | ||||
|     "fieldtype": "Section Break", | ||||
|     "label": "More Details" | ||||
|    }, | ||||
|    { | ||||
|     "default": "Draft", | ||||
|     "fieldname": "status", | ||||
|     "fieldtype": "Select", | ||||
|     "in_list_view": 1, | ||||
|     "label": "Status", | ||||
|     "no_copy": 1, | ||||
|     "options": "Draft\nPaid\nUnpaid\nRejected\nSubmitted\nCancelled", | ||||
|     "print_hide": 1, | ||||
|     "read_only": 1 | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "amended_from", | ||||
|     "fieldtype": "Link", | ||||
|     "ignore_user_permissions": 1, | ||||
|     "label": "Amended From", | ||||
|     "no_copy": 1, | ||||
|     "oldfieldname": "amended_from", | ||||
|     "oldfieldtype": "Data", | ||||
|     "options": "Expense Claim", | ||||
|     "print_hide": 1, | ||||
|     "read_only": 1, | ||||
|     "report_hide": 1, | ||||
|     "width": "160px" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "advance_payments", | ||||
|     "fieldtype": "Section Break", | ||||
|     "label": "Advance Payments" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "advances", | ||||
|     "fieldtype": "Table", | ||||
|     "label": "Advances", | ||||
|     "options": "Expense Claim Advance" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "total_advance_amount", | ||||
|     "fieldtype": "Currency", | ||||
|     "label": "Total Advance Amount", | ||||
|     "options": "Company:company:default_currency", | ||||
|     "read_only": 1 | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "accounting_dimensions_section", | ||||
|     "fieldtype": "Section Break", | ||||
|     "label": "Accounting Dimensions" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "dimension_col_break", | ||||
|     "fieldtype": "Column Break" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "taxes", | ||||
|     "fieldtype": "Table", | ||||
|     "label": "Expense Taxes and Charges", | ||||
|     "options": "Expense Taxes and Charges" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "section_break_16", | ||||
|     "fieldtype": "Section Break" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "transactions_section", | ||||
|     "fieldtype": "Section Break" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "grand_total", | ||||
|     "fieldtype": "Currency", | ||||
|     "in_list_view": 1, | ||||
|     "label": "Grand Total", | ||||
|     "options": "Company:company:default_currency", | ||||
|     "read_only": 1 | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "column_break_17", | ||||
|     "fieldtype": "Column Break" | ||||
|    }, | ||||
|    { | ||||
|     "fieldname": "total_taxes_and_charges", | ||||
|     "fieldtype": "Currency", | ||||
|     "label": "Total Taxes and Charges", | ||||
|     "options": "Company:company:default_currency", | ||||
|     "read_only": 1 | ||||
|    } | ||||
|   ], | ||||
|   "icon": "fa fa-money", | ||||
|   "idx": 1, | ||||
|   "is_submittable": 1, | ||||
|   "modified": "2019-06-26 18:05:52.530462", | ||||
|   "modified_by": "Administrator", | ||||
|   "module": "HR", | ||||
|   "name": "Expense Claim", | ||||
|   "name_case": "Title Case", | ||||
|   "owner": "harshada@webnotestech.com", | ||||
|   "permissions": [ | ||||
|    { | ||||
|     "amend": 1, | ||||
|     "cancel": 1, | ||||
|     "create": 1, | ||||
|     "delete": 1, | ||||
|     "email": 1, | ||||
|     "export": 1, | ||||
|     "print": 1, | ||||
|     "read": 1, | ||||
|     "report": 1, | ||||
|     "role": "HR Manager", | ||||
|     "share": 1, | ||||
|     "submit": 1, | ||||
|     "write": 1 | ||||
|    }, | ||||
|    { | ||||
|     "create": 1, | ||||
|     "email": 1, | ||||
|     "print": 1, | ||||
|     "read": 1, | ||||
|     "report": 1, | ||||
|     "role": "Employee", | ||||
|     "share": 1, | ||||
|     "write": 1 | ||||
|    }, | ||||
|    { | ||||
|     "amend": 1, | ||||
|     "cancel": 1, | ||||
|     "create": 1, | ||||
|     "delete": 1, | ||||
|     "email": 1, | ||||
|     "print": 1, | ||||
|     "read": 1, | ||||
|     "report": 1, | ||||
|     "role": "Expense Approver", | ||||
|     "share": 1, | ||||
|     "submit": 1, | ||||
|     "write": 1 | ||||
|    }, | ||||
|    { | ||||
|     "amend": 1, | ||||
|     "cancel": 1, | ||||
|     "create": 1, | ||||
|     "delete": 1, | ||||
|     "email": 1, | ||||
|     "print": 1, | ||||
|     "read": 1, | ||||
|     "report": 1, | ||||
|     "role": "HR User", | ||||
|     "share": 1, | ||||
|     "submit": 1, | ||||
|     "write": 1 | ||||
|    } | ||||
|   ], | ||||
|   "search_fields": "employee,employee_name", | ||||
|   "show_name_in_global_search": 1, | ||||
|   "sort_field": "modified", | ||||
|   "sort_order": "DESC", | ||||
|   "timeline_field": "employee", | ||||
|   "title_field": "title" | ||||
|  } | ||||
|  "allow_import": 1, | ||||
|  "autoname": "naming_series:", | ||||
|  "creation": "2013-01-10 16:34:14", | ||||
|  "doctype": "DocType", | ||||
|  "document_type": "Setup", | ||||
|  "engine": "InnoDB", | ||||
|  "field_order": [ | ||||
|   "naming_series", | ||||
|   "employee", | ||||
|   "employee_name", | ||||
|   "department", | ||||
|   "column_break_5", | ||||
|   "expense_approver", | ||||
|   "approval_status", | ||||
|   "is_paid", | ||||
|   "expense_details", | ||||
|   "expenses", | ||||
|   "sb1", | ||||
|   "taxes", | ||||
|   "transactions_section", | ||||
|   "total_sanctioned_amount", | ||||
|   "total_taxes_and_charges", | ||||
|   "total_advance_amount", | ||||
|   "column_break_17", | ||||
|   "grand_total", | ||||
|   "total_claimed_amount", | ||||
|   "total_amount_reimbursed", | ||||
|   "section_break_16", | ||||
|   "posting_date", | ||||
|   "vehicle_log", | ||||
|   "task", | ||||
|   "cb1", | ||||
|   "remark", | ||||
|   "title", | ||||
|   "email_id", | ||||
|   "accounting_details", | ||||
|   "company", | ||||
|   "mode_of_payment", | ||||
|   "clearance_date", | ||||
|   "column_break_24", | ||||
|   "payable_account", | ||||
|   "accounting_dimensions_section", | ||||
|   "project", | ||||
|   "dimension_col_break", | ||||
|   "cost_center", | ||||
|   "more_details", | ||||
|   "status", | ||||
|   "amended_from", | ||||
|   "advance_payments", | ||||
|   "advances" | ||||
|  ], | ||||
|  "fields": [ | ||||
|   { | ||||
|    "fieldname": "naming_series", | ||||
|    "fieldtype": "Select", | ||||
|    "label": "Series", | ||||
|    "no_copy": 1, | ||||
|    "options": "HR-EXP-.YYYY.-", | ||||
|    "print_hide": 1, | ||||
|    "reqd": 1, | ||||
|    "set_only_once": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "employee", | ||||
|    "fieldtype": "Link", | ||||
|    "in_global_search": 1, | ||||
|    "label": "From Employee", | ||||
|    "oldfieldname": "employee", | ||||
|    "oldfieldtype": "Link", | ||||
|    "options": "Employee", | ||||
|    "reqd": 1, | ||||
|    "search_index": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fetch_from": "employee.employee_name", | ||||
|    "fieldname": "employee_name", | ||||
|    "fieldtype": "Data", | ||||
|    "in_global_search": 1, | ||||
|    "label": "Employee Name", | ||||
|    "oldfieldname": "employee_name", | ||||
|    "oldfieldtype": "Data", | ||||
|    "read_only": 1, | ||||
|    "width": "150px" | ||||
|   }, | ||||
|   { | ||||
|    "fetch_from": "employee.department", | ||||
|    "fieldname": "department", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Department", | ||||
|    "options": "Department", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "column_break_5", | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "expense_approver", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Expense Approver", | ||||
|    "options": "User" | ||||
|   }, | ||||
|   { | ||||
|    "default": "Draft", | ||||
|    "fieldname": "approval_status", | ||||
|    "fieldtype": "Select", | ||||
|    "label": "Approval Status", | ||||
|    "no_copy": 1, | ||||
|    "options": "Draft\nApproved\nRejected", | ||||
|    "search_index": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "total_claimed_amount", | ||||
|    "fieldtype": "Currency", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Total Claimed Amount", | ||||
|    "no_copy": 1, | ||||
|    "oldfieldname": "total_claimed_amount", | ||||
|    "oldfieldtype": "Currency", | ||||
|    "options": "Company:company:default_currency", | ||||
|    "read_only": 1, | ||||
|    "width": "160px" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "total_sanctioned_amount", | ||||
|    "fieldtype": "Currency", | ||||
|    "label": "Total Sanctioned Amount", | ||||
|    "no_copy": 1, | ||||
|    "oldfieldname": "total_sanctioned_amount", | ||||
|    "oldfieldtype": "Currency", | ||||
|    "options": "Company:company:default_currency", | ||||
|    "read_only": 1, | ||||
|    "width": "160px" | ||||
|   }, | ||||
|   { | ||||
|    "default": "0", | ||||
|    "depends_on": "eval:(doc.docstatus==0 || doc.is_paid)", | ||||
|    "fieldname": "is_paid", | ||||
|    "fieldtype": "Check", | ||||
|    "label": "Is Paid" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "expense_details", | ||||
|    "fieldtype": "Section Break", | ||||
|    "oldfieldtype": "Section Break" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "expenses", | ||||
|    "fieldtype": "Table", | ||||
|    "label": "Expenses", | ||||
|    "oldfieldname": "expense_voucher_details", | ||||
|    "oldfieldtype": "Table", | ||||
|    "options": "Expense Claim Detail", | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "sb1", | ||||
|    "fieldtype": "Section Break", | ||||
|    "options": "Simple" | ||||
|   }, | ||||
|   { | ||||
|    "default": "Today", | ||||
|    "fieldname": "posting_date", | ||||
|    "fieldtype": "Date", | ||||
|    "label": "Posting Date", | ||||
|    "oldfieldname": "posting_date", | ||||
|    "oldfieldtype": "Date", | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "vehicle_log", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Vehicle Log", | ||||
|    "options": "Vehicle Log", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "project", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Project", | ||||
|    "options": "Project" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "task", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Task", | ||||
|    "options": "Task", | ||||
|    "remember_last_selected_value": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "cb1", | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "total_amount_reimbursed", | ||||
|    "fieldtype": "Currency", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Total Amount Reimbursed", | ||||
|    "no_copy": 1, | ||||
|    "options": "Company:company:default_currency", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "remark", | ||||
|    "fieldtype": "Small Text", | ||||
|    "label": "Remark", | ||||
|    "no_copy": 1, | ||||
|    "oldfieldname": "remark", | ||||
|    "oldfieldtype": "Small Text" | ||||
|   }, | ||||
|   { | ||||
|    "allow_on_submit": 1, | ||||
|    "default": "{employee_name}", | ||||
|    "fieldname": "title", | ||||
|    "fieldtype": "Data", | ||||
|    "hidden": 1, | ||||
|    "label": "Title", | ||||
|    "no_copy": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "email_id", | ||||
|    "fieldtype": "Data", | ||||
|    "hidden": 1, | ||||
|    "label": "Employees Email Id", | ||||
|    "oldfieldname": "email_id", | ||||
|    "oldfieldtype": "Data", | ||||
|    "print_hide": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "accounting_details", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "Accounting Details" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "company", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Company", | ||||
|    "oldfieldname": "company", | ||||
|    "oldfieldtype": "Link", | ||||
|    "options": "Company", | ||||
|    "remember_last_selected_value": 1, | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "depends_on": "is_paid", | ||||
|    "fieldname": "mode_of_payment", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Mode of Payment", | ||||
|    "options": "Mode of Payment" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "clearance_date", | ||||
|    "fieldtype": "Date", | ||||
|    "label": "Clearance Date" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "column_break_24", | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "payable_account", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Payable Account", | ||||
|    "options": "Account", | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "cost_center", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Cost Center", | ||||
|    "options": "Cost Center" | ||||
|   }, | ||||
|   { | ||||
|    "collapsible": 1, | ||||
|    "fieldname": "more_details", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "More Details" | ||||
|   }, | ||||
|   { | ||||
|    "default": "Draft", | ||||
|    "fieldname": "status", | ||||
|    "fieldtype": "Select", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Status", | ||||
|    "no_copy": 1, | ||||
|    "options": "Draft\nPaid\nUnpaid\nRejected\nSubmitted\nCancelled", | ||||
|    "print_hide": 1, | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "amended_from", | ||||
|    "fieldtype": "Link", | ||||
|    "ignore_user_permissions": 1, | ||||
|    "label": "Amended From", | ||||
|    "no_copy": 1, | ||||
|    "oldfieldname": "amended_from", | ||||
|    "oldfieldtype": "Data", | ||||
|    "options": "Expense Claim", | ||||
|    "print_hide": 1, | ||||
|    "read_only": 1, | ||||
|    "report_hide": 1, | ||||
|    "width": "160px" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "advance_payments", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "Advance Payments" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "advances", | ||||
|    "fieldtype": "Table", | ||||
|    "label": "Advances", | ||||
|    "options": "Expense Claim Advance" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "total_advance_amount", | ||||
|    "fieldtype": "Currency", | ||||
|    "label": "Total Advance Amount", | ||||
|    "options": "Company:company:default_currency", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "accounting_dimensions_section", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "Accounting Dimensions" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "dimension_col_break", | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "taxes", | ||||
|    "fieldtype": "Table", | ||||
|    "label": "Expense Taxes and Charges", | ||||
|    "options": "Expense Taxes and Charges" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "section_break_16", | ||||
|    "fieldtype": "Section Break" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "transactions_section", | ||||
|    "fieldtype": "Section Break" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "grand_total", | ||||
|    "fieldtype": "Currency", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Grand Total", | ||||
|    "options": "Company:company:default_currency", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "column_break_17", | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "total_taxes_and_charges", | ||||
|    "fieldtype": "Currency", | ||||
|    "label": "Total Taxes and Charges", | ||||
|    "options": "Company:company:default_currency", | ||||
|    "read_only": 1 | ||||
|   } | ||||
|  ], | ||||
|  "icon": "fa fa-money", | ||||
|  "idx": 1, | ||||
|  "is_submittable": 1, | ||||
|  "modified": "2019-11-08 14:13:08.964547", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "HR", | ||||
|  "name": "Expense Claim", | ||||
|  "name_case": "Title Case", | ||||
|  "owner": "harshada@webnotestech.com", | ||||
|  "permissions": [ | ||||
|   { | ||||
|    "amend": 1, | ||||
|    "cancel": 1, | ||||
|    "create": 1, | ||||
|    "delete": 1, | ||||
|    "email": 1, | ||||
|    "export": 1, | ||||
|    "print": 1, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "role": "HR Manager", | ||||
|    "share": 1, | ||||
|    "submit": 1, | ||||
|    "write": 1 | ||||
|   }, | ||||
|   { | ||||
|    "create": 1, | ||||
|    "email": 1, | ||||
|    "print": 1, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "role": "Employee", | ||||
|    "share": 1, | ||||
|    "write": 1 | ||||
|   }, | ||||
|   { | ||||
|    "amend": 1, | ||||
|    "cancel": 1, | ||||
|    "create": 1, | ||||
|    "delete": 1, | ||||
|    "email": 1, | ||||
|    "print": 1, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "role": "Expense Approver", | ||||
|    "share": 1, | ||||
|    "submit": 1, | ||||
|    "write": 1 | ||||
|   }, | ||||
|   { | ||||
|    "amend": 1, | ||||
|    "cancel": 1, | ||||
|    "create": 1, | ||||
|    "delete": 1, | ||||
|    "email": 1, | ||||
|    "print": 1, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "role": "HR User", | ||||
|    "share": 1, | ||||
|    "submit": 1, | ||||
|    "write": 1 | ||||
|   } | ||||
|  ], | ||||
|  "search_fields": "employee,employee_name", | ||||
|  "show_name_in_global_search": 1, | ||||
|  "sort_field": "modified", | ||||
|  "sort_order": "DESC", | ||||
|  "timeline_field": "employee", | ||||
|  "title_field": "title" | ||||
| } | ||||
| @ -144,6 +144,33 @@ class ExpenseClaim(AccountsController): | ||||
| 					"against_voucher": self.name | ||||
| 				}) | ||||
| 			) | ||||
| 
 | ||||
| 			gl_entry.append( | ||||
| 				self.get_gl_dict({ | ||||
| 					"account": data.advance_account, | ||||
| 					"debit": data.allocated_amount, | ||||
| 					"debit_in_account_currency": data.allocated_amount, | ||||
| 					"against": self.payable_account, | ||||
| 					"party_type": "Employee", | ||||
| 					"party": self.employee, | ||||
| 					"against_voucher_type": self.doctype, | ||||
| 					"against_voucher": self.name | ||||
| 				}) | ||||
| 			) | ||||
| 
 | ||||
| 			gl_entry.append( | ||||
| 				self.get_gl_dict({ | ||||
| 					"account": self.payable_account, | ||||
| 					"credit": data.allocated_amount, | ||||
| 					"credit_in_account_currency": data.allocated_amount, | ||||
| 					"against": data.advance_account, | ||||
| 					"party_type": "Employee", | ||||
| 					"party": self.employee, | ||||
| 					"against_voucher_type": "Employee Advance", | ||||
| 					"against_voucher": data.employee_advance | ||||
| 				}) | ||||
| 			) | ||||
| 
 | ||||
| 		self.add_tax_gl_entries(gl_entry) | ||||
| 
 | ||||
| 		if self.is_paid and self.grand_total: | ||||
| @ -192,9 +219,6 @@ class ExpenseClaim(AccountsController): | ||||
| 		if not self.cost_center: | ||||
| 			frappe.throw(_("Cost center is required to book an expense claim")) | ||||
| 
 | ||||
| 		if not self.payable_account: | ||||
| 			frappe.throw(_("Please set default payable account for the company {0}").format(getlink("Company",self.company))) | ||||
| 
 | ||||
| 		if self.is_paid: | ||||
| 			if not self.mode_of_payment: | ||||
| 				frappe.throw(_("Mode of payment is required to make a payment").format(self.employee)) | ||||
|  | ||||
| @ -46,10 +46,12 @@ frappe.ui.form.on('Salary Structure', { | ||||
| 		frm.trigger("toggle_fields"); | ||||
| 		frm.fields_dict['earnings'].grid.set_column_disp("default_amount", false); | ||||
| 		frm.fields_dict['deductions'].grid.set_column_disp("default_amount", false); | ||||
| 
 | ||||
| 		frm.add_custom_button(__("Preview Salary Slip"), function() { | ||||
| 			frm.trigger('preview_salary_slip'); | ||||
| 		}); | ||||
| 		 | ||||
| 		if(frm.doc.docstatus === 1) { | ||||
| 			frm.add_custom_button(__("Preview Salary Slip"), function() { | ||||
| 				frm.trigger('preview_salary_slip'); | ||||
| 			}); | ||||
| 		} | ||||
| 
 | ||||
| 		if(frm.doc.docstatus==1) { | ||||
| 			frm.add_custom_button(__("Assign Salary Structure"), function() { | ||||
|  | ||||
| @ -169,5 +169,10 @@ def make_salary_slip(source_name, target_doc = None, employee = None, as_print = | ||||
| @frappe.whitelist() | ||||
| def get_employees(salary_structure): | ||||
| 	employees = frappe.get_list('Salary Structure Assignment', | ||||
| 		filters={'salary_structure': salary_structure}, fields=['employee']) | ||||
| 		filters={'salary_structure': salary_structure, 'docstatus': 1}, fields=['employee']) | ||||
| 	 | ||||
| 	if not employees: | ||||
| 		frappe.throw(_("There's no Employee with Salary Structure: {0}. \ | ||||
| 			Assign {1} to an Employee to preview Salary Slip").format(salary_structure, salary_structure)) | ||||
| 
 | ||||
| 	return list(set([d.employee for d in employees])) | ||||
|  | ||||
| @ -7,6 +7,7 @@ import frappe | ||||
| from frappe.model.document import Document | ||||
| from frappe import _ | ||||
| from frappe.utils import getdate, nowdate, cint, flt | ||||
| from frappe.utils.nestedset import get_descendants_of | ||||
| 
 | ||||
| class SubsidiaryCompanyError(frappe.ValidationError): pass | ||||
| class ParentCompanyError(frappe.ValidationError): pass | ||||
| @ -131,7 +132,8 @@ def get_designation_counts(designation, company): | ||||
| 		return False | ||||
| 
 | ||||
| 	employee_counts = {} | ||||
| 	company_set = get_company_set(company) | ||||
| 	company_set = get_descendants_of('Company', company) | ||||
| 	company_set.append(company) | ||||
| 
 | ||||
| 	employee_counts["employee_count"] = frappe.db.get_value("Employee", | ||||
| 		filters={ | ||||
| @ -167,14 +169,4 @@ def get_active_staffing_plan_details(company, designation, from_date=getdate(now | ||||
| 				designation, from_date, to_date) | ||||
| 
 | ||||
| 	# Only a single staffing plan can be active for a designation on given date | ||||
| 	return staffing_plan if staffing_plan else None | ||||
| 
 | ||||
| def get_company_set(company): | ||||
| 	return frappe.db.sql_list(""" | ||||
| 		SELECT | ||||
| 			name | ||||
| 		FROM `tabCompany` | ||||
| 		WHERE | ||||
| 			parent_company=%(company)s | ||||
| 			OR name=%(company)s | ||||
| 	""", (dict(company=company))) | ||||
| 	return staffing_plan if staffing_plan else None | ||||
| @ -2,4 +2,14 @@ | ||||
| // For license information, please see license.txt
 | ||||
| 
 | ||||
| frappe.query_reports["Department Analytics"] = { | ||||
| 	"filters": [ | ||||
| 		{ | ||||
| 			"fieldname":"company", | ||||
| 			"label": __("Company"), | ||||
| 			"fieldtype": "Link", | ||||
| 			"options": "Company", | ||||
| 			"default": frappe.defaults.get_user_default("Company"), | ||||
| 			"reqd": 1 | ||||
| 		}, | ||||
| 	] | ||||
| }; | ||||
| @ -7,6 +7,10 @@ from frappe import _ | ||||
| 
 | ||||
| def execute(filters=None): | ||||
| 	if not filters: filters = {} | ||||
| 
 | ||||
| 	if not filters["company"]: | ||||
| 		frappe.throw(_('{0} is mandatory').format(_('Company'))) | ||||
| 
 | ||||
| 	columns = get_columns() | ||||
| 	employees = get_employees(filters) | ||||
| 	departments_result = get_department(filters) | ||||
| @ -28,6 +32,9 @@ def get_conditions(filters): | ||||
| 	conditions = "" | ||||
| 	if filters.get("department"): conditions += " and department = '%s'" % \ | ||||
| 		filters["department"].replace("'", "\\'") | ||||
| 	 | ||||
| 	if filters.get("company"): conditions += " and company = '%s'" % \ | ||||
| 		filters["company"].replace("'", "\\'") | ||||
| 	return conditions | ||||
| 
 | ||||
| def get_employees(filters): | ||||
| @ -37,7 +44,7 @@ def get_employees(filters): | ||||
| 	gender, company from `tabEmployee` where status = 'Active' %s""" % conditions, as_list=1) | ||||
| 
 | ||||
| def get_department(filters): | ||||
| 	return frappe.db.sql("""select name from `tabDepartment`""" , as_list=1) | ||||
| 	return frappe.db.sql("""select name from `tabDepartment` where company = %s""", (filters["company"]), as_list=1) | ||||
| 	 | ||||
| def get_chart_data(departments,employees): | ||||
| 	if not departments: | ||||
|  | ||||
| @ -420,8 +420,12 @@ class BOM(WebsiteGenerator): | ||||
| 
 | ||||
| 	def traverse_tree(self, bom_list=None): | ||||
| 		def _get_children(bom_no): | ||||
| 			return frappe.db.sql_list("""select bom_no from `tabBOM Item` | ||||
| 				where parent = %s and ifnull(bom_no, '') != '' and parenttype='BOM'""", bom_no) | ||||
| 			children = frappe.cache().hget('bom_children', bom_no) | ||||
| 			if children is None: | ||||
| 				children = frappe.db.sql_list("""SELECT `bom_no` FROM `tabBOM Item` | ||||
| 					WHERE `parent`=%s AND `bom_no`!='' AND `parenttype`='BOM'""", bom_no) | ||||
| 				frappe.cache().hset('bom_children', bom_no, children) | ||||
| 			return children | ||||
| 
 | ||||
| 		count = 0 | ||||
| 		if not bom_list: | ||||
| @ -534,12 +538,24 @@ class BOM(WebsiteGenerator): | ||||
| 	def get_child_exploded_items(self, bom_no, stock_qty): | ||||
| 		""" Add all items from Flat BOM of child BOM""" | ||||
| 		# Did not use qty_consumed_per_unit in the query, as it leads to rounding loss | ||||
| 		child_fb_items = frappe.db.sql("""select bom_item.item_code, bom_item.item_name, | ||||
| 			bom_item.description, bom_item.source_warehouse, bom_item.operation, | ||||
| 			bom_item.stock_uom, bom_item.stock_qty, bom_item.rate, bom_item.include_item_in_manufacturing, | ||||
| 			bom_item.stock_qty / ifnull(bom.quantity, 1) as qty_consumed_per_unit | ||||
| 			from `tabBOM Explosion Item` bom_item, tabBOM bom | ||||
| 			where bom_item.parent = bom.name and bom.name = %s and bom.docstatus = 1""", bom_no, as_dict = 1) | ||||
| 		child_fb_items = frappe.db.sql(""" | ||||
| 			SELECT | ||||
| 				bom_item.item_code, | ||||
| 				bom_item.item_name, | ||||
| 				bom_item.description, | ||||
| 				bom_item.source_warehouse, | ||||
| 				bom_item.operation, | ||||
| 				bom_item.stock_uom, | ||||
| 				bom_item.stock_qty, | ||||
| 				bom_item.rate, | ||||
| 				bom_item.include_item_in_manufacturing, | ||||
| 				bom_item.stock_qty / ifnull(bom.quantity, 1) AS qty_consumed_per_unit | ||||
| 			FROM `tabBOM Explosion Item` bom_item, tabBOM bom | ||||
| 			WHERE | ||||
| 				bom_item.parent = bom.name | ||||
| 				AND bom.name = %s | ||||
| 				AND bom.docstatus = 1 | ||||
| 		""", bom_no, as_dict = 1) | ||||
| 
 | ||||
| 		for d in child_fb_items: | ||||
| 			self.add_to_cur_exploded_items(frappe._dict({ | ||||
| @ -760,6 +776,8 @@ def add_additional_cost(stock_entry, work_order): | ||||
| 	# Add non stock items cost in the additional cost | ||||
| 	bom = frappe.get_doc('BOM', work_order.bom_no) | ||||
| 	table = 'exploded_items' if work_order.get('use_multi_level_bom') else 'items' | ||||
| 	expenses_included_in_valuation = frappe.get_cached_value("Company", work_order.company, | ||||
| 		"expenses_included_in_valuation") | ||||
| 
 | ||||
| 	items = {} | ||||
| 	for d in bom.get(table): | ||||
| @ -770,6 +788,7 @@ def add_additional_cost(stock_entry, work_order): | ||||
| 
 | ||||
| 	for name in non_stock_items: | ||||
| 		stock_entry.append('additional_costs', { | ||||
| 			'expense_account': expenses_included_in_valuation, | ||||
| 			'description': name[0], | ||||
| 			'amount': items.get(name[0]) | ||||
| 		}) | ||||
|  | ||||
| @ -14,23 +14,23 @@ class BOMUpdateTool(Document): | ||||
| 	def replace_bom(self): | ||||
| 		self.validate_bom() | ||||
| 		self.update_new_bom() | ||||
| 		frappe.cache().delete_key('bom_children') | ||||
| 		bom_list = self.get_parent_boms(self.new_bom) | ||||
| 		updated_bom = [] | ||||
| 
 | ||||
| 		for bom in bom_list: | ||||
| 			try: | ||||
| 				bom_obj = frappe.get_doc("BOM", bom) | ||||
| 				bom_obj.load_doc_before_save() | ||||
| 				updated_bom = bom_obj.update_cost_and_exploded_items(updated_bom) | ||||
| 				bom_obj = frappe.get_cached_doc('BOM', bom) | ||||
| 				# this is only used for versioning and we do not want | ||||
| 				# to make separate db calls by using load_doc_before_save | ||||
| 				# which proves to be expensive while doing bulk replace | ||||
| 				bom_obj._doc_before_save = bom_obj.as_dict() | ||||
| 				bom_obj.calculate_cost() | ||||
| 				bom_obj.update_parent_cost() | ||||
| 				bom_obj.db_update() | ||||
| 				if (getattr(bom_obj.meta, 'track_changes', False) and not bom_obj.flags.ignore_version): | ||||
| 				if bom_obj.meta.get('track_changes') and not bom_obj.flags.ignore_version: | ||||
| 					bom_obj.save_version() | ||||
| 
 | ||||
| 				frappe.db.commit() | ||||
| 			except Exception: | ||||
| 				frappe.db.rollback() | ||||
| 				frappe.log_error(frappe.get_traceback()) | ||||
| 
 | ||||
| 	def validate_bom(self): | ||||
| @ -42,22 +42,22 @@ class BOMUpdateTool(Document): | ||||
| 				frappe.throw(_("The selected BOMs are not for the same item")) | ||||
| 
 | ||||
| 	def update_new_bom(self): | ||||
| 		new_bom_unitcost = frappe.db.sql("""select total_cost/quantity | ||||
| 			from `tabBOM` where name = %s""", self.new_bom) | ||||
| 		new_bom_unitcost = frappe.db.sql("""SELECT `total_cost`/`quantity` | ||||
| 			FROM `tabBOM` WHERE name = %s""", self.new_bom) | ||||
| 		new_bom_unitcost = flt(new_bom_unitcost[0][0]) if new_bom_unitcost else 0 | ||||
| 
 | ||||
| 		frappe.db.sql("""update `tabBOM Item` set bom_no=%s, | ||||
| 			rate=%s, amount=stock_qty*%s where bom_no = %s and docstatus < 2 and parenttype='BOM'""", | ||||
| 			(self.new_bom, new_bom_unitcost, new_bom_unitcost, self.current_bom)) | ||||
| 
 | ||||
| 	def get_parent_boms(self, bom, bom_list=None): | ||||
| 		if not bom_list: | ||||
| 			bom_list = [] | ||||
| 
 | ||||
| 		data = frappe.db.sql(""" select distinct parent from `tabBOM Item` | ||||
| 			where bom_no = %s and docstatus < 2 and parenttype='BOM'""", bom) | ||||
| 	def get_parent_boms(self, bom, bom_list=[]): | ||||
| 		data = frappe.db.sql("""SELECT DISTINCT parent FROM `tabBOM Item` | ||||
| 			WHERE bom_no = %s AND docstatus < 2 AND parenttype='BOM'""", bom) | ||||
| 
 | ||||
| 		for d in data: | ||||
| 			if self.new_bom == d[0]: | ||||
| 				frappe.throw(_("BOM recursion: {0} cannot be child of {1}").format(bom, self.new_bom)) | ||||
| 
 | ||||
| 			bom_list.append(d[0]) | ||||
| 			self.get_parent_boms(d[0], bom_list) | ||||
| 
 | ||||
|  | ||||
| @ -1,443 +1,135 @@ | ||||
| { | ||||
|  "allow_copy": 0,  | ||||
|  "allow_events_in_timeline": 0,  | ||||
|  "allow_guest_to_view": 0,  | ||||
|  "allow_import": 0,  | ||||
|  "allow_rename": 0,  | ||||
|  "beta": 0,  | ||||
|  "creation": "2017-12-01 12:12:55.048691",  | ||||
|  "custom": 0,  | ||||
|  "docstatus": 0,  | ||||
|  "doctype": "DocType",  | ||||
|  "document_type": "",  | ||||
|  "editable_grid": 1,  | ||||
|  "engine": "InnoDB",  | ||||
|  "creation": "2017-12-01 12:12:55.048691", | ||||
|  "doctype": "DocType", | ||||
|  "editable_grid": 1, | ||||
|  "engine": "InnoDB", | ||||
|  "field_order": [ | ||||
|   "item_code", | ||||
|   "item_name", | ||||
|   "warehouse", | ||||
|   "material_request_type", | ||||
|   "column_break_4", | ||||
|   "quantity", | ||||
|   "uom", | ||||
|   "projected_qty", | ||||
|   "actual_qty", | ||||
|   "item_details", | ||||
|   "description", | ||||
|   "min_order_qty", | ||||
|   "section_break_8", | ||||
|   "sales_order", | ||||
|   "requested_qty" | ||||
|  ], | ||||
|  "fields": [ | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_in_quick_entry": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fetch_if_empty": 0,  | ||||
|    "fieldname": "item_code",  | ||||
|    "fieldtype": "Link",  | ||||
|    "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": "Item Code",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "options": "Item",  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 0,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 1,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "translatable": 0,  | ||||
|    "unique": 0 | ||||
|   },  | ||||
|    "fieldname": "item_code", | ||||
|    "fieldtype": "Link", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Item Code", | ||||
|    "options": "Item", | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_in_quick_entry": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fetch_if_empty": 0,  | ||||
|    "fieldname": "item_name",  | ||||
|    "fieldtype": "Data",  | ||||
|    "hidden": 0,  | ||||
|    "ignore_user_permissions": 0,  | ||||
|    "ignore_xss_filter": 0,  | ||||
|    "in_filter": 0,  | ||||
|    "in_global_search": 0,  | ||||
|    "in_list_view": 0,  | ||||
|    "in_standard_filter": 0,  | ||||
|    "label": "Item Name",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "options": "",  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 0,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 0,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "translatable": 0,  | ||||
|    "unique": 0 | ||||
|   },  | ||||
|    "fieldname": "item_name", | ||||
|    "fieldtype": "Data", | ||||
|    "label": "Item Name" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_in_quick_entry": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fetch_if_empty": 0,  | ||||
|    "fieldname": "warehouse",  | ||||
|    "fieldtype": "Link",  | ||||
|    "hidden": 0,  | ||||
|    "ignore_user_permissions": 0,  | ||||
|    "ignore_xss_filter": 0,  | ||||
|    "in_filter": 0,  | ||||
|    "in_global_search": 0,  | ||||
|    "in_list_view": 1,  | ||||
|    "in_standard_filter": 1,  | ||||
|    "label": "Warehouse",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "options": "Warehouse",  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 0,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 1,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "translatable": 0,  | ||||
|    "unique": 0 | ||||
|   },  | ||||
|    "fieldname": "warehouse", | ||||
|    "fieldtype": "Link", | ||||
|    "in_list_view": 1, | ||||
|    "in_standard_filter": 1, | ||||
|    "label": "Warehouse", | ||||
|    "options": "Warehouse", | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_in_quick_entry": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fetch_if_empty": 0,  | ||||
|    "fieldname": "material_request_type",  | ||||
|    "fieldtype": "Select",  | ||||
|    "hidden": 0,  | ||||
|    "ignore_user_permissions": 0,  | ||||
|    "ignore_xss_filter": 0,  | ||||
|    "in_filter": 0,  | ||||
|    "in_global_search": 0,  | ||||
|    "in_list_view": 0,  | ||||
|    "in_standard_filter": 0,  | ||||
|    "label": "Material Request Type",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "options": "\nPurchase\nMaterial Transfer\nMaterial Issue\nManufacture\nCustomer Provided",  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 0,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 0,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "translatable": 0,  | ||||
|    "unique": 0 | ||||
|   },  | ||||
|    "fieldname": "material_request_type", | ||||
|    "fieldtype": "Select", | ||||
|    "label": "Material Request Type", | ||||
|    "options": "\nPurchase\nMaterial Transfer\nMaterial Issue\nManufacture\nCustomer Provided" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_in_quick_entry": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fetch_if_empty": 0,  | ||||
|    "fieldname": "column_break_4",  | ||||
|    "fieldtype": "Column Break",  | ||||
|    "hidden": 0,  | ||||
|    "ignore_user_permissions": 0,  | ||||
|    "ignore_xss_filter": 0,  | ||||
|    "in_filter": 0,  | ||||
|    "in_global_search": 0,  | ||||
|    "in_list_view": 0,  | ||||
|    "in_standard_filter": 0,  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 0,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 0,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "translatable": 0,  | ||||
|    "unique": 0 | ||||
|   },  | ||||
|    "fieldname": "column_break_4", | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_in_quick_entry": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fetch_if_empty": 0,  | ||||
|    "fieldname": "quantity",  | ||||
|    "fieldtype": "Float",  | ||||
|    "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": "Required Quantity",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 1,  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 0,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 1,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "translatable": 0,  | ||||
|    "unique": 0 | ||||
|   },  | ||||
|    "fieldname": "quantity", | ||||
|    "fieldtype": "Float", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Required Quantity", | ||||
|    "no_copy": 1, | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_in_quick_entry": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fetch_if_empty": 0,  | ||||
|    "fieldname": "projected_qty",  | ||||
|    "fieldtype": "Float",  | ||||
|    "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": "Projected Qty",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 1,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 0,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "translatable": 0,  | ||||
|    "unique": 0 | ||||
|   },  | ||||
|    "fieldname": "projected_qty", | ||||
|    "fieldtype": "Float", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Projected Qty", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_in_quick_entry": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "collapsible_depends_on": "",  | ||||
|    "columns": 0,  | ||||
|    "depends_on": "",  | ||||
|    "fetch_if_empty": 0,  | ||||
|    "fieldname": "actual_qty",  | ||||
|    "fieldtype": "Float",  | ||||
|    "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": "Actual Qty",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 1,  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 1,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 0,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "translatable": 0,  | ||||
|    "unique": 0 | ||||
|   },  | ||||
|    "fieldname": "actual_qty", | ||||
|    "fieldtype": "Float", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Actual Qty", | ||||
|    "no_copy": 1, | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_in_quick_entry": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fetch_if_empty": 0,  | ||||
|    "fieldname": "min_order_qty",  | ||||
|    "fieldtype": "Float",  | ||||
|    "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": "Minimum Order Quantity",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 1,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 0,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "translatable": 0,  | ||||
|    "unique": 0 | ||||
|   },  | ||||
|    "fieldname": "min_order_qty", | ||||
|    "fieldtype": "Float", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Minimum Order Quantity", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_in_quick_entry": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 1,  | ||||
|    "columns": 0,  | ||||
|    "fetch_if_empty": 0,  | ||||
|    "fieldname": "section_break_8",  | ||||
|    "fieldtype": "Section Break",  | ||||
|    "hidden": 0,  | ||||
|    "ignore_user_permissions": 0,  | ||||
|    "ignore_xss_filter": 0,  | ||||
|    "in_filter": 0,  | ||||
|    "in_global_search": 0,  | ||||
|    "in_list_view": 0,  | ||||
|    "in_standard_filter": 0,  | ||||
|    "label": "Reference",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 0,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 0,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "translatable": 0,  | ||||
|    "unique": 0 | ||||
|   },  | ||||
|    "collapsible": 1, | ||||
|    "fieldname": "section_break_8", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "Reference" | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_in_quick_entry": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fetch_if_empty": 0,  | ||||
|    "fieldname": "sales_order",  | ||||
|    "fieldtype": "Link",  | ||||
|    "hidden": 0,  | ||||
|    "ignore_user_permissions": 0,  | ||||
|    "ignore_xss_filter": 0,  | ||||
|    "in_filter": 0,  | ||||
|    "in_global_search": 0,  | ||||
|    "in_list_view": 0,  | ||||
|    "in_standard_filter": 0,  | ||||
|    "label": "Sales Order",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "options": "Sales Order",  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 1,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 0,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "translatable": 0,  | ||||
|    "unique": 0 | ||||
|   },  | ||||
|    "fieldname": "sales_order", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Sales Order", | ||||
|    "options": "Sales Order", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_in_quick_entry": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "depends_on": "",  | ||||
|    "fetch_if_empty": 0,  | ||||
|    "fieldname": "requested_qty",  | ||||
|    "fieldtype": "Float",  | ||||
|    "hidden": 0,  | ||||
|    "ignore_user_permissions": 0,  | ||||
|    "ignore_xss_filter": 0,  | ||||
|    "in_filter": 0,  | ||||
|    "in_global_search": 0,  | ||||
|    "in_list_view": 0,  | ||||
|    "in_standard_filter": 0,  | ||||
|    "label": "Requested Qty",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "permlevel": 0,  | ||||
|    "precision": "",  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 1,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 0,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "translatable": 0,  | ||||
|    "unique": 0 | ||||
|    "fieldname": "requested_qty", | ||||
|    "fieldtype": "Float", | ||||
|    "label": "Requested Qty", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
|    "collapsible": 1, | ||||
|    "fieldname": "item_details", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "Item Description" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "description", | ||||
|    "fieldtype": "Text Editor", | ||||
|    "label": "Description" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "uom", | ||||
|    "fieldtype": "Link", | ||||
|    "label": "UOM", | ||||
|    "options": "UOM", | ||||
|    "read_only": 1 | ||||
|   } | ||||
|  ],  | ||||
|  "has_web_view": 0,  | ||||
|  "hide_toolbar": 0,  | ||||
|  "idx": 0,  | ||||
|  "in_create": 0,  | ||||
|  "is_submittable": 0,  | ||||
|  "issingle": 0,  | ||||
|  "istable": 1,  | ||||
|  "max_attachments": 0,  | ||||
|  "modified": "2019-04-08 18:15:26.849602",  | ||||
|  "modified_by": "Administrator",  | ||||
|  "module": "Manufacturing",  | ||||
|  "name": "Material Request Plan Item",  | ||||
|  "name_case": "",  | ||||
|  "owner": "Administrator",  | ||||
|  "permissions": [],  | ||||
|  "quick_entry": 1,  | ||||
|  "read_only": 0,  | ||||
|  "show_name_in_global_search": 0,  | ||||
|  "sort_field": "modified",  | ||||
|  "sort_order": "DESC",  | ||||
|  "track_changes": 1,  | ||||
|  "track_seen": 0,  | ||||
|  "track_views": 0 | ||||
|  ], | ||||
|  "istable": 1, | ||||
|  "modified": "2019-11-08 15:15:43.979360", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Manufacturing", | ||||
|  "name": "Material Request Plan Item", | ||||
|  "owner": "Administrator", | ||||
|  "permissions": [], | ||||
|  "quick_entry": 1, | ||||
|  "sort_field": "modified", | ||||
|  "sort_order": "DESC", | ||||
|  "track_changes": 1 | ||||
| } | ||||
| @ -182,8 +182,8 @@ frappe.ui.form.on('Production Plan', { | ||||
| 	}, | ||||
| 
 | ||||
| 	get_items_for_mr: function(frm) { | ||||
| 		const set_fields = ['actual_qty', 'item_code', | ||||
| 			'item_name', 'min_order_qty', 'quantity', 'sales_order', 'warehouse', 'projected_qty', 'material_request_type']; | ||||
| 		const set_fields = ['actual_qty', 'item_code','item_name', 'description', 'uom',  | ||||
| 			'min_order_qty', 'quantity', 'sales_order', 'warehouse', 'projected_qty', 'material_request_type']; | ||||
| 		frappe.call({ | ||||
| 			method: "erpnext.manufacturing.doctype.production_plan.production_plan.get_items_for_material_requests", | ||||
| 			freeze: true, | ||||
| @ -233,7 +233,7 @@ frappe.ui.form.on('Production Plan', { | ||||
| 
 | ||||
| 		if (item_wise_qty) { | ||||
| 			for (var key in item_wise_qty) { | ||||
| 				title += __('Item {0}: {1} qty produced, ', [key, item_wise_qty[key]]); | ||||
| 				title += __('Item {0}: {1} qty produced. ', [key, item_wise_qty[key]]); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|  | ||||
| @ -99,7 +99,7 @@ class ProductionPlan(Document): | ||||
| 			self.get_mr_items() | ||||
| 
 | ||||
| 	def get_so_items(self): | ||||
| 		so_list = [d.sales_order for d in self.get("sales_orders", []) if d.sales_order] | ||||
| 		so_list = [d.sales_order for d in self.sales_orders if d.sales_order] | ||||
| 		if not so_list: | ||||
| 			msgprint(_("Please enter Sales Orders in the above table")) | ||||
| 			return [] | ||||
| @ -109,7 +109,7 @@ class ProductionPlan(Document): | ||||
| 			item_condition = ' and so_item.item_code = {0}'.format(frappe.db.escape(self.item_code)) | ||||
| 
 | ||||
| 		items = frappe.db.sql("""select distinct parent, item_code, warehouse, | ||||
| 			(qty - work_order_qty) * conversion_factor as pending_qty, name | ||||
| 			(qty - work_order_qty) * conversion_factor as pending_qty, description, name | ||||
| 			from `tabSales Order Item` so_item | ||||
| 			where parent in (%s) and docstatus = 1 and qty > work_order_qty | ||||
| 			and exists (select name from `tabBOM` bom where bom.item=so_item.item_code | ||||
| @ -121,7 +121,7 @@ class ProductionPlan(Document): | ||||
| 
 | ||||
| 		packed_items = frappe.db.sql("""select distinct pi.parent, pi.item_code, pi.warehouse as warehouse, | ||||
| 			(((so_item.qty - so_item.work_order_qty) * pi.qty) / so_item.qty) | ||||
| 				as pending_qty, pi.parent_item, so_item.name | ||||
| 				as pending_qty, pi.parent_item, pi.description, so_item.name | ||||
| 			from `tabSales Order Item` so_item, `tabPacked Item` pi | ||||
| 			where so_item.parent = pi.parent and so_item.docstatus = 1 | ||||
| 			and pi.parent_item = so_item.item_code | ||||
| @ -134,7 +134,7 @@ class ProductionPlan(Document): | ||||
| 		self.calculate_total_planned_qty() | ||||
| 
 | ||||
| 	def get_mr_items(self): | ||||
| 		mr_list = [d.material_request for d in self.get("material_requests", []) if d.material_request] | ||||
| 		mr_list = [d.material_request for d in self.material_requests if d.material_request] | ||||
| 		if not mr_list: | ||||
| 			msgprint(_("Please enter Material Requests in the above table")) | ||||
| 			return [] | ||||
| @ -143,7 +143,7 @@ class ProductionPlan(Document): | ||||
| 		if self.item_code: | ||||
| 			item_condition = " and mr_item.item_code ={0}".format(frappe.db.escape(self.item_code)) | ||||
| 
 | ||||
| 		items = frappe.db.sql("""select distinct parent, name, item_code, warehouse, | ||||
| 		items = frappe.db.sql("""select distinct parent, name, item_code, warehouse, description, | ||||
| 			(qty - ordered_qty) as pending_qty | ||||
| 			from `tabMaterial Request Item` mr_item | ||||
| 			where parent in (%s) and docstatus = 1 and qty > ordered_qty | ||||
| @ -162,7 +162,7 @@ class ProductionPlan(Document): | ||||
| 				'include_exploded_items': 1, | ||||
| 				'warehouse': data.warehouse, | ||||
| 				'item_code': data.item_code, | ||||
| 				'description': item_details and item_details.description or '', | ||||
| 				'description': data.description or item_details.description, | ||||
| 				'stock_uom': item_details and item_details.stock_uom or '', | ||||
| 				'bom_no': item_details and item_details.bom_no or '', | ||||
| 				'planned_qty': data.pending_qty, | ||||
| @ -174,10 +174,12 @@ class ProductionPlan(Document): | ||||
| 			if self.get_items_from == "Sales Order": | ||||
| 				pi.sales_order = data.parent | ||||
| 				pi.sales_order_item = data.name | ||||
| 				pi.description = data.description | ||||
| 
 | ||||
| 			elif self.get_items_from == "Material Request": | ||||
| 				pi.material_request = data.parent | ||||
| 				pi.material_request_item = data.name | ||||
| 				pi.description = data.description | ||||
| 
 | ||||
| 	def calculate_total_planned_qty(self): | ||||
| 		self.total_planned_qty = 0 | ||||
| @ -195,7 +197,6 @@ class ProductionPlan(Document): | ||||
| 		for data in self.po_items: | ||||
| 			if data.name == production_plan_item: | ||||
| 				data.produced_qty = produced_qty | ||||
| 				data.pending_qty = data.planned_qty - data.produced_qty | ||||
| 				data.db_update() | ||||
| 
 | ||||
| 		self.calculate_total_produced_qty() | ||||
| @ -302,6 +303,7 @@ class ProductionPlan(Document): | ||||
| 				wo_list.extend(work_orders) | ||||
| 
 | ||||
| 		frappe.flags.mute_messages = False | ||||
| 
 | ||||
| 		if wo_list: | ||||
| 			wo_list = ["""<a href="#Form/Work Order/%s" target="_blank">%s</a>""" % \ | ||||
| 				(p, p) for p in wo_list] | ||||
| @ -309,16 +311,15 @@ class ProductionPlan(Document): | ||||
| 		else : | ||||
| 			msgprint(_("No Work Orders created")) | ||||
| 
 | ||||
| 
 | ||||
| 	def make_work_order_for_sub_assembly_items(self, item): | ||||
| 		work_orders = [] | ||||
| 		bom_data = {} | ||||
| 
 | ||||
| 		get_sub_assembly_items(item.get("bom_no"), bom_data, item.get("qty")) | ||||
| 		get_sub_assembly_items(item.get("bom_no"), bom_data) | ||||
| 
 | ||||
| 		for key, data in bom_data.items(): | ||||
| 			data.update({ | ||||
| 				'qty': data.get("stock_qty"), | ||||
| 				'qty': data.get("stock_qty") * item.get("qty"), | ||||
| 				'production_plan': self.name, | ||||
| 				'company': self.company, | ||||
| 				'fg_warehouse': item.get("fg_warehouse"), | ||||
| @ -528,6 +529,7 @@ def get_material_request_items(row, sales_order, | ||||
| 		required_qty = ceil(required_qty) | ||||
| 
 | ||||
| 	if required_qty > 0: | ||||
| 		print(row) | ||||
| 		return { | ||||
| 			'item_code': row.item_code, | ||||
| 			'item_name': row.item_name, | ||||
| @ -540,7 +542,9 @@ def get_material_request_items(row, sales_order, | ||||
| 			'projected_qty': bin_dict.get("projected_qty", 0), | ||||
| 			'min_order_qty': row['min_order_qty'], | ||||
| 			'material_request_type': row.get("default_material_request_type"), | ||||
| 			'sales_order': sales_order | ||||
| 			'sales_order': sales_order, | ||||
| 			'description': row.get("description"), | ||||
| 			'uom': row.get("purchase_uom") or row.get("stock_uom") | ||||
| 		} | ||||
| 
 | ||||
| def get_sales_orders(self): | ||||
| @ -558,7 +562,7 @@ def get_sales_orders(self): | ||||
| 		item_filter += " and so_item.item_code = %(item)s" | ||||
| 
 | ||||
| 	open_so = frappe.db.sql(""" | ||||
| 		select distinct so.name, so.transaction_date, so.customer, so.base_grand_total as grand_total | ||||
| 		select distinct so.name, so.transaction_date, so.customer, so.base_grand_total | ||||
| 		from `tabSales Order` so, `tabSales Order Item` so_item | ||||
| 		where so_item.parent = so.name | ||||
| 			and so.docstatus = 1 and so.status not in ("Stopped", "Closed") | ||||
| @ -622,7 +626,7 @@ def get_items_for_material_requests(doc, ignore_existing_ordered_qty=None): | ||||
| 	for data in po_items: | ||||
| 		planned_qty = data.get('required_qty') or data.get('planned_qty') | ||||
| 		ignore_existing_ordered_qty = data.get('ignore_existing_ordered_qty') or ignore_existing_ordered_qty | ||||
| 		warehouse = warehouse or data.get("warehouse") | ||||
| 		warehouse = data.get("warehouse") or warehouse | ||||
| 
 | ||||
| 		item_details = {} | ||||
| 		if data.get("bom") or data.get("bom_no"): | ||||
| @ -705,11 +709,11 @@ def get_item_data(item_code): | ||||
| 
 | ||||
| 	return { | ||||
| 		"bom_no": item_details.get("bom_no"), | ||||
| 		"stock_uom": item_details.get("stock_uom"), | ||||
| 		"description": item_details.get("description") | ||||
| 		"stock_uom": item_details.get("stock_uom") | ||||
| #		"description": item_details.get("description") | ||||
| 	} | ||||
| 
 | ||||
| def get_sub_assembly_items(bom_no, bom_data, qty): | ||||
| def get_sub_assembly_items(bom_no, bom_data): | ||||
| 	data = get_children('BOM', parent = bom_no) | ||||
| 	for d in data: | ||||
| 		if d.expandable: | ||||
| @ -726,6 +730,6 @@ def get_sub_assembly_items(bom_no, bom_data, qty): | ||||
| 				}) | ||||
| 
 | ||||
| 			bom_item = bom_data.get(key) | ||||
| 			bom_item["stock_qty"] += ((d.stock_qty * qty) / d.parent_bom_qty) | ||||
| 			bom_item["stock_qty"] += d.stock_qty | ||||
| 
 | ||||
| 			get_sub_assembly_items(bom_item.get("bom_no"), bom_data, bom_item["stock_qty"]) | ||||
| 			get_sub_assembly_items(bom_item.get("bom_no"), bom_data) | ||||
|  | ||||
| @ -11,11 +11,9 @@ from erpnext.manufacturing.doctype.production_plan.production_plan import get_sa | ||||
| from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation | ||||
| from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order | ||||
| from erpnext.manufacturing.doctype.production_plan.production_plan import get_items_for_material_requests | ||||
| from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory | ||||
| 
 | ||||
| class TestProductionPlan(unittest.TestCase): | ||||
| 	def setUp(self): | ||||
| 		set_perpetual_inventory(0) | ||||
| 		for item in ['Test Production Item 1', 'Subassembly Item 1', | ||||
| 			'Raw Material Item 1', 'Raw Material Item 2']: | ||||
| 			create_item(item, valuation_rate=100) | ||||
|  | ||||
| @ -645,7 +645,8 @@ def make_stock_entry(work_order_id, purpose, qty=None): | ||||
| 		stock_entry.to_warehouse = work_order.fg_warehouse | ||||
| 		stock_entry.project = work_order.project | ||||
| 		if purpose=="Manufacture": | ||||
| 			additional_costs = get_additional_costs(work_order, fg_qty=stock_entry.fg_completed_qty) | ||||
| 			additional_costs = get_additional_costs(work_order, fg_qty=stock_entry.fg_completed_qty, | ||||
| 				company=work_order.company) | ||||
| 			stock_entry.set("additional_costs", additional_costs) | ||||
| 
 | ||||
| 	stock_entry.set_stock_entry_type() | ||||
|  | ||||
| @ -640,4 +640,9 @@ erpnext.patches.v12_0.create_default_energy_point_rules | ||||
| erpnext.patches.v12_0.set_produced_qty_field_in_sales_order_for_work_order | ||||
| erpnext.patches.v12_0.generate_leave_ledger_entries | ||||
| erpnext.patches.v12_0.set_default_shopify_app_type | ||||
| erpnext.patches.v12_0.set_cwip_and_delete_asset_settings | ||||
| erpnext.patches.v12_0.set_expense_account_in_landed_cost_voucher_taxes | ||||
| erpnext.patches.v12_0.replace_accounting_with_accounts_in_home_settings | ||||
| erpnext.patches.v12_0.set_payment_entry_status | ||||
| erpnext.patches.v12_0.update_owner_fields_in_acc_dimension_custom_fields | ||||
| erpnext.patches.v12_0.set_default_for_add_taxes_from_item_tax_template | ||||
| @ -1,27 +1,28 @@ | ||||
| # Copyright (c) 2017, Frappe 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', 'delivery_trip') | ||||
| 	frappe.reload_doc('stock', 'doctype', 'delivery_stop', force=True) | ||||
| 
 | ||||
| 	for trip in frappe.get_all("Delivery Trip"): | ||||
| 		trip_doc = frappe.get_doc("Delivery Trip", trip.name) | ||||
| 
 | ||||
| 		status = { | ||||
| 			0: "Draft", | ||||
| 			1: "Scheduled", | ||||
| 			2: "Cancelled" | ||||
| 		}[trip_doc.docstatus] | ||||
| 
 | ||||
| 		if trip_doc.docstatus == 1: | ||||
| 			visited_stops = [stop.visited for stop in trip_doc.delivery_stops] | ||||
| 			if all(visited_stops): | ||||
| 				status = "Completed" | ||||
| 			elif any(visited_stops): | ||||
| 				status = "In Transit" | ||||
| 
 | ||||
| 		frappe.db.set_value("Delivery Trip", trip.name, "status", status, update_modified=False) | ||||
| # Copyright (c) 2017, Frappe and Contributors | ||||
| # License: GNU General Public License v3. See license.txt | ||||
| 
 | ||||
| from __future__ import unicode_literals | ||||
| import frappe | ||||
| 
 | ||||
| def execute(): | ||||
| 	frappe.reload_doc('setup', 'doctype', 'global_defaults', force=True) | ||||
| 	frappe.reload_doc('stock', 'doctype', 'delivery_trip') | ||||
| 	frappe.reload_doc('stock', 'doctype', 'delivery_stop', force=True) | ||||
| 
 | ||||
| 	for trip in frappe.get_all("Delivery Trip"): | ||||
| 		trip_doc = frappe.get_doc("Delivery Trip", trip.name) | ||||
| 
 | ||||
| 		status = { | ||||
| 			0: "Draft", | ||||
| 			1: "Scheduled", | ||||
| 			2: "Cancelled" | ||||
| 		}[trip_doc.docstatus] | ||||
| 
 | ||||
| 		if trip_doc.docstatus == 1: | ||||
| 			visited_stops = [stop.visited for stop in trip_doc.delivery_stops] | ||||
| 			if all(visited_stops): | ||||
| 				status = "Completed" | ||||
| 			elif any(visited_stops): | ||||
| 				status = "In Transit" | ||||
| 
 | ||||
| 		frappe.db.set_value("Delivery Trip", trip.name, "status", status, update_modified=False) | ||||
|  | ||||
							
								
								
									
										22
									
								
								erpnext/patches/v12_0/set_cwip_and_delete_asset_settings.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								erpnext/patches/v12_0/set_cwip_and_delete_asset_settings.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| from __future__ import unicode_literals | ||||
| import frappe | ||||
| from frappe.utils import cint | ||||
| 
 | ||||
| 
 | ||||
| def execute(): | ||||
| 	'''Get 'Disable CWIP Accounting value' from Asset Settings, set it in 'Enable Capital Work in Progress Accounting' field | ||||
| 	in Company, delete Asset Settings ''' | ||||
| 
 | ||||
| 	if frappe.db.exists("DocType","Asset Settings"): | ||||
| 		frappe.reload_doctype("Company") | ||||
| 		cwip_value = frappe.db.sql(""" SELECT value FROM `tabSingles` WHERE doctype='Asset Settings' | ||||
| 			and field='disable_cwip_accounting' """, as_dict=1) | ||||
| 
 | ||||
| 		companies = [x['name'] for x in frappe.get_all("Company", "name")] | ||||
| 		for company in companies: | ||||
| 			enable_cwip_accounting = cint(not cint(cwip_value[0]['value'])) | ||||
| 			frappe.set_value("Company", company, "enable_cwip_accounting", enable_cwip_accounting) | ||||
| 
 | ||||
| 		frappe.db.sql( | ||||
| 			""" DELETE FROM `tabSingles` where doctype = 'Asset Settings' """) | ||||
| 		frappe.delete_doc_if_exists("DocType","Asset Settings") | ||||
| @ -0,0 +1,5 @@ | ||||
| import frappe | ||||
| 
 | ||||
| def execute(): | ||||
| 	frappe.db.set_value("Accounts Settings", None, "add_taxes_from_item_tax_template", 1) | ||||
| 	frappe.db.set_default("add_taxes_from_item_tax_template", 1) | ||||
| @ -0,0 +1,33 @@ | ||||
| from __future__ import unicode_literals | ||||
| import frappe | ||||
| from six import iteritems | ||||
| 
 | ||||
| def execute(): | ||||
| 	frappe.reload_doctype('Landed Cost Taxes and Charges') | ||||
| 
 | ||||
| 	company_account_map = frappe._dict(frappe.db.sql(""" | ||||
| 		SELECT name, expenses_included_in_valuation from `tabCompany` | ||||
| 	""")) | ||||
| 
 | ||||
| 	for company, account in iteritems(company_account_map): | ||||
| 		frappe.db.sql(""" | ||||
| 			UPDATE | ||||
| 				`tabLanded Cost Taxes and Charges` t, `tabLanded Cost Voucher` l | ||||
| 			SET | ||||
| 				t.expense_account = %s | ||||
| 			WHERE | ||||
| 				l.docstatus = 1 | ||||
| 				AND l.company = %s | ||||
| 				AND t.parent = l.name | ||||
| 		""", (account, company)) | ||||
| 
 | ||||
| 		frappe.db.sql(""" | ||||
| 			UPDATE | ||||
| 				`tabLanded Cost Taxes and Charges` t, `tabStock Entry` s | ||||
| 			SET | ||||
| 				t.expense_account = %s | ||||
| 			WHERE | ||||
| 				s.docstatus = 1 | ||||
| 				AND s.company = %s | ||||
| 				AND t.parent = s.name | ||||
| 		""", (account, company)) | ||||
							
								
								
									
										9
									
								
								erpnext/patches/v12_0/set_payment_entry_status.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								erpnext/patches/v12_0/set_payment_entry_status.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| import frappe | ||||
| 
 | ||||
| def execute(): | ||||
| 	frappe.reload_doctype("Payment Entry") | ||||
| 	frappe.db.sql("""update `tabPayment Entry` set status = CASE | ||||
| 		WHEN docstatus = 1 THEN 'Submitted' | ||||
| 		WHEN docstatus = 2 THEN 'Cancelled' | ||||
| 		ELSE 'Draft' | ||||
| 		END;""") | ||||
| @ -0,0 +1,17 @@ | ||||
| from __future__ import unicode_literals | ||||
| import frappe | ||||
| from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_doctypes_with_dimensions | ||||
| 
 | ||||
| def execute(): | ||||
| 	accounting_dimensions = frappe.db.sql("""select fieldname from | ||||
| 		`tabAccounting Dimension`""", as_dict=1) | ||||
| 
 | ||||
| 	doclist = get_doctypes_with_dimensions() | ||||
| 
 | ||||
| 	for dimension in accounting_dimensions: | ||||
| 		frappe.db.sql(""" | ||||
| 			UPDATE `tabCustom Field` | ||||
| 			SET owner = 'Administrator' | ||||
| 			WHERE fieldname = %s | ||||
| 			AND dt IN (%s)""" %			#nosec | ||||
| 			('%s', ', '.join(['%s']* len(doclist))), tuple([dimension.fieldname] + doclist)) | ||||
| @ -19,7 +19,7 @@ frappe.ui.form.on("Project", { | ||||
| 					frappe.ui.form.make_quick_entry(doctype, null, null, new_doc); | ||||
| 				}); | ||||
| 			}, | ||||
| 		} | ||||
| 		}; | ||||
| 	}, | ||||
| 	onload: function (frm) { | ||||
| 		var so = frappe.meta.get_docfield("Project", "sales_order"); | ||||
| @ -28,15 +28,15 @@ frappe.ui.form.on("Project", { | ||||
| 			return { | ||||
| 				"customer": frm.doc.customer, | ||||
| 				"project_name": frm.doc.name | ||||
| 			} | ||||
| 		} | ||||
| 			}; | ||||
| 		}; | ||||
| 
 | ||||
| 		frm.set_query('customer', 'erpnext.controllers.queries.customer_query'); | ||||
| 
 | ||||
| 		frm.set_query("user", "users", function () { | ||||
| 			return { | ||||
| 				query: "erpnext.projects.doctype.project.project.get_users_for_project" | ||||
| 			} | ||||
| 			}; | ||||
| 		}); | ||||
| 
 | ||||
| 		// sales order
 | ||||
| @ -51,9 +51,36 @@ frappe.ui.form.on("Project", { | ||||
| 
 | ||||
| 			return { | ||||
| 				filters: filters | ||||
| 			} | ||||
| 			}; | ||||
| 		}); | ||||
| 	}, | ||||
| 
 | ||||
| 	refresh: function (frm) { | ||||
| 		if (frm.doc.__islocal) { | ||||
| 			frm.web_link && frm.web_link.remove(); | ||||
| 		} else { | ||||
| 			frm.add_web_link("/projects?project=" + encodeURIComponent(frm.doc.name)); | ||||
| 
 | ||||
| 			frm.trigger('show_dashboard'); | ||||
| 		} | ||||
| 		frm.events.set_buttons(frm); | ||||
| 	}, | ||||
| 
 | ||||
| 	set_buttons: function(frm) { | ||||
| 		if (!frm.is_new()) { | ||||
| 			frm.add_custom_button(__('Duplicate Project with Tasks'), () => { | ||||
| 				frm.events.create_duplicate(frm); | ||||
| 			}); | ||||
| 
 | ||||
| 			frm.add_custom_button(__('Completed'), () => { | ||||
| 				frm.events.set_status(frm, 'Completed'); | ||||
| 			}, __('Set Status')); | ||||
| 
 | ||||
| 			frm.add_custom_button(__('Cancelled'), () => { | ||||
| 				frm.events.set_status(frm, 'Cancelled'); | ||||
| 			}, __('Set Status')); | ||||
| 		} | ||||
| 		 | ||||
| 		if (frappe.model.can_read("Task")) { | ||||
| 			frm.add_custom_button(__("Gantt Chart"), function () { | ||||
| 				frappe.route_options = { | ||||
| @ -72,27 +99,20 @@ frappe.ui.form.on("Project", { | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	refresh: function (frm) { | ||||
| 		if (frm.doc.__islocal) { | ||||
| 			frm.web_link && frm.web_link.remove(); | ||||
| 		} else { | ||||
| 			frm.add_web_link("/projects?project=" + encodeURIComponent(frm.doc.name)); | ||||
| 
 | ||||
| 			frm.trigger('show_dashboard'); | ||||
| 		} | ||||
| 		frm.events.set_buttons(frm); | ||||
| 	}, | ||||
| 
 | ||||
| 	set_buttons: function(frm) { | ||||
| 		if (!frm.is_new()) { | ||||
| 			frm.add_custom_button(__('Completed'), () => { | ||||
| 				frm.events.set_status(frm, 'Completed'); | ||||
| 			}, __('Set Status')); | ||||
| 
 | ||||
| 			frm.add_custom_button(__('Cancelled'), () => { | ||||
| 				frm.events.set_status(frm, 'Cancelled'); | ||||
| 			}, __('Set Status')); | ||||
| 		} | ||||
| 	create_duplicate: function(frm) { | ||||
| 		return new Promise(resolve => { | ||||
| 			frappe.prompt('Project Name', (data) => { | ||||
| 				frappe.xcall('erpnext.projects.doctype.project.project.create_duplicate_project', | ||||
| 					{ | ||||
| 						prev_doc: frm.doc, | ||||
| 						project_name: data.value | ||||
| 					}).then(() => { | ||||
| 					frappe.set_route('Form', "Project", data.value); | ||||
| 					frappe.show_alert(__("Duplicate project has been created")); | ||||
| 				}); | ||||
| 				resolve(); | ||||
| 			}); | ||||
| 		}); | ||||
| 	}, | ||||
| 
 | ||||
| 	set_status: function(frm, status) { | ||||
|  | ||||
| @ -323,6 +323,37 @@ def allow_to_make_project_update(project, time, frequency): | ||||
| 	if get_time(nowtime()) >= get_time(time): | ||||
| 		return True | ||||
| 
 | ||||
| 
 | ||||
| @frappe.whitelist() | ||||
| def create_duplicate_project(prev_doc, project_name): | ||||
| 	''' Create duplicate project based on the old project ''' | ||||
| 	import json | ||||
| 	prev_doc = json.loads(prev_doc) | ||||
| 
 | ||||
| 	if project_name == prev_doc.get('name'): | ||||
| 		frappe.throw(_("Use a name that is different from previous project name")) | ||||
| 
 | ||||
| 	# change the copied doc name to new project name | ||||
| 	project = frappe.copy_doc(prev_doc) | ||||
| 	project.name = project_name | ||||
| 	project.project_template = '' | ||||
| 	project.project_name = project_name | ||||
| 	project.insert() | ||||
| 
 | ||||
| 	# fetch all the task linked with the old project | ||||
| 	task_list = frappe.get_all("Task", filters={ | ||||
| 		'project': prev_doc.get('name') | ||||
| 	}, fields=['name']) | ||||
| 
 | ||||
| 	# Create duplicate task for all the task | ||||
| 	for task in task_list: | ||||
| 		task = frappe.get_doc('Task', task) | ||||
| 		new_task = frappe.copy_doc(task) | ||||
| 		new_task.project = project.name | ||||
| 		new_task.insert() | ||||
| 
 | ||||
| 	project.db_set('project_template', prev_doc.get('project_template')) | ||||
| 
 | ||||
| def get_projects_for_collect_progress(frequency, fields): | ||||
| 	fields.extend(["name"]) | ||||
| 
 | ||||
|  | ||||
| @ -188,6 +188,8 @@ class Timesheet(Document): | ||||
| 			}, as_dict=True) | ||||
| 		# check internal overlap | ||||
| 		for time_log in self.time_logs: | ||||
| 			if not (time_log.from_time or time_log.to_time): continue | ||||
| 
 | ||||
| 			if (fieldname != 'workstation' or args.get(fieldname) == time_log.get(fieldname)) and \ | ||||
| 				args.idx != time_log.idx and ((args.from_time > time_log.from_time and args.from_time < time_log.to_time) or | ||||
| 				(args.to_time > time_log.from_time and args.to_time < time_log.to_time) or | ||||
|  | ||||
| @ -63,12 +63,15 @@ $.extend(erpnext, { | ||||
| 			let callback = ''; | ||||
| 			let on_close = ''; | ||||
| 
 | ||||
| 			if (grid_row.doc.serial_no) { | ||||
| 				grid_row.doc.has_serial_no = true; | ||||
| 			} | ||||
| 
 | ||||
| 			me.show_serial_batch_selector(grid_row.frm, grid_row.doc, | ||||
| 				callback, on_close, true); | ||||
| 			frappe.model.get_value('Item', {'name':grid_row.doc.item_code}, 'has_serial_no', | ||||
| 				(data) => { | ||||
| 					if(data) { | ||||
| 						grid_row.doc.has_serial_no = data.has_serial_no; | ||||
| 						me.show_serial_batch_selector(grid_row.frm, grid_row.doc, | ||||
| 							callback, on_close, true); | ||||
| 					} | ||||
| 				} | ||||
| 			); | ||||
| 		}); | ||||
| 	}, | ||||
| }); | ||||
|  | ||||
| @ -10,3 +10,21 @@ def check_deletion_permission(doc, method): | ||||
| 	region = get_region(doc.company) | ||||
| 	if region in ["Nepal", "France"] and doc.docstatus != 0: | ||||
| 		frappe.throw(_("Deletion is not permitted for country {0}".format(region))) | ||||
| 
 | ||||
| def create_transaction_log(doc, method): | ||||
| 	""" | ||||
| 	Appends the transaction to a chain of hashed logs for legal resons. | ||||
| 	Called on submit of Sales Invoice and Payment Entry. | ||||
| 	""" | ||||
| 	region = get_region() | ||||
| 	if region not in ["France", "Germany"]: | ||||
| 		return | ||||
| 
 | ||||
| 	data = str(doc.as_dict()) | ||||
| 
 | ||||
| 	frappe.get_doc({ | ||||
| 		"doctype": "Transaction Log", | ||||
| 		"reference_doctype": doc.doctype, | ||||
| 		"document_name": doc.name, | ||||
| 		"data": data | ||||
| 	}).insert(ignore_permissions=True) | ||||
|  | ||||
| @ -3,22 +3,6 @@ | ||||
| 
 | ||||
| from __future__ import unicode_literals | ||||
| import frappe | ||||
| from frappe import _ | ||||
| from erpnext import get_region | ||||
| 
 | ||||
| def create_transaction_log(doc, method): | ||||
| 	region = get_region() | ||||
| 	if region not in ["France"]: | ||||
| 		return | ||||
| 	else: | ||||
| 		data = str(doc.as_dict()) | ||||
| 
 | ||||
| 		frappe.get_doc({ | ||||
| 			"doctype": "Transaction Log", | ||||
| 			"reference_doctype": doc.doctype, | ||||
| 			"document_name": doc.name, | ||||
| 			"data": data | ||||
| 		}).insert(ignore_permissions=True) | ||||
| 
 | ||||
| # don't remove this function it is used in tests | ||||
| def test_method(): | ||||
|  | ||||
| @ -72,8 +72,8 @@ def validate_gstin_check_digit(gstin, label='GSTIN'): | ||||
| 		total += digit | ||||
| 		factor = 2 if factor == 1 else 1 | ||||
| 	if gstin[-1] != code_point_chars[((mod - (total % mod)) % mod)]: | ||||
| 		frappe.throw(_("Invalid {0}! The check digit validation has failed. " + | ||||
| 			"Please ensure you've typed the {0} correctly.".format(label))) | ||||
| 		frappe.throw(_("""Invalid {0}! The check digit validation has failed. | ||||
| 			Please ensure you've typed the {0} correctly.""".format(label))) | ||||
| 
 | ||||
| def get_itemised_tax_breakup_header(item_doctype, tax_accounts): | ||||
| 	if frappe.get_meta(item_doctype).has_field('gst_hsn_code'): | ||||
|  | ||||
| @ -116,7 +116,7 @@ class Gstr1Report(object): | ||||
| 		taxable_value = 0 | ||||
| 		for item_code, net_amount in self.invoice_items.get(invoice).items(): | ||||
| 				if item_code in items: | ||||
| 					if self.item_tax_rate.get(invoice) and tax_rate in self.item_tax_rate.get(invoice, {}).get(item_code): | ||||
| 					if self.item_tax_rate.get(invoice) and tax_rate in self.item_tax_rate.get(invoice, {}).get(item_code, []): | ||||
| 						taxable_value += abs(net_amount) | ||||
| 					elif not self.item_tax_rate.get(invoice): | ||||
| 						taxable_value += abs(net_amount) | ||||
|  | ||||
| @ -150,7 +150,7 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( | ||||
| 
 | ||||
| 					// delivery note
 | ||||
| 					if(flt(doc.per_delivered, 6) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1 && allow_delivery) { | ||||
| 						this.frm.add_custom_button(__('Delivery'), () => this.make_delivery_note_based_on_delivery_date(), __('Create')); | ||||
| 						this.frm.add_custom_button(__('Delivery Note'), () => this.make_delivery_note_based_on_delivery_date(), __('Create')); | ||||
| 						this.frm.add_custom_button(__('Work Order'), () => this.make_work_order(), __('Create')); | ||||
| 					} | ||||
| 
 | ||||
|  | ||||
| @ -0,0 +1,33 @@ | ||||
| // Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
 | ||||
| // For license information, please see license.txt
 | ||||
| /* eslint-disable */ | ||||
| 
 | ||||
| frappe.query_reports["Item-wise Sales History"] = { | ||||
| 	"filters": [ | ||||
| 		{ | ||||
| 			fieldname:"company", | ||||
| 			label: __("Company"), | ||||
| 			fieldtype: "Link", | ||||
| 			options: "Company", | ||||
| 			default: frappe.defaults.get_user_default("Company"), | ||||
| 			reqd: 1 | ||||
| 		}, | ||||
| 		{ | ||||
| 			fieldname:"item_group", | ||||
| 			label: __("Item Group"), | ||||
| 			fieldtype: "Link", | ||||
| 			options: "Item Group" | ||||
| 		}, | ||||
| 		{ | ||||
| 			fieldname:"from_date", | ||||
| 			label: __("From Date"), | ||||
| 			fieldtype: "Date", | ||||
| 		}, | ||||
| 		{ | ||||
| 			fieldname:"to_date", | ||||
| 			label: __("To Date"), | ||||
| 			fieldtype: "Date", | ||||
| 		}, | ||||
| 
 | ||||
| 	] | ||||
| }; | ||||
| @ -1,34 +1,34 @@ | ||||
| { | ||||
|  "add_total_row": 1,  | ||||
|  "creation": "2013-05-23 17:42:24",  | ||||
|  "disabled": 0,  | ||||
|  "docstatus": 0,  | ||||
|  "doctype": "Report",  | ||||
|  "idx": 3,  | ||||
|  "is_standard": "Yes",  | ||||
|  "modified": "2019-01-03 22:52:41.519890",  | ||||
|  "modified_by": "Administrator",  | ||||
|  "module": "Selling",  | ||||
|  "name": "Item-wise Sales History",  | ||||
|  "owner": "Administrator",  | ||||
|  "prepared_report": 0,  | ||||
|  "query": "select\n    so_item.item_code as \"Item Code:Link/Item:120\",\n\tso_item.item_name as \"Item Name::120\",\n        so_item.item_group as \"Item Group:Link/Item Group:120\",\n\tso_item.description as \"Description::150\",\n\tso_item.qty as \"Qty:Data:100\",\n\tso_item.uom as \"UOM:Link/UOM:80\",\n\tso_item.base_rate as \"Rate:Currency:120\",\n\tso_item.base_amount as \"Amount:Currency:120\",\n\tso.name as \"Sales Order:Link/Sales Order:120\",\n\tso.transaction_date as \"Transaction Date:Date:140\",\n\tso.customer as \"Customer:Link/Customer:130\",\n        cu.customer_name as \"Customer Name::150\",\n\tcu.customer_group as \"Customer Group:Link/Customer Group:130\",\n\tso.territory as \"Territory:Link/Territory:130\",\n    \tso.project as \"Project:Link/Project:130\",\n\tifnull(so_item.delivered_qty, 0) as \"Delivered Qty:Float:120\",\n\tifnull(so_item.billed_amt, 0) as \"Billed Amount:Currency:120\",\n\tso.company as \"Company:Link/Company:\"\nfrom\n\t`tabSales Order` so, `tabSales Order Item` so_item, `tabCustomer` cu\nwhere\n\tso.name = so_item.parent and so.customer=cu.name\n\tand so.docstatus = 1\norder by so.name desc",  | ||||
|  "ref_doctype": "Sales Order",  | ||||
|  "report_name": "Item-wise Sales History",  | ||||
|  "report_type": "Query Report",  | ||||
|  "add_total_row": 1, | ||||
|  "creation": "2013-05-23 17:42:24", | ||||
|  "disable_prepared_report": 0, | ||||
|  "disabled": 0, | ||||
|  "docstatus": 0, | ||||
|  "doctype": "Report", | ||||
|  "idx": 3, | ||||
|  "is_standard": "Yes", | ||||
|  "modified": "2019-11-04 16:28:14.608904", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Selling", | ||||
|  "name": "Item-wise Sales History", | ||||
|  "owner": "Administrator", | ||||
|  "prepared_report": 0, | ||||
|  "ref_doctype": "Sales Order", | ||||
|  "report_name": "Item-wise Sales History", | ||||
|  "report_type": "Script Report", | ||||
|  "roles": [ | ||||
|   { | ||||
|    "role": "Sales User" | ||||
|   },  | ||||
|   }, | ||||
|   { | ||||
|    "role": "Sales Manager" | ||||
|   },  | ||||
|   }, | ||||
|   { | ||||
|    "role": "Maintenance User" | ||||
|   },  | ||||
|   }, | ||||
|   { | ||||
|    "role": "Accounts User" | ||||
|   },  | ||||
|   }, | ||||
|   { | ||||
|    "role": "Stock User" | ||||
|   } | ||||
|  | ||||
| @ -0,0 +1,214 @@ | ||||
| # Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors | ||||
| # For license information, please see license.txt | ||||
| 
 | ||||
| from __future__ import unicode_literals | ||||
| import frappe | ||||
| from frappe import _ | ||||
| from frappe.utils import flt | ||||
| from frappe.utils.nestedset import get_descendants_of | ||||
| 
 | ||||
| def execute(filters=None): | ||||
| 	filters = frappe._dict(filters or {}) | ||||
| 	columns = get_columns(filters) | ||||
| 	data = get_data(filters) | ||||
| 	return columns, data | ||||
| 
 | ||||
| def get_columns(filters): | ||||
| 	return [ | ||||
| 		{ | ||||
| 			"label": _("Item Code"), | ||||
| 			"fieldtype": "Link", | ||||
| 			"fieldname": "item_code", | ||||
| 			"options": "Item", | ||||
| 			"width": 120 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"label": _("Item Name"), | ||||
| 			"fieldtype": "Data", | ||||
| 			"fieldname": "item_name", | ||||
| 			"width": 140 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"label": _("Item Group"), | ||||
| 			"fieldtype": "Link", | ||||
| 			"fieldname": "item_group", | ||||
| 			"options": "Item Group", | ||||
| 			"width": 120 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"label": _("Description"), | ||||
| 			"fieldtype": "Data", | ||||
| 			"fieldname": "description", | ||||
| 			"width": 150 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"label": _("Quantity"), | ||||
| 			"fieldtype": "Float", | ||||
| 			"fieldname": "quantity", | ||||
| 			"width": 150 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"label": _("UOM"), | ||||
| 			"fieldtype": "Link", | ||||
| 			"fieldname": "uom", | ||||
| 			"options": "UOM", | ||||
| 			"width": 100 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"label": _("Rate"), | ||||
| 			"fieldname": "rate", | ||||
| 			"options": "Currency", | ||||
| 			"width": 120 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"label": _("Amount"), | ||||
| 			"fieldname": "amount", | ||||
| 			"options": "Currency", | ||||
| 			"width": 120 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"label": _("Sales Order"), | ||||
| 			"fieldtype": "Link", | ||||
| 			"fieldname": "sales_order", | ||||
| 			"options": "Sales Order", | ||||
| 			"width": 100 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"label": _("Transaction Date"), | ||||
| 			"fieldtype": "Date", | ||||
| 			"fieldname": "transaction_date", | ||||
| 			"width": 90 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"label": _("Customer"), | ||||
| 			"fieldtype": "Link", | ||||
| 			"fieldname": "customer", | ||||
| 			"options": "Customer", | ||||
| 			"width": 100 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"label": _("Customer Name"), | ||||
| 			"fieldtype": "Data", | ||||
| 			"fieldname": "customer_name", | ||||
| 			"width": 140 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"label": _("Customer Group"), | ||||
| 			"fieldtype": "Link", | ||||
| 			"fieldname": "customer_group", | ||||
| 			"options": "customer Group", | ||||
| 			"width": 120 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"label": _("Territory"), | ||||
| 			"fieldtype": "Link", | ||||
| 			"fieldname": "territory", | ||||
| 			"options": "Territory", | ||||
| 			"width": 100 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"label": _("Project"), | ||||
| 			"fieldtype": "Link", | ||||
| 			"fieldname": "project", | ||||
| 			"options": "Project", | ||||
| 			"width": 100 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"label": _("Delivered Quantity"), | ||||
| 			"fieldtype": "Float", | ||||
| 			"fieldname": "delivered_quantity", | ||||
| 			"width": 150 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"label": _("Billed Amount"), | ||||
| 			"fieldname": "rate", | ||||
| 			"options": "billed_amount", | ||||
| 			"width": 120 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"label": _("Company"), | ||||
| 			"fieldtype": "Link", | ||||
| 			"fieldname": "company", | ||||
| 			"options": "Company", | ||||
| 			"width": 100 | ||||
| 		} | ||||
| 	] | ||||
| 
 | ||||
| def get_data(filters): | ||||
| 
 | ||||
| 	data = [] | ||||
| 
 | ||||
| 	company_list = get_descendants_of("Company", filters.get("company")) | ||||
| 	company_list.append(filters.get("company")) | ||||
| 
 | ||||
| 	customer_details = get_customer_details() | ||||
| 	sales_order_records = get_sales_order_details(company_list, filters) | ||||
| 
 | ||||
| 	for record in sales_order_records: | ||||
| 		customer_record = customer_details.get(record.customer) | ||||
| 		row = { | ||||
| 			"item_code": record.item_code, | ||||
| 			"item_name": record.item_name, | ||||
| 			"item_group": record.item_group, | ||||
| 			"description": record.description, | ||||
| 			"quantity": record.qty, | ||||
| 			"uom": record.uom, | ||||
| 			"rate": record.base_rate, | ||||
| 			"amount": record.base_amount, | ||||
| 			"sales_order": record.name, | ||||
| 			"transaction_date": record.transaction_date, | ||||
| 			"customer": record.customer, | ||||
| 			"customer_name": customer_record.customer_name, | ||||
| 			"customer_group": customer_record.customer_group, | ||||
| 			"territory": record.territory, | ||||
| 			"project": record.project, | ||||
| 			"delivered_quantity": flt(record.delivered_qty), | ||||
| 			"billed_amount": flt(record.billed_amt), | ||||
| 			"company": record.company | ||||
| 		} | ||||
| 		data.append(row) | ||||
| 
 | ||||
| 	return data | ||||
| 
 | ||||
| def get_conditions(filters): | ||||
| 	conditions = '' | ||||
| 	if filters.get('item_group'): | ||||
| 		conditions += "AND so_item.item_group = %s" %frappe.db.escape(filters.item_group) | ||||
| 
 | ||||
| 	if filters.get('from_date'): | ||||
| 		conditions += "AND so.transaction_date >= '%s'" %filters.from_date | ||||
| 
 | ||||
| 	if filters.get('to_date'): | ||||
| 		conditions += "AND so.transaction_date <= '%s'" %filters.to_date | ||||
| 
 | ||||
| 	return conditions | ||||
| 
 | ||||
| def get_customer_details(): | ||||
| 	details = frappe.get_all('Customer', | ||||
| 		fields=['name', 'customer_name', "customer_group"]) | ||||
| 	customer_details = {} | ||||
| 	for d in details: | ||||
| 		customer_details.setdefault(d.name, frappe._dict({ | ||||
| 			"customer_name": d.customer_name, | ||||
| 			"customer_group": d.customer_group | ||||
| 		})) | ||||
| 	return customer_details | ||||
| 
 | ||||
| def get_sales_order_details(company_list, filters): | ||||
| 	conditions = get_conditions(filters) | ||||
| 	return frappe.db.sql(""" | ||||
| 		SELECT | ||||
| 			so_item.item_code, so_item.item_name, so_item.item_group, | ||||
| 			so_item.description, so_item.qty, so_item.uom, | ||||
| 			so_item.base_rate, so_item.base_amount, so.name, | ||||
| 			so.transaction_date, so.customer, so.territory, | ||||
| 			so.project, so_item.delivered_qty, | ||||
| 			so_item.billed_amt, so.company | ||||
| 		FROM | ||||
| 			`tabSales Order` so, `tabSales Order Item` so_item | ||||
| 		WHERE | ||||
| 			so.name = so_item.parent | ||||
| 			AND so.company in (%s) | ||||
| 			AND so.docstatus = 1 | ||||
| 			{0} | ||||
| 	""".format(conditions), company_list, as_dict=1) #nosec | ||||
| @ -72,6 +72,7 @@ | ||||
|   "stock_received_but_not_billed", | ||||
|   "expenses_included_in_valuation", | ||||
|   "fixed_asset_depreciation_settings", | ||||
|   "enable_cwip_accounting", | ||||
|   "accumulated_depreciation_account", | ||||
|   "depreciation_expense_account", | ||||
|   "series_for_depreciation_entry", | ||||
| @ -720,12 +721,18 @@ | ||||
|    "fieldtype": "Link", | ||||
|    "label": "Default Buying Terms", | ||||
|    "options": "Terms and Conditions" | ||||
|   }, | ||||
|   { | ||||
|    "default": "0", | ||||
|    "fieldname": "enable_cwip_accounting", | ||||
|    "fieldtype": "Check", | ||||
|    "label": "Enable Capital Work in Progress Accounting" | ||||
|   } | ||||
|  ], | ||||
|  "icon": "fa fa-building", | ||||
|  "idx": 1, | ||||
|  "image_field": "company_logo", | ||||
|  "modified": "2019-07-04 22:20:45.104307", | ||||
|  "modified": "2019-10-09 14:42:04.440974", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Setup", | ||||
|  "name": "Company", | ||||
| @ -767,6 +774,18 @@ | ||||
|   { | ||||
|    "read": 1, | ||||
|    "role": "Projects User" | ||||
|   }, | ||||
|   { | ||||
|    "create": 1, | ||||
|    "delete": 1, | ||||
|    "email": 1, | ||||
|    "export": 1, | ||||
|    "print": 1, | ||||
|    "read": 1, | ||||
|    "report": 1, | ||||
|    "role": "Accounts Manager", | ||||
|    "share": 1, | ||||
|    "write": 1 | ||||
|   } | ||||
|  ], | ||||
|  "show_name_in_global_search": 1, | ||||
|  | ||||
| @ -207,7 +207,7 @@ class Company(NestedSet): | ||||
| 				"default_expense_account": "Cost of Goods Sold" | ||||
| 			}) | ||||
| 
 | ||||
| 		if self.update_default_account or frappe.flags.in_test: | ||||
| 		if self.update_default_account: | ||||
| 			for default_account in default_accounts: | ||||
| 				self._set_default_account(default_account, default_accounts.get(default_account)) | ||||
| 
 | ||||
|  | ||||
| @ -11,10 +11,15 @@ from frappe.utils import get_datetime_str, formatdate, nowdate, cint | ||||
| 
 | ||||
| class CurrencyExchange(Document): | ||||
| 	def autoname(self): | ||||
| 		purpose = "" | ||||
| 		if not self.date: | ||||
| 			self.date = nowdate() | ||||
| 		self.name = '{0}-{1}-{2}'.format(formatdate(get_datetime_str(self.date), "yyyy-MM-dd"), | ||||
| 			self.from_currency, self.to_currency) | ||||
| 		if cint(self.for_buying)==0 and cint(self.for_selling)==1: | ||||
| 			purpose = "Selling" | ||||
| 		if cint(self.for_buying)==1 and cint(self.for_selling)==0: | ||||
| 			purpose = "Buying" | ||||
| 		self.name = '{0}-{1}-{2}{3}'.format(formatdate(get_datetime_str(self.date), "yyyy-MM-dd"), | ||||
| 			self.from_currency, self.to_currency, ("-" + purpose) if purpose else "") | ||||
| 
 | ||||
| 	def validate(self): | ||||
| 		self.validate_value("exchange_rate", ">", 0) | ||||
| @ -23,4 +28,4 @@ class CurrencyExchange(Document): | ||||
| 			throw(_("From Currency and To Currency cannot be same")) | ||||
| 
 | ||||
| 		if not cint(self.for_buying) and not cint(self.for_selling): | ||||
| 			throw(_("Currency Exchange must be applicable for Buying or for Selling.")) | ||||
| 			throw(_("Currency Exchange must be applicable for Buying or for Selling.")) | ||||
|  | ||||
| @ -4,15 +4,21 @@ from __future__ import unicode_literals | ||||
| import frappe, unittest | ||||
| from frappe.utils import flt | ||||
| from erpnext.setup.utils import get_exchange_rate | ||||
| from frappe.utils import cint | ||||
| 
 | ||||
| test_records = frappe.get_test_records('Currency Exchange') | ||||
| 
 | ||||
| 
 | ||||
| def save_new_records(test_records): | ||||
| 	for record in test_records: | ||||
| 		purpose = str("") | ||||
| 		if cint(record.get("for_buying"))==0 and cint(record.get("for_selling"))==1: | ||||
| 			purpose = "Selling" | ||||
| 		if cint(record.get("for_buying"))==1 and cint(record.get("for_selling"))==0: | ||||
| 			purpose = "Buying" | ||||
| 		kwargs = dict( | ||||
| 			doctype=record.get("doctype"), | ||||
| 			docname=record.get("date") + '-' + record.get("from_currency") + '-' + record.get("to_currency"), | ||||
| 			docname=record.get("date") + '-' + record.get("from_currency") + '-' + record.get("to_currency") + '-' + purpose, | ||||
| 			fieldname="exchange_rate", | ||||
| 			value=record.get("exchange_rate"), | ||||
| 		) | ||||
| @ -25,6 +31,8 @@ def save_new_records(test_records): | ||||
| 			curr_exchange.from_currency = record["from_currency"] | ||||
| 			curr_exchange.to_currency = record["to_currency"] | ||||
| 			curr_exchange.exchange_rate = record["exchange_rate"] | ||||
| 			curr_exchange.for_buying = record["for_buying"] | ||||
| 			curr_exchange.for_selling = record["for_selling"] | ||||
| 			curr_exchange.insert() | ||||
| 
 | ||||
| 
 | ||||
| @ -44,18 +52,18 @@ class TestCurrencyExchange(unittest.TestCase): | ||||
| 		frappe.db.set_value("Accounts Settings", None, "allow_stale", 1) | ||||
| 
 | ||||
| 		# Start with allow_stale is True | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-01") | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-01", "for_buying") | ||||
| 		self.assertEqual(flt(exchange_rate, 3), 60.0) | ||||
| 
 | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-15") | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-15", "for_buying") | ||||
| 		self.assertEqual(exchange_rate, 65.1) | ||||
| 
 | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-30") | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-30", "for_selling") | ||||
| 		self.assertEqual(exchange_rate, 62.9) | ||||
| 		 | ||||
| 		# Exchange rate as on 15th Dec, 2015, should be fetched from fixer.io | ||||
| 		self.clear_cache() | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2015-12-15") | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2015-12-15", "for_selling") | ||||
| 		self.assertFalse(exchange_rate == 60) | ||||
| 		self.assertEqual(flt(exchange_rate, 3), 66.894) | ||||
| 
 | ||||
| @ -64,35 +72,35 @@ class TestCurrencyExchange(unittest.TestCase): | ||||
| 		frappe.db.set_value("Accounts Settings", None, "allow_stale", 0) | ||||
| 		frappe.db.set_value("Accounts Settings", None, "stale_days", 1) | ||||
| 
 | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-01") | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-01", "for_buying") | ||||
| 		self.assertEqual(exchange_rate, 60.0) | ||||
| 
 | ||||
| 		# Will fetch from fixer.io | ||||
| 		self.clear_cache() | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-15") | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-15", "for_buying") | ||||
| 		self.assertEqual(flt(exchange_rate, 3), 67.79) | ||||
| 
 | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-30") | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-30", "for_selling") | ||||
| 		self.assertEqual(exchange_rate, 62.9) | ||||
| 
 | ||||
| 		# Exchange rate as on 15th Dec, 2015, should be fetched from fixer.io | ||||
| 		self.clear_cache() | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2015-12-15") | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2015-12-15", "for_buying") | ||||
| 		self.assertEqual(flt(exchange_rate, 3), 66.894) | ||||
| 
 | ||||
| 		exchange_rate = get_exchange_rate("INR", "NGN", "2016-01-10") | ||||
| 		exchange_rate = get_exchange_rate("INR", "NGN", "2016-01-10", "for_selling") | ||||
| 		self.assertEqual(exchange_rate, 65.1) | ||||
| 
 | ||||
| 		# NGN is not available on fixer.io so these should return 0 | ||||
| 		exchange_rate = get_exchange_rate("INR", "NGN", "2016-01-09") | ||||
| 		exchange_rate = get_exchange_rate("INR", "NGN", "2016-01-09", "for_selling") | ||||
| 		self.assertEqual(exchange_rate, 0) | ||||
| 
 | ||||
| 		exchange_rate = get_exchange_rate("INR", "NGN", "2016-01-11") | ||||
| 		exchange_rate = get_exchange_rate("INR", "NGN", "2016-01-11", "for_selling") | ||||
| 		self.assertEqual(exchange_rate, 0) | ||||
| 
 | ||||
| 	def test_exchange_rate_strict_switched(self): | ||||
| 		# Start with allow_stale is True | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-15") | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-15", "for_buying") | ||||
| 		self.assertEqual(exchange_rate, 65.1) | ||||
| 
 | ||||
| 		frappe.db.set_value("Accounts Settings", None, "allow_stale", 0) | ||||
| @ -100,5 +108,5 @@ class TestCurrencyExchange(unittest.TestCase): | ||||
| 
 | ||||
| 		# Will fetch from fixer.io | ||||
| 		self.clear_cache() | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-15") | ||||
| 		self.assertEqual(flt(exchange_rate, 3), 67.79) | ||||
| 		exchange_rate = get_exchange_rate("USD", "INR", "2016-01-15", "for_buying") | ||||
| 		self.assertEqual(flt(exchange_rate, 3), 67.79) | ||||
|  | ||||
| @ -1,44 +1,56 @@ | ||||
| [ | ||||
|  { | ||||
|   "doctype": "Currency Exchange",  | ||||
|   "date": "2016-01-01", | ||||
|   "exchange_rate": 60.0,  | ||||
|   "from_currency": "USD",  | ||||
|   "to_currency": "INR" | ||||
|  },  | ||||
|  { | ||||
|   "doctype": "Currency Exchange",  | ||||
|   "date": "2016-01-01", | ||||
|   "exchange_rate": 0.773,  | ||||
|   "from_currency": "USD",  | ||||
|   "to_currency": "EUR" | ||||
|  },  | ||||
|  { | ||||
|   "doctype": "Currency Exchange",  | ||||
|   "date": "2016-01-01", | ||||
|   "exchange_rate": 0.0167,  | ||||
|   "from_currency": "INR",  | ||||
|   "to_currency": "USD" | ||||
|  }, | ||||
|  { | ||||
|   "doctype": "Currency Exchange", | ||||
|   "date": "2016-01-10", | ||||
|   "exchange_rate": 65.1, | ||||
|   "from_currency": "USD", | ||||
|   "to_currency": "INR" | ||||
|  }, | ||||
| 	{ | ||||
| 		"doctype": "Currency Exchange", | ||||
| 		"date": "2016-01-01", | ||||
| 		"exchange_rate": 60.0, | ||||
| 		"from_currency": "USD", | ||||
| 		"to_currency": "INR", | ||||
| 		"for_buying": 1, | ||||
| 		"for_selling": 0 | ||||
|   }, | ||||
|   { | ||||
|   "doctype": "Currency Exchange", | ||||
|   "date": "2016-01-30", | ||||
|   "exchange_rate": 62.9, | ||||
|   "from_currency": "USD", | ||||
|   "to_currency": "INR" | ||||
|  }, | ||||
|  { | ||||
|   "doctype": "Currency Exchange", | ||||
|   "date": "2016-01-10", | ||||
|   "exchange_rate": 65.1, | ||||
|   "from_currency": "INR", | ||||
|   "to_currency": "NGN" | ||||
|  } | ||||
| ] | ||||
| 		"doctype": "Currency Exchange", | ||||
| 		"date": "2016-01-01", | ||||
| 		"exchange_rate": 0.773, | ||||
| 		"from_currency": "USD", | ||||
| 		"to_currency": "EUR", | ||||
| 		"for_buying": 0, | ||||
| 		"for_selling": 1 | ||||
|   }, | ||||
|   { | ||||
| 		"doctype": "Currency Exchange", | ||||
| 		"date": "2016-01-01", | ||||
| 		"exchange_rate": 0.0167, | ||||
| 		"from_currency": "INR", | ||||
| 		"to_currency": "USD", | ||||
| 		"for_buying": 1, | ||||
| 		"for_selling": 0 | ||||
|   }, | ||||
|   { | ||||
|     "doctype": "Currency Exchange", | ||||
| 		"date": "2016-01-10", | ||||
| 		"exchange_rate": 65.1, | ||||
| 		"from_currency": "USD", | ||||
| 		"to_currency": "INR", | ||||
| 		"for_buying": 1, | ||||
| 		"for_selling": 0 | ||||
|   }, | ||||
|   { | ||||
| 		"doctype": "Currency Exchange", | ||||
| 		"date": "2016-01-30", | ||||
| 		"exchange_rate": 62.9, | ||||
| 		"from_currency": "USD", | ||||
| 		"to_currency": "INR", | ||||
| 		"for_buying": 1, | ||||
| 		"for_selling": 1 | ||||
|   }, | ||||
|   { | ||||
| 		"doctype": "Currency Exchange", | ||||
| 		"date": "2016-01-10", | ||||
| 		"exchange_rate": 65.1, | ||||
| 		"from_currency": "INR", | ||||
| 		"to_currency": "NGN", | ||||
| 		"for_buying": 1, | ||||
| 		"for_selling": 1 | ||||
|   } | ||||
| ] | ||||
|  | ||||
| @ -4,8 +4,8 @@ | ||||
| from __future__ import unicode_literals | ||||
| import frappe | ||||
| from frappe import _ | ||||
| from frappe.utils import fmt_money, formatdate, format_time, now_datetime, \ | ||||
| 	get_url_to_form, get_url_to_list, flt, get_link_to_report | ||||
| from frappe.utils import (fmt_money, formatdate, format_time, now_datetime, | ||||
| 	get_url_to_form, get_url_to_list, flt, get_link_to_report, add_to_date, today) | ||||
| from datetime import timedelta | ||||
| from dateutil.relativedelta import relativedelta | ||||
| from frappe.core.doctype.user.user import STANDARD_USERS | ||||
| @ -151,8 +151,9 @@ class EmailDigest(Document): | ||||
| 	def get_calendar_events(self): | ||||
| 		"""Get calendar events for given user""" | ||||
| 		from frappe.desk.doctype.event.event import get_events | ||||
| 		events = get_events(self.future_from_date.strftime("%Y-%m-%d"), | ||||
| 			self.future_to_date.strftime("%Y-%m-%d")) or [] | ||||
| 		from_date, to_date = get_future_date_for_calendaer_event(self.frequency) | ||||
| 
 | ||||
| 		events = get_events(from_date, to_date) | ||||
| 
 | ||||
| 		event_count = 0 | ||||
| 		for i, e in enumerate(events): | ||||
| @ -825,4 +826,14 @@ def get_count_for_period(account, fieldname, from_date, to_date): | ||||
| 		last_year_closing_count = get_count_on(account, fieldname, fy_start_date - timedelta(days=1)) | ||||
| 		count = count_on_to_date + (last_year_closing_count - count_before_from_date) | ||||
| 
 | ||||
| 	return count | ||||
| 	return count | ||||
| 
 | ||||
| def get_future_date_for_calendaer_event(frequency): | ||||
| 	from_date = to_date = today() | ||||
| 
 | ||||
| 	if frequency == "Weekly": | ||||
| 		to_date = add_to_date(from_date, weeks=1) | ||||
| 	elif frequency == "Monthly": | ||||
| 		to_date = add_to_date(from_date, months=1) | ||||
| 
 | ||||
| 	return from_date, to_date | ||||
| @ -11,6 +11,7 @@ from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings | ||||
| from frappe.utils.nestedset import get_root_of | ||||
| from erpnext.accounts.utils import get_account_name | ||||
| from erpnext.utilities.product import get_qty_in_stock | ||||
| from frappe.contacts.doctype.contact.contact import get_contact_name | ||||
| 
 | ||||
| 
 | ||||
| class WebsitePriceListMissingError(frappe.ValidationError): | ||||
| @ -371,7 +372,7 @@ def get_party(user=None): | ||||
| 	if not user: | ||||
| 		user = frappe.session.user | ||||
| 
 | ||||
| 	contact_name = frappe.db.get_value("Contact", {"email_id": user}) | ||||
| 	contact_name = get_contact_name(user) | ||||
| 	party = None | ||||
| 
 | ||||
| 	if contact_name: | ||||
| @ -417,7 +418,7 @@ def get_party(user=None): | ||||
| 		contact = frappe.new_doc("Contact") | ||||
| 		contact.update({ | ||||
| 			"first_name": fullname, | ||||
| 			"email_id": user | ||||
| 			"email_ids": [{"email_id": user, "is_primary": 1}] | ||||
| 		}) | ||||
| 		contact.append('links', dict(link_doctype='Customer', link_name=customer.name)) | ||||
| 		contact.flags.ignore_mandatory = True | ||||
| @ -504,7 +505,7 @@ def get_applicable_shipping_rules(party=None, quotation=None): | ||||
| 	if shipping_rules: | ||||
| 		rule_label_map = frappe.db.get_values("Shipping Rule", shipping_rules, "label") | ||||
| 		# we need this in sorted order as per the position of the rule in the settings page | ||||
| 		return [[rule, rule_label_map.get(rule)] for rule in shipping_rules] | ||||
| 		return [[rule, rule] for rule in shipping_rules] | ||||
| 
 | ||||
| def get_shipping_rules(quotation=None, cart_settings=None): | ||||
| 	if not quotation: | ||||
| @ -562,4 +563,4 @@ def apply_coupon_code(applied_code,applied_referral_sales_partner): | ||||
| 			frappe.throw(_("Please enter valid coupon code !!")) | ||||
| 	else: | ||||
| 		frappe.throw(_("Please enter coupon code !!")) | ||||
| 	return quotation | ||||
| 	return quotation | ||||
|  | ||||
| @ -185,9 +185,17 @@ def get_batches_by_oldest(item_code, warehouse): | ||||
| def split_batch(batch_no, item_code, warehouse, qty, new_batch_id=None): | ||||
| 	"""Split the batch into a new batch""" | ||||
| 	batch = frappe.get_doc(dict(doctype='Batch', item=item_code, batch_id=new_batch_id)).insert() | ||||
| 
 | ||||
| 	company = frappe.db.get_value('Stock Ledger Entry', dict( | ||||
| 			item_code=item_code, | ||||
| 			batch_no=batch_no, | ||||
| 			warehouse=warehouse | ||||
| 		), ['company']) | ||||
| 
 | ||||
| 	stock_entry = frappe.get_doc(dict( | ||||
| 		doctype='Stock Entry', | ||||
| 		purpose='Repack', | ||||
| 		company=company, | ||||
| 		items=[ | ||||
| 			dict( | ||||
| 				item_code=item_code, | ||||
|  | ||||
| @ -1,129 +1,51 @@ | ||||
| { | ||||
|  "allow_copy": 0,  | ||||
|  "allow_guest_to_view": 0,  | ||||
|  "allow_import": 0,  | ||||
|  "allow_rename": 0,  | ||||
|  "beta": 0,  | ||||
|  "creation": "2014-07-11 11:51:00.453717",  | ||||
|  "custom": 0,  | ||||
|  "docstatus": 0,  | ||||
|  "doctype": "DocType",  | ||||
|  "document_type": "",  | ||||
|  "editable_grid": 1,  | ||||
|  "engine": "InnoDB",  | ||||
|  "creation": "2014-07-11 11:51:00.453717", | ||||
|  "doctype": "DocType", | ||||
|  "editable_grid": 1, | ||||
|  "engine": "InnoDB", | ||||
|  "field_order": [ | ||||
|   "expense_account", | ||||
|   "description", | ||||
|   "col_break3", | ||||
|   "amount" | ||||
|  ], | ||||
|  "fields": [ | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fieldname": "description",  | ||||
|    "fieldtype": "Small Text",  | ||||
|    "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": "Description",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "permlevel": 0,  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 0,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 1,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "unique": 0 | ||||
|   },  | ||||
|    "fieldname": "description", | ||||
|    "fieldtype": "Small Text", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Description", | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fieldname": "col_break3",  | ||||
|    "fieldtype": "Column Break",  | ||||
|    "hidden": 0,  | ||||
|    "ignore_user_permissions": 0,  | ||||
|    "ignore_xss_filter": 0,  | ||||
|    "in_filter": 0,  | ||||
|    "in_global_search": 0,  | ||||
|    "in_list_view": 0,  | ||||
|    "in_standard_filter": 0,  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "permlevel": 0,  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 0,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 0,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "unique": 0,  | ||||
|    "fieldname": "col_break3", | ||||
|    "fieldtype": "Column Break", | ||||
|    "width": "50%" | ||||
|   },  | ||||
|   }, | ||||
|   { | ||||
|    "allow_bulk_edit": 0,  | ||||
|    "allow_on_submit": 0,  | ||||
|    "bold": 0,  | ||||
|    "collapsible": 0,  | ||||
|    "columns": 0,  | ||||
|    "fieldname": "amount",  | ||||
|    "fieldtype": "Currency",  | ||||
|    "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": "Amount",  | ||||
|    "length": 0,  | ||||
|    "no_copy": 0,  | ||||
|    "options": "Company:company:default_currency",  | ||||
|    "permlevel": 0,  | ||||
|    "print_hide": 0,  | ||||
|    "print_hide_if_no_value": 0,  | ||||
|    "read_only": 0,  | ||||
|    "remember_last_selected_value": 0,  | ||||
|    "report_hide": 0,  | ||||
|    "reqd": 1,  | ||||
|    "search_index": 0,  | ||||
|    "set_only_once": 0,  | ||||
|    "unique": 0 | ||||
|    "fieldname": "amount", | ||||
|    "fieldtype": "Currency", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Amount", | ||||
|    "options": "Company:company:default_currency", | ||||
|    "reqd": 1 | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "expense_account", | ||||
|    "fieldtype": "Link", | ||||
|    "in_list_view": 1, | ||||
|    "label": "Expense Account", | ||||
|    "options": "Account", | ||||
|    "reqd": 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": 1,  | ||||
|  "max_attachments": 0,  | ||||
|  "modified": "2017-11-15 19:27:59.542487",  | ||||
|  "modified_by": "Administrator",  | ||||
|  "module": "Stock",  | ||||
|  "name": "Landed Cost Taxes and Charges",  | ||||
|  "name_case": "",  | ||||
|  "owner": "Administrator",  | ||||
|  "permissions": [],  | ||||
|  "quick_entry": 0,  | ||||
|  "read_only": 0,  | ||||
|  "read_only_onload": 0,  | ||||
|  "show_name_in_global_search": 0,  | ||||
|  "sort_field": "modified",  | ||||
|  "sort_order": "DESC",  | ||||
|  "track_changes": 0,  | ||||
|  "track_seen": 0 | ||||
|  ], | ||||
|  "istable": 1, | ||||
|  "modified": "2019-09-30 18:28:32.070655", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Stock", | ||||
|  "name": "Landed Cost Taxes and Charges", | ||||
|  "owner": "Administrator", | ||||
|  "permissions": [], | ||||
|  "sort_field": "modified", | ||||
|  "sort_order": "DESC" | ||||
| } | ||||
| @ -30,6 +30,16 @@ erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({ | ||||
| 		this.frm.add_fetch("receipt_document", "posting_date", "posting_date"); | ||||
| 		this.frm.add_fetch("receipt_document", "base_grand_total", "grand_total"); | ||||
| 
 | ||||
| 		this.frm.set_query("expense_account", "taxes", function() { | ||||
| 			return { | ||||
| 				query: "erpnext.controllers.queries.tax_account_query", | ||||
| 				filters: { | ||||
| 					"account_type": ["Tax", "Chargeable", "Income Account", "Expenses Included In Valuation", "Expenses Included In Asset Valuation"], | ||||
| 					"company": me.frm.doc.company | ||||
| 				} | ||||
| 			}; | ||||
| 		}); | ||||
| 
 | ||||
| 	}, | ||||
| 
 | ||||
| 	refresh: function(frm) { | ||||
| @ -38,7 +48,7 @@ erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({ | ||||
| 			<table class="table table-bordered" style="background-color: #f9f9f9;"> | ||||
| 				<tr><td> | ||||
| 					<h4> | ||||
| 						<i class="fa fa-hand-right"></i>  | ||||
| 						<i class="fa fa-hand-right"></i> | ||||
| 						${__("Notes")}: | ||||
| 					</h4> | ||||
| 					<ul> | ||||
| @ -96,7 +106,7 @@ erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({ | ||||
| 		var me = this; | ||||
| 
 | ||||
| 		if(this.frm.doc.taxes.length) { | ||||
| 			 | ||||
| 
 | ||||
| 			var total_item_cost = 0.0; | ||||
| 			var based_on = this.frm.doc.distribute_charges_based_on.toLowerCase(); | ||||
| 			$.each(this.frm.doc.items || [], function(i, d) { | ||||
| @ -105,7 +115,7 @@ erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({ | ||||
| 
 | ||||
| 			var total_charges = 0.0; | ||||
| 			$.each(this.frm.doc.items || [], function(i, item) { | ||||
| 				item.applicable_charges = flt(item[based_on]) * flt(me.frm.doc.total_taxes_and_charges) / flt(total_item_cost)			 | ||||
| 				item.applicable_charges = flt(item[based_on]) * flt(me.frm.doc.total_taxes_and_charges) / flt(total_item_cost) | ||||
| 				item.applicable_charges = flt(item.applicable_charges, precision("applicable_charges", item)) | ||||
| 				total_charges += item.applicable_charges | ||||
| 			}); | ||||
|  | ||||
| @ -179,7 +179,7 @@ def submit_landed_cost_voucher(receipt_document_type, receipt_document, charges= | ||||
| 
 | ||||
| 	lcv.set("taxes", [{ | ||||
| 		"description": "Insurance Charges", | ||||
| 		"account": "_Test Account Insurance Charges - _TC", | ||||
| 		"expense_account": "Expenses Included In Valuation - TCP1", | ||||
| 		"amount": charges | ||||
| 	}]) | ||||
| 
 | ||||
|  | ||||
| @ -173,8 +173,10 @@ frappe.ui.form.on('Pick List Item', { | ||||
| }); | ||||
| 
 | ||||
| function get_item_details(item_code, uom=null) { | ||||
| 	return frappe.xcall('erpnext.stock.doctype.pick_list.pick_list.get_item_details', { | ||||
| 		item_code, | ||||
| 		uom | ||||
| 	}); | ||||
| 	if (item_code) { | ||||
| 		return frappe.xcall('erpnext.stock.doctype.pick_list.pick_list.get_item_details', { | ||||
| 			item_code, | ||||
| 			uom | ||||
| 		}); | ||||
| 	} | ||||
| } | ||||
| @ -14,7 +14,7 @@ from erpnext.accounts.utils import get_account_currency | ||||
| from frappe.desk.notifications import clear_doctype_notifications | ||||
| from frappe.model.mapper import get_mapped_doc | ||||
| from erpnext.buying.utils import check_on_hold_or_closed_status | ||||
| from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_disabled | ||||
| from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_enabled | ||||
| from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account | ||||
| from six import iteritems | ||||
| 
 | ||||
| @ -195,6 +195,7 @@ class PurchaseReceipt(BuyingController): | ||||
| 		from erpnext.accounts.general_ledger import process_gl_map | ||||
| 
 | ||||
| 		stock_rbnb = self.get_company_default("stock_received_but_not_billed") | ||||
| 		landed_cost_entries = get_item_account_wise_additional_cost(self.name) | ||||
| 		expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") | ||||
| 
 | ||||
| 		gl_entries = [] | ||||
| @ -233,15 +234,16 @@ class PurchaseReceipt(BuyingController): | ||||
| 					negative_expense_to_be_booked += flt(d.item_tax_amount) | ||||
| 
 | ||||
| 					# Amount added through landed-cost-voucher | ||||
| 					if flt(d.landed_cost_voucher_amount): | ||||
| 						gl_entries.append(self.get_gl_dict({ | ||||
| 							"account": expenses_included_in_valuation, | ||||
| 							"against": warehouse_account[d.warehouse]["account"], | ||||
| 							"cost_center": d.cost_center, | ||||
| 							"remarks": self.get("remarks") or _("Accounting Entry for Stock"), | ||||
| 							"credit": flt(d.landed_cost_voucher_amount), | ||||
| 							"project": d.project | ||||
| 						}, item=d)) | ||||
| 					if landed_cost_entries: | ||||
| 						for account, amount in iteritems(landed_cost_entries[(d.item_code, d.name)]): | ||||
| 							gl_entries.append(self.get_gl_dict({ | ||||
| 								"account": account, | ||||
| 								"against": warehouse_account[d.warehouse]["account"], | ||||
| 								"cost_center": d.cost_center, | ||||
| 								"remarks": self.get("remarks") or _("Accounting Entry for Stock"), | ||||
| 								"credit": flt(amount), | ||||
| 								"project": d.project | ||||
| 							}, item=d)) | ||||
| 
 | ||||
| 					# sub-contracting warehouse | ||||
| 					if flt(d.rm_supp_cost) and warehouse_account.get(self.supplier_warehouse): | ||||
| @ -336,12 +338,13 @@ class PurchaseReceipt(BuyingController): | ||||
| 	def get_asset_gl_entry(self, gl_entries, expenses_included_in_valuation=None): | ||||
| 		arbnb_account, cwip_account = None, None | ||||
| 
 | ||||
| 		cwip_disabled = is_cwip_accounting_disabled() | ||||
| 
 | ||||
| 		if not expenses_included_in_valuation: | ||||
| 			expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") | ||||
| 
 | ||||
| 		for d in self.get("items"): | ||||
| 			asset_category = frappe.get_cached_value("Item", d.item_code, "asset_category") | ||||
| 			cwip_enabled = is_cwip_accounting_enabled(self.company, asset_category) | ||||
| 
 | ||||
| 			if d.is_fixed_asset and not (arbnb_account and cwip_account): | ||||
| 				arbnb_account = self.get_company_default("asset_received_but_not_billed") | ||||
| 
 | ||||
| @ -349,8 +352,7 @@ class PurchaseReceipt(BuyingController): | ||||
| 				cwip_account = get_asset_account("capital_work_in_progress_account", d.asset, | ||||
| 					company = self.company) | ||||
| 
 | ||||
| 			if d.is_fixed_asset and not cwip_disabled: | ||||
| 
 | ||||
| 			if d.is_fixed_asset and cwip_enabled: | ||||
| 				asset_amount = flt(d.net_amount) + flt(d.item_tax_amount/self.conversion_rate) | ||||
| 				base_asset_amount = flt(d.base_net_amount + d.item_tax_amount) | ||||
| 
 | ||||
| @ -379,7 +381,7 @@ class PurchaseReceipt(BuyingController): | ||||
| 
 | ||||
| 			if d.is_fixed_asset and flt(d.landed_cost_voucher_amount): | ||||
| 				asset_account = (get_asset_category_account(d.asset, 'fixed_asset_account', | ||||
| 					company = self.company) if cwip_disabled else cwip_account) | ||||
| 					company = self.company) if not cwip_enabled else cwip_account) | ||||
| 
 | ||||
| 				gl_entries.append(self.get_gl_dict({ | ||||
| 					"account": expenses_included_in_valuation, | ||||
| @ -584,3 +586,30 @@ def make_stock_entry(source_name,target_doc=None): | ||||
| 	}, target_doc, set_missing_values) | ||||
| 
 | ||||
| 	return doclist | ||||
| 
 | ||||
| def get_item_account_wise_additional_cost(purchase_document): | ||||
| 	landed_cost_voucher = frappe.get_value("Landed Cost Purchase Receipt", | ||||
| 		{"receipt_document": purchase_document}, "parent") | ||||
| 
 | ||||
| 	if not landed_cost_voucher: | ||||
| 		return | ||||
| 
 | ||||
| 	total_item_cost = 0 | ||||
| 	item_account_wise_cost = {} | ||||
| 	landed_cost_voucher_doc = frappe.get_doc("Landed Cost Voucher", landed_cost_voucher) | ||||
| 	based_on_field = frappe.scrub(landed_cost_voucher_doc.distribute_charges_based_on) | ||||
| 
 | ||||
| 	for item in landed_cost_voucher_doc.items: | ||||
| 		if item.receipt_document == purchase_document: | ||||
| 			total_item_cost += item.get(based_on_field) | ||||
| 
 | ||||
| 	for item in landed_cost_voucher_doc.items: | ||||
| 		if item.receipt_document == purchase_document: | ||||
| 			for account in landed_cost_voucher_doc.taxes: | ||||
| 				item_account_wise_cost.setdefault((item.item_code, item.purchase_receipt_item), {}) | ||||
| 				item_account_wise_cost[(item.item_code, item.purchase_receipt_item)].setdefault(account.expense_account, 0.0) | ||||
| 				item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][account.expense_account] += \ | ||||
| 					account.amount * item.get(based_on_field) / total_item_cost | ||||
| 
 | ||||
| 	return item_account_wise_cost | ||||
| 
 | ||||
|  | ||||
| @ -68,6 +68,16 @@ frappe.ui.form.on('Stock Entry', { | ||||
| 			} | ||||
| 		}); | ||||
| 
 | ||||
| 		frm.set_query("expense_account", "additional_costs", function() { | ||||
| 			return { | ||||
| 				query: "erpnext.controllers.queries.tax_account_query", | ||||
| 				filters: { | ||||
| 					"account_type": ["Tax", "Chargeable", "Income Account", "Expenses Included In Valuation", "Expenses Included In Asset Valuation"], | ||||
| 					"company": frm.doc.company | ||||
| 				} | ||||
| 			}; | ||||
| 		}); | ||||
| 
 | ||||
| 		frm.add_fetch("bom_no", "inspection_required", "inspection_required"); | ||||
| 	}, | ||||
| 
 | ||||
| @ -727,7 +737,8 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ | ||||
| 		return frappe.call({ | ||||
| 			method: "erpnext.stock.doctype.stock_entry.stock_entry.get_work_order_details", | ||||
| 			args: { | ||||
| 				work_order: me.frm.doc.work_order | ||||
| 				work_order: me.frm.doc.work_order, | ||||
| 				company: me.frm.doc.company | ||||
| 			}, | ||||
| 			callback: function(r) { | ||||
| 				if (!r.exc) { | ||||
| @ -743,6 +754,8 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ | ||||
| 						if (me.frm.doc.purpose == "Manufacture") { | ||||
| 							if (!me.frm.doc.to_warehouse) me.frm.set_value("to_warehouse", r.message["fg_warehouse"]); | ||||
| 							if (r.message["additional_costs"].length) { | ||||
| 								me.frm.clear_table("additional_costs"); | ||||
| 
 | ||||
| 								$.each(r.message["additional_costs"], function(i, row) { | ||||
| 									me.frm.add_child("additional_costs", row); | ||||
| 								}) | ||||
|  | ||||
| @ -644,28 +644,37 @@ class StockEntry(StockController): | ||||
| 		self.make_sl_entries(sl_entries, self.amended_from and 'Yes' or 'No') | ||||
| 
 | ||||
| 	def get_gl_entries(self, warehouse_account): | ||||
| 		expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") | ||||
| 
 | ||||
| 		gl_entries = super(StockEntry, self).get_gl_entries(warehouse_account) | ||||
| 
 | ||||
| 		for d in self.get("items"): | ||||
| 			additional_cost = flt(d.additional_cost, d.precision("additional_cost")) | ||||
| 			if additional_cost: | ||||
| 				gl_entries.append(self.get_gl_dict({ | ||||
| 					"account": expenses_included_in_valuation, | ||||
| 					"against": d.expense_account, | ||||
| 					"cost_center": d.cost_center, | ||||
| 					"remarks": self.get("remarks") or _("Accounting Entry for Stock"), | ||||
| 					"credit": additional_cost | ||||
| 				}, item=d)) | ||||
| 		total_basic_amount = sum([flt(t.basic_amount) for t in self.get("items") if t.t_warehouse]) | ||||
| 		item_account_wise_additional_cost = {} | ||||
| 
 | ||||
| 				gl_entries.append(self.get_gl_dict({ | ||||
| 					"account": d.expense_account, | ||||
| 					"against": expenses_included_in_valuation, | ||||
| 					"cost_center": d.cost_center, | ||||
| 					"remarks": self.get("remarks") or _("Accounting Entry for Stock"), | ||||
| 					"credit": -1 * additional_cost # put it as negative credit instead of debit purposefully | ||||
| 				}, item=d)) | ||||
| 		for t in self.get("additional_costs"): | ||||
| 			for d in self.get("items"): | ||||
| 				if d.t_warehouse: | ||||
| 					item_account_wise_additional_cost.setdefault((d.item_code, d.name), {}) | ||||
| 					item_account_wise_additional_cost[(d.item_code, d.name)].setdefault(t.expense_account, 0.0) | ||||
| 					item_account_wise_additional_cost[(d.item_code, d.name)][t.expense_account] += \ | ||||
| 						(t.amount * d.basic_amount) / total_basic_amount | ||||
| 
 | ||||
| 		if item_account_wise_additional_cost: | ||||
| 			for d in self.get("items"): | ||||
| 				for account, amount in iteritems(item_account_wise_additional_cost.get((d.item_code, d.name), {})): | ||||
| 					gl_entries.append(self.get_gl_dict({ | ||||
| 						"account": account, | ||||
| 						"against": d.expense_account, | ||||
| 						"cost_center": d.cost_center, | ||||
| 						"remarks": self.get("remarks") or _("Accounting Entry for Stock"), | ||||
| 						"credit": amount | ||||
| 					}, item=d)) | ||||
| 
 | ||||
| 					gl_entries.append(self.get_gl_dict({ | ||||
| 						"account": d.expense_account, | ||||
| 						"against": account, | ||||
| 						"cost_center": d.cost_center, | ||||
| 						"remarks": self.get("remarks") or _("Accounting Entry for Stock"), | ||||
| 						"credit": -1 * amount # put it as negative credit instead of debit purposefully | ||||
| 					}, item=d)) | ||||
| 
 | ||||
| 		return gl_entries | ||||
| 
 | ||||
| @ -1349,7 +1358,7 @@ def make_stock_in_entry(source_name, target_doc=None): | ||||
| 	return doclist | ||||
| 
 | ||||
| @frappe.whitelist() | ||||
| def get_work_order_details(work_order): | ||||
| def get_work_order_details(work_order, company): | ||||
| 	work_order = frappe.get_doc("Work Order", work_order) | ||||
| 	pending_qty_to_produce = flt(work_order.qty) - flt(work_order.produced_qty) | ||||
| 
 | ||||
| @ -1360,14 +1369,17 @@ def get_work_order_details(work_order): | ||||
| 		"wip_warehouse": work_order.wip_warehouse, | ||||
| 		"fg_warehouse": work_order.fg_warehouse, | ||||
| 		"fg_completed_qty": pending_qty_to_produce, | ||||
| 		"additional_costs": get_additional_costs(work_order, fg_qty=pending_qty_to_produce) | ||||
| 		"additional_costs": get_additional_costs(work_order, fg_qty=pending_qty_to_produce, company=company) | ||||
| 	} | ||||
| 
 | ||||
| def get_additional_costs(work_order=None, bom_no=None, fg_qty=None): | ||||
| def get_additional_costs(work_order=None, bom_no=None, fg_qty=None, company=None): | ||||
| 	additional_costs = [] | ||||
| 	operating_cost_per_unit = get_operating_cost_per_unit(work_order, bom_no) | ||||
| 	expenses_included_in_valuation = frappe.get_cached_value("Company", company, "expenses_included_in_valuation") | ||||
| 
 | ||||
| 	if operating_cost_per_unit: | ||||
| 		additional_costs.append({ | ||||
| 			"expense_account": expenses_included_in_valuation, | ||||
| 			"description": "Operating Cost as per Work Order / BOM", | ||||
| 			"amount": operating_cost_per_unit * flt(fg_qty) | ||||
| 		}) | ||||
| @ -1377,6 +1389,7 @@ def get_additional_costs(work_order=None, bom_no=None, fg_qty=None): | ||||
| 			flt(work_order.additional_operating_cost) / flt(work_order.qty) | ||||
| 
 | ||||
| 		additional_costs.append({ | ||||
| 			"expense_account": expenses_included_in_valuation, | ||||
| 			"description": "Additional Operating Cost", | ||||
| 			"amount": additional_operating_cost_per_unit * flt(fg_qty) | ||||
| 		}) | ||||
|  | ||||
| @ -259,6 +259,8 @@ class TestStockEntry(unittest.TestCase): | ||||
| 		repack.posting_date = nowdate() | ||||
| 		repack.posting_time = nowtime() | ||||
| 
 | ||||
| 		expenses_included_in_valuation = frappe.get_value("Company", company, "expenses_included_in_valuation") | ||||
| 
 | ||||
| 		items = get_multiple_items() | ||||
| 		repack.items = [] | ||||
| 		for item in items: | ||||
| @ -266,11 +268,13 @@ class TestStockEntry(unittest.TestCase): | ||||
| 
 | ||||
| 		repack.set("additional_costs", [ | ||||
| 			{ | ||||
| 				"description": "Actual Oerating Cost", | ||||
| 				"expense_account": expenses_included_in_valuation, | ||||
| 				"description": "Actual Operating Cost", | ||||
| 				"amount": 1000 | ||||
| 			}, | ||||
| 			{ | ||||
| 				"description": "additional operating costs", | ||||
| 				"expense_account": expenses_included_in_valuation, | ||||
| 				"description": "Additional Operating Cost", | ||||
| 				"amount": 200 | ||||
| 			}, | ||||
| 		]) | ||||
|  | ||||
| @ -19,10 +19,26 @@ def execute(filters=None): | ||||
| 	if opening_row: | ||||
| 		data.append(opening_row) | ||||
| 
 | ||||
| 	actual_qty = stock_value = 0 | ||||
| 
 | ||||
| 	for sle in sl_entries: | ||||
| 		item_detail = item_details[sle.item_code] | ||||
| 
 | ||||
| 		sle.update(item_detail) | ||||
| 
 | ||||
| 		if filters.get("batch_no"): | ||||
| 			actual_qty += sle.actual_qty | ||||
| 			stock_value += sle.stock_value_difference | ||||
| 
 | ||||
| 			if sle.voucher_type == 'Stock Reconciliation': | ||||
| 				actual_qty = sle.qty_after_transaction | ||||
| 				stock_value = sle.stock_value | ||||
| 
 | ||||
| 			sle.update({ | ||||
| 				"qty_after_transaction": actual_qty, | ||||
| 				"stock_value": stock_value | ||||
| 			}) | ||||
| 
 | ||||
| 		data.append(sle) | ||||
| 
 | ||||
| 		if include_uom: | ||||
| @ -67,7 +83,7 @@ def get_stock_ledger_entries(filters, items): | ||||
| 
 | ||||
| 	return frappe.db.sql("""select concat_ws(" ", posting_date, posting_time) as date, | ||||
| 			item_code, warehouse, actual_qty, qty_after_transaction, incoming_rate, valuation_rate, | ||||
| 			stock_value, voucher_type, voucher_no, batch_no, serial_no, company, project | ||||
| 			stock_value, voucher_type, voucher_no, batch_no, serial_no, company, project, stock_value_difference | ||||
| 		from `tabStock Ledger Entry` sle | ||||
| 		where company = %(company)s and | ||||
| 			posting_date between %(from_date)s and %(to_date)s | ||||
|  | ||||
| @ -271,6 +271,7 @@ def update_included_uom_in_report(columns, result, include_uom, conversion_facto | ||||
| 				'fieldtype': 'Currency' if d.get("convertible") == 'rate' else 'Float' | ||||
| 			}) | ||||
| 
 | ||||
| 	update_dict_values = [] | ||||
| 	for row_idx, row in enumerate(result): | ||||
| 		data = row.items() if is_dict_obj else enumerate(row) | ||||
| 		for key, value in data: | ||||
| @ -286,7 +287,11 @@ def update_included_uom_in_report(columns, result, include_uom, conversion_facto | ||||
| 				row.insert(key+1, new_value) | ||||
| 			else: | ||||
| 				new_key = "{0}_{1}".format(key, frappe.scrub(include_uom)) | ||||
| 				row[new_key] = new_value | ||||
| 				update_dict_values.append([row, new_key, new_value]) | ||||
| 
 | ||||
| 	for data in update_dict_values: | ||||
| 		row, key, value = data | ||||
| 		row[key] = value | ||||
| 
 | ||||
| def get_available_serial_nos(item_code, warehouse): | ||||
| 	return frappe.get_all("Serial No", filters = {'item_code': item_code, | ||||
|  | ||||
| @ -8,7 +8,4 @@ from frappe import _ | ||||
| from frappe.model.document import Document | ||||
| 
 | ||||
| class IssuePriority(Document): | ||||
| 
 | ||||
| 	def validate(self): | ||||
| 		if frappe.db.exists("Issue Priority", {"name": self.name}): | ||||
| 			frappe.throw(_("Issue Priority Already Exists")) | ||||
| 	pass | ||||
| @ -18,6 +18,7 @@ class TestWoocommerce(unittest.TestCase): | ||||
| 			woo_settings.api_consumer_key = "ck_fd43ff5756a6abafd95fadb6677100ce95a758a1" | ||||
| 			woo_settings.api_consumer_secret = "cs_94360a1ad7bef7fa420a40cf284f7b3e0788454e" | ||||
| 			woo_settings.enable_sync = 1 | ||||
| 			woo_settings.company = "Woocommerce" | ||||
| 			woo_settings.tax_account = "Sales Expenses - W" | ||||
| 			woo_settings.f_n_f_account = "Expenses - W" | ||||
| 			woo_settings.creation_user = "Administrator" | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user