From da5e1bd53c21338d09cc131b307058a24fad6713 Mon Sep 17 00:00:00 2001 From: Dany Robert Date: Thu, 9 Mar 2023 13:59:24 +0530 Subject: [PATCH 1/4] fix(transaction): only fetch party gst details if party name is available (#494) * fix(party-gst-detail): return empty dict if no customer * chore: linter issues * fix: misc changes during review --------- Co-authored-by: Sagar Vora (cherry picked from commit e414595157a825813f40551d559357d19cec32f2) --- india_compliance/gst_india/overrides/transaction.py | 11 ++++++++--- india_compliance/public/js/transaction.js | 11 ++++++++--- india_compliance/public/js/utils.js | 5 ----- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/india_compliance/gst_india/overrides/transaction.py b/india_compliance/gst_india/overrides/transaction.py index c6536b698..624ba7593 100644 --- a/india_compliance/gst_india/overrides/transaction.py +++ b/india_compliance/gst_india/overrides/transaction.py @@ -506,9 +506,11 @@ def get_gst_details(party_details, doctype, company): ) if not party_details.get(party_address_field): party_gst_details = get_party_gst_details(party_details, is_sales_transaction) + # updating party details to get correct place of supply - party_details.update(party_gst_details) - gst_details.update(party_gst_details) + if party_gst_details: + party_details.update(party_gst_details) + gst_details.update(party_gst_details) gst_details.place_of_supply = get_place_of_supply(party_details, doctype) @@ -589,9 +591,12 @@ def get_party_gst_details(party_details, is_sales_transaction): "billing_address_gstin" if is_sales_transaction else "supplier_gstin" ) + if not (party := party_details.get(party_type.lower())): + return + return frappe.db.get_value( party_type, - party_details[party_type.lower()], + party, ("gst_category", f"gstin as {gstin_fieldname}"), as_dict=True, ) diff --git a/india_compliance/public/js/transaction.js b/india_compliance/public/js/transaction.js index 93cbb36bb..6686e1150 100644 --- a/india_compliance/public/js/transaction.js +++ b/india_compliance/public/js/transaction.js @@ -40,7 +40,9 @@ function fetch_gst_details(doctype) { async function update_gst_details(frm) { if (frm.__gst_update_triggered || frm.updating_party_details || !frm.doc.company) return; - const party = frm.doc[ic.get_party_fieldname(frm.doc.doctype)]; + const party_type = ic.get_party_type(frm.doc.doctype).toLowerCase(); + const party_fieldname = frm.doc.doctype === "Quotation" ? "party_name" : party_type; + const party = frm.doc[party_fieldname]; if (!party) return; frm.__gst_update_triggered = true; @@ -50,8 +52,11 @@ async function update_gst_details(frm) { const party_details = {}; - // fieldname may be "party_name" for Quotation, but "customer" is expected by get_gst_details - party_details[ic.get_party_type(frm.doc.doctype).toLowerCase()] = party; + // set "customer" or "supplier" (not applicable for Quotations with Lead) + if (frm.doc.doctype !== "Quotation" || frm.doc.party_type === "Customer") { + party_details[party_type] = party; + } + const fieldnames_to_set = ["tax_category", "gst_category", "company_gstin"]; diff --git a/india_compliance/public/js/utils.js b/india_compliance/public/js/utils.js index 86e1c927a..a5ce2b393 100644 --- a/india_compliance/public/js/utils.js +++ b/india_compliance/public/js/utils.js @@ -39,11 +39,6 @@ Object.assign(ic, { return in_list(frappe.boot.sales_doctypes, doctype) ? "Customer" : "Supplier"; }, - get_party_fieldname(doctype) { - if (doctype == "Quotation") return "party_name"; - return ic.get_party_type(doctype).toLowerCase(); - }, - set_state_options(frm) { const state_field = frm.get_field("state"); const country = frm.get_field("country").value; From 0907e8a6105c42293e7c7a2eb51024f9f6040baf Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Thu, 9 Mar 2023 15:05:18 +0530 Subject: [PATCH 2/4] refactor: `window.ic` => `window.india_compliance` (cherry picked from commit 38a53480c70a2c820049f023cbabbdaa3ea8aad6) --- .../gst_india/client_scripts/address.js | 4 ++-- .../client_scripts/e_invoice_actions.js | 4 ++-- .../client_scripts/e_waybill_actions.js | 12 +++++------ .../gst_india/client_scripts/party.js | 4 ++-- .../client_scripts/sales_invoice_list.js | 2 +- .../doctype/gst_settings/gst_settings.js | 2 +- .../doctype/gst_settings/gst_settings.json | 20 +++++++++---------- .../india_compliance_account.js | 2 +- .../gst_india/report/gstr_1/gstr_1.js | 2 +- .../components/auth/AuthForm.vue | 2 +- .../india_compliance_account.bundle.js | 8 ++++---- .../services/AccountService.js | 8 ++++---- .../services/AuthService.js | 8 ++++---- india_compliance/public/js/quick_entry.js | 8 ++++---- india_compliance/public/js/transaction.js | 2 +- india_compliance/public/js/utils.js | 14 ++++++++----- 16 files changed, 53 insertions(+), 49 deletions(-) diff --git a/india_compliance/gst_india/client_scripts/address.js b/india_compliance/gst_india/client_scripts/address.js index e0b08cde9..a96057e87 100644 --- a/india_compliance/gst_india/client_scripts/address.js +++ b/india_compliance/gst_india/client_scripts/address.js @@ -9,7 +9,7 @@ set_gst_category(DOCTYPE); frappe.ui.form.on(DOCTYPE, { country(frm) { - ic.set_state_options(frm); + india_compliance.set_state_options(frm); if (!frm.doc.country) return; @@ -20,7 +20,7 @@ frappe.ui.form.on(DOCTYPE, { } }, async refresh(frm) { - ic.set_state_options(frm); + india_compliance.set_state_options(frm); // set default values for GST fields if (!frm.is_new() || !frm.doc.links || frm.doc.gstin) return; diff --git a/india_compliance/gst_india/client_scripts/e_invoice_actions.js b/india_compliance/gst_india/client_scripts/e_invoice_actions.js index 2decc07e6..f57f797e6 100644 --- a/india_compliance/gst_india/client_scripts/e_invoice_actions.js +++ b/india_compliance/gst_india/client_scripts/e_invoice_actions.js @@ -59,7 +59,7 @@ frappe.ui.form.on("Sales Invoice", { resolve(); }; - if (!is_irn_cancellable(frm) || !ic.is_e_invoice_enabled()) { + if (!is_irn_cancellable(frm) || !india_compliance.is_e_invoice_enabled()) { const d = frappe.warn( __("Cannot Cancel IRN"), __( @@ -159,7 +159,7 @@ function show_cancel_e_invoice_dialog(frm, callback) { function is_e_invoice_applicable(frm) { return ( - ic.is_e_invoice_enabled() && + india_compliance.is_e_invoice_enabled() && frm.doc.docstatus == 1 && frm.doc.company_gstin && frm.doc.gst_category != "Unregistered" && diff --git a/india_compliance/gst_india/client_scripts/e_waybill_actions.js b/india_compliance/gst_india/client_scripts/e_waybill_actions.js index e1cf9472c..301ccf051 100644 --- a/india_compliance/gst_india/client_scripts/e_waybill_actions.js +++ b/india_compliance/gst_india/client_scripts/e_waybill_actions.js @@ -10,7 +10,7 @@ function setup_e_waybill_actions(doctype) { frm.set_value("gst_vehicle_type", get_vehicle_type(frm.doc)); }, setup(frm) { - if (!ic.is_api_enabled()) return; + if (!india_compliance.is_api_enabled()) return; frappe.realtime.on("e_waybill_pdf_update", message => { frappe.model.sync_docinfo(message); @@ -59,7 +59,7 @@ function setup_e_waybill_actions(doctype) { return; } - if (!ic.is_api_enabled() || !is_e_waybill_generated_using_api(frm)) { + if (!india_compliance.is_api_enabled() || !is_e_waybill_generated_using_api(frm)) { return; } @@ -118,7 +118,7 @@ function setup_e_waybill_actions(doctype) { frm.doc.ewaybill || frm.doc.is_return || frm.doc.is_debit_note || - !ic.is_api_enabled() || + !india_compliance.is_api_enabled() || !gst_settings.auto_generate_e_waybill || is_e_invoice_applicable(frm) || !is_e_waybill_applicable(frm) @@ -134,7 +134,7 @@ function setup_e_waybill_actions(doctype) { }, before_cancel(frm) { // if IRN is present, e-Waybill gets cancelled in e-Invoice action - if (!ic.is_api_enabled() || frm.doc.irn || !frm.doc.ewaybill) return; + if (!india_compliance.is_api_enabled() || frm.doc.irn || !frm.doc.ewaybill) return; frappe.validated = false; @@ -332,7 +332,7 @@ function show_generate_e_waybill_dialog(frm) { }); } - const api_enabled = ic.is_api_enabled(); + const api_enabled = india_compliance.is_api_enabled(); const d = new frappe.ui.Dialog({ title: __("Generate e-Waybill"), @@ -668,7 +668,7 @@ function update_generation_dialog(dialog) { } function get_primary_action_label_for_generation(doc) { - const label = ic.is_api_enabled() ? __("Generate") : __("Download JSON"); + const label = india_compliance.is_api_enabled() ? __("Generate") : __("Download JSON"); if (are_transport_details_available(doc)) { return label; diff --git a/india_compliance/gst_india/client_scripts/party.js b/india_compliance/gst_india/client_scripts/party.js index 2d87cf201..e71894084 100644 --- a/india_compliance/gst_india/client_scripts/party.js +++ b/india_compliance/gst_india/client_scripts/party.js @@ -122,7 +122,7 @@ function set_gstin_query(doctype) { frm._gstin_options_set_for = frm.doc.name; const field = frm.get_field("gstin"); field.df.ignore_validation = true; - field.set_data(await ic.get_gstin_options(frm.doc.name, doctype)); + field.set_data(await india_compliance.get_gstin_options(frm.doc.name, doctype)); }, }); } @@ -132,7 +132,7 @@ function set_gst_category(doctype) { gstin(frm) { frm.set_value( "gst_category", - ic.guess_gst_category(frm.doc.gstin, frm.doc.country) + india_compliance.guess_gst_category(frm.doc.gstin, frm.doc.country) ); }, }); diff --git a/india_compliance/gst_india/client_scripts/sales_invoice_list.js b/india_compliance/gst_india/client_scripts/sales_invoice_list.js index 426b2d648..009c71c45 100644 --- a/india_compliance/gst_india/client_scripts/sales_invoice_list.js +++ b/india_compliance/gst_india/client_scripts/sales_invoice_list.js @@ -14,7 +14,7 @@ frappe.listview_settings[DOCTYPE].onload = function (list_view) { generate_e_waybill_json ); - if (ic.is_e_invoice_enabled()) + if (india_compliance.is_e_invoice_enabled()) add_bulk_action_for_submitted_invoices( list_view, __("Enqueue Bulk e-Invoice Generation"), diff --git a/india_compliance/gst_india/doctype/gst_settings/gst_settings.js b/india_compliance/gst_india/doctype/gst_settings/gst_settings.js index 8cda6323a..2bc35eeaf 100644 --- a/india_compliance/gst_india/doctype/gst_settings/gst_settings.js +++ b/india_compliance/gst_india/doctype/gst_settings/gst_settings.js @@ -19,7 +19,7 @@ frappe.ui.form.on("GST Settings", { frm.set_query("company", "credentials", company_query); frm.set_query("gstin", "credentials", (_, cdt, cdn) => { const row = frappe.get_doc(cdt, cdn); - return ic.get_gstin_query(row.company); + return india_compliance.get_gstin_query(row.company); }); }, onload: show_ic_api_promo, diff --git a/india_compliance/gst_india/doctype/gst_settings/gst_settings.json b/india_compliance/gst_india/doctype/gst_settings/gst_settings.json index 1a5661200..c87df5241 100644 --- a/india_compliance/gst_india/doctype/gst_settings/gst_settings.json +++ b/india_compliance/gst_india/doctype/gst_settings/gst_settings.json @@ -91,7 +91,7 @@ "label": "Accounts" }, { - "depends_on": "eval: ic.is_api_enabled(doc)", + "depends_on": "eval: india_compliance.is_api_enabled(doc)", "fieldname": "credentials_tab", "fieldtype": "Tab Break", "label": "Credentials" @@ -124,7 +124,7 @@ }, { "default": "1", - "depends_on": "eval: ic.is_api_enabled(doc) && doc.enable_e_waybill", + "depends_on": "eval: india_compliance.is_api_enabled(doc) && doc.enable_e_waybill", "description": "If checked, a PDF of the e-Waybill will be automatically attached to the transaction after it's generation", "fieldname": "attach_e_waybill_print", "fieldtype": "Check", @@ -132,14 +132,14 @@ }, { "default": "0", - "depends_on": "eval: ic.can_enable_api(doc)", + "depends_on": "eval: india_compliance.can_enable_api(doc)", "description": "Enable this to use API features like e-Waybill / e-Invoice generation from your ERP", "fieldname": "enable_api", "fieldtype": "Check", "label": "Enable API Features" }, { - "depends_on": "eval: ic.is_api_enabled(doc)", + "depends_on": "eval: india_compliance.is_api_enabled(doc)", "fieldname": "e_invoice_section", "fieldtype": "Section Break", "label": "e-Invoice" @@ -166,16 +166,16 @@ }, { "default": "1", - "depends_on": "eval: ic.is_api_enabled(doc) && doc.enable_e_waybill", + "depends_on": "eval: india_compliance.is_api_enabled(doc) && doc.enable_e_waybill", "description": "e-Waybill will be automatically generated after Sales Invoice submission if the invoice value threshold is met, and data is available and valid", "fieldname": "auto_generate_e_waybill", "fieldtype": "Check", "label": "Automatically Generate e-Waybill on Invoice Submission", - "read_only_depends_on": "eval: ic.is_api_enabled(doc) && doc.enable_e_invoice" + "read_only_depends_on": "eval: india_compliance.is_api_enabled(doc) && doc.enable_e_invoice" }, { "default": "1", - "depends_on": "eval: ic.is_api_enabled(doc) && doc.enable_e_waybill", + "depends_on": "eval: india_compliance.is_api_enabled(doc) && doc.enable_e_waybill", "description": "Automatically fetch e-Waybill data after it's generation for printing or logging purposes. This will lead to one additional API request.", "fieldname": "fetch_e_waybill_data", "fieldtype": "Check", @@ -217,7 +217,7 @@ "label": "Enable SEZ / Overseas Transactions" }, { - "depends_on": "eval: ic.is_api_enabled(doc)", + "depends_on": "eval: india_compliance.is_api_enabled(doc)", "fieldname": "other_apis_section", "fieldtype": "Section Break", "label": "Other APIs" @@ -240,7 +240,7 @@ }, { "default": "0", - "depends_on": "eval: ic.is_api_enabled(doc)", + "depends_on": "eval: india_compliance.is_api_enabled(doc)", "description": "Enable this to explore GST API features in a test environment. API actions executed in sandbox mode won't affect your actual business data on the GST portal.", "fieldname": "sandbox_mode", "fieldtype": "Check", @@ -250,7 +250,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-01-03 02:39:59.034386", + "modified": "2023-03-09 04:10:39.690511", "modified_by": "Administrator", "module": "GST India", "name": "GST Settings", diff --git a/india_compliance/gst_india/page/india_compliance_account/india_compliance_account.js b/india_compliance/gst_india/page/india_compliance_account/india_compliance_account.js index e14faf835..58b037be5 100644 --- a/india_compliance/gst_india/page/india_compliance_account/india_compliance_account.js +++ b/india_compliance/gst_india/page/india_compliance_account/india_compliance_account.js @@ -4,5 +4,5 @@ frappe.pages["india-compliance-account"].on_page_load = async function (wrapper) "india_compliance_account.bundle.css", ]); - new ic.pages.IndiaComplianceAccountPage(wrapper); + new india_compliance.pages.IndiaComplianceAccountPage(wrapper); }; diff --git a/india_compliance/gst_india/report/gstr_1/gstr_1.js b/india_compliance/gst_india/report/gstr_1/gstr_1.js index d350c4f8b..95365b654 100644 --- a/india_compliance/gst_india/report/gstr_1/gstr_1.js +++ b/india_compliance/gst_india/report/gstr_1/gstr_1.js @@ -32,7 +32,7 @@ frappe.query_reports["GSTR-1"] = { "fieldtype": "Autocomplete", "get_query": function () { const company = frappe.query_report.get_filter_value('company'); - return ic.get_gstin_query(company); + return india_compliance.get_gstin_query(company); } }, { diff --git a/india_compliance/public/js/india_compliance_account/components/auth/AuthForm.vue b/india_compliance/public/js/india_compliance_account/components/auth/AuthForm.vue index 63028afa0..2d9fadb65 100644 --- a/india_compliance/public/js/india_compliance_account/components/auth/AuthForm.vue +++ b/india_compliance/public/js/india_compliance_account/components/auth/AuthForm.vue @@ -174,7 +174,7 @@ export default { if (!value) return set_error("GSTIN is required"); - value = ic.validate_gstin(value); + value = india_compliance.validate_gstin(value); if (!value) return set_error("Invalid GSTIN detected"); const { message, error } = await check_free_trial_eligibility(value); diff --git a/india_compliance/public/js/india_compliance_account/india_compliance_account.bundle.js b/india_compliance/public/js/india_compliance_account/india_compliance_account.bundle.js index 29aaac24f..eefa36129 100644 --- a/india_compliance/public/js/india_compliance_account/india_compliance_account.bundle.js +++ b/india_compliance/public/js/india_compliance_account/india_compliance_account.bundle.js @@ -43,11 +43,11 @@ class IndiaComplianceAccountPage { } } -frappe.provide("ic.pages"); -ic.pages.IndiaComplianceAccountPage = IndiaComplianceAccountPage; +frappe.provide("india_compliance.pages"); +india_compliance.pages.IndiaComplianceAccountPage = IndiaComplianceAccountPage; -frappe.provide("ic.gst_api"); -ic.gst_api.call = async function (endpoint, options) { +frappe.provide("india_compliance.gst_api"); +india_compliance.gst_api.call = async function (endpoint, options) { try { const base_url = "https://asp.resilient.tech/v1/"; const url = base_url + endpoint; diff --git a/india_compliance/public/js/india_compliance_account/services/AccountService.js b/india_compliance/public/js/india_compliance_account/services/AccountService.js index e4d460d8a..35a8cdda2 100644 --- a/india_compliance/public/js/india_compliance_account/services/AccountService.js +++ b/india_compliance/public/js/india_compliance_account/services/AccountService.js @@ -1,12 +1,12 @@ export async function get_details(type) { - return ic.gst_api.call(`account.get_${type}_details`, { + return india_compliance.gst_api.call(`account.get_${type}_details`, { method: "GET", with_api_secret: true, }); } export async function update_billing_details(new_billing_details) { - return ic.gst_api.call("account.update_billing_details", { + return india_compliance.gst_api.call("account.update_billing_details", { method: "POST", body: { new_billing_details }, with_api_secret: true, @@ -14,7 +14,7 @@ export async function update_billing_details(new_billing_details) { } export async function create_order(credits, amount) { - return ic.gst_api.call("account.create_order", { + return india_compliance.gst_api.call("account.create_order", { method: "POST", body: { credits, amount }, with_api_secret: true, @@ -22,7 +22,7 @@ export async function create_order(credits, amount) { } export async function verify_payment(orderId) { - return ic.gst_api.call("account.verify_payment", { + return india_compliance.gst_api.call("account.verify_payment", { method: "POST", body: { order_id: orderId }, with_api_secret: true, diff --git a/india_compliance/public/js/india_compliance_account/services/AuthService.js b/india_compliance/public/js/india_compliance_account/services/AuthService.js index cf6a64652..6f7ab8c48 100644 --- a/india_compliance/public/js/india_compliance_account/services/AuthService.js +++ b/india_compliance/public/js/india_compliance_account/services/AuthService.js @@ -12,21 +12,21 @@ export async function set_api_secret(api_secret) { } export function login(email) { - return ic.gst_api.call("auth/login", { + return india_compliance.gst_api.call("auth/login", { body: { email }, fail_silently: true, }); } export function signup(email, gstin) { - return ic.gst_api.call("auth/signup", { + return india_compliance.gst_api.call("auth/signup", { body: { email, gstin }, fail_silently: true, }); } export function check_free_trial_eligibility(gstin) { - return ic.gst_api.call("auth/is_eligible_for_free_trial", { + return india_compliance.gst_api.call("auth/is_eligible_for_free_trial", { body: { gstin }, fail_silently: true, }); @@ -43,7 +43,7 @@ export function set_session(session) { } export function validate_session(session_id) { - return ic.gst_api.call("auth/validate_session", { + return india_compliance.gst_api.call("auth/validate_session", { body: { session_id }, }); } diff --git a/india_compliance/public/js/quick_entry.js b/india_compliance/public/js/quick_entry.js index 7ccfd2214..fbfb0a0f2 100644 --- a/india_compliance/public/js/quick_entry.js +++ b/india_compliance/public/js/quick_entry.js @@ -6,12 +6,12 @@ class GSTQuickEntryForm extends frappe.ui.form.QuickEntryForm { constructor(...args) { super(...args); this.skip_redirect_on_error = true; - this.api_enabled = ic.is_api_enabled() && gst_settings.autofill_party_info; + this.api_enabled = india_compliance.is_api_enabled() && gst_settings.autofill_party_info; } render_dialog() { super.render_dialog(); - ic.set_state_options(this.dialog); + india_compliance.set_state_options(this.dialog); } get_address_fields() { @@ -67,7 +67,7 @@ class GSTQuickEntryForm extends frappe.ui.form.QuickEntryForm { options: "Country", default: frappe.defaults.get_user_default("country"), onchange: () => { - ic.set_state_options(this.dialog); + india_compliance.set_state_options(this.dialog); }, }, { @@ -93,7 +93,7 @@ class GSTQuickEntryForm extends frappe.ui.form.QuickEntryForm { d.set_value( "gst_category", - ic.guess_gst_category(d.doc._gstin, d.doc.country) + india_compliance.guess_gst_category(d.doc._gstin, d.doc.country) ); }, }, diff --git a/india_compliance/public/js/transaction.js b/india_compliance/public/js/transaction.js index 6686e1150..bd2441d13 100644 --- a/india_compliance/public/js/transaction.js +++ b/india_compliance/public/js/transaction.js @@ -40,7 +40,7 @@ function fetch_gst_details(doctype) { async function update_gst_details(frm) { if (frm.__gst_update_triggered || frm.updating_party_details || !frm.doc.company) return; - const party_type = ic.get_party_type(frm.doc.doctype).toLowerCase(); + const party_type = india_compliance.get_party_type(frm.doc.doctype).toLowerCase(); const party_fieldname = frm.doc.doctype === "Quotation" ? "party_name" : party_type; const party = frm.doc[party_fieldname]; if (!party) return; diff --git a/india_compliance/public/js/utils.js b/india_compliance/public/js/utils.js index a5ce2b393..7e216aea3 100644 --- a/india_compliance/public/js/utils.js +++ b/india_compliance/public/js/utils.js @@ -6,11 +6,11 @@ import { TDS_REGEX, } from "./regex_constants"; -frappe.provide("ic"); +frappe.provide("india_compliance"); window.gst_settings = frappe.boot.gst_settings; -Object.assign(ic, { +Object.assign(india_compliance, { get_gstin_query(party, party_type = "Company") { if (!party) { frappe.show_alert({ @@ -27,7 +27,7 @@ Object.assign(ic, { }, async get_gstin_options(party, party_type = "Company") { - const { query, params } = ic.get_gstin_query(party, party_type); + const { query, params } = india_compliance.get_gstin_query(party, party_type); const { message } = await frappe.call({ method: query, args: params, @@ -56,11 +56,11 @@ Object.assign(ic, { is_api_enabled(settings) { if (!settings) settings = gst_settings; - return settings.enable_api && ic.can_enable_api(settings); + return settings.enable_api && india_compliance.can_enable_api(settings); }, is_e_invoice_enabled() { - return ic.is_api_enabled() && gst_settings.enable_e_invoice; + return india_compliance.is_api_enabled() && gst_settings.enable_e_invoice; }, validate_gstin(gstin) { @@ -114,3 +114,7 @@ function is_gstin_check_digit_valid(gstin) { const checkCodePoint = (mod - (sum % mod)) % mod; return GSTIN_CODEPOINT_CHARS[checkCodePoint] === gstin[14]; } + +// Will be deprecated after v15 release, kept only for compatibility +// DO NOT USE IN CODE +window.ic = window.india_compliance; From 93f47c8e0bff5a1f5cf5faa63a0fa943e806c883 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Thu, 9 Mar 2023 15:23:56 +0530 Subject: [PATCH 3/4] chore: ignore refactor to `window.india_compliance` --- .git-blame-ignore-revs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 58a1afc8b..874170588 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -16,3 +16,6 @@ # sort lines in hooks dec2438be2d63eff24da45d6c936ec846d8ab0df + +# refactor window.ic => window.india_compliance +0907e8a6105c42293e7c7a2eb51024f9f6040baf From 39278fd1437d8b43cc2c63b961e2eab702396d99 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Thu, 9 Mar 2023 18:03:17 +0530 Subject: [PATCH 4/4] feat: ability to edit Place of Supply (cherry picked from commit 22588a166989be07b36e8bb90be5158b735bae49) --- .../gst_india/constants/custom_fields.py | 21 +++++-- .../gst_india/overrides/test_transaction.py | 23 +++++++- .../gst_india/overrides/transaction.py | 15 +++-- india_compliance/patches.txt | 2 +- india_compliance/public/js/transaction.js | 55 ++++++++++++++----- 5 files changed, 92 insertions(+), 24 deletions(-) diff --git a/india_compliance/gst_india/constants/custom_fields.py b/india_compliance/gst_india/constants/custom_fields.py index 5ea162de5..aaa589e21 100644 --- a/india_compliance/gst_india/constants/custom_fields.py +++ b/india_compliance/gst_india/constants/custom_fields.py @@ -8,6 +8,17 @@ gst_category_options = "\n".join(GST_CATEGORIES) default_gst_category = "Unregistered" + +def get_place_of_supply_options(): + options = [] + + for state_name, state_number in STATE_NUMBERS.items(): + options.append(f"{state_number}-{state_name}") + + options.append("96-Other Countries") + return "\n".join(sorted(options)) + + party_fields = [ { "fieldname": "tax_details_section", @@ -83,10 +94,11 @@ { "fieldname": "place_of_supply", "label": "Place of Supply", - "fieldtype": "Data", + "fieldtype": "Autocomplete", + "options": get_place_of_supply_options(), "insert_after": "company_gstin", "print_hide": 1, - "read_only": 1, + "read_only": 0, "translatable": 0, }, { @@ -164,10 +176,11 @@ { "fieldname": "place_of_supply", "label": "Place of Supply", - "fieldtype": "Data", + "fieldtype": "Autocomplete", + "options": get_place_of_supply_options(), "insert_after": "gst_category", "print_hide": 1, - "read_only": 1, + "read_only": 0, "length": 50, "translatable": 0, }, diff --git a/india_compliance/gst_india/overrides/test_transaction.py b/india_compliance/gst_india/overrides/test_transaction.py index dba224801..263baa028 100644 --- a/india_compliance/gst_india/overrides/test_transaction.py +++ b/india_compliance/gst_india/overrides/test_transaction.py @@ -431,13 +431,34 @@ def test_purchase_from_unregistered_supplier(self): doc.insert, ) + def test_purchase_with_different_place_of_supply(self): + if self.is_sales_doctype: + return + + doc = create_transaction( + **self.transaction_details, + is_out_state=True, + do_not_save=True, + ) + + doc.place_of_supply = "96-Other Countries" + doc.save() + + # place of supply shouldn't get overwritten + self.assertEqual(doc.place_of_supply, "96-Other Countries") + + # IGST should get applied + self.assertIn("IGST", doc.taxes[-1].description) + def test_invalid_gst_account_type(self): doc = create_transaction(**self.transaction_details, do_not_save=True) doc.append( "taxes", { "charge_type": "On Net Total", - "account_head": f"{'Input' if self.is_sales_doctype else 'Output'} Tax IGST - _TIRC", + "account_head": ( + f"{'Input' if self.is_sales_doctype else 'Output'} Tax IGST - _TIRC" + ), "description": "IGST", "rate": 18, "cost_center": "Main - _TIRC", diff --git a/india_compliance/gst_india/overrides/transaction.py b/india_compliance/gst_india/overrides/transaction.py index 624ba7593..c161008cb 100644 --- a/india_compliance/gst_india/overrides/transaction.py +++ b/india_compliance/gst_india/overrides/transaction.py @@ -347,7 +347,8 @@ def validate_items(doc): def set_place_of_supply(doc, method=None): - doc.place_of_supply = get_place_of_supply(doc, doc.doctype) + if not doc.place_of_supply: + doc.place_of_supply = get_place_of_supply(doc, doc.doctype) def is_inter_state_supply(doc): @@ -479,11 +480,13 @@ def get_regional_round_off_accounts(company, account_list): def update_party_details(party_details, doctype, company): - party_details.update(get_gst_details(party_details, doctype, company)) + party_details.update( + get_gst_details(party_details, doctype, company, update_place_of_supply=True) + ) @frappe.whitelist() -def get_gst_details(party_details, doctype, company): +def get_gst_details(party_details, doctype, company, *, update_place_of_supply=False): """ This function does not check for permissions since it returns insensitive data based on already sensitive input (party details) @@ -512,7 +515,11 @@ def get_gst_details(party_details, doctype, company): party_details.update(party_gst_details) gst_details.update(party_gst_details) - gst_details.place_of_supply = get_place_of_supply(party_details, doctype) + gst_details.place_of_supply = ( + party_details.place_of_supply + if (not update_place_of_supply and party_details.place_of_supply) + else get_place_of_supply(party_details, doctype) + ) if is_sales_transaction: source_gstin = party_details.company_gstin diff --git a/india_compliance/patches.txt b/india_compliance/patches.txt index 81b6124a4..41585a914 100644 --- a/india_compliance/patches.txt +++ b/india_compliance/patches.txt @@ -3,7 +3,7 @@ [post_model_sync] india_compliance.patches.v14.set_default_for_overridden_accounts_setting -execute:from india_compliance.gst_india.setup import create_custom_fields; create_custom_fields() #5 +execute:from india_compliance.gst_india.setup import create_custom_fields; create_custom_fields() #6 execute:from india_compliance.gst_india.setup import create_property_setters; create_property_setters() india_compliance.patches.post_install.update_custom_role_for_e_invoice_summary india_compliance.patches.v14.remove_ecommerce_gstin_from_purchase_invoice diff --git a/india_compliance/public/js/transaction.js b/india_compliance/public/js/transaction.js index bd2441d13..8c68dc7fd 100644 --- a/india_compliance/public/js/transaction.js +++ b/india_compliance/public/js/transaction.js @@ -17,7 +17,7 @@ for (const doctype of TRANSACTION_DOCTYPES) { } function fetch_gst_details(doctype) { - const event_fields = ["tax_category", "company_gstin"]; + const event_fields = ["tax_category", "company_gstin", "place_of_supply"]; // we are using address below to prevent multiple event triggers if (in_list(frappe.boot.sales_doctypes, doctype)) { @@ -31,24 +31,46 @@ function fetch_gst_details(doctype) { } const events = Object.fromEntries( - event_fields.map(field => [field, update_gst_details]) + event_fields.map(field => [field, frm => update_gst_details(frm, field)]) ); frappe.ui.form.on(doctype, events); } -async function update_gst_details(frm) { - if (frm.__gst_update_triggered || frm.updating_party_details || !frm.doc.company) return; +async function update_gst_details(frm, event) { + if ( + frm.updating_party_details || + !frm.doc.company || + (event === "place_of_supply" && frm.__updating_gst_details) + ) + return; const party_type = india_compliance.get_party_type(frm.doc.doctype).toLowerCase(); const party_fieldname = frm.doc.doctype === "Quotation" ? "party_name" : party_type; const party = frm.doc[party_fieldname]; if (!party) return; + if (in_list(["company_gstin", "customer_address", "supplier_address"], event)) { + frm.__update_place_of_supply = true; + } + + if (frm.__gst_update_triggered) return; frm.__gst_update_triggered = true; + const args = { + doctype: frm.doc.doctype, + company: frm.doc.company, + }; + // wait for GSTINs to get fetched - await frappe.after_ajax().then(() => frm.__gst_update_triggered = false); + await frappe.after_ajax().then(() => { + frm.__gst_update_triggered = false; + + if (frm.__update_place_of_supply) { + args.update_place_of_supply = 1; + frm.__update_place_of_supply = false; + } + }); const party_details = {}; @@ -57,8 +79,12 @@ async function update_gst_details(frm) { party_details[party_type] = party; } - - const fieldnames_to_set = ["tax_category", "gst_category", "company_gstin"]; + const fieldnames_to_set = [ + "tax_category", + "gst_category", + "company_gstin", + "place_of_supply", + ]; if (in_list(frappe.boot.sales_doctypes, frm.doc.doctype)) { fieldnames_to_set.push( @@ -75,16 +101,17 @@ async function update_gst_details(frm) { party_details[fieldname] = frm.doc[fieldname]; } + args.party_details = JSON.stringify(party_details); + frappe.call({ method: "india_compliance.gst_india.overrides.transaction.get_gst_details", - args: { - party_details: JSON.stringify(party_details), - doctype: frm.doc.doctype, - company: frm.doc.company, - }, - callback(r) { + args, + async callback(r) { if (!r.message) return; - frm.set_value(r.message); + + frm.__updating_gst_details = true; + await frm.set_value(r.message); + frm.__updating_gst_details = false; }, }); }