Merge branch 'develop' into fix-scrap-items-updation
This commit is contained in:
		
						commit
						6106a635f8
					
				| @ -533,8 +533,8 @@ frappe.ui.form.on('Payment Entry', { | |||||||
| 	source_exchange_rate: function(frm) { | 	source_exchange_rate: function(frm) { | ||||||
| 		if (frm.doc.paid_amount) { | 		if (frm.doc.paid_amount) { | ||||||
| 			frm.set_value("base_paid_amount", flt(frm.doc.paid_amount) * flt(frm.doc.source_exchange_rate)); | 			frm.set_value("base_paid_amount", flt(frm.doc.paid_amount) * flt(frm.doc.source_exchange_rate)); | ||||||
| 			if(!frm.set_paid_amount_based_on_received_amount && | 			// target exchange rate should always be same as source if both account currencies is same
 | ||||||
| 					(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency)) { | 			if(frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency) { | ||||||
| 				frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate); | 				frm.set_value("target_exchange_rate", frm.doc.source_exchange_rate); | ||||||
| 				frm.set_value("base_received_amount", frm.doc.base_paid_amount); | 				frm.set_value("base_received_amount", frm.doc.base_paid_amount); | ||||||
| 			} | 			} | ||||||
|  | |||||||
| @ -55,14 +55,17 @@ class PaymentEntry(AccountsController): | |||||||
| 		self.validate_mandatory() | 		self.validate_mandatory() | ||||||
| 		self.validate_reference_documents() | 		self.validate_reference_documents() | ||||||
| 		self.set_tax_withholding() | 		self.set_tax_withholding() | ||||||
| 		self.apply_taxes() |  | ||||||
| 		self.set_amounts() | 		self.set_amounts() | ||||||
|  | 		self.validate_amounts() | ||||||
|  | 		self.apply_taxes() | ||||||
|  | 		self.set_amounts_after_tax() | ||||||
| 		self.clear_unallocated_reference_document_rows() | 		self.clear_unallocated_reference_document_rows() | ||||||
| 		self.validate_payment_against_negative_invoice() | 		self.validate_payment_against_negative_invoice() | ||||||
| 		self.validate_transaction_reference() | 		self.validate_transaction_reference() | ||||||
| 		self.set_title() | 		self.set_title() | ||||||
| 		self.set_remarks() | 		self.set_remarks() | ||||||
| 		self.validate_duplicate_entry() | 		self.validate_duplicate_entry() | ||||||
|  | 		self.validate_payment_type_with_outstanding() | ||||||
| 		self.validate_allocated_amount() | 		self.validate_allocated_amount() | ||||||
| 		self.validate_paid_invoices() | 		self.validate_paid_invoices() | ||||||
| 		self.ensure_supplier_is_not_blocked() | 		self.ensure_supplier_is_not_blocked() | ||||||
| @ -118,6 +121,11 @@ class PaymentEntry(AccountsController): | |||||||
| 			if not self.get(field): | 			if not self.get(field): | ||||||
| 				self.set(field, bank_data.account) | 				self.set(field, bank_data.account) | ||||||
| 
 | 
 | ||||||
|  | 	def validate_payment_type_with_outstanding(self): | ||||||
|  | 		total_outstanding = sum(d.allocated_amount for d in self.get('references')) | ||||||
|  | 		if total_outstanding < 0 and self.party_type == 'Customer' and self.payment_type == 'Receive': | ||||||
|  | 			frappe.throw(_("Cannot receive from customer against negative outstanding"), title=_("Incorrect Payment Type")) | ||||||
|  | 
 | ||||||
| 	def validate_allocated_amount(self): | 	def validate_allocated_amount(self): | ||||||
| 		for d in self.get("references"): | 		for d in self.get("references"): | ||||||
| 			if (flt(d.allocated_amount))> 0: | 			if (flt(d.allocated_amount))> 0: | ||||||
| @ -236,7 +244,9 @@ class PaymentEntry(AccountsController): | |||||||
| 						self.company_currency, self.posting_date) | 						self.company_currency, self.posting_date) | ||||||
| 
 | 
 | ||||||
| 	def set_target_exchange_rate(self, ref_doc=None): | 	def set_target_exchange_rate(self, ref_doc=None): | ||||||
| 		if self.paid_to and not self.target_exchange_rate: | 		if self.paid_from_account_currency == self.paid_to_account_currency: | ||||||
|  | 			self.target_exchange_rate = self.source_exchange_rate | ||||||
|  | 		elif self.paid_to and not self.target_exchange_rate: | ||||||
| 			if ref_doc: | 			if ref_doc: | ||||||
| 				if self.paid_to_account_currency == ref_doc.currency: | 				if self.paid_to_account_currency == ref_doc.currency: | ||||||
| 					self.target_exchange_rate = ref_doc.get("exchange_rate") | 					self.target_exchange_rate = ref_doc.get("exchange_rate") | ||||||
| @ -468,13 +478,22 @@ class PaymentEntry(AccountsController): | |||||||
| 	def set_amounts(self): | 	def set_amounts(self): | ||||||
| 		self.set_received_amount() | 		self.set_received_amount() | ||||||
| 		self.set_amounts_in_company_currency() | 		self.set_amounts_in_company_currency() | ||||||
| 		self.set_amounts_after_tax() |  | ||||||
| 		self.set_total_allocated_amount() | 		self.set_total_allocated_amount() | ||||||
| 		self.set_unallocated_amount() | 		self.set_unallocated_amount() | ||||||
| 		self.set_difference_amount() | 		self.set_difference_amount() | ||||||
| 
 | 
 | ||||||
|  | 	def validate_amounts(self): | ||||||
|  | 		self.validate_received_amount() | ||||||
|  | 	 | ||||||
|  | 	def validate_received_amount(self): | ||||||
|  | 		if self.paid_from_account_currency == self.paid_to_account_currency: | ||||||
|  | 			if self.paid_amount != self.received_amount: | ||||||
|  | 				frappe.throw(_("Received Amount cannot be greater than Paid Amount")) | ||||||
|  | 
 | ||||||
| 	def set_received_amount(self): | 	def set_received_amount(self): | ||||||
| 		self.base_received_amount = self.base_paid_amount | 		self.base_received_amount = self.base_paid_amount | ||||||
|  | 		if self.paid_from_account_currency == self.paid_to_account_currency: | ||||||
|  | 			self.received_amount = self.paid_amount | ||||||
| 
 | 
 | ||||||
| 	def set_amounts_after_tax(self): | 	def set_amounts_after_tax(self): | ||||||
| 		applicable_tax = 0 | 		applicable_tax = 0 | ||||||
|  | |||||||
| @ -107,7 +107,7 @@ class TestPaymentEntry(unittest.TestCase): | |||||||
| 		pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC") | 		pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC") | ||||||
| 		pe.reference_no = "1" | 		pe.reference_no = "1" | ||||||
| 		pe.reference_date = "2016-01-01" | 		pe.reference_date = "2016-01-01" | ||||||
| 		pe.target_exchange_rate = 50 | 		pe.source_exchange_rate = 50 | ||||||
| 		pe.insert() | 		pe.insert() | ||||||
| 		pe.submit() | 		pe.submit() | ||||||
| 
 | 
 | ||||||
| @ -154,7 +154,7 @@ class TestPaymentEntry(unittest.TestCase): | |||||||
| 		pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC") | 		pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC") | ||||||
| 		pe.reference_no = "1" | 		pe.reference_no = "1" | ||||||
| 		pe.reference_date = "2016-01-01" | 		pe.reference_date = "2016-01-01" | ||||||
| 		pe.target_exchange_rate = 50 | 		pe.source_exchange_rate = 50 | ||||||
| 		pe.insert() | 		pe.insert() | ||||||
| 		pe.submit() | 		pe.submit() | ||||||
| 
 | 
 | ||||||
| @ -491,7 +491,7 @@ class TestPaymentEntry(unittest.TestCase): | |||||||
| 		pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC") | 		pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC") | ||||||
| 		pe.reference_no = "1" | 		pe.reference_no = "1" | ||||||
| 		pe.reference_date = "2016-01-01" | 		pe.reference_date = "2016-01-01" | ||||||
| 		pe.target_exchange_rate = 55 | 		pe.source_exchange_rate = 55 | ||||||
| 
 | 
 | ||||||
