From a57d13e1e9538e56b401d651c52d2b9c5b84250f Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 29 Jul 2021 19:46:17 +0530 Subject: [PATCH 01/23] fix: Multiple fixes in payment entry --- .../doctype/payment_entry/payment_entry.js | 4 ++-- .../doctype/payment_entry/payment_entry.py | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index 439b1edbce..d96bc271ef 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -533,8 +533,8 @@ frappe.ui.form.on('Payment Entry', { source_exchange_rate: function(frm) { if (frm.doc.paid_amount) { 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 && - (frm.doc.paid_from_account_currency == frm.doc.paid_to_account_currency)) { + // target exchange rate should always be same as source if both account currencies is same + 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("base_received_amount", frm.doc.base_paid_amount); } diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 46904f7c57..a131a810e1 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -55,8 +55,9 @@ class PaymentEntry(AccountsController): self.validate_mandatory() self.validate_reference_documents() self.set_tax_withholding() - self.apply_taxes() self.set_amounts() + self.validate_amounts() + self.apply_taxes() self.clear_unallocated_reference_document_rows() self.validate_payment_against_negative_invoice() self.validate_transaction_reference() @@ -236,7 +237,9 @@ class PaymentEntry(AccountsController): self.company_currency, self.posting_date) 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 self.paid_to_account_currency == ref_doc.currency: self.target_exchange_rate = ref_doc.get("exchange_rate") @@ -473,6 +476,14 @@ class PaymentEntry(AccountsController): self.set_unallocated_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): self.base_received_amount = self.base_paid_amount From c5276f3fd36764e5e90b0b068d0d9937a88e4447 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 1 Aug 2021 17:48:50 +0530 Subject: [PATCH 02/23] fix: Multiple fixes in payment entry --- .../accounts/doctype/payment_entry/payment_entry.py | 13 ++++++++----- erpnext/accounts/utils.py | 12 ++++++++---- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index a131a810e1..2231b47d9c 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -45,7 +45,7 @@ class PaymentEntry(AccountsController): self.party_account = self.paid_to self.party_account_currency = self.paid_to_account_currency - def validate(self): + def validate(self, on_reference_unlink=False): self.setup_party_account_field() self.set_missing_values() self.validate_payment_type() @@ -64,8 +64,9 @@ class PaymentEntry(AccountsController): self.set_title() self.set_remarks() self.validate_duplicate_entry() - self.validate_allocated_amount() - self.validate_paid_invoices() + if not on_reference_unlink: + self.validate_allocated_amount() + self.validate_paid_invoices() self.ensure_supplier_is_not_blocked() self.set_status() @@ -529,8 +530,10 @@ class PaymentEntry(AccountsController): base_total_allocated_amount += flt(flt(d.allocated_amount) * flt(d.exchange_rate), self.precision("base_paid_amount")) - self.total_allocated_amount = abs(total_allocated_amount) - self.base_total_allocated_amount = abs(base_total_allocated_amount) + # Do not use absolute values as only credit notes could be allocated + # and total allocated should be negative in that scenario + self.total_allocated_amount = total_allocated_amount + self.base_total_allocated_amount = base_total_allocated_amount def set_unallocated_amount(self): self.unallocated_amount = 0 diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 9272bc4fce..11e113d000 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -553,10 +553,14 @@ def remove_ref_doc_link_from_pe(ref_type, ref_no): and docstatus < 2""", (now(), frappe.session.user, ref_type, ref_no)) for pe in linked_pe: - pe_doc = frappe.get_doc("Payment Entry", pe) - pe_doc.set_total_allocated_amount() - pe_doc.set_unallocated_amount() - pe_doc.clear_unallocated_reference_document_rows() + try: + pe_doc = frappe.get_doc("Payment Entry", pe) + pe_doc.validate(on_reference_unlink=True) + except Exception as e: + msg = _("There were issues unlinking payment entry {0}.").format(pe_doc.name) + msg += '
' + msg += _("Please cancel payment entry manually first and then resubmit") + frappe.throw(msg, title=_("Payment Unlink Error")) frappe.db.sql("""update `tabPayment Entry` set total_allocated_amount=%s, base_total_allocated_amount=%s, unallocated_amount=%s, modified=%s, modified_by=%s From 188bba8feb64519de2c1ded0d5432308c397f04a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 10 Aug 2021 14:04:31 +0530 Subject: [PATCH 03/23] fix: Validation for receivingfrom customer against negative outstanding --- .../accounts/doctype/payment_entry/payment_entry.py | 12 ++++++++---- erpnext/accounts/utils.py | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 2231b47d9c..66b46675dc 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -64,6 +64,7 @@ class PaymentEntry(AccountsController): self.set_title() self.set_remarks() self.validate_duplicate_entry() + self.validate_payment_type_with_outstanding() if not on_reference_unlink: self.validate_allocated_amount() self.validate_paid_invoices() @@ -120,6 +121,11 @@ class PaymentEntry(AccountsController): if not self.get(field): 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): for d in self.get("references"): if (flt(d.allocated_amount))> 0: @@ -530,10 +536,8 @@ class PaymentEntry(AccountsController): base_total_allocated_amount += flt(flt(d.allocated_amount) * flt(d.exchange_rate), self.precision("base_paid_amount")) - # Do not use absolute values as only credit notes could be allocated - # and total allocated should be negative in that scenario - self.total_allocated_amount = total_allocated_amount - self.base_total_allocated_amount = base_total_allocated_amount + self.total_allocated_amount = abs(total_allocated_amount) + self.base_total_allocated_amount = abs(base_total_allocated_amount) def set_unallocated_amount(self): self.unallocated_amount = 0 diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 11e113d000..9d84d94074 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -559,7 +559,7 @@ def remove_ref_doc_link_from_pe(ref_type, ref_no): except Exception as e: msg = _("There were issues unlinking payment entry {0}.").format(pe_doc.name) msg += '
' - msg += _("Please cancel payment entry manually first and then resubmit") + msg += _("Please cancel payment entry manually first") frappe.throw(msg, title=_("Payment Unlink Error")) frappe.db.sql("""update `tabPayment Entry` set total_allocated_amount=%s, From b5162390e5881a110ca460ad4720de40ff7d4e1d Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 10 Aug 2021 14:52:24 +0530 Subject: [PATCH 04/23] fix: Only do specific validations on reference unlink --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 7 +++---- erpnext/accounts/utils.py | 5 ++++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 66b46675dc..16b4720b37 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -45,7 +45,7 @@ class PaymentEntry(AccountsController): self.party_account = self.paid_to self.party_account_currency = self.paid_to_account_currency - def validate(self, on_reference_unlink=False): + def validate(self): self.setup_party_account_field() self.set_missing_values() self.validate_payment_type() @@ -65,9 +65,8 @@ class PaymentEntry(AccountsController): self.set_remarks() self.validate_duplicate_entry() self.validate_payment_type_with_outstanding() - if not on_reference_unlink: - self.validate_allocated_amount() - self.validate_paid_invoices() + self.validate_allocated_amount() + self.validate_paid_invoices() self.ensure_supplier_is_not_blocked() self.set_status() diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 9d84d94074..0d3aa8f0ef 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -555,7 +555,10 @@ def remove_ref_doc_link_from_pe(ref_type, ref_no): for pe in linked_pe: try: pe_doc = frappe.get_doc("Payment Entry", pe) - pe_doc.validate(on_reference_unlink=True) + pe_doc.set_total_allocated_amount() + pe_doc.set_unallocated_amount() + 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 += '
' From 7141860c04fd1541f8d346a48e3e058f4ad443c9 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 10 Aug 2021 22:21:28 +0530 Subject: [PATCH 05/23] test: Update exchange rate in test cases --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 4 +++- .../accounts/doctype/payment_entry/test_payment_entry.py | 6 +++--- erpnext/accounts/utils.py | 6 +++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 16b4720b37..a991c0679b 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -58,6 +58,7 @@ class PaymentEntry(AccountsController): self.set_amounts() self.validate_amounts() self.apply_taxes() + self.set_amounts_after_tax() self.clear_unallocated_reference_document_rows() self.validate_payment_against_negative_invoice() self.validate_transaction_reference() @@ -477,7 +478,6 @@ class PaymentEntry(AccountsController): def set_amounts(self): self.set_received_amount() self.set_amounts_in_company_currency() - self.set_amounts_after_tax() self.set_total_allocated_amount() self.set_unallocated_amount() self.set_difference_amount() @@ -492,6 +492,8 @@ class PaymentEntry(AccountsController): def set_received_amount(self): 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): applicable_tax = 0 diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py index d1302f5ae7..420e8583ea 100644 --- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py @@ -107,7 +107,7 @@ class TestPaymentEntry(unittest.TestCase): pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC") pe.reference_no = "1" pe.reference_date = "2016-01-01" - pe.target_exchange_rate = 50 + pe.source_exchange_rate = 50 pe.insert() 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.reference_no = "1" pe.reference_date = "2016-01-01" - pe.target_exchange_rate = 50 + pe.source_exchange_rate = 50 pe.insert() pe.submit() @@ -463,7 +463,7 @@ class TestPaymentEntry(unittest.TestCase): pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC") pe.reference_no = "1" pe.reference_date = "2016-01-01" - pe.target_exchange_rate = 55 + pe.source_exchange_rate = 55 pe.append("deductions", { "account": "_Test Exchange Gain/Loss - _TC", diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 0d3aa8f0ef..73e2c2ea86 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -19,6 +19,7 @@ from erpnext.stock import get_warehouse_account_map class StockValueAndAccountBalanceOutOfSync(frappe.ValidationError): pass class FiscalYearError(frappe.ValidationError): pass +class PaymentEntryUnlinkError(frappe.ValidationError): pass @frappe.whitelist() def get_fiscal_year(date=None, fiscal_year=None, label="Date", verbose=1, company=None, as_dict=False): @@ -555,15 +556,14 @@ def remove_ref_doc_link_from_pe(ref_type, ref_no): for pe in linked_pe: try: pe_doc = frappe.get_doc("Payment Entry", pe) - pe_doc.set_total_allocated_amount() - pe_doc.set_unallocated_amount() + pe_doc.set_amounts() 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 += '
' msg += _("Please cancel payment entry manually first") - frappe.throw(msg, title=_("Payment Unlink Error")) + frappe.throw(msg, exc=PaymentEntryUnlinkError, title=_("Payment Unlink Error")) frappe.db.sql("""update `tabPayment Entry` set total_allocated_amount=%s, base_total_allocated_amount=%s, unallocated_amount=%s, modified=%s, modified_by=%s From 02f44528f2b43c16fc8660b3e353533ba1bc3976 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 10 Aug 2021 22:21:52 +0530 Subject: [PATCH 06/23] test: Add test case for payment entry unlink --- .../sales_invoice/test_sales_invoice.py | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index be20b18bea..623ab3f6f2 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -25,6 +25,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.delivery_note.delivery_note import make_sales_invoice from erpnext.stock.utils import get_incoming_rate +from erpnext.accounts.utils import PaymentEntryUnlinkError class TestSalesInvoice(unittest.TestCase): def make(self): @@ -135,7 +136,7 @@ class TestSalesInvoice(unittest.TestCase): pe.paid_to_account_currency = si.currency pe.source_exchange_rate = 1 pe.target_exchange_rate = 1 - pe.paid_amount = si.grand_total + pe.paid_amount = si.outstanding_amount pe.insert() pe.submit() @@ -144,6 +145,44 @@ class TestSalesInvoice(unittest.TestCase): self.assertRaises(frappe.LinkExistsError, si.cancel) 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() + + unlink_payment_on_cancel_of_invoice() + si2.load_from_db() + si2.cancel() + + si1.load_from_db() + self.assertRaises(PaymentEntryUnlinkError, si1.cancel) + unlink_payment_on_cancel_of_invoice(0) + + def test_sales_invoice_calculation_export_currency(self): si = frappe.copy_doc(test_records[2]) si.currency = "USD" From a1f0cebda5f21bf4d1dba4214fd77e0dec210578 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 11 Aug 2021 11:36:49 +0530 Subject: [PATCH 07/23] fix: Do not update settings for test --- erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 623ab3f6f2..92bf746ad8 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -174,13 +174,11 @@ class TestSalesInvoice(unittest.TestCase): pe.save() pe.submit() - unlink_payment_on_cancel_of_invoice() si2.load_from_db() si2.cancel() si1.load_from_db() self.assertRaises(PaymentEntryUnlinkError, si1.cancel) - unlink_payment_on_cancel_of_invoice(0) def test_sales_invoice_calculation_export_currency(self): From cf8d2d97dddb02e23fa338d9c15269528187c02b Mon Sep 17 00:00:00 2001 From: Noah Jacob Date: Thu, 19 Aug 2021 15:27:30 +0530 Subject: [PATCH 08/23] fix: Incorrect mandatory error message for warehouse --- erpnext/stock/doctype/stock_entry/stock_entry.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 7b31d2fdf2..90a33d3617 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -317,9 +317,6 @@ class StockEntry(StockController): d.s_warehouse = self.from_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.from_warehouse: d.s_warehouse = self.from_warehouse @@ -332,6 +329,7 @@ class StockEntry(StockController): else: frappe.throw(_("Target warehouse is mandatory for row {0}").format(d.idx)) + if self.purpose == "Manufacture": if validate_for_manufacture: 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": 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): if self.purpose in ("Manufacture", "Material Transfer for Manufacture", "Material Consumption for Manufacture"): # check if work order is entered From 6541453c1697571bbc8fd50d0598cc20dfef2c34 Mon Sep 17 00:00:00 2001 From: Noah Jacob Date: Thu, 19 Aug 2021 15:53:55 +0530 Subject: [PATCH 09/23] fix(ux): removed rate from grid view --- .../promotional_scheme_price_discount.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.json b/erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.json index 795fb1c6f4..a70d5c9d43 100644 --- a/erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.json +++ b/erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.json @@ -106,7 +106,6 @@ "depends_on": "eval:doc.rate_or_discount==\"Rate\"", "fieldname": "rate", "fieldtype": "Currency", - "in_list_view": 1, "label": "Rate" }, { @@ -170,7 +169,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2021-03-07 11:56:23.424137", + "modified": "2021-08-19 15:49:29.598727", "modified_by": "Administrator", "module": "Accounts", "name": "Promotional Scheme Price Discount", From 45617ae22fbcb2c32343acc0324151e24a51e48b Mon Sep 17 00:00:00 2001 From: marination Date: Thu, 19 Aug 2021 17:40:00 +0530 Subject: [PATCH 10/23] fix: Shopping cart Exchange rate validation - Use `get_exchange_rate` to check for price list exchange rate in cart settings - Move cart exchange rate validation for Price List from hooks to doc event - Call cart exchange rate validation on PL update only if PL is in cart and currency is changed --- erpnext/hooks.py | 2 +- .../shopping_cart_settings.py | 61 ++++++++----------- .../test_shopping_cart_settings.py | 4 +- .../stock/doctype/price_list/price_list.py | 14 +++++ 4 files changed, 42 insertions(+), 39 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 8f7c7db208..1aaf4ccd33 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -251,7 +251,7 @@ doc_events = { "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" }, "Website Settings": { diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py index 2a497225fb..efed1968a1 100644 --- a/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py +++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/shopping_cart_settings.py @@ -6,7 +6,7 @@ from __future__ import unicode_literals import frappe from frappe import _, msgprint -from frappe.utils import comma_and +from frappe.utils import flt from frappe.model.document import Document from frappe.utils import get_datetime, get_datetime_str, now_datetime @@ -18,46 +18,35 @@ class ShoppingCartSettings(Document): def validate(self): 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: - msgprint(_("Please specify currency in Company") + ": " + self.company, - raise_exception=ShoppingCartSetupError) + msg = f"Please specify currency in Company {self.company}" + frappe.throw(_(msg), title=_("Missing Currency"), exc=ShoppingCartSetupError) - price_list_currency_map = frappe.db.get_values("Price List", - [self.price_list], "currency") + if not 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 - for price_list, currency in price_list_currency_map.items(): - if not currency: - frappe.throw(_("Currency is required for Price List {0}").format(price_list)) + # Get exchange rate checks Currency Exchange Records too + exchange_rate = get_exchange_rate(from_currency, to_currency, args="for_selling") - expected_to_exist = [currency + "-" + company_currency - for currency in price_list_currency_map.values() - if currency != company_currency] - - # 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) + if not flt(exchange_rate): + msg = f"Missing Currency Exchange Rates for {from_currency}-{to_currency}" + frappe.throw(_(msg), title=_("Missing"), exc=ShoppingCartSetupError) def validate_tax_rule(self): 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): 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") def get_shopping_cart_settings(): diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py b/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py index 008751e208..18a492b2c0 100644 --- a/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py +++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py @@ -21,12 +21,12 @@ class TestShoppingCartSettings(unittest.TestCase): cart_settings = self.get_cart_settings() cart_settings.price_list = "_Test Price List Rest of the World" - self.assertRaises(ShoppingCartSetupError, cart_settings.validate_exchange_rates_exist) + self.assertRaises(ShoppingCartSetupError, cart_settings.validate_price_list_exchange_rate) 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_exchange_rates_exist() + cart_settings.validate_price_list_exchange_rate() def test_tax_rule_validation(self): frappe.db.sql("update `tabTax Rule` set use_for_shopping_cart = 0") diff --git a/erpnext/stock/doctype/price_list/price_list.py b/erpnext/stock/doctype/price_list/price_list.py index 10abde17eb..002d3d898e 100644 --- a/erpnext/stock/doctype/price_list/price_list.py +++ b/erpnext/stock/doctype/price_list/price_list.py @@ -13,6 +13,9 @@ class PriceList(Document): if not cint(self.buying) and not cint(self.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): self.set_default_if_missing() self.update_item_price() @@ -32,6 +35,17 @@ class PriceList(Document): buying=%s, selling=%s, modified=NOW() where price_list=%s""", (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): self.delete_price_list_details_key() From f13315809e2bd56edb62955c7aa7b0b4bc4998bb Mon Sep 17 00:00:00 2001 From: Noah Jacob Date: Thu, 19 Aug 2021 20:28:30 +0530 Subject: [PATCH 11/23] refactor: renamed varint_item_code to variant_item_code (#27025) --- erpnext/manufacturing/doctype/bom/bom.js | 6 +++--- erpnext/manufacturing/doctype/work_order/work_order.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js index 3f50b41be1..e72c8eb408 100644 --- a/erpnext/manufacturing/doctype/bom/bom.js +++ b/erpnext/manufacturing/doctype/bom/bom.js @@ -235,7 +235,7 @@ frappe.ui.form.on("BOM", { reqd: 1, }, { - fieldname: "varint_item_code", + fieldname: "variant_item_code", options: "Item", label: __("Variant Item"), fieldtype: "Link", @@ -287,7 +287,7 @@ frappe.ui.form.on("BOM", { let variant_items = data.items || []; 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])); } }) @@ -299,7 +299,7 @@ frappe.ui.form.on("BOM", { has_template_rm.forEach(d => { dialog.fields_dict.items.df.data.push({ "item_code": d.item_code, - "varint_item_code": "", + "variant_item_code": "", "qty": d.qty, "source_warehouse": d.source_warehouse, "operation": d.operation diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 282b5d0afe..69a4b95c9a 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -838,7 +838,7 @@ def add_variant_item(variant_items, wo_doc, bom_no, table_name="items"): for item in variant_items: args = frappe._dict({ - "item_code": item.get("varint_item_code"), + "item_code": item.get("variant_item_code"), "required_qty": item.get("qty"), "qty": item.get("qty"), # for bom "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) 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 args["amount"] = flt(args.get("required_qty")) * flt(args.get("rate")) From 8046d15ef0edf2d9abc708133a39830b9a45b843 Mon Sep 17 00:00:00 2001 From: marination Date: Thu, 19 Aug 2021 21:10:30 +0530 Subject: [PATCH 12/23] chore: Comment out obsolete test - Modifying this test means considering extreme edge cases, which seems pointless now --- .../test_shopping_cart_settings.py | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py b/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py index 18a492b2c0..9965e1af67 100644 --- a/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py +++ b/erpnext/shopping_cart/doctype/shopping_cart_settings/test_shopping_cart_settings.py @@ -16,17 +16,25 @@ class TestShoppingCartSettings(unittest.TestCase): return frappe.get_doc({"doctype": "Shopping Cart Settings", "company": "_Test Company"}) - def test_exchange_rate_exists(self): - frappe.db.sql("""delete from `tabCurrency Exchange`""") + # NOTE: Exchangrate API has all enabled currencies that ERPNext supports. + # 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() - cart_settings.price_list = "_Test Price List Rest of the World" - self.assertRaises(ShoppingCartSetupError, cart_settings.validate_price_list_exchange_rate) + # def test_exchange_rate_exists(self): + # frappe.db.sql("""delete from `tabCurrency Exchange`""") - 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() + # cart_settings = self.get_cart_settings() + # cart_settings.price_list = "_Test Price List Rest of the World" + # self.assertRaises(ShoppingCartSetupError, cart_settings.validate_price_list_exchange_rate) + + # 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): frappe.db.sql("update `tabTax Rule` set use_for_shopping_cart = 0") From 153fe1cdb4a0029d7327c2835007a96395479173 Mon Sep 17 00:00:00 2001 From: Saqib Date: Fri, 20 Aug 2021 11:09:51 +0530 Subject: [PATCH 13/23] refactor: scan barcode field scanning (#26990) --- .../doctype/pos_invoice/pos_invoice.json | 5 ++-- .../purchase_invoice/purchase_invoice.json | 5 ++-- .../doctype/sales_invoice/sales_invoice.json | 3 ++- .../purchase_order/purchase_order.json | 3 ++- erpnext/public/js/controllers/transaction.js | 24 ------------------- .../doctype/sales_order/sales_order.json | 5 ++-- .../doctype/delivery_note/delivery_note.json | 5 ++-- .../material_request/material_request.json | 7 +++--- .../purchase_receipt/purchase_receipt.json | 5 ++-- .../doctype/stock_entry/stock_entry.json | 3 ++- 10 files changed, 24 insertions(+), 41 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json index 33c3e0432b..fcccb39b70 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.json +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.json @@ -595,7 +595,8 @@ { "fieldname": "scan_barcode", "fieldtype": "Data", - "label": "Scan Barcode" + "label": "Scan Barcode", + "options": "Barcode" }, { "allow_bulk_edit": 1, @@ -1553,7 +1554,7 @@ "icon": "fa fa-file-text", "is_submittable": 1, "links": [], - "modified": "2021-07-29 13:37:20.636171", + "modified": "2021-08-17 20:13:44.255437", "modified_by": "Administrator", "module": "Accounts", "name": "POS Invoice", diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 7025dd98db..7822f747f6 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -668,8 +668,7 @@ "fieldname": "scan_barcode", "fieldtype": "Data", "label": "Scan Barcode", - "show_days": 1, - "show_seconds": 1 + "options": "Barcode" }, { "allow_bulk_edit": 1, @@ -1715,7 +1714,7 @@ "idx": 204, "is_submittable": 1, "links": [], - "modified": "2021-08-07 17:53:14.351439", + "modified": "2021-08-17 20:16:12.737743", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index b65b101051..e317443b91 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -692,6 +692,7 @@ { "fieldname": "scan_barcode", "fieldtype": "Data", + "options": "Barcode", "hide_days": 1, "hide_seconds": 1, "label": "Scan Barcode" @@ -2013,7 +2014,7 @@ "link_fieldname": "consolidated_invoice" } ], - "modified": "2021-08-17 19:00:32.230701", + "modified": "2021-08-17 20:16:12.737743", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index bb0ad60cab..a55a0b7f9f 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -565,6 +565,7 @@ "fieldname": "scan_barcode", "fieldtype": "Data", "label": "Scan Barcode", + "options": "Barcode", "show_days": 1, "show_seconds": 1 }, @@ -1378,7 +1379,7 @@ "idx": 105, "is_submittable": 1, "links": [], - "modified": "2021-05-30 15:17:53.663648", + "modified": "2021-08-17 20:16:12.737743", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order", diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 3c6c347540..9375e358a9 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -342,30 +342,6 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe this.set_dynamic_labels(); this.setup_sms(); 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 = $('
'); - scan_barcode_field.$input_wrapper.find('.control-input').append($input_group); - $input_group.append(scan_barcode_field.$input); - $(` - - `) - .on('click', '.btn', () => { - frappe.barcode.scan_barcode().then(barcode => { - scan_barcode_field.set_value(barcode); - }); - }) - .appendTo($input_group); - } - } } scan_barcode() { diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json index d31db820ab..38ea5c81d4 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.json +++ b/erpnext/selling/doctype/sales_order/sales_order.json @@ -571,7 +571,8 @@ "fieldtype": "Data", "hide_days": 1, "hide_seconds": 1, - "label": "Scan Barcode" + "label": "Scan Barcode", + "options": "Barcode" }, { "allow_bulk_edit": 1, @@ -1510,7 +1511,7 @@ "idx": 105, "is_submittable": 1, "links": [], - "modified": "2021-07-08 21:37:44.177493", + "modified": "2021-08-17 20:15:26.531553", "modified_by": "Administrator", "module": "Selling", "name": "Sales Order", diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json index dbfeb4a10b..958189614f 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.json +++ b/erpnext/stock/doctype/delivery_note/delivery_note.json @@ -515,7 +515,8 @@ { "fieldname": "scan_barcode", "fieldtype": "Data", - "label": "Scan Barcode" + "label": "Scan Barcode", + "options": "Barcode" }, { "allow_bulk_edit": 1, @@ -1305,7 +1306,7 @@ "idx": 146, "is_submittable": 1, "links": [], - "modified": "2021-07-08 21:37:20.802652", + "modified": "2021-08-17 20:15:50.574966", "modified_by": "Administrator", "module": "Stock", "name": "Delivery Note", diff --git a/erpnext/stock/doctype/material_request/material_request.json b/erpnext/stock/doctype/material_request/material_request.json index 4e2d9e6170..cb46a6c368 100644 --- a/erpnext/stock/doctype/material_request/material_request.json +++ b/erpnext/stock/doctype/material_request/material_request.json @@ -133,7 +133,8 @@ { "fieldname": "scan_barcode", "fieldtype": "Data", - "label": "Scan Barcode" + "label": "Scan Barcode", + "options": "Barcode" }, { "allow_bulk_edit": 1, @@ -181,7 +182,7 @@ "no_copy": 1, "oldfieldname": "status", "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_width": "100px", "read_only": 1, @@ -314,7 +315,7 @@ "idx": 70, "is_submittable": 1, "links": [], - "modified": "2021-03-31 23:52:55.392512", + "modified": "2021-08-17 20:16:12.737743", "modified_by": "Administrator", "module": "Stock", "name": "Material Request", diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json index 44fb736304..1a597343c0 100755 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json @@ -1098,7 +1098,8 @@ { "fieldname": "scan_barcode", "fieldtype": "Data", - "label": "Scan Barcode" + "label": "Scan Barcode", + "options": "Barcode" }, { "fieldname": "billing_address", @@ -1148,7 +1149,7 @@ "idx": 261, "is_submittable": 1, "links": [], - "modified": "2021-05-25 00:15:12.239017", + "modified": "2021-08-17 20:16:40.849885", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt", diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.json b/erpnext/stock/doctype/stock_entry/stock_entry.json index 523d332b8f..e6ce3c851f 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.json +++ b/erpnext/stock/doctype/stock_entry/stock_entry.json @@ -355,6 +355,7 @@ }, { "fieldname": "scan_barcode", + "options": "Barcode", "fieldtype": "Data", "label": "Scan Barcode" }, @@ -629,7 +630,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2021-05-26 17:07:58.015737", + "modified": "2021-08-17 20:16:12.737743", "modified_by": "Administrator", "module": "Stock", "name": "Stock Entry", From c335962827e4927f7ada084e9ba4ab2db15e3eb6 Mon Sep 17 00:00:00 2001 From: Saqib Date: Fri, 20 Aug 2021 11:10:46 +0530 Subject: [PATCH 14/23] refactor!: drop e-invoicing integration from erpnext (#26940) --- .../doctype/sales_invoice/regional/india.js | 2 - .../sales_invoice/regional/india_list.js | 135 --- .../doctype/sales_invoice/sales_invoice.py | 2 - .../sales_invoice/test_sales_invoice.py | 48 - .../gst_e_invoice/gst_e_invoice.html | 162 --- .../gst_e_invoice/gst_e_invoice.json | 24 - erpnext/controllers/accounts_controller.py | 9 - erpnext/hooks.py | 1 - erpnext/patches.txt | 9 +- .../add_company_link_to_einvoice_settings.py | 16 - .../v12_0/add_einvoice_status_field.py | 69 -- ...add_einvoice_summary_report_permissions.py | 18 - .../v12_0/add_ewaybill_validity_field.py | 16 - .../patches/v12_0/setup_einvoice_fields.py | 56 - .../show_einvoice_irn_cancelled_field.py | 12 - .../v13_0/einvoicing_deprecation_warning.py | 9 + .../v14_0}/__init__.py | 0 .../v14_0/delete_einvoicing_doctypes.py | 9 + .../doctype/e_invoice_request_log/__init__.py | 0 .../e_invoice_request_log.js | 8 - .../e_invoice_request_log.json | 102 -- .../e_invoice_request_log.py | 10 - .../test_e_invoice_request_log.py | 10 - .../doctype/e_invoice_settings/__init__.py | 0 .../e_invoice_settings/e_invoice_settings.js | 11 - .../e_invoice_settings.json | 73 -- .../e_invoice_settings/e_invoice_settings.py | 13 - .../test_e_invoice_settings.py | 10 - .../doctype/e_invoice_user/__init__.py | 0 .../e_invoice_user/e_invoice_user.json | 57 -- .../doctype/e_invoice_user/e_invoice_user.py | 10 - erpnext/regional/india/e_invoice/__init__.py | 0 .../india/e_invoice/einv_item_template.json | 31 - .../india/e_invoice/einv_template.json | 110 -- .../india/e_invoice/einv_validation.json | 957 ------------------ erpnext/regional/india/e_invoice/einvoice.js | 292 ------ erpnext/regional/india/setup.py | 50 +- .../report/e_invoice_summary/__init__.py | 0 .../e_invoice_summary/e_invoice_summary.js | 55 - .../e_invoice_summary/e_invoice_summary.json | 28 - .../e_invoice_summary/e_invoice_summary.py | 106 -- 41 files changed, 24 insertions(+), 2506 deletions(-) delete mode 100644 erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.html delete mode 100644 erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.json delete mode 100644 erpnext/patches/v12_0/add_company_link_to_einvoice_settings.py delete mode 100644 erpnext/patches/v12_0/add_einvoice_status_field.py delete mode 100644 erpnext/patches/v12_0/add_einvoice_summary_report_permissions.py delete mode 100644 erpnext/patches/v12_0/add_ewaybill_validity_field.py delete mode 100644 erpnext/patches/v12_0/setup_einvoice_fields.py delete mode 100644 erpnext/patches/v12_0/show_einvoice_irn_cancelled_field.py create mode 100644 erpnext/patches/v13_0/einvoicing_deprecation_warning.py rename erpnext/{accounts/print_format/gst_e_invoice => patches/v14_0}/__init__.py (100%) create mode 100644 erpnext/patches/v14_0/delete_einvoicing_doctypes.py delete mode 100644 erpnext/regional/doctype/e_invoice_request_log/__init__.py delete mode 100644 erpnext/regional/doctype/e_invoice_request_log/e_invoice_request_log.js delete mode 100644 erpnext/regional/doctype/e_invoice_request_log/e_invoice_request_log.json delete mode 100644 erpnext/regional/doctype/e_invoice_request_log/e_invoice_request_log.py delete mode 100644 erpnext/regional/doctype/e_invoice_request_log/test_e_invoice_request_log.py delete mode 100644 erpnext/regional/doctype/e_invoice_settings/__init__.py delete mode 100644 erpnext/regional/doctype/e_invoice_settings/e_invoice_settings.js delete mode 100644 erpnext/regional/doctype/e_invoice_settings/e_invoice_settings.json delete mode 100644 erpnext/regional/doctype/e_invoice_settings/e_invoice_settings.py delete mode 100644 erpnext/regional/doctype/e_invoice_settings/test_e_invoice_settings.py delete mode 100644 erpnext/regional/doctype/e_invoice_user/__init__.py delete mode 100644 erpnext/regional/doctype/e_invoice_user/e_invoice_user.json delete mode 100644 erpnext/regional/doctype/e_invoice_user/e_invoice_user.py delete mode 100644 erpnext/regional/india/e_invoice/__init__.py delete mode 100644 erpnext/regional/india/e_invoice/einv_item_template.json delete mode 100644 erpnext/regional/india/e_invoice/einv_template.json delete mode 100644 erpnext/regional/india/e_invoice/einv_validation.json delete mode 100644 erpnext/regional/india/e_invoice/einvoice.js delete mode 100644 erpnext/regional/report/e_invoice_summary/__init__.py delete mode 100644 erpnext/regional/report/e_invoice_summary/e_invoice_summary.js delete mode 100644 erpnext/regional/report/e_invoice_summary/e_invoice_summary.json delete mode 100644 erpnext/regional/report/e_invoice_summary/e_invoice_summary.py diff --git a/erpnext/accounts/doctype/sales_invoice/regional/india.js b/erpnext/accounts/doctype/sales_invoice/regional/india.js index f54bce8aac..6336db16eb 100644 --- a/erpnext/accounts/doctype/sales_invoice/regional/india.js +++ b/erpnext/accounts/doctype/sales_invoice/regional/india.js @@ -1,8 +1,6 @@ {% include "erpnext/regional/india/taxes.js" %} -{% include "erpnext/regional/india/e_invoice/einvoice.js" %} erpnext.setup_auto_gst_taxation('Sales Invoice'); -erpnext.setup_einvoice_actions('Sales Invoice') frappe.ui.form.on("Sales Invoice", { setup: function(frm) { diff --git a/erpnext/accounts/doctype/sales_invoice/regional/india_list.js b/erpnext/accounts/doctype/sales_invoice/regional/india_list.js index f01325d80b..d9d6634c39 100644 --- a/erpnext/accounts/doctype/sales_invoice/regional/india_list.js +++ b/erpnext/accounts/doctype/sales_invoice/regional/india_list.js @@ -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); - - 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: -
    - ${failures.map(d => `
  • ${d.docname}
  • `).join('')} -
- `; - 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: -
    - ${failures.map(d => `
  • ${d.docname}
  • `).join('')} -
- `; - frappe.msgprint({ - message: message, - title: __('Bulk E-Invoice Cancellation Complete'), - indicator: 'orange' - }); - } - }); }; diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 5fa622856b..1cf0df00db 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -285,8 +285,6 @@ class SalesInvoice(SellingController): def before_cancel(self): self.check_if_consolidated_invoice() - - super(SalesInvoice, self).before_cancel() self.update_time_sheet(None) def on_cancel(self): diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 4d1e0c3e06..984a652248 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2027,54 +2027,6 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(data['billLists'][0]['actualFromStateCode'],7) 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): item = create_item("T Shirt") diff --git a/erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.html b/erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.html deleted file mode 100644 index 7643eca763..0000000000 --- a/erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.html +++ /dev/null @@ -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) -%} - -
-
- {% if letter_head and not no_letterhead %} -
{{ letter_head }}
- {% endif %} - -
- {% if print_settings.repeat_header_footer %} - - {% endif %} -
1. Transaction Details
-
-
-
-
-
{{ einvoice.Irn }}
-
-
-
-
{{ einvoice.AckNo }}
-
-
-
-
{{ frappe.utils.format_datetime(einvoice.AckDt, "dd/MM/yyyy hh:mm:ss") }}
-
-
-
-
{{ einvoice.TranDtls.SupTyp }}
-
-
-
-
{{ einvoice.DocDtls.Typ }}
-
-
-
-
{{ einvoice.DocDtls.No }}
-
-
-
- -
-
-
2. Party Details
-
- {%- set seller = einvoice.SellerDtls -%} -
-
Seller
-

