Compare commits
3 Commits
ac5064e4f8
...
aaab008a9d
| Author | SHA1 | Date | |
|---|---|---|---|
| aaab008a9d | |||
| a9af2cde8a | |||
| a0f4568ba2 |
5
.dockerignore
Normal file
5
.dockerignore
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
.git
|
||||||
|
.idea
|
||||||
|
venv
|
||||||
25
.env
Normal file
25
.env
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# -----------------------------
|
||||||
|
# Flask App Configuration
|
||||||
|
# -----------------------------
|
||||||
|
FLASK_ENV=development
|
||||||
|
FLASK_DEBUG=true
|
||||||
|
FLASK_HOST=0.0.0.0
|
||||||
|
FLASK_PORT=5010
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Security
|
||||||
|
# -----------------------------
|
||||||
|
SECRET_KEY=secret1234
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Database Configuration
|
||||||
|
# -----------------------------
|
||||||
|
DB_DIALECT=mysql
|
||||||
|
# DB_DRIVER=pymysql
|
||||||
|
DB_HOST=127.0.0.1
|
||||||
|
# DB_HOST=db # this is production for use docker
|
||||||
|
DB_PORT=3306
|
||||||
|
DB_NAME=test_income_taxdb
|
||||||
|
DB_USER=root
|
||||||
|
DB_PASSWORD=root
|
||||||
|
|
||||||
@@ -3,7 +3,6 @@ import mysql.connector
|
|||||||
import pandas as pd
|
import pandas as pd
|
||||||
import io
|
import io
|
||||||
|
|
||||||
|
|
||||||
class AOHandler:
|
class AOHandler:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -33,6 +32,8 @@ class AOHandler:
|
|||||||
|
|
||||||
# Add AO record
|
# Add AO record
|
||||||
def add_ao(self, data):
|
def add_ao(self, data):
|
||||||
|
|
||||||
|
try:
|
||||||
fields = [
|
fields = [
|
||||||
'year', 'gross_total_income', 'disallowance_14a', 'disallowance_37',
|
'year', 'gross_total_income', 'disallowance_14a', 'disallowance_37',
|
||||||
'deduction_80ia_business', 'deduction_80ia_misc', 'deduction_80ia_other',
|
'deduction_80ia_business', 'deduction_80ia_misc', 'deduction_80ia_other',
|
||||||
@@ -41,14 +42,18 @@ class AOHandler:
|
|||||||
'tax_payable', 'surcharge', 'edu_cess',
|
'tax_payable', 'surcharge', 'edu_cess',
|
||||||
'total_tax_payable', 'mat_credit_created', 'mat_credit_utilized',
|
'total_tax_payable', 'mat_credit_created', 'mat_credit_utilized',
|
||||||
'interest_234c', 'total_tax', 'advance_tax', 'tds', 'tcs',
|
'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]
|
values = [data.get(f, 0) for f in fields]
|
||||||
|
|
||||||
self.cursor.callproc("InsertAO", values)
|
self.cursor.callproc("InsertAO", values)
|
||||||
self.conn.commit()
|
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
|
# UPDATE AO RECORD by AO id
|
||||||
def update_ao(self, id, data):
|
def update_ao(self, id, data):
|
||||||
@@ -193,8 +198,6 @@ class AOHandler:
|
|||||||
print("MySQL Error →", e)
|
print("MySQL Error →", e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# CLOSE CONNECTION
|
# CLOSE CONNECTION
|
||||||
def close(self):
|
def close(self):
|
||||||
self.cursor.close()
|
self.cursor.close()
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import mysql.connector
|
|||||||
import pandas as pd
|
import pandas as pd
|
||||||
import io
|
import io
|
||||||
|
|
||||||
|
|
||||||
class CITHandler:
|
class CITHandler:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|||||||
@@ -1,21 +1,43 @@
|
|||||||
|
# import mysql.connector
|
||||||
|
# import os
|
||||||
|
|
||||||
|
# # Database Config
|
||||||
|
# class DBConfig:
|
||||||
|
# MYSQL_HOST = os.getenv("DB_HOST")
|
||||||
|
# MYSQL_USER = os.getenv("DB_USER")
|
||||||
|
# MYSQL_PASSWORD = os.getenv("DB_PASSWORD")
|
||||||
|
# MYSQL_DB = os.getenv("DB_NAME")
|
||||||
|
|
||||||
|
# @staticmethod
|
||||||
|
# def get_db_connection():
|
||||||
|
# """
|
||||||
|
# Returns a MySQL connection object.
|
||||||
|
# """
|
||||||
|
# return mysql.connector.connect(
|
||||||
|
# host=DBConfig.MYSQL_HOST,
|
||||||
|
# user=DBConfig.MYSQL_USER,
|
||||||
|
# password=DBConfig.MYSQL_PASSWORD,
|
||||||
|
# database=DBConfig.MYSQL_DB
|
||||||
|
# )
|
||||||
|
|
||||||
|
|
||||||
import mysql.connector
|
import mysql.connector
|
||||||
import os
|
import os
|
||||||
|
|
||||||
# Database Config
|
|
||||||
class DBConfig:
|
|
||||||
MYSQL_HOST = os.getenv("DB_HOST")
|
|
||||||
MYSQL_USER = os.getenv("DB_USER")
|
|
||||||
MYSQL_PASSWORD = os.getenv("DB_PASSWORD")
|
|
||||||
MYSQL_DB = os.getenv("DB_NAME")
|
|
||||||
|
|
||||||
|
class DBConfig:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_db_connection():
|
def get_db_connection():
|
||||||
"""
|
"""
|
||||||
Returns a MySQL connection object.
|
Create and return a MySQL database connection
|
||||||
|
using environment variables.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return mysql.connector.connect(
|
return mysql.connector.connect(
|
||||||
host=DBConfig.MYSQL_HOST,
|
host=os.getenv("DB_HOST", "db"), # Docker service name
|
||||||
user=DBConfig.MYSQL_USER,
|
port=int(os.getenv("DB_PORT", 3306)),
|
||||||
password=DBConfig.MYSQL_PASSWORD,
|
user=os.getenv("DB_USER", "root"),
|
||||||
database=DBConfig.MYSQL_DB
|
password=os.getenv("DB_PASSWORD", "root"),
|
||||||
|
database=os.getenv("DB_NAME", "test_income_taxdb"),
|
||||||
|
autocommit=False
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import mysql.connector
|
import mysql.connector
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import pymysql
|
|
||||||
import io
|
import io
|
||||||
from flask import send_file, render_template, request
|
from flask import send_file, render_template, request
|
||||||
|
|
||||||
from AppCode.Config import DBConfig
|
from AppCode.Config import DBConfig
|
||||||
from AppCode.YearGet import YearGet
|
|
||||||
|
|
||||||
|
|
||||||
class ITRHandler:
|
class ITRHandler:
|
||||||
@@ -14,7 +12,6 @@ class ITRHandler:
|
|||||||
self.conn = DBConfig.get_db_connection()
|
self.conn = DBConfig.get_db_connection()
|
||||||
self.cursor = self.conn.cursor(dictionary=True)
|
self.cursor = self.conn.cursor(dictionary=True)
|
||||||
|
|
||||||
|
|
||||||
# GET ALL ITR RECORDS using stored procedure "GetAllItr"
|
# GET ALL ITR RECORDS using stored procedure "GetAllItr"
|
||||||
def get_all_itr(self):
|
def get_all_itr(self):
|
||||||
self.cursor.callproc("GetAllItr")
|
self.cursor.callproc("GetAllItr")
|
||||||
@@ -44,6 +41,7 @@ class ITRHandler:
|
|||||||
# INSERT ITR RECORD using procedure "add_itr"
|
# INSERT ITR RECORD using procedure "add_itr"
|
||||||
def add_itr(self, data):
|
def add_itr(self, data):
|
||||||
|
|
||||||
|
try:
|
||||||
columns = [
|
columns = [
|
||||||
'year', 'gross_total_income', 'disallowance_14a', 'disallowance_37',
|
'year', 'gross_total_income', 'disallowance_14a', 'disallowance_37',
|
||||||
'deduction_80ia_business', 'deduction_80ia_misc', 'deduction_80ia_other',
|
'deduction_80ia_business', 'deduction_80ia_misc', 'deduction_80ia_other',
|
||||||
@@ -52,13 +50,20 @@ class ITRHandler:
|
|||||||
'tax_payable', 'surcharge', 'edu_cess',
|
'tax_payable', 'surcharge', 'edu_cess',
|
||||||
'total_tax_payable', 'mat_credit_created', 'mat_credit_utilized',
|
'total_tax_payable', 'mat_credit_created', 'mat_credit_utilized',
|
||||||
'interest_234c', 'total_tax', 'advance_tax', 'tds', 'tcs',
|
'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]
|
values = [data.get(col, 0) for col in columns]
|
||||||
|
|
||||||
# Call your stored procedure
|
# Call your stored procedure
|
||||||
self.cursor.callproc("InsertITR", values)
|
self.cursor.callproc("InsertITR", values)
|
||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
|
except Exception as e:
|
||||||
|
self.conn.rollback()
|
||||||
|
raise e
|
||||||
|
finally:
|
||||||
|
self.cursor.close()
|
||||||
|
self.conn.close()
|
||||||
|
|
||||||
|
|
||||||
# update itr by id
|
# update itr by id
|
||||||
def update(self, id, data):
|
def update(self, id, data):
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
from AppCode.Config import DBConfig
|
from AppCode.Config import DBConfig
|
||||||
import mysql.connector
|
|
||||||
|
|
||||||
class MatCreditHandler:
|
class MatCreditHandler:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# db = DBConfig()
|
|
||||||
self.conn = DBConfig.get_db_connection()
|
self.conn = DBConfig.get_db_connection()
|
||||||
self.cursor = self.conn.cursor(dictionary=True)
|
self.cursor = self.conn.cursor(dictionary=True)
|
||||||
|
|
||||||
# get all Mat credit data
|
# --------------------------------------------------
|
||||||
|
# FETCH ALL MAT CREDIT + UTILIZATION (For UI Display)
|
||||||
|
# --------------------------------------------------
|
||||||
def fetch_all(self):
|
def fetch_all(self):
|
||||||
try:
|
try:
|
||||||
|
|
||||||
self.cursor.callproc("GetMatCedit")
|
self.cursor.callproc("GetMatCedit")
|
||||||
result_sets = self.cursor.stored_results()
|
result_sets = self.cursor.stored_results()
|
||||||
mat_rows = next(result_sets).fetchall()
|
mat_rows = next(result_sets).fetchall()
|
||||||
@@ -19,27 +21,35 @@ class MatCreditHandler:
|
|||||||
return mat_rows, utilization_rows
|
return mat_rows, utilization_rows
|
||||||
finally:
|
finally:
|
||||||
self.cursor.close()
|
self.cursor.close()
|
||||||
|
self.conn.close()
|
||||||
|
|
||||||
# Save Mat credit data single row
|
# --------------------------------------------------
|
||||||
|
# SAVE / UPDATE SINGLE MAT ROW (FROM MANUAL UI)
|
||||||
|
# --------------------------------------------------
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def save_single(data):
|
def save_single(data):
|
||||||
conn = DBConfig.get_db_connection()
|
conn = DBConfig.get_db_connection()
|
||||||
cur = conn.cursor(dictionary=True)
|
cur = conn.cursor(dictionary=True)
|
||||||
try:
|
|
||||||
|
|
||||||
cur.callproc("SaveOrUpdateMatCredit",(
|
try:
|
||||||
|
# Save / Update MAT Credit
|
||||||
|
cur.callproc(
|
||||||
|
"SaveOrUpdateMatCredit",
|
||||||
|
(
|
||||||
data["financial_year"],
|
data["financial_year"],
|
||||||
data["mat_credit"],
|
data["mat_credit"],
|
||||||
data["balance"]
|
data["balance"],
|
||||||
))
|
data.get("remarks", "")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
result = next(cur.stored_results()).fetchone()
|
mat_id = None
|
||||||
mat_id = result["mat_id"]
|
for result in cur.stored_results():
|
||||||
|
mat_id = result.fetchone()["mat_id"]
|
||||||
if not mat_id:
|
|
||||||
raise Exception("mat_id not returned from procedure")
|
|
||||||
|
|
||||||
|
# Save utilization rows
|
||||||
for u in data.get("utilization", []):
|
for u in data.get("utilization", []):
|
||||||
|
if float(u["amount"]) > 0:
|
||||||
cur.callproc(
|
cur.callproc(
|
||||||
"InsertMatUtilization",
|
"InsertMatUtilization",
|
||||||
(mat_id, u["year"], u["amount"])
|
(mat_id, u["year"], u["amount"])
|
||||||
@@ -50,56 +60,69 @@ class MatCreditHandler:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
conn.rollback()
|
conn.rollback()
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
cur.close()
|
cur.close()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
# save all Mat credit data
|
# --------------------------------------------------
|
||||||
# @staticmethod
|
# AUTO SAVE MAT FROM ITR (MAIN LOGIC)
|
||||||
# def save_bulk(rows):
|
# --------------------------------------------------
|
||||||
# conn = DBConfig.get_db_connection()
|
@staticmethod
|
||||||
# cur = conn.cursor()
|
def save_from_itr(year, mat_created, mat_utilized, remarks="Auto from"):
|
||||||
# skipped = []
|
conn = DBConfig.get_db_connection()
|
||||||
|
cur = conn.cursor(dictionary=True)
|
||||||
|
|
||||||
# try:
|
try:
|
||||||
# for row in rows:
|
mat_created = float(mat_created or 0)
|
||||||
# cur.execute(
|
mat_utilized = float(mat_utilized or 0)
|
||||||
# "SELECT id FROM mat_credit WHERE financial_year=%s",
|
|
||||||
# (row["financial_year"],)
|
|
||||||
# )
|
|
||||||
# if cur.fetchone():
|
|
||||||
# skipped.append(row["financial_year"])
|
|
||||||
# continue
|
|
||||||
|
|
||||||
# cur.execute("""
|
balance = mat_created - mat_utilized
|
||||||
# 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
|
# Save / Update MAT Credit
|
||||||
|
cur.callproc(
|
||||||
|
"SaveOrUpdateMatCredit",
|
||||||
|
(year, mat_created, balance, remarks)
|
||||||
|
)
|
||||||
|
|
||||||
# for u in row["utilization"]:
|
mat_id = None
|
||||||
# cur.execute("""
|
for result in cur.stored_results():
|
||||||
# INSERT INTO mat_utilization
|
mat_id = result.fetchone()["mat_id"]
|
||||||
# (mat_credit_id, utilized_year, utilized_amount)
|
|
||||||
# VALUES (%s,%s,%s)
|
|
||||||
# """, (mat_id, u["year"], u["amount"]))
|
|
||||||
|
|
||||||
# conn.commit()
|
# Save utilization only if used
|
||||||
# return skipped
|
if mat_utilized > 0:
|
||||||
|
cur.callproc(
|
||||||
|
"InsertMatUtilization",
|
||||||
|
(mat_id, year, mat_utilized)
|
||||||
|
)
|
||||||
|
|
||||||
# except Exception:
|
conn.commit()
|
||||||
# conn.rollback()
|
|
||||||
# raise
|
|
||||||
|
|
||||||
# finally:
|
except Exception as e:
|
||||||
# cur.close()
|
conn.rollback()
|
||||||
# conn.close()
|
raise e
|
||||||
|
finally:
|
||||||
|
cur.close()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
# CLOSE CONNECTION
|
# --------------------------------------------------
|
||||||
def close(self):
|
# 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.cursor.close()
|
||||||
self.conn.close()
|
self.conn.close()
|
||||||
|
|
||||||
|
# --------------------------------------------------
|
||||||
|
# CLOSE CONNECTION (MANUAL USE)
|
||||||
|
# --------------------------------------------------
|
||||||
|
def close(self):
|
||||||
|
if self.cursor:
|
||||||
|
self.cursor.close()
|
||||||
|
if self.conn:
|
||||||
|
self.conn.close()
|
||||||
|
|||||||
BIN
AppCode/__pycache__/AOHandler.cpython-313.pyc
Normal file
BIN
AppCode/__pycache__/AOHandler.cpython-313.pyc
Normal file
Binary file not shown.
BIN
AppCode/__pycache__/CITHandler.cpython-313.pyc
Normal file
BIN
AppCode/__pycache__/CITHandler.cpython-313.pyc
Normal file
Binary file not shown.
BIN
AppCode/__pycache__/Config.cpython-313.pyc
Normal file
BIN
AppCode/__pycache__/Config.cpython-313.pyc
Normal file
Binary file not shown.
BIN
AppCode/__pycache__/DocumentHandler.cpython-313.pyc
Normal file
BIN
AppCode/__pycache__/DocumentHandler.cpython-313.pyc
Normal file
Binary file not shown.
BIN
AppCode/__pycache__/ITRHandler.cpython-313.pyc
Normal file
BIN
AppCode/__pycache__/ITRHandler.cpython-313.pyc
Normal file
Binary file not shown.
BIN
AppCode/__pycache__/LoginAuth.cpython-313.pyc
Normal file
BIN
AppCode/__pycache__/LoginAuth.cpython-313.pyc
Normal file
Binary file not shown.
22
Dockerfile
Normal file
22
Dockerfile
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
# Prevent Python buffering
|
||||||
|
ENV PYTHONDONTWRITEBYTECODE=1
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install system deps (if needed later)
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
build-essential \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
EXPOSE 5000
|
||||||
|
|
||||||
|
CMD ["python", "main.py"]
|
||||||
|
|
||||||
0
db/income_tax.sql
Normal file
0
db/income_tax.sql
Normal file
29
docker-compose.yml
Normal file
29
docker-compose.yml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
version: "3.9"
|
||||||
|
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: mysql:8.0
|
||||||
|
container_name: income_tax_db
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: root
|
||||||
|
MYSQL_DATABASE: test_income_taxdb
|
||||||
|
ports:
|
||||||
|
- "3307:3306"
|
||||||
|
volumes:
|
||||||
|
- mysql_data:/var/lib/mysql
|
||||||
|
- ./db/income_tax.sql:/docker-entrypoint-initdb.d/income_tax.sql
|
||||||
|
|
||||||
|
web:
|
||||||
|
build: .
|
||||||
|
container_name: income_tax_web
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "5010:5010"
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mysql_data:
|
||||||
54
main.py
54
main.py
@@ -4,7 +4,7 @@ from dotenv import load_dotenv
|
|||||||
load_dotenv()
|
load_dotenv()
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
|
from datetime import date
|
||||||
from AppCode.Config import DBConfig
|
from AppCode.Config import DBConfig
|
||||||
from AppCode.LoginAuth import LoginAuth
|
from AppCode.LoginAuth import LoginAuth
|
||||||
from AppCode.FileHandler import FileHandler
|
from AppCode.FileHandler import FileHandler
|
||||||
@@ -15,6 +15,7 @@ from AppCode.AOHandler import AOHandler
|
|||||||
from AppCode.CITHandler import CITHandler
|
from AppCode.CITHandler import CITHandler
|
||||||
from AppCode.ITATHandler import ITATHandler
|
from AppCode.ITATHandler import ITATHandler
|
||||||
from AppCode.MatCreditHandler import MatCreditHandler
|
from AppCode.MatCreditHandler import MatCreditHandler
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -59,7 +60,6 @@ def view_documents():
|
|||||||
docHandler.View(request=request)
|
docHandler.View(request=request)
|
||||||
return render_template('view_docs.html', documents=docHandler.documents, years=docHandler.years)
|
return render_template('view_docs.html', documents=docHandler.documents, years=docHandler.years)
|
||||||
|
|
||||||
|
|
||||||
# Upload file documents
|
# Upload file documents
|
||||||
@app.route('/uploads/<filename>')
|
@app.route('/uploads/<filename>')
|
||||||
@auth.login_required
|
@auth.login_required
|
||||||
@@ -68,20 +68,26 @@ def uploaded_file(filename):
|
|||||||
filepath = os.path.join(FileHandler.UPLOAD_FOLDER, secure_filename(filename))
|
filepath = os.path.join(FileHandler.UPLOAD_FOLDER, secure_filename(filename))
|
||||||
|
|
||||||
if not os.path.exists(filepath):
|
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()
|
file_ext = filename.rsplit('.', 1)[-1].lower()
|
||||||
# --- View Mode ---
|
# --- View Mode ---
|
||||||
if mode == 'view':
|
if mode == 'view':
|
||||||
|
# pdf
|
||||||
if file_ext == 'pdf':
|
if file_ext == 'pdf':
|
||||||
return send_file(filepath, mimetype='application/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']:
|
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')
|
return send_file(filepath, as_attachment=False, download_name=filename, mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
|
||||||
else:
|
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,12 +111,26 @@ def display_itr():
|
|||||||
def add_itr():
|
def add_itr():
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
itr = ITRHandler()
|
itr = ITRHandler()
|
||||||
|
mat = MatCreditHandler()
|
||||||
itr.add_itr(request.form)
|
itr.add_itr(request.form)
|
||||||
itr.close()
|
itr.close()
|
||||||
flash("ITR record added successfully!", "success")
|
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 redirect(url_for('display_itr'))
|
||||||
|
|
||||||
return render_template('add_itr.html')
|
return render_template('add_itr.html',current_date=date.today().isoformat())
|
||||||
|
|
||||||
## 4. DELETE an ITR record
|
## 4. DELETE an ITR record
|
||||||
@app.route('/itr/delete/<int:id>', methods=['POST'])
|
@app.route('/itr/delete/<int:id>', methods=['POST'])
|
||||||
@@ -135,7 +155,7 @@ def update_itr(id):
|
|||||||
|
|
||||||
record = itr.get_itr_by_id(id)
|
record = itr.get_itr_by_id(id)
|
||||||
itr.close()
|
itr.close()
|
||||||
return render_template('update_itr.html', record=record)
|
return render_template('update_itr.html', record=record, current_date=date.today().isoformat())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -160,11 +180,25 @@ def display_ao():
|
|||||||
def add_ao():
|
def add_ao():
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
ao = AOHandler()
|
ao = AOHandler()
|
||||||
|
mat = MatCreditHandler()
|
||||||
ao.add_ao(request.form)
|
ao.add_ao(request.form)
|
||||||
ao.close()
|
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 ITR"
|
||||||
|
)
|
||||||
|
|
||||||
flash("AO record added successfully!", "success")
|
flash("AO record added successfully!", "success")
|
||||||
return redirect(url_for('display_ao'))
|
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
|
# 3. UPDATE AO record
|
||||||
@app.route('/ao/update/<int:id>', methods=['GET', 'POST'])
|
@app.route('/ao/update/<int:id>', methods=['GET', 'POST'])
|
||||||
|
|||||||
13
requirements.txt
Normal file
13
requirements.txt
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
Flask==3.0.1
|
||||||
|
python-dotenv==1.0.1
|
||||||
|
pandas==2.2.0
|
||||||
|
Werkzeug==3.0.1
|
||||||
|
|
||||||
|
mysql-connector-python==8.3.0
|
||||||
|
|
||||||
|
Flask-HTTPAuth==4.8.0
|
||||||
|
|
||||||
|
openpyxl==3.1.2
|
||||||
|
xlrd==2.0.1
|
||||||
|
|
||||||
|
gunicorn==21.2.0
|
||||||
@@ -46,16 +46,6 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
var tax_payable = (tax30 > tax185) ? tax30 : tax185;
|
var tax_payable = (tax30 > tax185) ? tax30 : tax185;
|
||||||
setValue("tax_payable", tax_payable);
|
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 ---
|
// --- SURCHARGE ---
|
||||||
var percent = getValue("persentage");
|
var percent = getValue("persentage");
|
||||||
var surcharge = tax_payable * (percent / 100);
|
var surcharge = tax_payable * (percent / 100);
|
||||||
@@ -70,11 +60,37 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
var total_tax_payable = tax_payable + surcharge + edu_cess;
|
var total_tax_payable = tax_payable + surcharge + edu_cess;
|
||||||
setValue("total_tax_payable", total_tax_payable);
|
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 ---
|
// --- FINAL TAX ---
|
||||||
var mat_credit = getValue("mat_credit_utilized");
|
var mat_credit = getValue("mat_credit_utilized");
|
||||||
var interest_234c = getValue("interest_234c");
|
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);
|
setValue("total_tax", total_tax);
|
||||||
|
|
||||||
// --- ASSESSMENT ---
|
// --- ASSESSMENT ---
|
||||||
|
|||||||
@@ -46,16 +46,6 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
var tax_payable = (tax30 > tax185) ? tax30 : tax185;
|
var tax_payable = (tax30 > tax185) ? tax30 : tax185;
|
||||||
setValue("tax_payable", tax_payable);
|
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 ---
|
// --- SURCHARGE ---
|
||||||
var percent = getValue("persentage");
|
var percent = getValue("persentage");
|
||||||
var surcharge = tax_payable * (percent / 100);
|
var surcharge = tax_payable * (percent / 100);
|
||||||
@@ -70,11 +60,37 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
var total_tax_payable = tax_payable + surcharge + edu_cess;
|
var total_tax_payable = tax_payable + surcharge + edu_cess;
|
||||||
setValue("total_tax_payable", total_tax_payable);
|
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_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 ---
|
// --- FINAL TAX ---
|
||||||
var mat_credit = getValue("mat_credit_utilized");
|
var mat_credit = getValue("mat_credit_utilized");
|
||||||
var interest_234c = getValue("interest_234c");
|
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);
|
setValue("total_tax", total_tax);
|
||||||
|
|
||||||
// --- ASSESSMENT ---
|
// --- ASSESSMENT ---
|
||||||
|
|||||||
@@ -45,11 +45,6 @@ document.getElementById("year").addEventListener("change", function () {
|
|||||||
|
|
||||||
// Show preview
|
// Show preview
|
||||||
previewDiv.style.display = "block";
|
previewDiv.style.display = "block";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
.catch(err => console.error("Preview load error:", err));
|
.catch(err => console.error("Preview load error:", err));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
<h2 style="text-align:center;">New Assessing Officer Form</h2>
|
<h2 style="text-align:center;">New Assessing Officer Form</h2>
|
||||||
<form id="ao" method="POST">
|
<form id="ao" method="POST" enctype="multipart/form-data">
|
||||||
|
<input type="hidden" name="stage" value="ao">
|
||||||
<div class="form-group full-width inline-2">
|
<div class="form-group full-width inline-2">
|
||||||
<div>
|
<div>
|
||||||
<label>Assessment Year:</label>
|
<label>Assessment Year:</label>
|
||||||
@@ -19,11 +20,12 @@
|
|||||||
-- Please select Assessment Year --
|
-- Please select Assessment Year --
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="yearError" style="color:red; display:none; margin-bottom:10px;"></div>
|
<div id="yearError" style="color:red; display:none; margin-bottom:10px;"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Record Created Date:</label>
|
||||||
|
<input type="date" name="created_at" value="{{ current_date }}" required>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group full-width inline-2">
|
<div class="form-group full-width inline-2">
|
||||||
@@ -170,10 +172,16 @@
|
|||||||
<input type="number" name="refund" class="auto" step="any" value="0.00" readonly>
|
<input type="number" name="refund" class="auto" step="any" value="0.00" readonly>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group full-width inline-2">
|
||||||
|
<div>
|
||||||
|
<label>Select Documents:</label>
|
||||||
|
<input type="file" name="documents" multiple>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
<label>Remarks:</label>
|
<label>Remarks:</label>
|
||||||
<input type="text" name="Remarks">
|
<input type="text" name="Remarks">
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<button type="submit">Submit</button>
|
<button type="submit">Submit</button>
|
||||||
|
|||||||
@@ -10,7 +10,8 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h2 style="text-align:center;">New Income Tax Return Form</h2>
|
<h2 style="text-align:center;">New Income Tax Return Form</h2>
|
||||||
<form id="itr" method="POST">
|
<form id="itr" method="POST" enctype="multipart/form-data">
|
||||||
|
<input type="hidden" name="stage" value="itr">
|
||||||
<div class="form-group full-width inline-2">
|
<div class="form-group full-width inline-2">
|
||||||
<div>
|
<div>
|
||||||
<label>Assessment Year:</label>
|
<label>Assessment Year:</label>
|
||||||
@@ -21,6 +22,10 @@
|
|||||||
</select>
|
</select>
|
||||||
<div id="yearError" style="color:red; display:none; margin-bottom:10px;"></div>
|
<div id="yearError" style="color:red; display:none; margin-bottom:10px;"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Record Created Date:</label>
|
||||||
|
<input type="date" name="created_at" value="{{ current_date }}" required>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group full-width inline-2">
|
<div class="form-group full-width inline-2">
|
||||||
<div>
|
<div>
|
||||||
@@ -166,10 +171,16 @@
|
|||||||
<input type="number" name="refund" class="auto" step="any" value="0.00" readonly>
|
<input type="number" name="refund" class="auto" step="any" value="0.00" readonly>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group full-width inline-2">
|
||||||
|
<div>
|
||||||
|
<label>Select Documents:</label>
|
||||||
|
<input type="file" name="documents" multiple>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
<label>Remarks:</label>
|
<label>Remarks:</label>
|
||||||
<input type="text" name="Remarks">
|
<input type="text" name="Remarks">
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button type="submit">Submit</button>
|
<button type="submit">Submit</button>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
<th>Gross Total Income</th>
|
<th>Gross Total Income</th>
|
||||||
<th>Net Taxable Income</th>
|
<th>Net Taxable Income</th>
|
||||||
<th>Total Tax</th>
|
<th>Total Tax</th>
|
||||||
|
<th>Created Record Date</th>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -32,6 +33,7 @@
|
|||||||
<td>{{ ao.gross_total_income }}</td>
|
<td>{{ ao.gross_total_income }}</td>
|
||||||
<td>{{ ao.net_taxable_income }}</td>
|
<td>{{ ao.net_taxable_income }}</td>
|
||||||
<td>{{ ao.total_tax }}</td>
|
<td>{{ ao.total_tax }}</td>
|
||||||
|
<td>{{ ao.created_at.strftime('%Y-%m-%d') }}</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ url_for('update_ao', id=ao.id) }}" class="btn btn-update">Edit</a>
|
<a href="{{ url_for('update_ao', id=ao.id) }}" class="btn btn-update">Edit</a>
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
<th>Net Taxable Income</th>
|
<th>Net Taxable Income</th>
|
||||||
<th>Total Tax Payable</th>
|
<th>Total Tax Payable</th>
|
||||||
<th>Refund</th>
|
<th>Refund</th>
|
||||||
|
<th>Created Record Date</th>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -33,6 +34,7 @@
|
|||||||
<td>{{ "{:,.2f}".format(record.net_taxable_income) }}</td>
|
<td>{{ "{:,.2f}".format(record.net_taxable_income) }}</td>
|
||||||
<td>{{ "{:,.2f}".format(record.total_tax_payable) }}</td>
|
<td>{{ "{:,.2f}".format(record.total_tax_payable) }}</td>
|
||||||
<td>{{ "{:,.2f}".format(record.refund) }}</td>
|
<td>{{ "{:,.2f}".format(record.refund) }}</td>
|
||||||
|
<td>{{ record.created_at.strftime('%Y-%m-%d') }}</td>
|
||||||
<td class="action-cell">
|
<td class="action-cell">
|
||||||
<a href="{{ url_for('update_itr', id=record.id) }}" class="btn btn-update">Edit</a>
|
<a href="{{ url_for('update_itr', id=record.id) }}" class="btn btn-update">Edit</a>
|
||||||
<form action="{{ url_for('delete_itr', id=record.id) }}" method="post"
|
<form action="{{ url_for('delete_itr', id=record.id) }}" method="post"
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
{% for row in mat_rows %}
|
{% for row in mat_rows %}
|
||||||
<tr>
|
<tr>
|
||||||
<td contenteditable="true">{{ row.financial_year }}</td>
|
<td contenteditable="false">{{ row.financial_year }}-{{ row.financial_year | int + 1 }}</td>
|
||||||
<td><input value="{{ row.mat_credit }}"></td>
|
<td><input value="{{ row.mat_credit }}"></td>
|
||||||
|
|
||||||
{% for y in added_years %}
|
{% for y in added_years %}
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
{% extends "base.html" %} {% block title %}Download Summary Report{% endblock %}
|
{% extends "base.html" %} {% block title %}Download Summary Report{% endblock %}
|
||||||
{% block extra_css %}
|
{% block extra_css %}
|
||||||
<link
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/summary.css') }}" />
|
||||||
rel="stylesheet"
|
|
||||||
href="{{ url_for('static', filename='css/summary.css') }}"
|
|
||||||
/>
|
|
||||||
{% endblock %} {% block content %}
|
{% endblock %} {% block content %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="head">
|
<div class="head">
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h2>Update AO Record for Year {{ record.year }}--{{ record.year + 1 }}</h2>
|
<h2>Update AO Record for Year {{ record.year }} - {{ record.year + 1 }}</h2>
|
||||||
<form method="POST" action="{{ url_for('update_ao', id=record.id) }}">
|
<form method="POST" action="{{ url_for('update_ao', id=record.id) }}">
|
||||||
<div class="form-group full-width inline-2">
|
<div class="form-group full-width inline-2">
|
||||||
<div>
|
<div>
|
||||||
@@ -169,6 +169,23 @@
|
|||||||
<input type="text" name="Remarks" value="{{ record.remarks}}">
|
<input type="text" name="Remarks" value="{{ record.remarks}}">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group full-width inline-2">
|
||||||
|
<div>
|
||||||
|
<label>Created Date:</label>
|
||||||
|
<input type="date" name="created_at"
|
||||||
|
value="{{ record.created_at.strftime('%Y-%m-%d') if record.created_at else current_date }}"
|
||||||
|
readonly>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label>Last Updated:</label>
|
||||||
|
<input type="date" name="updated_at"
|
||||||
|
value="{{ record.updated_at.strftime('%Y-%m-%d') if record.updated_at else current_date }}"
|
||||||
|
readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button type="submit">Update Record</button>
|
<button type="submit">Update Record</button>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -169,6 +169,22 @@
|
|||||||
<label>Remarks:</label>
|
<label>Remarks:</label>
|
||||||
<input type="text" name="Remarks" value="{{ record.Remarks }}">
|
<input type="text" name="Remarks" value="{{ record.Remarks }}">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group full-width inline-2">
|
||||||
|
<div>
|
||||||
|
<label>Created Date:</label>
|
||||||
|
<input type="date" name="created_at"
|
||||||
|
value="{{ record.created_at.strftime('%Y-%m-%d') if record.created_at else current_date }}"
|
||||||
|
readonly>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label>Last Updated:</label>
|
||||||
|
<input type="date" name="updated_at"
|
||||||
|
value="{{ record.updated_at.strftime('%Y-%m-%d') if record.updated_at else current_date }}"
|
||||||
|
readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button type="submit">Update Record</button>
|
<button type="submit">Update Record</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -27,7 +27,11 @@
|
|||||||
</select>
|
</select>
|
||||||
<button type="submit">Apply</button>
|
<button type="submit">Apply</button>
|
||||||
</form>
|
</form>
|
||||||
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||||
|
{% for category, message in messages %}
|
||||||
|
<div class="alert alert-{{ category }}">{{ message }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endwith %}
|
||||||
<!-- DOCUMENT TABLE -->
|
<!-- DOCUMENT TABLE -->
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table>
|
<table>
|
||||||
|
|||||||
Reference in New Issue
Block a user