diff --git a/india_compliance/gst_india/api_classes/taxpayer_base.py b/india_compliance/gst_india/api_classes/taxpayer_base.py index 2c59f1fc99..44f7173f83 100644 --- a/india_compliance/gst_india/api_classes/taxpayer_base.py +++ b/india_compliance/gst_india/api_classes/taxpayer_base.py @@ -502,10 +502,10 @@ def validate_auth_token(self): return @request_cache - def get_filing_preference(self, date=None): + def get_filing_preference(self, date=None, fy=None): return self.get( - action="GETPREF", params={"fy": self.get_fy(date)}, endpoint="returns" - ) + action="GETPREF", params={"fy": fy or self.get_fy(date)}, endpoint="returns" + ).response @staticmethod def get_fy(date=None): diff --git a/india_compliance/gst_india/doctype/gst_return_log/generate_gstr_1.py b/india_compliance/gst_india/doctype/gst_return_log/generate_gstr_1.py index 8e76ddf744..ef93491837 100644 --- a/india_compliance/gst_india/doctype/gst_return_log/generate_gstr_1.py +++ b/india_compliance/gst_india/doctype/gst_return_log/generate_gstr_1.py @@ -552,9 +552,17 @@ def generate_gstr1_data(self, filters, callback=None): # APIs Enabled status = self.get_return_status() - from india_compliance.gst_india.utils.gstin_info import get_filing_preference + # TODO: only if status is unfiled and first month or filing pref is not set + if True: + from india_compliance.gst_india.utils.gstin_info import ( + get_filing_preference, + ) - filing_preference = get_filing_preference(self.gstin, self.return_period) + filing_preference = get_filing_preference( + self.gstin, self.return_period, force=True + ) + else: + filing_preference = self.filing_preference if filing_preference and self.filing_preference is None: self.db_set({"filing_preference": filing_preference}) diff --git a/india_compliance/gst_india/doctype/gst_return_log/gst_return_log.json b/india_compliance/gst_india/doctype/gst_return_log/gst_return_log.json index 79689d8653..b3d766f692 100644 --- a/india_compliance/gst_india/doctype/gst_return_log/gst_return_log.json +++ b/india_compliance/gst_india/doctype/gst_return_log/gst_return_log.json @@ -196,7 +196,8 @@ { "fieldname": "filing_preference", "fieldtype": "Data", - "label": "Filing Preference" + "label": "Filing Preference", + "read_only": 1 }, { "fieldname": "upload_error", @@ -230,7 +231,7 @@ "link_fieldname": "reference_docname" } ], - "modified": "2024-11-07 23:12:55.966658", + "modified": "2024-12-19 13:28:20.406478", "modified_by": "Administrator", "module": "GST India", "name": "GST Return Log", diff --git a/india_compliance/gst_india/doctype/gstr_1_beta/gstr_1_beta.js b/india_compliance/gst_india/doctype/gstr_1_beta/gstr_1_beta.js index 9e2b14a305..a386157def 100644 --- a/india_compliance/gst_india/doctype/gstr_1_beta/gstr_1_beta.js +++ b/india_compliance/gst_india/doctype/gstr_1_beta/gstr_1_beta.js @@ -111,7 +111,7 @@ frappe.ui.form.on(DOCTYPE, { // Set Default Values set_default_company_gstin(frm); set_options_for_year(frm); - set_options_for_month_or_quarter(frm); + set_options_for_month_or_quarter(frm, true); frm.__setup_complete = true; @@ -197,7 +197,7 @@ frappe.ui.form.on(DOCTYPE, { year(frm) { render_empty_state(frm); - set_options_for_month_or_quarter(frm); + set_options_for_month_or_quarter(frm, true); }, is_quarterly(frm) { @@ -2918,20 +2918,20 @@ async function update_fields_based_on_filing_preference(frm) { } function update_month_or_quarter(frm) { - set_options_for_month_or_quarter(frm, set_only_options = true) + set_options_for_month_or_quarter(frm) if (frm.doc.is_quarterly === 1) { - const quarter = cint(india_compliance.MONTH.indexOf(frm.doc.month_or_quarter) / 3) - frm.doc.month_or_quarter = india_compliance.QUARTER[quarter] + const quarter_index = cint(india_compliance.MONTH.indexOf(frm.doc.month_or_quarter) / 3) + frm.doc.month_or_quarter = india_compliance.QUARTER[quarter_index] } else { const quarter_index = india_compliance.QUARTER.indexOf(frm.doc.month_or_quarter) - // added 2 to set month_or_quarter as last month of that quarter + // last month of that quarter frm.doc.month_or_quarter = india_compliance.MONTH[(quarter_index * 3) + 2] } frm.refresh_field("month_or_quarter") } -function set_options_for_month_or_quarter(frm, set_only_options = false) { +function set_options_for_month_or_quarter(frm, with_update = false) { /** * Set options for Month or Quarter based on the year and current date * 1. If the year is current year, then options are till current month @@ -2972,7 +2972,8 @@ function set_options_for_month_or_quarter(frm, set_only_options = false) { } set_field_options("month_or_quarter", options); - if (set_only_options) return + + if (!with_update) return if (frm.doc.year === current_year) // set second last option as default diff --git a/india_compliance/gst_india/utils/gstin_info.py b/india_compliance/gst_india/utils/gstin_info.py index 4d92f06638..81ebf47a83 100644 --- a/india_compliance/gst_india/utils/gstin_info.py +++ b/india_compliance/gst_india/utils/gstin_info.py @@ -4,8 +4,7 @@ import frappe from frappe import _ -from frappe.query_builder import Case -from frappe.utils import cint, get_last_day, getdate +from frappe.utils import cint, getdate from india_compliance.exceptions import GSPServerError from india_compliance.gst_india.api_classes.base import BASE_URL @@ -338,50 +337,49 @@ def get_gstr_1_return_status( return "Not Filed" -def get_filing_preference(gstin, period): - month = cint(period[:2]) - year = cint(period[2:]) +#################################################################################################### +#### GSTIN FILING PREFERENCE ###################################################################### +#################################################################################################### - start_month = (month - 1) // 3 * 3 + 1 - quarter = (month - 1) // 3 - start_date = getdate(f"{year}-{start_month}-01") - months_of_quarter = [start_month + i for i in range(3)] - log_names = [f"GSTR1-{month:02d}{year}-{gstin}" for month in months_of_quarter] +def get_filing_preference(gstin, period, force=False): + if not force: + log_name = f"GSTR1-{period}-{gstin}" - if filing_preference := frappe.get_list( - "GST Return Log", - filters={"name": ["in", log_names]}, - fields=["filing_preference"], - ): - for record in filing_preference: - if not record.get("filing_preference"): - continue + filing_preference = frappe.db.get_value( + "GST Return Log", log_name, "filing_preference" + ) - return record.get("filing_preference") + if filing_preference: + return filing_preference - if frappe.db.get_value( - "GST Return Log", log_names[0], "filing_status" - ) != "Filed" and getdate() < get_last_day(start_date): - return + filing_preference = fetch_filing_preference(gstin, period) - api = GSTR1API(company_gstin=gstin) - response = api.get_filing_preference(date=start_date).response - - filing_preference = ( - "Quarterly" if response[quarter].get("preference") == "Q" else "Monthly" - ) + # update GST Return Log frappe.enqueue( - create_gst_return_log_for_quarter, + create_or_update_logs_for_quarter, gstin=gstin, - log_names=log_names, + period=period, filing_preference=filing_preference, ) return filing_preference -def create_gst_return_log_for_quarter(gstin, log_names, filing_preference): +def fetch_filing_preference(gstin, period): + api = GSTR1API(company_gstin=gstin) + response = api.get_filing_preference(fy=get_fy(period)) + + quarter = get_financial_quarter(cint(period[:2])) + filing_preference = ( + "Quarterly" if response[quarter - 1].get("preference") == "Q" else "Monthly" + ) + + return filing_preference + + +def create_or_update_logs_for_quarter(gstin, period, filing_preference): + log_names = get_logs_for_quarter(gstin, period) existing_log = frappe.get_all( "GST Return Log", filters={"name": ["in", log_names]}, pluck="name" ) @@ -404,58 +402,30 @@ def create_gst_return_log_for_quarter(gstin, log_names, filing_preference): } ).insert() - update_logs_without_filing_preference(gstin) - - -def update_logs_without_filing_preference(gstin): - gst_return_logs = frappe.get_all( - "GST Return Log", - filters={"filing_preference": ["is", "not set"], "gstin": gstin}, - fields=["name", "return_period", "gstin"], + # patch + from india_compliance.patches.v15.update_return_logs_with_filing_preference import ( + patch_filing_preference, ) - if not gst_return_logs: - return - - filing_preferences = {} - logs_to_update = {} - - for log in gst_return_logs: - return_period = log.get("return_period") - gstin = log.get("gstin") - financial_year = get_fy(return_period) - key = f"{financial_year}:{gstin}" - - if key not in filing_preferences: - start_date = getdate(f"{return_period[2:]}-{return_period[:2]}-01") - api = GSTR1API(company_gstin=gstin) - filing_preferences[key] = api.get_filing_preference( - date=start_date - ).response - - month = cint(return_period[:2]) - quarter = (month - 1) // 3 - preference_data = filing_preferences.get(key) - logs_to_update[log.get("name")] = ( - "Quarterly" - if preference_data[quarter].get("preference") == "Q" - else "Monthly" - ) + patch_filing_preference(gstin) - gst_return_log = frappe.qb.DocType("GST Return Log") - case_conditions = Case() - for log_name, filing_preference in logs_to_update.items(): - case_conditions.when(gst_return_log.name == log_name, filing_preference) +def get_logs_for_quarter(gstin, period): + quarter = get_financial_quarter(cint(period[:2])) + start_month = quarter * 3 + 1 + year = period[2:] - ( - frappe.qb.update(gst_return_log) - .set(gst_return_log.filing_preference, case_conditions) - .where(gst_return_log.name.isin(list(logs_to_update.keys()))) - .run() + return ( + f"GSTR1-{month:02d}{year}-{gstin}" + for month in range(start_month, start_month + 3) ) +#################################################################################################### +#### GSTIN UTILITIES ############################################################################### +#################################################################################################### + + def get_fy(period, year_increment=0): month, year = period[:2], period[2:] year = str(int(year) + year_increment) @@ -470,3 +440,16 @@ def get_fy(period, year_increment=0): def get_current_fy(): period = getdate().strftime("%m%Y") return get_fy(period) + + +def get_financial_quarter(month): + if month in [4, 5, 6]: + return 1 # April, May, June + elif month in [7, 8, 9]: + return 2 # July, August, September + elif month in [10, 11, 12]: + return 3 # October, November, December + elif month in [1, 2, 3]: + return 4 # January, February, March + else: + raise ValueError("Month must be between 1 and 12") diff --git a/india_compliance/patches/v15/update_return_logs_with_filing_preference.py b/india_compliance/patches/v15/update_return_logs_with_filing_preference.py new file mode 100644 index 0000000000..44288f3e8a --- /dev/null +++ b/india_compliance/patches/v15/update_return_logs_with_filing_preference.py @@ -0,0 +1,22 @@ +import frappe + +from india_compliance.gst_india.utils.gstin_info import fetch_filing_preference + + +def patch_filing_preference(gstin): + logs = frappe.get_all( + "GST Return Log", + filters={ + "filing_preference": ["is", "not set"], + "gstin": gstin, + "return_perid": ["!=", "ALL"], + }, + fields=["name", "return_period", "gstin"], + ) + + if not logs: + return + + for log in logs: + preference = fetch_filing_preference(log.gstin, log.return_period) + frappe.db.set_value("GST Return Log", log.name, "filing_preference", preference)