diff --git a/.gitignore b/.gitignore index 4a2326d..c823ac0 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,13 @@ logs/ +# Environment variables +.env + +# Python cache +__pycache__/ +*.pyc + +# OS / Editor +.vscode/ +.idea/ diff --git a/AppCode/AOHandler.py b/AppCode/AOHandler.py index 7aa648c..9e0979d 100644 --- a/AppCode/AOHandler.py +++ b/AppCode/AOHandler.py @@ -32,6 +32,8 @@ class AOHandler: # Add AO record def add_ao(self, data): + + try: fields = [ 'year', 'gross_total_income', 'disallowance_14a', 'disallowance_37', 'deduction_80ia_business', 'deduction_80ia_misc', 'deduction_80ia_other', @@ -40,13 +42,18 @@ class AOHandler: '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' + 'sat', 'tax_on_assessment', 'refund', 'Remarks','created_at' ] values = [data.get(f, 0) for f in fields] - self.cursor.callproc("InsertAO", values) self.conn.commit() + except Exception as e: + self.conn.rollback() + raise e + finally: + self.cursor.close() + self.conn.close() # UPDATE AO RECORD by AO id def update_ao(self, id, data): diff --git a/AppCode/CITHandler.py b/AppCode/CITHandler.py index 7762870..e214620 100644 --- a/AppCode/CITHandler.py +++ b/AppCode/CITHandler.py @@ -43,7 +43,7 @@ class CITHandler: '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' + 'sat', 'tax_on_assessment', 'refund', 'Remarks','created_at' ] values = [data.get(col, 0) for col in columns] diff --git a/AppCode/DocumentHandler.py b/AppCode/DocumentHandler.py index 81df6df..833cd35 100644 --- a/AppCode/DocumentHandler.py +++ b/AppCode/DocumentHandler.py @@ -1,4 +1,6 @@ -from flask import Flask, render_template, request, redirect, url_for, send_from_directory, abort, flash,send_file +from flask import ( + render_template, request, send_file, jsonify +) from werkzeug.utils import secure_filename import pandas as pd import os @@ -17,11 +19,40 @@ class DocumentHandler: self.isSuccess = False self.resultMessage = "" - # VIEW DOCUMENTS + # ========================= + # 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 + # ========================= def View(self, request): - year = request.args.get('year', '') + year_raw = request.args.get('year', '') stage = request.args.get('stage', '') + year = self.parse_year(year_raw) + dbconfig = DBConfig() connection = dbconfig.get_db_connection() @@ -30,15 +61,13 @@ class DocumentHandler: return cursor = connection.cursor(dictionary=True) - # --- FILTER QUERY --- + cursor.callproc("GetDocuments", [year, stage]) - # fetch first result set for result in cursor.stored_results(): self.documents = result.fetchall() break - # ---- GET YEARS FROM STORED PROCEDURE ---- cursor.callproc("GetYear") for result in cursor.stored_results(): @@ -49,55 +78,72 @@ class DocumentHandler: cursor.close() connection.close() + self.isSuccess = True + # ========================= # Upload Documents + # ========================= def Upload(self, request): dbconfig = DBConfig() connection = dbconfig.get_db_connection() - if connection: - cursor = connection.cursor() - files = request.files.getlist('documents') - year = request.form['year'] - stage = request.form['stage'] + if not connection: + return - for file in files: - extension = file.filename.rsplit('.', 1)[1] - if extension not in FileHandler.ALLOWED_EXTENSIONS: - print("Skip invalid file type : ",extension) - continue + cursor = connection.cursor() - filename = secure_filename(file.filename) - filepath = os.path.join(FileHandler.UPLOAD_FOLDER, filename) - file.save(filepath) + files = request.files.getlist('documents') + year_raw = request.form.get('year') + stage = request.form.get('stage') - cursor.callproc('InsertDocument', [ filename, filepath, extension, year, stage ]) + year = self.parse_year(year_raw) - connection.commit() - cursor.close() - connection.close() - # return redirect(url_for('view_documents')) + if not year: + self.resultMessage = "Invalid year selected." + return - def Summary_report(self, request): - dbconfig = DBConfig() - connection = dbconfig.get_db_connection() + for file in files: + if '.' not in file.filename: + continue - year_str = request.args.get('year') + extension = file.filename.rsplit('.', 1)[1].lower() - # If year not selected - if not year_str or not year_str.isdigit(): - yearGetter = YearGet() - allYears = yearGetter.get_year_by_model("AllYearsInAllModel") - yearGetter.close() - return render_template( - 'summary_reports.html', - years=allYears, - message="Please select a valid year to download." + 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] ) - # Convert year to int (IMPORTANT FIX) - year = int(year_str) + 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 = { @@ -112,11 +158,111 @@ class DocumentHandler: 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() + 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' + ] + + 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]), + }) + + return jsonify(preview) + + finally: + connection.close() + + 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 + + if not year: + yearGetter = YearGet() + allYears = yearGetter.get_year_by_model("AllYearsInAllModel") + yearGetter.close() + + return render_template( + 'summary_reports.html', + years=allYears, + message="Please select a valid year to download." + ) + + 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() @@ -124,25 +270,45 @@ class DocumentHandler: 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", " ", + "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" + "Tax on Regular Assessment", + "Refund", "Remarks" ] 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' + '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' ] data = { @@ -155,56 +321,44 @@ class DocumentHandler: df = pd.DataFrame(data) - # ===== Excel Export ===== output = io.BytesIO() + with pd.ExcelWriter(output, engine='xlsxwriter') as writer: - sheet_name = f"AY {year} - {year + 1}" + sheet_name = f"AY {year}-{year + 1}" df.to_excel(writer, index=False, sheet_name=sheet_name, startrow=2) workbook = writer.book worksheet = writer.sheets[sheet_name] - # ===== Company Heading ===== - company_heading = workbook.add_format({ + title = workbook.add_format({ 'bold': True, 'font_size': 14, - 'font_color': 'black', - 'align': 'center', - 'valign': 'middle' + 'align': 'center' }) worksheet.merge_range( 0, 0, 0, len(df.columns) - 1, "Laxmi Civil Engineering Services Pvt Ltd", - company_heading + title ) - # ===== Header Format ===== header = workbook.add_format({ 'bold': True, 'align': 'center', - 'valign': 'middle', 'bg_color': '#007bff', 'font_color': 'white', 'border': 1 }) - cell = workbook.add_format({ - 'border': 1, - 'align': 'left', - 'valign': 'middle' - }) + cell = workbook.add_format({'border': 1}) - # Write headers for col_num, col_name in enumerate(df.columns): worksheet.write(2, col_num, col_name, header) - max_len = max(df[col_name].astype(str).map(len).max(), len(col_name)) + 2 - worksheet.set_column(col_num, col_num, max_len) + worksheet.set_column(col_num, col_num, 25) - # Write data rows - for row in range(3, len(df) + 3): + for row in range(len(df)): for col in range(len(df.columns)): - worksheet.write(row, col, df.iloc[row - 3, col], cell) + worksheet.write(row + 3, col, df.iloc[row, col], cell) worksheet.freeze_panes(3, 1) @@ -219,3 +373,4 @@ class DocumentHandler: finally: connection.close() + diff --git a/AppCode/ITRHandler.py b/AppCode/ITRHandler.py index 2cec0cb..0714ca1 100644 --- a/AppCode/ITRHandler.py +++ b/AppCode/ITRHandler.py @@ -41,21 +41,29 @@ class ITRHandler: # INSERT ITR RECORD using procedure "add_itr" def add_itr(self, data): - columns = [ - 'year', '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','created_at' - ] - values = [data.get(col, 0) for col in columns] + try: + columns = [ + 'year', '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','created_at' + ] + values = [data.get(col, 0) for col in columns] + + # Call your stored procedure + self.cursor.callproc("InsertITR", values) + self.conn.commit() + except Exception as e: + self.conn.rollback() + raise e + finally: + self.cursor.close() + self.conn.close() - # Call your stored procedure - self.cursor.callproc("InsertITR", values) - self.conn.commit() # update itr by id def update(self, id, data): diff --git a/AppCode/MatCreditHandler.py b/AppCode/MatCreditHandler.py index e2cf3e6..e31ea66 100644 --- a/AppCode/MatCreditHandler.py +++ b/AppCode/MatCreditHandler.py @@ -1,15 +1,18 @@ from AppCode.Config import DBConfig + class MatCreditHandler: def __init__(self): - # db = DBConfig() self.conn = DBConfig.get_db_connection() self.cursor = self.conn.cursor(dictionary=True) - # get all Mat credit data + # -------------------------------------------------- + # FETCH ALL MAT CREDIT + UTILIZATION (For UI Display) + # -------------------------------------------------- def fetch_all(self): try: + self.cursor.callproc("GetMatCedit") result_sets = self.cursor.stored_results() mat_rows = next(result_sets).fetchall() @@ -18,30 +21,78 @@ class MatCreditHandler: return mat_rows, utilization_rows finally: self.cursor.close() + self.conn.close() - # Save Mat credit data single row + # -------------------------------------------------- + # SAVE / UPDATE SINGLE MAT ROW (FROM MANUAL UI) + # -------------------------------------------------- @staticmethod def save_single(data): conn = DBConfig.get_db_connection() cur = conn.cursor(dictionary=True) + try: + # Save / Update MAT Credit + cur.callproc( + "SaveOrUpdateMatCredit", + ( + data["financial_year"], + data["mat_credit"], + data["balance"], + data.get("remarks", "") + ) + ) - cur.callproc("SaveOrUpdateMatCredit",( - data["financial_year"], - data["mat_credit"], - data["balance"] - )) - - result = next(cur.stored_results()).fetchone() - mat_id = result["mat_id"] - - if not mat_id: - raise Exception("mat_id not returned from procedure") + mat_id = None + for result in cur.stored_results(): + mat_id = result.fetchone()["mat_id"] + # Save utilization rows for u in data.get("utilization", []): + if float(u["amount"]) > 0: + cur.callproc( + "InsertMatUtilization", + (mat_id, u["year"], u["amount"]) + ) + + conn.commit() + + except Exception as e: + conn.rollback() + raise e + finally: + cur.close() + conn.close() + + # -------------------------------------------------- + # AUTO SAVE MAT FROM ITR (MAIN LOGIC) + # -------------------------------------------------- + @staticmethod + def save_from_itr(year, mat_created, mat_utilized, remarks="Auto from"): + conn = DBConfig.get_db_connection() + cur = conn.cursor(dictionary=True) + + try: + mat_created = float(mat_created or 0) + mat_utilized = float(mat_utilized or 0) + + balance = mat_created - mat_utilized + + # Save / Update MAT Credit + cur.callproc( + "SaveOrUpdateMatCredit", + (year, mat_created, balance, remarks) + ) + + mat_id = None + for result in cur.stored_results(): + mat_id = result.fetchone()["mat_id"] + + # Save utilization only if used + if mat_utilized > 0: cur.callproc( "InsertMatUtilization", - (mat_id, u["year"], u["amount"]) + (mat_id, year, mat_utilized) ) conn.commit() @@ -49,56 +100,29 @@ class MatCreditHandler: except Exception as e: conn.rollback() raise e - finally: cur.close() conn.close() - - # save all Mat credit data - # @staticmethod - # def save_bulk(rows): - # conn = DBConfig.get_db_connection() - # cur = conn.cursor() - # skipped = [] - # try: - # for row in rows: - # cur.execute( - # "SELECT id FROM mat_credit WHERE financial_year=%s", - # (row["financial_year"],) - # ) - # if cur.fetchone(): - # skipped.append(row["financial_year"]) - # continue + # -------------------------------------------------- + # DELETE MAT CREDIT SAFELY (OPTIONAL) + # -------------------------------------------------- + def delete_by_year(self, financial_year): + try: + self.cursor.execute( + "DELETE FROM mat_credit WHERE financial_year=%s", + (financial_year,) + ) + self.conn.commit() + finally: + self.cursor.close() + self.conn.close() - # cur.execute(""" - # INSERT INTO mat_credit (financial_year, mat_credit, balance) - # VALUES (%s,%s,%s) - # """, (row["financial_year"], row["mat_credit"], row["balance"])) - - # mat_id = cur.lastrowid - - # for u in row["utilization"]: - # cur.execute(""" - # INSERT INTO mat_utilization - # (mat_credit_id, utilized_year, utilized_amount) - # VALUES (%s,%s,%s) - # """, (mat_id, u["year"], u["amount"])) - - # conn.commit() - # return skipped - - # except Exception: - # conn.rollback() - # raise - - # finally: - # cur.close() - # conn.close() - - # CLOSE CONNECTION + # -------------------------------------------------- + # CLOSE CONNECTION (MANUAL USE) + # -------------------------------------------------- def close(self): - self.cursor.close() - self.conn.close() - - + if self.cursor: + self.cursor.close() + if self.conn: + self.conn.close() diff --git a/AppCode/__pycache__/AOHandler.cpython-311.pyc b/AppCode/__pycache__/AOHandler.cpython-311.pyc deleted file mode 100644 index f37200f..0000000 Binary files a/AppCode/__pycache__/AOHandler.cpython-311.pyc and /dev/null differ diff --git a/AppCode/__pycache__/AOHandler.cpython-312.pyc b/AppCode/__pycache__/AOHandler.cpython-312.pyc deleted file mode 100644 index ef05e4a..0000000 Binary files a/AppCode/__pycache__/AOHandler.cpython-312.pyc and /dev/null differ diff --git a/AppCode/__pycache__/AOHandler.cpython-313.pyc b/AppCode/__pycache__/AOHandler.cpython-313.pyc index d1b3df1..f240bf4 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-311.pyc b/AppCode/__pycache__/CITHandler.cpython-311.pyc deleted file mode 100644 index 86c8608..0000000 Binary files a/AppCode/__pycache__/CITHandler.cpython-311.pyc and /dev/null differ diff --git a/AppCode/__pycache__/CITHandler.cpython-312.pyc b/AppCode/__pycache__/CITHandler.cpython-312.pyc deleted file mode 100644 index aa7ce45..0000000 Binary files a/AppCode/__pycache__/CITHandler.cpython-312.pyc and /dev/null differ diff --git a/AppCode/__pycache__/CITHandler.cpython-313.pyc b/AppCode/__pycache__/CITHandler.cpython-313.pyc index 6c03b4e..db11e6d 100644 Binary files a/AppCode/__pycache__/CITHandler.cpython-313.pyc and b/AppCode/__pycache__/CITHandler.cpython-313.pyc differ diff --git a/AppCode/__pycache__/Config.cpython-311.pyc b/AppCode/__pycache__/Config.cpython-311.pyc deleted file mode 100644 index 7ac6d23..0000000 Binary files a/AppCode/__pycache__/Config.cpython-311.pyc and /dev/null differ diff --git a/AppCode/__pycache__/Config.cpython-312.pyc b/AppCode/__pycache__/Config.cpython-312.pyc deleted file mode 100644 index 0a9a5fc..0000000 Binary files a/AppCode/__pycache__/Config.cpython-312.pyc and /dev/null differ diff --git a/AppCode/__pycache__/Config.cpython-313.pyc b/AppCode/__pycache__/Config.cpython-313.pyc index 45757f6..6a4f56d 100644 Binary files a/AppCode/__pycache__/Config.cpython-313.pyc and b/AppCode/__pycache__/Config.cpython-313.pyc differ diff --git a/AppCode/__pycache__/DocumentHandler.cpython-311.pyc b/AppCode/__pycache__/DocumentHandler.cpython-311.pyc deleted file mode 100644 index b68a4c0..0000000 Binary files a/AppCode/__pycache__/DocumentHandler.cpython-311.pyc and /dev/null differ diff --git a/AppCode/__pycache__/DocumentHandler.cpython-312.pyc b/AppCode/__pycache__/DocumentHandler.cpython-312.pyc deleted file mode 100644 index ab89779..0000000 Binary files a/AppCode/__pycache__/DocumentHandler.cpython-312.pyc and /dev/null differ diff --git a/AppCode/__pycache__/DocumentHandler.cpython-313.pyc b/AppCode/__pycache__/DocumentHandler.cpython-313.pyc index e8cf652..cbff30c 100644 Binary files a/AppCode/__pycache__/DocumentHandler.cpython-313.pyc and b/AppCode/__pycache__/DocumentHandler.cpython-313.pyc differ diff --git a/AppCode/__pycache__/FileHandler.cpython-311.pyc b/AppCode/__pycache__/FileHandler.cpython-311.pyc deleted file mode 100644 index 1a058aa..0000000 Binary files a/AppCode/__pycache__/FileHandler.cpython-311.pyc and /dev/null differ diff --git a/AppCode/__pycache__/FileHandler.cpython-312.pyc b/AppCode/__pycache__/FileHandler.cpython-312.pyc deleted file mode 100644 index 095e62d..0000000 Binary files a/AppCode/__pycache__/FileHandler.cpython-312.pyc and /dev/null differ diff --git a/AppCode/__pycache__/FileHandler.cpython-313.pyc b/AppCode/__pycache__/FileHandler.cpython-313.pyc deleted file mode 100644 index de33b2b..0000000 Binary files a/AppCode/__pycache__/FileHandler.cpython-313.pyc and /dev/null differ diff --git a/AppCode/__pycache__/ITATHandler.cpython-311.pyc b/AppCode/__pycache__/ITATHandler.cpython-311.pyc deleted file mode 100644 index 14a3182..0000000 Binary files a/AppCode/__pycache__/ITATHandler.cpython-311.pyc and /dev/null differ diff --git a/AppCode/__pycache__/ITATHandler.cpython-312.pyc b/AppCode/__pycache__/ITATHandler.cpython-312.pyc deleted file mode 100644 index e750cde..0000000 Binary files a/AppCode/__pycache__/ITATHandler.cpython-312.pyc and /dev/null differ diff --git a/AppCode/__pycache__/ITATHandler.cpython-313.pyc b/AppCode/__pycache__/ITATHandler.cpython-313.pyc deleted file mode 100644 index 9901af2..0000000 Binary files a/AppCode/__pycache__/ITATHandler.cpython-313.pyc and /dev/null differ diff --git a/AppCode/__pycache__/ITRHandler.cpython-311.pyc b/AppCode/__pycache__/ITRHandler.cpython-311.pyc deleted file mode 100644 index 3233e6c..0000000 Binary files a/AppCode/__pycache__/ITRHandler.cpython-311.pyc and /dev/null differ diff --git a/AppCode/__pycache__/ITRHandler.cpython-312.pyc b/AppCode/__pycache__/ITRHandler.cpython-312.pyc deleted file mode 100644 index 43f711d..0000000 Binary files a/AppCode/__pycache__/ITRHandler.cpython-312.pyc and /dev/null differ diff --git a/AppCode/__pycache__/ITRHandler.cpython-313.pyc b/AppCode/__pycache__/ITRHandler.cpython-313.pyc index 7047dc7..ff3661d 100644 Binary files a/AppCode/__pycache__/ITRHandler.cpython-313.pyc and b/AppCode/__pycache__/ITRHandler.cpython-313.pyc differ diff --git a/AppCode/__pycache__/LoginAuth.cpython-311.pyc b/AppCode/__pycache__/LoginAuth.cpython-311.pyc deleted file mode 100644 index 9c2d837..0000000 Binary files a/AppCode/__pycache__/LoginAuth.cpython-311.pyc and /dev/null differ diff --git a/AppCode/__pycache__/LoginAuth.cpython-312.pyc b/AppCode/__pycache__/LoginAuth.cpython-312.pyc deleted file mode 100644 index cfc6d1f..0000000 Binary files a/AppCode/__pycache__/LoginAuth.cpython-312.pyc and /dev/null differ diff --git a/AppCode/__pycache__/YearGet.cpython-311.pyc b/AppCode/__pycache__/YearGet.cpython-311.pyc deleted file mode 100644 index b264802..0000000 Binary files a/AppCode/__pycache__/YearGet.cpython-311.pyc and /dev/null differ diff --git a/AppCode/__pycache__/YearGet.cpython-312.pyc b/AppCode/__pycache__/YearGet.cpython-312.pyc deleted file mode 100644 index 4f57296..0000000 Binary files a/AppCode/__pycache__/YearGet.cpython-312.pyc and /dev/null differ diff --git a/AppCode/__pycache__/YearGet.cpython-313.pyc b/AppCode/__pycache__/YearGet.cpython-313.pyc deleted file mode 100644 index 4f6509e..0000000 Binary files a/AppCode/__pycache__/YearGet.cpython-313.pyc and /dev/null differ diff --git a/main.py b/main.py index 1b2dfa6..28750b1 100644 --- a/main.py +++ b/main.py @@ -15,6 +15,7 @@ from AppCode.AOHandler import AOHandler from AppCode.CITHandler import CITHandler from AppCode.ITATHandler import ITATHandler from AppCode.MatCreditHandler import MatCreditHandler +import subprocess @@ -59,7 +60,6 @@ def view_documents(): docHandler.View(request=request) return render_template('view_docs.html', documents=docHandler.documents, years=docHandler.years) - # Upload file documents @app.route('/uploads/') @auth.login_required @@ -68,20 +68,26 @@ def uploaded_file(filename): filepath = os.path.join(FileHandler.UPLOAD_FOLDER, secure_filename(filename)) if not os.path.exists(filepath): - abort(404) + flash("Unsupported file type for viewing", "warning") + return redirect(url_for('view_documents')) file_ext = filename.rsplit('.', 1)[-1].lower() # --- View Mode --- if mode == 'view': + # pdf if file_ext == 'pdf': return send_file(filepath, mimetype='application/pdf') + # Word + elif file_ext in ['doc', 'docx']: + return send_file(filepath, as_attachment=True) + # Excel elif file_ext in ['xls', 'xlsx']: - # Excel cannot be rendered in-browser by Flask; trigger download instead return send_file(filepath, as_attachment=False, download_name=filename, mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') else: - return abort(415) # Unsupported type for viewing + flash("Unsupported file type for viewing", "warning") + return redirect(url_for('view_documents')) - return send_file(filepath, as_attachment=True) + return send_file(filepath, as_attachment=True, download_name=filename) @@ -105,20 +111,28 @@ def display_itr(): def add_itr(): if request.method == 'POST': itr = ITRHandler() + mat = MatCreditHandler() itr.add_itr(request.form) itr.close() - if 'documents' in request.files: doc = DocumentHandler() doc.Upload(request) + # AUTO SAVE MAT FROM ITR + mat.save_from_itr( + year=request.form["year"], + mat_created=float(request.form.get("mat_credit_created", 0)), + mat_utilized=float(request.form.get("mat_credit_utilized", 0)), + remarks="Created via ITR" + ) + # flash("ITR record added successfully!", "success") flash("ITR record and documents uploaded successfully!", "success") return redirect(url_for('display_itr')) return render_template('add_itr.html',current_date=date.today().isoformat()) -## 4. DELETE an ITR record +## 4. DELETE an ITR records @app.route('/itr/delete/', methods=['POST']) @auth.login_required def delete_itr(id): @@ -166,11 +180,25 @@ def display_ao(): def add_ao(): if request.method == 'POST': ao = AOHandler() + mat = MatCreditHandler() ao.add_ao(request.form) ao.close() + + if 'documents' in request.files: + doc = DocumentHandler() + doc.Upload(request) + + # AUTO SAVE MAT FROM ITR + mat.save_from_itr( + year=request.form["year"], + mat_created=float(request.form.get("mat_credit_created", 0)), + mat_utilized=float(request.form.get("mat_credit_utilized", 0)), + remarks="Created via ao" + ) + flash("AO record added successfully!", "success") return redirect(url_for('display_ao')) - return render_template('add_ao.html') + return render_template('add_ao.html',current_date=date.today().isoformat()) # 3. UPDATE AO record @app.route('/ao/update/', methods=['GET', 'POST']) @@ -224,12 +252,25 @@ def display_cit(): def add_cit(): if request.method == 'POST': cit = CITHandler() + mat = MatCreditHandler() cit.add_cit(request.form) cit.close() + + if 'documents' in request.files: + doc = DocumentHandler() + doc.Upload(request) + + # AUTO SAVE MAT FROM ITR + mat.save_from_itr( + year=request.form["year"], + mat_created=float(request.form.get("mat_credit_created", 0)), + mat_utilized=float(request.form.get("mat_credit_utilized", 0)), + remarks="Created via cit" + ) flash("CIT record added successfully!", "success") return redirect(url_for('display_cit')) - return render_template('add_cit.html') + return render_template('add_cit.html', current_date=date.today().isoformat()) # 3 delete CIT records by id @app.route('/cit/delete/', methods=['POST']) @@ -281,13 +322,27 @@ def display_itat(): def add_itat(): if request.method == 'POST': itat = ITATHandler() + mat = MatCreditHandler() data = {k: request.form.get(k, 0) for k in request.form} itat.add_itat(data) itat.close() + + if 'documents' in request.files: + doc = DocumentHandler() + doc.Upload(request) + + # AUTO SAVE MAT FROM ITR + mat.save_from_itr( + year=request.form["year"], + mat_created=float(request.form.get("mat_credit_created", 0)), + mat_utilized=float(request.form.get("mat_credit_utilized", 0)), + remarks="Created via ITR" + ) + flash("ITAT record added successfully!", "success") return redirect(url_for('display_itat')) - return render_template('add_itat.html') + return render_template('add_itat.html',current_date=date.today().isoformat()) # 3.Update ITAT records by id @app.route('/itat/update/', methods=['GET', 'POST']) @@ -449,6 +504,17 @@ def summary_report(): docHandler = DocumentHandler() return docHandler.Summary_report(request=request) +@app.route('/summary/download', methods=['GET']) +@auth.login_required +def download_summary(): + year_raw = request.args.get('year') + if not year_raw: + return "Year parameter is required", 400 + + docHandler = DocumentHandler() + # reuse your existing Summary_report method + return docHandler.Summary_report(request=request) + # check year in table existe or not by using ajax calling. # @app.route('/check_year', methods=['POST']) @@ -519,6 +585,12 @@ def save_mat_row(): finally: mat.close() +@app.route("/summary/preview") +def summary_preview_route(): + handler = DocumentHandler() + return handler.Summary_preview(request) + + # save mat credit bulk data # @app.route("/save_mat_all", methods=["POST"]) # @auth.login_required diff --git a/static/css/summary.css b/static/css/summary.css index 1888f4c..d83932b 100644 --- a/static/css/summary.css +++ b/static/css/summary.css @@ -1,153 +1,278 @@ -/* ================= GLOBAL FORM ELEMENTS ================= */ +/* ================= PAGE WRAPPER ================= */ +.main { + margin-left: 260px; + width: calc(100% - 260px); + margin-top: 80px; + padding: 20px; + transition: all 0.3s ease; +} + +/* ================= CONTAINER ================= */ +.container { + width: 100%; + max-width: none; + margin: 0; + padding: 25px 30px; + background: #ffffff; + border-radius: 12px; + box-shadow: 0 8px 22px rgba(0, 0, 0, 0.08); +} + +/* ================= PAGE TITLE ================= */ +.container h2 { + text-align: center; + color: #007bff; + font-size: 22px; + font-weight: 700; + margin-bottom: 20px; +} + +h3 { + text-align: center; + margin-top: 10px; +} + +/* ================= FORM ================= */ +form { + width: 100%; +} + form label { - display: block; - margin-top: 10px; - font-weight: bold; - color: #333; + display: block; + margin-top: 10px; + font-weight: 600; + color: #333; } -select { - width: 100%; - max-width: 300px; - /* restrict width on desktop/laptop */ - padding: 10px 12px; - border: 1px solid #ccc; - border-radius: 6px; - margin-top: 6px; - font-size: 15px; - background-color: white; - cursor: pointer; - transition: 0.2s; +/* ================= INPUTS ================= */ +form input, +form select { + width: 100%; + padding: 10px 12px; + margin-top: 6px; + border: 1px solid #ccc; + border-radius: 6px; + background-color: #f8f9ff; + font-size: 14px; } -select:focus { - border-color: #007bff; - box-shadow: 0 0 5px rgba(0, 123, 255, 0.5); - outline: none; +form input:focus, +form select:focus { + outline: none; + border-color: #007bff; + box-shadow: 0 0 6px rgba(0, 123, 255, 0.35); +} + +/* ================= AUTO FIELDS ================= */ +.auto { + background-color: #d5edd7; + font-weight: 600; +} + +/* ================= FORM GROUP ================= */ +.form-group { + margin-bottom: 16px; + display: flex; + flex-direction: column; + font-weight: 600; +} + +/* Inline two columns */ +.form-group.inline-2 { + flex-direction: row; + gap: 16px; +} + +.form-group.inline-2 > div { + flex: 1; } /* ================= BUTTONS ================= */ button { - margin-top: 20px; - padding: 10px 18px; - background-color: #007bff; - color: white; - border: none; - cursor: pointer; - border-radius: 6px; - font-size: 15px; - font-weight: 600; - transition: 0.3s; + display: block; + width: 60%; + margin: 25px auto 0; + padding: 12px 20px; + background-color: #28a745; + color: #fff; + border: none; + border-radius: 6px; + font-size: 15px; + font-weight: 600; + cursor: pointer; + transition: 0.3s; } button:hover { - background-color: #0069d9; -} - -/* ================= MAIN CONTAINER ================= */ -.main { - margin-left: 260px; - /* sidebar width if exists */ - padding: 70px 30px 40px 30px; - /* top padding for navbar */ - margin-top: 50px; - /* extra top spacing */ - width: auto; - transition: 0.3s; -} - -.container { - max-width: 800px; - margin: 0 auto; - background: #ffffff; - padding: 35px 40px; - border-radius: 12px; - box-shadow: 0 8px 22px rgba(0, 0, 0, 0.08); + background-color: #218838; + box-shadow: 0 4px 10px rgba(40, 167, 69, 0.35); } /* ================= BACK BUTTON ================= */ .back-btn { - display: inline-block; - margin-top: 20px; - padding: 10px 18px; - background-color: #007bff; - color: white; - font-size: 15px; - font-weight: 600; - border-radius: 6px; - text-decoration: none; - transition: 0.3s; + display: inline-block; + margin-top: 20px; + padding: 10px 18px; + background-color: #007bff; + color: #fff; + font-size: 15px; + font-weight: 600; + border-radius: 6px; + text-decoration: none; + transition: 0.3s; } .back-btn:hover { - background-color: #006ae6; + background-color: #006ae6; } -/* ================= MESSAGES ================= */ +/* ================= STICKY FILTER BAR ================= */ +.head { + position: sticky; + top: 60px; + background: #fff; + z-index: 1000; + padding: 15px 0; + border-bottom: 1px solid #ccc; +} + +/* ================= SELECT + DOWNLOAD ================= */ +.select-download-wrapper { + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 10px; +} + +.select-download-wrapper select { + max-width: 300px; +} + +select { + width: 100%; + max-width: 300px; + padding: 10px 12px; + border: 1px solid #ccc; + border-radius: 6px; + margin-top: 6px; + font-size: 15px; + background-color: white; + cursor: pointer; + transition: 0.2s; +} + +select:focus { + border-color: #007bff; + box-shadow: 0 0 5px rgba(0,123,255,0.5); + outline: none; +} + +/* ================= DOWNLOAD BUTTON ================= */ +#downloadBtn { + display: none; + padding: 10px 20px; + font-size: 16px; + background-color: #28a745; + color: #fff; + text-decoration: none; + border-radius: 4px; + white-space: nowrap; + transition: 0.3s; +} + +#downloadBtn:hover { + background-color: #218838; +} + +/* ================= TABLE PREVIEW ================= */ +#previewContent { + max-height: 60vh; + overflow-y: auto; + overflow-x: auto; + width: 100%; + margin-top: 15px; +} + +#previewContent table { + width: 100%; + min-width: 600px; + border-collapse: collapse; +} + +#previewContent th, +#previewContent td { + padding: 10px; + border: 1px solid #ccc; + white-space: nowrap; +} + +/* Sticky table header */ +#previewContent th { + position: sticky; + top: 0; + background-color: #007bff; + color: #fff; + z-index: 10; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); +} + +/* ================= MESSAGE ================= */ .message { - margin-top: 15px; - color: #555; - font-size: 14px; + margin-top: 15px; + color: #555; + font-size: 14px; } /* ================= RESPONSIVE ================= */ - -/* Tablets (<= 992px) */ @media (max-width: 992px) { - .main { - margin-left: 0; - /* remove sidebar spacing */ - padding: 50px 20px 20px 20px; - } + .main { + margin-left: 0; + width: 100%; + padding: 20px; + } - .container { - padding: 25px 20px; - } - - select { - max-width: 100%; - /* full width */ - } - - button { - width: 100%; - /* full width */ - padding: 12px 0; - } + button { + width: 100%; + } +} + +@media (max-width: 768px) { + .container { + padding: 18px; + } + + .container h2 { + font-size: 18px; + } + + .form-group.inline-2 { + flex-direction: column; + gap: 10px; + } } -/* Mobile (<= 576px) */ @media (max-width: 576px) { - .main { - padding: 40px 15px 15px 15px; - } + .main { + padding: 15px; + margin-top: 70px; + } - .container { - padding: 20px; - } + #previewContent table { + min-width: 500px; + } - h2 { - font-size: 22px; - text-align: center; - } + #previewContent th, + #previewContent td { + font-size: 13px; + padding: 8px; + } +} - select { - font-size: 14px; - padding: 10px; - } - - button { - font-size: 14px; - padding: 12px 0; - } - - .back-btn { - width: 100%; - text-align: center; - padding: 12px 0; - } - - .message { - font-size: 13px; - } -} \ No newline at end of file +@media (max-width: 420px) { + form input, + form select { + font-size: 13px; + padding: 9px; + } +} diff --git a/static/js/ao_calc.js b/static/js/ao_calc.js index 8e5b445..0241981 100644 --- a/static/js/ao_calc.js +++ b/static/js/ao_calc.js @@ -46,16 +46,6 @@ document.addEventListener("DOMContentLoaded", function () { var tax_payable = (tax30 > tax185) ? tax30 : tax185; setValue("tax_payable", tax_payable); - // // --- SURCHARGE --- - // var percent = getValue("persentage"); - // var surcharge = tax_payable * (percent / 100); - // setValue("surcharge", surcharge); - - // // --- edu_cess --- - // var per_cess = getValue("persentage_cess") - // var edu_cess = (tax_payable + surcharge) * (per_cess / 100); - // setValue("edu_cess", edu_cess); - // --- SURCHARGE --- var percent = getValue("persentage"); var surcharge = tax_payable * (percent / 100); @@ -70,11 +60,37 @@ document.addEventListener("DOMContentLoaded", function () { var total_tax_payable = tax_payable + surcharge + edu_cess; setValue("total_tax_payable", total_tax_payable); + // // --- mat_credit_created --- new + // setValue("mat_credit_created", Math.max(tax185 - total_tax_payable, 0)); + // // --- mat credit_utilized --- new + // setValue("mat_credit_utilized", Math.max(total_tax_payable - tax185, 0)); + + // --- MAT credit and utilized --- + var a = tax185 + var b = total_tax_payable + var result = 0 + if (a > b) { + result = a - b + setValue("mat_credit_created", result); + } + else { + setValue("mat_credit_created", result); + } + + if (b > a) { + result = b - a + setValue("mat_credit_utilized", result); + } + else { + setValue("mat_credit_utilized", result); + } + // --- FINAL TAX --- var mat_credit = getValue("mat_credit_utilized"); var interest_234c = getValue("interest_234c"); - var total_tax = total_tax_payable + mat_credit + interest_234c; + // var total_tax = total_tax_payable + mat_credit + interest_234c; + var total_tax = total_tax_payable - mat_credit + interest_234c; setValue("total_tax", total_tax); // --- ASSESSMENT --- diff --git a/static/js/cit_calc.js b/static/js/cit_calc.js index 1a08b64..26b731e 100644 --- a/static/js/cit_calc.js +++ b/static/js/cit_calc.js @@ -68,6 +68,28 @@ document.addEventListener("DOMContentLoaded", function () { var total_tax_payable = tax_payable + surcharge + edu_cess; setValue("total_tax_payable", total_tax_payable); + + // --- mat credit_utilized --- + var a = tax185 + var b = total_tax_payable + var result = 0 + if (a > b) { + result = a - b + setValue("mat_credit_created", result); + } + else { + setValue("mat_credit_created", result); + } + + if (b > a) { + result = b - a + setValue("mat_credit_utilized", result); + } + else { + setValue("mat_credit_utilized", result); + } + + // --- FINAL TAX --- var mat_credit = getValue("mat_credit_utilized"); var interest_234c = getValue("interest_234c"); diff --git a/static/js/itr_calc.js b/static/js/itr_calc.js index 1ca7d5d..d6ac2f2 100644 --- a/static/js/itr_calc.js +++ b/static/js/itr_calc.js @@ -61,16 +61,36 @@ document.addEventListener("DOMContentLoaded", function () { setValue("total_tax_payable", total_tax_payable); // --- mat_credit_created --- new - setValue("mat_credit_created", Math.max(tax185 - total_tax_payable, 0)); - // --- mat credit_utilized --- new - setValue("mat_credit_utilized", Math.max(total_tax_payable - tax185, 0)); + // setValue("mat_credit_created", Math.max(tax185 - total_tax_payable, 0)); + // // --- mat credit_utilized --- new + // setValue("mat_credit_utilized", Math.max(total_tax_payable - tax185, 0)); + + // --- mat credit_utilized --- + var a = tax185 + var b = total_tax_payable + var result = 0 + if (a > b) { + result = a - b + setValue("mat_credit_created", result); + } + else { + setValue("mat_credit_created", result); + } + + if (b > a) { + result = b - a + setValue("mat_credit_utilized", result); + } + else { + setValue("mat_credit_utilized", result); + } // --- FINAL TAX --- var mat_credit = getValue("mat_credit_utilized"); var interest_234c = getValue("interest_234c"); // var total_tax = total_tax_payable + mat_credit + interest_234c; - var total_tax = total_tax_payable + mat_credit + interest_234c; + var total_tax = total_tax_payable + interest_234c; setValue("total_tax", total_tax); // --- ASSESSMENT --- diff --git a/static/js/summary_preview.js b/static/js/summary_preview.js new file mode 100644 index 0000000..87ac7d7 --- /dev/null +++ b/static/js/summary_preview.js @@ -0,0 +1,50 @@ +document.getElementById("year").addEventListener("change", function () { + const year = this.value; + + const downloadBtn = document.getElementById("downloadBtn"); + const previewDiv = document.getElementById("preview"); + const contentDiv = document.getElementById("previewContent"); + + if (!year) { + downloadBtn.style.display = "none"; + previewDiv.style.display = "none"; + contentDiv.innerHTML = ""; + return; + } + + downloadBtn.href = `/summary/download?year=${year}`; + downloadBtn.style.display = "inline-block"; + + fetch(`/summary/preview?year=${year}`) + .then(res => res.json()) + .then(data => { + let html = ` + + + + + + + + + + `; + + data.forEach(row => { + html += ` + + + + + + `; + }); + + html += `
ParticularITRAOCITITAT
${row.Particular}${row.ITR}${row.AO}${row.CIT}${row.ITAT}
`; + contentDiv.innerHTML = html; + + // Show preview + previewDiv.style.display = "block"; + }) + .catch(err => console.error("Preview load error:", err)); +}); diff --git a/templates/add_ao.html b/templates/add_ao.html index 0ca4943..c5bef34 100644 --- a/templates/add_ao.html +++ b/templates/add_ao.html @@ -10,7 +10,8 @@

New Assessing Officer Form

-
+ +
@@ -19,11 +20,12 @@ -- Please select Assessment Year -- - - -
+
+ + +
@@ -170,9 +172,15 @@
-
- - +
+
+ + +
+
+ + +
diff --git a/templates/add_cit.html b/templates/add_cit.html index ad7c933..6b4ea4f 100644 --- a/templates/add_cit.html +++ b/templates/add_cit.html @@ -9,7 +9,8 @@ {% block content %}

New CIT Form

- + +
@@ -20,6 +21,10 @@
+
+ + +
@@ -166,9 +171,15 @@
-
- - +
+
+ + +
+
+ + +
diff --git a/templates/add_itat.html b/templates/add_itat.html index 346fa27..ab23faa 100644 --- a/templates/add_itat.html +++ b/templates/add_itat.html @@ -10,8 +10,8 @@ {% block content %}

New Income Tax Appellate Tribunal Form

- - + +
@@ -22,6 +22,10 @@
+
+ + +
@@ -172,9 +176,15 @@
-
- - +
+
+ + +
+
+ + +
diff --git a/templates/add_itr.html b/templates/add_itr.html index c112eff..d45dc75 100644 --- a/templates/add_itr.html +++ b/templates/add_itr.html @@ -23,7 +23,7 @@
- +
diff --git a/templates/display_ao.html b/templates/display_ao.html index 149cede..2877760 100644 --- a/templates/display_ao.html +++ b/templates/display_ao.html @@ -22,6 +22,7 @@ Gross Total Income Net Taxable Income Total Tax + Created Record Date Actions @@ -32,6 +33,7 @@ {{ ao.gross_total_income }} {{ ao.net_taxable_income }} {{ ao.total_tax }} + {{ ao.created_at.strftime('%Y-%m-%d') }} Edit diff --git a/templates/mat_credit.html b/templates/mat_credit.html index 7552245..a11f146 100644 --- a/templates/mat_credit.html +++ b/templates/mat_credit.html @@ -42,7 +42,7 @@ {% for row in mat_rows %} - {{ row.financial_year }} + {{ row.financial_year }}-{{ row.financial_year | int + 1 }} {% for y in added_years %} diff --git a/templates/summary_reports.html b/templates/summary_reports.html index def7dd6..e475d51 100644 --- a/templates/summary_reports.html +++ b/templates/summary_reports.html @@ -1,32 +1,34 @@ -{% extends "base.html" %} - -{% block title %}Download Summary Report{% endblock %} - +{% extends "base.html" %} {% block title %}Download Summary Report{% endblock %} {% block extra_css %} - - -{% endblock %} - -{% block content %} + +{% endblock %} {% block content %}
+

Download Year-wise Summary Report

{% if message %}

{{ message }}

{% endif %} - - - +
+ - - + Download Summary Report +
+
+ +
- +{% endblock %} {% block extra_js %} + {% endblock %} \ No newline at end of file diff --git a/templates/update_ao.html b/templates/update_ao.html index 9229ffa..42a0fdd 100644 --- a/templates/update_ao.html +++ b/templates/update_ao.html @@ -8,7 +8,7 @@ {% block content %}
-

Update AO Record for Year {{ record.year }}--{{ record.year + 1 }}

+

Update AO Record for Year {{ record.year }} - {{ record.year + 1 }}

@@ -169,6 +169,23 @@
+ +
+
+ + +
+ +
+ + +
+
+ diff --git a/templates/view_docs.html b/templates/view_docs.html index 2e04993..1bb81a1 100644 --- a/templates/view_docs.html +++ b/templates/view_docs.html @@ -27,7 +27,11 @@ - + {% with messages = get_flashed_messages(with_categories=true) %} + {% for category, message in messages %} +
{{ message }}
+ {% endfor %} + {% endwith %}