From a0f4568ba25fa9c06051d77b7bf3987e8c69b8c7 Mon Sep 17 00:00:00 2001 From: pjpatil12 Date: Thu, 5 Feb 2026 15:02:55 +0530 Subject: [PATCH] added docker and chnages of from model changes commits --- .dockerignore | 5 ++ .env | 3 +- AppCode/AOHandler.py | 4 -- AppCode/CITHandler.py | 1 - AppCode/Config.py | 44 +++++++++++++----- AppCode/ITRHandler.py | 5 +- AppCode/MatCreditHandler.py | 1 - AppCode/__pycache__/AOHandler.cpython-313.pyc | Bin 7623 -> 7623 bytes .../__pycache__/CITHandler.cpython-313.pyc | Bin 7674 -> 7674 bytes AppCode/__pycache__/Config.cpython-313.pyc | Bin 1263 -> 1260 bytes .../DocumentHandler.cpython-313.pyc | Bin 9583 -> 9583 bytes .../__pycache__/ITRHandler.cpython-313.pyc | Bin 7857 -> 7933 bytes AppCode/__pycache__/LoginAuth.cpython-313.pyc | Bin 2735 -> 2735 bytes Dockerfile | 22 +++++++++ db/income_tax.sql | 0 docker-compose.yml | 29 ++++++++++++ main.py | 14 ++++-- requirements.txt | 13 ++++++ static/js/itr_calc.js | 16 +++---- templates/add_itr.html | 19 ++++++-- templates/display_itr.html | 2 + templates/update_itr.html | 16 +++++++ templates/upload.html | 2 +- 23 files changed, 155 insertions(+), 41 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 db/income_tax.sql create mode 100644 docker-compose.yml create mode 100644 requirements.txt diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..02215c9 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +__pycache__/ +*.pyc +.git +.idea +venv diff --git a/.env b/.env index 8d571af..6ef70f0 100644 --- a/.env +++ b/.env @@ -2,7 +2,7 @@ # Flask App Configuration # ----------------------------- FLASK_ENV=development -FLASK_DEBUG=True +FLASK_DEBUG=true FLASK_HOST=0.0.0.0 FLASK_PORT=5010 @@ -17,6 +17,7 @@ SECRET_KEY=secret1234 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 diff --git a/AppCode/AOHandler.py b/AppCode/AOHandler.py index bc5327a..7aa648c 100644 --- a/AppCode/AOHandler.py +++ b/AppCode/AOHandler.py @@ -3,7 +3,6 @@ import mysql.connector import pandas as pd import io - class AOHandler: def __init__(self): @@ -49,7 +48,6 @@ class AOHandler: self.cursor.callproc("InsertAO", values) self.conn.commit() - # UPDATE AO RECORD by AO id def update_ao(self, id, data): fields = [ @@ -193,8 +191,6 @@ class AOHandler: print("MySQL Error →", e) return None - - # CLOSE CONNECTION def close(self): self.cursor.close() diff --git a/AppCode/CITHandler.py b/AppCode/CITHandler.py index 96b9ed9..7762870 100644 --- a/AppCode/CITHandler.py +++ b/AppCode/CITHandler.py @@ -3,7 +3,6 @@ import mysql.connector import pandas as pd import io - class CITHandler: def __init__(self): diff --git a/AppCode/Config.py b/AppCode/Config.py index 1d21e3a..0a83119 100644 --- a/AppCode/Config.py +++ b/AppCode/Config.py @@ -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 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 def get_db_connection(): """ - Returns a MySQL connection object. + Create and return a MySQL database connection + using environment variables. """ + return mysql.connector.connect( - host=DBConfig.MYSQL_HOST, - user=DBConfig.MYSQL_USER, - password=DBConfig.MYSQL_PASSWORD, - database=DBConfig.MYSQL_DB + host=os.getenv("DB_HOST", "db"), # Docker service name + port=int(os.getenv("DB_PORT", 3306)), + user=os.getenv("DB_USER", "root"), + password=os.getenv("DB_PASSWORD", "root"), + database=os.getenv("DB_NAME", "test_income_taxdb"), + autocommit=False ) diff --git a/AppCode/ITRHandler.py b/AppCode/ITRHandler.py index 4cb6bf1..2cec0cb 100644 --- a/AppCode/ITRHandler.py +++ b/AppCode/ITRHandler.py @@ -1,11 +1,9 @@ import mysql.connector import pandas as pd -import pymysql import io from flask import send_file, render_template, request from AppCode.Config import DBConfig -from AppCode.YearGet import YearGet class ITRHandler: @@ -14,7 +12,6 @@ class ITRHandler: self.conn = DBConfig.get_db_connection() self.cursor = self.conn.cursor(dictionary=True) - # GET ALL ITR RECORDS using stored procedure "GetAllItr" def get_all_itr(self): self.cursor.callproc("GetAllItr") @@ -52,7 +49,7 @@ class ITRHandler: '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/MatCreditHandler.py b/AppCode/MatCreditHandler.py index 2fa0a9b..e2cf3e6 100644 --- a/AppCode/MatCreditHandler.py +++ b/AppCode/MatCreditHandler.py @@ -1,5 +1,4 @@ from AppCode.Config import DBConfig -import mysql.connector class MatCreditHandler: diff --git a/AppCode/__pycache__/AOHandler.cpython-313.pyc b/AppCode/__pycache__/AOHandler.cpython-313.pyc index 3f90d31bf6b23ee643d775e8a724671586b6dc48..d1b3df1633c9ebd02158631a4ff19ed56fa084c7 100644 GIT binary patch delta 127 zcmX?ZecYP&GcPX}0}uo(Y0TU^k@qGe+s5Z6jEo$cWtfT?8F@EPU~Xq*6yGet8o|t{ zw7HOD7bBy|W*x2sMn?C|z1&Z^8GSYviyvfRJUrP{<`^T}W7(ir^AkantEleWK delta 127 zcmX?ZecYP&GcPX}0}z}Et7(ir^AkantLyjV# diff --git a/AppCode/__pycache__/CITHandler.cpython-313.pyc b/AppCode/__pycache__/CITHandler.cpython-313.pyc index 35670794dd26881a96fd1b04046eed848aa80ff4..6c03b4ed11d3c38af57abc13378984a29a94ca4a 100644 GIT binary patch delta 105 zcmexm{mYv7GcPX}0}zBSY0O+Ok@prO+r}5JjEo$c^_c1y8TmG^W$tEVl-O*^8qdtA zx_KtYenv*~&5>M@jEtU}H*>$|X7t^>So{bJM@jEr8JH*>$|X7t;rVGhVJ3A?j zAkmB9N!nG~qsRI$h&PX3lpHK${{cm?HG<&D*=>V3FwgAsKEHiunE4U?9*uWnF%5{Z z^X{qrUfGS8HOaSPbaT5~sYxVV0)?{zpdlnvwWj1lJTf;kOPqDP_H{^v)pHE+UE{q!y%}3HMA}BoP$t;YdS$ z6KW3R`yVZ8vlN>Q8>V9!6tgCE4AWR@p}UKQWiqp3y4a`^$H7%*6Gv;hwo@~(vu#u2 zG_b>rZIjw&rHNul{dHZu>_)}u|SWoQ_?hPJHytX>}^<#bD zWof^>S3YPR<~r${9ew;Cu-?&c9H%ou{P=LalP>gJ>*MHTCp~qP89Ir9-%9km%w%@8f!PMJ=oRmeoNZ@)DnR{%Ql%$;$sG{#3><~@Qz;hG zx-w8Nbp5ZhAAB~i@I<5KZq>)m--l3|_Iq6PCFu754m@(ZL9AvSPtg&9T!TW~jF1x< WLf9P#F!KdOf2#?o{RBdSt^NWp8O0U= literal 1263 zcmZ`(O-~a+7@pm3+wHc{F1SERjE&Z66YPydj3EI^f(iw9F@&(mWZN#K+U}Owty&X9 zPbPXHAtCS=yc+*V!vQjIF!96_M=6V_wdX!@Atm*X1fCe0w5wsQFWRH;5)te z!g-{7pOAf^0EKx55aXOIV#mO3ps?dW2~3hmDkxB4vfMePg%U+y0v_ppC1f9{P8P%} z3<{{6>~!F}x+l#%$+#SauJsA@e8SiIa6KRXTAyIgC!z{UXdFy>?VzXEa!X%K6qWguwKG-1W zitG*0ztdBuWv<9Z$XCd`&-&*j>wiXi$r|g&`0SE((AV`(g_+{gAj`f>3$kuEkzu8@ z)KW`%zL+YRhM|}2s%fOm;!DDELYBkamTB3TYg#(Od_%LWHzq1$zO30=QM2?ckAwA= zwOzvzFWy8r>`_Gb4hu``B)vOgk2_NyboISK^X@%A`x$g;!}#IcBX!M0uhd#eZ`9xl zGHF+q`ot)ib$wNPtF$azud6eS#++H!RrgVIjTROwx(&-k*#9Iv?mv3&A6t|Zv+@Mm z;Fkar((ca3o#S|>6VIH9$zw6y5z~Dl-8_~iI?}`$C7F(txrl(oy$cXb2m~Sm8YPL) z2!TR&0P_$UT3v?_3lP@LaX4|M*Y}&d7q0@%j&=`%T&*1=FNNbV62XG<| zA0+pZhf_!5-S*QfH)-@>eQ*8n{gL#bT{wx0yRA>H!{kx?PJ7{7Q2fD0fjRr0N delta 20 acmaFw_1=s7GcPX}0}%Z2ui40*q6z>_wg#a9 diff --git a/AppCode/__pycache__/ITRHandler.cpython-313.pyc b/AppCode/__pycache__/ITRHandler.cpython-313.pyc index 351f0f8be539f7e9bf44799eb4bbf24a09960355..7047dc732c6c70085f52a136340d21174931801f 100644 GIT binary patch delta 1339 zcmZvcO>7%Q6vuaL?`Hk6scUayJBizEoHSXJxK0x%p-HNSHf@tq66$b3NVuEzBwfk& zy0dGg*-H)-&V;!jaVcC7+$u|aTsU(>2)Jw{5E9&}5#oS~cyB8RNbKRKnfGSioA;kL z`*`K)it?+X#02=7=0l4fDLJxrG@(^Ox5N#JNgI8vZ$oCXCRBxL_*Qfy#$uX~6-I?> zWJsurl@M+f1Qy>Tx^(pR^GDw{r6?Fo!dK&J_cf9yB;Gv;iG=j?!*G!#`N!crInBQe zPr~>~_(h_2FGmvOQa^^tAhL)Yz!%%hYPouZC2TC#o!vH4&(BNaI`9pDvb4ksNvFj&2ahqa(3t>hk^km({45`R~K25ezg|c(#T|-<)+(6s}I1&JB4yyhnc808Uzl+7m+m~ zGRQ7~#(wAu1FEAvNb?Fwq{#nHND9N_Zc0z9SK zVdg!9?NL}g9^8kQTB~VBy@!6`izqxNWz6(Q;|i zVORP3;HOI(#L;ul+FfyIgPPdA2h?DGgxUK}(E5HDhQ6|E(MG-2G}>*ewa3=@Qs#5$ z;NLQfbO(8z$^NPoF7m2btIhX!z#{zP#MD>zxL@%svDMisBRizk~@P$HL&T bkUkcoKM0kth04!D;dg02M230-G6?b)^CL9I delta 1299 zcmZvcU1%d!6vyW#nMu-Qnzm`$^doh)+1)m^&9>Wi+g*1hrMvAm#dc{bs4sCkbJHD2 zGP7r_Ak{L^hXTuY$Tf7m@u^w?09#_)1*$AgaN`J!j~Pe znqDCS-DHI<6NV@@jBq0e4Ik(cT%KgZ;vLyy8S#hwW9Vq8^@H*O6K}<`gD0|`q@fsg zqhWak8M?*iu?ei`mzc(;TFLkgwhCuSov!D{pL9&!<7?Ynu#9#=2}*!bN?0MR60Q^0 z5UzrtYJz&k5+khCT1h0>_FyU7{s$9Kto#R!fX$MADK zt6;mXwrzWQU0ZA74LB4iFtB8rm$a*vtJmxHZM|u5ZSS0`&CD&q1jV!eAD>--M=3ld zzE1avW;#1INoLn(Q+vX44Q-1X+;Th@rpO&b_ojD~0~E!*^e{UozDnmNrYY33!98tT z-`98Q{GY;RC=f@dR?=pt&%k-n-K&*m$(tbW4gG-9VU9d%We<#-I_z@HJ_GZC=rwcC z&^^m;YReq2O@RyIR&PIB5U=;<*rNET_Z9JFN1m0$MkdErMLknHt>ac-*|EXILU+)B z8i~d7lllB~ae5k?UK77%YDy5(#ZKSCsgwWaWa7e(?fA0g@rDam#bxFpYi~m%duFc-^cvbjPupyRahe_J4{KR?9B3r&{l4_alpR zq%RwF+vPy>2we!5A#je#eh=Yy;n-c*ncuBrXOLw6T!#Q;h@nR=sH0%_g?V26!3$zT)6rbQc^l zqRv5(1R$OtDLQ^?$#Ir#lNbN~fIt+pf lJC^#6rS!4Xc`U`hm*&5b=6{m%-%9!4mHiMKY)iyI>M!!eJxKrn diff --git a/AppCode/__pycache__/LoginAuth.cpython-313.pyc b/AppCode/__pycache__/LoginAuth.cpython-313.pyc index aab739603afdfc7213eb59580f413b9dba8f1513..9f22f7cb534d076fdca4d87590e65810b9541c34 100644 GIT binary patch delta 20 acmZ24x?Ys~GcPX}0}!|vG;icy!UX^~hy@G) delta 20 acmZ24x?Ys~GcPX}0}vb%D%!}sgbM&U@daA| diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..42dac6e --- /dev/null +++ b/Dockerfile @@ -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"] + diff --git a/db/income_tax.sql b/db/income_tax.sql new file mode 100644 index 0000000..e69de29 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..62d4f52 --- /dev/null +++ b/docker-compose.yml @@ -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: diff --git a/main.py b/main.py index 57459f8..1b2dfa6 100644 --- a/main.py +++ b/main.py @@ -4,7 +4,7 @@ from dotenv import load_dotenv load_dotenv() import pandas as pd from werkzeug.utils import secure_filename - +from datetime import date from AppCode.Config import DBConfig from AppCode.LoginAuth import LoginAuth from AppCode.FileHandler import FileHandler @@ -107,10 +107,16 @@ def add_itr(): itr = ITRHandler() itr.add_itr(request.form) itr.close() - flash("ITR record added successfully!", "success") + + if 'documents' in request.files: + doc = DocumentHandler() + doc.Upload(request) + + # 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') + return render_template('add_itr.html',current_date=date.today().isoformat()) ## 4. DELETE an ITR record @app.route('/itr/delete/', methods=['POST']) @@ -135,7 +141,7 @@ def update_itr(id): record = itr.get_itr_by_id(id) itr.close() - return render_template('update_itr.html', record=record) + return render_template('update_itr.html', record=record, current_date=date.today().isoformat()) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..094b0db --- /dev/null +++ b/requirements.txt @@ -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 diff --git a/static/js/itr_calc.js b/static/js/itr_calc.js index 8e5b445..1ca7d5d 100644 --- a/static/js/itr_calc.js +++ b/static/js/itr_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,10 +60,16 @@ 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)); + // --- 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; setValue("total_tax", total_tax); diff --git a/templates/add_itr.html b/templates/add_itr.html index 54f1378..c112eff 100644 --- a/templates/add_itr.html +++ b/templates/add_itr.html @@ -10,7 +10,8 @@ {% block content %}

New Income Tax Return Form

-
+ +
@@ -21,6 +22,10 @@
+
+ + +
@@ -166,9 +171,15 @@
-
- - +
+
+ + +
+
+ + +
diff --git a/templates/display_itr.html b/templates/display_itr.html index 9a8e774..9a1e6ac 100644 --- a/templates/display_itr.html +++ b/templates/display_itr.html @@ -22,6 +22,7 @@ Net Taxable Income Total Tax Payable Refund + Created Record Date Actions @@ -33,6 +34,7 @@ {{ "{:,.2f}".format(record.net_taxable_income) }} {{ "{:,.2f}".format(record.total_tax_payable) }} {{ "{:,.2f}".format(record.refund) }} + {{ record.created_at.strftime('%Y-%m-%d') }} Edit Remarks:
+
+
+ + +
+ +
+ + +
+
+
diff --git a/templates/upload.html b/templates/upload.html index 19c2c93..bf2100c 100644 --- a/templates/upload.html +++ b/templates/upload.html @@ -9,7 +9,7 @@ {% block content %}

Upload Income Tax Documents

-
+