From 9c2486fdd6a348e58f6d40275822eb83a7bb844d Mon Sep 17 00:00:00 2001 From: pjpatil12 Date: Wed, 7 Jan 2026 00:49:42 +0530 Subject: [PATCH] changes of summary report --- AppCode/AOHandler.py | 12 +-- AppCode/DocumentHandler.py | 96 +++++++++++------- AppCode/ITRHandler.py | 9 +- AppCode/__pycache__/AOHandler.cpython-313.pyc | Bin 5548 -> 5548 bytes .../DocumentHandler.cpython-313.pyc | Bin 8866 -> 9570 bytes .../__pycache__/ITRHandler.cpython-313.pyc | Bin 5909 -> 5909 bytes AppCode/__pycache__/YearGet.cpython-313.pyc | Bin 2020 -> 1881 bytes templates/summary_reports.html | 7 +- 8 files changed, 71 insertions(+), 53 deletions(-) diff --git a/AppCode/AOHandler.py b/AppCode/AOHandler.py index a103f9a..d7535df 100644 --- a/AppCode/AOHandler.py +++ b/AppCode/AOHandler.py @@ -22,20 +22,18 @@ class AOHandler: return records - + # get ao recourd def get_ao_by_id(self, id): - # Call stored procedure self.cursor.callproc('GetAOById', [id]) - # Fetch result records = [] for result in self.cursor.stored_results(): records = result.fetchall() if records: - return records[0] # return single record - + return records[0] return None + # Add AO record def add_ao(self, data): fields = [ "year","gross_total_income", "disallowance_14a", "disallowance_37", @@ -53,7 +51,7 @@ class AOHandler: self.conn.commit() - # UPDATE ITR RECORD by AO id + # UPDATE AO RECORD by AO id def update_ao(self, id, data): fields = [ @@ -75,7 +73,6 @@ class AOHandler: # DELETE RECORD by AO id def delete_ao_by_id(self, id): - # Call the stored procedure self.cursor.callproc('DeleteAOById', [id]) self.conn.commit() @@ -85,6 +82,7 @@ class AOHandler: self.cursor.close() self.conn.close() + # report download by year def ao_report_download(self, selected_year): try: # Call stored proc to fetch year-wise records diff --git a/AppCode/DocumentHandler.py b/AppCode/DocumentHandler.py index 4524006..2100941 100644 --- a/AppCode/DocumentHandler.py +++ b/AppCode/DocumentHandler.py @@ -79,22 +79,26 @@ class DocumentHandler: connection.close() # return redirect(url_for('view_documents')) - - # Summary report def Summary_report(self, request): dbconfig = DBConfig() connection = dbconfig.get_db_connection() - year = request.args.get('year') - # if not year get all year in list. - if not year: + year_str = request.args.get('year') + + # 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." + ) - return render_template('summary_reports.html', years=allYears,message="Please select a year to download.") + # Convert year to int (IMPORTANT FIX) + year = int(year_str) - # for excel try: stages = { "ITR": "itr", @@ -102,39 +106,43 @@ class DocumentHandler: "CIT": "cit", "ITAT": "itat", } - # stages = ['itr', 'ao', 'cit', '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() - df = pd.DataFrame(rows) if rows else pd.DataFrame() - stage_data[stage_name] = df - + stage_data[stage_name] = pd.DataFrame(rows) if rows else pd.DataFrame() cursor.close() - def safe_get(df, col): return df[col].values[0] if col in df.columns and not df.empty else "-" particulars = [ - "Gross Total Income", "Add: Disallowance u/s 14A", "Add: Disallowance u/s 37", "GTI as per", - "Less: Deduction u/s 80IA", "Less: Deduction u/s 80G", "Net Taxable Income", "Tax @ 30%", - "Tax @ 18.5% on Book Profit", "Surcharge @ 12%", "Education Cess @ 3%", "Total Tax Payable", - "Less: MAT Credit", "Net Tax", "Add: Interest u/s 234C", "Total Tax", - "Advance Tax", "TDS", "TCS", "SAT", "Tax on Regular Assessment", "Refund" + "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 @ 3%", "Total Tax Payable", + "Less: MAT Credit Utilized", "Add: Interest u/s 234C", "Total Tax", " ", + "Advance Tax", "TDS", "TCS", "SAT", + "Tax on Regular Assessment", "Refund" , "Remarks" ] columns = [ - 'gross_total_income', 'disallowance_14a', 'disallowance_37', 'gti', - 'deduction_80ia', 'deduction_80g', 'net_taxable_income', 'tax_30', - 'book_profit_tax', 'surcharge_12', 'education_cess', 'total_tax', - 'mat_credit', 'net_tax', 'interest_234c', 'total_tax_payable', - 'advance_tax', 'tds', 'tcs', 'sat', 'tax_regular', 'refund' + '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_12', 'edu_cess_3', 'total_tax_payable', + 'mat_credit' , 'interest_234c','total_tax', '-', + 'advance_tax', 'tds', 'tcs', 'sat', + 'tax_on_assessment', 'refund', 'Remarks' ] data = { @@ -147,13 +155,31 @@ class DocumentHandler: df = pd.DataFrame(data) - # Export to Excel + # ===== Excel Export ===== output = io.BytesIO() with pd.ExcelWriter(output, engine='xlsxwriter') as writer: - df.to_excel(writer, index=False, sheet_name=f'AY {year}') - workbook = writer.book - worksheet = writer.sheets[f'AY {year}'] + 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({ + 'bold': True, + 'font_size': 14, + 'font_color': 'black', + 'align': 'center', + 'valign': 'middle' + }) + + worksheet.merge_range( + 0, 0, 0, len(df.columns) - 1, + "Laxmi Civil Engineering Services Pvt Ltd", + company_heading + ) + + # ===== Header Format ===== header = workbook.add_format({ 'bold': True, 'align': 'center', @@ -165,29 +191,31 @@ class DocumentHandler: cell = workbook.add_format({ 'border': 1, - 'align': 'center', + 'align': 'left', 'valign': 'middle' }) - # Apply formatting + # Write headers for col_num, col_name in enumerate(df.columns): - worksheet.write(0, col_num, col_name, header) + 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) - for row in range(1, len(df) + 1): + # Write data rows + for row in range(3, len(df) + 3): for col in range(len(df.columns)): - worksheet.write(row, col, df.iloc[row - 1, col], cell) + worksheet.write(row, col, df.iloc[row - 3, col], cell) + + worksheet.freeze_panes(3, 1) output.seek(0) - + return send_file( output, - download_name=f"Summary_Report_{year}.xlsx", + download_name=f"AY{year}-{year + 1}_Summary_Report.xlsx", as_attachment=True, mimetype="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ) finally: connection.close() - diff --git a/AppCode/ITRHandler.py b/AppCode/ITRHandler.py index 93665e7..997e5e8 100644 --- a/AppCode/ITRHandler.py +++ b/AppCode/ITRHandler.py @@ -33,7 +33,7 @@ class ITRHandler: return records - + # get itr record by id def get_itr_by_id(self, id): # Call stored procedure self.cursor.callproc('GetITRById', [id]) @@ -50,8 +50,6 @@ class ITRHandler: return None - - # INSERT ITR RECORD using procedure "add_itr" def add_itr(self, data): @@ -70,7 +68,7 @@ class ITRHandler: self.cursor.callproc("InsertITR", values) self.conn.commit() - + # update itr by id def update(self, id, data): columns = [ 'year', 'gross_total_income', 'disallowance_14a', 'disallowance_37', @@ -91,12 +89,11 @@ class ITRHandler: # DELETE RECORD by ITR id def delete_itr_by_id(self, id): - # Call the stored procedure self.cursor.callproc('DeleteITRById', [id]) self.conn.commit() - + # report download by year def itr_report_download(self, selected_year): try: diff --git a/AppCode/__pycache__/AOHandler.cpython-313.pyc b/AppCode/__pycache__/AOHandler.cpython-313.pyc index c5761ff0746d21ce53ff35dddc9fa047ad7102f4..f57f9d90c3ccf2d49a4e25d30f39c7f131ce2a48 100644 GIT binary patch delta 148 zcmZ3Zy+)h&GcPX}0}${e#Aa%5v z#&~0M0qY|sM%B&193L1N%{RMnWi#@41GN`x0Eq^M8p|UsX|kj vB)M5dK1uPh%70Q3V3q!)!3-q$m{_I0a!eKy?dC6KWR&^D03wS7fkprT@F6Ll diff --git a/AppCode/__pycache__/DocumentHandler.cpython-313.pyc b/AppCode/__pycache__/DocumentHandler.cpython-313.pyc index 5f452bd2cca4142143f3331536ec1927a8f13e9e..8817cf136e3cf302d3b1b36321d751d1f2c6c5d1 100644 GIT binary patch delta 3110 zcmZt|YiwIr`TG5K9NV#z>udYk&ZAD-#A)ItY5EF%uMKg1cUe1kT;13w>818{cJ57+ z8f`)Qvxp&)auDstqy_k~3@Q;cB>0ICs}MyjfudMflbFV@PH0NI2_$}Tj-4BaX|{B} z?|kpqIp_ZL+$Ya@KlgZ?6#o4q@{;s4{wwblW8dVNV>e!?!do}WMKE6$aP*jy0 zm*ir#0-hI_xI2mpD(|~Z-*g&fJ1TpY>|zH+@#ee(eaA_&2Z%xZD;=e%f~$#BRCX7U zEhy#<`8Z?N(4@##-jZ*_nvAi~j!t`n1BHOD#GCh|Y%z+nayHJ+IXLHlS+-{=*}>cM z9mJE(~JGpbejGbe|#JWD6!KKCqX3u#nU_`EK-?FS^{ZFN|KD*MeBP zg9~xtaifuvLtH0s^HN+FZ{z60SjbBao8>Sc%%@u#I>v{%2p{GcE;?>zDL$0%*EuaH zcP268P>Y~reAt3fxr^`250Vy~ig9s{*Z*!Z@{|eB0~7Op%%na2e5p4z_cgH6h?Kv?hwWN zuH~p4!(oo=ycXmbKFY`VNY>n>u~cC~=kh^5MhcKWp;KD0a8k#0-}y0uyG6ywT=OIc-X?ZxB+f( z+>Eb{=HV>`&v~w&FvY1^LxR$&&RMESN@vhV!J$xJt_(y4unH*S+mRL7+hSQNy&vrm z42Ex`S3*Y(4ElBG8_S2U07W^*o&}|aqAFEoc41Iq$1;~D*~9F#%zkY_kz_2vHgDIO zzd@anlp>o4MIgf z-TK5R@d9D4cTWmQncC6bgNHC`yqi}%8CMwkb%2xL_YlKo7zdP|sx z)mcduhQ@@f<|5SjW;rysqL)J$I-)soDnb!=MHtrF)v79%iHkj9XGK(nVxvZyM`C0Z zK%l6?k>Qb|=GYT&1c<_2(Re#iuF8U_DA;C&gk*(ac0n$|5-IA%uBqjkY4SQ-GvT3t z_|>G&KOrwu+N4<|xdfIpr*abjRglFB(CmsTLKRjQpLj{(Ei+}YcuTXARB;Wh6{%Dz zgS166&s57L%`sb*RYAdh)SL~pSS?qfX2H`sCu>$RwR19DChlqnu82z&i9I9Tmdflo zc@9q|fRa4Nasb|za6#DIZI!*EmTIM}2lG{^qA^;D^+9rh zLGsMP9EPqRr%Nt%;X^gB9bHc7IIKB1+As{-(33s98jfMzNK8D1m84j?aJj;I3k zVkC}UjdXGDSqMN4;NId>sF@W2Zb4GkbOMsE252V>xd!0?UNrk1AVNV=q2?sm1)!3e z+wm#9j<*VoV5#o|T_*%o@BL31Mv#B`< z)@ZZVhCj4$KzD?jKrG?wo<;%`%ByL!L9hPqTi9h>4Wd6iF zimf`gupwXQp8Kx*N8YCa>frdZkim1!@XYFncvmhz3pv8xl?ywa$QFCB98a!|to5#& z*3WJXy?1f_*k<(TsTR!gNNaCG|Hz!u@btd`F)SFZ5 z{aZ|S)v;rxQU|w_*{x)@&am}Fs-8^OqdoOl?^Bm`)c-kUO$Aolc6?Mjz3uDS^7Yh% z9jht?$%7q@LjYy?mGb0em-8R9Qf3Wmwj zi5{~#!yiyj;)?0$Wg}7(53Fwy#@nbj8K)l+lpHun<3+O{uT)D5WpENcMnZC=?W)NT Ke@2nDA@o1BE%0Rk delta 2270 zcmah~Yi!%r6(&WAdQ-90)$4JZ>1;p({4*$I=W~f$q=l zwM^UVkB$WHIrlui^WAeVFaPrOpB-WT<@LG<^t^ZBc(WOQgE?Wj_?wxDc|ns@ZGO7Z zZp!mtQcA~v-7CrgE6a$RXlr^IvMyrxU-!tkL&u~aAxm&$yB7v-k5{C}bbN_oEc zWicbA@|U@h_lq1>N;kf1Ipeal?C>McxkTd-LCiVvqVQAh3PQFCwyGPZsi4nNCc8$N zMm8^e$D7RicESii2{f<*+c=dYQUsuZ9XNm!xCX7VeVC9P@O5hnPBL!WO9E95La`?d zzs*=}Zoyp*WAvc+^s7UbvZag16UZKcX(kD;qbQHysrJH4R6OgQ4HJZ$;E8W|2X;z} zEaDwAc~ledGbUZ$H#a?dGPAcj=JekLXFqbGdU!<%DEY=o2fXSVqZ}XrU-6ZZ4DQGf zl8FEa58CA5|CC(yb0h=*!SEBieGBai$n4cNwG1JI01G1H77HPV1*X~uUvUNtVGsqq zf|VggEFd;cp+1DG2h5y3DYM8vfcw_76Kz9IIU=ytgSfZxI7ombNC6J;gY@pcMYsJZ zE6o8MkshRWeZ6x96Cbe|MBNU;Gl76TCdY+HwTNr=WrUaz7oufrH#{_(%C-35wCL#QY~DO`G6nr%&-Ss?=!e zYxaty^XR^UKaXbNo#-Q$JPRYeV;2o-NpBiVLuz#DdQ*{W4-Yp*!@GaJWCUbMuj%4B zaiJyEn%h^OL8EzXWZ3X6D9Tf{v#PS#+>S9kn#reDEEx<27Ppb>h?C*e6ax58g%MGttmGoR76{r5P4Z_O9ow+Ft$Orn~g?GTC-<|hsPEc7Y*C$auYf5 zAbwO!044c?$F3ASH(v^;drCMESDXQUGRAhZerxz5pA*p#v{Q=5VzenWI_v+(Ie2>vvYg|`yRKBpvi+L9_F7N=1XtRy)r z)ske`O2#}^O_H8c8D!6=V9_16ayaByNf!PgS@fzyxQbO(RyB1F22y=~gH}5F*^X|| zt14a>d?LldbEzR~3g^9%io;*09v(l1CfXYM?4Bn66pX`(b;njXc`rP)86Nr|TwHf; z`Pk{>GUN%U1s2m5ELNfe-!cWzQwgPnb``#KG|g zG17aQd_dE2X8rgBKOJG#AHN@fkMpmM`2&~Tm)ut#yVm!1{buea`}TXjj&Kz} zb%z>2lRHx(G`{b5RZ{l%V|J{k1Ck5D6ch{6}LC&{miPac#9n;V3-FfmS^Y%2OtK#iYO`jZNXP-6xXe3RA09`HLeF-m=60FgzaK%D@^Od9V1 diff --git a/AppCode/__pycache__/YearGet.cpython-313.pyc b/AppCode/__pycache__/YearGet.cpython-313.pyc index 188b8ebfab5fd4b14522ee713ae47df390b3758e..0a977cf8d6b5609e84278f512876c0decf3cf98a 100644 GIT binary patch delta 93 zcmaFDf0K{*GcPX}0}zt=K9Q*(P delta 233 zcmcb~_k^GKGcPX}0}vdq@y;yV$lJnLf5h1;CbT%Us5r(kB{wrK#wEWzFDE}Sr8p+c zNY^tjIX^cwB(Wm6vbZEQSJ%Ky*U(7U$iT={L02I$FS9s
- - -

Download Year-wise Summary Report

{% if message %} @@ -38,6 +35,4 @@ {% endblock %} -{% block extra_js %} -{% endblock %} -{% endblock %} +{% endblock %} \ No newline at end of file