Files
IncomeTaxSystem/AppCode/DocumentHandler.py

377 lines
12 KiB
Python
Raw Normal View History

from flask import (
render_template, request, send_file, jsonify
)
from werkzeug.utils import secure_filename
2025-12-02 15:38:19 +05:30
import pandas as pd
import os
2025-12-02 15:38:19 +05:30
import io
from AppCode.Config import DBConfig
from AppCode.FileHandler import FileHandler
2025-12-02 15:38:19 +05:30
from AppCode.YearGet import YearGet
2025-11-30 16:24:49 +05:30
class DocumentHandler:
def __init__(self):
self.years = []
self.documents = []
self.isSuccess = False
self.resultMessage = ""
# =========================
# Utility: Parse Year
# =========================
def parse_year(self, year_value):
"""
Accepts:
- '2026'
- 'AY 2026-2027'
Returns:
- 2026 (int)
"""
if not year_value:
return None
year_value = year_value.strip()
if year_value.isdigit():
return int(year_value)
try:
# "AY 2026-2027" → 2026
return int(year_value.split()[1].split('-')[0])
except Exception:
return None
# =========================
# View Documents
# =========================
2025-11-30 16:24:49 +05:30
def View(self, request):
year_raw = request.args.get('year', '')
2025-11-30 16:24:49 +05:30
stage = request.args.get('stage', '')
year = self.parse_year(year_raw)
2025-11-30 16:24:49 +05:30
dbconfig = DBConfig()
connection = dbconfig.get_db_connection()
if not connection:
self.isSuccess = False
return
cursor = connection.cursor(dictionary=True)
cursor.callproc("GetDocuments", [year, stage])
2025-11-30 16:24:49 +05:30
for result in cursor.stored_results():
self.documents = result.fetchall()
break
2025-11-30 16:24:49 +05:30
cursor.callproc("GetYear")
for result in cursor.stored_results():
year_rows = result.fetchall()
break
2025-11-30 16:24:49 +05:30
self.years = [row['year'] for row in year_rows]
cursor.close()
connection.close()
2025-11-30 16:24:49 +05:30
self.isSuccess = True
# =========================
# Upload Documents
# =========================
2025-11-30 16:24:49 +05:30
def Upload(self, request):
dbconfig = DBConfig()
connection = dbconfig.get_db_connection()
if not connection:
return
cursor = connection.cursor()
files = request.files.getlist('documents')
year_raw = request.form.get('year')
stage = request.form.get('stage')
year = self.parse_year(year_raw)
if not year:
self.resultMessage = "Invalid year selected."
return
for file in files:
if '.' not in file.filename:
continue
extension = file.filename.rsplit('.', 1)[1].lower()
if extension not in FileHandler.ALLOWED_EXTENSIONS:
print("Skipping invalid file:", extension)
continue
filename = secure_filename(file.filename)
filepath = os.path.join(FileHandler.UPLOAD_FOLDER, filename)
file.save(filepath)
cursor.callproc(
'InsertDocument',
[filename, filepath, extension, year, stage]
)
connection.commit()
cursor.close()
connection.close()
# =========================
# Summary Preview (JSON)
# =========================
def Summary_preview(self, request):
"""
Returns JSON preview of summary report for selected year.
"""
year_raw = request.args.get("year")
year = self.parse_year(year_raw)
if not year:
return jsonify([])
dbconfig = DBConfig()
connection = dbconfig.get_db_connection()
if not connection:
return jsonify([])
try:
stages = {
"ITR": "itr",
"AO": "ao",
"CIT": "cit",
"ITAT": "itat",
}
stage_data = {}
for stage_name, table_name in stages.items():
cursor = connection.cursor(dictionary=True)
cursor.callproc("sp_get_stage_data", [table_name, year])
rows = []
for result in cursor.stored_results():
rows = result.fetchall()
stage_data[stage_name] = pd.DataFrame(rows) if rows else pd.DataFrame()
cursor.close()
2025-11-30 16:24:49 +05:30
columns = [
'gross_total_income', 'disallowance_14a',
'disallowance_37', '-',
'deduction_80ia_business',
'deduction_80ia_misc',
'deduction_80ia_other',
'deduction_sec37_disallowance',
'deduction_80g', '-',
'net_taxable_income',
'tax_30_percent',
'tax_book_profit_18_5',
'tax_payable', 'surcharge',
'edu_cess', 'total_tax_payable',
'mat_credit_created',
'mat_credit_utilized',
'interest_234c', 'total_tax',
'-', 'advance_tax', 'tds',
'tcs', 'sat',
'tax_on_assessment',
'refund', 'Remarks'
]
2025-11-30 16:24:49 +05:30
particulars = [
"Gross Total Income", "Add: Disallowance u/s 14A",
"Add: Disallowance u/s 37", "GTI as per",
"Less: Deduction u/s 80IA - On Business Income",
"- On Misc Receipts", "- On Other",
"- On Sec 37 Disallowance",
"Less: Deduction u/s 80G", " ",
"Net Taxable Income", "Tax @ 30%",
"Tax @ 18.5% on Book Profit",
"Tax Payable", "Surcharge @ %",
"Education Cess @ %", "Total Tax Payable",
"Add: MAT Credit Created",
"Less: MAT Credit Utilized",
"Add: Interest u/s 234C",
"Total Tax", " ",
"Advance Tax", "TDS", "TCS", "SAT",
"Tax on Regular Assessment",
"Refund", "Remarks"
]
def safe_get(df, col):
return df[col].values[0] if col in df.columns and not df.empty else 0
preview = []
for i, part in enumerate(particulars):
preview.append({
"Particular": part,
"ITR": safe_get(stage_data['ITR'], columns[i]),
"AO": safe_get(stage_data['AO'], columns[i]),
"CIT": safe_get(stage_data['CIT'], columns[i]),
"ITAT": safe_get(stage_data['ITAT'], columns[i]),
})
2025-11-30 16:24:49 +05:30
return jsonify(preview)
finally:
2025-11-30 16:24:49 +05:30
connection.close()
2025-12-02 15:38:19 +05:30
def Summary_report(self, request):
dbconfig = DBConfig()
connection = dbconfig.get_db_connection()
year_raw = request.args.get('year')
# Safely parse year to int
try:
year = int(year_raw)
except (TypeError, ValueError):
year = None
2026-01-07 00:49:42 +05:30
if not year:
2025-12-02 15:38:19 +05:30
yearGetter = YearGet()
allYears = yearGetter.get_year_by_model("AllYearsInAllModel")
yearGetter.close()
2026-01-07 00:49:42 +05:30
return render_template(
'summary_reports.html',
years=allYears,
message="Please select a valid year to download."
)
2025-12-02 15:38:19 +05:30
try:
stages = {
"ITR": "itr",
"AO": "ao",
"CIT": "cit",
"ITAT": "itat",
}
2026-01-07 00:49:42 +05:30
2025-12-02 15:38:19 +05:30
stage_data = {}
for stage_name, table_name in stages.items():
cursor = connection.cursor(dictionary=True)
cursor.callproc("sp_get_stage_data", [table_name, year])
2026-01-07 00:49:42 +05:30
rows = []
2025-12-02 15:38:19 +05:30
for result in cursor.stored_results():
rows = result.fetchall()
2026-01-07 00:49:42 +05:30
stage_data[stage_name] = pd.DataFrame(rows) if rows else pd.DataFrame()
2025-12-02 15:38:19 +05:30
cursor.close()
def safe_get(df, col):
return df[col].values[0] if col in df.columns and not df.empty else "-"
particulars = [
"Gross Total Income", "Add: Disallowance u/s 14A",
"Add: Disallowance u/s 37", "GTI as per",
"Less: Deduction u/s 80IA - On Business Income",
"- On Misc Receipts", "- On Other",
"- On Sec 37 Disallowance",
"Less: Deduction u/s 80G", " ",
"Net Taxable Income", "Tax @ 30%",
"Tax @ 18.5% on Book Profit",
"Tax Payable", "Surcharge @ %",
"Education Cess @ %", "Total Tax Payable",
"Add: MAT Credit Created",
"Less: MAT Credit Utilized",
"Add: Interest u/s 234C",
"Total Tax", " ",
2026-01-07 00:49:42 +05:30
"Advance Tax", "TDS", "TCS", "SAT",
"Tax on Regular Assessment",
"Refund", "Remarks"
2025-12-02 15:38:19 +05:30
]
columns = [
'gross_total_income', 'disallowance_14a',
'disallowance_37', '-',
'deduction_80ia_business',
'deduction_80ia_misc',
'deduction_80ia_other',
'deduction_sec37_disallowance',
'deduction_80g', '-',
'net_taxable_income',
'tax_30_percent',
'tax_book_profit_18_5',
'tax_payable', 'surcharge',
'edu_cess', 'total_tax_payable',
'mat_credit_created',
'mat_credit_utilized',
'interest_234c', 'total_tax',
'-', 'advance_tax', 'tds',
'tcs', 'sat',
'tax_on_assessment',
'refund', 'Remarks'
2025-12-02 15:38:19 +05:30
]
data = {
"Particulars": particulars,
"ITR": [safe_get(stage_data['ITR'], col) for col in columns],
"AO": [safe_get(stage_data['AO'], col) for col in columns],
"CIT": [safe_get(stage_data['CIT'], col) for col in columns],
"ITAT": [safe_get(stage_data['ITAT'], col) for col in columns],
}
df = pd.DataFrame(data)
output = io.BytesIO()
2025-12-02 15:38:19 +05:30
with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
sheet_name = f"AY {year}-{year + 1}"
2026-01-07 00:49:42 +05:30
df.to_excel(writer, index=False, sheet_name=sheet_name, startrow=2)
2025-12-02 15:38:19 +05:30
workbook = writer.book
2026-01-07 00:49:42 +05:30
worksheet = writer.sheets[sheet_name]
title = workbook.add_format({
2026-01-07 00:49:42 +05:30
'bold': True,
'font_size': 14,
'align': 'center'
2026-01-07 00:49:42 +05:30
})
worksheet.merge_range(
0, 0, 0, len(df.columns) - 1,
"Laxmi Civil Engineering Services Pvt Ltd",
title
2026-01-07 00:49:42 +05:30
)
2025-12-02 15:38:19 +05:30
header = workbook.add_format({
'bold': True,
'align': 'center',
'bg_color': '#007bff',
'font_color': 'white',
'border': 1
})
cell = workbook.add_format({'border': 1})
2025-12-02 15:38:19 +05:30
for col_num, col_name in enumerate(df.columns):
2026-01-07 00:49:42 +05:30
worksheet.write(2, col_num, col_name, header)
worksheet.set_column(col_num, col_num, 25)
2025-12-02 15:38:19 +05:30
for row in range(len(df)):
2025-12-02 15:38:19 +05:30
for col in range(len(df.columns)):
worksheet.write(row + 3, col, df.iloc[row, col], cell)
2026-01-07 00:49:42 +05:30
worksheet.freeze_panes(3, 1)
2025-12-02 15:38:19 +05:30
output.seek(0)
2026-01-07 00:49:42 +05:30
2025-12-02 15:38:19 +05:30
return send_file(
output,
2026-01-07 00:49:42 +05:30
download_name=f"AY{year}-{year + 1}_Summary_Report.xlsx",
2025-12-02 15:38:19 +05:30
as_attachment=True,
mimetype="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
)
finally:
connection.close()