| 		pe.append("deductions", { | 		pe.append("deductions", { | ||||||
| 			"account": "_Test Exchange Gain/Loss - _TC", | 			"account": "_Test Exchange Gain/Loss - _TC", | ||||||
|  | |||||||
| @ -111,16 +111,12 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	write_off_outstanding_amount_automatically() { | 	write_off_outstanding_amount_automatically() { | ||||||
| 		if(cint(this.frm.doc.write_off_outstanding_amount_automatically)) { | 		if (cint(this.frm.doc.write_off_outstanding_amount_automatically)) { | ||||||
| 			frappe.model.round_floats_in(this.frm.doc, ["grand_total", "paid_amount"]); | 			frappe.model.round_floats_in(this.frm.doc, ["grand_total", "paid_amount"]); | ||||||
| 			// this will make outstanding amount 0
 | 			// this will make outstanding amount 0
 | ||||||
| 			this.frm.set_value("write_off_amount", | 			this.frm.set_value("write_off_amount", | ||||||
| 				flt(this.frm.doc.grand_total - this.frm.doc.paid_amount - this.frm.doc.total_advance, precision("write_off_amount")) | 				flt(this.frm.doc.grand_total - this.frm.doc.paid_amount - this.frm.doc.total_advance, precision("write_off_amount")) | ||||||
| 			); | 			); | ||||||
| 			this.frm.toggle_enable("write_off_amount", false); |  | ||||||
| 
 |  | ||||||
| 		} else { |  | ||||||
| 			this.frm.toggle_enable("write_off_amount", true); |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		this.calculate_outstanding_amount(false); | 		this.calculate_outstanding_amount(false); | ||||||
|  | |||||||
| @ -595,7 +595,8 @@ | |||||||
|   { |   { | ||||||
|    "fieldname": "scan_barcode", |    "fieldname": "scan_barcode", | ||||||
|    "fieldtype": "Data", |    "fieldtype": "Data", | ||||||
|    "label": "Scan Barcode" |    "label": "Scan Barcode", | ||||||
|  |    "options": "Barcode" | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|    "allow_bulk_edit": 1, |    "allow_bulk_edit": 1, | ||||||
| @ -1182,7 +1183,8 @@ | |||||||
|    "label": "Write Off Amount", |    "label": "Write Off Amount", | ||||||
|    "no_copy": 1, |    "no_copy": 1, | ||||||
|    "options": "currency", |    "options": "currency", | ||||||
|    "print_hide": 1 |    "print_hide": 1, | ||||||
|  |    "read_only_depends_on": "eval: doc.write_off_outstanding_amount_automatically" | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|    "fieldname": "base_write_off_amount", |    "fieldname": "base_write_off_amount", | ||||||
| @ -1553,7 +1555,7 @@ | |||||||
|  "icon": "fa fa-file-text", |  "icon": "fa fa-file-text", | ||||||
|  "is_submittable": 1, |  "is_submittable": 1, | ||||||
|  "links": [], |  "links": [], | ||||||
|  "modified": "2021-07-29 13:37:20.636171", |  "modified": "2021-08-18 16:13:52.080543", | ||||||
|  "modified_by": "Administrator", |  "modified_by": "Administrator", | ||||||
|  "module": "Accounts", |  "module": "Accounts", | ||||||
|  "name": "POS Invoice", |  "name": "POS Invoice", | ||||||
|  | |||||||
| @ -106,7 +106,6 @@ | |||||||
|    "depends_on": "eval:doc.rate_or_discount==\"Rate\"", |    "depends_on": "eval:doc.rate_or_discount==\"Rate\"", | ||||||
|    "fieldname": "rate", |    "fieldname": "rate", | ||||||
|    "fieldtype": "Currency", |    "fieldtype": "Currency", | ||||||
|    "in_list_view": 1, |  | ||||||
|    "label": "Rate" |    "label": "Rate" | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
| @ -170,7 +169,7 @@ | |||||||
|  "index_web_pages_for_search": 1, |  "index_web_pages_for_search": 1, | ||||||
|  "istable": 1, |  "istable": 1, | ||||||
|  "links": [], |  "links": [], | ||||||
|  "modified": "2021-03-07 11:56:23.424137", |  "modified": "2021-08-19 15:49:29.598727", | ||||||
|  "modified_by": "Administrator", |  "modified_by": "Administrator", | ||||||
|  "module": "Accounts", |  "module": "Accounts", | ||||||
|  "name": "Promotional Scheme Price Discount", |  "name": "Promotional Scheme Price Discount", | ||||||
|  | |||||||
| @ -668,8 +668,7 @@ | |||||||
|    "fieldname": "scan_barcode", |    "fieldname": "scan_barcode", | ||||||
|    "fieldtype": "Data", |    "fieldtype": "Data", | ||||||
|    "label": "Scan Barcode", |    "label": "Scan Barcode", | ||||||
|    "show_days": 1, |    "options": "Barcode" | ||||||
|    "show_seconds": 1 |  | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|    "allow_bulk_edit": 1, |    "allow_bulk_edit": 1, | ||||||
| @ -1715,7 +1714,7 @@ | |||||||
|  "idx": 204, |  "idx": 204, | ||||||
|  "is_submittable": 1, |  "is_submittable": 1, | ||||||
|  "links": [], |  "links": [], | ||||||
|  "modified": "2021-08-07 17:53:14.351439", |  "modified": "2021-08-17 20:16:12.737743", | ||||||
|  "modified_by": "Administrator", |  "modified_by": "Administrator", | ||||||
|  "module": "Accounts", |  "module": "Accounts", | ||||||
|  "name": "Purchase Invoice", |  "name": "Purchase Invoice", | ||||||
|  | |||||||
| @ -1,8 +1,6 @@ | |||||||
| {% include "erpnext/regional/india/taxes.js" %} | {% include "erpnext/regional/india/taxes.js" %} | ||||||
| {% include "erpnext/regional/india/e_invoice/einvoice.js" %} |  | ||||||
| 
 | 
 | ||||||
| erpnext.setup_auto_gst_taxation('Sales Invoice'); | erpnext.setup_auto_gst_taxation('Sales Invoice'); | ||||||
| erpnext.setup_einvoice_actions('Sales Invoice') |  | ||||||
| 
 | 
 | ||||||
| frappe.ui.form.on("Sales Invoice", { | frappe.ui.form.on("Sales Invoice", { | ||||||
| 	setup: function(frm) { | 	setup: function(frm) { | ||||||
|  | |||||||
| @ -36,139 +36,4 @@ frappe.listview_settings['Sales Invoice'].onload = function (list_view) { | |||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	list_view.page.add_actions_menu_item(__('Generate E-Way Bill JSON'), action, false); | 	list_view.page.add_actions_menu_item(__('Generate E-Way Bill JSON'), action, false); | ||||||
| 
 |  | ||||||
| 	const generate_irns = () => { |  | ||||||
| 		const docnames = list_view.get_checked_items(true); |  | ||||||
| 		if (docnames && docnames.length) { |  | ||||||
| 			frappe.call({ |  | ||||||
| 				method: 'erpnext.regional.india.e_invoice.utils.generate_einvoices', |  | ||||||
| 				args: { docnames }, |  | ||||||
| 				freeze: true, |  | ||||||
| 				freeze_message: __('Generating E-Invoices...') |  | ||||||
| 			}); |  | ||||||
| 		} else { |  | ||||||
| 			frappe.msgprint({ |  | ||||||
| 				message: __('Please select at least one sales invoice to generate IRN'), |  | ||||||
| 				title: __('No Invoice Selected'), |  | ||||||
| 				indicator: 'red' |  | ||||||
| 			}); |  | ||||||
| 		} |  | ||||||
| 	}; |  | ||||||
| 
 |  | ||||||
| 	const cancel_irns = () => { |  | ||||||
| 		const docnames = list_view.get_checked_items(true); |  | ||||||
| 
 |  | ||||||
| 		const fields = [ |  | ||||||
| 			{ |  | ||||||
| 				"label": "Reason", |  | ||||||
| 				"fieldname": "reason", |  | ||||||
| 				"fieldtype": "Select", |  | ||||||
| 				"reqd": 1, |  | ||||||
| 				"default": "1-Duplicate", |  | ||||||
| 				"options": ["1-Duplicate", "2-Data Entry Error", "3-Order Cancelled", "4-Other"] |  | ||||||
| 			}, |  | ||||||
| 			{ |  | ||||||
| 				"label": "Remark", |  | ||||||
| 				"fieldname": "remark", |  | ||||||
| 				"fieldtype": "Data", |  | ||||||
| 				"reqd": 1 |  | ||||||
| 			} |  | ||||||
| 		]; |  | ||||||
| 
 |  | ||||||
| 		const d = new frappe.ui.Dialog({ |  | ||||||
| 			title: __("Cancel IRN"), |  | ||||||
| 			fields: fields, |  | ||||||
| 			primary_action: function() { |  | ||||||
| 				const data = d.get_values(); |  | ||||||
| 				frappe.call({ |  | ||||||
| 					method: 'erpnext.regional.india.e_invoice.utils.cancel_irns', |  | ||||||
| 					args: { |  | ||||||
| 						doctype: list_view.doctype, |  | ||||||
| 						docnames, |  | ||||||
| 						reason: data.reason.split('-')[0], |  | ||||||
| 						remark: data.remark |  | ||||||
| 					}, |  | ||||||
| 					freeze: true, |  | ||||||
| 					freeze_message: __('Cancelling E-Invoices...'), |  | ||||||
| 				}); |  | ||||||
| 				d.hide(); |  | ||||||
| 			}, |  | ||||||
| 			primary_action_label: __('Submit') |  | ||||||
| 		}); |  | ||||||
| 		d.show(); |  | ||||||
| 	}; |  | ||||||
| 
 |  | ||||||
| 	let einvoicing_enabled = false; |  | ||||||
| 	frappe.db.get_single_value("E Invoice Settings", "enable").then(enabled => { |  | ||||||
| 		einvoicing_enabled = enabled; |  | ||||||
| 	}); |  | ||||||
| 
 |  | ||||||
| 	list_view.$result.on("change", "input[type=checkbox]", () => { |  | ||||||
| 		if (einvoicing_enabled) { |  | ||||||
| 			const docnames = list_view.get_checked_items(true); |  | ||||||
| 			// show/hide e-invoicing actions when no sales invoices are checked
 |  | ||||||
| 			if (docnames && docnames.length) { |  | ||||||
| 				// prevent adding actions twice if e-invoicing action group already exists
 |  | ||||||
| 				if (list_view.page.get_inner_group_button(__('E-Invoicing')).length == 0) { |  | ||||||
| 					list_view.page.add_inner_button(__('Generate IRNs'), generate_irns, __('E-Invoicing')); |  | ||||||
| 					list_view.page.add_inner_button(__('Cancel IRNs'), cancel_irns, __('E-Invoicing')); |  | ||||||
| 				} |  | ||||||
| 			} else { |  | ||||||
| 				list_view.page.remove_inner_button(__('Generate IRNs'), __('E-Invoicing')); |  | ||||||
| 				list_view.page.remove_inner_button(__('Cancel IRNs'), __('E-Invoicing')); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	}); |  | ||||||
| 
 |  | ||||||
| 	frappe.realtime.on("bulk_einvoice_generation_complete", (data) => { |  | ||||||
| 		const { failures, user, invoices } = data; |  | ||||||
| 
 |  | ||||||
| 		if (invoices.length != failures.length) { |  | ||||||
| 			frappe.msgprint({ |  | ||||||
| 				message: __('{0} e-invoices generated successfully', [invoices.length]), |  | ||||||
| 				title: __('Bulk E-Invoice Generation Complete'), |  | ||||||
| 				indicator: 'orange' |  | ||||||
| 			}); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if (failures && failures.length && user == frappe.session.user) { |  | ||||||
| 			let message = ` |  | ||||||
| 				Failed to generate IRNs for following ${failures.length} sales invoices: |  | ||||||
| 				<ul style="padding-left: 20px; padding-top: 5px;"> |  | ||||||
| 					${failures.map(d => `<li>${d.docname}</li>`).join('')} |  | ||||||
| 				</ul> |  | ||||||
| 			`;
 |  | ||||||
| 			frappe.msgprint({ |  | ||||||
| 				message: message, |  | ||||||
| 				title: __('Bulk E-Invoice Generation Complete'), |  | ||||||
| 				indicator: 'orange' |  | ||||||
| 			}); |  | ||||||
| 		} |  | ||||||
| 	}); |  | ||||||
| 
 |  | ||||||
| 	frappe.realtime.on("bulk_einvoice_cancellation_complete", (data) => { |  | ||||||
| 		const { failures, user, invoices } = data; |  | ||||||
| 
 |  | ||||||
| 		if (invoices.length != failures.length) { |  | ||||||
| 			frappe.msgprint({ |  | ||||||
| 				message: __('{0} e-invoices cancelled successfully', [invoices.length]), |  | ||||||
| 				title: __('Bulk E-Invoice Cancellation Complete'), |  | ||||||
| 				indicator: 'orange' |  | ||||||
| 			}); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if (failures && failures.length && user == frappe.session.user) { |  | ||||||
| 			let message = ` |  | ||||||
| 				Failed to cancel IRNs for following ${failures.length} sales invoices: |  | ||||||
| 				<ul style="padding-left: 20px; padding-top: 5px;"> |  | ||||||
| 					${failures.map(d => `<li>${d.docname}</li>`).join('')} |  | ||||||
| 				</ul> |  | ||||||
| 			`;
 |  | ||||||
| 			frappe.msgprint({ |  | ||||||
| 				message: message, |  | ||||||
| 				title: __('Bulk E-Invoice Cancellation Complete'), |  | ||||||
| 				indicator: 'orange' |  | ||||||
| 			}); |  | ||||||
| 		} |  | ||||||
| 	}); |  | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -324,16 +324,12 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	write_off_outstanding_amount_automatically() { | 	write_off_outstanding_amount_automatically() { | ||||||
| 		if(cint(this.frm.doc.write_off_outstanding_amount_automatically)) { | 		if (cint(this.frm.doc.write_off_outstanding_amount_automatically)) { | ||||||
| 			frappe.model.round_floats_in(this.frm.doc, ["grand_total", "paid_amount"]); | 			frappe.model.round_floats_in(this.frm.doc, ["grand_total", "paid_amount"]); | ||||||
| 			// this will make outstanding amount 0
 | 			// this will make outstanding amount 0
 | ||||||
| 			this.frm.set_value("write_off_amount", | 			this.frm.set_value("write_off_amount", | ||||||
| 				flt(this.frm.doc.grand_total - this.frm.doc.paid_amount - this.frm.doc.total_advance, precision("write_off_amount")) | 				flt(this.frm.doc.grand_total - this.frm.doc.paid_amount - this.frm.doc.total_advance, precision("write_off_amount")) | ||||||
| 			); | 			); | ||||||
| 			this.frm.toggle_enable("write_off_amount", false); |  | ||||||
| 
 |  | ||||||
| 		} else { |  | ||||||
| 			this.frm.toggle_enable("write_off_amount", true); |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		this.calculate_outstanding_amount(false); | 		this.calculate_outstanding_amount(false); | ||||||
| @ -787,8 +783,6 @@ frappe.ui.form.on('Sales Invoice', { | |||||||
| 		if (frappe.boot.sysdefaults.country == 'India') unhide_field(['c_form_applicable', 'c_form_no']); | 		if (frappe.boot.sysdefaults.country == 'India') unhide_field(['c_form_applicable', 'c_form_no']); | ||||||
| 		else hide_field(['c_form_applicable', 'c_form_no']); | 		else hide_field(['c_form_applicable', 'c_form_no']); | ||||||
| 
 | 
 | ||||||
| 		frm.toggle_enable("write_off_amount", !!!cint(doc.write_off_outstanding_amount_automatically)); |  | ||||||
| 
 |  | ||||||
| 		frm.refresh_fields(); | 		frm.refresh_fields(); | ||||||
| 	}, | 	}, | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -692,6 +692,7 @@ | |||||||
|   { |   { | ||||||
|    "fieldname": "scan_barcode", |    "fieldname": "scan_barcode", | ||||||
|    "fieldtype": "Data", |    "fieldtype": "Data", | ||||||
|  |    "options": "Barcode", | ||||||
|    "hide_days": 1, |    "hide_days": 1, | ||||||
|    "hide_seconds": 1, |    "hide_seconds": 1, | ||||||
|    "label": "Scan Barcode" |    "label": "Scan Barcode" | ||||||
| @ -1443,7 +1444,8 @@ | |||||||
|    "label": "Write Off Amount", |    "label": "Write Off Amount", | ||||||
|    "no_copy": 1, |    "no_copy": 1, | ||||||
|    "options": "currency", |    "options": "currency", | ||||||
|    "print_hide": 1 |    "print_hide": 1, | ||||||
|  |    "read_only_depends_on": "eval:doc.write_off_outstanding_amount_automatically" | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|    "fieldname": "base_write_off_amount", |    "fieldname": "base_write_off_amount", | ||||||
| @ -2013,7 +2015,7 @@ | |||||||
|    "link_fieldname": "consolidated_invoice" |    "link_fieldname": "consolidated_invoice" | ||||||
|   } |   } | ||||||
|  ], |  ], | ||||||
|  "modified": "2021-08-17 19:00:32.230701", |  "modified": "2021-08-18 16:07:45.122570", | ||||||
|  "modified_by": "Administrator", |  "modified_by": "Administrator", | ||||||
|  "module": "Accounts", |  "module": "Accounts", | ||||||
|  "name": "Sales Invoice", |  "name": "Sales Invoice", | ||||||
|  | |||||||
| @ -285,8 +285,6 @@ class SalesInvoice(SellingController): | |||||||
| 
 | 
 | ||||||
| 	def before_cancel(self): | 	def before_cancel(self): | ||||||
| 		self.check_if_consolidated_invoice() | 		self.check_if_consolidated_invoice() | ||||||
| 
 |  | ||||||
| 		super(SalesInvoice, self).before_cancel() |  | ||||||
| 		self.update_time_sheet(None) | 		self.update_time_sheet(None) | ||||||
| 
 | 
 | ||||||
| 	def on_cancel(self): | 	def on_cancel(self): | ||||||
|  | |||||||
| @ -26,6 +26,7 @@ from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry | |||||||
| from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt | from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt | ||||||
| from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice | from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_invoice | ||||||
| from erpnext.stock.utils import get_incoming_rate | from erpnext.stock.utils import get_incoming_rate | ||||||
|  | from erpnext.accounts.utils import PaymentEntryUnlinkError | ||||||
| 
 | 
 | ||||||
| class TestSalesInvoice(unittest.TestCase): | class TestSalesInvoice(unittest.TestCase): | ||||||
| 	def make(self): | 	def make(self): | ||||||
| @ -136,7 +137,7 @@ class TestSalesInvoice(unittest.TestCase): | |||||||
| 		pe.paid_to_account_currency = si.currency | 		pe.paid_to_account_currency = si.currency | ||||||
| 		pe.source_exchange_rate = 1 | 		pe.source_exchange_rate = 1 | ||||||
| 		pe.target_exchange_rate = 1 | 		pe.target_exchange_rate = 1 | ||||||
| 		pe.paid_amount = si.grand_total | 		pe.paid_amount = si.outstanding_amount | ||||||
| 		pe.insert() | 		pe.insert() | ||||||
| 		pe.submit() | 		pe.submit() | ||||||
| 
 | 
 | ||||||
| @ -145,6 +146,42 @@ class TestSalesInvoice(unittest.TestCase): | |||||||
| 		self.assertRaises(frappe.LinkExistsError, si.cancel) | 		self.assertRaises(frappe.LinkExistsError, si.cancel) | ||||||
| 		unlink_payment_on_cancel_of_invoice() | 		unlink_payment_on_cancel_of_invoice() | ||||||
| 
 | 
 | ||||||
|  | 	def test_payment_entry_unlink_against_standalone_credit_note(self): | ||||||
|  | 		from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry | ||||||
|  | 		si1 = create_sales_invoice(rate=1000) | ||||||
|  | 		si2 = create_sales_invoice(rate=300) | ||||||
|  | 		si3 = create_sales_invoice(qty=-1, rate=300, is_return=1) | ||||||
|  | 		 | ||||||
|  | 
 | ||||||
|  | 		pe = get_payment_entry("Sales Invoice", si1.name, bank_account="_Test Bank - _TC") | ||||||
|  | 		pe.append('references', { | ||||||
|  | 			'reference_doctype': 'Sales Invoice', | ||||||
|  | 			'reference_name': si2.name, | ||||||
|  | 			'total_amount': si2.grand_total, | ||||||
|  | 			'outstanding_amount': si2.outstanding_amount, | ||||||
|  | 			'allocated_amount': si2.outstanding_amount | ||||||
|  | 		}) | ||||||
|  | 
 | ||||||
|  | 		pe.append('references', { | ||||||
|  | 			'reference_doctype': 'Sales Invoice', | ||||||
|  | 			'reference_name': si3.name, | ||||||
|  | 			'total_amount': si3.grand_total, | ||||||
|  | 			'outstanding_amount': si3.outstanding_amount, | ||||||
|  | 			'allocated_amount': si3.outstanding_amount | ||||||
|  | 		}) | ||||||
|  | 
 | ||||||
|  | 		pe.reference_no = 'Test001' | ||||||
|  | 		pe.reference_date = nowdate() | ||||||
|  | 		pe.save() | ||||||
|  | 		pe.submit() | ||||||
|  | 
 | ||||||
|  | 		si2.load_from_db() | ||||||
|  | 		si2.cancel() | ||||||
|  | 
 | ||||||
|  | 		si1.load_from_db() | ||||||
|  | 		self.assertRaises(PaymentEntryUnlinkError, si1.cancel) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| 	def test_sales_invoice_calculation_export_currency(self): | 	def test_sales_invoice_calculation_export_currency(self): | ||||||
| 		si = frappe.copy_doc(test_records[2]) | 		si = frappe.copy_doc(test_records[2]) | ||||||
| 		si.currency = "USD" | 		si.currency = "USD" | ||||||
| @ -2014,7 +2051,7 @@ class TestSalesInvoice(unittest.TestCase): | |||||||
| 
 | 
 | ||||||
| 		data = get_ewb_data("Sales Invoice", [si.name]) | 		data = get_ewb_data("Sales Invoice", [si.name]) | ||||||
| 
 | 
 | ||||||
| 		self.assertEqual(data['version'], '1.0.1118') | 		self.assertEqual(data['version'], '1.0.0421') | ||||||
| 		self.assertEqual(data['billLists'][0]['fromGstin'], '27AAECE4835E1ZR') | 		self.assertEqual(data['billLists'][0]['fromGstin'], '27AAECE4835E1ZR') | ||||||
| 		self.assertEqual(data['billLists'][0]['fromTrdName'], '_Test Company') | 		self.assertEqual(data['billLists'][0]['fromTrdName'], '_Test Company') | ||||||
| 		self.assertEqual(data['billLists'][0]['toTrdName'], '_Test Customer') | 		self.assertEqual(data['billLists'][0]['toTrdName'], '_Test Customer') | ||||||
| @ -2027,54 +2064,6 @@ class TestSalesInvoice(unittest.TestCase): | |||||||
| 		self.assertEqual(data['billLists'][0]['actualFromStateCode'],7) | 		self.assertEqual(data['billLists'][0]['actualFromStateCode'],7) | ||||||
| 		self.assertEqual(data['billLists'][0]['fromStateCode'],27) | 		self.assertEqual(data['billLists'][0]['fromStateCode'],27) | ||||||
| 
 | 
 | ||||||
| 	def test_einvoice_submission_without_irn(self): |  | ||||||
| 		# init |  | ||||||
| 		einvoice_settings = frappe.get_doc('E Invoice Settings') |  | ||||||
| 		einvoice_settings.enable = 1 |  | ||||||
| 		einvoice_settings.applicable_from = nowdate() |  | ||||||
| 		einvoice_settings.append('credentials', { |  | ||||||
| 			'company': '_Test Company', |  | ||||||
| 			'gstin': '27AAECE4835E1ZR', |  | ||||||
| 			'username': 'test', |  | ||||||
| 			'password': 'test' |  | ||||||
| 		}) |  | ||||||
| 		einvoice_settings.save() |  | ||||||
| 
 |  | ||||||
| 		country = frappe.flags.country |  | ||||||
| 		frappe.flags.country = 'India' |  | ||||||
| 
 |  | ||||||
| 		si = make_sales_invoice_for_ewaybill() |  | ||||||
| 		self.assertRaises(frappe.ValidationError, si.submit) |  | ||||||
| 
 |  | ||||||
| 		si.irn = 'test_irn' |  | ||||||
| 		si.submit() |  | ||||||
| 
 |  | ||||||
| 		# reset |  | ||||||
| 		einvoice_settings = frappe.get_doc('E Invoice Settings') |  | ||||||
| 		einvoice_settings.enable = 0 |  | ||||||
| 		frappe.flags.country = country |  | ||||||
| 
 |  | ||||||
| 	def test_einvoice_json(self): |  | ||||||
| 		from erpnext.regional.india.e_invoice.utils import make_einvoice, validate_totals |  | ||||||
| 
 |  | ||||||
| 		si = get_sales_invoice_for_e_invoice() |  | ||||||
| 		si.discount_amount = 100 |  | ||||||
| 		si.save() |  | ||||||
| 
 |  | ||||||
| 		einvoice = make_einvoice(si) |  | ||||||
| 		self.assertTrue(einvoice['EwbDtls']) |  | ||||||
| 		validate_totals(einvoice) |  | ||||||
| 
 |  | ||||||
| 		si.apply_discount_on = 'Net Total' |  | ||||||
| 		si.save() |  | ||||||
| 		einvoice = make_einvoice(si) |  | ||||||
| 		validate_totals(einvoice) |  | ||||||
| 
 |  | ||||||
| 		[d.set('included_in_print_rate', 1) for d in si.taxes] |  | ||||||
| 		si.save() |  | ||||||
| 		einvoice = make_einvoice(si) |  | ||||||
| 		validate_totals(einvoice) |  | ||||||
| 
 |  | ||||||
| 	def test_item_tax_net_range(self): | 	def test_item_tax_net_range(self): | ||||||
| 		item = create_item("T Shirt") | 		item = create_item("T Shirt") | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,162 +0,0 @@ | |||||||
| {%- from "templates/print_formats/standard_macros.html" import add_header, render_field, print_value -%} |  | ||||||
| {%- set einvoice = json.loads(doc.signed_einvoice) -%} |  | ||||||
| 
 |  | ||||||
| <div class="page-break"> |  | ||||||
| 	<div {% if print_settings.repeat_header_footer %} id="header-html" class="hidden-pdf" {% endif %}> |  | ||||||
| 		{% if letter_head and not no_letterhead %} |  | ||||||
| 			<div class="letter-head">{{ letter_head }}</div> |  | ||||||
| 		{% endif %} |  | ||||||
| 		<div class="print-heading"> |  | ||||||
| 			<h2>E Invoice<br><small>{{ doc.name }}</small></h2> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	{% if print_settings.repeat_header_footer %} |  | ||||||
| 	<div id="footer-html" class="visible-pdf"> |  | ||||||
| 		{% if not no_letterhead and footer %} |  | ||||||
| 		<div class="letter-head-footer"> |  | ||||||
| 			{{ footer }} |  | ||||||
| 		</div> |  | ||||||
| 		{% endif %} |  | ||||||
| 		<p class="text-center small page-number visible-pdf"> |  | ||||||
| 			{{ _("Page {0} of {1}").format('<span class="page"></span>', '<span class="topage"></span>') }} |  | ||||||
| 		</p> |  | ||||||
| 	</div> |  | ||||||
| 	{% endif %} |  | ||||||
| 	<h5 class="font-bold" style="margin-top: 0px;">1. Transaction Details</h5> |  | ||||||
| 	<div class="row section-break" style="border-bottom: 1px solid #d1d8dd; padding-bottom: 10px;"> |  | ||||||
| 		<div class="col-xs-8 column-break"> |  | ||||||
| 			<div class="row data-field"> |  | ||||||
| 				<div class="col-xs-4"><label>IRN</label></div> |  | ||||||
| 				<div class="col-xs-8 value">{{ einvoice.Irn }}</div> |  | ||||||
| 			</div> |  | ||||||
| 			<div class="row data-field"> |  | ||||||
| 				<div class="col-xs-4"><label>Ack. No</label></div> |  | ||||||
| 				<div class="col-xs-8 value">{{ einvoice.AckNo }}</div> |  | ||||||
| 			</div> |  | ||||||
| 			<div class="row data-field"> |  | ||||||
| 				<div class="col-xs-4"><label>Ack. Date</label></div> |  | ||||||
| 				<div class="col-xs-8 value">{{ frappe.utils.format_datetime(einvoice.AckDt, "dd/MM/yyyy hh:mm:ss") }}</div> |  | ||||||
| 			</div> |  | ||||||
| 			<div class="row data-field"> |  | ||||||
| 				<div class="col-xs-4"><label>Category</label></div> |  | ||||||
| 				<div class="col-xs-8 value">{{ einvoice.TranDtls.SupTyp }}</div> |  | ||||||
| 			</div> |  | ||||||
| 			<div class="row data-field"> |  | ||||||
| 				<div class="col-xs-4"><label>Document Type</label></div> |  | ||||||
| 				<div class="col-xs-8 value">{{ einvoice.DocDtls.Typ }}</div> |  | ||||||
| 			</div> |  | ||||||
| 			<div class="row data-field"> |  | ||||||
| 				<div class="col-xs-4"><label>Document No</label></div> |  | ||||||
| 				<div class="col-xs-8 value">{{ einvoice.DocDtls.No }}</div> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="col-xs-4 column-break"> |  | ||||||
| 			<img src="{{ doc.qrcode_image }}" width="175px" style="float: right;"> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<h5 class="font-bold" style="margin-top: 15px; margin-bottom: 10px;">2. Party Details</h5> |  | ||||||
| 	<div class="row section-break" style="border-bottom: 1px solid #d1d8dd; padding-bottom: 10px;"> |  | ||||||
| 		{%- set seller = einvoice.SellerDtls -%} |  | ||||||
| 		<div class="col-xs-6 column-break"> |  | ||||||
| 			<h5 style="margin-bottom: 5px;">Seller</h5> |  | ||||||
| 			<p>{{ seller.Gstin }}</p> |  | ||||||
| 			<p>{{ seller.LglNm }}</p> |  | ||||||
| 			<p>{{ seller.Addr1 }}</p> |  | ||||||
| 			{%- if seller.Addr2 -%} <p>{{ seller.Addr2 }}</p> {% endif %} |  | ||||||
| 			<p>{{ seller.Loc }}</p> |  | ||||||
| 			<p>{{ frappe.db.get_value("Address", doc.company_address, "gst_state") }} - {{ seller.Pin }}</p> |  | ||||||
| 
 |  | ||||||
| 			{%- if einvoice.ShipDtls -%} |  | ||||||
| 				{%- set shipping = einvoice.ShipDtls -%} |  | ||||||
| 				<h5 style="margin-bottom: 5px;">Shipping</h5> |  | ||||||
| 				<p>{{ shipping.Gstin }}</p> |  | ||||||
| 				<p>{{ shipping.LglNm }}</p> |  | ||||||
| 				<p>{{ shipping.Addr1 }}</p> |  | ||||||
| 				{%- if shipping.Addr2 -%} <p>{{ shipping.Addr2 }}</p> {% endif %} |  | ||||||
| 				<p>{{ shipping.Loc }}</p> |  | ||||||
| 				<p>{{ frappe.db.get_value("Address", doc.shipping_address_name, "gst_state") }} - {{ shipping.Pin }}</p> |  | ||||||
| 			{% endif %} |  | ||||||
| 		</div> |  | ||||||
| 		{%- set buyer = einvoice.BuyerDtls -%} |  | ||||||
| 		<div class="col-xs-6 column-break"> |  | ||||||
| 			<h5 style="margin-bottom: 5px;">Buyer</h5> |  | ||||||
| 			<p>{{ buyer.Gstin }}</p> |  | ||||||
| 			<p>{{ buyer.LglNm }}</p> |  | ||||||
| 			<p>{{ buyer.Addr1 }}</p> |  | ||||||
| 			{%- if buyer.Addr2 -%} <p>{{ buyer.Addr2 }}</p> {% endif %} |  | ||||||
| 			<p>{{ buyer.Loc }}</p> |  | ||||||
| 			<p>{{ frappe.db.get_value("Address", doc.customer_address, "gst_state") }} - {{ buyer.Pin }}</p> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<div style="overflow-x: auto;"> |  | ||||||
| 		<h5 class="font-bold" style="margin-top: 15px; margin-bottom: 10px;">3. Item Details</h5> |  | ||||||
| 		<table class="table table-bordered"> |  | ||||||
| 			<thead> |  | ||||||
| 				<tr> |  | ||||||
| 					<th class="text-left" style="width: 3%;">Sr. No.</th> |  | ||||||
| 					<th class="text-left">Item</th> |  | ||||||
| 					<th class="text-left" style="width: 10%;">HSN Code</th> |  | ||||||
| 					<th class="text-left" style="width: 5%;">Qty</th> |  | ||||||
| 					<th class="text-left" style="width: 5%;">UOM</th> |  | ||||||
| 					<th class="text-left">Rate</th> |  | ||||||
| 					<th class="text-left" style="width: 5%;">Discount</th> |  | ||||||
| 					<th class="text-left">Taxable Amount</th> |  | ||||||
| 					<th class="text-left" style="width: 7%;">Tax Rate</th> |  | ||||||
| 					<th class="text-left" style="width: 5%;">Other Charges</th> |  | ||||||
| 					<th class="text-left">Total</th> |  | ||||||
| 				</tr> |  | ||||||
| 			</thead> |  | ||||||
| 			<tbody> |  | ||||||
| 				{% for item in einvoice.ItemList %} |  | ||||||
| 					<tr> |  | ||||||
| 						<td class="text-left" style="width: 3%;">{{ item.SlNo }}</td> |  | ||||||
| 						<td class="text-left">{{ item.PrdDesc }}</td> |  | ||||||
| 						<td class="text-left" style="width: 10%;">{{ item.HsnCd }}</td> |  | ||||||
| 						<td class="text-right" style="width: 5%;">{{ item.Qty }}</td> |  | ||||||
| 						<td class="text-left" style="width: 5%;">{{ item.Unit }}</td> |  | ||||||
| 						<td class="text-right">{{ frappe.utils.fmt_money(item.UnitPrice, None, "INR") }}</td> |  | ||||||
| 						<td class="text-right" style="width: 5%;">{{ frappe.utils.fmt_money(item.Discount, None, "INR") }}</td> |  | ||||||
| 						<td class="text-right">{{ frappe.utils.fmt_money(item.AssAmt, None, "INR") }}</td> |  | ||||||
| 						<td class="text-right" style="width: 7%;">{{ item.GstRt + item.CesRt }} %</td> |  | ||||||
| 						<td class="text-right" style="width: 5%;">{{ frappe.utils.fmt_money(0, None, "INR") }}</td> |  | ||||||
| 						<td class="text-right">{{ frappe.utils.fmt_money(item.TotItemVal, None, "INR") }}</td> |  | ||||||
| 					</tr> |  | ||||||
| 				{% endfor %} |  | ||||||
| 			</tbody> |  | ||||||
| 		</table> |  | ||||||
| 	</div> |  | ||||||
| 	<div style="overflow-x: auto;"> |  | ||||||
| 		<h5 class="font-bold" style="margin-bottom: 0px;">4. Value Details</h5> |  | ||||||
| 		<table class="table table-bordered"> |  | ||||||
| 			<thead> |  | ||||||
| 				<tr> |  | ||||||
| 					<th class="text-left">Taxable Amount</th> |  | ||||||
| 					<th class="text-left">CGST</th> |  | ||||||
| 					<th class="text-left"">SGST</th> |  | ||||||
| 					<th class="text-left">IGST</th> |  | ||||||
| 					<th class="text-left">CESS</th> |  | ||||||
| 					<th class="text-left" style="width: 10%;">State CESS</th> |  | ||||||
| 					<th class="text-left">Discount</th> |  | ||||||
| 					<th class="text-left" style="width: 10%;">Other Charges</th> |  | ||||||
| 					<th class="text-left" style="width: 10%;">Round Off</th> |  | ||||||
| 					<th class="text-left">Total Value</th> |  | ||||||
| 				</tr> |  | ||||||
| 			</thead> |  | ||||||
| 			<tbody> |  | ||||||
| 				{%- set value_details = einvoice.ValDtls -%} |  | ||||||
| 				<tr> |  | ||||||
| 					<td class="text-right">{{ frappe.utils.fmt_money(value_details.AssVal, None, "INR") }}</td> |  | ||||||
| 					<td class="text-right">{{ frappe.utils.fmt_money(value_details.CgstVal, None, "INR") }}</td> |  | ||||||
| 					<td class="text-right">{{ frappe.utils.fmt_money(value_details.SgstVal, None, "INR") }}</td> |  | ||||||
| 					<td class="text-right">{{ frappe.utils.fmt_money(value_details.IgstVal, None, "INR") }}</td> |  | ||||||
| 					<td class="text-right">{{ frappe.utils.fmt_money(value_details.CesVal, None, "INR") }}</td> |  | ||||||
| 					<td class="text-right">{{ frappe.utils.fmt_money(0, None, "INR") }}</td> |  | ||||||
| 					<td class="text-right">{{ frappe.utils.fmt_money(value_details.Discount, None, "INR") }}</td> |  | ||||||
| 					<td class="text-right">{{ frappe.utils.fmt_money(value_details.OthChrg, None, "INR") }}</td> |  | ||||||
| 					<td class="text-right">{{ frappe.utils.fmt_money(value_details.RndOffAmt, None, "INR") }}</td> |  | ||||||
| 					<td class="text-right">{{ frappe.utils.fmt_money(value_details.TotInvVal, None, "INR") }}</td> |  | ||||||
| 				</tr> |  | ||||||
| 			</tbody> |  | ||||||
| 		</table> |  | ||||||
| 	</div> |  | ||||||
| </div> |  | ||||||
| @ -1,24 +0,0 @@ | |||||||
| { |  | ||||||
|  "align_labels_right": 1, |  | ||||||
|  "creation": "2020-10-10 18:01:21.032914", |  | ||||||
|  "custom_format": 0, |  | ||||||
|  "default_print_language": "en-US", |  | ||||||
|  "disabled": 1, |  | ||||||
|  "doc_type": "Sales Invoice", |  | ||||||
|  "docstatus": 0, |  | ||||||
|  "doctype": "Print Format", |  | ||||||
|  "font": "Default", |  | ||||||
|  "html": "", |  | ||||||
|  "idx": 0, |  | ||||||
|  "line_breaks": 1, |  | ||||||
|  "modified": "2020-10-23 19:54:40.634936", |  | ||||||
|  "modified_by": "Administrator", |  | ||||||
|  "module": "Accounts", |  | ||||||
|  "name": "GST E-Invoice", |  | ||||||
|  "owner": "Administrator", |  | ||||||
|  "print_format_builder": 0, |  | ||||||
|  "print_format_type": "Jinja", |  | ||||||
|  "raw_printing": 0, |  | ||||||
|  "show_section_headings": 1, |  | ||||||
|  "standard": "Yes" |  | ||||||
| } |  | ||||||
| @ -535,6 +535,8 @@ class ReceivablePayableReport(object): | |||||||
| 		if getdate(entry_date) > getdate(self.filters.report_date): | 		if getdate(entry_date) > getdate(self.filters.report_date): | ||||||
| 			row.range1 = row.range2 = row.range3 = row.range4 = row.range5 = 0.0 | 			row.range1 = row.range2 = row.range3 = row.range4 = row.range5 = 0.0 | ||||||
| 
 | 
 | ||||||
|  | 		row.total_due = row.range1 + row.range2 + row.range3 + row.range4 + row.range5 | ||||||
|  | 
 | ||||||
| 	def get_ageing_data(self, entry_date, row): | 	def get_ageing_data(self, entry_date, row): | ||||||
| 		# [0-30, 30-60, 60-90, 90-120, 120-above] | 		# [0-30, 30-60, 60-90, 90-120, 120-above] | ||||||
| 		row.range1 = row.range2 = row.range3 = row.range4 = row.range5 = 0.0 | 		row.range1 = row.range2 = row.range3 = row.range4 = row.range5 = 0.0 | ||||||
|  | |||||||
| @ -82,6 +82,7 @@ class AccountsReceivableSummary(ReceivablePayableReport): | |||||||
| 			"range3": 0.0, | 			"range3": 0.0, | ||||||
| 			"range4": 0.0, | 			"range4": 0.0, | ||||||
| 			"range5": 0.0, | 			"range5": 0.0, | ||||||
|  | 			"total_due": 0.0, | ||||||
| 			"sales_person": [] | 			"sales_person": [] | ||||||
| 		})) | 		})) | ||||||
| 
 | 
 | ||||||
| @ -135,3 +136,6 @@ class AccountsReceivableSummary(ReceivablePayableReport): | |||||||
| 			"{range3}-{range4}".format(range3=cint(self.filters["range3"])+ 1, range4=self.filters["range4"]), | 			"{range3}-{range4}".format(range3=cint(self.filters["range3"])+ 1, range4=self.filters["range4"]), | ||||||
| 			"{range4}-{above}".format(range4=cint(self.filters["range4"])+ 1, above=_("Above"))]): | 			"{range4}-{above}".format(range4=cint(self.filters["range4"])+ 1, above=_("Above"))]): | ||||||
| 				self.add_column(label=label, fieldname='range' + str(i+1)) | 				self.add_column(label=label, fieldname='range' + str(i+1)) | ||||||
|  | 
 | ||||||
|  | 		# Add column for total due amount | ||||||
|  | 		self.add_column(label="Total Amount Due", fieldname='total_due') | ||||||
|  | |||||||
| @ -210,10 +210,10 @@ def get_data(companies, root_type, balance_must_be, fiscal_year, filters=None, i | |||||||
| 	company_currency = get_company_currency(filters) | 	company_currency = get_company_currency(filters) | ||||||
| 
 | 
 | ||||||
| 	if filters.filter_based_on == 'Fiscal Year': | 	if filters.filter_based_on == 'Fiscal Year': | ||||||
| 		start_date = fiscal_year.year_start_date | 		start_date = fiscal_year.year_start_date if filters.report != 'Balance Sheet' else None | ||||||
| 		end_date = fiscal_year.year_end_date | 		end_date = fiscal_year.year_end_date | ||||||
| 	else: | 	else: | ||||||
| 		start_date = filters.period_start_date | 		start_date = filters.period_start_date if filters.report != 'Balance Sheet' else None | ||||||
| 		end_date = filters.period_end_date | 		end_date = filters.period_end_date | ||||||
| 
 | 
 | ||||||
| 	gl_entries_by_account = {} | 	gl_entries_by_account = {} | ||||||
|  | |||||||
| @ -19,6 +19,7 @@ from erpnext.stock import get_warehouse_account_map | |||||||
| 
 | 
 | ||||||
| class StockValueAndAccountBalanceOutOfSync(frappe.ValidationError): pass | class StockValueAndAccountBalanceOutOfSync(frappe.ValidationError): pass | ||||||
| class FiscalYearError(frappe.ValidationError): pass | class FiscalYearError(frappe.ValidationError): pass | ||||||
|  | class PaymentEntryUnlinkError(frappe.ValidationError): pass | ||||||
| 
 | 
 | ||||||
| @frappe.whitelist() | @frappe.whitelist() | ||||||
| def get_fiscal_year(date=None, fiscal_year=None, label="Date", verbose=1, company=None, as_dict=False): | def get_fiscal_year(date=None, fiscal_year=None, label="Date", verbose=1, company=None, as_dict=False): | ||||||
| @ -555,10 +556,16 @@ def remove_ref_doc_link_from_pe(ref_type, ref_no): | |||||||
| 			and docstatus < 2""", (now(), frappe.session.user, ref_type, ref_no)) | 			and docstatus < 2""", (now(), frappe.session.user, ref_type, ref_no)) | ||||||
| 
 | 
 | ||||||
| 		for pe in linked_pe: | 		for pe in linked_pe: | ||||||
| 			pe_doc = frappe.get_doc("Payment Entry", pe) | 			try: | ||||||
| 			pe_doc.set_total_allocated_amount() | 				pe_doc = frappe.get_doc("Payment Entry", pe) | ||||||
| 			pe_doc.set_unallocated_amount() | 				pe_doc.set_amounts() | ||||||
| 			pe_doc.clear_unallocated_reference_document_rows() | 				pe_doc.clear_unallocated_reference_document_rows() | ||||||
|  | 				pe_doc.validate_payment_type_with_outstanding() | ||||||
|  | 			except Exception as e: | ||||||
|  | 				msg = _("There were issues unlinking payment entry {0}.").format(pe_doc.name) | ||||||
|  | 				msg += '<br>' | ||||||
|  | 				msg += _("Please cancel payment entry manually first") | ||||||
|  | 				frappe.throw(msg, exc=PaymentEntryUnlinkError, title=_("Payment Unlink Error")) | ||||||
| 
 | 
 | ||||||
| 			frappe.db.sql("""update `tabPayment Entry` set total_allocated_amount=%s, | 			frappe.db.sql("""update `tabPayment Entry` set total_allocated_amount=%s, | ||||||
| 				base_total_allocated_amount=%s, unallocated_amount=%s, modified=%s, modified_by=%s | 				base_total_allocated_amount=%s, unallocated_amount=%s, modified=%s, modified_by=%s | ||||||
|  | |||||||
| @ -565,6 +565,7 @@ | |||||||
|    "fieldname": "scan_barcode", |    "fieldname": "scan_barcode", | ||||||
|    "fieldtype": "Data", |    "fieldtype": "Data", | ||||||
|    "label": "Scan Barcode", |    "label": "Scan Barcode", | ||||||
|  |    "options": "Barcode", | ||||||
|    "show_days": 1, |    "show_days": 1, | ||||||
|    "show_seconds": 1 |    "show_seconds": 1 | ||||||
|   }, |   }, | ||||||
| @ -1378,7 +1379,7 @@ | |||||||
|  "idx": 105, |  "idx": 105, | ||||||
|  "is_submittable": 1, |  "is_submittable": 1, | ||||||
|  "links": [], |  "links": [], | ||||||
|  "modified": "2021-05-30 15:17:53.663648", |  "modified": "2021-08-17 20:16:12.737743", | ||||||
|  "modified_by": "Administrator", |  "modified_by": "Administrator", | ||||||
|  "module": "Buying", |  "module": "Buying", | ||||||
|  "name": "Purchase Order", |  "name": "Purchase Order", | ||||||
|  | |||||||
| @ -135,14 +135,9 @@ class AccountsController(TransactionBase): | |||||||
| 
 | 
 | ||||||
| 		validate_regional(self) | 		validate_regional(self) | ||||||
| 
 | 
 | ||||||
| 		validate_einvoice_fields(self) |  | ||||||
| 
 |  | ||||||
| 		if self.doctype != 'Material Request': | 		if self.doctype != 'Material Request': | ||||||
| 			apply_pricing_rule_on_transaction(self) | 			apply_pricing_rule_on_transaction(self) | ||||||
| 
 | 
 | ||||||
| 	def before_cancel(self): |  | ||||||
| 		validate_einvoice_fields(self) |  | ||||||
| 
 |  | ||||||
| 	def on_trash(self): | 	def on_trash(self): | ||||||
| 		# delete sl and gl entries on deletion of transaction | 		# delete sl and gl entries on deletion of transaction | ||||||
| 		if frappe.db.get_single_value('Accounts Settings', 'delete_linked_ledger_entries'): | 		if frappe.db.get_single_value('Accounts Settings', 'delete_linked_ledger_entries'): | ||||||
| @ -1975,7 +1970,3 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil | |||||||
| @erpnext.allow_regional | @erpnext.allow_regional | ||||||
| def validate_regional(doc): | def validate_regional(doc): | ||||||
| 	pass | 	pass | ||||||
| 
 |  | ||||||
| @erpnext.allow_regional |  | ||||||
| def validate_einvoice_fields(doc): |  | ||||||
| 	pass |  | ||||||
|  | |||||||
| @ -595,7 +595,8 @@ class calculate_taxes_and_totals(object): | |||||||
| 				self.doc.precision("outstanding_amount")) | 				self.doc.precision("outstanding_amount")) | ||||||
| 
 | 
 | ||||||
| 			if self.doc.doctype == 'Sales Invoice' and self.doc.get('is_pos') and self.doc.get('is_return'): | 			if self.doc.doctype == 'Sales Invoice' and self.doc.get('is_pos') and self.doc.get('is_return'): | ||||||
| 			 	self.update_paid_amount_for_return(total_amount_to_pay) | 				self.set_total_amount_to_default_mop(total_amount_to_pay) | ||||||
|  | 				self.calculate_paid_amount() | ||||||
| 
 | 
 | ||||||
| 	def calculate_paid_amount(self): | 	def calculate_paid_amount(self): | ||||||
| 
 | 
 | ||||||
| @ -675,7 +676,7 @@ class calculate_taxes_and_totals(object): | |||||||
| 	def set_item_wise_tax_breakup(self): | 	def set_item_wise_tax_breakup(self): | ||||||
| 		self.doc.other_charges_calculation = get_itemised_tax_breakup_html(self.doc) | 		self.doc.other_charges_calculation = get_itemised_tax_breakup_html(self.doc) | ||||||
| 
 | 
 | ||||||
| 	def update_paid_amount_for_return(self, total_amount_to_pay): | 	def set_total_amount_to_default_mop(self, total_amount_to_pay): | ||||||
| 		default_mode_of_payment = frappe.db.get_value('POS Payment Method', | 		default_mode_of_payment = frappe.db.get_value('POS Payment Method', | ||||||
| 			{'parent': self.doc.pos_profile, 'default': 1}, ['mode_of_payment'], as_dict=1) | 			{'parent': self.doc.pos_profile, 'default': 1}, ['mode_of_payment'], as_dict=1) | ||||||
| 
 | 
 | ||||||
| @ -685,9 +686,7 @@ class calculate_taxes_and_totals(object): | |||||||
| 				'mode_of_payment': default_mode_of_payment.mode_of_payment, | 				'mode_of_payment': default_mode_of_payment.mode_of_payment, | ||||||
| 				'amount': total_amount_to_pay, | 				'amount': total_amount_to_pay, | ||||||
| 				'default': 1 | 				'default': 1 | ||||||
| 			}) | 			})	 | ||||||
| 
 |  | ||||||
| 		self.calculate_paid_amount() |  | ||||||
| 
 | 
 | ||||||
| def get_itemised_tax_breakup_html(doc): | def get_itemised_tax_breakup_html(doc): | ||||||
| 	if not doc.taxes: | 	if not doc.taxes: | ||||||
|  | |||||||
| @ -251,7 +251,7 @@ doc_events = { | |||||||
| 			"erpnext.support.doctype.issue.issue.set_first_response_time" | 			"erpnext.support.doctype.issue.issue.set_first_response_time" | ||||||
| 		] | 		] | ||||||
| 	}, | 	}, | ||||||
| 	("Sales Taxes and Charges Template", 'Price List'): { | 	"Sales Taxes and Charges Template": { | ||||||
| 		"on_update": "erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings.validate_cart_settings" | 		"on_update": "erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings.validate_cart_settings" | ||||||
| 	}, | 	}, | ||||||
| 	"Website Settings": { | 	"Website Settings": { | ||||||
| @ -308,6 +308,9 @@ doc_events = { | |||||||
| 	}, | 	}, | ||||||
| 	('Quotation', 'Sales Order', 'Sales Invoice'): { | 	('Quotation', 'Sales Order', 'Sales Invoice'): { | ||||||
| 		'validate': ["erpnext.erpnext_integrations.taxjar_integration.set_sales_tax"] | 		'validate': ["erpnext.erpnext_integrations.taxjar_integration.set_sales_tax"] | ||||||
|  | 	}, | ||||||
|  | 	"Company": { | ||||||
|  | 		"on_trash": "erpnext.regional.india.utils.delete_gst_settings_for_company" | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -436,7 +439,6 @@ regional_overrides = { | |||||||
| 		'erpnext.controllers.taxes_and_totals.get_regional_round_off_accounts': 'erpnext.regional.india.utils.get_regional_round_off_accounts', | 		'erpnext.controllers.taxes_and_totals.get_regional_round_off_accounts': 'erpnext.regional.india.utils.get_regional_round_off_accounts', | ||||||
| 		'erpnext.hr.utils.calculate_annual_eligible_hra_exemption': 'erpnext.regional.india.utils.calculate_annual_eligible_hra_exemption', | 		'erpnext.hr.utils.calculate_annual_eligible_hra_exemption': 'erpnext.regional.india.utils.calculate_annual_eligible_hra_exemption', | ||||||
| 		'erpnext.hr.utils.calculate_hra_exemption_for_period': 'erpnext.regional.india.utils.calculate_hra_exemption_for_period', | 		'erpnext.hr.utils.calculate_hra_exemption_for_period': 'erpnext.regional.india.utils.calculate_hra_exemption_for_period', | ||||||
| 		'erpnext.controllers.accounts_controller.validate_einvoice_fields': 'erpnext.regional.india.e_invoice.utils.validate_einvoice_fields', |  | ||||||
| 		'erpnext.assets.doctype.asset.asset.get_depreciation_amount': 'erpnext.regional.india.utils.get_depreciation_amount', | 		'erpnext.assets.doctype.asset.asset.get_depreciation_amount': 'erpnext.regional.india.utils.get_depreciation_amount', | ||||||
| 		'erpnext.stock.doctype.item.item.set_item_tax_from_hsn_code': 'erpnext.regional.india.utils.set_item_tax_from_hsn_code' | 		'erpnext.stock.doctype.item.item.set_item_tax_from_hsn_code': 'erpnext.regional.india.utils.set_item_tax_from_hsn_code' | ||||||
| 	}, | 	}, | ||||||
|  | |||||||
| @ -235,7 +235,7 @@ frappe.ui.form.on("BOM", { | |||||||
| 						reqd: 1, | 						reqd: 1, | ||||||
| 					}, | 					}, | ||||||
| 					{ | 					{ | ||||||
| 						fieldname: "varint_item_code", | 						fieldname: "variant_item_code", | ||||||
| 						options: "Item", | 						options: "Item", | ||||||
| 						label: __("Variant Item"), | 						label: __("Variant Item"), | ||||||
| 						fieldtype: "Link", | 						fieldtype: "Link", | ||||||
| @ -287,7 +287,7 @@ frappe.ui.form.on("BOM", { | |||||||
| 			let variant_items = data.items || []; | 			let variant_items = data.items || []; | ||||||
| 
 | 
 | ||||||
| 			variant_items.forEach(d => { | 			variant_items.forEach(d => { | ||||||
| 				if (!d.varint_item_code) { | 				if (!d.variant_item_code) { | ||||||
| 					frappe.throw(__("Select variant item code for the template item {0}", [d.item_code])); | 					frappe.throw(__("Select variant item code for the template item {0}", [d.item_code])); | ||||||
| 				} | 				} | ||||||
| 			}) | 			}) | ||||||
| @ -299,7 +299,7 @@ frappe.ui.form.on("BOM", { | |||||||
| 		has_template_rm.forEach(d => { | 		has_template_rm.forEach(d => { | ||||||
| 			dialog.fields_dict.items.df.data.push({ | 			dialog.fields_dict.items.df.data.push({ | ||||||
| 				"item_code": d.item_code, | 				"item_code": d.item_code, | ||||||
| 				"varint_item_code": "", | 				"variant_item_code": "", | ||||||
| 				"qty": d.qty, | 				"qty": d.qty, | ||||||
| 				"source_warehouse": d.source_warehouse, | 				"source_warehouse": d.source_warehouse, | ||||||
| 				"operation": d.operation | 				"operation": d.operation | ||||||
|  | |||||||
| @ -297,7 +297,7 @@ class ProductionPlan(Document): | |||||||
| 
 | 
 | ||||||
| 		if self.total_produced_qty > 0: | 		if self.total_produced_qty > 0: | ||||||
| 			self.status = "In Process" | 			self.status = "In Process" | ||||||
| 			if self.total_produced_qty == self.total_planned_qty: | 			if self.total_produced_qty >= self.total_planned_qty: | ||||||
| 				self.status = "Completed" | 				self.status = "Completed" | ||||||
| 
 | 
 | ||||||
| 		if self.status != 'Completed': | 		if self.status != 'Completed': | ||||||
| @ -346,6 +346,7 @@ class ProductionPlan(Document): | |||||||
| 				"production_plan"       : self.name, | 				"production_plan"       : self.name, | ||||||
| 				"production_plan_item"  : d.name, | 				"production_plan_item"  : d.name, | ||||||
| 				"product_bundle_item"	: d.product_bundle_item, | 				"product_bundle_item"	: d.product_bundle_item, | ||||||
|  | 				"planned_start_date"    : d.planned_start_date, | ||||||
| 				"make_work_order_for_sub_assembly_items": d.get("make_work_order_for_sub_assembly_items", 0) | 				"make_work_order_for_sub_assembly_items": d.get("make_work_order_for_sub_assembly_items", 0) | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ from __future__ import unicode_literals | |||||||
| 
 | 
 | ||||||
| import frappe | import frappe | ||||||
| import unittest | import unittest | ||||||
| from frappe.utils import nowdate, now_datetime, flt | from frappe.utils import nowdate, now_datetime, flt, add_to_date | ||||||
| from erpnext.stock.doctype.item.test_item import create_item | from erpnext.stock.doctype.item.test_item import create_item | ||||||
| from erpnext.manufacturing.doctype.production_plan.production_plan import get_sales_orders | from erpnext.manufacturing.doctype.production_plan.production_plan import get_sales_orders | ||||||
| from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation | from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation | ||||||
| @ -61,6 +61,21 @@ class TestProductionPlan(unittest.TestCase): | |||||||
| 		pln = frappe.get_doc('Production Plan', pln.name) | 		pln = frappe.get_doc('Production Plan', pln.name) | ||||||
| 		pln.cancel() | 		pln.cancel() | ||||||
| 
 | 
 | ||||||
|  | 	def test_production_plan_start_date(self): | ||||||
|  | 		planned_date = add_to_date(date=None, days=3) | ||||||
|  | 		plan = create_production_plan(item_code='Test Production Item 1', planned_start_date=planned_date) | ||||||
|  | 		plan.make_work_order() | ||||||
|  | 
 | ||||||
|  | 		work_orders = frappe.get_all('Work Order', fields = ['name', 'planned_start_date'], | ||||||
|  | 			filters = {'production_plan': plan.name}) | ||||||
|  | 
 | ||||||
|  | 		self.assertEqual(work_orders[0].planned_start_date, planned_date) | ||||||
|  | 
 | ||||||
|  | 		for wo in work_orders: | ||||||
|  | 			frappe.delete_doc('Work Order', wo.name) | ||||||
|  | 
 | ||||||
|  | 		frappe.get_doc('Production Plan', plan.name).cancel() | ||||||
|  | 
 | ||||||
| 	def test_production_plan_for_existing_ordered_qty(self): | 	def test_production_plan_for_existing_ordered_qty(self): | ||||||
| 		sr1 = create_stock_reconciliation(item_code="Raw Material Item 1", | 		sr1 = create_stock_reconciliation(item_code="Raw Material Item 1", | ||||||
| 			target="_Test Warehouse - _TC", qty=1, rate=110) | 			target="_Test Warehouse - _TC", qty=1, rate=110) | ||||||
|  | |||||||
| @ -602,7 +602,7 @@ class WorkOrder(Document): | |||||||
| 
 | 
 | ||||||
| 		if self.docstatus==1: | 		if self.docstatus==1: | ||||||
| 			# calculate transferred qty based on submitted stock entries | 			# calculate transferred qty based on submitted stock entries | ||||||
| 			self.update_transaferred_qty_for_required_items() | 			self.update_transferred_qty_for_required_items() | ||||||
| 
 | 
 | ||||||
| 			# update in bin | 			# update in bin | ||||||
| 			self.update_reserved_qty_for_production() | 			self.update_reserved_qty_for_production() | ||||||
| @ -671,7 +671,7 @@ class WorkOrder(Document): | |||||||
| 
 | 
 | ||||||
| 			self.set_available_qty() | 			self.set_available_qty() | ||||||
| 
 | 
 | ||||||
| 	def update_transaferred_qty_for_required_items(self): | 	def update_transferred_qty_for_required_items(self): | ||||||
| 		'''update transferred qty from submitted stock entries for that item against | 		'''update transferred qty from submitted stock entries for that item against | ||||||
| 			the work order''' | 			the work order''' | ||||||
| 
 | 
 | ||||||
| @ -838,7 +838,7 @@ def add_variant_item(variant_items, wo_doc, bom_no, table_name="items"): | |||||||
| 
 | 
 | ||||||
| 	for item in variant_items: | 	for item in variant_items: | ||||||
| 		args = frappe._dict({ | 		args = frappe._dict({ | ||||||
| 			"item_code": item.get("varint_item_code"), | 			"item_code": item.get("variant_item_code"), | ||||||
| 			"required_qty": item.get("qty"), | 			"required_qty": item.get("qty"), | ||||||
| 			"qty": item.get("qty"), # for bom | 			"qty": item.get("qty"), # for bom | ||||||
| 			"source_warehouse": item.get("source_warehouse"), | 			"source_warehouse": item.get("source_warehouse"), | ||||||
| @ -859,7 +859,7 @@ def add_variant_item(variant_items, wo_doc, bom_no, table_name="items"): | |||||||
| 		}, bom_doc) | 		}, bom_doc) | ||||||
| 
 | 
 | ||||||
| 		if not args.source_warehouse: | 		if not args.source_warehouse: | ||||||
| 			args["source_warehouse"] = get_item_defaults(item.get("varint_item_code"), | 			args["source_warehouse"] = get_item_defaults(item.get("variant_item_code"), | ||||||
| 				wo_doc.company).default_warehouse | 				wo_doc.company).default_warehouse | ||||||
| 
 | 
 | ||||||
| 		args["amount"] = flt(args.get("required_qty")) * flt(args.get("rate")) | 		args["amount"] = flt(args.get("required_qty")) * flt(args.get("rate")) | ||||||
|  | |||||||
| @ -214,7 +214,6 @@ erpnext.patches.v13_0.delete_old_sales_reports | |||||||
| execute:frappe.delete_doc_if_exists("DocType", "Bank Reconciliation") | execute:frappe.delete_doc_if_exists("DocType", "Bank Reconciliation") | ||||||
| erpnext.patches.v13_0.move_doctype_reports_and_notification_from_hr_to_payroll #22-06-2020 | erpnext.patches.v13_0.move_doctype_reports_and_notification_from_hr_to_payroll #22-06-2020 | ||||||
| erpnext.patches.v13_0.move_payroll_setting_separately_from_hr_settings #22-06-2020 | erpnext.patches.v13_0.move_payroll_setting_separately_from_hr_settings #22-06-2020 | ||||||
| execute:frappe.reload_doc("regional", "doctype", "e_invoice_settings") |  | ||||||
| erpnext.patches.v13_0.check_is_income_tax_component #22-06-2020 | erpnext.patches.v13_0.check_is_income_tax_component #22-06-2020 | ||||||
| erpnext.patches.v13_0.loyalty_points_entry_for_pos_invoice #22-07-2020 | erpnext.patches.v13_0.loyalty_points_entry_for_pos_invoice #22-07-2020 | ||||||
| erpnext.patches.v12_0.add_taxjar_integration_field | erpnext.patches.v12_0.add_taxjar_integration_field | ||||||
| @ -237,7 +236,6 @@ erpnext.patches.v13_0.set_app_name | |||||||
| erpnext.patches.v13_0.print_uom_after_quantity_patch | erpnext.patches.v13_0.print_uom_after_quantity_patch | ||||||
| erpnext.patches.v13_0.set_payment_channel_in_payment_gateway_account | erpnext.patches.v13_0.set_payment_channel_in_payment_gateway_account | ||||||
| erpnext.patches.v13_0.create_healthcare_custom_fields_in_stock_entry_detail | erpnext.patches.v13_0.create_healthcare_custom_fields_in_stock_entry_detail | ||||||
| erpnext.patches.v12_0.setup_einvoice_fields #2020-12-02 |  | ||||||
| erpnext.patches.v13_0.updates_for_multi_currency_payroll | erpnext.patches.v13_0.updates_for_multi_currency_payroll | ||||||
| erpnext.patches.v13_0.update_reason_for_resignation_in_employee | erpnext.patches.v13_0.update_reason_for_resignation_in_employee | ||||||
| execute:frappe.delete_doc("Report", "Quoted Item Comparison") | execute:frappe.delete_doc("Report", "Quoted Item Comparison") | ||||||
| @ -259,14 +257,11 @@ erpnext.patches.v12_0.add_state_code_for_ladakh | |||||||
| erpnext.patches.v13_0.item_reposting_for_incorrect_sl_and_gl | erpnext.patches.v13_0.item_reposting_for_incorrect_sl_and_gl | ||||||
| erpnext.patches.v13_0.delete_old_bank_reconciliation_doctypes | erpnext.patches.v13_0.delete_old_bank_reconciliation_doctypes | ||||||
| erpnext.patches.v12_0.update_vehicle_no_reqd_condition | erpnext.patches.v12_0.update_vehicle_no_reqd_condition | ||||||
| erpnext.patches.v12_0.add_einvoice_status_field #2021-03-17 |  | ||||||
| erpnext.patches.v12_0.add_einvoice_summary_report_permissions |  | ||||||
| erpnext.patches.v13_0.setup_fields_for_80g_certificate_and_donation | erpnext.patches.v13_0.setup_fields_for_80g_certificate_and_donation | ||||||
| erpnext.patches.v13_0.rename_membership_settings_to_non_profit_settings | erpnext.patches.v13_0.rename_membership_settings_to_non_profit_settings | ||||||
| erpnext.patches.v13_0.setup_gratuity_rule_for_india_and_uae | erpnext.patches.v13_0.setup_gratuity_rule_for_india_and_uae | ||||||
| erpnext.patches.v13_0.setup_uae_vat_fields | erpnext.patches.v13_0.setup_uae_vat_fields | ||||||
| execute:frappe.db.set_value('System Settings', None, 'app_name', 'ERPNext') | execute:frappe.db.set_value('System Settings', None, 'app_name', 'ERPNext') | ||||||
| erpnext.patches.v12_0.add_company_link_to_einvoice_settings |  | ||||||
| erpnext.patches.v13_0.rename_discharge_date_in_ip_record | erpnext.patches.v13_0.rename_discharge_date_in_ip_record | ||||||
| erpnext.patches.v12_0.create_taxable_value_field | erpnext.patches.v12_0.create_taxable_value_field | ||||||
| erpnext.patches.v12_0.add_gst_category_in_delivery_note | erpnext.patches.v12_0.add_gst_category_in_delivery_note | ||||||
| @ -277,7 +272,6 @@ erpnext.patches.v12_0.add_document_type_field_for_italy_einvoicing | |||||||
| erpnext.patches.v13_0.make_non_standard_user_type #13-04-2021 | erpnext.patches.v13_0.make_non_standard_user_type #13-04-2021 | ||||||
| erpnext.patches.v13_0.update_shipment_status | erpnext.patches.v13_0.update_shipment_status | ||||||
| erpnext.patches.v13_0.remove_attribute_field_from_item_variant_setting | erpnext.patches.v13_0.remove_attribute_field_from_item_variant_setting | ||||||
| erpnext.patches.v12_0.add_ewaybill_validity_field |  | ||||||
| erpnext.patches.v13_0.germany_make_custom_fields | erpnext.patches.v13_0.germany_make_custom_fields | ||||||
| erpnext.patches.v13_0.germany_fill_debtor_creditor_number | erpnext.patches.v13_0.germany_fill_debtor_creditor_number | ||||||
| erpnext.patches.v13_0.set_pos_closing_as_failed | erpnext.patches.v13_0.set_pos_closing_as_failed | ||||||
| @ -294,10 +288,11 @@ erpnext.patches.v13_0.update_level_in_bom #1234sswef | |||||||
| erpnext.patches.v13_0.add_missing_fg_item_for_stock_entry | erpnext.patches.v13_0.add_missing_fg_item_for_stock_entry | ||||||
| erpnext.patches.v13_0.update_subscription_status_in_memberships | erpnext.patches.v13_0.update_subscription_status_in_memberships | ||||||
| erpnext.patches.v13_0.update_amt_in_work_order_required_items | erpnext.patches.v13_0.update_amt_in_work_order_required_items | ||||||
| erpnext.patches.v12_0.show_einvoice_irn_cancelled_field |  | ||||||
| erpnext.patches.v13_0.delete_orphaned_tables | erpnext.patches.v13_0.delete_orphaned_tables | ||||||
| erpnext.patches.v13_0.update_export_type_for_gst #2021-08-16 | erpnext.patches.v13_0.update_export_type_for_gst #2021-08-16 | ||||||
| erpnext.patches.v13_0.update_tds_check_field #3 | erpnext.patches.v13_0.update_tds_check_field #3 | ||||||
| erpnext.patches.v13_0.add_custom_field_for_south_africa #2 | erpnext.patches.v13_0.add_custom_field_for_south_africa #2 | ||||||
| erpnext.patches.v13_0.update_recipient_email_digest | erpnext.patches.v13_0.update_recipient_email_digest | ||||||
| erpnext.patches.v13_0.shopify_deprecation_warning | erpnext.patches.v13_0.shopify_deprecation_warning | ||||||
|  | erpnext.patches.v13_0.einvoicing_deprecation_warning | ||||||
|  | erpnext.patches.v14_0.delete_einvoicing_doctypes | ||||||
|  | |||||||
| @ -1,16 +0,0 @@ | |||||||
| from __future__ import unicode_literals |  | ||||||
| import frappe |  | ||||||
| 
 |  | ||||||
| def execute(): |  | ||||||
| 	company = frappe.get_all('Company', filters = {'country': 'India'}) |  | ||||||
| 	if not company or not frappe.db.count('E Invoice User'): |  | ||||||
| 		return |  | ||||||
| 
 |  | ||||||
| 	frappe.reload_doc("regional", "doctype", "e_invoice_user") |  | ||||||
| 	for creds in frappe.db.get_all('E Invoice User', fields=['name', 'gstin']): |  | ||||||
| 		company_name = frappe.db.sql(""" |  | ||||||
| 			select dl.link_name from `tabAddress` a, `tabDynamic Link` dl |  | ||||||
| 			where a.gstin = %s and dl.parent = a.name and dl.link_doctype = 'Company' |  | ||||||
| 		""", (creds.get('gstin'))) |  | ||||||
| 		if company_name and len(company_name) > 0: |  | ||||||
| 			frappe.db.set_value('E Invoice User', creds.get('name'), 'company', company_name[0][0]) |  | ||||||
| @ -1,69 +0,0 @@ | |||||||
| from __future__ import unicode_literals |  | ||||||
| import json |  | ||||||
| import frappe |  | ||||||
| from frappe.custom.doctype.custom_field.custom_field import create_custom_fields |  | ||||||
| 
 |  | ||||||
| def execute(): |  | ||||||
| 	company = frappe.get_all('Company', filters = {'country': 'India'}) |  | ||||||
| 	if not company: |  | ||||||
| 		return |  | ||||||
| 
 |  | ||||||
| 	# move hidden einvoice fields to a different section |  | ||||||
| 	custom_fields = { |  | ||||||
| 		'Sales Invoice': [ |  | ||||||
| 			dict(fieldname='einvoice_section', label='E-Invoice Fields', fieldtype='Section Break', insert_after='gst_vehicle_type', |  | ||||||
| 			print_hide=1, hidden=1), |  | ||||||
| 
 |  | ||||||
| 			dict(fieldname='ack_no', label='Ack. No.', fieldtype='Data', read_only=1, hidden=1, insert_after='einvoice_section', |  | ||||||
| 				no_copy=1, print_hide=1), |  | ||||||
| 
 |  | ||||||
| 			dict(fieldname='ack_date', label='Ack. Date', fieldtype='Data', read_only=1, hidden=1, insert_after='ack_no', no_copy=1, print_hide=1), |  | ||||||
| 
 |  | ||||||
| 			dict(fieldname='irn_cancel_date', label='Cancel Date', fieldtype='Data', read_only=1, hidden=1, insert_after='ack_date', |  | ||||||
| 				no_copy=1, print_hide=1), |  | ||||||
| 
 |  | ||||||
| 			dict(fieldname='signed_einvoice', label='Signed E-Invoice', fieldtype='Code', options='JSON', hidden=1, insert_after='irn_cancel_date', |  | ||||||
| 				no_copy=1, print_hide=1, read_only=1), |  | ||||||
| 
 |  | ||||||
| 			dict(fieldname='signed_qr_code', label='Signed QRCode', fieldtype='Code', options='JSON', hidden=1, insert_after='signed_einvoice', |  | ||||||
| 				no_copy=1, print_hide=1, read_only=1), |  | ||||||
| 
 |  | ||||||
| 			dict(fieldname='qrcode_image', label='QRCode', fieldtype='Attach Image', hidden=1, insert_after='signed_qr_code', |  | ||||||
| 				no_copy=1, print_hide=1, read_only=1), |  | ||||||
| 
 |  | ||||||
| 			dict(fieldname='einvoice_status', label='E-Invoice Status', fieldtype='Select', insert_after='qrcode_image', |  | ||||||
| 				options='\nPending\nGenerated\nCancelled\nFailed', default=None, hidden=1, no_copy=1, print_hide=1, read_only=1), |  | ||||||
| 
 |  | ||||||
| 			dict(fieldname='failure_description', label='E-Invoice Failure Description', fieldtype='Code', options='JSON', |  | ||||||
| 				hidden=1, insert_after='einvoice_status', no_copy=1, print_hide=1, read_only=1) |  | ||||||
| 		] |  | ||||||
| 	} |  | ||||||
| 	create_custom_fields(custom_fields, update=True) |  | ||||||
| 
 |  | ||||||
| 	if frappe.db.exists('E Invoice Settings') and frappe.db.get_single_value('E Invoice Settings', 'enable'): |  | ||||||
| 		frappe.db.sql(''' |  | ||||||
| 			UPDATE `tabSales Invoice` SET einvoice_status = 'Pending' |  | ||||||
| 			WHERE |  | ||||||
| 				posting_date >= '2021-04-01' |  | ||||||
| 				AND ifnull(irn, '') = '' |  | ||||||
| 				AND ifnull(`billing_address_gstin`, '') != ifnull(`company_gstin`, '') |  | ||||||
| 				AND ifnull(gst_category, '') in ('Registered Regular', 'SEZ', 'Overseas', 'Deemed Export') |  | ||||||
| 		''') |  | ||||||
| 
 |  | ||||||
| 		# set appropriate statuses |  | ||||||
| 		frappe.db.sql('''UPDATE `tabSales Invoice` SET einvoice_status = 'Generated' |  | ||||||
| 			WHERE ifnull(irn, '') != '' AND ifnull(irn_cancelled, 0) = 0''') |  | ||||||
| 
 |  | ||||||
| 		frappe.db.sql('''UPDATE `tabSales Invoice` SET einvoice_status = 'Cancelled' |  | ||||||
| 			WHERE ifnull(irn_cancelled, 0) = 1''') |  | ||||||
| 
 |  | ||||||
| 	# set correct acknowledgement in e-invoices |  | ||||||
| 	einvoices = frappe.get_all('Sales Invoice', {'irn': ['is', 'set']}, ['name', 'signed_einvoice']) |  | ||||||
| 
 |  | ||||||
| 	if einvoices: |  | ||||||
| 		for inv in einvoices: |  | ||||||
| 			signed_einvoice = inv.get('signed_einvoice') |  | ||||||
| 			if signed_einvoice: |  | ||||||
| 				signed_einvoice = json.loads(signed_einvoice) |  | ||||||
| 				frappe.db.set_value('Sales Invoice', inv.get('name'), 'ack_no', signed_einvoice.get('AckNo'), update_modified=False) |  | ||||||
| 				frappe.db.set_value('Sales Invoice', inv.get('name'), 'ack_date', signed_einvoice.get('AckDt'), update_modified=False) |  | ||||||
| @ -1,18 +0,0 @@ | |||||||
| from __future__ import unicode_literals |  | ||||||
| import frappe |  | ||||||
| 
 |  | ||||||
| def execute(): |  | ||||||
| 	company = frappe.get_all('Company', filters = {'country': 'India'}) |  | ||||||
| 	if not company: |  | ||||||
| 		return |  | ||||||
| 
 |  | ||||||
| 	if frappe.db.exists('Report', 'E-Invoice Summary') and \ |  | ||||||
| 		not frappe.db.get_value('Custom Role', dict(report='E-Invoice Summary')): |  | ||||||
| 		frappe.get_doc(dict( |  | ||||||
| 			doctype='Custom Role', |  | ||||||
| 			report='E-Invoice Summary', |  | ||||||
| 			roles= [ |  | ||||||
| 				dict(role='Accounts User'), |  | ||||||
| 				dict(role='Accounts Manager') |  | ||||||
| 			] |  | ||||||
| 		)).insert() |  | ||||||
| @ -1,16 +0,0 @@ | |||||||
| from __future__ import unicode_literals |  | ||||||
| import frappe |  | ||||||
| from frappe.custom.doctype.custom_field.custom_field import create_custom_fields |  | ||||||
| 
 |  | ||||||
| def execute(): |  | ||||||
| 	company = frappe.get_all('Company', filters = {'country': 'India'}) |  | ||||||
| 	if not company: |  | ||||||
| 		return |  | ||||||
| 
 |  | ||||||
| 	custom_fields = { |  | ||||||
| 		'Sales Invoice': [ |  | ||||||
| 			dict(fieldname='eway_bill_validity', label='E-Way Bill Validity', fieldtype='Data', no_copy=1, print_hide=1, |  | ||||||
| 				depends_on='ewaybill', read_only=1, allow_on_submit=1, insert_after='ewaybill') |  | ||||||
| 		] |  | ||||||
| 	} |  | ||||||
| 	create_custom_fields(custom_fields, update=True) |  | ||||||
| @ -1,56 +0,0 @@ | |||||||
| from __future__ import unicode_literals |  | ||||||
| import frappe |  | ||||||
| from frappe.custom.doctype.custom_field.custom_field import create_custom_fields |  | ||||||
| from erpnext.regional.india.setup import add_permissions, add_print_formats |  | ||||||
| 
 |  | ||||||
| def execute(): |  | ||||||
| 	company = frappe.get_all('Company', filters = {'country': 'India'}) |  | ||||||
| 	if not company: |  | ||||||
| 		return |  | ||||||
| 
 |  | ||||||
| 	frappe.reload_doc("custom", "doctype", "custom_field") |  | ||||||
| 	frappe.reload_doc("regional", "doctype", "e_invoice_settings") |  | ||||||
| 	custom_fields = { |  | ||||||
| 		'Sales Invoice': [ |  | ||||||
| 			dict(fieldname='irn', label='IRN', fieldtype='Data', read_only=1, insert_after='customer', no_copy=1, print_hide=1, |  | ||||||
| 				depends_on='eval:in_list(["Registered Regular", "SEZ", "Overseas", "Deemed Export"], doc.gst_category) && doc.irn_cancelled === 0'), |  | ||||||
| 
 |  | ||||||
| 			dict(fieldname='ack_no', label='Ack. No.', fieldtype='Data', read_only=1, hidden=1, insert_after='irn', no_copy=1, print_hide=1), |  | ||||||
| 
 |  | ||||||
| 			dict(fieldname='ack_date', label='Ack. Date', fieldtype='Data', read_only=1, hidden=1, insert_after='ack_no', no_copy=1, print_hide=1), |  | ||||||
| 
 |  | ||||||
| 			dict(fieldname='irn_cancelled', label='IRN Cancelled', fieldtype='Check', no_copy=1, print_hide=1, |  | ||||||
| 				depends_on='eval:(doc.irn_cancelled === 1)', read_only=1, allow_on_submit=1, insert_after='customer'), |  | ||||||
| 
 |  | ||||||
| 			dict(fieldname='eway_bill_cancelled', label='E-Way Bill Cancelled', fieldtype='Check', no_copy=1, print_hide=1, |  | ||||||
| 				depends_on='eval:(doc.eway_bill_cancelled === 1)', read_only=1, allow_on_submit=1, insert_after='customer'), |  | ||||||
| 
 |  | ||||||
| 			dict(fieldname='signed_einvoice', fieldtype='Code', options='JSON', hidden=1, no_copy=1, print_hide=1, read_only=1), |  | ||||||
| 
 |  | ||||||
| 			dict(fieldname='signed_qr_code', fieldtype='Code', options='JSON', hidden=1, no_copy=1, print_hide=1, read_only=1), |  | ||||||
| 
 |  | ||||||
| 			dict(fieldname='qrcode_image', label='QRCode', fieldtype='Attach Image', hidden=1, no_copy=1, print_hide=1, read_only=1) |  | ||||||
| 		] |  | ||||||
| 	} |  | ||||||
| 	create_custom_fields(custom_fields, update=True) |  | ||||||
| 	add_permissions() |  | ||||||
| 	add_print_formats() |  | ||||||
| 
 |  | ||||||
| 	einvoice_cond = 'in_list(["Registered Regular", "SEZ", "Overseas", "Deemed Export"], doc.gst_category)' |  | ||||||
| 	t = { |  | ||||||
| 		'mode_of_transport': [{'default': None}], |  | ||||||
| 		'distance': [{'mandatory_depends_on': f'eval:{einvoice_cond} && doc.transporter'}], |  | ||||||
| 		'gst_vehicle_type': [{'mandatory_depends_on': f'eval:{einvoice_cond} && doc.mode_of_transport == "Road"'}], |  | ||||||
| 		'lr_date': [{'mandatory_depends_on': f'eval:{einvoice_cond} && in_list(["Air", "Ship", "Rail"], doc.mode_of_transport)'}], |  | ||||||
| 		'lr_no': [{'mandatory_depends_on': f'eval:{einvoice_cond} && in_list(["Air", "Ship", "Rail"], doc.mode_of_transport)'}], |  | ||||||
| 		'vehicle_no': [{'mandatory_depends_on': f'eval:{einvoice_cond} && doc.mode_of_transport == "Road"'}], |  | ||||||
| 		'ewaybill': [ |  | ||||||
| 			{'read_only_depends_on': 'eval:doc.irn && doc.ewaybill'}, |  | ||||||
| 			{'depends_on': 'eval:((doc.docstatus === 1 || doc.ewaybill) && doc.eway_bill_cancelled === 0)'} |  | ||||||
| 		] |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	for field, conditions in t.items(): |  | ||||||
| 		for c in conditions: |  | ||||||
| 			[(prop, value)] = c.items() |  | ||||||
| 			frappe.db.set_value('Custom Field', { 'fieldname': field }, prop, value) |  | ||||||
| @ -1,12 +0,0 @@ | |||||||
| from __future__ import unicode_literals |  | ||||||
| import frappe |  | ||||||
| 
 |  | ||||||
| def execute(): |  | ||||||
| 	company = frappe.get_all('Company', filters = {'country': 'India'}) |  | ||||||
| 	if not company: |  | ||||||
| 		return |  | ||||||
| 
 |  | ||||||
| 	irn_cancelled_field = frappe.db.exists('Custom Field', {'dt': 'Sales Invoice', 'fieldname': 'irn_cancelled'}) |  | ||||||
| 	if irn_cancelled_field: |  | ||||||
| 		frappe.db.set_value('Custom Field', irn_cancelled_field, 'depends_on', 'eval: doc.irn') |  | ||||||
| 		frappe.db.set_value('Custom Field', irn_cancelled_field, 'read_only', 0) |  | ||||||
							
								
								
									
										9
									
								
								erpnext/patches/v13_0/einvoicing_deprecation_warning.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								erpnext/patches/v13_0/einvoicing_deprecation_warning.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | import click | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def execute(): | ||||||
|  | 	click.secho( | ||||||
|  | 		"Indian E-Invoicing integration is moved to a separate app and will be removed from ERPNext in version-14.\n" | ||||||
|  | 		"Please install the app to continue using the integration: https://github.com/frappe/erpnext_gst_compliance", | ||||||
|  | 		fg="yellow", | ||||||
|  | 	) | ||||||
							
								
								
									
										9
									
								
								erpnext/patches/v14_0/delete_einvoicing_doctypes.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								erpnext/patches/v14_0/delete_einvoicing_doctypes.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | import frappe | ||||||
|  | 
 | ||||||
|  | def execute(): | ||||||
|  | 	frappe.delete_doc('DocType', 'E Invoice Settings', ignore_missing=True) | ||||||
|  | 	frappe.delete_doc('DocType', 'E Invoice User', ignore_missing=True) | ||||||
|  | 	frappe.delete_doc('Report', 'E-Invoice Summary', ignore_missing=True) | ||||||
|  | 	frappe.delete_doc('Print Format', 'GST E-Invoice', ignore_missing=True) | ||||||
|  | 	frappe.delete_doc('Custom Field', 'Sales Invoice-eway_bill_cancelled', ignore_missing=True) | ||||||
|  | 	frappe.delete_doc('Custom Field', 'Sales Invoice-irn_cancelled', ignore_missing=True) | ||||||
| @ -4,18 +4,11 @@ | |||||||
| frappe.ui.form.on('Salary Component', { | frappe.ui.form.on('Salary Component', { | ||||||
| 	setup: function(frm) { | 	setup: function(frm) { | ||||||
| 		frm.set_query("account", "accounts", function(doc, cdt, cdn) { | 		frm.set_query("account", "accounts", function(doc, cdt, cdn) { | ||||||
| 			let d = frappe.get_doc(cdt, cdn); | 			var d = locals[cdt][cdn]; | ||||||
| 
 |  | ||||||
| 			let root_type = "Liability"; |  | ||||||
| 			if (frm.doc.type == "Deduction") { |  | ||||||
| 				root_type = "Expense"; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			return { | 			return { | ||||||
| 				filters: { | 				filters: { | ||||||
| 					"is_group": 0, | 					"is_group": 0, | ||||||
| 					"company": d.company, | 					"company": d.company | ||||||
| 					"root_type": root_type |  | ||||||
| 				} | 				} | ||||||
| 			}; | 			}; | ||||||
| 		}); | 		}); | ||||||
|  | |||||||
| @ -754,8 +754,6 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments { | |||||||
| 			} | 			} | ||||||
| 		}); | 		}); | ||||||
| 		this.frm.refresh_fields(); | 		this.frm.refresh_fields(); | ||||||
| 
 |  | ||||||
| 		this.calculate_paid_amount(); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	set_default_payment(total_amount_to_pay, update_paid_amount) { | 	set_default_payment(total_amount_to_pay, update_paid_amount) { | ||||||
|  | |||||||
| @ -342,30 +342,6 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe | |||||||
| 		this.set_dynamic_labels(); | 		this.set_dynamic_labels(); | ||||||
| 		this.setup_sms(); | 		this.setup_sms(); | ||||||
| 		this.setup_quality_inspection(); | 		this.setup_quality_inspection(); | ||||||
| 		let scan_barcode_field = this.frm.get_field('scan_barcode'); |  | ||||||
| 		if (scan_barcode_field && scan_barcode_field.get_value()) { |  | ||||||
| 			scan_barcode_field.set_value(""); |  | ||||||
| 			scan_barcode_field.set_new_description(""); |  | ||||||
| 
 |  | ||||||
| 			if (frappe.is_mobile()) { |  | ||||||
| 				if (scan_barcode_field.$input_wrapper.find('.input-group').length) return; |  | ||||||
| 
 |  | ||||||
| 				let $input_group = $('<div class="input-group">'); |  | ||||||
| 				scan_barcode_field.$input_wrapper.find('.control-input').append($input_group); |  | ||||||
| 				$input_group.append(scan_barcode_field.$input); |  | ||||||
| 				$(`<span class="input-group-btn" style="vertical-align: top">
 |  | ||||||
| 						<button class="btn btn-default border" type="button"> |  | ||||||
| 							<i class="fa fa-camera text-muted"></i> |  | ||||||
| 						</button> |  | ||||||
| 					</span>`) |  | ||||||
| 					.on('click', '.btn', () => { |  | ||||||
| 						frappe.barcode.scan_barcode().then(barcode => { |  | ||||||
| 							scan_barcode_field.set_value(barcode); |  | ||||||
| 						}); |  | ||||||
| 					}) |  | ||||||
| 					.appendTo($input_group); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	scan_barcode() { | 	scan_barcode() { | ||||||
|  | |||||||
| @ -1,8 +0,0 @@ | |||||||
| // Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
 |  | ||||||
| // For license information, please see license.txt
 |  | ||||||
| 
 |  | ||||||
| frappe.ui.form.on('E Invoice Request Log', { |  | ||||||
| 	// refresh: function(frm) {
 |  | ||||||
| 
 |  | ||||||
| 	// }
 |  | ||||||
| }); |  | ||||||
| @ -1,102 +0,0 @@ | |||||||
| { |  | ||||||
|  "actions": [], |  | ||||||
|  "autoname": "EINV-REQ-.#####", |  | ||||||
|  "creation": "2020-12-08 12:54:08.175992", |  | ||||||
|  "doctype": "DocType", |  | ||||||
|  "editable_grid": 1, |  | ||||||
|  "engine": "InnoDB", |  | ||||||
|  "field_order": [ |  | ||||||
|   "user", |  | ||||||
|   "url", |  | ||||||
|   "headers", |  | ||||||
|   "response", |  | ||||||
|   "column_break_7", |  | ||||||
|   "timestamp", |  | ||||||
|   "reference_invoice", |  | ||||||
|   "data" |  | ||||||
|  ], |  | ||||||
|  "fields": [ |  | ||||||
|   { |  | ||||||
|    "fieldname": "user", |  | ||||||
|    "fieldtype": "Link", |  | ||||||
|    "label": "User", |  | ||||||
|    "options": "User" |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|    "fieldname": "reference_invoice", |  | ||||||
|    "fieldtype": "Data", |  | ||||||
|    "label": "Reference Invoice" |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|    "fieldname": "headers", |  | ||||||
|    "fieldtype": "Code", |  | ||||||
|    "label": "Headers", |  | ||||||
|    "options": "JSON" |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|    "fieldname": "data", |  | ||||||
|    "fieldtype": "Code", |  | ||||||
|    "label": "Data", |  | ||||||
|    "options": "JSON" |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|    "default": "Now", |  | ||||||
|    "fieldname": "timestamp", |  | ||||||
|    "fieldtype": "Datetime", |  | ||||||
|    "label": "Timestamp" |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|    "fieldname": "response", |  | ||||||
|    "fieldtype": "Code", |  | ||||||
|    "label": "Response", |  | ||||||
|    "options": "JSON" |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|    "fieldname": "url", |  | ||||||
|    "fieldtype": "Data", |  | ||||||
|    "label": "URL" |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|    "fieldname": "column_break_7", |  | ||||||
|    "fieldtype": "Column Break" |  | ||||||
|   } |  | ||||||
|  ], |  | ||||||
|  "index_web_pages_for_search": 1, |  | ||||||
|  "links": [], |  | ||||||
|  "modified": "2021-01-13 12:06:57.253111", |  | ||||||
|  "modified_by": "Administrator", |  | ||||||
|  "module": "Regional", |  | ||||||
|  "name": "E Invoice Request Log", |  | ||||||
|  "owner": "Administrator", |  | ||||||
|  "permissions": [ |  | ||||||
|   { |  | ||||||
|    "email": 1, |  | ||||||
|    "export": 1, |  | ||||||
|    "print": 1, |  | ||||||
|    "read": 1, |  | ||||||
|    "report": 1, |  | ||||||
|    "role": "System Manager", |  | ||||||
|    "share": 1 |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|    "email": 1, |  | ||||||
|    "export": 1, |  | ||||||
|    "print": 1, |  | ||||||
|    "read": 1, |  | ||||||
|    "report": 1, |  | ||||||
|    "role": "Accounts User", |  | ||||||
|    "share": 1 |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|    "email": 1, |  | ||||||
|    "export": 1, |  | ||||||
|    "print": 1, |  | ||||||
|    "read": 1, |  | ||||||
|    "report": 1, |  | ||||||
|    "role": "Accounts Manager", |  | ||||||
|    "share": 1 |  | ||||||
|   } |  | ||||||
|  ], |  | ||||||
|  "sort_field": "modified", |  | ||||||
|  "sort_order": "DESC" |  | ||||||
| } |  | ||||||
| @ -1,10 +0,0 @@ | |||||||
| # -*- coding: utf-8 -*- |  | ||||||
| # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors |  | ||||||
| # For license information, please see license.txt |  | ||||||
| 
 |  | ||||||
| from __future__ import unicode_literals |  | ||||||
| # import frappe |  | ||||||
| from frappe.model.document import Document |  | ||||||
| 
 |  | ||||||
| class EInvoiceRequestLog(Document): |  | ||||||
| 	pass |  | ||||||
| @ -1,10 +0,0 @@ | |||||||
| # -*- coding: utf-8 -*- |  | ||||||
| # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors |  | ||||||
| # See license.txt |  | ||||||
| from __future__ import unicode_literals |  | ||||||
| 
 |  | ||||||
| # import frappe |  | ||||||
| import unittest |  | ||||||
| 
 |  | ||||||
| class TestEInvoiceRequestLog(unittest.TestCase): |  | ||||||
| 	pass |  | ||||||
| @ -1,11 +0,0 @@ | |||||||
| // Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
 |  | ||||||
| // For license information, please see license.txt
 |  | ||||||
| 
 |  | ||||||
| frappe.ui.form.on('E Invoice Settings', { |  | ||||||
| 	refresh(frm) { |  | ||||||
| 		const docs_link = 'https://docs.erpnext.com/docs/v13/user/manual/en/regional/india/setup-e-invoicing'; |  | ||||||
| 		frm.dashboard.set_headline( |  | ||||||
| 			__("Read {0} for more information on E Invoicing features.", [`<a href='${docs_link}'>documentation</a>`]) |  | ||||||
| 		); |  | ||||||
| 	} |  | ||||||
| }); |  | ||||||
| @ -1,73 +0,0 @@ | |||||||
| { |  | ||||||
|  "actions": [], |  | ||||||
|  "creation": "2020-09-24 16:23:16.235722", |  | ||||||
|  "doctype": "DocType", |  | ||||||
|  "editable_grid": 1, |  | ||||||
|  "engine": "InnoDB", |  | ||||||
|  "field_order": [ |  | ||||||
|   "enable", |  | ||||||
|   "section_break_2", |  | ||||||
|   "sandbox_mode", |  | ||||||
|   "applicable_from", |  | ||||||
|   "credentials", |  | ||||||
|   "auth_token", |  | ||||||
|   "token_expiry" |  | ||||||
|  ], |  | ||||||
|  "fields": [ |  | ||||||
|   { |  | ||||||
|    "default": "0", |  | ||||||
|    "fieldname": "enable", |  | ||||||
|    "fieldtype": "Check", |  | ||||||
|    "label": "Enable" |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|    "depends_on": "enable", |  | ||||||
|    "fieldname": "section_break_2", |  | ||||||
|    "fieldtype": "Section Break" |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|    "fieldname": "auth_token", |  | ||||||
|    "fieldtype": "Data", |  | ||||||
|    "hidden": 1, |  | ||||||
|    "read_only": 1 |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|    "fieldname": "token_expiry", |  | ||||||
|    "fieldtype": "Datetime", |  | ||||||
|    "hidden": 1, |  | ||||||
|    "read_only": 1 |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|    "fieldname": "credentials", |  | ||||||
|    "fieldtype": "Table", |  | ||||||
|    "label": "Credentials", |  | ||||||
|    "mandatory_depends_on": "enable", |  | ||||||
|    "options": "E Invoice User" |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|    "default": "0", |  | ||||||
|    "fieldname": "sandbox_mode", |  | ||||||
|    "fieldtype": "Check", |  | ||||||
|    "label": "Sandbox Mode" |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|    "fieldname": "applicable_from", |  | ||||||
|    "fieldtype": "Date", |  | ||||||
|    "in_list_view": 1, |  | ||||||
|    "label": "Applicable From", |  | ||||||
|    "reqd": 1 |  | ||||||
|   } |  | ||||||
|  ], |  | ||||||
|  "index_web_pages_for_search": 1, |  | ||||||
|  "issingle": 1, |  | ||||||
|  "links": [], |  | ||||||
|  "modified": "2021-03-30 12:26:25.538294", |  | ||||||
|  "modified_by": "Administrator", |  | ||||||
|  "module": "Regional", |  | ||||||
|  "name": "E Invoice Settings", |  | ||||||
|  "owner": "Administrator", |  | ||||||
|  "permissions": [], |  | ||||||
|  "sort_field": "modified", |  | ||||||
|  "sort_order": "DESC", |  | ||||||
|  "track_changes": 1 |  | ||||||
| } |  | ||||||
| @ -1,13 +0,0 @@ | |||||||
| # -*- coding: utf-8 -*- |  | ||||||
| # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors |  | ||||||
| # For license information, please see license.txt |  | ||||||
| from __future__ import unicode_literals |  | ||||||
| 
 |  | ||||||
| import frappe |  | ||||||
| from frappe import _ |  | ||||||
| from frappe.model.document import Document |  | ||||||
| 
 |  | ||||||
| class EInvoiceSettings(Document): |  | ||||||
| 	def validate(self): |  | ||||||
| 		if self.enable and not self.credentials: |  | ||||||
| 			frappe.throw(_('You must add atleast one credentials to be able to use E Invoicing.')) |  | ||||||
| @ -1,10 +0,0 @@ | |||||||
| # -*- coding: utf-8 -*- |  | ||||||
| # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors |  | ||||||
| # See license.txt |  | ||||||
| from __future__ import unicode_literals |  | ||||||
| 
 |  | ||||||
| # import frappe |  | ||||||
| import unittest |  | ||||||
| 
 |  | ||||||
| class TestEInvoiceSettings(unittest.TestCase): |  | ||||||
| 	pass |  | ||||||
| @ -1,57 +0,0 @@ | |||||||
| { |  | ||||||
|  "actions": [], |  | ||||||
|  "creation": "2020-12-22 15:02:46.229474", |  | ||||||
|  "doctype": "DocType", |  | ||||||
|  "editable_grid": 1, |  | ||||||
|  "engine": "InnoDB", |  | ||||||
|  "field_order": [ |  | ||||||
|   "company", |  | ||||||
|   "gstin", |  | ||||||
|   "username", |  | ||||||
|   "password" |  | ||||||
|  ], |  | ||||||
|  "fields": [ |  | ||||||
|   { |  | ||||||
|    "fieldname": "gstin", |  | ||||||
|    "fieldtype": "Data", |  | ||||||
|    "in_list_view": 1, |  | ||||||
|    "label": "GSTIN", |  | ||||||
|    "reqd": 1 |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|    "fieldname": "username", |  | ||||||
|    "fieldtype": "Data", |  | ||||||
|    "in_list_view": 1, |  | ||||||
|    "label": "Username", |  | ||||||
|    "reqd": 1 |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|    "fieldname": "password", |  | ||||||
|    "fieldtype": "Password", |  | ||||||
|    "in_list_view": 1, |  | ||||||
|    "label": "Password", |  | ||||||
|    "reqd": 1 |  | ||||||
|   }, |  | ||||||
|   { |  | ||||||
|    "fieldname": "company", |  | ||||||
|    "fieldtype": "Link", |  | ||||||
|    "in_list_view": 1, |  | ||||||
|    "label": "Company", |  | ||||||
|    "options": "Company", |  | ||||||
|    "reqd": 1 |  | ||||||
|   } |  | ||||||
|  ], |  | ||||||
|  "index_web_pages_for_search": 1, |  | ||||||
|  "istable": 1, |  | ||||||
|  "links": [], |  | ||||||
|  "modified": "2021-03-22 12:16:56.365616", |  | ||||||
|  "modified_by": "Administrator", |  | ||||||
|  "module": "Regional", |  | ||||||
|  "name": "E Invoice User", |  | ||||||
|  "owner": "Administrator", |  | ||||||
|  "permissions": [], |  | ||||||
|  "quick_entry": 1, |  | ||||||
|  "sort_field": "modified", |  | ||||||
|  "sort_order": "DESC", |  | ||||||
|  "track_changes": 1 |  | ||||||
| } |  | ||||||
| @ -1,10 +0,0 @@ | |||||||
| # -*- coding: utf-8 -*- |  | ||||||
| # Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors |  | ||||||
| # For license information, please see license.txt |  | ||||||
| 
 |  | ||||||
| from __future__ import unicode_literals |  | ||||||
| # import frappe |  | ||||||
| from frappe.model.document import Document |  | ||||||
| 
 |  | ||||||
| class EInvoiceUser(Document): |  | ||||||
| 	pass |  | ||||||
| @ -1,31 +0,0 @@ | |||||||
| {{ |  | ||||||
|     "SlNo": "{item.sr_no}", |  | ||||||
|     "PrdDesc": "{item.description}", |  | ||||||
|     "IsServc": "{item.is_service_item}", |  | ||||||
|     "HsnCd": "{item.gst_hsn_code}", |  | ||||||
|     "Barcde": "{item.barcode}", |  | ||||||
|     "Unit": "{item.uom}", |  | ||||||
|     "Qty": "{item.qty}", |  | ||||||
|     "FreeQty": "{item.free_qty}", |  | ||||||
|     "UnitPrice": "{item.unit_rate}", |  | ||||||
|     "TotAmt": "{item.gross_amount}", |  | ||||||
|     "Discount": "{item.discount_amount}", |  | ||||||
|     "AssAmt": "{item.taxable_value}", |  | ||||||
|     "PrdSlNo": "{item.serial_no}", |  | ||||||
|     "GstRt": "{item.tax_rate}", |  | ||||||
|     "IgstAmt": "{item.igst_amount}", |  | ||||||
|     "CgstAmt": "{item.cgst_amount}", |  | ||||||
|     "SgstAmt": "{item.sgst_amount}", |  | ||||||
|     "CesRt": "{item.cess_rate}", |  | ||||||
|     "CesAmt": "{item.cess_amount}", |  | ||||||
|     "CesNonAdvlAmt": "{item.cess_nadv_amount}", |  | ||||||
|     "StateCesRt": "{item.state_cess_rate}", |  | ||||||
|     "StateCesAmt": "{item.state_cess_amount}", |  | ||||||
|     "StateCesNonAdvlAmt": "{item.state_cess_nadv_amount}", |  | ||||||
|     "OthChrg": "{item.other_charges}", |  | ||||||
|     "TotItemVal": "{item.total_value}", |  | ||||||
|     "BchDtls": {{ |  | ||||||
|         "Nm": "{item.batch_no}", |  | ||||||
|         "ExpDt": "{item.batch_expiry_date}" |  | ||||||
|     }} |  | ||||||
| }} |  | ||||||
| @ -1,110 +0,0 @@ | |||||||
| {{ |  | ||||||
|     "Version": "1.1", |  | ||||||
|     "TranDtls": {{ |  | ||||||
|         "TaxSch": "{transaction_details.tax_scheme}", |  | ||||||
|         "SupTyp": "{transaction_details.supply_type}", |  | ||||||
|         "RegRev": "{transaction_details.reverse_charge}", |  | ||||||
|         "EcmGstin": "{transaction_details.ecom_gstin}", |  | ||||||
|         "IgstOnIntra": "{transaction_details.igst_on_intra}" |  | ||||||
|     }}, |  | ||||||
|     "DocDtls": {{ |  | ||||||
|         "Typ": "{doc_details.invoice_type}", |  | ||||||
|         "No": "{doc_details.invoice_name}", |  | ||||||
|         "Dt": "{doc_details.invoice_date}" |  | ||||||
|     }}, |  | ||||||
|     "SellerDtls": {{ |  | ||||||
|         "Gstin": "{seller_details.gstin}", |  | ||||||
|         "LglNm": "{seller_details.legal_name}", |  | ||||||
|         "TrdNm": "{seller_details.trade_name}", |  | ||||||
|         "Loc": "{seller_details.location}", |  | ||||||
|         "Pin": "{seller_details.pincode}", |  | ||||||
|         "Stcd": "{seller_details.state_code}", |  | ||||||
|         "Addr1": "{seller_details.address_line1}", |  | ||||||
|         "Addr2": "{seller_details.address_line2}", |  | ||||||
|         "Ph": "{seller_details.phone}", |  | ||||||
|         "Em": "{seller_details.email}" |  | ||||||
|     }}, |  | ||||||
|     "BuyerDtls": {{ |  | ||||||
|         "Gstin": "{buyer_details.gstin}", |  | ||||||
|         "LglNm": "{buyer_details.legal_name}", |  | ||||||
|         "TrdNm": "{buyer_details.trade_name}", |  | ||||||
|         "Addr1": "{buyer_details.address_line1}", |  | ||||||
|         "Addr2": "{buyer_details.address_line2}", |  | ||||||
|         "Loc": "{buyer_details.location}", |  | ||||||
|         "Pin": "{buyer_details.pincode}", |  | ||||||
|         "Stcd": "{buyer_details.state_code}", |  | ||||||
|         "Ph": "{buyer_details.phone}", |  | ||||||
|         "Em": "{buyer_details.email}", |  | ||||||
|         "Pos": "{buyer_details.place_of_supply}" |  | ||||||
|     }}, |  | ||||||
|     "DispDtls": {{ |  | ||||||
|         "Nm": "{dispatch_details.company_name}", |  | ||||||
|         "Addr1": "{dispatch_details.address_line1}", |  | ||||||
|         "Addr2": "{dispatch_details.address_line2}", |  | ||||||
|         "Loc": "{dispatch_details.location}", |  | ||||||
|         "Pin": "{dispatch_details.pincode}", |  | ||||||
|         "Stcd": "{dispatch_details.state_code}" |  | ||||||
|     }}, |  | ||||||
|     "ShipDtls": {{ |  | ||||||
|         "Gstin": "{shipping_details.gstin}", |  | ||||||
|         "LglNm": "{shipping_details.legal_name}", |  | ||||||
|         "TrdNm": "{shipping_details.trader_name}", |  | ||||||
|         "Addr1": "{shipping_details.address_line1}", |  | ||||||
|         "Addr2": "{shipping_details.address_line2}", |  | ||||||
|         "Loc": "{shipping_details.location}", |  | ||||||
|         "Pin": "{shipping_details.pincode}", |  | ||||||
|         "Stcd": "{shipping_details.state_code}" |  | ||||||
|     }}, |  | ||||||
|     "ItemList": [ |  | ||||||
|         {item_list} |  | ||||||
|     ], |  | ||||||
|     "ValDtls": {{ |  | ||||||
|         "AssVal": "{invoice_value_details.base_total}", |  | ||||||
|         "CgstVal": "{invoice_value_details.total_cgst_amt}", |  | ||||||
|         "SgstVal": "{invoice_value_details.total_sgst_amt}", |  | ||||||
|         "IgstVal": "{invoice_value_details.total_igst_amt}", |  | ||||||
|         "CesVal": "{invoice_value_details.total_cess_amt}", |  | ||||||
|         "Discount": "{invoice_value_details.invoice_discount_amt}", |  | ||||||
|         "RndOffAmt": "{invoice_value_details.round_off}", |  | ||||||
|         "OthChrg": "{invoice_value_details.total_other_charges}", |  | ||||||
|         "TotInvVal": "{invoice_value_details.base_grand_total}", |  | ||||||
|         "TotInvValFc": "{invoice_value_details.grand_total}" |  | ||||||
|     }}, |  | ||||||
|     "PayDtls": {{ |  | ||||||
|         "Nm": "{payment_details.payee_name}", |  | ||||||
|         "AccDet": "{payment_details.account_no}", |  | ||||||
|         "Mode": "{payment_details.mode_of_payment}", |  | ||||||
|         "FinInsBr": "{payment_details.ifsc_code}", |  | ||||||
|         "PayTerm": "{payment_details.terms}", |  | ||||||
|         "PaidAmt": "{payment_details.paid_amount}", |  | ||||||
|         "PaymtDue": "{payment_details.outstanding_amount}" |  | ||||||
|     }}, |  | ||||||
|     "RefDtls": {{ |  | ||||||
|         "DocPerdDtls": {{ |  | ||||||
|             "InvStDt": "{period_details.start_date}", |  | ||||||
|             "InvEndDt": "{period_details.end_date}" |  | ||||||
|         }}, |  | ||||||
|         "PrecDocDtls": [{{ |  | ||||||
|             "InvNo": "{prev_doc_details.invoice_name}", |  | ||||||
|             "InvDt": "{prev_doc_details.invoice_date}" |  | ||||||
|         }}] |  | ||||||
|     }}, |  | ||||||
|     "ExpDtls": {{ |  | ||||||
|         "ShipBNo": "{export_details.bill_no}", |  | ||||||
|         "ShipBDt": "{export_details.bill_date}", |  | ||||||
|         "Port": "{export_details.port}", |  | ||||||
|         "ForCur": "{export_details.foreign_curr_code}", |  | ||||||
|         "CntCode": "{export_details.country_code}", |  | ||||||
|         "ExpDuty": "{export_details.export_duty}" |  | ||||||
|     }}, |  | ||||||
|     "EwbDtls": {{ |  | ||||||
|         "TransId": "{eway_bill_details.gstin}", |  | ||||||
|         "TransName": "{eway_bill_details.name}", |  | ||||||
|         "TransMode": "{eway_bill_details.mode_of_transport}", |  | ||||||
|         "Distance": "{eway_bill_details.distance}", |  | ||||||
|         "TransDocNo": "{eway_bill_details.document_name}", |  | ||||||
|         "TransDocDt": "{eway_bill_details.document_date}", |  | ||||||
|         "VehNo": "{eway_bill_details.vehicle_no}", |  | ||||||
|         "VehType": "{eway_bill_details.vehicle_type}" |  | ||||||
|     }} |  | ||||||
| }} |  | ||||||
| @ -1,957 +0,0 @@ | |||||||
| { |  | ||||||
|   "Version": { |  | ||||||
|     "type": "string", |  | ||||||
|     "minLength": 1, |  | ||||||
|     "maxLength": 6, |  | ||||||
|     "description": "Version of the schema" |  | ||||||
|   }, |  | ||||||
|   "Irn": { |  | ||||||
|     "type": "string", |  | ||||||
|     "minLength": 64, |  | ||||||
|     "maxLength": 64, |  | ||||||
|     "description": "Invoice Reference Number" |  | ||||||
|   }, |  | ||||||
|   "TranDtls": { |  | ||||||
|     "type": "object", |  | ||||||
|     "properties": { |  | ||||||
|       "TaxSch": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 10, |  | ||||||
|         "enum": ["GST"], |  | ||||||
|         "description": "GST- Goods and Services Tax Scheme" |  | ||||||
|       }, |  | ||||||
|       "SupTyp": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 10, |  | ||||||
|         "enum": ["B2B", "SEZWP", "SEZWOP", "EXPWP", "EXPWOP", "DEXP"], |  | ||||||
|         "description": "Type of Supply: B2B-Business to Business, SEZWP - SEZ with payment, SEZWOP - SEZ without payment, EXPWP - Export with Payment, EXPWOP - Export without payment,DEXP - Deemed Export" |  | ||||||
|       }, |  | ||||||
|       "RegRev": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 1, |  | ||||||
|         "enum": ["Y", "N"], |  | ||||||
|         "description": "Y- whether the tax liability is payable under reverse charge" |  | ||||||
|       }, |  | ||||||
|       "EcmGstin": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 15, |  | ||||||
|         "maxLength": 15, |  | ||||||
|         "pattern": "([0-9]{2}[0-9A-Z]{13})", |  | ||||||
|         "description": "E-Commerce GSTIN", |  | ||||||
|         "validationMsg": "E-Commerce GSTIN is invalid" |  | ||||||
|       }, |  | ||||||
|       "IgstOnIntra": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 1, |  | ||||||
|         "enum": ["Y", "N"], |  | ||||||
|         "description": "Y- indicates the supply is intra state but chargeable to IGST" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "required": ["TaxSch", "SupTyp"] |  | ||||||
|   }, |  | ||||||
|   "DocDtls": { |  | ||||||
|     "type": "object", |  | ||||||
|     "properties": { |  | ||||||
|       "Typ": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 3, |  | ||||||
|         "enum": ["INV", "CRN", "DBN"], |  | ||||||
|         "description": "Document Type" |  | ||||||
|       }, |  | ||||||
|       "No": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 16, |  | ||||||
|         "pattern": "^([A-Z1-9]{1}[A-Z0-9/-]{0,15})$", |  | ||||||
|         "description": "Document Number", |  | ||||||
|         "validationMsg": "Document Number should not be starting with 0, / and -" |  | ||||||
|       }, |  | ||||||
|       "Dt": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 10, |  | ||||||
|         "maxLength": 10, |  | ||||||
|         "pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]", |  | ||||||
|         "description": "Document Date" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "required": ["Typ", "No", "Dt"] |  | ||||||
|   }, |  | ||||||
|   "SellerDtls": { |  | ||||||
|     "type": "object", |  | ||||||
|     "properties": { |  | ||||||
|       "Gstin": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 15, |  | ||||||
|         "maxLength": 15, |  | ||||||
|         "pattern": "([0-9]{2}[0-9A-Z]{13})", |  | ||||||
|         "description": "Supplier GSTIN", |  | ||||||
|         "validationMsg": "Company GSTIN is invalid" |  | ||||||
|       }, |  | ||||||
|       "LglNm": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Legal Name" |  | ||||||
|       }, |  | ||||||
|       "TrdNm": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Tradename" |  | ||||||
|       }, |  | ||||||
|       "Addr1": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Address Line 1" |  | ||||||
|       }, |  | ||||||
|       "Addr2": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Address Line 2" |  | ||||||
|       }, |  | ||||||
|       "Loc": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 50, |  | ||||||
|         "description": "Location" |  | ||||||
|       }, |  | ||||||
|       "Pin": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 100000, |  | ||||||
|         "maximum": 999999, |  | ||||||
|         "description": "Pincode" |  | ||||||
|       }, |  | ||||||
|       "Stcd": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 2, |  | ||||||
|         "description": "Supplier State Code" |  | ||||||
|       }, |  | ||||||
|       "Ph": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 6, |  | ||||||
|         "maxLength": 12, |  | ||||||
|         "description": "Phone" |  | ||||||
|       }, |  | ||||||
|       "Em": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 6, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Email-Id" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "required": ["Gstin", "LglNm", "Addr1", "Loc", "Pin", "Stcd"] |  | ||||||
|   }, |  | ||||||
|   "BuyerDtls": { |  | ||||||
|     "type": "object", |  | ||||||
|     "properties": { |  | ||||||
|       "Gstin": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 15, |  | ||||||
|         "pattern": "^(([0-9]{2}[0-9A-Z]{13})|URP)$", |  | ||||||
|         "description": "Buyer GSTIN", |  | ||||||
|         "validationMsg": "Customer GSTIN is invalid" |  | ||||||
|       }, |  | ||||||
|       "LglNm": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Legal Name" |  | ||||||
|       }, |  | ||||||
|       "TrdNm": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Trade Name" |  | ||||||
|       }, |  | ||||||
|       "Pos": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 2, |  | ||||||
|         "description": "Place of Supply State code" |  | ||||||
|       }, |  | ||||||
|       "Addr1": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Address Line 1" |  | ||||||
|       }, |  | ||||||
|       "Addr2": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Address Line 2" |  | ||||||
|       }, |  | ||||||
|       "Loc": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Location" |  | ||||||
|       }, |  | ||||||
|       "Pin": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 100000, |  | ||||||
|         "maximum": 999999, |  | ||||||
|         "description": "Pincode" |  | ||||||
|       }, |  | ||||||
|       "Stcd": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 2, |  | ||||||
|         "description": "Buyer State Code" |  | ||||||
|       }, |  | ||||||
|       "Ph": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 6, |  | ||||||
|         "maxLength": 12, |  | ||||||
|         "description": "Phone" |  | ||||||
|       }, |  | ||||||
|       "Em": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 6, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Email-Id" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "required": ["Gstin", "LglNm", "Pos", "Addr1", "Loc", "Stcd"] |  | ||||||
|   }, |  | ||||||
|   "DispDtls": { |  | ||||||
|     "type": "object", |  | ||||||
|     "properties": { |  | ||||||
|       "Nm": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Dispatch Address Name" |  | ||||||
|       }, |  | ||||||
|       "Addr1": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Address Line 1" |  | ||||||
|       }, |  | ||||||
|       "Addr2": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Address Line 2" |  | ||||||
|       }, |  | ||||||
|       "Loc": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Location" |  | ||||||
|       }, |  | ||||||
|       "Pin": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 100000, |  | ||||||
|         "maximum": 999999, |  | ||||||
|         "description": "Pincode" |  | ||||||
|       }, |  | ||||||
|       "Stcd": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 2, |  | ||||||
|         "description": "State Code" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "required": ["Nm", "Addr1", "Loc", "Pin", "Stcd"] |  | ||||||
|   }, |  | ||||||
|   "ShipDtls": { |  | ||||||
|     "type": "object", |  | ||||||
|     "properties": { |  | ||||||
|       "Gstin": { |  | ||||||
|         "type": "string", |  | ||||||
|         "maxLength": 15, |  | ||||||
|         "minLength": 3, |  | ||||||
|         "pattern": "^(([0-9]{2}[0-9A-Z]{13})|URP)$", |  | ||||||
|         "description": "Shipping Address GSTIN", |  | ||||||
|         "validationMsg": "Shipping Address GSTIN is invalid" |  | ||||||
|       }, |  | ||||||
|       "LglNm": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Legal Name" |  | ||||||
|       }, |  | ||||||
|       "TrdNm": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Trade Name" |  | ||||||
|       }, |  | ||||||
|       "Addr1": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Address Line 1" |  | ||||||
|       }, |  | ||||||
|       "Addr2": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Address Line 2" |  | ||||||
|       }, |  | ||||||
|       "Loc": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Location" |  | ||||||
|       }, |  | ||||||
|       "Pin": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 100000, |  | ||||||
|         "maximum": 999999, |  | ||||||
|         "description": "Pincode" |  | ||||||
|       }, |  | ||||||
|       "Stcd": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 2, |  | ||||||
|         "description": "State Code" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "required": ["LglNm", "Addr1", "Loc", "Pin", "Stcd"] |  | ||||||
|   }, |  | ||||||
|   "ItemList": { |  | ||||||
|     "type": "Array", |  | ||||||
|     "properties": { |  | ||||||
|       "SlNo": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 6, |  | ||||||
|         "description": "Serial No. of Item" |  | ||||||
|       }, |  | ||||||
|       "PrdDesc": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 300, |  | ||||||
|         "description": "Item Name" |  | ||||||
|       }, |  | ||||||
|       "IsServc": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 1, |  | ||||||
|         "enum": ["Y", "N"], |  | ||||||
|         "description": "Is Service Item" |  | ||||||
|       }, |  | ||||||
|       "HsnCd": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 4, |  | ||||||
|         "maxLength": 8, |  | ||||||
|         "description": "HSN Code" |  | ||||||
|       }, |  | ||||||
|       "Barcde": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 30, |  | ||||||
|         "description": "Barcode" |  | ||||||
|       }, |  | ||||||
|       "Qty": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 9999999999.999, |  | ||||||
|         "description": "Quantity" |  | ||||||
|       }, |  | ||||||
|       "FreeQty": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 9999999999.999, |  | ||||||
|         "description": "Free Quantity" |  | ||||||
|       }, |  | ||||||
|       "Unit": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 8, |  | ||||||
|         "description": "UOM" |  | ||||||
|       }, |  | ||||||
|       "UnitPrice": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 999999999999.999, |  | ||||||
|         "description": "Rate" |  | ||||||
|       }, |  | ||||||
|       "TotAmt": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 999999999999.99, |  | ||||||
|         "description": "Gross Amount" |  | ||||||
|       }, |  | ||||||
|       "Discount": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 999999999999.99, |  | ||||||
|         "description": "Discount" |  | ||||||
|       }, |  | ||||||
|       "PreTaxVal": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 999999999999.99, |  | ||||||
|         "description": "Pre tax value" |  | ||||||
|       }, |  | ||||||
|       "AssAmt": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 999999999999.99, |  | ||||||
|         "description": "Taxable Value" |  | ||||||
|       }, |  | ||||||
|       "GstRt": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 999.999, |  | ||||||
|         "description": "GST Rate" |  | ||||||
|       }, |  | ||||||
|       "IgstAmt": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 999999999999.99, |  | ||||||
|         "description": "IGST Amount" |  | ||||||
|       }, |  | ||||||
|       "CgstAmt": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 999999999999.99, |  | ||||||
|         "description": "CGST Amount" |  | ||||||
|       }, |  | ||||||
|       "SgstAmt": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 999999999999.99, |  | ||||||
|         "description": "SGST Amount" |  | ||||||
|       }, |  | ||||||
|       "CesRt": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 999.999, |  | ||||||
|         "description": "Cess Rate" |  | ||||||
|       }, |  | ||||||
|       "CesAmt": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 999999999999.99, |  | ||||||
|         "description": "Cess Amount (Advalorem)" |  | ||||||
|       }, |  | ||||||
|       "CesNonAdvlAmt": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 999999999999.99, |  | ||||||
|         "description": "Cess Amount (Non-Advalorem)" |  | ||||||
|       }, |  | ||||||
|       "StateCesRt": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 999.999, |  | ||||||
|         "description": "State CESS Rate" |  | ||||||
|       }, |  | ||||||
|       "StateCesAmt": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 999999999999.99, |  | ||||||
|         "description": "State CESS Amount" |  | ||||||
|       }, |  | ||||||
|       "StateCesNonAdvlAmt": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 999999999999.99, |  | ||||||
|         "description": "State CESS Amount (Non Advalorem)" |  | ||||||
|       }, |  | ||||||
|       "OthChrg": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 999999999999.99, |  | ||||||
|         "description": "Other Charges" |  | ||||||
|       }, |  | ||||||
|       "TotItemVal": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 999999999999.99, |  | ||||||
|         "description": "Total Item Value" |  | ||||||
|       }, |  | ||||||
|       "OrdLineRef": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 50, |  | ||||||
|         "description": "Order line reference" |  | ||||||
|       }, |  | ||||||
|       "OrgCntry": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 2, |  | ||||||
|         "maxLength": 2, |  | ||||||
|         "description": "Origin Country" |  | ||||||
|       }, |  | ||||||
|       "PrdSlNo": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 20, |  | ||||||
|         "description": "Serial number" |  | ||||||
|       }, |  | ||||||
|       "BchDtls": { |  | ||||||
|         "type": "object", |  | ||||||
|         "properties": { |  | ||||||
|           "Nm": { |  | ||||||
|             "type": "string", |  | ||||||
|             "minLength": 3, |  | ||||||
|             "maxLength": 20, |  | ||||||
|             "description": "Batch number" |  | ||||||
|           }, |  | ||||||
|           "ExpDt": { |  | ||||||
|             "type": "string", |  | ||||||
|             "maxLength": 10, |  | ||||||
|             "minLength": 10, |  | ||||||
|             "pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]", |  | ||||||
|             "description": "Batch Expiry Date" |  | ||||||
|           }, |  | ||||||
|           "WrDt": { |  | ||||||
|             "type": "string", |  | ||||||
|             "maxLength": 10, |  | ||||||
|             "minLength": 10, |  | ||||||
|             "pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]", |  | ||||||
|             "description": "Warranty Date" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "required": ["Nm"] |  | ||||||
|       }, |  | ||||||
|       "AttribDtls": { |  | ||||||
|         "type": "Array", |  | ||||||
|         "Attribute": { |  | ||||||
|           "type": "object", |  | ||||||
|           "properties": { |  | ||||||
|             "Nm": { |  | ||||||
|               "type": "string", |  | ||||||
|               "minLength": 1, |  | ||||||
|               "maxLength": 100, |  | ||||||
|               "description": "Attribute name of the item" |  | ||||||
|             }, |  | ||||||
|             "Val": { |  | ||||||
|               "type": "string", |  | ||||||
|               "minLength": 1, |  | ||||||
|               "maxLength": 100, |  | ||||||
|               "description": "Attribute value of the item" |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "required": [ |  | ||||||
|       "SlNo", |  | ||||||
|       "IsServc", |  | ||||||
|       "HsnCd", |  | ||||||
|       "UnitPrice", |  | ||||||
|       "TotAmt", |  | ||||||
|       "AssAmt", |  | ||||||
|       "GstRt", |  | ||||||
|       "TotItemVal" |  | ||||||
|     ] |  | ||||||
|   }, |  | ||||||
|   "ValDtls": { |  | ||||||
|     "type": "object", |  | ||||||
|     "properties": { |  | ||||||
|       "AssVal": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 99999999999999.99, |  | ||||||
|         "description": "Total Assessable value of all items" |  | ||||||
|       }, |  | ||||||
|       "CgstVal": { |  | ||||||
|         "type": "number", |  | ||||||
|         "maximum": 99999999999999.99, |  | ||||||
|         "minimum": 0, |  | ||||||
|         "description": "Total CGST value of all items" |  | ||||||
|       }, |  | ||||||
|       "SgstVal": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 99999999999999.99, |  | ||||||
|         "description": "Total SGST value of all items" |  | ||||||
|       }, |  | ||||||
|       "IgstVal": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 99999999999999.99, |  | ||||||
|         "description": "Total IGST value of all items" |  | ||||||
|       }, |  | ||||||
|       "CesVal": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 99999999999999.99, |  | ||||||
|         "description": "Total CESS value of all items" |  | ||||||
|       }, |  | ||||||
|       "StCesVal": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 99999999999999.99, |  | ||||||
|         "description": "Total State CESS value of all items" |  | ||||||
|       }, |  | ||||||
|       "Discount": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 99999999999999.99, |  | ||||||
|         "description": "Invoice Discount" |  | ||||||
|       }, |  | ||||||
|       "OthChrg": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 99999999999999.99, |  | ||||||
|         "description": "Other Charges" |  | ||||||
|       }, |  | ||||||
|       "RndOffAmt": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": -99.99, |  | ||||||
|         "maximum": 99.99, |  | ||||||
|         "description": "Rounded off Amount" |  | ||||||
|       }, |  | ||||||
|       "TotInvVal": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 99999999999999.99, |  | ||||||
|         "description": "Final Invoice Value " |  | ||||||
|       }, |  | ||||||
|       "TotInvValFc": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 99999999999999.99, |  | ||||||
|         "description": "Final Invoice value in Foreign Currency" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "required": ["AssVal", "TotInvVal"] |  | ||||||
|   }, |  | ||||||
|   "PayDtls": { |  | ||||||
|     "type": "object", |  | ||||||
|     "properties": { |  | ||||||
|       "Nm": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Payee Name" |  | ||||||
|       }, |  | ||||||
|       "AccDet": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 18, |  | ||||||
|         "description": "Bank Account Number of Payee" |  | ||||||
|       }, |  | ||||||
|       "Mode": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 18, |  | ||||||
|         "description": "Mode of Payment" |  | ||||||
|       }, |  | ||||||
|       "FinInsBr": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 11, |  | ||||||
|         "description": "Branch or IFSC code" |  | ||||||
|       }, |  | ||||||
|       "PayTerm": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Terms of Payment" |  | ||||||
|       }, |  | ||||||
|       "PayInstr": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Payment Instruction" |  | ||||||
|       }, |  | ||||||
|       "CrTrn": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Credit Transfer" |  | ||||||
|       }, |  | ||||||
|       "DirDr": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Direct Debit" |  | ||||||
|       }, |  | ||||||
|       "CrDay": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 9999, |  | ||||||
|         "description": "Credit Days" |  | ||||||
|       }, |  | ||||||
|       "PaidAmt": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 99999999999999.99, |  | ||||||
|         "description": "Advance Amount" |  | ||||||
|       }, |  | ||||||
|       "PaymtDue": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 99999999999999.99, |  | ||||||
|         "description": "Outstanding Amount" |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
|   "RefDtls": { |  | ||||||
|     "type": "object", |  | ||||||
|     "properties": { |  | ||||||
|       "InvRm": { |  | ||||||
|         "type": "string", |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "minLength": 3, |  | ||||||
|         "pattern": "^[0-9A-Za-z/-]{3,100}$", |  | ||||||
|         "description": "Remarks/Note" |  | ||||||
|       }, |  | ||||||
|       "DocPerdDtls": { |  | ||||||
|         "type": "object", |  | ||||||
|         "properties": { |  | ||||||
|           "InvStDt": { |  | ||||||
|             "type": "string", |  | ||||||
|             "maxLength": 10, |  | ||||||
|             "minLength": 10, |  | ||||||
|             "pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]", |  | ||||||
|             "description": "Invoice Period Start Date" |  | ||||||
|           }, |  | ||||||
|           "InvEndDt": { |  | ||||||
|             "type": "string", |  | ||||||
|             "maxLength": 10, |  | ||||||
|             "minLength": 10, |  | ||||||
|             "pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]", |  | ||||||
|             "description": "Invoice Period End Date" |  | ||||||
|           } |  | ||||||
|         }, |  | ||||||
|         "required": ["InvStDt ", "InvEndDt "] |  | ||||||
|       }, |  | ||||||
|       "PrecDocDtls": { |  | ||||||
|         "type": "object", |  | ||||||
|         "properties": { |  | ||||||
|           "InvNo": { |  | ||||||
|             "type": "string", |  | ||||||
|             "minLength": 1, |  | ||||||
|             "maxLength": 16, |  | ||||||
|             "pattern": "^[1-9A-Z]{1}[0-9A-Z/-]{1,15}$", |  | ||||||
|             "description": "Reference of Original Invoice" |  | ||||||
|           }, |  | ||||||
|           "InvDt": { |  | ||||||
|             "type": "string", |  | ||||||
|             "maxLength": 10, |  | ||||||
|             "minLength": 10, |  | ||||||
|             "pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]", |  | ||||||
|             "description": "Date of Orginal Invoice" |  | ||||||
|           }, |  | ||||||
|           "OthRefNo": { |  | ||||||
|             "type": "string", |  | ||||||
|             "minLength": 1, |  | ||||||
|             "maxLength": 20, |  | ||||||
|             "description": "Other Reference" |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       }, |  | ||||||
|       "required": ["InvNo", "InvDt"], |  | ||||||
|       "ContrDtls": { |  | ||||||
|         "type": "object", |  | ||||||
|         "properties": { |  | ||||||
|           "RecAdvRefr": { |  | ||||||
|             "type": "string", |  | ||||||
|             "minLength": 1, |  | ||||||
|             "maxLength": 20, |  | ||||||
|             "pattern": "^([0-9A-Za-z/-]){1,20}$", |  | ||||||
|             "description": "Receipt Advice No." |  | ||||||
|           }, |  | ||||||
|           "RecAdvDt": { |  | ||||||
|             "type": "string", |  | ||||||
|             "minLength": 10, |  | ||||||
|             "maxLength": 10, |  | ||||||
|             "pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]", |  | ||||||
|             "description": "Date of receipt advice" |  | ||||||
|           }, |  | ||||||
|           "TendRefr": { |  | ||||||
|             "type": "string", |  | ||||||
|             "minLength": 1, |  | ||||||
|             "maxLength": 20, |  | ||||||
|             "pattern": "^([0-9A-Za-z/-]){1,20}$", |  | ||||||
|             "description": "Lot/Batch Reference No." |  | ||||||
|           }, |  | ||||||
|           "ContrRefr": { |  | ||||||
|             "type": "string", |  | ||||||
|             "minLength": 1, |  | ||||||
|             "maxLength": 20, |  | ||||||
|             "pattern": "^([0-9A-Za-z/-]){1,20}$", |  | ||||||
|             "description": "Contract Reference Number" |  | ||||||
|           }, |  | ||||||
|           "ExtRefr": { |  | ||||||
|             "type": "string", |  | ||||||
|             "minLength": 1, |  | ||||||
|             "maxLength": 20, |  | ||||||
|             "pattern": "^([0-9A-Za-z/-]){1,20}$", |  | ||||||
|             "description": "Any other reference" |  | ||||||
|           }, |  | ||||||
|           "ProjRefr": { |  | ||||||
|             "type": "string", |  | ||||||
|             "minLength": 1, |  | ||||||
|             "maxLength": 20, |  | ||||||
|             "pattern": "^([0-9A-Za-z/-]){1,20}$", |  | ||||||
|             "description": "Project Reference Number" |  | ||||||
|           }, |  | ||||||
|           "PORefr": { |  | ||||||
|             "type": "string", |  | ||||||
|             "minLength": 1, |  | ||||||
|             "maxLength": 16, |  | ||||||
|             "pattern": "^([0-9A-Za-z/-]){1,16}$", |  | ||||||
|             "description": "PO Reference Number" |  | ||||||
|           }, |  | ||||||
|           "PORefDt": { |  | ||||||
|             "type": "string", |  | ||||||
|             "minLength": 10, |  | ||||||
|             "maxLength": 10, |  | ||||||
|             "pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]", |  | ||||||
|             "description": "PO Reference date" |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
|   "AddlDocDtls": { |  | ||||||
|     "type": "Array", |  | ||||||
|     "properties": { |  | ||||||
|       "Url": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Supporting document URL" |  | ||||||
|       }, |  | ||||||
|       "Docs": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 1000, |  | ||||||
|         "description": "Supporting document in Base64 Format" |  | ||||||
|       }, |  | ||||||
|       "Info": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 1000, |  | ||||||
|         "description": "Any additional information" |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
| 
 |  | ||||||
|   "ExpDtls": { |  | ||||||
|     "type": "object", |  | ||||||
|     "properties": { |  | ||||||
|       "ShipBNo": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 20, |  | ||||||
|         "description": "Shipping Bill No." |  | ||||||
|       }, |  | ||||||
|       "ShipBDt": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 10, |  | ||||||
|         "maxLength": 10, |  | ||||||
|         "pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]", |  | ||||||
|         "description": "Shipping Bill Date" |  | ||||||
|       }, |  | ||||||
|       "Port": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 2, |  | ||||||
|         "maxLength": 10, |  | ||||||
|         "pattern": "^[0-9A-Za-z]{2,10}$", |  | ||||||
|         "description": "Port Code. Refer the master" |  | ||||||
|       }, |  | ||||||
|       "RefClm": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 1, |  | ||||||
|         "description": "Claiming Refund. Y/N" |  | ||||||
|       }, |  | ||||||
|       "ForCur": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 16, |  | ||||||
|         "description": "Additional Currency Code. Refer the master" |  | ||||||
|       }, |  | ||||||
|       "CntCode": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 2, |  | ||||||
|         "maxLength": 2, |  | ||||||
|         "description": "Country Code. Refer the master" |  | ||||||
|       }, |  | ||||||
|       "ExpDuty": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 0, |  | ||||||
|         "maximum": 999999999999.99, |  | ||||||
|         "description": "Export Duty" |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   }, |  | ||||||
|   "EwbDtls": { |  | ||||||
|     "type": "object", |  | ||||||
|     "properties": { |  | ||||||
|       "TransId": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 15, |  | ||||||
|         "maxLength": 15, |  | ||||||
|         "description": "Transporter GSTIN" |  | ||||||
|       }, |  | ||||||
|       "TransName": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 3, |  | ||||||
|         "maxLength": 100, |  | ||||||
|         "description": "Transporter Name" |  | ||||||
|       }, |  | ||||||
|       "TransMode": { |  | ||||||
|         "type": "string", |  | ||||||
|         "maxLength": 1, |  | ||||||
|         "minLength": 1, |  | ||||||
|         "enum": ["1", "2", "3", "4"], |  | ||||||
|         "description": "Mode of Transport" |  | ||||||
|       }, |  | ||||||
|       "Distance": { |  | ||||||
|         "type": "number", |  | ||||||
|         "minimum": 1, |  | ||||||
|         "maximum": 9999, |  | ||||||
|         "description": "Distance" |  | ||||||
|       }, |  | ||||||
|       "TransDocNo": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 15, |  | ||||||
|         "pattern": "^([0-9A-Z/-]){1,15}$", |  | ||||||
|         "description": "Tranport Document Number", |  | ||||||
|         "validationMsg": "Transport Receipt No is invalid" |  | ||||||
|       }, |  | ||||||
|       "TransDocDt": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 10, |  | ||||||
|         "maxLength": 10, |  | ||||||
|         "pattern": "[0-3][0-9]/[0-1][0-9]/[2][0][1-2][0-9]", |  | ||||||
|         "description": "Transport Document Date" |  | ||||||
|       }, |  | ||||||
|       "VehNo": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 4, |  | ||||||
|         "maxLength": 20, |  | ||||||
|         "description": "Vehicle Number" |  | ||||||
|       }, |  | ||||||
|       "VehType": { |  | ||||||
|         "type": "string", |  | ||||||
|         "minLength": 1, |  | ||||||
|         "maxLength": 1, |  | ||||||
|         "enum": ["O", "R"], |  | ||||||
|         "description": "Vehicle Type" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "required": ["Distance"] |  | ||||||
|   }, |  | ||||||
|   "required": [ |  | ||||||
|     "Version", |  | ||||||
|     "TranDtls", |  | ||||||
|     "DocDtls", |  | ||||||
|     "SellerDtls", |  | ||||||
|     "BuyerDtls", |  | ||||||
|     "ItemList", |  | ||||||
|     "ValDtls" |  | ||||||
|   ] |  | ||||||
| } |  | ||||||
| @ -1,292 +0,0 @@ | |||||||
| erpnext.setup_einvoice_actions = (doctype) => { |  | ||||||
| 	frappe.ui.form.on(doctype, { |  | ||||||
| 		async refresh(frm) { |  | ||||||
| 			if (frm.doc.docstatus == 2) return; |  | ||||||
| 
 |  | ||||||
| 			const res = await frappe.call({ |  | ||||||
| 				method: 'erpnext.regional.india.e_invoice.utils.validate_eligibility', |  | ||||||
| 				args: { doc: frm.doc } |  | ||||||
| 			}); |  | ||||||
| 			const invoice_eligible = res.message; |  | ||||||
| 
 |  | ||||||
| 			if (!invoice_eligible) return; |  | ||||||
| 
 |  | ||||||
| 			const { doctype, irn, irn_cancelled, ewaybill, eway_bill_cancelled, name, __unsaved } = frm.doc; |  | ||||||
| 
 |  | ||||||
| 			const add_custom_button = (label, action) => { |  | ||||||
| 				if (!frm.custom_buttons[label]) { |  | ||||||
| 					frm.add_custom_button(label, action, __('E Invoicing')); |  | ||||||
| 				} |  | ||||||
| 			}; |  | ||||||
| 
 |  | ||||||
| 			if (!irn && !__unsaved) { |  | ||||||
| 				const action = () => { |  | ||||||
| 					if (frm.doc.__unsaved) { |  | ||||||
| 						frappe.throw(__('Please save the document to generate IRN.')); |  | ||||||
| 					} |  | ||||||
| 					frappe.call({ |  | ||||||
| 						method: 'erpnext.regional.india.e_invoice.utils.get_einvoice', |  | ||||||
| 						args: { doctype, docname: name }, |  | ||||||
| 						freeze: true, |  | ||||||
| 						callback: (res) => { |  | ||||||
| 							const einvoice = res.message; |  | ||||||
| 							show_einvoice_preview(frm, einvoice); |  | ||||||
| 						} |  | ||||||
| 					}); |  | ||||||
| 				}; |  | ||||||
| 
 |  | ||||||
| 				add_custom_button(__("Generate IRN"), action); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if (irn && !irn_cancelled && !ewaybill) { |  | ||||||
| 				const fields = [ |  | ||||||
| 					{ |  | ||||||
| 						"label": "Reason", |  | ||||||
| 						"fieldname": "reason", |  | ||||||
| 						"fieldtype": "Select", |  | ||||||
| 						"reqd": 1, |  | ||||||
| 						"default": "1-Duplicate", |  | ||||||
| 						"options": ["1-Duplicate", "2-Data Entry Error", "3-Order Cancelled", "4-Other"] |  | ||||||
| 					}, |  | ||||||
| 					{ |  | ||||||
| 						"label": "Remark", |  | ||||||
| 						"fieldname": "remark", |  | ||||||
| 						"fieldtype": "Data", |  | ||||||
| 						"reqd": 1 |  | ||||||
| 					} |  | ||||||
| 				]; |  | ||||||
| 				const action = () => { |  | ||||||
| 					const d = new frappe.ui.Dialog({ |  | ||||||
| 						title: __("Cancel IRN"), |  | ||||||
| 						fields: fields, |  | ||||||
| 						primary_action: function() { |  | ||||||
| 							const data = d.get_values(); |  | ||||||
| 							frappe.call({ |  | ||||||
| 								method: 'erpnext.regional.india.e_invoice.utils.cancel_irn', |  | ||||||
| 								args: { |  | ||||||
| 									doctype, |  | ||||||
| 									docname: name, |  | ||||||
| 									irn: irn, |  | ||||||
| 									reason: data.reason.split('-')[0], |  | ||||||
| 									remark: data.remark |  | ||||||
| 								}, |  | ||||||
| 								freeze: true, |  | ||||||
| 								callback: () => frm.reload_doc() || d.hide(), |  | ||||||
| 								error: () => d.hide() |  | ||||||
| 							}); |  | ||||||
| 						}, |  | ||||||
| 						primary_action_label: __('Submit') |  | ||||||
| 					}); |  | ||||||
| 					d.show(); |  | ||||||
| 				}; |  | ||||||
| 				add_custom_button(__("Cancel IRN"), action); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if (irn && !irn_cancelled && !ewaybill) { |  | ||||||
| 				const action = () => { |  | ||||||
| 					const d = new frappe.ui.Dialog({ |  | ||||||
| 						title: __('Generate E-Way Bill'), |  | ||||||
| 						size: "large", |  | ||||||
| 						fields: get_ewaybill_fields(frm), |  | ||||||
| 						primary_action: function() { |  | ||||||
| 							const data = d.get_values(); |  | ||||||
| 							frappe.call({ |  | ||||||
| 								method: 'erpnext.regional.india.e_invoice.utils.generate_eway_bill', |  | ||||||
| 								args: { |  | ||||||
| 									doctype, |  | ||||||
| 									docname: name, |  | ||||||
| 									irn, |  | ||||||
| 									...data |  | ||||||
| 								}, |  | ||||||
| 								freeze: true, |  | ||||||
| 								callback: () => frm.reload_doc() || d.hide(), |  | ||||||
| 								error: () => d.hide() |  | ||||||
| 							}); |  | ||||||
| 						}, |  | ||||||
| 						primary_action_label: __('Submit') |  | ||||||
| 					}); |  | ||||||
| 					d.show(); |  | ||||||
| 				}; |  | ||||||
| 
 |  | ||||||
| 				add_custom_button(__("Generate E-Way Bill"), action); |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if (irn && ewaybill && !irn_cancelled && !eway_bill_cancelled) { |  | ||||||
| 				const action = () => { |  | ||||||
| 					let message = __('Cancellation of e-way bill is currently not supported.') + ' '; |  | ||||||
| 					message += '<br><br>'; |  | ||||||
| 					message += __('You must first use the portal to cancel the e-way bill and then update the cancelled status in the ERPNext system.'); |  | ||||||
| 
 |  | ||||||
| 					const dialog = frappe.msgprint({ |  | ||||||
| 						title: __('Update E-Way Bill Cancelled Status?'), |  | ||||||
| 						message: message, |  | ||||||
| 						indicator: 'orange', |  | ||||||
| 						primary_action: { |  | ||||||
| 							action: function() { |  | ||||||
| 								frappe.call({ |  | ||||||
| 									method: 'erpnext.regional.india.e_invoice.utils.cancel_eway_bill', |  | ||||||
| 									args: { doctype, docname: name }, |  | ||||||
| 									freeze: true, |  | ||||||
| 									callback: () => frm.reload_doc() || dialog.hide() |  | ||||||
| 								}); |  | ||||||
| 							} |  | ||||||
| 						}, |  | ||||||
| 						primary_action_label: __('Yes') |  | ||||||
| 					}); |  | ||||||
| 				}; |  | ||||||
| 				add_custom_button(__("Cancel E-Way Bill"), action); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	}); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const get_ewaybill_fields = (frm) => { |  | ||||||
| 	return [ |  | ||||||
| 		{ |  | ||||||
| 			'fieldname': 'transporter', |  | ||||||
| 			'label': 'Transporter', |  | ||||||
| 			'fieldtype': 'Link', |  | ||||||
| 			'options': 'Supplier', |  | ||||||
| 			'default': frm.doc.transporter |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			'fieldname': 'gst_transporter_id', |  | ||||||
| 			'label': 'GST Transporter ID', |  | ||||||
| 			'fieldtype': 'Data', |  | ||||||
| 			'fetch_from': 'transporter.gst_transporter_id', |  | ||||||
| 			'default': frm.doc.gst_transporter_id |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			'fieldname': 'driver', |  | ||||||
| 			'label': 'Driver', |  | ||||||
| 			'fieldtype': 'Link', |  | ||||||
| 			'options': 'Driver', |  | ||||||
| 			'default': frm.doc.driver |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			'fieldname': 'lr_no', |  | ||||||
| 			'label': 'Transport Receipt No', |  | ||||||
| 			'fieldtype': 'Data', |  | ||||||
| 			'default': frm.doc.lr_no |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			'fieldname': 'vehicle_no', |  | ||||||
| 			'label': 'Vehicle No', |  | ||||||
| 			'fieldtype': 'Data', |  | ||||||
| 			'default': frm.doc.vehicle_no |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			'fieldname': 'distance', |  | ||||||
| 			'label': 'Distance (in km)', |  | ||||||
| 			'fieldtype': 'Float', |  | ||||||
| 			'default': frm.doc.distance |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			'fieldname': 'transporter_col_break', |  | ||||||
| 			'fieldtype': 'Column Break', |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			'fieldname': 'transporter_name', |  | ||||||
| 			'label': 'Transporter Name', |  | ||||||
| 			'fieldtype': 'Data', |  | ||||||
| 			'fetch_from': 'transporter.name', |  | ||||||
| 			'read_only': 1, |  | ||||||
| 			'default': frm.doc.transporter_name |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			'fieldname': 'mode_of_transport', |  | ||||||
| 			'label': 'Mode of Transport', |  | ||||||
| 			'fieldtype': 'Select', |  | ||||||
| 			'options': `\nRoad\nAir\nRail\nShip`, |  | ||||||
| 			'default': frm.doc.mode_of_transport |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			'fieldname': 'driver_name', |  | ||||||
| 			'label': 'Driver Name', |  | ||||||
| 			'fieldtype': 'Data', |  | ||||||
| 			'fetch_from': 'driver.full_name', |  | ||||||
| 			'read_only': 1, |  | ||||||
| 			'default': frm.doc.driver_name |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			'fieldname': 'lr_date', |  | ||||||
| 			'label': 'Transport Receipt Date', |  | ||||||
| 			'fieldtype': 'Date', |  | ||||||
| 			'default': frm.doc.lr_date |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			'fieldname': 'gst_vehicle_type', |  | ||||||
| 			'label': 'GST Vehicle Type', |  | ||||||
| 			'fieldtype': 'Select', |  | ||||||
| 			'options': `Regular\nOver Dimensional Cargo (ODC)`, |  | ||||||
| 			'depends_on': 'eval:(doc.mode_of_transport === "Road")', |  | ||||||
| 			'default': frm.doc.gst_vehicle_type |  | ||||||
| 		} |  | ||||||
| 	]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const request_irn_generation = (frm) => { |  | ||||||
| 	frappe.call({ |  | ||||||
| 		method: 'erpnext.regional.india.e_invoice.utils.generate_irn', |  | ||||||
| 		args: { doctype: frm.doc.doctype, docname: frm.doc.name }, |  | ||||||
| 		freeze: true, |  | ||||||
| 		callback: () => frm.reload_doc() |  | ||||||
| 	}); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const get_preview_dialog = (frm, action) => { |  | ||||||
| 	const dialog = new frappe.ui.Dialog({ |  | ||||||
| 		title: __("Preview"), |  | ||||||
| 		size: "large", |  | ||||||
| 		fields: [ |  | ||||||
| 			{ |  | ||||||
| 				"label": "Preview", |  | ||||||
| 				"fieldname": "preview_html", |  | ||||||
| 				"fieldtype": "HTML" |  | ||||||
| 			} |  | ||||||
| 		], |  | ||||||
| 		primary_action: () => action(frm) || dialog.hide(), |  | ||||||
| 		primary_action_label: __('Generate IRN') |  | ||||||
| 	}); |  | ||||||
| 	return dialog; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const show_einvoice_preview = (frm, einvoice) => { |  | ||||||
| 	const preview_dialog = get_preview_dialog(frm, request_irn_generation); |  | ||||||
| 
 |  | ||||||
| 	// initialize e-invoice fields
 |  | ||||||
| 	einvoice["Irn"] = einvoice["AckNo"] = ''; einvoice["AckDt"] = frappe.datetime.nowdate(); |  | ||||||
| 	frm.doc.signed_einvoice = JSON.stringify(einvoice); |  | ||||||
| 
 |  | ||||||
| 	// initialize preview wrapper
 |  | ||||||
| 	const $preview_wrapper = preview_dialog.get_field("preview_html").$wrapper; |  | ||||||
| 	$preview_wrapper.html( |  | ||||||
| 		`<div>
 |  | ||||||
| 			<div class="print-preview"> |  | ||||||
| 				<div class="print-format"></div> |  | ||||||
| 			</div> |  | ||||||
| 			<div class="page-break-message text-muted text-center text-medium margin-top"></div> |  | ||||||
| 		</div>` |  | ||||||
| 	); |  | ||||||
| 
 |  | ||||||
| 	frappe.call({ |  | ||||||
| 		method: "frappe.www.printview.get_html_and_style", |  | ||||||
| 		args: { |  | ||||||
| 			doc: frm.doc, |  | ||||||
| 			print_format: "GST E-Invoice", |  | ||||||
| 			no_letterhead: 1 |  | ||||||
| 		}, |  | ||||||
| 		callback: function (r) { |  | ||||||
| 			if (!r.exc) { |  | ||||||
| 				$preview_wrapper.find(".print-format").html(r.message.html); |  | ||||||
| 				const style = ` |  | ||||||
| 					.print-format { box-shadow: 0px 0px 5px rgba(0,0,0,0.2); padding: 0.30in; min-height: 80vh; } |  | ||||||
| 					.print-preview { min-height: 0px; } |  | ||||||
| 					.modal-dialog { width: 720px; }`;
 |  | ||||||
| 
 |  | ||||||
| 				frappe.dom.set_style(style, "custom-print-style"); |  | ||||||
| 				preview_dialog.show(); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	}); |  | ||||||
| }; |  | ||||||
| @ -61,7 +61,7 @@ def create_hsn_codes(data, code_field): | |||||||
| 
 | 
 | ||||||
| def add_custom_roles_for_reports(): | def add_custom_roles_for_reports(): | ||||||
| 	for report_name in ('GST Sales Register', 'GST Purchase Register', | 	for report_name in ('GST Sales Register', 'GST Purchase Register', | ||||||
| 		'GST Itemised Sales Register', 'GST Itemised Purchase Register', 'Eway Bill', 'E-Invoice Summary'): | 		'GST Itemised Sales Register', 'GST Itemised Purchase Register', 'Eway Bill'): | ||||||
| 
 | 
 | ||||||
| 		if not frappe.db.get_value('Custom Role', dict(report=report_name)): | 		if not frappe.db.get_value('Custom Role', dict(report=report_name)): | ||||||
| 			frappe.get_doc(dict( | 			frappe.get_doc(dict( | ||||||
| @ -100,7 +100,7 @@ def add_custom_roles_for_reports(): | |||||||
| 			)).insert() | 			)).insert() | ||||||
| 
 | 
 | ||||||
| def add_permissions(): | def add_permissions(): | ||||||
| 	for doctype in ('GST HSN Code', 'GST Settings', 'GSTR 3B Report', 'Lower Deduction Certificate', 'E Invoice Settings'): | 	for doctype in ('GST HSN Code', 'GST Settings', 'GSTR 3B Report', 'Lower Deduction Certificate'): | ||||||
| 		add_permission(doctype, 'All', 0) | 		add_permission(doctype, 'All', 0) | ||||||
| 		for role in ('Accounts Manager', 'Accounts User', 'System Manager'): | 		for role in ('Accounts Manager', 'Accounts User', 'System Manager'): | ||||||
| 			add_permission(doctype, role, 0) | 			add_permission(doctype, role, 0) | ||||||
| @ -116,11 +116,9 @@ def add_permissions(): | |||||||
| def add_print_formats(): | def add_print_formats(): | ||||||
| 	frappe.reload_doc("regional", "print_format", "gst_tax_invoice") | 	frappe.reload_doc("regional", "print_format", "gst_tax_invoice") | ||||||
| 	frappe.reload_doc("accounts", "print_format", "gst_pos_invoice") | 	frappe.reload_doc("accounts", "print_format", "gst_pos_invoice") | ||||||
| 	frappe.reload_doc("accounts", "print_format", "GST E-Invoice") |  | ||||||
| 
 | 
 | ||||||
| 	frappe.db.set_value("Print Format", "GST POS Invoice", "disabled", 0) | 	frappe.db.set_value("Print Format", "GST POS Invoice", "disabled", 0) | ||||||
| 	frappe.db.set_value("Print Format", "GST Tax Invoice", "disabled", 0) | 	frappe.db.set_value("Print Format", "GST Tax Invoice", "disabled", 0) | ||||||
| 	frappe.db.set_value("Print Format", "GST E-Invoice", "disabled", 0) |  | ||||||
| 
 | 
 | ||||||
| def make_property_setters(patch=False): | def make_property_setters(patch=False): | ||||||
| 	# GST rules do not allow for an invoice no. bigger than 16 characters | 	# GST rules do not allow for an invoice no. bigger than 16 characters | ||||||
| @ -445,53 +443,13 @@ def make_custom_fields(update=True): | |||||||
| 			'fieldname': 'ewaybill', | 			'fieldname': 'ewaybill', | ||||||
| 			'label': 'E-Way Bill No.', | 			'label': 'E-Way Bill No.', | ||||||
| 			'fieldtype': 'Data', | 			'fieldtype': 'Data', | ||||||
| 			'depends_on': 'eval:((doc.docstatus === 1 || doc.ewaybill) && doc.eway_bill_cancelled === 0)', | 			'depends_on': 'eval:(doc.docstatus === 1)', | ||||||
| 			'allow_on_submit': 1, | 			'allow_on_submit': 1, | ||||||
| 			'insert_after': 'tax_id', | 			'insert_after': 'tax_id', | ||||||
| 			'translatable': 0 | 			'translatable': 0 | ||||||
| 		} | 		} | ||||||
| 	] | 	] | ||||||
| 
 | 
 | ||||||
| 	si_einvoice_fields = [ |  | ||||||
| 		dict(fieldname='irn', label='IRN', fieldtype='Data', read_only=1, insert_after='customer', no_copy=1, print_hide=1, |  | ||||||
| 			depends_on='eval:in_list(["Registered Regular", "SEZ", "Overseas", "Deemed Export"], doc.gst_category) && doc.irn_cancelled === 0'), |  | ||||||
| 
 |  | ||||||
| 		dict(fieldname='irn_cancelled', label='IRN Cancelled', fieldtype='Check', no_copy=1, print_hide=1, |  | ||||||
| 			depends_on='eval: doc.irn', allow_on_submit=1, insert_after='customer'), |  | ||||||
| 
 |  | ||||||
| 		dict(fieldname='eway_bill_validity', label='E-Way Bill Validity', fieldtype='Data', no_copy=1, print_hide=1, |  | ||||||
| 			depends_on='ewaybill', read_only=1, allow_on_submit=1, insert_after='ewaybill'), |  | ||||||
| 
 |  | ||||||
| 		dict(fieldname='eway_bill_cancelled', label='E-Way Bill Cancelled', fieldtype='Check', no_copy=1, print_hide=1, |  | ||||||
| 			depends_on='eval:(doc.eway_bill_cancelled === 1)', read_only=1, allow_on_submit=1, insert_after='customer'), |  | ||||||
| 
 |  | ||||||
| 		dict(fieldname='einvoice_section', label='E-Invoice Fields', fieldtype='Section Break', insert_after='gst_vehicle_type', |  | ||||||
| 			print_hide=1, hidden=1), |  | ||||||
| 
 |  | ||||||
| 		dict(fieldname='ack_no', label='Ack. No.', fieldtype='Data', read_only=1, hidden=1, insert_after='einvoice_section', |  | ||||||
| 			no_copy=1, print_hide=1), |  | ||||||
| 
 |  | ||||||
| 		dict(fieldname='ack_date', label='Ack. Date', fieldtype='Data', read_only=1, hidden=1, insert_after='ack_no', no_copy=1, print_hide=1), |  | ||||||
| 
 |  | ||||||
| 		dict(fieldname='irn_cancel_date', label='Cancel Date', fieldtype='Data', read_only=1, hidden=1, insert_after='ack_date', |  | ||||||
| 			no_copy=1, print_hide=1), |  | ||||||
| 
 |  | ||||||
| 		dict(fieldname='signed_einvoice', label='Signed E-Invoice', fieldtype='Code', options='JSON', hidden=1, insert_after='irn_cancel_date', |  | ||||||
| 			no_copy=1, print_hide=1, read_only=1), |  | ||||||
| 
 |  | ||||||
| 		dict(fieldname='signed_qr_code', label='Signed QRCode', fieldtype='Code', options='JSON', hidden=1, insert_after='signed_einvoice', |  | ||||||
| 			no_copy=1, print_hide=1, read_only=1), |  | ||||||
| 
 |  | ||||||
| 		dict(fieldname='qrcode_image', label='QRCode', fieldtype='Attach Image', hidden=1, insert_after='signed_qr_code', |  | ||||||
| 			no_copy=1, print_hide=1, read_only=1), |  | ||||||
| 
 |  | ||||||
| 		dict(fieldname='einvoice_status', label='E-Invoice Status', fieldtype='Select', insert_after='qrcode_image', |  | ||||||
| 			options='\nPending\nGenerated\nCancelled\nFailed', default=None, hidden=1, no_copy=1, print_hide=1, read_only=1), |  | ||||||
| 
 |  | ||||||
| 		dict(fieldname='failure_description', label='E-Invoice Failure Description', fieldtype='Code', options='JSON', |  | ||||||
| 			hidden=1, insert_after='einvoice_status', no_copy=1, print_hide=1, read_only=1) |  | ||||||
| 	] |  | ||||||
| 
 |  | ||||||
| 	custom_fields = { | 	custom_fields = { | ||||||
| 		'Address': [ | 		'Address': [ | ||||||
| 			dict(fieldname='gstin', label='Party GSTIN', fieldtype='Data', | 			dict(fieldname='gstin', label='Party GSTIN', fieldtype='Data', | ||||||
| @ -504,7 +462,7 @@ def make_custom_fields(update=True): | |||||||
| 		'Purchase Invoice': purchase_invoice_gst_category + invoice_gst_fields + purchase_invoice_itc_fields + purchase_invoice_gst_fields, | 		'Purchase Invoice': purchase_invoice_gst_category + invoice_gst_fields + purchase_invoice_itc_fields + purchase_invoice_gst_fields, | ||||||
| 		'Purchase Order': purchase_invoice_gst_fields, | 		'Purchase Order': purchase_invoice_gst_fields, | ||||||
| 		'Purchase Receipt': purchase_invoice_gst_fields, | 		'Purchase Receipt': purchase_invoice_gst_fields, | ||||||
| 		'Sales Invoice': sales_invoice_gst_category + invoice_gst_fields + sales_invoice_shipping_fields + sales_invoice_gst_fields + si_ewaybill_fields + si_einvoice_fields, | 		'Sales Invoice': sales_invoice_gst_category + invoice_gst_fields + sales_invoice_shipping_fields + sales_invoice_gst_fields + si_ewaybill_fields, | ||||||
| 		'Delivery Note': sales_invoice_gst_fields + ewaybill_fields + sales_invoice_shipping_fields + delivery_note_gst_category, | 		'Delivery Note': sales_invoice_gst_fields + ewaybill_fields + sales_invoice_shipping_fields + delivery_note_gst_category, | ||||||
| 		'Journal Entry': journal_entry_fields, | 		'Journal Entry': journal_entry_fields, | ||||||
| 		'Sales Order': sales_invoice_gst_fields, | 		'Sales Order': sales_invoice_gst_fields, | ||||||
|  | |||||||
| @ -475,7 +475,7 @@ def get_ewb_data(dt, dn): | |||||||
| 		ewaybills.append(data) | 		ewaybills.append(data) | ||||||
| 
 | 
 | ||||||
| 	data = { | 	data = { | ||||||
| 		'version': '1.0.1118', | 		'version': '1.0.0421', | ||||||
| 		'billLists': ewaybills | 		'billLists': ewaybills | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -871,3 +871,20 @@ def set_item_tax_from_hsn_code(item): | |||||||
| 				'tax_category': tax.tax_category, | 				'tax_category': tax.tax_category, | ||||||
| 				'valid_from': tax.valid_from | 				'valid_from': tax.valid_from | ||||||
| 			}) | 			}) | ||||||
|  | 
 | ||||||
|  | def delete_gst_settings_for_company(doc, method): | ||||||
|  | 	if doc.country != 'India': | ||||||
|  | 		return | ||||||
|  | 
 | ||||||
|  | 	gst_settings = frappe.get_doc("GST Settings") | ||||||
|  | 	records_to_delete = [] | ||||||
|  | 
 | ||||||
|  | 	for d in reversed(gst_settings.get('gst_accounts')): | ||||||
|  | 		if d.company == doc.name: | ||||||
|  | 			records_to_delete.append(d) | ||||||
|  | 
 | ||||||
|  | 	for d in records_to_delete: | ||||||
|  | 		gst_settings.remove(d) | ||||||
|  | 
 | ||||||
|  | 	gst_settings.save() | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -1,55 +0,0 @@ | |||||||
| // Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
 |  | ||||||
| // For license information, please see license.txt
 |  | ||||||
| /* eslint-disable */ |  | ||||||
| 
 |  | ||||||
| frappe.query_reports["E-Invoice Summary"] = { |  | ||||||
| 	"filters": [ |  | ||||||
| 		{ |  | ||||||
| 			"fieldtype": "Link", |  | ||||||
| 			"options": "Company", |  | ||||||
| 			"reqd": 1, |  | ||||||
| 			"fieldname": "company", |  | ||||||
| 			"label": __("Company"), |  | ||||||
| 			"default": frappe.defaults.get_user_default("Company"), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"fieldtype": "Link", |  | ||||||
| 			"options": "Customer", |  | ||||||
| 			"fieldname": "customer", |  | ||||||
| 			"label": __("Customer") |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"fieldtype": "Date", |  | ||||||
| 			"reqd": 1, |  | ||||||
| 			"fieldname": "from_date", |  | ||||||
| 			"label": __("From Date"), |  | ||||||
| 			"default": frappe.datetime.add_months(frappe.datetime.get_today(), -1), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"fieldtype": "Date", |  | ||||||
| 			"reqd": 1, |  | ||||||
| 			"fieldname": "to_date", |  | ||||||
| 			"label": __("To Date"), |  | ||||||
| 			"default": frappe.datetime.get_today(), |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"fieldtype": "Select", |  | ||||||
| 			"fieldname": "status", |  | ||||||
| 			"label": __("Status"), |  | ||||||
| 			"options": "\nPending\nGenerated\nCancelled\nFailed" |  | ||||||
| 		} |  | ||||||
| 	], |  | ||||||
| 
 |  | ||||||
| 	"formatter": function (value, row, column, data, default_formatter) { |  | ||||||
| 		value = default_formatter(value, row, column, data); |  | ||||||
| 
 |  | ||||||
| 		if (column.fieldname == "einvoice_status" && value) { |  | ||||||
| 			if (value == 'Pending') value = `<span class="bold" style="color: var(--text-on-orange)">${value}</span>`; |  | ||||||
| 			else if (value == 'Generated') value = `<span class="bold" style="color: var(--text-on-green)">${value}</span>`; |  | ||||||
| 			else if (value == 'Cancelled') value = `<span class="bold" style="color: var(--text-on-red)">${value}</span>`; |  | ||||||
| 			else if (value == 'Failed') value = `<span class="bold"  style="color: var(--text-on-red)">${value}</span>`; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		return value; |  | ||||||
| 	} |  | ||||||
| }; |  | ||||||
| @ -1,28 +0,0 @@ | |||||||
| { |  | ||||||
|  "add_total_row": 0, |  | ||||||
|  "columns": [], |  | ||||||
|  "creation": "2021-03-12 11:23:37.312294", |  | ||||||
|  "disable_prepared_report": 0, |  | ||||||
|  "disabled": 0, |  | ||||||
|  "docstatus": 0, |  | ||||||
|  "doctype": "Report", |  | ||||||
|  "filters": [], |  | ||||||
|  "idx": 0, |  | ||||||
|  "is_standard": "Yes", |  | ||||||
|  "json": "{}", |  | ||||||
|  "letter_head": "Logo", |  | ||||||
|  "modified": "2021-03-13 12:36:48.689413", |  | ||||||
|  "modified_by": "Administrator", |  | ||||||
|  "module": "Regional", |  | ||||||
|  "name": "E-Invoice Summary", |  | ||||||
|  "owner": "Administrator", |  | ||||||
|  "prepared_report": 0, |  | ||||||
|  "ref_doctype": "Sales Invoice", |  | ||||||
|  "report_name": "E-Invoice Summary", |  | ||||||
|  "report_type": "Script Report", |  | ||||||
|  "roles": [ |  | ||||||
|   { |  | ||||||
|    "role": "Administrator" |  | ||||||
|   } |  | ||||||
|  ] |  | ||||||
| } |  | ||||||
| @ -1,106 +0,0 @@ | |||||||
| # Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors |  | ||||||
| # For license information, please see license.txt |  | ||||||
| 
 |  | ||||||
| from __future__ import unicode_literals |  | ||||||
| import frappe |  | ||||||
| from frappe import _ |  | ||||||
| 
 |  | ||||||
| def execute(filters=None): |  | ||||||
| 	validate_filters(filters) |  | ||||||
| 
 |  | ||||||
| 	columns = get_columns() |  | ||||||
| 	data = get_data(filters) |  | ||||||
| 
 |  | ||||||
| 	return columns, data |  | ||||||
| 
 |  | ||||||
| def validate_filters(filters={}): |  | ||||||
| 	filters = frappe._dict(filters) |  | ||||||
| 
 |  | ||||||
| 	if not filters.company: |  | ||||||
| 		frappe.throw(_('{} is mandatory for generating E-Invoice Summary Report').format(_('Company')), title=_('Invalid Filter')) |  | ||||||
| 	if filters.company: |  | ||||||
| 		# validate if company has e-invoicing enabled |  | ||||||
| 		pass |  | ||||||
| 	if not filters.from_date or not filters.to_date: |  | ||||||
| 		frappe.throw(_('From Date & To Date is mandatory for generating E-Invoice Summary Report'), title=_('Invalid Filter')) |  | ||||||
| 	if filters.from_date > filters.to_date: |  | ||||||
| 		frappe.throw(_('From Date must be before To Date'), title=_('Invalid Filter')) |  | ||||||
| 
 |  | ||||||
| def get_data(filters={}): |  | ||||||
| 	query_filters = { |  | ||||||
| 		'posting_date': ['between', [filters.from_date, filters.to_date]], |  | ||||||
| 		'einvoice_status': ['is', 'set'], |  | ||||||
| 		'company': filters.company |  | ||||||
| 	} |  | ||||||
| 	if filters.customer: |  | ||||||
| 		query_filters['customer'] = filters.customer |  | ||||||
| 	if filters.status: |  | ||||||
| 		query_filters['einvoice_status'] = filters.status |  | ||||||
| 
 |  | ||||||
| 	data = frappe.get_all( |  | ||||||
| 		'Sales Invoice', |  | ||||||
| 		filters=query_filters, |  | ||||||
| 		fields=[d.get('fieldname') for d in get_columns()] |  | ||||||
| 	) |  | ||||||
| 
 |  | ||||||
| 	return data |  | ||||||
| 
 |  | ||||||
| def get_columns(): |  | ||||||
| 	return [ |  | ||||||
| 		{ |  | ||||||
| 			"fieldtype": "Date", |  | ||||||
| 			"fieldname": "posting_date", |  | ||||||
| 			"label": _("Posting Date"), |  | ||||||
| 			"width": 0 |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"fieldtype": "Link", |  | ||||||
| 			"fieldname": "name", |  | ||||||
| 			"label": _("Sales Invoice"), |  | ||||||
| 			"options": "Sales Invoice", |  | ||||||
| 			"width": 140 |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"fieldtype": "Data", |  | ||||||
| 			"fieldname": "einvoice_status", |  | ||||||
| 			"label": _("Status"), |  | ||||||
| 			"width": 100 |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"fieldtype": "Link", |  | ||||||
| 			"fieldname": "customer", |  | ||||||
| 			"options": "Customer", |  | ||||||
| 			"label": _("Customer") |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"fieldtype": "Check", |  | ||||||
| 			"fieldname": "is_return", |  | ||||||
| 			"label": _("Is Return"), |  | ||||||
| 			"width": 85 |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"fieldtype": "Data", |  | ||||||
| 			"fieldname": "ack_no", |  | ||||||
| 			"label": "Ack. No.", |  | ||||||
| 			"width": 145 |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"fieldtype": "Data", |  | ||||||
| 			"fieldname": "ack_date", |  | ||||||
| 			"label": "Ack. Date", |  | ||||||
| 			"width": 165 |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"fieldtype": "Data", |  | ||||||
| 			"fieldname": "irn", |  | ||||||
| 			"label": _("IRN No."), |  | ||||||
| 			"width": 250 |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"fieldtype": "Currency", |  | ||||||
| 			"options": "Company:company:default_currency", |  | ||||||
| 			"fieldname": "base_grand_total", |  | ||||||
| 			"label": _("Grand Total"), |  | ||||||
| 			"width": 120 |  | ||||||
| 		} |  | ||||||
| 	] |  | ||||||
| @ -571,7 +571,8 @@ | |||||||
|    "fieldtype": "Data", |    "fieldtype": "Data", | ||||||
|    "hide_days": 1, |    "hide_days": 1, | ||||||
|    "hide_seconds": 1, |    "hide_seconds": 1, | ||||||
|    "label": "Scan Barcode" |    "label": "Scan Barcode", | ||||||
|  |    "options": "Barcode" | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|    "allow_bulk_edit": 1, |    "allow_bulk_edit": 1, | ||||||
| @ -1510,7 +1511,7 @@ | |||||||
|  "idx": 105, |  "idx": 105, | ||||||
|  "is_submittable": 1, |  "is_submittable": 1, | ||||||
|  "links": [], |  "links": [], | ||||||
|  "modified": "2021-07-08 21:37:44.177493", |  "modified": "2021-08-17 20:15:26.531553", | ||||||
|  "modified_by": "Administrator", |  "modified_by": "Administrator", | ||||||
|  "module": "Selling", |  "module": "Selling", | ||||||
|  "name": "Sales Order", |  "name": "Sales Order", | ||||||
|  | |||||||
| @ -44,6 +44,18 @@ def get_data(filters, period_list, partner_doctype): | |||||||
| 		if d.item_group not in item_groups: | 		if d.item_group not in item_groups: | ||||||
| 			item_groups.append(d.item_group) | 			item_groups.append(d.item_group) | ||||||
| 
 | 
 | ||||||
|  | 	if item_groups: | ||||||
|  | 		child_items = [] | ||||||
|  | 		for item_group in item_groups: | ||||||
|  | 			if frappe.db.get_value("Item Group", {"name":item_group}, "is_group"): | ||||||
|  | 				for child_item_group in frappe.get_all("Item Group", {"parent_item_group":item_group}): | ||||||
|  | 					if child_item_group['name'] not in child_items: | ||||||
|  | 						child_items.append(child_item_group['name']) | ||||||
|  | 
 | ||||||
|  | 		for item in child_items: | ||||||
|  | 			if item not in item_groups: | ||||||
|  | 				item_groups.append(item) | ||||||
|  | 
 | ||||||
| 	date_field = ("transaction_date" | 	date_field = ("transaction_date" | ||||||
| 		if filters.get('doctype') == "Sales Order" else "posting_date") | 		if filters.get('doctype') == "Sales Order" else "posting_date") | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -394,6 +394,10 @@ erpnext.selling.SellingController = class SellingController extends erpnext.Tran | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	_set_batch_number(doc) { | 	_set_batch_number(doc) { | ||||||
|  | 		if (doc.batch_no) { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		let args = {'item_code': doc.item_code, 'warehouse': doc.warehouse, 'qty': flt(doc.qty) * flt(doc.conversion_factor)}; | 		let args = {'item_code': doc.item_code, 'warehouse': doc.warehouse, 'qty': flt(doc.qty) * flt(doc.conversion_factor)}; | ||||||
| 		if (doc.has_serial_no && doc.serial_no) { | 		if (doc.has_serial_no && doc.serial_no) { | ||||||
| 			args['serial_no'] = doc.serial_no | 			args['serial_no'] = doc.serial_no | ||||||
|  | |||||||
| @ -393,6 +393,10 @@ class Company(NestedSet): | |||||||
| 		frappe.db.sql("delete from `tabPurchase Taxes and Charges Template` where company=%s", self.name) | 		frappe.db.sql("delete from `tabPurchase Taxes and Charges Template` where company=%s", self.name) | ||||||
| 		frappe.db.sql("delete from `tabItem Tax Template` where company=%s", self.name) | 		frappe.db.sql("delete from `tabItem Tax Template` where company=%s", self.name) | ||||||
| 
 | 
 | ||||||
|  | 		# delete Process Deferred Accounts if no GL Entry found | ||||||
|  | 		if not frappe.db.get_value('GL Entry', {'company': self.name}): | ||||||
|  | 			frappe.db.sql("delete from `tabProcess Deferred Accounting` where company=%s", self.name) | ||||||
|  | 
 | ||||||
| @frappe.whitelist() | @frappe.whitelist() | ||||||
| def enqueue_replace_abbr(company, old, new): | def enqueue_replace_abbr(company, old, new): | ||||||
| 	kwargs = dict(queue="long", company=company, old=old, new=new) | 	kwargs = dict(queue="long", company=company, old=old, new=new) | ||||||
|  | |||||||
| @ -308,7 +308,7 @@ def update_party(fullname, company_name=None, mobile_no=None, phone=None): | |||||||
| 	party = get_party() | 	party = get_party() | ||||||
| 
 | 
 | ||||||
| 	party.customer_name = company_name or fullname | 	party.customer_name = company_name or fullname | ||||||
| 	party.customer_type == "Company" if company_name else "Individual" | 	party.customer_type = "Company" if company_name else "Individual" | ||||||
| 
 | 
 | ||||||
| 	contact_name = frappe.db.get_value("Contact", {"email_id": frappe.session.user}) | 	contact_name = frappe.db.get_value("Contact", {"email_id": frappe.session.user}) | ||||||
| 	contact = frappe.get_doc("Contact", contact_name) | 	contact = frappe.get_doc("Contact", contact_name) | ||||||
|  | |||||||
| @ -6,7 +6,7 @@ | |||||||
| from __future__ import unicode_literals | from __future__ import unicode_literals | ||||||
| import frappe | import frappe | ||||||
| from frappe import _, msgprint | from frappe import _, msgprint | ||||||
| from frappe.utils import comma_and | from frappe.utils import flt | ||||||
| from frappe.model.document import Document | from frappe.model.document import Document | ||||||
| from frappe.utils import get_datetime, get_datetime_str, now_datetime | from frappe.utils import get_datetime, get_datetime_str, now_datetime | ||||||
| 
 | 
 | ||||||
| @ -18,46 +18,35 @@ class ShoppingCartSettings(Document): | |||||||
| 
 | 
 | ||||||
| 	def validate(self): | 	def validate(self): | ||||||
| 		if self.enabled: | 		if self.enabled: | ||||||
| 			self.validate_exchange_rates_exist() | 			self.validate_price_list_exchange_rate() | ||||||
|  | 
 | ||||||
|  | 	def validate_price_list_exchange_rate(self): | ||||||
|  | 		"Check if exchange rate exists for Price List currency (to Company's currency)." | ||||||
|  | 		from erpnext.setup.utils import get_exchange_rate | ||||||
|  | 
 | ||||||
|  | 		if not self.enabled or not self.company or not self.price_list: | ||||||
|  | 			return # this function is also called from hooks, check values again | ||||||
|  | 
 | ||||||
|  | 		company_currency = frappe.get_cached_value("Company", self.company, "default_currency") | ||||||
|  | 		price_list_currency = frappe.db.get_value("Price List", self.price_list, "currency") | ||||||
| 
 | 
 | ||||||
| 	def validate_exchange_rates_exist(self): |  | ||||||
| 		"""check if exchange rates exist for all Price List currencies (to company's currency)""" |  | ||||||
| 		company_currency = frappe.get_cached_value('Company',  self.company,  "default_currency") |  | ||||||
| 		if not company_currency: | 		if not company_currency: | ||||||
| 			msgprint(_("Please specify currency in Company") + ": " + self.company, | 			msg = f"Please specify currency in Company {self.company}" | ||||||
| 				raise_exception=ShoppingCartSetupError) | 			frappe.throw(_(msg), title=_("Missing Currency"), exc=ShoppingCartSetupError) | ||||||
| 
 | 
 | ||||||
| 		price_list_currency_map = frappe.db.get_values("Price List", | 		if not price_list_currency: | ||||||
| 			[self.price_list], "currency") | 			msg = f"Please specify currency in Price List {frappe.bold(self.price_list)}" | ||||||
|  | 			frappe.throw(_(msg), title=_("Missing Currency"), exc=ShoppingCartSetupError) | ||||||
| 
 | 
 | ||||||
| 		price_list_currency_map = dict(price_list_currency_map) | 		if price_list_currency != company_currency: | ||||||
|  | 			from_currency, to_currency = price_list_currency, company_currency | ||||||
| 
 | 
 | ||||||
| 		# check if all price lists have a currency | 			# Get exchange rate checks Currency Exchange Records too | ||||||
| 		for price_list, currency in price_list_currency_map.items(): | 			exchange_rate = get_exchange_rate(from_currency, to_currency, args="for_selling") | ||||||
| 			if not currency: |  | ||||||
| 				frappe.throw(_("Currency is required for Price List {0}").format(price_list)) |  | ||||||
| 
 | 
 | ||||||
| 		expected_to_exist = [currency + "-" + company_currency | 			if not flt(exchange_rate): | ||||||
| 			for currency in price_list_currency_map.values() | 				msg = f"Missing Currency Exchange Rates for {from_currency}-{to_currency}" | ||||||
| 			if currency != company_currency] | 				frappe.throw(_(msg), title=_("Missing"), exc=ShoppingCartSetupError) | ||||||
| 
 |  | ||||||
| 		# manqala 20/09/2016: set up selection parameters for query from tabCurrency Exchange |  | ||||||
| 		from_currency = [currency for currency in price_list_currency_map.values() if currency != company_currency] |  | ||||||
| 		to_currency = company_currency |  | ||||||
| 		# manqala end |  | ||||||
| 
 |  | ||||||
| 		if expected_to_exist: |  | ||||||
| 			# manqala 20/09/2016: modify query so that it uses date in the selection from Currency Exchange. |  | ||||||
| 			# exchange rates defined with date less than the date on which this document is being saved will be selected |  | ||||||
| 			exists = frappe.db.sql_list("""select CONCAT(from_currency,'-',to_currency) from `tabCurrency Exchange` |  | ||||||
| 				where from_currency in (%s) and to_currency = "%s" and date <= curdate()""" % (", ".join(["%s"]*len(from_currency)), to_currency), tuple(from_currency)) |  | ||||||
| 			# manqala end |  | ||||||
| 
 |  | ||||||
| 			missing = list(set(expected_to_exist).difference(exists)) |  | ||||||
| 
 |  | ||||||
| 			if missing: |  | ||||||
| 				msgprint(_("Missing Currency Exchange Rates for {0}").format(comma_and(missing)), |  | ||||||
| 					raise_exception=ShoppingCartSetupError) |  | ||||||
| 
 | 
 | ||||||
| 	def validate_tax_rule(self): | 	def validate_tax_rule(self): | ||||||
| 		if not frappe.db.get_value("Tax Rule", {"use_for_shopping_cart" : 1}, "name"): | 		if not frappe.db.get_value("Tax Rule", {"use_for_shopping_cart" : 1}, "name"): | ||||||
| @ -71,7 +60,7 @@ class ShoppingCartSettings(Document): | |||||||
| 	def get_shipping_rules(self, shipping_territory): | 	def get_shipping_rules(self, shipping_territory): | ||||||
| 		return self.get_name_from_territory(shipping_territory, "shipping_rules", "shipping_rule") | 		return self.get_name_from_territory(shipping_territory, "shipping_rules", "shipping_rule") | ||||||
| 
 | 
 | ||||||
| def validate_cart_settings(doc, method): | def validate_cart_settings(doc=None, method=None): | ||||||
| 	frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings").run_method("validate") | 	frappe.get_doc("Shopping Cart Settings", "Shopping Cart Settings").run_method("validate") | ||||||
| 
 | 
 | ||||||
| def get_shopping_cart_settings(): | def get_shopping_cart_settings(): | ||||||
|  | |||||||
| @ -16,17 +16,25 @@ class TestShoppingCartSettings(unittest.TestCase): | |||||||
| 		return frappe.get_doc({"doctype": "Shopping Cart Settings", | 		return frappe.get_doc({"doctype": "Shopping Cart Settings", | ||||||
| 			"company": "_Test Company"}) | 			"company": "_Test Company"}) | ||||||
| 
 | 
 | ||||||
| 	def test_exchange_rate_exists(self): | 	# NOTE: Exchangrate API has all enabled currencies that ERPNext supports. | ||||||
| 		frappe.db.sql("""delete from `tabCurrency Exchange`""") | 	# We aren't checking just currency exchange record anymore | ||||||
|  | 	# while validating price list currency exchange rate to that of company. | ||||||
|  | 	# The API is being used to fetch the rate which again almost always | ||||||
|  | 	# gives back a valid value (for valid currencies). | ||||||
|  | 	# This makes the test obsolete. | ||||||
|  | 	# Commenting because im not sure if there's a better test we can write | ||||||
| 
 | 
 | ||||||
| 		cart_settings = self.get_cart_settings() | 	# def test_exchange_rate_exists(self): | ||||||
| 		cart_settings.price_list = "_Test Price List Rest of the World" | 	# 	frappe.db.sql("""delete from `tabCurrency Exchange`""") | ||||||
| 		self.assertRaises(ShoppingCartSetupError, cart_settings.validate_exchange_rates_exist) |  | ||||||
| 
 | 
 | ||||||
| 		from erpnext.setup.doctype.currency_exchange.test_currency_exchange import test_records as \ | 	# 	cart_settings = self.get_cart_settings() | ||||||
| 			currency_exchange_records | 	# 	cart_settings.price_list = "_Test Price List Rest of the World" | ||||||
| 		frappe.get_doc(currency_exchange_records[0]).insert() | 	# 	self.assertRaises(ShoppingCartSetupError, cart_settings.validate_price_list_exchange_rate) | ||||||
| 		cart_settings.validate_exchange_rates_exist() | 
 | ||||||
|  | 	# 	from erpnext.setup.doctype.currency_exchange.test_currency_exchange import test_records as \ | ||||||
|  | 	# 		currency_exchange_records | ||||||
|  | 	# 	frappe.get_doc(currency_exchange_records[0]).insert() | ||||||
|  | 	# 	cart_settings.validate_price_list_exchange_rate() | ||||||
| 
 | 
 | ||||||
| 	def test_tax_rule_validation(self): | 	def test_tax_rule_validation(self): | ||||||
| 		frappe.db.sql("update `tabTax Rule` set use_for_shopping_cart = 0") | 		frappe.db.sql("update `tabTax Rule` set use_for_shopping_cart = 0") | ||||||
|  | |||||||
| @ -515,7 +515,8 @@ | |||||||
|   { |   { | ||||||
|    "fieldname": "scan_barcode", |    "fieldname": "scan_barcode", | ||||||
|    "fieldtype": "Data", |    "fieldtype": "Data", | ||||||
|    "label": "Scan Barcode" |    "label": "Scan Barcode", | ||||||
|  |    "options": "Barcode" | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|    "allow_bulk_edit": 1, |    "allow_bulk_edit": 1, | ||||||
| @ -1305,7 +1306,7 @@ | |||||||
|  "idx": 146, |  "idx": 146, | ||||||
|  "is_submittable": 1, |  "is_submittable": 1, | ||||||
|  "links": [], |  "links": [], | ||||||
|  "modified": "2021-07-08 21:37:20.802652", |  "modified": "2021-08-17 20:15:50.574966", | ||||||
|  "modified_by": "Administrator", |  "modified_by": "Administrator", | ||||||
|  "module": "Stock", |  "module": "Stock", | ||||||
|  "name": "Delivery Note", |  "name": "Delivery Note", | ||||||
|  | |||||||
| @ -133,7 +133,8 @@ | |||||||
|   { |   { | ||||||
|    "fieldname": "scan_barcode", |    "fieldname": "scan_barcode", | ||||||
|    "fieldtype": "Data", |    "fieldtype": "Data", | ||||||
|    "label": "Scan Barcode" |    "label": "Scan Barcode", | ||||||
|  |    "options": "Barcode" | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|    "allow_bulk_edit": 1, |    "allow_bulk_edit": 1, | ||||||
| @ -181,7 +182,7 @@ | |||||||
|    "no_copy": 1, |    "no_copy": 1, | ||||||
|    "oldfieldname": "status", |    "oldfieldname": "status", | ||||||
|    "oldfieldtype": "Select", |    "oldfieldtype": "Select", | ||||||
|    "options": "\nDraft\nSubmitted\nStopped\nCancelled\nPending\nPartially Ordered\nPartially Received\nOrdered\nIssued\nTransferred\nReceived", |    "options": "\nDraft\nSubmitted\nStopped\nCancelled\nPending\nPartially Ordered\nOrdered\nIssued\nTransferred\nReceived", | ||||||
|    "print_hide": 1, |    "print_hide": 1, | ||||||
|    "print_width": "100px", |    "print_width": "100px", | ||||||
|    "read_only": 1, |    "read_only": 1, | ||||||
| @ -314,7 +315,7 @@ | |||||||
|  "idx": 70, |  "idx": 70, | ||||||
|  "is_submittable": 1, |  "is_submittable": 1, | ||||||
|  "links": [], |  "links": [], | ||||||
|  "modified": "2021-03-31 23:52:55.392512", |  "modified": "2021-08-17 20:16:12.737743", | ||||||
|  "modified_by": "Administrator", |  "modified_by": "Administrator", | ||||||
|  "module": "Stock", |  "module": "Stock", | ||||||
|  "name": "Material Request", |  "name": "Material Request", | ||||||
|  | |||||||
| @ -13,6 +13,9 @@ class PriceList(Document): | |||||||
| 		if not cint(self.buying) and not cint(self.selling): | 		if not cint(self.buying) and not cint(self.selling): | ||||||
| 			throw(_("Price List must be applicable for Buying or Selling")) | 			throw(_("Price List must be applicable for Buying or Selling")) | ||||||
| 
 | 
 | ||||||
|  | 		if not self.is_new(): | ||||||
|  | 			self.check_impact_on_shopping_cart() | ||||||
|  | 
 | ||||||
| 	def on_update(self): | 	def on_update(self): | ||||||
| 		self.set_default_if_missing() | 		self.set_default_if_missing() | ||||||
| 		self.update_item_price() | 		self.update_item_price() | ||||||
| @ -32,6 +35,17 @@ class PriceList(Document): | |||||||
| 			buying=%s, selling=%s, modified=NOW() where price_list=%s""", | 			buying=%s, selling=%s, modified=NOW() where price_list=%s""", | ||||||
| 			(self.currency, cint(self.buying), cint(self.selling), self.name)) | 			(self.currency, cint(self.buying), cint(self.selling), self.name)) | ||||||
| 
 | 
 | ||||||
|  | 	def check_impact_on_shopping_cart(self): | ||||||
|  | 		"Check if Price List currency change impacts Shopping Cart." | ||||||
|  | 		from erpnext.shopping_cart.doctype.shopping_cart_settings.shopping_cart_settings import validate_cart_settings | ||||||
|  | 
 | ||||||
|  | 		doc_before_save = self.get_doc_before_save() | ||||||
|  | 		currency_changed = self.currency != doc_before_save.currency | ||||||
|  | 		affects_cart = self.name == frappe.get_cached_value("Shopping Cart Settings", None, "price_list") | ||||||
|  | 
 | ||||||
|  | 		if currency_changed and affects_cart: | ||||||
|  | 			validate_cart_settings() | ||||||
|  | 
 | ||||||
| 	def on_trash(self): | 	def on_trash(self): | ||||||
| 		self.delete_price_list_details_key() | 		self.delete_price_list_details_key() | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1098,7 +1098,8 @@ | |||||||
|   { |   { | ||||||
|    "fieldname": "scan_barcode", |    "fieldname": "scan_barcode", | ||||||
|    "fieldtype": "Data", |    "fieldtype": "Data", | ||||||
|    "label": "Scan Barcode" |    "label": "Scan Barcode", | ||||||
|  |    "options": "Barcode" | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|    "fieldname": "billing_address", |    "fieldname": "billing_address", | ||||||
| @ -1148,7 +1149,7 @@ | |||||||
|  "idx": 261, |  "idx": 261, | ||||||
|  "is_submittable": 1, |  "is_submittable": 1, | ||||||
|  "links": [], |  "links": [], | ||||||
|  "modified": "2021-05-25 00:15:12.239017", |  "modified": "2021-08-17 20:16:40.849885", | ||||||
|  "modified_by": "Administrator", |  "modified_by": "Administrator", | ||||||
|  "module": "Stock", |  "module": "Stock", | ||||||
|  "name": "Purchase Receipt", |  "name": "Purchase Receipt", | ||||||
|  | |||||||
| @ -355,6 +355,7 @@ | |||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|    "fieldname": "scan_barcode", |    "fieldname": "scan_barcode", | ||||||
|  |    "options": "Barcode", | ||||||
|    "fieldtype": "Data", |    "fieldtype": "Data", | ||||||
|    "label": "Scan Barcode" |    "label": "Scan Barcode" | ||||||
|   }, |   }, | ||||||
| @ -629,7 +630,7 @@ | |||||||
|  "index_web_pages_for_search": 1, |  "index_web_pages_for_search": 1, | ||||||
|  "is_submittable": 1, |  "is_submittable": 1, | ||||||
|  "links": [], |  "links": [], | ||||||
|  "modified": "2021-05-26 17:07:58.015737", |  "modified": "2021-08-17 20:16:12.737743", | ||||||
|  "modified_by": "Administrator", |  "modified_by": "Administrator", | ||||||
|  "module": "Stock", |  "module": "Stock", | ||||||
|  "name": "Stock Entry", |  "name": "Stock Entry", | ||||||
|  | |||||||
| @ -317,9 +317,6 @@ class StockEntry(StockController): | |||||||
| 				d.s_warehouse = self.from_warehouse | 				d.s_warehouse = self.from_warehouse | ||||||
| 				d.t_warehouse = self.to_warehouse | 				d.t_warehouse = self.to_warehouse | ||||||
| 
 | 
 | ||||||
| 			if not (d.s_warehouse or d.t_warehouse): |  | ||||||
| 				frappe.throw(_("Atleast one warehouse is mandatory")) |  | ||||||
| 
 |  | ||||||
| 			if self.purpose in source_mandatory and not d.s_warehouse: | 			if self.purpose in source_mandatory and not d.s_warehouse: | ||||||
| 				if self.from_warehouse: | 				if self.from_warehouse: | ||||||
| 					d.s_warehouse = self.from_warehouse | 					d.s_warehouse = self.from_warehouse | ||||||
| @ -332,6 +329,7 @@ class StockEntry(StockController): | |||||||
| 				else: | 				else: | ||||||
| 					frappe.throw(_("Target warehouse is mandatory for row {0}").format(d.idx)) | 					frappe.throw(_("Target warehouse is mandatory for row {0}").format(d.idx)) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| 			if self.purpose == "Manufacture": | 			if self.purpose == "Manufacture": | ||||||
| 				if validate_for_manufacture: | 				if validate_for_manufacture: | ||||||
| 					if d.is_finished_item or d.is_scrap_item: | 					if d.is_finished_item or d.is_scrap_item: | ||||||
| @ -346,6 +344,9 @@ class StockEntry(StockController): | |||||||
| 			if cstr(d.s_warehouse) == cstr(d.t_warehouse) and not self.purpose == "Material Transfer for Manufacture": | 			if cstr(d.s_warehouse) == cstr(d.t_warehouse) and not self.purpose == "Material Transfer for Manufacture": | ||||||
| 				frappe.throw(_("Source and target warehouse cannot be same for row {0}").format(d.idx)) | 				frappe.throw(_("Source and target warehouse cannot be same for row {0}").format(d.idx)) | ||||||
| 
 | 
 | ||||||
|  | 			if not (d.s_warehouse or d.t_warehouse): | ||||||
|  | 				frappe.throw(_("Atleast one warehouse is mandatory")) | ||||||
|  | 
 | ||||||
| 	def validate_work_order(self): | 	def validate_work_order(self): | ||||||
| 		if self.purpose in ("Manufacture", "Material Transfer for Manufacture", "Material Consumption for Manufacture"): | 		if self.purpose in ("Manufacture", "Material Transfer for Manufacture", "Material Consumption for Manufacture"): | ||||||
| 			# check if work order is entered | 			# check if work order is entered | ||||||
|  | |||||||
| @ -278,6 +278,10 @@ def get_basic_details(args, item, overwrite_warehouse=True): | |||||||
| 		else: | 		else: | ||||||
| 			args.uom = item.stock_uom | 			args.uom = item.stock_uom | ||||||
| 
 | 
 | ||||||
|  | 	if (args.get("batch_no") and | ||||||
|  | 		item.name != frappe.get_cached_value('Batch', args.get("batch_no"), 'item')): | ||||||
|  | 		args['batch_no'] = '' | ||||||
|  | 
 | ||||||
| 	out = frappe._dict({ | 	out = frappe._dict({ | ||||||
| 		"item_code": item.name, | 		"item_code": item.name, | ||||||
| 		"item_name": item.item_name, | 		"item_name": item.item_name, | ||||||
|  | |||||||
| @ -23,6 +23,7 @@ def execute(filters=None): | |||||||
| 	conversion_factors = [] | 	conversion_factors = [] | ||||||
| 	if opening_row: | 	if opening_row: | ||||||
| 		data.append(opening_row) | 		data.append(opening_row) | ||||||
|  | 		conversion_factors.append(0) | ||||||
| 
 | 
 | ||||||
| 	actual_qty = stock_value = 0 | 	actual_qty = stock_value = 0 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -267,11 +267,15 @@ class TestServiceLevelAgreement(unittest.TestCase): | |||||||
| 		) | 		) | ||||||
| 		creation = datetime.datetime(2019, 3, 4, 12, 0) | 		creation = datetime.datetime(2019, 3, 4, 12, 0) | ||||||
| 		lead = make_lead(creation=creation, index=4) | 		lead = make_lead(creation=creation, index=4) | ||||||
| 		self.assertFalse(lead.service_level_agreement) | 		applied_sla = frappe.db.get_value('Lead', lead.name, 'service_level_agreement') | ||||||
|  | 		self.assertFalse(applied_sla) | ||||||
| 
 | 
 | ||||||
|  | 		source = frappe.get_doc(doctype='Lead Source', source_name='Test Source') | ||||||
|  | 		source.insert(ignore_if_duplicate=True) | ||||||
| 		lead.source = "Test Source" | 		lead.source = "Test Source" | ||||||
| 		lead.save() | 		lead.save() | ||||||
| 		self.assertEqual(lead.service_level_agreement, lead_sla.name) | 		applied_sla = frappe.db.get_value('Lead', lead.name, 'service_level_agreement') | ||||||
|  | 		self.assertEqual(applied_sla, lead_sla.name) | ||||||
| 
 | 
 | ||||||
| 	def tearDown(self): | 	def tearDown(self): | ||||||
| 		for d in frappe.get_all("Service Level Agreement"): | 		for d in frappe.get_all("Service Level Agreement"): | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user