{{ seller.Gstin }}

-

{{ seller.LglNm }}

-

{{ seller.Addr1 }}

- {%- if seller.Addr2 -%}

{{ seller.Addr2 }}

{% endif %} -

{{ seller.Loc }}

-

{{ frappe.db.get_value("Address", doc.company_address, "gst_state") }} - {{ seller.Pin }}

- - {%- if einvoice.ShipDtls -%} - {%- set shipping = einvoice.ShipDtls -%} -
Shipping
-

{{ shipping.Gstin }}

-

{{ shipping.LglNm }}

-

{{ shipping.Addr1 }}

- {%- if shipping.Addr2 -%}

{{ shipping.Addr2 }}

{% endif %} -

{{ shipping.Loc }}

-

{{ frappe.db.get_value("Address", doc.shipping_address_name, "gst_state") }} - {{ shipping.Pin }}

- {% endif %} -
- {%- set buyer = einvoice.BuyerDtls -%} -
-
Buyer
-

{{ buyer.Gstin }}

-

{{ buyer.LglNm }}

-

{{ buyer.Addr1 }}

- {%- if buyer.Addr2 -%}

{{ buyer.Addr2 }}

{% endif %} -

{{ buyer.Loc }}

-

{{ frappe.db.get_value("Address", doc.customer_address, "gst_state") }} - {{ buyer.Pin }}

