From 2cbcfb2883e72008854127733f9d514dfd006bbc Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Thu, 28 Aug 2025 10:22:54 +0000 Subject: [PATCH 01/52] fix: for version-15 --- rohit_common/core/file.py | 6 ++++-- rohit_common/patches/backend_table_analysis.py | 12 ++++++++---- rohit_common/patches/manual_delete_orphaned_files.py | 8 +++++--- .../doctype/gst_return_status/gst_return_status.py | 1 + rohit_common/rohit_common/india_gst_api/einv.py | 6 ++++-- .../rohit_common/india_gst_api/eway_bill_api.py | 6 ++++-- rohit_common/rohit_common/validations/address.py | 6 ++++-- .../rohit_common/validations/sales_invoice.py | 6 +++--- 8 files changed, 33 insertions(+), 18 deletions(-) diff --git a/rohit_common/core/file.py b/rohit_common/core/file.py index 7cdfc11..48a436e 100644 --- a/rohit_common/core/file.py +++ b/rohit_common/core/file.py @@ -503,8 +503,10 @@ def change_file_path(fd): frappe.db.set_value("File", fd.name, "file_available_on_server", 1) frappe.db.set_value("File", fd.name, "is_private", 1) else: - print("File Name is Not There hence Exiting") - exit() + frappe.throw("File Name is Not There hence Exiting") + return + # print("File Name is Not There hence Exiting") + # exit() def delete_only_file_doc(fd, comment=None, ref_doc_exists=1): diff --git a/rohit_common/patches/backend_table_analysis.py b/rohit_common/patches/backend_table_analysis.py index 3c997fd..2db1e6d 100644 --- a/rohit_common/patches/backend_table_analysis.py +++ b/rohit_common/patches/backend_table_analysis.py @@ -46,8 +46,10 @@ def input_table_name(): tb = input("Enter the Name of the Table for Dropping Fields Ex: Sales Invoice, enter the value exactly as in ERP: ") tbl_exists = frappe.db.sql("""SHOW TABLES LIKE 'tab%s'""" % tb) if not tbl_exists: - print(f"There is No Table Named tab{tb}. Hence Exiting") - exit() + frappe.throw(f"There is No Table Named tab{tb}. Hence Exiting") + # print(f"There is No Table Named tab{tb}. Hence Exiting") + # exit() + return else: return tb @@ -202,8 +204,10 @@ def change_varchar_len_as_per_input(tbl_name, col_name, exist_len, max_len, sug_ f"Time Taken for Field Conversion = {int(time.time() - fd_time)} secs and Total Elapsed " f"Time = {int(time.time() - st_time)} secs\n") else: - print(f"{usr_inp} is an Illegal Value please Restart again") - exit() + frappe.throw(f"{usr_inp} is an Illegal Value please Restart again") + return + # print(f"{usr_inp} is an Illegal Value please Restart again") + # exit() def alter_varchar_table(tb_name, col_name, var_len): diff --git a/rohit_common/patches/manual_delete_orphaned_files.py b/rohit_common/patches/manual_delete_orphaned_files.py index 87d6ba0..a7106c2 100644 --- a/rohit_common/patches/manual_delete_orphaned_files.py +++ b/rohit_common/patches/manual_delete_orphaned_files.py @@ -21,9 +21,11 @@ def execute(): if delete_file == "y" or delete_file == "n": pass else: - print("Wrong Input Enter either y or n. y = If you want to delete files and n = If you only want a list of " - "orphaned files at the end of this patch") - exit() + frappe.throw("Wrong Input Enter either y or n. y = If you want to delete files and n = If you only want a list of orphaned files at the end of this patch") + # print("Wrong Input Enter either y or n. y = If you want to delete files and n = If you only want a list of " + # "orphaned files at the end of this patch") + # exit() + return st_time = time.time() public_files_path = get_files_path() private_files_path = get_files_path(is_private=1) diff --git a/rohit_common/rohit_common/doctype/gst_return_status/gst_return_status.py b/rohit_common/rohit_common/doctype/gst_return_status/gst_return_status.py index 4bb41d0..12beee4 100644 --- a/rohit_common/rohit_common/doctype/gst_return_status/gst_return_status.py +++ b/rohit_common/rohit_common/doctype/gst_return_status/gst_return_status.py @@ -13,6 +13,7 @@ class GSTReturnStatus(Document): + @frappe.whitelist() def get_return_status(self): today = datetime.today() self.returns = [] diff --git a/rohit_common/rohit_common/india_gst_api/einv.py b/rohit_common/rohit_common/india_gst_api/einv.py index cd4c8d4..23a7cf6 100644 --- a/rohit_common/rohit_common/india_gst_api/einv.py +++ b/rohit_common/rohit_common/india_gst_api/einv.py @@ -519,8 +519,10 @@ def get_auth_token_if_needed(): frappe.db.commit() rset.reload() else: - print(f"Error while fetching the Auth Token {res_json}") - exit() + frappe.throw(f"Error while fetching the Auth Token {res_json}") + # print(f"Error while fetching the Auth Token {res_json}") + # exit() + return else: access_token = rset.access_token return access_token diff --git a/rohit_common/rohit_common/india_gst_api/eway_bill_api.py b/rohit_common/rohit_common/india_gst_api/eway_bill_api.py index b9acf48..a822251 100644 --- a/rohit_common/rohit_common/india_gst_api/eway_bill_api.py +++ b/rohit_common/rohit_common/india_gst_api/eway_bill_api.py @@ -593,8 +593,10 @@ def get_ewb_access_token(): frappe.db.commit() rset.reload() else: - print(f"Error while fetching the Auth Token {res_json}") - exit() + frappe.throw(f"Error while fetching the Auth Token {res_json}") + # print(f"Error while fetching the Auth Token {res_json}") + # exit() + return else: access_token = rset.access_token return access_token diff --git a/rohit_common/rohit_common/validations/address.py b/rohit_common/rohit_common/validations/address.py index d187f33..85eb072 100644 --- a/rohit_common/rohit_common/validations/address.py +++ b/rohit_common/rohit_common/validations/address.py @@ -339,8 +339,10 @@ def validate_gstin_from_portal(doc): doc.gst_status = gstin_json.get("sts") doc.gst_validation_date = date.today() else: - frappe.msgprint("Status Code Return is Zero Hence Exiting") - exit() + frappe.throw("Status Code Return is Zero Hence Exiting") + # frappe.msgprint("Status Code Return is Zero Hence Exiting") + # exit() + return if doc.gst_status in ('Inactive', 'Cancelled'): doc.disabled = 1 elif doc.gst_status == 'Suspended': diff --git a/rohit_common/rohit_common/validations/sales_invoice.py b/rohit_common/rohit_common/validations/sales_invoice.py index a0ed61b..ff4bc0f 100644 --- a/rohit_common/rohit_common/validations/sales_invoice.py +++ b/rohit_common/rohit_common/validations/sales_invoice.py @@ -373,9 +373,9 @@ def check_validated_gstin(add_name, doc=None): days_since_validation = (date.today() - getdate(add_doc.gst_validation_date)).days else: days_since_validation = 999 - if add_doc.validated_gstin != add_doc.gstin or days_since_validation > stale_days: - frappe.throw(f"GSTIN# {add_doc.gstin} for {frappe.get_desk_link(add_doc.doctype, add_doc.name)} is " - f"NOT Validated from GST Website. Please update the Address from GST Website") + # if add_doc.validated_gstin != add_doc.gstin or days_since_validation > stale_days: + # frappe.throw(f"GSTIN# {add_doc.gstin} for {frappe.get_desk_link(add_doc.doctype, add_doc.name)} is " + # f"NOT Validated from GST Website. Please update the Address from GST Website") if add_doc.gst_status == "Suspended": if doc: if doc.doctype == "Sales Invoice": From b389f1cad7213be2e3d0aad054bb9590768697d5 Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Fri, 29 Aug 2025 09:05:44 +0000 Subject: [PATCH 02/52] fix: file permission --- rohit_common/core/file.py | 34 ++++++++++++++---------- rohit_common/utils/rohit_common_utils.py | 13 ++++----- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/rohit_common/core/file.py b/rohit_common/core/file.py index 48a436e..45ab929 100644 --- a/rohit_common/core/file.py +++ b/rohit_common/core/file.py @@ -22,27 +22,33 @@ def custom_file_permissions(doc, ptype=None, user=None): has_access = False user = user or frappe.session.user is_sys = check_system_manager(user) + + # System Manager & Administrator always get full access + if user == "Administrator" or is_sys: + return True + + # Check if shared shd_name = get_share_name(doctype=doc.doctype, name=doc.name, user=user, everyone=0) if shd_name: shd = frappe.get_doc("DocShare", shd_name) if shd.write or shd.share or shd.submit: - has_access = "write" - else: - has_access = "read" - elif ptype == "create": - has_access = frappe.has_permission("File", "create", user=user) - elif not doc.is_private or doc.owner in [user, "Guest"] \ - or user == "Administrator" or is_sys == 1: - has_access = True - elif doc.attached_to_doctype and doc.attached_to_name: - attached_to_doctype = doc.attached_to_doctype - attached_to_name = doc.attached_to_name - try: - ref_doc = frappe.get_doc(attached_to_doctype, attached_to_name) + return "write" + return "read" + # Creating a new file + if ptype == "create": + return frappe.has_permission("File", "create", user=user) + + # Public file or owner + if not doc.is_private or doc.owner in [user, "Guest"]: + return True + + # If attached → check permission on parent doc + if doc.attached_to_doctype and doc.attached_to_name: + try: + ref_doc = frappe.get_doc(doc.attached_to_doctype, doc.attached_to_name) if ptype in ["write", "create", "delete"]: has_access = ref_doc.has_permission("write") - if ptype == "delete" and not has_access: frappe.throw( _( diff --git a/rohit_common/utils/rohit_common_utils.py b/rohit_common/utils/rohit_common_utils.py index 34217d6..1903e83 100644 --- a/rohit_common/utils/rohit_common_utils.py +++ b/rohit_common/utils/rohit_common_utils.py @@ -146,12 +146,13 @@ def check_system_manager(user): """ Returns boolean for a system manager user """ - sys_list = frappe.db.sql(f"""SELECT name FROM `tabHas Role` WHERE parenttype = 'User' - AND parent = '{user}' AND role = 'System Manager'""", as_list=1) - if sys_list: - return 1 - else: - return 0 + return "System Manager" in frappe.get_roles(user) + # sys_list = frappe.db.sql(f"""SELECT name FROM `tabHas Role` WHERE parenttype = 'User' + # AND parent = '{user}' AND role = 'System Manager'""", as_list=1) + # if sys_list: + # return 1 + # else: + # return 0 def rebuild_tree(doctype, parent_field, group_field): From ffdb27a6a7f68488efaf27adc6766280e84b0696 Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Fri, 29 Aug 2025 12:41:25 +0000 Subject: [PATCH 03/52] fix: message typo --- rohit_common/rohit_common/india_gst_api/gst_public_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rohit_common/rohit_common/india_gst_api/gst_public_api.py b/rohit_common/rohit_common/india_gst_api/gst_public_api.py index 9acb849..07480e1 100644 --- a/rohit_common/rohit_common/india_gst_api/gst_public_api.py +++ b/rohit_common/rohit_common/india_gst_api/gst_public_api.py @@ -54,5 +54,5 @@ def get_arn_status(ret_status_json, type_of_return, ret_period): if found != 1: frappe.msgprint(f"No Filing Data found for {type_of_return} for Period: {ret_period}") else: - fraeppe.msgprint("No eFiling Data Received") + frappe.msgprint("No eFiling Data Received") return arn, status, dof, mof From a0c2a17ee3ff920ef5592502b7b3a149f774b6bd Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Mon, 1 Sep 2025 06:52:53 +0000 Subject: [PATCH 04/52] fix: sales invoice --- rohit_common/rohit_common/validations/sales_invoice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rohit_common/rohit_common/validations/sales_invoice.py b/rohit_common/rohit_common/validations/sales_invoice.py index ff4bc0f..a434da2 100644 --- a/rohit_common/rohit_common/validations/sales_invoice.py +++ b/rohit_common/rohit_common/validations/sales_invoice.py @@ -140,7 +140,7 @@ def check_local_natl_tax_rules(doc, template_doc): Change the Selected Tax") elif ship_country == 'India' and bill_state != template_doc.state and \ template_doc.is_sample != 1: - doc.place_of_supply = bill_state + # doc.place_of_supply = bill_state if template_doc.is_local_sales == 1: frappe.throw(f"Selected Tax {doc.taxes_and_charges} is LOCAL Tax but Billing Address \ is in Different State {bill_state}, hence either change Billing Address or Change \ From 4bc08b87a0379fe19b30917dc2acf55dfc307270 Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Wed, 3 Sep 2025 13:35:37 +0530 Subject: [PATCH 05/52] feat: rigpl general ledger (#1) * feat: rigpl general ledger * fix: period closing voucher checking --- .../report/rigpl_general_ledger/__init__.py | 0 .../rigpl_general_ledger.js | 230 +++++ .../rigpl_general_ledger.json | 35 + .../rigpl_general_ledger.py | 819 ++++++++++++++++++ 4 files changed, 1084 insertions(+) create mode 100644 rohit_common/rohit_common/report/rigpl_general_ledger/__init__.py create mode 100644 rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.js create mode 100644 rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.json create mode 100644 rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py diff --git a/rohit_common/rohit_common/report/rigpl_general_ledger/__init__.py b/rohit_common/rohit_common/report/rigpl_general_ledger/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.js b/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.js new file mode 100644 index 0000000..2b5c1d8 --- /dev/null +++ b/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.js @@ -0,0 +1,230 @@ +// Copyright (c) 2025, Rohit Industries Ltd. and contributors +// For license information, please see license.txt + +frappe.query_reports["RIGPL General Ledger"] = { + filters: [ + { + fieldname: "company", + label: __("Company"), + fieldtype: "Link", + options: "Company", + default: frappe.defaults.get_user_default("Company"), + reqd: 1, + }, + { + fieldname: "finance_book", + label: __("Finance Book"), + fieldtype: "Link", + options: "Finance Book", + }, + { + fieldname: "from_date", + label: __("From Date"), + fieldtype: "Date", + default: frappe.datetime.add_months(frappe.datetime.get_today(), -1), + reqd: 1, + width: "60px", + }, + { + fieldname: "to_date", + label: __("To Date"), + fieldtype: "Date", + default: frappe.datetime.get_today(), + reqd: 1, + width: "60px", + }, + { + fieldname: "account", + label: __("Account"), + fieldtype: "MultiSelectList", + options: "Account", + get_data: function (txt) { + return frappe.db.get_link_options("Account", txt, { + company: frappe.query_report.get_filter_value("company"), + }); + }, + }, + { + fieldname: "voucher_no", + label: __("Voucher No"), + fieldtype: "Data", + on_change: function () { + frappe.query_report.set_filter_value("categorize_by", "Categorize by Voucher (Consolidated)"); + }, + }, + { + fieldname: "against_voucher_no", + label: __("Against Voucher No"), + fieldtype: "Data", + }, + { + fieldtype: "Break", + }, + { + fieldname: "party_type", + label: __("Party Type"), + fieldtype: "Autocomplete", + options: Object.keys(frappe.boot.party_account_types), + on_change: function () { + frappe.query_report.set_filter_value("party", []); + }, + }, + { + fieldname: "party", + label: __("Party"), + fieldtype: "MultiSelectList", + options: "party_type", + get_data: function (txt) { + if (!frappe.query_report.filters) return; + + let party_type = frappe.query_report.get_filter_value("party_type"); + if (!party_type) return; + + return frappe.db.get_link_options(party_type, txt); + }, + on_change: function () { + var party_type = frappe.query_report.get_filter_value("party_type"); + var parties = frappe.query_report.get_filter_value("party"); + + if (!party_type || parties.length === 0 || parties.length > 1) { + frappe.query_report.set_filter_value("party_name", ""); + frappe.query_report.set_filter_value("tax_id", ""); + return; + } else { + var party = parties[0]; + var fieldname = erpnext.utils.get_party_name(party_type) || "name"; + frappe.db.get_value(party_type, party, fieldname, function (value) { + frappe.query_report.set_filter_value("party_name", value[fieldname]); + }); + + if (party_type === "Customer" || party_type === "Supplier") { + frappe.db.get_value(party_type, party, "tax_id", function (value) { + frappe.query_report.set_filter_value("tax_id", value["tax_id"]); + }); + } + } + }, + }, + { + fieldname: "party_name", + label: __("Party Name"), + fieldtype: "Data", + hidden: 1, + }, + { + fieldname: "categorize_by", + label: __("Categorize by"), + fieldtype: "Select", + options: [ + "", + { + label: __("Categorize by Voucher"), + value: "Categorize by Voucher", + }, + { + label: __("Categorize by Voucher (Consolidated)"), + value: "Categorize by Voucher (Consolidated)", + }, + { + label: __("Categorize by Account"), + value: "Categorize by Account", + }, + { + label: __("Categorize by Party"), + value: "Categorize by Party", + }, + ], + default: "Categorize by Voucher (Consolidated)", + }, + { + fieldname: "tax_id", + label: __("Tax Id"), + fieldtype: "Data", + hidden: 1, + }, + { + fieldname: "presentation_currency", + label: __("Currency"), + fieldtype: "Select", + options: erpnext.get_presentation_currency_list(), + }, + { + fieldname: "cost_center", + label: __("Cost Center"), + fieldtype: "MultiSelectList", + options: "Cost Center", + get_data: function (txt) { + return frappe.db.get_link_options("Cost Center", txt, { + company: frappe.query_report.get_filter_value("company"), + }); + }, + }, + { + fieldname: "project", + label: __("Project"), + fieldtype: "MultiSelectList", + options: "Project", + get_data: function (txt) { + return frappe.db.get_link_options("Project", txt, { + company: frappe.query_report.get_filter_value("company"), + }); + }, + }, + { + fieldname: "include_dimensions", + label: __("Consider Accounting Dimensions"), + fieldtype: "Check", + default: 1, + }, + { + fieldname: "show_opening_entries", + label: __("Show Opening Entries"), + fieldtype: "Check", + }, + { + fieldname: "include_default_book_entries", + label: __("Include Default FB Entries"), + fieldtype: "Check", + default: 1, + }, + { + fieldname: "show_cancelled_entries", + label: __("Show Cancelled Entries"), + fieldtype: "Check", + }, + { + fieldname: "show_net_values_in_party_account", + label: __("Show Net Values in Party Account"), + fieldtype: "Check", + }, + { + fieldname: "show_amount_in_company_currency", + label: __("Show Credit / Debit in Company Currency"), + fieldtype: "Check", + }, + { + fieldname: "add_values_in_transaction_currency", + label: __("Add Columns in Transaction Currency"), + fieldtype: "Check", + }, + { + fieldname: "show_remarks", + label: __("Show Remarks"), + fieldtype: "Check", + }, + { + fieldname: "ignore_err", + label: __("Ignore Exchange Rate Revaluation and Gain / Loss Journals"), + fieldtype: "Check", + }, + { + fieldname: "ignore_cr_dr_notes", + label: __("Ignore System Generated Credit / Debit Notes"), + fieldtype: "Check", + }, + ], + collapsible_filters: true, + seperate_check_filters: true, +}; + +erpnext.utils.add_dimensions("RIGPL General Ledger", 15); \ No newline at end of file diff --git a/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.json b/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.json new file mode 100644 index 0000000..6e8dca9 --- /dev/null +++ b/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.json @@ -0,0 +1,35 @@ +{ + "add_total_row": 0, + "add_translate_data": 0, + "columns": [], + "creation": "2025-09-03 12:33:05.831760", + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "filters": [], + "idx": 0, + "is_standard": "Yes", + "letter_head": "RIGB", + "letterhead": null, + "modified": "2025-09-03 12:33:05.831760", + "modified_by": "Administrator", + "module": "rohit_common", + "name": "RIGPL General Ledger", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "GL Entry", + "report_name": "RIGPL General Ledger", + "report_type": "Script Report", + "roles": [ + { + "role": "Accounts User" + }, + { + "role": "Accounts Manager" + }, + { + "role": "Auditor" + } + ], + "timeout": 0 +} diff --git a/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py b/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py new file mode 100644 index 0000000..05e5102 --- /dev/null +++ b/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py @@ -0,0 +1,819 @@ +# Copyright (c) 2025, Rohit Industries Ltd. and contributors +# For license information, please see license.txt + +import frappe +from frappe import _, _dict +from frappe.query_builder import Criterion +from frappe.utils import cstr, getdate + +from erpnext import get_company_currency, get_default_company +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_accounting_dimensions, + get_dimension_with_children, +) +from erpnext.accounts.report.financial_statements import get_cost_centers_with_children +from erpnext.accounts.report.utils import convert_to_presentation_currency, get_currency +from erpnext.accounts.utils import get_account_currency, get_fiscal_year + +DEBIT_CREDIT_DICT = { + "debit": 0.0, + "credit": 0.0, + "debit_in_account_currency": 0.0, + "credit_in_account_currency": 0.0, + "debit_in_transaction_currency": None, + "credit_in_transaction_currency": None, +} + + +def execute(filters=None): + if not filters: + return [], [] + + account_details = {} + + if filters and filters.get("print_in_account_currency") and not filters.get("account"): + frappe.throw(_("Select an account to print in account currency")) + + for acc in frappe.db.sql("""select name, is_group from tabAccount""", as_dict=1): + account_details.setdefault(acc.name, acc) + + if filters.get("party"): + filters.party = frappe.parse_json(filters.get("party")) + + validate_filters(filters, account_details) + + validate_party(filters) + + filters = set_account_currency(filters) + + columns = get_columns(filters) + + res = get_result(filters, account_details) + + return columns, res + + +def validate_filters(filters, account_details): + if not filters.get("company"): + frappe.throw(_("{0} is mandatory").format(_("Company"))) + + if not filters.get("from_date") and not filters.get("to_date"): + frappe.throw( + _("{0} and {1} are mandatory").format(frappe.bold(_("From Date")), frappe.bold(_("To Date"))) + ) + + if filters.get("account"): + filters.account = frappe.parse_json(filters.get("account")) + for account in filters.account: + if not account_details.get(account): + frappe.throw(_("Account {0} does not exists").format(account)) + + if not filters.get("categorize_by") and filters.get("group_by"): + filters["categorize_by"] = filters["group_by"] + filters["categorize_by"] = filters["categorize_by"].replace("Group by", "Categorize by") + + if filters.get("account") and filters.get("categorize_by") == "Categorize by Account": + filters.account = frappe.parse_json(filters.get("account")) + for account in filters.account: + if account_details[account].is_group == 0: + frappe.throw(_("Can not filter based on Child Account, if grouped by Account")) + + if filters.get("voucher_no") and filters.get("categorize_by") in ["Categorize by Voucher"]: + frappe.throw(_("Can not filter based on Voucher No, if grouped by Voucher")) + + if filters.from_date > filters.to_date: + frappe.throw(_("From Date must be before To Date")) + + if filters.get("project"): + filters.project = frappe.parse_json(filters.get("project")) + + if filters.get("cost_center"): + filters.cost_center = frappe.parse_json(filters.get("cost_center")) + + +def validate_party(filters): + party_type, party = filters.get("party_type"), filters.get("party") + + if party and party_type: + for d in party: + if not frappe.db.exists(party_type, d): + frappe.throw(_("Invalid {0}: {1}").format(party_type, d)) + + +def set_account_currency(filters): + if filters.get("account") or (filters.get("party") and len(filters.party) == 1): + filters["company_currency"] = frappe.get_cached_value("Company", filters.company, "default_currency") + account_currency = None + + if filters.get("account"): + if len(filters.get("account")) == 1: + account_currency = get_account_currency(filters.account[0]) + else: + currency = get_account_currency(filters.account[0]) + is_same_account_currency = True + for account in filters.get("account"): + if get_account_currency(account) != currency: + is_same_account_currency = False + break + + if is_same_account_currency: + account_currency = currency + + elif filters.get("party") and filters.get("party_type"): + gle_currency = frappe.db.get_value( + "GL Entry", + {"party_type": filters.party_type, "party": filters.party[0], "company": filters.company}, + "account_currency", + ) + + if gle_currency: + account_currency = gle_currency + else: + account_currency = ( + None + if filters.party_type in ["Employee", "Shareholder", "Member"] + else frappe.get_cached_value(filters.party_type, filters.party[0], "default_currency") + ) + + filters["account_currency"] = account_currency or filters.company_currency + if filters.account_currency != filters.company_currency and not filters.presentation_currency: + filters.presentation_currency = filters.account_currency + + return filters + + +def get_result(filters, account_details): + accounting_dimensions = [] + if filters.get("include_dimensions"): + accounting_dimensions = get_accounting_dimensions() + + gl_entries = get_gl_entries(filters, accounting_dimensions) + + data = get_data_with_opening_closing(filters, account_details, accounting_dimensions, gl_entries) + + result = get_result_as_list(data, filters) + + return result + + +def get_gl_entries(filters, accounting_dimensions): + currency_map = get_currency(filters) + select_fields = """, debit, credit, debit_in_account_currency, + credit_in_account_currency """ + + if filters.get("show_remarks"): + if remarks_length := frappe.get_single_value("Accounts Settings", "general_ledger_remarks_length"): + select_fields += f",substr(remarks, 1, {remarks_length}) as 'remarks'" + else: + select_fields += """,remarks""" + + order_by_statement = "order by posting_date, account, creation" + + if filters.get("include_dimensions"): + order_by_statement = "order by posting_date, creation" + + if filters.get("categorize_by") == "Categorize by Voucher": + order_by_statement = "order by posting_date, voucher_type, voucher_no" + if filters.get("categorize_by") == "Categorize by Account": + order_by_statement = "order by account, posting_date, creation" + + if filters.get("include_default_book_entries"): + filters["company_fb"] = frappe.get_cached_value( + "Company", filters.get("company"), "default_finance_book" + ) + + dimension_fields = "" + if accounting_dimensions: + dimension_fields = ", ".join(accounting_dimensions) + "," + + transaction_currency_fields = "" + if filters.get("add_values_in_transaction_currency"): + transaction_currency_fields = ( + "debit_in_transaction_currency, credit_in_transaction_currency, transaction_currency," + ) + + gl_entries = frappe.db.sql( + f""" + select + name as gl_entry, posting_date, account, party_type, party, + voucher_type, voucher_subtype, voucher_no, {dimension_fields} + cost_center, project, {transaction_currency_fields} + against_voucher_type, against_voucher, account_currency, + against, is_opening, creation {select_fields} + from `tabGL Entry` + where company=%(company)s {get_conditions(filters)} + {order_by_statement} + """, + filters, + as_dict=1, + ) + + party_name_map = get_party_name_map() + + for gl_entry in gl_entries: + if gl_entry.party_type and gl_entry.party: + gl_entry.party_name = party_name_map.get(gl_entry.party_type, {}).get(gl_entry.party) + + if filters.get("presentation_currency"): + return convert_to_presentation_currency(gl_entries, currency_map, filters) + else: + return gl_entries + + +def get_conditions(filters): + conditions = [] + + ignore_is_opening = frappe.get_single_value("Accounts Settings", "ignore_is_opening_check_for_reporting") + + if filters.get("account"): + filters.account = get_accounts_with_children(filters.account) + if filters.account: + conditions.append("account in %(account)s") + + if filters.get("cost_center"): + filters.cost_center = get_cost_centers_with_children(filters.cost_center) + conditions.append("cost_center in %(cost_center)s") + + if filters.get("voucher_no"): + conditions.append("voucher_no=%(voucher_no)s") + + if filters.get("against_voucher_no"): + conditions.append("against_voucher=%(against_voucher_no)s") + + if filters.get("ignore_err"): + err_journals = frappe.db.get_all( + "Journal Entry", + filters={ + "company": filters.get("company"), + "docstatus": 1, + "voucher_type": ("in", ["Exchange Rate Revaluation", "Exchange Gain Or Loss"]), + }, + as_list=True, + ) + if err_journals: + filters.update({"voucher_no_not_in": [x[0] for x in err_journals]}) + + if filters.get("ignore_cr_dr_notes"): + system_generated_cr_dr_journals = frappe.db.get_all( + "Journal Entry", + filters={ + "company": filters.get("company"), + "docstatus": 1, + "voucher_type": ("in", ["Credit Note", "Debit Note"]), + "is_system_generated": 1, + }, + as_list=True, + ) + if system_generated_cr_dr_journals: + vouchers_to_ignore = (filters.get("voucher_no_not_in") or []) + [ + x[0] for x in system_generated_cr_dr_journals + ] + filters.update({"voucher_no_not_in": vouchers_to_ignore}) + + if filters.get("voucher_no_not_in"): + conditions.append("voucher_no not in %(voucher_no_not_in)s") + + if filters.get("categorize_by") == "Categorize by Party" and not filters.get("party_type"): + conditions.append("party_type in ('Customer', 'Supplier')") + + if filters.get("party_type"): + conditions.append("party_type=%(party_type)s") + + if filters.get("party"): + conditions.append("party in %(party)s") + + if not ( + filters.get("account") + or filters.get("party") + or filters.get("categorize_by") in ["Categorize by Account", "Categorize by Party"] + ): + if not ignore_is_opening: + conditions.append("(posting_date >=%(from_date)s or is_opening = 'Yes')") + else: + conditions.append("posting_date >=%(from_date)s") + + if not ignore_is_opening: + conditions.append("(posting_date <=%(to_date)s or is_opening = 'Yes')") + else: + conditions.append("posting_date <=%(to_date)s") + + if filters.get("project"): + conditions.append("project in %(project)s") + + if filters.get("include_default_book_entries"): + if filters.get("finance_book"): + if filters.get("company_fb") and cstr(filters.get("finance_book")) != cstr( + filters.get("company_fb") + ): + frappe.throw( + _("To use a different finance book, please uncheck 'Include Default FB Entries'") + ) + else: + conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)") + else: + conditions.append("(finance_book in (%(company_fb)s, '') OR finance_book IS NULL)") + else: + if filters.get("finance_book"): + conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)") + else: + conditions.append("(finance_book in ('') OR finance_book IS NULL)") + + if not filters.get("show_cancelled_entries"): + conditions.append("is_cancelled = 0") + + from frappe.desk.reportview import build_match_conditions + + match_conditions = build_match_conditions("GL Entry") + + if match_conditions: + conditions.append(match_conditions) + + accounting_dimensions = get_accounting_dimensions(as_list=False) + + if accounting_dimensions: + for dimension in accounting_dimensions: + # Ignore 'Finance Book' set up as dimension in below logic, as it is already handled in above section + if not dimension.disabled and dimension.document_type != "Finance Book": + if filters.get(dimension.fieldname): + if frappe.get_cached_value("DocType", dimension.document_type, "is_tree"): + filters[dimension.fieldname] = get_dimension_with_children( + dimension.document_type, filters.get(dimension.fieldname) + ) + conditions.append(f"{dimension.fieldname} in %({dimension.fieldname})s") + else: + conditions.append(f"{dimension.fieldname} in %({dimension.fieldname})s") + + return "and {}".format(" and ".join(conditions)) if conditions else "" + + +def get_party_name_map(): + party_map = {} + + customers = frappe.get_all("Customer", fields=["name", "customer_name"]) + party_map["Customer"] = {c.name: c.customer_name for c in customers} + + suppliers = frappe.get_all("Supplier", fields=["name", "supplier_name"]) + party_map["Supplier"] = {s.name: s.supplier_name for s in suppliers} + + employees = frappe.get_all("Employee", fields=["name", "employee_name"]) + party_map["Employee"] = {e.name: e.employee_name for e in employees} + return party_map + + +def get_accounts_with_children(accounts): + if not isinstance(accounts, list): + accounts = [d.strip() for d in accounts.strip().split(",") if d] + + if not accounts: + return + + doctype = frappe.qb.DocType("Account") + accounts_data = ( + frappe.qb.from_(doctype) + .select(doctype.lft, doctype.rgt) + .where(doctype.name.isin(accounts)) + .run(as_dict=True) + ) + + conditions = [] + for account in accounts_data: + conditions.append((doctype.lft >= account.lft) & (doctype.rgt <= account.rgt)) + + return frappe.qb.from_(doctype).select(doctype.name).where(Criterion.any(conditions)).run(pluck=True) + + +def set_bill_no(gl_entries): + inv_details = get_supplier_invoice_details() + for gl in gl_entries: + gl["bill_no"] = inv_details.get(gl.get("against_voucher"), "") + + +def get_translated_labels_for_totals(): + def wrap_in_quotes(label): + return f"'{label}'" + + return { + "opening": wrap_in_quotes(_("Opening")), + "total": wrap_in_quotes(_("Total")), + "closing": wrap_in_quotes(_("Closing (Opening + Total)")), + } + + +def get_data_with_opening_closing(filters, account_details, accounting_dimensions, gl_entries): + def add_total_to_data(totals, key): + row = totals[key] + row["account"] = labels[key] + data.append(row) + + labels = get_translated_labels_for_totals() + + data = [] + + set_bill_no(gl_entries) + + gle_map = initialize_gle_map(gl_entries, filters) + + totals, entries = get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map) + + # Opening for filtered account + add_total_to_data(totals, "opening") + + if filters.get("categorize_by") != "Categorize by Voucher (Consolidated)": + set_opening_closing = (not filters.get("categorize_by") and not filters.get("voucher_no")) or ( + filters.get("categorize_by") and filters.get("categorize_by") != "Categorize by Voucher" + ) + set_total = filters.get("categorize_by") or not filters.voucher_no + + for acc_dict in gle_map.values(): + if not acc_dict.entries: + continue + + # opening + data.append({"debit_in_transaction_currency": None, "credit_in_transaction_currency": None}) + if set_opening_closing: + add_total_to_data(acc_dict.totals, "opening") + + data += acc_dict.entries + + # totals + if set_total: + add_total_to_data(acc_dict.totals, "total") + + # closing + if set_opening_closing: + add_total_to_data(acc_dict.totals, "closing") + + data.append({"debit_in_transaction_currency": None, "credit_in_transaction_currency": None}) + else: + data += entries + + # totals + add_total_to_data(totals, "total") + + # closing + add_total_to_data(totals, "closing") + + return data + + +def get_totals_dict(): + return _dict( + opening=_dict(DEBIT_CREDIT_DICT), + total=_dict(DEBIT_CREDIT_DICT), + closing=_dict(DEBIT_CREDIT_DICT), + ) + + +def get_group_by_field(group_by): + if group_by == "Categorize by Party": + return "party" + elif group_by in ["Categorize by Voucher (Consolidated)", "Categorize by Account"]: + return "account" + else: + return "voucher_no" + + +def initialize_gle_map(gl_entries, filters): + gle_map = {} + group_by = get_group_by_field(filters.get("categorize_by")) + + for gle in gl_entries: + group_by_value = gle.get(group_by) + if group_by_value not in gle_map: + gle_map[group_by_value] = _dict( + totals=get_totals_dict(), + entries=[], + ) + + return gle_map + + +def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map): + entries = [] + consolidated_gle = {} + group_by = get_group_by_field(filters.get("categorize_by")) + group_by_voucher_consolidated = filters.get("categorize_by") == "Categorize by Voucher (Consolidated)" + + # Get a map of account names to their root types ('Income', 'Expense', etc.). + account_root_type_map = get_account_root_type_map(filters.get("company")) + profit_loss_root_types = {"Income", "Expense"} + + immutable_ledger = frappe.get_single_value("Accounts Settings", "enable_immutable_ledger") + + # --- Period Closing Check --- + # Determine the previous fiscal year based on the report's date filters. + from frappe.utils import add_days + current_fy_start_date = get_fiscal_year(filters.from_date, company=filters.company)[1] + previous_fy_end_date = add_days(current_fy_start_date, -1) + previous_fiscal_year = get_fiscal_year(previous_fy_end_date, company=filters.company)[0] + + # Check if a submitted Period Closing Voucher exists for the previous fiscal year. + # This ensures that we only adjust opening balances if the prior year is formally closed. + is_previous_year_closed = frappe.db.exists( + "Period Closing Voucher", + { + "company": filters.get("company"), + "fiscal_year": previous_fiscal_year, + "docstatus": 1, + }, + ) + + def update_value_in_dict(data, key, gle): + """A helper function to aggregate debit/credit values into a dictionary.""" + data[key].debit += gle.debit + data[key].credit += gle.credit + data[key].debit_in_account_currency += gle.debit_in_account_currency + data[key].credit_in_account_currency += gle.credit_in_account_currency + + if filters.get("add_values_in_transaction_currency") and key not in ["opening", "closing", "total"]: + data[key].debit_in_transaction_currency += gle.debit_in_transaction_currency + data[key].credit_in_transaction_currency += gle.credit_in_transaction_currency + + if filters.get("show_net_values_in_party_account") and account_root_type_map.get(data[key].account) in ( + "Receivable", + "Payable", + ): + net_value = data[key].debit - data[key].credit + net_value_in_account_currency = ( + data[key].debit_in_account_currency - data[key].credit_in_account_currency + ) + if net_value < 0: + dr_or_cr = "credit" + rev_dr_or_cr = "debit" + else: + dr_or_cr = "debit" + rev_dr_or_cr = "credit" + data[key][dr_or_cr] = abs(net_value) + data[key][dr_or_cr + "_in_account_currency"] = abs(net_value_in_account_currency) + data[key][rev_dr_or_cr] = 0 + data[key][rev_dr_or_cr + "_in_account_currency"] = 0 + + if data[key].against_voucher and gle.against_voucher: + data[key].against_voucher += ", " + gle.against_voucher + + from_date, to_date = getdate(filters.from_date), getdate(filters.to_date) + show_opening_entries = filters.get("show_opening_entries") + + totals = get_totals_dict() + for gle in gl_entries: + group_by_value = gle.get(group_by) + gle.voucher_subtype = _(gle.voucher_subtype) + gle.against_voucher_type = _(gle.against_voucher_type) + gle.remarks = _(gle.remarks) + gle.party_type = _(gle.party_type) + + # An entry is considered part of the "Opening" if its date is before the report's start date. + is_opening_entry = gle.posting_date < from_date or (cstr(gle.is_opening) == "Yes" and not show_opening_entries) + + root_type = account_root_type_map.get(gle.account) + + # It will only apply IF the previous year has been formally closed via a PCV. + if ( + is_previous_year_closed + and is_opening_entry + and root_type in profit_loss_root_types + and gle.posting_date < current_fy_start_date + ): + # Skip this entry from being added to the opening balance because it's + # a P&L entry from a prior, closed fiscal year. + continue + + if is_opening_entry: + if not group_by_voucher_consolidated: + update_value_in_dict(gle_map[group_by_value].totals, "opening", gle) + update_value_in_dict(gle_map[group_by_value].totals, "closing", gle) + update_value_in_dict(totals, "opening", gle) + update_value_in_dict(totals, "closing", gle) + elif gle.posting_date <= to_date or (cstr(gle.is_opening) == "Yes" and show_opening_entries): + if not group_by_voucher_consolidated: + update_value_in_dict(gle_map[group_by_value].totals, "total", gle) + update_value_in_dict(gle_map[group_by_value].totals, "closing", gle) + update_value_in_dict(totals, "total", gle) + update_value_in_dict(totals, "closing", gle) + gle_map[group_by_value].entries.append(gle) + elif group_by_voucher_consolidated: + keylist = [ + gle.get("posting_date"), + gle.get("voucher_type"), + gle.get("voucher_no"), + gle.get("account"), + gle.get("party_type"), + gle.get("party"), + ] + if immutable_ledger: + keylist.append(gle.get("creation")) + if filters.get("include_dimensions"): + for dim in accounting_dimensions: + keylist.append(gle.get(dim)) + keylist.append(gle.get("cost_center")) + keylist.append(gle.get("project")) + key = tuple(keylist) + if key not in consolidated_gle: + consolidated_gle.setdefault(key, gle) + else: + update_value_in_dict(consolidated_gle, key, gle) + + for value in consolidated_gle.values(): + update_value_in_dict(totals, "total", value) + update_value_in_dict(totals, "closing", value) + entries.append(value) + + return totals, entries + + +def get_account_type_map(company): + account_type_map = frappe._dict( + frappe.get_all("Account", fields=["name", "account_type"], filters={"company": company}, as_list=1) + ) + + return account_type_map + + +def get_result_as_list(data, filters): + balance = 0 + + for d in data: + if not d.get("posting_date"): + balance = 0 + + balance = get_balance(d, balance, "debit", "credit") + + d["balance"] = balance + + d["account_currency"] = filters.account_currency + + d["presentation_currency"] = filters.presentation_currency + + return data + + +def get_supplier_invoice_details(): + inv_details = {} + for d in frappe.db.sql( + """ select name, bill_no from `tabPurchase Invoice` + where docstatus = 1 and bill_no is not null and bill_no != '' """, + as_dict=1, + ): + inv_details[d.name] = d.bill_no + + return inv_details + + +def get_balance(row, balance, debit_field, credit_field): + balance += row.get(debit_field, 0) - row.get(credit_field, 0) + + return balance + + +def get_columns(filters): + if filters.get("presentation_currency"): + currency = filters["presentation_currency"] + else: + company = filters.get("company") or get_default_company() + filters["presentation_currency"] = currency = get_company_currency(company) + + company_currency = get_company_currency(filters.get("company") or get_default_company()) + + if ( + filters.get("show_amount_in_company_currency") + and filters["presentation_currency"] != company_currency + ): + frappe.throw( + _( + f'Presentation Currency cannot be {frappe.bold(filters["presentation_currency"])} , When {frappe.bold("Show Credit / Debit in Company Currency")} is enabled.' + ) + ) + + columns = [ + { + "label": _("GL Entry"), + "fieldname": "gl_entry", + "fieldtype": "Link", + "options": "GL Entry", + "hidden": 1, + }, + {"label": _("Posting Date"), "fieldname": "posting_date", "fieldtype": "Date", "width": 100}, + { + "label": _("Account"), + "fieldname": "account", + "fieldtype": "Link", + "options": "Account", + "width": 180, + }, + { + "label": _("Debit ({0})").format(currency), + "fieldname": "debit", + "fieldtype": "Currency", + "options": "presentation_currency", + "width": 130, + }, + { + "label": _("Credit ({0})").format(currency), + "fieldname": "credit", + "fieldtype": "Currency", + "options": "presentation_currency", + "width": 130, + }, + { + "label": _("Balance ({0})").format(currency), + "fieldname": "balance", + "fieldtype": "Currency", + "options": "presentation_currency", + "width": 130, + }, + ] + + if filters.get("add_values_in_transaction_currency"): + columns += [ + { + "label": _("Debit (Transaction)"), + "fieldname": "debit_in_transaction_currency", + "fieldtype": "Currency", + "width": 130, + "options": "transaction_currency", + }, + { + "label": _("Credit (Transaction)"), + "fieldname": "credit_in_transaction_currency", + "fieldtype": "Currency", + "width": 130, + "options": "transaction_currency", + }, + { + "label": "Transaction Currency", + "fieldname": "transaction_currency", + "fieldtype": "Link", + "options": "Currency", + "width": 70, + }, + ] + + columns += [ + {"label": _("Voucher Type"), "fieldname": "voucher_type", "width": 120}, + { + "label": _("Voucher Subtype"), + "fieldname": "voucher_subtype", + "fieldtype": "Data", + "width": 180, + }, + { + "label": _("Voucher No"), + "fieldname": "voucher_no", + "fieldtype": "Dynamic Link", + "options": "voucher_type", + "width": 180, + }, + {"label": _("Against Account"), "fieldname": "against", "width": 120}, + {"label": _("Party Type"), "fieldname": "party_type", "width": 100}, + {"label": _("Party"), "fieldname": "party", "width": 100}, + ] + + supplier_master_name = frappe.db.get_single_value("Buying Settings", "supp_master_name") + customer_master_name = frappe.db.get_single_value("Selling Settings", "cust_master_name") + + if supplier_master_name != "Supplier Name" or customer_master_name != "Customer Name": + columns.append( + { + "label": _("Party Name"), + "fieldname": "party_name", + "fieldtype": "Data", + "width": 150, + } + ) + + if filters.get("include_dimensions"): + columns.append({"label": _("Project"), "options": "Project", "fieldname": "project", "width": 100}) + + for dim in get_accounting_dimensions(as_list=False): + columns.append( + {"label": _(dim.label), "options": dim.label, "fieldname": dim.fieldname, "width": 100} + ) + columns.append( + {"label": _("Cost Center"), "options": "Cost Center", "fieldname": "cost_center", "width": 100} + ) + + columns.extend( + [ + {"label": _("Against Voucher Type"), "fieldname": "against_voucher_type", "width": 100}, + { + "label": _("Against Voucher"), + "fieldname": "against_voucher", + "fieldtype": "Dynamic Link", + "options": "against_voucher_type", + "width": 100, + }, + {"label": _("Supplier Invoice No"), "fieldname": "bill_no", "fieldtype": "Data", "width": 100}, + ] + ) + + if filters.get("show_remarks"): + columns.extend([{"label": _("Remarks"), "fieldname": "remarks", "width": 400}]) + + return columns + + +def get_account_root_type_map(company): + """Returns a dictionary mapping each account to its root_type.""" + return frappe._dict( + frappe.get_all("Account", fields=["name", "root_type"], filters={"company": company}, as_list=1) + ) \ No newline at end of file From b7b841d972f76bb90075a9e1f4ea339627699972 Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Thu, 11 Sep 2025 14:56:59 +0000 Subject: [PATCH 06/52] fix: file customization in attachment --- rohit_common/hooks.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rohit_common/hooks.py b/rohit_common/hooks.py index 689f000..e341a3f 100644 --- a/rohit_common/hooks.py +++ b/rohit_common/hooks.py @@ -17,7 +17,8 @@ override_whitelisted_methods = { # Below mentod would also take into account the search fields # mentioned in the Customize form view - "frappe.core.doctype.file.file.get_files_by_search_text": "rohit_common.core.file.get_files_by_search_text" + # "frappe.core.doctype.file.file.get_files_by_search_text": "rohit_common.core.file.get_files_by_search_text", + "frappe.core.api.file.get_files_by_search_text": "rohit_common.core.file.get_files_by_search_text" } # Includes in From 774704ab0f93bd17b15dc6df8aafed957f365b05 Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Fri, 12 Sep 2025 15:03:08 +0530 Subject: [PATCH 07/52] fix: general ledger (#2) * fix: general ledger * fix: some issues * fix: gl --- .../rigpl_general_ledger.py | 1308 ++++++++--------- 1 file changed, 639 insertions(+), 669 deletions(-) diff --git a/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py b/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py index 05e5102..c0975a3 100644 --- a/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py +++ b/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py @@ -8,812 +8,782 @@ from erpnext import get_company_currency, get_default_company from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( - get_accounting_dimensions, - get_dimension_with_children, + get_accounting_dimensions, + get_dimension_with_children, ) from erpnext.accounts.report.financial_statements import get_cost_centers_with_children from erpnext.accounts.report.utils import convert_to_presentation_currency, get_currency from erpnext.accounts.utils import get_account_currency, get_fiscal_year DEBIT_CREDIT_DICT = { - "debit": 0.0, - "credit": 0.0, - "debit_in_account_currency": 0.0, - "credit_in_account_currency": 0.0, - "debit_in_transaction_currency": None, - "credit_in_transaction_currency": None, + "debit": 0.0, + "credit": 0.0, + "debit_in_account_currency": 0.0, + "credit_in_account_currency": 0.0, + "debit_in_transaction_currency": None, + "credit_in_transaction_currency": None, } def execute(filters=None): - if not filters: - return [], [] + if not filters: + return [], [] - account_details = {} + if filters.get("from_date"): + filters.from_date = getdate(filters.from_date) + if filters.get("to_date"): + filters.to_date = getdate(filters.to_date) - if filters and filters.get("print_in_account_currency") and not filters.get("account"): - frappe.throw(_("Select an account to print in account currency")) + account_details = {} - for acc in frappe.db.sql("""select name, is_group from tabAccount""", as_dict=1): - account_details.setdefault(acc.name, acc) + if filters and filters.get("print_in_account_currency") and not filters.get("account"): + frappe.throw(_("Select an account to print in account currency")) - if filters.get("party"): - filters.party = frappe.parse_json(filters.get("party")) + for acc in frappe.db.sql("""select name, is_group from tabAccount""", as_dict=1): + account_details.setdefault(acc.name, acc) - validate_filters(filters, account_details) + if filters.get("party"): + filters.party = frappe.parse_json(filters.get("party")) - validate_party(filters) + validate_filters(filters, account_details) - filters = set_account_currency(filters) + validate_party(filters) - columns = get_columns(filters) + filters = set_account_currency(filters) - res = get_result(filters, account_details) + columns = get_columns(filters) - return columns, res + res = get_result(filters, account_details) + + return columns, res def validate_filters(filters, account_details): - if not filters.get("company"): - frappe.throw(_("{0} is mandatory").format(_("Company"))) + if not filters.get("company"): + frappe.throw(_("{0} is mandatory").format(_("Company"))) - if not filters.get("from_date") and not filters.get("to_date"): - frappe.throw( - _("{0} and {1} are mandatory").format(frappe.bold(_("From Date")), frappe.bold(_("To Date"))) - ) + if not filters.get("from_date") and not filters.get("to_date"): + frappe.throw( + _("{0} and {1} are mandatory").format(frappe.bold(_("From Date")), frappe.bold(_("To Date"))) + ) - if filters.get("account"): - filters.account = frappe.parse_json(filters.get("account")) - for account in filters.account: - if not account_details.get(account): - frappe.throw(_("Account {0} does not exists").format(account)) + if filters.get("account"): + filters.account = frappe.parse_json(filters.get("account")) + for account in filters.account: + if not account_details.get(account): + frappe.throw(_("Account {0} does not exists").format(account)) - if not filters.get("categorize_by") and filters.get("group_by"): - filters["categorize_by"] = filters["group_by"] - filters["categorize_by"] = filters["categorize_by"].replace("Group by", "Categorize by") + if not filters.get("categorize_by") and filters.get("group_by"): + filters["categorize_by"] = filters["group_by"] + filters["categorize_by"] = filters["categorize_by"].replace("Group by", "Categorize by") - if filters.get("account") and filters.get("categorize_by") == "Categorize by Account": - filters.account = frappe.parse_json(filters.get("account")) - for account in filters.account: - if account_details[account].is_group == 0: - frappe.throw(_("Can not filter based on Child Account, if grouped by Account")) + if filters.get("account") and filters.get("categorize_by") == "Categorize by Account": + filters.account = frappe.parse_json(filters.get("account")) + for account in filters.account: + if account_details[account].is_group == 0: + frappe.throw(_("Can not filter based on Child Account, if grouped by Account")) - if filters.get("voucher_no") and filters.get("categorize_by") in ["Categorize by Voucher"]: - frappe.throw(_("Can not filter based on Voucher No, if grouped by Voucher")) + if filters.get("voucher_no") and filters.get("categorize_by") in ["Categorize by Voucher"]: + frappe.throw(_("Can not filter based on Voucher No, if grouped by Voucher")) - if filters.from_date > filters.to_date: - frappe.throw(_("From Date must be before To Date")) + if filters.from_date > filters.to_date: + frappe.throw(_("From Date must be before To Date")) - if filters.get("project"): - filters.project = frappe.parse_json(filters.get("project")) + if filters.get("project"): + filters.project = frappe.parse_json(filters.get("project")) - if filters.get("cost_center"): - filters.cost_center = frappe.parse_json(filters.get("cost_center")) + if filters.get("cost_center"): + filters.cost_center = frappe.parse_json(filters.get("cost_center")) def validate_party(filters): - party_type, party = filters.get("party_type"), filters.get("party") + party_type, party = filters.get("party_type"), filters.get("party") - if party and party_type: - for d in party: - if not frappe.db.exists(party_type, d): - frappe.throw(_("Invalid {0}: {1}").format(party_type, d)) + if party and party_type: + for d in party: + if not frappe.db.exists(party_type, d): + frappe.throw(_("Invalid {0}: {1}").format(party_type, d)) def set_account_currency(filters): - if filters.get("account") or (filters.get("party") and len(filters.party) == 1): - filters["company_currency"] = frappe.get_cached_value("Company", filters.company, "default_currency") - account_currency = None - - if filters.get("account"): - if len(filters.get("account")) == 1: - account_currency = get_account_currency(filters.account[0]) - else: - currency = get_account_currency(filters.account[0]) - is_same_account_currency = True - for account in filters.get("account"): - if get_account_currency(account) != currency: - is_same_account_currency = False - break - - if is_same_account_currency: - account_currency = currency - - elif filters.get("party") and filters.get("party_type"): - gle_currency = frappe.db.get_value( - "GL Entry", - {"party_type": filters.party_type, "party": filters.party[0], "company": filters.company}, - "account_currency", - ) - - if gle_currency: - account_currency = gle_currency - else: - account_currency = ( - None - if filters.party_type in ["Employee", "Shareholder", "Member"] - else frappe.get_cached_value(filters.party_type, filters.party[0], "default_currency") - ) - - filters["account_currency"] = account_currency or filters.company_currency - if filters.account_currency != filters.company_currency and not filters.presentation_currency: - filters.presentation_currency = filters.account_currency - - return filters + if filters.get("account") or (filters.get("party") and len(filters.party) == 1): + filters["company_currency"] = frappe.get_cached_value("Company", filters.company, "default_currency") + account_currency = None + + if filters.get("account"): + if len(filters.get("account")) == 1: + account_currency = get_account_currency(filters.account[0]) + else: + currency = get_account_currency(filters.account[0]) + is_same_account_currency = True + for account in filters.get("account"): + if get_account_currency(account) != currency: + is_same_account_currency = False + break + + if is_same_account_currency: + account_currency = currency + + elif filters.get("party") and filters.get("party_type"): + gle_currency = frappe.db.get_value( + "GL Entry", + {"party_type": filters.party_type, "party": filters.party[0], "company": filters.company}, + "account_currency", + ) + + if gle_currency: + account_currency = gle_currency + else: + account_currency = ( + None + if filters.party_type in ["Employee", "Shareholder", "Member"] + else frappe.get_cached_value(filters.party_type, filters.party[0], "default_currency") + ) + + filters["account_currency"] = account_currency or filters.company_currency + if filters.account_currency != filters.company_currency and not filters.presentation_currency: + filters.presentation_currency = filters.account_currency + + return filters def get_result(filters, account_details): - accounting_dimensions = [] - if filters.get("include_dimensions"): - accounting_dimensions = get_accounting_dimensions() + accounting_dimensions = [] + if filters.get("include_dimensions"): + accounting_dimensions = get_accounting_dimensions() - gl_entries = get_gl_entries(filters, accounting_dimensions) + gl_entries = get_gl_entries(filters, accounting_dimensions) - data = get_data_with_opening_closing(filters, account_details, accounting_dimensions, gl_entries) + data = get_data_with_opening_closing(filters, account_details, accounting_dimensions, gl_entries) - result = get_result_as_list(data, filters) + result = get_result_as_list(data, filters) - return result + return result def get_gl_entries(filters, accounting_dimensions): - currency_map = get_currency(filters) - select_fields = """, debit, credit, debit_in_account_currency, - credit_in_account_currency """ - - if filters.get("show_remarks"): - if remarks_length := frappe.get_single_value("Accounts Settings", "general_ledger_remarks_length"): - select_fields += f",substr(remarks, 1, {remarks_length}) as 'remarks'" - else: - select_fields += """,remarks""" - - order_by_statement = "order by posting_date, account, creation" - - if filters.get("include_dimensions"): - order_by_statement = "order by posting_date, creation" - - if filters.get("categorize_by") == "Categorize by Voucher": - order_by_statement = "order by posting_date, voucher_type, voucher_no" - if filters.get("categorize_by") == "Categorize by Account": - order_by_statement = "order by account, posting_date, creation" - - if filters.get("include_default_book_entries"): - filters["company_fb"] = frappe.get_cached_value( - "Company", filters.get("company"), "default_finance_book" - ) - - dimension_fields = "" - if accounting_dimensions: - dimension_fields = ", ".join(accounting_dimensions) + "," - - transaction_currency_fields = "" - if filters.get("add_values_in_transaction_currency"): - transaction_currency_fields = ( - "debit_in_transaction_currency, credit_in_transaction_currency, transaction_currency," - ) - - gl_entries = frappe.db.sql( - f""" - select - name as gl_entry, posting_date, account, party_type, party, - voucher_type, voucher_subtype, voucher_no, {dimension_fields} - cost_center, project, {transaction_currency_fields} - against_voucher_type, against_voucher, account_currency, - against, is_opening, creation {select_fields} - from `tabGL Entry` - where company=%(company)s {get_conditions(filters)} - {order_by_statement} - """, - filters, - as_dict=1, - ) - - party_name_map = get_party_name_map() - - for gl_entry in gl_entries: - if gl_entry.party_type and gl_entry.party: - gl_entry.party_name = party_name_map.get(gl_entry.party_type, {}).get(gl_entry.party) - - if filters.get("presentation_currency"): - return convert_to_presentation_currency(gl_entries, currency_map, filters) - else: - return gl_entries + currency_map = get_currency(filters) + select_fields = """, debit, credit, debit_in_account_currency, + credit_in_account_currency """ + + if filters.get("show_remarks"): + if remarks_length := frappe.get_single_value("Accounts Settings", "general_ledger_remarks_length"): + select_fields += f",substr(remarks, 1, {remarks_length}) as 'remarks'" + else: + select_fields += """,remarks""" + + order_by_statement = "order by posting_date, account, creation" + + if filters.get("include_dimensions"): + order_by_statement = "order by posting_date, creation" + + if filters.get("categorize_by") == "Categorize by Voucher": + order_by_statement = "order by posting_date, voucher_type, voucher_no" + if filters.get("categorize_by") == "Categorize by Account": + order_by_statement = "order by account, posting_date, creation" + + if filters.get("include_default_book_entries"): + filters["company_fb"] = frappe.get_cached_value( + "Company", filters.get("company"), "default_finance_book" + ) + + dimension_fields = "" + if accounting_dimensions: + dimension_fields = ", ".join(accounting_dimensions) + "," + + transaction_currency_fields = "" + if filters.get("add_values_in_transaction_currency"): + transaction_currency_fields = ( + "debit_in_transaction_currency, credit_in_transaction_currency, transaction_currency," + ) + + gl_entries = frappe.db.sql( + f""" + select + name as gl_entry, posting_date, account, party_type, party, + voucher_type, voucher_subtype, voucher_no, {dimension_fields} + cost_center, project, {transaction_currency_fields} + against_voucher_type, against_voucher, account_currency, + against, is_opening, creation {select_fields} + from `tabGL Entry` + where company=%(company)s {get_conditions(filters)} + {order_by_statement} + """, + filters, + as_dict=1, + ) + + party_name_map = get_party_name_map() + + for gl_entry in gl_entries: + if gl_entry.party_type and gl_entry.party: + gl_entry.party_name = party_name_map.get(gl_entry.party_type, {}).get(gl_entry.party) + + if filters.get("presentation_currency"): + return convert_to_presentation_currency(gl_entries, currency_map, filters) + else: + return gl_entries def get_conditions(filters): - conditions = [] - - ignore_is_opening = frappe.get_single_value("Accounts Settings", "ignore_is_opening_check_for_reporting") - - if filters.get("account"): - filters.account = get_accounts_with_children(filters.account) - if filters.account: - conditions.append("account in %(account)s") - - if filters.get("cost_center"): - filters.cost_center = get_cost_centers_with_children(filters.cost_center) - conditions.append("cost_center in %(cost_center)s") - - if filters.get("voucher_no"): - conditions.append("voucher_no=%(voucher_no)s") - - if filters.get("against_voucher_no"): - conditions.append("against_voucher=%(against_voucher_no)s") - - if filters.get("ignore_err"): - err_journals = frappe.db.get_all( - "Journal Entry", - filters={ - "company": filters.get("company"), - "docstatus": 1, - "voucher_type": ("in", ["Exchange Rate Revaluation", "Exchange Gain Or Loss"]), - }, - as_list=True, - ) - if err_journals: - filters.update({"voucher_no_not_in": [x[0] for x in err_journals]}) - - if filters.get("ignore_cr_dr_notes"): - system_generated_cr_dr_journals = frappe.db.get_all( - "Journal Entry", - filters={ - "company": filters.get("company"), - "docstatus": 1, - "voucher_type": ("in", ["Credit Note", "Debit Note"]), - "is_system_generated": 1, - }, - as_list=True, - ) - if system_generated_cr_dr_journals: - vouchers_to_ignore = (filters.get("voucher_no_not_in") or []) + [ - x[0] for x in system_generated_cr_dr_journals - ] - filters.update({"voucher_no_not_in": vouchers_to_ignore}) - - if filters.get("voucher_no_not_in"): - conditions.append("voucher_no not in %(voucher_no_not_in)s") - - if filters.get("categorize_by") == "Categorize by Party" and not filters.get("party_type"): - conditions.append("party_type in ('Customer', 'Supplier')") - - if filters.get("party_type"): - conditions.append("party_type=%(party_type)s") - - if filters.get("party"): - conditions.append("party in %(party)s") - - if not ( - filters.get("account") - or filters.get("party") - or filters.get("categorize_by") in ["Categorize by Account", "Categorize by Party"] - ): - if not ignore_is_opening: - conditions.append("(posting_date >=%(from_date)s or is_opening = 'Yes')") - else: - conditions.append("posting_date >=%(from_date)s") - - if not ignore_is_opening: - conditions.append("(posting_date <=%(to_date)s or is_opening = 'Yes')") - else: - conditions.append("posting_date <=%(to_date)s") - - if filters.get("project"): - conditions.append("project in %(project)s") - - if filters.get("include_default_book_entries"): - if filters.get("finance_book"): - if filters.get("company_fb") and cstr(filters.get("finance_book")) != cstr( - filters.get("company_fb") - ): - frappe.throw( - _("To use a different finance book, please uncheck 'Include Default FB Entries'") - ) - else: - conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)") - else: - conditions.append("(finance_book in (%(company_fb)s, '') OR finance_book IS NULL)") - else: - if filters.get("finance_book"): - conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)") - else: - conditions.append("(finance_book in ('') OR finance_book IS NULL)") - - if not filters.get("show_cancelled_entries"): - conditions.append("is_cancelled = 0") - - from frappe.desk.reportview import build_match_conditions - - match_conditions = build_match_conditions("GL Entry") - - if match_conditions: - conditions.append(match_conditions) - - accounting_dimensions = get_accounting_dimensions(as_list=False) - - if accounting_dimensions: - for dimension in accounting_dimensions: - # Ignore 'Finance Book' set up as dimension in below logic, as it is already handled in above section - if not dimension.disabled and dimension.document_type != "Finance Book": - if filters.get(dimension.fieldname): - if frappe.get_cached_value("DocType", dimension.document_type, "is_tree"): - filters[dimension.fieldname] = get_dimension_with_children( - dimension.document_type, filters.get(dimension.fieldname) - ) - conditions.append(f"{dimension.fieldname} in %({dimension.fieldname})s") - else: - conditions.append(f"{dimension.fieldname} in %({dimension.fieldname})s") - - return "and {}".format(" and ".join(conditions)) if conditions else "" + # Get the start and end dates of the fiscal year based on the 'from_date' filter + fy = get_fiscal_year(filters.from_date, company=filters.company) + filters.fy_start_date = fy[1] + + conditions = [] + ignore_is_opening = frappe.get_single_value("Accounts Settings", "ignore_is_opening_check_for_reporting") + + if filters.get("account"): + filters.account = get_accounts_with_children(filters.account) + if filters.account: + conditions.append("account in %(account)s") + if filters.get("cost_center"): + filters.cost_center = get_cost_centers_with_children(filters.cost_center) + conditions.append("cost_center in %(cost_center)s") + if filters.get("voucher_no"): + conditions.append("voucher_no=%(voucher_no)s") + if filters.get("against_voucher_no"): + conditions.append("against_voucher=%(against_voucher_no)s") + if filters.get("ignore_err"): + err_journals = frappe.db.get_all( + "Journal Entry", + filters={ + "company": filters.get("company"), + "docstatus": 1, + "voucher_type": ("in", ["Exchange Rate Revaluation", "Exchange Gain Or Loss"]), + }, + as_list=True, + ) + if err_journals: + filters.update({"voucher_no_not_in": [x[0] for x in err_journals]}) + if filters.get("ignore_cr_dr_notes"): + system_generated_cr_dr_journals = frappe.db.get_all( + "Journal Entry", + filters={ + "company": filters.get("company"), + "docstatus": 1, + "voucher_type": ("in", ["Credit Note", "Debit Note"]), + "is_system_generated": 1, + }, + as_list=True, + ) + if system_generated_cr_dr_journals: + vouchers_to_ignore = (filters.get("voucher_no_not_in") or []) + [ + x[0] for x in system_generated_cr_dr_journals + ] + filters.update({"voucher_no_not_in": vouchers_to_ignore}) + if filters.get("voucher_no_not_in"): + conditions.append("voucher_no not in %(voucher_no_not_in)s") + if filters.get("categorize_by") == "Categorize by Party" and not filters.get("party_type"): + conditions.append("party_type in ('Customer', 'Supplier')") + if filters.get("party_type"): + conditions.append("party_type=%(party_type)s") + if filters.get("party"): + conditions.append("party in %(party)s") + + # Always fetch data from the start of the fiscal year to correctly calculate the opening balance. + # The python logic will handle separating the transactions that occurred before the 'from_date'. + if not ignore_is_opening: + conditions.append("(posting_date >= %(fy_start_date)s or is_opening = 'Yes')") + else: + conditions.append("posting_date >= %(fy_start_date)s") + + if not ignore_is_opening: + conditions.append("(posting_date <=%(to_date)s or is_opening = 'Yes')") + else: + conditions.append("posting_date <=%(to_date)s") + if filters.get("project"): + conditions.append("project in %(project)s") + if filters.get("include_default_book_entries"): + if filters.get("finance_book"): + if filters.get("company_fb") and cstr(filters.get("finance_book")) != cstr( + filters.get("company_fb") + ): + frappe.throw( + _("To use a different finance book, please uncheck 'Include Default FB Entries'") + ) + else: + conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)") + else: + conditions.append("(finance_book in (%(company_fb)s, '') OR finance_book IS NULL)") + else: + if filters.get("finance_book"): + conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)") + else: + conditions.append("(finance_book in ('') OR finance_book IS NULL)") + if not filters.get("show_cancelled_entries"): + conditions.append("is_cancelled = 0") + from frappe.desk.reportview import build_match_conditions + match_conditions = build_match_conditions("GL Entry") + if match_conditions: + conditions.append(match_conditions) + accounting_dimensions = get_accounting_dimensions(as_list=False) + if accounting_dimensions: + for dimension in accounting_dimensions: + if not dimension.disabled and dimension.document_type != "Finance Book": + if filters.get(dimension.fieldname): + if frappe.get_cached_value("DocType", dimension.document_type, "is_tree"): + filters[dimension.fieldname] = get_dimension_with_children( + dimension.document_type, filters.get(dimension.fieldname) + ) + conditions.append(f"{dimension.fieldname} in %({dimension.fieldname})s") + else: + conditions.append(f"{dimension.fieldname} in %({dimension.fieldname})s") + return "and {}".format(" and ".join(conditions)) if conditions else "" def get_party_name_map(): - party_map = {} + party_map = {} - customers = frappe.get_all("Customer", fields=["name", "customer_name"]) - party_map["Customer"] = {c.name: c.customer_name for c in customers} + customers = frappe.get_all("Customer", fields=["name", "customer_name"]) + party_map["Customer"] = {c.name: c.customer_name for c in customers} - suppliers = frappe.get_all("Supplier", fields=["name", "supplier_name"]) - party_map["Supplier"] = {s.name: s.supplier_name for s in suppliers} + suppliers = frappe.get_all("Supplier", fields=["name", "supplier_name"]) + party_map["Supplier"] = {s.name: s.supplier_name for s in suppliers} - employees = frappe.get_all("Employee", fields=["name", "employee_name"]) - party_map["Employee"] = {e.name: e.employee_name for e in employees} - return party_map + employees = frappe.get_all("Employee", fields=["name", "employee_name"]) + party_map["Employee"] = {e.name: e.employee_name for e in employees} + return party_map def get_accounts_with_children(accounts): - if not isinstance(accounts, list): - accounts = [d.strip() for d in accounts.strip().split(",") if d] - - if not accounts: - return - - doctype = frappe.qb.DocType("Account") - accounts_data = ( - frappe.qb.from_(doctype) - .select(doctype.lft, doctype.rgt) - .where(doctype.name.isin(accounts)) - .run(as_dict=True) - ) + if not isinstance(accounts, list): + accounts = [d.strip() for d in accounts.strip().split(",") if d] + + if not accounts: + return + + doctype = frappe.qb.DocType("Account") + accounts_data = ( + frappe.qb.from_(doctype) + .select(doctype.lft, doctype.rgt) + .where(doctype.name.isin(accounts)) + .run(as_dict=True) + ) - conditions = [] - for account in accounts_data: - conditions.append((doctype.lft >= account.lft) & (doctype.rgt <= account.rgt)) + conditions = [] + for account in accounts_data: + conditions.append((doctype.lft >= account.lft) & (doctype.rgt <= account.rgt)) - return frappe.qb.from_(doctype).select(doctype.name).where(Criterion.any(conditions)).run(pluck=True) + return frappe.qb.from_(doctype).select(doctype.name).where(Criterion.any(conditions)).run(pluck=True) def set_bill_no(gl_entries): - inv_details = get_supplier_invoice_details() - for gl in gl_entries: - gl["bill_no"] = inv_details.get(gl.get("against_voucher"), "") + inv_details = get_supplier_invoice_details() + for gl in gl_entries: + gl["bill_no"] = inv_details.get(gl.get("against_voucher"), "") def get_translated_labels_for_totals(): - def wrap_in_quotes(label): - return f"'{label}'" + def wrap_in_quotes(label): + return f"'{label}'" - return { - "opening": wrap_in_quotes(_("Opening")), - "total": wrap_in_quotes(_("Total")), - "closing": wrap_in_quotes(_("Closing (Opening + Total)")), - } + return { + "opening": wrap_in_quotes(_("Opening")), + "total": wrap_in_quotes(_("Total")), + "closing": wrap_in_quotes(_("Closing (Opening + Total)")), + } def get_data_with_opening_closing(filters, account_details, accounting_dimensions, gl_entries): - def add_total_to_data(totals, key): - row = totals[key] - row["account"] = labels[key] - data.append(row) + def add_total_to_data(totals, key): + row = totals.get(key, _dict(DEBIT_CREDIT_DICT)) + row["account"] = labels[key] + data.append(row) - labels = get_translated_labels_for_totals() + labels = get_translated_labels_for_totals() - data = [] + data = [] - set_bill_no(gl_entries) + set_bill_no(gl_entries) - gle_map = initialize_gle_map(gl_entries, filters) + gle_map = initialize_gle_map(gl_entries, filters) - totals, entries = get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map) + totals, entries = get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map) - # Opening for filtered account - add_total_to_data(totals, "opening") + # Opening for filtered account + add_total_to_data(totals, "opening") - if filters.get("categorize_by") != "Categorize by Voucher (Consolidated)": - set_opening_closing = (not filters.get("categorize_by") and not filters.get("voucher_no")) or ( - filters.get("categorize_by") and filters.get("categorize_by") != "Categorize by Voucher" - ) - set_total = filters.get("categorize_by") or not filters.voucher_no + if filters.get("categorize_by") != "Categorize by Voucher (Consolidated)": + set_opening_closing = (not filters.get("categorize_by") and not filters.get("voucher_no")) or ( + filters.get("categorize_by") and filters.get("categorize_by") != "Categorize by Voucher" + ) + set_total = filters.get("categorize_by") or not filters.voucher_no - for acc_dict in gle_map.values(): - if not acc_dict.entries: - continue + for acc_dict in gle_map.values(): + if not acc_dict.entries: + continue - # opening - data.append({"debit_in_transaction_currency": None, "credit_in_transaction_currency": None}) - if set_opening_closing: - add_total_to_data(acc_dict.totals, "opening") + # opening + data.append({"debit_in_transaction_currency": None, "credit_in_transaction_currency": None}) + if set_opening_closing: + add_total_to_data(acc_dict.totals, "opening") - data += acc_dict.entries + data += acc_dict.entries - # totals - if set_total: - add_total_to_data(acc_dict.totals, "total") + # totals + if set_total: + add_total_to_data(acc_dict.totals, "total") - # closing - if set_opening_closing: - add_total_to_data(acc_dict.totals, "closing") + # closing + if set_opening_closing: + add_total_to_data(acc_dict.totals, "closing") - data.append({"debit_in_transaction_currency": None, "credit_in_transaction_currency": None}) - else: - data += entries + data.append({"debit_in_transaction_currency": None, "credit_in_transaction_currency": None}) + else: + data += entries - # totals - add_total_to_data(totals, "total") + # totals + add_total_to_data(totals, "total") - # closing - add_total_to_data(totals, "closing") + # closing + add_total_to_data(totals, "closing") - return data + return data def get_totals_dict(): - return _dict( - opening=_dict(DEBIT_CREDIT_DICT), - total=_dict(DEBIT_CREDIT_DICT), - closing=_dict(DEBIT_CREDIT_DICT), - ) + return _dict( + opening=_dict(DEBIT_CREDIT_DICT), + total=_dict(DEBIT_CREDIT_DICT), + closing=_dict(DEBIT_CREDIT_DICT), + ) def get_group_by_field(group_by): - if group_by == "Categorize by Party": - return "party" - elif group_by in ["Categorize by Voucher (Consolidated)", "Categorize by Account"]: - return "account" - else: - return "voucher_no" + if group_by == "Categorize by Party": + return "party" + elif group_by in ["Categorize by Voucher (Consolidated)", "Categorize by Account"]: + return "account" + else: + return "voucher_no" def initialize_gle_map(gl_entries, filters): - gle_map = {} - group_by = get_group_by_field(filters.get("categorize_by")) + gle_map = {} + group_by = get_group_by_field(filters.get("categorize_by")) - for gle in gl_entries: - group_by_value = gle.get(group_by) - if group_by_value not in gle_map: - gle_map[group_by_value] = _dict( - totals=get_totals_dict(), - entries=[], - ) + for gle in gl_entries: + group_by_value = gle.get(group_by) + if group_by_value not in gle_map: + gle_map[group_by_value] = _dict( + totals=get_totals_dict(), + entries=[], + ) - return gle_map + return gle_map def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map): - entries = [] - consolidated_gle = {} - group_by = get_group_by_field(filters.get("categorize_by")) - group_by_voucher_consolidated = filters.get("categorize_by") == "Categorize by Voucher (Consolidated)" - - # Get a map of account names to their root types ('Income', 'Expense', etc.). - account_root_type_map = get_account_root_type_map(filters.get("company")) - profit_loss_root_types = {"Income", "Expense"} - - immutable_ledger = frappe.get_single_value("Accounts Settings", "enable_immutable_ledger") - - # --- Period Closing Check --- - # Determine the previous fiscal year based on the report's date filters. - from frappe.utils import add_days - current_fy_start_date = get_fiscal_year(filters.from_date, company=filters.company)[1] - previous_fy_end_date = add_days(current_fy_start_date, -1) - previous_fiscal_year = get_fiscal_year(previous_fy_end_date, company=filters.company)[0] - - # Check if a submitted Period Closing Voucher exists for the previous fiscal year. - # This ensures that we only adjust opening balances if the prior year is formally closed. - is_previous_year_closed = frappe.db.exists( - "Period Closing Voucher", - { - "company": filters.get("company"), - "fiscal_year": previous_fiscal_year, - "docstatus": 1, - }, + data = frappe._dict() + account_root_type_map = frappe._dict( + frappe.get_all("Account", fields=["name", "root_type"], as_list=1) ) + totals = get_totals_dict() + def update_value_in_dict(data, key, gle): - """A helper function to aggregate debit/credit values into a dictionary.""" + if key not in data: + data[key] = frappe._dict( + debit=0.0, + credit=0.0, + debit_in_account_currency=0.0, + credit_in_account_currency=0.0, + ) + data[key].debit += gle.debit data[key].credit += gle.credit data[key].debit_in_account_currency += gle.debit_in_account_currency data[key].credit_in_account_currency += gle.credit_in_account_currency - if filters.get("add_values_in_transaction_currency") and key not in ["opening", "closing", "total"]: - data[key].debit_in_transaction_currency += gle.debit_in_transaction_currency - data[key].credit_in_transaction_currency += gle.credit_in_transaction_currency - - if filters.get("show_net_values_in_party_account") and account_root_type_map.get(data[key].account) in ( - "Receivable", - "Payable", - ): - net_value = data[key].debit - data[key].credit - net_value_in_account_currency = ( - data[key].debit_in_account_currency - data[key].credit_in_account_currency - ) - if net_value < 0: - dr_or_cr = "credit" - rev_dr_or_cr = "debit" - else: - dr_or_cr = "debit" - rev_dr_or_cr = "credit" - data[key][dr_or_cr] = abs(net_value) - data[key][dr_or_cr + "_in_account_currency"] = abs(net_value_in_account_currency) - data[key][rev_dr_or_cr] = 0 - data[key][rev_dr_or_cr + "_in_account_currency"] = 0 + if filters.get("show_net_values_in_party_account"): + root_type_for_entry = account_root_type_map.get(gle.account) + if root_type_for_entry in ("Receivable", "Payable"): + net_value = data[key].debit - data[key].credit + net_value_in_account_currency = ( + data[key].debit_in_account_currency + - data[key].credit_in_account_currency + ) + if net_value < 0: + dr_or_cr, rev_dr_or_cr = "credit", "debit" + else: + dr_or_cr, rev_dr_or_cr = "debit", "credit" + data[key][dr_or_cr] = abs(net_value) + data[key][dr_or_cr + "_in_account_currency"] = abs( + net_value_in_account_currency + ) + data[key][rev_dr_or_cr] = 0 + data[key][rev_dr_or_cr + "_in_account_currency"] = 0 + + # Opening from PCV if closed, else from raw GL + is_closed = frappe.db.get_value( + "Company", filters.company, "enable_perpetual_inventory" + ) - if data[key].against_voucher and gle.against_voucher: - data[key].against_voucher += ", " + gle.against_voucher + if is_closed: + fy = get_fiscal_year(filters.from_date, as_dict=True) + # Get the previous fiscal year by finding the year for the date right before the current one starts + prev_fy = get_fiscal_year(fy.year_start_date - 1, as_dict=True) + + pcv_filters = { + "company": filters.company, + "voucher_type": "Period Closing Voucher", + "fiscal_year": prev_fy.name, + "is_cancelled": 0, + } + # If report is filtered by account, apply the same to the opening balance query + if filters.get("account"): + pcv_filters["account"] = ("in", filters.account) + + pcv_entries = frappe.db.get_all( + "GL Entry", + filters=pcv_filters, + fields=["debit", "credit", "account", "debit_in_account_currency", "credit_in_account_currency"], + ) + for e in pcv_entries: + update_value_in_dict(totals, "opening", _dict(e)) + update_value_in_dict(totals, "closing", _dict(e)) + else: + for g in gl_entries: + if getdate(g.posting_date) < filters.from_date: + update_value_in_dict(totals, "opening", g) + update_value_in_dict(totals, "closing", g) + + # Transactions within date range + for g in gl_entries: + if filters.from_date <= getdate(g.posting_date) <= filters.to_date: + update_value_in_dict(totals, "total", g) + update_value_in_dict(totals, "closing", g) + + return totals, gl_entries - from_date, to_date = getdate(filters.from_date), getdate(filters.to_date) - show_opening_entries = filters.get("show_opening_entries") - totals = get_totals_dict() - for gle in gl_entries: - group_by_value = gle.get(group_by) - gle.voucher_subtype = _(gle.voucher_subtype) - gle.against_voucher_type = _(gle.against_voucher_type) - gle.remarks = _(gle.remarks) - gle.party_type = _(gle.party_type) - - # An entry is considered part of the "Opening" if its date is before the report's start date. - is_opening_entry = gle.posting_date < from_date or (cstr(gle.is_opening) == "Yes" and not show_opening_entries) - - root_type = account_root_type_map.get(gle.account) - - # It will only apply IF the previous year has been formally closed via a PCV. - if ( - is_previous_year_closed - and is_opening_entry - and root_type in profit_loss_root_types - and gle.posting_date < current_fy_start_date - ): - # Skip this entry from being added to the opening balance because it's - # a P&L entry from a prior, closed fiscal year. - continue - - if is_opening_entry: - if not group_by_voucher_consolidated: - update_value_in_dict(gle_map[group_by_value].totals, "opening", gle) - update_value_in_dict(gle_map[group_by_value].totals, "closing", gle) - update_value_in_dict(totals, "opening", gle) - update_value_in_dict(totals, "closing", gle) - elif gle.posting_date <= to_date or (cstr(gle.is_opening) == "Yes" and show_opening_entries): - if not group_by_voucher_consolidated: - update_value_in_dict(gle_map[group_by_value].totals, "total", gle) - update_value_in_dict(gle_map[group_by_value].totals, "closing", gle) - update_value_in_dict(totals, "total", gle) - update_value_in_dict(totals, "closing", gle) - gle_map[group_by_value].entries.append(gle) - elif group_by_voucher_consolidated: - keylist = [ - gle.get("posting_date"), - gle.get("voucher_type"), - gle.get("voucher_no"), - gle.get("account"), - gle.get("party_type"), - gle.get("party"), - ] - if immutable_ledger: - keylist.append(gle.get("creation")) - if filters.get("include_dimensions"): - for dim in accounting_dimensions: - keylist.append(gle.get(dim)) - keylist.append(gle.get("cost_center")) - keylist.append(gle.get("project")) - key = tuple(keylist) - if key not in consolidated_gle: - consolidated_gle.setdefault(key, gle) - else: - update_value_in_dict(consolidated_gle, key, gle) +def get_account_type_map(company): + account_type_map = frappe._dict( + frappe.get_all("Account", fields=["name", "account_type"], filters={"company": company}, as_list=1) + ) - for value in consolidated_gle.values(): - update_value_in_dict(totals, "total", value) - update_value_in_dict(totals, "closing", value) - entries.append(value) + return account_type_map - return totals, entries +def get_result_as_list(data, filters): + balance = 0.0 + opening_balance = None -def get_account_type_map(company): - account_type_map = frappe._dict( - frappe.get_all("Account", fields=["name", "account_type"], filters={"company": company}, as_list=1) - ) + def contains_label(s, label): + return label in (s or "").lower() - return account_type_map + total_debit = 0.0 + total_credit = 0.0 + for d in data: + acct_text = d.get("account") or "" + acct_text_l = acct_text.lower() -def get_result_as_list(data, filters): - balance = 0 + if contains_label(acct_text_l, "opening"): + opening_balance = d.get("debit", 0.0) - d.get("credit", 0.0) + balance = opening_balance + d["balance"] = balance + continue - for d in data: - if not d.get("posting_date"): - balance = 0 + if d.get("posting_date"): + balance += d.get("debit", 0.0) - d.get("credit", 0.0) + total_debit += d.get("debit", 0.0) + total_credit += d.get("credit", 0.0) + d["balance"] = balance + continue - balance = get_balance(d, balance, "debit", "credit") + if contains_label(acct_text_l, "total"): + d["balance"] = total_debit - total_credit + continue - d["balance"] = balance + if contains_label(acct_text_l, "closing"): + d["balance"] = opening_balance + (total_debit - total_credit) + balance = 0.0 + opening_balance = None + total_debit = 0.0 + total_credit = 0.0 + continue - d["account_currency"] = filters.account_currency + if not d.get("posting_date"): + balance = 0.0 + opening_balance = None + d["balance"] = None - d["presentation_currency"] = filters.presentation_currency + for d in data: + d["account_currency"] = filters.account_currency + d["presentation_currency"] = filters.presentation_currency - return data + return data def get_supplier_invoice_details(): - inv_details = {} - for d in frappe.db.sql( - """ select name, bill_no from `tabPurchase Invoice` - where docstatus = 1 and bill_no is not null and bill_no != '' """, - as_dict=1, - ): - inv_details[d.name] = d.bill_no + inv_details = {} + for d in frappe.db.sql( + """ select name, bill_no from `tabPurchase Invoice` + where docstatus = 1 and bill_no is not null and bill_no != '' """, + as_dict=1, + ): + inv_details[d.name] = d.bill_no - return inv_details + return inv_details def get_balance(row, balance, debit_field, credit_field): - balance += row.get(debit_field, 0) - row.get(credit_field, 0) + balance += row.get(debit_field, 0) - row.get(credit_field, 0) - return balance + return balance def get_columns(filters): - if filters.get("presentation_currency"): - currency = filters["presentation_currency"] - else: - company = filters.get("company") or get_default_company() - filters["presentation_currency"] = currency = get_company_currency(company) - - company_currency = get_company_currency(filters.get("company") or get_default_company()) - - if ( - filters.get("show_amount_in_company_currency") - and filters["presentation_currency"] != company_currency - ): - frappe.throw( - _( - f'Presentation Currency cannot be {frappe.bold(filters["presentation_currency"])} , When {frappe.bold("Show Credit / Debit in Company Currency")} is enabled.' - ) - ) - - columns = [ - { - "label": _("GL Entry"), - "fieldname": "gl_entry", - "fieldtype": "Link", - "options": "GL Entry", - "hidden": 1, - }, - {"label": _("Posting Date"), "fieldname": "posting_date", "fieldtype": "Date", "width": 100}, - { - "label": _("Account"), - "fieldname": "account", - "fieldtype": "Link", - "options": "Account", - "width": 180, - }, - { - "label": _("Debit ({0})").format(currency), - "fieldname": "debit", - "fieldtype": "Currency", - "options": "presentation_currency", - "width": 130, - }, - { - "label": _("Credit ({0})").format(currency), - "fieldname": "credit", - "fieldtype": "Currency", - "options": "presentation_currency", - "width": 130, - }, - { - "label": _("Balance ({0})").format(currency), - "fieldname": "balance", - "fieldtype": "Currency", - "options": "presentation_currency", - "width": 130, - }, - ] - - if filters.get("add_values_in_transaction_currency"): - columns += [ - { - "label": _("Debit (Transaction)"), - "fieldname": "debit_in_transaction_currency", - "fieldtype": "Currency", - "width": 130, - "options": "transaction_currency", - }, - { - "label": _("Credit (Transaction)"), - "fieldname": "credit_in_transaction_currency", - "fieldtype": "Currency", - "width": 130, - "options": "transaction_currency", - }, - { - "label": "Transaction Currency", - "fieldname": "transaction_currency", - "fieldtype": "Link", - "options": "Currency", - "width": 70, - }, - ] - - columns += [ - {"label": _("Voucher Type"), "fieldname": "voucher_type", "width": 120}, - { - "label": _("Voucher Subtype"), - "fieldname": "voucher_subtype", - "fieldtype": "Data", - "width": 180, - }, - { - "label": _("Voucher No"), - "fieldname": "voucher_no", - "fieldtype": "Dynamic Link", - "options": "voucher_type", - "width": 180, - }, - {"label": _("Against Account"), "fieldname": "against", "width": 120}, - {"label": _("Party Type"), "fieldname": "party_type", "width": 100}, - {"label": _("Party"), "fieldname": "party", "width": 100}, - ] - - supplier_master_name = frappe.db.get_single_value("Buying Settings", "supp_master_name") - customer_master_name = frappe.db.get_single_value("Selling Settings", "cust_master_name") - - if supplier_master_name != "Supplier Name" or customer_master_name != "Customer Name": - columns.append( - { - "label": _("Party Name"), - "fieldname": "party_name", - "fieldtype": "Data", - "width": 150, - } - ) - - if filters.get("include_dimensions"): - columns.append({"label": _("Project"), "options": "Project", "fieldname": "project", "width": 100}) - - for dim in get_accounting_dimensions(as_list=False): - columns.append( - {"label": _(dim.label), "options": dim.label, "fieldname": dim.fieldname, "width": 100} - ) - columns.append( - {"label": _("Cost Center"), "options": "Cost Center", "fieldname": "cost_center", "width": 100} - ) - - columns.extend( - [ - {"label": _("Against Voucher Type"), "fieldname": "against_voucher_type", "width": 100}, - { - "label": _("Against Voucher"), - "fieldname": "against_voucher", - "fieldtype": "Dynamic Link", - "options": "against_voucher_type", - "width": 100, - }, - {"label": _("Supplier Invoice No"), "fieldname": "bill_no", "fieldtype": "Data", "width": 100}, - ] - ) - - if filters.get("show_remarks"): - columns.extend([{"label": _("Remarks"), "fieldname": "remarks", "width": 400}]) - - return columns + if filters.get("presentation_currency"): + currency = filters["presentation_currency"] + else: + company = filters.get("company") or get_default_company() + filters["presentation_currency"] = currency = get_company_currency(company) + + company_currency = get_company_currency(filters.get("company") or get_default_company()) + + if ( + filters.get("show_amount_in_company_currency") + and filters["presentation_currency"] != company_currency + ): + frappe.throw( + _( + f'Presentation Currency cannot be {frappe.bold(filters["presentation_currency"])} , When {frappe.bold("Show Credit / Debit in Company Currency")} is enabled.' + ) + ) + + columns = [ + { + "label": _("GL Entry"), + "fieldname": "gl_entry", + "fieldtype": "Link", + "options": "GL Entry", + "hidden": 1, + }, + {"label": _("Posting Date"), "fieldname": "posting_date", "fieldtype": "Date", "width": 100}, + { + "label": _("Account"), + "fieldname": "account", + "fieldtype": "Link", + "options": "Account", + "width": 180, + }, + { + "label": _("Debit ({0})").format(currency), + "fieldname": "debit", + "fieldtype": "Currency", + "options": "presentation_currency", + "width": 130, + }, + { + "label": _("Credit ({0})").format(currency), + "fieldname": "credit", + "fieldtype": "Currency", + "options": "presentation_currency", + "width": 130, + }, + { + "label": _("Balance ({0})").format(currency), + "fieldname": "balance", + "fieldtype": "Currency", + "options": "presentation_currency", + "width": 130, + }, + ] + + if filters.get("add_values_in_transaction_currency"): + columns += [ + { + "label": _("Debit (Transaction)"), + "fieldname": "debit_in_transaction_currency", + "fieldtype": "Currency", + "width": 130, + "options": "transaction_currency", + }, + { + "label": _("Credit (Transaction)"), + "fieldname": "credit_in_transaction_currency", + "fieldtype": "Currency", + "width": 130, + "options": "transaction_currency", + }, + { + "label": "Transaction Currency", + "fieldname": "transaction_currency", + "fieldtype": "Link", + "options": "Currency", + "width": 70, + }, + ] + + columns += [ + {"label": _("Voucher Type"), "fieldname": "voucher_type", "width": 120}, + { + "label": _("Voucher Subtype"), + "fieldname": "voucher_subtype", + "fieldtype": "Data", + "width": 180, + }, + { + "label": _("Voucher No"), + "fieldname": "voucher_no", + "fieldtype": "Dynamic Link", + "options": "voucher_type", + "width": 180, + }, + {"label": _("Against Account"), "fieldname": "against", "width": 120}, + {"label": _("Party Type"), "fieldname": "party_type", "width": 100}, + {"label": _("Party"), "fieldname": "party", "width": 100}, + ] + + supplier_master_name = frappe.db.get_single_value("Buying Settings", "supp_master_name") + customer_master_name = frappe.db.get_single_value("Selling Settings", "cust_master_name") + + if supplier_master_name != "Supplier Name" or customer_master_name != "Customer Name": + columns.append( + { + "label": _("Party Name"), + "fieldname": "party_name", + "fieldtype": "Data", + "width": 150, + } + ) + + if filters.get("include_dimensions"): + columns.append({"label": _("Project"), "options": "Project", "fieldname": "project", "width": 100}) + + for dim in get_accounting_dimensions(as_list=False): + columns.append( + {"label": _(dim.label), "options": dim.label, "fieldname": dim.fieldname, "width": 100} + ) + columns.append( + {"label": _("Cost Center"), "options": "Cost Center", "fieldname": "cost_center", "width": 100} + ) + + columns.extend( + [ + {"label": _("Against Voucher Type"), "fieldname": "against_voucher_type", "width": 100}, + { + "label": _("Against Voucher"), + "fieldname": "against_voucher", + "fieldtype": "Dynamic Link", + "options": "against_voucher_type", + "width": 100, + }, + {"label": _("Supplier Invoice No"), "fieldname": "bill_no", "fieldtype": "Data", "width": 100}, + ] + ) + + if filters.get("show_remarks"): + columns.extend([{"label": _("Remarks"), "fieldname": "remarks", "width": 400}]) + + return columns def get_account_root_type_map(company): - """Returns a dictionary mapping each account to its root_type.""" - return frappe._dict( - frappe.get_all("Account", fields=["name", "root_type"], filters={"company": company}, as_list=1) - ) \ No newline at end of file + """Returns a dictionary mapping each account to its root_type.""" + return frappe._dict( + frappe.get_all("Account", fields=["name", "root_type"], filters={"company": company}, as_list=1) + ) \ No newline at end of file From cf518a7147596cdb745a99e5e187011fb3e61263 Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Fri, 12 Sep 2025 09:58:35 +0000 Subject: [PATCH 08/52] fix: file permissions --- rohit_common/fixtures/custom_docperm.json | 50 +++++++++++++++++++++++ rohit_common/hooks.py | 15 ++++++- 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 rohit_common/fixtures/custom_docperm.json diff --git a/rohit_common/fixtures/custom_docperm.json b/rohit_common/fixtures/custom_docperm.json new file mode 100644 index 0000000..6e059b8 --- /dev/null +++ b/rohit_common/fixtures/custom_docperm.json @@ -0,0 +1,50 @@ +[ + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 0, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 0, + "export": 1, + "if_owner": 1, + "import": 0, + "modified": "2025-09-10 17:02:02.310659", + "name": "5ba2783e5e", + "parent": "File", + "permlevel": 0, + "print": 0, + "read": 1, + "report": 0, + "role": "All", + "select": 0, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 0, + "if_owner": 0, + "import": 0, + "modified": "2025-09-10 17:02:00.837323", + "name": "f5341bed97", + "parent": "File", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "select": 0, + "share": 1, + "submit": 0, + "write": 1 + } +] \ No newline at end of file diff --git a/rohit_common/hooks.py b/rohit_common/hooks.py index e341a3f..052a7d8 100644 --- a/rohit_common/hooks.py +++ b/rohit_common/hooks.py @@ -13,7 +13,20 @@ hide_in_installer = True # Fixtures help https://frappeframework.com/docs/v13/user/en/python-api/hooks#fixtures -fixtures = [] +fixtures = [ + { + "doctype": "Custom DocPerm", + "filters": [ + [ + "parent", + "in", + [ + "File" + ], + ] + ], + }, +] override_whitelisted_methods = { # Below mentod would also take into account the search fields # mentioned in the Customize form view From fb1b30fac4620bcccf3835a92b8e795232cf5091 Mon Sep 17 00:00:00 2001 From: Devansh Shetty Date: Mon, 15 Sep 2025 14:25:40 +0000 Subject: [PATCH 09/52] fix: create_asset_depreciation_schedules_from_assets override the patch --- rohit_common/__init__.py | 7 +++++++ rohit_common/before_migrate_patches.py | 6 +++--- .../patches/asset_depr_schedule_patch_utils.py | 15 +++++++++++++++ rohit_common/rohit_common/validations/asset.py | 4 ++-- 4 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 rohit_common/patches/asset_depr_schedule_patch_utils.py diff --git a/rohit_common/__init__.py b/rohit_common/__init__.py index d5793af..0bb3cca 100644 --- a/rohit_common/__init__.py +++ b/rohit_common/__init__.py @@ -1 +1,8 @@ __version__ = "15.0.0" + +# Monkey-patch AssetDepreciationSchedule to add set_draft_asset_depr_schedule_details + +from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import AssetDepreciationSchedule +from rohit_common.patches.asset_depr_schedule_patch_utils import set_draft_asset_depr_schedule_details +AssetDepreciationSchedule.set_draft_asset_depr_schedule_details = set_draft_asset_depr_schedule_details + diff --git a/rohit_common/before_migrate_patches.py b/rohit_common/before_migrate_patches.py index 57f158e..b001204 100644 --- a/rohit_common/before_migrate_patches.py +++ b/rohit_common/before_migrate_patches.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- + import frappe import erpnext - def execute (): add_default_company_fy() @@ -10,8 +10,8 @@ def add_default_company_fy(): fyd = frappe.db.get_list('Fiscal Year', fields=['name'], order_by='year_start_date asc') def_comp = erpnext.get_default_company() for fy in fyd: - fyc = frappe.db.get_list("Fiscal Year Company", filters={"parent": fy.name, - "parentfield": "companies", + fyc = frappe.db.get_list("Fiscal Year Company", filters={"parent": fy.name, + "parentfield": "companies", "parenttype": "Fiscal Year"}) if not fyc: print(f"No Company defined for FY {fy.name} so setting to Default Company {def_comp}") diff --git a/rohit_common/patches/asset_depr_schedule_patch_utils.py b/rohit_common/patches/asset_depr_schedule_patch_utils.py new file mode 100644 index 0000000..c6d8ae4 --- /dev/null +++ b/rohit_common/patches/asset_depr_schedule_patch_utils.py @@ -0,0 +1,15 @@ +def set_draft_asset_depr_schedule_details(self, asset_doc, row): + self.asset = asset_doc.name + self.finance_book = row.finance_book + self.finance_book_id = row.idx + self.opening_accumulated_depreciation = asset_doc.opening_accumulated_depreciation or 0 + self.opening_number_of_booked_depreciations = asset_doc.opening_number_of_booked_depreciations or 0 + self.gross_purchase_amount = asset_doc.gross_purchase_amount + self.depreciation_method = row.depreciation_method + self.total_number_of_depreciations = row.total_number_of_depreciations + self.frequency_of_depreciation = row.frequency_of_depreciation + self.rate_of_depreciation = row.rate_of_depreciation + self.expected_value_after_useful_life = row.expected_value_after_useful_life + self.daily_prorata_based = row.daily_prorata_based + self.shift_based = row.shift_based + self.status = "Draft" \ No newline at end of file diff --git a/rohit_common/rohit_common/validations/asset.py b/rohit_common/rohit_common/validations/asset.py index 1e2f7b9..460e96f 100644 --- a/rohit_common/rohit_common/validations/asset.py +++ b/rohit_common/rohit_common/validations/asset.py @@ -46,8 +46,8 @@ def validate(doc, method): for d in fb_list: doc.append("finance_books", d) #frappe.throw("Finance Book Entry is Mandatory") - base_dep_date = get_next_dep_date(doc, dep_freq, tot_no_of_deps) - make_dep_schedule(doc, base_dep_date, exp_val_aft_life, dep_freq, tot_no_of_deps) + # base_dep_date = get_next_dep_date(doc, dep_freq, tot_no_of_deps) + # make_dep_schedule(doc, base_dep_date, exp_val_aft_life, dep_freq, tot_no_of_deps) def autoname(doc, method): if doc.get_automatic_name == 1: From 93e423c97d845bf01f6a5bfda3e2eb8b4921258b Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Tue, 16 Sep 2025 11:00:45 +0530 Subject: [PATCH 10/52] fix: general ledger opening balance (#3) * fix: general ledger opening balance * fix: balance * fix: gl entries --- .../rigpl_general_ledger.json | 2 +- .../rigpl_general_ledger.py | 175 +++++++++--------- 2 files changed, 86 insertions(+), 91 deletions(-) diff --git a/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.json b/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.json index 6e8dca9..f83dcde 100644 --- a/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.json +++ b/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.json @@ -11,7 +11,7 @@ "is_standard": "Yes", "letter_head": "RIGB", "letterhead": null, - "modified": "2025-09-03 12:33:05.831760", + "modified": "2025-09-15 23:15:01.954268", "modified_by": "Administrator", "module": "rohit_common", "name": "RIGPL General Ledger", diff --git a/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py b/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py index c0975a3..72ef759 100644 --- a/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py +++ b/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py @@ -226,12 +226,13 @@ def get_gl_entries(filters, accounting_dimensions): def get_conditions(filters): - # Get the start and end dates of the fiscal year based on the 'from_date' filter fy = get_fiscal_year(filters.from_date, company=filters.company) filters.fy_start_date = fy[1] conditions = [] - ignore_is_opening = frappe.get_single_value("Accounts Settings", "ignore_is_opening_check_for_reporting") + + # Fetches transactions ONLY within the date range. Solves file size errors. + conditions.append("posting_date BETWEEN %(from_date)s AND %(to_date)s") if filters.get("account"): filters.account = get_accounts_with_children(filters.account) @@ -281,17 +282,6 @@ def get_conditions(filters): if filters.get("party"): conditions.append("party in %(party)s") - # Always fetch data from the start of the fiscal year to correctly calculate the opening balance. - # The python logic will handle separating the transactions that occurred before the 'from_date'. - if not ignore_is_opening: - conditions.append("(posting_date >= %(fy_start_date)s or is_opening = 'Yes')") - else: - conditions.append("posting_date >= %(fy_start_date)s") - - if not ignore_is_opening: - conditions.append("(posting_date <=%(to_date)s or is_opening = 'Yes')") - else: - conditions.append("posting_date <=%(to_date)s") if filters.get("project"): conditions.append("project in %(project)s") if filters.get("include_default_book_entries"): @@ -329,7 +319,7 @@ def get_conditions(filters): conditions.append(f"{dimension.fieldname} in %({dimension.fieldname})s") else: conditions.append(f"{dimension.fieldname} in %({dimension.fieldname})s") - return "and {}".format(" and ".join(conditions)) if conditions else "" + return " and {}".format(" and ".join(conditions)) if conditions else "" def get_party_name_map(): @@ -475,89 +465,87 @@ def initialize_gle_map(gl_entries, filters): def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map): - data = frappe._dict() - account_root_type_map = frappe._dict( - frappe.get_all("Account", fields=["name", "root_type"], as_list=1) - ) - totals = get_totals_dict() - def update_value_in_dict(data, key, gle): - if key not in data: - data[key] = frappe._dict( - debit=0.0, - credit=0.0, - debit_in_account_currency=0.0, - credit_in_account_currency=0.0, - ) - - data[key].debit += gle.debit - data[key].credit += gle.credit - data[key].debit_in_account_currency += gle.debit_in_account_currency - data[key].credit_in_account_currency += gle.credit_in_account_currency - - if filters.get("show_net_values_in_party_account"): - root_type_for_entry = account_root_type_map.get(gle.account) - if root_type_for_entry in ("Receivable", "Payable"): - net_value = data[key].debit - data[key].credit - net_value_in_account_currency = ( - data[key].debit_in_account_currency - - data[key].credit_in_account_currency - ) - if net_value < 0: - dr_or_cr, rev_dr_or_cr = "credit", "debit" - else: - dr_or_cr, rev_dr_or_cr = "debit", "credit" - data[key][dr_or_cr] = abs(net_value) - data[key][dr_or_cr + "_in_account_currency"] = abs( - net_value_in_account_currency - ) - data[key][rev_dr_or_cr] = 0 - data[key][rev_dr_or_cr + "_in_account_currency"] = 0 - - # Opening from PCV if closed, else from raw GL - is_closed = frappe.db.get_value( - "Company", filters.company, "enable_perpetual_inventory" - ) - - if is_closed: - fy = get_fiscal_year(filters.from_date, as_dict=True) - # Get the previous fiscal year by finding the year for the date right before the current one starts - prev_fy = get_fiscal_year(fy.year_start_date - 1, as_dict=True) - - pcv_filters = { - "company": filters.company, - "voucher_type": "Period Closing Voucher", - "fiscal_year": prev_fy.name, - "is_cancelled": 0, - } - # If report is filtered by account, apply the same to the opening balance query - if filters.get("account"): - pcv_filters["account"] = ("in", filters.account) - - pcv_entries = frappe.db.get_all( - "GL Entry", - filters=pcv_filters, - fields=["debit", "credit", "account", "debit_in_account_currency", "credit_in_account_currency"], - ) - for e in pcv_entries: - update_value_in_dict(totals, "opening", _dict(e)) - update_value_in_dict(totals, "closing", _dict(e)) + # Create a separate set of filters for the opening balance query + opening_filters = filters.copy() + + # Build conditions string for the opening balance query + opening_conditions = [] + for key, value in { + "account": "account in %(account)s", + "party": "party in %(party)s", + "party_type": "party_type=%(party_type)s", + "cost_center": "cost_center in %(cost_center)s", + "project": "project in %(project)s" + }.items(): + if opening_filters.get(key): + opening_conditions.append(value) + + for dim in get_accounting_dimensions(as_list=False): + if not dim.disabled and opening_filters.get(dim.fieldname): + opening_conditions.append(f"{dim.fieldname} in %({dim.fieldname})s") + + opening_conditions_str = " and " + " and ".join(opening_conditions) if opening_conditions else "" + + # Fetch the SUM of all transactions before the report's start date + opening_balance_data = frappe.db.sql(f""" + SELECT + SUM(debit) as debit, + SUM(credit) as credit, + SUM(debit_in_account_currency) as debit_in_account_currency, + SUM(credit_in_account_currency) as credit_in_account_currency + FROM `tabGL Entry` + WHERE company=%(company)s + AND posting_date < %(from_date)s + AND is_cancelled = 0 + {opening_conditions_str} + """, opening_filters, as_dict=1) + + if opening_balance_data and opening_balance_data[0] and opening_balance_data[0].debit is not None: + totals.opening.update(opening_balance_data[0]) + + # Calculate the sum of transactions within the report's date range for the "Total" row + for g in gl_entries: + totals.total.debit += g.debit + totals.total.credit += g.credit + totals.total.debit_in_account_currency += g.debit_in_account_currency + totals.total.credit_in_account_currency += g.credit_in_account_currency + + # --- FINAL CORRECTED LOGIC --- + + # 1. Net the opening balance first for display purposes. This modifies `totals.opening`. + # For company currency + opening_balance = totals.opening.debit - totals.opening.credit + if opening_balance > 0: + totals.opening.debit = opening_balance + totals.opening.credit = 0 else: - for g in gl_entries: - if getdate(g.posting_date) < filters.from_date: - update_value_in_dict(totals, "opening", g) - update_value_in_dict(totals, "closing", g) + totals.opening.credit = abs(opening_balance) + totals.opening.debit = 0 + + # For account currency + opening_balance_ac = totals.opening.debit_in_account_currency - totals.opening.credit_in_account_currency + if opening_balance_ac > 0: + totals.opening.debit_in_account_currency = opening_balance_ac + totals.opening.credit_in_account_currency = 0 + else: + totals.opening.credit_in_account_currency = abs(opening_balance_ac) + totals.opening.debit_in_account_currency = 0 - # Transactions within date range - for g in gl_entries: - if filters.from_date <= getdate(g.posting_date) <= filters.to_date: - update_value_in_dict(totals, "total", g) - update_value_in_dict(totals, "closing", g) + # 2. Now, calculate the closing balance using the (now netted) opening values and the period totals. + # For company currency + totals.closing.debit = totals.opening.debit + totals.total.debit + totals.closing.credit = totals.opening.credit + totals.total.credit + + # For account currency + totals.closing.debit_in_account_currency = totals.opening.debit_in_account_currency + totals.total.debit_in_account_currency + totals.closing.credit_in_account_currency = totals.opening.credit_in_account_currency + totals.total.credit_in_account_currency return totals, gl_entries + def get_account_type_map(company): account_type_map = frappe._dict( frappe.get_all("Account", fields=["name", "account_type"], filters={"company": company}, as_list=1) @@ -598,7 +586,14 @@ def contains_label(s, label): continue if contains_label(acct_text_l, "closing"): - d["balance"] = opening_balance + (total_debit - total_credit) + # The closing balance must be the sum of the opening balance and the net of period transactions. + if opening_balance is not None: + d["balance"] = opening_balance + (total_debit - total_credit) + else: + # Fallback for cases where there's no opening balance + d["balance"] = total_debit - total_credit + + # Reset for next group if any balance = 0.0 opening_balance = None total_debit = 0.0 From 4732184abb65b0691a56d09afa0e92d579a8a9e2 Mon Sep 17 00:00:00 2001 From: Devansh Shetty Date: Wed, 17 Sep 2025 05:37:38 +0000 Subject: [PATCH 11/52] feat: update gst settings --- .../gst_return_status/gst_return_status.py | 9 +- .../rohit_settings/rohit_settings.json | 20 +++- .../rohit_common/india_gst_api/common.py | 95 ++++++++++++++++++- .../india_gst_api/gst_public_api.py | 44 ++++++++- 4 files changed, 153 insertions(+), 15 deletions(-) diff --git a/rohit_common/rohit_common/doctype/gst_return_status/gst_return_status.py b/rohit_common/rohit_common/doctype/gst_return_status/gst_return_status.py index 12beee4..f4da4cd 100644 --- a/rohit_common/rohit_common/doctype/gst_return_status/gst_return_status.py +++ b/rohit_common/rohit_common/doctype/gst_return_status/gst_return_status.py @@ -23,17 +23,16 @@ def get_return_status(self): frappe.throw('Selected FY {} is before the GST Era'.format(tup[0])) elif tup[1] > today.date(): frappe.throw('Selected FY {} has not Even Started'.format(tup[0])) + # try: response = track_return(self.gstin, self.fiscal_year) + # except Exception as e: + frappe.throw(f"Error in GST API session or DSC: {str(response)}") efiled_list = response.get('EFiledlist') - # frappe.throw(str(efiled_list)) if efiled_list: self.json_reply = str(efiled_list) for d in efiled_list: temp_dict = frappe._dict({}) - if d.get('valid') == 'Y': - temp_dict['valid_gst_return'] = 'Yes' - else: - temp_dict['valid_gst_return'] = 'No' + temp_dict['valid_gst_return'] = 'Yes' if d.get('valid') == 'Y' else 'No' temp_dict['mode_of_filing'] = d.get('mof') temp_dict['date_of_filing'] = (datetime.strptime(d.get('dof'), '%d-%m-%Y')).date() temp_dict['return_period'] = d.get('ret_prd') diff --git a/rohit_common/rohit_common/doctype/rohit_settings/rohit_settings.json b/rohit_common/rohit_common/doctype/rohit_settings/rohit_settings.json index 8d8a240..998602f 100644 --- a/rohit_common/rohit_common/doctype/rohit_settings/rohit_settings.json +++ b/rohit_common/rohit_common/doctype/rohit_settings/rohit_settings.json @@ -1,10 +1,13 @@ { + "actions": [], "creation": "2020-09-23 15:55:42.979487", "doctype": "DocType", "editable_grid": 1, "engine": "InnoDB", "field_order": [ "sb0", + "dsc_pfx_path", + "dsc_password", "tax_pro_asp_id", "tax_pro_password", "gstin", @@ -51,6 +54,16 @@ "fieldtype": "Section Break", "label": "Tax Pro GSP" }, + { + "fieldname": "dsc_pfx_path", + "fieldtype": "Attach", + "label": "DSC PFX File Path" + }, + { + "fieldname": "dsc_password", + "fieldtype": "Data", + "label": "DSC Password" + }, { "fieldname": "tax_pro_asp_id", "fieldtype": "Data", @@ -269,7 +282,8 @@ } ], "issingle": 1, - "modified": "2022-08-08 09:37:52.222305", + "links": [], + "modified": "2025-09-16 12:33:40.529343", "modified_by": "Administrator", "module": "rohit_common", "name": "Rohit Settings", @@ -287,7 +301,9 @@ } ], "quick_entry": 1, + "row_format": "Dynamic", "sort_field": "modified", "sort_order": "DESC", + "states": [], "track_changes": 1 -} \ No newline at end of file +} diff --git a/rohit_common/rohit_common/india_gst_api/common.py b/rohit_common/rohit_common/india_gst_api/common.py index 09f9e4d..3776419 100644 --- a/rohit_common/rohit_common/india_gst_api/common.py +++ b/rohit_common/rohit_common/india_gst_api/common.py @@ -4,6 +4,11 @@ import frappe from datetime import datetime from frappe.utils import flt, get_last_day, getdate +import base64 +import requests +from cryptography.hazmat.primitives.serialization import pkcs12 +from cryptography.hazmat.primitives.asymmetric import padding as asym_padding +from cryptography.hazmat.primitives import hashes def get_place_of_supply(dtype, dname): @@ -154,14 +159,33 @@ def get_gsp_details(api, action, gstin=None, api_type=None): sandbox = rset.sandbox_mode gsp_link = rset.api_link asp_id = rset.tax_pro_asp_id - asp_pass = rset.tax_pro_password + asp_pass = rset.tax_pro_asp_secret + dsc_pfx_path = get_file_full_path(getattr(rset, 'dsc_pfx_path', None)) + dsc_password = getattr(rset, 'dsc_password', None) + if not dsc_pfx_path or not dsc_password: + frappe.throw("DSC PFX path or password not set in Rohit Settings") + txn_id = str(datetime.now().timestamp()).replace('.', '') + ip_usr = "127.0.0.1" # or fetch from settings if needed + result = call_getkey_api( + aspid=asp_id, + asp_password=asp_pass, + txn=txn_id, + pfx_file=dsc_pfx_path, + dsc_password=dsc_password, + ip_usr=ip_usr, + sandbox=sandbox + ) + session_id = result.get("asp_session_id") + asp_ek = result.get("enc_key") + # frappe.throw(f"Debug Info: {result}") + if not session_id: + frappe.throw(f"Session ID could not be generated: {result.get('error', 'Unknown error')}") if api == 'eway': gsp_link = gsp_link[:8] + "einvapi." + gsp_link[8:] else: gsp_link = gsp_link[:8] + "gstapi." + gsp_link[8:] - if not gstin: if api_type == 'common': gstin = rset.gstin @@ -180,9 +204,17 @@ def get_gsp_details(api, action, gstin=None, api_type=None): gsp_link = gsp_sandbox_link if api_type == 'common': gsp_link = gsp_link + api_url + 'aspid=' + asp_id + '&password=' + asp_pass + '&Action=' + action + print(gsp_link, asp_id, asp_pass, gstin, sandbox, session_id, asp_ek) + # frappe.throw(f"Debug Info: {gsp_link}, {asp_id}, {asp_pass}, {gstin}, {sandbox}, {session_id}, {asp_ek}") + # gsp_link, asp_id, asp_pass, caller_gstin, sandbox, session_id, asp_ek + return gsp_link, asp_id, asp_pass, gstin, sandbox, session_id, asp_ek - return gsp_link, asp_id, asp_pass, gstin, sandbox +def get_file_full_path(file): + if "private" not in file: + return frappe.get_site_path() + "/public" + file # noqa: 501 + else: + return frappe.get_site_path() + file def gst_return_period_validation(return_period): month = flt(return_period[:2]) @@ -215,3 +247,60 @@ def get_dates_from_return_period(monthly_ret_pd): def validate_gstin(gstin): if len(gstin) != 15: frappe.throw(f"GST Number: {gstin} Should be of 15 Characters") + +def call_getkey_api(aspid, asp_password, txn, pfx_file, dsc_password, ip_usr, sandbox): + """ + Calls the GST GSP GetKey API to generate session_id using DSC. + Returns a dict with asp_session_id and enc_key (and error if any). + """ + # Load DSC and sign content + try: + with open(pfx_file, 'rb') as f: + pfx_data = f.read() + private_key, certificate, _ = pkcs12.load_key_and_certificates( + pfx_data, + password=dsc_password.encode() if dsc_password else None + ) + if certificate is None or private_key is None: + return {"error": "Certificate not found"} + subject = certificate.subject.rfc4514_string() + if not any(attr.startswith("OU=GST") for attr in subject.split(',')): + return {"error": "Certificate not found"} + timestamp = datetime.now().strftime("%d%m%Y%H%M%S%f")[:20] + content_to_sign = aspid + timestamp + signature = private_key.sign( + content_to_sign.encode("utf-8"), + asym_padding.PKCS1v15(), + hashes.SHA256() + ) + signed_content = base64.b64encode(signature).decode('utf-8') + except Exception as e: + return {"error": str(e)} + + url = "https://gstsandbox.charteredinfo.com/aspapi/v1.0/getKey" if sandbox else "https://gstapi.charteredinfo.com/aspapi/v1.0/getKey" + headers = { + "aspid": aspid, + "txn": txn, + "Content-Type": "application/json; charset=utf-8", + "ip-usr": ip_usr + } + payload = { + "timestamp": timestamp, + "signed_content": signed_content + } + try: + response = requests.post(url, json=payload, headers=headers, timeout=15) + if response.status_code != 200: + return {"error": f"HTTP {response.status_code}", "details": response.text} + data = response.json() + if data.get("status_cd") != "1": + return {"error": "API call failed", "message": data.get("message")} + return { + "asp_session_id": data.get("session_id"), + "enc_key": data.get("enc_key"), + "validity_min": data.get("validity_min"), + "txn": data.get("txn"), + "raw_response": data + } + except Exception as e: + return {"error": str(e)} \ No newline at end of file diff --git a/rohit_common/rohit_common/india_gst_api/gst_public_api.py b/rohit_common/rohit_common/india_gst_api/gst_public_api.py index 07480e1..ce2ef26 100644 --- a/rohit_common/rohit_common/india_gst_api/gst_public_api.py +++ b/rohit_common/rohit_common/india_gst_api/gst_public_api.py @@ -23,18 +23,52 @@ def search_gstin(gstin=None): def track_return(gstin, fiscal_year, type_of_return=None): + # Debug logging for asp_secret value + # Debug logging for encryption diagnostics (mask sensitive info) # (fiscal_year, start_date, end_date) = get_fiscal_year(for_date) fy_format = fiscal_year[:5] + fiscal_year[7:] - gsp_link, asp_id, asp_pass, caller_gstin, sandbox = get_gsp_details(api_type="common", action='RETTRACK', - api="returns") + gsp_link, asp_id, asp_pass, caller_gstin, sandbox, session_id, asp_ek = get_gsp_details(api_type="common", action='RETTRACK', api="returns") + print(f"[GSTAPI DEBUG] tax_pro_asp_secret (len={len(asp_pass)}): {asp_pass[:8]}...{asp_pass[-8:]}") + if not session_id: + frappe.throw("Session ID could not be generated. Please check DSC and API credentials.") + # Encrypt asp_pass using AspEK (asp_ek) as per TaxPro GSP requirements + from Crypto.Cipher import AES + from Crypto.Util.Padding import pad + import base64 + + # Decode asp_ek and ensure it's 32 bytes for AES-256 + key_bytes = base64.b64decode(asp_ek) + if len(key_bytes) > 32: + key_bytes = key_bytes[:32] + elif len(key_bytes) < 32: + # Pad key to 32 bytes if needed (shouldn't happen, but for safety) + key_bytes = key_bytes.ljust(32, b'\0') + cipher = AES.new(key_bytes, AES.MODE_ECB) + # Base64 decode asp_pass (Asp Secret Key) before encryption, as per TaxPro GSP sample + payload = base64.b64decode(asp_pass) + padded = pad(payload, AES.block_size) + encrypted = cipher.encrypt(padded) + asp_secret_encrypted = base64.b64encode(encrypted).decode('utf-8') + print(f"[GSTAPI DEBUG] asp_ek (len={len(asp_ek)}): {asp_ek[:8]}...{asp_ek[-8:]}") + print(f"[GSTAPI DEBUG] asp_pass (len={len(asp_pass)}): {asp_pass[:2]}...{asp_pass[-2:]}") + print(f"[GSTAPI DEBUG] asp_secret_encrypted (len={len(asp_secret_encrypted)}): {asp_secret_encrypted[:8]}...{asp_secret_encrypted[-8:]}") + if type_of_return: full_url = gsp_link + '&Gstin=' + gstin + '&FY=' + fy_format + '&type=' + type_of_return else: full_url = gsp_link + '&Gstin=' + gstin + '&FY=' + fy_format - response = requests.get(url=full_url, timeout=timeout) - # frappe.throw(str(response.text)) + headers = { + "Content-Type": "application/json", + "Accept": "application/json", + "asp-secret": asp_secret_encrypted, + "session-id": session_id, + "aspid": asp_id, + "txn": str(datetime.datetime.now().timestamp()).replace('.', ''), + "GSTIN": gstin , + "ip-usr": "127.0.0.1" + } + response = requests.get(url=full_url, headers=headers, timeout=timeout) json_response = response.json() - # frappe.throw(str(json_response)) return json_response From 8995c4e9bd94a7871aabc0d0e249a87d6c365e6d Mon Sep 17 00:00:00 2001 From: Devansh Shetty Date: Wed, 17 Sep 2025 09:08:47 +0000 Subject: [PATCH 12/52] feat: add running unwanted patch --- rohit_common/before_migrate_patches.py | 2 + rohit_common/patches/run_unwanted_patches.py | 119 +++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 rohit_common/patches/run_unwanted_patches.py diff --git a/rohit_common/before_migrate_patches.py b/rohit_common/before_migrate_patches.py index b001204..ba30312 100644 --- a/rohit_common/before_migrate_patches.py +++ b/rohit_common/before_migrate_patches.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- +from rohit_common.patches.run_unwanted_patches import run_unwanted_patches import frappe import erpnext def execute (): + run_unwanted_patches() add_default_company_fy() def add_default_company_fy(): diff --git a/rohit_common/patches/run_unwanted_patches.py b/rohit_common/patches/run_unwanted_patches.py new file mode 100644 index 0000000..55fe417 --- /dev/null +++ b/rohit_common/patches/run_unwanted_patches.py @@ -0,0 +1,119 @@ +import frappe + +def run_unwanted_patches(): + if not frappe.db.exists("Patch Log", {"patch": "frappe.patches.v16.running_unwanted_patches"}): + #frappe + set_route_for_blog_category() + set_read_times() + update_icons_in_customized_desk_pages() + rename_desk_page_to_workspace() + setup_likes_from_feedback() + + #erpnext + update_is_cancelled_field() + change_is_subcontracted_fieldtype() + rename_account_type_doctype() + execute_rename_desk_page() + replace_pos_page_with_point_of_sale_page() + print_uom_after_quantity_patch() + update_member_email_address() + clear_reconciliation_values_from_singles() + execute_rename_tds_report() + + running_unwanted_patches() +def running_unwanted_patches(): + frappe.get_doc({ + 'doctype': 'Patch Log', + 'patch': 'frappe.patches.v16.running_unwanted_patches', + }).insert(ignore_permissions=True) + frappe.db.commit() +def setup_likes_from_feedback(): + frappe.get_doc({ + 'doctype': 'Patch Log', + 'patch': 'frappe.patches.v14_0.setup_likes_from_feedback', + }).insert(ignore_permissions=True) + frappe.db.commit() + +def rename_desk_page_to_workspace(): + frappe.get_doc({ + 'doctype': 'Patch Log', + 'patch': 'frappe.patches.v13_0.rename_desk_page_to_workspace # 02.02.2021', + }).insert(ignore_permissions=True) + frappe.db.commit() +def update_icons_in_customized_desk_pages(): + frappe.get_doc({ + 'doctype': 'Patch Log', + 'patch': 'frappe.patches.v13_0.update_icons_in_customized_desk_pages', + }).insert(ignore_permissions=True) + frappe.db.commit() + +def set_route_for_blog_category(): + frappe.get_doc({ + 'doctype': 'Patch Log', + 'patch': 'frappe.patches.v13_0.set_route_for_blog_category', + }).insert(ignore_permissions=True) + frappe.db.commit() + +def set_read_times(): + frappe.get_doc({ + 'doctype': 'Patch Log', + 'patch': 'frappe.patches.v13_0.set_read_times', + }).insert(ignore_permissions=True) + frappe.db.commit() +def update_is_cancelled_field(): + frappe.get_doc({ + 'doctype': 'Patch Log', + 'patch': 'erpnext.patches.v12_0.update_is_cancelled_field', + }).insert(ignore_permissions=True) + frappe.db.commit() +def change_is_subcontracted_fieldtype(): + frappe.get_doc({ + 'doctype': 'Patch Log', + 'patch': 'erpnext.patches.v14_0.change_is_subcontracted_fieldtype', + }).insert(ignore_permissions=True) + frappe.db.commit() +def rename_account_type_doctype(): + frappe.get_doc({ + 'doctype': 'Patch Log', + 'patch': 'erpnext.patches.v12_0.rename_account_type_doctype', + }).insert(ignore_permissions=True) + frappe.db.commit() + +def execute_rename_desk_page(): + frappe.get_doc({ + 'doctype': 'Patch Log', + 'patch': 'execute:frappe.rename_doc("Desk Page", "Getting Started", "Home", force=True)', + }).insert(ignore_permissions=True) + frappe.db.commit() + +def replace_pos_page_with_point_of_sale_page(): + frappe.get_doc({ + 'doctype': 'Patch Log', + 'patch': 'erpnext.patches.v13_0.replace_pos_page_with_point_of_sale_page', + }).insert(ignore_permissions=True) + frappe.db.commit() + +def print_uom_after_quantity_patch(): + frappe.get_doc({ + 'doctype': 'Patch Log', + 'patch': 'erpnext.patches.v13_0.print_uom_after_quantity_patch', + }).insert(ignore_permissions=True) + frappe.db.commit() +def update_member_email_address(): + frappe.get_doc({ + 'doctype': 'Patch Log', + 'patch': 'erpnext.patches.v13_0.update_member_email_address', + }).insert(ignore_permissions=True) + frappe.db.commit() +def clear_reconciliation_values_from_singles(): + frappe.get_doc({ + 'doctype': 'Patch Log', + 'patch': 'erpnext.patches.v14_0.clear_reconciliation_values_from_singles', + }).insert(ignore_permissions=True) + frappe.db.commit() +def execute_rename_tds_report(): + frappe.get_doc({ + 'doctype': 'Patch Log', + 'patch': 'execute:frappe.rename_doc("Report", "TDS Payable Monthly", "Tax Withholding Details", force=True)', + }).insert(ignore_permissions=True) + frappe.db.commit() From 70545a7928997921866fafaed9c647ef9ebbf3bd Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Wed, 17 Sep 2025 11:47:29 +0000 Subject: [PATCH 13/52] fix: method to populate payment ledger entry --- rohit_common/custom_method.py | 40 +++++++++++++++++++ .../rigpl_general_ledger.py | 2 - 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 rohit_common/custom_method.py diff --git a/rohit_common/custom_method.py b/rohit_common/custom_method.py new file mode 100644 index 0000000..4fa3df7 --- /dev/null +++ b/rohit_common/custom_method.py @@ -0,0 +1,40 @@ +from erpnext.accounts.utils import create_payment_ledger_entry +import frappe + +# from erpnext.accounts.payment_ledger import create_payment_ledger_entry + +def backfill_payment_ledger(batch_size=500): + """ + Rebuild Payment Ledger Entries (PLEs) from GL Entries for all submitted vouchers. + """ + + doctypes = ["Sales Invoice", "Purchase Invoice", "Payment Entry", "Journal Entry"] + + for doctype in doctypes: + names = frappe.get_all(doctype, filters={"docstatus": 1}, pluck="name") + total = len(names) + print(f"\n>>> Processing {doctype}: {total} documents") + + created_count = 0 + error_count = 0 + + for i in range(0, total, batch_size): + batch = names[i:i+batch_size] + for name in batch: + try: + doc = frappe.get_doc(doctype, name) + if hasattr(doc, "get_gl_entries"): + gl_entries = doc.get_gl_entries() + if gl_entries: + create_payment_ledger_entry(gl_entries) + created_count += 1 + except Exception: + error_count += 1 + frappe.log_error( + title=f"PLE Backfill Failed for {doctype} {name}", + message=frappe.get_traceback() + ) + frappe.db.commit() + print(f" ✔ Batch {(i//batch_size)+1}: processed {len(batch)} docs") + + print(f"✓ Done {doctype}: {created_count} created, {error_count} errors") \ No newline at end of file diff --git a/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py b/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py index 72ef759..ae0ee04 100644 --- a/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py +++ b/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py @@ -512,8 +512,6 @@ def get_accountwise_gle(filters, accounting_dimensions, gl_entries, gle_map): totals.total.debit_in_account_currency += g.debit_in_account_currency totals.total.credit_in_account_currency += g.credit_in_account_currency - # --- FINAL CORRECTED LOGIC --- - # 1. Net the opening balance first for display purposes. This modifies `totals.opening`. # For company currency opening_balance = totals.opening.debit - totals.opening.credit From 098faa6ba693f3087589313367b5d6c0276172a5 Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Thu, 18 Sep 2025 08:46:05 +0000 Subject: [PATCH 14/52] fix: file query if shared --- rohit_common/core/file.py | 42 +++++++++++++++++++++-- rohit_common/fixtures/custom_docperm.json | 28 +++++++-------- rohit_common/hooks.py | 4 +++ 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/rohit_common/core/file.py b/rohit_common/core/file.py index 45ab929..1de6702 100644 --- a/rohit_common/core/file.py +++ b/rohit_common/core/file.py @@ -6,6 +6,7 @@ import os import frappe from shutil import copyfile, move +from frappe.permissions import SYSTEM_USER_ROLE, get_doctypes_with_read from frappe.share import get_share_name from frappe.utils import get_site_base_path, cstr from frappe.core.doctype.file.file import File, get_content_hash @@ -32,8 +33,8 @@ def custom_file_permissions(doc, ptype=None, user=None): if shd_name: shd = frappe.get_doc("DocShare", shd_name) if shd.write or shd.share or shd.submit: - return "write" - return "read" + return True + return True # Creating a new file if ptype == "create": @@ -51,7 +52,7 @@ def custom_file_permissions(doc, ptype=None, user=None): has_access = ref_doc.has_permission("write") if ptype == "delete" and not has_access: frappe.throw( - _( + ( f"Cannot delete file as it belongs to {frappe.get_desk_link(doc.attached_to_doctype, doc.attached_to_name)} for which you do not have permissions" ), frappe.PermissionError, @@ -65,6 +66,41 @@ def custom_file_permissions(doc, ptype=None, user=None): return has_access +def custom_get_permission_query_conditions(user: str | None = None) -> str: + user = user or frappe.session.user + + if user == "Administrator": + return "" + + if SYSTEM_USER_ROLE not in frappe.get_roles(user): + # Basic user: return only own files or shared + return f""" + `tabFile`.`owner` = {frappe.db.escape(user)} + OR EXISTS ( + SELECT 1 FROM `tabDocShare` + WHERE + `tabDocShare`.share_doctype = 'File' + AND `tabDocShare`.share_name = `tabFile`.name + AND `tabDocShare`.user = {frappe.db.escape(user)} + AND `tabDocShare`.read = 1 + ) + """ + + # For system users, include additional readable doctypes and shares + readable_doctypes = ", ".join(repr(dt) for dt in get_doctypes_with_read()) + return f""" + (`tabFile`.`is_private` = 0) + OR (`tabFile`.`attached_to_doctype` IS NULL AND `tabFile`.`owner` = {frappe.db.escape(user)}) + OR (`tabFile`.`attached_to_doctype` IN ({readable_doctypes})) + OR EXISTS ( + SELECT 1 FROM `tabDocShare` + WHERE + `tabDocShare`.share_doctype = 'File' + AND `tabDocShare`.share_name = `tabFile`.name + AND `tabDocShare`.user = {frappe.db.escape(user)} + AND `tabDocShare`.read = 1 + ) + """ @frappe.whitelist() def get_files_by_search_text(text): diff --git a/rohit_common/fixtures/custom_docperm.json b/rohit_common/fixtures/custom_docperm.json index 6e059b8..bd982fa 100644 --- a/rohit_common/fixtures/custom_docperm.json +++ b/rohit_common/fixtures/custom_docperm.json @@ -3,21 +3,21 @@ "amend": 0, "cancel": 0, "create": 1, - "delete": 0, + "delete": 1, "docstatus": 0, "doctype": "Custom DocPerm", - "email": 0, - "export": 1, - "if_owner": 1, + "email": 1, + "export": 0, + "if_owner": 0, "import": 0, - "modified": "2025-09-10 17:02:02.310659", - "name": "5ba2783e5e", + "modified": "2025-09-18 12:27:05.391678", + "name": "f5341bed97", "parent": "File", "permlevel": 0, - "print": 0, + "print": 1, "read": 1, - "report": 0, - "role": "All", + "report": 1, + "role": "System Manager", "select": 0, "share": 1, "submit": 0, @@ -32,16 +32,16 @@ "doctype": "Custom DocPerm", "email": 1, "export": 0, - "if_owner": 0, + "if_owner": 1, "import": 0, - "modified": "2025-09-10 17:02:00.837323", - "name": "f5341bed97", + "modified": "2025-09-18 13:44:58.502414", + "name": "gi0c6fbkum", "parent": "File", "permlevel": 0, "print": 1, "read": 1, - "report": 1, - "role": "System Manager", + "report": 0, + "role": "All", "select": 0, "share": 1, "submit": 0, diff --git a/rohit_common/hooks.py b/rohit_common/hooks.py index 052a7d8..9ae0e3b 100644 --- a/rohit_common/hooks.py +++ b/rohit_common/hooks.py @@ -80,6 +80,10 @@ "File": "rohit_common.core.file.custom_file_permissions" } +permission_query_conditions = { + "File": "rohit_common.core.file.custom_get_permission_query_conditions", +} + # Javascripts for Standard Documents to Override Forms Script # ----------- doctype_js = { From f935ccc36f787c41a437aece5bb8b0ed6343f2be Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Thu, 18 Sep 2025 17:32:53 +0530 Subject: [PATCH 15/52] feat: monkey patched file permissions for system manager access (#8) --- rohit_common/__init__.py | 6 ++++ rohit_common/core/file.py | 2 +- rohit_common/overrides/file.py | 50 ++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 rohit_common/overrides/file.py diff --git a/rohit_common/__init__.py b/rohit_common/__init__.py index 0bb3cca..381c384 100644 --- a/rohit_common/__init__.py +++ b/rohit_common/__init__.py @@ -3,6 +3,12 @@ # Monkey-patch AssetDepreciationSchedule to add set_draft_asset_depr_schedule_details from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import AssetDepreciationSchedule +import frappe from rohit_common.patches.asset_depr_schedule_patch_utils import set_draft_asset_depr_schedule_details AssetDepreciationSchedule.set_draft_asset_depr_schedule_details = set_draft_asset_depr_schedule_details +# Monkey-patched File to allow System Manager to access all files + +from rohit_common.overrides.file import get_permission_query_conditions,has_permission +frappe.frappe.core.doctype.file.file.has_permission=has_permission +frappe.frappe.core.doctype.file.file.get_permission_query_conditions=get_permission_query_conditions \ No newline at end of file diff --git a/rohit_common/core/file.py b/rohit_common/core/file.py index 1de6702..522c3f8 100644 --- a/rohit_common/core/file.py +++ b/rohit_common/core/file.py @@ -69,7 +69,7 @@ def custom_file_permissions(doc, ptype=None, user=None): def custom_get_permission_query_conditions(user: str | None = None) -> str: user = user or frappe.session.user - if user == "Administrator": + if user == "Administrator" or check_system_manager(user): return "" if SYSTEM_USER_ROLE not in frappe.get_roles(user): diff --git a/rohit_common/overrides/file.py b/rohit_common/overrides/file.py new file mode 100644 index 0000000..1c33759 --- /dev/null +++ b/rohit_common/overrides/file.py @@ -0,0 +1,50 @@ +import frappe +from frappe.permissions import SYSTEM_USER_ROLE, get_doctypes_with_read +from rohit_common.utils.rohit_common_utils import check_system_manager + +def has_permission(doc, ptype=None, user=None, debug=False): + user = user or frappe.session.user + + if user == "Administrator" or check_system_manager(user): + return True + + if not doc.is_private and ptype in ("read", "select"): + return True + + if user != "Guest" and doc.owner == user: + return True + + if doc.attached_to_doctype and doc.attached_to_name: + attached_to_doctype = doc.attached_to_doctype + attached_to_name = doc.attached_to_name + + try: + ref_doc = frappe.get_doc(attached_to_doctype, attached_to_name) + except ModuleNotFoundError: + return False + except frappe.DoesNotExistError: + frappe.clear_last_message() + return False + + if ptype in ["write", "create", "delete"]: + return ref_doc.has_permission("write", debug=debug, user=user) + else: + return ref_doc.has_permission("read", debug=debug, user=user) + + return False + + +def get_permission_query_conditions(user: str | None = None) -> str: + user = user or frappe.session.user + if user == "Administrator" or check_system_manager(user): + return "" + + if SYSTEM_USER_ROLE not in frappe.get_roles(user): + return f""" `tabFile`.`owner` = {frappe.db.escape(user)} """ + + readable_doctypes = ", ".join(repr(dt) for dt in get_doctypes_with_read()) + return f""" + (`tabFile`.`is_private` = 0) + OR (`tabFile`.`attached_to_doctype` IS NULL AND `tabFile`.`owner` = {frappe.db.escape(user)}) + OR (`tabFile`.`attached_to_doctype` IN ({readable_doctypes})) + """ \ No newline at end of file From f1061c176d4b69482bf51b05f86e9e9aa791f94e Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Thu, 18 Sep 2025 19:30:14 +0530 Subject: [PATCH 16/52] feat(docs): added docs related to migration and related issues (#9) * fix: docs * fix: docs * fix: docs --- docs/09-2025.md | 107 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 docs/09-2025.md diff --git a/docs/09-2025.md b/docs/09-2025.md new file mode 100644 index 0000000..e1d753b --- /dev/null +++ b/docs/09-2025.md @@ -0,0 +1,107 @@ +# Migration Notes: V12 → V16 + +## Skipped Steps +- Skipped unnecessary patches (see **before_migrate_patches.py**). +- Reference: [Patch List Spreadsheet](https://docs.google.com/spreadsheets/d/1TUkAwRF6NhEAzFjcM6WAPyT6dEdREkuDl5sANb-eK4o/edit?pli=1&gid=1625746251#gid=1625746251) + +--- + +## Fixed & Pending Issues + +### 1. Sales Invoice (Unable to Save + E-Invoice Issues) +**Status:** Half Resolved +- Removed custom code resetting *place of supply* that caused save failures. + → File: `validations/sales_invoice.py` → Method: `check_local_natl_tax_rules()` +- E-Invoice re-enabled with **India Compliance**. + - Re-setup required for new sites. + - Path: **GST Settings → Enable E-Invoice** (currently sandbox mode). + - Setup Guide: [India Compliance Docs](https://docs.indiacompliance.app/docs/ewaybill-and-einvoice/gst_settings) + +**Pending:** +- Remove full validation (since using India Compliance). +- Add QR Code, Ack No, and Ack Date to E-Invoice. + +--- + +### 2. File List (Search Issues) +**Issue:** Unable to search file names attached to Doctypes. +**Fix:** Corrected hook path & method override. +- Hook: `override_whitelisted_methods` +- Method: `rohit_common.core.file.get_files_by_search_text` + +--- + +### 3. File List (Permission Issues) +**Issue:** System Manager unable to view files not attached to any Doctype. +**Fix:** Overridden Frappe File methods, since Frappe reverses the `has_permission` hooks, causing our hook to run before Frappe’s own. +- Reference: [frappe/permissions.py#L467](https://github.com/frappe/frappe/blob/develop/frappe/permissions.py#L467) +- Custom Code: `overrides/file.py` + `hooks/__init__.py` + +--- + +### 4. GST Return Status +**Status:** Pending +**Issue:** Unable to fetch GST Return Status. +**Plan:** Replace with **India Compliance API**. + +--- + +### 5. Address (GST Validation) +**Status:** Pending +**Issue:** GST API validation not working. +**Plan:** Replace with **India Compliance API**. + +--- + +### 6. GL Report +**Issue:** General Ledger should display only net opening. +**Fix:** Created custom report: **RIGPL General Ledger**. + +--- + +### 7. Asset (Customizations) +**Status:** Fix pushed, under review. + +--- + +### 8. Asset Report (Analysis) +**Status:** Fix pushed, under review. + +--- + +### 9. Contact (Search Fields) +**Issue:** Search not working based on fields defined in Customize Form. +**Status:** Pending check. + +--- + +### 10. Pricing Rule +**Issue:** Sales Orders not fetching rules for Item Group children (worked in V12). +**Action:** Skipped → **Not related to this app**. + +--- + +### 11. Asset Patch Failure +**Fix:** Patch issue resolved. + +--- + +### 12. Sales Invoice (E-Invoice JSON) +**Issue:** Should send only summary of items (not line-wise rates) to GSTIN. +**Status:** Pending check. + +--- + +### 13 & 14. Accounts Receivable (AR) Report +**Issue:** Payment Ledger empty due to skipped patch (introduced in later version). +**Fix:** Added script to backfill payment ledger. +- File: `custom_method.py` +- Method: `backfill_payment_ledger()` + +--- + +## ✅ Summary +- **Resolved:** File List issues, GL Report. +- **In Review:** Asset fixes. +- **Pending:** E-Invoice (QR, Ack fields, JSON summary), GST Return Status, GST Validation, Contact search. +- **Custom Reports/Patches:** Added where native functionality broke. From a19305adbdfea0ca035cd1e38df7ee037a721af2 Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Mon, 22 Sep 2025 14:26:23 +0530 Subject: [PATCH 17/52] fix: gst return status (#10) * fix: gst return status * fix: date format --- .../gst_return_status/gst_return_status.py | 69 +++++++++++-------- .../rohit_common/validations/sales_invoice.py | 4 +- 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/rohit_common/rohit_common/doctype/gst_return_status/gst_return_status.py b/rohit_common/rohit_common/doctype/gst_return_status/gst_return_status.py index f4da4cd..2204347 100644 --- a/rohit_common/rohit_common/doctype/gst_return_status/gst_return_status.py +++ b/rohit_common/rohit_common/doctype/gst_return_status/gst_return_status.py @@ -4,39 +4,48 @@ from __future__ import unicode_literals import frappe -import json from datetime import datetime -from frappe.utils.data import getdate -from ...india_gst_api.gst_public_api import track_return from frappe.model.document import Document from erpnext.accounts.utils import get_fiscal_year +from india_compliance.gst_india.api_classes.public import PublicAPI class GSTReturnStatus(Document): - @frappe.whitelist() - def get_return_status(self): - today = datetime.today() - self.returns = [] - if self.fiscal_year: - tup = get_fiscal_year(fiscal_year=self.fiscal_year) - if tup[1] < datetime.strptime('01-04-2017', '%d-%m-%Y').date(): - frappe.throw('Selected FY {} is before the GST Era'.format(tup[0])) - elif tup[1] > today.date(): - frappe.throw('Selected FY {} has not Even Started'.format(tup[0])) - # try: - response = track_return(self.gstin, self.fiscal_year) - # except Exception as e: - frappe.throw(f"Error in GST API session or DSC: {str(response)}") - efiled_list = response.get('EFiledlist') - if efiled_list: - self.json_reply = str(efiled_list) - for d in efiled_list: - temp_dict = frappe._dict({}) - temp_dict['valid_gst_return'] = 'Yes' if d.get('valid') == 'Y' else 'No' - temp_dict['mode_of_filing'] = d.get('mof') - temp_dict['date_of_filing'] = (datetime.strptime(d.get('dof'), '%d-%m-%Y')).date() - temp_dict['return_period'] = d.get('ret_prd') - temp_dict['return_type'] = d.get('rtntype') - temp_dict['arn_number'] = d.get('arn') - temp_dict['status'] = d.get('status') - self.append("returns", temp_dict.copy()) + @frappe.whitelist() + def get_return_status(self): + today = datetime.today() + self.returns = [] + + if self.fiscal_year: + tup = get_fiscal_year(fiscal_year=self.fiscal_year) + if tup[1] < datetime.strptime('01-04-2017', '%d-%m-%Y').date(): + frappe.throw('Selected FY {} is before the GST Era'.format(tup[0])) + elif tup[1] > today.date(): + frappe.throw('Selected FY {} has not Even Started'.format(tup[0])) + + api = PublicAPI() + fy = format_gst_fy(self.fiscal_year) + response = api.get_returns_info(self.gstin, fy) + + efiled_list = response.get("EFiledlist") or response.get("data") + if efiled_list: + self.json_reply = str(efiled_list) + for d in efiled_list: + temp_dict = frappe._dict({}) + temp_dict['valid_gst_return'] = 'Yes' if d.get('valid') == 'Y' else 'No' + temp_dict['mode_of_filing'] = d.get('mof') + temp_dict['date_of_filing'] = ( + datetime.strptime(d.get('dof'), '%d-%m-%Y') + ).date() if d.get('dof') else None + temp_dict['return_period'] = d.get('ret_prd') + temp_dict['return_type'] = d.get('rtntype') + temp_dict['arn_number'] = d.get('arn') + temp_dict['status'] = d.get('status') + self.append("returns", temp_dict.copy()) + +def format_gst_fy(fy: str) -> str: + """Convert ERPNext fiscal year like '20xx-20xx' to GST format '20xx-xx'.""" + if "-" in fy and len(fy) == 9: # 'YYYY-YYYY' + start, end = fy.split("-") + return f"{start}-{end[-2:]}" + return fy \ No newline at end of file diff --git a/rohit_common/rohit_common/validations/sales_invoice.py b/rohit_common/rohit_common/validations/sales_invoice.py index a434da2..482c307 100644 --- a/rohit_common/rohit_common/validations/sales_invoice.py +++ b/rohit_common/rohit_common/validations/sales_invoice.py @@ -133,7 +133,7 @@ def check_local_natl_tax_rules(doc, template_doc): if bill_state == template_doc.state and template_doc.is_export == 0 and \ template_doc.is_sample != 1: - doc.place_of_supply = template_doc.state + # doc.place_of_supply = template_doc.state if template_doc.is_local_sales != 1: frappe.throw(f"Selected Tax {doc.taxes_and_charges} is NOT LOCAL Tax but Billing \ Address is in Same State {bill_state}, hence either change Billing Address or \ @@ -146,7 +146,7 @@ def check_local_natl_tax_rules(doc, template_doc): is in Different State {bill_state}, hence either change Billing Address or Change \ the Selected Tax") elif ship_country != 'India': # Case of EXPORTS - doc.place_of_supply = "Exempted" + # doc.place_of_supply = "Exempted" if template_doc.is_export != 1: frappe.throw(f"Selected Tax {doc.taxes_and_charges} is for Indian Sales but Billing \ Address is in Different Country {ship_country}, hence either change Billing \ From 50c9a631fb002fa6d171c7ed6af23fa878122c8a Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Tue, 23 Sep 2025 13:41:05 +0530 Subject: [PATCH 18/52] feat: address gstin api replaced with india compliance api (#11) --- .../rohit_common/validations/address.py | 43 +++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/rohit_common/rohit_common/validations/address.py b/rohit_common/rohit_common/validations/address.py index 85eb072..acc4373 100644 --- a/rohit_common/rohit_common/validations/address.py +++ b/rohit_common/rohit_common/validations/address.py @@ -16,7 +16,8 @@ from ...utils.phone_utils import comma_phone_validations from ...utils.rohit_common_utils import get_country_code,replace_java_chars, check_system_manager,\ check_or_rename_doc - +from india_compliance.gst_india.api_classes.public import PublicAPI +from india_compliance.gst_india.utils.test_gstin_info import TestGstinInfo def autoname(doc, method): backend = 0 @@ -322,7 +323,7 @@ def update_fields_from_gmaps(doc, address_dict): def validate_gstin_from_portal(doc): """ - Validates GSTIN from GST Portal + Validates GSTIN using India Compliance Public API """ auto_days = flt(frappe.get_value("Rohit Settings", "Rohit Settings", "auto_validate_gstin_after")) @@ -330,31 +331,49 @@ def validate_gstin_from_portal(doc): days_since_validation = (date.today() - getdate(doc.gst_validation_date)).days else: days_since_validation = 999 + if doc.validated_gstin != doc.gstin or days_since_validation >= auto_days: - # Validate GSTIN status after 30 days if done manually changes - gstin_json = search_gstin(doc.gstin) - if not gstin_json.get("status_cd"): + try: + if frappe.get_single("GST Settings").sandbox_mode: + class DummyAPI: + def is_ignored_error(self, _): + return False + + api = DummyAPI() + gstin_json = TestGstinInfo.MOCK_GSTIN_INFO + else: + api = PublicAPI() + api.setup(doc=doc) + gstin_json = api.get_gstin_info(doc.gstin) + except Exception as e: + frappe.throw(f"Error validating GSTIN {doc.gstin}: {e}") + + # ignored/invalid responses + if api.is_ignored_error(gstin_json): + doc.gstin_json_reply = str(gstin_json) + doc.validated_gstin = doc.gstin + doc.gst_status = gstin_json.get("sts") or "Invalid" + doc.gst_validation_date = date.today() + else: + # normal success response doc.gstin_json_reply = str(gstin_json) doc.validated_gstin = gstin_json.get("gstin") doc.gst_status = gstin_json.get("sts") doc.gst_validation_date = date.today() - else: - frappe.throw("Status Code Return is Zero Hence Exiting") - # frappe.msgprint("Status Code Return is Zero Hence Exiting") - # exit() - return + + # disabling logic if doc.gst_status in ('Inactive', 'Cancelled'): doc.disabled = 1 elif doc.gst_status == 'Suspended': - # Disable the address for Supplier or unlinked address dl_list = frappe.db.sql(f"""SELECT name, link_doctype FROM `tabDynamic Link` - WHERE parenttype = 'Address' AND parent = '{doc.name}'""", as_dict=1) + WHERE parenttype = 'Address' AND parent = %s""", (doc.name,), as_dict=1) if dl_list: for dt in dl_list: if dt.link_doctype == 'Supplier': doc.disabled = 1 else: doc.disabled = 1 + update_address_title_from_gstin_json(doc) From f1c23881c14971bea349ef89c6a7c9d66a7b0603 Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Thu, 25 Sep 2025 11:49:53 +0530 Subject: [PATCH 19/52] fix: einvoice (#12) * fix: e-invoice * fix: commented code not needed for now --- rohit_common/__init__.py | 7 +- rohit_common/fixtures/custom_docperm.json | 72 +++++++++++++++++++ rohit_common/hooks.py | 3 +- .../overrides/india_compliance_einvoice.py | 47 ++++++++++++ .../rigpl_ic_e_invoice/__init__.py | 0 .../rigpl_ic_e_invoice.json | 33 +++++++++ 6 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 rohit_common/overrides/india_compliance_einvoice.py create mode 100644 rohit_common/rohit_common/print_format/rigpl_ic_e_invoice/__init__.py create mode 100644 rohit_common/rohit_common/print_format/rigpl_ic_e_invoice/rigpl_ic_e_invoice.json diff --git a/rohit_common/__init__.py b/rohit_common/__init__.py index 381c384..98b6920 100644 --- a/rohit_common/__init__.py +++ b/rohit_common/__init__.py @@ -11,4 +11,9 @@ from rohit_common.overrides.file import get_permission_query_conditions,has_permission frappe.frappe.core.doctype.file.file.has_permission=has_permission -frappe.frappe.core.doctype.file.file.get_permission_query_conditions=get_permission_query_conditions \ No newline at end of file +frappe.frappe.core.doctype.file.file.get_permission_query_conditions=get_permission_query_conditions + +# Override for EInvoiceData.get_data +# from india_compliance.gst_india.utils.e_invoice import EInvoiceData +# from rohit_common.overrides.india_compliance_einvoice import custom_get_data +# EInvoiceData.get_data = custom_get_data diff --git a/rohit_common/fixtures/custom_docperm.json b/rohit_common/fixtures/custom_docperm.json index bd982fa..1422cc8 100644 --- a/rohit_common/fixtures/custom_docperm.json +++ b/rohit_common/fixtures/custom_docperm.json @@ -1,4 +1,28 @@ [ + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 1, + "if_owner": 0, + "import": 1, + "modified": "2025-09-24 15:08:40.557587", + "name": "m7hut3b1u5", + "parent": "e-Invoice Log", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "select": 1, + "share": 1, + "submit": 0, + "write": 1 + }, { "amend": 0, "cancel": 0, @@ -46,5 +70,53 @@ "share": 1, "submit": 0, "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 1, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "modified": "2025-09-24 15:08:32.029829", + "name": "m7goptn66e", + "parent": "e-Invoice Log", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "select": 0, + "share": 1, + "submit": 0, + "write": 0 + }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 1, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "modified": "2025-09-24 15:08:32.127716", + "name": "m7hfu12j3g", + "parent": "e-Invoice Log", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "select": 0, + "share": 1, + "submit": 0, + "write": 0 } ] \ No newline at end of file diff --git a/rohit_common/hooks.py b/rohit_common/hooks.py index 9ae0e3b..94d176a 100644 --- a/rohit_common/hooks.py +++ b/rohit_common/hooks.py @@ -21,7 +21,8 @@ "parent", "in", [ - "File" + "File", + "e-Invoice Log" ], ] ], diff --git a/rohit_common/overrides/india_compliance_einvoice.py b/rohit_common/overrides/india_compliance_einvoice.py new file mode 100644 index 0000000..1120d81 --- /dev/null +++ b/rohit_common/overrides/india_compliance_einvoice.py @@ -0,0 +1,47 @@ +import frappe +from collections import defaultdict +from india_compliance.gst_india.utils.e_invoice import EInvoiceData + +original_get_data = EInvoiceData.get_data + +def custom_get_data(self): + frappe.log_error("Custom get_data called", "EInvoice Patch") + data = original_get_data(self) + + # Summarize ItemList by HSN + summarized = defaultdict(lambda: { + "HsnCd": "", + "IsServc": "N", + "GstRt": 0, + "AssAmt": 0.0, + "CgstAmt": 0.0, + "SgstAmt": 0.0, + "IgstAmt": 0.0, + "CesAmt": 0.0, + "TotItemVal": 0.0 + }) + + for item in data.get("ItemList", []): + hsn = item.get("HsnCd") + s = summarized[hsn] + + if not s["HsnCd"]: + s["HsnCd"] = hsn + s["IsServc"] = item.get("IsServc", "N") + s["GstRt"] = item.get("GstRt", 0) + + for k in ["AssAmt","CgstAmt","SgstAmt","IgstAmt","CesAmt","TotItemVal"]: + s[k] += item.get(k, 0.0) + + new_items = [] + for i, (hsn, vals) in enumerate(summarized.items(), 1): + vals["SlNo"] = str(i) + vals["PrdDesc"] = f"Goods with HSN {hsn}" + vals["Qty"] = 1.0 + vals["Unit"] = "OTH" + vals["UnitPrice"] = vals["AssAmt"] + vals["TotAmt"] = vals["AssAmt"] + new_items.append(vals) + + data["ItemList"] = new_items + return data \ No newline at end of file diff --git a/rohit_common/rohit_common/print_format/rigpl_ic_e_invoice/__init__.py b/rohit_common/rohit_common/print_format/rigpl_ic_e_invoice/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/rohit_common/rohit_common/print_format/rigpl_ic_e_invoice/rigpl_ic_e_invoice.json b/rohit_common/rohit_common/print_format/rigpl_ic_e_invoice/rigpl_ic_e_invoice.json new file mode 100644 index 0000000..ef6bb5c --- /dev/null +++ b/rohit_common/rohit_common/print_format/rigpl_ic_e_invoice/rigpl_ic_e_invoice.json @@ -0,0 +1,33 @@ +{ + "absolute_value": 0, + "align_labels_right": 0, + "creation": "2025-09-24 14:40:27.316661", + "custom_format": 1, + "default_print_language": "en", + "disabled": 0, + "doc_type": "e-Invoice Log", + "docstatus": 0, + "doctype": "Print Format", + "font_size": 14, + "html": "\n\n{%- from \"templates/print_formats/standard_macros.html\" import add_header, render_field, print_value -%}\n\n{% if not doc.irn %}\n
\n Please generate an e-Invoice to preview it.\n
\n\n{% else %}\n{% set e_invoice_log = frappe.db.get_value(\n \"e-Invoice Log\", doc.irn, (\"invoice_data\", \"signed_qr_code\"), as_dict=True\n) %}\n\n{% if not e_invoice_log %}\n
\n The e-Invoice Log linked to this Sales Invoice could not be found.\n
\n\n{% else %}\n{% if not e_invoice_log.invoice_data %}\n
\n Invoice Data is not available in the e-Invoice Log linked to this invoice.\n
\n\n{% else %}\n{%- set invoice_data = _dict(json.loads(e_invoice_log.invoice_data)) -%}\n\n{% macro get_address_html(address) %}\n{% for field in (\"Gstin\", \"LglNm\", \"Nm\", \"Addr1\", \"Addr2\", \"Loc\") %}\n{% if address.get(field) %}\n

{{ address[field] }}

\n{% endif %}\n{% endfor %}\n

{{ get_state(address[\"Stcd\"]) }} - {{ address[\"Pin\"] }}

\n{%- endmacro %}\n\n
\n {% if letter_head and not no_letterhead %}\n
{{ letter_head }}
\n {% endif %}\n
\n

e-Invoice

\n {{ doc.name }}\n
\n
\n\n{% if print_settings.repeat_header_footer %}\n
\n {% if not no_letterhead and footer %}\n
\n {{ footer }}\n
\n {% endif %}\n

\n {{ _(\"Page {0} of {1}\").format('', '') }}\n

\n
\n{% endif %}\n\n
1. Transaction Details
\n
\n
\n {%\n set transaction_details = {\n \"IRN\": invoice_data.Irn,\n \"Category\": invoice_data.TranDtls.SupTyp,\n \"Document Type\": invoice_data.DocDtls.Typ,\n \"Document No.\": invoice_data.DocDtls.No,\n \"e-Waybill No.\": doc.ewaybill,\n }\n %}\n {% for key, value in transaction_details.items() %}\n {% if value %}\n
\n
\n
{{ value }}
\n
\n {% endif %}\n {% endfor %}\n
\n \n
\n\n
2. Party Details
\n
\n
\n
\n {% if invoice_data.DispDtls %}\n Seller Details\n {% else %}\n Seller and Dispatch Details\n {% endif %}\n
\n {{ get_address_html(invoice_data.SellerDtls) }}\n\n {%- if invoice_data.DispDtls -%}\n
Dispatched From
\n {{ get_address_html(invoice_data.DispDtls) }}\n {% endif %}\n
\n
\n
\n {% if invoice_data.ShipDtls %}\n Buyer Details\n {% else %}\n Buyer and Shipping Details\n {% endif %}\n
\n {{ get_address_html(invoice_data.BuyerDtls) }}\n\n {%- if invoice_data.ShipDtls -%}\n
Shipped To
\n {{ get_address_html(invoice_data.ShipDtls) }}\n {% endif %}\n
\n
\n\n{% set items = invoice_data.ItemList %}\n{% set item_fields = get_e_invoice_item_fields(items) %}\n
3. Item Details
\n
\n
\n \n \n \n {% for field, label in item_fields.items() %}\n {{ label }}\n {% endfor %}\n \n \n \n {% for item in items %}\n \n {% for field in item_fields %}\n {% set value = item[field] %}\n \n {% if field.endswith((\"Val\", \"Amt\", \"Price\")) or field == \"Discount\" %}\n \n {% elif field.endswith(\"Rt\") %}\n \n {% elif value is not string or field == \"SlNo\" %}\n \n {% else %}\n \n {% endif %}\n {% endfor %}\n \n {% endfor %}\n \n
\n {{ frappe.utils.fmt_money(value, currency=\"INR\") }}\n \n {% if value % 1 == 0 %}\n {{ \"{}%\".format(frappe.utils.cint(value)) }}\n {% elif value % 0.1 == 0 %}\n {{ \"{}%\".format(frappe.utils.flt(value, 1)) }}\n {% else %}\n {{ \"{}%\".format(frappe.utils.flt(value, 2)) }}\n {% endif %}\n {{ value }}{{ value }}
\n
\n
\n\n{%- set amounts = invoice_data.ValDtls -%}\n{% set amount_fields = get_e_invoice_amount_fields(amounts, doc) %}\n
4. Value Details
\n
\n
\n \n \n \n {% for field, label in amount_fields.items() %}\n \n {% endfor %}\n \n \n \n \n {% for field in amount_fields %}\n \n {% endfor %}\n \n \n
{{ label }}
\n {{ frappe.utils.fmt_money(amounts[field], currency=\"INR\")}}\n
\n
\n
\n\n{% endif %}\n{% endif %}\n{% endif %}", + "idx": 0, + "line_breaks": 0, + "margin_bottom": 15.0, + "margin_left": 15.0, + "margin_right": 15.0, + "margin_top": 15.0, + "modified": "2025-09-24 14:40:37.321167", + "modified_by": "Administrator", + "module": "rohit_common", + "name": "RIGPL IC e-Invoice", + "owner": "Administrator", + "page_number": "Hide", + "pdf_generator": "wkhtmltopdf", + "print_format_builder": 0, + "print_format_builder_beta": 0, + "print_format_for": "DocType", + "print_format_type": "Jinja", + "raw_printing": 0, + "show_section_headings": 0, + "standard": "Yes" +} From 59e23bedb7ac8a47c47aff0f02e5a51b92033cf4 Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Tue, 30 Sep 2025 06:27:59 +0000 Subject: [PATCH 20/52] fix(docs): updated docs --- docs/09-2025.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/09-2025.md b/docs/09-2025.md index e1d753b..93f9a01 100644 --- a/docs/09-2025.md +++ b/docs/09-2025.md @@ -71,7 +71,7 @@ ### 9. Contact (Search Fields) **Issue:** Search not working based on fields defined in Customize Form. -**Status:** Pending check. +**Status:** Found Method but its not used anywhere rohit_common.utils.contact_utils.rigpl_contact_query. --- @@ -88,7 +88,7 @@ ### 12. Sales Invoice (E-Invoice JSON) **Issue:** Should send only summary of items (not line-wise rates) to GSTIN. -**Status:** Pending check. +**Status:** Cannot remove quantity and UnitPrice Both are required in india compliance API. --- From f9aecc081e3cb69bc43dc29142f9d6fb0a2407bc Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Tue, 30 Sep 2025 06:41:31 +0000 Subject: [PATCH 21/52] fix: updated cdocs --- docs/09-2025.md | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/docs/09-2025.md b/docs/09-2025.md index 93f9a01..6175a4b 100644 --- a/docs/09-2025.md +++ b/docs/09-2025.md @@ -9,17 +9,14 @@ ## Fixed & Pending Issues ### 1. Sales Invoice (Unable to Save + E-Invoice Issues) -**Status:** Half Resolved +**Status:** Resolved - Removed custom code resetting *place of supply* that caused save failures. → File: `validations/sales_invoice.py` → Method: `check_local_natl_tax_rules()` - E-Invoice re-enabled with **India Compliance**. - Re-setup required for new sites. - Path: **GST Settings → Enable E-Invoice** (currently sandbox mode). - Setup Guide: [India Compliance Docs](https://docs.indiacompliance.app/docs/ewaybill-and-einvoice/gst_settings) - -**Pending:** -- Remove full validation (since using India Compliance). -- Add QR Code, Ack No, and Ack Date to E-Invoice. +- To Remove QR Code, Ack No, and Ack Date in E-Invoice have created new print format RIGPL IC e-Invoice. --- @@ -40,16 +37,14 @@ --- ### 4. GST Return Status -**Status:** Pending +**Status:** Fixed **Issue:** Unable to fetch GST Return Status. -**Plan:** Replace with **India Compliance API**. --- ### 5. Address (GST Validation) -**Status:** Pending +**Status:** Fixed **Issue:** GST API validation not working. -**Plan:** Replace with **India Compliance API**. --- @@ -103,5 +98,5 @@ ## ✅ Summary - **Resolved:** File List issues, GL Report. - **In Review:** Asset fixes. -- **Pending:** E-Invoice (QR, Ack fields, JSON summary), GST Return Status, GST Validation, Contact search. +- **Pending:** Contact search. - **Custom Reports/Patches:** Added where native functionality broke. From 992d261c8078db8a26c4ef05f7fe7b089bb4a002 Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Wed, 8 Oct 2025 13:29:30 +0530 Subject: [PATCH 22/52] fix: role permission--ship to field and responses import error (#13) --- pyproject.toml | 1 + rohit_common/fixtures/custom_docperm.json | 264 + rohit_common/hooks.py | 5 +- rohit_common/public/js/address.js | 4 +- rohit_common/rohit_common/custom/address.json | 2175 ++++-- .../rohit_common/custom/packed_item.json | 39 + .../rohit_common/custom/sales_invoice.json | 6371 +++++++++++++++-- .../custom/sales_invoice_item.json | 2656 ++++++- .../custom/sales_taxes_and_charges.json | 411 ++ .../rohit_common/validations/address.py | 8 +- 10 files changed, 10694 insertions(+), 1240 deletions(-) create mode 100644 rohit_common/rohit_common/custom/packed_item.json create mode 100644 rohit_common/rohit_common/custom/sales_taxes_and_charges.json diff --git a/pyproject.toml b/pyproject.toml index 9264ff2..1017d25 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,5 +9,6 @@ dynamic = ["version"] dependencies = [ # Core dependencies "phonenumbers==8.13.13", + "responses>=0.25.8", "india-compliance @ git+https://github.com/resilient-tech/india-compliance.git#version-15", ] diff --git a/rohit_common/fixtures/custom_docperm.json b/rohit_common/fixtures/custom_docperm.json index 1422cc8..ed46082 100644 --- a/rohit_common/fixtures/custom_docperm.json +++ b/rohit_common/fixtures/custom_docperm.json @@ -1,4 +1,28 @@ [ + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 0, + "export": 1, + "if_owner": 0, + "import": 0, + "modified": "2025-10-08 13:03:41.259013", + "name": "7c73067c6e", + "parent": "Accounts Settings", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 0, + "role": "System Manager", + "select": 1, + "share": 0, + "submit": 0, + "write": 1 + }, { "amend": 0, "cancel": 0, @@ -118,5 +142,245 @@ "share": 1, "submit": 0, "write": 0 + }, + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 0, + "export": 1, + "if_owner": 0, + "import": 0, + "modified": "2025-10-08 12:55:33.622088", + "name": "ahvbd2d0tl", + "parent": "GSTR-1", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "select": 1, + "share": 0, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "modified": "2025-10-08 13:21:04.631867", + "name": "rmkmoq0a9h", + "parent": "GSTR2A RIGPL", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "select": 1, + "share": 1, + "submit": 1, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 0, + "export": 1, + "if_owner": 0, + "import": 0, + "modified": "2025-10-08 12:55:41.447242", + "name": "ahv4llqtun", + "parent": "GSTR-1", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "select": 1, + "share": 0, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "modified": "2025-10-08 13:20:58.021690", + "name": "rmkpgug6pi", + "parent": "GSTR2A RIGPL", + "permlevel": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "select": 0, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 0, + "export": 1, + "if_owner": 0, + "import": 0, + "modified": "2025-10-08 12:55:39.769575", + "name": "ahuqdqs6rd", + "parent": "GSTR-1", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "select": 1, + "share": 0, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "modified": "2025-10-08 13:21:11.670358", + "name": "rmjskl176l", + "parent": "GSTR2A RIGPL", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "select": 1, + "share": 1, + "submit": 1, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 0, + "export": 1, + "if_owner": 0, + "import": 0, + "modified": "2025-10-08 12:55:42.837348", + "name": "ahvas2oi6d", + "parent": "GSTR-1", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Auditor", + "select": 1, + "share": 0, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "modified": "2025-10-08 13:20:57.997129", + "name": "rmjd3p3ar7", + "parent": "GSTR2A RIGPL", + "permlevel": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "select": 0, + "share": 1, + "submit": 0, + "write": 0 + }, + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "modified": "2025-10-08 13:21:10.038098", + "name": "rmkqtrrcrd", + "parent": "GSTR2A RIGPL", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "select": 1, + "share": 1, + "submit": 1, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 1, + "if_owner": 0, + "import": 0, + "modified": "2025-10-08 13:20:58.002956", + "name": "rmkno92l39", + "parent": "GSTR2A RIGPL", + "permlevel": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "select": 0, + "share": 1, + "submit": 0, + "write": 0 } ] \ No newline at end of file diff --git a/rohit_common/hooks.py b/rohit_common/hooks.py index 94d176a..c4a9e9b 100644 --- a/rohit_common/hooks.py +++ b/rohit_common/hooks.py @@ -22,7 +22,10 @@ "in", [ "File", - "e-Invoice Log" + "e-Invoice Log", + "GSTR2A RIGPL", + "GSTR-1", + "Accounts Settings", ], ] ], diff --git a/rohit_common/public/js/address.js b/rohit_common/public/js/address.js index a31634d..e58ad7b 100644 --- a/rohit_common/public/js/address.js +++ b/rohit_common/public/js/address.js @@ -25,7 +25,9 @@ frappe.ui.form.on("Address", { "excise_no", "latitude", "longitude", "global_google_code", "known_states"]; for (let fld of reset_flds) { - frm.doc[fld] = "" ; + let df = frappe.meta.get_docfield("Address", fld, frm.doc.name); + let value = (df && df.fieldtype === "Check") ? 0 : ""; + frm.set_value(fld, value); } frm.refresh_fields(); diff --git a/rohit_common/rohit_common/custom/address.json b/rohit_common/rohit_common/custom/address.json index 0b2acf3..4ff986a 100644 --- a/rohit_common/rohit_common/custom/address.json +++ b/rohit_common/rohit_common/custom/address.json @@ -11,47 +11,63 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2014-11-06 22:27:23.786691", + "creation": "2020-09-26 13:14:18.954123", "default": null, - "depends_on": "eval: doc.country == 'India' && doc.tin_no != 'NA'", + "depends_on": null, "description": null, "docstatus": 0, "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "tin_no", + "fieldname": "airport", "fieldtype": "Data", "hidden": 0, - "idx": 23, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 14, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "pan", - "label": "TIN Number", + "index": null, + "insert_after": "sea_port", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Airport", "length": 0, - "modified": "2017-06-24 17:14:37.299623", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-09-26 13:14:18.954123", "modified_by": "Administrator", - "name": "Address-tin_no", - "no_copy": 1, + "module": null, + "name": "Address-airport", + "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": null, + "placeholder": null, + "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 1, + "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, + "trash_reason": null, "unique": 0, "width": null }, @@ -66,49 +82,65 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2014-11-06 22:27:24.462729", + "creation": "2020-06-27 19:18:10.647846", "default": null, - "depends_on": "eval: doc.country == 'India' && doc.excise_no != 'NA'", + "depends_on": null, "description": null, "docstatus": 0, "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "excise_no", - "fieldtype": "Data", + "fieldname": "approximate_location", + "fieldtype": "Check", "hidden": 0, - "idx": 24, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 34, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "tin_no", - "label": "Excise Registration Number", + "index": 0.0, + "insert_after": "dont_update_from_google", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Approximate Location", "length": 0, - "modified": "2017-06-24 17:14:37.437566", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-06-27 19:18:10.647846", "modified_by": "Administrator", - "name": "Address-excise_no", - "no_copy": 1, + "module": null, + "name": "Address-approximate_location", + "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": null, + "placeholder": null, + "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, - "width": "216" + "width": null }, { "_assign": null, @@ -121,47 +153,63 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2014-11-06 22:27:25.016738", + "creation": "2020-09-23 18:41:42.794822", "default": null, - "depends_on": "eval: doc.country == 'India' && doc.service_tax_no != 'NA'", + "depends_on": null, "description": null, "docstatus": 0, "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "service_tax_no", - "fieldtype": "Data", + "fieldname": "cb0", + "fieldtype": "Column Break", "hidden": 0, - "idx": 25, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 45, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "excise_no", - "label": "Service Tax Number", + "index": null, + "insert_after": "gstin_json_reply", + "is_system_generated": 1, + "is_virtual": 0, + "label": "", "length": 0, - "modified": "2017-06-24 17:14:37.520811", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-09-23 18:41:42.794822", "modified_by": "Administrator", - "name": "Address-service_tax_no", - "no_copy": 1, + "module": null, + "name": "Address-cb0", + "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": null, + "placeholder": null, + "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 1, + "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -176,49 +224,65 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2017-06-28 14:38:55.921911", + "creation": "2020-06-27 21:21:17.635416", "default": null, - "depends_on": "eval: doc.country == 'India'", + "depends_on": null, "description": null, "docstatus": 0, "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "gstin", - "fieldtype": "Data", + "fieldname": "dont_update_from_google", + "fieldtype": "Check", "hidden": 0, - "idx": 19, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 33, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "insert_after": "fax", - "label": "Party GSTIN", + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": 0.0, + "insert_after": "is_shipping_address", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Dont Update from Google", "length": 0, - "modified": "2017-06-28 14:38:55.921911", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-06-27 21:21:17.635416", "modified_by": "Administrator", - "name": "Address-gstin", + "module": null, + "name": "Address-dont_update_from_google", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, - "width": "210" + "width": null }, { "_assign": null, @@ -231,47 +295,63 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2017-06-28 14:38:56.077050", + "creation": "2021-01-05 12:07:50.424423", "default": null, - "depends_on": "eval: doc.country == 'India' && doc.gst_state != doc.state_rigpl", + "depends_on": null, "description": null, "docstatus": 0, "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "gst_state", - "fieldtype": "Select", + "fieldname": "email_address_validated", + "fieldtype": "Check", "hidden": 0, - "idx": 20, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 17, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "gstin", - "label": "GST State", + "index": null, + "insert_after": "email_id", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Email Address Validated", "length": 0, - "modified": "2017-06-28 14:38:56.077050", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2021-01-05 12:07:50.424423", "modified_by": "Administrator", - "name": "Address-gst_state", + "module": null, + "name": "Address-email_address_validated", "no_copy": 0, - "options": "\nAndhra Pradesh\nArunachal Pradesh\nAssam\nBihar\nChandigarh\nChhattisgarh\nDadra and Nagar Haveli\nDaman and Diu\nDelhi\nGoa\nGujarat\nHaryana\nHimachal Pradesh\nJammu and Kashmir\nJharkhand\nKarnataka\nKerala\nLakshadweep Islands\nMadhya Pradesh\nMaharashtra\nManipur\nMeghalaya\nMizoram\nNagaland\nOdisha\nPondicherry\nPunjab\nRajasthan\nSikkim\nTamil Nadu\nTelangana\nTripura\nUttar Pradesh\nUttarakhand\nWest Bengal", + "non_negative": 0, + "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -286,49 +366,65 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2017-06-28 14:53:06.402276", + "creation": "2014-11-06 22:27:24.462729", "default": null, - "depends_on": "eval: doc.known_states === 1", + "depends_on": "eval: doc.country == 'India' && doc.excise_no != 'NA'", "description": null, "docstatus": 0, "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "state_rigpl", - "fieldtype": "Link", + "fieldname": "excise_no", + "fieldtype": "Data", "hidden": 0, - "idx": 8, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 24, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 1, - "insert_after": "county", - "label": "State RIGPL", + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": 0.0, + "insert_after": "tin_no", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Excise Registration Number", "length": 0, - "modified": "2017-06-28 14:53:06.402276", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2017-06-24 17:14:37.437566", "modified_by": "Administrator", - "name": "Address-state_rigpl", - "no_copy": 0, - "options": "State", + "module": null, + "name": "Address-excise_no", + "no_copy": 1, + "non_negative": 0, + "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "", + "placeholder": null, + "precision": null, "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, - "width": null + "width": "216" }, { "_assign": null, @@ -341,47 +437,63 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2017-06-28 14:53:08.124957", + "creation": "2020-06-27 22:41:07.438568", "default": null, - "depends_on": "eval: doc.country == 'India' && doc.pan != 'NA'", + "depends_on": null, "description": null, "docstatus": 0, "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "pan", + "fieldname": "global_google_code", "fieldtype": "Data", "hidden": 0, - "idx": 22, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 28, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "gst_state_number", - "label": "Pan", + "index": 0.0, + "insert_after": "longitude", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Global Google Code", "length": 0, - "modified": "2017-06-28 14:53:08.124957", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-06-27 22:41:07.438568", "modified_by": "Administrator", - "name": "Address-pan", + "module": null, + "name": "Address-global_google_code", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, + "trash_reason": null, "unique": 0, "width": null }, @@ -396,47 +508,63 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2017-07-12 12:53:50.603085", + "creation": "2020-06-27 22:32:59.718129", "default": null, - "depends_on": "eval: doc.country == 'India'", + "depends_on": null, "description": null, "docstatus": 0, "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "gst_state_number", - "fieldtype": "Data", + "fieldname": "google_maps_view", + "fieldtype": "HTML", "hidden": 0, - "idx": 21, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 49, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "gst_state", - "label": "GST State Number", + "index": 0.0, + "insert_after": "json_reply", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Google Maps View", "length": 0, - "modified": "2017-07-12 12:53:50.603085", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-06-27 22:32:59.718129", "modified_by": "Administrator", - "name": "Address-gst_state_number", + "module": null, + "name": "Address-google_maps_view", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 1, + "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -451,47 +579,63 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2018-03-10 14:18:07.231197", - "default": null, + "creation": "2025-08-29 14:43:28.102392", + "default": "Unregistered", "depends_on": null, "description": null, "docstatus": 0, "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "is_residential", - "fieldtype": "Check", + "fieldname": "gst_category", + "fieldtype": "Select", "hidden": 0, - "idx": 29, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "global_google_code", - "label": "Is Residential", + "index": null, + "insert_after": "tax_details_column_break", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST Category", "length": 0, - "modified": "2018-03-10 14:18:07.231197", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:28.102392", "modified_by": "Administrator", - "name": "Address-is_residential", + "module": "GST India", + "name": "Address-gst_category", "no_copy": 0, - "options": null, + "non_negative": 0, + "options": "Registered Regular\nRegistered Composition\nUnregistered\nSEZ\nOverseas\nDeemed Export\nUIN Holders\nTax Deductor\nTax Collector\nInput Service Distributor", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, - "reqd": 0, + "reqd": 1, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -506,47 +650,63 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2018-12-28 22:29:21.828090", + "creation": "2017-06-28 14:38:56.077050", "default": null, - "depends_on": null, + "depends_on": "eval: doc.country == 'India' && doc.gst_state != doc.state_rigpl", "description": null, "docstatus": 0, "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "tax_category", - "fieldtype": "Link", + "fieldname": "gst_state", + "fieldtype": "Select", "hidden": 0, - "idx": 30, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 20, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "is_residential", - "label": "Tax Category", + "index": 0.0, + "insert_after": "gstin", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST State", "length": 0, - "modified": "2018-12-28 22:29:21.828090", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2017-06-28 14:38:56.077050", "modified_by": "Administrator", - "name": "Address-tax_category", + "module": "GST India", + "name": "Address-gst_state", "no_copy": 0, - "options": "Tax Category", + "non_negative": 0, + "options": "\nAndhra Pradesh\nArunachal Pradesh\nAssam\nBihar\nChandigarh\nChhattisgarh\nDadra and Nagar Haveli\nDaman and Diu\nDelhi\nGoa\nGujarat\nHaryana\nHimachal Pradesh\nJammu and Kashmir\nJharkhand\nKarnataka\nKerala\nLakshadweep Islands\nMadhya Pradesh\nMaharashtra\nManipur\nMeghalaya\nMizoram\nNagaland\nOdisha\nPondicherry\nPunjab\nRajasthan\nSikkim\nTamil Nadu\nTelangana\nTripura\nUttar Pradesh\nUttarakhand\nWest Bengal", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -561,47 +721,63 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-06-27 14:38:46.781789", + "creation": "2017-07-12 12:53:50.603085", "default": null, - "depends_on": null, + "depends_on": "eval: doc.country == 'India'", "description": null, "docstatus": 0, "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "json_reply", - "fieldtype": "Text", + "fieldname": "gst_state_number", + "fieldtype": "Data", "hidden": 0, - "idx": 48, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 21, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "gst_validation_date", - "label": "json_reply", + "index": 0.0, + "insert_after": "gst_state", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST State Number", "length": 0, - "modified": "2020-06-27 14:38:46.781789", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2017-07-12 12:53:50.603085", "modified_by": "Administrator", - "name": "Address-json_reply", + "module": "GST India", + "name": "Address-gst_state_number", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 1, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -616,7 +792,7 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-06-27 16:51:06.974304", + "creation": "2020-09-23 18:41:42.953554", "default": null, "depends_on": null, "description": null, @@ -624,39 +800,55 @@ "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "latitude", - "fieldtype": "Float", + "fieldname": "gst_status", + "fieldtype": "Select", "hidden": 0, - "idx": 26, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 46, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "service_tax_no", - "label": "Latitude", + "index": null, + "insert_after": "cb0", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST Status", "length": 0, - "modified": "2020-06-27 16:51:06.974304", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-09-23 18:41:42.953554", "modified_by": "Administrator", - "name": "Address-latitude", + "module": null, + "name": "Address-gst_status", "no_copy": 0, - "options": null, + "non_negative": 0, + "options": "\nActive\nInactive\nCancelled\nSuspended", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "7", + "placeholder": null, + "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, + "trash_reason": null, "unique": 0, "width": null }, @@ -668,10 +860,10 @@ "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, - "collapsible": 0, - "collapsible_depends_on": null, + "collapsible": 1, + "collapsible_depends_on": "eval:doc.validated_gstin", "columns": 0, - "creation": "2020-06-27 16:54:10.856760", + "creation": "2020-09-23 18:19:58.202739", "default": null, "depends_on": null, "description": null, @@ -679,39 +871,55 @@ "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "longitude", - "fieldtype": "Float", + "fieldname": "gst_validation_data", + "fieldtype": "Section Break", "hidden": 0, - "idx": 27, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 42, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "latitude", - "label": "Longitude", + "index": null, + "insert_after": "location", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST Validation Data", "length": 0, - "modified": "2020-06-27 16:54:10.856760", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-09-23 18:19:58.202739", "modified_by": "Administrator", - "name": "Address-longitude", + "module": null, + "name": "Address-gst_validation_data", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "7", + "placeholder": null, + "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 1, + "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -726,7 +934,7 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-06-27 19:18:10.647846", + "creation": "2021-02-10 07:50:20.345327", "default": null, "depends_on": null, "description": null, @@ -734,39 +942,55 @@ "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "approximate_location", - "fieldtype": "Check", + "fieldname": "gst_validation_date", + "fieldtype": "Date", "hidden": 0, - "idx": 34, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 47, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "dont_update_from_google", - "label": "Approximate Location", + "index": null, + "insert_after": "gst_status", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST Validation Date", "length": 0, - "modified": "2020-06-27 19:18:10.647846", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2021-02-10 07:50:20.345327", "modified_by": "Administrator", - "name": "Address-approximate_location", + "module": null, + "name": "Address-gst_validation_date", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -781,49 +1005,65 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-06-27 21:21:17.635416", + "creation": "2017-06-28 14:38:55.921911", "default": null, - "depends_on": null, + "depends_on": "eval: doc.country == 'India'", "description": null, "docstatus": 0, "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "dont_update_from_google", - "fieldtype": "Check", + "fieldname": "gstin", + "fieldtype": "Data", "hidden": 0, - "idx": 33, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 19, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "insert_after": "is_shipping_address", - "label": "Dont Update from Google", + "in_list_view": 1, + "in_preview": 0, + "in_standard_filter": 1, + "index": 0.0, + "insert_after": "fax", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Party GSTIN", "length": 0, - "modified": "2020-06-27 21:21:17.635416", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2017-06-28 14:38:55.921911", "modified_by": "Administrator", - "name": "Address-dont_update_from_google", + "module": "GST India", + "name": "Address-gstin", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, - "width": null + "width": "210" }, { "_assign": null, @@ -836,7 +1076,7 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-06-27 22:32:59.718129", + "creation": "2020-09-23 18:19:59.047521", "default": null, "depends_on": null, "description": null, @@ -844,39 +1084,55 @@ "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "google_maps_view", - "fieldtype": "HTML", + "fieldname": "gstin_json_reply", + "fieldtype": "Long Text", "hidden": 0, - "idx": 49, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 44, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "json_reply", - "label": "Google Maps View", + "index": null, + "insert_after": "validated_gstin", + "is_system_generated": 1, + "is_virtual": 0, + "label": "gstin_json_reply", "length": 0, - "modified": "2020-06-27 22:32:59.718129", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-09-23 18:19:59.047521", "modified_by": "Administrator", - "name": "Address-google_maps_view", + "module": null, + "name": "Address-gstin_json_reply", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, + "trash_reason": null, "unique": 0, "width": null }, @@ -891,7 +1147,7 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-06-27 22:41:07.438568", + "creation": "2018-03-10 14:18:07.231197", "default": null, "depends_on": null, "description": null, @@ -899,39 +1155,55 @@ "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "global_google_code", - "fieldtype": "Data", + "fieldname": "is_residential", + "fieldtype": "Check", "hidden": 0, - "idx": 28, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 29, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "longitude", - "label": "Global Google Code", + "index": 0.0, + "insert_after": "global_google_code", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Is Residential", "length": 0, - "modified": "2020-06-27 22:41:07.438568", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2018-03-10 14:18:07.231197", "modified_by": "Administrator", - "name": "Address-global_google_code", + "module": null, + "name": "Address-is_residential", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 1, + "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 1, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -946,47 +1218,63 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-01 13:36:46.629449", - "default": null, + "creation": "2020-10-14 17:41:40.878179", + "default": "0", "depends_on": null, "description": null, "docstatus": 0, "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "update_from_google", + "fieldname": "is_your_company_address", "fieldtype": "Check", "hidden": 0, - "idx": 35, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 20, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "approximate_location", - "label": "Update from Google", + "index": null, + "insert_after": "linked_with", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Is Your Company Address", "length": 0, - "modified": "2020-07-01 13:36:46.629449", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-10-14 17:41:40.878179", "modified_by": "Administrator", - "name": "Address-update_from_google", + "module": null, + "name": "Address-is_your_company_address", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -1001,47 +1289,63 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-08-11 16:14:35.360343", + "creation": "2020-06-27 14:38:46.781789", "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Address", - "fetch_from": "country.known_states", + "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "known_states", - "fieldtype": "Check", + "fieldname": "json_reply", + "fieldtype": "Text", "hidden": 0, - "idx": 12, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 48, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "pincode", - "label": "Known States", + "index": 0.0, + "insert_after": "gst_validation_date", + "is_system_generated": 1, + "is_virtual": 0, + "label": "json_reply", "length": 0, - "modified": "2020-08-11 16:14:35.360343", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-06-27 14:38:46.781789", "modified_by": "Administrator", - "name": "Address-known_states", + "module": null, + "name": "Address-json_reply", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, + "trash_reason": null, "unique": 0, "width": null }, @@ -1053,50 +1357,66 @@ "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, - "collapsible": 1, - "collapsible_depends_on": "eval:doc.validated_gstin", + "collapsible": 0, + "collapsible_depends_on": null, "columns": 0, - "creation": "2020-09-23 18:19:58.202739", + "creation": "2020-08-11 16:14:35.360343", "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Address", - "fetch_from": null, + "fetch_from": "country.known_states", "fetch_if_empty": 0, - "fieldname": "gst_validation_data", - "fieldtype": "Section Break", + "fieldname": "known_states", + "fieldtype": "Check", "hidden": 0, - "idx": 42, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 12, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "location", - "label": "GST Validation Data", + "index": null, + "insert_after": "pincode", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Known States", "length": 0, - "modified": "2020-09-23 18:19:58.202739", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-11 16:15:35.360343", "modified_by": "Administrator", - "name": "Address-gst_validation_data", + "module": null, + "name": "Address-known_states", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -1111,7 +1431,7 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-09-23 18:19:59.047521", + "creation": "2020-06-27 16:51:06.974304", "default": null, "depends_on": null, "description": null, @@ -1119,39 +1439,55 @@ "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "gstin_json_reply", - "fieldtype": "Long Text", + "fieldname": "latitude", + "fieldtype": "Float", "hidden": 0, - "idx": 44, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 26, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "validated_gstin", - "label": "gstin_json_reply", + "index": 0.0, + "insert_after": "service_tax_no", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Latitude", "length": 0, - "modified": "2020-09-23 18:19:59.047521", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-06-27 16:51:06.974304", "modified_by": "Administrator", - "name": "Address-gstin_json_reply", + "module": null, + "name": "Address-latitude", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "", + "placeholder": null, + "precision": "7", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 1, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -1164,9 +1500,9 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "collapsible_depends_on": null, + "collapsible_depends_on": "", "columns": 0, - "creation": "2020-09-23 18:41:42.794822", + "creation": "2020-10-11 20:19:07.328958", "default": null, "depends_on": null, "description": null, @@ -1174,39 +1510,55 @@ "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "cb0", - "fieldtype": "Column Break", + "fieldname": "location", + "fieldtype": "Geolocation", "hidden": 0, - "idx": 45, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 41, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "gstin_json_reply", - "label": "", + "index": null, + "insert_after": "maps_section", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Location", "length": 0, - "modified": "2020-09-23 18:41:42.794822", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-10-11 20:19:07.328958", "modified_by": "Administrator", - "name": "Address-cb0", + "module": null, + "name": "Address-location", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -1221,7 +1573,7 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-09-23 18:41:42.953554", + "creation": "2020-06-27 16:54:10.856760", "default": null, "depends_on": null, "description": null, @@ -1229,39 +1581,55 @@ "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "gst_status", - "fieldtype": "Select", + "fieldname": "longitude", + "fieldtype": "Float", "hidden": 0, - "idx": 46, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 27, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "cb0", - "label": "GST Status", + "index": 0.0, + "insert_after": "latitude", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Longitude", "length": 0, - "modified": "2020-09-23 18:41:42.953554", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-06-27 16:54:10.856760", "modified_by": "Administrator", - "name": "Address-gst_status", + "module": null, + "name": "Address-longitude", "no_copy": 0, - "options": "\nActive\nInactive\nCancelled\nSuspended", + "non_negative": 0, + "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": "", + "placeholder": null, + "precision": "7", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 1, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -1274,9 +1642,9 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "collapsible_depends_on": null, + "collapsible_depends_on": "", "columns": 0, - "creation": "2020-09-26 13:14:18.179483", + "creation": "2020-10-11 20:19:07.168565", "default": null, "depends_on": null, "description": null, @@ -1284,39 +1652,55 @@ "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "sea_port", - "fieldtype": "Data", + "fieldname": "maps_section", + "fieldtype": "Section Break", "hidden": 0, - "idx": 13, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 40, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "known_states", - "label": "Sea Port", + "index": null, + "insert_after": "links", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Maps Section", "length": 0, - "modified": "2020-09-26 13:14:18.179483", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-10-11 20:19:07.168565", "modified_by": "Administrator", - "name": "Address-sea_port", + "module": null, + "name": "Address-maps_section", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 1, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -1331,47 +1715,63 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-09-26 13:14:18.954123", + "creation": "2017-06-28 14:53:08.124957", "default": null, - "depends_on": null, + "depends_on": "eval: doc.country == 'India' && doc.pan != 'NA'", "description": null, "docstatus": 0, "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "airport", + "fieldname": "pan", "fieldtype": "Data", "hidden": 0, - "idx": 14, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 22, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "sea_port", - "label": "Airport", + "index": 0.0, + "insert_after": "gst_state_number", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Pan", "length": 0, - "modified": "2020-09-26 13:14:18.954123", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2017-06-28 14:53:08.124957", "modified_by": "Administrator", - "name": "Address-airport", + "module": null, + "name": "Address-pan", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 1, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -1384,9 +1784,9 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "collapsible_depends_on": "", + "collapsible_depends_on": null, "columns": 0, - "creation": "2020-10-11 20:19:07.168565", + "creation": "2020-09-26 13:14:18.179483", "default": null, "depends_on": null, "description": null, @@ -1394,39 +1794,126 @@ "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "maps_section", - "fieldtype": "Section Break", + "fieldname": "sea_port", + "fieldtype": "Data", "hidden": 0, - "idx": 40, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 13, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "links", - "label": "Maps Section", + "index": null, + "insert_after": "known_states", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Sea Port", "length": 0, - "modified": "2020-10-11 20:19:07.168565", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-09-26 13:14:18.179483", "modified_by": "Administrator", - "name": "Address-maps_section", + "module": null, + "name": "Address-sea_port", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2014-11-06 22:27:25.016738", + "default": null, + "depends_on": "eval: doc.country == 'India' && doc.service_tax_no != 'NA'", + "description": null, + "docstatus": 0, + "dt": "Address", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "service_tax_no", + "fieldtype": "Data", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 25, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": 0.0, + "insert_after": "excise_no", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Service Tax Number", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2017-06-24 17:14:37.520811", + "modified_by": "Administrator", + "module": null, + "name": "Address-service_tax_no", + "no_copy": 1, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": null, + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -1439,9 +1926,80 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "collapsible_depends_on": "", + "collapsible_depends_on": null, "columns": 0, - "creation": "2020-10-11 20:19:07.328958", + "creation": "2017-06-28 14:53:06.402276", + "default": null, + "depends_on": "eval: doc.known_states === 1", + "description": null, + "docstatus": 0, + "dt": "Address", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "state_rigpl", + "fieldtype": "Link", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 8, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_preview": 0, + "in_standard_filter": 1, + "index": 0.0, + "insert_after": "county", + "is_system_generated": 1, + "is_virtual": 0, + "label": "State RIGPL", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2017-06-28 14:53:06.402276", + "modified_by": "Administrator", + "module": null, + "name": "Address-state_rigpl", + "no_copy": 0, + "non_negative": 0, + "options": "State", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2018-12-28 22:29:21.828090", "default": null, "depends_on": null, "description": null, @@ -1449,39 +2007,126 @@ "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "location", - "fieldtype": "Geolocation", + "fieldname": "tax_category", + "fieldtype": "Link", "hidden": 0, - "idx": 41, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 30, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "maps_section", - "label": "Location", + "index": null, + "insert_after": "is_residential", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Tax Category", "length": 0, - "modified": "2020-10-11 20:19:07.328958", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2018-12-28 22:29:21.828090", "modified_by": "Administrator", - "name": "Address-location", + "module": null, + "name": "Address-tax_category", + "no_copy": 0, + "non_negative": 0, + "options": "Tax Category", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-08-29 14:43:28.081114", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Address", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "tax_details_column_break", + "fieldtype": "Column Break", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "gst_state", + "is_system_generated": 1, + "is_virtual": 0, + "label": null, + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:28.081114", + "modified_by": "Administrator", + "module": "GST India", + "name": "Address-tax_details_column_break", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -1496,7 +2141,7 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2021-02-10 07:50:20.345327", + "creation": "2025-08-29 14:43:28.035474", "default": null, "depends_on": null, "description": null, @@ -1504,39 +2149,197 @@ "dt": "Address", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "gst_validation_date", - "fieldtype": "Date", + "fieldname": "tax_details_section", + "fieldtype": "Section Break", "hidden": 0, - "idx": 47, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "gst_status", - "label": "GST Validation Date", + "index": null, + "insert_after": "disabled", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Tax Details", "length": 0, - "modified": "2021-02-10 07:50:20.345327", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:28.035474", "modified_by": "Administrator", - "name": "Address-gst_validation_date", + "module": "GST India", + "name": "Address-tax_details_section", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2014-11-06 22:27:23.786691", + "default": null, + "depends_on": "eval: doc.country == 'India' && doc.tin_no != 'NA'", + "description": null, + "docstatus": 0, + "dt": "Address", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "tin_no", + "fieldtype": "Data", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 23, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": 0.0, + "insert_after": "pan", + "is_system_generated": 1, + "is_virtual": 0, + "label": "TIN Number", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2017-06-24 17:14:37.299623", + "modified_by": "Administrator", + "module": null, + "name": "Address-tin_no", + "no_copy": 1, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": null, + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2020-07-01 13:36:46.629449", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Address", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "update_from_google", + "fieldtype": "Check", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 35, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": 0.0, + "insert_after": "approximate_location", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Update from Google", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-07-01 13:36:46.629449", + "modified_by": "Administrator", + "module": null, + "name": "Address-update_from_google", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -1562,6 +2365,9 @@ "fieldname": "validated_gstin", "fieldtype": "Data", "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, "idx": 43, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -1569,126 +2375,168 @@ "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, + "index": null, "insert_after": "gst_validation_data", + "is_system_generated": 1, + "is_virtual": 0, "label": "Validated GSTIN", "length": 0, + "link_filters": null, + "mandatory_depends_on": null, "modified": "2022-01-28 17:26:50.156873", "modified_by": "Administrator", + "module": null, "name": "Address-validated_gstin", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, "width": null } ], "custom_perms": [], "doctype": "Address", + "links": [], "property_setters": [ { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2021-02-13 11:37:48.321869", + "creation": "2017-01-17 10:50:56.369549", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "email_id", + "field_name": "address_line1", "idx": 0, - "modified": "2021-02-13 11:37:48.321869", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.561973", "modified_by": "Administrator", - "name": "Address-email_id-in_standard_filter", - "owner": "Administrator", + "module": null, + "name": "Address-address_line1-length", + "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "in_standard_filter", - "property_type": "Check", - "value": "1" + "property": "length", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "250" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2020-10-10 18:09:41.920168", + "creation": "2025-10-08 10:54:31.892658", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, - "doctype_or_field": "DocType", - "field_name": null, + "doctype_or_field": "DocField", + "field_name": "address_line1", "idx": 0, - "modified": "2020-10-10 18:09:41.920168", - "modified_by": "aditya@rigpl.com", - "name": "Address-search_fields", - "owner": "aditya@rigpl.com", + "is_system_generated": 0, + "modified": "2025-10-08 10:54:31.892658", + "modified_by": "Administrator", + "module": null, + "name": "Address-address_line1-translatable", + "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, - "property": "search_fields", - "property_type": "Data", - "value": "address_title, address_line1, address_line2, city, state, pincode, country, email_id, gstin, phone" + "property": "translatable", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2020-08-11 14:44:45.118963", + "creation": "2015-11-25 10:38:20.107511", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "state", + "field_name": "address_line1", "idx": 0, - "modified": "2020-08-11 14:44:45.118963", - "modified_by": "aditya@rigpl.com", - "name": "Address-state-depends_on", - "owner": "aditya@rigpl.com", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.659779", + "modified_by": "Administrator", + "module": null, + "name": "Address-address_line1-width", + "owner": "abhinav@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "depends_on", - "property_type": "Data", - "value": "eval: !doc.state_rigpl" + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "353" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2018-11-22 18:07:33.333222", + "creation": "2025-10-08 10:54:31.927981", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "country", + "field_name": "address_line2", "idx": 0, - "modified": "2018-11-22 18:07:33.333222", - "modified_by": "aditya@rigpl.com", - "name": "Address-country-ignore_user_permissions", - "owner": "aditya@rigpl.com", + "is_system_generated": 0, + "modified": "2025-10-08 10:54:31.927981", + "modified_by": "Administrator", + "module": null, + "name": "Address-address_line2-translatable", + "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, - "property": "ignore_user_permissions", + "property": "translatable", "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, "value": "1" }, { @@ -1696,45 +2544,59 @@ "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2018-11-08 16:48:54.783115", + "creation": "2015-11-25 10:38:20.528122", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", "field_name": "address_line2", "idx": 0, - "modified": "2018-11-08 16:48:54.783115", - "modified_by": null, - "name": "Address-address_line2-translatable", - "owner": null, + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.646005", + "modified_by": "Administrator", + "module": null, + "name": "Address-address_line2-width", + "owner": "abhinav@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "translatable", + "property": "width", "property_type": null, - "value": "1" + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "30" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2018-11-08 16:48:54.781795", + "creation": "2015-07-02 11:59:11.673217", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "address_line1", + "field_name": "address_title", "idx": 0, - "modified": "2018-11-08 16:48:54.781795", - "modified_by": null, - "name": "Address-address_line1-translatable", - "owner": null, + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.673674", + "modified_by": "Administrator", + "module": null, + "name": "Address-address_title-reqd", + "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "translatable", - "property_type": null, + "property": "reqd", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, "value": "1" }, { @@ -1742,23 +2604,30 @@ "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2018-03-31 16:34:27.679062", + "creation": "2017-06-28 11:40:24.080276", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "pincode", + "field_name": "address_type", "idx": 0, - "modified": "2018-03-31 16:34:27.679062", - "modified_by": "aditya@rigpl.com", - "name": "Address-pincode-in_standard_filter", - "owner": "aditya@rigpl.com", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.464209", + "modified_by": "Administrator", + "module": null, + "name": "Address-address_type-width", + "owner": "abhinav@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "in_standard_filter", - "property_type": "Check", - "value": "1" + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "96" }, { "_assign": null, @@ -1767,13 +2636,16 @@ "_user_tags": null, "creation": "2018-03-31 16:26:29.380766", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", "field_name": "city", "idx": 0, - "modified": "2018-03-31 16:26:29.380766", - "modified_by": "aditya@rigpl.com", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.338485", + "modified_by": "Administrator", + "module": null, "name": "Address-city-in_standard_filter", "owner": "aditya@rigpl.com", "parent": null, @@ -1781,31 +2653,12 @@ "parenttype": null, "property": "in_standard_filter", "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, "value": "1" }, - { - "_assign": null, - "_comments": null, - "_liked_by": null, - "_user_tags": null, - "creation": "2017-08-02 18:49:02.648335", - "default_value": null, - "doc_type": "Address", - "docstatus": 0, - "doctype_or_field": "DocField", - "field_name": "pincode", - "idx": 0, - "modified": "2017-08-02 18:49:02.648335", - "modified_by": "aditya@rigpl.com", - "name": "Address-pincode-width", - "owner": "aditya@rigpl.com", - "parent": null, - "parentfield": null, - "parenttype": null, - "property": "width", - "property_type": null, - "value": "213" - }, { "_assign": null, "_comments": null, @@ -1813,13 +2666,16 @@ "_user_tags": null, "creation": "2017-06-30 10:45:26.742653", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", "field_name": "city", "idx": 0, - "modified": "2017-06-30 10:45:26.742653", - "modified_by": "abhinav@rigpl.com", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.386242", + "modified_by": "Administrator", + "module": null, "name": "Address-city-width", "owner": "abhinav@rigpl.com", "parent": null, @@ -1827,6 +2683,10 @@ "parenttype": null, "property": "width", "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, "value": "105" }, { @@ -1834,46 +2694,60 @@ "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2017-06-28 12:16:17.618710", + "creation": "2016-07-14 19:31:06.705013", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "gstin", + "field_name": "company", "idx": 0, - "modified": "2017-06-28 12:16:17.618710", - "modified_by": "abhinav@rigpl.com", - "name": "Address-gstin-width", - "owner": "abhinav@rigpl.com", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.575395", + "modified_by": "Administrator", + "module": null, + "name": "Address-company-permlevel", + "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "width", - "property_type": null, - "value": "210" + "property": "permlevel", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2017-06-28 12:08:29.189605", + "creation": "2018-11-22 18:07:33.333222", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "phone", + "field_name": "country", "idx": 0, - "modified": "2017-06-28 12:08:29.189605", - "modified_by": "abhinav@rigpl.com", - "name": "Address-phone-width", - "owner": "abhinav@rigpl.com", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.211148", + "modified_by": "Administrator", + "module": null, + "name": "Address-country-ignore_user_permissions", + "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "width", - "property_type": null, - "value": "168" + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" }, { "_assign": null, @@ -1882,13 +2756,16 @@ "_user_tags": null, "creation": "2017-06-28 11:46:43.176278", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", "field_name": "country", "idx": 0, - "modified": "2017-06-28 11:46:43.176278", - "modified_by": "abhinav@rigpl.com", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.428606", + "modified_by": "Administrator", + "module": null, "name": "Address-country-width", "owner": "abhinav@rigpl.com", "parent": null, @@ -1896,6 +2773,10 @@ "parenttype": null, "property": "width", "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, "value": "80" }, { @@ -1903,137 +2784,179 @@ "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2017-06-28 11:40:24.080276", + "creation": "2017-01-17 10:50:56.379960", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "address_type", + "field_name": "county", "idx": 0, - "modified": "2017-06-28 11:40:24.080276", - "modified_by": "abhinav@rigpl.com", - "name": "Address-address_type-width", - "owner": "abhinav@rigpl.com", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.534163", + "modified_by": "Administrator", + "module": null, + "name": "Address-county-hidden", + "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "width", - "property_type": null, - "value": "96" + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2017-05-23 12:42:13.021433", + "creation": "2017-01-17 10:50:56.375227", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "state", + "field_name": "county", "idx": 0, - "modified": "2017-05-23 12:42:13.021433", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.548284", "modified_by": "Administrator", - "name": "Address-state-options", - "owner": "Administrator", + "module": null, + "name": "Address-county-read_only", + "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "options", - "property_type": "Text", - "value": "" + "property": "read_only", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2017-04-22 11:30:14.631078", + "creation": "2017-01-17 10:53:40.347615", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, - "doctype_or_field": "DocType", - "field_name": null, + "doctype_or_field": "DocField", + "field_name": "county", "idx": 0, - "modified": "2017-04-22 11:30:14.631078", - "modified_by": "aditya@rigpl.com", - "name": "Address-track_changes", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.505986", + "modified_by": "Administrator", + "module": null, + "name": "Address-county-width", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "track_changes", - "property_type": "Check", - "value": "1" + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "86" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2017-01-17 10:53:40.347615", + "creation": "2015-11-25 10:40:06.284980", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "county", + "field_name": "customer_name", "idx": 0, - "modified": "2017-01-17 10:53:40.347615", - "modified_by": "aditya@rigpl.com", - "name": "Address-county-width", - "owner": "aditya@rigpl.com", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.618363", + "modified_by": "Administrator", + "module": null, + "name": "Address-customer_name-width", + "owner": "abhinav@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, "property": "width", "property_type": null, - "value": "86" + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "43" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2017-01-17 10:53:37.766561", + "creation": "2014-01-16 10:27:47", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "state", + "field_name": "customer", "idx": 0, - "modified": "2017-01-17 10:53:37.766561", - "modified_by": "aditya@rigpl.com", - "name": "Address-state-width", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.719774", + "modified_by": "Administrator", + "module": null, + "name": "Address-customer-width", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, "property": "width", "property_type": null, - "value": "177" + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "194" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2017-01-17 10:50:56.379960", + "creation": "2021-02-13 11:37:48.321869", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "county", + "field_name": "email_id", "idx": 0, - "modified": "2017-01-17 10:50:56.379960", - "modified_by": "aditya@rigpl.com", - "name": "Address-county-hidden", - "owner": "aditya@rigpl.com", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.093304", + "modified_by": "Administrator", + "module": null, + "name": "Address-email_id-in_standard_filter", + "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, - "property": "hidden", + "property": "in_standard_filter", "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, "value": "1" }, { @@ -2041,69 +2964,90 @@ "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2017-01-17 10:50:56.375227", + "creation": "2015-11-25 10:38:32.684995", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "county", + "field_name": "email_id", "idx": 0, - "modified": "2017-01-17 10:50:56.375227", - "modified_by": "aditya@rigpl.com", - "name": "Address-county-read_only", - "owner": "aditya@rigpl.com", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.632330", + "modified_by": "Administrator", + "module": null, + "name": "Address-email_id-width", + "owner": "abhinav@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "read_only", - "property_type": "Check", - "value": "1" + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "248" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2017-01-17 10:50:56.369549", + "creation": "2015-02-16 18:02:02.375195", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "address_line1", + "field_name": "excise_no", "idx": 0, - "modified": "2017-01-17 10:50:56.369549", - "modified_by": "aditya@rigpl.com", - "name": "Address-address_line1-length", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.687749", + "modified_by": "Administrator", + "module": null, + "name": "Address-excise_no-width", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "length", - "property_type": "Int", - "value": "250" + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "216" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2016-07-14 19:31:06.705013", + "creation": "2017-06-28 12:16:17.618710", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "company", + "field_name": "gstin", "idx": 0, - "modified": "2016-07-14 19:31:06.705013", - "modified_by": "aditya@rigpl.com", - "name": "Address-company-permlevel", - "owner": "aditya@rigpl.com", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.399950", + "modified_by": "Administrator", + "module": null, + "name": "Address-gstin-width", + "owner": "abhinav@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "permlevel", - "property_type": "Int", - "value": "1" + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "210" }, { "_assign": null, @@ -2112,13 +3056,16 @@ "_user_tags": null, "creation": "2016-07-14 19:31:06.690460", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", "field_name": "is_your_company_address", "idx": 0, - "modified": "2016-07-14 19:31:06.690460", - "modified_by": "aditya@rigpl.com", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.589754", + "modified_by": "Administrator", + "module": null, "name": "Address-is_your_company_address-permlevel", "owner": "aditya@rigpl.com", "parent": null, @@ -2126,6 +3073,10 @@ "parenttype": null, "property": "permlevel", "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, "value": "1" }, { @@ -2135,20 +3086,27 @@ "_user_tags": null, "creation": "2015-12-30 14:57:06.953763", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocType", "field_name": null, "idx": 0, - "modified": "2015-12-30 14:57:06.953763", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.603884", "modified_by": "Administrator", - "name": "Address-_idx", + "module": null, + "name": "Address-main-_idx", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "property": "_idx", "property_type": "Text", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, "value": "[\"address_details\", \"address_title\", \"address_type\", \"address_line1\", \"address_line2\", \"city\", \"state\", \"pincode\", \"country\", \"column_break0\", \"email_id\", \"phone\", \"fax\", \"tin_no\", \"excise_no\", \"service_tax_no\", \"is_primary_address\", \"is_shipping_address\", \"linked_with\", \"customer\", \"customer_name\", \"supplier\", \"supplier_name\", \"sales_partner\", \"column_break_22\", \"lead\", \"lead_name\"]" }, { @@ -2156,114 +3114,179 @@ "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2015-11-25 10:40:06.284980", + "creation": "2025-10-08 10:54:31.851413", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, - "doctype_or_field": "DocField", - "field_name": "customer_name", + "doctype_or_field": "DocType", + "field_name": null, "idx": 0, - "modified": "2015-11-25 10:40:06.284980", - "modified_by": "abhinav@rigpl.com", - "name": "Address-customer_name-width", - "owner": "abhinav@rigpl.com", + "is_system_generated": 0, + "modified": "2025-10-08 10:54:31.851413", + "modified_by": "Administrator", + "module": null, + "name": "Address-main-field_order", + "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, - "property": "width", - "property_type": null, - "value": "43" + "property": "field_order", + "property_type": "Data", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "[\"address_details\", \"address_title\", \"address_type\", \"address_line1\", \"address_line2\", \"city\", \"county\", \"state_rigpl\", \"state\", \"country\", \"pincode\", \"known_states\", \"sea_port\", \"airport\", \"column_break0\", \"email_id\", \"email_address_validated\", \"phone\", \"fax\", \"gstin\", \"gst_state\", \"gst_state_number\", \"pan\", \"tin_no\", \"excise_no\", \"service_tax_no\", \"latitude\", \"longitude\", \"global_google_code\", \"is_residential\", \"tax_category\", \"tax_details_column_break\", \"gst_category\", \"is_primary_address\", \"is_shipping_address\", \"dont_update_from_google\", \"approximate_location\", \"update_from_google\", \"disabled\", \"linked_with\", \"is_your_company_address\", \"links\", \"maps_section\", \"location\", \"gst_validation_data\", \"validated_gstin\", \"gstin_json_reply\", \"cb0\", \"gst_status\", \"gst_validation_date\", \"json_reply\", \"google_maps_view\"]" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2015-11-25 10:38:32.684995", + "creation": "2012-03-29 16:16:12", + "default_value": "1", + "doc_name": null, + "doc_type": "Address", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": null, + "idx": 0, + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.734012", + "modified_by": "Administrator", + "module": null, + "name": "Address-main-in_dialog", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_dialog", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2020-10-10 18:09:41.920168", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, - "doctype_or_field": "DocField", - "field_name": "email_id", + "doctype_or_field": "DocType", + "field_name": null, "idx": 0, - "modified": "2015-11-25 10:38:32.684995", - "modified_by": "abhinav@rigpl.com", - "name": "Address-email_id-width", - "owner": "abhinav@rigpl.com", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.182158", + "modified_by": "Administrator", + "module": null, + "name": "Address-main-search_fields", + "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "width", - "property_type": null, - "value": "248" + "property": "search_fields", + "property_type": "Data", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "address_title, address_line1, address_line2, city, state, pincode, country, email_id, gstin, phone" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2015-11-25 10:38:20.528122", + "creation": "2017-04-22 11:30:14.631078", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, - "doctype_or_field": "DocField", - "field_name": "address_line2", + "doctype_or_field": "DocType", + "field_name": null, "idx": 0, - "modified": "2015-11-25 10:38:20.528122", - "modified_by": "abhinav@rigpl.com", - "name": "Address-address_line2-width", - "owner": "abhinav@rigpl.com", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.492054", + "modified_by": "Administrator", + "module": null, + "name": "Address-main-track_changes", + "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "width", - "property_type": null, - "value": "30" + "property": "track_changes", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2015-11-25 10:38:20.107511", + "creation": "2017-06-28 12:08:29.189605", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "address_line1", + "field_name": "phone", "idx": 0, - "modified": "2015-11-25 10:38:20.107511", - "modified_by": "abhinav@rigpl.com", - "name": "Address-address_line1-width", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.414238", + "modified_by": "Administrator", + "module": null, + "name": "Address-phone-width", "owner": "abhinav@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, "property": "width", "property_type": null, - "value": "353" + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "168" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2015-07-02 11:59:11.673217", + "creation": "2018-03-31 16:34:27.679062", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "address_title", + "field_name": "pincode", "idx": 0, - "modified": "2015-07-02 11:59:11.673217", - "modified_by": "aditya@rigpl.com", - "name": "Address-address_title-reqd", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.295246", + "modified_by": "Administrator", + "module": null, + "name": "Address-pincode-in_standard_filter", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "reqd", + "property": "in_standard_filter", "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, "value": "1" }, { @@ -2271,92 +3294,150 @@ "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2015-02-16 18:02:02.375195", + "creation": "2017-08-02 18:49:02.648335", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "excise_no", + "field_name": "pincode", "idx": 0, - "modified": "2015-02-16 18:02:02.375195", - "modified_by": "aditya@rigpl.com", - "name": "Address-excise_no-width", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.366987", + "modified_by": "Administrator", + "module": null, + "name": "Address-pincode-width", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, "property": "width", "property_type": null, - "value": "216" + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "213" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2014-12-26 11:11:35.636068", + "creation": "2020-08-11 14:44:45.118963", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "supplier", + "field_name": "state", "idx": 0, - "modified": "2014-12-26 11:11:35.636068", - "modified_by": "aditya@rigpl.com", - "name": "Address-supplier-width", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.196936", + "modified_by": "Administrator", + "module": null, + "name": "Address-state-depends_on", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "width", - "property_type": null, - "value": "312" + "property": "depends_on", + "property_type": "Data", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "eval: !doc.state_rigpl" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2014-01-16 10:27:47", + "creation": "2017-05-23 12:42:13.021433", "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "customer", + "field_name": "state", "idx": 0, - "modified": "2014-01-16 10:27:47", - "modified_by": "aditya@rigpl.com", - "name": "Address-customer-width", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.478529", + "modified_by": "Administrator", + "module": null, + "name": "Address-state-options", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "options", + "property_type": "Text", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-01-17 10:53:37.766561", + "default_value": null, + "doc_name": null, + "doc_type": "Address", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "state", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.519793", + "modified_by": "Administrator", + "module": null, + "name": "Address-state-width", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, "property": "width", "property_type": null, - "value": "194" + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "177" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2012-03-29 16:16:12", - "default_value": "1", + "creation": "2014-12-26 11:11:35.636068", + "default_value": null, + "doc_name": null, "doc_type": "Address", "docstatus": 0, - "doctype_or_field": "DocType", - "field_name": null, + "doctype_or_field": "DocField", + "field_name": "supplier", "idx": 0, - "modified": "2012-03-29 16:16:12", + "is_system_generated": 0, + "modified": "2025-09-30 13:07:50.706743", "modified_by": "Administrator", - "name": "Address-Address-in_dialog", - "owner": "Administrator", + "module": null, + "name": "Address-supplier-width", + "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "in_dialog", - "property_type": "Check", - "value": "0" + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "312" } ], "sync_on_migrate": 1 diff --git a/rohit_common/rohit_common/custom/packed_item.json b/rohit_common/rohit_common/custom/packed_item.json new file mode 100644 index 0000000..53637ee --- /dev/null +++ b/rohit_common/rohit_common/custom/packed_item.json @@ -0,0 +1,39 @@ +{ + "custom_fields": [], + "custom_perms": [], + "doctype": "Packed Item", + "links": [], + "property_setters": [ + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-09-13 20:05:50.321303", + "default_value": null, + "doc_name": null, + "doc_type": "Packed Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "rate", + "idx": 0, + "is_system_generated": 1, + "modified": "2025-09-13 20:05:50.321303", + "modified_by": "Administrator", + "module": null, + "name": "Packed Item-rate-read_only", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "read_only", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + } + ], + "sync_on_migrate": 1 +} \ No newline at end of file diff --git a/rohit_common/rohit_common/custom/sales_invoice.json b/rohit_common/rohit_common/custom/sales_invoice.json index 33b9da4..bdbb8b2 100644 --- a/rohit_common/rohit_common/custom/sales_invoice.json +++ b/rohit_common/rohit_common/custom/sales_invoice.json @@ -6,56 +6,70 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, "creation": "2012-05-02 10:03:06", - "default": null, + "default": "NA", "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "ship_terms", - "fieldtype": "Select", + "fieldname": "lr_no", + "fieldtype": "Data", "hidden": 0, - "idx": 19, - "ignore_user_permissions": 1, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 275, + "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": 0.0, - "insert_after": "offline_pos_name", - "label": "Shipping Terms", + "insert_after": "vehicle_no", + "is_system_generated": 0, + "is_virtual": 0, + "label": "LR No", "length": 0, - "modified": "2016-08-01 20:11:23.912350", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2016-08-01 20:11:27.720886", "modified_by": "aditya@rigpl.com", - "name": "Receivable Voucher-ship_terms", + "module": "GST India", + "name": "Receivable Voucher-lr_no", "no_copy": 0, - "options": "\nEXW-Ex Works\nCPT-Transport Paid\nCIP-Transport & Insurance Paid\nCIF-Cost Insurance & Freight\nCFR-Cost & Freight\nFOB-Free on Board\nDDU-Delivered Duty Unpaid", + "non_negative": 0, + "options": null, "owner": "aditya@rigpl.com", "parent": null, "parentfield": "fields", "parenttype": "DocType", "permlevel": 0, - "precision": null, + "placeholder": null, + "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 1, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, - "width": null + "width": "116" }, { "_assign": null, @@ -63,12 +77,12 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2012-05-02 10:03:06", + "creation": "2012-05-02 10:03:05", "default": null, "depends_on": null, "description": null, @@ -76,43 +90,57 @@ "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "transporters", - "fieldtype": "Link", + "fieldname": "removal_date", + "fieldtype": "Date", "hidden": 0, - "idx": 20, - "ignore_user_permissions": 1, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 24, + "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": 0.0, - "insert_after": "ship_terms", - "label": "Transporter Name", + "insert_after": "background_processing", + "is_system_generated": 0, + "is_virtual": 0, + "label": "Removal Date", "length": 0, - "modified": "2016-08-01 20:11:25.562279", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2016-08-01 20:11:35.096231", "modified_by": "aditya@rigpl.com", - "name": "Receivable Voucher-transporters", + "module": null, + "name": "Receivable Voucher-removal_date", "no_copy": 0, - "options": "Transporters", + "non_negative": 0, + "options": null, "owner": "aditya@rigpl.com", "parent": null, "parentfield": "fields", "parenttype": "DocType", "permlevel": 0, - "precision": null, + "placeholder": null, + "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 1, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, - "width": "114" + "width": "93" }, { "_assign": null, @@ -120,56 +148,70 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2012-05-02 10:03:06", - "default": "NA", + "creation": "2012-05-02 10:03:05", + "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "lr_no", - "fieldtype": "Data", + "fieldname": "removal_time", + "fieldtype": "Time", "hidden": 0, - "idx": 21, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 25, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": 0.0, - "insert_after": "transporters", - "label": "LR No", + "insert_after": "removal_date", + "is_system_generated": 0, + "is_virtual": 0, + "label": "Removal Time", "length": 0, - "modified": "2016-08-01 20:11:27.720886", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2016-08-01 20:11:40.129433", "modified_by": "aditya@rigpl.com", - "name": "Receivable Voucher-lr_no", + "module": null, + "name": "Receivable Voucher-removal_time", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "aditya@rigpl.com", "parent": null, "parentfield": "fields", "parenttype": "DocType", "permlevel": 0, - "precision": null, + "placeholder": null, + "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 1, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, - "width": "116" + "width": null }, { "_assign": null, @@ -177,12 +219,12 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2012-05-02 10:03:05", + "creation": "2012-05-02 10:03:06", "default": null, "depends_on": null, "description": null, @@ -190,39 +232,53 @@ "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "ship_to", - "fieldtype": "Data", + "fieldname": "ship_terms", + "fieldtype": "Select", "hidden": 0, - "idx": 75, - "ignore_user_permissions": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 277, + "ignore_user_permissions": 1, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": 0.0, - "insert_after": "shipping_address_gstin", - "label": "Ship To", - "length": 180, - "modified": "2016-08-01 20:11:33.499507", + "insert_after": "transporters", + "is_system_generated": 0, + "is_virtual": 0, + "label": "Shipping Terms", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2016-08-01 20:11:23.912350", "modified_by": "aditya@rigpl.com", - "name": "Receivable Voucher-ship_to", + "module": null, + "name": "Receivable Voucher-ship_terms", "no_copy": 0, - "options": null, - "owner": "Administrator", + "non_negative": 0, + "options": "\nEXW-Ex Works\nCPT-Transport Paid\nCIP-Transport & Insurance Paid\nCIF-Cost Insurance & Freight\nCFR-Cost & Freight\nFOB-Free on Board\nDDU-Delivered Duty Unpaid", + "owner": "aditya@rigpl.com", "parent": null, "parentfield": "fields", "parenttype": "DocType", "permlevel": 0, - "precision": null, + "placeholder": null, + "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 1, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, @@ -234,7 +290,7 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, @@ -247,43 +303,57 @@ "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "removal_date", - "fieldtype": "Date", + "fieldname": "ship_to", + "fieldtype": "Data", "hidden": 0, - "idx": 41, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 75, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": 0.0, - "insert_after": "background_processing", - "label": "Removal Date", - "length": 0, - "modified": "2016-08-01 20:11:35.096231", + "insert_after": "shipping_address_gstin", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Ship To", + "length": 180, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2016-08-01 20:11:33.499507", "modified_by": "aditya@rigpl.com", - "name": "Receivable Voucher-removal_date", + "module": null, + "name": "Receivable Voucher-ship_to", "no_copy": 0, + "non_negative": 0, "options": null, - "owner": "aditya@rigpl.com", + "owner": "Administrator", "parent": null, "parentfield": "fields", "parenttype": "DocType", "permlevel": 0, + "placeholder": null, "precision": null, "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 1, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, - "width": "93" + "width": null }, { "_assign": null, @@ -291,12 +361,12 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2012-05-02 10:03:05", + "creation": "2012-05-02 10:03:06", "default": null, "depends_on": null, "description": null, @@ -304,43 +374,57 @@ "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "removal_time", - "fieldtype": "Time", + "fieldname": "transporters", + "fieldtype": "Link", "hidden": 0, - "idx": 42, - "ignore_user_permissions": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 276, + "ignore_user_permissions": 1, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": 0.0, - "insert_after": "removal_date", - "label": "Removal Time", + "insert_after": "lr_no", + "is_system_generated": 0, + "is_virtual": 0, + "label": "Transporter Name", "length": 0, - "modified": "2016-08-01 20:11:40.129433", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2016-08-01 20:11:25.562279", "modified_by": "aditya@rigpl.com", - "name": "Receivable Voucher-removal_time", + "module": null, + "name": "Receivable Voucher-transporters", "no_copy": 0, - "options": null, + "non_negative": 0, + "options": "Transporters", "owner": "aditya@rigpl.com", "parent": null, "parentfield": "fields", "parenttype": "DocType", "permlevel": 0, - "precision": null, + "placeholder": null, + "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 1, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, - "width": null + "width": "114" }, { "_assign": null, @@ -353,51 +437,65 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2017-06-24 18:04:50.783580", - "default": "NA", + "creation": "2021-01-07 21:25:49.731425", + "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "billing_address_gstin", + "fieldname": "ack_date", "fieldtype": "Data", - "hidden": 0, - "idx": 59, + "hidden": 1, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 11, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "index": 0.0, - "insert_after": "customer_address", - "label": "Billing Address GSTIN", - "length": 15, - "modified": "2017-06-24 18:04:50.783580", + "index": null, + "insert_after": "ack_no", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Ack. Date", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2021-01-07 21:25:49.731425", "modified_by": "Administrator", - "name": "Sales Invoice-billing_address_gstin", - "no_copy": 0, + "module": null, + "name": "Sales Invoice-ack_date", + "no_copy": 1, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, - "reqd": 1, + "reqd": 0, "search_index": 0, - "translatable": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, "trash_reason": null, "unique": 0, - "width": "144" + "width": null }, { "_assign": null, @@ -410,51 +508,65 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2017-06-24 18:05:17.908154", - "default": "NA", + "creation": "2021-01-07 21:25:26.182634", + "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "shipping_address_gstin", + "fieldname": "ack_no", "fieldtype": "Data", - "hidden": 0, - "idx": 74, + "hidden": 1, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 10, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "index": 0.0, - "insert_after": "shipping_excise_no", - "label": "Shipping Address GSTIN", + "index": null, + "insert_after": "irn", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Ack. No.", "length": 0, - "modified": "2017-06-24 18:05:17.908154", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2021-01-07 21:25:26.182634", "modified_by": "Administrator", - "name": "Sales Invoice-shipping_address_gstin", - "no_copy": 0, + "module": null, + "name": "Sales Invoice-ack_no", + "no_copy": 1, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, - "reqd": 1, + "reqd": 0, "search_index": 0, - "translatable": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, "trash_reason": null, "unique": 0, - "width": "170" + "width": null }, { "_assign": null, @@ -462,12 +574,12 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, - "collapsible": 1, + "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:38:43.217975", + "creation": "2022-02-05 16:20:25.944618", "default": null, "depends_on": null, "description": null, @@ -475,39 +587,53 @@ "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "gst_section", - "fieldtype": "Section Break", + "fieldname": "background_processing", + "fieldtype": "Check", "hidden": 0, - "idx": 190, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 39, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "language", - "label": "GST Details", + "insert_after": "marked_to_submit", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Background Processing", "length": 0, - "modified": "2020-08-07 17:16:42.104616", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2022-02-05 16:20:25.944618", "modified_by": "Administrator", - "name": "Sales Invoice-gst_section", + "module": null, + "name": "Sales Invoice-background_processing", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, - "permlevel": 0, + "permlevel": 1, + "placeholder": null, "precision": "", - "print_hide": 1, + "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, @@ -519,56 +645,70 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:38:46.715455", - "default": null, + "creation": "2017-06-24 18:04:50.783580", + "default": "NA", "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", - "fetch_from": "customer.gst_category", - "fetch_if_empty": 1, - "fieldname": "gst_category", - "fieldtype": "Select", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "billing_address_gstin", + "fieldtype": "Data", "hidden": 0, - "idx": 191, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 59, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "index": null, - "insert_after": "gst_section", - "label": "GST Category", - "length": 0, - "modified": "2020-08-07 17:16:45.516062", + "index": 0.0, + "insert_after": "customer_address", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Billing Address GSTIN", + "length": 15, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2017-06-24 18:04:50.783580", "modified_by": "Administrator", - "name": "Sales Invoice-gst_category", + "module": "GST India", + "name": "Sales Invoice-billing_address_gstin", "no_copy": 0, - "options": "\nRegistered Regular\nRegistered Composition\nUnregistered\nSEZ\nOverseas\nConsumer\nDeemed Export\nUIN Holders", + "non_negative": 0, + "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 1, + "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, - "reqd": 0, + "reqd": 1, "search_index": 0, - "translatable": 1, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, "trash_reason": null, "unique": 0, - "width": null + "width": "144" }, { "_assign": null, @@ -576,52 +716,66 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:38:59.323639", + "creation": "2020-07-04 10:39:39.135855", "default": null, - "depends_on": "eval:in_list([\"SEZ\", \"Overseas\", \"Deemed Export\"], doc.gst_category)", + "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", - "fetch_from": "customer.export_type", - "fetch_if_empty": 1, - "fieldname": "export_type", - "fieldtype": "Select", + "fetch_from": "company_address.gstin", + "fetch_if_empty": 0, + "fieldname": "company_gstin", + "fieldtype": "Data", "hidden": 0, - "idx": 192, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 78, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "gst_category", - "label": "Export Type", - "length": 0, - "modified": "2020-08-07 17:16:48.578061", + "insert_after": "company_address", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Company GSTIN", + "length": 15, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:17:25.502131", "modified_by": "Administrator", - "name": "Sales Invoice-export_type", + "module": "GST India", + "name": "Sales Invoice-company_gstin", "no_copy": 0, - "options": "\nWith Payment of Tax\nWithout Payment of Tax", + "non_negative": 0, + "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 1, "trash_reason": null, "unique": 0, @@ -633,52 +787,66 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:39:02.554049", + "creation": "2020-07-04 10:39:32.355064", "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", - "fetch_from": null, + "fetch_from": "shipping_address_name.gstin", "fetch_if_empty": 0, - "fieldname": "invoice_copy", - "fieldtype": "Select", + "fieldname": "customer_gstin", + "fieldtype": "Data", "hidden": 0, - "idx": 193, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 70, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "export_type", - "label": "Invoice Copy", - "length": 0, - "modified": "2020-08-07 17:16:51.656477", + "insert_after": "shipping_address_name", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Customer GSTIN", + "length": 15, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:17:19.393252", "modified_by": "Administrator", - "name": "Sales Invoice-invoice_copy", + "module": null, + "name": "Sales Invoice-customer_gstin", "no_copy": 0, - "options": "Original for Recipient\nDuplicate for Transporter\nDuplicate for Supplier\nTriplicate for Supplier", + "non_negative": 0, + "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 1, "trash_reason": null, "unique": 0, @@ -695,48 +863,62 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:39:05.754965", - "default": "N", + "creation": "2020-07-04 10:40:01.923912", + "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "reverse_charge", - "fieldtype": "Select", + "fieldname": "distance", + "fieldtype": "Float", "hidden": 0, - "idx": 194, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 23, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "invoice_copy", - "label": "Reverse Charge", + "insert_after": "vehicle_no", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Distance (in km)", "length": 0, - "modified": "2020-08-07 17:16:54.733476", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:17:46.238453", "modified_by": "Administrator", - "name": "Sales Invoice-reverse_charge", + "module": "GST India", + "name": "Sales Invoice-distance", "no_copy": 0, - "options": "Y\nN", + "non_negative": 0, + "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 1, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, "trash_reason": null, "unique": 0, "width": null @@ -752,7 +934,7 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:39:08.909161", + "creation": "2020-07-04 10:39:52.291682", "default": null, "depends_on": null, "description": null, @@ -760,40 +942,54 @@ "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "ecommerce_gstin", - "fieldtype": "Data", + "fieldname": "driver", + "fieldtype": "Link", "hidden": 0, - "idx": 195, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 183, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "reverse_charge", - "label": "E-commerce GSTIN", + "insert_after": "gst_transporter_id", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Driver", "length": 0, - "modified": "2020-08-07 17:16:57.840544", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:17:37.157205", "modified_by": "Administrator", - "name": "Sales Invoice-ecommerce_gstin", + "module": "GST India", + "name": "Sales Invoice-driver", "no_copy": 0, - "options": null, + "non_negative": 0, + "options": "Driver", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 1, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, "trash_reason": null, "unique": 0, "width": null @@ -809,47 +1005,61 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:39:12.060675", + "creation": "2020-07-04 10:40:15.297916", "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", - "fetch_from": null, + "fetch_from": "driver.full_name", "fetch_if_empty": 0, - "fieldname": "gst_col_break", - "fieldtype": "Column Break", + "fieldname": "driver_name", + "fieldtype": "Data", "hidden": 0, - "idx": 196, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 30, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "ecommerce_gstin", - "label": null, + "insert_after": "mode_of_transport", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Driver Name", "length": 0, - "modified": "2020-08-07 17:17:00.982276", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:17:58.488300", "modified_by": "Administrator", - "name": "Sales Invoice-gst_col_break", + "module": "GST India", + "name": "Sales Invoice-driver_name", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, @@ -861,52 +1071,66 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:39:15.242498", + "creation": "2025-08-29 14:43:27.434275", "default": null, - "depends_on": "eval:doc.is_return==1", + "depends_on": "eval:doc.docstatus === 1 && !doc.ewaybill", "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "reason_for_issuing_document", + "fieldname": "e_waybill_status", "fieldtype": "Select", "hidden": 0, - "idx": 197, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "gst_col_break", - "label": "Reason For Issuing document", + "insert_after": "ewaybill", + "is_system_generated": 1, + "is_virtual": 0, + "label": "e-Waybill Status", "length": 0, - "modified": "2020-08-07 17:17:04.066008", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:27.434275", "modified_by": "Administrator", - "name": "Sales Invoice-reason_for_issuing_document", - "no_copy": 0, - "options": "\n01-Sales Return\n02-Post Sale Discount\n03-Deficiency in services\n04-Correction in Invoice\n05-Change in POS\n06-Finalization of Provisional assessment\n07-Others", + "module": "GST India", + "name": "Sales Invoice-e_waybill_status", + "no_copy": 1, + "non_negative": 0, + "options": "\nPending\nGenerated\nAuto-Retry\nCancelled\nNot Applicable\nManually Generated\nManually Cancelled", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": "eval:doc.ewaybill", "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 1, "trash_reason": null, "unique": 0, @@ -923,47 +1147,61 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:39:18.579350", + "creation": "2020-07-04 10:39:08.909161", "default": null, - "depends_on": "eval:doc.gst_category=='Overseas' ", + "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "port_code", + "fieldname": "ecommerce_gstin", "fieldtype": "Data", "hidden": 0, - "idx": 198, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 195, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "reason_for_issuing_document", - "label": "Port Code", + "insert_after": "reverse_charge", + "is_system_generated": 1, + "is_virtual": 0, + "label": "E-commerce GSTIN", "length": 0, - "modified": "2020-08-07 17:17:07.176905", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:16:57.840544", "modified_by": "Administrator", - "name": "Sales Invoice-port_code", + "module": "GST India", + "name": "Sales Invoice-ecommerce_gstin", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 1, "trash_reason": null, "unique": 0, @@ -975,53 +1213,67 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:39:21.815353", + "creation": "2025-08-29 14:43:23.716698", "default": null, - "depends_on": "eval:doc.gst_category=='Overseas' ", + "depends_on": "eval:gst_settings.enable_sales_through_ecommerce_operators && doc.ecommerce_gstin", "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "shipping_bill_number", + "fieldname": "ecommerce_supply_type", "fieldtype": "Data", "hidden": 0, - "idx": 199, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "port_code", - "label": " Shipping Bill Number", + "insert_after": "ecommerce_gstin", + "is_system_generated": 1, + "is_virtual": 1, + "label": "E-commerce Supply Type", "length": 0, - "modified": "2020-08-07 17:17:10.288321", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:23.716698", "modified_by": "Administrator", - "name": "Sales Invoice-shipping_bill_number", + "module": "GST India", + "name": "Sales Invoice-ecommerce_supply_type", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 1, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, "trash_reason": null, "unique": 0, "width": null @@ -1037,48 +1289,62 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:39:25.348204", + "creation": "2025-08-29 14:43:27.210997", "default": null, - "depends_on": "eval:doc.gst_category=='Overseas' ", + "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "shipping_bill_date", - "fieldtype": "Date", + "fieldname": "einvoice_status", + "fieldtype": "Select", "hidden": 0, - "idx": 200, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "shipping_bill_number", - "label": "Shipping Bill Date", + "insert_after": "status", + "is_system_generated": 1, + "is_virtual": 0, + "label": "e-Invoice Status", "length": 0, - "modified": "2020-08-07 17:17:13.353736", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-09-10 13:43:47.192776", "modified_by": "Administrator", - "name": "Sales Invoice-shipping_bill_date", - "no_copy": 0, - "options": null, + "module": "GST India", + "name": "Sales Invoice-einvoice_status", + "no_copy": 1, + "non_negative": 0, + "options": "\nPending\nGenerated\nManually Generated\nAuto-Retry\nCancelled\nManually Cancelled\nFailed\nNot Applicable\nPending Cancellation", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, "trash_reason": null, "unique": 0, "width": null @@ -1089,53 +1355,67 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:39:32.355064", + "creation": "2021-01-07 21:26:41.379141", "default": null, - "depends_on": null, + "depends_on": "eval:(doc.eway_bill_cancelled === 1)", "description": null, "docstatus": 0, "dt": "Sales Invoice", - "fetch_from": "shipping_address_name.gstin", + "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "customer_gstin", - "fieldtype": "Data", + "fieldname": "eway_bill_cancelled", + "fieldtype": "Check", "hidden": 0, - "idx": 70, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 12, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "shipping_address_name", - "label": "Customer GSTIN", - "length": 15, - "modified": "2020-08-07 17:17:19.393252", + "insert_after": "ack_date", + "is_system_generated": 1, + "is_virtual": 0, + "label": "E-Way Bill Cancelled", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2021-01-07 21:26:41.379141", "modified_by": "Administrator", - "name": "Sales Invoice-customer_gstin", - "no_copy": 0, + "module": null, + "name": "Sales Invoice-eway_bill_cancelled", + "no_copy": 1, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 1, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, "trash_reason": null, "unique": 0, "width": null @@ -1146,53 +1426,67 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:39:35.747072", + "creation": "2020-07-04 10:40:25.165602", "default": null, - "depends_on": null, + "depends_on": "eval:(doc.docstatus === 1)", "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "place_of_supply", + "fieldname": "ewaybill", "fieldtype": "Data", "hidden": 0, - "idx": 71, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 15, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "customer_gstin", - "label": "Place of Supply", + "insert_after": "tax_id", + "is_system_generated": 1, + "is_virtual": 0, + "label": "E-Way Bill No.", "length": 0, - "modified": "2020-08-07 17:17:22.487673", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:18:07.689669", "modified_by": "Administrator", - "name": "Sales Invoice-place_of_supply", + "module": "GST India", + "name": "Sales Invoice-ewaybill", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 1, + "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 1, + "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 1, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, "trash_reason": null, "unique": 0, "width": null @@ -1208,47 +1502,61 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:39:39.135855", + "creation": "2021-04-26 20:32:51.855389", "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", - "fetch_from": "company_address.gstin", + "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "company_gstin", + "fieldname": "excise_no", "fieldtype": "Data", - "hidden": 0, - "idx": 78, + "hidden": 1, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 61, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "company_address", - "label": "Company GSTIN", - "length": 15, - "modified": "2020-08-07 17:17:25.502131", + "insert_after": "tin_no", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Excise No", + "length": 50, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2021-04-26 20:32:51.855389", "modified_by": "Administrator", - "name": "Sales Invoice-company_gstin", + "module": null, + "name": "Sales Invoice-excise_no", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 1, + "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 1, "trash_reason": null, "unique": 0, @@ -1260,53 +1568,67 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, - "collapsible": 1, - "collapsible_depends_on": "transporter", + "collapsible": 0, + "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:39:42.525025", + "creation": "2020-09-25 14:30:05.781690", "default": null, - "depends_on": null, + "depends_on": "eval:doc.export_type", "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "transporter_info", - "fieldtype": "Section Break", + "fieldname": "export_invoice_no", + "fieldtype": "Data", "hidden": 0, - "idx": 180, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 28, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "terms", - "label": "Transporter Info", + "insert_after": "transporter_name", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Export Invoice No", "length": 0, - "modified": "2020-08-07 17:17:28.492028", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-09-25 14:30:05.781690", "modified_by": "Administrator", - "name": "Sales Invoice-transporter_info", + "module": null, + "name": "Sales Invoice-export_invoice_no", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 1, + "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, "trash_reason": null, "unique": 0, "width": null @@ -1317,53 +1639,67 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:39:45.791423", + "creation": "2020-07-04 10:38:59.323639", "default": null, - "depends_on": null, + "depends_on": "eval:in_list([\"SEZ\", \"Overseas\", \"Deemed Export\"], doc.gst_category)", "description": null, "docstatus": 0, "dt": "Sales Invoice", - "fetch_from": null, - "fetch_if_empty": 0, - "fieldname": "transporter", - "fieldtype": "Link", + "fetch_from": "customer.export_type", + "fetch_if_empty": 1, + "fieldname": "export_type", + "fieldtype": "Select", "hidden": 0, - "idx": 181, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 192, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "transporter_info", - "label": "Transporter", + "insert_after": "gst_category", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Export Type", "length": 0, - "modified": "2020-08-07 17:17:31.488252", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:16:48.578061", "modified_by": "Administrator", - "name": "Sales Invoice-transporter", + "module": null, + "name": "Sales Invoice-export_type", "no_copy": 0, - "options": "Supplier", + "non_negative": 0, + "options": "\nWith Payment of Tax\nWithout Payment of Tax", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, "trash_reason": null, "unique": 0, "width": null @@ -1374,52 +1710,66 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:39:49.065213", + "creation": "2025-08-29 14:43:24.174349", "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", - "fetch_from": "transporter.gst_transporter_id", + "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "gst_transporter_id", - "fieldtype": "Data", + "fieldname": "gst_breakup_table", + "fieldtype": "Text Editor", "hidden": 0, - "idx": 182, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "transporter", - "label": "GST Transporter ID", + "insert_after": "section_gst_breakup", + "is_system_generated": 1, + "is_virtual": 1, + "label": "GST Breakup Table", "length": 0, - "modified": "2020-08-07 17:17:34.538035", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:24.174349", "modified_by": "Administrator", - "name": "Sales Invoice-gst_transporter_id", + "module": "GST India", + "name": "Sales Invoice-gst_breakup_table", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 1, + "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, @@ -1431,53 +1781,67 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:39:52.291682", + "creation": "2020-07-04 10:38:46.715455", "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", - "fetch_from": null, - "fetch_if_empty": 0, - "fieldname": "driver", - "fieldtype": "Link", + "fetch_from": "customer.gst_category", + "fetch_if_empty": 1, + "fieldname": "gst_category", + "fieldtype": "Select", "hidden": 0, - "idx": 183, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 191, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "gst_transporter_id", - "label": "Driver", + "insert_after": "gst_section", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST Category", "length": 0, - "modified": "2020-08-07 17:17:37.157205", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:16:45.516062", "modified_by": "Administrator", - "name": "Sales Invoice-driver", + "module": "GST India", + "name": "Sales Invoice-gst_category", "no_copy": 0, - "options": "Driver", + "non_negative": 0, + "options": "\nRegistered Regular\nRegistered Composition\nUnregistered\nSEZ\nOverseas\nConsumer\nDeemed Export\nUIN Holders", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, "trash_reason": null, "unique": 0, "width": null @@ -1493,7 +1857,7 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:39:58.578015", + "creation": "2020-07-04 10:39:12.060675", "default": null, "depends_on": null, "description": null, @@ -1501,39 +1865,53 @@ "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "vehicle_no", - "fieldtype": "Data", + "fieldname": "gst_col_break", + "fieldtype": "Column Break", "hidden": 0, - "idx": 22, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 196, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "lr_no", - "label": "Vehicle No", + "insert_after": "ecommerce_gstin", + "is_system_generated": 1, + "is_virtual": 0, + "label": null, "length": 0, - "modified": "2020-08-07 17:17:43.181726", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:17:00.982276", "modified_by": "Administrator", - "name": "Sales Invoice-vehicle_no", + "module": "GST India", + "name": "Sales Invoice-gst_col_break", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 1, + "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, @@ -1547,10 +1925,10 @@ "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, - "collapsible": 0, + "collapsible": 1, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:40:01.923912", + "creation": "2020-07-04 10:38:43.217975", "default": null, "depends_on": null, "description": null, @@ -1558,39 +1936,53 @@ "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "distance", - "fieldtype": "Float", + "fieldname": "gst_section", + "fieldtype": "Section Break", "hidden": 0, - "idx": 23, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 190, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "vehicle_no", - "label": "Distance (in km)", + "insert_after": "language", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST Details", "length": 0, - "modified": "2020-08-07 17:17:46.238453", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:16:42.104616", "modified_by": "Administrator", - "name": "Sales Invoice-distance", + "module": "GST India", + "name": "Sales Invoice-gst_section", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, @@ -1607,47 +1999,61 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:40:05.275466", + "creation": "2020-07-04 10:39:49.065213", "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", - "fetch_from": null, + "fetch_from": "transporter.gst_transporter_id", "fetch_if_empty": 0, - "fieldname": "transporter_col_break", - "fieldtype": "Column Break", + "fieldname": "gst_transporter_id", + "fieldtype": "Data", "hidden": 0, - "idx": 24, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 182, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "distance", - "label": null, + "insert_after": "transporter", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST Transporter ID", "length": 0, - "modified": "2020-08-07 17:17:49.262738", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:17:34.538035", "modified_by": "Administrator", - "name": "Sales Invoice-transporter_col_break", + "module": "GST India", + "name": "Sales Invoice-gst_transporter_id", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, @@ -1664,47 +2070,61 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:40:08.602330", - "default": null, - "depends_on": null, + "creation": "2020-07-04 10:40:21.927490", + "default": "Regular", + "depends_on": "eval:(doc.mode_of_transport === \"Road\")", "description": null, "docstatus": 0, "dt": "Sales Invoice", - "fetch_from": "transporter.name", + "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "transporter_name", - "fieldtype": "Data", + "fieldname": "gst_vehicle_type", + "fieldtype": "Select", "hidden": 0, - "idx": 27, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 32, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "transporter_address_display", - "label": "Transporter Name", + "insert_after": "lr_date", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST Vehicle Type", "length": 0, - "modified": "2020-08-07 17:17:52.363168", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:18:04.623116", "modified_by": "Administrator", - "name": "Sales Invoice-transporter_name", + "module": "GST India", + "name": "Sales Invoice-gst_vehicle_type", "no_copy": 0, - "options": null, + "non_negative": 0, + "options": "Regular\nOver Dimensional Cargo (ODC)", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 1, + "read_only": 0, + "read_only_depends_on": "eval: doc.mode_of_transport == 'Ship'", "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, @@ -1721,48 +2141,62 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:40:12.026041", - "default": "Road", + "creation": "2020-07-04 10:39:02.554049", + "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "mode_of_transport", + "fieldname": "invoice_copy", "fieldtype": "Select", "hidden": 0, - "idx": 29, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 193, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "export_invoice_no", - "label": "Mode of Transport", + "insert_after": "export_type", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Invoice Copy", "length": 0, - "modified": "2020-08-07 17:17:55.417666", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:16:51.656477", "modified_by": "Administrator", - "name": "Sales Invoice-mode_of_transport", + "module": "GST India", + "name": "Sales Invoice-invoice_copy", "no_copy": 0, - "options": "\nRoad\nAir\nRail\nShip", + "non_negative": 0, + "options": "Original for Recipient\nDuplicate for Transporter\nDuplicate for Supplier\nTriplicate for Supplier", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, "trash_reason": null, "unique": 0, "width": null @@ -1778,48 +2212,62 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:40:15.297916", + "creation": "2021-01-07 21:25:04.449087", "default": null, - "depends_on": null, + "depends_on": "eval:in_list([\"Registered Regular\", \"SEZ\", \"Overseas\", \"Deemed Export\"], doc.gst_category) && doc.irn_cancelled === 0", "description": null, "docstatus": 0, "dt": "Sales Invoice", - "fetch_from": "driver.full_name", + "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "driver_name", + "fieldname": "irn", "fieldtype": "Data", "hidden": 0, - "idx": 30, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 9, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "mode_of_transport", - "label": "Driver Name", + "insert_after": "irn_cancelled", + "is_system_generated": 1, + "is_virtual": 0, + "label": "IRN", "length": 0, - "modified": "2020-08-07 17:17:58.488300", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2021-01-07 21:25:04.449087", "modified_by": "Administrator", - "name": "Sales Invoice-driver_name", - "no_copy": 0, + "module": "GST India", + "name": "Sales Invoice-irn", + "no_copy": 1, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, "trash_reason": null, "unique": 0, "width": null @@ -1830,52 +2278,66 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:40:18.670314", - "default": "Today", - "depends_on": null, + "creation": "2021-01-07 21:26:13.950963", + "default": null, + "depends_on": "eval:(doc.irn_cancelled === 1)", "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "lr_date", - "fieldtype": "Date", + "fieldname": "irn_cancelled", + "fieldtype": "Check", "hidden": 0, - "idx": 31, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 8, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "driver_name", - "label": "Transport Receipt Date", + "insert_after": "customer", + "is_system_generated": 1, + "is_virtual": 0, + "label": "IRN Cancelled", "length": 0, - "modified": "2020-08-07 17:18:01.494670", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2021-01-07 21:26:13.950963", "modified_by": "Administrator", - "name": "Sales Invoice-lr_date", - "no_copy": 0, + "module": null, + "name": "Sales Invoice-irn_cancelled", + "no_copy": 1, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, @@ -1892,47 +2354,61 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:40:21.927490", - "default": "Regular", - "depends_on": "eval:(doc.mode_of_transport === \"Road\")", + "creation": "2025-08-29 14:43:23.570334", + "default": "0", + "depends_on": "eval:doc.gst_category == \"SEZ\" || (doc.gst_category == \"Overseas\" && doc.place_of_supply == \"96-Other Countries\")", "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "gst_vehicle_type", - "fieldtype": "Select", + "fieldname": "is_export_with_gst", + "fieldtype": "Check", "hidden": 0, - "idx": 32, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "lr_date", - "label": "GST Vehicle Type", + "insert_after": "is_reverse_charge", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Is Export With Payment of GST", "length": 0, - "modified": "2020-08-07 17:18:04.623116", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:23.570334", "modified_by": "Administrator", - "name": "Sales Invoice-gst_vehicle_type", + "module": "GST India", + "name": "Sales Invoice-is_export_with_gst", "no_copy": 0, - "options": "Regular\nOver Dimensional Cargo (ODC)", + "non_negative": 0, + "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, @@ -1944,52 +2420,66 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:40:25.165602", - "default": null, - "depends_on": "eval:(doc.docstatus === 1)", + "creation": "2025-08-29 14:43:27.180002", + "default": "0", + "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "ewaybill", - "fieldtype": "Data", + "fieldname": "is_reverse_charge", + "fieldtype": "Check", "hidden": 0, - "idx": 15, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "tax_id", - "label": "E-Way Bill No.", + "insert_after": "is_debit_note", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Is Reverse Charge", "length": 0, - "modified": "2020-08-07 17:18:07.689669", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:27.180002", "modified_by": "Administrator", - "name": "Sales Invoice-ewaybill", + "module": "GST India", + "name": "Sales Invoice-is_reverse_charge", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, @@ -2006,48 +2496,62 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-09-25 14:30:05.781690", + "creation": "2020-09-27 12:16:26.579479", "default": null, - "depends_on": "eval:doc.export_type", + "depends_on": "eval: doc.gst_category === 'Overseas' || doc.update_stock === 1", "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "export_invoice_no", - "fieldtype": "Data", + "fieldname": "items_synopsis", + "fieldtype": "Table", "hidden": 0, - "idx": 28, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 94, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "transporter_name", - "label": "Export Invoice No", + "insert_after": "items", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Items Synopsis", "length": 0, - "modified": "2020-09-25 14:30:05.781690", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-09-27 12:16:26.579479", "modified_by": "Administrator", - "name": "Sales Invoice-export_invoice_no", + "module": null, + "name": "Sales Invoice-items_synopsis", "no_copy": 0, - "options": null, + "non_negative": 0, + "options": "Sales Invoice Item", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 1, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, "trash_reason": null, "unique": 0, "width": null @@ -2058,52 +2562,66 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-09-27 12:16:26.579479", - "default": null, - "depends_on": "eval: doc.gst_category === 'Overseas' || doc.update_stock === 1", + "creation": "2020-07-04 10:40:18.670314", + "default": "Today", + "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "items_synopsis", - "fieldtype": "Table", + "fieldname": "lr_date", + "fieldtype": "Date", "hidden": 0, - "idx": 94, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 31, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "items", - "label": "Items Synopsis", + "insert_after": "driver_name", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Transport Receipt Date", "length": 0, - "modified": "2020-09-27 12:16:26.579479", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:18:01.494670", "modified_by": "Administrator", - "name": "Sales Invoice-items_synopsis", + "module": "GST India", + "name": "Sales Invoice-lr_date", "no_copy": 0, - "options": "Sales Invoice Item", + "non_negative": 0, + "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, @@ -2120,48 +2638,62 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2021-01-07 21:25:04.449087", + "creation": "2022-03-31 12:54:13.800932", "default": null, - "depends_on": "eval:in_list([\"Registered Regular\", \"SEZ\", \"Overseas\", \"Deemed Export\"], doc.gst_category) && doc.irn_cancelled === 0", + "depends_on": "eval:doc.docstatus === 0", "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "irn", - "fieldtype": "Data", + "fieldname": "marked_to_submit", + "fieldtype": "Check", "hidden": 0, - "idx": 9, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 38, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "irn_cancelled", - "label": "IRN", + "insert_after": "set_posting_time", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Marked to Submit", "length": 0, - "modified": "2021-01-07 21:25:04.449087", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2022-03-31 12:54:13.800932", "modified_by": "Administrator", - "name": "Sales Invoice-irn", - "no_copy": 1, + "module": null, + "name": "Sales Invoice-marked_to_submit", + "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 1, + "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 1, + "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 1, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, "trash_reason": null, "unique": 0, "width": null @@ -2172,53 +2704,67 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2021-01-07 21:25:26.182634", - "default": null, + "creation": "2020-07-04 10:40:12.026041", + "default": "Road", "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "ack_no", - "fieldtype": "Data", - "hidden": 1, - "idx": 10, + "fieldname": "mode_of_transport", + "fieldtype": "Select", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 29, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "irn", - "label": "Ack. No.", + "insert_after": "export_invoice_no", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Mode of Transport", "length": 0, - "modified": "2021-01-07 21:25:26.182634", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:17:55.417666", "modified_by": "Administrator", - "name": "Sales Invoice-ack_no", - "no_copy": 1, - "options": null, + "module": "GST India", + "name": "Sales Invoice-mode_of_transport", + "no_copy": 0, + "non_negative": 0, + "options": "\nRoad\nAir\nRail\nShip", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 1, + "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 1, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, "trash_reason": null, "unique": 0, "width": null @@ -2234,7 +2780,7 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2021-01-07 21:25:49.731425", + "creation": "2020-07-04 10:39:35.747072", "default": null, "depends_on": null, "description": null, @@ -2242,39 +2788,53 @@ "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "ack_date", + "fieldname": "place_of_supply", "fieldtype": "Data", - "hidden": 1, - "idx": 11, + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 71, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "ack_no", - "label": "Ack. Date", + "insert_after": "customer_gstin", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Place of Supply", "length": 0, - "modified": "2021-01-07 21:25:49.731425", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:17:22.487673", "modified_by": "Administrator", - "name": "Sales Invoice-ack_date", - "no_copy": 1, + "module": "GST India", + "name": "Sales Invoice-place_of_supply", + "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 1, "trash_reason": null, "unique": 0, @@ -2286,52 +2846,66 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2021-01-07 21:26:13.950963", + "creation": "2025-08-29 14:43:27.149826", "default": null, - "depends_on": "eval:(doc.irn_cancelled === 1)", - "description": null, + "depends_on": "eval:doc.company_gstin && doc.gst_category === 'Overseas' && doc.place_of_supply == '96-Other Countries' && gst_settings.enable_e_waybill", + "description": "Address of the place / port in India from where goods are being exported
(for generating e-Waybill against export of goods)", "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "irn_cancelled", - "fieldtype": "Check", + "fieldname": "port_address", + "fieldtype": "Link", "hidden": 0, - "idx": 8, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "customer", - "label": "IRN Cancelled", + "insert_after": "shipping_address", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Origin Port / Border Checkpost Address Name", "length": 0, - "modified": "2021-01-07 21:26:13.950963", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:27.149826", "modified_by": "Administrator", - "name": "Sales Invoice-irn_cancelled", - "no_copy": 1, - "options": null, + "module": "GST India", + "name": "Sales Invoice-port_address", + "no_copy": 0, + "non_negative": 0, + "options": "Address", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 1, + "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, @@ -2343,53 +2917,67 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2021-01-07 21:26:41.379141", + "creation": "2020-07-04 10:39:18.579350", "default": null, - "depends_on": "eval:(doc.eway_bill_cancelled === 1)", + "depends_on": "eval:doc.gst_category=='Overseas' ", "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "eway_bill_cancelled", - "fieldtype": "Check", + "fieldname": "port_code", + "fieldtype": "Data", "hidden": 0, - "idx": 12, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 198, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "ack_date", - "label": "E-Way Bill Cancelled", + "insert_after": "reason_for_issuing_document", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Port Code", "length": 0, - "modified": "2021-01-07 21:26:41.379141", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:17:07.176905", "modified_by": "Administrator", - "name": "Sales Invoice-eway_bill_cancelled", - "no_copy": 1, + "module": "GST India", + "name": "Sales Invoice-port_code", + "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 1, + "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, "trash_reason": null, "unique": 0, "width": null @@ -2405,7 +2993,7 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2021-01-07 21:27:10.217491", + "creation": "2021-01-07 21:28:32.859514", "default": null, "depends_on": null, "description": null, @@ -2413,39 +3001,53 @@ "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "signed_einvoice", - "fieldtype": "Code", + "fieldname": "qrcode_image", + "fieldtype": "Attach Image", "hidden": 1, - "idx": 2, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 1, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "qrcode_image", - "label": null, + "insert_after": null, + "is_system_generated": 1, + "is_virtual": 0, + "label": "QRCode", "length": 0, - "modified": "2021-01-07 21:27:10.217491", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2021-01-07 21:28:32.859514", "modified_by": "Administrator", - "name": "Sales Invoice-signed_einvoice", + "module": null, + "name": "Sales Invoice-qrcode_image", "no_copy": 1, - "options": "JSON", + "non_negative": 0, + "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, @@ -2462,48 +3064,62 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2021-01-07 21:27:49.401314", + "creation": "2020-07-04 10:39:15.242498", "default": null, - "depends_on": null, + "depends_on": "eval:doc.is_return==1", "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "signed_qr_code", - "fieldtype": "Code", - "hidden": 1, - "idx": 3, + "fieldname": "reason_for_issuing_document", + "fieldtype": "Select", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 197, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "signed_einvoice", - "label": null, + "insert_after": "gst_col_break", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Reason For Issuing document", "length": 0, - "modified": "2021-01-07 21:27:49.401314", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:17:04.066008", "modified_by": "Administrator", - "name": "Sales Invoice-signed_qr_code", - "no_copy": 1, - "options": "JSON", + "module": null, + "name": "Sales Invoice-reason_for_issuing_document", + "no_copy": 0, + "non_negative": 0, + "options": "\n01-Sales Return\n02-Post Sale Discount\n03-Deficiency in services\n04-Correction in Invoice\n05-Change in POS\n06-Finalization of Provisional assessment\n07-Others", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 1, + "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, "trash_reason": null, "unique": 0, "width": null @@ -2519,48 +3135,62 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2021-01-07 21:28:32.859514", - "default": null, + "creation": "2020-07-04 10:39:05.754965", + "default": "N", "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "qrcode_image", - "fieldtype": "Attach Image", - "hidden": 1, - "idx": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, + "fieldname": "reverse_charge", + "fieldtype": "Select", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 194, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": null, - "label": "QRCode", + "insert_after": "invoice_copy", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Reverse Charge", "length": 0, - "modified": "2021-01-07 21:28:32.859514", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:16:54.733476", "modified_by": "Administrator", - "name": "Sales Invoice-qrcode_image", - "no_copy": 1, - "options": null, + "module": null, + "name": "Sales Invoice-reverse_charge", + "no_copy": 0, + "non_negative": 0, + "options": "Y\nN", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 1, + "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, "trash_reason": null, "unique": 0, "width": null @@ -2573,10 +3203,10 @@ "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, - "collapsible": 0, + "collapsible": 1, "collapsible_depends_on": null, "columns": 0, - "creation": "2021-01-27 11:14:50.975262", + "creation": "2025-08-29 14:43:24.155966", "default": null, "depends_on": null, "description": null, @@ -2584,39 +3214,53 @@ "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "transporter_address", - "fieldtype": "Link", + "fieldname": "section_gst_breakup", + "fieldtype": "Section Break", "hidden": 0, - "idx": 25, - "ignore_user_permissions": 1, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "transporter_col_break", - "label": "Transporter Address Name", + "insert_after": "other_charges_calculation", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST Breakup", "length": 0, - "modified": "2021-01-27 11:14:50.975262", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:24.155966", "modified_by": "Administrator", - "name": "Sales Invoice-transporter_address", + "module": "GST India", + "name": "Sales Invoice-section_gst_breakup", "no_copy": 0, - "options": "Address", + "non_negative": 0, + "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 1, + "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, @@ -2633,47 +3277,132 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2021-01-27 11:15:25.669351", - "default": null, + "creation": "2017-06-24 18:05:17.908154", + "default": "NA", "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "transporter_address_display", - "fieldtype": "Small Text", + "fieldname": "shipping_address_gstin", + "fieldtype": "Data", "hidden": 0, - "idx": 26, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 74, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": 0.0, + "insert_after": "shipping_excise_no", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Shipping Address GSTIN", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2017-06-24 18:05:17.908154", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-shipping_address_gstin", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": "170" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2020-07-04 10:39:25.348204", + "default": null, + "depends_on": "eval:doc.gst_category=='Overseas' ", + "description": null, + "docstatus": 0, + "dt": "Sales Invoice", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "shipping_bill_date", + "fieldtype": "Date", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 200, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "transporter_address", - "label": "Transporter Address Preview", + "insert_after": "shipping_bill_number", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Shipping Bill Date", "length": 0, - "modified": "2021-01-27 11:15:25.669351", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:17:13.353736", "modified_by": "Administrator", - "name": "Sales Invoice-transporter_address_display", + "module": "GST India", + "name": "Sales Invoice-shipping_bill_date", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 1, + "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, @@ -2690,47 +3419,61 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2021-04-26 20:32:39.561325", + "creation": "2020-07-04 10:39:21.815353", "default": null, - "depends_on": null, + "depends_on": "eval:doc.gst_category=='Overseas' ", "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "tin_no", + "fieldname": "shipping_bill_number", "fieldtype": "Data", - "hidden": 1, - "idx": 60, + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 199, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "billing_address_gstin", - "label": "TIN No", - "length": 50, - "modified": "2021-04-26 20:32:39.561325", + "insert_after": "port_code", + "is_system_generated": 1, + "is_virtual": 0, + "label": " Shipping Bill Number", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:17:10.288321", "modified_by": "Administrator", - "name": "Sales Invoice-tin_no", + "module": "GST India", + "name": "Sales Invoice-shipping_bill_number", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 1, + "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 1, "trash_reason": null, "unique": 0, @@ -2747,7 +3490,7 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2021-04-26 20:32:51.855389", + "creation": "2021-04-26 20:33:10.992678", "default": null, "depends_on": null, "description": null, @@ -2755,39 +3498,53 @@ "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "excise_no", + "fieldname": "shipping_excise_no", "fieldtype": "Data", "hidden": 1, - "idx": 61, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 73, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "tin_no", - "label": "Excise No", + "insert_after": "shipping_tin_no", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Shipping Excise No", "length": 50, - "modified": "2021-04-26 20:32:51.855389", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2021-04-26 20:33:10.992678", "modified_by": "Administrator", - "name": "Sales Invoice-excise_no", + "module": null, + "name": "Sales Invoice-shipping_excise_no", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 1, "trash_reason": null, "unique": 0, @@ -2815,6 +3572,9 @@ "fieldname": "shipping_tin_no", "fieldtype": "Data", "hidden": 1, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, "idx": 72, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -2822,29 +3582,40 @@ "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, "insert_after": "place_of_supply", + "is_system_generated": 1, + "is_virtual": 0, "label": "Shipping TIN No", "length": 50, + "link_filters": null, + "mandatory_depends_on": null, "modified": "2021-04-26 20:33:01.301511", "modified_by": "Administrator", + "module": null, "name": "Sales Invoice-shipping_tin_no", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 1, "trash_reason": null, "unique": 0, @@ -2861,7 +3632,7 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2021-04-26 20:33:10.992678", + "creation": "2021-01-07 21:27:10.217491", "default": null, "depends_on": null, "description": null, @@ -2869,40 +3640,54 @@ "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "shipping_excise_no", - "fieldtype": "Data", + "fieldname": "signed_einvoice", + "fieldtype": "Code", "hidden": 1, - "idx": 73, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 2, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "shipping_tin_no", - "label": "Shipping Excise No", - "length": 50, - "modified": "2021-04-26 20:33:10.992678", + "insert_after": "qrcode_image", + "is_system_generated": 1, + "is_virtual": 0, + "label": null, + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2021-01-07 21:27:10.217491", "modified_by": "Administrator", - "name": "Sales Invoice-shipping_excise_no", - "no_copy": 0, - "options": null, + "module": null, + "name": "Sales Invoice-signed_einvoice", + "no_copy": 1, + "non_negative": 0, + "options": "JSON", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 1, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, "trash_reason": null, "unique": 0, "width": null @@ -2913,12 +3698,12 @@ "_liked_by": null, "_user_tags": null, "allow_in_quick_entry": 0, - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2022-02-05 16:20:25.944618", + "creation": "2021-01-07 21:27:49.401314", "default": null, "depends_on": null, "description": null, @@ -2926,39 +3711,53 @@ "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "background_processing", - "fieldtype": "Check", - "hidden": 0, - "idx": 39, + "fieldname": "signed_qr_code", + "fieldtype": "Code", + "hidden": 1, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 3, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "marked_to_submit", - "label": "Background Processing", + "insert_after": "signed_einvoice", + "is_system_generated": 1, + "is_virtual": 0, + "label": null, "length": 0, - "modified": "2022-02-05 16:20:25.944618", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2021-01-07 21:27:49.401314", "modified_by": "Administrator", - "name": "Sales Invoice-background_processing", - "no_copy": 0, - "options": null, + "module": null, + "name": "Sales Invoice-signed_qr_code", + "no_copy": 1, + "non_negative": 0, + "options": "JSON", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, - "permlevel": 1, + "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "trash_reason": null, "unique": 0, @@ -2975,55 +3774,4339 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2022-03-31 12:54:13.800932", + "creation": "2021-04-26 20:32:39.561325", "default": null, - "depends_on": "eval:doc.docstatus === 0", + "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "marked_to_submit", - "fieldtype": "Check", - "hidden": 0, - "idx": 38, + "fieldname": "tin_no", + "fieldtype": "Data", + "hidden": 1, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 60, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "index": null, - "insert_after": "set_posting_time", - "label": "Marked to Submit", - "length": 0, - "modified": "2022-03-31 12:54:13.800932", + "insert_after": "billing_address_gstin", + "is_system_generated": 1, + "is_virtual": 0, + "label": "TIN No", + "length": 50, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2021-04-26 20:32:39.561325", "modified_by": "Administrator", - "name": "Sales Invoice-marked_to_submit", + "module": null, + "name": "Sales Invoice-tin_no", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, "trash_reason": null, "unique": 0, "width": null - } - ], - "custom_perms": [], - "doctype": "Sales Invoice", - "property_setters": [], + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2020-07-04 10:39:45.791423", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "transporter", + "fieldtype": "Link", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 181, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "transporter_info", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Transporter", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:17:31.488252", + "modified_by": "Administrator", + "module": "GST India", + "name": "Sales Invoice-transporter", + "no_copy": 0, + "non_negative": 0, + "options": "Supplier", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2021-01-27 11:14:50.975262", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "transporter_address", + "fieldtype": "Link", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 25, + "ignore_user_permissions": 1, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "transporter_col_break", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Transporter Address Name", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2021-01-27 11:14:50.975262", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-transporter_address", + "no_copy": 0, + "non_negative": 0, + "options": "Address", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2021-01-27 11:15:25.669351", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "transporter_address_display", + "fieldtype": "Small Text", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 26, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "transporter_address", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Transporter Address Preview", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2021-01-27 11:15:25.669351", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-transporter_address_display", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2020-07-04 10:40:05.275466", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "transporter_col_break", + "fieldtype": "Column Break", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 24, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "distance", + "is_system_generated": 1, + "is_virtual": 0, + "label": null, + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:17:49.262738", + "modified_by": "Administrator", + "module": "GST India", + "name": "Sales Invoice-transporter_col_break", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 1, + "collapsible_depends_on": "transporter", + "columns": 0, + "creation": "2020-07-04 10:39:42.525025", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "transporter_info", + "fieldtype": "Section Break", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 180, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "terms", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Transporter Info", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:17:28.492028", + "modified_by": "Administrator", + "module": "GST India", + "name": "Sales Invoice-transporter_info", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2020-07-04 10:40:08.602330", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice", + "fetch_from": "transporter.name", + "fetch_if_empty": 0, + "fieldname": "transporter_name", + "fieldtype": "Data", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 27, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "transporter_address_display", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Transporter Name", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:17:52.363168", + "modified_by": "Administrator", + "module": "GST India", + "name": "Sales Invoice-transporter_name", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2020-07-04 10:39:58.578015", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "vehicle_no", + "fieldtype": "Data", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 22, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "lr_no", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Vehicle No", + "length": 0, + "link_filters": null, + "mandatory_depends_on": "", + "modified": "2020-08-07 17:17:43.181726", + "modified_by": "Administrator", + "module": "GST India", + "name": "Sales Invoice-vehicle_no", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + } + ], + "custom_perms": [], + "doctype": "Sales Invoice", + "links": [ + { + "creation": "2022-01-25 10:29:57.771398", + "custom": 0, + "docstatus": 0, + "group": "Reference", + "hidden": 0, + "idx": 1, + "is_child_table": 0, + "link_doctype": "POS Invoice", + "link_fieldname": "consolidated_invoice", + "modified": "2025-09-17 14:52:30.430269", + "modified_by": "Administrator", + "name": "qj0bj8omk8", + "owner": "Administrator", + "parent": "Sales Invoice", + "parent_doctype": null, + "parentfield": "links", + "parenttype": "DocType", + "table_fieldname": null + } + ], + "property_setters": [ + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-12-30 14:57:06.966434", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": null, + "idx": 0, + "is_system_generated": 1, + "modified": "2015-12-30 14:57:06.966434", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-_idx", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "_idx", + "property_type": "Text", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "[\"customer_section\", \"naming_series\", \"customer\", \"customer_address\", \"shipping_address_name\", \"ship_to\", \"ship_terms\", \"transporters\", \"lr_no\", \"customer_name\", \"address_display\", \"contact_display\", \"contact_mobile\", \"contact_email\", \"column_break1\", \"is_pos\", \"amended_from\", \"company\", \"posting_date\", \"posting_time\", \"removal_date\", \"removal_time\", \"shipping_contact_no\", \"due_date\", \"mode_of_payment\", \"po_no\", \"po_date\", \"column_break4\", \"payments_section\", \"write_off_outstanding_amount_automatically\", \"paid_amount\", \"cash_bank_account\", \"column_break3\", \"write_off_amount\", \"write_off_account\", \"write_off_cost_center\", \"currency_and_price_list\", \"currency\", \"conversion_rate\", \"ignore_pricing_rule\", \"column_break2\", \"selling_price_list\", \"price_list_currency\", \"plc_conversion_rate\", \"update_stock\", \"items_section\", \"items\", \"packing_list\", \"packed_items\", \"sales_bom_help\", \"section_break_30\", \"base_net_total\", \"base_total\", \"net_total\", \"column_break_32\", \"total\", \"taxes_section\", \"taxes_and_charges\", \"column_break_38\", \"shipping_rule\", \"section_break_40\", \"taxes\", \"other_charges_calculation\", \"section_break_43\", \"base_total_taxes_and_charges\", \"column_break_47\", \"total_taxes_and_charges\", \"section_break_49\", \"apply_discount_on\", \"column_break_51\", \"discount_amount\", \"base_discount_amount\", \"totals\", \"base_grand_total\", \"base_rounded_total\", \"base_in_words\", \"column_break5\", \"grand_total\", \"rounded_total\", \"in_words\", \"total_advance\", \"outstanding_amount\", \"advances_section\", \"get_advances_received\", \"advances\", \"column_break_74\", \"fold\", \"terms_section_break\", \"tc_name\", \"terms\", \"contact_section\", \"territory\", \"customer_group\", \"col_break23\", \"shipping_address\", \"contact_person\", \"shipping_tin_no\", \"shipping_excise_no\", \"more_info\", \"debit_to\", \"project_name\", \"campaign\", \"source\", \"is_opening\", \"c_form_applicable\", \"c_form_no\", \"column_break8\", \"letter_head\", \"tin_no\", \"excise_no\", \"select_print_heading\", \"fiscal_year\", \"remarks\", \"sales_team_section_break\", \"column_break9\", \"sales_partner\", \"column_break10\", \"commission_rate\", \"total_commission\", \"section_break2\", \"sales_team\", \"recurring_invoice\", \"column_break11\", \"is_recurring\", \"recurring_type\", \"from_date\", \"to_date\", \"repeat_on_day_of_month\", \"end_date\", \"column_break12\", \"next_date\", \"recurring_id\", \"notification_email_address\", \"against_income_account\"]" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.383181", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "account_for_change_amount", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.383181", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-account_for_change_amount-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-09-13 20:05:50.377400", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "additional_discount_account", + "idx": 0, + "is_system_generated": 1, + "modified": "2025-09-13 20:05:50.377400", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-additional_discount_account-hidden", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-09-13 20:05:50.392317", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "additional_discount_account", + "idx": 0, + "is_system_generated": 1, + "modified": "2025-09-13 20:05:50.392317", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-additional_discount_account-mandatory_depends_on", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "mandatory_depends_on", + "property_type": "Code", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-08-01 20:11:19.916061", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "address_display", + "idx": 0, + "is_system_generated": 0, + "modified": "2016-08-04 14:32:36.308479", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-address_display-precision", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-03-15 14:00:59.875930", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "address_display", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-03-15 14:00:59.875930", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-address_display-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "334" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-09-22 07:13:05.580039", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_grand_total", + "idx": 0, + "is_system_generated": 0, + "modified": "2015-09-22 07:13:05.580039", + "modified_by": "ravi.singh@rigpl.com", + "module": null, + "name": "Sales Invoice-base_grand_total-width", + "owner": "ravi.singh@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "149" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 19:17:16.847419", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_net_total", + "idx": 0, + "is_system_generated": 1, + "modified": "2016-08-04 14:32:36.317189", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-base_net_total-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-08-22 16:43:09.563222", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_rounded_total", + "idx": 0, + "is_system_generated": 1, + "modified": "2025-08-22 16:43:09.563222", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-base_rounded_total-hidden", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-08-22 16:43:09.675430", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_rounded_total", + "idx": 0, + "is_system_generated": 1, + "modified": "2025-08-22 16:43:09.675430", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-base_rounded_total-print_hide", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_hide", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 19:17:16.571415", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_total", + "idx": 0, + "is_system_generated": 1, + "modified": "2016-08-04 14:32:36.326016", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-base_total-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-01-29 11:57:06.936887", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "billing_address_gstin", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-01-29 11:57:06.936887", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-billing_address_gstin-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "144" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-03-31 10:52:00.769438", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "c_form_applicable", + "idx": 0, + "is_system_generated": 0, + "modified": "2016-03-31 10:52:00.769438", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-c_form_applicable-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "55" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.599298", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "c_form_no", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.599298", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-c_form_no-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.518122", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "campaign", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.518122", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-campaign-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-01-03 15:16:02.823764", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "cash_bank_account", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-01-03 15:16:02.823764", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-cash_bank_account-hidden", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.361102", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "cash_bank_account", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.361102", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-cash_bank_account-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-31 17:53:58.193418", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "cash_bank_account", + "idx": 0, + "is_system_generated": 0, + "modified": "2015-05-31 17:53:58.193418", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-cash_bank_account-permlevel", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "permlevel", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-01-03 15:17:19.684768", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "cash_bank_account", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-01-03 15:17:19.684768", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-cash_bank_account-read_only", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "read_only", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-11-13 10:41:47.560750", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "company_address", + "idx": 0, + "is_system_generated": 1, + "modified": "2018-11-13 10:41:47.560750", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-company_address-ignore_user_permissions", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-10-28 18:50:31.541269", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "company", + "idx": 0, + "is_system_generated": 0, + "modified": "2016-10-28 18:50:31.541269", + "modified_by": "sham.patil@rigpl.com", + "module": null, + "name": "Sales Invoice-company-width", + "owner": "sham.patil@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "64" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-08-01 20:11:19.927597", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "contact_mobile", + "idx": 0, + "is_system_generated": 0, + "modified": "2016-08-04 14:32:36.334805", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-contact_mobile-precision", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.180826", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "contact_person", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.180826", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-contact_person-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-05-13 22:15:21.337313", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "currency_and_price_list", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-05-13 22:15:21.337313", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-currency_and_price_list-collapsible_depends_on", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "collapsible_depends_on", + "property_type": "Data", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "eval:doc.selling_price_list == 'PL49' || doc.currency !== 'INR' || doc.ignore_pricing_rule == 1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.221163", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "currency", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.221163", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-currency-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.170576", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "customer_address", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.170576", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-customer_address-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2014-11-07 10:37:27.258898", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "customer_address", + "idx": 0, + "is_system_generated": 0, + "modified": "2014-11-07 10:37:27.258898", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-customer_address-label", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "label", + "property_type": "Data", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "Billing Address" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-03-31 15:33:26.006015", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "customer_address", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-03-31 15:33:26.006015", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-customer_address-reqd", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "reqd", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.505126", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "customer_group", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.505126", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-customer_group-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-02-16 15:51:22.165282", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "customer_po_details", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-02-16 15:51:22.165282", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-customer_po_details-collapsible", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "collapsible", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-02-16 15:51:22.170815", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "customer_po_details", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-02-16 15:51:22.170815", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-customer_po_details-collapsible_depends_on", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "collapsible_depends_on", + "property_type": "Data", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-10-30 11:29:00.482106", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "customer", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-10-30 11:29:00.482106", + "modified_by": "abhinav@rigpl.com", + "module": null, + "name": "Sales Invoice-customer-width", + "owner": "abhinav@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "170" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.562953", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "debit_to", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.562953", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-debit_to-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-07-01 10:57:08.128685", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": null, + "idx": 0, + "is_system_generated": 0, + "modified": "2017-07-01 10:57:08.128685", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-default_print_format", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "default_print_format", + "property_type": "Data", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "Domestic Invoice" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-08-22 16:43:09.967648", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "disable_rounded_total", + "idx": 0, + "is_system_generated": 1, + "modified": "2025-08-22 16:43:09.967648", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-disable_rounded_total-default", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "default", + "property_type": "Text", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-03-31 15:17:08.839283", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "discount_amount", + "idx": 0, + "is_system_generated": 0, + "modified": "2015-03-31 15:17:08.839283", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-discount_amount-hidden", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-03-31 15:17:08.834103", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "discount_amount", + "idx": 0, + "is_system_generated": 0, + "modified": "2015-03-31 15:17:08.834103", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-discount_amount-permlevel", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "permlevel", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "9" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-07-18 14:37:34.371374", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "due_date", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-07-18 14:37:34.371374", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-due_date-print_hide", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_hide", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2012-03-05 13:32:29", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "posting_date", + "idx": 0, + "is_system_generated": 0, + "modified": "2012-03-05 13:32:29", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-FL02756-hidden", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2012-03-05 13:33:23", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "posting_date", + "idx": 0, + "is_system_generated": 0, + "modified": "2012-03-05 13:33:23", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-FL02756-label", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "label", + "property_type": "Data", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "Posting Date/ Invoice Date" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2012-03-05 13:33:23", + "default_value": "0", + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "posting_date", + "idx": 0, + "is_system_generated": 0, + "modified": "2012-03-05 13:33:23", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-FL02756-permlevel", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "permlevel", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2012-04-03 16:47:02", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "charge", + "idx": 0, + "is_system_generated": 0, + "modified": "2012-04-03 16:47:02", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-FL02771-in_filter", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_filter", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2012-04-03 16:47:02", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "charge", + "idx": 0, + "is_system_generated": 0, + "modified": "2012-04-03 16:47:02", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-FL02771-reqd", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "reqd", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2012-02-29 19:58:29", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "is_pos", + "idx": 0, + "is_system_generated": 0, + "modified": "2012-02-29 19:58:29", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-FL04365-hidden", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2012-03-05 13:32:29", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "posting_time", + "idx": 0, + "is_system_generated": 0, + "modified": "2012-03-05 13:32:29", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-FL04368-hidden", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2012-03-05 13:33:23", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "posting_time", + "idx": 0, + "is_system_generated": 0, + "modified": "2012-03-05 13:33:23", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-FL04368-label", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "label", + "property_type": "Data", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "Posting Time/ Invoice Time" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-07-20 12:28:36.815328", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "grand_total", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-07-20 12:28:36.815328", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-grand_total-in_standard_filter", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_standard_filter", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-03-04 00:32:42.584369", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "grand_total", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-03-04 00:32:42.584369", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-grand_total-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "114" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-06-03 15:01:05.592705", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "ignore_pricing_rule", + "idx": 0, + "is_system_generated": 0, + "modified": "2015-06-03 15:01:05.592705", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-ignore_pricing_rule-permlevel", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "permlevel", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-08-22 16:43:12.991007", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "in_words", + "idx": 0, + "is_system_generated": 1, + "modified": "2025-08-22 16:43:12.991007", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-in_words-hidden", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-08-22 16:43:13.087792", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "in_words", + "idx": 0, + "is_system_generated": 1, + "modified": "2025-08-22 16:43:13.087792", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-in_words-print_hide", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_hide", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-11-27 15:13:41.092020", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "is_pos", + "idx": 0, + "is_system_generated": 0, + "modified": "2015-11-27 15:13:41.092020", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-is_pos-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "47" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.468971", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "letter_head", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.468971", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-letter_head-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-09-24 16:44:43.828307", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "lr_no", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-09-24 16:44:43.828307", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-lr_no-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "116" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-09-30 12:40:07.972629", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": null, + "idx": 0, + "is_system_generated": 0, + "modified": "2025-09-30 12:40:07.972629", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-main-field_order", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "field_order", + "property_type": "Data", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "[\"qrcode_image\", \"signed_einvoice\", \"signed_qr_code\", \"customer_section\", \"naming_series\", \"customer\", \"irn_cancelled\", \"irn\", \"ack_no\", \"ack_date\", \"eway_bill_cancelled\", \"customer_name\", \"tax_id\", \"ewaybill\", \"e_waybill_status\", \"company\", \"company_tax_id\", \"column_break1\", \"posting_date\", \"posting_time\", \"set_posting_time\", \"marked_to_submit\", \"background_processing\", \"removal_date\", \"removal_time\", \"due_date\", \"column_break_14\", \"is_pos\", \"pos_profile\", \"is_consolidated\", \"is_return\", \"return_against\", \"update_outstanding_for_self\", \"update_billed_amount_in_sales_order\", \"update_billed_amount_in_delivery_note\", \"is_debit_note\", \"is_reverse_charge\", \"is_export_with_gst\", \"amended_from\", \"is_created_using_pos\", \"pos_closing_entry\", \"accounting_dimensions_section\", \"cost_center\", \"dimension_col_break\", \"project\", \"currency_and_price_list\", \"currency\", \"conversion_rate\", \"column_break2\", \"selling_price_list\", \"price_list_currency\", \"plc_conversion_rate\", \"ignore_pricing_rule\", \"items_section\", \"scan_barcode\", \"last_scanned_warehouse\", \"update_stock\", \"column_break_39\", \"set_warehouse\", \"set_target_warehouse\", \"section_break_42\", \"items\", \"items_synopsis\", \"section_break_30\", \"total_qty\", \"total_net_weight\", \"column_break_32\", \"base_total\", \"base_net_total\", \"column_break_52\", \"total\", \"net_total\", \"taxes_section\", \"tax_category\", \"taxes_and_charges\", \"column_break_38\", \"shipping_rule\", \"column_break_55\", \"incoterm\", \"named_place\", \"section_break_40\", \"taxes\", \"section_break_43\", \"base_total_taxes_and_charges\", \"column_break_47\", \"total_taxes_and_charges\", \"totals\", \"base_grand_total\", \"base_rounding_adjustment\", \"base_rounded_total\", \"base_in_words\", \"column_break5\", \"grand_total\", \"rounding_adjustment\", \"use_company_roundoff_cost_center\", \"rounded_total\", \"in_words\", \"total_advance\", \"outstanding_amount\", \"disable_rounded_total\", \"section_break_49\", \"apply_discount_on\", \"base_discount_amount\", \"coupon_code\", \"is_cash_or_non_trade_discount\", \"additional_discount_account\", \"column_break_51\", \"additional_discount_percentage\", \"discount_amount\", \"sec_tax_breakup\", \"other_charges_calculation\", \"section_gst_breakup\", \"gst_breakup_table\", \"pricing_rule_details\", \"pricing_rules\", \"packing_list\", \"packed_items\", \"product_bundle_help\", \"time_sheet_list\", \"timesheets\", \"section_break_104\", \"total_billing_hours\", \"column_break_106\", \"total_billing_amount\", \"payments_tab\", \"payments_section\", \"cash_bank_account\", \"payments\", \"section_break_84\", \"base_paid_amount\", \"column_break_86\", \"paid_amount\", \"section_break_88\", \"base_change_amount\", \"column_break_90\", \"change_amount\", \"account_for_change_amount\", \"advances_section\", \"allocate_advances_automatically\", \"only_include_allocated_payments\", \"get_advances\", \"advances\", \"write_off_section\", \"write_off_amount\", \"base_write_off_amount\", \"write_off_outstanding_amount_automatically\", \"column_break_74\", \"write_off_account\", \"write_off_cost_center\", \"loyalty_points_redemption\", \"redeem_loyalty_points\", \"loyalty_points\", \"loyalty_amount\", \"column_break_77\", \"loyalty_program\", \"dont_create_loyalty_points\", \"loyalty_redemption_account\", \"loyalty_redemption_cost_center\", \"contact_and_address_tab\", \"address_and_contact\", \"customer_address\", \"billing_address_gstin\", \"tin_no\", \"excise_no\", \"address_display\", \"col_break4\", \"contact_person\", \"contact_display\", \"contact_mobile\", \"contact_email\", \"territory\", \"shipping_address_section\", \"shipping_address_name\", \"customer_gstin\", \"place_of_supply\", \"shipping_tin_no\", \"shipping_excise_no\", \"shipping_address_gstin\", \"ship_to\", \"shipping_address\", \"port_address\", \"shipping_addr_col_break\", \"dispatch_address_name\", \"dispatch_address\", \"company_address_section\", \"company_address\", \"company_gstin\", \"company_address_display\", \"company_addr_col_break\", \"company_contact_person\", \"terms_tab\", \"payment_schedule_section\", \"ignore_default_payment_terms_template\", \"payment_terms_template\", \"payment_schedule\", \"terms_section_break\", \"tc_name\", \"terms\", \"more_info_tab\", \"transporter_info\", \"transporter\", \"gst_transporter_id\", \"driver\", \"customer_po_details\", \"po_no\", \"column_break_23\", \"po_date\", \"more_info\", \"debit_to\", \"party_account_currency\", \"is_opening\", \"column_break8\", \"unrealized_profit_loss_account\", \"against_income_account\", \"sales_team_section_break\", \"sales_partner\", \"amount_eligible_for_commission\", \"column_break10\", \"commission_rate\", \"total_commission\", \"section_break2\", \"sales_team\", \"edit_printing_settings\", \"letter_head\", \"group_same_items\", \"column_break_84\", \"select_print_heading\", \"language\", \"gst_section\", \"gst_category\", \"export_type\", \"invoice_copy\", \"reverse_charge\", \"ecommerce_gstin\", \"gst_col_break\", \"reason_for_issuing_document\", \"port_code\", \"shipping_bill_number\", \"shipping_bill_date\", \"ecommerce_supply_type\", \"subscription_section\", \"subscription\", \"from_date\", \"auto_repeat\", \"column_break_140\", \"to_date\", \"update_auto_repeat_reference\", \"more_information\", \"status\", \"einvoice_status\", \"inter_company_invoice_reference\", \"represents_company\", \"customer_group\", \"column_break_imbx\", \"utm_source\", \"utm_campaign\", \"utm_medium\", \"utm_content\", \"col_break23\", \"is_internal_customer\", \"is_discounted\", \"remarks\", \"connections_tab\", \"gst_vehicle_type\", \"lr_date\", \"driver_name\", \"mode_of_transport\", \"export_invoice_no\", \"transporter_name\", \"transporter_address_display\", \"transporter_address\", \"transporter_col_break\", \"distance\", \"vehicle_no\", \"lr_no\", \"transporters\", \"ship_terms\"]" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-08-29 14:43:18.087475", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": null, + "idx": 0, + "is_system_generated": 1, + "modified": "2025-08-29 14:43:18.087475", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-main-track_changes", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "track_changes", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2014-06-24 12:12:21.844572", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "naming_series", + "idx": 0, + "is_system_generated": 1, + "modified": "2025-04-01 07:07:10.211944", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-naming_series-default", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "default", + "property_type": "Text", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2022-02-05 17:46:39.029377", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "naming_series", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-04-01 07:07:10.160389", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-naming_series-options", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "options", + "property_type": "Text", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "\nR26\nRJ26\nRE26\nRCN26" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-04-14 11:00:42.527735", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "naming_series", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-04-14 11:00:42.527735", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-naming_series-reqd", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "reqd", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-11-27 15:13:43.420499", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "naming_series", + "idx": 0, + "is_system_generated": 0, + "modified": "2015-11-27 15:13:43.420499", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-naming_series-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "65" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-07-20 12:28:36.787556", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "net_total", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-07-20 12:28:36.787556", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-net_total-in_standard_filter", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_standard_filter", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-04-01 13:57:56.027512", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "net_total", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-04-01 13:57:56.027512", + "modified_by": "ravi.singh@rigpl.com", + "module": null, + "name": "Sales Invoice-net_total-width", + "owner": "ravi.singh@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "79" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-03-04 00:32:38.316021", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "outstanding_amount", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-03-04 00:32:38.316021", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-outstanding_amount-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "85" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.580443", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "party_account_currency", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.580443", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-party_account_currency-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-07-18 14:37:34.639818", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "payment_schedule", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-07-18 14:37:34.639818", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-payment_schedule-print_hide", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_hide", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-09-30 12:40:08.271931", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "po_date", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-09-30 12:40:08.271931", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-po_date-reqd", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "reqd", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-03-03 22:14:23.682308", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "po_no", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-03-03 22:14:23.682308", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-po_no-in_standard_filter", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_standard_filter", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-10-20 12:09:08.432903", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "po_no", + "idx": 0, + "is_system_generated": 1, + "modified": "2015-10-20 12:09:08.432903", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-po_no-length", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "length", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "188" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2014-09-16 11:23:37.495191", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "po_no", + "idx": 0, + "is_system_generated": 0, + "modified": "2014-09-16 11:23:37.495191", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-po_no-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "258" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.143356", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "pos_profile", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.143356", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-pos_profile-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-07-20 12:28:36.741168", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "posting_date", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-07-20 12:28:36.741168", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-posting_date-in_standard_filter", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_standard_filter", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-09-24 16:45:23.095951", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "posting_date", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-09-24 16:45:23.095951", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-posting_date-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "98" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2013-01-15 18:47:24", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "posting_time", + "idx": 0, + "is_system_generated": 0, + "modified": "2013-01-15 18:47:24", + "modified_by": "anuj@rigpl.com", + "module": null, + "name": "Sales Invoice-posting_time-reqd", + "owner": "anuj@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "reqd", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.248830", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "price_list_currency", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.248830", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-price_list_currency-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-03-31 15:32:07.056464", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "project", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-03-31 15:32:07.056464", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-project-hidden", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.123528", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "project", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.123528", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-project-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-03-31 15:32:07.036753", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "project", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-03-31 15:32:07.036753", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-project-in_global_search", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_global_search", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-10-28 18:50:21.884374", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "project", + "idx": 0, + "is_system_generated": 0, + "modified": "2016-10-28 18:50:21.884374", + "modified_by": "sham.patil@rigpl.com", + "module": null, + "name": "Sales Invoice-project-width", + "owner": "sham.patil@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "58" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.637403", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "recurring_id", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.637403", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-recurring_id-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.653861", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "recurring_print_format", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.653861", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-recurring_print_format-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-03-04 11:12:13.700024", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "remarks", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-03-04 11:15:16.405786", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-remarks-allow_on_submit", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "allow_on_submit", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-05-01 17:10:45.353238", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "removal_date", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-05-01 17:10:45.353238", + "modified_by": "ravi.singh@rigpl.com", + "module": null, + "name": "Sales Invoice-removal_date-width", + "owner": "ravi.singh@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "93" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.162224", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "return_against", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.162224", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-return_against-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-08-22 16:43:09.776050", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "rounded_total", + "idx": 0, + "is_system_generated": 1, + "modified": "2025-08-22 16:43:09.776050", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-rounded_total-hidden", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-08-22 16:43:09.872596", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "rounded_total", + "idx": 0, + "is_system_generated": 1, + "modified": "2025-08-22 16:43:09.872596", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-rounded_total-print_hide", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_hide", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2013-07-04 18:50:09", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "sales_order_main", + "idx": 0, + "is_system_generated": 0, + "modified": "2013-07-04 18:50:09", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-sales_order_main-hidden", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2013-07-04 18:51:20", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "sales_order_main", + "idx": 0, + "is_system_generated": 0, + "modified": "2013-07-04 18:51:20", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-sales_order_main-permlevel", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "permlevel", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "2" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-08-26 16:53:30.903516", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "sales_partner", + "idx": 0, + "is_system_generated": 0, + "modified": "2015-08-26 16:53:30.903516", + "modified_by": "balaji.v@rigpl.com", + "module": null, + "name": "Sales Invoice-sales_partner-width", + "owner": "balaji.v@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "130.247009277344" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-03-04 11:10:51.135182", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "sales_team", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-03-04 11:10:51.135182", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-sales_team-allow_on_submit", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "allow_on_submit", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-08-22 16:43:04.212361", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "scan_barcode", + "idx": 0, + "is_system_generated": 1, + "modified": "2025-08-22 16:43:04.212361", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-scan_barcode-hidden", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2020-11-02 15:03:08.894688", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "section_break_49", + "idx": 0, + "is_system_generated": 0, + "modified": "2020-11-02 15:03:08.894688", + "modified_by": "abhinav@rigpl.com", + "module": null, + "name": "Sales Invoice-section_break_49-permlevel", + "owner": "abhinav@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "permlevel", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.491241", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "select_print_heading", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.491241", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-select_print_heading-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.236593", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "selling_price_list", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.236593", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-selling_price_list-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-09-30 13:24:15.822320", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "ship_to", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-09-30 13:24:15.822320", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-ship_to-fetch_from", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "fetch_from", + "property_type": "Small Text", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "shipping_address_name.address_title" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-10-20 12:09:07.702723", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "ship_to", + "idx": 0, + "is_system_generated": 1, + "modified": "2015-10-20 12:09:07.702723", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-ship_to-length", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "length", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "180" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-01-29 11:57:21.481748", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "shipping_address_gstin", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-01-29 11:57:21.481748", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-shipping_address_gstin-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "170" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2014-10-16 13:50:27.346005", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "shipping_address_name", + "idx": 0, + "is_system_generated": 0, + "modified": "2014-10-16 13:50:27.346005", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-shipping_address_name-hidden", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.203235", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "shipping_address_name", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.203235", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-shipping_address_name-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-03-31 15:33:26.035055", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "shipping_address_name", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-03-31 15:33:26.035055", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-shipping_address_name-reqd", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "reqd", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-12-09 12:29:22.565513", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "shipping_address_name", + "idx": 0, + "is_system_generated": 0, + "modified": "2015-12-09 12:29:22.565513", + "modified_by": "ravi.singh@rigpl.com", + "module": null, + "name": "Sales Invoice-shipping_address_name-width", + "owner": "ravi.singh@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "110" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-11-24 19:13:28.594763", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "shipping_address", + "idx": 0, + "is_system_generated": 0, + "modified": "2015-11-24 19:13:28.594763", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-shipping_address-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "428" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.307612", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "shipping_rule", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.307612", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-shipping_rule-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2014-10-16 13:36:08.707283", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": null, + "idx": 0, + "is_system_generated": 0, + "modified": "2014-10-16 13:36:08.707283", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-sort_field", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "sort_field", + "property_type": "Data", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "creation" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.537831", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "source", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.537831", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-source-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-09-13 20:05:50.255550", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "tax_id", + "idx": 0, + "is_system_generated": 1, + "modified": "2025-09-13 20:05:50.255550", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-tax_id-hidden", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-09-13 20:05:50.272299", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "tax_id", + "idx": 0, + "is_system_generated": 1, + "modified": "2025-09-13 20:05:50.272299", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-tax_id-print_hide", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_hide", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.294181", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "taxes_and_charges", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.294181", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-taxes_and_charges-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-01-02 19:16:39.920441", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "taxes_and_charges", + "idx": 0, + "is_system_generated": 0, + "modified": "2015-01-02 19:16:39.920441", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-taxes_and_charges-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2020-10-26 09:01:06.796729", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "taxes_and_charges", + "idx": 0, + "is_system_generated": 0, + "modified": "2020-10-26 09:01:06.796729", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-taxes_and_charges-in_standard_filter", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_standard_filter", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-04-02 19:09:40.941137", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "taxes_and_charges", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-04-02 19:09:40.941137", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-taxes_and_charges-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "177" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.435258", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "tc_name", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.435258", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-tc_name-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.194153", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "territory", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.194153", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-territory-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-05-01 17:10:45.973240", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "territory", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-05-01 17:10:45.973240", + "modified_by": "ravi.singh@rigpl.com", + "module": null, + "name": "Sales Invoice-territory-width", + "owner": "ravi.singh@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "97" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-08-01 20:11:19.957870", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "time_sheet_list", + "idx": 0, + "is_system_generated": 0, + "modified": "2016-08-01 20:11:19.957870", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-time_sheet_list-hidden", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2022-02-07 05:50:03.743794", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": null, + "idx": 0, + "is_system_generated": 0, + "modified": "2022-02-07 05:50:03.743794", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-title_field", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "title_field", + "property_type": "Data", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "customer_name" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-03-03 14:36:37.155186", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "total_taxes_and_charges", + "idx": 0, + "is_system_generated": 0, + "modified": "2018-03-03 14:36:37.155186", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-total_taxes_and_charges-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "71" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 19:17:16.258611", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "total", + "idx": 0, + "is_system_generated": 1, + "modified": "2016-08-04 14:32:36.346704", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-total-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-11-03 16:42:24.060116", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "transporters", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-11-03 16:42:24.060116", + "modified_by": "abhinav@rigpl.com", + "module": null, + "name": "Sales Invoice-transporters-width", + "owner": "abhinav@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "114" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2022-02-07 11:03:28.359301", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "update_stock", + "idx": 0, + "is_system_generated": 0, + "modified": "2022-02-07 11:03:28.359301", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-update_stock-default", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "default", + "property_type": "Text", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2014-12-11 14:26:34.234729", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "update_stock", + "idx": 0, + "is_system_generated": 0, + "modified": "2014-12-11 14:26:34.234729", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-update_stock-hidden", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.403700", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "write_off_account", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.403700", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-write_off_account-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-31 17:53:58.250523", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "write_off_account", + "idx": 0, + "is_system_generated": 0, + "modified": "2015-05-31 17:53:58.250523", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-write_off_account-permlevel", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "permlevel", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-31 17:53:58.217006", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "write_off_amount", + "idx": 0, + "is_system_generated": 0, + "modified": "2015-05-31 17:53:58.217006", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-write_off_amount-permlevel", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "permlevel", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-09-01 11:32:01.416413", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "write_off_cost_center", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-09-01 11:32:01.416413", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-write_off_cost_center-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-31 17:53:58.265994", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "write_off_cost_center", + "idx": 0, + "is_system_generated": 0, + "modified": "2015-05-31 17:53:58.265994", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Invoice-write_off_cost_center-permlevel", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "permlevel", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + } + ], "sync_on_migrate": 1 } \ No newline at end of file diff --git a/rohit_common/rohit_common/custom/sales_invoice_item.json b/rohit_common/rohit_common/custom/sales_invoice_item.json index 746fa45..d9c07ed 100644 --- a/rohit_common/rohit_common/custom/sales_invoice_item.json +++ b/rohit_common/rohit_common/custom/sales_invoice_item.json @@ -11,7 +11,7 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2018-12-21 13:29:13.645810", + "creation": "2025-08-29 14:43:26.236960", "default": null, "depends_on": null, "description": null, @@ -19,13 +19,13 @@ "dt": "Sales Invoice Item", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "price_list", - "fieldtype": "Link", + "fieldname": "cb_gst_details", + "fieldtype": "Column Break", "hidden": 0, "hide_border": 0, "hide_days": 0, "hide_seconds": 0, - "idx": 21, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, @@ -34,20 +34,27 @@ "in_list_view": 0, "in_preview": 0, "in_standard_filter": 0, - "insert_after": "price_list_rate", - "label": "Price List", + "index": null, + "insert_after": "cess_non_advol_rate", + "is_system_generated": 1, + "is_virtual": 0, + "label": null, "length": 0, + "link_filters": null, "mandatory_depends_on": null, - "modified": "2018-12-21 13:29:13.645810", + "modified": "2025-08-29 14:43:26.236960", "modified_by": "Administrator", - "name": "Sales Invoice Item-price_list", + "module": "GST India", + "name": "Sales Invoice Item-cb_gst_details", "no_copy": 0, - "options": "Price List", + "non_negative": 0, + "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, @@ -57,7 +64,10 @@ "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -72,7 +82,7 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2018-12-22 05:56:30.738386", + "creation": "2025-08-29 14:43:26.308905", "default": null, "depends_on": null, "description": null, @@ -80,13 +90,13 @@ "dt": "Sales Invoice Item", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "gst_hsn_code", - "fieldtype": "Read Only", + "fieldname": "cess_amount", + "fieldtype": "Currency", "hidden": 0, "hide_border": 0, "hide_days": 0, "hide_seconds": 0, - "idx": 13, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, @@ -95,20 +105,169 @@ "in_list_view": 0, "in_preview": 0, "in_standard_filter": 0, - "insert_after": "stock_uom", - "label": "GST HSN Code", + "index": null, + "insert_after": "sgst_amount", + "is_system_generated": 1, + "is_virtual": 0, + "label": "CESS Amount", "length": 0, + "link_filters": null, "mandatory_depends_on": null, - "modified": "2018-12-22 05:56:30.738386", + "modified": "2025-08-29 14:43:26.308905", "modified_by": "Administrator", - "name": "Sales Invoice Item-gst_hsn_code", - "no_copy": 0, + "module": "GST India", + "name": "Sales Invoice Item-cess_amount", + "no_copy": 1, + "non_negative": 0, + "options": "Company:company:default_currency", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-08-29 14:43:26.322660", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "cess_non_advol_amount", + "fieldtype": "Currency", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "cess_amount", + "is_system_generated": 1, + "is_virtual": 0, + "label": "CESS Non Advol Amount", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:26.322660", + "modified_by": "Administrator", + "module": "GST India", + "name": "Sales Invoice Item-cess_non_advol_amount", + "no_copy": 1, + "non_negative": 0, + "options": "Company:company:default_currency", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-08-29 14:43:26.221766", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "cess_non_advol_rate", + "fieldtype": "Float", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "cess_rate", + "is_system_generated": 1, + "is_virtual": 0, + "label": "CESS Non Advol Rate", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:26.221766", + "modified_by": "Administrator", + "module": "GST India", + "name": "Sales Invoice Item-cess_non_advol_rate", + "no_copy": 1, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, @@ -118,7 +277,10 @@ "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -133,21 +295,21 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:42:32.559402", + "creation": "2025-08-29 14:43:26.209048", "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice Item", - "fetch_from": "item_code.is_nil_exempt", + "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "is_nil_exempt", - "fieldtype": "Check", + "fieldname": "cess_rate", + "fieldtype": "Float", "hidden": 0, "hide_border": 0, "hide_days": 0, "hide_seconds": 0, - "idx": 8, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, @@ -156,30 +318,40 @@ "in_list_view": 0, "in_preview": 0, "in_standard_filter": 0, - "insert_after": "gst_hsn_code", - "label": "Is Nil Rated or Exempted", + "index": null, + "insert_after": "sgst_rate", + "is_system_generated": 1, + "is_virtual": 0, + "label": "CESS Rate", "length": 0, + "link_filters": null, "mandatory_depends_on": null, - "modified": "2020-08-07 17:19:14.522065", + "modified": "2025-08-29 14:43:26.209048", "modified_by": "Administrator", - "name": "Sales Invoice Item-is_nil_exempt", - "no_copy": 0, + "module": "GST India", + "name": "Sales Invoice Item-cess_rate", + "no_copy": 1, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 1, + "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, "width": null }, @@ -194,21 +366,21 @@ "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-07-04 10:42:51.880658", + "creation": "2025-08-29 14:43:26.283319", "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Sales Invoice Item", - "fetch_from": "item_code.is_non_gst", + "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "is_non_gst", - "fieldtype": "Check", + "fieldname": "cgst_amount", + "fieldtype": "Currency", "hidden": 0, "hide_border": 0, "hide_days": 0, "hide_seconds": 0, - "idx": 9, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, @@ -217,22 +389,171 @@ "in_list_view": 0, "in_preview": 0, "in_standard_filter": 0, - "insert_after": "is_nil_exempt", - "label": "Is Non GST", + "index": null, + "insert_after": "igst_amount", + "is_system_generated": 1, + "is_virtual": 0, + "label": "CGST Amount", "length": 0, + "link_filters": null, "mandatory_depends_on": null, - "modified": "2020-08-07 17:19:17.955122", + "modified": "2025-08-29 14:43:26.283319", "modified_by": "Administrator", - "name": "Sales Invoice Item-is_non_gst", + "module": "GST India", + "name": "Sales Invoice Item-cgst_amount", + "no_copy": 1, + "non_negative": 0, + "options": "Company:company:default_currency", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-08-29 14:43:26.183631", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "cgst_rate", + "fieldtype": "Float", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "igst_rate", + "is_system_generated": 1, + "is_virtual": 0, + "label": "CGST Rate", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:26.183631", + "modified_by": "Administrator", + "module": "GST India", + "name": "Sales Invoice Item-cgst_rate", + "no_copy": 1, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 1, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-08-29 14:43:26.157620", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "gst_details_section", + "fieldtype": "Section Break", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "taxable_value", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST Details", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:26.157620", + "modified_by": "Administrator", + "module": "GST India", + "name": "Sales Invoice Item-gst_details_section", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 1, + "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, @@ -240,13 +561,2258 @@ "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, + "trash_reason": null, "unique": 0, "width": null - } - ], - "custom_perms": [], - "doctype": "Sales Invoice Item", - "property_setters": [], + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2018-12-22 05:56:30.738386", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "gst_hsn_code", + "fieldtype": "Read Only", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 13, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": 0.0, + "insert_after": "stock_uom", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST HSN Code", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2018-12-22 05:56:30.738386", + "modified_by": "Administrator", + "module": "GST India", + "name": "Sales Invoice Item-gst_hsn_code", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-08-29 14:43:26.143992", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice Item", + "fetch_from": "item_tax_template.gst_treatment", + "fetch_if_empty": 1, + "fieldname": "gst_treatment", + "fieldtype": "Autocomplete", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "item_tax_template", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST Treatment", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:26.143992", + "modified_by": "Administrator", + "module": "GST India", + "name": "Sales Invoice Item-gst_treatment", + "no_copy": 1, + "non_negative": 0, + "options": "Taxable\nZero-Rated\nNil-Rated\nExempted\nNon-GST", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-08-29 14:43:26.250216", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "igst_amount", + "fieldtype": "Currency", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "cb_gst_details", + "is_system_generated": 1, + "is_virtual": 0, + "label": "IGST Amount", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:26.250216", + "modified_by": "Administrator", + "module": "GST India", + "name": "Sales Invoice Item-igst_amount", + "no_copy": 1, + "non_negative": 0, + "options": "Company:company:default_currency", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-08-29 14:43:26.170746", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "igst_rate", + "fieldtype": "Float", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "gst_details_section", + "is_system_generated": 1, + "is_virtual": 0, + "label": "IGST Rate", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:26.170746", + "modified_by": "Administrator", + "module": "GST India", + "name": "Sales Invoice Item-igst_rate", + "no_copy": 1, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2020-07-04 10:42:32.559402", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice Item", + "fetch_from": "item_code.is_nil_exempt", + "fetch_if_empty": 0, + "fieldname": "is_nil_exempt", + "fieldtype": "Check", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 8, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "gst_hsn_code", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Is Nil Rated or Exempted", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:19:14.522065", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-is_nil_exempt", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2020-07-04 10:42:51.880658", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice Item", + "fetch_from": "item_code.is_non_gst", + "fetch_if_empty": 0, + "fieldname": "is_non_gst", + "fieldtype": "Check", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 9, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "is_nil_exempt", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Is Non GST", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-08-07 17:19:17.955122", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-is_non_gst", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2018-12-21 13:29:13.645810", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "price_list", + "fieldtype": "Link", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 21, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": 0.0, + "insert_after": "price_list_rate", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Price List", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2018-12-21 13:29:13.645810", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-price_list", + "no_copy": 0, + "non_negative": 0, + "options": "Price List", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-08-29 14:43:26.296093", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "sgst_amount", + "fieldtype": "Currency", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "cgst_amount", + "is_system_generated": 1, + "is_virtual": 0, + "label": "SGST Amount", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:26.296093", + "modified_by": "Administrator", + "module": "GST India", + "name": "Sales Invoice Item-sgst_amount", + "no_copy": 1, + "non_negative": 0, + "options": "Company:company:default_currency", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-08-29 14:43:26.196390", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "sgst_rate", + "fieldtype": "Float", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "cgst_rate", + "is_system_generated": 1, + "is_virtual": 0, + "label": "SGST Rate", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:26.196390", + "modified_by": "Administrator", + "module": "GST India", + "name": "Sales Invoice Item-sgst_rate", + "no_copy": 1, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2021-04-16 15:19:02.066613", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Invoice Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "taxable_value", + "fieldtype": "Currency", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 49, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "base_net_amount", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Taxable Value", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:24.582740", + "modified_by": "Administrator", + "module": "GST India", + "name": "Sales Invoice Item-taxable_value", + "no_copy": 1, + "non_negative": 0, + "options": "Company:company:default_currency", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + } + ], + "custom_perms": [], + "doctype": "Sales Invoice Item", + "links": [], + "property_setters": [ + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 15:54:56.271396", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "amount", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:39:58.580564", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-amount-columns", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "columns", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-08-08 16:54:22.385099", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "amount", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:02.851736", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-amount-precision", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 15:49:50.270739", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "amount", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:00.454902", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-amount-print_hide", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_hide", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-05-21 23:01:46.551812", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "amount", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:02.508594", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-amount-width", + "owner": "ravi.singh@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "64" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-11-04 13:28:02.586895", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "barcode", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:39:56.926377", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-barcode-hidden", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 19:17:17.733415", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_amount", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:04.547667", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-base_amount-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 19:17:17.527179", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_net_amount", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:04.387093", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-base_net_amount-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 19:17:17.330371", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_net_rate", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:04.215332", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-base_net_rate-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-08-08 16:54:22.365743", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_price_list_rate", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:03.179871", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-base_price_list_rate-precision", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 19:17:17.627396", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_rate", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:04.068218", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-base_rate-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 15:52:43.485609", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "batch_no", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:39:59.115229", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-batch_no-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-11-13 10:24:58.264310", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "cost_center", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:01.865792", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-cost_center-ignore_user_permissions", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2013-07-29 00:11:17", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "cost_center", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:05.810296", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-cost_center-reqd", + "owner": "anuj@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "reqd", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-11-13 10:24:58.274303", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "deferred_revenue_account", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:01.677049", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-deferred_revenue_account-ignore_user_permissions", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2014-08-08 10:48:02.829081", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "delivery_note", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:05.486956", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-delivery_note-print_hide", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_hide", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 15:52:43.417230", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "description", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:39:59.987151", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-description-columns", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "columns", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "2" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-06-06 02:23:09.983466", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "description", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:04.697492", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-description-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 15:49:50.230549", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "description", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:01.040994", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-description-print_width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_width", + "property_type": "Data", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "400px" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 15:45:37.145497", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "description", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:01.341978", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-description-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": "Data", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "100px" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-09-13 20:05:50.341901", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "discount_account", + "idx": 0, + "is_system_generated": 1, + "modified": "2025-09-13 20:05:50.341901", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-discount_account-hidden", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-09-13 20:05:50.360769", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "discount_account", + "idx": 0, + "is_system_generated": 1, + "modified": "2025-09-13 20:05:50.360769", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-discount_account-mandatory_depends_on", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "mandatory_depends_on", + "property_type": "Code", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 15:52:43.451304", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "discount_percentage", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:39:59.501573", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-discount_percentage-columns", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "columns", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 15:52:43.444022", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "discount_percentage", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:39:59.658175", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-discount_percentage-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-11-13 10:24:58.256685", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "expense_account", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:02.048191", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-expense_account-ignore_user_permissions", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 15:50:52.586273", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "image", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:00.307938", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-image-print_hide", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_hide", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-11-13 10:24:58.250202", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "income_account", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:02.212179", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-income_account-ignore_user_permissions", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 15:52:43.407462", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "item_code", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:00.151951", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-item_code-columns", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "columns", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 15:49:50.222881", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "item_code", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:01.191424", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-item_code-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": "Data", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "50px" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2012-01-27 18:02:19", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "item_name", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:06.109171", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-item_name-hidden", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-31 22:08:54.928454", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "item_name", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:04.844516", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-item_name-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-08-08 16:54:22.342277", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "item_name", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:03.491482", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-item_name-length", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "length", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "255" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2013-07-27 10:43:28", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "item_name", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:05.957494", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-item_name-reqd", + "owner": "anuj@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "reqd", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 15:54:56.231410", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": null, + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:39:58.754700", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-main-read_only_onload", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "read_only_onload", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 19:17:17.429526", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "net_amount", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:03.907870", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-net_amount-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 19:17:17.203129", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "net_rate", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:03.716386", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-net_rate-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-08-08 16:54:22.356025", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "price_list_rate", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:03.336684", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-price_list_rate-precision", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 15:52:43.426655", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "qty", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:39:59.809798", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-qty-columns", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "columns", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 15:49:50.247501", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "qty", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:00.744590", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-qty-print_width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_width", + "property_type": "Data", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "50px" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 15:49:50.241487", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "qty", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:00.894752", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-qty-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": "Data", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "50px" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 15:52:43.459945", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "rate", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:39:59.302966", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-rate-columns", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "columns", + "property_type": "Int", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-08-08 16:54:22.377666", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "rate", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:03.023302", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-rate-precision", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 15:49:50.261611", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "rate", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:00.597401", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-rate-print_hide", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_hide", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-11-24 12:43:31.567178", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "rate", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:02.666829", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-rate-width", + "owner": "abhinav@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "75" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-09 15:14:02.886254", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "sales_order", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:04.989570", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-sales_order-in_filter", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_filter", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2014-08-08 10:48:02.807031", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "sales_order", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:05.656218", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-sales_order-print_hide", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_hide", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-08-08 19:28:16.499844", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "sales_order", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:02.361954", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-sales_order-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "76" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 15:52:43.493332", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "serial_no", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:39:58.934808", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-serial_no-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-08-22 16:43:05.094055", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "target_warehouse", + "idx": 0, + "is_system_generated": 1, + "modified": "2025-08-22 16:43:05.094055", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-target_warehouse-hidden", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-11-13 10:24:58.289397", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "warehouse", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:01.494057", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-warehouse-ignore_user_permissions", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-09 15:11:05.493514", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "warehouse", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:05.160193", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-warehouse-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-04-03 17:32:01.557773", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "warehouse", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-08-22 18:40:05.330945", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice Item-warehouse-print_hide", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_hide", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + } + ], "sync_on_migrate": 1 } \ No newline at end of file diff --git a/rohit_common/rohit_common/custom/sales_taxes_and_charges.json b/rohit_common/rohit_common/custom/sales_taxes_and_charges.json new file mode 100644 index 0000000..43e045d --- /dev/null +++ b/rohit_common/rohit_common/custom/sales_taxes_and_charges.json @@ -0,0 +1,411 @@ +{ + "custom_fields": [ + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-08-29 14:43:27.450291", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Sales Taxes and Charges", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "gst_tax_type", + "fieldtype": "Data", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "index": null, + "insert_after": "rate", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST Tax Type", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-08-29 14:43:27.450291", + "modified_by": "Administrator", + "module": "GST India", + "name": "Sales Taxes and Charges-gst_tax_type", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "trash_reason": null, + "unique": 0, + "width": null + } + ], + "custom_perms": [], + "doctype": "Sales Taxes and Charges", + "links": [], + "property_setters": [ + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-11-08 16:23:11.312177", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": "", + "idx": 0, + "is_system_generated": 1, + "modified": "2018-11-08 16:23:11.312177", + "modified_by": "Administrator", + "module": null, + "name": "Sales Taxes and Charges-autoname", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "autoname", + "property_type": "", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "INVTD.######" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 18:20:45.508097", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_tax_amount_after_discount_amount", + "idx": 0, + "is_system_generated": 1, + "modified": "2015-05-30 18:20:45.508097", + "modified_by": "Administrator", + "module": null, + "name": "Sales Taxes and Charges-base_tax_amount_after_discount_amount-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "2" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 18:20:45.165010", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_tax_amount", + "idx": 0, + "is_system_generated": 1, + "modified": "2015-05-30 18:20:45.165010", + "modified_by": "Administrator", + "module": null, + "name": "Sales Taxes and Charges-base_tax_amount-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "2" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 18:20:45.336839", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_total", + "idx": 0, + "is_system_generated": 1, + "modified": "2015-05-30 18:20:45.336839", + "modified_by": "Administrator", + "module": null, + "name": "Sales Taxes and Charges-base_total-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "2" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-06-27 22:15:21.625039", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "charge_type", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-06-27 22:15:21.625039", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Taxes and Charges-charge_type-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2013-07-28 17:45:41", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "cost_center", + "idx": 0, + "is_system_generated": 0, + "modified": "2013-07-28 17:45:41", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Taxes and Charges-cost_center-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-06-27 22:15:21.633560", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "description", + "idx": 0, + "is_system_generated": 0, + "modified": "2017-06-27 22:15:21.633560", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Taxes and Charges-description-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2013-07-28 17:45:41", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "included_in_print_rate", + "idx": 0, + "is_system_generated": 0, + "modified": "2013-07-28 17:45:41", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Taxes and Charges-included_in_print_rate-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 18:20:45.423948", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "tax_amount_after_discount_amount", + "idx": 0, + "is_system_generated": 1, + "modified": "2015-05-30 18:20:45.423948", + "modified_by": "Administrator", + "module": null, + "name": "Sales Taxes and Charges-tax_amount_after_discount_amount-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "2" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2013-07-28 17:45:41", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "total", + "idx": 0, + "is_system_generated": 0, + "modified": "2013-07-28 17:45:41", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Sales Taxes and Charges-total-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 18:20:45.248409", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "total", + "idx": 0, + "is_system_generated": 1, + "modified": "2015-05-30 18:20:45.248409", + "modified_by": "Administrator", + "module": null, + "name": "Sales Taxes and Charges-total-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "2" + } + ], + "sync_on_migrate": 1 +} \ No newline at end of file diff --git a/rohit_common/rohit_common/validations/address.py b/rohit_common/rohit_common/validations/address.py index acc4373..4eef055 100644 --- a/rohit_common/rohit_common/validations/address.py +++ b/rohit_common/rohit_common/validations/address.py @@ -107,8 +107,12 @@ def country_validation(doc): WHERE country = '{doc.country}'""", as_dict=1) if state_list: if doc.state_rigpl is None or not doc.state_rigpl or doc.state_rigpl == "": - frappe.throw(f"State RIGPL for Country {doc.country} is Mandatory in \ - Address {doc.name}") + if doc.state: + doc.state_rigpl = doc.state + else: + frappe.throw(f"State RIGPL for Country {doc.country} is Mandatory in Address {doc.name}") + # frappe.throw(f"State RIGPL for Country {doc.country} is Mandatory in \ + # Address {doc.name}") if country_doc.pincode_length: pincode_length = replace_java_chars(country_doc.pincode_length) if 'or' in pincode_length: From cb84d7aebb792b530d4cfb3633a6805287787294 Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Mon, 13 Oct 2025 13:36:53 +0530 Subject: [PATCH 23/52] fix: update required_apps and modify address and sales_invoice (#14) --- rohit_common/hooks.py | 3 + rohit_common/rohit_common/custom/address.json | 102 +- .../rohit_common/custom/packed_item.json | 2 +- .../rohit_common/custom/sales_invoice.json | 1106 ++++++++--------- .../custom/sales_invoice_item.json | 102 +- .../custom/sales_taxes_and_charges.json | 90 +- 6 files changed, 719 insertions(+), 686 deletions(-) diff --git a/rohit_common/hooks.py b/rohit_common/hooks.py index c4a9e9b..9903518 100644 --- a/rohit_common/hooks.py +++ b/rohit_common/hooks.py @@ -12,6 +12,9 @@ app_version = "0.0.1" hide_in_installer = True +required_apps = ["frappe/erpnext", "resilient-tech/india-compliance"] + + # Fixtures help https://frappeframework.com/docs/v13/user/en/python-api/hooks#fixtures fixtures = [ { diff --git a/rohit_common/rohit_common/custom/address.json b/rohit_common/rohit_common/custom/address.json index 4ff986a..46acecd 100644 --- a/rohit_common/rohit_common/custom/address.json +++ b/rohit_common/rohit_common/custom/address.json @@ -2433,7 +2433,7 @@ "field_name": "address_line1", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.561973", + "modified": "2025-10-13 12:51:19.299752", "modified_by": "Administrator", "module": null, "name": "Address-address_line1-length", @@ -2463,7 +2463,7 @@ "field_name": "address_line1", "idx": 0, "is_system_generated": 0, - "modified": "2025-10-08 10:54:31.892658", + "modified": "2025-10-13 12:51:19.445916", "modified_by": "Administrator", "module": null, "name": "Address-address_line1-translatable", @@ -2493,7 +2493,7 @@ "field_name": "address_line1", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.659779", + "modified": "2025-10-13 12:51:19.477317", "modified_by": "Administrator", "module": null, "name": "Address-address_line1-width", @@ -2523,7 +2523,7 @@ "field_name": "address_line2", "idx": 0, "is_system_generated": 0, - "modified": "2025-10-08 10:54:31.927981", + "modified": "2025-10-13 12:51:19.507140", "modified_by": "Administrator", "module": null, "name": "Address-address_line2-translatable", @@ -2553,7 +2553,7 @@ "field_name": "address_line2", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.646005", + "modified": "2025-10-13 12:51:19.538796", "modified_by": "Administrator", "module": null, "name": "Address-address_line2-width", @@ -2583,7 +2583,7 @@ "field_name": "address_title", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.673674", + "modified": "2025-10-13 12:51:19.571034", "modified_by": "Administrator", "module": null, "name": "Address-address_title-reqd", @@ -2613,7 +2613,7 @@ "field_name": "address_type", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.464209", + "modified": "2025-10-13 12:51:19.602743", "modified_by": "Administrator", "module": null, "name": "Address-address_type-width", @@ -2643,7 +2643,7 @@ "field_name": "city", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.338485", + "modified": "2025-10-13 12:51:19.636042", "modified_by": "Administrator", "module": null, "name": "Address-city-in_standard_filter", @@ -2673,7 +2673,7 @@ "field_name": "city", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.386242", + "modified": "2025-10-13 12:51:19.670097", "modified_by": "Administrator", "module": null, "name": "Address-city-width", @@ -2703,7 +2703,7 @@ "field_name": "company", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.575395", + "modified": "2025-10-13 12:51:19.704557", "modified_by": "Administrator", "module": null, "name": "Address-company-permlevel", @@ -2733,7 +2733,7 @@ "field_name": "country", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.211148", + "modified": "2025-10-13 12:51:19.739594", "modified_by": "Administrator", "module": null, "name": "Address-country-ignore_user_permissions", @@ -2763,7 +2763,7 @@ "field_name": "country", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.428606", + "modified": "2025-10-13 12:51:19.774005", "modified_by": "Administrator", "module": null, "name": "Address-country-width", @@ -2793,7 +2793,7 @@ "field_name": "county", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.534163", + "modified": "2025-10-13 12:51:19.804161", "modified_by": "Administrator", "module": null, "name": "Address-county-hidden", @@ -2823,7 +2823,7 @@ "field_name": "county", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.548284", + "modified": "2025-10-13 12:51:19.842981", "modified_by": "Administrator", "module": null, "name": "Address-county-read_only", @@ -2853,7 +2853,7 @@ "field_name": "county", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.505986", + "modified": "2025-10-13 12:51:19.876941", "modified_by": "Administrator", "module": null, "name": "Address-county-width", @@ -2883,7 +2883,7 @@ "field_name": "customer_name", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.618363", + "modified": "2025-10-13 12:51:19.909948", "modified_by": "Administrator", "module": null, "name": "Address-customer_name-width", @@ -2913,7 +2913,7 @@ "field_name": "customer", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.719774", + "modified": "2025-10-13 12:51:19.942886", "modified_by": "Administrator", "module": null, "name": "Address-customer-width", @@ -2943,7 +2943,7 @@ "field_name": "email_id", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.093304", + "modified": "2025-10-13 12:51:19.977106", "modified_by": "Administrator", "module": null, "name": "Address-email_id-in_standard_filter", @@ -2973,7 +2973,7 @@ "field_name": "email_id", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.632330", + "modified": "2025-10-13 12:51:20.000107", "modified_by": "Administrator", "module": null, "name": "Address-email_id-width", @@ -3003,7 +3003,7 @@ "field_name": "excise_no", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.687749", + "modified": "2025-10-13 12:51:20.020616", "modified_by": "Administrator", "module": null, "name": "Address-excise_no-width", @@ -3033,7 +3033,7 @@ "field_name": "gstin", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.399950", + "modified": "2025-10-13 12:51:20.052730", "modified_by": "Administrator", "module": null, "name": "Address-gstin-width", @@ -3063,7 +3063,7 @@ "field_name": "is_your_company_address", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.589754", + "modified": "2025-10-13 12:51:20.085575", "modified_by": "Administrator", "module": null, "name": "Address-is_your_company_address-permlevel", @@ -3093,7 +3093,7 @@ "field_name": null, "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.603884", + "modified": "2025-10-13 12:51:20.120556", "modified_by": "Administrator", "module": null, "name": "Address-main-_idx", @@ -3123,7 +3123,7 @@ "field_name": null, "idx": 0, "is_system_generated": 0, - "modified": "2025-10-08 10:54:31.851413", + "modified": "2025-10-13 12:51:20.157778", "modified_by": "Administrator", "module": null, "name": "Address-main-field_order", @@ -3153,7 +3153,7 @@ "field_name": null, "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.734012", + "modified": "2025-10-13 12:51:20.191875", "modified_by": "Administrator", "module": null, "name": "Address-main-in_dialog", @@ -3183,7 +3183,7 @@ "field_name": null, "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.182158", + "modified": "2025-10-13 12:51:20.227981", "modified_by": "Administrator", "module": null, "name": "Address-main-search_fields", @@ -3213,7 +3213,7 @@ "field_name": null, "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.492054", + "modified": "2025-10-13 12:51:20.261641", "modified_by": "Administrator", "module": null, "name": "Address-main-track_changes", @@ -3243,7 +3243,7 @@ "field_name": "phone", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.414238", + "modified": "2025-10-13 12:51:20.298084", "modified_by": "Administrator", "module": null, "name": "Address-phone-width", @@ -3273,7 +3273,7 @@ "field_name": "pincode", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.295246", + "modified": "2025-10-13 12:51:20.335775", "modified_by": "Administrator", "module": null, "name": "Address-pincode-in_standard_filter", @@ -3303,7 +3303,7 @@ "field_name": "pincode", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.366987", + "modified": "2025-10-13 12:51:20.370340", "modified_by": "Administrator", "module": null, "name": "Address-pincode-width", @@ -3333,7 +3333,7 @@ "field_name": "state", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.196936", + "modified": "2025-10-13 12:51:20.396211", "modified_by": "Administrator", "module": null, "name": "Address-state-depends_on", @@ -3342,13 +3342,43 @@ "parentfield": null, "parenttype": null, "property": "depends_on", - "property_type": "Data", + "property_type": "Autocomplete", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, "value": "eval: !doc.state_rigpl" }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-10-13 13:03:26.964127", + "default_value": null, + "doc_name": null, + "doc_type": "Address", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "state", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-10-13 13:03:26.964127", + "modified_by": "Administrator", + "module": null, + "name": "Address-state-fieldtype", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "fieldtype", + "property_type": "Select", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "Autocomplete" + }, { "_assign": null, "_comments": null, @@ -3363,7 +3393,7 @@ "field_name": "state", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.478529", + "modified": "2025-10-13 12:51:20.416470", "modified_by": "Administrator", "module": null, "name": "Address-state-options", @@ -3372,7 +3402,7 @@ "parentfield": null, "parenttype": null, "property": "options", - "property_type": "Text", + "property_type": "Autocomplete", "row_name": null, "select_doctype": null, "select_item": null, @@ -3393,7 +3423,7 @@ "field_name": "state", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.519793", + "modified": "2025-10-13 12:51:20.434857", "modified_by": "Administrator", "module": null, "name": "Address-state-width", @@ -3423,7 +3453,7 @@ "field_name": "supplier", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:07:50.706743", + "modified": "2025-10-13 12:51:20.453667", "modified_by": "Administrator", "module": null, "name": "Address-supplier-width", diff --git a/rohit_common/rohit_common/custom/packed_item.json b/rohit_common/rohit_common/custom/packed_item.json index 53637ee..d46e44a 100644 --- a/rohit_common/rohit_common/custom/packed_item.json +++ b/rohit_common/rohit_common/custom/packed_item.json @@ -18,7 +18,7 @@ "field_name": "rate", "idx": 0, "is_system_generated": 1, - "modified": "2025-09-13 20:05:50.321303", + "modified": "2025-10-13 12:51:20.986298", "modified_by": "Administrator", "module": null, "name": "Packed Item-rate-read_only", diff --git a/rohit_common/rohit_common/custom/sales_invoice.json b/rohit_common/rohit_common/custom/sales_invoice.json index bdbb8b2..0693a1c 100644 --- a/rohit_common/rohit_common/custom/sales_invoice.json +++ b/rohit_common/rohit_common/custom/sales_invoice.json @@ -4357,36 +4357,6 @@ } ], "property_setters": [ - { - "_assign": null, - "_comments": null, - "_liked_by": null, - "_user_tags": null, - "creation": "2015-12-30 14:57:06.966434", - "default_value": null, - "doc_name": null, - "doc_type": "Sales Invoice", - "docstatus": 0, - "doctype_or_field": "DocType", - "field_name": null, - "idx": 0, - "is_system_generated": 1, - "modified": "2015-12-30 14:57:06.966434", - "modified_by": "Administrator", - "module": null, - "name": "Sales Invoice-_idx", - "owner": "Administrator", - "parent": null, - "parentfield": null, - "parenttype": null, - "property": "_idx", - "property_type": "Text", - "row_name": null, - "select_doctype": null, - "select_item": null, - "select_property": null, - "value": "[\"customer_section\", \"naming_series\", \"customer\", \"customer_address\", \"shipping_address_name\", \"ship_to\", \"ship_terms\", \"transporters\", \"lr_no\", \"customer_name\", \"address_display\", \"contact_display\", \"contact_mobile\", \"contact_email\", \"column_break1\", \"is_pos\", \"amended_from\", \"company\", \"posting_date\", \"posting_time\", \"removal_date\", \"removal_time\", \"shipping_contact_no\", \"due_date\", \"mode_of_payment\", \"po_no\", \"po_date\", \"column_break4\", \"payments_section\", \"write_off_outstanding_amount_automatically\", \"paid_amount\", \"cash_bank_account\", \"column_break3\", \"write_off_amount\", \"write_off_account\", \"write_off_cost_center\", \"currency_and_price_list\", \"currency\", \"conversion_rate\", \"ignore_pricing_rule\", \"column_break2\", \"selling_price_list\", \"price_list_currency\", \"plc_conversion_rate\", \"update_stock\", \"items_section\", \"items\", \"packing_list\", \"packed_items\", \"sales_bom_help\", \"section_break_30\", \"base_net_total\", \"base_total\", \"net_total\", \"column_break_32\", \"total\", \"taxes_section\", \"taxes_and_charges\", \"column_break_38\", \"shipping_rule\", \"section_break_40\", \"taxes\", \"other_charges_calculation\", \"section_break_43\", \"base_total_taxes_and_charges\", \"column_break_47\", \"total_taxes_and_charges\", \"section_break_49\", \"apply_discount_on\", \"column_break_51\", \"discount_amount\", \"base_discount_amount\", \"totals\", \"base_grand_total\", \"base_rounded_total\", \"base_in_words\", \"column_break5\", \"grand_total\", \"rounded_total\", \"in_words\", \"total_advance\", \"outstanding_amount\", \"advances_section\", \"get_advances_received\", \"advances\", \"column_break_74\", \"fold\", \"terms_section_break\", \"tc_name\", \"terms\", \"contact_section\", \"territory\", \"customer_group\", \"col_break23\", \"shipping_address\", \"contact_person\", \"shipping_tin_no\", \"shipping_excise_no\", \"more_info\", \"debit_to\", \"project_name\", \"campaign\", \"source\", \"is_opening\", \"c_form_applicable\", \"c_form_no\", \"column_break8\", \"letter_head\", \"tin_no\", \"excise_no\", \"select_print_heading\", \"fiscal_year\", \"remarks\", \"sales_team_section_break\", \"column_break9\", \"sales_partner\", \"column_break10\", \"commission_rate\", \"total_commission\", \"section_break2\", \"sales_team\", \"recurring_invoice\", \"column_break11\", \"is_recurring\", \"recurring_type\", \"from_date\", \"to_date\", \"repeat_on_day_of_month\", \"end_date\", \"column_break12\", \"next_date\", \"recurring_id\", \"notification_email_address\", \"against_income_account\"]" - }, { "_assign": null, "_comments": null, @@ -4401,8 +4371,8 @@ "field_name": "account_for_change_amount", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.383181", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:27.337367", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-account_for_change_amount-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -4431,7 +4401,7 @@ "field_name": "additional_discount_account", "idx": 0, "is_system_generated": 1, - "modified": "2025-09-13 20:05:50.377400", + "modified": "2025-10-13 12:51:27.356874", "modified_by": "Administrator", "module": null, "name": "Sales Invoice-additional_discount_account-hidden", @@ -4461,7 +4431,7 @@ "field_name": "additional_discount_account", "idx": 0, "is_system_generated": 1, - "modified": "2025-09-13 20:05:50.392317", + "modified": "2025-10-13 12:51:27.375563", "modified_by": "Administrator", "module": null, "name": "Sales Invoice-additional_discount_account-mandatory_depends_on", @@ -4491,8 +4461,8 @@ "field_name": "address_display", "idx": 0, "is_system_generated": 0, - "modified": "2016-08-04 14:32:36.308479", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:27.397204", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-address_display-precision", "owner": "aditya@rigpl.com", @@ -4521,8 +4491,8 @@ "field_name": "address_display", "idx": 0, "is_system_generated": 0, - "modified": "2017-03-15 14:00:59.875930", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:27.420394", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-address_display-width", "owner": "aditya@rigpl.com", @@ -4551,8 +4521,8 @@ "field_name": "base_grand_total", "idx": 0, "is_system_generated": 0, - "modified": "2015-09-22 07:13:05.580039", - "modified_by": "ravi.singh@rigpl.com", + "modified": "2025-10-13 12:51:27.441353", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-base_grand_total-width", "owner": "ravi.singh@rigpl.com", @@ -4581,8 +4551,8 @@ "field_name": "base_net_total", "idx": 0, "is_system_generated": 1, - "modified": "2016-08-04 14:32:36.317189", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:27.461387", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-base_net_total-precision", "owner": "Administrator", @@ -4611,7 +4581,7 @@ "field_name": "base_rounded_total", "idx": 0, "is_system_generated": 1, - "modified": "2025-08-22 16:43:09.563222", + "modified": "2025-10-13 12:51:27.480796", "modified_by": "Administrator", "module": null, "name": "Sales Invoice-base_rounded_total-hidden", @@ -4641,7 +4611,7 @@ "field_name": "base_rounded_total", "idx": 0, "is_system_generated": 1, - "modified": "2025-08-22 16:43:09.675430", + "modified": "2025-10-13 12:51:27.503580", "modified_by": "Administrator", "module": null, "name": "Sales Invoice-base_rounded_total-print_hide", @@ -4671,8 +4641,8 @@ "field_name": "base_total", "idx": 0, "is_system_generated": 1, - "modified": "2016-08-04 14:32:36.326016", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:27.522794", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-base_total-precision", "owner": "Administrator", @@ -4701,8 +4671,8 @@ "field_name": "billing_address_gstin", "idx": 0, "is_system_generated": 0, - "modified": "2018-01-29 11:57:06.936887", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:27.552850", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-billing_address_gstin-width", "owner": "aditya@rigpl.com", @@ -4731,8 +4701,8 @@ "field_name": "c_form_applicable", "idx": 0, "is_system_generated": 0, - "modified": "2016-03-31 10:52:00.769438", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:27.573582", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-c_form_applicable-width", "owner": "aditya@rigpl.com", @@ -4761,8 +4731,8 @@ "field_name": "c_form_no", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.599298", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:27.598284", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-c_form_no-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -4791,8 +4761,8 @@ "field_name": "campaign", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.518122", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:27.626431", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-campaign-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -4821,8 +4791,8 @@ "field_name": "cash_bank_account", "idx": 0, "is_system_generated": 0, - "modified": "2018-01-03 15:16:02.823764", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:27.657950", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-cash_bank_account-hidden", "owner": "aditya@rigpl.com", @@ -4851,8 +4821,8 @@ "field_name": "cash_bank_account", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.361102", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:27.690957", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-cash_bank_account-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -4881,8 +4851,8 @@ "field_name": "cash_bank_account", "idx": 0, "is_system_generated": 0, - "modified": "2015-05-31 17:53:58.193418", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:27.729652", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-cash_bank_account-permlevel", "owner": "aditya@rigpl.com", @@ -4911,8 +4881,8 @@ "field_name": "cash_bank_account", "idx": 0, "is_system_generated": 0, - "modified": "2018-01-03 15:17:19.684768", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:27.766751", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-cash_bank_account-read_only", "owner": "aditya@rigpl.com", @@ -4927,6 +4897,66 @@ "select_property": null, "value": "1" }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2012-04-03 16:47:02", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "charge", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-10-13 12:51:28.392083", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-charge-in_filter", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_filter", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2012-04-03 16:47:02", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "charge", + "idx": 0, + "is_system_generated": 0, + "modified": "2025-10-13 12:51:28.426578", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-charge-reqd", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "reqd", + "property_type": "Check", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "1" + }, { "_assign": null, "_comments": null, @@ -4941,7 +4971,7 @@ "field_name": "company_address", "idx": 0, "is_system_generated": 1, - "modified": "2018-11-13 10:41:47.560750", + "modified": "2025-10-13 12:51:27.803033", "modified_by": "Administrator", "module": null, "name": "Sales Invoice-company_address-ignore_user_permissions", @@ -4971,8 +5001,8 @@ "field_name": "company", "idx": 0, "is_system_generated": 0, - "modified": "2016-10-28 18:50:31.541269", - "modified_by": "sham.patil@rigpl.com", + "modified": "2025-10-13 12:51:27.844165", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-company-width", "owner": "sham.patil@rigpl.com", @@ -5001,8 +5031,8 @@ "field_name": "contact_mobile", "idx": 0, "is_system_generated": 0, - "modified": "2016-08-04 14:32:36.334805", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:27.869421", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-contact_mobile-precision", "owner": "aditya@rigpl.com", @@ -5031,8 +5061,8 @@ "field_name": "contact_person", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.180826", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:27.898666", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-contact_person-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -5061,8 +5091,8 @@ "field_name": "currency_and_price_list", "idx": 0, "is_system_generated": 0, - "modified": "2018-05-13 22:15:21.337313", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:27.926090", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-currency_and_price_list-collapsible_depends_on", "owner": "aditya@rigpl.com", @@ -5091,8 +5121,8 @@ "field_name": "currency", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.221163", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:27.953087", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-currency-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -5121,8 +5151,8 @@ "field_name": "customer_address", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.170576", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:27.984511", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-customer_address-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -5151,8 +5181,8 @@ "field_name": "customer_address", "idx": 0, "is_system_generated": 0, - "modified": "2014-11-07 10:37:27.258898", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.018199", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-customer_address-label", "owner": "aditya@rigpl.com", @@ -5181,8 +5211,8 @@ "field_name": "customer_address", "idx": 0, "is_system_generated": 0, - "modified": "2017-03-31 15:33:26.006015", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.047879", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-customer_address-reqd", "owner": "aditya@rigpl.com", @@ -5211,8 +5241,8 @@ "field_name": "customer_group", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.505126", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.081934", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-customer_group-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -5241,8 +5271,8 @@ "field_name": "customer_po_details", "idx": 0, "is_system_generated": 0, - "modified": "2018-02-16 15:51:22.165282", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.117898", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-customer_po_details-collapsible", "owner": "aditya@rigpl.com", @@ -5271,8 +5301,8 @@ "field_name": "customer_po_details", "idx": 0, "is_system_generated": 0, - "modified": "2018-02-16 15:51:22.170815", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.153349", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-customer_po_details-collapsible_depends_on", "owner": "aditya@rigpl.com", @@ -5301,8 +5331,8 @@ "field_name": "customer", "idx": 0, "is_system_generated": 0, - "modified": "2018-10-30 11:29:00.482106", - "modified_by": "abhinav@rigpl.com", + "modified": "2025-10-13 12:51:28.175293", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-customer-width", "owner": "abhinav@rigpl.com", @@ -5331,8 +5361,8 @@ "field_name": "debit_to", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.562953", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.194246", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-debit_to-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -5347,36 +5377,6 @@ "select_property": null, "value": "1" }, - { - "_assign": null, - "_comments": null, - "_liked_by": null, - "_user_tags": null, - "creation": "2017-07-01 10:57:08.128685", - "default_value": null, - "doc_name": null, - "doc_type": "Sales Invoice", - "docstatus": 0, - "doctype_or_field": "DocType", - "field_name": null, - "idx": 0, - "is_system_generated": 0, - "modified": "2017-07-01 10:57:08.128685", - "modified_by": "aditya@rigpl.com", - "module": null, - "name": "Sales Invoice-default_print_format", - "owner": "aditya@rigpl.com", - "parent": null, - "parentfield": null, - "parenttype": null, - "property": "default_print_format", - "property_type": "Data", - "row_name": null, - "select_doctype": null, - "select_item": null, - "select_property": null, - "value": "Domestic Invoice" - }, { "_assign": null, "_comments": null, @@ -5391,7 +5391,7 @@ "field_name": "disable_rounded_total", "idx": 0, "is_system_generated": 1, - "modified": "2025-08-22 16:43:09.967648", + "modified": "2025-10-13 12:51:28.233514", "modified_by": "Administrator", "module": null, "name": "Sales Invoice-disable_rounded_total-default", @@ -5421,8 +5421,8 @@ "field_name": "discount_amount", "idx": 0, "is_system_generated": 0, - "modified": "2015-03-31 15:17:08.839283", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.251285", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-discount_amount-hidden", "owner": "aditya@rigpl.com", @@ -5451,8 +5451,8 @@ "field_name": "discount_amount", "idx": 0, "is_system_generated": 0, - "modified": "2015-03-31 15:17:08.834103", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.268524", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-discount_amount-permlevel", "owner": "aditya@rigpl.com", @@ -5481,8 +5481,8 @@ "field_name": "due_date", "idx": 0, "is_system_generated": 0, - "modified": "2025-07-18 14:37:34.371374", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.288086", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-due_date-print_hide", "owner": "aditya@rigpl.com", @@ -5502,79 +5502,79 @@ "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2012-03-05 13:32:29", + "creation": "2017-07-20 12:28:36.815328", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "posting_date", + "field_name": "grand_total", "idx": 0, "is_system_generated": 0, - "modified": "2012-03-05 13:32:29", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.553682", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-FL02756-hidden", + "name": "Sales Invoice-grand_total-in_standard_filter", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "hidden", + "property": "in_standard_filter", "property_type": "Check", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "0" + "value": "1" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2012-03-05 13:33:23", + "creation": "2018-03-04 00:32:42.584369", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "posting_date", + "field_name": "grand_total", "idx": 0, "is_system_generated": 0, - "modified": "2012-03-05 13:33:23", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.589675", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-FL02756-label", + "name": "Sales Invoice-grand_total-width", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "label", - "property_type": "Data", + "property": "width", + "property_type": null, "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "Posting Date/ Invoice Date" + "value": "114" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2012-03-05 13:33:23", - "default_value": "0", + "creation": "2015-06-03 15:01:05.592705", + "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "posting_date", + "field_name": "ignore_pricing_rule", "idx": 0, "is_system_generated": 0, - "modified": "2012-03-05 13:33:23", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.624027", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-FL02756-permlevel", + "name": "Sales Invoice-ignore_pricing_rule-permlevel", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, @@ -5585,67 +5585,67 @@ "select_doctype": null, "select_item": null, "select_property": null, - "value": "1" + "value": "0" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2012-04-03 16:47:02", + "creation": "2025-08-22 16:43:12.991007", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "charge", + "field_name": "in_words", "idx": 0, - "is_system_generated": 0, - "modified": "2012-04-03 16:47:02", - "modified_by": "aditya@rigpl.com", + "is_system_generated": 1, + "modified": "2025-10-13 12:51:28.657896", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-FL02771-in_filter", - "owner": "aditya@rigpl.com", + "name": "Sales Invoice-in_words-hidden", + "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, - "property": "in_filter", + "property": "hidden", "property_type": "Check", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "1" + "value": "0" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2012-04-03 16:47:02", + "creation": "2025-08-22 16:43:13.087792", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "charge", + "field_name": "in_words", "idx": 0, - "is_system_generated": 0, - "modified": "2012-04-03 16:47:02", - "modified_by": "aditya@rigpl.com", + "is_system_generated": 1, + "modified": "2025-10-13 12:51:28.689170", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-FL02771-reqd", - "owner": "aditya@rigpl.com", + "name": "Sales Invoice-in_words-print_hide", + "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, - "property": "reqd", + "property": "print_hide", "property_type": "Check", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "1" + "value": "0" }, { "_assign": null, @@ -5661,10 +5661,10 @@ "field_name": "is_pos", "idx": 0, "is_system_generated": 0, - "modified": "2012-02-29 19:58:29", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.456440", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-FL04365-hidden", + "name": "Sales Invoice-is_pos-hidden", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, @@ -5682,354 +5682,414 @@ "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2012-03-05 13:32:29", + "creation": "2015-11-27 15:13:41.092020", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "posting_time", + "field_name": "is_pos", "idx": 0, "is_system_generated": 0, - "modified": "2012-03-05 13:32:29", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.709227", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-FL04368-hidden", + "name": "Sales Invoice-is_pos-width", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "hidden", - "property_type": "Check", + "property": "width", + "property_type": null, "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "0" + "value": "47" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2012-03-05 13:33:23", + "creation": "2017-09-01 11:32:01.468971", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "posting_time", + "field_name": "letter_head", "idx": 0, "is_system_generated": 0, - "modified": "2012-03-05 13:33:23", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.750692", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-FL04368-label", + "name": "Sales Invoice-letter_head-ignore_user_permissions", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "label", - "property_type": "Data", + "property": "ignore_user_permissions", + "property_type": "Check", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "Posting Time/ Invoice Time" + "value": "1" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2017-07-20 12:28:36.815328", + "creation": "2018-09-24 16:44:43.828307", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "grand_total", + "field_name": "lr_no", "idx": 0, "is_system_generated": 0, - "modified": "2017-07-20 12:28:36.815328", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.825949", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-grand_total-in_standard_filter", + "name": "Sales Invoice-lr_no-width", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "in_standard_filter", - "property_type": "Check", + "property": "width", + "property_type": null, "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "1" + "value": "116" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2018-03-04 00:32:42.584369", + "creation": "2015-12-30 14:57:06.966434", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, - "doctype_or_field": "DocField", - "field_name": "grand_total", + "doctype_or_field": "DocType", + "field_name": null, + "idx": 0, + "is_system_generated": 1, + "modified": "2025-10-13 12:51:27.306824", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-main-_idx", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "_idx", + "property_type": "Text", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "[\"customer_section\", \"naming_series\", \"customer\", \"customer_address\", \"shipping_address_name\", \"ship_to\", \"ship_terms\", \"transporters\", \"lr_no\", \"customer_name\", \"address_display\", \"contact_display\", \"contact_mobile\", \"contact_email\", \"column_break1\", \"is_pos\", \"amended_from\", \"company\", \"posting_date\", \"posting_time\", \"removal_date\", \"removal_time\", \"shipping_contact_no\", \"due_date\", \"mode_of_payment\", \"po_no\", \"po_date\", \"column_break4\", \"payments_section\", \"write_off_outstanding_amount_automatically\", \"paid_amount\", \"cash_bank_account\", \"column_break3\", \"write_off_amount\", \"write_off_account\", \"write_off_cost_center\", \"currency_and_price_list\", \"currency\", \"conversion_rate\", \"ignore_pricing_rule\", \"column_break2\", \"selling_price_list\", \"price_list_currency\", \"plc_conversion_rate\", \"update_stock\", \"items_section\", \"items\", \"packing_list\", \"packed_items\", \"sales_bom_help\", \"section_break_30\", \"base_net_total\", \"base_total\", \"net_total\", \"column_break_32\", \"total\", \"taxes_section\", \"taxes_and_charges\", \"column_break_38\", \"shipping_rule\", \"section_break_40\", \"taxes\", \"other_charges_calculation\", \"section_break_43\", \"base_total_taxes_and_charges\", \"column_break_47\", \"total_taxes_and_charges\", \"section_break_49\", \"apply_discount_on\", \"column_break_51\", \"discount_amount\", \"base_discount_amount\", \"totals\", \"base_grand_total\", \"base_rounded_total\", \"base_in_words\", \"column_break5\", \"grand_total\", \"rounded_total\", \"in_words\", \"total_advance\", \"outstanding_amount\", \"advances_section\", \"get_advances_received\", \"advances\", \"column_break_74\", \"fold\", \"terms_section_break\", \"tc_name\", \"terms\", \"contact_section\", \"territory\", \"customer_group\", \"col_break23\", \"shipping_address\", \"contact_person\", \"shipping_tin_no\", \"shipping_excise_no\", \"more_info\", \"debit_to\", \"project_name\", \"campaign\", \"source\", \"is_opening\", \"c_form_applicable\", \"c_form_no\", \"column_break8\", \"letter_head\", \"tin_no\", \"excise_no\", \"select_print_heading\", \"fiscal_year\", \"remarks\", \"sales_team_section_break\", \"column_break9\", \"sales_partner\", \"column_break10\", \"commission_rate\", \"total_commission\", \"section_break2\", \"sales_team\", \"recurring_invoice\", \"column_break11\", \"is_recurring\", \"recurring_type\", \"from_date\", \"to_date\", \"repeat_on_day_of_month\", \"end_date\", \"column_break12\", \"next_date\", \"recurring_id\", \"notification_email_address\", \"against_income_account\"]" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-07-01 10:57:08.128685", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": null, "idx": 0, "is_system_generated": 0, - "modified": "2018-03-04 00:32:42.584369", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.213534", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-grand_total-width", + "name": "Sales Invoice-main-default_print_format", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "width", - "property_type": null, + "property": "default_print_format", + "property_type": "Data", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "114" + "value": "Domestic Invoice" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2015-06-03 15:01:05.592705", + "creation": "2025-10-13 13:26:13.052421", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, - "doctype_or_field": "DocField", - "field_name": "ignore_pricing_rule", + "doctype_or_field": "DocType", + "field_name": null, "idx": 0, "is_system_generated": 0, - "modified": "2015-06-03 15:01:05.592705", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 13:26:13.052421", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-ignore_pricing_rule-permlevel", + "name": "Sales Invoice-main-field_order", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "field_order", + "property_type": "Data", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "[\"qrcode_image\", \"signed_einvoice\", \"signed_qr_code\", \"customer_section\", \"naming_series\", \"customer\", \"irn_cancelled\", \"irn\", \"ack_no\", \"ack_date\", \"eway_bill_cancelled\", \"customer_name\", \"tax_id\", \"ewaybill\", \"e_waybill_status\", \"company\", \"company_tax_id\", \"column_break1\", \"posting_date\", \"posting_time\", \"set_posting_time\", \"marked_to_submit\", \"background_processing\", \"removal_date\", \"removal_time\", \"due_date\", \"column_break_14\", \"is_pos\", \"pos_profile\", \"is_consolidated\", \"is_return\", \"return_against\", \"update_outstanding_for_self\", \"update_billed_amount_in_sales_order\", \"update_billed_amount_in_delivery_note\", \"is_debit_note\", \"is_reverse_charge\", \"is_export_with_gst\", \"amended_from\", \"is_created_using_pos\", \"pos_closing_entry\", \"customer_po_details\", \"po_no\", \"column_break_23\", \"po_date\", \"accounting_dimensions_section\", \"cost_center\", \"dimension_col_break\", \"project\", \"currency_and_price_list\", \"currency\", \"conversion_rate\", \"column_break2\", \"selling_price_list\", \"price_list_currency\", \"plc_conversion_rate\", \"ignore_pricing_rule\", \"items_section\", \"scan_barcode\", \"last_scanned_warehouse\", \"update_stock\", \"column_break_39\", \"set_warehouse\", \"set_target_warehouse\", \"section_break_42\", \"items\", \"items_synopsis\", \"section_break_30\", \"total_qty\", \"total_net_weight\", \"column_break_32\", \"base_total\", \"base_net_total\", \"column_break_52\", \"total\", \"net_total\", \"taxes_section\", \"tax_category\", \"taxes_and_charges\", \"column_break_38\", \"shipping_rule\", \"column_break_55\", \"incoterm\", \"named_place\", \"section_break_40\", \"taxes\", \"section_break_43\", \"base_total_taxes_and_charges\", \"column_break_47\", \"total_taxes_and_charges\", \"totals\", \"base_grand_total\", \"base_rounding_adjustment\", \"base_rounded_total\", \"base_in_words\", \"column_break5\", \"grand_total\", \"rounding_adjustment\", \"use_company_roundoff_cost_center\", \"rounded_total\", \"in_words\", \"total_advance\", \"outstanding_amount\", \"disable_rounded_total\", \"section_break_49\", \"apply_discount_on\", \"base_discount_amount\", \"coupon_code\", \"is_cash_or_non_trade_discount\", \"additional_discount_account\", \"column_break_51\", \"additional_discount_percentage\", \"discount_amount\", \"sec_tax_breakup\", \"other_charges_calculation\", \"section_gst_breakup\", \"gst_breakup_table\", \"pricing_rule_details\", \"pricing_rules\", \"packing_list\", \"packed_items\", \"product_bundle_help\", \"time_sheet_list\", \"timesheets\", \"section_break_104\", \"total_billing_hours\", \"column_break_106\", \"total_billing_amount\", \"payments_tab\", \"payments_section\", \"cash_bank_account\", \"payments\", \"section_break_84\", \"base_paid_amount\", \"column_break_86\", \"paid_amount\", \"section_break_88\", \"base_change_amount\", \"column_break_90\", \"change_amount\", \"account_for_change_amount\", \"advances_section\", \"allocate_advances_automatically\", \"only_include_allocated_payments\", \"get_advances\", \"advances\", \"write_off_section\", \"write_off_amount\", \"base_write_off_amount\", \"write_off_outstanding_amount_automatically\", \"column_break_74\", \"write_off_account\", \"write_off_cost_center\", \"loyalty_points_redemption\", \"redeem_loyalty_points\", \"loyalty_points\", \"loyalty_amount\", \"column_break_77\", \"loyalty_program\", \"dont_create_loyalty_points\", \"loyalty_redemption_account\", \"loyalty_redemption_cost_center\", \"contact_and_address_tab\", \"address_and_contact\", \"customer_address\", \"billing_address_gstin\", \"tin_no\", \"excise_no\", \"address_display\", \"col_break4\", \"contact_person\", \"contact_display\", \"contact_mobile\", \"contact_email\", \"territory\", \"shipping_address_section\", \"shipping_address_name\", \"customer_gstin\", \"place_of_supply\", \"shipping_tin_no\", \"shipping_excise_no\", \"shipping_address_gstin\", \"ship_to\", \"shipping_address\", \"port_address\", \"shipping_addr_col_break\", \"dispatch_address_name\", \"dispatch_address\", \"company_address_section\", \"company_address\", \"company_gstin\", \"company_address_display\", \"company_addr_col_break\", \"company_contact_person\", \"terms_tab\", \"payment_schedule_section\", \"ignore_default_payment_terms_template\", \"payment_terms_template\", \"payment_schedule\", \"terms_section_break\", \"tc_name\", \"terms\", \"more_info_tab\", \"transporter_info\", \"transporter\", \"gst_transporter_id\", \"driver\", \"more_info\", \"debit_to\", \"party_account_currency\", \"is_opening\", \"column_break8\", \"unrealized_profit_loss_account\", \"against_income_account\", \"sales_team_section_break\", \"sales_partner\", \"amount_eligible_for_commission\", \"column_break10\", \"commission_rate\", \"total_commission\", \"section_break2\", \"sales_team\", \"edit_printing_settings\", \"letter_head\", \"group_same_items\", \"column_break_84\", \"select_print_heading\", \"language\", \"gst_section\", \"gst_category\", \"export_type\", \"invoice_copy\", \"reverse_charge\", \"ecommerce_gstin\", \"gst_col_break\", \"reason_for_issuing_document\", \"port_code\", \"shipping_bill_number\", \"shipping_bill_date\", \"ecommerce_supply_type\", \"subscription_section\", \"subscription\", \"from_date\", \"auto_repeat\", \"column_break_140\", \"to_date\", \"update_auto_repeat_reference\", \"more_information\", \"status\", \"einvoice_status\", \"inter_company_invoice_reference\", \"represents_company\", \"customer_group\", \"column_break_imbx\", \"utm_source\", \"utm_campaign\", \"utm_medium\", \"utm_content\", \"col_break23\", \"is_internal_customer\", \"is_discounted\", \"remarks\", \"connections_tab\", \"gst_vehicle_type\", \"lr_date\", \"driver_name\", \"mode_of_transport\", \"export_invoice_no\", \"transporter_name\", \"transporter_address_display\", \"transporter_address\", \"transporter_col_break\", \"distance\", \"vehicle_no\", \"lr_no\", \"transporters\", \"ship_terms\"]" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2014-10-16 13:36:08.707283", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Invoice", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": null, + "idx": 0, + "is_system_generated": 0, + "modified": "2025-10-13 12:51:30.044796", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-main-sort_field", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "permlevel", - "property_type": "Int", + "property": "sort_field", + "property_type": "Data", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "0" + "value": "creation" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2025-08-22 16:43:12.991007", + "creation": "2022-02-07 05:50:03.743794", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, - "doctype_or_field": "DocField", - "field_name": "in_words", + "doctype_or_field": "DocType", + "field_name": null, "idx": 0, - "is_system_generated": 1, - "modified": "2025-08-22 16:43:12.991007", + "is_system_generated": 0, + "modified": "2025-10-13 12:51:30.334590", "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-in_words-hidden", - "owner": "Administrator", + "name": "Sales Invoice-main-title_field", + "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "hidden", - "property_type": "Check", + "property": "title_field", + "property_type": "Data", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "0" + "value": "customer_name" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2025-08-22 16:43:13.087792", + "creation": "2025-08-29 14:43:18.087475", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, - "doctype_or_field": "DocField", - "field_name": "in_words", + "doctype_or_field": "DocType", + "field_name": null, "idx": 0, "is_system_generated": 1, - "modified": "2025-08-22 16:43:13.087792", + "modified": "2025-10-13 12:51:28.918149", "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-in_words-print_hide", + "name": "Sales Invoice-main-track_changes", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, - "property": "print_hide", + "property": "track_changes", "property_type": "Check", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "0" + "value": "1" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2015-11-27 15:13:41.092020", + "creation": "2014-06-24 12:12:21.844572", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "is_pos", + "field_name": "naming_series", "idx": 0, - "is_system_generated": 0, - "modified": "2015-11-27 15:13:41.092020", - "modified_by": "aditya@rigpl.com", + "is_system_generated": 1, + "modified": "2025-10-13 12:51:28.946657", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-is_pos-width", - "owner": "aditya@rigpl.com", + "name": "Sales Invoice-naming_series-default", + "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, - "property": "width", - "property_type": null, + "property": "default", + "property_type": "Text", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "47" + "value": "" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2017-09-01 11:32:01.468971", + "creation": "2022-02-05 17:46:39.029377", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "letter_head", + "field_name": "naming_series", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.468971", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.975179", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-letter_head-ignore_user_permissions", + "name": "Sales Invoice-naming_series-options", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "ignore_user_permissions", - "property_type": "Check", + "property": "options", + "property_type": "Text", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "1" + "value": "\nR26\nRJ26\nRE26\nRCN26" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2018-09-24 16:44:43.828307", + "creation": "2017-04-14 11:00:42.527735", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "lr_no", + "field_name": "naming_series", "idx": 0, "is_system_generated": 0, - "modified": "2018-09-24 16:44:43.828307", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.003895", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-lr_no-width", + "name": "Sales Invoice-naming_series-reqd", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "width", - "property_type": null, + "property": "reqd", + "property_type": "Check", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "116" + "value": "0" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2025-09-30 12:40:07.972629", + "creation": "2015-11-27 15:13:43.420499", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, - "doctype_or_field": "DocType", - "field_name": null, + "doctype_or_field": "DocField", + "field_name": "naming_series", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 12:40:07.972629", + "modified": "2025-10-13 12:51:29.033064", "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-main-field_order", - "owner": "Administrator", + "name": "Sales Invoice-naming_series-width", + "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "field_order", - "property_type": "Data", + "property": "width", + "property_type": null, "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "[\"qrcode_image\", \"signed_einvoice\", \"signed_qr_code\", \"customer_section\", \"naming_series\", \"customer\", \"irn_cancelled\", \"irn\", \"ack_no\", \"ack_date\", \"eway_bill_cancelled\", \"customer_name\", \"tax_id\", \"ewaybill\", \"e_waybill_status\", \"company\", \"company_tax_id\", \"column_break1\", \"posting_date\", \"posting_time\", \"set_posting_time\", \"marked_to_submit\", \"background_processing\", \"removal_date\", \"removal_time\", \"due_date\", \"column_break_14\", \"is_pos\", \"pos_profile\", \"is_consolidated\", \"is_return\", \"return_against\", \"update_outstanding_for_self\", \"update_billed_amount_in_sales_order\", \"update_billed_amount_in_delivery_note\", \"is_debit_note\", \"is_reverse_charge\", \"is_export_with_gst\", \"amended_from\", \"is_created_using_pos\", \"pos_closing_entry\", \"accounting_dimensions_section\", \"cost_center\", \"dimension_col_break\", \"project\", \"currency_and_price_list\", \"currency\", \"conversion_rate\", \"column_break2\", \"selling_price_list\", \"price_list_currency\", \"plc_conversion_rate\", \"ignore_pricing_rule\", \"items_section\", \"scan_barcode\", \"last_scanned_warehouse\", \"update_stock\", \"column_break_39\", \"set_warehouse\", \"set_target_warehouse\", \"section_break_42\", \"items\", \"items_synopsis\", \"section_break_30\", \"total_qty\", \"total_net_weight\", \"column_break_32\", \"base_total\", \"base_net_total\", \"column_break_52\", \"total\", \"net_total\", \"taxes_section\", \"tax_category\", \"taxes_and_charges\", \"column_break_38\", \"shipping_rule\", \"column_break_55\", \"incoterm\", \"named_place\", \"section_break_40\", \"taxes\", \"section_break_43\", \"base_total_taxes_and_charges\", \"column_break_47\", \"total_taxes_and_charges\", \"totals\", \"base_grand_total\", \"base_rounding_adjustment\", \"base_rounded_total\", \"base_in_words\", \"column_break5\", \"grand_total\", \"rounding_adjustment\", \"use_company_roundoff_cost_center\", \"rounded_total\", \"in_words\", \"total_advance\", \"outstanding_amount\", \"disable_rounded_total\", \"section_break_49\", \"apply_discount_on\", \"base_discount_amount\", \"coupon_code\", \"is_cash_or_non_trade_discount\", \"additional_discount_account\", \"column_break_51\", \"additional_discount_percentage\", \"discount_amount\", \"sec_tax_breakup\", \"other_charges_calculation\", \"section_gst_breakup\", \"gst_breakup_table\", \"pricing_rule_details\", \"pricing_rules\", \"packing_list\", \"packed_items\", \"product_bundle_help\", \"time_sheet_list\", \"timesheets\", \"section_break_104\", \"total_billing_hours\", \"column_break_106\", \"total_billing_amount\", \"payments_tab\", \"payments_section\", \"cash_bank_account\", \"payments\", \"section_break_84\", \"base_paid_amount\", \"column_break_86\", \"paid_amount\", \"section_break_88\", \"base_change_amount\", \"column_break_90\", \"change_amount\", \"account_for_change_amount\", \"advances_section\", \"allocate_advances_automatically\", \"only_include_allocated_payments\", \"get_advances\", \"advances\", \"write_off_section\", \"write_off_amount\", \"base_write_off_amount\", \"write_off_outstanding_amount_automatically\", \"column_break_74\", \"write_off_account\", \"write_off_cost_center\", \"loyalty_points_redemption\", \"redeem_loyalty_points\", \"loyalty_points\", \"loyalty_amount\", \"column_break_77\", \"loyalty_program\", \"dont_create_loyalty_points\", \"loyalty_redemption_account\", \"loyalty_redemption_cost_center\", \"contact_and_address_tab\", \"address_and_contact\", \"customer_address\", \"billing_address_gstin\", \"tin_no\", \"excise_no\", \"address_display\", \"col_break4\", \"contact_person\", \"contact_display\", \"contact_mobile\", \"contact_email\", \"territory\", \"shipping_address_section\", \"shipping_address_name\", \"customer_gstin\", \"place_of_supply\", \"shipping_tin_no\", \"shipping_excise_no\", \"shipping_address_gstin\", \"ship_to\", \"shipping_address\", \"port_address\", \"shipping_addr_col_break\", \"dispatch_address_name\", \"dispatch_address\", \"company_address_section\", \"company_address\", \"company_gstin\", \"company_address_display\", \"company_addr_col_break\", \"company_contact_person\", \"terms_tab\", \"payment_schedule_section\", \"ignore_default_payment_terms_template\", \"payment_terms_template\", \"payment_schedule\", \"terms_section_break\", \"tc_name\", \"terms\", \"more_info_tab\", \"transporter_info\", \"transporter\", \"gst_transporter_id\", \"driver\", \"customer_po_details\", \"po_no\", \"column_break_23\", \"po_date\", \"more_info\", \"debit_to\", \"party_account_currency\", \"is_opening\", \"column_break8\", \"unrealized_profit_loss_account\", \"against_income_account\", \"sales_team_section_break\", \"sales_partner\", \"amount_eligible_for_commission\", \"column_break10\", \"commission_rate\", \"total_commission\", \"section_break2\", \"sales_team\", \"edit_printing_settings\", \"letter_head\", \"group_same_items\", \"column_break_84\", \"select_print_heading\", \"language\", \"gst_section\", \"gst_category\", \"export_type\", \"invoice_copy\", \"reverse_charge\", \"ecommerce_gstin\", \"gst_col_break\", \"reason_for_issuing_document\", \"port_code\", \"shipping_bill_number\", \"shipping_bill_date\", \"ecommerce_supply_type\", \"subscription_section\", \"subscription\", \"from_date\", \"auto_repeat\", \"column_break_140\", \"to_date\", \"update_auto_repeat_reference\", \"more_information\", \"status\", \"einvoice_status\", \"inter_company_invoice_reference\", \"represents_company\", \"customer_group\", \"column_break_imbx\", \"utm_source\", \"utm_campaign\", \"utm_medium\", \"utm_content\", \"col_break23\", \"is_internal_customer\", \"is_discounted\", \"remarks\", \"connections_tab\", \"gst_vehicle_type\", \"lr_date\", \"driver_name\", \"mode_of_transport\", \"export_invoice_no\", \"transporter_name\", \"transporter_address_display\", \"transporter_address\", \"transporter_col_break\", \"distance\", \"vehicle_no\", \"lr_no\", \"transporters\", \"ship_terms\"]" + "value": "65" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2025-08-29 14:43:18.087475", + "creation": "2017-07-20 12:28:36.787556", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, - "doctype_or_field": "DocType", - "field_name": null, + "doctype_or_field": "DocField", + "field_name": "net_total", "idx": 0, - "is_system_generated": 1, - "modified": "2025-08-29 14:43:18.087475", + "is_system_generated": 0, + "modified": "2025-10-13 12:51:29.061649", "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-main-track_changes", - "owner": "Administrator", + "name": "Sales Invoice-net_total-in_standard_filter", + "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "track_changes", + "property": "in_standard_filter", "property_type": "Check", "row_name": null, "select_doctype": null, @@ -6042,144 +6102,144 @@ "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2014-06-24 12:12:21.844572", + "creation": "2017-04-01 13:57:56.027512", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "naming_series", + "field_name": "net_total", "idx": 0, - "is_system_generated": 1, - "modified": "2025-04-01 07:07:10.211944", - "modified_by": "aditya@rigpl.com", + "is_system_generated": 0, + "modified": "2025-10-13 12:51:29.089645", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-naming_series-default", - "owner": "Administrator", + "name": "Sales Invoice-net_total-width", + "owner": "ravi.singh@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "default", - "property_type": "Text", + "property": "width", + "property_type": null, "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "" + "value": "79" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2022-02-05 17:46:39.029377", + "creation": "2018-03-04 00:32:38.316021", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "naming_series", + "field_name": "outstanding_amount", "idx": 0, "is_system_generated": 0, - "modified": "2025-04-01 07:07:10.160389", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.118138", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-naming_series-options", + "name": "Sales Invoice-outstanding_amount-width", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "options", - "property_type": "Text", + "property": "width", + "property_type": null, "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "\nR26\nRJ26\nRE26\nRCN26" + "value": "85" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2017-04-14 11:00:42.527735", + "creation": "2017-09-01 11:32:01.580443", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "naming_series", + "field_name": "party_account_currency", "idx": 0, "is_system_generated": 0, - "modified": "2017-04-14 11:00:42.527735", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.141668", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-naming_series-reqd", + "name": "Sales Invoice-party_account_currency-ignore_user_permissions", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "reqd", + "property": "ignore_user_permissions", "property_type": "Check", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "0" + "value": "1" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2015-11-27 15:13:43.420499", + "creation": "2025-07-18 14:37:34.639818", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "naming_series", + "field_name": "payment_schedule", "idx": 0, "is_system_generated": 0, - "modified": "2015-11-27 15:13:43.420499", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.163819", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-naming_series-width", + "name": "Sales Invoice-payment_schedule-print_hide", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "width", - "property_type": null, + "property": "print_hide", + "property_type": "Check", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "65" + "value": "1" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2017-07-20 12:28:36.787556", + "creation": "2025-09-30 12:40:08.271931", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "net_total", + "field_name": "po_date", "idx": 0, "is_system_generated": 0, - "modified": "2017-07-20 12:28:36.787556", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.192488", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-net_total-in_standard_filter", - "owner": "aditya@rigpl.com", + "name": "Sales Invoice-po_date-reqd", + "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, - "property": "in_standard_filter", + "property": "reqd", "property_type": "Check", "row_name": null, "select_doctype": null, @@ -6192,114 +6252,114 @@ "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2017-04-01 13:57:56.027512", + "creation": "2018-03-03 22:14:23.682308", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "net_total", + "field_name": "po_no", "idx": 0, "is_system_generated": 0, - "modified": "2017-04-01 13:57:56.027512", - "modified_by": "ravi.singh@rigpl.com", + "modified": "2025-10-13 12:51:29.221734", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-net_total-width", - "owner": "ravi.singh@rigpl.com", + "name": "Sales Invoice-po_no-in_standard_filter", + "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "width", - "property_type": null, + "property": "in_standard_filter", + "property_type": "Check", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "79" + "value": "1" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2018-03-04 00:32:38.316021", + "creation": "2015-10-20 12:09:08.432903", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "outstanding_amount", + "field_name": "po_no", "idx": 0, - "is_system_generated": 0, - "modified": "2018-03-04 00:32:38.316021", - "modified_by": "aditya@rigpl.com", - "module": null, - "name": "Sales Invoice-outstanding_amount-width", - "owner": "aditya@rigpl.com", + "is_system_generated": 1, + "modified": "2025-10-13 12:51:29.256005", + "modified_by": "Administrator", + "module": null, + "name": "Sales Invoice-po_no-length", + "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, - "property": "width", - "property_type": null, + "property": "length", + "property_type": "Int", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "85" + "value": "188" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2017-09-01 11:32:01.580443", + "creation": "2014-09-16 11:23:37.495191", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "party_account_currency", + "field_name": "po_no", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.580443", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.283048", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-party_account_currency-ignore_user_permissions", + "name": "Sales Invoice-po_no-width", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "ignore_user_permissions", - "property_type": "Check", + "property": "width", + "property_type": null, "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "1" + "value": "258" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2025-07-18 14:37:34.639818", + "creation": "2017-09-01 11:32:01.143356", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "payment_schedule", + "field_name": "pos_profile", "idx": 0, "is_system_generated": 0, - "modified": "2025-07-18 14:37:34.639818", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.310630", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-payment_schedule-print_hide", + "name": "Sales Invoice-pos_profile-ignore_user_permissions", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "print_hide", + "property": "ignore_user_permissions", "property_type": "Check", "row_name": null, "select_doctype": null, @@ -6312,49 +6372,49 @@ "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2025-09-30 12:40:08.271931", + "creation": "2012-03-05 13:32:29", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "po_date", + "field_name": "posting_date", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 12:40:08.271931", + "modified": "2025-10-13 12:51:28.308375", "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-po_date-reqd", - "owner": "Administrator", + "name": "Sales Invoice-posting_date-hidden", + "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "reqd", + "property": "hidden", "property_type": "Check", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "1" + "value": "0" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2018-03-03 22:14:23.682308", + "creation": "2017-07-20 12:28:36.741168", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "po_no", + "field_name": "posting_date", "idx": 0, "is_system_generated": 0, - "modified": "2018-03-03 22:14:23.682308", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.341799", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-po_no-in_standard_filter", + "name": "Sales Invoice-posting_date-in_standard_filter", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, @@ -6372,150 +6432,150 @@ "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2015-10-20 12:09:08.432903", + "creation": "2012-03-05 13:33:23", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "po_no", + "field_name": "posting_date", "idx": 0, - "is_system_generated": 1, - "modified": "2015-10-20 12:09:08.432903", + "is_system_generated": 0, + "modified": "2025-10-13 12:51:28.327848", "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-po_no-length", - "owner": "Administrator", + "name": "Sales Invoice-posting_date-label", + "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "length", - "property_type": "Int", + "property": "label", + "property_type": "Data", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "188" + "value": "Posting Date/ Invoice Date" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2014-09-16 11:23:37.495191", - "default_value": null, + "creation": "2012-03-05 13:33:23", + "default_value": "0", "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "po_no", + "field_name": "posting_date", "idx": 0, "is_system_generated": 0, - "modified": "2014-09-16 11:23:37.495191", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.358409", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-po_no-width", + "name": "Sales Invoice-posting_date-permlevel", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "width", - "property_type": null, + "property": "permlevel", + "property_type": "Int", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "258" + "value": "1" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2017-09-01 11:32:01.143356", + "creation": "2018-09-24 16:45:23.095951", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "pos_profile", + "field_name": "posting_date", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.143356", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.372154", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-pos_profile-ignore_user_permissions", + "name": "Sales Invoice-posting_date-width", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "ignore_user_permissions", - "property_type": "Check", + "property": "width", + "property_type": null, "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "1" + "value": "98" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2017-07-20 12:28:36.741168", + "creation": "2012-03-05 13:32:29", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "posting_date", + "field_name": "posting_time", "idx": 0, "is_system_generated": 0, - "modified": "2017-07-20 12:28:36.741168", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.483748", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-posting_date-in_standard_filter", + "name": "Sales Invoice-posting_time-hidden", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "in_standard_filter", + "property": "hidden", "property_type": "Check", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "1" + "value": "0" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2018-09-24 16:45:23.095951", + "creation": "2012-03-05 13:33:23", "default_value": null, "doc_name": null, "doc_type": "Sales Invoice", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "posting_date", + "field_name": "posting_time", "idx": 0, "is_system_generated": 0, - "modified": "2018-09-24 16:45:23.095951", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:28.518895", + "modified_by": "Administrator", "module": null, - "name": "Sales Invoice-posting_date-width", + "name": "Sales Invoice-posting_time-label", "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, - "property": "width", - "property_type": null, + "property": "label", + "property_type": "Data", "row_name": null, "select_doctype": null, "select_item": null, "select_property": null, - "value": "98" + "value": "Posting Time/ Invoice Time" }, { "_assign": null, @@ -6531,8 +6591,8 @@ "field_name": "posting_time", "idx": 0, "is_system_generated": 0, - "modified": "2013-01-15 18:47:24", - "modified_by": "anuj@rigpl.com", + "modified": "2025-10-13 12:51:29.409082", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-posting_time-reqd", "owner": "anuj@rigpl.com", @@ -6561,8 +6621,8 @@ "field_name": "price_list_currency", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.248830", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.444746", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-price_list_currency-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -6591,8 +6651,8 @@ "field_name": "project", "idx": 0, "is_system_generated": 0, - "modified": "2017-03-31 15:32:07.056464", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.480454", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-project-hidden", "owner": "aditya@rigpl.com", @@ -6621,8 +6681,8 @@ "field_name": "project", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.123528", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.513969", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-project-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -6651,8 +6711,8 @@ "field_name": "project", "idx": 0, "is_system_generated": 0, - "modified": "2017-03-31 15:32:07.036753", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.543831", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-project-in_global_search", "owner": "aditya@rigpl.com", @@ -6681,8 +6741,8 @@ "field_name": "project", "idx": 0, "is_system_generated": 0, - "modified": "2016-10-28 18:50:21.884374", - "modified_by": "sham.patil@rigpl.com", + "modified": "2025-10-13 12:51:29.562723", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-project-width", "owner": "sham.patil@rigpl.com", @@ -6711,8 +6771,8 @@ "field_name": "recurring_id", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.637403", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.581339", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-recurring_id-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -6741,8 +6801,8 @@ "field_name": "recurring_print_format", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.653861", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.600273", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-recurring_print_format-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -6771,8 +6831,8 @@ "field_name": "remarks", "idx": 0, "is_system_generated": 0, - "modified": "2018-03-04 11:15:16.405786", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.619826", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-remarks-allow_on_submit", "owner": "aditya@rigpl.com", @@ -6801,8 +6861,8 @@ "field_name": "removal_date", "idx": 0, "is_system_generated": 0, - "modified": "2018-05-01 17:10:45.353238", - "modified_by": "ravi.singh@rigpl.com", + "modified": "2025-10-13 12:51:29.638858", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-removal_date-width", "owner": "ravi.singh@rigpl.com", @@ -6831,8 +6891,8 @@ "field_name": "return_against", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.162224", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.657473", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-return_against-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -6861,7 +6921,7 @@ "field_name": "rounded_total", "idx": 0, "is_system_generated": 1, - "modified": "2025-08-22 16:43:09.776050", + "modified": "2025-10-13 12:51:29.674848", "modified_by": "Administrator", "module": null, "name": "Sales Invoice-rounded_total-hidden", @@ -6891,7 +6951,7 @@ "field_name": "rounded_total", "idx": 0, "is_system_generated": 1, - "modified": "2025-08-22 16:43:09.872596", + "modified": "2025-10-13 12:51:29.692382", "modified_by": "Administrator", "module": null, "name": "Sales Invoice-rounded_total-print_hide", @@ -6921,8 +6981,8 @@ "field_name": "sales_order_main", "idx": 0, "is_system_generated": 0, - "modified": "2013-07-04 18:50:09", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.710503", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-sales_order_main-hidden", "owner": "aditya@rigpl.com", @@ -6951,8 +7011,8 @@ "field_name": "sales_order_main", "idx": 0, "is_system_generated": 0, - "modified": "2013-07-04 18:51:20", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.730064", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-sales_order_main-permlevel", "owner": "aditya@rigpl.com", @@ -6981,8 +7041,8 @@ "field_name": "sales_partner", "idx": 0, "is_system_generated": 0, - "modified": "2015-08-26 16:53:30.903516", - "modified_by": "balaji.v@rigpl.com", + "modified": "2025-10-13 12:51:29.748410", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-sales_partner-width", "owner": "balaji.v@rigpl.com", @@ -7011,8 +7071,8 @@ "field_name": "sales_team", "idx": 0, "is_system_generated": 0, - "modified": "2018-03-04 11:10:51.135182", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.767808", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-sales_team-allow_on_submit", "owner": "aditya@rigpl.com", @@ -7041,7 +7101,7 @@ "field_name": "scan_barcode", "idx": 0, "is_system_generated": 1, - "modified": "2025-08-22 16:43:04.212361", + "modified": "2025-10-13 12:51:29.786874", "modified_by": "Administrator", "module": null, "name": "Sales Invoice-scan_barcode-hidden", @@ -7071,8 +7131,8 @@ "field_name": "section_break_49", "idx": 0, "is_system_generated": 0, - "modified": "2020-11-02 15:03:08.894688", - "modified_by": "abhinav@rigpl.com", + "modified": "2025-10-13 12:51:29.805087", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-section_break_49-permlevel", "owner": "abhinav@rigpl.com", @@ -7101,8 +7161,8 @@ "field_name": "select_print_heading", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.491241", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.824636", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-select_print_heading-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -7131,8 +7191,8 @@ "field_name": "selling_price_list", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.236593", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.845462", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-selling_price_list-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -7161,7 +7221,7 @@ "field_name": "ship_to", "idx": 0, "is_system_generated": 0, - "modified": "2025-09-30 13:24:15.822320", + "modified": "2025-10-13 12:51:29.862884", "modified_by": "Administrator", "module": null, "name": "Sales Invoice-ship_to-fetch_from", @@ -7191,7 +7251,7 @@ "field_name": "ship_to", "idx": 0, "is_system_generated": 1, - "modified": "2015-10-20 12:09:07.702723", + "modified": "2025-10-13 12:51:29.881725", "modified_by": "Administrator", "module": null, "name": "Sales Invoice-ship_to-length", @@ -7221,8 +7281,8 @@ "field_name": "shipping_address_gstin", "idx": 0, "is_system_generated": 0, - "modified": "2018-01-29 11:57:21.481748", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.901334", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-shipping_address_gstin-width", "owner": "aditya@rigpl.com", @@ -7251,8 +7311,8 @@ "field_name": "shipping_address_name", "idx": 0, "is_system_generated": 0, - "modified": "2014-10-16 13:50:27.346005", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.921786", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-shipping_address_name-hidden", "owner": "aditya@rigpl.com", @@ -7281,8 +7341,8 @@ "field_name": "shipping_address_name", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.203235", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.944347", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-shipping_address_name-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -7311,8 +7371,8 @@ "field_name": "shipping_address_name", "idx": 0, "is_system_generated": 0, - "modified": "2017-03-31 15:33:26.035055", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:29.964334", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-shipping_address_name-reqd", "owner": "aditya@rigpl.com", @@ -7341,8 +7401,8 @@ "field_name": "shipping_address_name", "idx": 0, "is_system_generated": 0, - "modified": "2015-12-09 12:29:22.565513", - "modified_by": "ravi.singh@rigpl.com", + "modified": "2025-10-13 12:51:29.984088", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-shipping_address_name-width", "owner": "ravi.singh@rigpl.com", @@ -7371,8 +7431,8 @@ "field_name": "shipping_address", "idx": 0, "is_system_generated": 0, - "modified": "2015-11-24 19:13:28.594763", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.003365", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-shipping_address-width", "owner": "aditya@rigpl.com", @@ -7401,8 +7461,8 @@ "field_name": "shipping_rule", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.307612", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.024351", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-shipping_rule-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -7417,36 +7477,6 @@ "select_property": null, "value": "1" }, - { - "_assign": null, - "_comments": null, - "_liked_by": null, - "_user_tags": null, - "creation": "2014-10-16 13:36:08.707283", - "default_value": null, - "doc_name": null, - "doc_type": "Sales Invoice", - "docstatus": 0, - "doctype_or_field": "DocType", - "field_name": null, - "idx": 0, - "is_system_generated": 0, - "modified": "2014-10-16 13:36:08.707283", - "modified_by": "aditya@rigpl.com", - "module": null, - "name": "Sales Invoice-sort_field", - "owner": "aditya@rigpl.com", - "parent": null, - "parentfield": null, - "parenttype": null, - "property": "sort_field", - "property_type": "Data", - "row_name": null, - "select_doctype": null, - "select_item": null, - "select_property": null, - "value": "creation" - }, { "_assign": null, "_comments": null, @@ -7461,8 +7491,8 @@ "field_name": "source", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.537831", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.064269", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-source-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -7491,7 +7521,7 @@ "field_name": "tax_id", "idx": 0, "is_system_generated": 1, - "modified": "2025-09-13 20:05:50.255550", + "modified": "2025-10-13 12:51:30.084405", "modified_by": "Administrator", "module": null, "name": "Sales Invoice-tax_id-hidden", @@ -7521,7 +7551,7 @@ "field_name": "tax_id", "idx": 0, "is_system_generated": 1, - "modified": "2025-09-13 20:05:50.272299", + "modified": "2025-10-13 12:51:30.104117", "modified_by": "Administrator", "module": null, "name": "Sales Invoice-tax_id-print_hide", @@ -7551,8 +7581,8 @@ "field_name": "taxes_and_charges", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.294181", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.123963", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-taxes_and_charges-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -7581,8 +7611,8 @@ "field_name": "taxes_and_charges", "idx": 0, "is_system_generated": 0, - "modified": "2015-01-02 19:16:39.920441", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.143613", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-taxes_and_charges-in_list_view", "owner": "aditya@rigpl.com", @@ -7611,8 +7641,8 @@ "field_name": "taxes_and_charges", "idx": 0, "is_system_generated": 0, - "modified": "2020-10-26 09:01:06.796729", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.163417", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-taxes_and_charges-in_standard_filter", "owner": "aditya@rigpl.com", @@ -7641,8 +7671,8 @@ "field_name": "taxes_and_charges", "idx": 0, "is_system_generated": 0, - "modified": "2018-04-02 19:09:40.941137", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.181802", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-taxes_and_charges-width", "owner": "aditya@rigpl.com", @@ -7671,8 +7701,8 @@ "field_name": "tc_name", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.435258", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.204424", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-tc_name-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -7701,8 +7731,8 @@ "field_name": "territory", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.194153", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.236801", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-territory-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -7731,8 +7761,8 @@ "field_name": "territory", "idx": 0, "is_system_generated": 0, - "modified": "2018-05-01 17:10:45.973240", - "modified_by": "ravi.singh@rigpl.com", + "modified": "2025-10-13 12:51:30.268836", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-territory-width", "owner": "ravi.singh@rigpl.com", @@ -7761,8 +7791,8 @@ "field_name": "time_sheet_list", "idx": 0, "is_system_generated": 0, - "modified": "2016-08-01 20:11:19.957870", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.299974", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-time_sheet_list-hidden", "owner": "aditya@rigpl.com", @@ -7777,36 +7807,6 @@ "select_property": null, "value": "1" }, - { - "_assign": null, - "_comments": null, - "_liked_by": null, - "_user_tags": null, - "creation": "2022-02-07 05:50:03.743794", - "default_value": null, - "doc_name": null, - "doc_type": "Sales Invoice", - "docstatus": 0, - "doctype_or_field": "DocType", - "field_name": null, - "idx": 0, - "is_system_generated": 0, - "modified": "2022-02-07 05:50:03.743794", - "modified_by": "aditya@rigpl.com", - "module": null, - "name": "Sales Invoice-title_field", - "owner": "aditya@rigpl.com", - "parent": null, - "parentfield": null, - "parenttype": null, - "property": "title_field", - "property_type": "Data", - "row_name": null, - "select_doctype": null, - "select_item": null, - "select_property": null, - "value": "customer_name" - }, { "_assign": null, "_comments": null, @@ -7821,8 +7821,8 @@ "field_name": "total_taxes_and_charges", "idx": 0, "is_system_generated": 0, - "modified": "2018-03-03 14:36:37.155186", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.366897", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-total_taxes_and_charges-width", "owner": "aditya@rigpl.com", @@ -7851,8 +7851,8 @@ "field_name": "total", "idx": 0, "is_system_generated": 1, - "modified": "2016-08-04 14:32:36.346704", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.398491", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-total-precision", "owner": "Administrator", @@ -7881,8 +7881,8 @@ "field_name": "transporters", "idx": 0, "is_system_generated": 0, - "modified": "2017-11-03 16:42:24.060116", - "modified_by": "abhinav@rigpl.com", + "modified": "2025-10-13 12:51:30.431633", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-transporters-width", "owner": "abhinav@rigpl.com", @@ -7911,8 +7911,8 @@ "field_name": "update_stock", "idx": 0, "is_system_generated": 0, - "modified": "2022-02-07 11:03:28.359301", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.458637", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-update_stock-default", "owner": "aditya@rigpl.com", @@ -7941,8 +7941,8 @@ "field_name": "update_stock", "idx": 0, "is_system_generated": 0, - "modified": "2014-12-11 14:26:34.234729", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.478023", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-update_stock-hidden", "owner": "aditya@rigpl.com", @@ -7971,8 +7971,8 @@ "field_name": "write_off_account", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.403700", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.497324", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-write_off_account-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -8001,8 +8001,8 @@ "field_name": "write_off_account", "idx": 0, "is_system_generated": 0, - "modified": "2015-05-31 17:53:58.250523", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.516202", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-write_off_account-permlevel", "owner": "aditya@rigpl.com", @@ -8031,8 +8031,8 @@ "field_name": "write_off_amount", "idx": 0, "is_system_generated": 0, - "modified": "2015-05-31 17:53:58.217006", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.535220", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-write_off_amount-permlevel", "owner": "aditya@rigpl.com", @@ -8061,8 +8061,8 @@ "field_name": "write_off_cost_center", "idx": 0, "is_system_generated": 0, - "modified": "2017-09-01 11:32:01.416413", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.554764", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-write_off_cost_center-ignore_user_permissions", "owner": "aditya@rigpl.com", @@ -8091,8 +8091,8 @@ "field_name": "write_off_cost_center", "idx": 0, "is_system_generated": 0, - "modified": "2015-05-31 17:53:58.265994", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:30.577970", + "modified_by": "Administrator", "module": null, "name": "Sales Invoice-write_off_cost_center-permlevel", "owner": "aditya@rigpl.com", diff --git a/rohit_common/rohit_common/custom/sales_invoice_item.json b/rohit_common/rohit_common/custom/sales_invoice_item.json index d9c07ed..063aa64 100644 --- a/rohit_common/rohit_common/custom/sales_invoice_item.json +++ b/rohit_common/rohit_common/custom/sales_invoice_item.json @@ -1297,7 +1297,7 @@ "field_name": "amount", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:39:58.580564", + "modified": "2025-10-13 12:51:36.443888", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-amount-columns", @@ -1327,7 +1327,7 @@ "field_name": "amount", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:02.851736", + "modified": "2025-10-13 12:51:36.487317", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-amount-precision", @@ -1357,7 +1357,7 @@ "field_name": "amount", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:00.454902", + "modified": "2025-10-13 12:51:36.524134", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-amount-print_hide", @@ -1387,7 +1387,7 @@ "field_name": "amount", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:02.508594", + "modified": "2025-10-13 12:51:36.550981", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-amount-width", @@ -1417,7 +1417,7 @@ "field_name": "barcode", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:39:56.926377", + "modified": "2025-10-13 12:51:36.572232", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-barcode-hidden", @@ -1447,7 +1447,7 @@ "field_name": "base_amount", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:04.547667", + "modified": "2025-10-13 12:51:36.593708", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-base_amount-precision", @@ -1477,7 +1477,7 @@ "field_name": "base_net_amount", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:04.387093", + "modified": "2025-10-13 12:51:36.616137", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-base_net_amount-precision", @@ -1507,7 +1507,7 @@ "field_name": "base_net_rate", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:04.215332", + "modified": "2025-10-13 12:51:36.637069", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-base_net_rate-precision", @@ -1537,7 +1537,7 @@ "field_name": "base_price_list_rate", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:03.179871", + "modified": "2025-10-13 12:51:36.658223", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-base_price_list_rate-precision", @@ -1567,7 +1567,7 @@ "field_name": "base_rate", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:04.068218", + "modified": "2025-10-13 12:51:36.679861", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-base_rate-precision", @@ -1597,7 +1597,7 @@ "field_name": "batch_no", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:39:59.115229", + "modified": "2025-10-13 12:51:36.700600", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-batch_no-in_list_view", @@ -1627,7 +1627,7 @@ "field_name": "cost_center", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:01.865792", + "modified": "2025-10-13 12:51:36.735991", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-cost_center-ignore_user_permissions", @@ -1657,7 +1657,7 @@ "field_name": "cost_center", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:05.810296", + "modified": "2025-10-13 12:51:36.764697", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-cost_center-reqd", @@ -1687,7 +1687,7 @@ "field_name": "deferred_revenue_account", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:01.677049", + "modified": "2025-10-13 12:51:36.785229", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-deferred_revenue_account-ignore_user_permissions", @@ -1717,7 +1717,7 @@ "field_name": "delivery_note", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:05.486956", + "modified": "2025-10-13 12:51:36.805179", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-delivery_note-print_hide", @@ -1747,7 +1747,7 @@ "field_name": "description", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:39:59.987151", + "modified": "2025-10-13 12:51:36.824893", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-description-columns", @@ -1777,7 +1777,7 @@ "field_name": "description", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:04.697492", + "modified": "2025-10-13 12:51:36.845963", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-description-in_list_view", @@ -1807,7 +1807,7 @@ "field_name": "description", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:01.040994", + "modified": "2025-10-13 12:51:36.868987", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-description-print_width", @@ -1837,7 +1837,7 @@ "field_name": "description", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:01.341978", + "modified": "2025-10-13 12:51:36.899191", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-description-width", @@ -1867,7 +1867,7 @@ "field_name": "discount_account", "idx": 0, "is_system_generated": 1, - "modified": "2025-09-13 20:05:50.341901", + "modified": "2025-10-13 12:51:36.937211", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-discount_account-hidden", @@ -1897,7 +1897,7 @@ "field_name": "discount_account", "idx": 0, "is_system_generated": 1, - "modified": "2025-09-13 20:05:50.360769", + "modified": "2025-10-13 12:51:36.976820", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-discount_account-mandatory_depends_on", @@ -1927,7 +1927,7 @@ "field_name": "discount_percentage", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:39:59.501573", + "modified": "2025-10-13 12:51:37.021553", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-discount_percentage-columns", @@ -1957,7 +1957,7 @@ "field_name": "discount_percentage", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:39:59.658175", + "modified": "2025-10-13 12:51:37.060328", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-discount_percentage-in_list_view", @@ -1987,7 +1987,7 @@ "field_name": "expense_account", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:02.048191", + "modified": "2025-10-13 12:51:37.085628", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-expense_account-ignore_user_permissions", @@ -2017,7 +2017,7 @@ "field_name": "image", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:00.307938", + "modified": "2025-10-13 12:51:37.104599", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-image-print_hide", @@ -2047,7 +2047,7 @@ "field_name": "income_account", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:02.212179", + "modified": "2025-10-13 12:51:37.126644", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-income_account-ignore_user_permissions", @@ -2077,7 +2077,7 @@ "field_name": "item_code", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:00.151951", + "modified": "2025-10-13 12:51:37.151518", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-item_code-columns", @@ -2107,7 +2107,7 @@ "field_name": "item_code", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:01.191424", + "modified": "2025-10-13 12:51:37.177833", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-item_code-width", @@ -2137,7 +2137,7 @@ "field_name": "item_name", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:06.109171", + "modified": "2025-10-13 12:51:37.213652", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-item_name-hidden", @@ -2167,7 +2167,7 @@ "field_name": "item_name", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:04.844516", + "modified": "2025-10-13 12:51:37.251882", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-item_name-in_list_view", @@ -2197,7 +2197,7 @@ "field_name": "item_name", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:03.491482", + "modified": "2025-10-13 12:51:37.290622", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-item_name-length", @@ -2227,7 +2227,7 @@ "field_name": "item_name", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:05.957494", + "modified": "2025-10-13 12:51:37.325923", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-item_name-reqd", @@ -2257,7 +2257,7 @@ "field_name": null, "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:39:58.754700", + "modified": "2025-10-13 12:51:37.364022", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-main-read_only_onload", @@ -2287,7 +2287,7 @@ "field_name": "net_amount", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:03.907870", + "modified": "2025-10-13 12:51:37.403412", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-net_amount-precision", @@ -2317,7 +2317,7 @@ "field_name": "net_rate", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:03.716386", + "modified": "2025-10-13 12:51:37.442477", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-net_rate-precision", @@ -2347,7 +2347,7 @@ "field_name": "price_list_rate", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:03.336684", + "modified": "2025-10-13 12:51:37.481364", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-price_list_rate-precision", @@ -2377,7 +2377,7 @@ "field_name": "qty", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:39:59.809798", + "modified": "2025-10-13 12:51:37.517727", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-qty-columns", @@ -2407,7 +2407,7 @@ "field_name": "qty", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:00.744590", + "modified": "2025-10-13 12:51:37.565524", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-qty-print_width", @@ -2437,7 +2437,7 @@ "field_name": "qty", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:00.894752", + "modified": "2025-10-13 12:51:37.593228", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-qty-width", @@ -2467,7 +2467,7 @@ "field_name": "rate", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:39:59.302966", + "modified": "2025-10-13 12:51:37.618251", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-rate-columns", @@ -2497,7 +2497,7 @@ "field_name": "rate", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:03.023302", + "modified": "2025-10-13 12:51:37.647066", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-rate-precision", @@ -2527,7 +2527,7 @@ "field_name": "rate", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:00.597401", + "modified": "2025-10-13 12:51:37.676978", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-rate-print_hide", @@ -2557,7 +2557,7 @@ "field_name": "rate", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:02.666829", + "modified": "2025-10-13 12:51:37.706481", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-rate-width", @@ -2587,7 +2587,7 @@ "field_name": "sales_order", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:04.989570", + "modified": "2025-10-13 12:51:37.738928", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-sales_order-in_filter", @@ -2617,7 +2617,7 @@ "field_name": "sales_order", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:05.656218", + "modified": "2025-10-13 12:51:37.777580", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-sales_order-print_hide", @@ -2647,7 +2647,7 @@ "field_name": "sales_order", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:02.361954", + "modified": "2025-10-13 12:51:37.803258", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-sales_order-width", @@ -2677,7 +2677,7 @@ "field_name": "serial_no", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:39:58.934808", + "modified": "2025-10-13 12:51:37.823952", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-serial_no-in_list_view", @@ -2707,7 +2707,7 @@ "field_name": "target_warehouse", "idx": 0, "is_system_generated": 1, - "modified": "2025-08-22 16:43:05.094055", + "modified": "2025-10-13 12:51:37.844617", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-target_warehouse-hidden", @@ -2737,7 +2737,7 @@ "field_name": "warehouse", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:01.494057", + "modified": "2025-10-13 12:51:37.867548", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-warehouse-ignore_user_permissions", @@ -2767,7 +2767,7 @@ "field_name": "warehouse", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:05.160193", + "modified": "2025-10-13 12:51:37.888793", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-warehouse-in_list_view", @@ -2797,7 +2797,7 @@ "field_name": "warehouse", "idx": 0, "is_system_generated": 0, - "modified": "2025-08-22 18:40:05.330945", + "modified": "2025-10-13 12:51:37.907659", "modified_by": "Administrator", "module": null, "name": "Sales Invoice Item-warehouse-print_hide", diff --git a/rohit_common/rohit_common/custom/sales_taxes_and_charges.json b/rohit_common/rohit_common/custom/sales_taxes_and_charges.json index 43e045d..a37f1ae 100644 --- a/rohit_common/rohit_common/custom/sales_taxes_and_charges.json +++ b/rohit_common/rohit_common/custom/sales_taxes_and_charges.json @@ -76,36 +76,6 @@ "doctype": "Sales Taxes and Charges", "links": [], "property_setters": [ - { - "_assign": null, - "_comments": null, - "_liked_by": null, - "_user_tags": null, - "creation": "2018-11-08 16:23:11.312177", - "default_value": null, - "doc_name": null, - "doc_type": "Sales Taxes and Charges", - "docstatus": 0, - "doctype_or_field": "DocType", - "field_name": "", - "idx": 0, - "is_system_generated": 1, - "modified": "2018-11-08 16:23:11.312177", - "modified_by": "Administrator", - "module": null, - "name": "Sales Taxes and Charges-autoname", - "owner": "Administrator", - "parent": null, - "parentfield": null, - "parenttype": null, - "property": "autoname", - "property_type": "", - "row_name": null, - "select_doctype": null, - "select_item": null, - "select_property": null, - "value": "INVTD.######" - }, { "_assign": null, "_comments": null, @@ -120,7 +90,7 @@ "field_name": "base_tax_amount_after_discount_amount", "idx": 0, "is_system_generated": 1, - "modified": "2015-05-30 18:20:45.508097", + "modified": "2025-10-13 12:51:24.010533", "modified_by": "Administrator", "module": null, "name": "Sales Taxes and Charges-base_tax_amount_after_discount_amount-precision", @@ -150,7 +120,7 @@ "field_name": "base_tax_amount", "idx": 0, "is_system_generated": 1, - "modified": "2015-05-30 18:20:45.165010", + "modified": "2025-10-13 12:51:24.041269", "modified_by": "Administrator", "module": null, "name": "Sales Taxes and Charges-base_tax_amount-precision", @@ -180,7 +150,7 @@ "field_name": "base_total", "idx": 0, "is_system_generated": 1, - "modified": "2015-05-30 18:20:45.336839", + "modified": "2025-10-13 12:51:24.066355", "modified_by": "Administrator", "module": null, "name": "Sales Taxes and Charges-base_total-precision", @@ -210,8 +180,8 @@ "field_name": "charge_type", "idx": 0, "is_system_generated": 0, - "modified": "2017-06-27 22:15:21.625039", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:24.089900", + "modified_by": "Administrator", "module": null, "name": "Sales Taxes and Charges-charge_type-in_list_view", "owner": "aditya@rigpl.com", @@ -240,8 +210,8 @@ "field_name": "cost_center", "idx": 0, "is_system_generated": 0, - "modified": "2013-07-28 17:45:41", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:24.112001", + "modified_by": "Administrator", "module": null, "name": "Sales Taxes and Charges-cost_center-in_list_view", "owner": "aditya@rigpl.com", @@ -270,8 +240,8 @@ "field_name": "description", "idx": 0, "is_system_generated": 0, - "modified": "2017-06-27 22:15:21.633560", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:24.134476", + "modified_by": "Administrator", "module": null, "name": "Sales Taxes and Charges-description-in_list_view", "owner": "aditya@rigpl.com", @@ -300,8 +270,8 @@ "field_name": "included_in_print_rate", "idx": 0, "is_system_generated": 0, - "modified": "2013-07-28 17:45:41", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:24.157125", + "modified_by": "Administrator", "module": null, "name": "Sales Taxes and Charges-included_in_print_rate-in_list_view", "owner": "aditya@rigpl.com", @@ -316,6 +286,36 @@ "select_property": null, "value": "1" }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-11-08 16:23:11.312177", + "default_value": null, + "doc_name": null, + "doc_type": "Sales Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": "", + "idx": 0, + "is_system_generated": 1, + "modified": "2025-10-13 12:51:23.968576", + "modified_by": "Administrator", + "module": null, + "name": "Sales Taxes and Charges-main-autoname", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "autoname", + "property_type": "", + "row_name": null, + "select_doctype": null, + "select_item": null, + "select_property": null, + "value": "INVTD.######" + }, { "_assign": null, "_comments": null, @@ -330,7 +330,7 @@ "field_name": "tax_amount_after_discount_amount", "idx": 0, "is_system_generated": 1, - "modified": "2015-05-30 18:20:45.423948", + "modified": "2025-10-13 12:51:24.179259", "modified_by": "Administrator", "module": null, "name": "Sales Taxes and Charges-tax_amount_after_discount_amount-precision", @@ -360,8 +360,8 @@ "field_name": "total", "idx": 0, "is_system_generated": 0, - "modified": "2013-07-28 17:45:41", - "modified_by": "aditya@rigpl.com", + "modified": "2025-10-13 12:51:24.203012", + "modified_by": "Administrator", "module": null, "name": "Sales Taxes and Charges-total-in_list_view", "owner": "aditya@rigpl.com", @@ -390,7 +390,7 @@ "field_name": "total", "idx": 0, "is_system_generated": 1, - "modified": "2015-05-30 18:20:45.248409", + "modified": "2025-10-13 12:51:24.224962", "modified_by": "Administrator", "module": null, "name": "Sales Taxes and Charges-total-precision", From 7d9c3deb95d7ccdb7b6296cdf8aaefa451b8a54e Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Tue, 14 Oct 2025 08:40:21 +0000 Subject: [PATCH 24/52] fix: comment out place_of_supply assignment in update_fields function --- rohit_common/rohit_common/validations/purchase_invoice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rohit_common/rohit_common/validations/purchase_invoice.py b/rohit_common/rohit_common/validations/purchase_invoice.py index 5a4c040..223a3b1 100644 --- a/rohit_common/rohit_common/validations/purchase_invoice.py +++ b/rohit_common/rohit_common/validations/purchase_invoice.py @@ -65,7 +65,7 @@ def update_fields(doc,method): if it.gst_hsn_code != it_gst: it.gst_hsn_code = it_gst doc.letter_head = frappe.db.get_value("Purchase Taxes and Charges Template", doc.taxes_and_charges, "letter_head") - doc.place_of_supply = frappe.db.get_value("Purchase Taxes and Charges Template", doc.taxes_and_charges, "state") + # doc.place_of_supply = frappe.db.get_value("Purchase Taxes and Charges Template", doc.taxes_and_charges, "state") doc.supplier_gstin = frappe.db.get_value("Address", doc.supplier_address, "gstin") doc.company_gstin = frappe.db.get_value("Address", doc.shipping_address, "gstin") From 74dd4853553089b6dc3909765811a4435f1934bd Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Mon, 20 Oct 2025 13:21:09 +0530 Subject: [PATCH 25/52] feat: implement migration from GL Entries to Payment Ledger with dimension handling (#15) --- rohit_common/custom_method.py | 210 ++++++++++++++++++++++++++++------ 1 file changed, 172 insertions(+), 38 deletions(-) diff --git a/rohit_common/custom_method.py b/rohit_common/custom_method.py index 4fa3df7..8287c0a 100644 --- a/rohit_common/custom_method.py +++ b/rohit_common/custom_method.py @@ -1,40 +1,174 @@ -from erpnext.accounts.utils import create_payment_ledger_entry import frappe +from frappe import qb +from frappe.query_builder import CustomFunction +from frappe.query_builder.custom import ConstantColumn +from frappe.query_builder.functions import Count, IfNull +from frappe.utils import flt -# from erpnext.accounts.payment_ledger import create_payment_ledger_entry - -def backfill_payment_ledger(batch_size=500): - """ - Rebuild Payment Ledger Entries (PLEs) from GL Entries for all submitted vouchers. - """ - - doctypes = ["Sales Invoice", "Purchase Invoice", "Payment Entry", "Journal Entry"] - - for doctype in doctypes: - names = frappe.get_all(doctype, filters={"docstatus": 1}, pluck="name") - total = len(names) - print(f"\n>>> Processing {doctype}: {total} documents") - - created_count = 0 - error_count = 0 - - for i in range(0, total, batch_size): - batch = names[i:i+batch_size] - for name in batch: - try: - doc = frappe.get_doc(doctype, name) - if hasattr(doc, "get_gl_entries"): - gl_entries = doc.get_gl_entries() - if gl_entries: - create_payment_ledger_entry(gl_entries) - created_count += 1 - except Exception: - error_count += 1 - frappe.log_error( - title=f"PLE Backfill Failed for {doctype} {name}", - message=frappe.get_traceback() - ) - frappe.db.commit() - print(f" ✔ Batch {(i//batch_size)+1}: processed {len(batch)} docs") - - print(f"✓ Done {doctype}: {created_count} created, {error_count} errors") \ No newline at end of file +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_dimensions, + make_dimension_in_accounting_doctypes, +) + +# Note: Only run this script manually if official erpnext script fails or GLE not populated properly. +# Also before running take backup also truncate Payment Ledger Entry table +# Original patch path erpnext.erpnext.patches.v14_0.migrate_gl_to_payment_ledger + +# ------------------------- +# Helper Functions +# ------------------------- + +def create_accounting_dimension_fields(): + dimensions_and_defaults = get_dimensions() + if dimensions_and_defaults: + for dimension in dimensions_and_defaults[0]: + make_dimension_in_accounting_doctypes(dimension, ["Payment Ledger Entry"]) + + +def get_columns(): + columns = [ + "name", + "creation", + "modified", + "modified_by", + "owner", + "docstatus", + "posting_date", + "account_type", + "account", + "party_type", + "party", + "voucher_type", + "voucher_no", + "against_voucher_type", + "against_voucher_no", + "amount", + "amount_in_account_currency", + "account_currency", + "company", + "cost_center", + "due_date", + "finance_book", + ] + + if frappe.db.has_column("Payment Ledger Entry", "remarks"): + columns.append("remarks") + + dimensions_and_defaults = get_dimensions() + if dimensions_and_defaults: + for dimension in dimensions_and_defaults[0]: + columns.append(dimension.fieldname) + + return columns + + +def generate_name_and_calculate_amount(gl_entries, start, receivable_accounts): + for index, entry in enumerate(gl_entries, 0): + entry.name = start + index + if entry.account in receivable_accounts: + entry.account_type = "Receivable" + entry.amount = entry.debit - entry.credit + entry.amount_in_account_currency = entry.debit_in_account_currency - entry.credit_in_account_currency + else: + entry.account_type = "Payable" + entry.amount = entry.credit - entry.debit + entry.amount_in_account_currency = entry.credit_in_account_currency - entry.debit_in_account_currency + + +def build_insert_query(): + ple = qb.DocType("Payment Ledger Entry") + columns = get_columns() + insert_query = qb.into(ple).columns(tuple(columns)) + return insert_query + + +def insert_chunk_into_payment_ledger(insert_query, gl_entries): + if gl_entries: + columns = get_columns() + for entry in gl_entries: + data = tuple(entry[col] for col in columns) + insert_query = insert_query.insert(data) + insert_query.run() + frappe.db.commit() + + +# ------------------------- +# Main Migration Function +# ------------------------- + +def migrate_gl_to_payment_ledger(): + print("⚙️ Starting Payment Ledger migration...") + + # Ensure accounting dimension fields exist + create_accounting_dimension_fields() + + gl = qb.DocType("GL Entry") + account = qb.DocType("Account") + ifelse = CustomFunction("IF", ["condition", "then", "else"]) + + # Fetch Receivable and Payable accounts + relevant_accounts = ( + qb.from_(account) + .select(account.name, account.account_type) + .where((account.account_type == "Receivable") | (account.account_type == "Payable")) + .orderby(account.name) + .run(as_dict=True) + ) + + receivable_accounts = [x.name for x in relevant_accounts if x.account_type == "Receivable"] + accounts = [x.name for x in relevant_accounts] + + # Count unprocessed GL Entries + unprocessed_count = ( + qb.from_(gl) + .select(Count(gl.name)) + .where((gl.is_cancelled == 0) & (gl.account.isin(accounts))) + .run() + )[0][0] + + if not unprocessed_count: + print("No eligible GL Entries found. Exiting.") + return + + print(f"Migrating {unprocessed_count} GL Entries to Payment Ledger…") + + batch_size = 5000 + processed = 0 + last_name = None + + while True: + where_clause = (gl.account.isin(accounts) & (gl.is_cancelled == 0)) + if last_name: + where_clause &= gl.name.gt(last_name) + + gl_entries = ( + qb.from_(gl) + .select( + gl.star, + ConstantColumn(1).as_("docstatus"), + IfNull(ifelse(gl.against_voucher_type == "", None, gl.against_voucher_type), gl.voucher_type).as_("against_voucher_type"), + IfNull(ifelse(gl.against_voucher == "", None, gl.against_voucher), gl.voucher_no).as_("against_voucher_no"), + ) + .where(where_clause) + .orderby(gl.name) + .limit(batch_size) + .run(as_dict=True) + ) + + if not gl_entries: + break + + last_name = gl_entries[-1].name + + # Generate name and calculate amounts + generate_name_and_calculate_amount(gl_entries, processed, receivable_accounts) + + # Insert into Payment Ledger + insert_query = build_insert_query() + insert_chunk_into_payment_ledger(insert_query, gl_entries) + + processed += len(gl_entries) + percent = flt((processed / unprocessed_count) * 100, 2) + print(f"{percent}% ({processed}) records processed…") + + print(f"✅ Migration completed. Total records migrated: {processed}") From 69ebfba86c55938d6f3e8ea698eea8bb1a84745c Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Thu, 23 Oct 2025 09:57:46 +0000 Subject: [PATCH 26/52] feat(docs): updated --- docs/09-2025.md | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/docs/09-2025.md b/docs/09-2025.md index 6175a4b..0ec8c99 100644 --- a/docs/09-2025.md +++ b/docs/09-2025.md @@ -39,12 +39,14 @@ ### 4. GST Return Status **Status:** Fixed **Issue:** Unable to fetch GST Return Status. +**Fix:** Used India Compliance API. --- ### 5. Address (GST Validation) **Status:** Fixed -**Issue:** GST API validation not working. +**Issue:** GST API validation not working. +**Fix:** Used India Compliance API. --- @@ -55,12 +57,12 @@ --- ### 7. Asset (Customizations) -**Status:** Fix pushed, under review. +**Status:** Fix pushed. --- ### 8. Asset Report (Analysis) -**Status:** Fix pushed, under review. +**Status:** Fix pushed. --- @@ -91,12 +93,5 @@ **Issue:** Payment Ledger empty due to skipped patch (introduced in later version). **Fix:** Added script to backfill payment ledger. - File: `custom_method.py` -- Method: `backfill_payment_ledger()` - ---- - -## ✅ Summary -- **Resolved:** File List issues, GL Report. -- **In Review:** Asset fixes. -- **Pending:** Contact search. -- **Custom Reports/Patches:** Added where native functionality broke. +- Method: `migrate_gl_to_payment_ledger()` +- Note: Frappe Patch will run if it not populates the PLE than only run this Script Manullaly Also before running enable all fiscal year From 88a2cde6052f137bef68f6cdf6cda56c1d063554 Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Thu, 23 Oct 2025 10:11:46 +0000 Subject: [PATCH 27/52] fix(docs): added new issues --- docs/09-2025.md | 123 ++++++++++++++++++------------ docs/10-2025.md | 198 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 272 insertions(+), 49 deletions(-) create mode 100644 docs/10-2025.md diff --git a/docs/09-2025.md b/docs/09-2025.md index 0ec8c99..5be6ed3 100644 --- a/docs/09-2025.md +++ b/docs/09-2025.md @@ -8,90 +8,115 @@ ## Fixed & Pending Issues -### 1. Sales Invoice (Unable to Save + E-Invoice Issues) -**Status:** Resolved -- Removed custom code resetting *place of supply* that caused save failures. - → File: `validations/sales_invoice.py` → Method: `check_local_natl_tax_rules()` -- E-Invoice re-enabled with **India Compliance**. - - Re-setup required for new sites. - - Path: **GST Settings → Enable E-Invoice** (currently sandbox mode). +### 1. Sales Invoice (Save Failure + E-Invoice) +**Status:** ✅ Resolved + +- **Root Cause:** Custom code resetting *Place of Supply* caused save failures. + - **File:** `validations/sales_invoice.py` + - **Method:** `check_local_natl_tax_rules()` +- **Fix:** Removed the faulty custom code. +- **E-Invoice:** Re-enabled via **India Compliance**. + - Requires re-setup for new sites. + - Path: **GST Settings → Enable E-Invoice** (currently in sandbox mode). - Setup Guide: [India Compliance Docs](https://docs.indiacompliance.app/docs/ewaybill-and-einvoice/gst_settings) -- To Remove QR Code, Ack No, and Ack Date in E-Invoice have created new print format RIGPL IC e-Invoice. +- **Print Format:** Created new print format — **RIGPL IC e-Invoice** — which excludes QR Code, Ack No, and Ack Date. --- -### 2. File List (Search Issues) -**Issue:** Unable to search file names attached to Doctypes. -**Fix:** Corrected hook path & method override. -- Hook: `override_whitelisted_methods` -- Method: `rohit_common.core.file.get_files_by_search_text` +### 2. File List (Search Issues) +**Issue:** File names attached to Doctypes were not searchable. +**Fix:** Corrected hook path and method override. +- **Hook:** `override_whitelisted_methods` +- **Method:** `rohit_common.core.file.get_files_by_search_text` --- -### 3. File List (Permission Issues) -**Issue:** System Manager unable to view files not attached to any Doctype. -**Fix:** Overridden Frappe File methods, since Frappe reverses the `has_permission` hooks, causing our hook to run before Frappe’s own. -- Reference: [frappe/permissions.py#L467](https://github.com/frappe/frappe/blob/develop/frappe/permissions.py#L467) -- Custom Code: `overrides/file.py` + `hooks/__init__.py` +### 3. File List (Permission Issues) +**Issue:** *System Manager* could not view files not attached to any Doctype. +**Root Cause:** Frappe’s `has_permission` hooks run in reverse order, causing our hook to execute before Frappe’s own. +**Fix:** Overrode Frappe’s `File` methods to ensure proper permission evaluation. +- **Reference:** [frappe/permissions.py#L467](https://github.com/frappe/frappe/blob/develop/frappe/permissions.py#L467) +- **Custom Code:** + - `overrides/file.py` + - `hooks/__init__.py` --- -### 4. GST Return Status -**Status:** Fixed +### 4. GST Return Status +**Status:** ✅ Fixed **Issue:** Unable to fetch GST Return Status. -**Fix:** Used India Compliance API. +**Fix:** Integrated **India Compliance API** for fetching GST return data. --- -### 5. Address (GST Validation) -**Status:** Fixed -**Issue:** GST API validation not working. -**Fix:** Used India Compliance API. +### 5. Address (GST Validation) +**Status:** ✅ Fixed +**Issue:** GST API validation not working. +**Fix:** Switched to **India Compliance API** for validation. --- -### 6. GL Report -**Issue:** General Ledger should display only net opening. -**Fix:** Created custom report: **RIGPL General Ledger**. +### 6. General Ledger Report +**Issue:** The standard General Ledger displayed detailed opening balances instead of a net opening. +**Fix:** Created a custom report — **RIGPL General Ledger** — which shows only net opening balances. --- -### 7. Asset (Customizations) -**Status:** Fix pushed. +### 7. Asset (Customizations) +**Status:** ✅ Fix deployed. --- -### 8. Asset Report (Analysis) -**Status:** Fix pushed. +### 8. Asset Report (Analysis) +**Status:** ✅ Fix deployed. --- -### 9. Contact (Search Fields) -**Issue:** Search not working based on fields defined in Customize Form. -**Status:** Found Method but its not used anywhere rohit_common.utils.contact_utils.rigpl_contact_query. +### 9. Contact (Search Fields) +**Issue:** Search did not work based on fields defined in **Customize Form**. +**Findings:** The method `rohit_common.utils.contact_utils.rigpl_contact_query` exists but is not used anywhere. +**Status:** ⚙️ Pending review / refactor. --- -### 10. Pricing Rule -**Issue:** Sales Orders not fetching rules for Item Group children (worked in V12). -**Action:** Skipped → **Not related to this app**. +### 10. Pricing Rule +**Issue:** Sales Orders not fetching rules for *Item Group* children (worked in V12). +**Action:** Skipped — not related to this app. --- -### 11. Asset Patch Failure -**Fix:** Patch issue resolved. +### 11. Asset Patch Failure +**Status:** ✅ Fixed +**Fix:** Patch execution issue resolved. --- -### 12. Sales Invoice (E-Invoice JSON) -**Issue:** Should send only summary of items (not line-wise rates) to GSTIN. -**Status:** Cannot remove quantity and UnitPrice Both are required in india compliance API. +### 12. Sales Invoice (E-Invoice JSON) +**Issue:** E-Invoice JSON should send only item summaries, not line-wise rates. +**Status:** ⚠️ Limitation +- Quantity and Unit Price fields are mandatory per **India Compliance API** specifications, so they cannot be removed. --- -### 13 & 14. Accounts Receivable (AR) Report -**Issue:** Payment Ledger empty due to skipped patch (introduced in later version). -**Fix:** Added script to backfill payment ledger. -- File: `custom_method.py` -- Method: `migrate_gl_to_payment_ledger()` -- Note: Frappe Patch will run if it not populates the PLE than only run this Script Manullaly Also before running enable all fiscal year +### 13 & 14. Accounts Receivable (AR) Report +**Issue:** Payment Ledger was empty due to a skipped patch introduced in later versions. +**Fix:** Added a script to backfill Payment Ledger entries. + +- **File:** `custom_method.py` +- **Method:** `migrate_gl_to_payment_ledger()` + +**Notes:** +- The official Frappe ERPNext patch will run automatically. +- If it fails to populate the Payment Ledger, run the above script manually. +- Ensure **all Fiscal Years are enabled** before running the script. + +--- + +## ✅ Overall Migration Summary +- Core modules are functional. +- India Compliance integrations (E-Invoice, GST Validation, Return Status) are fully operational. +- Custom reports and patches applied successfully. +- All critical migration issues resolved or documented for follow-up. + +**Last Updated:** _October 2025_ +**Maintained By:** Development Team \ No newline at end of file diff --git a/docs/10-2025.md b/docs/10-2025.md new file mode 100644 index 0000000..5c6b1ee --- /dev/null +++ b/docs/10-2025.md @@ -0,0 +1,198 @@ +# New Issues Log: Post Migration (After #14) + +This document lists additional issues reported after the initial migration testing phase. +Format and structure follow the main migration notes for consistency. + +--- + +### 15. Sales Invoice (Multiple Save & UI Issues) +**Status:** ✅ Resolved + +**Issues Identified:** +1. Ship-to Address not auto-fetching and search not available. +2. Customer Purchase Order not editable. +3. “Total Amount (In Words)” missing in PDF/Print. +4. Letterhead missing in printed invoice. +5. Packing List, Export Invoice, and Custom Invoice not visible. +6. New interface more complex compared to old version. + +**Fix:** +- Ship-to Address now auto-fetches. +- Customer Purchase Order field made editable. +- Total Amount (In Words) now displays in print format. +- Letterhead added to PDF/Print. +- All required print formats are now available. + +--- + +### 16. Sales Invoice (Errors While Creating Invoices) +**Status:** ⚙️ Under Review + +**Issues Identified:** +1. “No permission for Accounts Settings.” +2. Customer PO details were under *More Info* instead of *Details*. +3. CETSH Code (82078000) missing for certain items. +4. Only Domestic Invoice format available. + +**Fix / Developer Notes:** +- Verified System Manager permissions. +- Moved PO details to the **Details** tab. +- Confirmed HSN Code presence. +- Other print formats are available for export invoices. + +--- + +### 17. Purchase Invoice (Unable to Save) +**Status:** ✅ Fixed + +**Issue:** +Validation error — *“Please set Account in Warehouse Machinery or Default Inventory Account in Company.”* + +**Fix:** +- Created and linked **Stock Account** in Warehouse and Company settings. +- Verified GL posting. +- Reference: [Default Warehouse](http://51.15.187.192:8000/app/warehouse/Default%20Warehouse) + +--- + +### 18. Journal Entry (Letterhead Missing) +**Status:** ✅ Fixed +**Issue:** Letterhead not appearing in PDF or print. +**Fix:** Letterhead template verified and restored. + +--- + +### 19. Payment Entry (Letterhead Missing) +**Status:** ✅ Fixed +**Issue:** Letterhead not appearing in PDF or print. +**Fix:** Verified and restored print format; working fine. + +--- + +### 20. General Ledger (Performance & Print) +**Status:** ⏳ Pending + +**Issues:** +- Report takes longer to load. +- Print & PDF options missing. + +--- + +### 21. Customer (Address Save Error) +**Status:** ✅ Fixed + +**Issues:** +1. State field not searchable. +2. Error while saving address: `ModuleNotFoundError: No module named 'responses'` (India Compliance). + +**Fix:** +- Fixed search filter for State field. +- Added missing India Compliance dependency. + +--- + +### 22. Supplier (Address Save Error) +**Status:** ✅ Fixed + +**Issues:** +1. State field not searchable. +2. Error while saving address: `ModuleNotFoundError: No module named 'responses'`. + +**Fix:** +- Same fix as Customer: State search and dependency added. + +--- + +### 23. Payment Period Based on Invoice Date (Incorrect Data) +**Status:** ⚙️ To Check +**Issue:** *Payment Posting Date* column missing, causing inaccurate delay calculation. +**Action:** Verify report field mapping and correct data source. + +--- + +### 24. GSTR2A (Permission Error) +**Status:** ⚙️ To Check +**Issue:** “You are not permitted to access this resource. Login to access.” +**Fix / Notes:** Updated user permissions; awaiting confirmation. + +--- + +### 25. GSTR1 (Permission & API Error) +**Status:** ⚙️ To Check + +**Issues:** +- Same “not permitted” access issue. +- API configuration error from India Compliance. + +**Action:** +- Permissions updated. +- API setup Needs to be verified. + +--- + +### 26. Trial Balance (Incorrect Data) +**Status:** 🟡 Pending +**Issue:** Data mismatch for April 2025 onwards — incorrect AR/AP/Duties and Taxes. +**Action:** Awaiting sample data from accounting team for verification. + +--- + +### 27. ClearTax Import Format (Background Report) +**Status:** ℹ️ Info +**Issue:** “This is a background report. Please set filters before generating.” + +--- + +### 28. Profit & Loss Statement (Incorrect Monthly Totals) +**Status:** 🟡 Pending +**Issue:** Totals for May include April+May, cascading for later months. +**Action:** Require sample dataset for validation. + +--- + +### 29. Balance Sheet (Incorrect Data) +**Status:** 🟡 Pending +**Issue:** AR/AP/Reserves/Duties and Taxes not displaying correctly for Apr 2025. +**Action:** Awaiting sample data for reconciliation testing. + +--- + +### 30. Asset Depreciations & Balances (Incorrect Values) +**Status:** 🟡 Pending +**Issue:** Incorrect depreciation for *Four Wheelers - Cars (Apr 2024 to Mar 2025)*. +**Action:** Cross-verify values with GL Report. + +--- + +### 31. Payment Ledger Entry (Incorrect Voucher Type) +**Status:** ⚙️ To Check +**Priority:** 🔴 Urgent + +**Issue:** +- Wrong Voucher Type displayed. +- Missing ledger entries for vendor payments. + +**Fix:** Added a script to backfill Payment Ledger entries. + +- **File:** `custom_method.py` +- **Method:** `migrate_gl_to_payment_ledger()` + +**Notes:** +- The official Frappe ERPNext patch will run automatically. +- If it fails to populate the Payment Ledger, run the above script manually. +- Ensure **all Fiscal Years are enabled** before running the script. + +--- + +### 32. Sales Invoice (India Compliance for Old Transactions) +**Status:** ⏳ Pending +**Priority:** 🔴 Urgent + +**Issue:** +India Compliance setup not working for older Sales & Purchase transactions. + + +--- + +**Last Updated:** _October 2025_ +**Maintained By:** Development Team From d08884b194921ad52a9b1f40fcf2dc78872fab8a Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Tue, 11 Nov 2025 15:48:25 +0530 Subject: [PATCH 28/52] fix: auto delete version job (#16) --- .../scheduled_tasks/auto_delete_version.py | 60 ++++++++++++------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/rohit_common/rohit_common/scheduled_tasks/auto_delete_version.py b/rohit_common/rohit_common/scheduled_tasks/auto_delete_version.py index 0e46d2d..f34b259 100644 --- a/rohit_common/rohit_common/scheduled_tasks/auto_delete_version.py +++ b/rohit_common/rohit_common/scheduled_tasks/auto_delete_version.py @@ -19,42 +19,58 @@ def enqueue_deletion(): def execute(): st_time = time.time() rset = frappe.get_single("Rohit Settings") - max_days = flt(rset.max_days_to_keep_version) - dt_list = [] - for row in rset.auto_delete_from_version: - dt_list.append(row.document_type) - if max_days == 0: - max_days = 30 - - # First delete all items except for the ones in table which are above the max days - query = """SELECT name, creation, ref_doctype, docname FROM `tabVersion` WHERE ref_doctype NOT IN %s - AND creation <= (DATE_SUB(CURDATE(), INTERVAL %s DAY))""" % (tuple(dt_list), max_days) - un_regulated_version = frappe.db.sql(query, as_dict=1) + max_days = int(flt(rset.max_days_to_keep_version)) or 30 # ensure int and default to 30 + dt_list = [row.document_type for row in rset.auto_delete_from_version] + + if dt_list: + placeholders = ", ".join(["%s"] * len(dt_list)) + query = f""" + SELECT name, creation, ref_doctype, docname + FROM `tabVersion` + WHERE ref_doctype NOT IN ({placeholders}) + AND creation <= (DATE_SUB(CURDATE(), INTERVAL {max_days} DAY)) + """ + un_regulated_version = frappe.db.sql(query, tuple(dt_list), as_dict=1) + else: + # If dt_list empty, simply skip the NOT IN clause + query = f""" + SELECT name, creation, ref_doctype, docname + FROM `tabVersion` + WHERE creation <= (DATE_SUB(CURDATE(), INTERVAL {max_days} DAY)) + """ + un_regulated_version = frappe.db.sql(query, as_dict=1) + deleted_0 = 0 deleted_1 = 0 + for d in un_regulated_version: print(f"Deleting Versions for All Un-Listed Doctypes older than {max_days} Days") deleted_0 += 1 frappe.delete_doc("Version", d.name, for_reload=1) - if deleted_0 % 2000 == 0 and deleted_0 > 0: + if deleted_0 % 2000 == 0: frappe.db.commit() print(f"Committing After {deleted_0} deletions. Time Elapsed {int(time.time() - st_time)} seconds") + + # Now process doctypes listed in settings for row in rset.auto_delete_from_version: - # dt_conds = "" - # if row.doctype_conditions: - # dt_conds = " AND %s" % row.doctype_conditions - - max_days = flt(row.days_to_keep) if flt(row.days_to_keep) > 0 else 1 - print(f"Deleting Versions for {row.document_type} older than {max_days} Days") - query = """SELECT name, creation, ref_doctype, docname FROM `tabVersion` WHERE ref_doctype = '%s' - AND creation <= (DATE_SUB(CURDATE(), INTERVAL %s DAY))""" % (row.document_type, max_days) - reg_version = frappe.db.sql(query, as_dict=1) + max_days_row = int(flt(row.days_to_keep)) if flt(row.days_to_keep) > 0 else 1 + print(f"Deleting Versions for {row.document_type} older than {max_days_row} Days") + + query = f""" + SELECT name, creation, ref_doctype, docname + FROM `tabVersion` + WHERE ref_doctype = %s + AND creation <= (DATE_SUB(CURDATE(), INTERVAL {max_days_row} DAY)) + """ + reg_version = frappe.db.sql(query, (row.document_type,), as_dict=1) + for d in reg_version: deleted_1 += 1 frappe.delete_doc("Version", d.name, for_reload=1) - if deleted_1 % 2000 == 0 and deleted_1 > 0: + if deleted_1 % 2000 == 0: frappe.db.commit() print(f"Committing After {deleted_1} deletions. Time Elapsed {int(time.time() - st_time)} seconds") + tot_time = int(time.time() - st_time) print(f"Total Versions Deleted = {deleted_0 + deleted_1}") print(f"Total Time Taken = {tot_time} seconds") From 1de840b41f408295a5e6784d11dde61553e7e85d Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Tue, 18 Nov 2025 18:31:25 +0530 Subject: [PATCH 29/52] fix: clear tax import format and gstr1 (#17) * fix: clear tax import format * fix: gstr and contact * fix: few improvements * fix: overrided contact query * fix: clear tax import * fix: clear tax show 0 tax rows * fix: improved structure --- rohit_common/__init__.py | 6 + rohit_common/core/contact.py | 65 ++ rohit_common/hooks.py | 3 +- .../migration_scripts/combined_gst_fix.py | 625 +++++++++++++ .../create_gst_adjustment_jes.py | 290 ++++++ .../create_purchase_gst_adjustment_jes.py | 308 ++++++ .../fix_purchase_invoices_gst.py | 550 +++++++++++ .../migration_scripts/patch_invoices.py | 160 ++++ .../repopulate_company_gstin.py | 147 +++ .../clear_tax_import_format.py | 526 ++++------- .../report/rigpl_legacy_gstr1/__init__.py | 0 .../rigpl_legacy_gstr1/rigpl_legacy_gstr1.js | 79 ++ .../rigpl_legacy_gstr1.json | 38 + .../rigpl_legacy_gstr1/rigpl_legacy_gstr1.py | 873 ++++++++++++++++++ 14 files changed, 3323 insertions(+), 347 deletions(-) create mode 100644 rohit_common/core/contact.py create mode 100644 rohit_common/migration_scripts/combined_gst_fix.py create mode 100644 rohit_common/migration_scripts/create_gst_adjustment_jes.py create mode 100644 rohit_common/migration_scripts/create_purchase_gst_adjustment_jes.py create mode 100644 rohit_common/migration_scripts/fix_purchase_invoices_gst.py create mode 100644 rohit_common/migration_scripts/patch_invoices.py create mode 100644 rohit_common/migration_scripts/repopulate_company_gstin.py create mode 100644 rohit_common/rohit_common/report/rigpl_legacy_gstr1/__init__.py create mode 100644 rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.js create mode 100644 rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.json create mode 100644 rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.py diff --git a/rohit_common/__init__.py b/rohit_common/__init__.py index 98b6920..e877da3 100644 --- a/rohit_common/__init__.py +++ b/rohit_common/__init__.py @@ -13,6 +13,12 @@ frappe.frappe.core.doctype.file.file.has_permission=has_permission frappe.frappe.core.doctype.file.file.get_permission_query_conditions=get_permission_query_conditions + +import frappe.contacts.doctype.contact.contact as original_contact_module +from rohit_common.core.contact import custom_contact_query +original_contact_module.contact_query = custom_contact_query + + # Override for EInvoiceData.get_data # from india_compliance.gst_india.utils.e_invoice import EInvoiceData # from rohit_common.overrides.india_compliance_einvoice import custom_get_data diff --git a/rohit_common/core/contact.py b/rohit_common/core/contact.py new file mode 100644 index 0000000..79ebe6b --- /dev/null +++ b/rohit_common/core/contact.py @@ -0,0 +1,65 @@ +import frappe + + +@frappe.whitelist() +@frappe.validate_and_sanitize_search_inputs +def custom_contact_query(doctype, txt, searchfield, start, page_len, filters): + from frappe.desk.reportview import get_match_cond + + doctype = "Contact" + if not frappe.get_meta(doctype).get_field(searchfield) and searchfield not in frappe.db.DEFAULT_COLUMNS: + return [] + + link_doctype = filters.pop("link_doctype") + link_name = filters.pop("link_name") + + # --- START OF DYNAMIC CHANGES --- + + # 1. Get the "Contact" DocType's metadata + meta = frappe.get_meta("Contact") + + # 2. Get the 'search_fields' string (e.g., "first_name, last_name, email_id") + search_fields_string = meta.search_fields + + # 3. Create a list, falling back to 'name' and 'full_name' if empty + if search_fields_string: + search_fields_list = [field.strip() for field in search_fields_string.split(",")] + else: + search_fields_list = ["name", "full_name"] # default + + # 4. Clean the list: remove empty strings just in case (e.g., "field1,,field2") + search_fields_list = [f for f in search_fields_list if f] + + # 5. Build the OR conditions dynamically + search_conditions = " OR ".join( + [f"`tabContact`.`{field}` like %(txt)s" for field in search_fields_list] + ) + + # --- END OF DYNAMIC CHANGES --- + + return frappe.db.sql( + f"""select + `tabContact`.name, `tabContact`.full_name, `tabContact`.company_name, + `tabContact`.email_id, `tabContact`.phone, `tabContact`.mobile_no + from + `tabContact`, `tabDynamic Link` + where + `tabDynamic Link`.parent = `tabContact`.name and + `tabDynamic Link`.parenttype = 'Contact' and + `tabDynamic Link`.link_doctype = %(link_doctype)s and + `tabDynamic Link`.link_name = %(link_name)s and + ({search_conditions}) + {get_match_cond(doctype)} + order by + if(locate(%(_txt)s, `tabContact`.full_name), locate(%(_txt)s, `tabContact`.company_name), 99999), + `tabContact`.idx desc, `tabContact`.full_name + limit %(start)s, %(page_len)s """, + { + "txt": "%" + txt + "%", + "_txt": txt.replace("%", ""), + "start": start, + "page_len": page_len, + "link_name": link_name, + "link_doctype": link_doctype, + }, + ) \ No newline at end of file diff --git a/rohit_common/hooks.py b/rohit_common/hooks.py index 9903518..12d14de 100644 --- a/rohit_common/hooks.py +++ b/rohit_common/hooks.py @@ -38,7 +38,8 @@ override_whitelisted_methods = { # Below mentod would also take into account the search fields # mentioned in the Customize form view # "frappe.core.doctype.file.file.get_files_by_search_text": "rohit_common.core.file.get_files_by_search_text", - "frappe.core.api.file.get_files_by_search_text": "rohit_common.core.file.get_files_by_search_text" + "frappe.core.api.file.get_files_by_search_text": "rohit_common.core.file.get_files_by_search_text", + # "frappe.contacts.doctype.contact.contact.contact_query":"rohit_common.core.contact.custom_contact_query" } # Includes in diff --git a/rohit_common/migration_scripts/combined_gst_fix.py b/rohit_common/migration_scripts/combined_gst_fix.py new file mode 100644 index 0000000..9efc91b --- /dev/null +++ b/rohit_common/migration_scripts/combined_gst_fix.py @@ -0,0 +1,625 @@ +import frappe +import csv +import os +import json +import math +from typing import Optional +from frappe.utils import now_datetime, flt, get_datetime + +# === CONSTANTS === +SUM_TOLERANCE = 0.5 +AMOUNT_MATCH_TOLERANCE = 0.5 +GST_START_DATE = "2017-07-01" + +# ==================================================================== +# === PART 1: FILL 'gst_tax_type' IN SALES TAXES AND CHARGES +# ==================================================================== + +def _first_two_gstin_digits(gstin: Optional[str]) -> Optional[str]: + if not gstin: + return None + gstin = gstin.strip() + if len(gstin) >= 2 and gstin[:2].isdigit(): + return gstin[:2] + return None + +def _keyword_in(text, keywords): + if not text: + return None + t = text.lower() + for k in keywords: + if k.lower() in t: + return k.lower() + return None + +def infer_tax_type_from_row_v4(tax_row, invoice_doc, company_state_code): + """ + Return one of 'igst','cgst','sgst','cess' or None if couldn't infer. + (This is your original logic from the first prompt, which was best) + """ + acct = tax_row.get("account_head") or "" + # Priority 1: keywords in account_head or description + if _keyword_in(acct, ["IGST", "Integrated GST", "Integrated","Excise Duty 10 - RIGB","Sales - RIGB","Postal Expenses - RIGB"] ) : + return "igst" + if _keyword_in(acct, ["CGST", "Central GST", "Central","CST-CForm - RIGB"] ) : + return "cgst" + if _keyword_in(acct, ["SGST", "State GST", "State"] ) : + return "sgst" + if _keyword_in(acct, ["Cess", "Edu. Cess", "SHE Cess", "SBC Service Tax", "KKC Service Tax"] ) : + return "cess" + + # Priority 2: compare GSTIN state codes (invoice -> company) + invoice_state_code = None + for f in ("shipping_address_gstin", "customer_gstin", "billing_address_gstin"): + if invoice_doc.get(f): + invoice_state_code = _first_two_gstin_digits(invoice_doc.get(f)) + if invoice_state_code: + break + + if not invoice_state_code and invoice_doc.get("place_of_supply"): + pos = invoice_doc.get("place_of_supply") + if isinstance(pos, str) and len(pos) >= 2 and pos[:2].isdigit(): + invoice_state_code = pos[:2] + + if invoice_state_code and company_state_code: + if invoice_state_code != company_state_code: + return "igst" + else: + # same state -> likely CGST + SGST. + return None # Let sibling logic handle this. + + return None + +def choose_cgst_or_sgst_by_siblings(tax_rows, idx_missing): + """ + If some siblings have cgst/sgst, pick the complementary type if possible. + (Your original logic) + """ + types = set([r.get("gst_tax_type") for r in tax_rows if r.get("gst_tax_type")]) + if "cgst" in types and "sgst" not in types: + return "sgst" + if "sgst" in types and "cgst" not in types: + return "cgst" + # if neither or both present, cannot decide + return None + +def run_part_1_fill_gst_tax_type(dry_run=True, batch_size=200, limit=None, write_csv=True): + print("\n--- Running Part 1: Repopulating gst_tax_type in Sales Taxes and Charges ---") + frappe.flags.in_migrate = True + + writer = None + csv_file = None + csv_path = "" + + if write_csv: + timestamp = frappe.utils.now_datetime().strftime("%Y%m%d%H%M%S") + csv_path = f"/tmp/part1_gst_tax_type_{'dryrun' if dry_run else 'update'}_{timestamp}.csv" + os.makedirs("/tmp", exist_ok=True) + csv_file = open(csv_path, "w", newline="", encoding="utf-8") + writer = csv.DictWriter(csv_file, fieldnames=[ + "invoice", "tax_row_name", "account_head", "description", "rate", "inferred_gst_tax_type", "action", "reason" + ]) + writer.writeheader() + + limit_clause = f"LIMIT {int(limit)}" if limit else "" + + query = f""" + SELECT DISTINCT t.parent AS name + FROM `tabSales Taxes and Charges` t + JOIN `tabSales Invoice` si ON t.parent = si.name + WHERE IFNULL(t.gst_tax_type, '') = '' + AND t.parenttype = 'Sales Invoice' + AND si.posting_date >= %(gst_start_date)s + {limit_clause} + """ + + invoices = frappe.db.sql( + query, + {"gst_start_date": GST_START_DATE}, + as_dict=True, + ) + + invoice_names = [r["name"] for r in invoices] + total_invoices = len(invoice_names) + print(f"Found {total_invoices} Sales Invoice(s) *since {GST_START_DATE}* with missing gst_tax_type.") + + summary = { + "part": 1, + "total_invoices_found": total_invoices, + "rows_examined": 0, + "rows_updated": 0, + "rows_skipped_ambiguous": 0, + "errors": [], + "audit_csv": csv_path if write_csv else "Disabled" + } + + updated_count = 0 + processed_invoices = 0 + + for inv_name in invoice_names: + processed_invoices += 1 + try: + inv = frappe.get_doc("Sales Invoice", inv_name) + except Exception as e: + summary["errors"].append((inv_name, f"read invoice error: {e}")) + continue + + company_state_code = None + if inv.get("company_gstin"): + company_state_code = _first_two_gstin_digits(inv.get("company_gstin")) + else: + try: + comp = frappe.get_doc("Company", inv.get("company")) + if comp and comp.get("company_gstin"): + company_state_code = _first_two_gstin_digits(comp.get("company_gstin")) + except Exception: + company_state_code = None + + tax_rows = inv.get("taxes") or [] + + # We must process rows in order, allowing sibling logic to build up + invoice_rows_updated = 0 + invoice_rows_skipped = 0 + + for idx, tax_row in enumerate(tax_rows): + if tax_row.get("gst_tax_type"): + continue # already present + + summary["rows_examined"] += 1 + inferred = None + reason = "" + + # First try strong inference from account_head/description and place_of_supply/company state + inferred = infer_tax_type_from_row_v4(tax_row, inv.as_dict(), company_state_code) + + if inferred: + reason = "keyword_or_state_mismatch" + else: + # try sibling-based inference if same state (CGST+SGST situation) + sibling_choice = choose_cgst_or_sgst_by_siblings(tax_rows, idx) + if sibling_choice: + inferred = sibling_choice + reason = "sibling_complement" + else: + reason = "ambiguous" + + if inferred: + if write_csv and writer: + writer.writerow({ + "invoice": inv_name, "tax_row_name": tax_row.get("name"), "account_head": tax_row.get("account_head"), + "description": tax_row.get("description"), "rate": tax_row.get("rate"), + "inferred_gst_tax_type": inferred, "action": "would_set" if dry_run else "set", "reason": reason + }) + + if not dry_run: + try: + frappe.db.set_value("Sales Taxes and Charges", tax_row.get("name"), "gst_tax_type", inferred, update_modified=False) + updated_count += 1 + invoice_rows_updated += 1 + # *** CRITICAL: Update the doc in memory so sibling logic works *** + tax_row.gst_tax_type = inferred + except Exception as e: + summary["errors"].append((inv_name, tax_row.get("name"), f"update error: {e}")) + if write_csv and writer: + writer.writerow({"invoice": inv_name, "tax_row_name": tax_row.get("name"), "action": "error", "reason": str(e)}) + else: + # ambiguous - do not change + invoice_rows_skipped += 1 + if write_csv and writer: + writer.writerow({ + "invoice": inv_name, "tax_row_name": tax_row.get("name"), "account_head": tax_row.get("account_head"), + "description": tax_row.get("description"), "rate": tax_row.get("rate"), + "inferred_gst_tax_type": "", "action": "skipped", "reason": reason + }) + + summary["rows_skipped_ambiguous"] += invoice_rows_skipped + + if not dry_run and invoice_rows_updated > 0 and (processed_invoices % batch_size == 0): + frappe.db.commit() + + if not dry_run: + frappe.db.commit() + print("Part 1: Final commit done.") + + if csv_file: + csv_file.close() + + summary["rows_updated"] = updated_count + print(f"Part 1 Finished. Summary: {summary}") + return summary + + +# ==================================================================== +# === PART 2: RECONSTRUCT 'Sales Invoice Item' FROM 'item_wise_tax_detail' +# (This part is unchanged) +# ==================================================================== + +def _parse_item_wise_blob_v2(blob): + if not blob: + return {} + if isinstance(blob, dict): + data = blob + else: + try: + data = json.loads(blob) + except Exception: + return {} + out = {} + for key, val in data.items(): + if isinstance(val, dict): + out[key] = { + "tax_rate": float(val.get("tax_rate") or val.get("rate") or 0) if (val.get("tax_rate") or val.get("rate")) else None, + "tax_amount": float(val.get("tax_amount")) if val.get("tax_amount") not in (None, "") else None, + "net_amount": float(val.get("net_amount")) if val.get("net_amount") not in (None, "") else None, + } + else: + try: + out[key] = {"tax_rate": float(val), "tax_amount": None, "net_amount": None} + except Exception: + out[key] = {"tax_rate": None, "tax_amount": None, "net_amount": None} + return out + +def _find_best_item_v2(candidates, inferred_taxable_value, inferred_rate, tol_amount=AMOUNT_MATCH_TOLERANCE): + if not candidates: + return None + best = None + best_score = None + for it in candidates: + tv = flt(it.get("taxable_value") or it.get("amount") or 0) + nr = flt(it.get("net_rate") or it.get("rate") or 0) + if inferred_taxable_value: + diff = abs(tv - inferred_taxable_value) + if diff <= tol_amount: + return it + if inferred_rate and nr is not None: + diff_rate = abs(nr - inferred_rate) + if best_score is None or diff_rate < best_score: + best = it + best_score = diff_rate + return best or candidates[0] + +def _determine_target_fields_v2(gst_type): + gst_type = (gst_type or "").lower() + if gst_type == "igst": + return "igst_rate", "igst_amount" + if gst_type == "cgst": + return "cgst_rate", "cgst_amount" + if gst_type == "sgst": + return "sgst_rate", "sgst_amount" + if gst_type == "cess": + return "cess_rate", "cess_amount" + return None, None + +def run_part_2_reconstruct_item_taxes(dry_run=True, limit=None, batch_size=200, sum_tolerance=SUM_TOLERANCE, write_csv=True): + print("\n--- Running Part 2: Reconstructing Sales Invoice Item Taxes ---") + + limit_clause = f"LIMIT {int(limit)}" if limit else "" + + query = f""" + SELECT t.name, t.parent as invoice, t.gst_tax_type, t.rate, t.tax_amount, t.item_wise_tax_detail + FROM `tabSales Taxes and Charges` t + JOIN `tabSales Invoice` si ON t.parent = si.name + WHERE t.parenttype = 'Sales Invoice' + AND IFNULL(t.tax_amount,0) <> 0 + AND IFNULL(t.item_wise_tax_detail,'') <> '' + AND IFNULL(t.gst_tax_type,'') != '' + AND si.posting_date >= %(gst_start_date)s + {limit_clause} + """ + rows = frappe.db.sql( + query, + {"gst_start_date": GST_START_DATE}, + as_dict=True + ) + + total = len(rows) + print(f"Found {total} tax rows (since {GST_START_DATE}) with 'gst_tax_type' and 'item_wise_tax_detail' to process.") + if total == 0: + return {"part": 2, "rows_examined": 0, "notes": "No rows found. Did Part 1 run successfully?"} + + csv_path = "" + writer = None + + if write_csv: + os.makedirs("/tmp", exist_ok=True) + timestamp = frappe.utils.now_datetime().strftime('%Y%m%d%H%M%S') + csv_path = f"/tmp/part2_reconstruct_item_taxes_{'dryrun' if dry_run else 'update'}_{timestamp}.csv" + + summary = { + "part": 2, + "rows_examined": total, + "rows_updated": 0, + "errors": [], + "audit_csv": csv_path if write_csv else "Disabled" + } + + with open(csv_path, "w", newline='', encoding='utf-8') if write_csv else open(os.devnull, "w") as f: + if write_csv: + fieldnames = [ + "tax_row", "invoice", "tax_row_amount", "sum_itemwise", "row_status", + "item_key", "matched_item_name", "matched_item_code", + "tax_row_gst_type", "tax_row_rate", "inferred_taxable_value", "inferred_tax_amount", + "field_before", "field_after", "action", "notes" + ] + writer = csv.DictWriter(f, fieldnames=fieldnames) + writer.writeheader() + + updated = 0 + processed = 0 + + invoice_item_cache = {} + + def get_invoice_items(invoice_name): + if invoice_name not in invoice_item_cache: + try: + invoice_item_cache[invoice_name] = frappe.db.sql(""" + SELECT name, item_code, item_name, amount, taxable_value, rate, net_rate, idx, + igst_rate, igst_amount, cgst_rate, cgst_amount, + sgst_rate, sgst_amount, cess_rate, cess_amount + FROM `tabSales Invoice Item` + WHERE parent=%s + """, invoice_name, as_dict=True) + except Exception as e: + if write_csv and writer: writer.writerow({"tax_row": "N/A", "invoice": invoice_name, "row_status":"invoice_read_error", "notes":str(e)}) + summary['errors'].append((invoice_name, f"invoice_read_error: {e}")) + invoice_item_cache[invoice_name] = None + return invoice_item_cache[invoice_name] + + for r in rows: + processed += 1 + tax_row_name = r["name"] + invoice_name = r["invoice"] + gst_type = (r.get("gst_tax_type") or "").lower() + tax_row_rate = flt(r.get("rate") or 0) + tax_row_amount = flt(r.get("tax_amount") or 0) + blob = r.get("item_wise_tax_detail") or "" + parsed = _parse_item_wise_blob_v2(blob) + + sum_itemwise = 0.0 + has_item_amounts = False + for info in parsed.values(): + if info.get("tax_amount") not in (None, ""): + has_item_amounts = True + sum_itemwise += flt(info.get("tax_amount") or 0) + + # ----- STRATEGY 1: Blob has explicit tax_amount ----- + if has_item_amounts: + if abs(tax_row_amount - sum_itemwise) > sum_tolerance: + if write_csv and writer: writer.writerow({ + "tax_row": tax_row_name, "invoice": invoice_name, "tax_row_amount": tax_row_amount, + "sum_itemwise": sum_itemwise, "row_status": "mismatch_sum", + "notes": f"tax_row_amount != sum(item_wise) (diff {tax_row_amount - sum_itemwise})" + }) + continue + + inv_items = get_invoice_items(invoice_name) + if inv_items is None: continue + + item_index = {} + for it in inv_items: + keys = [str(it.get("name")).strip()] + if it.get("item_code"): keys.append(str(it.get("item_code")).strip()) + if it.get("item_name"): keys.append(str(it.get("item_name")).strip()) + if it.get("idx"): keys.append(str(int(flt(it.get("idx") or 0)))) + for k in keys: + if k: item_index.setdefault(k, []).append(it) + + for item_key, info in parsed.items(): + inferred_tax_amount = info.get("tax_amount") + inferred_rate = info.get("tax_rate") or tax_row_rate or None + inferred_taxable_value = info.get("net_amount") + + if not inferred_taxable_value and inferred_tax_amount is not None and inferred_rate: + try: + inferred_taxable_value = round((float(inferred_tax_amount) * 100.0) / float(inferred_rate), 6) + except Exception: pass + + candidates = item_index.get(str(item_key).strip(), [])[:] + if not candidates: + for k, lst in item_index.items(): + if str(item_key).strip().lower() in str(k).strip().lower(): + candidates.extend(lst) + + seen = set(); final_candidates = [c for c in candidates if c.get("name") not in seen and not seen.add(c.get("name"))] + candidates = final_candidates or inv_items[:] + + best_item = _find_best_item_v2(candidates, inferred_taxable_value, inferred_rate) + if not best_item: + if write_csv and writer: writer.writerow({"tax_row": tax_row_name, "invoice": invoice_name, "item_key": item_key, "row_status":"no_invoice_item_found"}) + continue + + target_rate_field, target_amount_field = _determine_target_fields_v2(gst_type) + if not target_rate_field: + if write_csv and writer: writer.writerow({"tax_row": tax_row_name, "invoice": invoice_name, "item_key": item_key, "row_status": "unknown_gst_type", "notes": gst_type}) + continue + + before_val = { + "taxable_value": flt(best_item.get("taxable_value") or 0), + target_rate_field: flt(best_item.get(target_rate_field) or 0), + target_amount_field: flt(best_item.get(target_amount_field) or 0) + } + + writes = {} + if (not before_val["taxable_value"]) and inferred_taxable_value: + writes["taxable_value"] = inferred_taxable_value + if (not before_val[target_rate_field]) and inferred_rate: + writes[target_rate_field] = inferred_rate + if (not before_val[target_amount_field]) and inferred_tax_amount is not None: + writes[target_amount_field] = round(float(inferred_tax_amount), 2) + + if writes: + if write_csv and writer: + for k, v in writes.items(): + writer.writerow({ + "tax_row": tax_row_name, "invoice": invoice_name, "row_status": "will_write", "item_key": item_key, + "matched_item_name": best_item.get("item_name"), "matched_item_code": best_item.get("item_code"), + "tax_row_gst_type": gst_type, "inferred_tax_amount": inferred_tax_amount, + "field_before": f"{k}:{before_val.get(k)}", "field_after": f"{k}:{v}", + "action": "would_set" if dry_run else "set" + }) + if not dry_run: + try: + frappe.db.set_value("Sales Invoice Item", best_item.get("name"), writes, update_modified=False) + updated += 1 + except Exception as e: + if write_csv and writer: writer.writerow({"tax_row": tax_row_name, "invoice": invoice_name, "row_status": "write_error", "item_key": item_key, "notes": str(e)}) + summary['errors'].append((invoice_name, best_item.get("name"), f"write_error: {e}")) + + # ----- STRATEGY 2: Blob has NO explicit tax_amount (rate-only) ----- + else: + inv_items = get_invoice_items(invoice_name) + if inv_items is None: continue + + item_index = {} + for it in inv_items: + keys = [str(it.get("name")).strip()] + if it.get("item_code"): keys.append(str(it.get("item_code")).strip()) + if it.get("item_name"): keys.append(str(it.get("item_name")).strip()) + if it.get("idx"): keys.append(str(int(flt(it.get("idx") or 0)))) + for k in keys: + if k: item_index.setdefault(k, []).append(it) + + inferred_rows = [] + sum_inferred = 0.0 + for item_key, info in parsed.items(): + rate_only = info.get("tax_rate") + if not rate_only or rate_only == 0: continue + + candidates = item_index.get(str(item_key).strip(), [])[:] + if not candidates: + for k, lst in item_index.items(): + if str(item_key).strip().lower() in str(k).strip().lower(): + candidates.extend(lst) + + seen = set(); final_candidates = [c for c in candidates if c.get("name") not in seen and not seen.add(c.get("name"))] + candidates = final_candidates or inv_items[:] + + best_item = _find_best_item_v2(candidates, None, rate_only) + if not best_item: continue + + tv = flt(best_item.get("taxable_value") or 0) + if not tv: tv = flt(best_item.get("amount") or 0) + if not tv or tv == 0: continue + + inferred_tax_amount = round((tv * float(rate_only) / 100.0), 2) + inferred_rows.append((best_item, rate_only, tv, inferred_tax_amount, item_key)) + sum_inferred += inferred_tax_amount + + if not inferred_rows: + if write_csv and writer: writer.writerow({"tax_row": tax_row_name, "invoice": invoice_name, "row_status": "no_inference_possible"}) + continue + + if abs(sum_inferred - tax_row_amount) > sum_tolerance: + if write_csv and writer: writer.writerow({ + "tax_row": tax_row_name, "invoice": invoice_name, "tax_row_amount": tax_row_amount, + "sum_itemwise": sum_inferred, "row_status": "mismatch_inferred", + "notes": f"sum inferred ({sum_inferred}) != tax_row_amount (diff {tax_row_amount - sum_inferred})" + }) + continue + + # Sums match! Apply inferred writes + for best_item, rate_used, tv, inferred_tax_amount, item_key in inferred_rows: + target_rate_field, target_amount_field = _determine_target_fields_v2(gst_type) + if not target_rate_field: continue + + before_val = { + "taxable_value": flt(best_item.get("taxable_value") or 0), + target_rate_field: flt(best_item.get(target_rate_field) or 0), + target_amount_field: flt(best_item.get(target_amount_field) or 0) + } + + writes = {} + if (not before_val["taxable_value"]) and tv: + writes["taxable_value"] = tv + if (not before_val[target_rate_field]) and rate_used: + writes[target_rate_field] = rate_used + if (not before_val[target_amount_field]) and inferred_tax_amount is not None: + writes[target_amount_field] = inferred_tax_amount + + if writes: + if write_csv and writer: + for k, v in writes.items(): + writer.writerow({ + "tax_row": tax_row_name, "invoice": invoice_name, "row_status": "will_write_inferred", "item_key": item_key, + "matched_item_name": best_item.get("item_name"), "matched_item_code": best_item.get("item_code"), + "tax_row_gst_type": gst_type, "inferred_tax_amount": inferred_tax_amount, + "field_before": f"{k}:{before_val.get(k)}", "field_after": f"{k}:{v}", + "action": "would_set" if dry_run else "set" + }) + if not dry_run: + try: + frappe.db.set_value("Sales Invoice Item", best_item.get("name"), writes, update_modified=False) + updated += 1 + except Exception as e: + if write_csv and writer: writer.writerow({"tax_row": tax_row_name, "invoice": invoice_name, "row_status": "write_error", "item_key": item_key, "notes": str(e)}) + summary['errors'].append((invoice_name, best_item.get("name"), f"write_error: {e}")) + + if not dry_run and (updated and updated % batch_size == 0): + frappe.db.commit() + if processed % (batch_size * 5) == 0: + print(f" ... Part 2 processing: {processed}/{total} tax rows processed, {updated} items updated.") + + + # end for rows + if not dry_run: + frappe.db.commit() + print("Part 2: Final commit done.") + + summary['rows_updated'] = updated if not dry_run else 0 + print(f"Part 2 Finished. Summary: {summary}") + return summary + + +# ==================================================================== +# === MAIN EXECUTE FUNCTION +# ==================================================================== + +def execute(dry_run=True, batch_size=200, limit=None, sum_tolerance=SUM_TOLERANCE, write_csv=True): + """ + Main execution function to fix GST data. + """ + dry_run = bool(dry_run) + batch_size = int(batch_size) if batch_size else 200 + limit = int(limit) if limit else None + sum_tolerance = float(sum_tolerance) if sum_tolerance else SUM_TOLERANCE + write_csv = bool(write_csv) + + print(f"*** STARTING GST DATA RECONSTRUCTION (V4) ***") + print(f"*** {'DRY RUN' if dry_run else 'APPLYING CHANGES'} ***") + print(f"*** Limit: {limit}, Batch Size: {batch_size}, Tolerance: {sum_tolerance}, Write CSV: {write_csv} ***") + print(f"*** (Note: Processing is limited to invoices on or after {GST_START_DATE}) ***") + + summary1 = {} + summary2 = {} + + # --- Part 1 --- + try: + summary1 = run_part_1_fill_gst_tax_type(dry_run=dry_run, batch_size=batch_size, limit=limit, write_csv=write_csv) + print("\n=== Part 1 Summary ===") + print(json.dumps(summary1, indent=2, default=str)) + except Exception as e: + print(f"\n*** ERROR in Part 1 (fill_gst_tax_type): {e} ***") + frappe.log_error(title="GST Fix Script Part 1 Failed") + frappe.db.rollback() + return {"error": "Part 1 Failed", "details": str(e)} + + # --- Part 2 --- + try: + summary2 = run_part_2_reconstruct_item_taxes(dry_run=dry_run, limit=limit, batch_size=batch_size, sum_tolerance=sum_tolerance, write_csv=write_csv) + print("\n=== Part 2 Summary ===") + print(json.dumps(summary2, indent=2, default=str)) + except Exception as e: + print(f"\n*** ERROR in Part 2 (reconstruct_item_taxes): {e} ***") + frappe.log_error(title="GST Fix Script Part 2 Failed") + frappe.db.rollback() + return {"error": "Part 2 Failed", "details": str(e)} + + if dry_run: + print("\n*** DRY RUN COMPLETE. No changes were made. Rolling back. ***") + frappe.db.rollback() + else: + print("\n*** ALL PARTS COMPLETE. Final commit issued. ***") + frappe.db.commit() + + print("\n--- SCRIPT FINISHED ---") + return {"part1_summary": summary1, "part2_summary": summary2} \ No newline at end of file diff --git a/rohit_common/migration_scripts/create_gst_adjustment_jes.py b/rohit_common/migration_scripts/create_gst_adjustment_jes.py new file mode 100644 index 0000000..54926c7 --- /dev/null +++ b/rohit_common/migration_scripts/create_gst_adjustment_jes.py @@ -0,0 +1,290 @@ +# rohit_common/utils/create_gst_adjustment_jes.py +import frappe +import json +from frappe.utils import flt, nowdate, get_last_day, getdate +from datetime import datetime +from dateutil.relativedelta import relativedelta + +# Import the function from India Compliance to read GL totals +try: + from india_compliance.gst_india.doctype.gstr_1.gstr_1 import get_net_gst_liability + from india_compliance.gst_india.utils import get_gst_accounts_by_type +except ImportError: + print("="*40) + print("ERROR: Could not import 'india_compliance'.") + print("Please ensure the 'india_compliance' app is installed.") + print("="*40) + raise + +GST_START_DATE = "2017-07-01" + +def _get_correct_totals(from_date, to_date): + """ + Calculates the correct, final GST totals for a given period + by summing the data in the (now fixed) Sales Invoice Item table. + """ + query = """ + SELECT + SUM(sii.taxable_value) as total_taxable_value, + SUM(sii.igst_amount) as total_igst, + SUM(sii.cgst_amount) as total_cgst, + SUM(sii.sgst_amount) as total_sgst, + SUM(sii.cess_amount) as total_cess + FROM + `tabSales Invoice Item` sii + JOIN + `tabSales Invoice` si ON sii.parent = si.name + WHERE + si.docstatus = 1 + AND si.posting_date BETWEEN %(from_date)s AND %(to_date)s + """ + + result = frappe.db.sql(query, {"from_date": from_date, "to_date": to_date}, as_dict=True) + + if not result or not result[0]: + return {} + + summary = result[0] + return { + "total_igst_amount": flt(summary.get('total_igst')), + "total_cgst_amount": flt(summary.get('total_cgst')), + "total_sgst_amount": flt(summary.get('total_sgst')), + "total_cess_amount": flt(summary.get('total_cess')), + } + +def _get_gl_totals(company, company_gstin, month, year, filing_preference="Monthly"): + """ + Gets the *wrong* totals currently in the General Ledger. + This uses the exact same function as the GSTR-1 report. + """ + try: + # Note: This function reads from `tabGL Entry` + totals = get_net_gst_liability( + company=company, + company_gstin=company_gstin, + month_or_quarter=month, + year=year, + filing_preference=filing_preference + ) + return totals + except Exception as e: + print(f" Error getting GL totals for {month}-{year}: {e}") + return {} + +def create_adjustment_je(company, company_gstin, posting_date, diff_totals, sales_account, gst_accounts, dry_run=True): + """ + Creates and submits the adjustment Journal Entry. + """ + total_adjustment = sum(diff_totals.values()) + + if abs(total_adjustment) < 0.01: + print(f" Skipping {posting_date}: No adjustment needed.") + return None + + # Get default cost center + default_cost_center = frappe.db.get_value("Company", company, "cost_center") + if not default_cost_center: + print(f" WARNING: No default Cost Center found for company {company}. JEs might fail if Cost Center is mandatory.") + # Fallback just in case + default_cost_center = "Main - " + frappe.db.get_value("Company", company, "abbr") + + + je_doc = { + "doctype": "Journal Entry", + "company": company, + "company_gstin": company_gstin, + "posting_date": posting_date, + "voucher_type": "Journal Entry", + "user_remark": f"Automated GST adjustment for migrated invoices, period {posting_date.strftime('%b-%Y')}", + "accounts": [] + } + + # 1. Debit the Sales account + je_doc["accounts"].append({ + "account": sales_account, + "debit_in_account_currency": flt(total_adjustment, 2), + "credit_in_account_currency": 0, + "cost_center": default_cost_center + }) + + # 2. Credit the individual tax accounts + if diff_totals["total_igst_amount"] > 0.01: + je_doc["accounts"].append({ + "account": gst_accounts["igst_account"], + "debit_in_account_currency": 0, + "credit_in_account_currency": flt(diff_totals["total_igst_amount"], 2), + "cost_center": default_cost_center + }) + + if diff_totals["total_cgst_amount"] > 0.01: + je_doc["accounts"].append({ + "account": gst_accounts["cgst_account"], + "debit_in_account_currency": 0, + "credit_in_account_currency": flt(diff_totals["total_cgst_amount"], 2), + "cost_center": default_cost_center + }) + + if diff_totals["total_sgst_amount"] > 0.01: + je_doc["accounts"].append({ + "account": gst_accounts["sgst_account"], + "debit_in_account_currency": 0, + "credit_in_account_currency": flt(diff_totals["total_sgst_amount"], 2), + "cost_center": default_cost_center + }) + + if diff_totals["total_cess_amount"] > 0.01: + cess_acct = gst_accounts.get("cess_account") or gst_accounts.get("cess_non_advol_account") + if not cess_acct: + print(f" WARNING: No CESS account found in GST Accounts. Skipping CESS amount {diff_totals['total_cess_amount']}") + else: + je_doc["accounts"].append({ + "account": cess_acct, + "debit_in_account_currency": 0, + "credit_in_account_currency": flt(diff_totals["total_cess_amount"], 2), + "cost_center": default_cost_center + }) + + print(f" Period {posting_date.strftime('%b-%Y')}: Total Adjustment: {flt(total_adjustment, 2)}") + + if dry_run: + print(f" [DRY RUN] Would create JE with {len(je_doc['accounts'])} lines.") + return None + + try: + je = frappe.get_doc(je_doc) + je.insert() + je.submit() + print(f" SUCCESS: Created and Submitted JE {je.name} for {posting_date.strftime('%b-%Y')}") + return je.name + except Exception as e: + print(f" ERROR creating JE for {posting_date.strftime('%b-%Y')}: {e}") + frappe.log_error(title="GST Adjustment JE Failed") + return None + + +def execute(company, company_gstin, dry_run=True, default_sales_account=None): + """ + Main execution function. + + :param company: Your Company name, e.g., "Rohit Industries Group Private Ltd" + :param company_gstin: Your Company GSTIN, e.g., "06AAACR1567J1ZC" + :param dry_run: If True, no JEs will be created. + :param default_sales_account: (Optional) Specify your main Income/Sales account. + If None, the script will try to guess it. + """ + dry_run = bool(dry_run) + print(f"*** STARTING GST ADJUSTMENT JOURNAL ENTRY CREATION (V3) ***") + print(f"*** {'DRY RUN' if dry_run else 'APPLYING CHANGES'} ***") + print(f"*** Company: {company} | GSTIN: {company_gstin} ***") + + # --- Find Accounts --- + try: + gst_accounts = get_gst_accounts_by_type(company, "Output") + if not gst_accounts.get("igst_account") or not gst_accounts.get("cgst_account"): + print(f"ERROR: Could not find GST Output accounts for Company '{company}'. Check your Chart of Accounts.") + return + except Exception as e: + print(f"ERROR: Failed to get GST accounts. Is 'india_compliance' app installed correctly? {e}") + return + + if default_sales_account: + sales_account = default_sales_account + else: + sales_account = None + sales_account_query = f""" + SELECT income_account + FROM `tabSales Invoice Item` sii + JOIN `tabSales Invoice` si ON sii.parent = si.name + WHERE si.posting_date >= '{GST_START_DATE}' + AND si.company = %(company)s + AND sii.income_account IS NOT NULL + AND sii.income_account != '' + GROUP BY income_account + ORDER BY COUNT(*) DESC + LIMIT 1 + """ + sales_account_result = frappe.db.sql(sales_account_query, {"company": company}) + if sales_account_result and sales_account_result[0]: + sales_account = sales_account_result[0][0] + + if not sales_account: + print(f"ERROR: Could not guess 'default_sales_account'. Please pass it as an argument.") + print("Example: --kwargs \"{'company': 'My Company', ..., 'default_sales_account': 'Sales - RIGB'}\"") + return + + print(f"Using Income Account: {sales_account}") + print(f"Using Tax Accounts: IGST:{gst_accounts.get('igst_account')}, CGST:{gst_accounts.get('cgst_account')}, ...") + print("---") + + # --- Loop through all periods --- + start_date = datetime.strptime(GST_START_DATE, "%Y-%m-%d").date() + + end_date = getdate(nowdate()) # Convert string from nowdate() to a date object + + current_date = start_date + + while current_date <= end_date: + month_name = current_date.strftime("%B") + year = current_date.strftime("%Y") + period_start = current_date + period_end = get_last_day(current_date) + + # Don't process the current, incomplete month. Stop at the beginning of this month. + if current_date.year == end_date.year and current_date.month == end_date.month: + print(f"Skipping current month ({month_name} {year}) as it is not yet complete.") + break + + print(f"Processing Period: {month_name} {year} ({period_start} to {period_end})") + + # 1. Get Correct totals from fixed Sales Invoice Items + correct_totals = _get_correct_totals(period_start, period_end) + + # 2. Get Wrong totals from General Ledger + wrong_totals = _get_gl_totals(company, company_gstin, month_name, year) + + if not correct_totals and (not wrong_totals or sum(wrong_totals.values()) == 0): + print(" No data found in Items or GL. Skipping.") + current_date = current_date + relativedelta(months=1) + continue + + # 3. Calculate the difference + diff_totals = { + "total_igst_amount": flt(correct_totals.get("total_igst_amount")) - flt(wrong_totals.get("total_igst_amount")), + "total_cgst_amount": flt(correct_totals.get("total_cgst_amount")) - flt(wrong_totals.get("total_cgst_amount")), + "total_sgst_amount": flt(correct_totals.get("total_sgst_amount")) - flt(wrong_totals.get("total_sgst_amount")), + "total_cess_amount": flt(correct_totals.get("total_cess_amount")) - flt(wrong_totals.get("total_cess_amount")), + } + + # 4. Create the JE + create_adjustment_je( + company=company, + company_gstin=company_gstin, + posting_date=period_end, # Post on the last day of the month + diff_totals=diff_totals, + sales_account=sales_account, + gst_accounts=gst_accounts, + dry_run=dry_run + ) + + # Move to the next month + current_date = current_date + relativedelta(months=1) + + print("\n--- SCRIPT FINISHED ---") + +# bench --site development.localhost execute rohit_common.migration_scripts.create_gst_adjustment_jes.execute \ +# --kwargs "{ \ +# 'company': 'Rohit Industries Group Private Ltd', \ +# 'company_gstin': '06AAACR1567J1ZC', \ +# 'dry_run': True \ +# }" + + +# bench --site development.localhost execute rohit_common.migration_scripts.create_gst_adjustment_jes.execute \ +# --kwargs "{ \ +# 'company': 'Rohit Industries Group Private Ltd', \ +# 'company_gstin': '06AAACR1567J1ZC', \ +# 'dry_run': False \ +# }" + +# before running enable all fiscal year and acc_frozen_upto from account settings +# manually cancel all period closing voucher and after completing the script submit them again \ No newline at end of file diff --git a/rohit_common/migration_scripts/create_purchase_gst_adjustment_jes.py b/rohit_common/migration_scripts/create_purchase_gst_adjustment_jes.py new file mode 100644 index 0000000..fae854e --- /dev/null +++ b/rohit_common/migration_scripts/create_purchase_gst_adjustment_jes.py @@ -0,0 +1,308 @@ +import frappe +import json +from frappe.utils import flt, nowdate, get_last_day, getdate +from datetime import datetime +from dateutil.relativedelta import relativedelta + +try: + from frappe.query_builder.functions import Sum, Date +except ImportError: + # Fallback for very old versions (less likely) + from pypika.functions import Sum + from pypika.terms import Date + +# Import the function from India Compliance +try: + from india_compliance.gst_india.utils import get_gst_accounts_by_type, get_period + # We need MONTHS from the utils + from india_compliance.gst_india.utils import MONTHS +except ImportError: + print("="*40) + print("ERROR: Could not import 'india_compliance'.") + print("Please ensure the 'india_compliance' app is installed.") + print("="*40) + raise + +GST_START_DATE = "2017-07-01" + +def _get_correct_purchase_totals(from_date, to_date): + """ + Calculates the correct, final INPUT GST totals for a given period + by summing the data in the (now fixed) Purchase Invoice Item table. + """ + query = """ + SELECT + SUM(pii.taxable_value) as total_taxable_value, + SUM(pii.igst_amount) as total_igst, + SUM(pii.cgst_amount) as total_cgst, + SUM(pii.sgst_amount) as total_sgst, + SUM(pii.cess_amount) as total_cess + FROM + `tabPurchase Invoice Item` pii + JOIN + `tabPurchase Invoice` pi ON pii.parent = pi.name + WHERE + pi.docstatus = 1 + AND pi.posting_date BETWEEN %(from_date)s AND %(to_date)s + """ + + result = frappe.db.sql(query, {"from_date": from_date, "to_date": to_date}, as_dict=True) + + if not result or not result[0]: + return {} + + summary = result[0] + return { + "total_igst_amount": flt(summary.get('total_igst')), + "total_cgst_amount": flt(summary.get('total_cgst')), + "total_sgst_amount": flt(summary.get('total_sgst')), + "total_cess_amount": flt(summary.get('total_cess')), + } + +def _get_gl_input_totals(company, company_gstin, from_date, to_date): + """ + Gets the *wrong* INPUT totals currently in the General Ledger. + This is a correct implementation using the query builder functions. + """ + try: + # 1. Get the "Input" GST Accounts + accounts = get_gst_accounts_by_type(company, "Input") + + # 2. Query the GL Entry table for those accounts + gl_entry = frappe.qb.DocType("GL Entry") + gst_ledger = frappe._dict( + frappe.qb.from_(gl_entry) + .select(gl_entry.account, (Sum(gl_entry.debit) - Sum(gl_entry.credit))) # Input tax is a DEBIT + .where(gl_entry.account.isin(list(accounts.values()))) + .where(gl_entry.company == company) + .where(Date(gl_entry.posting_date) >= getdate(from_date)) + .where(Date(gl_entry.posting_date) <= getdate(to_date)) + .where(gl_entry.company_gstin == company_gstin) + .groupby(gl_entry.account) + .run() + ) + + net_input_balance = { + "total_igst_amount": gst_ledger.get(accounts.get("igst_account"), 0), + "total_cgst_amount": gst_ledger.get(accounts.get("cgst_account"), 0), + "total_sgst_amount": gst_ledger.get(accounts.get("sgst_account"), 0), + "total_cess_amount": gst_ledger.get(accounts.get("cess_account"), 0) + + gst_ledger.get(accounts.get("cess_non_advol_account"), 0), + } + return net_input_balance + + except Exception as e: + print(f" Error getting GL totals for period {from_date}: {e}") + return {} + +def create_adjustment_je(company, company_gstin, posting_date, diff_totals, expense_account, gst_accounts, dry_run=True): + """ + Creates and submits the adjustment Journal Entry for Input Tax. + """ + total_adjustment = sum(diff_totals.values()) + + if abs(total_adjustment) < 0.01: + print(f" Skipping {posting_date}: No adjustment needed.") + return None + + default_cost_center = frappe.db.get_value("Company", company, "cost_center") + if not default_cost_center: + print(f" WARNING: No default Cost Center found for company {company}. JEs might fail if Cost Center is mandatory.") + default_cost_center = "Main - " + frappe.db.get_value("Company", company, "abbr") + + + je_doc = { + "doctype": "Journal Entry", + "company": company, + "company_gstin": company_gstin, + "posting_date": posting_date, + "voucher_type": "Journal Entry", + "user_remark": f"Automated GST Input Tax adjustment for migrated invoices, period {posting_date.strftime('%b-%Y')}", + "accounts": [] + } + + # 1. Debit the individual tax accounts + if diff_totals["total_igst_amount"] > 0.01: + je_doc["accounts"].append({ + "account": gst_accounts["igst_account"], + "debit_in_account_currency": flt(diff_totals["total_igst_amount"], 2), + "credit_in_account_currency": 0, + "cost_center": default_cost_center + }) + + if diff_totals["total_cgst_amount"] > 0.01: + je_doc["accounts"].append({ + "account": gst_accounts["cgst_account"], + "debit_in_account_currency": flt(diff_totals["total_cgst_amount"], 2), + "credit_in_account_currency": 0, + "cost_center": default_cost_center + }) + + if diff_totals["total_sgst_amount"] > 0.01: + je_doc["accounts"].append({ + "account": gst_accounts["sgst_account"], + "debit_in_account_currency": flt(diff_totals["total_sgst_amount"], 2), + "credit_in_account_currency": 0, + "cost_center": default_cost_center + }) + + if diff_totals["total_cess_amount"] > 0.01: + cess_acct = gst_accounts.get("cess_account") or gst_accounts.get("cess_non_advol_account") + if not cess_acct: + print(f" WARNING: No CESS account found in GST Accounts. Skipping CESS amount {diff_totals['total_cess_amount']}") + else: + je_doc["accounts"].append({ + "account": cess_acct, + "debit_in_account_currency": flt(diff_totals["total_cess_amount"], 2), + "credit_in_account_currency": 0, + "cost_center": default_cost_center + }) + + # 2. Credit the main Expense account + je_doc["accounts"].append({ + "account": expense_account, + "debit_in_account_currency": 0, + "credit_in_account_currency": flt(total_adjustment, 2), + "cost_center": default_cost_center + }) + + print(f" Period {posting_date.strftime('%b-%Y')}: Total Input Tax Adjustment: {flt(total_adjustment, 2)}") + + if dry_run: + print(f" [DRY RUN] Would create JE with {len(je_doc['accounts'])} lines.") + return None + + try: + je = frappe.get_doc(je_doc) + je.insert() + je.submit() + print(f" SUCCESS: Created and Submitted JE {je.name} for {posting_date.strftime('%b-%Y')}") + return je.name + except Exception as e: + print(f" ERROR creating JE for {posting_date.strftime('%b-%Y')}: {e}") + frappe.log_error(title="GST Input Tax Adjustment JE Failed") + return None + + +def execute(company, company_gstin, dry_run=True, default_expense_account=None): + """ + Main execution function. + """ + dry_run = bool(dry_run) + print(f"*** STARTING GST INPUT TAX ADJUSTMENT JOURNAL ENTRY CREATION (V2 - Rerunnable) ***") + print(f"*** {'DRY RUN' if dry_run else 'APPLYING CHANGES'} ***") + print(f"*** Company: {company} | GSTIN: {company_gstin} ***") + + # --- Find Accounts --- + try: + gst_accounts = get_gst_accounts_by_type(company, "Input") + if not gst_accounts.get("igst_account") or not gst_accounts.get("cgst_account"): + print(f"ERROR: Could not find GST Input accounts for Company '{company}'. Check your Chart of Accounts.") + return + except Exception as e: + print(f"ERROR: Failed to get GST accounts. Is 'india_compliance' app installed correctly? {e}") + return + + if default_expense_account: + expense_account = default_expense_account + else: + expense_account = None + expense_account_query = f""" + SELECT expense_account + FROM `tabPurchase Invoice Item` pii + JOIN `tabPurchase Invoice` pi ON pii.parent = pi.name + WHERE pi.posting_date >= '{GST_START_DATE}' + AND pi.company = %(company)s + AND pii.expense_account IS NOT NULL + AND pii.expense_account != '' + GROUP BY expense_account + ORDER BY COUNT(*) DESC + LIMIT 1 + """ + expense_account_result = frappe.db.sql(expense_account_query, {"company": company}) + if expense_account_result and expense_account_result[0]: + expense_account = expense_account_result[0][0] + + if not expense_account: + print(f"ERROR: Could not guess 'default_expense_account'. Please pass it as an argument.") + print("Example: --kwargs \"{'company': 'My Company', ..., 'default_expense_account': 'Expenses Included In Valuation'}\"") + return + + print(f"Using fallback Expense Account: {expense_account}") + print(f"Using Tax Accounts: IGST:{gst_accounts.get('igst_account')}, CGST:{gst_accounts.get('cgst_account')}, ...") + print("---") + + # --- Loop through all periods --- + start_date = datetime.strptime(GST_START_DATE, "%Y-%m-%d").date() + end_date = getdate(nowdate()) + + current_date = start_date + + while current_date <= end_date: + month_name = current_date.strftime("%B") + year = current_date.strftime("%Y") + period_start = current_date + period_end = get_last_day(current_date) + + if current_date.year == end_date.year and current_date.month == end_date.month: + print(f"Skipping current month ({month_name} {year}) as it is not yet complete.") + break + + print(f"Processing Period: {month_name} {year} ({period_start} to {period_end})") + + remark_search = f"Automated GST Input Tax adjustment for migrated invoices, period {period_end.strftime('%b-%Y')}" + je_exists = frappe.db.exists("Journal Entry", { + "posting_date": period_end, + "user_remark": ["like", f"%{remark_search}%"], + "docstatus": 1 + }) + + if je_exists: + print(f" Skipping {month_name} {year}: Adjustment JE {je_exists} already exists.") + current_date = current_date + relativedelta(months=1) + continue + + correct_totals = _get_correct_purchase_totals(period_start, period_end) + + wrong_totals = _get_gl_input_totals(company, company_gstin, period_start, period_end) + + if not correct_totals and (not wrong_totals or sum(wrong_totals.values()) == 0): + print(" No data found in Items or GL. Skipping.") + current_date = current_date + relativedelta(months=1) + continue + + diff_totals = { + "total_igst_amount": flt(correct_totals.get("total_igst_amount")) - flt(wrong_totals.get("total_igst_amount")), + "total_cgst_amount": flt(correct_totals.get("total_cgst_amount")) - flt(wrong_totals.get("total_cgst_amount")), + "total_sgst_amount": flt(correct_totals.get("total_sgst_amount")) - flt(wrong_totals.get("total_sgst_amount")), + "total_cess_amount": flt(correct_totals.get("total_cess_amount")) - flt(wrong_totals.get("total_cess_amount")), + } + + create_adjustment_je( + company=company, + company_gstin=company_gstin, + posting_date=period_end, + diff_totals=diff_totals, + expense_account=expense_account, + gst_accounts=gst_accounts, + dry_run=dry_run + ) + + current_date = current_date + relativedelta(months=1) + + print("\n--- SCRIPT FINISHED ---") + + +# bench --site development.localhost execute rohit_common.migration_scripts.create_purchase_gst_adjustment_jes.execute \ +# --kwargs "{ \ +# 'company': 'Rohit Industries Group Private Ltd', \ +# 'company_gstin': '06AAACR1567J1ZC', \ +# 'dry_run': True \ +# }" + +# bench --site development.localhost execute rohit_common.migration_scripts.create_purchase_gst_adjustment_jes.execute \ +# --kwargs "{ \ +# 'company': 'Rohit Industries Group Private Ltd', \ +# 'company_gstin': '06AAACR1567J1ZC', \ +# 'dry_run': False \ +# }" \ No newline at end of file diff --git a/rohit_common/migration_scripts/fix_purchase_invoices_gst.py b/rohit_common/migration_scripts/fix_purchase_invoices_gst.py new file mode 100644 index 0000000..140c223 --- /dev/null +++ b/rohit_common/migration_scripts/fix_purchase_invoices_gst.py @@ -0,0 +1,550 @@ +import frappe +import csv +import os +import json +import math +from typing import Optional +from frappe.utils import now_datetime, flt, get_datetime + +# === CONSTANTS === +SUM_TOLERANCE = 0.5 +AMOUNT_MATCH_TOLERANCE = 0.5 +GST_START_DATE = "2017-07-01" +# These are the non-tax accounts we found in your data +NON_TAX_ACCOUNTS = [ + "Discount & Rebates - RIGB", + "Insurance Expenses - RIGB", + "International Courier Charged - RIGB", + "Freight & Forwarding Charges - RIGB" +] + +# === DOCTYPE MAPPING === +BASE_DOCTYPE = "Purchase Invoice" +CHILD_DOCTYPE = "Purchase Invoice Item" +TAX_CHILD_DOCTYPE = "Purchase Taxes and Charges" + +# ==================================================================== +# === PART 1: FILL 'gst_tax_type' IN PURCHASE TAXES AND CHARGES +# ==================================================================== + +def _first_two_gstin_digits(gstin: Optional[str]) -> Optional[str]: + if not gstin: + return None + gstin = gstin.strip() + if len(gstin) >= 2 and gstin[:2].isdigit(): + return gstin[:2] + return None + +def _keyword_in(text, keywords): + if not text: + return None + t = text.lower() + for k in keywords: + if k.lower() in t: + return k.lower() + return None + +def infer_tax_type_from_row(tax_row, invoice_doc, company_state_code): + """ + Return one of 'igst','cgst','sgst','cess' or None if couldn't infer. + """ + acct = tax_row.get("account_head") or "" + # Priority 1: keywords in account_head or description + if _keyword_in(acct, ["IGST", "Integrated GST", "Integrated"] ) : + return "igst" + if _keyword_in(acct, ["CGST", "Central GST", "Central"] ) : + return "cgst" + if _keyword_in(acct, ["SGST", "State GST", "State"] ) : + return "sgst" + if _keyword_in(acct, ["Cess", "Edu. Cess", "SHE Cess", "SBC Service Tax", "KKC Service Tax"] ) : + return "cess" + + # Priority 2: compare GSTIN state codes (invoice -> company) + # For Purchase, we compare supplier_gstin to company_gstin (place_of_supply) + invoice_state_code = None + if invoice_doc.get("supplier_gstin"): + invoice_state_code = _first_two_gstin_digits(invoice_doc.get("supplier_gstin")) + + if not invoice_state_code and invoice_doc.get("place_of_supply"): + pos = invoice_doc.get("place_of_supply") + if isinstance(pos, str) and len(pos) >= 2 and pos[:2].isdigit(): + invoice_state_code = pos[:2] + + if invoice_state_code and company_state_code: + if invoice_state_code != company_state_code: + return "igst" + else: + # same state -> likely CGST + SGST. + return None # Let sibling logic handle this. + + return None + +def choose_cgst_or_sgst_by_siblings(tax_rows, idx_missing): + """ + If some siblings have cgst/sgst, pick the complementary type if possible. + """ + types = set([r.get("gst_tax_type") for r in tax_rows if r.get("gst_tax_type")]) + if "cgst" in types and "sgst" not in types: + return "sgst" + if "sgst" in types and "cgst" not in types: + return "cgst" + return None + +def run_part_1_fill_gst_tax_type(dry_run=True, batch_size=200, limit=None): + print(f"\n--- Running Part 1: Repopulating gst_tax_type in {TAX_CHILD_DOCTYPE} ---") + frappe.flags.in_migrate = True + + limit_clause = f"LIMIT {int(limit)}" if limit else "" + + query = f""" + SELECT DISTINCT t.parent AS name + FROM `tab{TAX_CHILD_DOCTYPE}` t + JOIN `tab{BASE_DOCTYPE}` pi ON t.parent = pi.name + WHERE IFNULL(t.gst_tax_type, '') = '' + AND t.parenttype = '{BASE_DOCTYPE}' + AND pi.posting_date >= %(gst_start_date)s + AND t.account_head NOT IN %(non_tax_accounts)s + {limit_clause} + """ + + invoices = frappe.db.sql( + query, + {"gst_start_date": GST_START_DATE, "non_tax_accounts": NON_TAX_ACCOUNTS}, + as_dict=True, + ) + + invoice_names = [r["name"] for r in invoices] + total_invoices = len(invoice_names) + print(f"Found {total_invoices} {BASE_DOCTYPE}(s) *since {GST_START_DATE}* with missing gst_tax_type.") + + summary = { + "part": 1, + "total_invoices_found": total_invoices, + "rows_examined": 0, + "rows_updated": 0, + "rows_skipped_ambiguous": 0, + "errors": [], + } + + updated_count = 0 + processed_invoices = 0 + + for inv_name in invoice_names: + processed_invoices += 1 + try: + inv = frappe.get_doc(BASE_DOCTYPE, inv_name) + except Exception as e: + summary["errors"].append((inv_name, f"read invoice error: {e}")) + continue + + company_state_code = None + if inv.get("company_gstin"): + company_state_code = _first_two_gstin_digits(inv.get("company_gstin")) + else: + try: + comp = frappe.get_doc("Company", inv.get("company")) + if comp and comp.get("company_gstin"): + company_state_code = _first_two_gstin_digits(comp.get("company_gstin")) + except Exception: + company_state_code = None + + tax_rows = inv.get("taxes") or [] + + invoice_rows_updated = 0 + invoice_rows_skipped = 0 + + for idx, tax_row in enumerate(tax_rows): + if tax_row.get("gst_tax_type") or tax_row.account_head in NON_TAX_ACCOUNTS: + continue + + summary["rows_examined"] += 1 + inferred = None + reason = "" + + inferred = infer_tax_type_from_row(tax_row, inv.as_dict(), company_state_code) + + if inferred: + reason = "keyword_or_state_mismatch" + else: + sibling_choice = choose_cgst_or_sgst_by_siblings(tax_rows, idx) + if sibling_choice: + inferred = sibling_choice + reason = "sibling_complement" + else: + reason = "ambiguous" + + if inferred: + if not dry_run: + try: + frappe.db.set_value(TAX_CHILD_DOCTYPE, tax_row.get("name"), "gst_tax_type", inferred, update_modified=False) + updated_count += 1 + invoice_rows_updated += 1 + tax_row.gst_tax_type = inferred + except Exception as e: + summary["errors"].append((inv_name, tax_row.get("name"), f"update error: {e}")) + else: + invoice_rows_skipped += 1 + + summary["rows_skipped_ambiguous"] += invoice_rows_skipped + + if not dry_run and invoice_rows_updated > 0 and (processed_invoices % batch_size == 0): + frappe.db.commit() + + if not dry_run: + frappe.db.commit() + print("Part 1: Final commit done.") + + summary["rows_updated"] = updated_count + print(f"Part 1 Finished. Summary: {summary}") + return summary + + +# ==================================================================== +# === PART 2: RECONSTRUCT 'Purchase Invoice Item' FROM 'item_wise_tax_detail' +# ==================================================================== + +def _parse_item_wise_blob_v2(blob): + if not blob: + return {} + if isinstance(blob, dict): + data = blob + else: + try: + data = json.loads(blob) + except Exception: + return {} + out = {} + for key, val in data.items(): + if isinstance(val, dict): + out[key] = { + "tax_rate": float(val.get("tax_rate") or val.get("rate") or 0) if (val.get("tax_rate") or val.get("rate")) else None, + "tax_amount": float(val.get("tax_amount")) if val.get("tax_amount") not in (None, "") else None, + "net_amount": float(val.get("net_amount")) if val.get("net_amount") not in (None, "") else None, + } + else: + try: + out[key] = {"tax_rate": float(val), "tax_amount": None, "net_amount": None} + except Exception: + out[key] = {"tax_rate": None, "tax_amount": None, "net_amount": None} + return out + +def _find_best_item_v2(candidates, inferred_taxable_value, inferred_rate, tol_amount=AMOUNT_MATCH_TOLERANCE): + if not candidates: + return None + best = None + best_score = None + for it in candidates: + tv = flt(it.get("taxable_value") or it.get("amount") or 0) + nr = flt(it.get("net_rate") or it.get("rate") or 0) + if inferred_taxable_value: + diff = abs(tv - inferred_taxable_value) + if diff <= tol_amount: + return it + if inferred_rate and nr is not None: + diff_rate = abs(nr - inferred_rate) + if best_score is None or diff_rate < best_score: + best = it + best_score = diff_rate + return best or candidates[0] + +def _determine_target_fields_v2(gst_type): + gst_type = (gst_type or "").lower() + if gst_type == "igst": + return "igst_rate", "igst_amount" + if gst_type == "cgst": + return "cgst_rate", "cgst_amount" + if gst_type == "sgst": + return "sgst_rate", "sgst_amount" + if gst_type == "cess": + return "cess_rate", "cess_amount" + return None, None + +def run_part_2_reconstruct_item_taxes(dry_run=True, limit=None, batch_size=200, sum_tolerance=SUM_TOLERANCE): + print(f"\n--- Running Part 2: Reconstructing {CHILD_DOCTYPE} Taxes ---") + + limit_clause = f"LIMIT {int(limit)}" if limit else "" + + query = f""" + SELECT t.name, t.parent as invoice, t.gst_tax_type, t.rate, t.tax_amount, t.item_wise_tax_detail + FROM `tab{TAX_CHILD_DOCTYPE}` t + JOIN `tab{BASE_DOCTYPE}` pi ON t.parent = pi.name + WHERE t.parenttype = '{BASE_DOCTYPE}' + AND IFNULL(t.tax_amount,0) <> 0 + AND IFNULL(t.item_wise_tax_detail,'') <> '' + AND IFNULL(t.gst_tax_type,'') != '' + AND pi.posting_date >= %(gst_start_date)s + {limit_clause} + """ + rows = frappe.db.sql( + query, + {"gst_start_date": GST_START_DATE}, + as_dict=True + ) + + total = len(rows) + print(f"Found {total} tax rows (since {GST_START_DATE}) with 'gst_tax_type' and 'item_wise_tax_detail' to process.") + if total == 0: + return {"part": 2, "rows_examined": 0, "notes": "No rows found. Did Part 1 run successfully?"} + + summary = { + "part": 2, + "rows_examined": total, + "rows_updated": 0, + "errors": [], + } + + updated = 0 + processed = 0 + invoice_item_cache = {} + + def get_invoice_items(invoice_name): + if invoice_name not in invoice_item_cache: + try: + invoice_item_cache[invoice_name] = frappe.db.sql(f""" + SELECT name, item_code, item_name, amount, taxable_value, rate, net_rate, idx, + igst_rate, igst_amount, cgst_rate, cgst_amount, + sgst_rate, sgst_amount, cess_rate, cess_amount + FROM `tab{CHILD_DOCTYPE}` + WHERE parent=%s + """, invoice_name, as_dict=True) + except Exception as e: + summary['errors'].append((invoice_name, f"invoice_read_error: {e}")) + invoice_item_cache[invoice_name] = None + return invoice_item_cache[invoice_name] + + for r in rows: + processed += 1 + tax_row_name = r["name"] + invoice_name = r["invoice"] + gst_type = (r.get("gst_tax_type") or "").lower() + tax_row_rate = flt(r.get("rate") or 0) + tax_row_amount = flt(r.get("tax_amount") or 0) + blob = r.get("item_wise_tax_detail") or "" + parsed = _parse_item_wise_blob_v2(blob) + + sum_itemwise = 0.0 + has_item_amounts = False + for info in parsed.values(): + if info.get("tax_amount") not in (None, ""): + has_item_amounts = True + sum_itemwise += flt(info.get("tax_amount") or 0) + + # ----- STRATEGY 1: Blob has explicit tax_amount ----- + if has_item_amounts: + if abs(tax_row_amount - sum_itemwise) > sum_tolerance: + continue # Mismatch sum, skip for safety + + inv_items = get_invoice_items(invoice_name) + if inv_items is None: continue + + item_index = {} + for it in inv_items: + keys = [str(it.get("name")).strip()] + if it.get("item_code"): keys.append(str(it.get("item_code")).strip()) + if it.get("item_name"): keys.append(str(it.get("item_name")).strip()) + if it.get("idx"): keys.append(str(int(flt(it.get("idx") or 0)))) + for k in keys: + if k: item_index.setdefault(k, []).append(it) + + for item_key, info in parsed.items(): + inferred_tax_amount = info.get("tax_amount") + inferred_rate = info.get("tax_rate") or tax_row_rate or None + inferred_taxable_value = info.get("net_amount") + + if not inferred_taxable_value and inferred_tax_amount is not None and inferred_rate: + try: + inferred_taxable_value = round((float(inferred_tax_amount) * 100.0) / float(inferred_rate), 6) + except Exception: pass + + candidates = item_index.get(str(item_key).strip(), [])[:] + if not candidates: + for k, lst in item_index.items(): + if str(item_key).strip().lower() in str(k).strip().lower(): + candidates.extend(lst) + + seen = set(); final_candidates = [c for c in candidates if c.get("name") not in seen and not seen.add(c.get("name"))] + candidates = final_candidates or inv_items[:] + + best_item = _find_best_item_v2(candidates, inferred_taxable_value, inferred_rate) + if not best_item: + continue + + target_rate_field, target_amount_field = _determine_target_fields_v2(gst_type) + if not target_rate_field: + continue + + before_val = { + "taxable_value": flt(best_item.get("taxable_value") or 0), + target_rate_field: flt(best_item.get(target_rate_field) or 0), + target_amount_field: flt(best_item.get(target_amount_field) or 0) + } + + # *** V5 LOGIC: FORCE OVERWRITE *** + writes = {} + # Only write taxable_value if it's currently 0 + if (not before_val["taxable_value"]) and inferred_taxable_value: + writes["taxable_value"] = inferred_taxable_value + + # Force overwrite tax rates and amounts if they differ + if inferred_rate is not None and abs(before_val[target_rate_field] - inferred_rate) > 0.01: + writes[target_rate_field] = inferred_rate + if inferred_tax_amount is not None and abs(before_val[target_amount_field] - inferred_tax_amount) > 0.01: + writes[target_amount_field] = round(float(inferred_tax_amount), 2) + + if writes: + if not dry_run: + try: + frappe.db.set_value(CHILD_DOCTYPE, best_item.get("name"), writes, update_modified=False) + updated += len(writes) # Count each field update + except Exception as e: + summary['errors'].append((invoice_name, best_item.get("name"), f"write_error: {e}")) + else: + updated += len(writes) # Count presumed updates + + # ----- STRATEGY 2: Blob has NO explicit tax_amount (rate-only) ----- + else: + inv_items = get_invoice_items(invoice_name) + if inv_items is None: continue + + item_index = {} + for it in inv_items: + keys = [str(it.get("name")).strip()] + if it.get("item_code"): keys.append(str(it.get("item_code")).strip()) + if it.get("item_name"): keys.append(str(it.get("item_name")).strip()) + if it.get("idx"): keys.append(str(int(flt(it.get("idx") or 0)))) + for k in keys: + if k: item_index.setdefault(k, []).append(it) + + inferred_rows = [] + sum_inferred = 0.0 + for item_key, info in parsed.items(): + rate_only = info.get("tax_rate") + if not rate_only or rate_only == 0: continue + + candidates = item_index.get(str(item_key).strip(), [])[:] + if not candidates: + for k, lst in item_index.items(): + if str(item_key).strip().lower() in str(k).strip().lower(): + candidates.extend(lst) + + seen = set(); final_candidates = [c for c in candidates if c.get("name") not in seen and not seen.add(c.get("name"))] + candidates = final_candidates or inv_items[:] + + best_item = _find_best_item_v2(candidates, None, rate_only) + if not best_item: continue + + tv = flt(best_item.get("taxable_value") or 0) + if not tv: tv = flt(best_item.get("amount") or 0) + if not tv or tv == 0: continue + + inferred_tax_amount = round((tv * float(rate_only) / 100.0), 2) + inferred_rows.append((best_item, rate_only, tv, inferred_tax_amount, item_key)) + sum_inferred += inferred_tax_amount + + if not inferred_rows: + continue + + if abs(sum_inferred - tax_row_amount) > sum_tolerance: + continue + + for best_item, rate_used, tv, inferred_tax_amount, item_key in inferred_rows: + target_rate_field, target_amount_field = _determine_target_fields_v2(gst_type) + if not target_rate_field: continue + + before_val = { + "taxable_value": flt(best_item.get("taxable_value") or 0), + target_rate_field: flt(best_item.get(target_rate_field) or 0), + target_amount_field: flt(best_item.get(target_amount_field) or 0) + } + + # *** V5 LOGIC: FORCE OVERWRITE *** + writes = {} + if tv is not None and (not before_val["taxable_value"]): # Only write taxable if 0 + writes["taxable_value"] = tv + if rate_used is not None and abs(before_val[target_rate_field] - rate_used) > 0.01: + writes[target_rate_field] = rate_used + if inferred_tax_amount is not None and abs(before_val[target_amount_field] - inferred_tax_amount) > 0.01: + writes[target_amount_field] = inferred_tax_amount + + if writes: + if not dry_run: + try: + frappe.db.set_value(CHILD_DOCTYPE, best_item.get("name"), writes, update_modified=False) + updated += len(writes) # Count each field update + except Exception as e: + summary['errors'].append((invoice_name, best_item.get("name"), f"write_error: {e}")) + else: + updated += len(writes) + + if not dry_run and (updated and (processed % batch_size == 0)): + frappe.db.commit() + if processed % (batch_size * 5) == 0: + print(f" ... Part 2 processing: {processed}/{total} tax rows processed, {updated} items updated.") + + if not dry_run: + frappe.db.commit() + print("Part 2: Final commit done.") + + summary['rows_updated'] = updated + print(f"Part 2 Finished. Summary: {summary}") + return summary + + +# ==================================================================== +# === MAIN EXECUTE FUNCTION +# ==================================================================== + +def execute(dry_run=True, batch_size=200, limit=None, sum_tolerance=SUM_TOLERANCE): + """ + Main execution function to fix Purchase Invoice GST data. + """ + dry_run = bool(dry_run) + batch_size = int(batch_size) if batch_size else 200 + limit = int(limit) if limit else None + sum_tolerance = float(sum_tolerance) if sum_tolerance else SUM_TOLERANCE + + print(f"*** STARTING PURCHASE INVOICE GST DATA RECONSTRUCTION ***") + print(f"*** {'DRY RUN' if dry_run else 'APPLYING CHANGES'} ***") + print(f"*** (Note: Processing is limited to invoices on or after {GST_START_DATE}) ***") + + summary1 = {} + summary2 = {} + + # --- Part 1 --- + try: + summary1 = run_part_1_fill_gst_tax_type(dry_run=dry_run, batch_size=batch_size, limit=limit) + print("\n=== Part 1 Summary ===") + print(json.dumps(summary1, indent=2, default=str)) + except Exception as e: + print(f"\n*** ERROR in Part 1 (fill_gst_tax_type): {e} ***") + frappe.log_error(title="GST Fix Script Part 1 Failed") + frappe.db.rollback() + return {"error": "Part 1 Failed", "details": str(e)} + + # --- Part 2 --- + try: + summary2 = run_part_2_reconstruct_item_taxes(dry_run=dry_run, limit=limit, batch_size=batch_size, sum_tolerance=sum_tolerance) + print("\n=== Part 2 Summary ===") + print(json.dumps(summary2, indent=2, default=str)) + except Exception as e: + print(f"\n*** ERROR in Part 2 (reconstruct_item_taxes): {e} ***") + frappe.log_error(title="GST Fix Script Part 2 Failed") + frappe.db.rollback() + return {"error": "Part 2 Failed", "details": str(e)} + + if dry_run: + print("\n*** DRY RUN COMPLETE. No changes were made. Rolling back. ***") + frappe.db.rollback() + else: + print("\n*** ALL PARTS COMPLETE. Final commit issued. ***") + frappe.db.commit() + + print("\n--- SCRIPT FINISHED ---") + return {"part1_summary": summary1, "part2_summary": summary2} + + +# bench --site development.localhost execute rohit_common.migration_scripts.fix_purchase_invoices_gst.execute \ +# --kwargs "{'dry_run': True, 'limit': 100}" + +# bench --site development.localhost execute rohit_common.migration_scripts.fix_purchase_invoices_gst.execute \ +# --kwargs "{'dry_run': False}" \ No newline at end of file diff --git a/rohit_common/migration_scripts/patch_invoices.py b/rohit_common/migration_scripts/patch_invoices.py new file mode 100644 index 0000000..de1b079 --- /dev/null +++ b/rohit_common/migration_scripts/patch_invoices.py @@ -0,0 +1,160 @@ +import frappe + +def run_patch(dry_run=True): + """ + Patches old Sales Invoices with missing gst_category and place_of_supply + after migrating from v12 to v15. + + V5 Logic: + - Uses correct category names ("Registered Regular", "Unregistered"). + - Checks both `customer_gstin` and `billing_address_gstin` to find registered customers. + - Re-formats `place_of_supply` from "State Name" to "Code-State Name" using the built-in map. + - Falls back to checking the linked Address if data is missing. + """ + + # State mapping you provided from the constants file + STATE_NUMBERS = { + "Andaman and Nicobar Islands": "35", "Andhra Pradesh": "37", "Arunachal Pradesh": "12", + "Assam": "18", "Bihar": "10", "Chandigarh": "04", "Chhattisgarh": "22", + "Dadra and Nagar Haveli and Daman and Diu": "26", "Delhi": "07", "Goa": "30", + "Gujarat": "24", "Haryana": "06", "Himachal Pradesh": "02", "Jammu and Kashmir": "01", + "Jharkhand": "20", "Karnataka": "29", "Kerala": "32", "Ladakh": "38", + "Lakshadweep Islands": "31", "Madhya Pradesh": "23", "Maharashtra": "27", "Manipur": "14", + "Meghalaya": "17", "Mizoram": "15", "Nagaland": "13", "Odisha": "21", + "Other Countries": "96", "Other Territory": "97", "Puducherry": "34", "Punjab": "03", + "Rajasthan": "08", "Sikkim": "11", "Tamil Nadu": "33", "Telangana": "36", + "Tripura": "16", "Uttar Pradesh": "09", "Uttarakhand": "05", "West Bengal": "19", + } + + frappe.db.auto_commit_on_many_writes = True + post_gst_start_date = "2017-07-01" + + print("--- Starting Patch for GST Fields (V5 Logic) ---") + if dry_run: + print("*** DRY RUN MODE: No changes will be saved. ***") + + print("Finding invoices to patch...") + + # We query for invoices that have a blank category OR a place_of_supply + # that does NOT contain a hyphen (e.g., "Tamil Nadu" instead of "33-Tamil Nadu") + invoices_to_patch = frappe.db.sql(f""" + SELECT + name, customer_gstin, billing_address_gstin, + customer_address, shipping_address_name, place_of_supply, gst_category + FROM + `tabSales Invoice` + WHERE + docstatus = 1 + AND posting_date >= '{post_gst_start_date}' + AND ( + IFNULL(gst_category, '') = '' + OR IFNULL(place_of_supply, '') = '' + OR place_of_supply NOT LIKE '%-%' + ) + """, as_dict=True) + + total_invoices = len(invoices_to_patch) + if not total_invoices: + print("No invoices found that need patching. Exiting.") + return + + print(f"Found {total_invoices} submitted invoices to patch...") + + updated_count = 0 + failed_count = 0 + processed_count = 0 + + for i, inv in enumerate(invoices_to_patch): + processed_count += 1 + doc_needs_update = False + update_data = {} + log_msgs = [] + + try: + # 1. Logic for GST Category + if not inv.gst_category: + customer_has_gstin = inv.customer_gstin or inv.billing_address_gstin + + if customer_has_gstin: + update_data["gst_category"] = "Registered Regular" + log_msgs.append("set gst_category=Registered Regular") + else: + update_data["gst_category"] = "Unregistered" + log_msgs.append("set gst_category=Unregistered") + doc_needs_update = True + + # 2. Logic for Place of Supply + current_pos = inv.place_of_supply + pos_is_correct_format = current_pos and "-" in current_pos + + if not pos_is_correct_format: + new_pos_value = None + + # Try 1: Re-format the existing value (e.g., "Tamil Nadu") + if current_pos: + state_name = current_pos.strip() + state_code = STATE_NUMBERS.get(state_name) + if state_code: + new_pos_value = f"{state_code}-{state_name}" + log_msgs.append(f"re-formatted place_of_supply to {new_pos_value}") + + # Try 2: If Try 1 failed (blank field or bad state name), get from Address + if not new_pos_value: + address_name = inv.customer_address or inv.shipping_address_name + if address_name: + gst_state = frappe.db.get_value("Address", address_name, "gst_state") + if gst_state and "-" in gst_state: # Ensure address value is valid + new_pos_value = gst_state + log_msgs.append(f"set place_of_supply from Address {address_name}") + + # Now, update if we found a value + if new_pos_value: + update_data["place_of_supply"] = new_pos_value + doc_needs_update = True + elif not current_pos: + log_msgs.append("SKIP place_of_supply: Field is blank and linked Address has no data.") + else: + log_msgs.append(f"SKIP place_of_supply: Unknown state name '{current_pos}' and no Address fallback.") + + # 3. Update the document + if doc_needs_update: + if dry_run: + print(f"[{processed_count}/{total_invoices}] (DRY RUN) {inv.name}: {', '.join(log_msgs)}") + updated_count += 1 + else: + frappe.db.set_value("Sales Invoice", inv.name, update_data, update_modified=False) + updated_count += 1 + print(f"[{processed_count}/{total_invoices}] UPDATED {inv.name}: {', '.join(log_msgs)}") + + elif not log_msgs: + print(f"[{processed_count}/{total_invoices}] (DRY RUN) {inv.name}: Fields already populated correctly.") + + except Exception as e: + print(f" - ERROR: Failed to process {inv.name}: {e}") + frappe.db.rollback() + failed_count += 1 + + # Commit every 100 records in a live run + if not dry_run and (i + 1) % 100 == 0: + frappe.db.commit() + print(f"--- Committed batch ({i + 1} processed) ---") + + # Final commit + if not dry_run: + frappe.db.commit() + print("--- Final Commit Done. ---") + + print("--- Patching Complete! ---") + print(f"Total Processed: {total_invoices}") + print(f"Targeted for Update: {updated_count}") + print(f"Failed: {failed_count}") + if dry_run: + print("*** DRY RUN MODE: No changes were saved. ***") + +# bench execute entrypoint +def execute(dry_run=True, batch_size=200): + is_dry_run = bool(dry_run) + return run_patch(dry_run=is_dry_run) + +# bench --site development.localhost execute rohit_common.migration_scripts.patch_invoices.execute --kwargs "{'dry_run': True}" +# bench --site development.localhost execute rohit_common.migration_scripts.patch_invoices.execute --kwargs "{'dry_run': False}" \ No newline at end of file diff --git a/rohit_common/migration_scripts/repopulate_company_gstin.py b/rohit_common/migration_scripts/repopulate_company_gstin.py new file mode 100644 index 0000000..8954799 --- /dev/null +++ b/rohit_common/migration_scripts/repopulate_company_gstin.py @@ -0,0 +1,147 @@ +import frappe + +def repopulate_sales_invoice_company_gstin(dry_run=True, batch_size=200, limit=None): + """ + Populate Sales Invoice.company_gstin from Company (common GSTIN fields). + - dry_run=True : only prints what would be changed + - batch_size : number of updates before commit + - limit : optional integer - limit number of invoices processed (for testing) + Returns a summary dict. + """ + frappe.flags.in_migrate = True + + possible_company_gstin_fields = ["company_gstin", "gstin", "gstin_number", "tax_id", "tax_id_number"] + + # build company -> gstin mapping + company_gstin_map = {} + for c in frappe.get_all("Company", fields=["name"]): + cname = c.get("name") + try: + comp_doc = frappe.get_doc("Company", cname) + except Exception: + continue + gst = None + for f in possible_company_gstin_fields: + if hasattr(comp_doc, f): + val = comp_doc.get(f) + if val: + gst = val.strip() + break + if gst: + company_gstin_map[cname] = gst + + # fetch invoices where company_gstin is empty or null + # NOTE: use limit_page_length only if limit not given + kwargs = { + "filters": {"company_gstin": ["in", ["", None]]}, + "fields": ["name", "company", "posting_date"], + } + if limit: + kwargs["limit_page_length"] = limit + else: + kwargs["limit_page_length"] = 100000 + + invoices = frappe.get_all("Sales Invoice", **kwargs) + + # fallback to SQL if get_all returned nothing (covers schema mismatches) + if not invoices: + limit_clause = "LIMIT %s" % int(limit) if limit else "" + invoices = frappe.db.sql( + f""" + SELECT name, company, posting_date + FROM `tabSales Invoice` + WHERE IFNULL(company_gstin, '') = '' + {limit_clause} + """, + as_dict=True, + ) + + total = len(invoices) + print("Found %d Sales Invoice(s) with empty company_gstin." % total) + if total == 0: + return {"total_found": 0, "updated": 0, "skipped_no_company": 0, "skipped_no_gstin": 0, "errors": []} + + updated = 0 + skipped_no_company = 0 + skipped_no_gstin = 0 + errors = [] + counter = 0 + + for inv in invoices: + counter += 1 + name = inv.get("name") + company = inv.get("company") + posting_date = inv.get("posting_date") + + if not company: + skipped_no_company += 1 + print(f"[{counter}/{total}] SKIP {name} — no company set.") + continue + + gst_value = company_gstin_map.get(company) + if not gst_value: + # try reading company doc live + try: + comp_doc = frappe.get_doc("Company", company) + for f in possible_company_gstin_fields: + if hasattr(comp_doc, f): + val = comp_doc.get(f) + if val: + gst_value = val.strip() + break + except Exception as e: + errors.append((name, f"read company error: {e}")) + print(f"[{counter}/{total}] ERROR reading Company for {name}: {e}") + continue + + if not gst_value: + skipped_no_gstin += 1 + print(f"[{counter}/{total}] SKIP {name} — company '{company}' has no GSTIN.") + continue + + print(f"[{counter}/{total}] Invoice {name}: set company_gstin -> {gst_value} (company: {company}, posting_date: {posting_date})") + + if not dry_run: + try: + frappe.db.set_value("Sales Invoice", name, "company_gstin", gst_value, update_modified=True) + updated += 1 + except Exception as e: + errors.append((name, f"update error: {e}")) + print(f" ERROR updating {name}: {e}") + + if updated and (updated % batch_size == 0): + frappe.db.commit() + print(" Committed batch up to %d updates." % updated) + + if not dry_run: + frappe.db.commit() + print("Final commit done.") + + print("Done. Summary:") + print(f" Total invoices found: {total}") + print(f" Updated: {updated}") + print(f" Skipped (no company set): {skipped_no_company}") + print(f" Skipped (company has no GSTIN): {skipped_no_gstin}") + print(f" Errors: {len(errors)}") + + return { + "total_found": total, + "updated": updated, + "skipped_no_company": skipped_no_company, + "skipped_no_gstin": skipped_no_gstin, + "errors": errors, + } + +# bench execute entrypoint +def execute(dry_run=True, batch_size=200, limit=None): + # bench execute passes JSON-like values; ensure types are correct + dry_run = bool(dry_run) + batch_size = int(batch_size) if batch_size else 200 + limit = int(limit) if limit else None + return repopulate_sales_invoice_company_gstin(dry_run=dry_run, batch_size=batch_size, limit=limit) + +# dry run - prints actions, does not write +# bench --site development.localhost execute rohit_common.migration_scripts.repopulate_company_gstin.execute --kwargs "{'dry_run': True, 'limit': 100}" + +# when happy, perform actual update (no limit): +# bench --site development.localhost execute rohit_common.migration_scripts.repopulate_company_gstin.execute --kwargs "{'dry_run': False, 'batch_size': 200}" diff --git a/rohit_common/rohit_common/report/clear_tax_import_format/clear_tax_import_format.py b/rohit_common/rohit_common/report/clear_tax_import_format/clear_tax_import_format.py index c7e64b5..80bad0f 100644 --- a/rohit_common/rohit_common/report/clear_tax_import_format/clear_tax_import_format.py +++ b/rohit_common/rohit_common/report/clear_tax_import_format/clear_tax_import_format.py @@ -4,361 +4,195 @@ from __future__ import unicode_literals import frappe from datetime import date -from erpnext.regional.report.gstr_1.gstr_1 import Gstr1Report +from rohit_common.rohit_common.report.rigpl_legacy_gstr1.rigpl_legacy_gstr1 import Gstr1Report +from frappe.utils import flt def execute(filters=None): - return ClearTaxImport(filters).run() + return ClearTaxImport(filters).run() class ClearTaxImport(Gstr1Report): - def __init__(self, filters=None): - self.filters = frappe._dict(filters or {}) - self.columns = [] - self.data = [] - self.doctype = filters.get("type") - if filters.get("type") == 'Sales Invoice': - self.tax_doctype = "Sales Taxes and Charges" - self.select_columns = """ - name as invoice_number, - customer, - posting_date as posting_date_unformatted, - base_grand_total, - base_net_total, - taxes_and_charges, + def __init__(self, filters=None): + super(ClearTaxImport, self).__init__(filters) + self.filters = frappe._dict(filters or {}) + self.columns = [] + self.data = [] + self.doctype = filters.get("type") + + if filters.get("type") == 'Sales Invoice': + self.tax_doctype = "Sales Taxes and Charges" + self.select_columns = """ + name as invoice_number, + customer, + posting_date as posting_date_unformatted, + base_grand_total, + base_net_total, + taxes_and_charges, + COALESCE(NULLIF(customer_gstin,''), NULLIF(billing_address_gstin, '')) as customer_gstin, + place_of_supply, + ecommerce_gstin, + reverse_charge, + invoice_type, + return_against, + is_return, + export_type, + port_code, + shipping_bill_number, + shipping_bill_date, + reason_for_issuing_document, + customer_address + """ + elif filters.get("type") == 'Purchase Invoice': + self.tax_doctype = "Purchase Taxes and Charges" + self.select_columns = """ + name as invoice_number, + supplier, + posting_date as posting_date_unformatted, + bill_date, + bill_no, + taxes_and_charges, + base_grand_total, + base_net_total, + supplier_gstin, + place_of_supply, + ecommerce_gstin, + reverse_charge, + invoice_type, + return_against, + is_return, + export_type, + reason_for_issuing_document, + eligibility_for_itc + """ - COALESCE(NULLIF(customer_gstin,''), NULLIF(billing_address_gstin, '')) as customer_gstin, - place_of_supply, - ecommerce_gstin, - reverse_charge, - invoice_type, - return_against, - is_return, - invoice_type, - export_type, - port_code, - shipping_bill_number, - shipping_bill_date, - reason_for_issuing_document - """ - elif filters.get("type") == 'Purchase Invoice': - self.tax_doctype = "Purchase Taxes and Charges" - self.select_columns = """ - name as invoice_number, - supplier, - posting_date as posting_date_unformatted, - bill_date, - bill_no, - taxes_and_charges, - base_grand_total, - base_net_total, - supplier_gstin, - place_of_supply, - ecommerce_gstin, - reverse_charge, - invoice_type, - return_against, - is_return, - invoice_type, - export_type, - reason_for_issuing_document, - eligibility_for_itc, - itc_integrated_tax, - itc_central_tax, - itc_state_tax, - itc_cess_amount - """ + def get_data(self): + # Use self.invoice_items_details if available (from fixed parent), otherwise fallback + items_source = getattr(self, "invoice_items_details", None) + if not items_source and hasattr(self, "invoices"): + items_source = {} - def get_data(self): - self.get_igst_invoices() - for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): - invoice_details = self.invoices.get(inv) - for rate, items in items_based_on_rate.items(): - row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, items) - tax_amount = taxable_value * rate / 100 - if inv in self.igst_invoices: - row += [tax_amount, 0, 0] - else: - row += [0, tax_amount / 2, tax_amount / 2] + for inv_name, invoice_details in self.invoices.items(): + items = items_source.get(inv_name, []) + + # Group items by rate + items_by_rate = {} + for item in items: + rate = flt(item.igst_rate) + flt(item.cgst_rate) + flt(item.sgst_rate) + items_by_rate.setdefault(rate, []).append(item) + + for rate, rate_items in items_by_rate.items(): + row, taxable_value = self.get_row_data_for_invoice(inv_name, invoice_details, rate, rate_items) + + # --- FILTER: Remove rows with no value --- + # This is the ONLY filter we need. It removes true duplicates/empty rows. + # We DO NOT filter by rate==0 , so valid 0% items will show. + if taxable_value <= 0: + continue + # ----------------------------------------- - row += [ - self.invoice_cess.get(inv), - invoice_details.get('eligibility_for_itc'), - invoice_details.get('itc_integrated_tax'), - invoice_details.get('itc_central_tax'), - invoice_details.get('itc_state_tax'), - invoice_details.get('itc_cess_amount') - ] - if self.filters.get("type_of_business") == "CDNR": - row.append("Y" if invoice_details.posting_date <= date(2017, 7, 1) else "N") - row.append("C" if invoice_details.return_against else "R") + igst_paid = 0 + cgst_paid = 0 + sgst_paid = 0 + cess_paid = 0 + itc_igst = 0 + itc_cgst = 0 + itc_sgst = 0 + itc_cess = 0 + + for item in rate_items: + igst_paid += flt(item.igst_amount) + cgst_paid += flt(item.cgst_amount) + sgst_paid += flt(item.sgst_amount) + cess_paid += flt(item.cess_amount) + + if self.doctype == 'Purchase Invoice': + itc_igst += flt(item.igst_amount) + itc_cgst += flt(item.cgst_amount) + itc_sgst += flt(item.sgst_amount) + itc_cess += flt(item.cess_amount) - self.data.append(row) - def get_igst_invoices(self): - self.igst_invoices = [] - for d in self.tax_details: - is_igst = True if d[1] in self.gst_accounts.igst_account else False - if is_igst and d[0] not in self.igst_invoices: - self.igst_invoices.append(d[0]) + if self.doctype == 'Purchase Invoice': + row += [ + igst_paid, cgst_paid, sgst_paid, cess_paid, + invoice_details.get('eligibility_for_itc') or 'All Other ITC', + itc_igst, itc_cgst, itc_sgst, itc_cess + ] + elif self.doctype == 'Sales Invoice': + if self.is_igst_invoice(inv_name): + row += [igst_paid, 0, 0] + else: + row += [0, cgst_paid, sgst_paid] + row.append(cess_paid) + + if self.filters.get("type_of_business") == "CDNR": + row.append("Y" if invoice_details.posting_date <= date(2017, 7, 1) else "N") + row.append("C" if invoice_details.return_against else "R") - def get_conditions(self): - conditions = "" - if self.filters.get("letter_head"): - conditions += " AND letter_head = '%s'" %(self.filters.get("letter_head")) + self.data.append(row) + + def is_igst_invoice(self, inv_name): + # Check if invoice is in the IGST list (populated by parent) + return hasattr(self, "igst_invoices") and inv_name in self.igst_invoices - for opts in (("company", " and company=%(company)s"), - ("from_date", " and posting_date>=%(from_date)s"), - ("to_date", " and posting_date<=%(to_date)s")): - if self.filters.get(opts[0]): - conditions += opts[1] + def get_columns(self): + tax_val_col = { "fieldname": "taxable_value", "label": "Taxable Value", "fieldtype": "Currency", "width": 100 } + rate_col = { "fieldname": "rate", "label": "Rate", "fieldtype": "Int", "width": 60 } - if self.filters.get("type_of_business") == "B2B": - conditions += "and ifnull(invoice_type, '') != 'Export' and is_return != 1 " + if self.filters.get("type") == 'Sales Invoice': + self.invoice_columns = [ + { "fieldname": "posting_date_unformatted", "label": "Invoice Date", "fieldtype": "Date", "width": 80 }, + { "fieldname": "invoice_number", "label": "Invoice Number", "fieldtype": "Link", "options": "Sales Invoice", "width": 120 }, + { "fieldname": "base_net_total", "label": "Net Total", "fieldtype": "Currency", "width": 80 }, + { "fieldname": "base_grand_total", "label": "Grand Total", "fieldtype": "Currency", "width": 80 }, + { "fieldname": "customer", "label": "Customer Link", "fieldtype": "Link", "options": "Customer", "width": 200 }, + { "fieldname": "taxes_and_charges", "label": "Tax Link", "fieldtype": "Link", "options": "Sales Taxes and Charges Template", "width": 150 }, + { "fieldname": "customer_gstin", "label": "Customer GSTIN", "fieldtype": "Data", "width": 120 }, + { "fieldname": "place_of_supply", "label": "Place of Supply", "fieldtype": "Data", "width": 120 }, + { "fieldname": "reverse_charge", "label": "Reverse Charge", "fieldtype": "Data", "width": 80 }, + { "fieldname": "invoice_type", "label": "Invoice Type", "fieldtype": "Data", "width": 80 }, + { "fieldname": "ecommerce_gstin", "label": "E-Comm GSTIN", "fieldtype": "Data", "width": 120 }, + { "fieldname": "reason_for_issuing_document", "label": "Reason", "fieldtype": "Data", "width": 120 }, + { "fieldname": "is_export", "label": "Is EXP", "fieldtype": "Data", "width": 30 }, + { "fieldname": "gst_paid_on_export", "label": "GST Paid on EXP", "fieldtype": "Data", "width": 30 }, + { "fieldname": "export_shb_no", "label": "EXP SHB #", "fieldtype": "Data", "width": 30 }, + { "fieldname": "export_shb_date", "label": "EXP SHB Date", "fieldtype": "Data", "width": 30 }, + { "fieldname": "export_destination_country_code", "label": "Exp Dest Country Code", "fieldtype": "Data", "width": 30 }, + { "fieldname": "customer_address", "label": "Billing Address Link", "fieldtype": "Link", "options": "Address", "width": 80 } + ] + self.tax_columns = [ + rate_col, tax_val_col, + { "fieldname": "integrated_tax_paid", "label": "Integrated Tax Paid", "fieldtype": "Currency", "width": 100 }, + { "fieldname": "central_tax_paid", "label": "Central Tax Paid", "fieldtype": "Currency", "width": 100 }, + { "fieldname": "state_tax_paid", "label": "State/UT Tax Paid", "fieldtype": "Currency", "width": 100 }, + { "fieldname": "cess_amount", "label": "Cess Paid", "fieldtype": "Currency", "width": 100 } + ] + self.other_columns = [] - elif self.filters.get("type_of_business") == "CDNR": - conditions += """ and is_return = 1 """ - - return conditions - - def get_columns(self): - if self.filters.get("type") == 'Sales Invoice': - self.tax_columns = [ - { - "fieldname": "rate", - "label": "Rate", - "fieldtype": "Int", - "width": 60 - }, - { - "fieldname": "taxable_value", - "label": "Taxable Value", - "fieldtype": "Currency", - "width": 100 - } - ] - self.other_columns = [] - self.invoice_columns = [ - { - "fieldname": "posting_date_unformatted", - "label": "Invoice Date", - "fieldtype": "Date", - "width": 80 - }, - { - "fieldname": "invoice_number", - "label": "Invoice Number", - "fieldtype": "Link", - "options": "Sales Invoice", - "width": 120 - }, - { - "fieldname": "base_net_total", - "label": "Net Total", - "fieldtype": "Currency", - "width": 80 - }, - { - "fieldname": "base_grand_total", - "label": "Grand Total", - "fieldtype": "Currency", - "width": 80 - }, - { - "fieldname": "customer", - "label": "Customer Link", - "fieldtype": "Link", - "options": "Customer", - "width": 200 - }, - { - "fieldname": "taxes_and_charges", - "label": "Tax Link", - "fieldtype": "Link", - "options": "Sales Taxes and Charges Template", - "width": 150 - }, - { - "fieldname": "is_export", - "label": "Is EXP", - "fieldtype": "Data", - "width": 30 - }, - { - "fieldname": "gst_paid_on_export", - "label": "GST Paid on EXP", - "fieldtype": "Data", - "width": 30 - }, - { - "fieldname": "export_shb_no", - "label": "EXP SHB #", - "fieldtype": "Data", - "width": 30 - }, - { - "fieldname": "export_shb_date", - "label": "EXP SHB Date", - "fieldtype": "Data", - "width": 30 - }, - { - "fieldname": "export_destination_country_code", - "label": "Exp Dest Country Code", - "fieldtype": "Data", - "width": 30 - }, - { - "fieldname": "customer_address", - "label": "Billing Address Link", - "fieldtype": "Link", - "options": "Address", - "width": 80 - }, - { - "fieldname": "customer_address", - "label": "Billing Address Link", - "fieldtype": "Link", - "options": "Address", - "width": 80 - }, - ] - elif self.filters.get("type") == 'Purchase Invoice': - self.tax_columns = [ - { - "fieldname": "rate", - "label": "Rate", - "fieldtype": "Int", - "width": 60 - }, - { - "fieldname": "taxable_value", - "label": "Taxable Value", - "fieldtype": "Currency", - "width": 100 - }, - { - "fieldname": "integrated_tax_paid", - "label": "Integrated Tax Paid", - "fieldtype": "Currency", - "width": 100 - }, - { - "fieldname": "central_tax_paid", - "label": "Central Tax Paid", - "fieldtype": "Currency", - "width": 100 - }, - { - "fieldname": "state_tax_paid", - "label": "State/UT Tax Paid", - "fieldtype": "Currency", - "width": 100 - }, - { - "fieldname": "cess_amount", - "label": "Cess Paid", - "fieldtype": "Currency", - "width": 100 - }, - { - "fieldname": "eligibility_for_itc", - "label": "Eligibility For ITC", - "fieldtype": "Data", - "width": 100 - }, - { - "fieldname": "itc_integrated_tax", - "label": "Availed ITC Integrated Tax", - "fieldtype": "Currency", - "width": 100 - }, - { - "fieldname": "itc_central_tax", - "label": "Availed ITC Central Tax", - "fieldtype": "Currency", - "width": 100 - }, - { - "fieldname": "itc_state_tax", - "label": "Availed ITC State/UT Tax", - "fieldtype": "Currency", - "width": 100 - }, - { - "fieldname": "itc_cess_amount", - "label": "Availed ITC Cess ", - "fieldtype": "Currency", - "width": 100 - } - ] - self.other_columns = [] - self.invoice_columns = [ - { - "fieldname": "invoice_number", - "label": "PI #", - "fieldtype": "Link", - "options": "Purchase Invoice", - "width": 120 - }, - { - "fieldname": "posting_date_unformatted", - "label": "PI Posting Date", - "fieldtype": "Date", - "width": 80 - }, - { - "fieldname": "bill_date", - "label": "Supplier PI Date", - "fieldtype": "Date", - "width": 80 - }, - { - "fieldname": "bill_no", - "label": "Supplier PI No", - "fieldtype": "Data", - "width": 80 - }, - { - "fieldname": "supplier", - "label": "Supplier Link", - "fieldtype": "Link", - "options": "Supplier", - "width": 200 - }, - { - "fieldname": "taxes_and_charges", - "label": "Tax Link", - "fieldtype": "Link", - "options": "Purchase Taxes and Charges Template", - "width": 150 - }, - { - "fieldname": "supplier_gstin", - "label": "GSTIN of Supplier", - "fieldtype": "Data", - "width": 130 - }, - { - "fieldname": "place_of_supply", - "label": "Place of Supply", - "fieldtype": "Data", - "width": 120 - }, - { - "fieldname": "invoice_value", - "label": "Invoice Value", - "fieldtype": "Currency", - "width": 120 - }, - { - "fieldname": "reverse_charge", - "label": "Reverse Charge", - "fieldtype": "Data", - "width": 80 - }, - { - "fieldname": "invoice_type", - "label": "Invoice Type", - "fieldtype": "Data", - "width": 80 - } - ] - self.columns = self.invoice_columns + self.tax_columns + self.other_columns \ No newline at end of file + elif self.filters.get("type") == 'Purchase Invoice': + self.invoice_columns = [ + { "fieldname": "invoice_number", "label": "PI #", "fieldtype": "Link", "options": "Purchase Invoice", "width": 120 }, + { "fieldname": "posting_date_unformatted", "label": "PI Posting Date", "fieldtype": "Date", "width": 80 }, + { "fieldname": "bill_date", "label": "Supplier PI Date", "fieldtype": "Date", "width": 80 }, + { "fieldname": "bill_no", "label": "Supplier PI No", "fieldtype": "Data", "width": 80 }, + { "fieldname": "supplier", "label": "Supplier Link", "fieldtype": "Link", "options": "Supplier", "width": 200 }, + { "fieldname": "taxes_and_charges", "label": "Tax Link", "fieldtype": "Link", "options": "Purchase Taxes and Charges Template", "width": 150 }, + { "fieldname": "supplier_gstin", "label": "GSTIN of Supplier", "fieldtype": "Data", "width": 130 }, + { "fieldname": "place_of_supply", "label": "Place of Supply", "fieldtype": "Data", "width": 120 }, + { "fieldname": "invoice_value", "label": "Invoice Value", "fieldtype": "Currency", "width": 120 }, + { "fieldname": "reverse_charge", "label": "Reverse Charge", "fieldtype": "Data", "width": 80 }, + { "fieldname": "invoice_type", "label": "Invoice Type", "fieldtype": "Data", "width": 80 } + ] + self.tax_columns = [ + rate_col, tax_val_col, + { "fieldname": "integrated_tax_paid", "label": "Integrated Tax Paid", "fieldtype": "Currency", "width": 100 }, + { "fieldname": "central_tax_paid", "label": "Central Tax Paid", "fieldtype": "Currency", "width": 100 }, + { "fieldname": "state_tax_paid", "label": "State/UT Tax Paid", "fieldtype": "Currency", "width": 100 }, + { "fieldname": "cess_amount", "label": "Cess Paid", "fieldtype": "Currency", "width": 100 }, + { "fieldname": "eligibility_for_itc", "label": "Eligibility For ITC", "fieldtype": "Data", "width": 100 }, + { "fieldname": "itc_integrated_tax", "label": "Availed ITC Integrated Tax", "fieldtype": "Currency", "width": 100 }, + { "fieldname": "itc_central_tax", "label": "Availed ITC Central Tax", "fieldtype": "Currency", "width": 100 }, + { "fieldname": "itc_state_tax", "label": "Availed ITC State/UT Tax", "fieldtype": "Currency", "width": 100 }, + { "fieldname": "itc_cess_amount", "label": "Availed ITC Cess ", "fieldtype": "Currency", "width": 100 } + ] + self.other_columns = [] + + self.columns = self.invoice_columns + self.tax_columns + self.other_columns \ No newline at end of file diff --git a/rohit_common/rohit_common/report/rigpl_legacy_gstr1/__init__.py b/rohit_common/rohit_common/report/rigpl_legacy_gstr1/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.js b/rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.js new file mode 100644 index 0000000..3f8c0d2 --- /dev/null +++ b/rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.js @@ -0,0 +1,79 @@ +// Copyright (c) 2025, Rohit Industries Ltd. and contributors +// For license information, please see license.txt + +frappe.query_reports["RIGPL Legacy GSTR1"] = { + "filters": [ + { + "fieldname": "company", + "label": __("Company"), + "fieldtype": "Link", + "options": "Company", + "reqd": 1, + "default": frappe.defaults.get_user_default("Company") + }, + { + "fieldname": "company_address", + "label": __("Address"), + "fieldtype": "Link", + "options": "Address", + "get_query": function () { + var company = frappe.query_report.get_filter_value('company'); + if (company) { + return { + "query": 'frappe.contacts.doctype.address.address.address_query', + "filters": { link_doctype: 'Company', link_name: company } + }; + } + } + }, + { + "fieldname": "from_date", + "label": __("From Date"), + "fieldtype": "Date", + "reqd": 1, + "default": frappe.datetime.add_months(frappe.datetime.get_today(), -3), + "width": "80" + }, + { + "fieldname": "to_date", + "label": __("To Date"), + "fieldtype": "Date", + "reqd": 1, + "default": frappe.datetime.get_today() + }, + { + "fieldname": "type_of_business", + "label": __("Type of Business"), + "fieldtype": "Select", + "reqd": 1, + "options": ["B2B", "B2C Large", "B2C Small", "CDNR", "EXPORT"], + "default": "B2B" + } + ], + onload: function (report) { + + report.page.add_inner_button(__("Download as Json"), function () { + var filters = report.get_values(); + + frappe.call({ + method: 'rohit_common.report.rigpl_legacy_gstr1.get_json', + args: { + data: report.data, + report_name: report.report_name, + filters: filters + }, + callback: function(r) { + if (r.message) { + const args = { + cmd: 'rohit_common.report.rigpl_legacy_gstr1.download_json_file', + data: r.message.data, + report_name: r.message.report_name, + report_type: r.message.report_type + }; + open_url_post(frappe.request.url, args); + } + } + }); + }); + } +}; diff --git a/rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.json b/rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.json new file mode 100644 index 0000000..b91869a --- /dev/null +++ b/rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.json @@ -0,0 +1,38 @@ +{ + "add_total_row": 1, + "add_translate_data": 0, + "columns": [], + "creation": "2025-11-13 17:41:25.710025", + "disabled": 0, + "docstatus": 0, + "doctype": "Report", + "filters": [], + "idx": 0, + "is_standard": "Yes", + "letter_head": "RIGB", + "letterhead": null, + "modified": "2025-11-13 17:41:25.710025", + "modified_by": "Administrator", + "module": "rohit_common", + "name": "RIGPL Legacy GSTR1", + "owner": "Administrator", + "prepared_report": 0, + "ref_doctype": "GL Entry", + "report_name": "RIGPL Legacy GSTR1", + "report_type": "Script Report", + "roles": [ + { + "role": "Accounts User" + }, + { + "role": "Accounts Manager" + }, + { + "role": "RIGB Auditor" + }, + { + "role": "Invoice Maker" + } + ], + "timeout": 0 +} diff --git a/rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.py b/rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.py new file mode 100644 index 0000000..8c9a5af --- /dev/null +++ b/rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.py @@ -0,0 +1,873 @@ +# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe, json +from frappe import _ +from frappe.utils import flt, formatdate, now_datetime, getdate +from datetime import date +from six import iteritems + +# *** FIX 1: Import the correct, modern function *** +from india_compliance.gst_india.utils import get_gst_accounts_by_type + +def execute(filters=None): + return Gstr1Report(filters).run() + +class Gstr1Report(object): + def __init__(self, filters=None): + self.filters = frappe._dict(filters or {}) + self.columns = [] + self.data = [] + self.doctype = "Sales Invoice" + self.tax_doctype = "Sales Taxes and Charges" + self.select_columns = """ + name as invoice_number, + customer_name, + posting_date, + base_grand_total, + base_rounded_total, + COALESCE(NULLIF(customer_gstin,''), NULLIF(billing_address_gstin, '')) as customer_gstin, + place_of_supply, + ecommerce_gstin, + reverse_charge, + return_against, + is_return, + gst_category, + export_type, + port_code, + shipping_bill_number, + shipping_bill_date, + reason_for_issuing_document + """ + + def run(self): + self.get_columns() + + # *** FIX 2: Correctly get Input or Output accounts based on doctype *** + if self.doctype == "Purchase Invoice": + account_type = "Input" + else: + account_type = "Output" + + if not self.filters.company: + frappe.throw(_("Please select a Company")) + + # Get the correct accounts + raw_gst_accounts = get_gst_accounts_by_type(self.filters.company, account_type) + + # The new function returns a dict, so we just need to adapt it + gst_accounts = frappe._dict({ + "cgst_account": raw_gst_accounts.get("cgst_account"), + "sgst_account": raw_gst_accounts.get("sgst_account"), + "igst_account": raw_gst_accounts.get("igst_account"), + "cess_account": [raw_gst_accounts.get("cess_account"), raw_gst_accounts.get("cess_non_advol_account")] + }) + + # Filter out None values and put them in lists + gst_accounts.cgst_account = [gst_accounts.cgst_account] if gst_accounts.cgst_account else [] + gst_accounts.sgst_account = [gst_accounts.sgst_account] if gst_accounts.sgst_account else [] + gst_accounts.igst_account = [gst_accounts.igst_account] if gst_accounts.igst_account else [] + gst_accounts.cess_account = [acc for acc in gst_accounts.cess_account if acc] + + self.gst_accounts = gst_accounts + # *** END OF FIX 2 *** + + self.get_invoice_data() + + if self.invoices: + # *** FIX 3: Rewritten data fetching *** + # Get all items for all invoices at once + self.get_all_invoice_items() + + # Use the tax table to find the *overall* rate + self.get_tax_rates_from_tax_table() + + self.invoice_fields = [d["fieldname"] for d in self.invoice_columns] + self.get_data() + # *** END OF FIX 3 *** + + return self.columns, self.data + + def get_data(self): + # This function is now overridden by clear_tax_import.py + # We leave the original B2C/etc logic here for Gstr1Report + if self.filters.get("type_of_business") in ("B2C Small", "B2C Large"): + self.get_b2c_data() + else: + # This loop is now simplified. We get items grouped by rate. + for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): + invoice_details = self.invoices.get(inv) + for rate, items in items_based_on_rate.items(): + # We pass the full item list to the row data function + row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, items) + + if self.filters.get("type_of_business") == "CDNR": + row.append("Y" if invoice_details.posting_date <= date(2017, 7, 1) else "N") + row.append("C" if invoice_details.return_against else "R") + + if taxable_value: + self.data.append(row) + + def get_b2c_data(self): + # This logic remains as it's for B2C sales + b2cs_output = {} + for inv, items_by_rate in self.items_based_on_tax_rate.items(): + invoice_details = self.invoices.get(inv) + for rate, items in items_by_rate.items(): + place_of_supply = invoice_details.get("place_of_supply") + ecommerce_gstin = invoice_details.get("ecommerce_gstin") + + b2cs_output.setdefault((rate, place_of_supply, ecommerce_gstin),{ + "place_of_supply": "", + "ecommerce_gstin": "", + "rate": "", + "taxable_value": 0, + "cess_amount": 0, + "type": "", + "invoice_number": invoice_details.get("invoice_number"), + "posting_date": invoice_details.get("posting_date"), + "invoice_value": invoice_details.get("base_grand_total"), + }) + + row = b2cs_output.get((rate, place_of_supply, ecommerce_gstin)) + row["place_of_supply"] = place_of_supply + row["ecommerce_gstin"] = ecommerce_gstin + row["rate"] = rate + + # *** FIX: Use new items list structure *** + taxable_value = 0 + for item in items: + taxable_value += flt(item.get('taxable_value')) + row["taxable_value"] += taxable_value + + cess_amount = 0 + for item in items: + cess_amount += flt(item.get('cess_amount')) + row["cess_amount"] += cess_amount + # *** END FIX *** + + row["type"] = "E" if ecommerce_gstin else "OE" + + for key, value in iteritems(b2cs_output): + self.data.append(value) + + + def get_row_data_for_invoice(self, invoice, invoice_details, tax_rate, items_at_this_rate): + row = [] + for fieldname in self.invoice_fields: + if self.filters.get("type_of_business") == "CDNR" and fieldname == "invoice_value": + row.append(abs(invoice_details.base_rounded_total) or abs(invoice_details.base_grand_total)) + elif fieldname == "invoice_value": + row.append(invoice_details.base_rounded_total or invoice_details.base_grand_total) + elif fieldname in ('posting_date', 'shipping_bill_date'): + # Handle None posting_date if it occurs + p_date = invoice_details.get(fieldname) + row.append(formatdate(p_date, 'dd-MMM-YY') if p_date else None) + elif fieldname == "export_type": + export_type = "WPAY" if invoice_details.get(fieldname)=="With Payment of Tax" else "WOPAY" + row.append(export_type) + else: + row.append(invoice_details.get(fieldname)) + + # *** FIX 5: Calculate taxable_value from the items *** + # `items_at_this_rate` is a list of item dicts + taxable_value = 0 + for item in items_at_this_rate: + taxable_value += flt(item.get('taxable_value')) + + row += [tax_rate or 0, taxable_value] + + # CESS is now summed in get_data() of the child report + # We just add a placeholder if the column exists + for column in self.other_columns: + if column.get('fieldname') == 'cess_amount': + # Calculate cess for this specific rate + cess_at_this_rate = 0 + for item in items_at_this_rate: + cess_at_this_rate += flt(item.get('cess_amount')) + row.append(cess_at_this_rate) + + return row, taxable_value + + def get_invoice_data(self): + self.invoices = frappe._dict() + conditions = self.get_conditions() + invoice_data = frappe.db.sql(""" + select + {select_columns} + from `tab{doctype}` + where docstatus = 1 {where_conditions} + and is_opening = 'No' + order by posting_date desc + """.format(select_columns=self.select_columns, doctype=self.doctype, + where_conditions=conditions), self.filters, as_dict=1) + + for d in invoice_data: + self.invoices.setdefault(d.invoice_number, d) + + def get_conditions(self): + conditions = "" + + for opts in (("company", " and company=%(company)s"), + ("from_date", " and posting_date>=%(from_date)s"), + ("to_date", " and posting_date<=%(to_date)s"), + ("company_address", " and company_address=%(company_address)s")): + if self.filters.get(opts[0]): + conditions += opts[1] + + # This logic is for GSTR-1 (Sales) + if self.doctype == "Sales Invoice": + if self.filters.get("type_of_business") == "B2B": + conditions += "and ifnull(gst_category, '') in ('Registered Regular', 'Deemed Export', 'SEZ') and is_return != 1" + + if self.filters.get("type_of_business") in ("B2C Large", "B2C Small"): + b2c_limit = frappe.db.get_single_value('GST Settings', 'b2c_limit') + if not b2c_limit: + frappe.throw(_("Please set B2C Limit in GST Settings.")) + + if self.filters.get("type_of_business") == "B2C Large": + conditions += """ and ifnull(SUBSTR(place_of_supply, 1, 2),'') != ifnull(SUBSTR(company_gstin, 1, 2),'') + and grand_total > {0} and is_return != 1 and gst_category ='Unregistered' """.format(flt(b2c_limit)) + + elif self.filters.get("type_of_business") == "B2C Small": + conditions += """ and ( + SUBSTR(place_of_supply, 1, 2) = SUBSTR(company_gstin, 1, 2) + or grand_total <= {0}) and is_return != 1 and gst_category ='Unregistered' """.format(flt(b2c_limit)) + + elif self.filters.get("type_of_business") == "CDNR": + conditions += """ and is_return = 1 """ + + elif self.filters.get("type_of_business") == "EXPORT": + conditions += """ and is_return !=1 and gst_category = 'Overseas' """ + + # This logic is for GSTR-2 (Purchases) + elif self.doctype == "Purchase Invoice": + if self.filters.get("type_of_business") == "B2B": + conditions += "and ifnull(gst_category, '') in ('Registered Regular', 'Deemed Export', 'SEZ') and is_return != 1" + elif self.filters.get("type_of_business") == "CDNR": + conditions += """ and is_return = 1 """ + + return conditions + + def get_all_invoice_items(self): + """ + *** NEW FUNCTION (FIX 4) *** + Get all item details at once and store them. + We now fetch the fields we fixed in the database. + """ + self.invoice_items_details = frappe._dict() + + item_fields = [ + "parent", "item_code", "taxable_value", "base_net_amount", + "igst_rate", "igst_amount", + "cgst_rate", "cgst_amount", + "sgst_rate", "sgst_amount", + "cess_rate", "cess_amount" + ] + + # Ensure we have invoices to query + if not self.invoices: + return + + items = frappe.db.sql(""" + select {fields} + from `tab{doctype} Item` + where parent in ({invoices}) + """.format( + fields=", ".join(item_fields), + doctype=self.doctype, + invoices=', '.join(['%s']*len(self.invoices)) + ), tuple(self.invoices), as_dict=1) + + for d in items: + self.invoice_items_details.setdefault(d.parent, []).append(d) + + def get_tax_rates_from_tax_table(self): + """ + *** NEW FUNCTION (FIX 4) *** + Get tax rates from the tax table and map items to them. + This replaces the complex 'get_items_based_on_tax_rate' logic. + """ + self.items_based_on_tax_rate = {} + self.invoice_cess = frappe._dict() + self.cgst_sgst_invoices = [] + self.igst_invoices = [] # *** FIX: Initialize igst_invoices here *** + + if not self.invoices: + return + + # *** THIS IS THE FIX for the SQL Error *** + # 1. Create the list of placeholders + placeholders = ', '.join(['%s'] * len(self.invoices.keys())) + + # 2. Format the query string with table name and placeholders + query = """ + select parent, account_head, rate + from `tab{tax_doctype}` + where + parenttype = %s and docstatus = 1 + and parent in ({parent_placeholders}) + """.format( + tax_doctype=self.tax_doctype, + parent_placeholders=placeholders + ) + + # 3. Create the list of values + values = [self.doctype] + list(self.invoices.keys()) + + # 4. Execute the query + tax_details = frappe.db.sql(query, tuple(values), as_dict=1) + # *** END OF FIX *** + + for tax in tax_details: + parent = tax.parent + account = tax.account_head + rate = flt(tax.rate) + + # Identify CESS + if account in self.gst_accounts.cess_account: + # We sum up CESS per invoice from items later + continue + + # Identify tax type + is_igst = account in self.gst_accounts.igst_account + is_cgst_sgst = account in self.gst_accounts.cgst_account or account in self.gst_accounts.sgst_account + + if not (is_igst or is_cgst_sgst): + continue # Skip non-gst accounts + + if is_cgst_sgst and parent not in self.cgst_sgst_invoices: + self.cgst_sgst_invoices.append(parent) + + # *** FIX: Populate self.igst_invoices *** + if is_igst and parent not in self.igst_invoices: + self.igst_invoices.append(parent) + # *** END OF FIX *** + + # The "rate" in the report is the *combined* rate + # For CGST/SGST, the table rate is 9, so we store 18 + report_rate = rate * 2 if is_cgst_sgst else rate + + # Get all items for this invoice + invoice_items = self.invoice_items_details.get(parent, []) + + # Find items that match this tax + items_for_this_rate = [] + for item in invoice_items: + item_rate = flt(item.igst_rate) or flt(item.cgst_rate) or flt(item.sgst_rate) + + # if it's cgst, we compare 9 with 9 + if is_cgst_sgst and flt(item.cgst_rate) == rate: + items_for_this_rate.append(item) + # if it's igst, we compare 18 with 18 + elif is_igst and flt(item.igst_rate) == rate: + items_for_this_rate.append(item) + + if items_for_this_rate: + # Group items by the combined rate + self.items_based_on_tax_rate.setdefault(parent, {}).setdefault(report_rate, []).extend(items_for_this_rate) + + # Handle Nil Rated / Exempt items (where no tax row exists) + for inv, items in self.invoice_items_details.items(): + for item in items: + rate_sum = flt(item.igst_rate) + flt(item.cgst_rate) + flt(item.sgst_rate) + if rate_sum == 0: + self.items_based_on_tax_rate.setdefault(inv, {}).setdefault(0.0, []).append(item) + + def get_columns(self): + # *** FIX 6: Always define self.invoice_columns *** + self.invoice_columns = [] + self.tax_columns = [ + { + "fieldname": "rate", + "label": "Rate", + "fieldtype": "Int", + "width": 60 + }, + { + "fieldname": "taxable_value", + "label": "Taxable Value", + "fieldtype": "Currency", + "width": 100 + } + ] + self.other_columns = [] + + if self.filters.get("type_of_business") == "B2B": + self.invoice_columns = [ + { + "fieldname": "customer_gstin", + "label": "GSTIN/UIN of Recipient", + "fieldtype": "Data", + "width": 150 + }, + { + "fieldname": "customer_name", + "label": "Receiver Name", + "fieldtype": "Data", + "width":100 + }, + { + "fieldname": "invoice_number", + "label": "Invoice Number", + "fieldtype": "Link", + "options": "Sales Invoice", + "width":100 + }, + { + "fieldname": "posting_date", + "label": "Invoice date", + "fieldtype": "Data", + "width":80 + }, + { + "fieldname": "invoice_value", + "label": "Invoice Value", + "fieldtype": "Currency", + "width":100 + }, + { + "fieldname": "place_of_supply", + "label": "Place Of Supply", + "fieldtype": "Data", + "width":100 + }, + { + "fieldname": "reverse_charge", + "label": "Reverse Charge", + "fieldtype": "Data" + }, + { + "fieldname": "gst_category", + "label": "Invoice Type", + "fieldtype": "Data" + }, + { + "fieldname": "ecommerce_gstin", + "label": "E-Commerce GSTIN", + "fieldtype": "Data", + "width":120 + } + ] + self.other_columns = [ + { + "fieldname": "cess_amount", + "label": "Cess Amount", + "fieldtype": "Currency", + "width": 100 + } + ] + + elif self.filters.get("type_of_business") == "B2C Large": + self.invoice_columns = [ + { + "fieldname": "invoice_number", + "label": "Invoice Number", + "fieldtype": "Link", + "options": "Sales Invoice", + "width": 120 + }, + { + "fieldname": "posting_date", + "label": "Invoice date", + "fieldtype": "Data", + "width": 100 + }, + { + "fieldname": "invoice_value", + "label": "Invoice Value", + "fieldtype": "Currency", + "width": 100 + }, + { + "fieldname": "place_of_supply", + "label": "Place Of Supply", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "ecommerce_gstin", + "label": "E-Commerce GSTIN", + "fieldtype": "Data", + "width": 130 + } + ] + self.other_columns = [ + { + "fieldname": "cess_amount", + "label": "Cess Amount", + "fieldtype": "Currency", + "width": 100 + } + ] + elif self.filters.get("type_of_business") == "CDNR": + self.invoice_columns = [ + { + "fieldname": "customer_gstin", + "label": "GSTIN/UIN of Recipient", + "fieldtype": "Data", + "width": 150 + }, + { + "fieldname": "customer_name", + "label": "Receiver Name", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "return_against", + "label": "Invoice/Advance Receipt Number", + "fieldtype": "Link", + "options": "Sales Invoice", + "width": 120 + }, + { + "fieldname": "posting_date", + "label": "Invoice/Advance Receipt date", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "invoice_number", + "label": "Invoice/Advance Receipt Number", + "fieldtype": "Link", + "options": "Sales Invoice", + "width":120 + }, + { + "fieldname": "reason_for_issuing_document", + "label": "Reason For Issuing document", + "fieldtype": "Data", + "width": 140 + }, + { + "fieldname": "place_of_supply", + "label": "Place Of Supply", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "invoice_value", + "label": "Invoice Value", + "fieldtype": "Currency", + "width": 120 + } + ] + self.other_columns = [ + { + "fieldname": "cess_amount", + "label": "Cess Amount", + "fieldtype": "Currency", + "width": 100 + }, + { + "fieldname": "pre_gst", + "label": "PRE GST", + "fieldtype": "Data", + "width": 80 + }, + { + "fieldname": "document_type", + "label": "Document Type", + "fieldtype": "Data", + "width": 80 + } + ] + elif self.filters.get("type_of_business") == "B2C Small": + self.invoice_columns = [ + { + "fieldname": "place_of_supply", + "label": "Place Of Supply", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "ecommerce_gstin", + "label": "E-Commerce GSTIN", + "fieldtype": "Data", + "width": 130 + } + ] + self.other_columns = [ + { + "fieldname": "cess_amount", + "label": "Cess Amount", + "fieldtype": "Currency", + "width": 100 + }, + { + "fieldname": "type", + "label": "Type", + "fieldtype": "Data", + "width": 50 + } + ] + elif self.filters.get("type_of_business") == "EXPORT": + self.invoice_columns = [ + { + "fieldname": "export_type", + "label": "Export Type", + "fieldtype": "Data", + "width":120 + }, + { + "fieldname": "invoice_number", + "label": "Invoice Number", + "fieldtype": "Link", + "options": "Sales Invoice", + "width":120 + }, + { + "fieldname": "posting_date", + "label": "Invoice date", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "invoice_value", + "label": "Invoice Value", + "fieldtype": "Currency", + "width": 120 + }, + { + "fieldname": "port_code", + "label": "Port Code", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "shipping_bill_number", + "label": "Shipping Bill Number", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "shipping_bill_date", + "label": "Shipping Bill Date", + "fieldtype": "Data", + "width": 120 + } + ] + + # This is the line that gets called by the child report + # If no 'type_of_business' filter exists, self.invoice_columns is empty + # We must add a default definition + if not self.invoice_columns: + self.invoice_columns = [] # Ensure it's at least an empty list + + self.columns = self.invoice_columns + self.tax_columns + self.other_columns + +@frappe.whitelist() +def get_json(filters, report_name, data): + filters = json.loads(filters) + report_data = json.loads(data) + gstin = get_company_gstin_number(filters["company"]) + + fp = "%02d%s" % (getdate(filters["to_date"]).month, getdate(filters["to_date"]).year) + + gst_json = {"gstin": "", "version": "GST2.2.9", + "hash": "hash", "gstin": gstin, "fp": fp} + + res = {} + if filters["type_of_business"] == "B2B": + for item in report_data[:-1]: + res.setdefault(item["customer_gstin"], {}).setdefault(item["invoice_number"],[]).append(item) + + out = get_b2b_json(res, gstin) + gst_json["b2b"] = out + + elif filters["type_of_business"] == "B2C Large": + for item in report_data[:-1]: + res.setdefault(item["place_of_supply"], []).append(item) + + out = get_b2cl_json(res, gstin) + gst_json["b2cl"] = out + + elif filters["type_of_business"] == "B2C Small": + out = get_b2cs_json(report_data[:-1], gstin) + gst_json["b2cs"] = out + + elif filters["type_of_business"] == "EXPORT": + for item in report_data[:-1]: + res.setdefault(item["export_type"], []).append(item) + + out = get_export_json(res) + gst_json["exp"] = out + + return { + 'report_name': report_name, + 'report_type': filters['type_of_business'], + 'data': gst_json + } + +def get_b2b_json(res, gstin): + inv_type, out = {"Registered Regular": "R", "Deemed Export": "DE", "URD": "URD", "SEZ": "SEZ"}, [] + for gst_in in res: + b2b_item, inv = {"ctin": gst_in, "inv": []}, [] + if not gst_in: continue + + for number, invoice in iteritems(res[gst_in]): + if not invoice[0]["place_of_supply"]: + frappe.throw(_("""{0} not entered in Invoice {1}. + Please update and try again""").format(frappe.bold("Place Of Supply"), + frappe.bold(invoice[0]['invoice_number']))) + + inv_item = get_basic_invoice_detail(invoice[0]) + inv_item["pos"] = "%02d" % int(invoice[0]["place_of_supply"].split('-')[0]) + inv_item["rchrg"] = invoice[0]["reverse_charge"] + inv_item["inv_typ"] = inv_type.get(invoice[0].get("gst_category", ""),"") + + if inv_item["pos"]=="00": continue + inv_item["itms"] = [] + + for item in invoice: + inv_item["itms"].append(get_rate_and_tax_details(item, gstin)) + + inv.append(inv_item) + + if not inv: continue + b2b_item["inv"] = inv + out.append(b2b_item) + + return out + +def get_b2cs_json(data, gstin): + + company_state_number = gstin[0:2] + + out = [] + for d in data: + if not d.get("place_of_supply"): + frappe.throw(_("""{0} not entered in some invoices. + Please update and try again""").format(frappe.bold("Place Of Supply"))) + + pos = d.get('place_of_supply').split('-')[0] + tax_details = {} + + rate = d.get('rate', 0) + tax = flt((d["taxable_value"]*rate)/100.0, 2) + + if company_state_number == pos: + tax_details.update({"camt": flt(tax/2.0, 2), "samt": flt(tax/2.0, 2)}) + else: + tax_details.update({"iamt": tax}) + + inv = { + "sply_ty": "INTRA" if company_state_number == pos else "INTER", + "pos": pos, + "typ": d.get('type'), + "txval": flt(d.get('taxable_value'), 2), + "rt": rate, + "iamt": flt(tax_details.get('iamt'), 2), + "camt": flt(tax_details.get('camt'), 2), + "samt": flt(tax_details.get('samt'), 2), + "csamt": flt(d.get('cess_amount'), 2) + } + + if d.get('type') == "E" and d.get('ecommerce_gstin'): + inv.update({ + "etin": d.get('ecommerce_gstin') + }) + + out.append(inv) + + return out + +def get_b2cl_json(res, gstin): + out = [] + for pos in res: + if not pos: + frappe.throw(_("""{0} not entered in some invoices. + Please update and try again""").format(frappe.bold("Place Of Supply"))) + + b2cl_item, inv = {"pos": "%02d" % int(pos.split('-')[0]), "inv": []}, [] + + for row in res[pos]: + inv_item = get_basic_invoice_detail(row) + if row.get("sale_from_bonded_wh"): + inv_item["inv_typ"] = "CBW" + + inv_item["itms"] = [get_rate_and_tax_details(row, gstin)] + + inv.append(inv_item) + + b2cl_item["inv"] = inv + out.append(b2cl_item) + + return out + +def get_export_json(res): + out = [] + for exp_type in res: + exp_item, inv = {"exp_typ": exp_type, "inv": []}, [] + + for row in res[exp_type]: + inv_item = get_basic_invoice_detail(row) + inv_item["itms"] = [{ + "txval": flt(row["taxable_value"], 2), + "rt": row["rate"] or 0, + "iamt": 0, + "csamt": 0 + }] + + inv.append(inv_item) + + exp_item["inv"] = inv + out.append(exp_item) + + return out + +def get_basic_invoice_detail(row): + return { + "inum": row["invoice_number"], + "idt": getdate(row["posting_date"]).strftime('%d-%m-%Y'), + "val": flt(row["invoice_value"], 2) + } + +def get_rate_and_tax_details(row, gstin): + itm_det = {"txval": flt(row["taxable_value"], 2), + "rt": row["rate"], + "csamt": (flt(row.get("cess_amount"), 2) or 0) + } + + # calculate rate + num = 1 if not row["rate"] else "%d%02d" % (row["rate"], 1) + rate = row.get("rate") or 0 + + # calculate tax amount added + tax = flt((row["taxable_value"]*rate)/100.0, 2) + + # *** FIX: Check customer_gstin, not place_of_supply *** + if row.get("customer_gstin") and gstin[0:2] == row["customer_gstin"][0:2]: + itm_det.update({"camt": flt(tax/2.0, 2), "samt": flt(tax/2.0, 2)}) + else: + itm_det.update({"iamt": tax}) + + return {"num": int(num), "itm_det": itm_det} + +def get_company_gstin_number(company): + filters = [ + ["is_your_company_address", "=", 1], + ["Dynamic Link", "link_doctype", "=", "Company"], + ["Dynamic Link", "link_name", "=", company], + ["Dynamic Link", "parenttype", "=", "Address"], + ] + + gstin = frappe.get_all("Address", filters=filters, fields=["gstin"]) + + if gstin: + return gstin[0]["gstin"] + else: + frappe.throw(_("Please set valid GSTIN No. in Company Address for company {0}".format( + frappe.bold(company) + ))) + +@frappe.whitelist() +def download_json_file(): + ''' download json content in a file ''' + data = frappe._dict(frappe.local.form_dict) + frappe.response['filename'] = frappe.scrub("{0} {1}".format(data['report_name'], data['report_type'])) + '.json' + frappe.response['filecontent'] = data['data'] + frappe.response['content_type'] = 'application/json' + frappe.response['type'] = 'download' \ No newline at end of file From 4213da695fcc4da35ef8dc282025c1dbff9dc2e7 Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Sun, 23 Nov 2025 07:21:43 +0000 Subject: [PATCH 30/52] feat(doc): script execution docs --- .../migration_scripts/docs_execution_order.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 rohit_common/migration_scripts/docs_execution_order.txt diff --git a/rohit_common/migration_scripts/docs_execution_order.txt b/rohit_common/migration_scripts/docs_execution_order.txt new file mode 100644 index 0000000..fc3274b --- /dev/null +++ b/rohit_common/migration_scripts/docs_execution_order.txt @@ -0,0 +1,12 @@ +Step 1: Fix Company GSTIN +bench --site [your.site] execute rohit_common.migration_scripts.repopulate_company_gstin.execute +Step 2: Fix Invoice Headers +bench --site [your.site] execute rohit_common.migration_scripts.patch_invoices.execute --kwargs "{'dry_run': False}" +Step 3: Fix Sales Invoice Data +bench --site [your.site] execute rohit_common.migration_scripts.combined_gst_fix.execute --kwargs "{'dry_run': False, 'write_csv': False}" +Step 4: Fix Sales Ledger +bench --site [your.site] execute rohit_common.migration_scripts.create_gst_adjustment_jes.execute --kwargs "{'company': 'Rohit Industries Group Private Ltd', 'company_gstin': '06AAACR1567J1ZC', 'dry_run': False}" +Step 5: Fix Purchase Invoice Data +bench --site [your.site] execute rohit_common.migration_scripts.fix_purchase_invoices_gst.execute --kwargs "{'dry_run': False}" +Step 6: Fix Purchase Ledger +bench --site [your.site] execute rohit_common.migration_scripts.create_purchase_gst_adjustment_jes.execute --kwargs "{'company': 'Rohit Industries Group Private Ltd', 'company_gstin': '06AAACR1567J1ZC', 'dry_run': False}" \ No newline at end of file From 0bdae8b4d4a254479e7f5882aa1be3d94f307668 Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Tue, 25 Nov 2025 06:49:31 +0000 Subject: [PATCH 31/52] fix: for latest migration issue --- pyproject.toml | 1 - rohit_common/before_migrate_patches.py | 110 +++++++++++++++++++++---- rohit_common/hooks.py | 2 +- 3 files changed, 97 insertions(+), 16 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1017d25..ed573fb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,5 +10,4 @@ dependencies = [ # Core dependencies "phonenumbers==8.13.13", "responses>=0.25.8", - "india-compliance @ git+https://github.com/resilient-tech/india-compliance.git#version-15", ] diff --git a/rohit_common/before_migrate_patches.py b/rohit_common/before_migrate_patches.py index ba30312..7d906f2 100644 --- a/rohit_common/before_migrate_patches.py +++ b/rohit_common/before_migrate_patches.py @@ -1,22 +1,104 @@ # -*- coding: utf-8 -*- -from rohit_common.patches.run_unwanted_patches import run_unwanted_patches - import frappe -import erpnext -def execute (): + +# avoid importing erpnext unless tables exist +try: + import erpnext +except Exception: + erpnext = None + +def execute(): + # Don't run heavy ORM logic if the DB/schema isn't ready run_unwanted_patches() add_default_company_fy() + +def table_exists(table_name: str) -> bool: + """ + Return True if a physical SQL table `table_name` exists. + `table_name` should be the exact table name e.g. 'tabFiscal Year'. + """ + try: + # most frappe DB backends support this helper + if hasattr(frappe.db, "table_exists"): + return frappe.db.table_exists(table_name) + except Exception: + # fall through to basic SQL check + pass + + try: + res = frappe.db.sql("SHOW TABLES LIKE %s", (table_name,)) + return bool(res) + except Exception: + return False + + +def run_unwanted_patches(): + # keep existing behavior (import inside function to avoid imports at module load) + try: + from rohit_common.patches.run_unwanted_patches import run_unwanted_patches as _rup + _rup() + except Exception as e: + # If patch runner can't be imported/run at this stage, log and continue. + print("run_unwanted_patches() skipped (not available at this stage):", e) + + def add_default_company_fy(): - fyd = frappe.db.get_list('Fiscal Year', fields=['name'], order_by='year_start_date asc') - def_comp = erpnext.get_default_company() - for fy in fyd: - fyc = frappe.db.get_list("Fiscal Year Company", filters={"parent": fy.name, - "parentfield": "companies", - "parenttype": "Fiscal Year"}) - if not fyc: - print(f"No Company defined for FY {fy.name} so setting to Default Company {def_comp}") - fydoc = frappe.get_doc("Fiscal Year", fy.name) + # guard: ensure SQL tables exist before calling any ORM that triggers permission/meta resolution + if not table_exists("tabFiscal Year"): + print("Skipping add_default_company_fy(): table `tabFiscal Year` is not present yet.") + return + + # If you call erpnext.get_default_company(), ensure Company table exists + if erpnext is None or not table_exists("tabCompany"): + print("Skipping setting default company for Fiscal Year: Company table / erpnext not available yet.") + return + + # safe to query the fiscal years directly via SQL (avoids permission checks) + try: + rows = frappe.db.sql( + "SELECT `name` FROM `tabFiscal Year` ORDER BY `year_start_date` ASC", + as_dict=True, + ) + except Exception as e: + print("Failed to read `tabFiscal Year` via SQL; skipping. Error:", e) + return + + def_comp = None + try: + # call erpnext helper now that erpnext import succeeded and Company table exists + def_comp = erpnext.get_default_company() + except Exception as e: + print("erpnext.get_default_company() failed; skipping adding default company to Fiscal Year. Error:", e) + return + + for r in rows: + fy_name = r.get("name") + if not fy_name: + continue + + # check if there is already a Fiscal Year Company link — use a direct SQL check + try: + existing = frappe.db.sql( + """ + SELECT 1 FROM `tabFiscal Year Company` + WHERE parent=%s LIMIT 1 + """, + (fy_name,), + ) + except Exception as e: + print(f"Could not query Fiscal Year Company for {fy_name}; skipping. Error:", e) + continue + + if existing: + # already has a company -> nothing to do + continue + + try: + fydoc = frappe.get_doc("Fiscal Year", fy_name) fydoc.append("companies", {"company": def_comp}) - fydoc.save() \ No newline at end of file + fydoc.save() + print(f"Set default company {def_comp} for Fiscal Year {fy_name}") + except Exception as e: + print(f"Failed to append company for Fiscal Year {fy_name}: {e}") diff --git a/rohit_common/hooks.py b/rohit_common/hooks.py index 12d14de..9f9e7fd 100644 --- a/rohit_common/hooks.py +++ b/rohit_common/hooks.py @@ -12,7 +12,7 @@ app_version = "0.0.1" hide_in_installer = True -required_apps = ["frappe/erpnext", "resilient-tech/india-compliance"] +required_apps = ["frappe/erpnext", "https://github.com/adityaduggal/india_compliance.git@develop"] # Fixtures help https://frappeframework.com/docs/v13/user/en/python-api/hooks#fixtures From 718d300dda7c02905bd54d5009005f488b368889 Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Tue, 2 Dec 2025 10:58:50 +0530 Subject: [PATCH 32/52] fix: update migration scripts for local execution and add gl entry update script (#18) --- .../docs_execution_order.txt | 18 +-- .../migration_scripts/gl_entry_update.py | 128 ++++++++++++++++++ .../rohit_common/validations/docshare.py | 1 + 3 files changed, 139 insertions(+), 8 deletions(-) create mode 100644 rohit_common/migration_scripts/gl_entry_update.py diff --git a/rohit_common/migration_scripts/docs_execution_order.txt b/rohit_common/migration_scripts/docs_execution_order.txt index fc3274b..35af948 100644 --- a/rohit_common/migration_scripts/docs_execution_order.txt +++ b/rohit_common/migration_scripts/docs_execution_order.txt @@ -1,12 +1,14 @@ Step 1: Fix Company GSTIN -bench --site [your.site] execute rohit_common.migration_scripts.repopulate_company_gstin.execute +bench --site development.localhost execute rohit_common.migration_scripts.repopulate_company_gstin.execute #1 +Step 7: Fix GL Entry Data +bench --site development.localhost execute rohit_common.migration_scripts.gl_entry_update.execute --kwargs "{'dry_run': False, 'batch_size': 2000}" #2 Step 2: Fix Invoice Headers -bench --site [your.site] execute rohit_common.migration_scripts.patch_invoices.execute --kwargs "{'dry_run': False}" +bench --site development.localhost execute rohit_common.migration_scripts.patch_invoices.execute --kwargs "{'dry_run': False}" #3 Step 3: Fix Sales Invoice Data -bench --site [your.site] execute rohit_common.migration_scripts.combined_gst_fix.execute --kwargs "{'dry_run': False, 'write_csv': False}" -Step 4: Fix Sales Ledger -bench --site [your.site] execute rohit_common.migration_scripts.create_gst_adjustment_jes.execute --kwargs "{'company': 'Rohit Industries Group Private Ltd', 'company_gstin': '06AAACR1567J1ZC', 'dry_run': False}" +bench --site development.localhost execute rohit_common.migration_scripts.combined_gst_fix.execute --kwargs "{'dry_run': False, 'write_csv': False}" #4 +# Step 4: Fix Sales Ledger +# bench --site development.localhost execute rohit_common.migration_scripts.create_gst_adjustment_jes.execute --kwargs "{'company': 'Rohit Industries Group Private Ltd', 'company_gstin': '06AAACR1567J1ZC', 'dry_run': False}" Step 5: Fix Purchase Invoice Data -bench --site [your.site] execute rohit_common.migration_scripts.fix_purchase_invoices_gst.execute --kwargs "{'dry_run': False}" -Step 6: Fix Purchase Ledger -bench --site [your.site] execute rohit_common.migration_scripts.create_purchase_gst_adjustment_jes.execute --kwargs "{'company': 'Rohit Industries Group Private Ltd', 'company_gstin': '06AAACR1567J1ZC', 'dry_run': False}" \ No newline at end of file +bench --site development.localhost execute rohit_common.migration_scripts.fix_purchase_invoices_gst.execute --kwargs "{'dry_run': False}" #5 +# Step 6: Fix Purchase Ledger +# bench --site development.localhost execute rohit_common.migration_scripts.create_purchase_gst_adjustment_jes.execute --kwargs "{'company': 'Rohit Industries Group Private Ltd', 'company_gstin': '06AAACR1567J1ZC', 'dry_run': False}" \ No newline at end of file diff --git a/rohit_common/migration_scripts/gl_entry_update.py b/rohit_common/migration_scripts/gl_entry_update.py new file mode 100644 index 0000000..d07694d --- /dev/null +++ b/rohit_common/migration_scripts/gl_entry_update.py @@ -0,0 +1,128 @@ +import frappe + +def repopulate_gl_entry_company_gstin(dry_run=True, batch_size=1000, limit=None): + """ + Populate GL Entry.company_gstin from Company (common GSTIN fields). + - dry_run=True : only prints what would be changed + - batch_size : number of updates before commit + - limit : optional integer - limit number of entries processed (for testing) + Returns a summary dict. + """ + # Important for GL Entries to bypass some immutable checks during migration + frappe.flags.in_migrate = True + + possible_company_gstin_fields = ["company_gstin", "gstin", "gstin_number", "tax_id", "tax_id_number"] + + # 1. Build company -> gstin mapping + print("Building Company GSTIN Map...") + company_gstin_map = {} + for c in frappe.get_all("Company", fields=["name"]): + cname = c.get("name") + try: + comp_doc = frappe.get_doc("Company", cname) + except Exception: + continue + gst = None + for f in possible_company_gstin_fields: + if hasattr(comp_doc, f): + val = comp_doc.get(f) + if val: + gst = val.strip() + break + if gst: + company_gstin_map[cname] = gst + + # 2. Fetch GL Entries where company_gstin is empty or null + print("Fetching GL Entries with missing GSTIN...") + + limit_clause = f"LIMIT {int(limit)}" if limit else "" + + # Using SQL directly for fetching is faster for GL Entry due to table size + gl_entries = frappe.db.sql( + f""" + SELECT name, company, posting_date + FROM `tabGL Entry` + WHERE IFNULL(company_gstin, '') = '' + {limit_clause} + """, + as_dict=True, + ) + + total = len(gl_entries) + print(f"Found {total} GL Entry(s) with empty company_gstin.") + + if total == 0: + return {"total_found": 0, "updated": 0, "skipped": 0, "errors": []} + + updated = 0 + skipped = 0 + errors = [] + counter = 0 + + for gle in gl_entries: + counter += 1 + name = gle.get("name") + company = gle.get("company") + posting_date = gle.get("posting_date") + + if not company: + skipped += 1 + continue + + # Get GSTIN from map + gst_value = company_gstin_map.get(company) + + # If not in map, try last ditch fetch (rarely needed if map built correctly) + if not gst_value: + skipped += 1 + print(f"[{counter}/{total}] SKIP {name} — Company '{company}' has no GSTIN found.") + continue + + if dry_run: + # Print only every 100th line to avoid spamming console on huge GL tables + if counter % 100 == 0 or counter < 20: + print(f"[{counter}/{total}] Would update {name}: {company} -> {gst_value}") + else: + try: + # update_modified=False preserves the original modification date of the ledger entry + frappe.db.set_value("GL Entry", name, "company_gstin", gst_value, update_modified=False) + updated += 1 + except Exception as e: + errors.append((name, str(e))) + print(f" ERROR updating {name}: {e}") + + if updated and (updated % batch_size == 0): + frappe.db.commit() + print(f" Committed batch up to {updated} updates...") + + if not dry_run: + frappe.db.commit() + print("Final commit done.") + + print("Done. Summary:") + print(f" Total found: {total}") + print(f" Updated: {updated}") + print(f" Skipped: {skipped}") + print(f" Errors: {len(errors)}") + + return { + "total_found": total, + "updated": updated, + "skipped": skipped, + "errors": errors, + } + +# bench execute entrypoint +def execute(dry_run=True, batch_size=1000, limit=None): + dry_run = bool(dry_run) + batch_size = int(batch_size) if batch_size else 1000 + limit = int(limit) if limit else None + return repopulate_gl_entry_company_gstin(dry_run=dry_run, batch_size=batch_size, limit=limit) + +# Command to run (Dry Run): +# bench --site [your-site] execute path.to.script.execute --kwargs "{'dry_run': True, 'limit': 100}" + +# Command to run (Actual): +# bench --site [your-site] execute path.to.script.execute --kwargs "{'dry_run': False, 'batch_size': 2000}" + +# bench --site development.localhost execute rohit_common.migration_scripts.gl_entry_update.execute --kwargs "{'dry_run': False, 'batch_size': 2000}" \ No newline at end of file diff --git a/rohit_common/rohit_common/validations/docshare.py b/rohit_common/rohit_common/validations/docshare.py index 6cc3b36..5c3d41c 100644 --- a/rohit_common/rohit_common/validations/docshare.py +++ b/rohit_common/rohit_common/validations/docshare.py @@ -12,6 +12,7 @@ from __future__ import unicode_literals import frappe from frappe.utils.background_jobs import enqueue +from rohit_common.utils.rohit_common_utils import check_system_manager def on_trash(doc, method): From fe8b24e1e25914f0ccd379ec8968508a33597960 Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Mon, 8 Dec 2025 23:27:56 +0530 Subject: [PATCH 33/52] fix: clear tax import report (#19) * fix: clear tax report * fix: sales invoice * fix: merged both * fix: formatting --- .../clear_tax_import_format.py | 906 ++++++++-- .../rigpl_legacy_gstr1/rigpl_legacy_gstr1.py | 1550 ++++++++--------- 2 files changed, 1487 insertions(+), 969 deletions(-) diff --git a/rohit_common/rohit_common/report/clear_tax_import_format/clear_tax_import_format.py b/rohit_common/rohit_common/report/clear_tax_import_format/clear_tax_import_format.py index 80bad0f..e84d2a2 100644 --- a/rohit_common/rohit_common/report/clear_tax_import_format/clear_tax_import_format.py +++ b/rohit_common/rohit_common/report/clear_tax_import_format/clear_tax_import_format.py @@ -2,197 +2,773 @@ # For license information, please see license.txt from __future__ import unicode_literals -import frappe +import frappe, json +from frappe import _ +from frappe.utils import flt, formatdate, getdate from datetime import date from rohit_common.rohit_common.report.rigpl_legacy_gstr1.rigpl_legacy_gstr1 import Gstr1Report -from frappe.utils import flt + def execute(filters=None): return ClearTaxImport(filters).run() + class ClearTaxImport(Gstr1Report): def __init__(self, filters=None): super(ClearTaxImport, self).__init__(filters) self.filters = frappe._dict(filters or {}) self.columns = [] self.data = [] - self.doctype = filters.get("type") - - if filters.get("type") == 'Sales Invoice': - self.tax_doctype = "Sales Taxes and Charges" + self.doctype = self.filters.get("type") + self.tax_doctype = ( + "Sales Taxes and Charges" + if self.doctype == "Sales Invoice" + else "Purchase Taxes and Charges" + ) + + # --- DEFINE COLUMNS / SELECTS --- + # NOTE: base_net_total included in both doctypes; only used for Sales columns + if self.doctype == "Sales Invoice": self.select_columns = """ - name as invoice_number, - customer, - posting_date as posting_date_unformatted, - base_grand_total, - base_net_total, - taxes_and_charges, + name as invoice_number, customer as customer_name, posting_date, + base_grand_total, base_rounded_total, base_net_total, taxes_and_charges, COALESCE(NULLIF(customer_gstin,''), NULLIF(billing_address_gstin, '')) as customer_gstin, - place_of_supply, - ecommerce_gstin, - reverse_charge, - invoice_type, - return_against, - is_return, - export_type, - port_code, - shipping_bill_number, - shipping_bill_date, - reason_for_issuing_document, + place_of_supply, ecommerce_gstin, reverse_charge, invoice_type, + return_against, is_return, export_type, port_code, + shipping_bill_number, shipping_bill_date, reason_for_issuing_document, customer_address """ - elif filters.get("type") == 'Purchase Invoice': - self.tax_doctype = "Purchase Taxes and Charges" + elif self.doctype == "Purchase Invoice": self.select_columns = """ - name as invoice_number, - supplier, - posting_date as posting_date_unformatted, - bill_date, - bill_no, - taxes_and_charges, - base_grand_total, - base_net_total, - supplier_gstin, - place_of_supply, - ecommerce_gstin, - reverse_charge, - invoice_type, - return_against, - is_return, - export_type, - reason_for_issuing_document, - eligibility_for_itc + name as invoice_number, supplier as customer_name, posting_date, + bill_date, bill_no, taxes_and_charges, + base_grand_total, base_rounded_total, base_net_total, + supplier_gstin as customer_gstin, place_of_supply, ecommerce_gstin, + reverse_charge, invoice_type, return_against, is_return, + export_type, reason_for_issuing_document, eligibility_for_itc, + itc_integrated_tax, itc_central_tax, itc_state_tax, itc_cess_amount """ - def get_data(self): - # Use self.invoice_items_details if available (from fixed parent), otherwise fallback - items_source = getattr(self, "invoice_items_details", None) - if not items_source and hasattr(self, "invoices"): - items_source = {} - - for inv_name, invoice_details in self.invoices.items(): - items = items_source.get(inv_name, []) - - # Group items by rate - items_by_rate = {} - for item in items: - rate = flt(item.igst_rate) + flt(item.cgst_rate) + flt(item.sgst_rate) - items_by_rate.setdefault(rate, []).append(item) - - for rate, rate_items in items_by_rate.items(): - row, taxable_value = self.get_row_data_for_invoice(inv_name, invoice_details, rate, rate_items) - - # --- FILTER: Remove rows with no value --- - # This is the ONLY filter we need. It removes true duplicates/empty rows. - # We DO NOT filter by rate==0 , so valid 0% items will show. - if taxable_value <= 0: - continue - # ----------------------------------------- - - igst_paid = 0 - cgst_paid = 0 - sgst_paid = 0 - cess_paid = 0 - itc_igst = 0 - itc_cgst = 0 - itc_sgst = 0 - itc_cess = 0 - - for item in rate_items: - igst_paid += flt(item.igst_amount) - cgst_paid += flt(item.cgst_amount) - sgst_paid += flt(item.sgst_amount) - cess_paid += flt(item.cess_amount) - - if self.doctype == 'Purchase Invoice': - itc_igst += flt(item.igst_amount) - itc_cgst += flt(item.cgst_amount) - itc_sgst += flt(item.sgst_amount) - itc_cess += flt(item.cess_amount) - - if self.doctype == 'Purchase Invoice': - row += [ - igst_paid, cgst_paid, sgst_paid, cess_paid, - invoice_details.get('eligibility_for_itc') or 'All Other ITC', - itc_igst, itc_cgst, itc_sgst, itc_cess - ] - elif self.doctype == 'Sales Invoice': - if self.is_igst_invoice(inv_name): - row += [igst_paid, 0, 0] - else: - row += [0, cgst_paid, sgst_paid] - row.append(cess_paid) - - if self.filters.get("type_of_business") == "CDNR": - row.append("Y" if invoice_details.posting_date <= date(2017, 7, 1) else "N") - row.append("C" if invoice_details.return_against else "R") - - self.data.append(row) - - def is_igst_invoice(self, inv_name): - # Check if invoice is in the IGST list (populated by parent) - return hasattr(self, "igst_invoices") and inv_name in self.igst_invoices + def run(self): + self.get_columns() + self.gst_accounts = self.get_gst_accounts_safe() + self.get_invoice_data_custom() + + if self.invoices: + # Fetch items + self.get_invoice_items_custom() + # Map items to tax rates + self.get_items_based_on_tax_rate_custom() + # Build rows + self.invoice_fields = [d["fieldname"] for d in self.invoice_columns] + self.get_data_custom() + + return self.columns, self.data + + # ---------------------------------------------------------------------- + # COMMON: GST Accounts + # ---------------------------------------------------------------------- + def get_gst_accounts_safe(self): + accs = frappe._dict( + { + "cgst_account": [], + "sgst_account": [], + "igst_account": [], + "cess_account": [], + } + ) + gst_type = "Input" if self.doctype == "Purchase Invoice" else "Output" + try: + from india_compliance.gst_india.utils import get_gst_accounts_by_type + + res = get_gst_accounts_by_type(self.filters.company, gst_type) + if res: + if res.get("cgst_account"): + accs.cgst_account = res.get("cgst_account") + if res.get("sgst_account"): + accs.sgst_account = res.get("sgst_account") + if res.get("igst_account"): + accs.igst_account = res.get("igst_account") + if res.get("cess_account"): + accs.cess_account = res.get("cess_account") + except ImportError: + pass + # Ensure all are lists + for key in accs: + if not isinstance(accs[key], list): + accs[key] = [accs[key]] if accs[key] else [] + + return accs + + # ---------------------------------------------------------------------- + # COLUMNS + # ---------------------------------------------------------------------- def get_columns(self): - tax_val_col = { "fieldname": "taxable_value", "label": "Taxable Value", "fieldtype": "Currency", "width": 100 } - rate_col = { "fieldname": "rate", "label": "Rate", "fieldtype": "Int", "width": 60 } + tax_val_col = { + "fieldname": "taxable_value", + "label": "Taxable Value", + "fieldtype": "Currency", + "width": 100, + } + rate_col = {"fieldname": "rate", "label": "Rate", "fieldtype": "Int", "width": 60} + + self.tax_columns = [ + rate_col, + tax_val_col, + { + "fieldname": "integrated_tax_paid", + "label": "Integrated Tax Paid", + "fieldtype": "Currency", + "width": 100, + }, + { + "fieldname": "central_tax_paid", + "label": "Central Tax Paid", + "fieldtype": "Currency", + "width": 100, + }, + { + "fieldname": "state_tax_paid", + "label": "State/UT Tax Paid", + "fieldtype": "Currency", + "width": 100, + }, + { + "fieldname": "cess_amount", + "label": "Cess Paid", + "fieldtype": "Currency", + "width": 100, + }, + ] - if self.filters.get("type") == 'Sales Invoice': + # --- SALES COLUMNS --- + if self.doctype == "Sales Invoice": self.invoice_columns = [ - { "fieldname": "posting_date_unformatted", "label": "Invoice Date", "fieldtype": "Date", "width": 80 }, - { "fieldname": "invoice_number", "label": "Invoice Number", "fieldtype": "Link", "options": "Sales Invoice", "width": 120 }, - { "fieldname": "base_net_total", "label": "Net Total", "fieldtype": "Currency", "width": 80 }, - { "fieldname": "base_grand_total", "label": "Grand Total", "fieldtype": "Currency", "width": 80 }, - { "fieldname": "customer", "label": "Customer Link", "fieldtype": "Link", "options": "Customer", "width": 200 }, - { "fieldname": "taxes_and_charges", "label": "Tax Link", "fieldtype": "Link", "options": "Sales Taxes and Charges Template", "width": 150 }, - { "fieldname": "customer_gstin", "label": "Customer GSTIN", "fieldtype": "Data", "width": 120 }, - { "fieldname": "place_of_supply", "label": "Place of Supply", "fieldtype": "Data", "width": 120 }, - { "fieldname": "reverse_charge", "label": "Reverse Charge", "fieldtype": "Data", "width": 80 }, - { "fieldname": "invoice_type", "label": "Invoice Type", "fieldtype": "Data", "width": 80 }, - { "fieldname": "ecommerce_gstin", "label": "E-Comm GSTIN", "fieldtype": "Data", "width": 120 }, - { "fieldname": "reason_for_issuing_document", "label": "Reason", "fieldtype": "Data", "width": 120 }, - { "fieldname": "is_export", "label": "Is EXP", "fieldtype": "Data", "width": 30 }, - { "fieldname": "gst_paid_on_export", "label": "GST Paid on EXP", "fieldtype": "Data", "width": 30 }, - { "fieldname": "export_shb_no", "label": "EXP SHB #", "fieldtype": "Data", "width": 30 }, - { "fieldname": "export_shb_date", "label": "EXP SHB Date", "fieldtype": "Data", "width": 30 }, - { "fieldname": "export_destination_country_code", "label": "Exp Dest Country Code", "fieldtype": "Data", "width": 30 }, - { "fieldname": "customer_address", "label": "Billing Address Link", "fieldtype": "Link", "options": "Address", "width": 80 } - ] - self.tax_columns = [ - rate_col, tax_val_col, - { "fieldname": "integrated_tax_paid", "label": "Integrated Tax Paid", "fieldtype": "Currency", "width": 100 }, - { "fieldname": "central_tax_paid", "label": "Central Tax Paid", "fieldtype": "Currency", "width": 100 }, - { "fieldname": "state_tax_paid", "label": "State/UT Tax Paid", "fieldtype": "Currency", "width": 100 }, - { "fieldname": "cess_amount", "label": "Cess Paid", "fieldtype": "Currency", "width": 100 } + { + "fieldname": "posting_date", + "label": "Invoice Date", + "fieldtype": "Date", + "width": 80, + }, + { + "fieldname": "invoice_number", + "label": "Invoice Number", + "fieldtype": "Link", + "options": "Sales Invoice", + "width": 120, + }, + { + "fieldname": "base_net_total", + "label": "Net Total", + "fieldtype": "Currency", + "width": 80, + }, + { + "fieldname": "invoice_value", + "label": "Grand Total", + "fieldtype": "Currency", + "width": 80, + }, + { + "fieldname": "customer_name", + "label": "Customer Link", + "fieldtype": "Link", + "options": "Customer", + "width": 200, + }, + { + "fieldname": "taxes_and_charges", + "label": "Tax Link", + "fieldtype": "Link", + "options": "Sales Taxes and Charges Template", + "width": 150, + }, + { + "fieldname": "customer_gstin", + "label": "Customer GSTIN", + "fieldtype": "Data", + "width": 120, + }, + { + "fieldname": "place_of_supply", + "label": "Place of Supply", + "fieldtype": "Data", + "width": 120, + }, + { + "fieldname": "reverse_charge", + "label": "Reverse Charge", + "fieldtype": "Data", + "width": 80, + }, + { + "fieldname": "invoice_type", + "label": "Invoice Type", + "fieldtype": "Data", + "width": 80, + }, + { + "fieldname": "ecommerce_gstin", + "label": "E-Comm GSTIN", + "fieldtype": "Data", + "width": 120, + }, + { + "fieldname": "reason_for_issuing_document", + "label": "Reason", + "fieldtype": "Data", + "width": 120, + }, + { + "fieldname": "is_export", + "label": "Is EXP", + "fieldtype": "Data", + "width": 30, + }, + { + "fieldname": "gst_paid_on_export", + "label": "GST Paid on EXP", + "fieldtype": "Data", + "width": 30, + }, + { + "fieldname": "export_shb_no", + "label": "EXP SHB #", + "fieldtype": "Data", + "width": 30, + }, + { + "fieldname": "export_shb_date", + "label": "EXP SHB Date", + "fieldtype": "Data", + "width": 30, + }, + { + "fieldname": "export_destination_country_code", + "label": "Exp Dest Country Code", + "fieldtype": "Data", + "width": 30, + }, + { + "fieldname": "customer_address", + "label": "Billing Address Link", + "fieldtype": "Link", + "options": "Address", + "width": 80, + }, ] self.other_columns = [] - elif self.filters.get("type") == 'Purchase Invoice': + # --- PURCHASE COLUMNS --- + elif self.doctype == "Purchase Invoice": self.invoice_columns = [ - { "fieldname": "invoice_number", "label": "PI #", "fieldtype": "Link", "options": "Purchase Invoice", "width": 120 }, - { "fieldname": "posting_date_unformatted", "label": "PI Posting Date", "fieldtype": "Date", "width": 80 }, - { "fieldname": "bill_date", "label": "Supplier PI Date", "fieldtype": "Date", "width": 80 }, - { "fieldname": "bill_no", "label": "Supplier PI No", "fieldtype": "Data", "width": 80 }, - { "fieldname": "supplier", "label": "Supplier Link", "fieldtype": "Link", "options": "Supplier", "width": 200 }, - { "fieldname": "taxes_and_charges", "label": "Tax Link", "fieldtype": "Link", "options": "Purchase Taxes and Charges Template", "width": 150 }, - { "fieldname": "supplier_gstin", "label": "GSTIN of Supplier", "fieldtype": "Data", "width": 130 }, - { "fieldname": "place_of_supply", "label": "Place of Supply", "fieldtype": "Data", "width": 120 }, - { "fieldname": "invoice_value", "label": "Invoice Value", "fieldtype": "Currency", "width": 120 }, - { "fieldname": "reverse_charge", "label": "Reverse Charge", "fieldtype": "Data", "width": 80 }, - { "fieldname": "invoice_type", "label": "Invoice Type", "fieldtype": "Data", "width": 80 } + { + "fieldname": "invoice_number", + "label": "PI #", + "fieldtype": "Link", + "options": "Purchase Invoice", + "width": 120, + }, + { + "fieldname": "posting_date", + "label": "PI Posting Date", + "fieldtype": "Date", + "width": 80, + }, + { + "fieldname": "bill_date", + "label": "Supplier PI Date", + "fieldtype": "Date", + "width": 80, + }, + { + "fieldname": "bill_no", + "label": "Supplier PI No", + "fieldtype": "Data", + "width": 80, + }, + { + "fieldname": "customer_name", + "label": "Supplier Link", + "fieldtype": "Link", + "options": "Supplier", + "width": 200, + }, + { + "fieldname": "taxes_and_charges", + "label": "Tax Link", + "fieldtype": "Link", + "options": "Purchase Taxes and Charges Template", + "width": 150, + }, + { + "fieldname": "customer_gstin", + "label": "GSTIN of Supplier", + "fieldtype": "Data", + "width": 130, + }, + { + "fieldname": "place_of_supply", + "label": "Place of Supply", + "fieldtype": "Data", + "width": 120, + }, + { + "fieldname": "invoice_value", + "label": "Invoice Value", + "fieldtype": "Currency", + "width": 120, + }, + { + "fieldname": "reverse_charge", + "label": "Reverse Charge", + "fieldtype": "Data", + "width": 80, + }, + { + "fieldname": "invoice_type", + "label": "Invoice Type", + "fieldtype": "Data", + "width": 80, + }, ] - self.tax_columns = [ - rate_col, tax_val_col, - { "fieldname": "integrated_tax_paid", "label": "Integrated Tax Paid", "fieldtype": "Currency", "width": 100 }, - { "fieldname": "central_tax_paid", "label": "Central Tax Paid", "fieldtype": "Currency", "width": 100 }, - { "fieldname": "state_tax_paid", "label": "State/UT Tax Paid", "fieldtype": "Currency", "width": 100 }, - { "fieldname": "cess_amount", "label": "Cess Paid", "fieldtype": "Currency", "width": 100 }, - { "fieldname": "eligibility_for_itc", "label": "Eligibility For ITC", "fieldtype": "Data", "width": 100 }, - { "fieldname": "itc_integrated_tax", "label": "Availed ITC Integrated Tax", "fieldtype": "Currency", "width": 100 }, - { "fieldname": "itc_central_tax", "label": "Availed ITC Central Tax", "fieldtype": "Currency", "width": 100 }, - { "fieldname": "itc_state_tax", "label": "Availed ITC State/UT Tax", "fieldtype": "Currency", "width": 100 }, - { "fieldname": "itc_cess_amount", "label": "Availed ITC Cess ", "fieldtype": "Currency", "width": 100 } + self.other_columns = [ + { + "fieldname": "eligibility_for_itc", + "label": "Eligibility For ITC", + "fieldtype": "Data", + "width": 100, + }, + { + "fieldname": "itc_integrated_tax", + "label": "Availed ITC Integrated Tax", + "fieldtype": "Currency", + "width": 100, + }, + { + "fieldname": "itc_central_tax", + "label": "Availed ITC Central Tax", + "fieldtype": "Currency", + "width": 100, + }, + { + "fieldname": "itc_state_tax", + "label": "Availed ITC State/UT Tax", + "fieldtype": "Currency", + "width": 100, + }, + { + "fieldname": "itc_cess_amount", + "label": "Availed ITC Cess ", + "fieldtype": "Currency", + "width": 100, + }, ] - self.other_columns = [] - - self.columns = self.invoice_columns + self.tax_columns + self.other_columns \ No newline at end of file + + self.columns = self.invoice_columns + self.tax_columns + self.other_columns + + # ---------------------------------------------------------------------- + # INVOICE DATA + # ---------------------------------------------------------------------- + def get_invoice_data_custom(self): + self.invoices = frappe._dict() + conditions = "" + + # Common filters + if self.filters.get("letter_head"): + conditions += " AND letter_head = '%s'" % (self.filters.get("letter_head")) + if self.filters.get("company"): + conditions += " and company=%(company)s" + if self.filters.get("from_date"): + conditions += " and posting_date>=%(from_date)s" + if self.filters.get("to_date"): + conditions += " and posting_date<=%(to_date)s" + + # Sales-specific type_of_business filters + if self.doctype == "Sales Invoice": + if self.filters.get("type_of_business") == "B2B": + conditions += ( + " and ifnull(invoice_type, '') != 'Export' and is_return != 1 " + ) + elif self.filters.get("type_of_business") == "CDNR": + conditions += " and is_return = 1 " + + invoice_data = frappe.db.sql( + """ + select {select_columns} from `tab{doctype}` + where docstatus = 1 {where_conditions} and is_opening = 'No' + order by posting_date desc + """.format( + select_columns=self.select_columns, + doctype=self.doctype, + where_conditions=conditions, + ), + self.filters, + as_dict=1, + ) + + for d in invoice_data: + self.invoices.setdefault(d.invoice_number, d) + + # ---------------------------------------------------------------------- + # INVOICE ITEMS (doctype-specific) + # ---------------------------------------------------------------------- + def get_invoice_items_custom(self): + if not self.invoices: + return + + # --- SALES: simple dict parent -> {item_key: taxable_value} --- + if self.doctype == "Sales Invoice": + self.invoice_items = frappe._dict() + items = frappe.db.sql( + """ + select item_code, item_name, parent, taxable_value, base_net_amount + from `tab%s Item` where parent in (%s) + """ + % ( + self.doctype, + ", ".join(["%s"] * len(self.invoices)), + ), + tuple(self.invoices), + as_dict=1, + ) + + for d in items: + if d.parent not in self.invoice_items: + self.invoice_items[d.parent] = {} + key = d.item_code or d.item_name + if not key: + continue + val = flt(d.taxable_value) or flt(d.base_net_amount) + current_val = self.invoice_items[d.parent].get(key, 0.0) + self.invoice_items[d.parent][key] = current_val + val + + # --- PURCHASE: list with rate info (to avoid double counting) --- + else: + self.invoice_items = frappe._dict() + items = frappe.db.sql( + """ + select item_code, item_name, parent, taxable_value, base_net_amount, + igst_rate, cgst_rate, sgst_rate + from `tab%s Item` where parent in (%s) + """ + % ( + self.doctype, + ", ".join(["%s"] * len(self.invoices)), + ), + tuple(self.invoices), + as_dict=1, + ) + + for d in items: + if d.parent not in self.invoice_items: + self.invoice_items[d.parent] = [] + + key = d.item_code or d.item_name + if not key: + continue + + val = flt(d.taxable_value) or flt(d.base_net_amount) + rate = flt(d.igst_rate) + flt(d.cgst_rate) + flt(d.sgst_rate) + + self.invoice_items[d.parent].append( + {"key": key, "value": val, "item_rate": rate} + ) + + # ---------------------------------------------------------------------- + # TAX DETAILS → items_based_on_tax_rate + # ---------------------------------------------------------------------- + def get_items_based_on_tax_rate_custom(self): + if not self.invoices: + return + + self.tax_details = frappe.db.sql( + """ + select parent, account_head, item_wise_tax_detail, base_tax_amount_after_discount_amount + from `tab%s` where parenttype = %%s and docstatus = 1 and parent in (%s) + order by account_head + """ + % ( + self.tax_doctype, + ", ".join(["%s"] * len(self.invoices.keys())), + ), + tuple([self.doctype] + list(self.invoices.keys())), + ) + + self.items_based_on_tax_rate = {} + self.invoice_cess = frappe._dict() + self.cgst_sgst_invoices = [] + + for parent, account, item_wise_tax_detail, tax_amount in self.tax_details: + # Handle Cess separately + if account in self.gst_accounts.cess_account: + self.invoice_cess.setdefault(parent, 0.0) + self.invoice_cess[parent] += flt(tax_amount) + continue # Skip Cess rows for Rate grouping + + # Strict GST Account check to ignore freight/other charges + is_cgst_sgst = False + if ( + account in self.gst_accounts.cgst_account + or account in self.gst_accounts.sgst_account + ): + is_cgst_sgst = True + elif account in self.gst_accounts.igst_account: + pass + else: + acct_lower = account.lower() + if "cgst" in acct_lower or "sgst" in acct_lower: + is_cgst_sgst = True + elif "igst" in acct_lower: + pass + else: + # Non-GST tax row → ignore + continue + + if item_wise_tax_detail: + try: + detail = json.loads(item_wise_tax_detail) + + for item_key, tax_amounts in detail.items(): + if isinstance(tax_amounts, dict): + tax_rate = flt( + tax_amounts.get("tax_rate") + or tax_amounts.get("rate") + or 0 + ) + elif isinstance(tax_amounts, (list, tuple)): + tax_rate = flt(tax_amounts[0]) + else: + tax_rate = 0.0 + + if tax_rate > 0: + # For CGST+SGST, table stores half rate; convert to total + if is_cgst_sgst: + tax_rate *= 2 + if parent not in self.cgst_sgst_invoices: + self.cgst_sgst_invoices.append(parent) + + rate_based_dict = ( + self.items_based_on_tax_rate.setdefault(parent, {}) + .setdefault(tax_rate, []) + ) + if item_key not in rate_based_dict: + rate_based_dict.append(item_key) + except ValueError: + # bad JSON, ignore + pass + + # --- Add 0-rated invoices (imports/exempt) not present in tax table --- + if hasattr(self, "invoice_items"): + for inv, items in self.invoice_items.items(): + if inv not in self.items_based_on_tax_rate: + if self.doctype == "Sales Invoice": + keys = list(items.keys()) # dict + else: + keys = list({x["key"] for x in items}) # list of dicts + self.items_based_on_tax_rate.setdefault(inv, {}).setdefault( + 0.0, keys + ) + + # ---------------------------------------------------------------------- + # DATA BUILD (doctype-specific) + # ---------------------------------------------------------------------- + def get_data_custom(self): + if self.doctype == "Sales Invoice": + # Use Sales logic with _append_row (handles 0-rate suppress/export logic) + for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): + self._append_row(inv, items_based_on_rate) + else: + # Use Purchase logic (rate-aware filtering) + for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): + invoice_details = self.invoices.get(inv) + for rate, item_keys in items_based_on_rate.items(): + row = [] + + is_return = ( + flt(invoice_details.get("is_return")) == 1 + or invoice_details.get("return_against") + ) + + def val_format(v): + return abs(flt(v)) if is_return else flt(v) + + # invoice-level fields + for fieldname in self.invoice_fields: + if fieldname == "invoice_value": + val = ( + invoice_details.base_rounded_total + or invoice_details.base_grand_total + ) + row.append(flt(val)) # keep sign + elif fieldname in ( + "posting_date", + "bill_date", + "shipping_bill_date", + ): + val = invoice_details.get(fieldname) + row.append(formatdate(val, "dd-MMM-YY") if val else None) + elif fieldname == "export_type": + val = ( + "WPAY" + if invoice_details.get(fieldname) + == "With Payment of Tax" + else "WOPAY" + ) + row.append(val) + else: + row.append(invoice_details.get(fieldname)) + + # --- FILTER ITEMS BY RATE --- + taxable_value = 0.0 + inv_items = self.invoice_items.get(inv, []) + + for item_data in inv_items: + if item_data["key"] in item_keys: + # allow minor float diff + if abs(item_data["item_rate"] - rate) < 0.1: + taxable_value += item_data["value"] + # special case for 0-rate bucket + elif rate == 0 and item_data["item_rate"] == 0: + taxable_value += item_data["value"] + + tax_amount = taxable_value * rate / 100.0 + + # If filtered taxable value is 0, skip row unless invoice is purely 0-rate + if taxable_value == 0: + all_rates_zero = all( + x["item_rate"] == 0 for x in inv_items + ) or not inv_items + if not all_rates_zero: + continue + + row += [rate, val_format(taxable_value)] + + if inv in self.cgst_sgst_invoices: + row += [ + 0.0, + val_format(tax_amount / 2.0), + val_format(tax_amount / 2.0), + ] + else: + row += [val_format(tax_amount), 0.0, 0.0] + + row += [val_format(self.invoice_cess.get(inv, 0.0))] + + # Purchase-specific ITC cols + row += [ + invoice_details.get("eligibility_for_itc") or "All Other ITC", + invoice_details.get("itc_integrated_tax"), + invoice_details.get("itc_central_tax"), + invoice_details.get("itc_state_tax"), + invoice_details.get("itc_cess_amount"), + ] + + # CDNR flags (if used for purchase CDNR) + if self.filters.get("type_of_business") == "CDNR": + row.append( + "Y" + if getdate(invoice_details.posting_date) + <= date(2017, 7, 1) + else "N" + ) + row.append( + "C" if invoice_details.return_against else "R" + ) + + self.data.append(row) + + # ---------------------------------------------------------------------- + # SALES helper (unchanged from your Sales working version) + # ---------------------------------------------------------------------- + def _append_row(self, inv, items_based_on_rate): + invoice_details = self.invoices.get(inv) + + # Sort rates in ascending order + for rate in sorted(items_based_on_rate.keys()): + items = items_based_on_rate[rate] + + # Hide 0-rate if taxable rate exists (except export/exempt cases) + if rate == 0 and len(items_based_on_rate) > 1: + is_export = ( + invoice_details.get("invoice_type") == "Export" + or invoice_details.get("export_type") + in ["With Payment of Tax", "Without Payment of Tax"] + ) + if not is_export: + continue + + row = [] + + is_return = ( + flt(invoice_details.get("is_return")) == 1 + or invoice_details.get("return_against") + ) + + def val_format(v): + return abs(flt(v)) if is_return else flt(v) + + # invoice-level fields + for fieldname in self.invoice_fields: + if fieldname == "invoice_value": + val = ( + invoice_details.base_rounded_total + or invoice_details.base_grand_total + ) + row.append(flt(val)) # keep negative sign for returns + elif fieldname == "base_net_total": + val = invoice_details.base_net_total + if val is None: + val = 0 + row.append(flt(val)) + elif fieldname in ("posting_date", "bill_date", "shipping_bill_date"): + val = invoice_details.get(fieldname) + row.append(formatdate(val, "dd-MMM-YY") if val else None) + elif fieldname == "export_type": + val = ( + "WPAY" + if invoice_details.get(fieldname) == "With Payment of Tax" + else "WOPAY" + ) + row.append(val) + elif fieldname == "invoice_number": + row.append(invoice_details.get(fieldname)) + elif fieldname == "customer_name": + row.append(invoice_details.get(fieldname)) + else: + row.append(invoice_details.get(fieldname)) + + # Taxable value from items + taxable_value = 0.0 + inv_items = self.invoice_items.get(inv, {}) + for item_key in items: + taxable_value += inv_items.get(item_key, 0.0) + + tax_amount = taxable_value * rate / 100.0 + + row += [rate, val_format(taxable_value)] + + if inv in self.cgst_sgst_invoices: + row += [ + 0.0, + val_format(tax_amount / 2.0), + val_format(tax_amount / 2.0), + ] + else: + row += [val_format(tax_amount), 0.0, 0.0] + + row += [val_format(self.invoice_cess.get(inv, 0.0))] + + # Purchase-only ITC columns do NOT apply here + + # Sales CDNR flags + if self.filters.get("type_of_business") == "CDNR": + row.append( + "Y" + if getdate(invoice_details.posting_date) <= date(2017, 7, 1) + else "N" + ) + row.append("C" if invoice_details.return_against else "R") + + self.data.append(row) \ No newline at end of file diff --git a/rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.py b/rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.py index 8c9a5af..3462171 100644 --- a/rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.py +++ b/rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.py @@ -8,866 +8,808 @@ from datetime import date from six import iteritems -# *** FIX 1: Import the correct, modern function *** -from india_compliance.gst_india.utils import get_gst_accounts_by_type - def execute(filters=None): - return Gstr1Report(filters).run() + return Gstr1Report(filters).run() class Gstr1Report(object): - def __init__(self, filters=None): - self.filters = frappe._dict(filters or {}) - self.columns = [] - self.data = [] - self.doctype = "Sales Invoice" - self.tax_doctype = "Sales Taxes and Charges" - self.select_columns = """ - name as invoice_number, - customer_name, - posting_date, - base_grand_total, - base_rounded_total, - COALESCE(NULLIF(customer_gstin,''), NULLIF(billing_address_gstin, '')) as customer_gstin, - place_of_supply, - ecommerce_gstin, - reverse_charge, - return_against, - is_return, - gst_category, - export_type, - port_code, - shipping_bill_number, - shipping_bill_date, - reason_for_issuing_document - """ - - def run(self): - self.get_columns() - - # *** FIX 2: Correctly get Input or Output accounts based on doctype *** - if self.doctype == "Purchase Invoice": - account_type = "Input" - else: - account_type = "Output" - - if not self.filters.company: - frappe.throw(_("Please select a Company")) - - # Get the correct accounts - raw_gst_accounts = get_gst_accounts_by_type(self.filters.company, account_type) - - # The new function returns a dict, so we just need to adapt it - gst_accounts = frappe._dict({ - "cgst_account": raw_gst_accounts.get("cgst_account"), - "sgst_account": raw_gst_accounts.get("sgst_account"), - "igst_account": raw_gst_accounts.get("igst_account"), - "cess_account": [raw_gst_accounts.get("cess_account"), raw_gst_accounts.get("cess_non_advol_account")] - }) - - # Filter out None values and put them in lists - gst_accounts.cgst_account = [gst_accounts.cgst_account] if gst_accounts.cgst_account else [] - gst_accounts.sgst_account = [gst_accounts.sgst_account] if gst_accounts.sgst_account else [] - gst_accounts.igst_account = [gst_accounts.igst_account] if gst_accounts.igst_account else [] - gst_accounts.cess_account = [acc for acc in gst_accounts.cess_account if acc] - - self.gst_accounts = gst_accounts - # *** END OF FIX 2 *** - - self.get_invoice_data() - - if self.invoices: - # *** FIX 3: Rewritten data fetching *** - # Get all items for all invoices at once - self.get_all_invoice_items() - - # Use the tax table to find the *overall* rate - self.get_tax_rates_from_tax_table() - - self.invoice_fields = [d["fieldname"] for d in self.invoice_columns] - self.get_data() - # *** END OF FIX 3 *** - - return self.columns, self.data - - def get_data(self): - # This function is now overridden by clear_tax_import.py - # We leave the original B2C/etc logic here for Gstr1Report - if self.filters.get("type_of_business") in ("B2C Small", "B2C Large"): - self.get_b2c_data() - else: - # This loop is now simplified. We get items grouped by rate. - for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): - invoice_details = self.invoices.get(inv) - for rate, items in items_based_on_rate.items(): - # We pass the full item list to the row data function - row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, items) - - if self.filters.get("type_of_business") == "CDNR": - row.append("Y" if invoice_details.posting_date <= date(2017, 7, 1) else "N") - row.append("C" if invoice_details.return_against else "R") - - if taxable_value: - self.data.append(row) - - def get_b2c_data(self): - # This logic remains as it's for B2C sales - b2cs_output = {} - for inv, items_by_rate in self.items_based_on_tax_rate.items(): - invoice_details = self.invoices.get(inv) - for rate, items in items_by_rate.items(): - place_of_supply = invoice_details.get("place_of_supply") - ecommerce_gstin = invoice_details.get("ecommerce_gstin") - - b2cs_output.setdefault((rate, place_of_supply, ecommerce_gstin),{ - "place_of_supply": "", - "ecommerce_gstin": "", - "rate": "", - "taxable_value": 0, - "cess_amount": 0, - "type": "", - "invoice_number": invoice_details.get("invoice_number"), - "posting_date": invoice_details.get("posting_date"), - "invoice_value": invoice_details.get("base_grand_total"), - }) - - row = b2cs_output.get((rate, place_of_supply, ecommerce_gstin)) - row["place_of_supply"] = place_of_supply - row["ecommerce_gstin"] = ecommerce_gstin - row["rate"] = rate - - # *** FIX: Use new items list structure *** - taxable_value = 0 - for item in items: - taxable_value += flt(item.get('taxable_value')) - row["taxable_value"] += taxable_value - - cess_amount = 0 - for item in items: - cess_amount += flt(item.get('cess_amount')) - row["cess_amount"] += cess_amount - # *** END FIX *** - - row["type"] = "E" if ecommerce_gstin else "OE" - - for key, value in iteritems(b2cs_output): - self.data.append(value) - - - def get_row_data_for_invoice(self, invoice, invoice_details, tax_rate, items_at_this_rate): - row = [] - for fieldname in self.invoice_fields: - if self.filters.get("type_of_business") == "CDNR" and fieldname == "invoice_value": - row.append(abs(invoice_details.base_rounded_total) or abs(invoice_details.base_grand_total)) - elif fieldname == "invoice_value": - row.append(invoice_details.base_rounded_total or invoice_details.base_grand_total) - elif fieldname in ('posting_date', 'shipping_bill_date'): - # Handle None posting_date if it occurs - p_date = invoice_details.get(fieldname) - row.append(formatdate(p_date, 'dd-MMM-YY') if p_date else None) - elif fieldname == "export_type": - export_type = "WPAY" if invoice_details.get(fieldname)=="With Payment of Tax" else "WOPAY" - row.append(export_type) - else: - row.append(invoice_details.get(fieldname)) - - # *** FIX 5: Calculate taxable_value from the items *** - # `items_at_this_rate` is a list of item dicts - taxable_value = 0 - for item in items_at_this_rate: - taxable_value += flt(item.get('taxable_value')) - - row += [tax_rate or 0, taxable_value] - - # CESS is now summed in get_data() of the child report - # We just add a placeholder if the column exists - for column in self.other_columns: - if column.get('fieldname') == 'cess_amount': - # Calculate cess for this specific rate - cess_at_this_rate = 0 - for item in items_at_this_rate: - cess_at_this_rate += flt(item.get('cess_amount')) - row.append(cess_at_this_rate) - - return row, taxable_value - - def get_invoice_data(self): - self.invoices = frappe._dict() - conditions = self.get_conditions() - invoice_data = frappe.db.sql(""" - select - {select_columns} - from `tab{doctype}` - where docstatus = 1 {where_conditions} - and is_opening = 'No' - order by posting_date desc - """.format(select_columns=self.select_columns, doctype=self.doctype, - where_conditions=conditions), self.filters, as_dict=1) - - for d in invoice_data: - self.invoices.setdefault(d.invoice_number, d) - - def get_conditions(self): - conditions = "" - - for opts in (("company", " and company=%(company)s"), - ("from_date", " and posting_date>=%(from_date)s"), - ("to_date", " and posting_date<=%(to_date)s"), - ("company_address", " and company_address=%(company_address)s")): - if self.filters.get(opts[0]): - conditions += opts[1] - - # This logic is for GSTR-1 (Sales) - if self.doctype == "Sales Invoice": - if self.filters.get("type_of_business") == "B2B": - conditions += "and ifnull(gst_category, '') in ('Registered Regular', 'Deemed Export', 'SEZ') and is_return != 1" - - if self.filters.get("type_of_business") in ("B2C Large", "B2C Small"): - b2c_limit = frappe.db.get_single_value('GST Settings', 'b2c_limit') - if not b2c_limit: - frappe.throw(_("Please set B2C Limit in GST Settings.")) - - if self.filters.get("type_of_business") == "B2C Large": - conditions += """ and ifnull(SUBSTR(place_of_supply, 1, 2),'') != ifnull(SUBSTR(company_gstin, 1, 2),'') - and grand_total > {0} and is_return != 1 and gst_category ='Unregistered' """.format(flt(b2c_limit)) - - elif self.filters.get("type_of_business") == "B2C Small": - conditions += """ and ( - SUBSTR(place_of_supply, 1, 2) = SUBSTR(company_gstin, 1, 2) - or grand_total <= {0}) and is_return != 1 and gst_category ='Unregistered' """.format(flt(b2c_limit)) - - elif self.filters.get("type_of_business") == "CDNR": - conditions += """ and is_return = 1 """ - - elif self.filters.get("type_of_business") == "EXPORT": - conditions += """ and is_return !=1 and gst_category = 'Overseas' """ - - # This logic is for GSTR-2 (Purchases) - elif self.doctype == "Purchase Invoice": - if self.filters.get("type_of_business") == "B2B": - conditions += "and ifnull(gst_category, '') in ('Registered Regular', 'Deemed Export', 'SEZ') and is_return != 1" - elif self.filters.get("type_of_business") == "CDNR": - conditions += """ and is_return = 1 """ - - return conditions - - def get_all_invoice_items(self): - """ - *** NEW FUNCTION (FIX 4) *** - Get all item details at once and store them. - We now fetch the fields we fixed in the database. - """ - self.invoice_items_details = frappe._dict() - - item_fields = [ - "parent", "item_code", "taxable_value", "base_net_amount", - "igst_rate", "igst_amount", - "cgst_rate", "cgst_amount", - "sgst_rate", "sgst_amount", - "cess_rate", "cess_amount" - ] - - # Ensure we have invoices to query - if not self.invoices: - return - - items = frappe.db.sql(""" - select {fields} - from `tab{doctype} Item` - where parent in ({invoices}) - """.format( - fields=", ".join(item_fields), - doctype=self.doctype, - invoices=', '.join(['%s']*len(self.invoices)) - ), tuple(self.invoices), as_dict=1) - - for d in items: - self.invoice_items_details.setdefault(d.parent, []).append(d) - - def get_tax_rates_from_tax_table(self): - """ - *** NEW FUNCTION (FIX 4) *** - Get tax rates from the tax table and map items to them. - This replaces the complex 'get_items_based_on_tax_rate' logic. - """ - self.items_based_on_tax_rate = {} - self.invoice_cess = frappe._dict() - self.cgst_sgst_invoices = [] - self.igst_invoices = [] # *** FIX: Initialize igst_invoices here *** - - if not self.invoices: - return - - # *** THIS IS THE FIX for the SQL Error *** - # 1. Create the list of placeholders - placeholders = ', '.join(['%s'] * len(self.invoices.keys())) - - # 2. Format the query string with table name and placeholders - query = """ - select parent, account_head, rate - from `tab{tax_doctype}` - where - parenttype = %s and docstatus = 1 - and parent in ({parent_placeholders}) - """.format( - tax_doctype=self.tax_doctype, - parent_placeholders=placeholders - ) - - # 3. Create the list of values - values = [self.doctype] + list(self.invoices.keys()) - - # 4. Execute the query - tax_details = frappe.db.sql(query, tuple(values), as_dict=1) - # *** END OF FIX *** - - for tax in tax_details: - parent = tax.parent - account = tax.account_head - rate = flt(tax.rate) - - # Identify CESS - if account in self.gst_accounts.cess_account: - # We sum up CESS per invoice from items later - continue - - # Identify tax type - is_igst = account in self.gst_accounts.igst_account - is_cgst_sgst = account in self.gst_accounts.cgst_account or account in self.gst_accounts.sgst_account - - if not (is_igst or is_cgst_sgst): - continue # Skip non-gst accounts - - if is_cgst_sgst and parent not in self.cgst_sgst_invoices: - self.cgst_sgst_invoices.append(parent) - - # *** FIX: Populate self.igst_invoices *** - if is_igst and parent not in self.igst_invoices: - self.igst_invoices.append(parent) - # *** END OF FIX *** - - # The "rate" in the report is the *combined* rate - # For CGST/SGST, the table rate is 9, so we store 18 - report_rate = rate * 2 if is_cgst_sgst else rate - - # Get all items for this invoice - invoice_items = self.invoice_items_details.get(parent, []) - - # Find items that match this tax - items_for_this_rate = [] - for item in invoice_items: - item_rate = flt(item.igst_rate) or flt(item.cgst_rate) or flt(item.sgst_rate) - - # if it's cgst, we compare 9 with 9 - if is_cgst_sgst and flt(item.cgst_rate) == rate: - items_for_this_rate.append(item) - # if it's igst, we compare 18 with 18 - elif is_igst and flt(item.igst_rate) == rate: - items_for_this_rate.append(item) - - if items_for_this_rate: - # Group items by the combined rate - self.items_based_on_tax_rate.setdefault(parent, {}).setdefault(report_rate, []).extend(items_for_this_rate) - - # Handle Nil Rated / Exempt items (where no tax row exists) - for inv, items in self.invoice_items_details.items(): - for item in items: - rate_sum = flt(item.igst_rate) + flt(item.cgst_rate) + flt(item.sgst_rate) - if rate_sum == 0: - self.items_based_on_tax_rate.setdefault(inv, {}).setdefault(0.0, []).append(item) - - def get_columns(self): - # *** FIX 6: Always define self.invoice_columns *** - self.invoice_columns = [] - self.tax_columns = [ - { - "fieldname": "rate", - "label": "Rate", - "fieldtype": "Int", - "width": 60 - }, - { - "fieldname": "taxable_value", - "label": "Taxable Value", - "fieldtype": "Currency", - "width": 100 - } - ] - self.other_columns = [] - - if self.filters.get("type_of_business") == "B2B": - self.invoice_columns = [ - { - "fieldname": "customer_gstin", - "label": "GSTIN/UIN of Recipient", - "fieldtype": "Data", - "width": 150 - }, - { - "fieldname": "customer_name", - "label": "Receiver Name", - "fieldtype": "Data", - "width":100 - }, - { - "fieldname": "invoice_number", - "label": "Invoice Number", - "fieldtype": "Link", - "options": "Sales Invoice", - "width":100 - }, - { - "fieldname": "posting_date", - "label": "Invoice date", - "fieldtype": "Data", - "width":80 - }, - { - "fieldname": "invoice_value", - "label": "Invoice Value", - "fieldtype": "Currency", - "width":100 - }, - { - "fieldname": "place_of_supply", - "label": "Place Of Supply", - "fieldtype": "Data", - "width":100 - }, - { - "fieldname": "reverse_charge", - "label": "Reverse Charge", - "fieldtype": "Data" - }, - { - "fieldname": "gst_category", - "label": "Invoice Type", - "fieldtype": "Data" - }, - { - "fieldname": "ecommerce_gstin", - "label": "E-Commerce GSTIN", - "fieldtype": "Data", - "width":120 - } - ] - self.other_columns = [ - { - "fieldname": "cess_amount", - "label": "Cess Amount", - "fieldtype": "Currency", - "width": 100 - } - ] - - elif self.filters.get("type_of_business") == "B2C Large": - self.invoice_columns = [ - { - "fieldname": "invoice_number", - "label": "Invoice Number", - "fieldtype": "Link", - "options": "Sales Invoice", - "width": 120 - }, - { - "fieldname": "posting_date", - "label": "Invoice date", - "fieldtype": "Data", - "width": 100 - }, - { - "fieldname": "invoice_value", - "label": "Invoice Value", - "fieldtype": "Currency", - "width": 100 - }, - { - "fieldname": "place_of_supply", - "label": "Place Of Supply", - "fieldtype": "Data", - "width": 120 - }, - { - "fieldname": "ecommerce_gstin", - "label": "E-Commerce GSTIN", - "fieldtype": "Data", - "width": 130 - } - ] - self.other_columns = [ - { - "fieldname": "cess_amount", - "label": "Cess Amount", - "fieldtype": "Currency", - "width": 100 - } - ] - elif self.filters.get("type_of_business") == "CDNR": - self.invoice_columns = [ - { - "fieldname": "customer_gstin", - "label": "GSTIN/UIN of Recipient", - "fieldtype": "Data", - "width": 150 - }, - { - "fieldname": "customer_name", - "label": "Receiver Name", - "fieldtype": "Data", - "width": 120 - }, - { - "fieldname": "return_against", - "label": "Invoice/Advance Receipt Number", - "fieldtype": "Link", - "options": "Sales Invoice", - "width": 120 - }, - { - "fieldname": "posting_date", - "label": "Invoice/Advance Receipt date", - "fieldtype": "Data", - "width": 120 - }, - { - "fieldname": "invoice_number", - "label": "Invoice/Advance Receipt Number", - "fieldtype": "Link", - "options": "Sales Invoice", - "width":120 - }, - { - "fieldname": "reason_for_issuing_document", - "label": "Reason For Issuing document", - "fieldtype": "Data", - "width": 140 - }, - { - "fieldname": "place_of_supply", - "label": "Place Of Supply", - "fieldtype": "Data", - "width": 120 - }, - { - "fieldname": "invoice_value", - "label": "Invoice Value", - "fieldtype": "Currency", - "width": 120 - } - ] - self.other_columns = [ - { - "fieldname": "cess_amount", - "label": "Cess Amount", - "fieldtype": "Currency", - "width": 100 - }, - { - "fieldname": "pre_gst", - "label": "PRE GST", - "fieldtype": "Data", - "width": 80 - }, - { - "fieldname": "document_type", - "label": "Document Type", - "fieldtype": "Data", - "width": 80 - } - ] - elif self.filters.get("type_of_business") == "B2C Small": - self.invoice_columns = [ - { - "fieldname": "place_of_supply", - "label": "Place Of Supply", - "fieldtype": "Data", - "width": 120 - }, - { - "fieldname": "ecommerce_gstin", - "label": "E-Commerce GSTIN", - "fieldtype": "Data", - "width": 130 - } - ] - self.other_columns = [ - { - "fieldname": "cess_amount", - "label": "Cess Amount", - "fieldtype": "Currency", - "width": 100 - }, - { - "fieldname": "type", - "label": "Type", - "fieldtype": "Data", - "width": 50 - } - ] - elif self.filters.get("type_of_business") == "EXPORT": - self.invoice_columns = [ - { - "fieldname": "export_type", - "label": "Export Type", - "fieldtype": "Data", - "width":120 - }, - { - "fieldname": "invoice_number", - "label": "Invoice Number", - "fieldtype": "Link", - "options": "Sales Invoice", - "width":120 - }, - { - "fieldname": "posting_date", - "label": "Invoice date", - "fieldtype": "Data", - "width": 120 - }, - { - "fieldname": "invoice_value", - "label": "Invoice Value", - "fieldtype": "Currency", - "width": 120 - }, - { - "fieldname": "port_code", - "label": "Port Code", - "fieldtype": "Data", - "width": 120 - }, - { - "fieldname": "shipping_bill_number", - "label": "Shipping Bill Number", - "fieldtype": "Data", - "width": 120 - }, - { - "fieldname": "shipping_bill_date", - "label": "Shipping Bill Date", - "fieldtype": "Data", - "width": 120 - } - ] - - # This is the line that gets called by the child report - # If no 'type_of_business' filter exists, self.invoice_columns is empty - # We must add a default definition - if not self.invoice_columns: - self.invoice_columns = [] # Ensure it's at least an empty list - - self.columns = self.invoice_columns + self.tax_columns + self.other_columns + def __init__(self, filters=None): + self.filters = frappe._dict(filters or {}) + self.columns = [] + self.data = [] + self.doctype = "Sales Invoice" + self.tax_doctype = "Sales Taxes and Charges" + self.select_columns = """ + name as invoice_number, + customer_name, + posting_date, + base_grand_total, + base_rounded_total, + COALESCE(NULLIF(customer_gstin,''), NULLIF(billing_address_gstin, '')) as customer_gstin, + place_of_supply, + ecommerce_gstin, + reverse_charge, + return_against, + is_return, + gst_category, + export_type, + port_code, + shipping_bill_number, + shipping_bill_date, + reason_for_issuing_document + """ + + def run(self): + self.get_columns() + self.gst_accounts = get_gst_accounts(self.filters.company) + self.get_invoice_data() + + if self.invoices: + self.get_invoice_items() + self.get_items_based_on_tax_rate() + self.invoice_fields = [d["fieldname"] for d in self.invoice_columns] + self.get_data() + + return self.columns, self.data + + def get_data(self): + if self.filters.get("type_of_business") in ("B2C Small", "B2C Large"): + self.get_b2c_data() + else: + for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): + invoice_details = self.invoices.get(inv) + for rate, items in items_based_on_rate.items(): + row, taxable_value = self.get_row_data_for_invoice(inv, invoice_details, rate, items) + + if self.filters.get("type_of_business") == "CDNR": + row.append("Y" if invoice_details.posting_date <= date(2017, 7, 1) else "N") + row.append("C" if invoice_details.return_against else "R") + + if taxable_value: + self.data.append(row) + + def get_b2c_data(self): + b2cs_output = {} + + for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): + invoice_details = self.invoices.get(inv) + for rate, items in items_based_on_rate.items(): + place_of_supply = invoice_details.get("place_of_supply") + ecommerce_gstin = invoice_details.get("ecommerce_gstin") + + b2cs_output.setdefault((rate, place_of_supply, ecommerce_gstin),{ + "place_of_supply": "", + "ecommerce_gstin": "", + "rate": "", + "taxable_value": 0, + "cess_amount": 0, + "type": "", + "invoice_number": invoice_details.get("invoice_number"), + "posting_date": invoice_details.get("posting_date"), + "invoice_value": invoice_details.get("base_grand_total"), + }) + + row = b2cs_output.get((rate, place_of_supply, ecommerce_gstin)) + row["place_of_supply"] = place_of_supply + row["ecommerce_gstin"] = ecommerce_gstin + row["rate"] = rate + row["taxable_value"] += sum([abs(net_amount) + for item_code, net_amount in self.invoice_items.get(inv).items() if item_code in items]) + row["cess_amount"] += flt(self.invoice_cess.get(inv), 2) + row["type"] = "E" if ecommerce_gstin else "OE" + + for key, value in iteritems(b2cs_output): + self.data.append(value) + + def get_row_data_for_invoice(self, invoice, invoice_details, tax_rate, items): + row = [] + for fieldname in self.invoice_fields: + if self.filters.get("type_of_business") == "CDNR" and fieldname == "invoice_value": + row.append(abs(invoice_details.base_rounded_total) or abs(invoice_details.base_grand_total)) + elif fieldname == "invoice_value": + row.append(invoice_details.base_rounded_total or invoice_details.base_grand_total) + elif fieldname in ('posting_date', 'shipping_bill_date'): + row.append(formatdate(invoice_details.get(fieldname), 'dd-MMM-YY')) + elif fieldname == "export_type": + export_type = "WPAY" if invoice_details.get(fieldname)=="With Payment of Tax" else "WOPAY" + row.append(export_type) + else: + row.append(invoice_details.get(fieldname)) + taxable_value = 0 + + if invoice in self.cgst_sgst_invoices: + division_factor = 2 + else: + division_factor = 1 + + for item_code, net_amount in self.invoice_items.get(invoice).items(): + if item_code in items: + if self.item_tax_rate.get(invoice) and tax_rate/division_factor in self.item_tax_rate.get(invoice, {}).get(item_code, []): + taxable_value += abs(net_amount) + elif not self.item_tax_rate.get(invoice): + taxable_value += abs(net_amount) + elif tax_rate: + taxable_value += abs(net_amount) + elif not tax_rate and self.filters.get('type_of_business') == 'EXPORT' \ + and invoice_details.get('export_type') == "Without Payment of Tax": + taxable_value += abs(net_amount) + + row += [tax_rate or 0, taxable_value] + + for column in self.other_columns: + if column.get('fieldname') == 'cess_amount': + row.append(flt(self.invoice_cess.get(invoice), 2)) + + return row, taxable_value + + def get_invoice_data(self): + self.invoices = frappe._dict() + conditions = self.get_conditions() + invoice_data = frappe.db.sql(""" + select + {select_columns} + from `tab{doctype}` + where docstatus = 1 {where_conditions} + and is_opening = 'No' + order by posting_date desc + """.format(select_columns=self.select_columns, doctype=self.doctype, + where_conditions=conditions), self.filters, as_dict=1) + + for d in invoice_data: + self.invoices.setdefault(d.invoice_number, d) + + def get_conditions(self): + conditions = "" + + for opts in (("company", " and company=%(company)s"), + ("from_date", " and posting_date>=%(from_date)s"), + ("to_date", " and posting_date<=%(to_date)s"), + ("company_address", " and company_address=%(company_address)s")): + if self.filters.get(opts[0]): + conditions += opts[1] + + + if self.filters.get("type_of_business") == "B2B": + conditions += "and ifnull(gst_category, '') in ('Registered Regular', 'Deemed Export', 'SEZ') and is_return != 1" + + if self.filters.get("type_of_business") in ("B2C Large", "B2C Small"): + b2c_limit = frappe.db.get_single_value('GST Settings', 'b2c_limit') + if not b2c_limit: + frappe.throw(_("Please set B2C Limit in GST Settings.")) + + if self.filters.get("type_of_business") == "B2C Large": + conditions += """ and ifnull(SUBSTR(place_of_supply, 1, 2),'') != ifnull(SUBSTR(company_gstin, 1, 2),'') + and grand_total > {0} and is_return != 1 and gst_category ='Unregistered' """.format(flt(b2c_limit)) + + elif self.filters.get("type_of_business") == "B2C Small": + conditions += """ and ( + SUBSTR(place_of_supply, 1, 2) = SUBSTR(company_gstin, 1, 2) + or grand_total <= {0}) and is_return != 1 and gst_category ='Unregistered' """.format(flt(b2c_limit)) + + elif self.filters.get("type_of_business") == "CDNR": + conditions += """ and is_return = 1 """ + + elif self.filters.get("type_of_business") == "EXPORT": + conditions += """ and is_return !=1 and gst_category = 'Overseas' """ + return conditions + + def get_invoice_items(self): + self.invoice_items = frappe._dict() + self.item_tax_rate = frappe._dict() + + items = frappe.db.sql(""" + select item_code, parent, taxable_value, base_net_amount, item_tax_rate + from `tab%s Item` + where parent in (%s) + """ % (self.doctype, ', '.join(['%s']*len(self.invoices))), tuple(self.invoices), as_dict=1) + + for d in items: + if d.item_code not in self.invoice_items.get(d.parent, {}): + self.invoice_items.setdefault(d.parent, {}).setdefault(d.item_code, + sum((i.get('taxable_value', 0) or i.get('base_net_amount', 0)) for i in items + if i.item_code == d.item_code and i.parent == d.parent)) + + item_tax_rate = {} + + if d.item_tax_rate: + item_tax_rate = json.loads(d.item_tax_rate) + + for account, rate in item_tax_rate.items(): + tax_rate_dict = self.item_tax_rate.setdefault(d.parent, {}).setdefault(d.item_code, []) + tax_rate_dict.append(rate) + + def get_items_based_on_tax_rate(self): + self.tax_details = frappe.db.sql(""" + select + parent, account_head, item_wise_tax_detail, base_tax_amount_after_discount_amount + from `tab%s` + where + parenttype = %s and docstatus = 1 + and parent in (%s) + order by account_head + """ % (self.tax_doctype, '%s', ', '.join(['%s']*len(self.invoices.keys()))), + tuple([self.doctype] + list(self.invoices.keys()))) + + self.items_based_on_tax_rate = {} + self.invoice_cess = frappe._dict() + self.cgst_sgst_invoices = [] + + unidentified_gst_accounts = [] + unidentified_gst_accounts_invoice = [] + for parent, account, item_wise_tax_detail, tax_amount in self.tax_details: + if account in self.gst_accounts.cess_account: + self.invoice_cess.setdefault(parent, tax_amount) + else: + if item_wise_tax_detail: + try: + item_wise_tax_detail = json.loads(item_wise_tax_detail) + cgst_or_sgst = False + if account in self.gst_accounts.cgst_account \ + or account in self.gst_accounts.sgst_account: + cgst_or_sgst = True + + if not (cgst_or_sgst or account in self.gst_accounts.igst_account): + if "gst" in account.lower() and account not in unidentified_gst_accounts: + unidentified_gst_accounts.append(account) + unidentified_gst_accounts_invoice.append(parent) + continue + + for item_code, tax_amounts in item_wise_tax_detail.items(): + tax_rate = 0 + if isinstance(tax_amounts, (list, tuple)): + tax_rate = tax_amounts[0] if len(tax_amounts) > 0 else 0 + elif isinstance(tax_amounts, dict): + tax_rate = tax_amounts.get("tax_rate") or tax_amounts.get("rate") or 0 + else: + try: + tax_rate = float(tax_amounts) + except Exception: + tax_rate = 0 + if tax_rate: + if cgst_or_sgst: + tax_rate *= 2 + if parent not in self.cgst_sgst_invoices: + self.cgst_sgst_invoices.append(parent) + + rate_based_dict = self.items_based_on_tax_rate\ + .setdefault(parent, {}).setdefault(tax_rate, []) + if item_code not in rate_based_dict: + rate_based_dict.append(item_code) + except ValueError: + continue + if unidentified_gst_accounts: + frappe.msgprint(_("Following accounts might be selected in GST Settings:") + + "
" + "
".join(unidentified_gst_accounts), alert=True) + + # Build itemised tax for export invoices where tax table is blank + for invoice, items in iteritems(self.invoice_items): + if invoice not in self.items_based_on_tax_rate and invoice not in unidentified_gst_accounts_invoice \ + and frappe.db.get_value(self.doctype, invoice, "export_type") == "Without Payment of Tax": + self.items_based_on_tax_rate.setdefault(invoice, {}).setdefault(0, items.keys()) + + def get_columns(self): + self.tax_columns = [ + { + "fieldname": "rate", + "label": "Rate", + "fieldtype": "Int", + "width": 60 + }, + { + "fieldname": "taxable_value", + "label": "Taxable Value", + "fieldtype": "Currency", + "width": 100 + } + ] + self.other_columns = [] + + if self.filters.get("type_of_business") == "B2B": + self.invoice_columns = [ + { + "fieldname": "customer_gstin", + "label": "GSTIN/UIN of Recipient", + "fieldtype": "Data", + "width": 150 + }, + { + "fieldname": "customer_name", + "label": "Receiver Name", + "fieldtype": "Data", + "width":100 + }, + { + "fieldname": "invoice_number", + "label": "Invoice Number", + "fieldtype": "Link", + "options": "Sales Invoice", + "width":100 + }, + { + "fieldname": "posting_date", + "label": "Invoice date", + "fieldtype": "Data", + "width":80 + }, + { + "fieldname": "invoice_value", + "label": "Invoice Value", + "fieldtype": "Currency", + "width":100 + }, + { + "fieldname": "place_of_supply", + "label": "Place Of Supply", + "fieldtype": "Data", + "width":100 + }, + { + "fieldname": "reverse_charge", + "label": "Reverse Charge", + "fieldtype": "Data" + }, + { + "fieldname": "gst_category", + "label": "Invoice Type", + "fieldtype": "Data" + }, + { + "fieldname": "ecommerce_gstin", + "label": "E-Commerce GSTIN", + "fieldtype": "Data", + "width":120 + } + ] + self.other_columns = [ + { + "fieldname": "cess_amount", + "label": "Cess Amount", + "fieldtype": "Currency", + "width": 100 + } + ] + + elif self.filters.get("type_of_business") == "B2C Large": + self.invoice_columns = [ + { + "fieldname": "invoice_number", + "label": "Invoice Number", + "fieldtype": "Link", + "options": "Sales Invoice", + "width": 120 + }, + { + "fieldname": "posting_date", + "label": "Invoice date", + "fieldtype": "Data", + "width": 100 + }, + { + "fieldname": "invoice_value", + "label": "Invoice Value", + "fieldtype": "Currency", + "width": 100 + }, + { + "fieldname": "place_of_supply", + "label": "Place Of Supply", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "ecommerce_gstin", + "label": "E-Commerce GSTIN", + "fieldtype": "Data", + "width": 130 + } + ] + self.other_columns = [ + { + "fieldname": "cess_amount", + "label": "Cess Amount", + "fieldtype": "Currency", + "width": 100 + } + ] + elif self.filters.get("type_of_business") == "CDNR": + self.invoice_columns = [ + { + "fieldname": "customer_gstin", + "label": "GSTIN/UIN of Recipient", + "fieldtype": "Data", + "width": 150 + }, + { + "fieldname": "customer_name", + "label": "Receiver Name", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "return_against", + "label": "Invoice/Advance Receipt Number", + "fieldtype": "Link", + "options": "Sales Invoice", + "width": 120 + }, + { + "fieldname": "posting_date", + "label": "Invoice/Advance Receipt date", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "invoice_number", + "label": "Invoice/Advance Receipt Number", + "fieldtype": "Link", + "options": "Sales Invoice", + "width":120 + }, + { + "fieldname": "reason_for_issuing_document", + "label": "Reason For Issuing document", + "fieldtype": "Data", + "width": 140 + }, + { + "fieldname": "place_of_supply", + "label": "Place Of Supply", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "invoice_value", + "label": "Invoice Value", + "fieldtype": "Currency", + "width": 120 + } + ] + self.other_columns = [ + { + "fieldname": "cess_amount", + "label": "Cess Amount", + "fieldtype": "Currency", + "width": 100 + }, + { + "fieldname": "pre_gst", + "label": "PRE GST", + "fieldtype": "Data", + "width": 80 + }, + { + "fieldname": "document_type", + "label": "Document Type", + "fieldtype": "Data", + "width": 80 + } + ] + elif self.filters.get("type_of_business") == "B2C Small": + self.invoice_columns = [ + { + "fieldname": "place_of_supply", + "label": "Place Of Supply", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "ecommerce_gstin", + "label": "E-Commerce GSTIN", + "fieldtype": "Data", + "width": 130 + } + ] + self.other_columns = [ + { + "fieldname": "cess_amount", + "label": "Cess Amount", + "fieldtype": "Currency", + "width": 100 + }, + { + "fieldname": "type", + "label": "Type", + "fieldtype": "Data", + "width": 50 + } + ] + elif self.filters.get("type_of_business") == "EXPORT": + self.invoice_columns = [ + { + "fieldname": "export_type", + "label": "Export Type", + "fieldtype": "Data", + "width":120 + }, + { + "fieldname": "invoice_number", + "label": "Invoice Number", + "fieldtype": "Link", + "options": "Sales Invoice", + "width":120 + }, + { + "fieldname": "posting_date", + "label": "Invoice date", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "invoice_value", + "label": "Invoice Value", + "fieldtype": "Currency", + "width": 120 + }, + { + "fieldname": "port_code", + "label": "Port Code", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "shipping_bill_number", + "label": "Shipping Bill Number", + "fieldtype": "Data", + "width": 120 + }, + { + "fieldname": "shipping_bill_date", + "label": "Shipping Bill Date", + "fieldtype": "Data", + "width": 120 + } + ] + self.columns = self.invoice_columns + self.tax_columns + self.other_columns @frappe.whitelist() def get_json(filters, report_name, data): - filters = json.loads(filters) - report_data = json.loads(data) - gstin = get_company_gstin_number(filters["company"]) + filters = json.loads(filters) + report_data = json.loads(data) + gstin = get_company_gstin_number(filters["company"]) - fp = "%02d%s" % (getdate(filters["to_date"]).month, getdate(filters["to_date"]).year) + fp = "%02d%s" % (getdate(filters["to_date"]).month, getdate(filters["to_date"]).year) - gst_json = {"gstin": "", "version": "GST2.2.9", - "hash": "hash", "gstin": gstin, "fp": fp} + gst_json = {"gstin": "", "version": "GST2.2.9", + "hash": "hash", "gstin": gstin, "fp": fp} - res = {} - if filters["type_of_business"] == "B2B": - for item in report_data[:-1]: - res.setdefault(item["customer_gstin"], {}).setdefault(item["invoice_number"],[]).append(item) + res = {} + if filters["type_of_business"] == "B2B": + for item in report_data[:-1]: + res.setdefault(item["customer_gstin"], {}).setdefault(item["invoice_number"],[]).append(item) - out = get_b2b_json(res, gstin) - gst_json["b2b"] = out + out = get_b2b_json(res, gstin) + gst_json["b2b"] = out - elif filters["type_of_business"] == "B2C Large": - for item in report_data[:-1]: - res.setdefault(item["place_of_supply"], []).append(item) + elif filters["type_of_business"] == "B2C Large": + for item in report_data[:-1]: + res.setdefault(item["place_of_supply"], []).append(item) - out = get_b2cl_json(res, gstin) - gst_json["b2cl"] = out + out = get_b2cl_json(res, gstin) + gst_json["b2cl"] = out - elif filters["type_of_business"] == "B2C Small": - out = get_b2cs_json(report_data[:-1], gstin) - gst_json["b2cs"] = out + elif filters["type_of_business"] == "B2C Small": + out = get_b2cs_json(report_data[:-1], gstin) + gst_json["b2cs"] = out - elif filters["type_of_business"] == "EXPORT": - for item in report_data[:-1]: - res.setdefault(item["export_type"], []).append(item) + elif filters["type_of_business"] == "EXPORT": + for item in report_data[:-1]: + res.setdefault(item["export_type"], []).append(item) - out = get_export_json(res) - gst_json["exp"] = out + out = get_export_json(res) + gst_json["exp"] = out - return { - 'report_name': report_name, - 'report_type': filters['type_of_business'], - 'data': gst_json - } + return { + 'report_name': report_name, + 'report_type': filters['type_of_business'], + 'data': gst_json + } def get_b2b_json(res, gstin): - inv_type, out = {"Registered Regular": "R", "Deemed Export": "DE", "URD": "URD", "SEZ": "SEZ"}, [] - for gst_in in res: - b2b_item, inv = {"ctin": gst_in, "inv": []}, [] - if not gst_in: continue + inv_type, out = {"Registered Regular": "R", "Deemed Export": "DE", "URD": "URD", "SEZ": "SEZ"}, [] + for gst_in in res: + b2b_item, inv = {"ctin": gst_in, "inv": []}, [] + if not gst_in: continue - for number, invoice in iteritems(res[gst_in]): - if not invoice[0]["place_of_supply"]: - frappe.throw(_("""{0} not entered in Invoice {1}. - Please update and try again""").format(frappe.bold("Place Of Supply"), - frappe.bold(invoice[0]['invoice_number']))) + for number, invoice in iteritems(res[gst_in]): + if not invoice[0]["place_of_supply"]: + frappe.throw(_("""{0} not entered in Invoice {1}. + Please update and try again""").format(frappe.bold("Place Of Supply"), + frappe.bold(invoice[0]['invoice_number']))) - inv_item = get_basic_invoice_detail(invoice[0]) - inv_item["pos"] = "%02d" % int(invoice[0]["place_of_supply"].split('-')[0]) - inv_item["rchrg"] = invoice[0]["reverse_charge"] - inv_item["inv_typ"] = inv_type.get(invoice[0].get("gst_category", ""),"") + inv_item = get_basic_invoice_detail(invoice[0]) + inv_item["pos"] = "%02d" % int(invoice[0]["place_of_supply"].split('-')[0]) + inv_item["rchrg"] = invoice[0]["reverse_charge"] + inv_item["inv_typ"] = inv_type.get(invoice[0].get("gst_category", ""),"") - if inv_item["pos"]=="00": continue - inv_item["itms"] = [] + if inv_item["pos"]=="00": continue + inv_item["itms"] = [] - for item in invoice: - inv_item["itms"].append(get_rate_and_tax_details(item, gstin)) + for item in invoice: + inv_item["itms"].append(get_rate_and_tax_details(item, gstin)) - inv.append(inv_item) + inv.append(inv_item) - if not inv: continue - b2b_item["inv"] = inv - out.append(b2b_item) + if not inv: continue + b2b_item["inv"] = inv + out.append(b2b_item) - return out + return out def get_b2cs_json(data, gstin): - company_state_number = gstin[0:2] + company_state_number = gstin[0:2] - out = [] - for d in data: - if not d.get("place_of_supply"): - frappe.throw(_("""{0} not entered in some invoices. - Please update and try again""").format(frappe.bold("Place Of Supply"))) + out = [] + for d in data: + if not d.get("place_of_supply"): + frappe.throw(_("""{0} not entered in some invoices. + Please update and try again""").format(frappe.bold("Place Of Supply"))) - pos = d.get('place_of_supply').split('-')[0] - tax_details = {} + pos = d.get('place_of_supply').split('-')[0] + tax_details = {} - rate = d.get('rate', 0) - tax = flt((d["taxable_value"]*rate)/100.0, 2) + rate = d.get('rate', 0) + tax = flt((d["taxable_value"]*rate)/100.0, 2) - if company_state_number == pos: - tax_details.update({"camt": flt(tax/2.0, 2), "samt": flt(tax/2.0, 2)}) - else: - tax_details.update({"iamt": tax}) + if company_state_number == pos: + tax_details.update({"camt": flt(tax/2.0, 2), "samt": flt(tax/2.0, 2)}) + else: + tax_details.update({"iamt": tax}) - inv = { - "sply_ty": "INTRA" if company_state_number == pos else "INTER", - "pos": pos, - "typ": d.get('type'), - "txval": flt(d.get('taxable_value'), 2), - "rt": rate, - "iamt": flt(tax_details.get('iamt'), 2), - "camt": flt(tax_details.get('camt'), 2), - "samt": flt(tax_details.get('samt'), 2), - "csamt": flt(d.get('cess_amount'), 2) - } + inv = { + "sply_ty": "INTRA" if company_state_number == pos else "INTER", + "pos": pos, + "typ": d.get('type'), + "txval": flt(d.get('taxable_value'), 2), + "rt": rate, + "iamt": flt(tax_details.get('iamt'), 2), + "camt": flt(tax_details.get('camt'), 2), + "samt": flt(tax_details.get('samt'), 2), + "csamt": flt(d.get('cess_amount'), 2) + } - if d.get('type') == "E" and d.get('ecommerce_gstin'): - inv.update({ - "etin": d.get('ecommerce_gstin') - }) + if d.get('type') == "E" and d.get('ecommerce_gstin'): + inv.update({ + "etin": d.get('ecommerce_gstin') + }) - out.append(inv) + out.append(inv) - return out + return out def get_b2cl_json(res, gstin): - out = [] - for pos in res: - if not pos: - frappe.throw(_("""{0} not entered in some invoices. - Please update and try again""").format(frappe.bold("Place Of Supply"))) + out = [] + for pos in res: + if not pos: + frappe.throw(_("""{0} not entered in some invoices. + Please update and try again""").format(frappe.bold("Place Of Supply"))) - b2cl_item, inv = {"pos": "%02d" % int(pos.split('-')[0]), "inv": []}, [] + b2cl_item, inv = {"pos": "%02d" % int(pos.split('-')[0]), "inv": []}, [] - for row in res[pos]: - inv_item = get_basic_invoice_detail(row) - if row.get("sale_from_bonded_wh"): - inv_item["inv_typ"] = "CBW" + for row in res[pos]: + inv_item = get_basic_invoice_detail(row) + if row.get("sale_from_bonded_wh"): + inv_item["inv_typ"] = "CBW" - inv_item["itms"] = [get_rate_and_tax_details(row, gstin)] + inv_item["itms"] = [get_rate_and_tax_details(row, gstin)] - inv.append(inv_item) + inv.append(inv_item) - b2cl_item["inv"] = inv - out.append(b2cl_item) + b2cl_item["inv"] = inv + out.append(b2cl_item) - return out + return out def get_export_json(res): - out = [] - for exp_type in res: - exp_item, inv = {"exp_typ": exp_type, "inv": []}, [] + out = [] + for exp_type in res: + exp_item, inv = {"exp_typ": exp_type, "inv": []}, [] - for row in res[exp_type]: - inv_item = get_basic_invoice_detail(row) - inv_item["itms"] = [{ - "txval": flt(row["taxable_value"], 2), - "rt": row["rate"] or 0, - "iamt": 0, - "csamt": 0 - }] + for row in res[exp_type]: + inv_item = get_basic_invoice_detail(row) + inv_item["itms"] = [{ + "txval": flt(row["taxable_value"], 2), + "rt": row["rate"] or 0, + "iamt": 0, + "csamt": 0 + }] - inv.append(inv_item) + inv.append(inv_item) - exp_item["inv"] = inv - out.append(exp_item) + exp_item["inv"] = inv + out.append(exp_item) - return out + return out def get_basic_invoice_detail(row): - return { - "inum": row["invoice_number"], - "idt": getdate(row["posting_date"]).strftime('%d-%m-%Y'), - "val": flt(row["invoice_value"], 2) - } + return { + "inum": row["invoice_number"], + "idt": getdate(row["posting_date"]).strftime('%d-%m-%Y'), + "val": flt(row["invoice_value"], 2) + } def get_rate_and_tax_details(row, gstin): - itm_det = {"txval": flt(row["taxable_value"], 2), - "rt": row["rate"], - "csamt": (flt(row.get("cess_amount"), 2) or 0) - } - - # calculate rate - num = 1 if not row["rate"] else "%d%02d" % (row["rate"], 1) - rate = row.get("rate") or 0 - - # calculate tax amount added - tax = flt((row["taxable_value"]*rate)/100.0, 2) - - # *** FIX: Check customer_gstin, not place_of_supply *** - if row.get("customer_gstin") and gstin[0:2] == row["customer_gstin"][0:2]: - itm_det.update({"camt": flt(tax/2.0, 2), "samt": flt(tax/2.0, 2)}) - else: - itm_det.update({"iamt": tax}) - - return {"num": int(num), "itm_det": itm_det} + itm_det = {"txval": flt(row["taxable_value"], 2), + "rt": row["rate"], + "csamt": (flt(row.get("cess_amount"), 2) or 0) + } + + # calculate rate + num = 1 if not row["rate"] else "%d%02d" % (row["rate"], 1) + rate = row.get("rate") or 0 + + # calculate tax amount added + tax = flt((row["taxable_value"]*rate)/100.0, 2) + frappe.errprint([tax, tax/2]) + if row.get("customer_gstin") and gstin[0:2] == row["customer_gstin"][0:2]: + itm_det.update({"camt": flt(tax/2.0, 2), "samt": flt(tax/2.0, 2)}) + else: + itm_det.update({"iamt": tax}) + + return {"num": int(num), "itm_det": itm_det} def get_company_gstin_number(company): - filters = [ - ["is_your_company_address", "=", 1], - ["Dynamic Link", "link_doctype", "=", "Company"], - ["Dynamic Link", "link_name", "=", company], - ["Dynamic Link", "parenttype", "=", "Address"], - ] - - gstin = frappe.get_all("Address", filters=filters, fields=["gstin"]) - - if gstin: - return gstin[0]["gstin"] - else: - frappe.throw(_("Please set valid GSTIN No. in Company Address for company {0}".format( - frappe.bold(company) - ))) + filters = [ + ["is_your_company_address", "=", 1], + ["Dynamic Link", "link_doctype", "=", "Company"], + ["Dynamic Link", "link_name", "=", company], + ["Dynamic Link", "parenttype", "=", "Address"], + ] + + gstin = frappe.get_all("Address", filters=filters, fields=["gstin"]) + + if gstin: + return gstin[0]["gstin"] + else: + frappe.throw(_("Please set valid GSTIN No. in Company Address for company {0}".format( + frappe.bold(company) + ))) @frappe.whitelist() def download_json_file(): - ''' download json content in a file ''' - data = frappe._dict(frappe.local.form_dict) - frappe.response['filename'] = frappe.scrub("{0} {1}".format(data['report_name'], data['report_type'])) + '.json' - frappe.response['filecontent'] = data['data'] - frappe.response['content_type'] = 'application/json' - frappe.response['type'] = 'download' \ No newline at end of file + ''' download json content in a file ''' + data = frappe._dict(frappe.local.form_dict) + frappe.response['filename'] = frappe.scrub("{0} {1}".format(data['report_name'], data['report_type'])) + '.json' + frappe.response['filecontent'] = data['data'] + frappe.response['content_type'] = 'application/json' + frappe.response['type'] = 'download' + +def get_period(month, year=None): + + month_no = { + "January": 1, + "February": 2, + "March": 3, + "April": 4, + "May": 5, + "June": 6, + "July": 7, + "August": 8, + "September": 9, + "October": 10, + "November": 11, + "December": 12 + }.get(month) + + if year: + return str(month_no).zfill(2) + str(year) + else: + return month_no + +@frappe.whitelist() +def get_gst_accounts(company, account_wise=False): + gst_accounts = frappe._dict() + gst_settings_accounts = frappe.get_all("GST Account", + filters={"parent": "GST Settings", "company": company}, + fields=["cgst_account", "sgst_account", "igst_account", "cess_account"]) + + if not gst_settings_accounts and not frappe.flags.in_test: + frappe.throw(_("Please set GST Accounts in GST Settings")) + + for d in gst_settings_accounts: + for acc, val in d.items(): + if not account_wise: + gst_accounts.setdefault(acc, []).append(val) + elif val: + gst_accounts[val] = acc + + return gst_accounts \ No newline at end of file From 75b0bb3c7c8e8b947d670247981958480446f2b3 Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Wed, 10 Dec 2025 12:40:54 +0000 Subject: [PATCH 34/52] fix: integrate normalize_place_of_supply function for place of supply handling in purchase and sales invoices --- .../validations/purchase_invoice.py | 4 +-- .../rohit_common/validations/sales_invoice.py | 14 ++++---- rohit_common/utils/rohit_common_utils.py | 33 +++++++++++++++++++ 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/rohit_common/rohit_common/validations/purchase_invoice.py b/rohit_common/rohit_common/validations/purchase_invoice.py index 223a3b1..9b7558a 100644 --- a/rohit_common/rohit_common/validations/purchase_invoice.py +++ b/rohit_common/rohit_common/validations/purchase_invoice.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe -from .sales_invoice import check_validated_gstin +from .sales_invoice import check_validated_gstin, normalize_place_of_supply def validate(doc,method): @@ -65,7 +65,7 @@ def update_fields(doc,method): if it.gst_hsn_code != it_gst: it.gst_hsn_code = it_gst doc.letter_head = frappe.db.get_value("Purchase Taxes and Charges Template", doc.taxes_and_charges, "letter_head") - # doc.place_of_supply = frappe.db.get_value("Purchase Taxes and Charges Template", doc.taxes_and_charges, "state") + doc.place_of_supply = normalize_place_of_supply(frappe.db.get_value("Purchase Taxes and Charges Template", doc.taxes_and_charges, "state")) doc.supplier_gstin = frappe.db.get_value("Address", doc.supplier_address, "gstin") doc.company_gstin = frappe.db.get_value("Address", doc.shipping_address, "gstin") diff --git a/rohit_common/rohit_common/validations/sales_invoice.py b/rohit_common/rohit_common/validations/sales_invoice.py index 482c307..f0b9784 100644 --- a/rohit_common/rohit_common/validations/sales_invoice.py +++ b/rohit_common/rohit_common/validations/sales_invoice.py @@ -8,7 +8,7 @@ from datetime import date from frappe.utils import getdate, flt from frappe.utils.background_jobs import enqueue -from ...utils.rohit_common_utils import replace_java_chars, check_dynamic_link, \ +from ...utils.rohit_common_utils import normalize_place_of_supply, replace_java_chars, check_dynamic_link, \ check_sales_taxes_integrity, remove_html def on_submit(doc, method): @@ -133,20 +133,20 @@ def check_local_natl_tax_rules(doc, template_doc): if bill_state == template_doc.state and template_doc.is_export == 0 and \ template_doc.is_sample != 1: - # doc.place_of_supply = template_doc.state + doc.place_of_supply = normalize_place_of_supply(template_doc.state) if template_doc.is_local_sales != 1: frappe.throw(f"Selected Tax {doc.taxes_and_charges} is NOT LOCAL Tax but Billing \ Address is in Same State {bill_state}, hence either change Billing Address or \ Change the Selected Tax") elif ship_country == 'India' and bill_state != template_doc.state and \ template_doc.is_sample != 1: - # doc.place_of_supply = bill_state + doc.place_of_supply = normalize_place_of_supply(bill_state) if template_doc.is_local_sales == 1: frappe.throw(f"Selected Tax {doc.taxes_and_charges} is LOCAL Tax but Billing Address \ is in Different State {bill_state}, hence either change Billing Address or Change \ the Selected Tax") elif ship_country != 'India': # Case of EXPORTS - # doc.place_of_supply = "Exempted" + doc.place_of_supply = "Exempted" if template_doc.is_export != 1: frappe.throw(f"Selected Tax {doc.taxes_and_charges} is for Indian Sales but Billing \ Address is in Different Country {ship_country}, hence either change Billing \ @@ -373,9 +373,9 @@ def check_validated_gstin(add_name, doc=None): days_since_validation = (date.today() - getdate(add_doc.gst_validation_date)).days else: days_since_validation = 999 - # if add_doc.validated_gstin != add_doc.gstin or days_since_validation > stale_days: - # frappe.throw(f"GSTIN# {add_doc.gstin} for {frappe.get_desk_link(add_doc.doctype, add_doc.name)} is " - # f"NOT Validated from GST Website. Please update the Address from GST Website") + if add_doc.validated_gstin != add_doc.gstin or days_since_validation > stale_days: + frappe.throw(f"GSTIN# {add_doc.gstin} for {frappe.get_desk_link(add_doc.doctype, add_doc.name)} is " + f"NOT Validated from GST Website. Please update the Address from GST Website") if add_doc.gst_status == "Suspended": if doc: if doc.doctype == "Sales Invoice": diff --git a/rohit_common/utils/rohit_common_utils.py b/rohit_common/utils/rohit_common_utils.py index 1903e83..e9067cb 100644 --- a/rohit_common/utils/rohit_common_utils.py +++ b/rohit_common/utils/rohit_common_utils.py @@ -7,6 +7,8 @@ import time import frappe from frappe.utils import get_files_path +from india_compliance.gst_india.constants import STATE_NUMBERS +from india_compliance.gst_india.utils import get_place_of_supply_options def check_or_rename_doc(document, backend): @@ -339,3 +341,34 @@ def fn_next_string(doc, s): if tail == 'N': return head+'P' return head + chr(ord(tail)+1) + +def normalize_place_of_supply(value: str | None) -> str | None: + """ + Convert things like "Karnataka" into "29-Karnataka" using india_compliance constants. + + Rules: + - If empty/None -> return None + - If value is in SPECIAL_POS_VALUES -> return as-is + - If value is already a valid PoS (e.g. "29-Karnataka") -> return as-is + - Else treat value as a state name and map via STATE_NUMBERS + - If no match -> throw the same error as india_compliance + """ + VALID_POS_VALUES = set(get_place_of_supply_options()) + SPECIAL_POS_VALUES = {"Exempted"} + + if not value: + return None + + value = str(value).strip() + + if value in SPECIAL_POS_VALUES: + return value + + if value in VALID_POS_VALUES: + return value + + code = STATE_NUMBERS.get(value) + if code: + return f"{code}-{value}" + + return value # Let india_compliance handle the error \ No newline at end of file From 4ee135b5ad3349aa4ba9006b9e4ed2cf696af54b Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Thu, 11 Dec 2025 10:41:39 +0000 Subject: [PATCH 35/52] fix: sales invoice e-invoice status --- docs/09-2025.md | 2 +- docs/10-2025.md | 2 +- rohit_common/custom_method.py | 178 +----------------- rohit_common/hooks.py | 3 + .../migrate_gl_to_payment_ledger.py | 174 +++++++++++++++++ .../rohit_common/validations/sales_invoice.py | 5 +- 6 files changed, 188 insertions(+), 176 deletions(-) create mode 100644 rohit_common/migration_scripts/migrate_gl_to_payment_ledger.py diff --git a/docs/09-2025.md b/docs/09-2025.md index 5be6ed3..ec9628c 100644 --- a/docs/09-2025.md +++ b/docs/09-2025.md @@ -102,7 +102,7 @@ **Issue:** Payment Ledger was empty due to a skipped patch introduced in later versions. **Fix:** Added a script to backfill Payment Ledger entries. -- **File:** `custom_method.py` +- **File:** `rohit_common/rohit_common/migration_scripts/migrate_gl_to_payment_ledger.py` - **Method:** `migrate_gl_to_payment_ledger()` **Notes:** diff --git a/docs/10-2025.md b/docs/10-2025.md index 5c6b1ee..d74b4fa 100644 --- a/docs/10-2025.md +++ b/docs/10-2025.md @@ -174,7 +174,7 @@ Validation error — *“Please set Account in Warehouse Machinery or Default In **Fix:** Added a script to backfill Payment Ledger entries. -- **File:** `custom_method.py` +- **File:** `rohit_common/rohit_common/migration_scripts/migrate_gl_to_payment_ledger.py` - **Method:** `migrate_gl_to_payment_ledger()` **Notes:** diff --git a/rohit_common/custom_method.py b/rohit_common/custom_method.py index 8287c0a..5cd43e6 100644 --- a/rohit_common/custom_method.py +++ b/rohit_common/custom_method.py @@ -1,174 +1,8 @@ import frappe -from frappe import qb -from frappe.query_builder import CustomFunction -from frappe.query_builder.custom import ConstantColumn -from frappe.query_builder.functions import Count, IfNull -from frappe.utils import flt -from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( - get_dimensions, - make_dimension_in_accounting_doctypes, -) - -# Note: Only run this script manually if official erpnext script fails or GLE not populated properly. -# Also before running take backup also truncate Payment Ledger Entry table -# Original patch path erpnext.erpnext.patches.v14_0.migrate_gl_to_payment_ledger - -# ------------------------- -# Helper Functions -# ------------------------- - -def create_accounting_dimension_fields(): - dimensions_and_defaults = get_dimensions() - if dimensions_and_defaults: - for dimension in dimensions_and_defaults[0]: - make_dimension_in_accounting_doctypes(dimension, ["Payment Ledger Entry"]) - - -def get_columns(): - columns = [ - "name", - "creation", - "modified", - "modified_by", - "owner", - "docstatus", - "posting_date", - "account_type", - "account", - "party_type", - "party", - "voucher_type", - "voucher_no", - "against_voucher_type", - "against_voucher_no", - "amount", - "amount_in_account_currency", - "account_currency", - "company", - "cost_center", - "due_date", - "finance_book", - ] - - if frappe.db.has_column("Payment Ledger Entry", "remarks"): - columns.append("remarks") - - dimensions_and_defaults = get_dimensions() - if dimensions_and_defaults: - for dimension in dimensions_and_defaults[0]: - columns.append(dimension.fieldname) - - return columns - - -def generate_name_and_calculate_amount(gl_entries, start, receivable_accounts): - for index, entry in enumerate(gl_entries, 0): - entry.name = start + index - if entry.account in receivable_accounts: - entry.account_type = "Receivable" - entry.amount = entry.debit - entry.credit - entry.amount_in_account_currency = entry.debit_in_account_currency - entry.credit_in_account_currency - else: - entry.account_type = "Payable" - entry.amount = entry.credit - entry.debit - entry.amount_in_account_currency = entry.credit_in_account_currency - entry.debit_in_account_currency - - -def build_insert_query(): - ple = qb.DocType("Payment Ledger Entry") - columns = get_columns() - insert_query = qb.into(ple).columns(tuple(columns)) - return insert_query - - -def insert_chunk_into_payment_ledger(insert_query, gl_entries): - if gl_entries: - columns = get_columns() - for entry in gl_entries: - data = tuple(entry[col] for col in columns) - insert_query = insert_query.insert(data) - insert_query.run() - frappe.db.commit() - - -# ------------------------- -# Main Migration Function -# ------------------------- - -def migrate_gl_to_payment_ledger(): - print("⚙️ Starting Payment Ledger migration...") - - # Ensure accounting dimension fields exist - create_accounting_dimension_fields() - - gl = qb.DocType("GL Entry") - account = qb.DocType("Account") - ifelse = CustomFunction("IF", ["condition", "then", "else"]) - - # Fetch Receivable and Payable accounts - relevant_accounts = ( - qb.from_(account) - .select(account.name, account.account_type) - .where((account.account_type == "Receivable") | (account.account_type == "Payable")) - .orderby(account.name) - .run(as_dict=True) - ) - - receivable_accounts = [x.name for x in relevant_accounts if x.account_type == "Receivable"] - accounts = [x.name for x in relevant_accounts] - - # Count unprocessed GL Entries - unprocessed_count = ( - qb.from_(gl) - .select(Count(gl.name)) - .where((gl.is_cancelled == 0) & (gl.account.isin(accounts))) - .run() - )[0][0] - - if not unprocessed_count: - print("No eligible GL Entries found. Exiting.") - return - - print(f"Migrating {unprocessed_count} GL Entries to Payment Ledger…") - - batch_size = 5000 - processed = 0 - last_name = None - - while True: - where_clause = (gl.account.isin(accounts) & (gl.is_cancelled == 0)) - if last_name: - where_clause &= gl.name.gt(last_name) - - gl_entries = ( - qb.from_(gl) - .select( - gl.star, - ConstantColumn(1).as_("docstatus"), - IfNull(ifelse(gl.against_voucher_type == "", None, gl.against_voucher_type), gl.voucher_type).as_("against_voucher_type"), - IfNull(ifelse(gl.against_voucher == "", None, gl.against_voucher), gl.voucher_no).as_("against_voucher_no"), - ) - .where(where_clause) - .orderby(gl.name) - .limit(batch_size) - .run(as_dict=True) - ) - - if not gl_entries: - break - - last_name = gl_entries[-1].name - - # Generate name and calculate amounts - generate_name_and_calculate_amount(gl_entries, processed, receivable_accounts) - - # Insert into Payment Ledger - insert_query = build_insert_query() - insert_chunk_into_payment_ledger(insert_query, gl_entries) - - processed += len(gl_entries) - percent = flt((processed / unprocessed_count) * 100, 2) - print(f"{percent}% ({processed}) records processed…") - - print(f"✅ Migration completed. Total records migrated: {processed}") +def set_einvoice_log_status_in_sales_invoice(doc, method=None): + """ + Set e-invoice status in Sales Invoice based on e-Invoice Log changes + """ + if doc.reference_doctype == "Sales Invoice" and doc.reference_name: + frappe.db.set_value("Sales Invoice", doc.reference_name, "einvoice_status", "Generated") \ No newline at end of file diff --git a/rohit_common/hooks.py b/rohit_common/hooks.py index 9f9e7fd..141fe2c 100644 --- a/rohit_common/hooks.py +++ b/rohit_common/hooks.py @@ -153,6 +153,9 @@ "validate": "rohit_common.rohit_common.validations.supplier.validate", }, "User": {"validate": "rohit_common.rohit_common.validations.user.validate"}, + "e-Invoice Log": { + "before_save": "rohit_common.custom_method.set_einvoice_log_status_in_sales_invoice", + }, # "*": { # "on_update": "method", # "on_cancel": "method", diff --git a/rohit_common/migration_scripts/migrate_gl_to_payment_ledger.py b/rohit_common/migration_scripts/migrate_gl_to_payment_ledger.py new file mode 100644 index 0000000..8287c0a --- /dev/null +++ b/rohit_common/migration_scripts/migrate_gl_to_payment_ledger.py @@ -0,0 +1,174 @@ +import frappe +from frappe import qb +from frappe.query_builder import CustomFunction +from frappe.query_builder.custom import ConstantColumn +from frappe.query_builder.functions import Count, IfNull +from frappe.utils import flt + +from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( + get_dimensions, + make_dimension_in_accounting_doctypes, +) + +# Note: Only run this script manually if official erpnext script fails or GLE not populated properly. +# Also before running take backup also truncate Payment Ledger Entry table +# Original patch path erpnext.erpnext.patches.v14_0.migrate_gl_to_payment_ledger + +# ------------------------- +# Helper Functions +# ------------------------- + +def create_accounting_dimension_fields(): + dimensions_and_defaults = get_dimensions() + if dimensions_and_defaults: + for dimension in dimensions_and_defaults[0]: + make_dimension_in_accounting_doctypes(dimension, ["Payment Ledger Entry"]) + + +def get_columns(): + columns = [ + "name", + "creation", + "modified", + "modified_by", + "owner", + "docstatus", + "posting_date", + "account_type", + "account", + "party_type", + "party", + "voucher_type", + "voucher_no", + "against_voucher_type", + "against_voucher_no", + "amount", + "amount_in_account_currency", + "account_currency", + "company", + "cost_center", + "due_date", + "finance_book", + ] + + if frappe.db.has_column("Payment Ledger Entry", "remarks"): + columns.append("remarks") + + dimensions_and_defaults = get_dimensions() + if dimensions_and_defaults: + for dimension in dimensions_and_defaults[0]: + columns.append(dimension.fieldname) + + return columns + + +def generate_name_and_calculate_amount(gl_entries, start, receivable_accounts): + for index, entry in enumerate(gl_entries, 0): + entry.name = start + index + if entry.account in receivable_accounts: + entry.account_type = "Receivable" + entry.amount = entry.debit - entry.credit + entry.amount_in_account_currency = entry.debit_in_account_currency - entry.credit_in_account_currency + else: + entry.account_type = "Payable" + entry.amount = entry.credit - entry.debit + entry.amount_in_account_currency = entry.credit_in_account_currency - entry.debit_in_account_currency + + +def build_insert_query(): + ple = qb.DocType("Payment Ledger Entry") + columns = get_columns() + insert_query = qb.into(ple).columns(tuple(columns)) + return insert_query + + +def insert_chunk_into_payment_ledger(insert_query, gl_entries): + if gl_entries: + columns = get_columns() + for entry in gl_entries: + data = tuple(entry[col] for col in columns) + insert_query = insert_query.insert(data) + insert_query.run() + frappe.db.commit() + + +# ------------------------- +# Main Migration Function +# ------------------------- + +def migrate_gl_to_payment_ledger(): + print("⚙️ Starting Payment Ledger migration...") + + # Ensure accounting dimension fields exist + create_accounting_dimension_fields() + + gl = qb.DocType("GL Entry") + account = qb.DocType("Account") + ifelse = CustomFunction("IF", ["condition", "then", "else"]) + + # Fetch Receivable and Payable accounts + relevant_accounts = ( + qb.from_(account) + .select(account.name, account.account_type) + .where((account.account_type == "Receivable") | (account.account_type == "Payable")) + .orderby(account.name) + .run(as_dict=True) + ) + + receivable_accounts = [x.name for x in relevant_accounts if x.account_type == "Receivable"] + accounts = [x.name for x in relevant_accounts] + + # Count unprocessed GL Entries + unprocessed_count = ( + qb.from_(gl) + .select(Count(gl.name)) + .where((gl.is_cancelled == 0) & (gl.account.isin(accounts))) + .run() + )[0][0] + + if not unprocessed_count: + print("No eligible GL Entries found. Exiting.") + return + + print(f"Migrating {unprocessed_count} GL Entries to Payment Ledger…") + + batch_size = 5000 + processed = 0 + last_name = None + + while True: + where_clause = (gl.account.isin(accounts) & (gl.is_cancelled == 0)) + if last_name: + where_clause &= gl.name.gt(last_name) + + gl_entries = ( + qb.from_(gl) + .select( + gl.star, + ConstantColumn(1).as_("docstatus"), + IfNull(ifelse(gl.against_voucher_type == "", None, gl.against_voucher_type), gl.voucher_type).as_("against_voucher_type"), + IfNull(ifelse(gl.against_voucher == "", None, gl.against_voucher), gl.voucher_no).as_("against_voucher_no"), + ) + .where(where_clause) + .orderby(gl.name) + .limit(batch_size) + .run(as_dict=True) + ) + + if not gl_entries: + break + + last_name = gl_entries[-1].name + + # Generate name and calculate amounts + generate_name_and_calculate_amount(gl_entries, processed, receivable_accounts) + + # Insert into Payment Ledger + insert_query = build_insert_query() + insert_chunk_into_payment_ledger(insert_query, gl_entries) + + processed += len(gl_entries) + percent = flt((processed / unprocessed_count) * 100, 2) + print(f"{percent}% ({processed}) records processed…") + + print(f"✅ Migration completed. Total records migrated: {processed}") diff --git a/rohit_common/rohit_common/validations/sales_invoice.py b/rohit_common/rohit_common/validations/sales_invoice.py index f0b9784..7f7394c 100644 --- a/rohit_common/rohit_common/validations/sales_invoice.py +++ b/rohit_common/rohit_common/validations/sales_invoice.py @@ -374,8 +374,9 @@ def check_validated_gstin(add_name, doc=None): else: days_since_validation = 999 if add_doc.validated_gstin != add_doc.gstin or days_since_validation > stale_days: - frappe.throw(f"GSTIN# {add_doc.gstin} for {frappe.get_desk_link(add_doc.doctype, add_doc.name)} is " - f"NOT Validated from GST Website. Please update the Address from GST Website") + pass + # frappe.throw(f"GSTIN# {add_doc.gstin} for {frappe.get_desk_link(add_doc.doctype, add_doc.name)} is " + # f"NOT Validated from GST Website. Please update the Address from GST Website") if add_doc.gst_status == "Suspended": if doc: if doc.doctype == "Sales Invoice": From 636226acb427c70e3932cc8f9fb3d48f8a826bc7 Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Thu, 11 Dec 2025 10:43:13 +0000 Subject: [PATCH 36/52] fix: sales invoice qrcode and ack --- rohit_common/custom_method.py | 75 ++++++++++++++++++++++++++++++++++- rohit_common/hooks.py | 1 + 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/rohit_common/custom_method.py b/rohit_common/custom_method.py index 5cd43e6..7e9133f 100644 --- a/rohit_common/custom_method.py +++ b/rohit_common/custom_method.py @@ -1,8 +1,81 @@ +import io +import re +import json import frappe +from pyqrcode import create as qrcreate +from frappe.utils import get_datetime def set_einvoice_log_status_in_sales_invoice(doc, method=None): """ Set e-invoice status in Sales Invoice based on e-Invoice Log changes """ if doc.reference_doctype == "Sales Invoice" and doc.reference_name: - frappe.db.set_value("Sales Invoice", doc.reference_name, "einvoice_status", "Generated") \ No newline at end of file + frappe.db.set_value("Sales Invoice", doc.reference_name, "einvoice_status", "Generated") + +def attach_qr_to_invoice(reference_doctype, reference_name, qr_value): + """Create a File doc for QR and attach to Sales Invoice.qrcode_image field.""" + if not qr_value: + return None + + # sanitize filename + new_name = re.sub('[^A-Za-z0-9]+', '', reference_name) + filename = f"QRCode_{new_name}.png" + + qr_image = io.BytesIO() + url = qrcreate(qr_value, error='L') + # scale can be adjusted; quiet_zone=1 keeps small whitespace + url.png(qr_image, scale=2, quiet_zone=1) + + file_doc = frappe.get_doc({ + "doctype": "File", + "file_name": filename, + "attached_to_doctype": reference_doctype, + "attached_to_name": reference_name, + "attached_to_field": "qrcode_image", + "is_private": 1, + "content": qr_image.getvalue() + }) + file_doc.insert(ignore_permissions=True) + # set qrcode_image field value as file URL + frappe.db.set_value(reference_doctype, reference_name, "qrcode_image", file_doc.file_url) + frappe.db.commit() + return file_doc.file_url + +def sync_einvoice_log_to_reference(doc, method=None): + """ + doc = e-Invoice Log document (india_compliance's doctype name may be exactly 'e-Invoice Log') + This will update the Sales Invoice (or other reference_doctype) with IRN, AckNo, AckDt and attach QR image. + """ + ref_doctype = getattr(doc, "reference_doctype", None) + ref_name = getattr(doc, "reference_name", None) + if not (ref_doctype and ref_name): + return + + try: + if getattr(doc, "irn", None): + frappe.db.set_value(ref_doctype, ref_name, "irn", doc.irn) + + if getattr(doc, "acknowledgement_number", None): + frappe.db.set_value(ref_doctype, ref_name, "ack_no", doc.acknowledgement_number) + + if getattr(doc, "acknowledged_on", None): + ack_dt = get_datetime(doc.acknowledged_on) if isinstance(doc.acknowledged_on, str) else doc.acknowledged_on + frappe.db.set_value(ref_doctype, ref_name, "ack_date", ack_dt) + + # Attach QR — try doc.signed_qr_code first, otherwise check invoice_data JSON for SignedQRCode + qr_value = getattr(doc, "signed_qr_code", None) + if not qr_value: + invoice_data = getattr(doc, "invoice_data", None) + if invoice_data: + try: + inv_json = json.loads(invoice_data) if isinstance(invoice_data, str) else invoice_data + # common places: SignedQRCode or SignedQRCode (case-sensitive may vary) + qr_value = inv_json.get("SignedQRCode") or inv_json.get("signed_qr_code") or inv_json.get("signedQrCode") + except Exception: + qr_value = None + + if qr_value: + attach_qr_to_invoice(ref_doctype, ref_name, qr_value) + + except Exception as e: + frappe.log_error(message=frappe.get_traceback(), title="sync_einvoice_log_to_reference failed") \ No newline at end of file diff --git a/rohit_common/hooks.py b/rohit_common/hooks.py index 141fe2c..1a8ee76 100644 --- a/rohit_common/hooks.py +++ b/rohit_common/hooks.py @@ -155,6 +155,7 @@ "User": {"validate": "rohit_common.rohit_common.validations.user.validate"}, "e-Invoice Log": { "before_save": "rohit_common.custom_method.set_einvoice_log_status_in_sales_invoice", + "after_insert": "rohit_common.custom_method.sync_einvoice_log_to_reference" }, # "*": { # "on_update": "method", From e5c10e9ad108d6bdad24193f6a41ada3d174efcf Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Thu, 11 Dec 2025 10:44:15 +0000 Subject: [PATCH 37/52] fix: gst validation --- rohit_common/rohit_common/validations/sales_invoice.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rohit_common/rohit_common/validations/sales_invoice.py b/rohit_common/rohit_common/validations/sales_invoice.py index 7f7394c..f0b9784 100644 --- a/rohit_common/rohit_common/validations/sales_invoice.py +++ b/rohit_common/rohit_common/validations/sales_invoice.py @@ -374,9 +374,8 @@ def check_validated_gstin(add_name, doc=None): else: days_since_validation = 999 if add_doc.validated_gstin != add_doc.gstin or days_since_validation > stale_days: - pass - # frappe.throw(f"GSTIN# {add_doc.gstin} for {frappe.get_desk_link(add_doc.doctype, add_doc.name)} is " - # f"NOT Validated from GST Website. Please update the Address from GST Website") + frappe.throw(f"GSTIN# {add_doc.gstin} for {frappe.get_desk_link(add_doc.doctype, add_doc.name)} is " + f"NOT Validated from GST Website. Please update the Address from GST Website") if add_doc.gst_status == "Suspended": if doc: if doc.doctype == "Sales Invoice": From 4b13dc5d5d9c43424a097540502d99f6058ee79e Mon Sep 17 00:00:00 2001 From: kalelkar-noman Date: Mon, 22 Dec 2025 11:11:32 +0000 Subject: [PATCH 38/52] fix: je gstin --- .../migration_scripts/je_company_gstin.py | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 rohit_common/migration_scripts/je_company_gstin.py diff --git a/rohit_common/migration_scripts/je_company_gstin.py b/rohit_common/migration_scripts/je_company_gstin.py new file mode 100644 index 0000000..2cecc48 --- /dev/null +++ b/rohit_common/migration_scripts/je_company_gstin.py @@ -0,0 +1,118 @@ +import frappe + +def repopulate_journal_entry_company_gstin( + dry_run=True, batch_size=1000, limit=None +): + """ + Populate Journal Entry.company_gstin from Company master. + Only fills missing GSTINs. + """ + + frappe.flags.in_migrate = True + + possible_company_gstin_fields = [ + "company_gstin", "gstin", "gstin_number", "tax_id", "tax_id_number" + ] + + print("Building Company GSTIN Map...") + company_gstin_map = {} + + for c in frappe.get_all("Company", fields=["name"]): + try: + comp = frappe.get_doc("Company", c.name) + except Exception: + continue + + gst = None + for f in possible_company_gstin_fields: + if hasattr(comp, f): + val = comp.get(f) + if val: + gst = val.strip() + break + + if gst: + company_gstin_map[c.name] = gst + + limit_clause = f"LIMIT {int(limit)}" if limit else "" + + print("Fetching Journal Entries with missing GSTIN...") + + jes = frappe.db.sql( + f""" + SELECT name, company, posting_date + FROM `tabJournal Entry` + WHERE docstatus = 1 + AND IFNULL(company_gstin, '') = '' + AND company IS NOT NULL + {limit_clause} + """, + as_dict=True, + ) + + total = len(jes) + print(f"Found {total} Journal Entry(s)") + + updated = skipped = 0 + errors = [] + + for idx, je in enumerate(jes, start=1): + company = je.company + gstin = company_gstin_map.get(company) + + if not gstin: + skipped += 1 + continue + + if dry_run: + if idx <= 20 or idx % 100 == 0: + print(f"[{idx}/{total}] Would update {je.name} → {gstin}") + else: + try: + frappe.db.set_value( + "Journal Entry", + je.name, + "company_gstin", + gstin, + update_modified=False, + ) + updated += 1 + except Exception as e: + errors.append((je.name, str(e))) + + if updated and updated % batch_size == 0: + frappe.db.commit() + print(f"Committed {updated} updates") + + if not dry_run: + frappe.db.commit() + print("Final commit done") + + print("Summary") + print("Total:", total) + print("Updated:", updated) + print("Skipped:", skipped) + print("Errors:", len(errors)) + + return { + "total": total, + "updated": updated, + "skipped": skipped, + "errors": errors, + } + + +def execute(dry_run=True, batch_size=1000, limit=None): + return repopulate_journal_entry_company_gstin( + dry_run=bool(dry_run), + batch_size=int(batch_size or 1000), + limit=int(limit) if limit else None, + ) + +# bench --site development.localhost \ +# execute rohit_common.migration_scripts.je_company_gstin.execute \ +# --kwargs "{'dry_run': True, 'limit': 50}" + +# bench --site development.localhost \ +# execute rohit_common.migration_scripts.je_company_gstin.execute \ +# --kwargs "{'dry_run': False, 'batch_size': 2000}" From 2783a84b063c09bdb0cdcf857abdd62ceaa7ec5f Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Mon, 12 Jan 2026 16:24:24 +0530 Subject: [PATCH 39/52] fix: address book report (#20) --- .../docs_execution_order.txt | 2 + .../migrate_gl_to_payment_ledger.py | 4 ++ .../address_book_rigpl/address_book_rigpl.js | 52 +++++++++---------- .../address_book_rigpl/address_book_rigpl.py | 42 +++++++++++++++ 4 files changed, 74 insertions(+), 26 deletions(-) diff --git a/rohit_common/migration_scripts/docs_execution_order.txt b/rohit_common/migration_scripts/docs_execution_order.txt index 35af948..5899ff2 100644 --- a/rohit_common/migration_scripts/docs_execution_order.txt +++ b/rohit_common/migration_scripts/docs_execution_order.txt @@ -1,3 +1,5 @@ +je_company_gstin.py +migrate_gl_to_payment_ledger.py Step 1: Fix Company GSTIN bench --site development.localhost execute rohit_common.migration_scripts.repopulate_company_gstin.execute #1 Step 7: Fix GL Entry Data diff --git a/rohit_common/migration_scripts/migrate_gl_to_payment_ledger.py b/rohit_common/migration_scripts/migrate_gl_to_payment_ledger.py index 8287c0a..c5e1ee8 100644 --- a/rohit_common/migration_scripts/migrate_gl_to_payment_ledger.py +++ b/rohit_common/migration_scripts/migrate_gl_to_payment_ledger.py @@ -172,3 +172,7 @@ def migrate_gl_to_payment_ledger(): print(f"{percent}% ({processed}) records processed…") print(f"✅ Migration completed. Total records migrated: {processed}") + + +# from rohit_common.migration_scripts.migrate_gl_to_payment_ledger import migrate_gl_to_payment_ledger +# migrate_gl_to_payment_ledger() \ No newline at end of file diff --git a/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.js b/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.js index 338f29d..0b35552 100644 --- a/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.js +++ b/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.js @@ -18,32 +18,32 @@ frappe.query_reports["Address Book RIGPL"] = { } }, { - "fieldname":"link_type", - "label": "Linked to", - "fieldtype": "Link", - "options": "DocType", - "reqd": 0, - "get_query": function() { - let type = frappe.query_report.get_filter_value('type'); - if (type === "Address"){ - return { - "filters": { - "fieldtype": ["=", "HTML"], - "fieldname": ["=", "address_html"], - } - } - } else if (type === "Contact"){ - return { - "filters": { - "fieldtype": ["=", "HTML"], - "fieldname": ["=", "contact_html"], - } - } - } else { - frappe.throw("Please Select Address or Contact based Report") - } - } - }, + "fieldname": "link_type", + "label": "Linked to", + "fieldtype": "Link", + "options": "DocType", + "reqd": 0, + "get_query": function() { + let type = frappe.query_report.get_filter_value('type'); + let target_field = ""; + + if (type === "Address") { + target_field = "address_html"; + } else if (type === "Contact") { + target_field = "contact_html"; + } else { + frappe.throw("Please Select Address or Contact based Report"); + } + + return { + query: "rohit_common.rohit_common.report.address_book_rigpl.address_book_rigpl.get_doctypes_with_field", + filters: { + "fieldtype": "HTML", + "fieldname": target_field + } + }; + } + }, { "fieldname":"linked_to", "label": "Master Name", diff --git a/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.py b/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.py index acdef45..3fe48c5 100644 --- a/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.py +++ b/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.py @@ -5,6 +5,7 @@ import frappe import datetime import urllib.parse +from frappe.utils import getdate from ....utils.contact_utils import get_contact_phones, get_contact_emails @@ -78,9 +79,14 @@ def get_columns(filters, data): terr_fd = {"fieldname": "territory", "label": "Territory", "fieldtype":"Link", "options":"Territory"} col_map.append(terr_fd.copy()) + + if not data: + return col_map, [] + drop_cols = [] col_size = [] cols = frappe._dict({}) + for key in data[0].keys(): mlen = 0 for d in data: @@ -229,3 +235,39 @@ def get_conditions(filters): else: cond += " AND cu.customer_group = '%s'" % filters["customer_group"] return cond, tbl_join, fd_add + +@frappe.whitelist() +@frappe.validate_and_sanitize_search_inputs +def get_doctypes_with_field(doctype, txt, searchfield, start, page_len, filters): + """ + Finds DocTypes that contain a specific fieldname and fieldtype. + Searches both standard DocFields and Custom Fields. + """ + fieldname = filters.get("fieldname") + fieldtype = filters.get("fieldtype") + + standard_doctypes = frappe.get_all("DocField", + filters={ + "fieldname": fieldname, + "fieldtype": fieldtype, + "parent": ["like", f"%{txt}%"] + }, + fields=["parent"], + distinct=1, + pluck="parent" + ) + + custom_doctypes = frappe.get_all("Custom Field", + filters={ + "fieldname": fieldname, + "fieldtype": fieldtype, + "dt": ["like", f"%{txt}%"] + }, + fields=["dt"], + distinct=1, + pluck="dt" + ) + + results = sorted(list(set(standard_doctypes + custom_doctypes))) + + return [[r] for r in results] \ No newline at end of file From e2f9c127d56b8ce6e8812af2d00a02b14a0bca73 Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Wed, 14 Jan 2026 14:14:27 +0530 Subject: [PATCH 40/52] fix: contact not showing in address book (#21) --- .../report/address_book_rigpl/address_book_rigpl.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.js b/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.js index 0b35552..38a6667 100644 --- a/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.js +++ b/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.js @@ -12,7 +12,7 @@ frappe.query_reports["Address Book RIGPL"] = { "get_query": function() { return { "filters": { - "name": ["in", "Address, Contact"], + "name": ["in", ["Address", "Contact"]] } } } From 75eb271ef1ba6547cf7ca72e43d961320d3fc563 Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Fri, 16 Jan 2026 19:41:47 +0530 Subject: [PATCH 41/52] fix: report issues (#22) --- .../address_book_rigpl/address_book_rigpl.js | 79 ++++++++++--------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.js b/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.js index 38a6667..08d1f4e 100644 --- a/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.js +++ b/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.js @@ -4,12 +4,13 @@ frappe.query_reports["Address Book RIGPL"] = { "filters": [ { - "fieldname":"type", + "fieldname": "type", "label": "Address or Contact", "fieldtype": "Link", "options": "DocType", "reqd": 1, - "get_query": function() { + "ignore_link_validation": 1, + "get_query": function () { return { "filters": { "name": ["in", ["Address", "Contact"]] @@ -18,74 +19,80 @@ frappe.query_reports["Address Book RIGPL"] = { } }, { - "fieldname": "link_type", - "label": "Linked to", - "fieldtype": "Link", - "options": "DocType", - "reqd": 0, - "get_query": function() { - let type = frappe.query_report.get_filter_value('type'); - let target_field = ""; + "fieldname": "link_type", + "label": "Linked to", + "fieldtype": "Link", + "options": "DocType", + "reqd": 0, + "ignore_link_validation": 1, + "get_query": function () { + let type = frappe.query_report.get_filter_value('type'); + let target_field = ""; - if (type === "Address") { - target_field = "address_html"; - } else if (type === "Contact") { - target_field = "contact_html"; - } else { - frappe.throw("Please Select Address or Contact based Report"); - } + if (type === "Address") { + target_field = "address_html"; + } else if (type === "Contact") { + target_field = "contact_html"; + } else { + frappe.throw("Please Select Address or Contact based Report"); + } - return { - query: "rohit_common.rohit_common.report.address_book_rigpl.address_book_rigpl.get_doctypes_with_field", - filters: { - "fieldtype": "HTML", - "fieldname": target_field - } - }; - } - }, + return { + query: "rohit_common.rohit_common.report.address_book_rigpl.address_book_rigpl.get_doctypes_with_field", + filters: { + "fieldtype": "HTML", + "fieldname": target_field + } + }; + } + }, { - "fieldname":"linked_to", + "fieldname": "linked_to", "label": "Master Name", "fieldtype": "Dynamic Link", "options": "DocType", "reqd": 0, - "get_options": function() { + "ignore_link_validation": 1, + "get_options": function () { let link_type = frappe.query_report.get_filter_value('link_type'); - if(!link_type) { + if (!link_type) { frappe.throw(__("Please First Select Linked To Type")); } return link_type; } }, { - "fieldname":"territory", + "fieldname": "territory", "label": "Territory", "fieldtype": "Link", + "options": "Territory", "reqd": 0, - "get_options": function() { + "ignore_link_validation": 1, + "get_options": function () { let link_type = frappe.query_report.get_filter_value('link_type'); - if(link_type !== "Customer") { + if (link_type !== "Customer") { frappe.throw(__("Please First Select Linked To Customer")); } return "Territory"; } }, { - "fieldname":"customer_group", + "fieldname": "customer_group", "label": "Customer Group", "fieldtype": "Link", + "options": "Customer Group", "reqd": 0, - "get_options": function() { + "ignore_link_validation": 1, + "get_options": function () { let link_type = frappe.query_report.get_filter_value('link_type'); - if(link_type !== "Customer") { + if (link_type !== "Customer") { frappe.throw(__("Please First Select Linked To Customer")); } return "Customer Group"; } }, { - "fieldname":"orphaned", + "fieldname": "orphaned", "label": "Orphaned", "fieldtype": "Check", "reqd": 0, From 0dd0d9a75898da48ed441a81650617e52552f80a Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Mon, 2 Feb 2026 19:00:14 +0530 Subject: [PATCH 42/52] fix: transporters include FedEx client ID and secret fields (#23) --- .../doctype/transporters/transporters.json | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/rohit_common/rohit_common/doctype/transporters/transporters.json b/rohit_common/rohit_common/doctype/transporters/transporters.json index 44fb05c..4f5433e 100644 --- a/rohit_common/rohit_common/doctype/transporters/transporters.json +++ b/rohit_common/rohit_common/doctype/transporters/transporters.json @@ -1,5 +1,5 @@ { - "_last_update": "1297792942", + "actions": [], "allow_import": 1, "allow_rename": 1, "autoname": "field:shipping_co", @@ -38,6 +38,8 @@ "fedex_meter_number", "cb1", "fedex_password", + "fedex_client_id", + "fedex_client_secret", "region_code", "maximum_amount", "sb2", @@ -176,11 +178,19 @@ "fieldtype": "Column Break" }, { - "fieldname": "fedex_password", - "fieldtype": "Data", "label": "Fedex Password", "permlevel": 1 }, + { + "fieldname": "fedex_client_id", + "fieldtype": "Data", + "label": "FedEx Client ID" + }, + { + "fieldname": "fedex_client_secret", + "fieldtype": "Data", + "label": "FedEx Client Secret" + }, { "default": "0", "depends_on": "eval: doc.fedex_credentials === 1 || doc.dtdc_credentials === 1", @@ -323,13 +333,24 @@ "fieldname": "port_code", "fieldtype": "Data", "label": "Port Code" + }, + { + "fieldname": "fedex_client_id", + "fieldtype": "Data", + "label": "fedex client id" + }, + { + "fieldname": "fedex_client_secret", + "fieldtype": "Data", + "label": "fedex client secret" } ], - "modified": "2021-03-10 09:03:02.494447", + "links": [], + "modified": "2026-01-29 13:29:01.296181", "modified_by": "Administrator", "module": "rohit_common", "name": "Transporters", - "name_case": "Title Case", + "naming_rule": "By fieldname", "owner": "aditya@rigpl.com", "permissions": [ { @@ -342,7 +363,6 @@ "read": 1, "report": 1, "role": "System Manager", - "set_user_permissions": 1, "share": 1, "write": 1 }, @@ -359,7 +379,9 @@ "write": 1 } ], + "row_format": "Dynamic", "search_fields": "shipping_co", "sort_field": "modified", - "sort_order": "DESC" -} \ No newline at end of file + "sort_order": "DESC", + "states": [] +} From 278d84de7b9bb69b3eccb6f9c1854bd6a378378e Mon Sep 17 00:00:00 2001 From: Kalelker-Noman Date: Tue, 3 Feb 2026 10:02:34 +0000 Subject: [PATCH 43/52] fix: fedex_password field --- .../rohit_common/doctype/transporters/transporters.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rohit_common/rohit_common/doctype/transporters/transporters.json b/rohit_common/rohit_common/doctype/transporters/transporters.json index 4f5433e..dc67737 100644 --- a/rohit_common/rohit_common/doctype/transporters/transporters.json +++ b/rohit_common/rohit_common/doctype/transporters/transporters.json @@ -178,6 +178,9 @@ "fieldtype": "Column Break" }, { + + "fieldname": "fedex_password", + "fieldtype": "Data", "label": "Fedex Password", "permlevel": 1 }, From bd38f0c6b4ec3c68d22f0b13e07d912c83349260 Mon Sep 17 00:00:00 2001 From: Kalelker-Noman Date: Tue, 3 Feb 2026 17:27:32 +0000 Subject: [PATCH 44/52] fix: fedex creds fields --- .../doctype/transporters/transporters.json | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/rohit_common/rohit_common/doctype/transporters/transporters.json b/rohit_common/rohit_common/doctype/transporters/transporters.json index dc67737..45e5758 100644 --- a/rohit_common/rohit_common/doctype/transporters/transporters.json +++ b/rohit_common/rohit_common/doctype/transporters/transporters.json @@ -178,7 +178,6 @@ "fieldtype": "Column Break" }, { - "fieldname": "fedex_password", "fieldtype": "Data", "label": "Fedex Password", @@ -187,12 +186,12 @@ { "fieldname": "fedex_client_id", "fieldtype": "Data", - "label": "FedEx Client ID" + "label": "Fedex Client ID" }, { "fieldname": "fedex_client_secret", "fieldtype": "Data", - "label": "FedEx Client Secret" + "label": "Fedex Client Secret" }, { "default": "0", @@ -336,20 +335,10 @@ "fieldname": "port_code", "fieldtype": "Data", "label": "Port Code" - }, - { - "fieldname": "fedex_client_id", - "fieldtype": "Data", - "label": "fedex client id" - }, - { - "fieldname": "fedex_client_secret", - "fieldtype": "Data", - "label": "fedex client secret" } ], "links": [], - "modified": "2026-01-29 13:29:01.296181", + "modified": "2026-02-03 22:52:18.326871", "modified_by": "Administrator", "module": "rohit_common", "name": "Transporters", From e7818cfc9f226140d97bc318cb74efff84345eb9 Mon Sep 17 00:00:00 2001 From: Kalelker-Noman Date: Fri, 6 Feb 2026 09:27:01 +0000 Subject: [PATCH 45/52] fix: synced gross_purchase_amount field with eprnext --- .../patches/asset_depr_schedule_patch_utils.py | 2 +- .../report/asset_analysis/asset_analysis.py | 4 ++-- rohit_common/rohit_common/validations/asset.py | 14 +++++++------- rohit_common/utils/asset_utils.py | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/rohit_common/patches/asset_depr_schedule_patch_utils.py b/rohit_common/patches/asset_depr_schedule_patch_utils.py index c6d8ae4..1f2a3e7 100644 --- a/rohit_common/patches/asset_depr_schedule_patch_utils.py +++ b/rohit_common/patches/asset_depr_schedule_patch_utils.py @@ -4,7 +4,7 @@ def set_draft_asset_depr_schedule_details(self, asset_doc, row): self.finance_book_id = row.idx self.opening_accumulated_depreciation = asset_doc.opening_accumulated_depreciation or 0 self.opening_number_of_booked_depreciations = asset_doc.opening_number_of_booked_depreciations or 0 - self.gross_purchase_amount = asset_doc.gross_purchase_amount + self.net_purchase_amount = asset_doc.net_purchase_amount self.depreciation_method = row.depreciation_method self.total_number_of_depreciations = row.total_number_of_depreciations self.frequency_of_depreciation = row.frequency_of_depreciation diff --git a/rohit_common/rohit_common/report/asset_analysis/asset_analysis.py b/rohit_common/rohit_common/report/asset_analysis/asset_analysis.py index a907fb1..0db239d 100644 --- a/rohit_common/rohit_common/report/asset_analysis/asset_analysis.py +++ b/rohit_common/rohit_common/report/asset_analysis/asset_analysis.py @@ -20,7 +20,7 @@ def execute(filters=None): data = [] for a in assets: open_acc_dep = a.opening_accumulated_depreciation - purchase = a.gross_purchase_amount + purchase = a.net_purchase_amount row = [a.name, a.item_code, a.purchase_date, purchase, a.total_number_of_depreciations, open_acc_dep] check = 0 @@ -97,7 +97,7 @@ def get_assets(conditions, filters): IFNULL(ass.warehouse, "NIL") as warehouse, IFNULL(ass.model, "NIL") as model, IFNULL(ass.manufacturer, "NIL") as manufacturer, IFNULL(ass.status, "NO STATUS") as status, IFNULL(ass.description, "NIL") as description, ass.purchase_date, - ass.gross_purchase_amount, ass.opening_accumulated_depreciation, + ass.net_purchase_amount, ass.opening_accumulated_depreciation, IFNULL(ass_fb.expected_value_after_useful_life, 0) AS salvage, IFNULL(ass.disposal_date, '2199-12-31') as disposal_date, ass_fb.total_number_of_depreciations, as_cat_acc.fixed_asset_account, ass.purchase_receipt, diff --git a/rohit_common/rohit_common/validations/asset.py b/rohit_common/rohit_common/validations/asset.py index 460e96f..1087830 100644 --- a/rohit_common/rohit_common/validations/asset.py +++ b/rohit_common/rohit_common/validations/asset.py @@ -23,7 +23,7 @@ def validate(doc, method): for d in doc.finance_books: if d.depreciation_method != 'Manual': d.expected_value_after_useful_life = round((ass_cat.residual_value_percent * - doc.gross_purchase_amount)/100,0) + doc.net_purchase_amount)/100,0) exp_val_aft_life = d.expected_value_after_useful_life d.frequency_of_depreciation = dep_freq d.depreciation_method = dep_meth @@ -40,7 +40,7 @@ def validate(doc, method): fb_dict.setdefault("depreciation_start_date", doc.purchase_date) fb_dict.setdefault("total_number_of_depreciations", tot_no_of_deps) fb_dict.setdefault("frequency_of_depreciation", dep_freq) - exp_val_aft_life = round((ass_cat.residual_value_percent * doc.gross_purchase_amount)/100,0) + exp_val_aft_life = round((ass_cat.residual_value_percent * doc.net_purchase_amount)/100,0) fb_dict.setdefault("expected_value_after_useful_life", exp_val_aft_life) fb_list.append(fb_dict) for d in fb_list: @@ -109,11 +109,11 @@ def make_dep_schedule(doc, base_dep_date, exp_val_aft_life, dep_freq, tot_dep): middle_purchase_factor = flt(diff_days)/flt(fy_days) if tot_dep == cint(doc.number_of_depreciations_booked): - doc.opening_accumulated_depreciation = (doc.gross_purchase_amount - exp_val_aft_life) + doc.opening_accumulated_depreciation = (doc.net_purchase_amount - exp_val_aft_life) doc.schedules = [] dont_make_sch = 1 else: - if doc.opening_accumulated_depreciation == (doc.gross_purchase_amount - exp_val_aft_life): + if doc.opening_accumulated_depreciation == (doc.net_purchase_amount - exp_val_aft_life): doc.number_of_depreciations_booked = tot_dep doc.schedules = [] dont_make_sch = 1 @@ -123,7 +123,7 @@ def make_dep_schedule(doc, base_dep_date, exp_val_aft_life, dep_freq, tot_dep): if dont_make_sch != 1: if not doc.get("schedules") and doc.next_depreciation_date: - value_after_depreciation = doc.gross_purchase_amount - doc.opening_accumulated_depreciation + value_after_depreciation = doc.net_purchase_amount - doc.opening_accumulated_depreciation if diff_months < dep_freq: number_of_pending_depreciations = cint(tot_dep) - \ @@ -157,7 +157,7 @@ def make_dep_schedule(doc, base_dep_date, exp_val_aft_life, dep_freq, tot_dep): depreciation_amount = flt(d.depreciation_amount, d.precision("depreciation_amount")) if i==len(doc.get("schedules"))-1 and doc.depreciation_method == "Straight Line": - depreciation_amount = flt((doc.gross_purchase_amount) - flt(accumulated_depreciation) - flt(exp_val_aft_life), + depreciation_amount = flt((doc.net_purchase_amount) - flt(accumulated_depreciation) - flt(exp_val_aft_life), d.precision("depreciation_amount")) d.depreciation_amount = depreciation_amount @@ -170,7 +170,7 @@ def get_depreciation_amount(doc, depreciable_value, middle_purchase_factor): dep_freq, tot_no_of_deps, dep_meth, exp_val_aft_life = get_defaults(doc) if dep_meth in ("Straight Line", "Manual"): - depreciation_amount = round((flt(doc.gross_purchase_amount) - + depreciation_amount = round((flt(doc.net_purchase_amount) - flt(exp_val_aft_life) - flt(doc.opening_accumulated_depreciation))* middle_purchase_factor / (cint(tot_no_of_deps) - cint(doc.number_of_depreciations_booked)),0) diff --git a/rohit_common/utils/asset_utils.py b/rohit_common/utils/asset_utils.py index d63749b..cf876fd 100644 --- a/rohit_common/utils/asset_utils.py +++ b/rohit_common/utils/asset_utils.py @@ -44,7 +44,7 @@ def get_total_assets_for_item_code(item_code, on_date, active=1): else: disp_date_cond = "" query = f"""SELECT asst.name, asst.purchase_date, asst.status, - IFNULL(asst.disposal_date, '2099-12-31') as disposal_date, asst.gross_purchase_amount + IFNULL(asst.disposal_date, '2099-12-31') as disposal_date, asst.net_purchase_amount FROM `tabAsset` asst WHERE asst.docstatus = 1 AND asst.purchase_date <= '{on_date}' AND asst.item_code = '{item_code}' {disp_date_cond} @@ -54,6 +54,6 @@ def get_total_assets_for_item_code(item_code, on_date, active=1): frappe.msgprint(f"No Assets found for {frappe.get_desk_link('Item', item_code)}") ast_dict["no_of_assets"] = len(assets) for ast in assets: - total_asst_value += ast.gross_purchase_amount + total_asst_value += ast.net_purchase_amount ast_dict["total_value"] = total_asst_value return ast_dict From 2fe34734e706486b87c847a0afef53bb31751652 Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Thu, 26 Feb 2026 13:57:37 +0530 Subject: [PATCH 46/52] fix: purchase order title issue (#24) --- rohit_common/fixtures/custom_docperm.json | 110 + .../rohit_common/custom/purchase_order.json | 1318 +++++++++- .../custom/purchase_order_item.json | 2294 +++++++++++++++-- .../custom/purchase_taxes_and_charges.json | 471 ++++ 4 files changed, 3921 insertions(+), 272 deletions(-) create mode 100644 rohit_common/rohit_common/custom/purchase_taxes_and_charges.json diff --git a/rohit_common/fixtures/custom_docperm.json b/rohit_common/fixtures/custom_docperm.json index ed46082..4ab9ebf 100644 --- a/rohit_common/fixtures/custom_docperm.json +++ b/rohit_common/fixtures/custom_docperm.json @@ -1,4 +1,82 @@ [ + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 0, + "export": 1, + "if_owner": 1, + "impersonate": 0, + "import": 0, + "mask": 0, + "modified": "2020-10-19 11:51:56.257826", + "name": "6571655e2b", + "parent": "File", + "permlevel": 0, + "print": 0, + "read": 1, + "report": 1, + "role": "All", + "select": 0, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 0, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 0, + "export": 1, + "if_owner": 0, + "impersonate": 0, + "import": 0, + "mask": 0, + "modified": "2025-11-25 12:25:57.562209", + "name": "ff73pccb0n", + "parent": "File", + "permlevel": 0, + "print": 0, + "read": 1, + "report": 0, + "role": "Employee Self Service", + "select": 0, + "share": 0, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 1, + "if_owner": 0, + "impersonate": 0, + "import": 1, + "mask": 0, + "modified": "2017-03-30 23:11:36.855856", + "name": "45309661aa", + "parent": "File", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "select": 0, + "share": 1, + "submit": 0, + "write": 1 + }, { "amend": 0, "cancel": 0, @@ -9,7 +87,9 @@ "email": 0, "export": 1, "if_owner": 0, + "impersonate": 0, "import": 0, + "mask": 0, "modified": "2025-10-08 13:03:41.259013", "name": "7c73067c6e", "parent": "Accounts Settings", @@ -33,7 +113,9 @@ "email": 1, "export": 1, "if_owner": 0, + "impersonate": 0, "import": 1, + "mask": 0, "modified": "2025-09-24 15:08:40.557587", "name": "m7hut3b1u5", "parent": "e-Invoice Log", @@ -57,7 +139,9 @@ "email": 1, "export": 0, "if_owner": 0, + "impersonate": 0, "import": 0, + "mask": 0, "modified": "2025-09-18 12:27:05.391678", "name": "f5341bed97", "parent": "File", @@ -81,7 +165,9 @@ "email": 1, "export": 0, "if_owner": 1, + "impersonate": 0, "import": 0, + "mask": 0, "modified": "2025-09-18 13:44:58.502414", "name": "gi0c6fbkum", "parent": "File", @@ -105,7 +191,9 @@ "email": 1, "export": 1, "if_owner": 0, + "impersonate": 0, "import": 0, + "mask": 0, "modified": "2025-09-24 15:08:32.029829", "name": "m7goptn66e", "parent": "e-Invoice Log", @@ -129,7 +217,9 @@ "email": 1, "export": 1, "if_owner": 0, + "impersonate": 0, "import": 0, + "mask": 0, "modified": "2025-09-24 15:08:32.127716", "name": "m7hfu12j3g", "parent": "e-Invoice Log", @@ -153,7 +243,9 @@ "email": 0, "export": 1, "if_owner": 0, + "impersonate": 0, "import": 0, + "mask": 0, "modified": "2025-10-08 12:55:33.622088", "name": "ahvbd2d0tl", "parent": "GSTR-1", @@ -177,7 +269,9 @@ "email": 1, "export": 1, "if_owner": 0, + "impersonate": 0, "import": 0, + "mask": 0, "modified": "2025-10-08 13:21:04.631867", "name": "rmkmoq0a9h", "parent": "GSTR2A RIGPL", @@ -201,7 +295,9 @@ "email": 0, "export": 1, "if_owner": 0, + "impersonate": 0, "import": 0, + "mask": 0, "modified": "2025-10-08 12:55:41.447242", "name": "ahv4llqtun", "parent": "GSTR-1", @@ -225,7 +321,9 @@ "email": 1, "export": 1, "if_owner": 0, + "impersonate": 0, "import": 0, + "mask": 0, "modified": "2025-10-08 13:20:58.021690", "name": "rmkpgug6pi", "parent": "GSTR2A RIGPL", @@ -249,7 +347,9 @@ "email": 0, "export": 1, "if_owner": 0, + "impersonate": 0, "import": 0, + "mask": 0, "modified": "2025-10-08 12:55:39.769575", "name": "ahuqdqs6rd", "parent": "GSTR-1", @@ -273,7 +373,9 @@ "email": 1, "export": 1, "if_owner": 0, + "impersonate": 0, "import": 0, + "mask": 0, "modified": "2025-10-08 13:21:11.670358", "name": "rmjskl176l", "parent": "GSTR2A RIGPL", @@ -297,7 +399,9 @@ "email": 0, "export": 1, "if_owner": 0, + "impersonate": 0, "import": 0, + "mask": 0, "modified": "2025-10-08 12:55:42.837348", "name": "ahvas2oi6d", "parent": "GSTR-1", @@ -321,7 +425,9 @@ "email": 1, "export": 1, "if_owner": 0, + "impersonate": 0, "import": 0, + "mask": 0, "modified": "2025-10-08 13:20:57.997129", "name": "rmjd3p3ar7", "parent": "GSTR2A RIGPL", @@ -345,7 +451,9 @@ "email": 1, "export": 1, "if_owner": 0, + "impersonate": 0, "import": 0, + "mask": 0, "modified": "2025-10-08 13:21:10.038098", "name": "rmkqtrrcrd", "parent": "GSTR2A RIGPL", @@ -369,7 +477,9 @@ "email": 1, "export": 1, "if_owner": 0, + "impersonate": 0, "import": 0, + "mask": 0, "modified": "2025-10-08 13:20:58.002956", "name": "rmkno92l39", "parent": "GSTR2A RIGPL", diff --git a/rohit_common/rohit_common/custom/purchase_order.json b/rohit_common/rohit_common/custom/purchase_order.json index 8eccfe6..fe38b7d 100644 --- a/rohit_common/rohit_common/custom/purchase_order.json +++ b/rohit_common/rohit_common/custom/purchase_order.json @@ -5,13 +5,15 @@ "_comments": null, "_liked_by": null, "_user_tags": null, + "alignment": null, "allow_in_quick_entry": 0, - "allow_on_submit": 0, + "allow_on_submit": 1, "bold": 0, + "button_color": null, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2016-08-13 17:11:41", + "creation": "2022-01-03 12:06:24.744367", "default": null, "depends_on": null, "description": null, @@ -19,38 +21,52 @@ "dt": "Purchase Order", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "is_subcontracting", + "fieldname": "background_processing", "fieldtype": "Check", "hidden": 0, - "idx": 13, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 12, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "background_processing", - "label": "Is Subcontracting", + "insert_after": "transaction_date", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Background Processing", "length": 0, - "modified": "2017-11-16 13:08:26.291744", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2022-01-03 12:06:24.744367", "modified_by": "Administrator", - "name": "Purchase Order-is_subcontracting", + "module": null, + "name": "Purchase Order-background_processing", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, - "permlevel": 0, - "precision": null, + "permlevel": 1, + "placeholder": null, + "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "unique": 0, "width": null @@ -60,53 +76,69 @@ "_comments": null, "_liked_by": null, "_user_tags": null, + "alignment": null, "allow_in_quick_entry": 0, - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, + "button_color": null, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2018-03-21 11:53:13.887727", + "creation": "2020-10-17 23:16:23.069205", "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Purchase Order", - "fetch_from": null, + "fetch_from": "shipping_address.gstin", "fetch_if_empty": 0, - "fieldname": "transporters", - "fieldtype": "Link", + "fieldname": "company_gstin", + "fieldtype": "Data", "hidden": 0, - "idx": 7, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 39, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "supplier_name", - "label": "Transporters", + "insert_after": "billing_address", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Company GSTIN", "length": 0, - "modified": "2018-03-21 11:53:13.887727", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-10-18 00:09:29.421608", "modified_by": "Administrator", - "name": "Purchase Order-transporters", + "module": "GST India", + "name": "Purchase Order-company_gstin", "no_copy": 0, - "options": "Transporters", + "non_negative": 0, + "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, "unique": 0, "width": null }, @@ -115,52 +147,68 @@ "_comments": null, "_liked_by": null, "_user_tags": null, + "alignment": null, "allow_in_quick_entry": 0, "allow_on_submit": 1, "bold": 0, + "button_color": null, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2018-03-21 11:54:04.631248", + "creation": "2025-11-25 12:38:58.645188", "default": null, - "depends_on": "eval: doc.transporters", + "depends_on": null, "description": null, "docstatus": 0, "dt": "Purchase Order", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "lr_no", - "fieldtype": "Data", + "fieldname": "gst_breakup_table", + "fieldtype": "Text Editor", "hidden": 0, - "idx": 8, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "transporters", - "label": "LR No", + "insert_after": "section_gst_breakup", + "is_system_generated": 1, + "is_virtual": 1, + "label": "GST Breakup Table", "length": 0, - "modified": "2018-03-21 11:54:04.631248", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-11-25 12:38:58.645188", "modified_by": "Administrator", - "name": "Purchase Order-lr_no", + "module": "GST India", + "name": "Purchase Order-gst_breakup_table", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "unique": 0, "width": null @@ -170,53 +218,69 @@ "_comments": null, "_liked_by": null, "_user_tags": null, + "alignment": null, "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, + "button_color": null, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-10-17 23:16:22.379772", + "creation": "2025-11-25 12:38:58.638562", "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Purchase Order", - "fetch_from": "supplier_address.gstin", + "fetch_from": "supplier_address.gst_category", "fetch_if_empty": 0, - "fieldname": "supplier_gstin", + "fieldname": "gst_category", "fieldtype": "Data", "hidden": 0, - "idx": 28, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "supplier_address", - "label": "Supplier GSTIN", + "insert_after": "supplier_gstin", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST Category", "length": 0, - "modified": "2020-10-18 00:09:28.562645", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-11-25 12:38:58.638562", "modified_by": "Administrator", - "name": "Purchase Order-supplier_gstin", + "module": "GST India", + "name": "Purchase Order-gst_category", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 1, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, "unique": 0, "width": null }, @@ -225,53 +289,211 @@ "_comments": null, "_liked_by": null, "_user_tags": null, + "alignment": null, "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, + "button_color": null, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-10-17 23:16:23.069205", + "creation": "2025-11-25 12:38:58.642410", + "default": "0", + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Purchase Order", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "is_reverse_charge", + "fieldtype": "Check", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "apply_tds", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Is Reverse Charge", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-11-25 12:38:58.642410", + "modified_by": "Administrator", + "module": "GST India", + "name": "Purchase Order-is_reverse_charge", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2016-08-13 17:11:41", "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Purchase Order", - "fetch_from": "shipping_address.gstin", + "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "company_gstin", + "fieldname": "is_subcontracting", + "fieldtype": "Check", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 13, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "background_processing", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Is Subcontracting", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2017-11-16 13:08:26.291744", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-is_subcontracting", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": null, + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 1, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2018-03-21 11:54:04.631248", + "default": null, + "depends_on": "eval: doc.transporters", + "description": null, + "docstatus": 0, + "dt": "Purchase Order", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "lr_no", "fieldtype": "Data", "hidden": 0, - "idx": 39, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 8, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "billing_address", - "label": "Company GSTIN", + "insert_after": "transporters", + "is_system_generated": 1, + "is_virtual": 0, + "label": "LR No", "length": 0, - "modified": "2020-10-18 00:09:29.421608", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2018-03-21 11:54:04.631248", "modified_by": "Administrator", - "name": "Purchase Order-company_gstin", + "module": null, + "name": "Purchase Order-lr_no", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 1, + "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 1, + "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, - "translatable": 1, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, "unique": 0, "width": null }, @@ -280,9 +502,11 @@ "_comments": null, "_liked_by": null, "_user_tags": null, + "alignment": null, "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, + "button_color": null, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, @@ -297,6 +521,9 @@ "fieldname": "place_of_supply", "fieldtype": "Data", "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, "idx": 36, "ignore_user_permissions": 0, "ignore_xss_filter": 0, @@ -304,28 +531,39 @@ "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, "insert_after": "shipping_address", + "is_system_generated": 1, + "is_virtual": 0, "label": "Place of Supply", "length": 0, + "link_filters": null, + "mandatory_depends_on": null, "modified": "2020-10-18 00:09:30.289191", "modified_by": "Administrator", + "module": "GST India", "name": "Purchase Order-place_of_supply", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": null, "read_only": 1, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 1, "unique": 0, "width": null @@ -335,13 +573,15 @@ "_comments": null, "_liked_by": null, "_user_tags": null, + "alignment": null, "allow_in_quick_entry": 0, - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, - "collapsible": 0, + "button_color": null, + "collapsible": 1, "collapsible_depends_on": null, "columns": 0, - "creation": "2022-01-03 12:06:24.744367", + "creation": "2025-11-25 12:38:58.643823", "default": null, "depends_on": null, "description": null, @@ -349,45 +589,983 @@ "dt": "Purchase Order", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "background_processing", - "fieldtype": "Check", + "fieldname": "section_gst_breakup", + "fieldtype": "Section Break", "hidden": 0, - "idx": 12, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, "in_filter_dash": 0, "in_global_search": 0, "in_list_view": 0, + "in_preview": 0, "in_standard_filter": 0, - "insert_after": "transaction_date", - "label": "Background Processing", + "insert_after": "other_charges_calculation", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST Breakup", "length": 0, - "modified": "2022-01-03 12:06:24.744367", + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-11-25 12:38:58.643823", "modified_by": "Administrator", - "name": "Purchase Order-background_processing", + "module": "GST India", + "name": "Purchase Order-section_gst_breakup", "no_copy": 0, + "non_negative": 0, "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, - "permlevel": 1, + "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, "read_only": 0, + "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, "translatable": 0, "unique": 0, "width": null - } - ], - "custom_perms": [], - "doctype": "Purchase Order", - "property_setters": [], + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2020-10-17 23:16:22.379772", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Purchase Order", + "fetch_from": "supplier_address.gstin", + "fetch_if_empty": 0, + "fieldname": "supplier_gstin", + "fieldtype": "Data", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 28, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "supplier_address", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Supplier GSTIN", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-10-18 00:09:28.562645", + "modified_by": "Administrator", + "module": "GST India", + "name": "Purchase Order-supplier_gstin", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 1, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2018-03-21 11:53:13.887727", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Purchase Order", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "transporters", + "fieldtype": "Link", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 7, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "supplier_name", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Transporters", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2018-03-21 11:53:13.887727", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-transporters", + "no_copy": 0, + "non_negative": 0, + "options": "Transporters", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + } + ], + "custom_perms": [], + "doctype": "Purchase Order", + "links": [], + "property_setters": [ + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 19:19:34.263579", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_net_total", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:38.327447", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-base_net_total-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-11-23 15:20:53.365262", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_rounded_total", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:38.365256", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-base_rounded_total-hidden", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-11-23 15:20:53.377229", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_rounded_total", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:38.404037", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-base_rounded_total-print_hide", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_hide", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 19:19:34.001405", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_total", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:38.448759", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-base_total-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-11-13 11:05:12.545173", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "contact_person", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:38.484920", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-contact_person-ignore_user_permissions", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-11-23 15:20:53.406241", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "disable_rounded_total", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:38.564888", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-disable_rounded_total-default", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "default", + "property_type": "Text", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-07-18 14:37:25.621563", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "due_date", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:38.615399", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-due_date-print_hide", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_hide", + "property_type": "Check", + "row_name": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-11-23 15:20:53.618601", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "in_words", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:38.707342", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-in_words-hidden", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-11-23 15:20:53.630502", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "in_words", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:38.748148", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-in_words-print_hide", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_hide", + "property_type": "Check", + "row_name": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-31 22:16:51.637632", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "is_subcontracted", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:38.781783", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-is_subcontracted-hidden", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2012-04-02 20:33:48", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "letter_head", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:38.656096", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-letter_head-reqd", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "reqd", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-12-30 14:57:07.261200", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": null, + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:38.277324", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-main-_idx", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "_idx", + "property_type": "Text", + "row_name": null, + "value": "[\"supplier_section\", \"naming_series\", \"supplier\", \"is_subcontracted\", \"supplier_name\", \"address_display\", \"contact_display\", \"contact_mobile\", \"contact_email\", \"column_break1\", \"transaction_date\", \"challan_number\", \"amended_from\", \"company\", \"currency_and_price_list\", \"cb_currency\", \"currency\", \"conversion_rate\", \"cb_price_list\", \"buying_price_list\", \"price_list_currency\", \"plc_conversion_rate\", \"ignore_pricing_rule\", \"items_section\", \"items\", \"get_last_purchase_rate\", \"sb_last_purchase\", \"base_total\", \"base_net_total\", \"column_break_26\", \"total\", \"net_total\", \"taxes_section\", \"taxes_and_charges\", \"taxes\", \"other_charges_calculation\", \"totals\", \"base_taxes_and_charges_added\", \"base_taxes_and_charges_deducted\", \"base_total_taxes_and_charges\", \"column_break_39\", \"taxes_and_charges_added\", \"taxes_and_charges_deducted\", \"total_taxes_and_charges\", \"discount_section\", \"apply_discount_on\", \"column_break_45\", \"discount_amount\", \"base_discount_amount\", \"totals_section\", \"base_grand_total\", \"base_in_words\", \"base_rounded_total\", \"advance_paid\", \"column_break4\", \"grand_total\", \"in_words\", \"fold\", \"terms_section_break\", \"tc_name\", \"terms\", \"contact_section\", \"supplier_address\", \"cb_contact\", \"contact_person\", \"more_info\", \"status\", \"fiscal_year\", \"ref_sq\", \"column_break5\", \"letter_head\", \"select_print_heading\", \"payment_terms\", \"sub_contracting\", \"per_received\", \"remarks\", \"column_break_74\", \"per_billed\", \"instructions\", \"raw_material_details\", \"supplied_items\", \"recurring_order\", \"column_break\", \"is_recurring\", \"recurring_type\", \"from_date\", \"to_date\", \"repeat_on_day_of_month\", \"end_date\", \"column_break83\", \"next_date\", \"recurring_id\", \"notification_email_address\"]" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2014-09-20 11:43:04.884052", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": null, + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:38.520980", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-main-default_print_format", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "default_print_format", + "property_type": "Data", + "row_name": null, + "value": "Purchase Order" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2026-02-26 13:30:55.802956", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": null, + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:30:55.802956", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-main-field_order", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "field_order", + "property_type": "Data", + "row_name": null, + "value": "[\"supplier_section\", \"title\", \"naming_series\", \"supplier\", \"supplier_name\", \"transporters\", \"lr_no\", \"order_confirmation_no\", \"order_confirmation_date\", \"column_break_7\", \"transaction_date\", \"background_processing\", \"is_subcontracting\", \"schedule_date\", \"column_break1\", \"company\", \"is_subcontracted\", \"has_unit_price_items\", \"supplier_warehouse\", \"accounting_dimensions_section\", \"cost_center\", \"dimension_col_break\", \"project\", \"currency_and_price_list\", \"currency\", \"conversion_rate\", \"cb_price_list\", \"buying_price_list\", \"price_list_currency\", \"plc_conversion_rate\", \"ignore_pricing_rule\", \"before_items_section\", \"scan_barcode\", \"last_scanned_warehouse\", \"items_col_break\", \"set_from_warehouse\", \"set_warehouse\", \"items_section\", \"items\", \"sb_last_purchase\", \"total_qty\", \"total_net_weight\", \"column_break_40\", \"base_total\", \"base_net_total\", \"column_break_26\", \"total\", \"net_total\", \"section_break_48\", \"pricing_rules\", \"raw_material_details\", \"set_reserve_warehouse\", \"supplied_items\", \"taxes_section\", \"tax_category\", \"taxes_and_charges\", \"column_break_53\", \"shipping_rule\", \"column_break_50\", \"incoterm\", \"named_place\", \"section_break_52\", \"taxes\", \"totals\", \"base_taxes_and_charges_added\", \"base_taxes_and_charges_deducted\", \"base_total_taxes_and_charges\", \"column_break_39\", \"taxes_and_charges_added\", \"taxes_and_charges_deducted\", \"total_taxes_and_charges\", \"totals_section\", \"grand_total\", \"in_words\", \"column_break4\", \"disable_rounded_total\", \"rounding_adjustment\", \"rounded_total\", \"base_totals_section\", \"base_grand_total\", \"base_in_words\", \"column_break_jkoz\", \"base_rounding_adjustment\", \"base_rounded_total\", \"section_break_tnkm\", \"advance_paid\", \"discount_section\", \"apply_discount_on\", \"base_discount_amount\", \"column_break_45\", \"additional_discount_percentage\", \"discount_amount\", \"sec_tax_breakup\", \"other_charges_calculation\", \"item_wise_tax_details\", \"address_and_contact_tab\", \"section_gst_breakup\", \"gst_breakup_table\", \"section_addresses\", \"supplier_address\", \"supplier_gstin\", \"gst_category\", \"address_display\", \"supplier_group\", \"col_break_address\", \"contact_person\", \"contact_display\", \"contact_mobile\", \"contact_email\", \"shipping_address_section\", \"dispatch_address\", \"dispatch_address_display\", \"column_break_99\", \"shipping_address\", \"place_of_supply\", \"shipping_address_display\", \"company_billing_address_section\", \"billing_address\", \"company_gstin\", \"column_break_103\", \"billing_address_display\", \"drop_ship\", \"customer\", \"customer_name\", \"column_break_19\", \"customer_contact_person\", \"customer_contact_display\", \"customer_contact_mobile\", \"customer_contact_email\", \"terms_tab\", \"payment_schedule_section\", \"payment_terms_template\", \"payment_schedule\", \"terms_section_break\", \"tc_name\", \"terms\", \"more_info_tab\", \"tracking_section\", \"status\", \"advance_payment_status\", \"column_break_75\", \"per_billed\", \"per_received\", \"column_break5\", \"letter_head\", \"group_same_items\", \"column_break_86\", \"select_print_heading\", \"language\", \"subscription_section\", \"from_date\", \"to_date\", \"column_break_97\", \"auto_repeat\", \"update_auto_repeat_reference\", \"additional_info_section\", \"party_account_currency\", \"represents_company\", \"ref_sq\", \"amended_from\", \"column_break_74\", \"mps\", \"is_internal_supplier\", \"inter_company_order_reference\", \"is_old_subcontracting_flow\", \"connections_tab\", \"is_reverse_charge\"]" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2022-02-07 05:40:16.798285", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": null, + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:39.282376", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-main-title_field", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "title_field", + "property_type": "Data", + "row_name": null, + "value": "supplier_name" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2014-06-24 12:12:21.213817", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "naming_series", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:38.823575", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-naming_series-default", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "default", + "property_type": "Text", + "row_name": null, + "value": "" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2014-06-24 12:12:21.167989", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "naming_series", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:38.855873", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-naming_series-options", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "options", + "property_type": "Text", + "row_name": null, + "value": "\nPORB26\nPOOG26" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-07-18 14:37:25.805456", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "payment_schedule", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:38.887134", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-payment_schedule-print_hide", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_hide", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-11-23 15:20:53.389248", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "rounded_total", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:38.933556", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-rounded_total-hidden", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-11-23 15:20:53.401366", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "rounded_total", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:38.977179", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-rounded_total-print_hide", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "print_hide", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2025-11-23 15:20:40.865130", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "scan_barcode", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:39.025774", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-scan_barcode-hidden", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-07-13 15:56:23.108397", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "shipping_address", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:39.070425", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-shipping_address-ignore_user_permissions", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-02-26 16:08:14.405192", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "status", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:39.129234", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-status-in_list_view", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-11-13 11:05:12.537948", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "supplier_address", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:39.169159", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-supplier_address-ignore_user_permissions", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-10-16 13:27:06.599204", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "supplier", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:39.206010", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-supplier-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "value": "158" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2021-03-15 13:39:07.572705", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "terms", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:39.249749", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-terms-allow_on_submit", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "allow_on_submit", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2026-02-26 13:30:55.974995", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "title", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:30:55.974995", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-title-fetch_from", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "fetch_from", + "property_type": "Small Text", + "row_name": null, + "value": "supplier.supplier_name" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 19:19:33.833799", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "total", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:39.351199", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-total-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2013-09-12 16:50:31", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "transaction_date", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:39.391566", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-transaction_date-default", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "default", + "property_type": "Text", + "row_name": null, + "value": "Today" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-07-11 17:53:46.118377", + "default_value": null, + "doc_type": "Purchase Order", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "transaction_date", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:39.438762", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order-transaction_date-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "value": "90" + } + ], "sync_on_migrate": 1 } \ No newline at end of file diff --git a/rohit_common/rohit_common/custom/purchase_order_item.json b/rohit_common/rohit_common/custom/purchase_order_item.json index 022fda2..eeea64f 100644 --- a/rohit_common/rohit_common/custom/purchase_order_item.json +++ b/rohit_common/rohit_common/custom/purchase_order_item.json @@ -5,13 +5,15 @@ "_comments": null, "_liked_by": null, "_user_tags": null, + "alignment": null, "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, + "button_color": null, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2016-06-09 09:04:18.182559", + "creation": "2025-11-25 12:38:58.810649", "default": null, "depends_on": null, "description": null, @@ -19,13 +21,13 @@ "dt": "Purchase Order Item", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "so_detail", - "fieldtype": "Data", + "fieldname": "cb_gst_details", + "fieldtype": "Column Break", "hidden": 0, "hide_border": 0, "hide_days": 0, "hide_seconds": 0, - "idx": 74, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, @@ -34,37 +36,38 @@ "in_list_view": 0, "in_preview": 0, "in_standard_filter": 0, - "index": null, - "insert_after": "delivered_by_supplier", - "is_system_generated": 0, + "insert_after": "cess_non_advol_rate", + "is_system_generated": 1, "is_virtual": 0, - "label": "SO Detail", + "label": null, "length": 0, + "link_filters": null, "mandatory_depends_on": null, - "modified": "2016-09-20 15:12:47.580282", - "modified_by": "aditya@rigpl.com", - "module": null, - "name": "Purchase Order Item-so_detail", + "modified": "2025-11-25 12:38:58.810649", + "modified_by": "Administrator", + "module": "GST India", + "name": "Purchase Order Item-cb_gst_details", "no_copy": 0, "non_negative": 0, "options": null, - "owner": "aditya@rigpl.com", + "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 1, + "read_only": 0, "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, "sort_options": 0, "translatable": 0, - "trash_reason": null, "unique": 0, "width": null }, @@ -73,13 +76,15 @@ "_comments": null, "_liked_by": null, "_user_tags": null, + "alignment": null, "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, + "button_color": null, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2016-08-13 17:27:02", + "creation": "2025-11-25 12:38:58.816452", "default": null, "depends_on": null, "description": null, @@ -87,13 +92,13 @@ "dt": "Purchase Order Item", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "subcontracted_item", - "fieldtype": "Link", + "fieldname": "cess_amount", + "fieldtype": "Currency", "hidden": 0, "hide_border": 0, "hide_days": 0, "hide_seconds": 0, - "idx": 2, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, @@ -102,37 +107,38 @@ "in_list_view": 0, "in_preview": 0, "in_standard_filter": 0, - "index": null, - "insert_after": "item_code", + "insert_after": "sgst_amount", "is_system_generated": 1, "is_virtual": 0, - "label": "Subcontracted Item", + "label": "CESS Amount", "length": 0, + "link_filters": null, "mandatory_depends_on": null, - "modified": "2017-11-16 13:08:26.585670", + "modified": "2025-11-25 12:38:58.816452", "modified_by": "Administrator", - "module": null, - "name": "Purchase Order Item-subcontracted_item", - "no_copy": 0, + "module": "GST India", + "name": "Purchase Order Item-cess_amount", + "no_copy": 1, "non_negative": 0, - "options": "Item", + "options": "Company:company:default_currency", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, - "precision": null, + "placeholder": null, + "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, "sort_options": 0, "translatable": 0, - "trash_reason": null, "unique": 0, "width": null }, @@ -141,13 +147,15 @@ "_comments": null, "_liked_by": null, "_user_tags": null, + "alignment": null, "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, + "button_color": null, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-10-16 16:28:03.959296", + "creation": "2025-11-25 12:38:58.817850", "default": null, "depends_on": null, "description": null, @@ -155,13 +163,13 @@ "dt": "Purchase Order Item", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "reference_dt", - "fieldtype": "Link", + "fieldname": "cess_non_advol_amount", + "fieldtype": "Currency", "hidden": 0, "hide_border": 0, "hide_days": 0, "hide_seconds": 0, - "idx": 61, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, @@ -170,25 +178,26 @@ "in_list_view": 0, "in_preview": 0, "in_standard_filter": 0, - "index": null, - "insert_after": "project", + "insert_after": "cess_amount", "is_system_generated": 1, "is_virtual": 0, - "label": "Reference DT", + "label": "CESS Non Advol Amount", "length": 0, + "link_filters": null, "mandatory_depends_on": null, - "modified": "2020-10-16 16:28:03.959296", + "modified": "2025-11-25 12:38:58.817850", "modified_by": "Administrator", - "module": null, - "name": "Purchase Order Item-reference_dt", - "no_copy": 0, + "module": "GST India", + "name": "Purchase Order Item-cess_non_advol_amount", + "no_copy": 1, "non_negative": 0, - "options": "DocType", + "options": "Company:company:default_currency", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, @@ -198,9 +207,9 @@ "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, "sort_options": 0, "translatable": 0, - "trash_reason": null, "unique": 0, "width": null }, @@ -209,27 +218,29 @@ "_comments": null, "_liked_by": null, "_user_tags": null, + "alignment": null, "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, + "button_color": null, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-10-16 16:28:09.079292", + "creation": "2025-11-25 12:38:58.809267", "default": null, - "depends_on": "", + "depends_on": null, "description": null, "docstatus": 0, "dt": "Purchase Order Item", "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "reference_dn", - "fieldtype": "Dynamic Link", + "fieldname": "cess_non_advol_rate", + "fieldtype": "Float", "hidden": 0, "hide_border": 0, "hide_days": 0, "hide_seconds": 0, - "idx": 74, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, @@ -238,25 +249,26 @@ "in_list_view": 0, "in_preview": 0, "in_standard_filter": 0, - "index": null, - "insert_after": "bom", + "insert_after": "cess_rate", "is_system_generated": 1, "is_virtual": 0, - "label": "Reference DN", + "label": "CESS Non Advol Rate", "length": 0, + "link_filters": null, "mandatory_depends_on": null, - "modified": "2020-10-16 16:28:09.079292", + "modified": "2025-11-25 12:38:58.809267", "modified_by": "Administrator", - "module": null, - "name": "Purchase Order Item-reference_dn", - "no_copy": 0, + "module": "GST India", + "name": "Purchase Order Item-cess_non_advol_rate", + "no_copy": 1, "non_negative": 0, - "options": "reference_dt", + "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, @@ -266,9 +278,9 @@ "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, "sort_options": 0, "translatable": 0, - "trash_reason": null, "unique": 0, "width": null }, @@ -277,27 +289,29 @@ "_comments": null, "_liked_by": null, "_user_tags": null, + "alignment": null, "allow_in_quick_entry": 0, - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, + "button_color": null, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2017-07-06 18:27:01.333438", + "creation": "2025-11-25 12:38:58.807822", "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Purchase Order Item", - "fetch_from": "item_code.gst_hsn_code", - "fetch_if_empty": 1, - "fieldname": "gst_hsn_code", - "fieldtype": "Data", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "cess_rate", + "fieldtype": "Float", "hidden": 0, "hide_border": 0, "hide_days": 0, "hide_seconds": 0, - "idx": 8, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, @@ -306,18 +320,18 @@ "in_list_view": 0, "in_preview": 0, "in_standard_filter": 0, - "index": 0.0, - "insert_after": "description", + "insert_after": "sgst_rate", "is_system_generated": 1, "is_virtual": 0, - "label": "HSN/SAC", + "label": "CESS Rate", "length": 0, + "link_filters": null, "mandatory_depends_on": null, - "modified": "2020-10-17 21:02:16.684364", + "modified": "2025-11-25 12:38:58.807822", "modified_by": "Administrator", - "module": null, - "name": "Purchase Order Item-gst_hsn_code", - "no_copy": 0, + "module": "GST India", + "name": "Purchase Order Item-cess_rate", + "no_copy": 1, "non_negative": 0, "options": null, "owner": "Administrator", @@ -325,18 +339,19 @@ "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 1, + "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, "sort_options": 0, - "translatable": 1, - "trash_reason": null, + "translatable": 0, "unique": 0, "width": null }, @@ -345,27 +360,29 @@ "_comments": null, "_liked_by": null, "_user_tags": null, + "alignment": null, "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, + "button_color": null, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-10-17 20:55:04.563651", + "creation": "2025-11-25 12:38:58.813730", "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Purchase Order Item", - "fetch_from": "item_code.is_nil_exempt", + "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "is_nil_exempt", - "fieldtype": "Check", + "fieldname": "cgst_amount", + "fieldtype": "Currency", "hidden": 0, "hide_border": 0, "hide_days": 0, "hide_seconds": 0, - "idx": 9, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, @@ -374,37 +391,38 @@ "in_list_view": 0, "in_preview": 0, "in_standard_filter": 0, - "index": null, - "insert_after": "gst_hsn_code", + "insert_after": "igst_amount", "is_system_generated": 1, "is_virtual": 0, - "label": "Is nil rated or exempted", + "label": "CGST Amount", "length": 0, + "link_filters": null, "mandatory_depends_on": null, - "modified": "2020-10-17 21:02:17.377577", + "modified": "2025-11-25 12:38:58.813730", "modified_by": "Administrator", - "module": null, - "name": "Purchase Order Item-is_nil_exempt", - "no_copy": 0, + "module": "GST India", + "name": "Purchase Order Item-cgst_amount", + "no_copy": 1, "non_negative": 0, - "options": null, + "options": "Company:company:default_currency", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 1, + "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, "sort_options": 0, "translatable": 0, - "trash_reason": null, "unique": 0, "width": null }, @@ -413,27 +431,29 @@ "_comments": null, "_liked_by": null, "_user_tags": null, + "alignment": null, "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, + "button_color": null, "collapsible": 0, "collapsible_depends_on": null, "columns": 0, - "creation": "2020-10-17 20:55:07.388909", + "creation": "2025-11-25 12:38:58.805062", "default": null, "depends_on": null, "description": null, "docstatus": 0, "dt": "Purchase Order Item", - "fetch_from": "item_code.is_non_gst", + "fetch_from": null, "fetch_if_empty": 0, - "fieldname": "is_non_gst", - "fieldtype": "Check", + "fieldname": "cgst_rate", + "fieldtype": "Float", "hidden": 0, "hide_border": 0, "hide_days": 0, "hide_seconds": 0, - "idx": 10, + "idx": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, @@ -442,18 +462,18 @@ "in_list_view": 0, "in_preview": 0, "in_standard_filter": 0, - "index": null, - "insert_after": "is_nil_exempt", + "insert_after": "igst_rate", "is_system_generated": 1, "is_virtual": 0, - "label": "Is Non GST", + "label": "CGST Rate", "length": 0, + "link_filters": null, "mandatory_depends_on": null, - "modified": "2020-10-17 21:02:18.064369", + "modified": "2025-11-25 12:38:58.805062", "modified_by": "Administrator", - "module": null, - "name": "Purchase Order Item-is_non_gst", - "no_copy": 0, + "module": "GST India", + "name": "Purchase Order Item-cgst_rate", + "no_copy": 1, "non_negative": 0, "options": null, "owner": "Administrator", @@ -461,104 +481,1681 @@ "parentfield": null, "parenttype": null, "permlevel": 0, + "placeholder": null, "precision": "", - "print_hide": 1, + "print_hide": 0, "print_hide_if_no_value": 0, "print_width": null, - "read_only": 0, + "read_only": 1, "read_only_depends_on": null, "report_hide": 0, "reqd": 0, "search_index": 0, + "show_dashboard": 0, "sort_options": 0, "translatable": 0, - "trash_reason": null, "unique": 0, "width": null - } - ], - "custom_perms": [], - "doctype": "Purchase Order Item", - "links": [], - "property_setters": [ + }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2023-09-09 17:22:46.800587", - "default_value": null, - "doc_name": null, - "doc_type": "Purchase Order Item", + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "button_color": null, + "collapsible": 1, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-11-25 12:38:58.802296", + "default": null, + "depends_on": null, + "description": null, "docstatus": 0, - "doctype_or_field": "DocType", - "field_name": null, + "dt": "Purchase Order Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "gst_details_section", + "fieldtype": "Section Break", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, "idx": 0, - "is_system_generated": 0, - "modified": "2023-09-09 17:22:46.800587", + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "taxable_value", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST Details", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-11-25 12:38:58.802296", "modified_by": "Administrator", - "module": null, - "name": "Purchase Order Item-main-field_order", + "module": "GST India", + "name": "Purchase Order Item-gst_details_section", + "no_copy": 0, + "non_negative": 0, + "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, - "property": "field_order", - "property_type": "Data", - "row_name": null, - "select_doctype": null, - "select_item": null, - "select_property": null, - "value": "[\"item_code\", \"subcontracted_item\", \"supplier_part_no\", \"item_name\", \"brand\", \"product_bundle\", \"fg_item\", \"fg_item_qty\", \"column_break_4\", \"schedule_date\", \"expected_delivery_date\", \"item_group\", \"section_break_5\", \"description\", \"gst_hsn_code\", \"is_nil_exempt\", \"is_non_gst\", \"col_break1\", \"image\", \"image_view\", \"quantity_and_rate\", \"qty\", \"stock_uom\", \"col_break2\", \"uom\", \"conversion_factor\", \"stock_qty\", \"sec_break1\", \"price_list_rate\", \"last_purchase_rate\", \"col_break3\", \"base_price_list_rate\", \"discount_and_margin_section\", \"margin_type\", \"margin_rate_or_amount\", \"rate_with_margin\", \"column_break_28\", \"discount_percentage\", \"discount_amount\", \"base_rate_with_margin\", \"sec_break2\", \"rate\", \"amount\", \"item_tax_template\", \"col_break4\", \"base_rate\", \"base_amount\", \"pricing_rules\", \"stock_uom_rate\", \"is_free_item\", \"apply_tds\", \"section_break_29\", \"net_rate\", \"net_amount\", \"column_break_32\", \"base_net_rate\", \"base_net_amount\", \"warehouse_and_reference\", \"from_warehouse\", \"warehouse\", \"column_break_54\", \"actual_qty\", \"company_total_stock\", \"references_section\", \"material_request\", \"material_request_item\", \"sales_order\", \"sales_order_item\", \"sales_order_packed_item\", \"supplier_quotation\", \"supplier_quotation_item\", \"col_break5\", \"delivered_by_supplier\", \"so_detail\", \"against_blanket_order\", \"blanket_order\", \"blanket_order_rate\", \"section_break_56\", \"received_qty\", \"returned_qty\", \"column_break_60\", \"billed_amt\", \"accounting_details\", \"expense_account\", \"manufacture_details\", \"manufacturer\", \"manufacturer_part_no\", \"column_break_14\", \"bom\", \"reference_dn\", \"include_exploded_items\", \"item_weight_details\", \"weight_per_unit\", \"total_weight\", \"column_break_40\", \"weight_uom\", \"accounting_dimensions_section\", \"project\", \"reference_dt\", \"dimension_col_break\", \"cost_center\", \"more_info_section_break\", \"is_fixed_asset\", \"item_tax_rate\", \"section_break_72\", \"production_plan\", \"production_plan_item\", \"production_plan_sub_assembly_item\", \"page_break\"]" + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2015-05-30 18:21:46.377856", - "default_value": null, - "doc_name": null, - "doc_type": "Purchase Order Item", + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 1, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2017-07-06 18:27:01.333438", + "default": null, + "depends_on": null, + "description": null, "docstatus": 0, - "doctype_or_field": "DocField", - "field_name": "base_amount", - "idx": 0, + "dt": "Purchase Order Item", + "fetch_from": "item_code.gst_hsn_code", + "fetch_if_empty": 1, + "fieldname": "gst_hsn_code", + "fieldtype": "Data", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 8, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "description", "is_system_generated": 1, - "modified": "2015-05-30 18:21:46.377856", + "is_virtual": 0, + "label": "HSN/SAC", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-10-17 21:02:16.684364", "modified_by": "Administrator", "module": null, - "name": "Purchase Order Item-base_amount-precision", + "name": "Purchase Order Item-gst_hsn_code", + "no_copy": 0, + "non_negative": 0, + "options": null, "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, - "property": "precision", - "property_type": "Select", - "row_name": null, - "select_doctype": null, - "select_item": null, - "select_property": null, - "value": "2" + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 1, + "unique": 0, + "width": null }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2015-05-30 18:21:46.285418", - "default_value": null, - "doc_name": null, - "doc_type": "Purchase Order Item", - "docstatus": 0, - "doctype_or_field": "DocField", - "field_name": "base_rate", - "idx": 0, - "is_system_generated": 1, - "modified": "2015-05-30 18:21:46.285418", - "modified_by": "Administrator", - "module": null, - "name": "Purchase Order Item-base_rate-precision", + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-11-25 12:38:58.800909", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Purchase Order Item", + "fetch_from": "item_tax_template.gst_treatment", + "fetch_if_empty": 1, + "fieldname": "gst_treatment", + "fieldtype": "Autocomplete", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "item_tax_template", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST Treatment", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-11-25 12:38:58.800909", + "modified_by": "Administrator", + "module": "GST India", + "name": "Purchase Order Item-gst_treatment", + "no_copy": 1, + "non_negative": 0, + "options": "Taxable\nZero-Rated\nNil-Rated\nExempted\nNon-GST", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-11-25 12:38:58.812325", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Purchase Order Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "igst_amount", + "fieldtype": "Currency", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "cb_gst_details", + "is_system_generated": 1, + "is_virtual": 0, + "label": "IGST Amount", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-11-25 12:38:58.812325", + "modified_by": "Administrator", + "module": "GST India", + "name": "Purchase Order Item-igst_amount", + "no_copy": 1, + "non_negative": 0, + "options": "Company:company:default_currency", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-11-25 12:38:58.803685", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Purchase Order Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "igst_rate", + "fieldtype": "Float", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "gst_details_section", + "is_system_generated": 1, + "is_virtual": 0, + "label": "IGST Rate", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-11-25 12:38:58.803685", + "modified_by": "Administrator", + "module": "GST India", + "name": "Purchase Order Item-igst_rate", + "no_copy": 1, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-11-25 12:38:58.984240", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Purchase Order Item", + "fetch_from": "item_code.is_ineligible_for_itc", + "fetch_if_empty": 1, + "fieldname": "is_ineligible_for_itc", + "fieldtype": "Check", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "gst_hsn_code", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Is Ineligible for Input Tax Credit", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-11-25 12:38:58.984240", + "modified_by": "Administrator", + "module": "GST India", + "name": "Purchase Order Item-is_ineligible_for_itc", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2020-10-17 20:55:04.563651", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Purchase Order Item", + "fetch_from": "item_code.is_nil_exempt", + "fetch_if_empty": 0, + "fieldname": "is_nil_exempt", + "fieldtype": "Check", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 9, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "gst_hsn_code", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Is nil rated or exempted", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-10-17 21:02:17.377577", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-is_nil_exempt", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2020-10-17 20:55:07.388909", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Purchase Order Item", + "fetch_from": "item_code.is_non_gst", + "fetch_if_empty": 0, + "fieldname": "is_non_gst", + "fieldtype": "Check", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 10, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "is_nil_exempt", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Is Non GST", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-10-17 21:02:18.064369", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-is_non_gst", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2020-10-16 16:28:09.079292", + "default": null, + "depends_on": "", + "description": null, + "docstatus": 0, + "dt": "Purchase Order Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "reference_dn", + "fieldtype": "Dynamic Link", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 74, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "bom", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Reference DN", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-10-16 16:28:09.079292", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-reference_dn", + "no_copy": 0, + "non_negative": 0, + "options": "reference_dt", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2020-10-16 16:28:03.959296", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Purchase Order Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "reference_dt", + "fieldtype": "Link", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 61, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "project", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Reference DT", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2020-10-16 16:28:03.959296", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-reference_dt", + "no_copy": 0, + "non_negative": 0, + "options": "DocType", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-11-25 12:38:58.815063", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Purchase Order Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "sgst_amount", + "fieldtype": "Currency", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "cgst_amount", + "is_system_generated": 1, + "is_virtual": 0, + "label": "SGST Amount", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-11-25 12:38:58.815063", + "modified_by": "Administrator", + "module": "GST India", + "name": "Purchase Order Item-sgst_amount", + "no_copy": 1, + "non_negative": 0, + "options": "Company:company:default_currency", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-11-25 12:38:58.806438", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Purchase Order Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "sgst_rate", + "fieldtype": "Float", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "cgst_rate", + "is_system_generated": 1, + "is_virtual": 0, + "label": "SGST Rate", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-11-25 12:38:58.806438", + "modified_by": "Administrator", + "module": "GST India", + "name": "Purchase Order Item-sgst_rate", + "no_copy": 1, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2016-06-09 09:04:18.182559", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Purchase Order Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "so_detail", + "fieldtype": "Data", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 74, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "delivered_by_supplier", + "is_system_generated": 0, + "is_virtual": 0, + "label": "SO Detail", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2016-09-20 15:12:47.580282", + "modified_by": "aditya@rigpl.com", + "module": null, + "name": "Purchase Order Item-so_detail", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2016-08-13 17:27:02", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Purchase Order Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "subcontracted_item", + "fieldtype": "Link", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 2, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "item_code", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Subcontracted Item", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2017-11-16 13:08:26.585670", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-subcontracted_item", + "no_copy": 0, + "non_negative": 0, + "options": "Item", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": null, + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 0, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-11-25 12:38:58.759455", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Purchase Order Item", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "taxable_value", + "fieldtype": "Currency", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "base_net_amount", + "is_system_generated": 1, + "is_virtual": 0, + "label": "Taxable Value", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-11-25 12:38:58.759455", + "modified_by": "Administrator", + "module": "GST India", + "name": "Purchase Order Item-taxable_value", + "no_copy": 1, + "non_negative": 0, + "options": "Company:company:default_currency", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + } + ], + "custom_perms": [], + "doctype": "Purchase Order Item", + "links": [], + "property_setters": [ + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 12:13:26.763080", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "amount", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:41.076613", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-amount-columns", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "columns", + "property_type": "Int", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 16:53:45.467370", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "amount", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:41.126970", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-amount-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 18:21:46.377856", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_amount", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:41.161603", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-base_amount-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "value": "2" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 18:21:46.171662", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_net_amount", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:41.200999", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-base_net_amount-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "value": "2" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 18:21:45.976960", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_net_rate", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:41.236446", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-base_net_rate-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "value": "2" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 18:21:46.285418", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_rate", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:41.268506", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-base_rate-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "value": "2" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-11-13 10:38:09.751208", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "cost_center", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:41.299637", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-cost_center-ignore_user_permissions", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2023-03-09 16:55:16.488751", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "description", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:41.396445", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-description-columns", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "columns", + "property_type": "Int", + "row_name": null, + "value": "2" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-06-06 02:24:14.671647", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "description", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:41.430773", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-description-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-10-25 11:32:42.856448", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "description", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:41.464813", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-description-width", + "owner": "sushil.rathee@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "value": "360" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 16:53:45.455175", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "discount_percentage", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:41.510413", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-discount_percentage-columns", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "columns", + "property_type": "Int", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 16:53:45.450234", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "discount_percentage", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:41.554339", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-discount_percentage-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-07-11 17:12:33.436600", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "discount_percentage", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:41.596280", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-discount_percentage-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "value": "46" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-11-13 10:38:09.741093", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "expense_account", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:41.662412", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-expense_account-ignore_user_permissions", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-16 13:00:37.482456", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "item_code", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:41.719233", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-item_code-columns", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "columns", + "property_type": "Int", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-04-22 02:11:04.382712", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "item_code", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:41.792841", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-item_code-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "value": "139" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-06-06 02:24:14.640482", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "item_name", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:41.918050", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-item_name-hidden", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2014-12-06 16:25:08.497696", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "item_name", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:41.980602", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-item_name-in_filter", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_filter", + "property_type": "Check", + "row_name": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2014-12-06 16:25:03.464484", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "item_name", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:42.035518", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-item_name-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-11-24 18:19:29.852416", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "item_name", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:42.097945", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-item_name-length", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "length", + "property_type": "Int", + "row_name": null, + "value": "255" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2014-12-06 16:25:03.467264", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "item_name", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:42.154989", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-item_name-reqd", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "reqd", + "property_type": "Check", + "row_name": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2023-09-09 17:22:46.800587", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": null, + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:42.231612", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-main-field_order", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "field_order", + "property_type": "Data", + "row_name": null, + "value": "[\"item_code\", \"subcontracted_item\", \"supplier_part_no\", \"item_name\", \"brand\", \"product_bundle\", \"fg_item\", \"fg_item_qty\", \"column_break_4\", \"schedule_date\", \"expected_delivery_date\", \"item_group\", \"section_break_5\", \"description\", \"gst_hsn_code\", \"is_nil_exempt\", \"is_non_gst\", \"col_break1\", \"image\", \"image_view\", \"quantity_and_rate\", \"qty\", \"stock_uom\", \"col_break2\", \"uom\", \"conversion_factor\", \"stock_qty\", \"sec_break1\", \"price_list_rate\", \"last_purchase_rate\", \"col_break3\", \"base_price_list_rate\", \"discount_and_margin_section\", \"margin_type\", \"margin_rate_or_amount\", \"rate_with_margin\", \"column_break_28\", \"discount_percentage\", \"discount_amount\", \"base_rate_with_margin\", \"sec_break2\", \"rate\", \"amount\", \"item_tax_template\", \"col_break4\", \"base_rate\", \"base_amount\", \"pricing_rules\", \"stock_uom_rate\", \"is_free_item\", \"apply_tds\", \"section_break_29\", \"net_rate\", \"net_amount\", \"column_break_32\", \"base_net_rate\", \"base_net_amount\", \"warehouse_and_reference\", \"from_warehouse\", \"warehouse\", \"column_break_54\", \"actual_qty\", \"company_total_stock\", \"references_section\", \"material_request\", \"material_request_item\", \"sales_order\", \"sales_order_item\", \"sales_order_packed_item\", \"supplier_quotation\", \"supplier_quotation_item\", \"col_break5\", \"delivered_by_supplier\", \"so_detail\", \"against_blanket_order\", \"blanket_order\", \"blanket_order_rate\", \"section_break_56\", \"received_qty\", \"returned_qty\", \"column_break_60\", \"billed_amt\", \"accounting_details\", \"expense_account\", \"manufacture_details\", \"manufacturer\", \"manufacturer_part_no\", \"column_break_14\", \"bom\", \"reference_dn\", \"include_exploded_items\", \"item_weight_details\", \"weight_per_unit\", \"total_weight\", \"column_break_40\", \"weight_uom\", \"accounting_dimensions_section\", \"project\", \"reference_dt\", \"dimension_col_break\", \"cost_center\", \"more_info_section_break\", \"is_fixed_asset\", \"item_tax_rate\", \"section_break_72\", \"production_plan\", \"production_plan_item\", \"production_plan_sub_assembly_item\", \"page_break\"]" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 18:21:46.062588", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "net_amount", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:22:42.296297", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-net_amount-precision", "owner": "Administrator", "parent": null, "parentfield": null, @@ -566,9 +2163,6 @@ "property": "precision", "property_type": "Select", "row_name": null, - "select_doctype": null, - "select_item": null, - "select_property": null, "value": "2" }, { @@ -576,19 +2170,18 @@ "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2015-05-30 18:21:46.171662", + "creation": "2015-05-30 18:21:45.886299", "default_value": null, - "doc_name": null, "doc_type": "Purchase Order Item", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "base_net_amount", + "field_name": "net_rate", "idx": 0, "is_system_generated": 1, - "modified": "2015-05-30 18:21:46.171662", + "modified": "2026-02-26 13:22:42.384108", "modified_by": "Administrator", "module": null, - "name": "Purchase Order Item-base_net_amount-precision", + "name": "Purchase Order Item-net_rate-precision", "owner": "Administrator", "parent": null, "parentfield": null, @@ -596,9 +2189,6 @@ "property": "precision", "property_type": "Select", "row_name": null, - "select_doctype": null, - "select_item": null, - "select_property": null, "value": "2" }, { @@ -606,90 +2196,390 @@ "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2015-05-30 18:21:46.062588", + "creation": "2014-12-06 16:25:08.508894", "default_value": null, - "doc_name": null, "doc_type": "Purchase Order Item", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "net_amount", + "field_name": "prevdoc_doctype", "idx": 0, - "is_system_generated": 1, - "modified": "2015-05-30 18:21:46.062588", + "is_system_generated": 0, + "modified": "2026-02-26 13:22:42.450307", "modified_by": "Administrator", "module": null, - "name": "Purchase Order Item-net_amount-precision", - "owner": "Administrator", + "name": "Purchase Order Item-prevdoc_doctype-hidden", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "hidden", + "property_type": "Check", + "row_name": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2014-12-06 16:25:08.506439", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "prevdoc_doctype", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:42.513975", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-prevdoc_doctype-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-16 13:00:37.606225", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "price_list_rate", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:42.559767", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-price_list_rate-columns", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "columns", + "property_type": "Int", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-08-03 11:22:29.947002", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "price_list_rate", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:42.608168", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-price_list_rate-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-06-09 11:11:18.135226", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "price_list_rate", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:42.674365", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-price_list_rate-precision", + "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, "property": "precision", "property_type": "Select", "row_name": null, - "select_doctype": null, - "select_item": null, - "select_property": null, - "value": "2" + "value": "3" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2015-05-30 18:21:45.976960", + "creation": "2016-12-02 11:52:53.071908", "default_value": null, - "doc_name": null, "doc_type": "Purchase Order Item", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "base_net_rate", + "field_name": "price_list_rate", "idx": 0, - "is_system_generated": 1, - "modified": "2015-05-30 18:21:45.976960", + "is_system_generated": 0, + "modified": "2026-02-26 13:22:42.737411", "modified_by": "Administrator", "module": null, - "name": "Purchase Order Item-base_net_rate-precision", - "owner": "Administrator", + "name": "Purchase Order Item-price_list_rate-width", + "owner": "rajpal.singh@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "value": "111" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-04-20 13:59:04.557535", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "qty", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:42.784350", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-qty-width", + "owner": "sumit.kumar@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "value": "60" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 12:13:26.755789", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "rate", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:42.825791", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-rate-columns", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "columns", + "property_type": "Int", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2017-06-09 11:12:06.654422", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "rate", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:42.872683", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-rate-precision", + "owner": "aditya@rigpl.com", "parent": null, "parentfield": null, "parenttype": null, "property": "precision", "property_type": "Select", "row_name": null, - "select_doctype": null, - "select_item": null, - "select_property": null, - "value": "2" + "value": "3" }, { "_assign": null, "_comments": null, "_liked_by": null, "_user_tags": null, - "creation": "2015-05-30 18:21:45.886299", + "creation": "2018-07-11 17:12:36.401478", "default_value": null, - "doc_name": null, "doc_type": "Purchase Order Item", "docstatus": 0, "doctype_or_field": "DocField", - "field_name": "net_rate", + "field_name": "rate", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:42.913378", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-rate-width", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "value": "54" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-04-20 13:59:09.883429", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "received_qty", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:42.954605", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-received_qty-width", + "owner": "sumit.kumar@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "width", + "property_type": null, + "row_name": null, + "value": "62" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-16 13:00:37.567053", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "schedule_date", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:42.998405", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-schedule_date-columns", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "columns", + "property_type": "Int", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 16:53:45.435748", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "section_break_5", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:43.040939", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-section_break_5-collapsible", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "collapsible", + "property_type": "Check", + "row_name": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-11-13 10:38:09.715743", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "warehouse", "idx": 0, "is_system_generated": 1, - "modified": "2015-05-30 18:21:45.886299", + "modified": "2026-02-26 13:22:43.078012", "modified_by": "Administrator", "module": null, - "name": "Purchase Order Item-net_rate-precision", + "name": "Purchase Order Item-warehouse-ignore_user_permissions", "owner": "Administrator", "parent": null, "parentfield": null, "parenttype": null, - "property": "precision", - "property_type": "Select", + "property": "ignore_user_permissions", + "property_type": "Check", "row_name": null, - "select_doctype": null, - "select_item": null, - "select_property": null, - "value": "2" + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2019-01-17 12:13:26.775134", + "default_value": null, + "doc_type": "Purchase Order Item", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "warehouse", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:22:43.109938", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Order Item-warehouse-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "value": "0" } ], "sync_on_migrate": 1 diff --git a/rohit_common/rohit_common/custom/purchase_taxes_and_charges.json b/rohit_common/rohit_common/custom/purchase_taxes_and_charges.json new file mode 100644 index 0000000..3b582c4 --- /dev/null +++ b/rohit_common/rohit_common/custom/purchase_taxes_and_charges.json @@ -0,0 +1,471 @@ +{ + "custom_fields": [ + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "alignment": null, + "allow_in_quick_entry": 0, + "allow_on_submit": 0, + "bold": 0, + "button_color": null, + "collapsible": 0, + "collapsible_depends_on": null, + "columns": 0, + "creation": "2025-11-25 12:38:59.005372", + "default": null, + "depends_on": null, + "description": null, + "docstatus": 0, + "dt": "Purchase Taxes and Charges", + "fetch_from": null, + "fetch_if_empty": 0, + "fieldname": "gst_tax_type", + "fieldtype": "Data", + "hidden": 0, + "hide_border": 0, + "hide_days": 0, + "hide_seconds": 0, + "idx": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_filter_dash": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_preview": 0, + "in_standard_filter": 0, + "insert_after": "rate", + "is_system_generated": 1, + "is_virtual": 0, + "label": "GST Tax Type", + "length": 0, + "link_filters": null, + "mandatory_depends_on": null, + "modified": "2025-11-25 12:38:59.005372", + "modified_by": "Administrator", + "module": "GST India", + "name": "Purchase Taxes and Charges-gst_tax_type", + "no_copy": 0, + "non_negative": 0, + "options": null, + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "permlevel": 0, + "placeholder": null, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "print_width": null, + "read_only": 1, + "read_only_depends_on": null, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "show_dashboard": 0, + "sort_options": 0, + "translatable": 0, + "unique": 0, + "width": null + } + ], + "custom_perms": [], + "doctype": "Purchase Taxes and Charges", + "links": [], + "property_setters": [ + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-11-13 11:01:46.295569", + "default_value": null, + "doc_type": "Purchase Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "account_head", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:23:00.667239", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Taxes and Charges-account_head-ignore_user_permissions", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-03-02 10:11:57.393053", + "default_value": null, + "doc_type": "Purchase Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "account_head", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:23:00.713548", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Taxes and Charges-account_head-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 19:20:23.469516", + "default_value": null, + "doc_type": "Purchase Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_tax_amount_after_discount_amount", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:23:00.756927", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Taxes and Charges-base_tax_amount_after_discount_amount-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 19:20:23.022221", + "default_value": null, + "doc_type": "Purchase Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_tax_amount", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:23:00.804934", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Taxes and Charges-base_tax_amount-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 19:20:23.246971", + "default_value": null, + "doc_type": "Purchase Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "base_total", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:23:00.847698", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Taxes and Charges-base_total-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2013-07-30 18:17:36", + "default_value": null, + "doc_type": "Purchase Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "category", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:23:00.891766", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Taxes and Charges-category-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2014-02-04 19:59:34", + "default_value": null, + "doc_type": "Purchase Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "charge_type", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:23:00.948683", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Taxes and Charges-charge_type-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2018-11-13 11:01:46.305499", + "default_value": null, + "doc_type": "Purchase Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "cost_center", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:23:01.005668", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Taxes and Charges-cost_center-ignore_user_permissions", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "ignore_user_permissions", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2013-07-30 18:17:36", + "default_value": null, + "doc_type": "Purchase Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "cost_center", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:23:01.056645", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Taxes and Charges-cost_center-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "value": "0" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-03-02 10:11:57.383983", + "default_value": null, + "doc_type": "Purchase Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "included_in_print_rate", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:23:01.115303", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Taxes and Charges-included_in_print_rate-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-03-02 10:11:57.342961", + "default_value": null, + "doc_type": "Purchase Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocType", + "field_name": null, + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:23:01.169458", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Taxes and Charges-main-sort_order", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "sort_order", + "property_type": "Data", + "row_name": null, + "value": "ASC" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 19:20:23.358279", + "default_value": null, + "doc_type": "Purchase Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "tax_amount_after_discount_amount", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:23:01.234196", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Taxes and Charges-tax_amount_after_discount_amount-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "value": "3" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2013-07-30 18:17:36", + "default_value": null, + "doc_type": "Purchase Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "tax_amount", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:23:01.278952", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Taxes and Charges-tax_amount-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2016-03-02 10:11:57.403818", + "default_value": null, + "doc_type": "Purchase Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "total", + "idx": 0, + "is_system_generated": 0, + "modified": "2026-02-26 13:23:01.324192", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Taxes and Charges-total-in_list_view", + "owner": "aditya@rigpl.com", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "in_list_view", + "property_type": "Check", + "row_name": null, + "value": "1" + }, + { + "_assign": null, + "_comments": null, + "_liked_by": null, + "_user_tags": null, + "creation": "2015-05-30 19:20:23.132104", + "default_value": null, + "doc_type": "Purchase Taxes and Charges", + "docstatus": 0, + "doctype_or_field": "DocField", + "field_name": "total", + "idx": 0, + "is_system_generated": 1, + "modified": "2026-02-26 13:23:01.371485", + "modified_by": "Administrator", + "module": null, + "name": "Purchase Taxes and Charges-total-precision", + "owner": "Administrator", + "parent": null, + "parentfield": null, + "parenttype": null, + "property": "precision", + "property_type": "Select", + "row_name": null, + "value": "3" + } + ], + "sync_on_migrate": 1 +} \ No newline at end of file From de4981d808a3cb083a50200cdb95c742163313b1 Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Mon, 2 Mar 2026 13:28:06 +0530 Subject: [PATCH 47/52] =?UTF-8?q?fix:=20sales=20invoice=20insufficient=20p?= =?UTF-8?q?ermission=20for=20accounts=20settings=20and=20=E2=80=A6=20(#25)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: sales invoice insufficient permission for accounts settings and disabled background jobs * fix: remove no needed comments --- rohit_common/api.py | 6 ++ rohit_common/hooks.py | 59 ++++++++++--------- .../public/js/transaction_override.js | 42 +++++++++++++ 3 files changed, 78 insertions(+), 29 deletions(-) create mode 100644 rohit_common/api.py create mode 100644 rohit_common/public/js/transaction_override.js diff --git a/rohit_common/api.py b/rohit_common/api.py new file mode 100644 index 0000000..13d3d64 --- /dev/null +++ b/rohit_common/api.py @@ -0,0 +1,6 @@ +import frappe + +@frappe.whitelist() +def get_accounts_settings_value(fieldname): + # Ignore permissions to allow fetching this value from Accounts Settings directly + return frappe.db.get_single_value("Accounts Settings", fieldname) diff --git a/rohit_common/hooks.py b/rohit_common/hooks.py index 1a8ee76..6742161 100644 --- a/rohit_common/hooks.py +++ b/rohit_common/hooks.py @@ -99,6 +99,7 @@ "Asset": "public/js/asset.js", "Contact": "public/js/contact.js", "Sales Taxes and Charges Template": "public/js/stct.js", + "Sales Invoice": "public/js/transaction_override.js", } # Document Events @@ -167,35 +168,35 @@ # Scheduled Tasks # --------------- -scheduler_events = { - "cron": { - "10 2 * * *": [ - "rohit_common.rohit_common.scheduled_tasks.auto_update_gstin_status.enqueue_gstin_update" - # Runs everyday at 2:10 AM - ], - # Runs every 15 mins below jobs - "*/15 * * * *": [ - "rohit_common.rohit_common.scheduled_tasks.auto_einvoice_tasks.enq_inv_sub", - "rohit_common.rohit_common.scheduled_tasks.auto_einvoice_tasks.enq_einv_create", - ], - }, - "all": [ - "rohit_common.rohit_common.scheduled_tasks.auto_refresh_gstin_auth_code.execute" - ], - "daily": [ - "rohit_common.rohit_common.scheduled_tasks.auto_update_from_erp.update_export_invoices" - ], - "hourly": [ - "rohit_common.rohit_common.scheduled_tasks.delete_unneeded_files.check_correct_folders", - "rohit_common.utils.background_doc_processing.enqueue_bg", - ], - "weekly_long": [ - "rohit_common.rohit_common.scheduled_tasks.auto_einvoice_tasks.get_unposted_invoices", - "rohit_common.rohit_common.scheduled_tasks.auto_delete_version.enqueue_deletion", - "rohit_common.rohit_common.scheduled_tasks.delete_unneeded_files.execute", - ], - "monthly": ["rohit_common.rohit_common.scheduled_tasks.email_queue_delete.execute"], -} +# scheduler_events = { +# "cron": { +# "10 2 * * *": [ +# "rohit_common.rohit_common.scheduled_tasks.auto_update_gstin_status.enqueue_gstin_update" +# # Runs everyday at 2:10 AM +# ], +# # Runs every 15 mins below jobs +# "*/15 * * * *": [ +# "rohit_common.rohit_common.scheduled_tasks.auto_einvoice_tasks.enq_inv_sub", +# "rohit_common.rohit_common.scheduled_tasks.auto_einvoice_tasks.enq_einv_create", +# ], +# }, +# "all": [ +# "rohit_common.rohit_common.scheduled_tasks.auto_refresh_gstin_auth_code.execute" +# ], +# "daily": [ +# "rohit_common.rohit_common.scheduled_tasks.auto_update_from_erp.update_export_invoices" +# ], +# "hourly": [ +# "rohit_common.rohit_common.scheduled_tasks.delete_unneeded_files.check_correct_folders", +# "rohit_common.utils.background_doc_processing.enqueue_bg", +# ], +# "weekly_long": [ +# "rohit_common.rohit_common.scheduled_tasks.auto_einvoice_tasks.get_unposted_invoices", +# "rohit_common.rohit_common.scheduled_tasks.auto_delete_version.enqueue_deletion", +# "rohit_common.rohit_common.scheduled_tasks.delete_unneeded_files.execute", +# ], +# "monthly": ["rohit_common.rohit_common.scheduled_tasks.email_queue_delete.execute"], +# } # Testing # ------- diff --git a/rohit_common/public/js/transaction_override.js b/rohit_common/public/js/transaction_override.js new file mode 100644 index 0000000..d11d101 --- /dev/null +++ b/rohit_common/public/js/transaction_override.js @@ -0,0 +1,42 @@ +frappe.provide("erpnext"); + +function override_transaction_controller(doctype) { + frappe.ui.form.on(doctype, { + setup: function(frm) { + if (!erpnext.TransactionController) return; + + erpnext.TransactionController.prototype.confirm_posting_date_change = async function() { + if (!frappe.meta.has_field(this.frm.doc.doctype, "set_posting_time")) return; + if (this.frm.doc.set_posting_time) return; + if (frappe.datetime.get_today() == this.frm.doc.posting_date) return; + + // Fetch the setting without throwing a permission error + let is_confirmation_reqd = await frappe.call({ + method: "rohit_common.api.get_accounts_settings_value", + args: { fieldname: "confirm_before_resetting_posting_date" } + }).then(r => r.message); + + if (!is_confirmation_reqd) return; + + return new Promise((resolve, reject) => { + frappe.confirm( + __("Posting Date will change to today's date as Edit Posting Date and Time is unchecked. Are you sure want to proceed?"), + () => { + this.frm.doc.posting_date = frappe.datetime.get_today(); + this.frm.refresh_field("posting_date"); + resolve(); + }, + () => reject() + ); + }); + }; + } + }); +} + +const transaction_doctypes = [ + "Sales Invoice", "Purchase Invoice", "Sales Order", "Purchase Order", + "Quotation", "Delivery Note", "Purchase Receipt", "POS Invoice" +]; + +transaction_doctypes.forEach(override_transaction_controller); From f8f279ce73b9e6da7eba4c9a88705df8bc52df3a Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Thu, 5 Mar 2026 16:53:17 +0530 Subject: [PATCH 48/52] fix: delivery note showing not applicable in sales invoice (#26) --- .../close_zero_amount_dns.py | 209 ++++++++++++++++++ .../docs_execution_order.txt | 5 +- 2 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 rohit_common/migration_scripts/close_zero_amount_dns.py diff --git a/rohit_common/migration_scripts/close_zero_amount_dns.py b/rohit_common/migration_scripts/close_zero_amount_dns.py new file mode 100644 index 0000000..16a0437 --- /dev/null +++ b/rohit_common/migration_scripts/close_zero_amount_dns.py @@ -0,0 +1,209 @@ +import frappe +import csv +import os +from frappe.utils import now_datetime + + +def close_zero_amount_delivery_notes(dry_run=True, batch_size=500, limit=None, write_csv=True): + """ + Close zero-amount Delivery Notes that incorrectly show in + "Get Items from Delivery Note" in Sales Invoice. + + After v12 → v16 migration, ~2200 old Delivery Notes have grand_total = 0 + (rates/amounts zeroed out during migration). Since per_billed = billed_amt/amount, + and both are 0, per_billed stays at 0% forever, causing them to appear as + unbilled in Sales Invoice. + + This script uses ERPNext's "Close" workflow status — the proper way to mark DNs + as finalized without modifying any financial data (per_billed, billed_amt, etc.). + + The get_delivery_notes_to_be_billed query already excludes status='Closed'. + + - dry_run=True : only prints what would be changed, no DB writes + - batch_size : number of updates before commit + - limit : optional integer - limit number of entries processed (for testing) + - write_csv : write audit CSV to /tmp/ + Returns a summary dict. + """ + frappe.flags.in_migrate = True + + limit_clause = f"LIMIT {int(limit)}" if limit else "" + + # Find all affected DNs + affected_dns = frappe.db.sql(f""" + SELECT dn.name, dn.posting_date, dn.customer, dn.status, + dn.per_billed, dn.per_returned, dn.grand_total + FROM `tabDelivery Note` dn + WHERE dn.docstatus = 1 + AND dn.grand_total = 0 + AND dn.per_billed < 100 + AND dn.status NOT IN ('Stopped', 'Closed') + ORDER BY dn.posting_date + {limit_clause} + """, as_dict=1) + + total = len(affected_dns) + print(f"\nFound {total} zero-amount Delivery Note(s) with per_billed < 100.") + + if total == 0: + return {"total_found": 0, "updated": 0, "skipped": 0, "errors": []} + + # Breakdown by status + status_counts = {} + for dn in affected_dns: + status_counts[dn.status] = status_counts.get(dn.status, 0) + 1 + print("\nBreakdown by current status:") + for status, count in sorted(status_counts.items()): + print(f" {status}: {count}") + + # Date range + print(f"\nDate range: {affected_dns[0].posting_date} to {affected_dns[-1].posting_date}") + + # Check how many have SI references + with_si = frappe.db.sql(""" + SELECT COUNT(DISTINCT dn.name) + FROM `tabDelivery Note` dn + WHERE dn.docstatus = 1 AND dn.grand_total = 0 AND dn.per_billed < 100 + AND dn.status NOT IN ('Stopped', 'Closed') + AND EXISTS ( + SELECT 1 FROM `tabSales Invoice Item` sii + JOIN `tabSales Invoice` si ON si.name = sii.parent AND si.docstatus = 1 + WHERE sii.delivery_note = dn.name + ) + """)[0][0] + print(f"\nOf these, {with_si} already have linked Sales Invoices") + print(f"And {total - with_si} have no SI references (zero-value, nothing to bill)") + + # CSV audit log + writer = None + csv_file = None + csv_path = "" + + if write_csv: + timestamp = now_datetime().strftime("%Y%m%d%H%M%S") + csv_path = f"/tmp/close_zero_dns_{'dryrun' if dry_run else 'update'}_{timestamp}.csv" + os.makedirs("/tmp", exist_ok=True) + csv_file = open(csv_path, "w", newline="", encoding="utf-8") + writer = csv.DictWriter(csv_file, fieldnames=[ + "name", "posting_date", "customer", "old_status", "new_status", + "per_billed", "per_returned", "grand_total", "has_si", "action" + ]) + writer.writeheader() + + updated = 0 + skipped = 0 + errors = [] + + for counter, dn in enumerate(affected_dns, 1): + new_status = "Closed" + + # Check if this DN has SI references + has_si = frappe.db.sql(""" + SELECT 1 FROM `tabSales Invoice Item` sii + JOIN `tabSales Invoice` si ON si.name = sii.parent AND si.docstatus = 1 + WHERE sii.delivery_note = %s LIMIT 1 + """, dn.name) + has_si_flag = "Yes" if has_si else "No" + + if write_csv and writer: + writer.writerow({ + "name": dn.name, "posting_date": dn.posting_date, + "customer": dn.customer, "old_status": dn.status, + "new_status": new_status, "per_billed": dn.per_billed, + "per_returned": dn.per_returned, "grand_total": dn.grand_total, + "has_si": has_si_flag, + "action": "would_close" if dry_run else "closed" + }) + + if dry_run: + if counter <= 10 or counter % 500 == 0: + print(f" [{counter}/{total}] Would close {dn.name} | " + f"{dn.posting_date} | {dn.customer} | has_si={has_si_flag}") + else: + try: + frappe.db.sql(""" + UPDATE `tabDelivery Note` + SET status = %s, modified = NOW(), modified_by = %s + WHERE name = %s + """, (new_status, frappe.session.user, dn.name)) + updated += 1 + except Exception as e: + errors.append((dn.name, str(e))) + print(f" ERROR closing {dn.name}: {e}") + + if updated and (updated % batch_size == 0): + frappe.db.commit() + print(f" Committed batch up to {updated} updates...") + + if not dry_run: + frappe.db.commit() + print("Final commit done.") + + if csv_file: + csv_file.close() + + # Verify + remaining = frappe.db.sql(""" + SELECT COUNT(*) FROM `tabDelivery Note` + WHERE docstatus = 1 AND grand_total = 0 AND per_billed < 100 + AND status NOT IN ('Stopped', 'Closed') + """)[0][0] + + print("\nDone. Summary:") + print(f" Total found: {total}") + print(f" Updated: {updated}") + print(f" Skipped: {skipped}") + print(f" Errors: {len(errors)}") + print(f" Remaining zero-amount unbilled DNs: {remaining}") + if csv_path: + print(f" Audit CSV: {csv_path}") + + return { + "total_found": total, + "updated": updated, + "skipped": skipped, + "errors": errors, + "remaining": remaining, + "audit_csv": csv_path, + } + + +# bench execute entrypoint +def execute(dry_run=True, batch_size=500, limit=None, write_csv=True): + dry_run = bool(dry_run) + batch_size = int(batch_size) if batch_size else 500 + limit = int(limit) if limit else None + write_csv = bool(write_csv) + + print(f"*** CLOSE ZERO-AMOUNT DELIVERY NOTES ***") + print(f"*** {'DRY RUN' if dry_run else 'APPLYING CHANGES'} ***") + print(f"*** Limit: {limit}, Batch Size: {batch_size}, Write CSV: {write_csv} ***") + + try: + summary = close_zero_amount_delivery_notes( + dry_run=dry_run, batch_size=batch_size, + limit=limit, write_csv=write_csv + ) + except Exception as e: + print(f"\n*** ERROR: {e} ***") + frappe.log_error(title="Close Zero Amount DNs Failed") + frappe.db.rollback() + return {"error": str(e)} + + if dry_run: + print(f"\n*** DRY RUN COMPLETE. No changes were made. ***") + frappe.db.rollback() + else: + print(f"\n*** COMPLETE. Changes committed. ***") + + return summary + + +# Dry Run (test with limit): +# bench --site rigplerpnext.localhost execute rohit_common.migration_scripts.close_zero_amount_dns.execute --kwargs "{'dry_run': True, 'limit': 20}" + +# Dry Run (all): +# bench --site rigplerpnext.localhost execute rohit_common.migration_scripts.close_zero_amount_dns.execute --kwargs "{'dry_run': True}" + +# Actual Run: +# bench --site rigplerpnext.localhost execute rohit_common.migration_scripts.close_zero_amount_dns.execute --kwargs "{'dry_run': False, 'batch_size': 500}" diff --git a/rohit_common/migration_scripts/docs_execution_order.txt b/rohit_common/migration_scripts/docs_execution_order.txt index 5899ff2..7853362 100644 --- a/rohit_common/migration_scripts/docs_execution_order.txt +++ b/rohit_common/migration_scripts/docs_execution_order.txt @@ -13,4 +13,7 @@ bench --site development.localhost execute rohit_common.migration_scripts.combin Step 5: Fix Purchase Invoice Data bench --site development.localhost execute rohit_common.migration_scripts.fix_purchase_invoices_gst.execute --kwargs "{'dry_run': False}" #5 # Step 6: Fix Purchase Ledger -# bench --site development.localhost execute rohit_common.migration_scripts.create_purchase_gst_adjustment_jes.execute --kwargs "{'company': 'Rohit Industries Group Private Ltd', 'company_gstin': '06AAACR1567J1ZC', 'dry_run': False}" \ No newline at end of file +# bench --site development.localhost execute rohit_common.migration_scripts.create_purchase_gst_adjustment_jes.execute --kwargs "{'company': 'Rohit Industries Group Private Ltd', 'company_gstin': '06AAACR1567J1ZC', 'dry_run': False}" + +# Step 7: Fix Delivery Note +# bench --site rigplerpnext.localhost execute rohit_common.migration_scripts.close_zero_amount_dns.execute --kwargs "{'dry_run': False, 'batch_size': 500}" #6 \ No newline at end of file From 2f6b96217ac40b1cccf16ab335b9b18d9ffb1704 Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Tue, 17 Mar 2026 12:46:58 +0530 Subject: [PATCH 49/52] fix: scheduled jobs (#27) * fix: scheduled jobs * fix: auto_einvoice_tasks jobs * fix: small improvement in auto_refresh_gstin_auth_code * fix: auto_update_from_erp * fix: delete_unneeded_files and background_doc_processing * fix: weekly_long jobs * fix: updated hook --- rohit_common/hooks.py | 59 +-- .../rohit_common/india_gst_api/einv.py | 200 ++++++- .../india_gst_api/eway_bill_api.py | 49 ++ .../rohit_common/india_gst_api/gst_api.py | 145 +++--- .../scheduled_tasks/auto_delete_version.py | 146 ++++-- .../scheduled_tasks/auto_einvoice_tasks.py | 194 +++++-- .../auto_refresh_gstin_auth_code.py | 28 +- .../scheduled_tasks/auto_update_from_erp.py | 93 +++- .../auto_update_gstin_status.py | 104 ++-- .../scheduled_tasks/delete_unneeded_files.py | 487 ++++++++++++------ .../rohit_common/validations/address.py | 8 +- .../utils/background_doc_processing.py | 97 ++-- rohit_common/utils/rohit_common_utils.py | 45 +- 13 files changed, 1178 insertions(+), 477 deletions(-) diff --git a/rohit_common/hooks.py b/rohit_common/hooks.py index 6742161..6c58037 100644 --- a/rohit_common/hooks.py +++ b/rohit_common/hooks.py @@ -168,35 +168,36 @@ # Scheduled Tasks # --------------- -# scheduler_events = { -# "cron": { -# "10 2 * * *": [ -# "rohit_common.rohit_common.scheduled_tasks.auto_update_gstin_status.enqueue_gstin_update" -# # Runs everyday at 2:10 AM -# ], -# # Runs every 15 mins below jobs -# "*/15 * * * *": [ -# "rohit_common.rohit_common.scheduled_tasks.auto_einvoice_tasks.enq_inv_sub", -# "rohit_common.rohit_common.scheduled_tasks.auto_einvoice_tasks.enq_einv_create", -# ], -# }, -# "all": [ -# "rohit_common.rohit_common.scheduled_tasks.auto_refresh_gstin_auth_code.execute" -# ], -# "daily": [ -# "rohit_common.rohit_common.scheduled_tasks.auto_update_from_erp.update_export_invoices" -# ], -# "hourly": [ -# "rohit_common.rohit_common.scheduled_tasks.delete_unneeded_files.check_correct_folders", -# "rohit_common.utils.background_doc_processing.enqueue_bg", -# ], -# "weekly_long": [ -# "rohit_common.rohit_common.scheduled_tasks.auto_einvoice_tasks.get_unposted_invoices", -# "rohit_common.rohit_common.scheduled_tasks.auto_delete_version.enqueue_deletion", -# "rohit_common.rohit_common.scheduled_tasks.delete_unneeded_files.execute", -# ], -# "monthly": ["rohit_common.rohit_common.scheduled_tasks.email_queue_delete.execute"], -# } +scheduler_events = { + "cron": { + "10 2 * * *": [ + "rohit_common.rohit_common.scheduled_tasks.auto_update_gstin_status.enqueue_gstin_update" + # Runs everyday at 2:10 AM + ], + # Runs every 15 mins below jobs + "*/15 * * * *": [ + "rohit_common.rohit_common.scheduled_tasks.auto_einvoice_tasks.enq_inv_sub", + "rohit_common.rohit_common.scheduled_tasks.auto_einvoice_tasks.enq_einv_create", + ], + }, + "all": [ + "rohit_common.rohit_common.scheduled_tasks.auto_refresh_gstin_auth_code.execute" + ], + "daily": [ + "rohit_common.rohit_common.scheduled_tasks.auto_update_from_erp.update_export_invoices" + ], + "hourly": [ + "rohit_common.rohit_common.scheduled_tasks.delete_unneeded_files.check_correct_folders", + "rohit_common.utils.background_doc_processing.enqueue_bg", + ], + "weekly_long": [ + "rohit_common.rohit_common.scheduled_tasks.auto_einvoice_tasks.get_unposted_invoices", + "rohit_common.rohit_common.scheduled_tasks.auto_delete_version.enqueue_deletion", + "rohit_common.rohit_common.scheduled_tasks.delete_unneeded_files.execute", + ], + # No need for an email queue cleanup job it is handled automatically by Frappe. + # "monthly": ["rohit_common.rohit_common.scheduled_tasks.email_queue_delete.execute"], +} # Testing # ------- diff --git a/rohit_common/rohit_common/india_gst_api/einv.py b/rohit_common/rohit_common/india_gst_api/einv.py index 23a7cf6..ba4fc9e 100644 --- a/rohit_common/rohit_common/india_gst_api/einv.py +++ b/rohit_common/rohit_common/india_gst_api/einv.py @@ -9,7 +9,7 @@ from datetime import datetime from pyqrcode import create as qrcreate from frappe.utils import get_datetime, flt -from .eway_bill_api import get_eway_pass, get_taxes_type, get_transport_mode, get_eway_distance +from .eway_bill_api import get_eway_pass, get_taxes_type,get_taxes_type_from_doc, get_transport_mode, get_eway_distance from .common import get_base_url, get_aspid_pass, get_default_gstin, get_numeric_state_code, \ get_gst_pincode, get_gst_based_uom, get_place_of_supply TIMEOUT = 10 @@ -579,3 +579,201 @@ def einv_needed(dtype, dname): if dtd.gst_category != "Unregistered": einv_need = 1 return einv_need + + +def generate_irn_from_doc(doc): + """ + Optimized IRN generation using an already loaded document. + Used by background jobs to avoid repeated frappe.get_doc calls. + """ + + api = "generate_irn" + full_url = get_full_einv_url(api) + full_url = add_qr_code_size(url=full_url) + headers = get_headers() + + einv_json = generate_einv_json_from_doc(doc) + + try: + response = requests.post( + url=full_url, + headers=headers, + data=einv_json, + timeout=TIMEOUT + ) + response.raise_for_status() + + except requests.RequestException: + frappe.log_error( + frappe.get_traceback(), + f"IRN API Request Failed for {doc.name}" + ) + return + + res = json.loads(response.text) + + if flt(res.get("Status")) == 1: + irn_dict = json.loads(res.get("Data")) + update_irn_details(doc.doctype, doc.name, irn_dict) + + else: + errors = res.get("ErrorDetails") or [] + + if errors: + error = errors[0] + else: + frappe.log_error(json.dumps(res, indent=2), "Unknown IRN Error") + return + if error.get("ErrorCode") == "2150": + info_det = res.get("InfoDtls")[0] + # CRITICAL FIX: Parse the stringified JSON + irn_dict = json.loads(info_det.get("Desc")) + update_irn_details(doc.doctype, doc.name, irn_dict) + + else: + frappe.log_error( + json.dumps(res, indent=2), + "IRN Generation Failed" + ) + + +def generate_einv_json_from_doc(doc): + """ + Generates eInvoice JSON using an already loaded document. + """ + + einv_dt = frappe._dict({}) + einv_dt.Title = "GST-India Invoice Document" + einv_dt.Description = "GST Invoice format for IRN Generation in INDIA" + einv_dt.Version = "1.1" + + pos = get_place_of_supply(doc.doctype, doc.name) + + einv_dt = add_einv_doc_details_from_doc(einv_dt, doc) + + sell_add = doc.company_address + buy_add = doc.customer_address + ship_add = doc.shipping_address_name + + einv_dt = add_einv_adr_details(einv_dt, sell_add, "seller") + einv_dt = add_einv_adr_details(einv_dt, buy_add, "buyer", pos=pos) + einv_dt = add_einv_adr_details(einv_dt, ship_add, "ship", port_code=doc.port_code) + + item_list, val_dt = get_einv_item_details_from_doc(doc) + + einv_dt.ItemList = item_list + einv_dt.ValDtls = val_dt + + return json.dumps(einv_dt) + + +def get_einv_item_details_from_doc(doc): + """ + Returns item details dictionary for the eInvoice JSON using a loaded document. + """ + itm_lst = [] + val_dt = frappe._dict({}) + + if doc.doctype != "Sales Invoice": + frappe.throw( + f"e-Invoice Not Supported for {doc.doctype} and Doc No: {doc.name}" + ) + + tax_details = get_taxes_type_from_doc(doc) + + val_dt.AssVal = round(abs(tax_details.get("tax_val", 0)), 2) + val_dt.TotInvVal = round(abs(tax_details.get("tot_val", 0)), 2) + val_dt.CgstVal = round(abs(tax_details.get("cgst_amt", 0)), 2) + val_dt.SgstVal = round(abs(tax_details.get("sgst_amt", 0)), 2) + val_dt.IgstVal = round(abs(tax_details.get("igst_amt", 0)), 2) + val_dt.Discount = round(abs(tax_details.get("discount_amt", 0)), 2) + val_dt.OthChrg = round(abs(tax_details.get("other_amt", 0)), 2) + + gst_rate = tax_details.get("gst_per", 0) + igst_per = tax_details.get("igst_per", 0) + cgst_per = tax_details.get("cgst_per", 0) + sgst_per = tax_details.get("sgst_per", 0) + + unique_hsns = list(set(row.gst_hsn_code for row in doc.items if row.gst_hsn_code)) + + if unique_hsns: + hsn_records = frappe.get_all( + "GST HSN Code", + filters={"name": ("in", unique_hsns)}, + fields=["name", "description", "is_service"] + ) + else: + hsn_records = [] + + hsn_map = {hsn.name: hsn for hsn in hsn_records} + + for row in doc.items: + hsn_doc = hsn_map.get(row.gst_hsn_code) + + is_ser = "Y" if hsn_doc and flt(hsn_doc.is_service) else "N" + prd_desc = hsn_doc.description[:299] if hsn_doc and hsn_doc.description else "Product Description Missing" + + it_row_dict = frappe._dict({}) + + it_row_dict.SlNo = str(row.idx) + it_row_dict.PrdDesc = prd_desc + it_row_dict.IsServc = is_ser + it_row_dict.HsnCd = row.gst_hsn_code + it_row_dict.Qty = abs(row.qty) + it_row_dict.Unit = get_gst_based_uom(row.uom) + it_row_dict.UnitPrice = round(row.base_rate, 2) + it_row_dict.TotAmt = round(abs(row.base_amount), 2) + it_row_dict.AssAmt = round(abs(row.base_amount), 2) + it_row_dict.GstRt = gst_rate + + it_row_dict.IgstAmt = abs(round(row.base_amount * (igst_per / 100), 2)) + it_row_dict.CgstAmt = abs(round(row.base_amount * (cgst_per / 100), 2)) + it_row_dict.SgstAmt = abs(round(row.base_amount * (sgst_per / 100), 2)) + + it_row_dict.TotItemVal = abs(round(row.base_amount * (1 + gst_rate / 100), 2)) + + itm_lst.append(it_row_dict) + + return itm_lst, val_dt + + +def add_einv_doc_details_from_doc(einv_dt, doc): + """ + Adds document details to the eInvoice dictionary using a loaded document. + """ + + if len(doc.name) > 16: + frappe.throw( + f"Name of {frappe.get_desk_link(doc.doctype, doc.name)} exceeds 16 characters" + ) + + trans_dt = frappe._dict({}) + doc_dts = frappe._dict({}) + + trans_dt.TaxSch = "GST" + + supply_type = get_einv_supply_type( + gst_category=doc.gst_category, + exp_type=doc.export_type + ) + + trans_dt.SupTyp = supply_type + trans_dt.RegRev = get_einv_rcm(doc) + + ecom_gstin = get_ecom_gstin() + if ecom_gstin: + trans_dt.EcmGstin = ecom_gstin + + igst_on_intra = get_igst_on_intra() + if igst_on_intra == "Y": + trans_dt.IgstOnIntra = igst_on_intra + + einv_dt.TranDtls = trans_dt + + doc_dts.Typ = get_einv_doctype(doc) + doc_dts.No = doc.name + doc_dts.Dt = doc.posting_date.strftime("%d/%m/%Y") + + einv_dt.DocDtls = doc_dts + + return einv_dt \ No newline at end of file diff --git a/rohit_common/rohit_common/india_gst_api/eway_bill_api.py b/rohit_common/rohit_common/india_gst_api/eway_bill_api.py index a822251..f96b9b2 100644 --- a/rohit_common/rohit_common/india_gst_api/eway_bill_api.py +++ b/rohit_common/rohit_common/india_gst_api/eway_bill_api.py @@ -381,6 +381,55 @@ def get_taxes_type(dtype, dname): taxes_dict["tot_val"] = doc.base_grand_total return taxes_dict +def get_taxes_type_from_doc(doc): + """ + Optimized version of get_taxes_type that accepts a loaded document object. + Preserves exact matching against GST Settings and handles base_tax_amount correctly. + """ + gst_per = 0 + taxes_dict = { + "other_amt": 0, + "cgst_amt": 0, "cgst_per": 0, + "sgst_amt": 0, "sgst_per": 0, + "igst_amt": 0, "igst_per": 0, + "discount_amt": 0 + } + + gset = frappe.get_single('GST Settings') + + for tax in doc.taxes: + found = 0 + for acc in gset.gst_accounts: + if tax.account_head == acc.cgst_account: + found = 1 + taxes_dict["cgst_amt"] = tax.base_tax_amount + taxes_dict["cgst_per"] = tax.rate + gst_per += tax.rate + break + elif tax.account_head == acc.sgst_account: + found = 1 + taxes_dict["sgst_amt"] = tax.base_tax_amount + taxes_dict["sgst_per"] = tax.rate + gst_per += tax.rate + break + elif tax.account_head == acc.igst_account: + found = 1 + taxes_dict["igst_amt"] = tax.base_tax_amount + taxes_dict["igst_per"] = tax.rate + gst_per += tax.rate + break + + if found == 0: + if tax.description and re.search('discount', tax.description, re.IGNORECASE): + taxes_dict["discount_amt"] = tax.base_tax_amount + else: + taxes_dict["other_amt"] += tax.base_tax_amount + + taxes_dict["gst_per"] = gst_per + taxes_dict["tax_val"] = doc.base_net_total + taxes_dict["tot_val"] = doc.base_grand_total + + return taxes_dict def get_items_table(data, tbl_dict): """ diff --git a/rohit_common/rohit_common/india_gst_api/gst_api.py b/rohit_common/rohit_common/india_gst_api/gst_api.py index 8688afb..a09a90d 100644 --- a/rohit_common/rohit_common/india_gst_api/gst_api.py +++ b/rohit_common/rohit_common/india_gst_api/gst_api.py @@ -119,35 +119,43 @@ def authenticate_gst_otp(gstin, otp, row_id): frappe.throw(f"OTP Validation Failed and Error Message = {auth_resp} and Link = {auth_url}") -def check_for_refresh_token(row): +def check_for_refresh_token(row, settings_doc=None): """ - For a row dict would check if the Auth Token is needed to be refreshed for a GSTIN + For a row (Rohit GST Settings.gst_registration_details row) check if token requires refresh. + Accepts optional settings_doc to avoid reloading settings inside helpers. """ now_time = datetime.datetime.now() token_time = flt(row.update_token_every_mins) + if row.authorization_token and row.api_access_authorized == 1: token_update_time = row.validity_of_token - datetime.timedelta(minutes=360) + \ datetime.timedelta(minutes=token_time) + if token_update_time < now_time < row.validity_of_token: - new_auth_token, error_code = refresh_auth_token(row.gst_registration_number, - row.authorization_token) - if new_auth_token != "": - print(f"Auto Updated Auth Token for {row.gst_registration_number}") - update_auth_token(row_name=row.name, auth_token=new_auth_token) + new_auth_token, error_code = refresh_auth_token(row.gst_registration_number, row.authorization_token) + + if new_auth_token: + frappe.logger("gst_api").info(f"Auto Updated Auth Token for {row.gst_registration_number}") + # update_auth_token will commit + update_auth_token(row_name=row.name, auth_token=new_auth_token, settings_doc=settings_doc) else: - print(f"Auto Auth Token Update Failed for {row.gst_registration_number}") - update_auth_token(row_name=row.name, auth_token="", failed=1, error_code=error_code) + frappe.logger("gst_api").warning(f"Auto Auth Token Update Failed for {row.gst_registration_number}") + update_auth_token(row_name=row.name, auth_token="", failed=1, error_code=error_code, settings_doc=settings_doc) + elif token_update_time > now_time and row.validity_of_token > now_time: - print(f"No Need to Update the Auth Token for {row.gst_registration_number} as Token to \ - be Updated After {token_update_time}") + frappe.logger("gst_api").info( + f"No Need to Update the Auth Token for {row.gst_registration_number}; next update after {token_update_time}" + ) else: - print(f"Auth Token is Expired and hence Need to Generate OTP Again for \ - {row.gst_registration_number}") - update_auth_token(row_name=row.name, auth_token="", failed=1, error_code='AUTH4037') + frappe.logger("gst_api").warning( + f"Auth Token is expired for {row.gst_registration_number}; OTP regeneration required" + ) + update_auth_token(row_name=row.name, auth_token="", failed=1, error_code='AUTH4037', settings_doc=settings_doc) + elif row.api_access_authorized != 1: - print(f"API Authorization is Unchecked for {row.gst_registration_number}") + frappe.logger("gst_api").info(f"API Authorization is unchecked for {row.gst_registration_number}") else: - print(f"No API Authorization Token for {row.gst_registration_number}") + frappe.logger("gst_api").info(f"No API Authorization Token for {row.gst_registration_number}") def refresh_auth_token(gstin, auth_token): @@ -170,79 +178,86 @@ def refresh_auth_token(gstin, auth_token): return refresh_resp, error_code -def get_auth_token(gstin): +def get_auth_token(gstin, settings_doc=None): """ - Gets auth token for a given GSTIN + Gets auth token for a given GSTIN. If settings_doc passed, it will be used instead of reloading. """ - found = 0 - r_set = frappe.get_doc("Rohit GST Settings", "Rohit GST Settings") + found = False now_time = datetime.datetime.now() new_auth_token = "" + + if settings_doc is None: + r_set = frappe.get_doc("Rohit GST Settings", "Rohit GST Settings") + else: + r_set = settings_doc + for row in r_set.gst_registration_details: if row.gst_registration_number == gstin: - # Updates token after this many mins token_update_min = flt(row.update_token_every_mins) token_update_time = row.validity_of_token - datetime.timedelta(minutes=360) + \ datetime.timedelta(minutes=token_update_min) - found = 1 + found = True + if row.authorization_token and row.api_access_authorized == 1: if token_update_time > now_time and row.validity_of_token > now_time: new_auth_token = row.authorization_token elif token_update_time < now_time < row.validity_of_token: new_auth_token, error_code = refresh_auth_token(gstin=gstin, auth_token=row.authorization_token) - if new_auth_token != "": - update_auth_token(row_name=row.name, auth_token=new_auth_token, - error_code=error_code) + if new_auth_token: + update_auth_token(row_name=row.name, auth_token=new_auth_token, settings_doc=r_set) else: - update_auth_token(row_name=row.name, auth_token="", failed=1, - error_code=error_code) - frappe.throw(f"New Auth Token for {gstin} is Empty you might need to \ - Generate OTP Again") + update_auth_token(row_name=row.name, auth_token="", failed=1, error_code=error_code, settings_doc=r_set) + frappe.throw(f"New Auth Token for {gstin} is Empty you might need to Generate OTP Again") else: - update_auth_token(row_name=row.name, auth_token="", failed=1, - error_code="AUTH4037") - frappe.throw(f"Auth Token for {gstin} is Expired you might need to \ - Generate OTP Again") + update_auth_token(row_name=row.name, auth_token="", failed=1, error_code="AUTH4037", settings_doc=r_set) + frappe.throw(f"Auth Token for {gstin} is Expired you might need to Generate OTP Again") else: frappe.throw(f"Authorization Needed for {gstin}. Resend OTP and Get Authorization") - if found == 0: + + if not found: frappe.throw(f"{gstin} is Not Setup in Rohit GST Settings for API Access") + return new_auth_token -def update_auth_token(row_name, auth_token, failed=0, error_code=None): +def update_auth_token(row_name, auth_token, failed=0, error_code=None, settings_doc=None): """ - Updates the Auth Token for a Row Name in the GST Registration Details + Updates the Auth Token for a Row Name in the GST Registration Details. + Commits immediately after update so token state isn't lost if the worker crashes. """ if not error_code: error_code = "" ecl = ["AUTH4037", "RET11402", "SWEB9033", "AUTH4033", "GSP102"] + + # If failure, clear OTP, maybe disable access and commit if failed == 1: - # Only Update API Access to zero on certain errors and not all errors frappe.db.set_value("GST Registration Details", row_name, "otp", "") - if error_code != "" and error_code in ecl: - print("Removing API Access") + if error_code and error_code in ecl: + frappe.logger("gst_api").info(f"Removing API Access for row {row_name} due to error {error_code}") frappe.db.set_value("GST Registration Details", row_name, "api_access_authorized", 0) else: - print(f"Error Code: {str(error_code)} Not in List") + frappe.logger("gst_api").info(f"update_auth_token: error code {error_code} not in removal list") frappe.db.commit() + return + + # Normal successful update: increment counter, set token and validity, commit + auth_access = flt(frappe.db.get_value("GST Registration Details", row_name, "api_access_authorized")) + exist_token_times = flt(frappe.db.get_value("GST Registration Details", row_name, "no_of_times_token_updated")) + + if auth_access == 1: + frappe.db.set_value("GST Registration Details", row_name, "no_of_times_token_updated", exist_token_times + 1) else: - auth_access = flt(frappe.db.get_value("GST Registration Details", row_name, - "api_access_authorized")) - exist_token_times = flt(frappe.db.get_value("GST Registration Details", row_name, - "no_of_times_token_updated")) - if auth_access == 1: - frappe.db.set_value("GST Registration Details", row_name, "no_of_times_token_updated", - exist_token_times + 1) - else: - frappe.db.set_value("GST Registration Details", row_name, "no_of_times_token_updated", - 0) - frappe.db.set_value("GST Registration Details", row_name, "api_access_authorized", 1) - frappe.db.set_value("GST Registration Details", row_name, "authorization_token", auth_token) - frappe.db.set_value("GST Registration Details", row_name, "otp", "") - frappe.db.set_value("GST Registration Details", row_name, "validity_of_token", - datetime.datetime.now() + datetime.timedelta(minutes=360)) + frappe.db.set_value("GST Registration Details", row_name, "no_of_times_token_updated", 0) + + frappe.db.set_value("GST Registration Details", row_name, "api_access_authorized", 1) + frappe.db.set_value("GST Registration Details", row_name, "authorization_token", auth_token) + frappe.db.set_value("GST Registration Details", row_name, "otp", "") + frappe.db.set_value("GST Registration Details", row_name, "validity_of_token", + datetime.datetime.now() + datetime.timedelta(minutes=360)) + + # commit immediately so we don't lose the token on crash + frappe.db.commit() def get_gst_url(api, action, gstin): @@ -257,19 +272,23 @@ def get_gst_url(api, action, gstin): return gst_url -def get_gst_username(gstin): - """ - Get the GST Username from Rohit GST Settings for a given GSTIN - """ - found = 0 +def get_gst_username(gstin, settings_doc=None): + found = False gst_username = "" - r_set = frappe.get_doc("Rohit GST Settings", "Rohit GST Settings") + if settings_doc is None: + r_set = frappe.get_doc("Rohit GST Settings", "Rohit GST Settings") + else: + r_set = settings_doc + for row in r_set.gst_registration_details: if row.gst_registration_number == gstin: - found = 1 + found = True gst_username = row.gst_username - if found == 0: + break + + if not found: frappe.throw(f"No GSTIN username found for {gstin}") + return gst_username diff --git a/rohit_common/rohit_common/scheduled_tasks/auto_delete_version.py b/rohit_common/rohit_common/scheduled_tasks/auto_delete_version.py index f34b259..ec8fd15 100644 --- a/rohit_common/rohit_common/scheduled_tasks/auto_delete_version.py +++ b/rohit_common/rohit_common/scheduled_tasks/auto_delete_version.py @@ -5,72 +5,124 @@ # This Scheduled Tasks Would Periodically check the table TabVersion and delete from them old entries. # Based on Reference Doctype mentioned in the Rohit Settings. -from __future__ import unicode_literals import time import frappe -from frappe.utils import flt +from frappe.utils import flt, nowdate, add_days from frappe.utils.background_jobs import enqueue +log = frappe.logger("version_cleanup") + +BATCH_SIZE = 5000 + def enqueue_deletion(): enqueue(execute, queue="long", timeout=3600) +def delete_versions(query, params): + """ + Deletes versions using SQL batching + """ + deleted = 0 + + while True: + + rows = frappe.db.sql( + f""" + SELECT name + FROM `tabVersion` + {query} + LIMIT %s + """, + params + (BATCH_SIZE,), + as_dict=True, + ) + + if not rows: + break + + names = [r.name for r in rows] + + frappe.db.sql( + f""" + DELETE FROM `tabVersion` + WHERE name IN ({",".join(["%s"] * len(names))}) + """, + names, + ) + + frappe.db.commit() + + deleted += len(names) + + log.info(f"Deleted {deleted} versions so far") + + return deleted + + def execute(): - st_time = time.time() - rset = frappe.get_single("Rohit Settings") - max_days = int(flt(rset.max_days_to_keep_version)) or 30 # ensure int and default to 30 - dt_list = [row.document_type for row in rset.auto_delete_from_version] + + start = time.time() + + settings = frappe.get_single("Rohit Settings") + + max_days = int(flt(settings.max_days_to_keep_version) or 30) + + cutoff = add_days(nowdate(), -max_days) + + dt_list = [row.document_type for row in settings.auto_delete_from_version] + + # ------------------------- + # Unregulated doctypes + # ------------------------- if dt_list: + placeholders = ", ".join(["%s"] * len(dt_list)) + query = f""" - SELECT name, creation, ref_doctype, docname - FROM `tabVersion` - WHERE ref_doctype NOT IN ({placeholders}) - AND creation <= (DATE_SUB(CURDATE(), INTERVAL {max_days} DAY)) + WHERE ref_doctype NOT IN ({placeholders}) + AND creation <= %s """ - un_regulated_version = frappe.db.sql(query, tuple(dt_list), as_dict=1) + + params = tuple(dt_list) + (cutoff,) + else: - # If dt_list empty, simply skip the NOT IN clause - query = f""" - SELECT name, creation, ref_doctype, docname - FROM `tabVersion` - WHERE creation <= (DATE_SUB(CURDATE(), INTERVAL {max_days} DAY)) + + query = """ + WHERE creation <= %s """ - un_regulated_version = frappe.db.sql(query, as_dict=1) - deleted_0 = 0 - deleted_1 = 0 + params = (cutoff,) - for d in un_regulated_version: - print(f"Deleting Versions for All Un-Listed Doctypes older than {max_days} Days") - deleted_0 += 1 - frappe.delete_doc("Version", d.name, for_reload=1) - if deleted_0 % 2000 == 0: - frappe.db.commit() - print(f"Committing After {deleted_0} deletions. Time Elapsed {int(time.time() - st_time)} seconds") + deleted_unregulated = delete_versions(query, params) - # Now process doctypes listed in settings - for row in rset.auto_delete_from_version: - max_days_row = int(flt(row.days_to_keep)) if flt(row.days_to_keep) > 0 else 1 - print(f"Deleting Versions for {row.document_type} older than {max_days_row} Days") + # ------------------------- + # Regulated doctypes + # ------------------------- - query = f""" - SELECT name, creation, ref_doctype, docname - FROM `tabVersion` - WHERE ref_doctype = %s - AND creation <= (DATE_SUB(CURDATE(), INTERVAL {max_days_row} DAY)) + deleted_regulated = 0 + + for row in settings.auto_delete_from_version: + + days = int(flt(row.days_to_keep) or 1) + + cutoff = add_days(nowdate(), -days) + + log.info( + f"Deleting versions for {row.document_type} older than {days} days" + ) + + query = """ + WHERE ref_doctype = %s + AND creation <= %s """ - reg_version = frappe.db.sql(query, (row.document_type,), as_dict=1) - - for d in reg_version: - deleted_1 += 1 - frappe.delete_doc("Version", d.name, for_reload=1) - if deleted_1 % 2000 == 0: - frappe.db.commit() - print(f"Committing After {deleted_1} deletions. Time Elapsed {int(time.time() - st_time)} seconds") - - tot_time = int(time.time() - st_time) - print(f"Total Versions Deleted = {deleted_0 + deleted_1}") - print(f"Total Time Taken = {tot_time} seconds") + + params = (row.document_type, cutoff) + + deleted_regulated += delete_versions(query, params) + + total = deleted_unregulated + deleted_regulated + + log.info(f"Total Versions Deleted = {total}") + log.info(f"Total runtime = {int(time.time() - start)}s") diff --git a/rohit_common/rohit_common/scheduled_tasks/auto_einvoice_tasks.py b/rohit_common/rohit_common/scheduled_tasks/auto_einvoice_tasks.py index f45edbc..8766f8c 100644 --- a/rohit_common/rohit_common/scheduled_tasks/auto_einvoice_tasks.py +++ b/rohit_common/rohit_common/scheduled_tasks/auto_einvoice_tasks.py @@ -6,7 +6,8 @@ from frappe.utils import flt from frappe.utils.background_jobs import enqueue from erpnext.stock.stock_ledger import NegativeStockError -from ..india_gst_api.einv import einv_needed, generate_irn + +from ..india_gst_api.einv import generate_irn_from_doc def enq_inv_sub(): @@ -25,71 +26,164 @@ def enq_einv_create(): def get_unposted_invoices(): """ - Gets a list of invoices which are not posted in the General Ledger and also the ones - not posted in Stock Ledger + Finds submitted invoices without GL entries and resets them to Draft. """ - gl_not_posted = frappe.db.sql("""SELECT si.name, si.creation FROM `tabSales Invoice` si - WHERE si.base_grand_total > 0 AND si.docstatus = 1 AND si.name NOT IN (SELECT gle.voucher_no - FROM `tabGL Entry` gle WHERE gle.voucher_type = 'Sales Invoice' - AND gle.voucher_no = si.name) ORDER BY si.creation""", as_dict=1) - for un_si in gl_not_posted: - sid = frappe.get_doc("Sales Invoice", un_si) - sid.cancel() - frappe.db.set_value("Sales Invoice", un_si.name, "docstatus", 0) - frappe.db.set_value("Sales Invoice", un_si.name, "set_posting_time", 1) - frappe.db.set_value("Sales Invoice", un_si.name, "marked_to_submit", 1) - print(f"SI# {un_si.name} not Posted in General Ledger hence Made Draft") + log = frappe.logger("gl_repair") + + BATCH_SIZE = 20 + + invoices = frappe.db.sql( + """ + SELECT si.name + FROM `tabSales Invoice` si + LEFT JOIN `tabGL Entry` gle + ON gle.voucher_no = si.name + AND gle.voucher_type = 'Sales Invoice' + WHERE si.base_grand_total > 0 + AND si.docstatus = 1 + AND gle.name IS NULL + ORDER BY si.creation + """, + as_dict=True + ) + + processed = 0 + + for row in invoices: + + try: + doc = frappe.get_doc("Sales Invoice", row.name) + + doc.cancel() + + frappe.db.set_value( + "Sales Invoice", + row.name, + { + "docstatus": 0, + "set_posting_time": 1, + "marked_to_submit": 1 + } + ) + + log.info( + f"Sales Invoice {row.name} not posted in GL. Converted back to Draft." + ) + + processed += 1 + + except Exception: + frappe.log_error( + frappe.get_traceback(), + f"GL repair failed for Sales Invoice {row.name}" + ) + + if processed and processed % BATCH_SIZE == 0: + frappe.db.commit() + + frappe.db.commit() def get_docs_to_submit(): """ - Submits the Sales Invoices or JV which are marked to Submit + Submits documents which were marked to submit """ + doc_list = ["Sales Invoice"] - for doc in doc_list: - dft_doc = frappe.db.sql(f"""SELECT name FROM `tab{doc}` WHERE docstatus = 0 - AND marked_to_submit = 1""", as_dict=1) - if dft_doc: - for dtd in dft_doc: - doc_t = frappe.get_doc(doc, dtd.name) - try: - doc_t.submit() - print(f"Submitting {doc_t.name}") - except NegativeStockError: - print(f"Negative Stock Error for {doc_t.name} hence Rolling Back") - frappe.db.rollback() - except Exception as e: - print(f"Some Other Error for {doc_t.name} and Error = {e}") - frappe.db.rollback() + + for doctype in doc_list: + + draft_docs = frappe.db.sql( + f""" + SELECT name + FROM `tab{doctype}` + WHERE docstatus = 0 + AND marked_to_submit = 1 + """, + as_dict=True + ) + + for row in draft_docs: + + doc = frappe.get_doc(doctype, row.name) + + try: + doc.submit() + frappe.logger().info(f"Submitted {doctype} {doc.name}") + + # CRITICAL FIX: Commit only on success frappe.db.commit() + except NegativeStockError: + frappe.db.rollback() + frappe.logger().warning( + f"Negative stock error while submitting {doc.name}" + ) + + except Exception: + frappe.db.rollback() + frappe.log_error( + frappe.get_traceback(), + f"Submission failed for {doc.name}" + ) + def make_einvoice_for_docs(): """ - Makes the einvoice for the Docs based on eInvoice Applicability and its Date + Generates eInvoices for eligible documents """ - doc_list = ["Sales Invoice"] - einv_app = flt(frappe.get_value("Rohit Settings", "Rohit Settings", "enable_einvoice")) - einv_date = frappe.get_value("Rohit Settings", "Rohit Settings", "einvoice_applicable_date") - if einv_app == 1: - for doc in doc_list: - query = f"""SELECT name, posting_date FROM `tab{doc}` WHERE docstatus = 1 AND - (irn IS NULL OR ack_no IS NULL OR ack_date IS NULL) AND - posting_date >= '{einv_date}' ORDER BY posting_date DESC, name DESC""" - einv_docs = frappe.db.sql(query, as_dict=1) - if einv_docs: - for einv in einv_docs: - need_einv = einv_needed(doc, einv.name) - if need_einv == 1: - try: - print(f"Trying to Generate eInvoice for {doc}: {einv.name}") - generate_irn(dtype=doc, dname=einv.name) - except Exception as e: - print(e) + + enable_einv = flt( + frappe.db.get_single_value("Rohit Settings", "enable_einvoice") + ) + + if not enable_einv: + return + + einv_date = frappe.db.get_single_value( + "Rohit Settings", + "einvoice_applicable_date" + ) + + invoices = frappe.db.sql( + """ + SELECT name + FROM `tabSales Invoice` + WHERE docstatus = 1 + AND (irn IS NULL OR ack_no IS NULL OR ack_date IS NULL) + AND posting_date >= %s + ORDER BY posting_date DESC, name DESC + """, + einv_date, + as_dict=True + ) + + for row in invoices: + + try: + doc = frappe.get_doc("Sales Invoice", row.name) + + if doc.gst_category in ("Unregistered", "Consumer"): + continue + + frappe.logger().info( + f"Generating eInvoice for Sales Invoice {doc.name}" + ) + + generate_irn_from_doc(doc) + + frappe.db.commit() + + except Exception: + frappe.db.rollback() + frappe.log_error( + frappe.get_traceback(), + f"eInvoice generation failed for {row.name}" + ) def make_eway_bill_for_docs(): """ If eway is needed for a doc then eway bill is made based on IRN generated """ - pass + pass \ No newline at end of file diff --git a/rohit_common/rohit_common/scheduled_tasks/auto_refresh_gstin_auth_code.py b/rohit_common/rohit_common/scheduled_tasks/auto_refresh_gstin_auth_code.py index 35f3a46..b023581 100644 --- a/rohit_common/rohit_common/scheduled_tasks/auto_refresh_gstin_auth_code.py +++ b/rohit_common/rohit_common/scheduled_tasks/auto_refresh_gstin_auth_code.py @@ -1,14 +1,28 @@ # Copyright (c) 2021. Rohit Industries Group Private Limited and Contributors. # For license information, please see license.txt -import frappe + import time +import frappe from ..india_gst_api.gst_api import check_for_refresh_token - +from frappe import logger def execute(): st_time = time.time() - r_set = frappe.get_doc("Rohit GST Settings", "Rohit Settings") - for d in r_set.gst_registration_details: - check_for_refresh_token(row=d) - r_set.reload() - print(f"Total Time Taken = {int(time.time() - st_time)} seconds") + try: + r_set = frappe.get_doc("Rohit GST Settings", "Rohit GST Settings") + except Exception as e: + frappe.log_error(frappe.get_traceback(), "Failed to load Rohit GST Settings") + return + + for row in r_set.gst_registration_details: + try: + check_for_refresh_token(row=row, settings_doc=r_set) + except Exception: + frappe.log_error(frappe.get_traceback(), f"check_for_refresh_token failed for {row.gst_registration_number}") + + try: + r_set.reload() + except Exception: + frappe.log_error(frappe.get_traceback(), "Failed to reload Rohit GST Settings after refresh") + + logger("gst_api").info(f"auto_refresh_gstin_auth_code completed in {int(time.time() - st_time)}s") diff --git a/rohit_common/rohit_common/scheduled_tasks/auto_update_from_erp.py b/rohit_common/rohit_common/scheduled_tasks/auto_update_from_erp.py index 159e842..e9a5a10 100644 --- a/rohit_common/rohit_common/scheduled_tasks/auto_update_from_erp.py +++ b/rohit_common/rohit_common/scheduled_tasks/auto_update_from_erp.py @@ -5,33 +5,80 @@ # This Scheduled Tasks Would Periodically check the Sales Invoices in ERP and Update the # Shipping Bill No and Shipping Bill Date -from __future__ import unicode_literals -import frappe import time +import frappe from ..erpnext_api.erpnext_api_common import get_dt from ...utils.accounts_utils import get_base_doc_no +BATCH_SIZE = 50 + + def update_export_invoices(): - st_time = time.time() - records_updated = 0 - exp_inv = frappe.db.sql("""SELECT si.name, si.shipping_bill_number, si.shipping_bill_date - FROM `tabSales Invoice` si, `tabSales Taxes and Charges Template` st - WHERE si.docstatus=1 AND si.base_net_total > 0 AND si.taxes_and_charges = st.name AND st.disabled = 0 - AND st.is_export = 1 AND si.shipping_bill_number IS NULL ORDER BY si.creation""", as_dict=1) - for inv in exp_inv: - sid = frappe.get_doc("Sales Invoice", inv.name) - base_si_no = get_base_doc_no(sid) - fields = ["name", "shipping_bill_number", "shipping_bill_date"] - filters = [["docstatus", "=", 1], ["name", "LIKE", "%" + str(base_si_no) + "%"]] - r = get_dt(dt='Sales Invoice', fields_list=fields, filters=filters) - if r: - if r.get("data"): - epd = frappe._dict(r.get("data")[0]) - records_updated += 1 - frappe.db.set_value("Sales Invoice", sid.name, "shipping_bill_number", epd.shipping_bill_number) - frappe.db.set_value("Sales Invoice", sid.name, "shipping_bill_date", epd.shipping_bill_date) - print(f"Updated Shipping Bill No and Date in {sid.name}") - print(f"Total Invoices Updated = {records_updated}") - print(f"Total Time Taken = {int(time.time() - st_time)} seconds") + log = frappe.logger("export_invoice_update") + + start_time = time.time() + updated = 0 + + invoices = frappe.db.sql(""" + SELECT + si.name, + si.amended_from + FROM `tabSales Invoice` si + JOIN `tabSales Taxes and Charges Template` st + ON si.taxes_and_charges = st.name + WHERE + si.docstatus = 1 + AND si.base_net_total > 0 + AND st.disabled = 0 + AND st.is_export = 1 + AND si.shipping_bill_number IS NULL + ORDER BY si.creation + """, as_dict=True) + + for inv in invoices: + + try: + doc = frappe.get_doc("Sales Invoice", inv.name) + base_si_no = get_base_doc_no(doc) + + filters = [ + ["docstatus", "=", 1], + ["name", "like", f"%{base_si_no}%"] + ] + + result = get_dt( + dt="Sales Invoice", + fields_list=["name", "shipping_bill_number", "shipping_bill_date"], + filters=filters + ) + + if result and result.get("data"): + row = result["data"][0] + + frappe.db.set_value( + "Sales Invoice", + inv.name, + { + "shipping_bill_number": row.get("shipping_bill_number"), + "shipping_bill_date": row.get("shipping_bill_date"), + } + ) + + updated += 1 + log.info(f"Updated shipping bill for {inv.name}") + + except Exception: + frappe.log_error( + frappe.get_traceback(), + f"Export invoice update failed for {inv.name}" + ) + + if updated and updated % BATCH_SIZE == 0: + frappe.db.commit() + + frappe.db.commit() + + log.info(f"Total Invoices Updated = {updated}") + log.info(f"Total Time Taken = {int(time.time() - start_time)} seconds") diff --git a/rohit_common/rohit_common/scheduled_tasks/auto_update_gstin_status.py b/rohit_common/rohit_common/scheduled_tasks/auto_update_gstin_status.py index 6a4e327..134c8fb 100644 --- a/rohit_common/rohit_common/scheduled_tasks/auto_update_gstin_status.py +++ b/rohit_common/rohit_common/scheduled_tasks/auto_update_gstin_status.py @@ -6,57 +6,73 @@ import frappe import time from datetime import date -from frappe.utils import flt, getdate +from frappe.utils import flt from frappe.utils.background_jobs import enqueue from ..validations.address import validate_gstin_from_portal +BATCH_SIZE = 50 + + def enqueue_gstin_update(): enqueue(execute, queue="long", timeout=7200) def execute(): - st_time = time.time() - validate = 0 - auto_days = flt(frappe.get_value("Rohit Settings", "Rohit Settings", "auto_validate_gstin_after")) - query = """SELECT name, validated_gstin, disabled, - IFNULL(gst_validation_date, '1900-01-01') as gst_validation_date, gstin, gst_status - FROM `tabAddress` - WHERE gstin IS NOT NULL AND gstin != "NA" AND disabled=0 AND country = 'India' - AND (validated_gstin IS NULL OR DATE_ADD(IFNULL(gst_validation_date, '1900-01-01'), INTERVAL %s DAY) < CURDATE()) - ORDER BY gstin, name""" % auto_days - - add_list = frappe.db.sql(query, as_dict=1) - - for add in add_list: - print(f"Checking Address with GSTIN {add.gstin} with Validation Date {add.gst_validation_date}") - changes_made = 0 - if add.gst_validation_date: - if add.validated_gstin: - days_since_validation = (date.today() - getdate(add.gst_validation_date)).days - else: - days_since_validation = (date.today() - getdate('1900-01-01')).days - if days_since_validation > auto_days: - # Now Validate the GSTIN - add_doc = frappe.get_doc("Address", add.name) - validate_gstin_from_portal(add_doc) - changes_made = 1 - validate += 1 - else: - changes_made = 1 - add_doc = frappe.get_doc("Address", add.name) - validate_gstin_from_portal(add_doc) - validate += 1 - if changes_made == 1: - try: - add_doc.flags.ignore_mandatory = True - add_doc.save() - print(f"{add_doc.name} Saved") - except Exception as e: - print(f"{e}") - if validate % 50 == 0 and validate > 0: - print(f"Committing Changes after {validate} Changes. Time Elapsed = {int(time.time() - st_time)} seconds") - time.sleep(2) + start_time = time.time() + validated_count = 0 + + auto_days = flt( + frappe.db.get_single_value("Rohit Settings", "auto_validate_gstin_after") + ) + + addresses = frappe.db.sql( + """ + SELECT name, gstin + FROM `tabAddress` + WHERE gstin IS NOT NULL + AND gstin != 'NA' + AND disabled = 0 + AND country = 'India' + AND ( + validated_gstin IS NULL + OR DATE_ADD(IFNULL(gst_validation_date,'1900-01-01'), INTERVAL %s DAY) < CURDATE() + ) + ORDER BY gstin, name + """, + auto_days, + as_dict=True, + ) + + for i, row in enumerate(addresses, start=1): + print(f"Checking Address {row.name} with GSTIN {row.gstin}") + + try: + doc = frappe.get_doc("Address", row.name) + + validate_gstin_from_portal(doc, auto_days) + + doc.flags.ignore_mandatory = True + doc.save() + + validated_count += 1 + print(f"{doc.name} Saved") + + except Exception: + frappe.log_error( + frappe.get_traceback(), + f"GSTIN Validation Failed for {row.name}", + ) + + if validated_count and validated_count % BATCH_SIZE == 0: + print( + f"Committing after {validated_count} validations " + f"(Elapsed {int(time.time() - start_time)}s)" + ) frappe.db.commit() - print(f"Total GSTIN validated from GSTIN Website {validate}") - print(f"Total Time Taken = {int(time.time() - st_time)} seconds") + time.sleep(2) + + frappe.db.commit() + + print(f"Total GSTIN validated: {validated_count}") + print(f"Total Time Taken: {int(time.time() - start_time)} seconds") \ No newline at end of file diff --git a/rohit_common/rohit_common/scheduled_tasks/delete_unneeded_files.py b/rohit_common/rohit_common/scheduled_tasks/delete_unneeded_files.py index a92f815..3666360 100644 --- a/rohit_common/rohit_common/scheduled_tasks/delete_unneeded_files.py +++ b/rohit_common/rohit_common/scheduled_tasks/delete_unneeded_files.py @@ -8,195 +8,362 @@ from __future__ import unicode_literals import time import frappe -from frappe.utils import flt +from frappe.utils import flt,add_days from frappe.utils.fixtures import sync_fixtures from ...utils.rohit_common_utils import rebuild_tree from rohit_common.core.file import check_file_availability, delete_file_dt, check_and_move_file, correct_file_name_url sync_fixtures() - def execute(): - st_time = time.time() - # Check and delete files without File Name and File URL - print("Deleting Files without File Name and File URL") - delete_files = frappe.db.sql("""SELECT name FROM `tabFile` WHERE file_name IS NULL - AND file_url IS NULL""", as_dict=1) - for files in delete_files: - fd = frappe.get_doc("File", files.name) + log = frappe.logger("file_cleanup") + + BATCH_SIZE = 500 + start = time.time() + + # ------------------------------------------------ + # 1 Delete invalid files (no name + no url) + # ------------------------------------------------ + + rows = frappe.db.sql( + """ + SELECT name + FROM `tabFile` + WHERE file_name IS NULL + AND file_url IS NULL + """, + as_dict=True, + ) + + log.info(f"Deleting {len(rows)} files without name/url") + + for i, r in enumerate(rows, 1): + + fd = frappe.get_doc("File", r.name) delete_file_dt(fd) - print(f"Total Files Deleted due to no File Name and File URL {len(delete_files)}") - print("Converting the Incorrect File Names and File URL for Files") - incorrect_file_name = frappe.db.sql("""SELECT name FROM `tabFile` WHERE file_name IS NULL - AND is_folder=0""", as_dict=1) - for file in incorrect_file_name: - fd = frappe.get_doc("File", file.name) + + if i % BATCH_SIZE == 0: + frappe.db.commit() + + frappe.db.commit() + + # ------------------------------------------------ + # 2 Fix missing file_name + # ------------------------------------------------ + + rows = frappe.db.sql( + """ + SELECT name + FROM `tabFile` + WHERE file_name IS NULL + AND is_folder = 0 + """, + as_dict=True, + ) + + log.info(f"Fixing {len(rows)} files missing file_name") + + for r in rows: + fd = frappe.get_doc("File", r.name) correct_file_name_url(fd) - print(f"Total Files Corrected with File Names {len(incorrect_file_name)}") - null_file_url = frappe.db.sql("""SELECT name FROM `tabFile` WHERE file_url IS NULL - AND is_folder=0""", as_dict=1) - for file in null_file_url: - fd = frappe.get_doc("File", file.name) + + frappe.db.commit() + + # ------------------------------------------------ + # 3 Fix missing file_url + # ------------------------------------------------ + + rows = frappe.db.sql( + """ + SELECT name + FROM `tabFile` + WHERE file_url IS NULL + AND is_folder = 0 + """, + as_dict=True, + ) + + log.info(f"Fixing {len(rows)} files missing file_url") + + for r in rows: + fd = frappe.get_doc("File", r.name) correct_file_name_url(fd) + frappe.db.commit() - print(f"Total Files Corrected with NULL File URL {len(null_file_url)}") - print(f"Checking the Files with http URL and Trying to Correct it") - http_file_url = frappe.db.sql("""SELECT name FROM `tabFile` WHERE file_url LIKE 'http%' - AND is_folder=0""", as_dict=1) - for file in http_file_url: - fd = frappe.get_doc("File", file.name) + + # ------------------------------------------------ + # 4 Fix http URLs + # ------------------------------------------------ + + rows = frappe.db.sql( + """ + SELECT name + FROM `tabFile` + WHERE is_folder = 0 + AND (file_url LIKE 'http://%' OR file_url LIKE 'https://%') + """, + as_dict=True, + ) + + log.info(f"Fixing {len(rows)} http URL files") + + for r in rows: + fd = frappe.get_doc("File", r.name) correct_file_name_url(fd) - print(f"Total Files Corrected with http in File URL {len(http_file_url)}") + frappe.db.commit() - print("Checking for Archive Folders and Making All Files Under them Archive Files") - time.sleep(2) - archived = 0 - arch_folders = frappe.db.sql("""SELECT name, lft, rgt FROM `tabFile` WHERE is_folder=1 - AND important_document_for_archive=1 AND is_home_folder=0 AND is_attachments_folder=0""", as_dict=1) - for folder in arch_folders: - print(f"{folder.name} is a Archive Folder and Hence All files and Folders Under it Would be Archived") - files = frappe.db.sql("""SELECT name, file_name FROM `tabFile` WHERE rgt <= %s - AND lft >= %s AND important_document_for_archive = 0""" % (folder.rgt, folder.lft), as_dict=1) - for file in files: - print(f"{file.name} with File Name={file.file_name} is being made Archive File") - fd = frappe.get_doc("File", file.name) - fd.important_document_for_archive = 1 - fd.save() + + # ------------------------------------------------ + # 5 Archive folders + # ------------------------------------------------ + + folders = frappe.db.sql( + """ + SELECT name, lft, rgt + FROM `tabFile` + WHERE is_folder = 1 + AND important_document_for_archive = 1 + AND is_home_folder = 0 + AND is_attachments_folder = 0 + """, + as_dict=True, + ) + + for folder in folders: + + log.info(f"Archiving subtree under folder {folder.name}") + + files = frappe.db.sql( + """ + SELECT name + FROM `tabFile` + WHERE rgt <= %s + AND lft >= %s + AND important_document_for_archive = 0 + """, + (folder.rgt, folder.lft), + as_dict=True, + ) + + for f in files: + frappe.db.set_value( + "File", + f.name, + "important_document_for_archive", + 1, + ) + frappe.db.commit() - print("Checking for Files Marked to Delete") - time.sleep(1) - marked = 0 - files_marked_to_delete = frappe.db.sql("""SELECT name, file_name, file_url, attached_to_doctype, attached_to_name - FROM `tabFile` WHERE mark_for_deletion = 1""", as_dict=1) - for file in files_marked_to_delete: - marked += 1 - fd = frappe.get_doc("File", file.name) - comment = f"Removed {file.name} as it was Marked for Deletion" - delete_file_dt(fd, comment=comment) - if marked % 500 == 0 and marked > 0: + + # ------------------------------------------------ + # 6 Delete files marked for deletion + # ------------------------------------------------ + + rows = frappe.db.sql( + """ + SELECT name + FROM `tabFile` + WHERE mark_for_deletion = 1 + """, + as_dict=True, + ) + + log.info(f"Deleting {len(rows)} files marked for deletion") + + for i, r in enumerate(rows, 1): + + fd = frappe.get_doc("File", r.name) + + delete_file_dt( + fd, + comment=f"Removed {r.name} as it was marked for deletion", + ) + + if i % BATCH_SIZE == 0: frappe.db.commit() - print(f"Committing Changes after {marked} files Marked for Delete Deleted.") + frappe.db.commit() - mark_time = int(time.time() - st_time) - - # Now check the Doctypes in Settings for Auto Deletion Rule - print("Checking for Auto Deletion of Files") - time.sleep(1) - ro_set = frappe.get_single("Rohit Settings") - tot_auto_delete = 0 - auto_delete = 0 - for row in ro_set.auto_deletion_policy_for_files: - dt_conds = "" + + # ------------------------------------------------ + # 7 Auto deletion policy + # ------------------------------------------------ + + settings = frappe.get_single("Rohit Settings") + + # Cache allowed public doctypes + allowed_public = {d.document_type for d in settings.docs_with_pub_att} + + total_auto_deleted = 0 + + for row in settings.auto_deletion_policy_for_files: + + cutoff = add_days(frappe.utils.nowdate(), -int(row.days_to_keep)) + + query = f""" + SELECT fd.name + FROM `tabFile` fd + JOIN `tab{row.document_type}` dt + ON dt.name = fd.attached_to_name + WHERE fd.attached_to_doctype = %s + AND fd.creation <= %s + """ + if row.doctype_conditions: - dt_conds = " AND %s" % row.doctype_conditions - query = """SELECT fd.name FROM `tabFile` fd, `tab%s` dt WHERE fd.attached_to_doctype = '%s' AND - fd.creation <= DATE_SUB(NOW(), INTERVAL %s DAY) AND dt.name = fd.attached_to_name %s""" \ - % (row.document_type, row.document_type, row.days_to_keep, dt_conds) - files = frappe.db.sql(query, as_dict=1) - tot_auto_delete += len(files) - for file in files: - auto_delete += 1 - fd = frappe.get_doc("File", file.name) - doc = frappe.get_doc(row.document_type, fd.attached_to_name) - comment = f"Removed {file.name} Due to Deletion Policy to Delete After {row.days_to_keep} Days" - delete_file_dt(fd, comment=comment) - if auto_delete % 500 == 0 and auto_delete > 0: + query += f" AND {row.doctype_conditions}" + + rows = frappe.db.sql( + query, + (row.document_type, cutoff), + as_dict=True, + ) + + for i, r in enumerate(rows, 1): + + fd = frappe.get_doc("File", r.name) + + delete_file_dt( + fd, + comment=f"Removed {r.name} due to deletion policy ({row.days_to_keep} days)", + ) + + total_auto_deleted += 1 + + if i % BATCH_SIZE == 0: frappe.db.commit() - print(f"Committing Changes after {auto_delete} files Deleted. Total Time Elapsed " - f"{int(time.time() - st_time)} seconds") + frappe.db.commit() - del_time = int(time.time() - st_time) - # Lastly Check all files in DB which are not Marked as Available on Server and Delete those files - # Also note that if File is Public It would need to be converted into Private if Available and If attached to - # Doctype where Public Files are not allowed - print("Check for File Availability and Updating the Same") + # ------------------------------------------------ + # 8 File availability validation + # ------------------------------------------------ + + rows = frappe.db.sql( + """ + SELECT name, attached_to_doctype, attached_to_name + FROM `tabFile` + WHERE file_available_on_server = 0 + AND is_folder = 0 + """, + as_dict=True, + ) + + log.info(f"Checking availability of {len(rows)} files") + avail_count = 0 - non_validated_files = frappe.db.sql("""SELECT name FROM `tabFile` WHERE file_available_on_server = 0 - AND is_folder=0""", as_dict=1) - print(f"Total Non Available Files = {len(non_validated_files)}") - time.sleep(1) - non_avail_files = 0 - non_avail_dt = 0 - for file in non_validated_files: - avail_count += 1 - dont_save = 0 - # print(f"Checking {file.name}") - fd = frappe.get_doc("File", file.name) - file_available = check_file_availability(fd) - if file_available == 1: - pub_allowed = 0 - # File is available and now check if its public and attached to DT where Public Files are not allowed - # Then change the file to private and also mark as available - if fd.is_private != 1: - if fd.attached_to_doctype: - for d in ro_set.docs_with_pub_att: - if d.document_type == fd.attached_to_doctype: - pub_allowed = 1 - break - if pub_allowed != 1: - fd.file_available_on_server = 1 - fd.is_private = 1 - if fd.attached_to_name: - if not frappe.db.exists(fd.attached_to_doctype, fd.attached_to_name): - non_avail_dt += 1 - dont_save = 1 - delete_file_dt(fd, ref_doc_exists=0) - print(f"Deleting {fd.name} since Attached to Non-Existent Document") - else: - fd.file_available_on_server = 1 - if dont_save != 1: - fd.save() - elif file_available == 2: + invalid_attachment = 0 + + for i, r in enumerate(rows, 1): + + fd = frappe.get_doc("File", r.name) + + status = check_file_availability(fd) + + if status == 1: + + # Remove files attached to non-existent docs + if r.attached_to_name and not frappe.db.exists( + r.attached_to_doctype, + r.attached_to_name, + ): + invalid_attachment += 1 + delete_file_dt(fd, ref_doc_exists=0) + continue + + # Enforce privacy rules + if fd.is_private != 1 and fd.attached_to_doctype: + if fd.attached_to_doctype not in allowed_public: + fd.is_private = 1 + + fd.file_available_on_server = 1 + fd.save() + + elif status == 2: + check_and_move_file(fd) + else: - file_exists = 0 - if fd.attached_to_doctype: - if not frappe.db.exists(fd.attached_to_doctype, fd.attached_to_name): - file_exists = 0 - else: - file_exists = 1 - comment = f"File Removed Since Not Available on Server" - delete_file_dt(fd, comment=comment, ref_doc_exists=file_exists) - if avail_count % 500 == 0 and avail_count > 0: + + delete_file_dt( + fd, + comment="File removed since not available on server", + ) + + avail_count += 1 + + if i % BATCH_SIZE == 0: frappe.db.commit() - print(f"Committing Changes after {avail_count} files made available Time Elapsed " - f"{int(time.time() - st_time)} seconds") - avail_time = int(time.time() - st_time) - - tot_time = int(time.time() - st_time) - print(f"Total Marked Files Deleted = {len(files_marked_to_delete)}") - print(f"Total Time Taken for Marked Files Deletion = {mark_time} seconds") - print(f"Total Auto Files Deleted = {tot_auto_delete}") - print(f"Total Time Taken for Auto Deletion of Files {del_time - mark_time} seconds") - print(f"Total No of Files Made Available = {avail_count}") - print(f"Total No of Files Attached to Unavailable Documents = {non_avail_dt}") - print(f"Total No of Files Not Available on Server = {non_avail_files}") - print(f"Total Time Take for Making Files Available = {avail_time - mark_time} seconds") - print(f"Total Time Taken {tot_time} seconds") + + frappe.db.commit() + + runtime = int(time.time() - start) + + log.info(f"Files validated: {avail_count}") + log.info(f"Invalid attachments removed: {invalid_attachment}") + log.info(f"Auto deleted files: {total_auto_deleted}") + log.info(f"Cleanup finished in {runtime}s") def check_correct_folders(): - st_time = time.time() + log = frappe.logger("file_cleanup") + start = time.time() + rebuild_tree(doctype="File", parent_field="folder", group_field="is_folder") frappe.db.commit() - tr_time = time.time() - folders = frappe.db.sql("""SELECT name, folder, file_size, lft, rgt, important_document_for_archive - FROM `tabFile` WHERE is_folder=1 ORDER BY lft DESC, rgt DESC""", as_dict=1) + + rebuild_time = time.time() + + folders = frappe.db.sql(""" + SELECT name, folder, file_size, important_document_for_archive + FROM `tabFile` + WHERE is_folder = 1 + """, as_dict=True) + + # fetch folder sizes in one query + folder_sizes = frappe.db.sql(""" + SELECT folder, SUM(file_size) AS size + FROM `tabFile` + WHERE folder IS NOT NULL + GROUP BY folder + """, as_dict=True) + + size_map = {f.folder: f.size for f in folder_sizes} + + # fetch parent flags once + parent_flags = frappe.db.sql(""" + SELECT name, important_document_for_archive + FROM `tabFile` + WHERE is_folder = 1 + """, as_dict=True) + + parent_map = {p.name: p.important_document_for_archive for p in parent_flags} + for fd in folders: + + fd_size = size_map.get(fd.name, 0) + + # inherit archive flag if fd.folder: - pfd = frappe.get_doc("File", fd.folder) - if pfd.important_document_for_archive == 1: - if fd.important_document_for_archive != 1: - frappe.db.set_value("File", fd.name, "important_document_for_archive", pfd.important_document_for_archive) - fd_file_size = frappe.db.sql("""SELECT DISTINCT file_name, file_size, folder - FROM `tabFile` WHERE folder = '%s'""" % fd.name, as_dict=1) - fd_size = 0 - if fd_file_size: - for fl in fd_file_size: - fd_size += fl.file_size + parent_flag = parent_map.get(fd.folder) + + if parent_flag == 1 and fd.important_document_for_archive != 1: + frappe.db.set_value( + "File", + fd.name, + "important_document_for_archive", + 1 + ) + if fd_size != fd.file_size: - frappe.db.set_value("File", fd.name, "file_size", fd_size) - print(f"Updating Folder: {fd.name} with Actual File Size = {fd_file_size[0].size} old size {fd.file_size}") - print(f"Time Taken for Tree Rebuild = {int(tr_time - st_time)} seconds") - print(f"Total Time Taken For Tree Build and File Size Checking = {int(time.time() - st_time)} seconds") + frappe.db.set_value( + "File", + fd.name, + "file_size", + fd_size + ) + + log.info( + f"Updating Folder {fd.name} size {fd.file_size} → {fd_size}" + ) + + log.info(f"Tree rebuild time = {int(rebuild_time - start)}s") + log.info(f"Total runtime = {int(time.time() - start)}s") diff --git a/rohit_common/rohit_common/validations/address.py b/rohit_common/rohit_common/validations/address.py index 4eef055..366ddc7 100644 --- a/rohit_common/rohit_common/validations/address.py +++ b/rohit_common/rohit_common/validations/address.py @@ -325,12 +325,14 @@ def update_fields_from_gmaps(doc, address_dict): remove_google_updates(doc) -def validate_gstin_from_portal(doc): +def validate_gstin_from_portal(doc,auto_days=None): """ Validates GSTIN using India Compliance Public API """ - auto_days = flt(frappe.get_value("Rohit Settings", "Rohit Settings", - "auto_validate_gstin_after")) + if auto_days is None: + auto_days = flt( + frappe.db.get_single_value("Rohit Settings", "auto_validate_gstin_after") + ) if doc.gst_validation_date: days_since_validation = (date.today() - getdate(doc.gst_validation_date)).days else: diff --git a/rohit_common/utils/background_doc_processing.py b/rohit_common/utils/background_doc_processing.py index 6aba633..bdb831a 100644 --- a/rohit_common/utils/background_doc_processing.py +++ b/rohit_common/utils/background_doc_processing.py @@ -2,58 +2,71 @@ # Copyright (c) 2022, Rohit Industries Ltd. and contributors # For license information, please see license.txt -from __future__ import unicode_literals -import frappe import time +import frappe from frappe.utils.background_jobs import enqueue +BATCH_SIZE = 20 + + def enqueue_bg(): enqueue(process_bg_docs, queue="long", timeout=2700) def get_bg_docs(): - """ - Returns a list of document types which are enabled for Background processing - The document type should also have a checkbox with name background_processing - """ - doc_lst = [] rset = frappe.get_doc("Rohit Settings", "Rohit Settings") - for dtd in rset.bg_submit_cancel_docs: - doc_lst.append(dtd.document_type) - return doc_lst + return [d.document_type for d in rset.bg_submit_cancel_docs] def process_bg_docs(): - """ - Processes the background jobs for Document Types - """ - st_time = time.time() - dt_lst = get_bg_docs() - tot_docs = 0 - if dt_lst: - for dtd in dt_lst: - print(f"Processing Background Submit or Cancel for {dtd}") - docs_marked = frappe.db.sql(f"""SELECT name, background_processing, docstatus - FROM `tab{dtd}` WHERE background_processing = 1 AND (docstatus = 0 - OR docstatus = 1)""", as_dict=1) - if docs_marked: - for mkd_dt in docs_marked: - mkd_doc = frappe.get_doc(dtd, mkd_dt.name) - if mkd_dt.docstatus == 0: - tot_docs += 1 - print(f"Submitting {mkd_doc.name}") - mkd_doc.background_processing = 0 - mkd_doc.save() - mkd_doc.submit() - frappe.db.commit() - elif mkd_dt.docstatus == 1: - tot_docs += 1 - print(f"Cancelling {mkd_doc.name}") - mkd_doc.background_processing = 0 - mkd_doc.save() - mkd_doc.cancel() - frappe.db.commit() - else: - print(f"No Docs in {dtd}") - print(f"Total Time Taken = {int(time.time() - st_time)} seconds Docs Processed = {tot_docs}") + log = frappe.logger("bg_processing") + + start = time.time() + total = 0 + + doctypes = get_bg_docs() + + for dt in doctypes: + + log.info(f"Processing background docs for {dt}") + + docs = frappe.db.sql(f""" + SELECT name, docstatus + FROM `tab{dt}` + WHERE background_processing = 1 + AND docstatus IN (0,1) + """, as_dict=True) + + for row in docs: + + try: + + doc = frappe.get_doc(dt, row.name) + + doc.background_processing = 0 + + if row.docstatus == 0: + log.info(f"Submitting {doc.name}") + doc.submit() + + elif row.docstatus == 1: + log.info(f"Cancelling {doc.name}") + doc.cancel() + + total += 1 + + except Exception: + frappe.log_error( + frappe.get_traceback(), + f"Background processing failed for {dt} {row.name}" + ) + + if total % BATCH_SIZE == 0: + frappe.db.commit() + + frappe.db.commit() + + log.info( + f"Background processing completed in {int(time.time() - start)}s | Docs processed {total}" + ) \ No newline at end of file diff --git a/rohit_common/utils/rohit_common_utils.py b/rohit_common/utils/rohit_common_utils.py index e9067cb..bd20adf 100644 --- a/rohit_common/utils/rohit_common_utils.py +++ b/rohit_common/utils/rohit_common_utils.py @@ -158,19 +158,48 @@ def check_system_manager(user): def rebuild_tree(doctype, parent_field, group_field): - # call rebuild_node for all root nodes - # get all roots + lft = 1 - result = frappe.db.sql("SELECT name, %s, lft, rgt FROM `tab%s` WHERE `%s`='' or `%s` IS NULL " - "ORDER BY name ASC" % (group_field, doctype, parent_field, parent_field), as_dict=1) - for r in result: + + roots = frappe.db.sql( + f""" + SELECT name, `{group_field}` + FROM `tab{doctype}` + WHERE `{parent_field}` = '' OR `{parent_field}` IS NULL + ORDER BY name + """, + as_dict=True + ) + + frappe.db.auto_commit_on_many_writes = 1 + + for r in roots: + if r.get(group_field) == 1: - rebuild_group(doctype, parent_field, r.name, group_field, lft) + + lft = rebuild_group( + doctype, + parent_field, + r.name, + group_field, + lft + ) + else: - frappe.db.sql("""UPDATE `tab%s` SET lft=%s, rgt=%s WHERE name='%s'""" % ( - doctype, lft, lft+1, r.name)) + + frappe.db.sql( + f""" + UPDATE `tab{doctype}` + SET lft=%s, rgt=%s + WHERE name=%s + """, + (lft, lft + 1, r.name), + ) + lft += 2 + frappe.db.auto_commit_on_many_writes = 0 + def rebuild_group(doctype, parent_field, parent, group_field, left): right = left + 1 From bfcaa49437aaf42c591d5f0c1044d83aaa411bb3 Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Thu, 19 Mar 2026 13:36:08 +0530 Subject: [PATCH 50/52] fix: initial migration guide (#28) * fix: initial migration guide * fix: updated script --- rohit_common/patches/run_unwanted_patches.py | 18 ++ rohit_common/scripts/initial_migration.md | 24 ++ rohit_common/scripts/pre_migrate_fix.sql | 283 +++++++++++++++++++ 3 files changed, 325 insertions(+) create mode 100644 rohit_common/scripts/initial_migration.md create mode 100644 rohit_common/scripts/pre_migrate_fix.sql diff --git a/rohit_common/patches/run_unwanted_patches.py b/rohit_common/patches/run_unwanted_patches.py index 55fe417..1733ecc 100644 --- a/rohit_common/patches/run_unwanted_patches.py +++ b/rohit_common/patches/run_unwanted_patches.py @@ -8,6 +8,8 @@ def run_unwanted_patches(): update_icons_in_customized_desk_pages() rename_desk_page_to_workspace() setup_likes_from_feedback() + # skip_notification_channel_patch() + # skip_update_reports_with_range() #erpnext update_is_cancelled_field() @@ -117,3 +119,19 @@ def execute_rename_tds_report(): 'patch': 'execute:frappe.rename_doc("Report", "TDS Payable Monthly", "Tax Withholding Details", force=True)', }).insert(ignore_permissions=True) frappe.db.commit() +# def skip_notification_channel_patch(): +# if not frappe.db.exists("Patch Log", {"patch": "frappe.patches.v13_0.update_notification_channel_if_empty"}): +# frappe.get_doc({ +# "doctype": "Patch Log", +# "patch": "frappe.patches.v13_0.update_notification_channel_if_empty", +# }).insert(ignore_permissions=True) +# frappe.db.commit() + + +# def skip_update_reports_with_range(): +# if not frappe.db.exists("Patch Log", {"patch": "erpnext.patches.v14_0.update_reports_with_range"}): +# frappe.get_doc({ +# "doctype": "Patch Log", +# "patch": "erpnext.patches.v14_0.update_reports_with_range", +# }).insert(ignore_permissions=True) +# frappe.db.commit() \ No newline at end of file diff --git a/rohit_common/scripts/initial_migration.md b/rohit_common/scripts/initial_migration.md new file mode 100644 index 0000000..9ba6159 --- /dev/null +++ b/rohit_common/scripts/initial_migration.md @@ -0,0 +1,24 @@ +# ERPNext Migration (v12 → v16) + +## 1. Apps + +```json +{ + "frappe": "v16.0.0-beta.2", + "erpnext": "v16.0.0-beta.2", + "rohit_common": "fix--for-version-15", + "india_compliance": "16.2.0" +} +``` + +## 2. Restore Backup + +```bench --site testing.localhost restore ./RIGPL_BACK/backup.sql.gz --force``` + +## 3. Run Pre-Migrate Fix + +```bench --site testing.localhost mariadb < apps/rohit_common/rohit_common/scripts/pre_migrate_fix.sql``` + +## 4. Migrate + +```bench --site testing.localhost migrate --skip-failing``` \ No newline at end of file diff --git a/rohit_common/scripts/pre_migrate_fix.sql b/rohit_common/scripts/pre_migrate_fix.sql new file mode 100644 index 0000000..e8de4a4 --- /dev/null +++ b/rohit_common/scripts/pre_migrate_fix.sql @@ -0,0 +1,283 @@ +-- ========================================= +-- PRE-MIGRATE FIX SCRIPT (ERPNext v16) +-- Safe to rerun +-- ========================================= + +SET SQL_SAFE_UPDATES = 0; + +DROP PROCEDURE IF EXISTS add_col_if_missing; +DROP PROCEDURE IF EXISTS modify_col_if_exists; +DROP PROCEDURE IF EXISTS set_zero_if_exists; +DROP PROCEDURE IF EXISTS skip_patch_if_missing; +DROP PROCEDURE IF EXISTS set_workspace_type_if_needed; +DROP PROCEDURE IF EXISTS trim_po_no_if_needed; + +DELIMITER // + +CREATE PROCEDURE add_col_if_missing( + IN tbl_name VARCHAR(128), + IN col_name VARCHAR(128), + IN col_def TEXT +) +BEGIN + IF NOT EXISTS ( + SELECT 1 + FROM information_schema.columns + WHERE table_schema = DATABASE() + AND table_name = tbl_name + AND column_name = col_name + ) THEN + SET @sql = CONCAT( + 'ALTER TABLE `', tbl_name, '` ADD COLUMN `', col_name, '` ', col_def + ); + PREPARE stmt FROM @sql; + EXECUTE stmt; + DEALLOCATE PREPARE stmt; + END IF; +END// + +CREATE PROCEDURE modify_col_if_exists( + IN tbl_name VARCHAR(128), + IN col_name VARCHAR(128), + IN col_def TEXT +) +BEGIN + IF EXISTS ( + SELECT 1 + FROM information_schema.columns + WHERE table_schema = DATABASE() + AND table_name = tbl_name + AND column_name = col_name + ) THEN + SET @sql = CONCAT( + 'ALTER TABLE `', tbl_name, '` MODIFY `', col_name, '` ', col_def + ); + PREPARE stmt FROM @sql; + EXECUTE stmt; + DEALLOCATE PREPARE stmt; + END IF; +END// + +CREATE PROCEDURE set_zero_if_exists( + IN tbl_name VARCHAR(128), + IN col_name VARCHAR(128) +) +BEGIN + IF EXISTS ( + SELECT 1 + FROM information_schema.columns + WHERE table_schema = DATABASE() + AND table_name = tbl_name + AND column_name = col_name + ) THEN + SET @sql = CONCAT( + 'UPDATE `', tbl_name, '` ', + 'SET `', col_name, '` = 0 ', + 'WHERE `', col_name, '` IS NULL ', + 'OR CAST(`', col_name, '` AS CHAR) IN (''No'', '''')' + ); + PREPARE stmt FROM @sql; + EXECUTE stmt; + DEALLOCATE PREPARE stmt; + END IF; +END// + +CREATE PROCEDURE skip_patch_if_missing( + IN patch_name TEXT +) +BEGIN + IF NOT EXISTS ( + SELECT 1 + FROM `tabPatch Log` + WHERE patch = patch_name + ) THEN + INSERT INTO `tabPatch Log` (`name`, `patch`) + VALUES (UUID(), patch_name); + END IF; +END// + +CREATE PROCEDURE set_workspace_type_if_needed() +BEGIN + IF EXISTS ( + SELECT 1 + FROM information_schema.columns + WHERE table_schema = DATABASE() + AND table_name = 'tabWorkspace' + AND column_name = 'type' + ) THEN + UPDATE `tabWorkspace` + SET `type` = 'Workspace' + WHERE `name` = 'Rohit Common' + AND (`type` IS NULL OR `type` = ''); + END IF; +END// + +CREATE PROCEDURE trim_po_no_if_needed() +BEGIN + IF EXISTS ( + SELECT 1 + FROM information_schema.columns + WHERE table_schema = DATABASE() + AND table_name = 'tabSales Invoice' + AND column_name = 'po_no' + ) THEN + IF NOT EXISTS ( + SELECT 1 + FROM information_schema.columns + WHERE table_schema = DATABASE() + AND table_name = 'tabSales Invoice' + AND column_name = 'po_no_backup' + ) THEN + SET @sql = 'ALTER TABLE `tabSales Invoice` ADD COLUMN `po_no_backup` LONGTEXT'; + PREPARE stmt FROM @sql; + EXECUTE stmt; + DEALLOCATE PREPARE stmt; + END IF; + + UPDATE `tabSales Invoice` + SET `po_no_backup` = `po_no` + WHERE CHAR_LENGTH(`po_no`) > 188 + AND (`po_no_backup` IS NULL OR `po_no_backup` = ''); + + UPDATE `tabSales Invoice` + SET `po_no` = LEFT(`po_no`, 188) + WHERE CHAR_LENGTH(`po_no`) > 188; + END IF; +END// + +DELIMITER ; + +-- ========================================= +-- 1. CORE SCHEMA FIXES +-- ========================================= + +CALL add_col_if_missing('tabDocField', 'is_virtual', 'INT(1) NOT NULL DEFAULT 0'); + +CALL modify_col_if_exists('tabPatch Log', 'patch', 'VARCHAR(255)'); +CALL add_col_if_missing('tabPatch Log', 'migration_hash', 'VARCHAR(140)'); +CALL add_col_if_missing('tabDocType', 'migration_hash', 'VARCHAR(255)'); + +-- ========================================= +-- 2. BOOLEAN DATA NORMALIZATION +-- ========================================= + +CALL set_zero_if_exists('tabPurchase Invoice', 'disable_rounded_total'); +CALL set_zero_if_exists('tabPurchase Invoice', 'is_subcontracted'); + +CALL set_zero_if_exists('tabGL Entry', 'is_cancelled'); +CALL set_zero_if_exists('tabGL Entry', 'to_rename'); + +CALL set_zero_if_exists('tabPurchase Order', 'disable_rounded_total'); +CALL set_zero_if_exists('tabPurchase Order', 'group_same_items'); +CALL set_zero_if_exists('tabPurchase Order', 'background_processing'); +CALL set_zero_if_exists('tabPurchase Order', 'ignore_pricing_rule'); +CALL set_zero_if_exists('tabPurchase Order', 'is_subcontracting'); +CALL set_zero_if_exists('tabPurchase Order', 'is_subcontracted'); + +CALL set_zero_if_exists('tabStock Ledger Entry', 'is_cancelled'); +CALL set_zero_if_exists('tabStock Ledger Entry', 'to_rename'); + +CALL set_zero_if_exists('tabPurchase Receipt', 'disable_rounded_total'); +CALL set_zero_if_exists('tabPurchase Receipt', 'ignore_pricing_rule'); +CALL set_zero_if_exists('tabPurchase Receipt', 'group_same_items'); +CALL set_zero_if_exists('tabPurchase Receipt', 'set_posting_time'); +CALL set_zero_if_exists('tabPurchase Receipt', 'is_return'); +CALL set_zero_if_exists('tabPurchase Receipt', 'is_subcontracted'); + +-- ========================================= +-- 3. SALES INVOICE FIXES +-- ========================================= + +SET @has_sales_invoice := ( + SELECT COUNT(*) + FROM information_schema.tables + WHERE table_schema = DATABASE() + AND table_name = 'tabSales Invoice' +); + +-- Only run if Sales Invoice exists +SET @sql = IF(@has_sales_invoice > 0, 'ALTER TABLE `tabSales Invoice` ROW_FORMAT=DYNAMIC', 'SELECT 1'); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +CALL modify_col_if_exists('tabSales Invoice', 'customer_name', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'contact_display', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'remarks', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'base_in_words', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'in_words', 'TEXT'); + +CALL modify_col_if_exists('tabSales Invoice', 'po_no', 'LONGTEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'contact_mobile', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'contact_email', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'against_income_account', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'title', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'status', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'apply_discount_on', 'TEXT'); + +CALL modify_col_if_exists('tabSales Invoice', 'campaign', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'source', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'select_print_heading', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'mode_of_payment', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'shipping_rule', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'reason_for_issuing_document', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'invoice_type', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'export_type', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'transporters', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'transporter_name', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'driver_name', 'TEXT'); + +CALL modify_col_if_exists('tabSales Invoice', 'charge', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'in_words_export', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'shipping_location', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'ship_to', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'cancel_reason', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'delivery_note_main', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'sales_order_main', 'TEXT'); + +CALL modify_col_if_exists('tabSales Invoice', 'set_warehouse', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'scan_barcode', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'inter_company_invoice_reference', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'loyalty_program', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'auto_repeat', 'TEXT'); +CALL modify_col_if_exists('tabSales Invoice', 'subscription', 'TEXT'); + +CALL modify_col_if_exists('tabSales Invoice', 'shipping_tin_no', 'VARCHAR(50)'); +CALL modify_col_if_exists('tabSales Invoice', 'tin_no', 'VARCHAR(50)'); +CALL modify_col_if_exists('tabSales Invoice', 'excise_no', 'VARCHAR(50)'); +CALL modify_col_if_exists('tabSales Invoice', 'shipping_excise_no', 'VARCHAR(50)'); +CALL modify_col_if_exists('tabSales Invoice', 'port_code', 'VARCHAR(50)'); +CALL modify_col_if_exists('tabSales Invoice', 'ecommerce_gstin', 'VARCHAR(50)'); +CALL modify_col_if_exists('tabSales Invoice', 'shipping_bill_number', 'VARCHAR(50)'); +CALL modify_col_if_exists('tabSales Invoice', 'transporter', 'VARCHAR(80)'); +CALL modify_col_if_exists('tabSales Invoice', 'gst_transporter_id', 'VARCHAR(80)'); +CALL modify_col_if_exists('tabSales Invoice', 'vehicle_no', 'VARCHAR(80)'); + +CALL trim_po_no_if_needed(); + +-- ========================================= +-- 4. PATCH FIXES / SKIPS +-- ========================================= + +CALL add_col_if_missing('tabNewsletter', 'content_type', 'VARCHAR(50)'); + +CALL set_workspace_type_if_needed(); + +CALL add_col_if_missing('tabProcess Statement Of Accounts', 'cc_to', 'TEXT'); + +CALL add_col_if_missing('tabCompany', 'enable_perpetual_inventory_for_non_stock_items', 'INT(1) DEFAULT 0'); +CALL add_col_if_missing('tabCompany', 'service_received_but_not_billed', 'VARCHAR(255)'); + +CALL skip_patch_if_missing('frappe.patches.v13_0.update_notification_channel_if_empty'); +CALL skip_patch_if_missing('erpnext.patches.v14_0.update_reports_with_range'); + +-- ========================================= +-- 5. CLEANUP +-- ========================================= + +DROP PROCEDURE IF EXISTS add_col_if_missing; +DROP PROCEDURE IF EXISTS modify_col_if_exists; +DROP PROCEDURE IF EXISTS set_zero_if_exists; +DROP PROCEDURE IF EXISTS skip_patch_if_missing; +DROP PROCEDURE IF EXISTS set_workspace_type_if_needed; +DROP PROCEDURE IF EXISTS trim_po_no_if_needed; \ No newline at end of file From 280053b50f3857491323c9293c49e0b18f00af66 Mon Sep 17 00:00:00 2001 From: Kalelkar-Noman Date: Wed, 25 Mar 2026 15:18:14 +0530 Subject: [PATCH 51/52] refactor: reports (#29) * fix: reports * fix: rigpl GL and backend database analysis * fix: gstr2 analysis * fix: clear tax and file analysis * fix: gst offline * fix: address book and assest analysis * fix: stock ledger --- .../patches/backend_table_analysis.py | 72 +++- .../address_book_rigpl/address_book_rigpl.py | 326 ++++++++------- .../report/asset_analysis/asset_analysis.py | 257 ++++++++---- .../backend_database_analysis_rigpl.py | 79 ++-- .../clear_tax_import_format.py | 224 ++++------- .../file_attachment_analysis_rigpl.py | 87 ++-- .../gst_offline_import_format_rigpl.py | 203 +++++++--- .../gstr2_analysis_rigpl.py | 372 ++++++++++-------- .../rigpl_general_ledger.py | 99 +++-- .../rigpl_legacy_gstr1/rigpl_legacy_gstr1.py | 61 +-- .../stock_ledger_normal.py | 134 ++++--- 11 files changed, 1116 insertions(+), 798 deletions(-) diff --git a/rohit_common/patches/backend_table_analysis.py b/rohit_common/patches/backend_table_analysis.py index 2db1e6d..f7ad30c 100644 --- a/rohit_common/patches/backend_table_analysis.py +++ b/rohit_common/patches/backend_table_analysis.py @@ -226,19 +226,67 @@ def get_input_for_change(col_name, exist_len, max_len, sug_len, limit): def get_size_of_all_tables(): config = frappe.get_site_config() - query = """SELECT table_schema AS db_name, table_name AS tbl_name, - ROUND(((data_length + index_length) / 1024 / 1024), 2) AS size_mb, ROUND(((data_length) / 1024 / 1024), 2) AS dl_mb, - ROUND(((index_length) / 1024 / 1024), 2) AS ind_mb, TABLE_ROWS as tbl_rows - FROM information_schema.TABLES - WHERE TABLE_SCHEMA = '%s' - ORDER BY (data_length + index_length) DESC""" % config.db_name - data = frappe.db.sql(query, as_dict=1) - return data + query = """ + SELECT + t.table_schema AS db_name, + t.table_name AS tbl_name, + ROUND(((t.data_length + t.index_length) / 1024 / 1024), 2) AS size_mb, + ROUND((t.data_length / 1024 / 1024), 2) AS dl_mb, + ROUND((t.index_length / 1024 / 1024), 2) AS ind_mb, + t.TABLE_ROWS as tbl_rows, + COALESCE(c.col_count, 0) as no_of_cols + FROM information_schema.TABLES t + LEFT JOIN ( + SELECT table_schema, table_name, COUNT(*) as col_count + FROM INFORMATION_SCHEMA.COLUMNS + WHERE table_schema = '%s' + GROUP BY table_schema, table_name + ) c ON c.table_schema = t.table_schema AND c.table_name = t.table_name + WHERE t.TABLE_SCHEMA = '%s' + ORDER BY (t.data_length + t.index_length) DESC + """ % (config.db_name, config.db_name) + return frappe.db.sql(query, as_dict=1) def get_columns_of_all_tables(): config = frappe.get_site_config() - query = """SELECT table_schema AS db_name, table_name AS tbl_name, COUNT(*) AS no_of_cols - FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = '%s' GROUP BY tbl_name ORDER BY no_of_cols DESC;""" % config.db_name - data = frappe.db.sql(query, as_dict=1) - return data + query = """ + SELECT table_schema AS db_name, table_name AS tbl_name, COUNT(*) AS no_of_cols + FROM INFORMATION_SCHEMA.COLUMNS + WHERE table_schema = '%s' + GROUP BY tbl_name + ORDER BY no_of_cols DESC; + """ % config.db_name + return frappe.db.sql(query, as_dict=1) + + +def get_orphaned_tables(): + """ + Identifies tables in DB that don't have a corresponding DocType. + """ + all_tabs = get_size_of_all_tables() + + # Fetch all doctypes to check against + all_dts = frappe.get_all("DocType", fields=["name", "module", "issingle", "istable", "creation", "modified"]) + dt_names = {f"tab{d.name}" for d in all_dts if not d.issingle} + dt_map = {f"tab{d.name}": d for d in all_dts} + + # Core tables to ignore + core_tables = { + "__global_search", "__record_log", "tabDefaultValue", "tabDocField", + "tabDocPerm", "tabDocType", "tabDocType Action", "tabDocType State", + "tabModule Def", "tabUser", "tabSessions", "tabAuth Log", "tabSingles" + } + + orphaned = [] + for t in all_tabs: + if t.tbl_name.startswith("tab") and t.tbl_name not in dt_names and t.tbl_name not in core_tables: + t.update({ + "app": "N/A", + "module": "N/A", + "dt_name": t.tbl_name[3:], + "last_entry": "Check Manually" + }) + orphaned.append(t) + + return orphaned diff --git a/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.py b/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.py index 3fe48c5..89cdb16 100644 --- a/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.py +++ b/rohit_common/rohit_common/report/address_book_rigpl/address_book_rigpl.py @@ -10,8 +10,8 @@ def execute(filters=None): - conditions, tbl_join, fd_add = get_conditions(filters) - data = get_entries(filters, conditions, tbl_join, fd_add) + conditions, tbl_join, fd_add, params = get_conditions(filters) + data = get_entries(filters, conditions, tbl_join, fd_add, params) columns, data = get_columns(filters, data) return columns, data @@ -21,169 +21,170 @@ def get_columns(filters, data): new_data = [] if filters.get("type") == "Address": col_map = [ - {"fieldname": "name", "label": f"{filters.get('type')} Link", "fieldtype":"Link", - "options":f"{filters.get('type')}", "width": 100}, - {"fieldname": "address_type", "label": "Address Type", "fieldtype":"", "options":""}, - {"fieldname": "address_title", "label": "Address Title", "fieldtype":"", "options":""}, - {"fieldname": "address_line1", "label": "Address Line1", "fieldtype":"", "options":""}, - {"fieldname": "address_line2", "label": "Address Line2", "fieldtype":"", "options":""}, - {"fieldname": "city", "label": "City", "fieldtype":"", "options":""}, - {"fieldname": "state", "label": "State", "fieldtype":"", "option":""}, - {"fieldname": "country", "label": "Country", "fieldtype":"Link", "options":"Country"}, - {"fieldname": "airport", "label": "Airport", "fieldtype":"", "options":""}, - {"fieldname": "sea_port", "label": "Sea Port", "fieldtype":"", "options":""}, - {"fieldname": "email_id", "label": "Email", "fieldtype":"", "options":""}, - {"fieldname": "phone", "label": "Phone", "fieldtype":"", "option":""}, - {"fieldname": "fax", "label": "Fax", "fieldtype":"", "options":""}, - {"fieldname": "gstin", "label": "GSTIN", "fieldtype":"", "options":""}, - {"fieldname": "gst_status", "label": "GST Status", "fieldtype":"", "options":""}, - {"fieldname": "gst_validation_date", "label": "Validation Date", "fieldtype":"Date", - "options":"", "width": 80}, - {"fieldname": "global_google_code", "label": "Google Code", "fieldtype":"", "options":""}, - {"fieldname": "disabled", "label": "Disabled", "fieldtype":"Int", "options":"", - "width": 20}, - {"fieldname": "link_doctype", "label": "Master Type", "fieldtype":"", "options":""}, - {"fieldname": "link_name", "label": "Master Name", "fieldtype":"Dynamic Link", - "options":"link_doctype"} + {"fieldname": "name", "label": "Address Link", "fieldtype":"Link", "options":"Address", "width": 120}, + {"fieldname": "address_type", "label": "Address Type", "fieldtype":"Data", "width": 100}, + {"fieldname": "address_title", "label": "Address Title", "fieldtype":"Data", "width": 120}, + {"fieldname": "address_line1", "label": "Address Line1", "fieldtype":"Data", "width": 150}, + {"fieldname": "address_line2", "label": "Address Line2", "fieldtype":"Data", "width": 120}, + {"fieldname": "city", "label": "City", "fieldtype":"Data", "width": 100}, + {"fieldname": "state", "label": "State", "fieldtype":"Data", "width": 100}, + {"fieldname": "country", "label": "Country", "fieldtype":"Link", "options":"Country", "width": 100}, + {"fieldname": "airport", "label": "Airport", "fieldtype":"Data", "width": 100}, + {"fieldname": "sea_port", "label": "Sea Port", "fieldtype":"Data", "width": 100}, + {"fieldname": "email_id", "label": "Email", "fieldtype":"Data", "width": 150}, + {"fieldname": "phone", "label": "Phone", "fieldtype":"Data", "width": 120}, + {"fieldname": "fax", "label": "Fax", "fieldtype":"Data", "width": 100}, + {"fieldname": "gstin", "label": "GSTIN", "fieldtype":"Data", "width": 140}, + {"fieldname": "gst_status", "label": "GST Status", "fieldtype":"Data", "width": 100}, + {"fieldname": "gst_validation_date", "label": "Validation Date", "fieldtype":"Date", "width": 100}, + {"fieldname": "global_google_code", "label": "Google Code", "fieldtype":"Data", "width": 120}, + {"fieldname": "disabled", "label": "Disabled", "fieldtype":"Check", "width": 80}, + {"fieldname": "link_doctype", "label": "Master Type", "fieldtype":"Data", "width": 120}, + {"fieldname": "link_name", "label": "Master Name", "fieldtype":"Dynamic Link", "options":"link_doctype", "width": 120} ] else: col_map = [ - {"fieldname": "name", "label": f"{filters.get('type')} Link", "fieldtype":"Link", - "options":f"{filters.get('type')}", "width": 100}, - {"fieldname": "salutation", "label": "Salutation", "fieldtype":"", "options":"", - "width": 30}, - {"fieldname": "first_name", "label": "First Name", "fieldtype":"", "options":""}, - {"fieldname": "middle_name", "label": "Middle Name", "fieldtype":"", "options":""}, - {"fieldname": "last_name", "label": "Last Name", "fieldtype":"", "options":""}, - {"fieldname": "phone", "label": "Phone", "fieldtype":"", "options":""}, - {"fieldname": "email", "label": "Email", "fieldtype":"", "options":""}, - {"fieldname": "designation", "label": "Designation", "fieldtype":"", "option":""}, - {"fieldname": "department", "label": "Department", "fieldtype":"", "option":""}, - {"fieldname": "birthday", "label": "Birthday", "fieldtype":"Date", "options":"", - "width": 80}, - {"fieldname": "anniversary", "label": "Anniversary", "fieldtype":"Date", "options":"", - "width":80}, - {"fieldname": "notes", "label": "Notes", "fieldtype":"", "option":""}, - {"fieldname": "is_primary_contact", "label": "Primary", "fieldtype":"Int", "options":"", - "width": 20}, - {"fieldname": "link_doctype", "label": "Master Type", "fieldtype":"", "options":""}, - {"fieldname": "link_name", "label": "Master Name", "fieldtype":"Dynamic Link", - "options":"link_doctype"}, - {"fieldname": "gender", "label": "Gender", "fieldtype":"", "options":""} + {"fieldname": "name", "label": "Contact Link", "fieldtype":"Link", "options":"Contact", "width": 120}, + {"fieldname": "salutation", "label": "Salutation", "fieldtype":"Data", "width": 100}, + {"fieldname": "first_name", "label": "First Name", "fieldtype":"Data", "width": 120}, + {"fieldname": "middle_name", "label": "Middle Name", "fieldtype":"Data", "width": 100}, + {"fieldname": "last_name", "label": "Last Name", "fieldtype":"Data", "width": 120}, + {"fieldname": "phone", "label": "Phone", "fieldtype":"Data", "width": 150}, + {"fieldname": "email", "label": "Email", "fieldtype":"Data", "width": 200}, + {"fieldname": "designation", "label": "Designation", "fieldtype":"Data", "width": 120}, + {"fieldname": "department", "label": "Department", "fieldtype":"Data", "width": 120}, + {"fieldname": "birthday", "label": "Birthday", "fieldtype":"Date", "width": 100}, + {"fieldname": "anniversary", "label": "Anniversary", "fieldtype":"Date", "width": 100}, + {"fieldname": "notes", "label": "Small Text", "fieldtype":"Small Text", "width": 150}, + {"fieldname": "is_primary_contact", "label": "Primary", "fieldtype":"Check", "width": 80}, + {"fieldname": "link_doctype", "label": "Master Type", "fieldtype":"Data", "width": 120}, + {"fieldname": "link_name", "label": "Master Name", "fieldtype":"Dynamic Link", "options":"link_doctype", "width": 120}, + {"fieldname": "gender", "label": "Gender", "fieldtype":"Data", "width": 100} ] + if filters.get("customer_group"): - cg_fd = {"fieldname": "customer_group", "label": "Cust Group", "fieldtype":"Link", - "options":"Customer Group"} - col_map.append(cg_fd.copy()) + col_map.append({"fieldname": "customer_group", "label": "Cust Group", "fieldtype":"Link", "options":"Customer Group", "width": 120}) if filters.get("territory"): - terr_fd = {"fieldname": "territory", "label": "Territory", "fieldtype":"Link", - "options":"Territory"} - col_map.append(terr_fd.copy()) + col_map.append({"fieldname": "territory", "label": "Territory", "fieldtype":"Link", "options":"Territory", "width": 120}) if not data: return col_map, [] - drop_cols = [] - col_size = [] - cols = frappe._dict({}) - - for key in data[0].keys(): - mlen = 0 - for d in data: - if d.get(key): - if isinstance(d.get(key), (datetime.date, int, float)): - ex_len = 4 - else: - ex_len = len(d.get(key)) - else: - ex_len = 0 - if ex_len > mlen: - mlen = ex_len - cols["fieldname"] = key - cols["width"] = mlen - col_size.append(cols.copy()) - if mlen == 0: - drop_cols.append(key) - for d in col_map: - for e in col_size: - if d["fieldname"] == e["fieldname"]: - if d.get("width", 0) == 0: - d["width"] = min(e["width"] * 10, 200) + # Efficient O(N) single-pass width and empty-column check + max_lengths = {col["fieldname"]: 0 for col in col_map} + for row in data: + for col in col_map: + val = row.get(col["fieldname"]) + if val: + w = len(str(val)) + if w > max_lengths[col["fieldname"]]: + max_lengths[col["fieldname"]] = w + + # Filter out empty columns and update widths dynamically + final_cols = [] for col in col_map: - if col.get("width") == 0: - col_map.remove(col) + mlen = max_lengths[col["fieldname"]] + if mlen > 0: + # Dynamically adjust width if content is longer than default + calc_w = min(mlen * 10, 300) + col["width"] = max(col.get("width", 100), calc_w) + final_cols.append(col) + + # Build final data list efficiently based on filtered columns for row in data: - drow = [] - for fd in col_map: - drow.append(row.get(fd.get("fieldname"))) - new_data.append(drow) + new_data.append([row.get(col["fieldname"]) for col in final_cols]) - return col_map, new_data + return final_cols, new_data -def get_entries(filters, conditions, tbl_join, fd_add): +def get_entries(filters, conditions, tbl_join, fd_add, params): data = [] if filters.get("type") == "Address": if filters.get("orphaned") != 1: - query = f"""SELECT ad.name, ad.address_title, ad.address_type, ad.address_line1, - ad.address_line2, ad.city, ad.state, ad.country, ad.pincode, ad.sea_port, ad.airport, - ad.email_id, ad.phone, ad.fax, ad.gstin, ad.disabled, dl.link_doctype, dl.link_name, - ad.global_google_code, ad.gst_status, ad.gst_validation_date, ad.latitude, ad.longitude - {fd_add} - FROM `tabAddress` ad, `tabDynamic Link` dl {tbl_join} - WHERE dl.parenttype = 'Address' AND dl.parent = ad.name {conditions} - ORDER BY dl.link_doctype, dl.link_name, ad.name""" + query = f""" + SELECT + ad.name, ad.address_title, ad.address_type, ad.address_line1, + ad.address_line2, ad.city, ad.state, ad.country, ad.pincode, ad.sea_port, ad.airport, + ad.email_id, ad.phone, ad.fax, ad.gstin, ad.disabled, dl.link_doctype, dl.link_name, + ad.global_google_code, ad.gst_status, ad.gst_validation_date, ad.latitude, ad.longitude + {fd_add} + FROM `tabAddress` ad + INNER JOIN `tabDynamic Link` dl ON dl.parent = ad.name + {tbl_join} + WHERE dl.parenttype = 'Address' {conditions} + ORDER BY dl.link_doctype, dl.link_name, ad.name + """ else: - query = f"""SELECT ad.name, ad.address_title, ad.address_type, ad.address_line1, - ad.address_line2, ad.city, ad.state, ad.country, ad.pincode, ad.sea_port, ad.airport, - ad.email_id, ad.phone, ad.fax, ad.gstin, ad.disabled, ad.global_google_code, - ad.gst_status, ad.gst_validation_date - FROM `tabAddress` ad - WHERE ad.name NOT IN (SELECT parent FROM `tabDynamic Link` WHERE parenttype = 'Address' - GROUP BY parent) - ORDER BY ad.name""" + query = """ + SELECT + ad.name, ad.address_title, ad.address_type, ad.address_line1, + ad.address_line2, ad.city, ad.state, ad.country, ad.pincode, ad.sea_port, ad.airport, + ad.email_id, ad.phone, ad.fax, ad.gstin, ad.disabled, ad.global_google_code, + ad.gst_status, ad.gst_validation_date + FROM `tabAddress` ad + WHERE ad.name NOT IN (SELECT parent FROM `tabDynamic Link` WHERE parenttype = 'Address' GROUP BY parent) + ORDER BY ad.name + """ else: if filters.get("orphaned") != 1: - query = f"""SELECT con.name, - IF(TRIM(con.salutation)="" or TRIM(con.salutation) IS NULL , 'zNo Salutation', - con.salutation) as salutation, - IF(TRIM(con.first_name)="" or TRIM(con.first_name) IS NULL , 'zNo First Name', - con.first_name) as first_name, - IF(TRIM(con.middle_name)="" or TRIM(con.middle_name) IS NULL , 'zNo Middle Name', - con.middle_name) as middle_name, - IF(TRIM(con.last_name)="" or TRIM(con.last_name) IS NULL , 'zNo Last Name', - con.last_name) as last_name, - IF(TRIM(con.gender)="" or TRIM(con.gender) IS NULL , 'zNo Gender', - con.gender) as gender, con.is_primary_contact, - con.birthday, con.anniversary, con.designation, con.department, con.notes, - dl.link_doctype, dl.link_name {fd_add} - FROM `tabContact` con, `tabDynamic Link` dl {tbl_join} - WHERE dl.parenttype = 'Contact' AND dl.parent = con.name {conditions} - ORDER BY dl.link_doctype, dl.link_name, con.name""" + query = f""" + SELECT + con.name, + COALESCE(NULLIF(TRIM(con.salutation), ''), 'zNo Salutation') as salutation, + COALESCE(NULLIF(TRIM(con.first_name), ''), 'zNo First Name') as first_name, + COALESCE(NULLIF(TRIM(con.middle_name), ''), 'zNo Middle Name') as middle_name, + COALESCE(NULLIF(TRIM(con.last_name), ''), 'zNo Last Name') as last_name, + COALESCE(NULLIF(TRIM(con.gender), ''), 'zNo Gender') as gender, + con.is_primary_contact, + con.birthday, con.anniversary, con.designation, con.department, con.notes, + dl.link_doctype, dl.link_name {fd_add} + FROM `tabContact` con + INNER JOIN `tabDynamic Link` dl ON dl.parent = con.name + {tbl_join} + WHERE dl.parenttype = 'Contact' {conditions} + ORDER BY dl.link_doctype, dl.link_name, con.name + """ else: - query = f"""SELECT con.name, - IF(TRIM(con.salutation)="" or TRIM(con.salutation) IS NULL , 'zNo Salutation', - con.salutation) as salutation, - IF(TRIM(con.first_name)="" or TRIM(con.first_name) IS NULL , 'zNo First Name', - con.first_name) as first_name, - IF(TRIM(con.middle_name)="" or TRIM(con.middle_name) IS NULL , 'zNo Middle Name', - con.middle_name) as middle_name, - IF(TRIM(con.last_name)="" or TRIM(con.last_name) IS NULL , 'zNo Last Name', - con.last_name) as last_name, - IF(TRIM(con.gender)="" or TRIM(con.gender) IS NULL , 'zNo Gender', - con.gender) as gender, con.is_primary_contact, - con.birthday, con.anniversary, con.designation, con.department, con.notes - FROM `tabContact` con - WHERE con.name NOT IN (SELECT parent FROM `tabDynamic Link` WHERE parenttype = 'Contact' - GROUP BY parent) - ORDER BY con.name""" - data = frappe.db.sql(query, as_dict=1) - if filters.get("type") == "Contact": + query = """ + SELECT + con.name, + COALESCE(NULLIF(TRIM(con.salutation), ''), 'zNo Salutation') as salutation, + COALESCE(NULLIF(TRIM(con.first_name), ''), 'zNo First Name') as first_name, + COALESCE(NULLIF(TRIM(con.middle_name), ''), 'zNo Middle Name') as middle_name, + COALESCE(NULLIF(TRIM(con.last_name), ''), 'zNo Last Name') as last_name, + COALESCE(NULLIF(TRIM(con.gender), ''), 'zNo Gender') as gender, + con.is_primary_contact, + con.birthday, con.anniversary, con.designation, con.department, con.notes + FROM `tabContact` con + WHERE con.name NOT IN (SELECT parent FROM `tabDynamic Link` WHERE parenttype = 'Contact' GROUP BY parent) + ORDER BY con.name + """ + + data = frappe.db.sql(query, params, as_dict=1) + + if filters.get("type") == "Contact" and data: + contact_names = [r.name for r in data] + + # Optimized Bulk fetching for Phones + phones = frappe.get_all("Contact Phone", filters={"parent": ["in", contact_names]}, fields=["parent", "phone"]) + phone_map = {} + for p in phones: + p_name = p.parent + if p_name not in phone_map: phone_map[p_name] = [] + phone_map[p_name].append(p.phone) + + # Optimized Bulk fetching for Emails + emails = frappe.get_all("Contact Email", filters={"parent": ["in", contact_names]}, fields=["parent", "email_id"]) + email_map = {} + for e in emails: + e_name = e.parent + if e_name not in email_map: email_map[e_name] = [] + email_map[e_name].append(e.email_id) + for row in data: - phone_nos = get_contact_phones(row.name) - emails = get_contact_emails(row.name) - row["phone"] = phone_nos - row["email"] = emails + row["phone"] = ", ".join(phone_map.get(row.name, [])) + row["email"] = ", ".join(email_map.get(row.name, [])) + return data @@ -191,11 +192,14 @@ def get_conditions(filters): cond = "" tbl_join = "" fd_add = "" + params = {} if filters.get("link_type"): - cond += f" AND dl.link_doctype = '{filters.get('link_type')}'" + cond += " AND dl.link_doctype = %(link_type)s" + params["link_type"] = filters.get("link_type") if filters.get("linked_to"): - cond += f" AND dl.link_name = '{filters.get('linked_to')}'" + cond += " AND dl.link_name = %(linked_to)s" + params["linked_to"] = filters.get("linked_to") if filters.get("territory"): fd_add += ", cu.territory" @@ -204,37 +208,27 @@ def get_conditions(filters): AND dl.link_name = cu.name""" terr = frappe.get_doc("Territory", filters["territory"]) if terr.is_group == 1: - child_territories = frappe.db.sql(f"""SELECT name FROM `tabTerritory` - WHERE lft >= {terr.lft} AND rgt <= {terr.rgt}""", as_list=1) - for i in child_territories: - if child_territories[0] == i: - cond += " AND (cu.territory = '%s'" % i[0] - elif child_territories[len(child_territories) - 1] == i: - cond += " OR cu.territory = '%s')" % i[0] - else: - cond += " OR cu.territory = '%s'" % i[0] + child_territories = frappe.get_all("Territory", filters={"lft": [">=", terr.lft], "rgt": ["<=", terr.rgt]}, pluck="name") + cond += " AND cu.territory IN %(territories)s" + params["territories"] = child_territories else: - cond += " AND cu.territory = '%s'" % filters["territory"] + cond += " AND cu.territory = %(territory)s" + params["territory"] = filters["territory"] if filters.get("customer_group"): fd_add += ", cu.customer_group" - if tbl_join == "": + if "tabCustomer" not in tbl_join: tbl_join += """ LEFT JOIN `tabCustomer` cu ON dl.link_doctype = 'Customer' AND dl.link_name = cu.name""" cg = frappe.get_doc("Customer Group", filters["customer_group"]) if cg.is_group == 1: - child_cgs = frappe.db.sql(f"""SELECT name FROM `tabCustomer Group` - WHERE lft >= {cg.lft} AND rgt <= {cg.rgt}""", as_list=1) - for i in child_cgs: - if child_cgs[0] == i: - cond += " AND (cu.customer_group = '%s'" % i[0] - elif child_cgs[len(child_cgs) - 1] == i: - cond += " OR cu.customer_group = '%s')" % i[0] - else: - cond += " OR cu.customer_group = '%s'" % i[0] + child_cgs = frappe.get_all("Customer Group", filters={"lft": [">=", cg.lft], "rgt": ["<=", cg.rgt]}, pluck="name") + cond += " AND cu.customer_group IN %(customer_groups)s" + params["customer_groups"] = child_cgs else: - cond += " AND cu.customer_group = '%s'" % filters["customer_group"] - return cond, tbl_join, fd_add + cond += " AND cu.customer_group = %(customer_group)s" + params["customer_group"] = filters["customer_group"] + return cond, tbl_join, fd_add, params @frappe.whitelist() @frappe.validate_and_sanitize_search_inputs diff --git a/rohit_common/rohit_common/report/asset_analysis/asset_analysis.py b/rohit_common/rohit_common/report/asset_analysis/asset_analysis.py index 0db239d..f46b4c2 100644 --- a/rohit_common/rohit_common/report/asset_analysis/asset_analysis.py +++ b/rohit_common/rohit_common/report/asset_analysis/asset_analysis.py @@ -10,64 +10,119 @@ def execute(filters=None): if not filters: filters = {} - conditions, cond_dep = get_conditions(filters) + + conditions, cond_dep, params = get_conditions(filters) columns = get_columns(filters) + if filters.get("compare_accounts") == 1: data = compare_asset_with_accounts(filters) else: - assets = get_assets(conditions, filters) - acc_dep = get_acc_dep(assets, cond_dep) + assets = get_assets(conditions, filters, params) + acc_dep_list = get_acc_dep(assets, cond_dep, params) + + # O(1) Lookup Optimization + acc_dep_map = {d.parent: d for d in acc_dep_list} + data = [] for a in assets: - open_acc_dep = a.opening_accumulated_depreciation - purchase = a.net_purchase_amount - row = [a.name, a.item_code, a.purchase_date, purchase, a.total_number_of_depreciations, - open_acc_dep] - check = 0 - for acc in acc_dep: - if acc.parent == a.name: - total_dep = flt(round(acc.dep,2)) - period_dep = flt(round(acc.monthly, 2)) - row += [(total_dep - period_dep), total_dep, period_dep] - check = 1 - if check == 0: # if fully depreciated asset - total_dep = purchase - a.salvage + purchase = flt(a.net_purchase_amount) + row = [ + a.name, a.item_code, a.purchase_date, purchase, + a.total_number_of_depreciations, a.opening_accumulated_depreciation + ] + + acc = acc_dep_map.get(a.name) + if acc: + total_dep = flt(round(acc.dep, 2)) + period_dep = flt(round(acc.monthly, 2)) + row += [(total_dep - period_dep), total_dep, period_dep] + else: + # Fully depreciated fallback + total_dep = purchase - flt(a.salvage) period_dep = 0 row += [(total_dep - period_dep), total_dep, period_dep] - row += [(purchase - total_dep), a.salvage, a.status, a.disposal_date, - a.fixed_asset_account, a.asset_category, - a.warehouse, a.model, a.manufacturer, a.description, a.purchase_receipt, - a.purchase_invoice] - + + row += [ + (purchase - total_dep), a.salvage, a.status, a.disposal_date, + a.fixed_asset_account, a.asset_category, + a.warehouse, a.model, a.manufacturer, a.description, a.purchase_receipt, + a.purchase_invoice + ] data.append(row) + return columns, data def compare_asset_with_accounts(filters): - """ - Returns the list of GRN or PI where Fixed Assets are not created - """ + to_date = filters.get("to_date") or frappe.utils.today() + + # Respect filters in reconciliation mode + item_conditions = "" + item_params = {"to_date": to_date} + + if filters.get("asset_category"): + item_conditions += " AND it.asset_category = %(asset_category)s" + item_params["asset_category"] = filters.get("asset_category") + + # 1. Bulk fetch Fixed Asset items with reconciliation filters + item_list = frappe.db.sql(f""" + SELECT + it.name, it.description, it.asset_category, + IFNULL(it.end_of_life, '2099-12-31') as eol, + ascat.type_of_asset + FROM `tabItem` it + INNER JOIN `tabAsset Category` ascat ON it.asset_category = ascat.name + WHERE it.is_fixed_asset = 1 {item_conditions} + ORDER BY it.name + """, item_params, as_dict=1) + + if not item_list: + return [] + + # 2. Bulk fetch Asset Category Accounts (O(1) mapping) + # Respect fixed_asset_account filter if provided + acc_filters = {} + if filters.get("account"): + acc_filters["fixed_asset_account"] = filters.get("account") + + category_accounts = frappe.get_all("Asset Category Account", + filters=acc_filters, + fields=["parent", "fixed_asset_account"]) + cat_acc_map = {d.parent: d.fixed_asset_account for d in category_accounts} + + # 3. Bulk calculate Asset Totals per Item Code (O(N) aggregation) + asset_totals = frappe.db.sql(""" + SELECT + item_code, + COUNT(name) as no_of_assets, + SUM(net_purchase_amount) as total_value + FROM `tabAsset` + WHERE docstatus = 1 AND purchase_date <= %s + AND (disposal_date IS NULL OR disposal_date > %s) + GROUP BY item_code + """, (to_date, to_date), as_dict=1) + asset_map = {d.item_code: d for d in asset_totals} + + # 4. Assembly with Bulk Balance fetching data = [] - item_list = frappe.db.sql("""SELECT it.name, it.description, it.asset_category, - IFNULL(it.end_of_life, '2099-12-31') as eol, ascat.type_of_asset, - ascat.residual_value_percent - FROM `tabItem` it, `tabAsset Category` ascat - WHERE it.is_fixed_asset = 1 AND it.asset_category = ascat.name - ORDER BY it.name""", as_dict=1) + account_balances = {} + for itm in item_list: - ast_fin = get_ast_cat_finance(itm.asset_category)[0] - tot_ast_dict = get_total_assets_for_item_code(item_code=itm.name, - on_date=filters.get("to_date")) - itm["asset_account"] = ast_fin.fixed_asset_account - itm["asset_acc_balance"] = get_balance_on(account=ast_fin.fixed_asset_account, - date=filters.get("to_date")) - itm["working_assets"] = tot_ast_dict.no_of_assets - itm["tot_asset_value"] = tot_ast_dict.total_value - row = [ - itm.name, itm.asset_category, itm.eol, itm.asset_account, itm.type_of_asset, - itm.asset_acc_balance, itm.tot_asset_value, itm.working_assets, - (itm.asset_acc_balance - itm.tot_asset_value) - ] - data.append(row) + acc = cat_acc_map.get(itm.asset_category) + if not acc: continue + + if acc not in account_balances: + account_balances[acc] = get_balance_on(account=acc, date=to_date) + + stats = asset_map.get(itm.name, frappe._dict({"no_of_assets": 0, "total_value": 0})) + + acc_bal = flt(account_balances[acc]) + asset_val = flt(stats.total_value) + + data.append([ + itm.name, itm.asset_category, itm.eol, acc, itm.type_of_asset, + acc_bal, asset_val, stats.no_of_assets, (acc_bal - asset_val) + ]) + return data @@ -92,62 +147,98 @@ def get_columns(filters): "PI:Link/Purchase Invoice:80" ] -def get_assets(conditions, filters): - query = """SELECT ass.name, ass.item_code, ass.asset_category, - IFNULL(ass.warehouse, "NIL") as warehouse, IFNULL(ass.model, "NIL") as model, - IFNULL(ass.manufacturer, "NIL") as manufacturer, IFNULL(ass.status, "NO STATUS") as status, - IFNULL(ass.description, "NIL") as description, ass.purchase_date, - ass.net_purchase_amount, ass.opening_accumulated_depreciation, - IFNULL(ass_fb.expected_value_after_useful_life, 0) AS salvage, - IFNULL(ass.disposal_date, '2199-12-31') as disposal_date, - ass_fb.total_number_of_depreciations, as_cat_acc.fixed_asset_account, ass.purchase_receipt, - ass.purchase_invoice - FROM `tabAsset` ass, `tabAsset Category` as_cat, `tabAsset Category Account` as_cat_acc, - `tabAsset Finance Book` ass_fb - WHERE ass.docstatus != 2 AND ass.asset_category = as_cat.name - AND ass_fb.parent = ass.name AND ass_fb.parenttype = 'Asset' - AND IFNULL(ass.disposal_date, '2099-12-31') >= '%s' - AND as_cat_acc.parent = as_cat.name %s - ORDER BY ass.purchase_date DESC, ass.asset_category""" %(filters.get("to_date"),conditions) - #frappe.msgprint(query) - assets = frappe.db.sql(query, as_dict = 1) - if assets: - pass - else: +def get_assets(conditions, filters, params): + # Ensure to_date has a value for disposal check + params["to_date"] = params.get("to_date") or frappe.utils.today() + + query = f""" + SELECT + ass.name, ass.item_code, ass.asset_category, + IFNULL(ass.warehouse, 'NIL') as warehouse, + IFNULL(ass.model, 'NIL') as model, + IFNULL(ass.manufacturer, 'NIL') as manufacturer, + IFNULL(ass.status, 'NO STATUS') as status, + IFNULL(ass.description, 'NIL') as description, + ass.purchase_date, + ass.net_purchase_amount, + ass.opening_accumulated_depreciation, + IFNULL(ass_fb.expected_value_after_useful_life, 0) AS salvage, + IFNULL(ass.disposal_date, '2199-12-31') as disposal_date, + ass_fb.total_number_of_depreciations, + as_cat_acc.fixed_asset_account, + ass.purchase_receipt, + ass.purchase_invoice + FROM `tabAsset` ass + INNER JOIN `tabAsset Category` as_cat ON ass.asset_category = as_cat.name + INNER JOIN `tabAsset Finance Book` ass_fb ON ass_fb.parent = ass.name + INNER JOIN `tabAsset Category Account` as_cat_acc ON as_cat_acc.parent = as_cat.name + WHERE ass.docstatus != 2 + AND ass_fb.parenttype = 'Asset' + AND IFNULL(ass.disposal_date, '2099-12-31') >= %(to_date)s + {conditions} + ORDER BY ass.purchase_date DESC, ass.asset_category + """ + assets = frappe.db.sql(query, params, as_dict=1) + + if not assets: frappe.throw("No Assets in the Selected Criterion") - #frappe.msgprint(str(assets)) return assets -def get_acc_dep(asset, cond_dep): - acc_dep = frappe.db.sql("""SELECT MAX(ds.accumulated_depreciation_amount) as dep, - ds.parent, SUM(ds.depreciation_amount) as monthly +def get_acc_dep(assets, cond_dep, params): + if not assets: + return [] + + # Bulk Fetch targeted by asset names + asset_names = [d.name for d in assets] + dep_params = params.copy() + + # Secure and highly compatible dictionary expansion for IN clause + placeholders = [] + for i, name in enumerate(asset_names): + key = f"asset_name_{i}" + dep_params[key] = name + placeholders.append(f"%({key})s") + + query = f""" + SELECT + MAX(ds.accumulated_depreciation_amount) as dep, + ds.parent, + SUM(ds.depreciation_amount) as monthly FROM `tabDepreciation Schedule` ds - WHERE ds.docstatus != 2 {condition} AND ds.parent IN (%s) - GROUP BY ds.parent""".format(condition = cond_dep) % - (', '.join(['%s']*len(asset))), tuple([d.name for d in asset]), as_dict=1) - return acc_dep + WHERE ds.docstatus != 2 + {cond_dep} + AND ds.parent IN ({', '.join(placeholders)}) + GROUP BY ds.parent + """ + + return frappe.db.sql(query, dep_params, as_dict=1) def get_conditions(filters): conditions = "" cond_dep = "" + to_date = filters.get("to_date") or frappe.utils.today() + params = {"to_date": to_date} if filters.get("from_date"): - if filters["from_date"] > filters["to_date"]: + if filters["from_date"] > to_date: frappe.throw("From Date cannot be greater than To Date") - cond_dep += "AND ds.schedule_date >= '%s'"% filters["from_date"] + cond_dep += " AND ds.schedule_date >= %(from_date)s" + params["from_date"] = filters.get("from_date") if filters.get("to_date"): - conditions += "AND ass.purchase_date <= '%s'" % filters["to_date"] - cond_dep += "AND ds.schedule_date <= '%s'"% filters["to_date"] + conditions += " AND ass.purchase_date <= %(to_date)s" + cond_dep += " AND ds.schedule_date <= %(to_date)s" if filters.get("asset_category"): - conditions += "AND ass.asset_category = '%s'" % filters["asset_category"] + conditions += " AND ass.asset_category = %(asset_category)s" + params["asset_category"] = filters.get("asset_category") if filters.get("asset"): - conditions += "AND ass.name = '%s'" % filters["asset"] + conditions += " AND ass.name = %(asset)s" + params["asset"] = filters.get("asset") if filters.get("account"): - conditions += "AND as_cat_acc.fixed_asset_account = '%s'" % filters["account"] - + conditions += " AND as_cat_acc.fixed_asset_account = %(account)s" + params["account"] = filters.get("account") - return conditions, cond_dep + return conditions, cond_dep, params diff --git a/rohit_common/rohit_common/report/backend_database_analysis_rigpl/backend_database_analysis_rigpl.py b/rohit_common/rohit_common/report/backend_database_analysis_rigpl/backend_database_analysis_rigpl.py index b15faa2..214904b 100644 --- a/rohit_common/rohit_common/report/backend_database_analysis_rigpl/backend_database_analysis_rigpl.py +++ b/rohit_common/rohit_common/report/backend_database_analysis_rigpl/backend_database_analysis_rigpl.py @@ -22,72 +22,51 @@ def get_columns(filters): Returns the columns for the Report """ get_conditions(filters) - cols = "" if filters.get("all_tables") == 1: - cols = [ - "Database Name::200", "Table Name::400", - "Size in MB:Float:100", "Data MB::100", "Index MB::100", "Total Row:Int:150" + return [ + {"label": "Database Name", "fieldname": "db_name", "fieldtype": "Data", "width": 150}, + {"label": "Table Name", "fieldname": "tbl_name", "fieldtype": "Data", "width": 250}, + {"label": "Size (MB)", "fieldname": "size_mb", "fieldtype": "Float", "width": 100}, + {"label": "Data (MB)", "fieldname": "dl_mb", "fieldtype": "Float", "width": 100}, + {"label": "Index (MB)", "fieldname": "ind_mb", "fieldtype": "Float", "width": 100}, + {"label": "Total Rows", "fieldname": "tbl_rows", "fieldtype": "Int", "width": 100}, + {"label": "Columns", "fieldname": "no_of_cols", "fieldtype": "Int", "width": 100} ] elif filters.get("unused_tables") == 1: - cols = [ - "DB Name::200", "App Name::100", "Module Name::100", "Table Name::200", - "DT Name:Link/DocType:200", "Size in MB:Float:100", "Data MB::100", - "Last Entry:Datetime:200", "Total Row:Int:150" + return [ + {"label": "DB Name", "fieldname": "db_name", "fieldtype": "Data", "width": 150}, + {"label": "App", "fieldname": "app", "fieldtype": "Data", "width": 100}, + {"label": "Module", "fieldname": "module", "fieldtype": "Data", "width": 120}, + {"label": "Table Name", "fieldname": "tbl_name", "fieldtype": "Data", "width": 200}, + {"label": "Potential DT", "fieldname": "dt_name", "fieldtype": "Data", "width": 180}, + {"label": "Size (MB)", "fieldname": "size_mb", "fieldtype": "Float", "width": 100}, + {"label": "Last Entry", "fieldname": "last_entry", "fieldtype": "Datetime", "width": 180}, + {"label": "Total Rows", "fieldname": "tbl_rows", "fieldtype": "Int", "width": 100} ] else: - cols = [ - "Database Name::200", "Table Name::400", "Total Columns:Int:150" + return [ + {"label": "Database Name", "fieldname": "db_name", "fieldtype": "Data", "width": 150}, + {"label": "Table Name", "fieldname": "tbl_name", "fieldtype": "Data", "width": 300}, + {"label": "Total Columns", "fieldname": "no_of_cols", "fieldtype": "Int", "width": 120} ] - return cols def get_data(filters): """ Returns the data in list format for the report """ - data = [] + from ....patches.backend_table_analysis import get_size_of_all_tables, get_columns_of_all_tables, get_orphaned_tables + if filters.get("all_tables") == 1: data_dict = get_size_of_all_tables() - for drow in data_dict: - row = [ - drow.db_name, drow.tbl_name, drow.size_mb, - drow.dl_mb, drow.ind_mb, drow.tbl_rows, drow.no_of_cols - ] - data.append(row) + return data_dict + elif filters.get("unused_tables") == 1: - data_dict = get_size_of_all_tables() - dt_fds = {"name", "modified", "issingle", - "istable", "module", "app", "is_virtual"} - virtual_dts = frappe.get_list( - "DocType", fields=dt_fds, filters={"is_virtual": 1}) - single_dts = frappe.get_list( - "DocType", fields=dt_fds, filters={"issingle": 1}) - all_dts = frappe.db.sql("""SELECT name, modified, issingle, istable, module, app, is_virtual - FROM `tabDocType`""", as_dict=1) - # frappe.throw(str(all_dts)) - core_dts = core_doctypes_list - installed_apps = frappe.get_installed_apps() - # frappe.throw(str(installed_apps)) - # To check if a Table is there in DB but not in any app we need to check the following - # 1. Table should not be default fields, get installed_apps, get_dts_from_installed_apps - for dty in core_dts: - # mdty = frappe.get_meta(dty) - print(dty) - - for drow in data_dict: - row = [ - drow.db_name, "app", "module", drow.tbl_name, "dt", - drow.size_mb, drow.dl_mb, drow.ind_mb, drow.tbl_rows, drow.no_of_cols - ] - data.append(row) + # Identified tables that exist in DB but aren't registered DocTypes + return get_orphaned_tables() + else: - data_dict = get_columns_of_all_tables() - for drow in data_dict: - row = [ - drow.db_name, drow.tbl_name, drow.no_of_cols - ] - data.append(row) - return data + return get_columns_of_all_tables() def get_conditions(filters): diff --git a/rohit_common/rohit_common/report/clear_tax_import_format/clear_tax_import_format.py b/rohit_common/rohit_common/report/clear_tax_import_format/clear_tax_import_format.py index e84d2a2..44f00a9 100644 --- a/rohit_common/rohit_common/report/clear_tax_import_format/clear_tax_import_format.py +++ b/rohit_common/rohit_common/report/clear_tax_import_format/clear_tax_import_format.py @@ -483,180 +483,118 @@ def get_items_based_on_tax_rate_custom(self): if not self.invoices: return - self.tax_details = frappe.db.sql( - """ + # Pre-cache GST accounts into distinct sets for O(1) lookups + cgst_sgst_accs = set( + self.gst_accounts.get("cgst_account", []) + + self.gst_accounts.get("sgst_account", []) + ) + igst_accs = set(self.gst_accounts.get("igst_account", [])) + cess_accs = set(self.gst_accounts.get("cess_account", [])) + + tax_details = frappe.db.sql(""" select parent, account_head, item_wise_tax_detail, base_tax_amount_after_discount_amount from `tab%s` where parenttype = %%s and docstatus = 1 and parent in (%s) order by account_head - """ - % ( - self.tax_doctype, - ", ".join(["%s"] * len(self.invoices.keys())), - ), - tuple([self.doctype] + list(self.invoices.keys())), - ) + """ % (self.tax_doctype, ", ".join(["%s"] * len(self.invoices))), + tuple([self.doctype] + list(self.invoices.keys())), as_dict=1) self.items_based_on_tax_rate = {} self.invoice_cess = frappe._dict() - self.cgst_sgst_invoices = [] + self.cgst_sgst_invoices = set() + + # Optimize JSON parsing by caching + json_load = json.loads - for parent, account, item_wise_tax_detail, tax_amount in self.tax_details: + for d in tax_details: + parent, account = d.parent, d.account_head + # Handle Cess separately - if account in self.gst_accounts.cess_account: - self.invoice_cess.setdefault(parent, 0.0) - self.invoice_cess[parent] += flt(tax_amount) - continue # Skip Cess rows for Rate grouping + if account in cess_accs: + self.invoice_cess[parent] = self.invoice_cess.get(parent, 0.0) + flt(d.base_tax_amount_after_discount_amount) + continue - # Strict GST Account check to ignore freight/other charges + # Strict GST Account check is_cgst_sgst = False - if ( - account in self.gst_accounts.cgst_account - or account in self.gst_accounts.sgst_account - ): + acct_lower = account.lower() + + if account in cgst_sgst_accs or "cgst" in acct_lower or "sgst" in acct_lower: is_cgst_sgst = True - elif account in self.gst_accounts.igst_account: + elif account in igst_accs or "igst" in acct_lower: pass else: - acct_lower = account.lower() - if "cgst" in acct_lower or "sgst" in acct_lower: - is_cgst_sgst = True - elif "igst" in acct_lower: - pass - else: - # Non-GST tax row → ignore - continue + # Non-GST tax row → ignore + continue - if item_wise_tax_detail: + if d.item_wise_tax_detail: try: - detail = json.loads(item_wise_tax_detail) - + detail = json_load(d.item_wise_tax_detail) for item_key, tax_amounts in detail.items(): if isinstance(tax_amounts, dict): - tax_rate = flt( - tax_amounts.get("tax_rate") - or tax_amounts.get("rate") - or 0 - ) + tax_rate = flt(tax_amounts.get("tax_rate") or tax_amounts.get("rate") or 0) elif isinstance(tax_amounts, (list, tuple)): tax_rate = flt(tax_amounts[0]) else: tax_rate = 0.0 if tax_rate > 0: - # For CGST+SGST, table stores half rate; convert to total if is_cgst_sgst: tax_rate *= 2 - if parent not in self.cgst_sgst_invoices: - self.cgst_sgst_invoices.append(parent) - - rate_based_dict = ( - self.items_based_on_tax_rate.setdefault(parent, {}) - .setdefault(tax_rate, []) - ) - if item_key not in rate_based_dict: - rate_based_dict.append(item_key) - except ValueError: - # bad JSON, ignore + self.cgst_sgst_invoices.add(parent) + + self.items_based_on_tax_rate.setdefault(parent, {}).setdefault(tax_rate, set()).add(item_key) + except (ValueError, TypeError): pass - # --- Add 0-rated invoices (imports/exempt) not present in tax table --- + # Add 0-rated invoices if hasattr(self, "invoice_items"): for inv, items in self.invoice_items.items(): if inv not in self.items_based_on_tax_rate: if self.doctype == "Sales Invoice": - keys = list(items.keys()) # dict + self.items_based_on_tax_rate.setdefault(inv, {})[0.0] = set(items.keys()) else: - keys = list({x["key"] for x in items}) # list of dicts - self.items_based_on_tax_rate.setdefault(inv, {}).setdefault( - 0.0, keys - ) + self.items_based_on_tax_rate.setdefault(inv, {})[0.0] = {x["key"] for x in items} # ---------------------------------------------------------------------- - # DATA BUILD (doctype-specific) + # DATA BUILD # ---------------------------------------------------------------------- def get_data_custom(self): - if self.doctype == "Sales Invoice": - # Use Sales logic with _append_row (handles 0-rate suppress/export logic) - for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): + is_sales = self.doctype == "Sales Invoice" + + for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): + if is_sales: self._append_row(inv, items_based_on_rate) - else: - # Use Purchase logic (rate-aware filtering) - for inv, items_based_on_rate in self.items_based_on_tax_rate.items(): + else: invoice_details = self.invoices.get(inv) + if not invoice_details: continue + + is_return = flt(invoice_details.get("is_return")) == 1 or invoice_details.get("return_against") + inv_items = self.invoice_items.get(inv, []) + for rate, item_keys in items_based_on_rate.items(): - row = [] - - is_return = ( - flt(invoice_details.get("is_return")) == 1 - or invoice_details.get("return_against") + # Optimization: Filter items once per rate + filtered_taxable = sum( + item["value"] for item in inv_items + if item["key"] in item_keys and (abs(item["item_rate"] - rate) < 0.1 or (rate == 0 and item["item_rate"] == 0)) ) - def val_format(v): - return abs(flt(v)) if is_return else flt(v) - - # invoice-level fields - for fieldname in self.invoice_fields: - if fieldname == "invoice_value": - val = ( - invoice_details.base_rounded_total - or invoice_details.base_grand_total - ) - row.append(flt(val)) # keep sign - elif fieldname in ( - "posting_date", - "bill_date", - "shipping_bill_date", - ): - val = invoice_details.get(fieldname) - row.append(formatdate(val, "dd-MMM-YY") if val else None) - elif fieldname == "export_type": - val = ( - "WPAY" - if invoice_details.get(fieldname) - == "With Payment of Tax" - else "WOPAY" - ) - row.append(val) - else: - row.append(invoice_details.get(fieldname)) - - # --- FILTER ITEMS BY RATE --- - taxable_value = 0.0 - inv_items = self.invoice_items.get(inv, []) - - for item_data in inv_items: - if item_data["key"] in item_keys: - # allow minor float diff - if abs(item_data["item_rate"] - rate) < 0.1: - taxable_value += item_data["value"] - # special case for 0-rate bucket - elif rate == 0 and item_data["item_rate"] == 0: - taxable_value += item_data["value"] - - tax_amount = taxable_value * rate / 100.0 - - # If filtered taxable value is 0, skip row unless invoice is purely 0-rate - if taxable_value == 0: - all_rates_zero = all( - x["item_rate"] == 0 for x in inv_items - ) or not inv_items - if not all_rates_zero: - continue - - row += [rate, val_format(taxable_value)] + if filtered_taxable == 0 and any(x["item_rate"] != 0 for x in inv_items): + continue + row = self._build_invoice_base_row(invoice_details, is_return) + + tax_amount = filtered_taxable * rate / 100.0 + val_fmt = lambda v: abs(flt(v)) if is_return else flt(v) + + row += [rate, val_fmt(filtered_taxable)] + if inv in self.cgst_sgst_invoices: - row += [ - 0.0, - val_format(tax_amount / 2.0), - val_format(tax_amount / 2.0), - ] + row += [0.0, val_fmt(tax_amount / 2.0), val_fmt(tax_amount / 2.0)] else: - row += [val_format(tax_amount), 0.0, 0.0] - - row += [val_format(self.invoice_cess.get(inv, 0.0))] + row += [val_fmt(tax_amount), 0.0, 0.0] - # Purchase-specific ITC cols + row += [val_fmt(self.invoice_cess.get(inv, 0.0))] + + # Purchase ITC Columns row += [ invoice_details.get("eligibility_for_itc") or "All Other ITC", invoice_details.get("itc_integrated_tax"), @@ -664,21 +602,27 @@ def val_format(v): invoice_details.get("itc_state_tax"), invoice_details.get("itc_cess_amount"), ] - - # CDNR flags (if used for purchase CDNR) + if self.filters.get("type_of_business") == "CDNR": - row.append( - "Y" - if getdate(invoice_details.posting_date) - <= date(2017, 7, 1) - else "N" - ) - row.append( - "C" if invoice_details.return_against else "R" - ) + row += ["Y" if getdate(invoice_details.posting_date) <= date(2017, 7, 1) else "N", + "C" if invoice_details.return_against else "R"] self.data.append(row) + def _build_invoice_base_row(self, details, is_return): + row = [] + for fieldname in self.invoice_fields: + if fieldname == "invoice_value": + row.append(flt(details.base_rounded_total or details.base_grand_total)) + elif fieldname in ("posting_date", "bill_date", "shipping_bill_date"): + val = details.get(fieldname) + row.append(formatdate(val, "dd-MMM-YY") if val else None) + elif fieldname == "export_type": + row.append("WPAY" if details.get(fieldname) == "With Payment of Tax" else "WOPAY") + else: + row.append(details.get(fieldname)) + return row + # ---------------------------------------------------------------------- # SALES helper (unchanged from your Sales working version) # ---------------------------------------------------------------------- diff --git a/rohit_common/rohit_common/report/file_attachment_analysis_rigpl/file_attachment_analysis_rigpl.py b/rohit_common/rohit_common/report/file_attachment_analysis_rigpl/file_attachment_analysis_rigpl.py index 7c937d2..5ff13fa 100644 --- a/rohit_common/rohit_common/report/file_attachment_analysis_rigpl/file_attachment_analysis_rigpl.py +++ b/rohit_common/rohit_common/report/file_attachment_analysis_rigpl/file_attachment_analysis_rigpl.py @@ -23,7 +23,7 @@ def get_columns(filters): if filters.get("is_folder") == 1: return [ "ID:Link/File:450", "File Name::200", "Parent Folder:Link/File:350", "Size(MB):Float:100", - "Left:Int:80", "Right:Int:80", "Files:Int:80","Is Home:Int:40", "Is Attachment::40" + "Left:Int:80", "Right:Int:80", "Files:Int:80", "Is Home:Int:40", "Is Attachment::40", "Owner::80" ] else: @@ -49,42 +49,73 @@ def get_columns(filters): def get_data(filters): data = [] conditions, cond_summary = get_conditions(filters) + if filters.get("summary_dt") == 1: - data = frappe.db.sql("""SELECT IFNULL(attached_to_doctype, "NO DOCTYPE"), COUNT(name) as no_of_files, - ROUND(((SUM(file_size))/1024/1024),2) as size FROM `tabFile` WHERE docstatus=0 AND is_folder=0 %s - GROUP BY attached_to_doctype ORDER BY size DESC, no_of_files DESC """ % cond_summary, as_list=1) + data = frappe.db.sql(""" + SELECT IFNULL(attached_to_doctype, "NO DOCTYPE"), COUNT(name) as no_of_files, + ROUND(((SUM(file_size))/1024/1024),2) as size + FROM `tabFile` WHERE docstatus=0 AND is_folder=0 %s + GROUP BY attached_to_doctype ORDER BY size DESC, no_of_files DESC + """ % cond_summary, as_list=1) + elif filters.get("summary_fol") == 1: - new_data = frappe.db.sql("""SELECT name, folder, ROUND(file_size/1024/1024, 2) as size, lft, rgt, - owner - FROM `tabFile` - WHERE docstatus=0 AND is_folder=1 - ORDER BY lft DESC, rgt DESC""", as_dict=1) + # Optimized joined query to get folder details and child file aggregate stats in one go + new_data = frappe.db.sql(""" + SELECT + f.name, f.folder, + ROUND(f.file_size/1024/1024, 2) as size, + f.lft, f.rgt, f.owner, + COALESCE(child_stats.nos, 0) as count, + COALESCE(child_stats.size, 0) as act_size + FROM `tabFile` f + LEFT JOIN ( + SELECT folder, COUNT(name) as nos, ROUND(SUM(file_size)/1024/1024, 2) as size + FROM `tabFile` + WHERE is_folder = 0 AND docstatus = 0 + GROUP BY folder + ) child_stats ON child_stats.folder = f.name + WHERE f.docstatus=0 AND f.is_folder=1 + ORDER BY f.lft DESC, f.rgt DESC + """, as_dict=1) + for row in new_data: - files = frappe.db.sql("""SELECT ROUND(((SUM(file_size))/1024/1024),2) as size, COUNT(name) as nos - FROM `tabFile` WHERE folder='%s'""" %row.name, as_dict=1) - row["act_size"] = files[0].size - row["count"] = files[0].nos - for row in new_data: - data_row = [row.name, row.folder, row.count, row.act_size, row.size, row.lft, row.rgt, - row.owner] + data_row = [row.name, row.folder, row.count, row.act_size, row.size, row.lft, row.rgt, row.owner] data.append(data_row) + else: if filters.get("is_folder") == 1: - data = frappe.db.sql("""SELECT name, file_name, folder, ROUND(file_size/1024/1024,2), lft, rgt, (rgt - lft), - is_home_folder, is_attachments_folder - FROM `tabFile` WHERE docstatus = 0 %s ORDER BY lft, rgt""" % (conditions), as_list=1) + data = frappe.db.sql(""" + SELECT name, file_name, folder, ROUND(file_size/1024/1024,2), lft, rgt, (rgt - lft), + is_home_folder, is_attachments_folder, owner + FROM `tabFile` WHERE docstatus = 0 %s ORDER BY lft, rgt + """ % conditions, as_list=1) else: - query = """SELECT name, IFNULL(file_name, "NO NAME") as file_name, IFNULL(attached_to_doctype, "NO DOCTYPE") as atd, - IFNULL(attached_to_name,"NO DOCNAME") as atn, file_available_on_server, - ROUND(file_size/1024,2) as size, lft, rgt, IFNULL(folder, "NO FOLDER") as folder, is_private, - important_document_for_archive, mark_for_deletion, owner, creation, file_url - FROM `tabFile` WHERE docstatus=0 %s ORDER BY creation""" % (conditions) + query = """ + SELECT + name, IFNULL(file_name, "NO NAME") as file_name, + IFNULL(attached_to_doctype, "NO DOCTYPE") as atd, + IFNULL(attached_to_name,"NO DOCNAME") as atn, + file_available_on_server, + ROUND(file_size/1024, 2) as size, lft, rgt, + IFNULL(folder, "NO FOLDER") as folder, is_private, + important_document_for_archive, mark_for_deletion, owner, creation, file_url + FROM `tabFile` WHERE docstatus=0 %s ORDER BY creation + """ % conditions + fd_data = frappe.db.sql(query, as_dict=1) for d in fd_data: - file_download_name = """%s""" % (d.file_url, d.file_name) - file_download_url = """%s""" % (d.file_url, d.file_url) - row = [d.name, file_download_name, d.atd, d.atn, d.file_available_on_server, d.size, d.lft, d.rgt, d.folder, - d.is_private, d.important_document_for_archive, d.mark_for_deletion, d.owner, d.creation, file_download_url] + file_download_name = d.file_name + file_download_url = d.file_url + + if d.file_url: + file_download_name = f'{d.file_name}' + file_download_url = f'{d.file_url}' + + row = [ + d.name, file_download_name, d.atd, d.atn, d.file_available_on_server, + d.size, d.lft, d.rgt, d.folder, d.is_private, d.important_document_for_archive, + d.mark_for_deletion, d.owner, d.creation, file_download_url + ] data.append(row) return data diff --git a/rohit_common/rohit_common/report/gst_offline_import_format_rigpl/gst_offline_import_format_rigpl.py b/rohit_common/rohit_common/report/gst_offline_import_format_rigpl/gst_offline_import_format_rigpl.py index 48c6569..c39a7fa 100644 --- a/rohit_common/rohit_common/report/gst_offline_import_format_rigpl/gst_offline_import_format_rigpl.py +++ b/rohit_common/rohit_common/report/gst_offline_import_format_rigpl/gst_offline_import_format_rigpl.py @@ -64,59 +64,166 @@ def get_columns(filters): def get_data(filters): si_cond, pi_cond = get_conditions(filters) + data = [] + if filters.get("type") == 'Sales Invoice': if filters.get("item_wise") == 1: - data = frappe.db.sql("""SELECT si.name, si.posting_date, si.base_net_total, - si.base_grand_total,si.customer, si.shipping_address_name, si.taxes_and_charges, - ad.country - FROM `tabSales Invoice` si, `tabSales Taxes and Charges Template` stct, `tabAddress` ad - WHERE stct.name = si.taxes_and_charges AND ad.name = si.shipping_address_name - AND si.docstatus = 1 AND stct.is_export = 1 %s - ORDER BY si.posting_date, si.name""" %(si_cond), as_list=1) + data = frappe.db.sql(""" + SELECT + si.name, si.posting_date, si.base_net_total, + si.base_grand_total, si.customer, si.shipping_address_name, si.taxes_and_charges, + ad.country + FROM `tabSales Invoice` si + JOIN `tabSales Taxes and Charges Template` stct ON stct.name = si.taxes_and_charges + JOIN `tabAddress` ad ON ad.name = si.shipping_address_name + WHERE si.docstatus = 1 AND stct.is_export = 1 %s + ORDER BY si.posting_date, si.name + """ % si_cond, as_list=1) + elif filters.get("hsn") == 1: - data = frappe.db.sql("""SELECT sid.item_code, it.customs_tariff_number, SUM(sid.qty), - it.stock_uom, SUM(sid.base_amount), SUM(sid.base_net_amount) - FROM `tabSales Invoice` si, `tabSales Invoice Item` sid, `tabItem` it - WHERE si.docstatus = 1 AND sid.parent = si.name - AND sid.item_code = it.name %s - GROUP BY sid.item_code - ORDER BY sid.item_code""" %(si_cond), as_list = 1) + data = frappe.db.sql(""" + SELECT + sid.item_code, it.customs_tariff_number, SUM(sid.qty), + it.stock_uom, SUM(sid.base_amount), SUM(sid.base_net_amount) + FROM `tabSales Invoice Item` sid + JOIN `tabSales Invoice` si ON sid.parent = si.name + JOIN `tabItem` it ON sid.item_code = it.name + WHERE si.docstatus = 1 %s + GROUP BY sid.item_code + ORDER BY sid.item_code + """ % si_cond, as_list=1) + else: - data = frappe.db.sql("""SELECT si.posting_date, si.name, si.base_net_total, - si.base_grand_total, si.customer, si.taxes_and_charges, - if(tax_template.is_export = 1, 'Y',''), - if(tax_template.is_export =1, 'Export with Payment of GST or Export without \ - Payment of GST or SEZ or Deemed Export', ''), - if(tax_template.is_export =1, si.shipping_bill_number, ''), - if(tax_template.is_export =1, si.shipping_bill_date, ''), - if(tax_template.is_export =1, si.port_code, ''), - if(tax_template.is_export =1, cn.code, ''), - si.customer_address, ad.address_title, ad.city, ad.pincode, ad.state_rigpl, - ad.gstin, - si.shipping_address_name, ad2.address_title, ad2.city, ad2.pincode, ad2.state_rigpl, - ad2.gstin, if(tax_template.is_local_sales = 1,9, ''), 0, - if(tax_template.is_local_sales = 1,9, ''), 0, - if(tax_template.is_local_sales != 1,18, ''), 0 - FROM `tabSales Invoice` si, `tabAddress` ad, `tabAddress` ad2, `tabCountry` cn, - `tabSales Taxes and Charges Template` tax_template - WHERE ad.name = si.customer_address AND cn.name = ad.country - AND ad2.name = si.shipping_address_name - AND si.taxes_and_charges = tax_template.name - AND si.docstatus != 2 %s""" %(si_cond), as_list=1) + # 1. Fetch Invoice Headers first (Targeted Fetch) + invoice_headers = frappe.db.sql(""" + SELECT + si.posting_date, si.name, si.base_net_total, + si.base_grand_total, si.customer, si.taxes_and_charges, + IF(tax_template.is_export = 1, 'Y', '') as is_export, + IF(tax_template.is_export = 1, 'Export with Payment of GST or Export without Payment of GST or SEZ or Deemed Export', '') as export_text, + IF(tax_template.is_export = 1, si.shipping_bill_number, '') as shipping_bill_number, + IF(tax_template.is_export = 1, si.shipping_bill_date, '') as shipping_bill_date, + IF(tax_template.is_export = 1, si.port_code, '') as port_code, + IF(tax_template.is_export = 1, cn.code, '') as country_code, + si.customer_address, + ad.address_title as billing_name, ad.city as billing_city, ad.pincode as billing_pincode, ad.state_rigpl as billing_state, ad.gstin as billing_gstin, + si.shipping_address_name, + ad2.address_title as shipping_name, ad2.city as shipping_city, ad2.pincode as shipping_pincode, ad2.state_rigpl as shipping_state, ad2.gstin as shipping_gstin + FROM `tabSales Invoice` si + INNER JOIN `tabSales Taxes and Charges Template` tax_template ON si.taxes_and_charges = tax_template.name + LEFT JOIN `tabAddress` ad ON ad.name = si.customer_address + LEFT JOIN `tabAddress` ad2 ON ad2.name = si.shipping_address_name + LEFT JOIN `tabCountry` cn ON cn.name = ad.country + WHERE si.docstatus != 2 %s + ORDER BY si.posting_date, si.name + """ % si_cond, as_dict=1) + + if not invoice_headers: + return [] + + # 2. Bulk fetch only required tax entries (Efficient) + invoice_names = [d['name'] for d in invoice_headers] + taxes_query = """ + SELECT + parent, + rate, + base_tax_amount_after_discount_amount as amount, + (account_head LIKE '%%CGST%%' OR description LIKE '%%CGST%%') as is_cgst, + (account_head LIKE '%%SGST%%' OR description LIKE '%%SGST%%') as is_sgst, + (account_head LIKE '%%IGST%%' OR description LIKE '%%IGST%%') as is_igst + FROM `tabSales Taxes and Charges` + WHERE parent IN ({}) + """.format(", ".join(["%s"] * len(invoice_names))) + + taxes = frappe.db.sql(taxes_query, tuple(invoice_names), as_dict=1) + + # 3. Aggregate in Python (O(N) Complexity) + tax_map = {} + for t in taxes: + p = t['parent'] + if p not in tax_map: + tax_map[p] = {'cr': 0, 'ca': 0, 'sr': 0, 'sa': 0, 'ir': 0, 'ia': 0} + + if t['is_cgst']: + tax_map[p]['cr'] = max(tax_map[p]['cr'], t['rate']) + tax_map[p]['ca'] += t['amount'] + elif t['is_sgst']: + tax_map[p]['sr'] = max(tax_map[p]['sr'], t['rate']) + tax_map[p]['sa'] += t['amount'] + elif t['is_igst']: + tax_map[p]['ir'] = max(tax_map[p]['ir'], t['rate']) + tax_map[p]['ia'] += t['amount'] + + # 4. Assembly + for d in invoice_headers: + t = tax_map.get(d['name'], {'cr': 0, 'ca': 0, 'sr': 0, 'sa': 0, 'ir': 0, 'ia': 0}) + row = [ + d['posting_date'], d['name'], d['base_net_total'], d['base_grand_total'], + d['customer'], d['taxes_and_charges'], d.get('is_export'), + d.get('export_text'), + d.get('shipping_bill_number'), + d.get('shipping_bill_date'), + d.get('port_code'), + d.get('country_code'), + d['customer_address'], d['billing_name'], d['billing_city'], d['billing_pincode'], d['billing_state'], d['billing_gstin'], + d['shipping_address_name'], d['shipping_name'], d['shipping_city'], d['shipping_pincode'], d['shipping_state'], d['shipping_gstin'], + t['cr'], t['ca'], t['sr'], t['sa'], t['ir'], t['ia'] + ] + data.append(row) + elif filters.get("type") == 'Purchase Invoice': - data = frappe.db.sql("""SELECT pi.posting_date, pi.name, - pi.bill_date, pi.bill_no, pi.base_net_total, - pi.base_grand_total, pi.supplier, pi.taxes_and_charges, - IFNULL(adb.gstin, "NA"), IFNULL(ads.state_rigpl, "X"), - if(tax_template.is_import = 1, 'Y','N'), 'Input', - 9,0,0 - FROM `tabPurchase Invoice` pi, `tabAddress` ads, - `tabAddress` adb, - `tabPurchase Taxes and Charges Template` tax_template - WHERE adb.name = pi.supplier_address - AND ads.name = pi.shipping_address - AND pi.taxes_and_charges = tax_template.name - AND pi.docstatus != 2 %s""" %(pi_cond), as_list=1) + invoice_headers = frappe.db.sql(""" + SELECT + pi.posting_date, pi.name, + pi.bill_date, pi.bill_no, pi.base_net_total, + pi.base_grand_total, pi.supplier, pi.taxes_and_charges, + IFNULL(adb.gstin, "NA") as gstin, + IFNULL(ads.state_rigpl, "X") as state, + IF(tax_template.is_import = 1, 'Y', 'N') as is_import + FROM `tabPurchase Invoice` pi + INNER JOIN `tabPurchase Taxes and Charges Template` tax_template ON pi.taxes_and_charges = tax_template.name + LEFT JOIN `tabAddress` adb ON adb.name = pi.supplier_address + LEFT JOIN `tabAddress` ads ON ads.name = pi.shipping_address + WHERE pi.docstatus != 2 %s + ORDER BY pi.posting_date, pi.name + """ % pi_cond, as_dict=1) + + if not invoice_headers: + return [] + + invoice_names = [d['name'] for d in invoice_headers] + taxes_query = """ + SELECT + parent, + base_tax_amount_after_discount_amount as amount, + (account_head LIKE '%%CGST%%' OR description LIKE '%%CGST%%') as is_cgst, + (account_head LIKE '%%SGST%%' OR description LIKE '%%SGST%%') as is_sgst, + (account_head LIKE '%%IGST%%' OR description LIKE '%%IGST%%') as is_igst + FROM `tabPurchase Taxes and Charges` + WHERE parent IN ({}) + """.format(", ".join(["%s"] * len(invoice_names))) + + taxes = frappe.db.sql(taxes_query, tuple(invoice_names), as_dict=1) + + tax_map = {} + for t in taxes: + p = t['parent'] + if p not in tax_map: + tax_map[p] = {'ca': 0, 'sa': 0, 'ia': 0} + if t['is_cgst']: tax_map[p]['ca'] += t['amount'] + elif t['is_sgst']: tax_map[p]['sa'] += t['amount'] + elif t['is_igst']: tax_map[p]['ia'] += t['amount'] + + for d in invoice_headers: + t = tax_map.get(d['name'], {'ca': 0, 'sa': 0, 'ia': 0}) + row = [ + d['posting_date'], d['name'], d['bill_date'], d['bill_no'], + d['base_net_total'], d['base_grand_total'], d['supplier'], d['taxes_and_charges'], + d['gstin'], d['state'], d['is_import'], 'Input', + t['ca'], t['sa'], t['ia'] + ] + data.append(row) + return data diff --git a/rohit_common/rohit_common/report/gstr2_analysis_rigpl/gstr2_analysis_rigpl.py b/rohit_common/rohit_common/report/gstr2_analysis_rigpl/gstr2_analysis_rigpl.py index 128170d..9110af2 100644 --- a/rohit_common/rohit_common/report/gstr2_analysis_rigpl/gstr2_analysis_rigpl.py +++ b/rohit_common/rohit_common/report/gstr2_analysis_rigpl/gstr2_analysis_rigpl.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import frappe -from frappe.utils import getdate +from frappe.utils import getdate, flt from datetime import datetime @@ -20,93 +20,171 @@ def get_data(filters): gst_set = frappe.get_doc("GST Settings", "GST Setting") gst_taxes = [] for d in gst_set.gst_accounts: - if d.get("cgst_account", "") and "Input" in d.get("cgst_account", "No"): - gst_taxes.append(d.cgst_account) - if d.get("sgst_account", "") and "Input" in d.get("sgst_account", "No"): - gst_taxes.append(d.sgst_account) - if d.get("igst_account", "") and "Input" in d.get("igst_account", "No"): - gst_taxes.append(d.igst_account) - if d.get("cess_account", "") and "Input" in d.get("cess_account", "No"): - gst_taxes.append(d.cess_account) - main_gl = [] - for tax in gst_taxes: - gl_entries = get_gl_entries(tax, cond) - for gl in gl_entries: - gl = get_party_details(gl) - gl = get_gstr2_details(gl) - cgst, sgst, igst, cess = 0, 0, 0, 0 - if "CGST" in tax: - if gl.debit > 0: - cgst = gl.debit - else: - cgst = -1 * gl.credit - if "IGST" in tax: - if gl.debit > 0: - igst = gl.debit - else: - igst = -1 * gl.credit - if "SGST" in tax: - if gl.debit > 0: - sgst = gl.debit - else: - sgst = -1 * gl.credit - if "CESS" in tax: - if gl.debit > 0: - cess = gl.debit - else: - cess = -1 * gl.credit - gstr2_tot_tax = gl.get("gstr2_igst", 0) + gl.get("gstr2_cgst", 0) + gl.get("gstr2_sgst", 0) + \ - gl.get("gstr2_cess", 0) - doc_tot_tax = igst + cgst + sgst + cess - gl["gstr2_tot_tax"] = gstr2_tot_tax - gl["doc_tot_tax"] = doc_tot_tax - gl["doc_igst"] = igst - gl["doc_sgst"] = sgst - gl["doc_cgst"] = cgst - gl["doc_cess"] = cess - found = 0 - for d in main_gl: - if d.get("voucher_type") == gl.get("voucher_type") and d.get("voucher_no") == gl.get("voucher_no"): - d["doc_tot_tax"] += gl.get("doc_tot_tax") - d["doc_igst"] += gl.get("doc_igst") - d["doc_sgst"] += gl.get("doc_sgst") - d["doc_cgst"] += gl.get("doc_cgst") - d["doc_cess"] += gl.get("doc_cess") - found = 1 - if found != 1: - main_gl.append(gl.copy()) - for gl in main_gl: - row = [gl.posting_date, gl.voucher_no, gl.get("party", ""), - gl.get("gstr1_stat", 0), gl.get("gstr1_fil_date", "1900-01-01"), - gl.get("period_gstr1", ""), gl.get("gstr2b_date", "1900-01-01"), - gl.get("gstr2b_period", "X"), gl.get("gstr3b_stat", 0), - gl.get("party_gstin", ""), gl.get("note_type", "X"), gl.get("sup_inv_no", ""), - gl.get("sup_inv_date", "1900-01-01"), - gl.get("gstr2_gt", 0), gl.get("gstr2_nt", 0), gl.get("gstr2_igst", 0), gl.get("gstr2_cgst", 0), - gl.get("gstr2_sgst", 0), gl.get("gstr2_cess", 0), gl.get("gstr2_tot_tax", 0), gl.get("doc_gt", 0), - gl.get("doc_nt", 0), gl.get("doc_igst", 0), gl.get("doc_cgst", 0), gl.get("doc_sgst", 0), - gl.get("doc_cess", 0), gl.get("doc_tot_tax", 0), gl.voucher_type, gl.get("party_type", ""), - gl.get("gstr2a_name", "")] + for field in ["cgst_account", "sgst_account", "igst_account", "cess_account"]: + acc = d.get(field) + if acc and "Input" in acc: + gst_taxes.append(acc) + + gst_taxes = list(set(gst_taxes)) + if not gst_taxes: + return [] + + # Fetch all relevant GL entries first + all_gl_entries = frappe.db.sql(""" + SELECT + name, posting_date, account, debit_in_account_currency as debit, + credit_in_account_currency as credit, voucher_type, voucher_no + FROM `tabGL Entry` gl + WHERE docstatus = 1 AND gl.account IN (%s) %s + ORDER BY gl.posting_date, gl.name + """ % (', '.join(['%s']*len(gst_taxes)), cond), tuple(gst_taxes), as_dict=1) + + if not all_gl_entries: + return [] + + # Collect unique vouchers for bulk fetching + vouchers_by_type = {} + for gl in all_gl_entries: + vouchers_by_type.setdefault(gl.voucher_type, set()).add(gl.voucher_no) + + # Bulk fetch Purchase Invoice details + pi_details = {} + if "Purchase Invoice" in vouchers_by_type: + pi_data = frappe.get_all("Purchase Invoice", + filters={"name": ["in", list(vouchers_by_type["Purchase Invoice"])]}, + fields=["name", "supplier", "supplier_gstin", "bill_no", "bill_date", + "base_grand_total", "base_net_total", "shipping_address"]) + pi_details = {d.name: d for d in pi_data} + + # Bulk fetch Non-PI Grand Totals (total_debit) + non_pi_totals = {} + for vtype, vnos in vouchers_by_type.items(): + if vtype != "Purchase Invoice": + try: + # Standard vouchers have a total_debit or base_grand_total field + fields = ["name", "total_debit"] + if vtype == "Journal Entry": + fields = ["name", "total_debit"] + + totals_data = frappe.get_all(vtype, filters={"name": ["in", list(vnos)]}, fields=fields) + for t in totals_data: + non_pi_totals[(vtype, t.name)] = t.get(fields[1], 0) + except Exception: + pass + + # Bulk fetch GSTR2 details + gstr2_map = get_bulk_gstr2_details(vouchers_by_type, pi_details) + + main_gl_map = {} # Key: (voucher_type, voucher_no) + + for gl in all_gl_entries: + key = (gl.voucher_type, gl.voucher_no) + + if key not in main_gl_map: + # Initialize entry with basic details and party info + entry = gl.copy() + if gl.voucher_type == "Purchase Invoice": + pi = pi_details.get(gl.voucher_no) + if pi: + entry.update({ + "party_type": "Supplier", + "party": pi.supplier, + "party_gstin": pi.supplier_gstin, + "sup_inv_no": pi.bill_no, + "sup_inv_date": pi.bill_date, + "doc_gt": pi.base_grand_total, + "doc_nt": pi.base_net_total + }) + else: + entry["doc_gt"] = non_pi_totals.get((gl.voucher_type, gl.voucher_no), 0) + + # Apply GSTR2 data if found + gstr2_info = gstr2_map.get(key) + if gstr2_info: + mf = -1 if gstr2_info.note_type == "Credit Note" else 1 + entry.update({ + "gstr1_stat": gstr2_info.filing_status_gstr1, + "gstr2b_date": gstr2_info.gstr2b_date, + "gstr2b_period": gstr2_info.gstr2b_period, + "period_gstr1": gstr2_info.filing_period_gstr1, + "note_type": gstr2_info.note_type, + "gstr3b_stat": 1 if gstr2_info.note_type == "Bill of Entry" else gstr2_info.filing_status_gstr3b, + "gstr1_fil_date": gstr2_info.supplier_invoice_date if gstr2_info.note_type == "Bill of Entry" else gstr2_info.filing_date_gstr1, + "gstr2_gt": gstr2_info.grand_total * mf, + "gstr2_nt": gstr2_info.taxable_value * mf, + "gstr2_igst": gstr2_info.igst_amount * mf, + "gstr2_cgst": gstr2_info.cgst_amount * mf, + "gstr2_sgst": gstr2_info.sgst_amount * mf, + "gstr2_cess": gstr2_info.cess_amount * mf, + "gstr2a_name": gstr2_info.parent + }) + + if gstr2_info.note_type == "Bill of Entry": + entry["sup_inv_date"] = gstr2_info.supplier_invoice_date + entry["sup_inv_no"] = gstr2_info.supplier_invoice_no + entry["party_gstin"] = gstr2_info.party_gstin + + # Initialize tax buckets + for tax_field in ["doc_igst", "doc_sgst", "doc_cgst", "doc_cess", "doc_tot_tax"]: + entry[tax_field] = 0 + + main_gl_map[key] = entry + + # Accumulate tax from the current GL entry + entry = main_gl_map[key] + tax_val = gl.debit if gl.debit > 0 else -gl.credit + + if "IGST" in gl.account: + entry["doc_igst"] += tax_val + elif "CGST" in gl.account: + entry["doc_cgst"] += tax_val + elif "SGST" in gl.account: + entry["doc_sgst"] += tax_val + elif "CESS" in gl.account: + entry["doc_cess"] += tax_val + + entry["doc_tot_tax"] += tax_val + + # Final Row Assembly + for gl in main_gl_map.values(): + gstr2_tot_tax = flt(gl.get("gstr2_igst", 0)) + flt(gl.get("gstr2_cgst", 0)) + \ + flt(gl.get("gstr2_sgst", 0)) + flt(gl.get("gstr2_cess", 0)) + + row = [ + gl.posting_date, gl.voucher_no, gl.get("party", ""), + gl.get("gstr1_stat", 0), gl.get("gstr1_fil_date", "1900-01-01"), + gl.get("period_gstr1", ""), gl.get("gstr2b_date", "1900-01-01"), + gl.get("gstr2b_period", "X"), gl.get("gstr3b_stat", 0), + gl.get("party_gstin", ""), gl.get("note_type", "X"), gl.get("sup_inv_no", ""), + gl.get("sup_inv_date", "1900-01-01"), + gl.get("gstr2_gt", 0), gl.get("gstr2_nt", 0), gl.get("gstr2_igst", 0), gl.get("gstr2_cgst", 0), + gl.get("gstr2_sgst", 0), gl.get("gstr2_cess", 0), gstr2_tot_tax, gl.get("doc_gt", 0), + gl.get("doc_nt", 0), gl.get("doc_igst", 0), gl.get("doc_cgst", 0), gl.get("doc_sgst", 0), + gl.get("doc_cess", 0), gl.get("doc_tot_tax", 0), gl.voucher_type, gl.get("party_type", ""), + gl.get("gstr2a_name", "") + ] data.append(row) else: + # GSTIN Wise logic remains mostly as is but uses parameter binding ret_period = get_ret_period(filters) + cond = "" if getdate(filters.get("from_date")) < datetime.strptime("01-07-2020", "%d-%m-%Y").date(): - cond = f" AND gri.filing_period_gstr1 = '{ret_period}' AND gri.gstr2b_period IS NULL" + cond = " AND gri.filing_period_gstr1 = %(ret_period)s AND gri.gstr2b_period IS NULL" else: - cond = f" AND gri.gstr2b_period = '{ret_period}'" - query = """SELECT gr.name, gri.gstr2b_period, gri.party_type, gri.party, gri.party_gstin, gri.note_type, - gri.supplier_invoice_no, gri.supplier_invoice_date, gri.linked_document_type, gri.linked_document_name, - gri.posting_date, gri.grand_total, gri.taxable_value, gri.igst_amount, gri.cgst_amount, gri.sgst_amount, - gri.cess_amount, gri.filing_date_gstr1, gri.gstr2b_date, gri.filing_status_gstr3b, gri.filing_period_gstr1 - FROM `tabGSTR2A RIGPL` gr, `tabGSTR2 Return Invoices` gri - WHERE gri.parent = gr.name AND gr.docstatus < 2 %s - ORDER BY gri.party, gri.posting_date""" % cond - gstr2ab = frappe.db.sql(query, as_dict=1) + cond = " AND gri.gstr2b_period = %(ret_period)s" + + gstr2ab = frappe.db.sql(""" + SELECT gr.name, gri.gstr2b_period, gri.party_type, gri.party, gri.party_gstin, gri.note_type, + gri.supplier_invoice_no, gri.supplier_invoice_date, gri.linked_document_type, gri.linked_document_name, + gri.posting_date, gri.grand_total, gri.taxable_value, gri.igst_amount, gri.cgst_amount, gri.sgst_amount, + gri.cess_amount, gri.filing_date_gstr1, gri.gstr2b_date, gri.filing_status_gstr3b, gri.filing_period_gstr1 + FROM `tabGSTR2A RIGPL` gr, `tabGSTR2 Return Invoices` gri + WHERE gri.parent = gr.name AND gr.docstatus < 2 %s + ORDER BY gri.party, gri.posting_date + """ % cond, {"ret_period": ret_period}, as_dict=1) + for d in gstr2ab: - if d.note_type == "Credit Note": - mf = -1 - else: - mf = 1 + mf = -1 if d.note_type == "Credit Note" else 1 row = [d.posting_date, d.linked_document_name, d.party, 1, d.filing_date_gstr1, d.filing_period_gstr1, d.gstr2b_date, d.gstr2b_period, d.filing_status_gstr3b, d.party_gstin, d.note_type, d.supplier_invoice_no, d.supplier_invoice_date, d.grand_total*mf, d.taxable_value*mf, @@ -117,6 +195,62 @@ def get_data(filters): return data +def get_bulk_gstr2_details(vouchers_by_type, pi_details): + gstr2_map = {} + + # Pre-fetch address GSTINs + address_map = {} + relevant_addresses = [d.shipping_address for d in pi_details.values() if d.shipping_address] + if relevant_addresses: + addr_data = frappe.get_all("Address", + filters={"name": ["in", relevant_addresses]}, + fields=["name", "gstin"]) + address_map = {d.name: d.gstin for d in addr_data} + + # Gather all possible matching numbers (Voucher Nos + Bill Nos) + matches = [] + for v_list in vouchers_by_type.values(): + matches.extend(list(v_list)) + for pi in pi_details.values(): + if pi.bill_no: + matches.append(pi.bill_no) + + if not matches: + return {} + + # Fetch ALL potential GSTR2 matches in one go + res = frappe.db.sql(""" + SELECT gstri.*, gstr.gstin as receiver_gstin + FROM `tabGSTR2 Return Invoices` gstri + JOIN `tabGSTR2A RIGPL` gstr ON gstri.parent = gstr.name + WHERE gstr.docstatus != 2 + AND (gstri.linked_document_name IN %(matches)s OR gstri.supplier_invoice_no IN %(matches)s) + """, {"matches": list(set(matches))}, as_dict=1) + + # Replicate the strict mapping logic in Python memory + for vtype, vnos_set in vouchers_by_type.items(): + for vno in vnos_set: + if vtype == "Purchase Invoice": + pi = pi_details.get(vno) + if not pi: continue + self_gstin = address_map.get(pi.shipping_address) + + # Check for a match using the 4 strict PI rules + for d in res: + if d.receiver_gstin == self_gstin and d.party == pi.supplier and d.party_type == "Supplier": + if d.linked_document_name == vno or (pi.bill_no and d.supplier_invoice_no == pi.bill_no): + gstr2_map[(vtype, vno)] = d + break + else: + # Standard matching for Non-PI vouchers + for d in res: + if d.linked_document_type == vtype and d.linked_document_name == vno: + gstr2_map[(vtype, vno)] = d + break + + return gstr2_map + + def get_ret_period(filters): frm_date = getdate(filters.get("from_date")) frm_mth = frm_date.month @@ -136,80 +270,6 @@ def get_ret_period(filters): return datetime.strftime(frm_date, "%b") + "-" + datetime.strftime(frm_date, "%y") -def get_gstr2_details(gl): - cond = "" - cond_or = "" - if gl.voucher_type == "Purchase Invoice": - cond_or += f" AND (gstri.supplier_invoice_no = '{gl.sup_inv_no}' OR " \ - f"gstri.linked_document_name = '{gl.voucher_no}')" - self_add = frappe.get_value(gl.voucher_type, gl.voucher_no, "shipping_address") - self_gstin = frappe.get_value("Address", self_add, "gstin") - cond += f" AND gstr.gstin = '{self_gstin}'" - cond += f" AND gstri.party = '{gl.party}' AND gstri.party_type = '{gl.party_type}'" - else: - cond += f" AND gstri.linked_document_type = '{gl.voucher_type}' AND " \ - f"gstri.linked_document_name = '{gl.voucher_no}'" - - query = """SELECT gstr.name, gstri.filing_status_gstr1, gstri.filing_date_gstr1, gstri.filing_status_gstr3b, - gstri.filing_period_gstr1, gstri.note_type, gstri.grand_total, gstri.taxable_value, gstri.cgst_amount, - gstri.sgst_amount, gstri.igst_amount, gstri.cess_amount, gstri.supplier_invoice_no, gstri.supplier_invoice_date, - gstri.party_gstin, gstri.gstr2b_date, gstri.gstr2b_period - FROM `tabGSTR2A RIGPL` gstr, `tabGSTR2 Return Invoices` gstri - WHERE gstr.docstatus != 2 AND gstri.parent = gstr.name %s %s""" % (cond, cond_or) - gstr2a_list = frappe.db.sql(query, as_dict=1) - if gstr2a_list: - gl["gstr1_stat"] = gstr2a_list[0].filing_status_gstr1 - if gstr2a_list[0].note_type == "Bill of Entry": - mf = 1 - gl["gstr3b_stat"] = 1 - gl["gstr1_fil_date"] = gstr2a_list[0].supplier_invoice_date - gl["sup_inv_date"] = gstr2a_list[0].supplier_invoice_date - gl["sup_inv_no"] = gstr2a_list[0].supplier_invoice_no - gl["party_gstin"] = gstr2a_list[0].party_gstin - elif gstr2a_list[0].note_type == "Credit Note": - mf = -1 - else: - mf = 1 - gl["gstr3b_stat"] = gstr2a_list[0].filing_status_gstr3b - gl["gstr1_fil_date"] = gstr2a_list[0].filing_date_gstr1 - - gl["gstr2b_date"] = gstr2a_list[0].gstr2b_date - gl["gstr2b_period"] = gstr2a_list[0].gstr2b_period - gl["period_gstr1"] = gstr2a_list[0].filing_period_gstr1 - gl["note_type"] = gstr2a_list[0].note_type - gl["gstr2_gt"] = gstr2a_list[0].grand_total * mf - gl["gstr2_nt"] = gstr2a_list[0].taxable_value * mf - gl["gstr2_cgst"] = gstr2a_list[0].cgst_amount * mf - gl["gstr2_sgst"] = gstr2a_list[0].sgst_amount * mf - gl["gstr2_igst"] = gstr2a_list[0].igst_amount * mf - gl["gstr2_cess"] = gstr2a_list[0].cess_amount * mf - gl["gstr2a_name"] = gstr2a_list[0].name - return gl - - -def get_party_details(gl_dict): - pid = frappe.get_doc(gl_dict.voucher_type, gl_dict.voucher_no) - if gl_dict.voucher_type == "Purchase Invoice": - gl_dict["party_type"] = "Supplier" - gl_dict["party"] = pid.supplier - gl_dict["party_gstin"] = pid.supplier_gstin - gl_dict["sup_inv_no"] = pid.bill_no - gl_dict["sup_inv_date"] = pid.bill_date - gl_dict["doc_gt"] = pid.base_grand_total - gl_dict["doc_nt"] = pid.base_net_total - else: - gl_dict["doc_gt"] = pid.total_debit - return gl_dict - - -def get_gl_entries(tax, conditions): - cond_acc = f" AND gl.account = '{tax}'" - gl_map = frappe.db.sql("""SELECT gl.name, gl.posting_date, gl.account, gl.debit_in_account_currency as debit, - gl.credit_in_account_currency as credit, gl.voucher_type, gl.voucher_no FROM `tabGL Entry` gl - WHERE docstatus = 1 %s %s ORDER BY gl.posting_date, gl.name""" % (cond_acc, conditions), as_dict=1) - return gl_map - - def get_columns(filters): columns = [ "Posting Date:Date:80", diff --git a/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py b/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py index ae0ee04..f766091 100644 --- a/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py +++ b/rohit_common/rohit_common/report/rigpl_general_ledger/rigpl_general_ledger.py @@ -213,7 +213,7 @@ def get_gl_entries(filters, accounting_dimensions): as_dict=1, ) - party_name_map = get_party_name_map() + party_name_map = get_party_name_map(gl_entries) for gl_entry in gl_entries: if gl_entry.party_type and gl_entry.party: @@ -322,46 +322,72 @@ def get_conditions(filters): return " and {}".format(" and ".join(conditions)) if conditions else "" -def get_party_name_map(): - party_map = {} +def get_party_name_map(gl_entries): + party_map = {} + party_to_fetch = {} + + # Collect only parties present in the current GL entries + for g in gl_entries: + if g.party_type and g.party: + party_to_fetch.setdefault(g.party_type, set()).add(g.party) + + # Bulk fetch names only for relevant parties + for party_type, parties in party_to_fetch.items(): + if not parties: + continue + + name_field = "name" + if party_type == "Customer": + name_field = "customer_name" + elif party_type == "Supplier": + name_field = "supplier_name" + elif party_type == "Employee": + name_field = "employee_name" + else: + # Fallback for other party types + meta = frappe.get_meta(party_type) + if meta.has_field(frappe.scrub(party_type) + "_name"): + name_field = frappe.scrub(party_type) + "_name" + + party_data = frappe.get_all(party_type, + filters={"name": ["in", list(parties)]}, + fields=["name", name_field]) + + party_map[party_type] = {p.name: p.get(name_field) for p in party_data} + + return party_map - customers = frappe.get_all("Customer", fields=["name", "customer_name"]) - party_map["Customer"] = {c.name: c.customer_name for c in customers} - suppliers = frappe.get_all("Supplier", fields=["name", "supplier_name"]) - party_map["Supplier"] = {s.name: s.supplier_name for s in suppliers} - - employees = frappe.get_all("Employee", fields=["name", "employee_name"]) - party_map["Employee"] = {e.name: e.employee_name for e in employees} - return party_map +def get_accounts_with_children(accounts): + if not isinstance(accounts, list): + accounts = [d.strip() for d in accounts.strip().split(",") if d] + if not accounts: + return -def get_accounts_with_children(accounts): - if not isinstance(accounts, list): - accounts = [d.strip() for d in accounts.strip().split(",") if d] - - if not accounts: - return - - doctype = frappe.qb.DocType("Account") - accounts_data = ( - frappe.qb.from_(doctype) - .select(doctype.lft, doctype.rgt) - .where(doctype.name.isin(accounts)) - .run(as_dict=True) - ) + doctype = frappe.qb.DocType("Account") + accounts_data = ( + frappe.qb.from_(doctype) + .select(doctype.lft, doctype.rgt) + .where(doctype.name.isin(accounts)) + .run(as_dict=True) + ) - conditions = [] - for account in accounts_data: - conditions.append((doctype.lft >= account.lft) & (doctype.rgt <= account.rgt)) + conditions = [] + for account in accounts_data: + conditions.append((doctype.lft >= account.lft) & (doctype.rgt <= account.rgt)) - return frappe.qb.from_(doctype).select(doctype.name).where(Criterion.any(conditions)).run(pluck=True) + return frappe.qb.from_(doctype).select(doctype.name).where(Criterion.any(conditions)).run(pluck=True) def set_bill_no(gl_entries): - inv_details = get_supplier_invoice_details() - for gl in gl_entries: - gl["bill_no"] = inv_details.get(gl.get("against_voucher"), "") + vouchers = [g.get("against_voucher") for g in gl_entries if g.get("against_voucher")] + if not vouchers: + return + + inv_details = get_supplier_invoice_details(vouchers) + for gl in gl_entries: + gl["bill_no"] = inv_details.get(gl.get("against_voucher"), "") def get_translated_labels_for_totals(): @@ -610,11 +636,16 @@ def contains_label(s, label): return data -def get_supplier_invoice_details(): +def get_supplier_invoice_details(vouchers): inv_details = {} + if not vouchers: + return inv_details + for d in frappe.db.sql( """ select name, bill_no from `tabPurchase Invoice` - where docstatus = 1 and bill_no is not null and bill_no != '' """, + where docstatus = 1 and bill_no is not null and bill_no != '' + and name in ({0}) """.format(", ".join(["%s"] * len(vouchers))), + tuple(vouchers), as_dict=1, ): inv_details[d.name] = d.bill_no diff --git a/rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.py b/rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.py index 3462171..e77dabe 100644 --- a/rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.py +++ b/rohit_common/rohit_common/report/rigpl_legacy_gstr1/rigpl_legacy_gstr1.py @@ -202,20 +202,18 @@ def get_invoice_items(self): where parent in (%s) """ % (self.doctype, ', '.join(['%s']*len(self.invoices))), tuple(self.invoices), as_dict=1) + # Aggregate net amounts in a single pass to avoid O(N^2) behavior for d in items: - if d.item_code not in self.invoice_items.get(d.parent, {}): - self.invoice_items.setdefault(d.parent, {}).setdefault(d.item_code, - sum((i.get('taxable_value', 0) or i.get('base_net_amount', 0)) for i in items - if i.item_code == d.item_code and i.parent == d.parent)) + item_val = flt(d.taxable_value) or flt(d.base_net_amount) + self.invoice_items.setdefault(d.parent, {}).setdefault(d.item_code, 0) + self.invoice_items[d.parent][d.item_code] += item_val - item_tax_rate = {} - - if d.item_tax_rate: - item_tax_rate = json.loads(d.item_tax_rate) - - for account, rate in item_tax_rate.items(): - tax_rate_dict = self.item_tax_rate.setdefault(d.parent, {}).setdefault(d.item_code, []) - tax_rate_dict.append(rate) + if d.item_tax_rate: + item_tax_rate = json.loads(d.item_tax_rate) + for account, rate in item_tax_rate.items(): + tax_rate_list = self.item_tax_rate.setdefault(d.parent, {}).setdefault(d.item_code, []) + if rate not in tax_rate_list: + tax_rate_list.append(rate) def get_items_based_on_tax_rate(self): self.tax_details = frappe.db.sql(""" @@ -234,23 +232,28 @@ def get_items_based_on_tax_rate(self): self.cgst_sgst_invoices = [] unidentified_gst_accounts = [] - unidentified_gst_accounts_invoice = [] + unidentified_gst_accounts_invoice = set() + + # Pre-cache GST account types for faster lookup + cgst_accs = set(self.gst_accounts.get('cgst_account', [])) + sgst_accs = set(self.gst_accounts.get('sgst_account', [])) + igst_accs = set(self.gst_accounts.get('igst_account', [])) + cess_accs = set(self.gst_accounts.get('cess_account', [])) + for parent, account, item_wise_tax_detail, tax_amount in self.tax_details: - if account in self.gst_accounts.cess_account: - self.invoice_cess.setdefault(parent, tax_amount) + if account in cess_accs: + self.invoice_cess.setdefault(parent, 0) + self.invoice_cess[parent] += flt(tax_amount) else: if item_wise_tax_detail: try: item_wise_tax_detail = json.loads(item_wise_tax_detail) - cgst_or_sgst = False - if account in self.gst_accounts.cgst_account \ - or account in self.gst_accounts.sgst_account: - cgst_or_sgst = True - - if not (cgst_or_sgst or account in self.gst_accounts.igst_account): + is_cgst_sgst = (account in cgst_accs or account in sgst_accs) + + if not (is_cgst_sgst or account in igst_accs): if "gst" in account.lower() and account not in unidentified_gst_accounts: unidentified_gst_accounts.append(account) - unidentified_gst_accounts_invoice.append(parent) + unidentified_gst_accounts_invoice.add(parent) continue for item_code, tax_amounts in item_wise_tax_detail.items(): @@ -264,8 +267,9 @@ def get_items_based_on_tax_rate(self): tax_rate = float(tax_amounts) except Exception: tax_rate = 0 + if tax_rate: - if cgst_or_sgst: + if is_cgst_sgst: tax_rate *= 2 if parent not in self.cgst_sgst_invoices: self.cgst_sgst_invoices.append(parent) @@ -274,17 +278,20 @@ def get_items_based_on_tax_rate(self): .setdefault(parent, {}).setdefault(tax_rate, []) if item_code not in rate_based_dict: rate_based_dict.append(item_code) - except ValueError: + except (ValueError, TypeError): continue + if unidentified_gst_accounts: frappe.msgprint(_("Following accounts might be selected in GST Settings:") + "
" + "
".join(unidentified_gst_accounts), alert=True) # Build itemised tax for export invoices where tax table is blank + # Use cached invoice data from self.invoices instead of hitting the database for invoice, items in iteritems(self.invoice_items): - if invoice not in self.items_based_on_tax_rate and invoice not in unidentified_gst_accounts_invoice \ - and frappe.db.get_value(self.doctype, invoice, "export_type") == "Without Payment of Tax": - self.items_based_on_tax_rate.setdefault(invoice, {}).setdefault(0, items.keys()) + inv_details = self.invoices.get(invoice) + if invoice not in self.items_based_on_tax_rate and invoice not in unidentified_gst_accounts_invoice \ + and inv_details and inv_details.get("export_type") == "Without Payment of Tax": + self.items_based_on_tax_rate.setdefault(invoice, {}).setdefault(0, list(items.keys())) def get_columns(self): self.tax_columns = [ diff --git a/rohit_common/rohit_common/report/stock_ledger_normal/stock_ledger_normal.py b/rohit_common/rohit_common/report/stock_ledger_normal/stock_ledger_normal.py index 68f16a5..528d1c8 100644 --- a/rohit_common/rohit_common/report/stock_ledger_normal/stock_ledger_normal.py +++ b/rohit_common/rohit_common/report/stock_ledger_normal/stock_ledger_normal.py @@ -46,75 +46,101 @@ def get_columns(): def get_sl_entries(filters): - conditions, conditions_item = get_conditions(filters) - - temp_data = frappe.db.sql("""SELECT sle.posting_date, sle.posting_time, sle.item_code, it.description, - sle.actual_qty, sle.qty_after_transaction, sle.warehouse, sle.voucher_no, sle.voucher_type, - 'X', sle.name, 'X' FROM `tabStock Ledger Entry` sle, `tabItem` it WHERE sle.is_cancelled = "No" - AND sle.item_code = it.name %s %s ORDER BY sle.posting_date DESC, sle.posting_time DESC, - sle.name DESC""" % (conditions, conditions_item), as_dict=1) - + conditions, params = get_conditions(filters) + + # Secure and efficient bulk query with explicit JOIN + temp_data = frappe.db.sql(f""" + SELECT + sle.posting_date, sle.posting_time, sle.item_code, it.description, + sle.actual_qty, sle.qty_after_transaction, sle.warehouse, + sle.voucher_no, sle.voucher_type, sle.name + FROM `tabStock Ledger Entry` sle + INNER JOIN `tabItem` it ON sle.item_code = it.name + WHERE sle.is_cancelled = 'No' + {conditions} + ORDER BY sle.posting_date DESC, sle.posting_time DESC, sle.name DESC + """, params, as_dict=1) + + if not temp_data: + return [] + + # O(N) Batch Processing Strategy + voucher_map = {} for d in temp_data: - d["posting_time"] = d["posting_time"] - datetime.timedelta(microseconds=d["posting_time"].microseconds) - if d.voucher_type in ('Delivery Note', 'Sales Invoice'): - dn_doc = frappe.get_doc(d.voucher_type, d.voucher_no) - d["linked_name"] = dn_doc.customer - d["link_type"] = "Customer" - - elif d.voucher_type in ('Purchase Receipt', 'Purchase Invoice'): - dn_doc = frappe.get_doc(d.voucher_type, d.voucher_no) - d["linked_name"] = dn_doc.supplier - d["link_type"] = "Supplier" - elif d.voucher_type == "Stock Entry": - dn_doc = frappe.get_doc(d.voucher_type, d.voucher_no) - if dn_doc.process_job_card is not None: - d["link_type"] = "Process Job Card RIGPL" - d["linked_name"] = dn_doc.process_job_card - elif dn_doc.sales_order is not None: - d["link_type"] = "Sales Order" - d["linked_name"] = dn_doc.sales_order - elif dn_doc.delivery_note_no is not None: - d["link_type"] = "Delivery Note" - d["linked_name"] = dn_doc.delivery_note_no - elif dn_doc.sales_invoice_no is not None: - d["link_type"] = "Sales Invoice" - d["linked_name"] = dn_doc.sales_invoice_no - elif dn_doc.purchase_order is not None: - d["link_type"] = "Purchase Order" - d["linked_name"] = dn_doc.purchase_order - elif dn_doc.purchase_receipt_no is not None: - d["link_type"] = "Purchase Receipt" - d["linked_name"] = dn_doc.purchase_receipt_no - else: - d["link_type"] = None - d["linked_name"] = None + vt = d.voucher_type + vn = d.voucher_no + if vt not in voucher_map: + voucher_map[vt] = set() + voucher_map[vt].add(vn) + + # Bulk fetch linked names for each voucher type + linked_data = {} + for vt, vnos in voucher_map.items(): + vnos_list = list(vnos) + if vt in ('Delivery Note', 'Sales Invoice'): + field = "customer" + elif vt in ('Purchase Receipt', 'Purchase Invoice'): + field = "supplier" + elif vt == "Stock Entry": + # For Stock Entry we need more fields + res = frappe.get_all(vt, + filters={"name": ["in", vnos_list]}, + fields=["name", "process_job_card", "sales_order", "delivery_note_no", + "sales_invoice_no", "purchase_order", "purchase_receipt_no"]) + for r in res: + lt, ln = None, None + if r.process_job_card: lt, ln = "Process Job Card RIGPL", r.process_job_card + elif r.sales_order: lt, ln = "Sales Order", r.sales_order + elif r.delivery_note_no: lt, ln = "Delivery Note", r.delivery_note_no + elif r.sales_invoice_no: lt, ln = "Sales Invoice", r.sales_invoice_no + elif r.purchase_order: lt, ln = "Purchase Order", r.purchase_order + elif r.purchase_receipt_no: lt, ln = "Purchase Receipt", r.purchase_receipt_no + + linked_data[(vt, r.name)] = {"link_type": lt, "linked_name": ln} + continue else: - d["link_type"] = None - d["linked_name"] = None + continue + + res = frappe.get_all(vt, filters={"name": ["in", vnos_list]}, fields=["name", field]) + for r in res: + linked_data[(vt, r.name)] = { + "link_type": "Customer" if field == "customer" else "Supplier", + "linked_name": r.get(field) + } + data = [] for d in temp_data: - row = [d.posting_date, d.posting_time, d.item_code, d.description, d.actual_qty, d.qty_after_transaction, - d.warehouse, d.voucher_no, d.voucher_type, d.linked_name, d.name, d.link_type] - data.append(row) + # Posting time cleanup + if d.posting_time: + d["posting_time"] = d["posting_time"] - datetime.timedelta(microseconds=d["posting_time"].microseconds) + + info = linked_data.get((d.voucher_type, d.voucher_no), {"link_type": None, "linked_name": None}) + + data.append([ + d.posting_date, d.posting_time, d.item_code, d.description, d.actual_qty, d.qty_after_transaction, + d.warehouse, d.voucher_no, d.voucher_type, info["linked_name"], d.name, info["link_type"] + ]) return data - def get_conditions(filters): conditions = "" - conditions_item = "" + params = {} if filters.get("item"): - conditions += " AND sle.item_code = '%s'" % filters["item"] - conditions_item += " AND it.name = '%s'" % filters["item"] + conditions += " AND sle.item_code = %(item)s" + params["item"] = filters["item"] if filters.get("warehouse"): - conditions += " AND sle.warehouse = '%s'" % filters["warehouse"] + conditions += " AND sle.warehouse = %(warehouse)s" + params["warehouse"] = filters["warehouse"] if filters.get("from_date"): - conditions += " AND sle.posting_date >= '%s'" % filters["from_date"] + conditions += " AND sle.posting_date >= %(from_date)s" + params["from_date"] = filters["from_date"] if filters.get("to_date"): - conditions += " AND sle.posting_date <= '%s'" % filters["to_date"] + conditions += " AND sle.posting_date <= %(to_date)s" + params["to_date"] = filters["to_date"] - return conditions, conditions_item + return conditions, params From 93763b30196d9d6ad310985f996a76490800c50f Mon Sep 17 00:00:00 2001 From: Kalelker-Noman Date: Wed, 15 Apr 2026 11:23:54 +0000 Subject: [PATCH 52/52] fix: permission sales invoice --- rohit_common/fixtures/custom_docperm.json | 346 +++++++++++++++++++++- rohit_common/hooks.py | 2 + 2 files changed, 344 insertions(+), 4 deletions(-) diff --git a/rohit_common/fixtures/custom_docperm.json b/rohit_common/fixtures/custom_docperm.json index 4ab9ebf..bcba740 100644 --- a/rohit_common/fixtures/custom_docperm.json +++ b/rohit_common/fixtures/custom_docperm.json @@ -1,4 +1,134 @@ [ + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 0, + "if_owner": 0, + "impersonate": 0, + "import": 0, + "mask": 0, + "modified": "2026-04-15 16:41:36.130958", + "name": "ecf1eb5474", + "parent": "Print Format", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "select": 1, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 0, + "export": 0, + "if_owner": 0, + "impersonate": 0, + "import": 0, + "mask": 0, + "modified": "2017-03-30 23:01:49.088768", + "name": "1307de602a", + "parent": "Print Format", + "permlevel": 1, + "print": 0, + "read": 1, + "report": 0, + "role": "System Manager", + "select": 0, + "share": 1, + "submit": 0, + "write": 0 + }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 0, + "export": 0, + "if_owner": 0, + "impersonate": 0, + "import": 0, + "mask": 0, + "modified": "2017-03-30 23:01:49.106864", + "name": "d72b641af7", + "parent": "Print Format", + "permlevel": 1, + "print": 0, + "read": 1, + "report": 1, + "role": "Administrator", + "select": 0, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 1, + "cancel": 0, + "create": 1, + "delete": 0, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 0, + "if_owner": 0, + "impersonate": 0, + "import": 1, + "mask": 0, + "modified": "2026-04-15 16:33:08.563297", + "name": "83c0b3938b", + "parent": "Sales Invoice", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 0, + "role": "Invoice Maker", + "select": 1, + "share": 0, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 1, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 1, + "if_owner": 0, + "impersonate": 0, + "import": 0, + "mask": 0, + "modified": "2017-04-14 18:52:12.274800", + "name": "22e248093b", + "parent": "Sales Invoice", + "permlevel": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "Invoice Maker", + "select": 0, + "share": 1, + "submit": 0, + "write": 0 + }, { "amend": 0, "cancel": 0, @@ -142,7 +272,7 @@ "impersonate": 0, "import": 0, "mask": 0, - "modified": "2025-09-18 12:27:05.391678", + "modified": "2026-04-15 16:42:52.417894", "name": "f5341bed97", "parent": "File", "permlevel": 0, @@ -150,7 +280,7 @@ "read": 1, "report": 1, "role": "System Manager", - "select": 0, + "select": 1, "share": 1, "submit": 0, "write": 1 @@ -168,7 +298,7 @@ "impersonate": 0, "import": 0, "mask": 0, - "modified": "2025-09-18 13:44:58.502414", + "modified": "2026-04-15 16:42:49.782323", "name": "gi0c6fbkum", "parent": "File", "permlevel": 0, @@ -176,7 +306,7 @@ "read": 1, "report": 0, "role": "All", - "select": 0, + "select": 1, "share": 1, "submit": 0, "write": 1 @@ -492,5 +622,213 @@ "share": 1, "submit": 0, "write": 0 + }, + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 0, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 1, + "if_owner": 0, + "impersonate": 0, + "import": 0, + "mask": 0, + "modified": "2026-04-15 16:44:01.390467", + "name": "v9akq6e4bq", + "parent": "Print Format", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "select": 1, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 1, + "delete": 0, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 0, + "if_owner": 0, + "impersonate": 0, + "import": 0, + "mask": 0, + "modified": "2026-04-15 16:41:34.285564", + "name": "87ee51c356", + "parent": "Print Format", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Administrator", + "select": 1, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 1, + "cancel": 0, + "create": 1, + "delete": 0, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 1, + "if_owner": 0, + "impersonate": 0, + "import": 0, + "mask": 0, + "modified": "2026-04-15 16:32:59.269881", + "name": "27f3bd9581", + "parent": "Sales Invoice", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts Manager", + "select": 1, + "share": 0, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 0, + "if_owner": 0, + "impersonate": 0, + "import": 0, + "mask": 0, + "modified": "2026-04-15 16:33:11.091821", + "name": "39f81f764d", + "parent": "Sales Invoice", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "RIGB Auditor", + "select": 1, + "share": 0, + "submit": 0, + "write": 0 + }, + { + "amend": 1, + "cancel": 1, + "create": 1, + "delete": 1, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 1, + "if_owner": 0, + "impersonate": 0, + "import": 0, + "mask": 0, + "modified": "2026-04-15 16:33:02.567313", + "name": "2da0f3cacc", + "parent": "Sales Invoice", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "select": 1, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 1, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 1, + "if_owner": 0, + "impersonate": 0, + "import": 0, + "mask": 0, + "modified": "2017-03-30 23:01:49.180502", + "name": "4d00b16973", + "parent": "Sales Invoice", + "permlevel": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "select": 0, + "share": 1, + "submit": 0, + "write": 1 + }, + { + "amend": 1, + "cancel": 0, + "create": 1, + "delete": 0, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 1, + "export": 0, + "if_owner": 0, + "impersonate": 0, + "import": 0, + "mask": 0, + "modified": "2026-04-15 16:33:00.550120", + "name": "10ec782ab1", + "parent": "Sales Invoice", + "permlevel": 0, + "print": 1, + "read": 1, + "report": 1, + "role": "Accounts User", + "select": 1, + "share": 0, + "submit": 0, + "write": 1 + }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "delete": 0, + "docstatus": 0, + "doctype": "Custom DocPerm", + "email": 0, + "export": 0, + "if_owner": 0, + "impersonate": 0, + "import": 0, + "mask": 0, + "modified": "2017-03-30 23:01:49.267905", + "name": "a792fc1b58", + "parent": "Sales Invoice", + "permlevel": 1, + "print": 0, + "read": 1, + "report": 0, + "role": "Accounts Manager", + "select": 0, + "share": 0, + "submit": 0, + "write": 0 } ] \ No newline at end of file diff --git a/rohit_common/hooks.py b/rohit_common/hooks.py index 6c58037..0ee9250 100644 --- a/rohit_common/hooks.py +++ b/rohit_common/hooks.py @@ -25,6 +25,8 @@ "in", [ "File", + "Print Format", + "Sales Invoice", "e-Invoice Log", "GSTR2A RIGPL", "GSTR-1",