diff --git a/AppCode/AOHandler.py b/AppCode/AOHandler.py index 24a21bc..86b0820 100644 --- a/AppCode/AOHandler.py +++ b/AppCode/AOHandler.py @@ -71,49 +71,127 @@ class AOHandler: self.cursor.callproc('DeleteAOById', [id]) self.conn.commit() + # report download by year + def ao_report_download(self, selected_year): + try: + # AY calculation (2020 -> AY 2020-2021) + ay_start = int(selected_year) + ay_end = ay_start + 1 + assessment_year = f"AY {ay_start}-{ay_end}" + + # Fetch AO records + self.cursor.callproc("GetAOByYear", [selected_year]) + + rows = [] + for result in self.cursor.stored_results(): + rows = result.fetchall() + + if not rows: + return None + + # Remove id column if exists + for row in rows: + row.pop("id", None) + + # Mapping DB fields → readable Excel labels + field_mapping = { + "gross_total_income": "Gross Total Income", + "disallowance_14a": "Add: Disallowance u/s 14A", + "disallowance_37": "Add: Disallowance u/s 37", + "deduction_80ia_business": "Less: Deduction u/s 80IA - On Business Income", + "deduction_80ia_misc": "On Misc Receipts", + "deduction_80ia_other": "On Other", + "deduction_sec37_disallowance": "On Sec 37 Disallowance", + "deduction_80g": "Less: Deduction u/s 80G", + "net_taxable_income": "Net Taxable Income", + "tax_30_percent": "Tax @ 30%", + "tax_book_profit_18_5": "Tax @ 18.5% on Book Profit", + "tax_payable": "Tax Payable", + "surcharge_12": "Surcharge @ 12%", + "edu_cess_3": "Education Cess @ 3%", + "total_tax_payable": "Total Tax Payable", + "mat_credit": "Less: MAT Credit Utilized", + "interest_234c": "Add: Interest u/s 234C", + "total_tax": "Total Tax", + "advance_tax": "Advance Tax", + "tds": "TDS", + "tcs": "TCS", + "sat": "SAT", + "tax_on_assessment": "Tax on Regular Assessment", + "refund": "Refund", + "Remarks": "Remarks" + } + + # Vertical AO structure + data = [] + for key, label in field_mapping.items(): + value = rows[0].get(key, 0) + data.append([label, value]) + + df = pd.DataFrame(data, columns=["Particulars", "AO"]) + + # Excel output + output = io.BytesIO() + with pd.ExcelWriter(output, engine="xlsxwriter") as writer: + workbook = writer.book + worksheet = workbook.add_worksheet("AO Report") + writer.sheets["AO Report"] = worksheet + + # Formats + title_fmt = workbook.add_format({ + "bold": True, + "align": "center", + "font_size": 14 + }) + header_fmt = workbook.add_format({ + "bold": True, + "border": 1, + "align": "center" + }) + text_fmt = workbook.add_format({"border": 1}) + num_fmt = workbook.add_format({ + "border": 1, + "num_format": "#,##0.00" + }) + + # Company Name + worksheet.merge_range( + "A1:B1", + "Laxmi Civil Engineering Services Pvt Ltd", + title_fmt + ) + + # Assessment Year + worksheet.merge_range( + "A2:B2", + f"Assessment Year : {assessment_year}", + workbook.add_format({"bold": True, "align": "center"}) + ) + + # Header + worksheet.write_row("A4", ["Particulars", "AO"], header_fmt) + + # Data rows + row_no = 4 + for _, row in df.iterrows(): + worksheet.write(row_no, 0, row["Particulars"], text_fmt) + worksheet.write(row_no, 1, row["AO"], num_fmt) + row_no += 1 + + # Column width + worksheet.set_column("A:A", 45) + worksheet.set_column("B:B", 20) + + output.seek(0) + return output + + except mysql.connector.Error as e: + print("MySQL Error →", e) + return None + + # CLOSE CONNECTION def close(self): self.cursor.close() - self.conn.close() - - # report download by year - def ao_report_download(self, selected_year): - try: - # Call stored proc to fetch year-wise records - self.cursor.callproc("GetAOByYear", [selected_year]) - - rows = [] - for result in self.cursor.stored_results(): - rows = result.fetchall() - - if not rows: - return None - - df = pd.DataFrame(rows) - - # TRANSPOSE - df_transposed = df.transpose() - df_transposed.insert(0, 'Field', df_transposed.index) - - # Rename columns: Record 1, 2, 3... - record_cols = { - i: f"Record {i}" - for i in df_transposed.columns if isinstance(i, int) - } - df_transposed.rename(columns=record_cols, inplace=True) - df_transposed.reset_index(drop=True, inplace=True) - - # Excel Output - output = io.BytesIO() - with pd.ExcelWriter(output, engine="xlsxwriter") as writer: - df_transposed.to_excel(writer, index=False, sheet_name="AO_Vertical") - worksheet = writer.sheets["AO_Vertical"] - worksheet.set_column(0, 0, 30) - - output.seek(0) - return output - - except mysql.connector.Error as e: - print("MySQL Error:", e) - return None \ No newline at end of file + self.conn.close() \ No newline at end of file diff --git a/AppCode/CITHandler.py b/AppCode/CITHandler.py index 1612d8a..a1d9ca0 100644 --- a/AppCode/CITHandler.py +++ b/AppCode/CITHandler.py @@ -4,7 +4,6 @@ import pandas as pd import io - class CITHandler: def __init__(self): @@ -51,8 +50,6 @@ class CITHandler: self.cursor.callproc("InsertCIT", values) self.conn.commit() - - # UPDATE CIT RECORD def update_cit(self, id, data): columns = [ @@ -69,53 +66,130 @@ class CITHandler: self.cursor.callproc("UpdateCITById", values) self.conn.commit() - - # DELETE CIT RECORD def delete_cit(self, id): self.cursor.callproc("DeleteCITById", [id]) self.conn.commit() + # + def cit_report_download(self, selected_year): + try: + # AY calculation (2020 -> AY 2020-2021) + ay_start = int(selected_year) + ay_end = ay_start + 1 + assessment_year = f"AY {ay_start}-{ay_end}" - # CLOSE CONNECTION + # Fetch CIT records + self.cursor.callproc("GetCITByYear", [selected_year]) + + rows = [] + for result in self.cursor.stored_results(): + rows = result.fetchall() + + if not rows: + return None + + # Remove id column if exists + for row in rows: + row.pop("id", None) + + # Mapping DB fields → readable Excel labels + field_mapping = { + "gross_total_income": "Gross Total Income", + "disallowance_14a": "Add: Disallowance u/s 14A", + "disallowance_37": "Add: Disallowance u/s 37", + "deduction_80ia_business": "Less: Deduction u/s 80IA - On Business Income", + "deduction_80ia_misc": "On Misc Receipts", + "deduction_80ia_other": "On Other", + "deduction_sec37_disallowance": "On Sec 37 Disallowance", + "deduction_80g": "Less: Deduction u/s 80G", + "net_taxable_income": "Net Taxable Income", + "tax_30_percent": "Tax @ 30%", + "tax_book_profit_18_5": "Tax @ 18.5% on Book Profit", + "tax_payable": "Tax Payable", + "surcharge_12": "Surcharge @ 12%", + "edu_cess_3": "Education Cess @ 3%", + "total_tax_payable": "Total Tax Payable", + "mat_credit": "Less: MAT Credit Utilized", + "interest_234c": "Add: Interest u/s 234C", + "total_tax": "Total Tax", + "advance_tax": "Advance Tax", + "tds": "TDS", + "tcs": "TCS", + "sat": "SAT", + "tax_on_assessment": "Tax on Regular Assessment", + "refund": "Refund", + "Remarks": "Remarks" + } + + # Vertical CIT structure (single record per year) + data = [] + for key, label in field_mapping.items(): + value = rows[0].get(key, 0) + data.append([label, value]) + + df = pd.DataFrame(data, columns=["Particulars", "CIT"]) + + # Excel output + output = io.BytesIO() + with pd.ExcelWriter(output, engine="xlsxwriter") as writer: + workbook = writer.book + worksheet = workbook.add_worksheet("CIT Report") + writer.sheets["CIT Report"] = worksheet + + # Formats + title_fmt = workbook.add_format({ + "bold": True, + "align": "center", + "font_size": 14 + }) + header_fmt = workbook.add_format({ + "bold": True, + "border": 1, + "align": "center" + }) + text_fmt = workbook.add_format({"border": 1}) + num_fmt = workbook.add_format({ + "border": 1, + "num_format": "#,##0.00" + }) + + # Company Name + worksheet.merge_range( + "A1:B1", + "Laxmi Civil Engineering Services Pvt Ltd", + title_fmt + ) + + # Assessment Year + worksheet.merge_range( + "A2:B2", + f"Assessment Year : {assessment_year}", + workbook.add_format({"bold": True, "align": "center"}) + ) + + # Header + worksheet.write_row("A4", ["Particulars", "CIT"], header_fmt) + + # Data rows + row_no = 4 + for _, row in df.iterrows(): + worksheet.write(row_no, 0, row["Particulars"], text_fmt) + worksheet.write(row_no, 1, row["CIT"], num_fmt) + row_no += 1 + + # Column widths + worksheet.set_column("A:A", 45) + worksheet.set_column("B:B", 20) + + output.seek(0) + return output + + except mysql.connector.Error as e: + print("MySQL Error →", e) + return None + + + # CLOSE CONNECTION def close(self): self.cursor.close() - self.conn.close() - - - def cit_report_download(self, selected_year): - try: - # Call stored procedure - self.cursor.callproc("GetCITByYear", [selected_year]) - - rows = [] - for result in self.cursor.stored_results(): - rows = result.fetchall() - - if not rows: - return None - - df = pd.DataFrame(rows) - - # Excel output - output = io.BytesIO() - with pd.ExcelWriter(output, engine="xlsxwriter") as writer: - - for i, (_, row) in enumerate(df.iterrows(), start=1): - # Convert row to vertical format - vertical_df = pd.DataFrame(row).reset_index() - vertical_df.columns = ['Field', 'Value'] - - start_row = (i - 1) * (len(vertical_df) + 3) # gap between blocks - vertical_df.to_excel( - writer, - sheet_name='CIT_Report', - index=False, - startrow=start_row - ) - - output.seek(0) - return output - - except mysql.connector.Error as e: - print("MySQL Error:", e) - return None \ No newline at end of file + self.conn.close() \ No newline at end of file diff --git a/AppCode/ITATHandler.py b/AppCode/ITATHandler.py index b810bd5..f714e5f 100644 --- a/AppCode/ITATHandler.py +++ b/AppCode/ITATHandler.py @@ -65,32 +65,123 @@ class ITATHandler: self.conn.commit() - def itat_report_download(self, selected_year): - try: - # Call stored procedure - self.cursor.callproc("GetITATByYear", [selected_year]) - rows = [] - for result in self.cursor.stored_results(): - rows = result.fetchall() + try: + # AY calculation (2020 -> AY 2020-2021) + ay_start = int(selected_year) + ay_end = ay_start + 1 + assessment_year = f"AY {ay_start}-{ay_end}" - if not rows: - return None + # Fetch ITAT data + self.cursor.callproc("GetITATByYear", [selected_year]) + rows = [] + for result in self.cursor.stored_results(): + rows = result.fetchall() - df = pd.DataFrame(rows) - - # Excel output - output = io.BytesIO() - with pd.ExcelWriter(output, engine="xlsxwriter") as writer: - df.T.to_excel(writer, header=False, sheet_name="ITAT_Report") - - output.seek(0) - return output - - except mysql.connector.Error as e: - print("MySQL Error:", e) + if not rows: return None + # Remove id column if exists + for row in rows: + row.pop("id", None) + + # Mapping DB fields → readable Excel labels + field_mapping = { + "gross_total_income": "Gross Total Income", + "disallowance_14a": "Add: Disallowance u/s 14A", + "disallowance_37": "Add: Disallowance u/s 37", + "deduction_80ia_business": "Less: Deduction u/s 80IA - On Business Income", + "deduction_80ia_misc": "On Misc Receipts", + "deduction_80ia_other": "On Other", + "deduction_sec37_disallowance": "On Sec 37 Disallowance", + "deduction_80g": "Less: Deduction u/s 80G", + "net_taxable_income": "Net Taxable Income", + "tax_30_percent": "Tax @ 30%", + "tax_book_profit_18_5": "Tax @ 18.5% on Book Profit", + "tax_payable": "Tax Payable", + "surcharge_12": "Surcharge @ 12%", + "edu_cess_3": "Education Cess @ 3%", + "total_tax_payable": "Total Tax Payable", + "mat_credit": "Less: MAT Credit Utilized", + "interest_234c": "Add: Interest u/s 234C", + "total_tax": "Total Tax", + "advance_tax": "Advance Tax", + "tds": "TDS", + "tcs": "TCS", + "sat": "SAT", + "tax_on_assessment": "Tax on Regular Assessment", + "refund": "Refund", + "Remarks": "Remarks" + } + + # Vertical ITAT structure + data = [] + for key, label in field_mapping.items(): + value = rows[0].get(key, 0) + data.append([label, value]) + + df = pd.DataFrame(data, columns=["Particulars", "ITAT"]) + + # Excel output + output = io.BytesIO() + with pd.ExcelWriter(output, engine="xlsxwriter") as writer: + workbook = writer.book + worksheet = workbook.add_worksheet("ITAT Report") + writer.sheets["ITAT Report"] = worksheet + + # Formats + title_fmt = workbook.add_format({ + "bold": True, + "align": "center", + "font_size": 14 + }) + header_fmt = workbook.add_format({ + "bold": True, + "border": 1, + "align": "center" + }) + text_fmt = workbook.add_format({"border": 1}) + num_fmt = workbook.add_format({ + "border": 1, + "num_format": "#,##0.00" + }) + + # Company Name + worksheet.merge_range( + "A1:B1", + "Laxmi Civil Engineering Services Pvt Ltd", + title_fmt + ) + + # Assessment Year + worksheet.merge_range( + "A2:B2", + f"Assessment Year : {assessment_year}", + workbook.add_format({"bold": True, "align": "center"}) + ) + + # Header + worksheet.write_row("A4", ["Particulars", "ITAT"], header_fmt) + + # Data rows + row_no = 4 + for _, row in df.iterrows(): + worksheet.write(row_no, 0, row["Particulars"], text_fmt) + worksheet.write(row_no, 1, row["ITAT"], num_fmt) + row_no += 1 + + # Column widths + worksheet.set_column("A:A", 45) + worksheet.set_column("B:B", 20) + + output.seek(0) + return output + + except mysql.connector.Error as e: + print("MySQL Error →", e) + return None + + # CLOSE CONNECTION def close(self): self.cursor.close() diff --git a/AppCode/ITRHandler.py b/AppCode/ITRHandler.py index 87091ec..3731c99 100644 --- a/AppCode/ITRHandler.py +++ b/AppCode/ITRHandler.py @@ -81,48 +81,111 @@ class ITRHandler: self.conn.commit() - # report download by year + # # report download by year def itr_report_download(self, selected_year): - try: - # Call stored procedure - self.cursor.callproc("GetITRByYear", [selected_year]) + try: + # Call stored procedure + self.cursor.callproc("GetITRByYear", [selected_year]) - rows = [] - for result in self.cursor.stored_results(): - rows = result.fetchall() + rows = [] + for result in self.cursor.stored_results(): + rows = result.fetchall() - if not rows: - return None - - # Convert SQL rows to DataFrame - df = pd.DataFrame(rows) - # Transpose - df_transposed = df.transpose() - df_transposed.insert(0, 'Field', df_transposed.index) - - record_cols = { - i: f"Record {i}" - for i in df_transposed.columns if isinstance(i, int) - } - - df_transposed.rename(columns=record_cols, inplace=True) - df_transposed.reset_index(drop=True, inplace=True) - - # Save to Excel in memory - output = io.BytesIO() - with pd.ExcelWriter(output, engine='xlsxwriter') as writer: - df_transposed.to_excel(writer, index=False, sheet_name='ITR_Vertical') - worksheet = writer.sheets['ITR_Vertical'] - worksheet.set_column(0, 0, 30) - - output.seek(0) - return output - - except mysql.connector.Error as e: - print("MySQL Error →", e) + if not rows: return None + for row in rows: + row.pop('id', None) + + # Mapping DB fields → Excel labels (NO underscores) + field_mapping = { + "gross_total_income": "Gross Total Income", + "disallowance_14a": "Add: Disallowance u/s 14A", + "disallowance_37": "Add: Disallowance u/s 37", + "deduction_80ia_business": "Less: Deduction u/s 80IA - On Business Income", + "deduction_80ia_misc": "On Misc Receipts", + "deduction_80ia_other": "On Other", + "deduction_sec37_disallowance": "On Sec 37 Disallowance", + "deduction_80g": "Less: Deduction u/s 80G", + "net_taxable_income": "Net Taxable Income", + "tax_30_percent": "Tax @ 30%", + "tax_book_profit_18_5": "Tax @ 18.5% on Book Profit", + "tax_payable": "Tax Payable", + "surcharge_12": "Surcharge @ 12%", + "edu_cess_3": "Education Cess @ 3%", + "total_tax_payable": "Total Tax Payable", + "mat_credit": "Less: MAT Credit Utilized", + "interest_234c": "Add: Interest u/s 234C", + "total_tax": "Total Tax", + "advance_tax": "Advance Tax", + "tds": "TDS", + "tcs": "TCS", + "sat": "SAT", + "tax_on_assessment": "Tax on Regular Assessment", + "refund": "Refund" + } + + # Convert to vertical structure + data = [] + for key, label in field_mapping.items(): + value = rows[0].get(key, 0) + data.append([label, value]) + + df = pd.DataFrame(data, columns=["Particulars", "ITR"]) + + # Excel output + output = io.BytesIO() + with pd.ExcelWriter(output, engine="xlsxwriter") as writer: + workbook = writer.book + worksheet = workbook.add_worksheet("ITR Report") + writer.sheets["ITR Report"] = worksheet + + # Formats + title_fmt = workbook.add_format({ + "bold": True, "align": "center", "valign": "vcenter", + "font_size": 14 + }) + header_fmt = workbook.add_format({ + "bold": True, "border": 1, "align": "center" + }) + cell_fmt = workbook.add_format({"border": 1}) + num_fmt = workbook.add_format({"border": 1, "num_format": "#,##0.00"}) + + # Company name + worksheet.merge_range("A1:B1", "Laxmi Civil Engineering Services Pvt Ltd", title_fmt) + + ay_start = int(selected_year) + ay_end = ay_start + 1 + assessment_year = f"AY {ay_start}-{ay_end}" + + # Assessment Year + worksheet.merge_range( + "A2:B2", + f"Assessment Year : {assessment_year}", + workbook.add_format({"align": "center", "bold": True}) + ) + + # Headers + worksheet.write_row("A4", ["Particulars", "ITR"], header_fmt) + + # Data rows + row_no = 4 + for _, row in df.iterrows(): + worksheet.write(row_no, 0, row["Particulars"], cell_fmt) + worksheet.write(row_no, 1, row["ITR"], num_fmt) + row_no += 1 + + # Column widths + worksheet.set_column("A:A", 45) + worksheet.set_column("B:B", 20) + + output.seek(0) + return output + + except mysql.connector.Error as e: + print("MySQL Error →", e) + return None # CLOSE CONNECTION def close(self): self.cursor.close() - self.conn.close() + self.conn.close() \ No newline at end of file diff --git a/AppCode/__pycache__/AOHandler.cpython-313.pyc b/AppCode/__pycache__/AOHandler.cpython-313.pyc index 1f472ea..f533e36 100644 Binary files a/AppCode/__pycache__/AOHandler.cpython-313.pyc and b/AppCode/__pycache__/AOHandler.cpython-313.pyc differ diff --git a/AppCode/__pycache__/CITHandler.cpython-313.pyc b/AppCode/__pycache__/CITHandler.cpython-313.pyc index c6579df..f4bad4e 100644 Binary files a/AppCode/__pycache__/CITHandler.cpython-313.pyc and b/AppCode/__pycache__/CITHandler.cpython-313.pyc differ diff --git a/AppCode/__pycache__/DocumentHandler.cpython-313.pyc b/AppCode/__pycache__/DocumentHandler.cpython-313.pyc index 0f783dd..d3e2722 100644 Binary files a/AppCode/__pycache__/DocumentHandler.cpython-313.pyc and b/AppCode/__pycache__/DocumentHandler.cpython-313.pyc differ diff --git a/AppCode/__pycache__/ITATHandler.cpython-313.pyc b/AppCode/__pycache__/ITATHandler.cpython-313.pyc index cd0d19b..4f59d0e 100644 Binary files a/AppCode/__pycache__/ITATHandler.cpython-313.pyc and b/AppCode/__pycache__/ITATHandler.cpython-313.pyc differ diff --git a/AppCode/__pycache__/ITRHandler.cpython-313.pyc b/AppCode/__pycache__/ITRHandler.cpython-313.pyc index 05e7347..25312c2 100644 Binary files a/AppCode/__pycache__/ITRHandler.cpython-313.pyc and b/AppCode/__pycache__/ITRHandler.cpython-313.pyc differ