-
-
-
-
3. Item Details
- - - - - - - - - - - - - - - - - - {% for item in einvoice.ItemList %} - - - - - - - - - - - - - - {% endfor %} - -
Sr. No.ItemHSN CodeQtyUOMRateDiscountTaxable AmountTax RateOther ChargesTotal
{{ item.SlNo }}{{ item.PrdDesc }}{{ item.HsnCd }}{{ item.Qty }}{{ item.Unit }}{{ frappe.utils.fmt_money(item.UnitPrice, None, "INR") }}{{ frappe.utils.fmt_money(item.Discount, None, "INR") }}{{ frappe.utils.fmt_money(item.AssAmt, None, "INR") }}{{ item.GstRt + item.CesRt }} %{{ frappe.utils.fmt_money(0, None, "INR") }}{{ frappe.utils.fmt_money(item.TotItemVal, None, "INR") }}
-
-
-
4. Value Details
- - - - - - - - - - - - - - - - - {%- set value_details = einvoice.ValDtls -%} - - - - - - - - - - - - - -
Taxable AmountCGSTSGSTIGSTCESSState CESSDiscountOther ChargesRound OffTotal Value
{{ frappe.utils.fmt_money(value_details.AssVal, None, "INR") }}{{ frappe.utils.fmt_money(value_details.CgstVal, None, "INR") }}{{ frappe.utils.fmt_money(value_details.SgstVal, None, "INR") }}{{ frappe.utils.fmt_money(value_details.IgstVal, None, "INR") }}{{ frappe.utils.fmt_money(value_details.CesVal, None, "INR") }}{{ frappe.utils.fmt_money(0, None, "INR") }}{{ frappe.utils.fmt_money(value_details.Discount, None, "INR") }}{{ frappe.utils.fmt_money(value_details.OthChrg, None, "INR") }}{{ frappe.utils.fmt_money(value_details.RndOffAmt, None, "INR") }}{{ frappe.utils.fmt_money(value_details.TotInvVal, None, "INR") }}
-
-
diff --git a/erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.json b/erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.json deleted file mode 100644 index 1001199a09..0000000000 --- a/erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.json +++ /dev/null @@ -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" -} \ No newline at end of file diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 4c243d0cc4..8addbeb98f 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -135,14 +135,9 @@ class AccountsController(TransactionBase): validate_regional(self) - validate_einvoice_fields(self) - if self.doctype != 'Material Request': apply_pricing_rule_on_transaction(self) - def before_cancel(self): - validate_einvoice_fields(self) - def on_trash(self): # delete sl and gl entries on deletion of transaction 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 def validate_regional(doc): pass - -@erpnext.allow_regional -def validate_einvoice_fields(doc): - pass diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 1aaf4ccd33..73831bf9af 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -436,7 +436,6 @@ regional_overrides = { '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_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.stock.doctype.item.item.set_item_tax_from_hsn_code': 'erpnext.regional.india.utils.set_item_tax_from_hsn_code' }, diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 776b41dcc2..b86c236a7f 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -214,7 +214,6 @@ erpnext.patches.v13_0.delete_old_sales_reports 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_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.loyalty_points_entry_for_pos_invoice #22-07-2020 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.set_payment_channel_in_payment_gateway_account 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.update_reason_for_resignation_in_employee 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.delete_old_bank_reconciliation_doctypes 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.rename_membership_settings_to_non_profit_settings erpnext.patches.v13_0.setup_gratuity_rule_for_india_and_uae erpnext.patches.v13_0.setup_uae_vat_fields 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.v12_0.create_taxable_value_field 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.update_shipment_status 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_fill_debtor_creditor_number 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.update_subscription_status_in_memberships 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.update_export_type_for_gst #2021-08-16 erpnext.patches.v13_0.update_tds_check_field #3 erpnext.patches.v13_0.add_custom_field_for_south_africa #2 erpnext.patches.v13_0.update_recipient_email_digest erpnext.patches.v13_0.shopify_deprecation_warning +erpnext.patches.v13_0.einvoicing_deprecation_warning +erpnext.patches.v14_0.delete_einvoicing_doctypes diff --git a/erpnext/patches/v12_0/add_company_link_to_einvoice_settings.py b/erpnext/patches/v12_0/add_company_link_to_einvoice_settings.py deleted file mode 100644 index c2ed6c288f..0000000000 --- a/erpnext/patches/v12_0/add_company_link_to_einvoice_settings.py +++ /dev/null @@ -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]) diff --git a/erpnext/patches/v12_0/add_einvoice_status_field.py b/erpnext/patches/v12_0/add_einvoice_status_field.py deleted file mode 100644 index 2dfd30714c..0000000000 --- a/erpnext/patches/v12_0/add_einvoice_status_field.py +++ /dev/null @@ -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) diff --git a/erpnext/patches/v12_0/add_einvoice_summary_report_permissions.py b/erpnext/patches/v12_0/add_einvoice_summary_report_permissions.py deleted file mode 100644 index c1c11e2600..0000000000 --- a/erpnext/patches/v12_0/add_einvoice_summary_report_permissions.py +++ /dev/null @@ -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() diff --git a/erpnext/patches/v12_0/add_ewaybill_validity_field.py b/erpnext/patches/v12_0/add_ewaybill_validity_field.py deleted file mode 100644 index f29b71437e..0000000000 --- a/erpnext/patches/v12_0/add_ewaybill_validity_field.py +++ /dev/null @@ -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) diff --git a/erpnext/patches/v12_0/setup_einvoice_fields.py b/erpnext/patches/v12_0/setup_einvoice_fields.py deleted file mode 100644 index 82b14fc9d6..0000000000 --- a/erpnext/patches/v12_0/setup_einvoice_fields.py +++ /dev/null @@ -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) diff --git a/erpnext/patches/v12_0/show_einvoice_irn_cancelled_field.py b/erpnext/patches/v12_0/show_einvoice_irn_cancelled_field.py deleted file mode 100644 index 2319c17b34..0000000000 --- a/erpnext/patches/v12_0/show_einvoice_irn_cancelled_field.py +++ /dev/null @@ -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) diff --git a/erpnext/patches/v13_0/einvoicing_deprecation_warning.py b/erpnext/patches/v13_0/einvoicing_deprecation_warning.py new file mode 100644 index 0000000000..e123a55f5a --- /dev/null +++ b/erpnext/patches/v13_0/einvoicing_deprecation_warning.py @@ -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", + ) diff --git a/erpnext/accounts/print_format/gst_e_invoice/__init__.py b/erpnext/patches/v14_0/__init__.py similarity index 100% rename from erpnext/accounts/print_format/gst_e_invoice/__init__.py rename to erpnext/patches/v14_0/__init__.py diff --git a/erpnext/patches/v14_0/delete_einvoicing_doctypes.py b/erpnext/patches/v14_0/delete_einvoicing_doctypes.py new file mode 100644 index 0000000000..b77d2440eb --- /dev/null +++ b/erpnext/patches/v14_0/delete_einvoicing_doctypes.py @@ -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) \ No newline at end of file diff --git a/erpnext/regional/doctype/e_invoice_request_log/__init__.py b/erpnext/regional/doctype/e_invoice_request_log/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/regional/doctype/e_invoice_request_log/e_invoice_request_log.js b/erpnext/regional/doctype/e_invoice_request_log/e_invoice_request_log.js deleted file mode 100644 index 7b7ba964e5..0000000000 --- a/erpnext/regional/doctype/e_invoice_request_log/e_invoice_request_log.js +++ /dev/null @@ -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) { - - // } -}); diff --git a/erpnext/regional/doctype/e_invoice_request_log/e_invoice_request_log.json b/erpnext/regional/doctype/e_invoice_request_log/e_invoice_request_log.json deleted file mode 100644 index 3034370fea..0000000000 --- a/erpnext/regional/doctype/e_invoice_request_log/e_invoice_request_log.json +++ /dev/null @@ -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" -} \ No newline at end of file diff --git a/erpnext/regional/doctype/e_invoice_request_log/e_invoice_request_log.py b/erpnext/regional/doctype/e_invoice_request_log/e_invoice_request_log.py deleted file mode 100644 index 9150bdd926..0000000000 --- a/erpnext/regional/doctype/e_invoice_request_log/e_invoice_request_log.py +++ /dev/null @@ -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 diff --git a/erpnext/regional/doctype/e_invoice_request_log/test_e_invoice_request_log.py b/erpnext/regional/doctype/e_invoice_request_log/test_e_invoice_request_log.py deleted file mode 100644 index c84e9a249b..0000000000 --- a/erpnext/regional/doctype/e_invoice_request_log/test_e_invoice_request_log.py +++ /dev/null @@ -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 diff --git a/erpnext/regional/doctype/e_invoice_settings/__init__.py b/erpnext/regional/doctype/e_invoice_settings/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/regional/doctype/e_invoice_settings/e_invoice_settings.js b/erpnext/regional/doctype/e_invoice_settings/e_invoice_settings.js deleted file mode 100644 index 54e488610d..0000000000 --- a/erpnext/regional/doctype/e_invoice_settings/e_invoice_settings.js +++ /dev/null @@ -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.", [`documentation`]) - ); - } -}); diff --git a/erpnext/regional/doctype/e_invoice_settings/e_invoice_settings.json b/erpnext/regional/doctype/e_invoice_settings/e_invoice_settings.json deleted file mode 100644 index 68ed3391d0..0000000000 --- a/erpnext/regional/doctype/e_invoice_settings/e_invoice_settings.json +++ /dev/null @@ -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 -} \ No newline at end of file diff --git a/erpnext/regional/doctype/e_invoice_settings/e_invoice_settings.py b/erpnext/regional/doctype/e_invoice_settings/e_invoice_settings.py deleted file mode 100644 index 4f6b3eca7a..0000000000 --- a/erpnext/regional/doctype/e_invoice_settings/e_invoice_settings.py +++ /dev/null @@ -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.')) diff --git a/erpnext/regional/doctype/e_invoice_settings/test_e_invoice_settings.py b/erpnext/regional/doctype/e_invoice_settings/test_e_invoice_settings.py deleted file mode 100644 index a11ce63ee6..0000000000 --- a/erpnext/regional/doctype/e_invoice_settings/test_e_invoice_settings.py +++ /dev/null @@ -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 diff --git a/erpnext/regional/doctype/e_invoice_user/__init__.py b/erpnext/regional/doctype/e_invoice_user/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/regional/doctype/e_invoice_user/e_invoice_user.json b/erpnext/regional/doctype/e_invoice_user/e_invoice_user.json deleted file mode 100644 index a65b1ca7ca..0000000000 --- a/erpnext/regional/doctype/e_invoice_user/e_invoice_user.json +++ /dev/null @@ -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 -} \ No newline at end of file diff --git a/erpnext/regional/doctype/e_invoice_user/e_invoice_user.py b/erpnext/regional/doctype/e_invoice_user/e_invoice_user.py deleted file mode 100644 index 056c54f069..0000000000 --- a/erpnext/regional/doctype/e_invoice_user/e_invoice_user.py +++ /dev/null @@ -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 diff --git a/erpnext/regional/india/e_invoice/__init__.py b/erpnext/regional/india/e_invoice/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/regional/india/e_invoice/einv_item_template.json b/erpnext/regional/india/e_invoice/einv_item_template.json deleted file mode 100644 index 78e56518df..0000000000 --- a/erpnext/regional/india/e_invoice/einv_item_template.json +++ /dev/null @@ -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}" - }} -}} \ No newline at end of file diff --git a/erpnext/regional/india/e_invoice/einv_template.json b/erpnext/regional/india/e_invoice/einv_template.json deleted file mode 100644 index 60f490d616..0000000000 --- a/erpnext/regional/india/e_invoice/einv_template.json +++ /dev/null @@ -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}" - }} -}} \ No newline at end of file diff --git a/erpnext/regional/india/e_invoice/einv_validation.json b/erpnext/regional/india/e_invoice/einv_validation.json deleted file mode 100644 index f4a3542a60..0000000000 --- a/erpnext/regional/india/e_invoice/einv_validation.json +++ /dev/null @@ -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" - ] -} diff --git a/erpnext/regional/india/e_invoice/einvoice.js b/erpnext/regional/india/e_invoice/einvoice.js deleted file mode 100644 index 348f0c6fee..0000000000 --- a/erpnext/regional/india/e_invoice/einvoice.js +++ /dev/null @@ -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 += '

'; - 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( - `
- -
-
` - ); - - 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(); - } - } - }); -}; diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index 2d6b913390..a6ab6aba77 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -61,7 +61,7 @@ def create_hsn_codes(data, code_field): def add_custom_roles_for_reports(): 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)): frappe.get_doc(dict( @@ -100,7 +100,7 @@ def add_custom_roles_for_reports(): )).insert() 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) for role in ('Accounts Manager', 'Accounts User', 'System Manager'): add_permission(doctype, role, 0) @@ -116,11 +116,9 @@ def add_permissions(): def add_print_formats(): 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 E-Invoice") 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 E-Invoice", "disabled", 0) def make_property_setters(patch=False): # 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', 'label': 'E-Way Bill No.', '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, 'insert_after': 'tax_id', '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 = { 'Address': [ 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 Order': 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, 'Journal Entry': journal_entry_fields, 'Sales Order': sales_invoice_gst_fields, diff --git a/erpnext/regional/report/e_invoice_summary/__init__.py b/erpnext/regional/report/e_invoice_summary/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/regional/report/e_invoice_summary/e_invoice_summary.js b/erpnext/regional/report/e_invoice_summary/e_invoice_summary.js deleted file mode 100644 index 4713217d83..0000000000 --- a/erpnext/regional/report/e_invoice_summary/e_invoice_summary.js +++ /dev/null @@ -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 = `${value}`; - else if (value == 'Generated') value = `${value}`; - else if (value == 'Cancelled') value = `${value}`; - else if (value == 'Failed') value = `${value}`; - } - - return value; - } -}; diff --git a/erpnext/regional/report/e_invoice_summary/e_invoice_summary.json b/erpnext/regional/report/e_invoice_summary/e_invoice_summary.json deleted file mode 100644 index d0000ad50d..0000000000 --- a/erpnext/regional/report/e_invoice_summary/e_invoice_summary.json +++ /dev/null @@ -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" - } - ] -} \ No newline at end of file diff --git a/erpnext/regional/report/e_invoice_summary/e_invoice_summary.py b/erpnext/regional/report/e_invoice_summary/e_invoice_summary.py deleted file mode 100644 index 66ffceae53..0000000000 --- a/erpnext/regional/report/e_invoice_summary/e_invoice_summary.py +++ /dev/null @@ -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 - } - ] From 2b2572b9b997eaeaae86e23f8b74803db85daf5a Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Fri, 20 Aug 2021 14:40:12 +0530 Subject: [PATCH 15/23] fix: Cascade deletion for Company (#26923) * fix: Cascade deletion for Company --- erpnext/hooks.py | 3 +++ erpnext/regional/india/utils.py | 17 +++++++++++++++++ erpnext/setup/doctype/company/company.py | 4 ++++ 3 files changed, 24 insertions(+) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 73831bf9af..74977cd8bc 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -308,6 +308,9 @@ doc_events = { }, ('Quotation', 'Sales Order', 'Sales Invoice'): { 'validate': ["erpnext.erpnext_integrations.taxjar_integration.set_sales_tax"] + }, + "Company": { + "on_trash": "erpnext.regional.india.utils.delete_gst_settings_for_company" } } diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index 949733e0ad..4e4dcf8585 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -871,3 +871,20 @@ def set_item_tax_from_hsn_code(item): 'tax_category': tax.tax_category, '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() + diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 54c67538ae..45d5ce0c1c 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -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 `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() def enqueue_replace_abbr(company, old, new): kwargs = dict(queue="long", company=company, old=old, new=new) From 62c590261c5c7cc96d1cad29bc44615229a0f83a Mon Sep 17 00:00:00 2001 From: Alan <2.alan.tom@gmail.com> Date: Fri, 20 Aug 2021 18:21:09 +0530 Subject: [PATCH 16/23] refactor: rectify typo (#27057) [skip ci] --- erpnext/manufacturing/doctype/work_order/work_order.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 69a4b95c9a..5fe9fec2af 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -602,7 +602,7 @@ class WorkOrder(Document): if self.docstatus==1: # 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 self.update_reserved_qty_for_production() @@ -671,7 +671,7 @@ class WorkOrder(Document): 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 the work order''' From ec258551bf48c93ce7190397ec34adee6eee66e6 Mon Sep 17 00:00:00 2001 From: Saqib Date: Fri, 20 Aug 2021 19:09:31 +0530 Subject: [PATCH 17/23] fix: flaky test for SLA (#27051) --- .../test_service_level_agreement.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py index a81516ec11..d9c671e9a2 100644 --- a/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py @@ -267,11 +267,15 @@ class TestServiceLevelAgreement(unittest.TestCase): ) creation = datetime.datetime(2019, 3, 4, 12, 0) 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.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): for d in frappe.get_all("Service Level Agreement"): From 57e326e7d0ad1a1053ac2d987aacd540353ef47d Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Sat, 21 Aug 2021 17:59:11 +0530 Subject: [PATCH 18/23] fix: Consolidated balance sheet showing incorrect values (#26975) --- .../consolidated_financial_statement.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py index 56a67bb098..fc4212733a 100644 --- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py +++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py @@ -210,10 +210,10 @@ def get_data(companies, root_type, balance_must_be, fiscal_year, filters=None, i company_currency = get_company_currency(filters) 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 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 gl_entries_by_account = {} From 496bff5136c7a72c3346361af7b7e41e787cff1b Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Sun, 22 Aug 2021 18:10:51 +0530 Subject: [PATCH 19/23] feat: Column for total amount due in Accounts Receivable/Payable Summary (#27069) --- .../report/accounts_receivable/accounts_receivable.py | 2 ++ .../accounts_receivable_summary.py | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index b54646fd27..cedfc0f58b 100755 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -535,6 +535,8 @@ class ReceivablePayableReport(object): if getdate(entry_date) > getdate(self.filters.report_date): 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): # [0-30, 30-60, 60-90, 90-120, 120-above] row.range1 = row.range2 = row.range3 = row.range4 = row.range5 = 0.0 diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py index e94b30921f..4bfb022c4e 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py @@ -82,6 +82,7 @@ class AccountsReceivableSummary(ReceivablePayableReport): "range3": 0.0, "range4": 0.0, "range5": 0.0, + "total_due": 0.0, "sales_person": [] })) @@ -135,3 +136,6 @@ class AccountsReceivableSummary(ReceivablePayableReport): "{range3}-{range4}".format(range3=cint(self.filters["range3"])+ 1, range4=self.filters["range4"]), "{range4}-{above}".format(range4=cint(self.filters["range4"])+ 1, above=_("Above"))]): 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') From 7d627df4dbe15b3db16da031945ab98ccaae71ea Mon Sep 17 00:00:00 2001 From: Subin Tom <36098155+nemesis189@users.noreply.github.com> Date: Mon, 23 Aug 2021 11:05:07 +0530 Subject: [PATCH 20/23] fix: pos return payment mode issue (#26872) --- erpnext/controllers/taxes_and_totals.py | 9 ++++----- erpnext/public/js/controllers/taxes_and_totals.js | 2 -- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 05edb2530c..7c6d3552f1 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -595,7 +595,8 @@ class calculate_taxes_and_totals(object): self.doc.precision("outstanding_amount")) 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): @@ -675,7 +676,7 @@ class calculate_taxes_and_totals(object): def set_item_wise_tax_breakup(self): 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', {'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, 'amount': total_amount_to_pay, 'default': 1 - }) - - self.calculate_paid_amount() + }) def get_itemised_tax_breakup_html(doc): if not doc.taxes: diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index e8f31225ba..702064fe55 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -754,8 +754,6 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments { } }); this.frm.refresh_fields(); - - this.calculate_paid_amount(); } set_default_payment(total_amount_to_pay, update_paid_amount) { From 8b2fe9e793e226339bbcec554d8c57a09f87b5c5 Mon Sep 17 00:00:00 2001 From: Subin Tom <36098155+nemesis189@users.noreply.github.com> Date: Mon, 23 Aug 2021 11:17:31 +0530 Subject: [PATCH 21/23] fix: eway bill version changed to 1.0.0421 (#27044) --- erpnext/regional/india/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index 4e4dcf8585..ce5aa10902 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -475,7 +475,7 @@ def get_ewb_data(dt, dn): ewaybills.append(data) data = { - 'version': '1.0.1118', + 'version': '1.0.0421', 'billLists': ewaybills } From 47b63a627d7d8b6d32cc5ff5713af9eb973001d3 Mon Sep 17 00:00:00 2001 From: Subin Tom <36098155+nemesis189@users.noreply.github.com> Date: Mon, 23 Aug 2021 15:38:26 +0530 Subject: [PATCH 22/23] fix: Eway bill test update to check ver 1.0.0421 (#27083) --- erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 984a652248..01a6b02732 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2014,7 +2014,7 @@ class TestSalesInvoice(unittest.TestCase): 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]['fromTrdName'], '_Test Company') self.assertEqual(data['billLists'][0]['toTrdName'], '_Test Customer') From 49e0a4f28714b468ba5edad296b30f22991210f3 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Tue, 24 Aug 2021 08:33:57 +0530 Subject: [PATCH 23/23] Revert "fix: Salary component account filter (#26604)" This reverts commit ae9d1d9617015b6e2714a9fcd027a2957053d99a. --- .../doctype/salary_component/salary_component.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/erpnext/payroll/doctype/salary_component/salary_component.js b/erpnext/payroll/doctype/salary_component/salary_component.js index e9e6f81862..dbf75140ac 100644 --- a/erpnext/payroll/doctype/salary_component/salary_component.js +++ b/erpnext/payroll/doctype/salary_component/salary_component.js @@ -4,18 +4,11 @@ frappe.ui.form.on('Salary Component', { setup: function(frm) { frm.set_query("account", "accounts", function(doc, cdt, cdn) { - let d = frappe.get_doc(cdt, cdn); - - let root_type = "Liability"; - if (frm.doc.type == "Deduction") { - root_type = "Expense"; - } - + var d = locals[cdt][cdn]; return { filters: { "is_group": 0, - "company": d.company, - "root_type": root_type + "company": d.company } }; });