diff --git a/controllers/block_controller.py b/controllers/block_controller.py index 8f2e80a..225a158 100644 --- a/controllers/block_controller.py +++ b/controllers/block_controller.py @@ -7,12 +7,12 @@ from model.Block import Block from model.Utilities import HtmlHelper block_bp = Blueprint('block', __name__) - +block = Block() # --- Add Block page ------- @block_bp.route('/add_block', methods=['GET', 'POST']) @login_required def add_block(): - block = Block() + # block = Block() if request.method == 'POST': block.AddBlock(request) @@ -62,7 +62,7 @@ def get_districts(state_id): @login_required def check_block(): - block = Block() + # block = Block() return block.CheckBlock(request) @@ -70,8 +70,8 @@ def check_block(): @login_required def edit_block(block_id): - block = Block() - + +# block = Block() if request.method == 'POST': block.EditBlock(request, block_id) block.resultMessage @@ -90,7 +90,10 @@ def edit_block(block_id): for rs in cursor.stored_results(): states = rs.fetchall() - cursor.callproc("GetAllDistrictsData") + # cursor.callproc("GetAllDistrictsData") + # for rs in cursor.stored_results(): + # districts = rs.fetchall() + cursor.callproc("GetAllDistricts") for rs in cursor.stored_results(): districts = rs.fetchall() @@ -111,7 +114,7 @@ def edit_block(block_id): @login_required def delete_block(block_id): - block = Block() + # block = Block() block.DeleteBlock(request, block_id) return redirect(url_for('block.add_block')) \ No newline at end of file diff --git a/controllers/district_controller.py b/controllers/district_controller.py index fe6efd7..7cbf337 100644 --- a/controllers/district_controller.py +++ b/controllers/district_controller.py @@ -5,12 +5,13 @@ from model.District import District from model.State import State district_bp = Blueprint('district', __name__) +district = District() # ------- District page -------- @district_bp.route('/add_district', methods=['GET', 'POST']) @login_required def add_district(): - district = District() + # district = District() if request.method == 'POST': district.AddDistrict(request=request) @@ -32,7 +33,7 @@ def add_district(): @login_required def check_district(): - district = District() + # district = District() return district.CheckDistrict(request=request) @@ -41,7 +42,7 @@ def check_district(): @login_required def delete_district(district_id): - district = District() + # district = District() district.DeleteDistrict(request=request, district_id=district_id) @@ -56,7 +57,7 @@ def delete_district(district_id): @login_required def edit_district(district_id): - district = District() + # district = District() state = State() if request.method == 'POST': diff --git a/controllers/excel_upload_controller.py b/controllers/excel_upload_controller.py index df020d0..e1d7a46 100644 --- a/controllers/excel_upload_controller.py +++ b/controllers/excel_upload_controller.py @@ -59,21 +59,21 @@ def show_table(filename): try: cursor = connection.cursor(dictionary=True) - cursor.callproc('GetStateByName', [file_info['State']]) + cursor.callproc('CheckStateExists', [file_info['State']]) for result in cursor.stored_results(): state_data = result.fetchone() if not state_data: errors.append(f"State '{file_info['State']}' is not valid. Please add it.") if state_data: - cursor.callproc('GetDistrictByNameAndStates', [file_info['District'], state_data['State_ID']]) + cursor.callproc('GetDistrictByNameAndState', [file_info['District'], state_data['State_Id']]) # Change GetDistrictByNameAndStates to GetDistrictByNameAndState for result in cursor.stored_results(): district_data = result.fetchone() if not district_data: errors.append(f"District '{file_info['District']}' is not valid under state '{file_info['State']}'.") if district_data: - cursor.callproc('GetBlockByNameAndDistricts', [file_info['Block'], district_data['District_ID']]) + cursor.callproc('GetBlockByNameAndDistrict', [file_info['Block'], district_data['District_id']]) #Change District_ID to District_id and GetBlockByNameAndDistricts to GetBlockByNameAndDistrict for result in cursor.stored_results(): block_data = result.fetchone() if not block_data: @@ -84,7 +84,9 @@ def show_table(filename): subcontractor_data = result.fetchone() if not subcontractor_data: - cursor.callproc('InsertSubcontractor', [file_info['Subcontractor']]) + # cursor.callproc('InsertSubcontractor', [file_info['Subcontractor']]) + # connection.commit() + cursor.callproc('SaveContractor', [file_info.get('Subcontractor'),None,None,None,None,None,None,None,None]) connection.commit() cursor.callproc('GetSubcontractorByName', [file_info['Subcontractor']]) for result in cursor.stored_results(): @@ -152,17 +154,19 @@ def show_table(filename): ) -# save Excel data + # save Excel data @excel_bp.route('/save_data', methods=['POST']) def save_data(): # Extract form data subcontractor_id = request.form.get("subcontractor_data") + state_id = request.form.get("state_data") + district_id = request.form.get("district_data") block_id = request.form.get("block_data") + variables = request.form.getlist('variables[]') hold_columns = request.form.get("hold_columns") - + hold_counter = request.form.get("hold_counter") if not data: return jsonify({"error": "No data provided to save"}), 400 - if data: connection = config.get_db_connection() cursor = connection.cursor() @@ -172,7 +176,7 @@ def save_data(): "PMC_No": entry.get("PMC_No"), "Invoice_Details": entry.get("Invoice_Details", ''), "Work_Type": 'none', - "In oice_Date": entry.get("Invoice_Date").strftime('%Y-%m-%d') if entry.get( + "Invoice_Date": entry.get("Invoice_Date").strftime('%Y-%m-%d') if entry.get( "Invoice_Date") else None, "Invoice_No": entry.get("Invoice_No", ''), "Basic_Amount": entry.get("Basic_Amount", 0.00), @@ -227,6 +231,7 @@ def save_data(): else: work_type = " ".join(words[:work_pos + 1]) if Invoice_Details and 'village' in Invoice_Details.lower() and 'work' in Invoice_Details.lower(): + # print("village_name ::", village_name, "|| work_type ::", work_type) if block_id and village_name: village_id = None cursor.callproc("GetVillageId", (block_id, village_name)) @@ -239,7 +244,12 @@ def save_data(): for result in cursor.stored_results(): result = result.fetchone() village_id = result[0] if result else None - + # print("village_id :", village_id) + # print("block_id :", block_id) + # print("invoice :", PMC_No, village_id, work_type, Invoice_Details, Invoice_Date, Invoice_No, + # Basic_Amount, Debit_Amount, After_Debit_Amount, Amount, GST_Amount, TDS_Amount, + # SD_Amount, On_Commission, Hydro_Testing, GST_SD_Amount, Final_Amount) + args = ( PMC_No, village_id, work_type, Invoice_Details, Invoice_Date, Invoice_No, Basic_Amount, Debit_Amount, After_Debit_Amount, Amount, GST_Amount, TDS_Amount, @@ -247,24 +257,39 @@ def save_data(): subcontractor_id, 0 ) + # print("All invoice Details ",args) + # add subcontarctor id in invoice table results = cursor.callproc('SaveInvoice', args) invoice_id = results[-1] - - - cursor.callproc("SavePayment",( PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount,Total_Amount, UTR,invoice_id)) + print("**************************************************************") + print(invoice_id) + print("**************************************************************") + cursor.callproc( + "SavePayment", + ( + PMC_No, + Invoice_No, # required + Payment_Amount, + TDS_Payment_Amount, + Total_Amount, + UTR, + invoice_id # last + ) + ) + # print("invoice id from the excel ", invoice_id) if isinstance(hold_columns, str): hold_columns = ast.literal_eval(hold_columns) if isinstance(hold_columns, list) and all(isinstance(hold, dict) for hold in hold_columns): for hold in hold_columns: - - hold_column_name = hold.get('column_name') - hold_type_id = hold.get('hold_type_id') + # print(f"Processing hold: {hold}") + hold_column_name = hold.get('column_name') # Get column name + hold_type_id = hold.get('hold_type_id') # Get hold_type_id if hold_column_name: hold_amount = entry.get( - hold_column_name) + hold_column_name) # Get the value for that specific hold column if hold_amount is not None: - + # print(f"Processing hold type: {hold_column_name}, Hold Amount: {hold_amount}") hold_join_data = { "Contractor_Id": subcontractor_id, "Invoice_Id": invoice_id, @@ -281,9 +306,10 @@ def save_data(): print(f"Invalid hold entry: {hold}") else: print("Hold columns data is not a valid list of dictionaries.") - #-------------------------Credit Note-------------------------------------------------- +#---------------------------------------------Credit Note--------------------------------------------------------------------------- elif any(keyword in Invoice_Details.lower() for keyword in ['credit note','logging report']): - + # print("Credit note found:", PMC_No, Invoice_No, Basic_Amount, Debit_Amount, Final_Amount, + # After_Debit_Amount, GST_Amount, Amount, Final_Amount, Payment_Amount, Total_Amount, UTR, Invoice_No) cursor.callproc( 'AddCreditNoteFromExcel', [ @@ -292,7 +318,7 @@ def save_data(): subcontractor_id, Invoice_No ] ) - #--------------------------Hold Amount------------------------------------------------- +#-----------------------------------------------Hold Amount---------------------------------------------------------------------- # Step 1: Normalize Invoice_Details: lowercase, trim, remove extra spaces normalized_details = re.sub(r'\s+', ' ', Invoice_Details.strip()).lower() # Step 2: Define lowercase keywords @@ -308,13 +334,13 @@ def save_data(): ] # Step 3: Matching condition if any(kw in normalized_details for kw in keywords): - # print(" Match found. Inserting hold release for:", Invoice_Details) + # print("✅ Match found. Inserting hold release for:", Invoice_Details) cursor.callproc( 'AddHoldReleaseFromExcel', [PMC_No, Invoice_No, Invoice_Details, Basic_Amount, Final_Amount, UTR, subcontractor_id] ) connection.commit() - # print(" Hold release inserted for:", PMC_No, Invoice_Details) + # print("✅ Hold release inserted for:", PMC_No, Invoice_Details) #------------------------------------------------------------------------------------------------------------------ elif Invoice_Details and any( keyword in Invoice_Details.lower() for keyword in ['gst', 'release', 'gst release note']): @@ -324,33 +350,51 @@ def save_data(): [PMC_No, Invoice_No, Basic_Amount, Final_Amount, Total_Amount, UTR, subcontractor_id] ) - # -------------------------------------- - # If no village/work detected, only PMC/Payment - if not (Invoice_Details and 'village' in Invoice_Details.lower() and 'work' in Invoice_Details.lower()): +# -------------------------------------- +# If no village/work detected, only PMC/Payment + if not (Invoice_Details and 'village' in Invoice_Details.lower() and 'work' in Invoice_Details.lower()): + # if not (Invoice_Details and 'village' in Invoice_Details.lower() and 'work' in Invoice_Details.lower() and 'gst' in Invoice_Details.lower() and 'gst release note' in Invoice_Details.lower() and 'release' in Invoice_Details.lower()): + # ---------- Only PMC / Payment rows ---------- if PMC_No and not Invoice_No and UTR : + # print("No village/work, using PMC only :", PMC_No) + + # check invoice exists + # cursor.execute( + # "SELECT invoice_id FROM invoice WHERE PMC_No=%s ORDER BY invoice_id DESC LIMIT 1", + # (PMC_No,) + # ) + # row = cursor.fetchone() + # invoice_id = row[0] if row else None + + # # insert invoice if not exists + + # if not invoice_id: + print(" extra payment :", PMC_No,Total_Amount,UTR, subcontractor_id) - cursor.execute( - """ - INSERT INTO invoice (PMC_No,Contractor_Id) VALUES (%s, %s); - """, - (PMC_No, subcontractor_id) - ) - connection.commit() - - cursor.execute( - "SELECT invoice_id FROM invoice WHERE PMC_No=%s AND Contractor_Id =%s ORDER BY invoice_id DESC LIMIT 1", - (PMC_No, subcontractor_id) - ) - row = cursor.fetchone() - invoice_id = row[0] if row else None + # cursor.execute( + # """ + # INSERT INTO invoice (PMC_No,Contractor_Id) VALUES (%s, %s); + # """, + # (PMC_No, subcontractor_id) + # ) + # connection.commit() + # cursor.execute( + # "SELECT invoice_id FROM invoice WHERE PMC_No=%s AND Contractor_Id =%s ORDER BY invoice_id DESC LIMIT 1", + # (PMC_No, subcontractor_id) + # ) + # row = cursor.fetchone() + cursor.callproc("insertExtrapaymet",(PMC_No, subcontractor_id)) + for result in cursor.stored_results(): + row = result.fetchone() + invoice_id = row[0] if row else None # insert payment cursor.callproc( "SavePayment", ( PMC_No, - Invoice_No, + Invoice_No, # required Payment_Amount, TDS_Payment_Amount, Total_Amount, @@ -358,7 +402,40 @@ def save_data(): invoice_id ) ) - + + # if PMC_No and Total_Amount and UTR: + # print("Payment :", PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR ) + + # Add inoice id in payment table + # cursor.callproc("SavePayment",(PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR, invoice_id)) + + # if not village_id: + # village_id = None + # cursor.callproc('InsertOrUpdateInPayment', ( + # PMC_No, + # village_id, + # work_type, + # Invoice_Details, + # Invoice_Date, + # Invoice_No, + # Basic_Amount, + # Debit_Amount, + # After_Debit_Amount, + # Amount, + # GST_Amount, + # TDS_Amount, + # SD_Amount, + # On_Commission, + # Hydro_Testing, + # 0, + # GST_SD_Amount, + # Final_Amount, + # Payment_Amount, + # TDS_Payment_Amount, + # Total_Amount, + # UTR,f + # subcontractor_id + # )) connection.commit() return jsonify({"success": "Data saved successfully!"}), 200 except Exception as e: @@ -368,3 +445,4 @@ def save_data(): cursor.close() connection.close() return render_template('index.html') +# ---------------------- Report -------------------------------- \ No newline at end of file diff --git a/controllers/gst_release_controller.py b/controllers/gst_release_controller.py index 87f6ff1..5827f8a 100644 --- a/controllers/gst_release_controller.py +++ b/controllers/gst_release_controller.py @@ -1,10 +1,10 @@ +# routes/gst_release_routes.py from flask import Blueprint, render_template, request, redirect, url_for, flash from flask_login import login_required from model.gst_release import GSTRelease from model.Log import LogHelper gst_release_bp = Blueprint('gst_release_bp', __name__) - gst_service = GSTRelease() # ---------------- ADD GST RELEASE ---------------- diff --git a/controllers/hold_types_controller.py b/controllers/hold_types_controller.py index 3cc5c94..6b82334 100644 --- a/controllers/hold_types_controller.py +++ b/controllers/hold_types_controller.py @@ -5,16 +5,16 @@ from model.GST import GST hold_bp = Blueprint("hold_types", __name__) - +hold = HoldTypes() # ---------------- ADD HOLD TYPE ---------------- @hold_bp.route('/add_hold_type', methods=['GET','POST']) @login_required def add_hold_type(): - hold = HoldTypes() + # hold = HoldTypes() if request.method == 'POST': hold.AddHoldType(request) - # Always redirect to same page (NO JSON) + # ✅ Always redirect to same page (NO JSON) return redirect(url_for("hold_types.add_hold_type")) # GET request → show data @@ -30,7 +30,7 @@ def add_hold_type(): @login_required def check_hold_type(): - hold = HoldTypes() + # hold = HoldTypes() return hold.CheckHoldType(request) # if exists @@ -39,13 +39,13 @@ def check_hold_type(): @login_required def edit_hold_type(id): - hold = HoldTypes() + # hold = HoldTypes() if request.method == 'POST': - hold.EditHoldType(request, id) + hold.EditHoldType(request, id) # ✅ return hold.resultMessage - hold_data = hold.GetHoldTypeByID(id) + hold_data = hold.GetHoldTypeByID(id) # ✅ return render_template( "edit_hold_type.html", @@ -58,8 +58,8 @@ def edit_hold_type(id): @login_required def delete_hold_type(id): - hold = HoldTypes() - hold.DeleteHoldType(request, id) + # hold = HoldTypes() + hold.DeleteHoldType(request, id) # ✅ return redirect(url_for("hold_types.add_hold_type")) diff --git a/controllers/invoice_controller.py b/controllers/invoice_controller.py index 0ee43d3..0bc947a 100644 --- a/controllers/invoice_controller.py +++ b/controllers/invoice_controller.py @@ -1,3 +1,5 @@ +# controllers/invoice_controller.py + from flask import Blueprint, request, jsonify, render_template from flask_login import login_required, current_user from model.Invoice import * @@ -35,7 +37,11 @@ def add_invoice(): village_id = village_result['Village_Id'] invoice_id = insert_invoice(data, village_id) - assign_subcontractor(data, village_id) + # assign_subcontractor(data, village_id) + print("********************************************************************") + print("Manully added invoice id :",invoice_id) + print("********************************************************************") + insert_hold_types(data, invoice_id) log_action("Add invoice", f"added invoice '{data.get('pmc_no')}'") @@ -78,6 +84,7 @@ def edit_invoice(invoice_id): if request.method == 'POST': data = request.form update_invoice(data, invoice_id) + # update_inpayment(data) log_action("Edit invoice", f"edited invoice '{invoice_id}'") return jsonify({"status": "success", "message": "Invoice updated successfully"}), 200 diff --git a/controllers/payment_controller.py b/controllers/payment_controller.py index 6e42a0e..ed10850 100644 --- a/controllers/payment_controller.py +++ b/controllers/payment_controller.py @@ -29,6 +29,7 @@ def add_payment(): LogHelper.log_action("Add Payment", f"User {current_user.id} Add Payment '{pmc_no}'") Paymentmodel.insert_payment(subcontractor_id,pmc_no, invoice_no, amount, tds_amount, total_amount, utr) + # Paymentmodel.update_inpayment(subcontractor_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr) return redirect(url_for('payment_bp.add_payment')) @@ -70,15 +71,14 @@ def edit_payment(payment_id): LogHelper.log_action("Edit Payment", f"User {current_user.id} Edit Payment '{pmc_no}'") Paymentmodel.call_update_payment_proc(payment_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr) - connection = Paymentmodel.get_connection() - cursor = connection.cursor() - cursor.callproc( - 'UpdateInpaymentByPMCInvoiceUTR', - [amount, tds_amount, total_amount, pmc_no, invoice_no, utr] -) - connection.commit() - cursor.close() - connection.close() + # Update inpayment + # connection = Paymentmodel.get_connection() + # cursor = connection.cursor() + # cursor.callproc('UpdateInpaymentByPMCInvoiceUTR',[amount, tds_amount, total_amount, pmc_no, invoice_no, utr]) + + # connection.commit() + # cursor.close() + # connection.close() return redirect(url_for('payment_bp.add_payment')) diff --git a/controllers/pmc_report_controller.py b/controllers/pmc_report_controller.py index 06814aa..e1223ee 100644 --- a/controllers/pmc_report_controller.py +++ b/controllers/pmc_report_controller.py @@ -1,41 +1,40 @@ -from flask import Blueprint, render_template, send_from_directory -from flask_login import login_required +# from flask import Blueprint, render_template, send_from_directory +# from flask_login import login_required +# from model.PmcReport import PmcReport -from model.PmcReport import PmcReport +# pmc_report_bp = Blueprint("pmc_report", __name__) -pmc_report_bp = Blueprint("pmc_report", __name__) +# # ---------------- Contractor Report by pmc no ---------------- +# @pmc_report_bp.route("/pmc_report/") +# @login_required +# def pmc_report(pmc_no): +# data = PmcReport.get_pmc_report(pmc_no) +# if not data: +# return "No PMC found with this number", 404 -# ---------------- Contractor Report by pmc no ---------------- -@pmc_report_bp.route("/pmc_report/") -@login_required -def pmc_report(pmc_no): - data = PmcReport.get_pmc_report(pmc_no) - if not data: - return "No PMC found with this number", 404 +# return render_template( +# "pmc_report.html", +# info=data["info"], +# invoices=data["invoices"], +# hold_types=data["hold_types"], +# gst_rel=data["gst_rel"], +# payments=data["payments"], +# credit_note=data["credit_note"], +# hold_release=data["hold_release"], +# total=data["total"] +# ) - return render_template( - "pmc_report.html", - info=data["info"], - invoices=data["invoices"], - hold_types=data["hold_types"], - gst_rel=data["gst_rel"], - payments=data["payments"], - credit_note=data["credit_note"], - hold_release=data["hold_release"], - total=data["total"] - ) +# # ---------------- Contractor Download Report by pmc no ---------------- +# @pmc_report_bp.route("/download_pmc_report/") +# @login_required +# def download_pmc_report(pmc_no): -# ---------------- Contractor Download Report by pmc no ---------------- -@pmc_report_bp.route("/download_pmc_report/") -@login_required -def download_pmc_report(pmc_no): +# result = PmcReport.download_pmc_report(pmc_no) - result = PmcReport.download_pmc_report(pmc_no) +# if not result: +# return "No contractor found for this PMC No", 404 - if not result: - return "No contractor found for this PMC No", 404 +# output_folder, file_name = result - output_folder, file_name = result - - return send_from_directory(output_folder, file_name, as_attachment=True) +# return send_from_directory(output_folder, file_name, as_attachment=True) diff --git a/controllers/report_controller.py b/controllers/report_controller.py index 46cf6f3..4354ecc 100644 --- a/controllers/report_controller.py +++ b/controllers/report_controller.py @@ -1,12 +1,10 @@ -from flask import Blueprint, render_template, request, jsonify,send_file +from flask import Blueprint, render_template, request, jsonify, send_file from flask_login import login_required, current_user - +from services.ReportService import ReportService from model.Report import ReportHelper -from model.Log import LogHelper report_bp = Blueprint("report", __name__) - # ---------------- Report Page ---------------- @report_bp.route("/report") @login_required @@ -19,36 +17,70 @@ def report_page(): @login_required def search_contractor(): - subcontractor_name = request.form.get("subcontractor_name") - - LogHelper.log_action( - "Search Contractor", - f"User {current_user.id} searched contractor '{subcontractor_name}'" - ) - data = ReportHelper.search_contractor(request) - return jsonify(data) + # Pagination (basic) + page = int(request.form.get("page", 1)) + per_page = 20 + + start = (page - 1) * per_page + end = start + per_page + + paginated_data = data[start:end] + + return jsonify({ + "data": paginated_data, + "total": len(data) + }) # ---------------- Contractor Report by contractor id ---------------- @report_bp.route('/contractor_report/') @login_required def contractor_report(contractor_id): - data = ReportHelper.get_contractor_report(contractor_id) + service = ReportService(contractor_id=contractor_id).load_data() return render_template( 'subcontractor_report.html', contractor_id=contractor_id, - **data + **service.get_web_data() + ) + +# ---------------- Contractor Report by pmc no ---------------- +@report_bp.route("/pmc_report/") +@login_required +def pmc_report(pmc_no): + + service = ReportService(pmc_no=pmc_no).load_data() + + return render_template( + "pmc_report.html", + **service.get_web_data() ) # ---------------- Contractor Download Report by contractor id ---------------- @report_bp.route('/download_report/') +@login_required def download_report(contractor_id): - output_file, error = ReportHelper.create_contractor_report(contractor_id) - + + service = ReportService(contractor_id=contractor_id).load_data() + + file, error = service.download_excel() + if error: return error, 404 - return send_file(output_file, as_attachment=True) \ No newline at end of file + return send_file(file, as_attachment=True) + +# ---------------- Contractor Download Report by pmc no ---------------- +@report_bp.route("/download_pmc_report/") +@login_required +def download_pmc_report(pmc_no): + + service = ReportService(pmc_no=pmc_no).load_data() + + file, error = service.download_excel() + if error: + return error, 404 + + return send_file(file, as_attachment=True) \ No newline at end of file diff --git a/controllers/state_controller.py b/controllers/state_controller.py index a26c951..cf1bb13 100644 --- a/controllers/state_controller.py +++ b/controllers/state_controller.py @@ -3,13 +3,13 @@ from flask_login import login_required from model.State import State state_bp = Blueprint('state', __name__) - +state = State() # ----- State page ------ @state_bp.route('/add_state', methods=['GET', 'POST']) @login_required def add_state(): - state = State() + # state = State() if request.method == 'POST': state.AddState(request=request) @@ -24,7 +24,7 @@ def add_state(): @login_required def check_state(): - state = State() + # state = State() return state.CheckState(request=request) @@ -33,7 +33,7 @@ def check_state(): @login_required def deleteState(id): - state = State() + # state = State() state.DeleteState(request=request, id=id) @@ -47,7 +47,7 @@ def deleteState(id): @login_required def editState(id): - state = State() + # state = State() if request.method == 'POST': diff --git a/controllers/subcontractor_controller.py b/controllers/subcontractor_controller.py index f9733f8..d9f7fbd 100644 --- a/controllers/subcontractor_controller.py +++ b/controllers/subcontractor_controller.py @@ -3,12 +3,17 @@ from flask_login import login_required from model.Subcontractor import Subcontractor from model.Utilities import HtmlHelper, ResponseHandler + subcontractor_bp = Blueprint('subcontractor', __name__) + +# ---------------------------------------------------------- # LIST + ADD +# ---------------------------------------------------------- @subcontractor_bp.route('/subcontractor', methods=['GET', 'POST']) @login_required def subcontract(): + sub = Subcontractor() # ---------------- GET ---------------- @@ -26,22 +31,27 @@ def subcontract(): if request.method == 'POST': sub.AddSubcontractor(request) + if not sub.isSuccess: return HtmlHelper.json_response( ResponseHandler.add_failure("Subcontractor"), 500 ) + # Reload list after insert subcontractor = sub.GetAllSubcontractors(request) return render_template('add_subcontractor.html', subcontractor=subcontractor) +# ---------------------------------------------------------- # EDIT +# ---------------------------------------------------------- @subcontractor_bp.route('/edit_subcontractor/', methods=['GET', 'POST']) @login_required def edit_subcontractor(id): sub = Subcontractor() + # Fetch data subcontractor = sub.GetSubcontractorByID(id) @@ -65,7 +75,9 @@ def edit_subcontractor(id): return render_template('edit_subcontractor.html', subcontractor=subcontractor) +# ---------------------------------------------------------- # DELETE +# ---------------------------------------------------------- @subcontractor_bp.route('/deleteSubContractor/', methods=['GET', 'POST']) @login_required def deleteSubContractor(id): diff --git a/controllers/village_controller.py b/controllers/village_controller.py index e173ae1..2567c9b 100644 --- a/controllers/village_controller.py +++ b/controllers/village_controller.py @@ -1,3 +1,7 @@ + + + + from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify from flask_login import login_required @@ -7,14 +11,14 @@ from model.State import State # Create Blueprint village_bp = Blueprint('village', __name__) - +village = Village() # ------------------------- Add Village ------------------------- @village_bp.route('/add_village', methods=['GET', 'POST']) @login_required def add_village(): - village = Village() + # village = Village() if request.method == 'POST': village.AddVillage(request=request) @@ -75,24 +79,25 @@ def get_blocks(district_id): @village_bp.route('/check_village', methods=['POST']) @login_required def check_village(): - village = Village() + # village = Village() return village.CheckVillage(request=request) @village_bp.route('/delete_village/') @login_required def delete_village(village_id): - village = Village() + # village = Village() village.DeleteVillage(request=request, village_id=village_id) - # Convert resultMessage to string if it's a Response or tuple + # ✅ Convert resultMessage to string if it's a Response or tuple raw_msg = village.resultMessage if isinstance(raw_msg, tuple): + # e.g., (, 200) msg = "Village deleted successfully!" elif hasattr(raw_msg, 'get_data'): # Flask Response object - msg = raw_msg.get_data(as_text=True) + msg = raw_msg.get_data(as_text=True) # get raw text else: # fallback msg = str(raw_msg) if raw_msg else "Village deleted successfully!" @@ -107,7 +112,7 @@ def delete_village(village_id): @login_required def edit_village(village_id): - village = Village() + # village = Village() if request.method == 'POST': @@ -130,6 +135,7 @@ def edit_village(village_id): ) else: + # ✅ FIXED HERE (removed request) village_data = village.GetVillageByID(id=village_id) if not village.isSuccess: diff --git a/main.py b/main.py index 96a2977..f664f5a 100644 --- a/main.py +++ b/main.py @@ -16,7 +16,7 @@ from controllers.payment_controller import payment_bp from controllers.gst_release_controller import gst_release_bp from controllers.excel_upload_controller import excel_bp from controllers.report_controller import report_bp -from controllers.pmc_report_controller import pmc_report_bp +# from controllers.pmc_report_controller import pmc_report_bp from controllers.hold_types_controller import hold_bp from dotenv import load_dotenv @@ -57,7 +57,7 @@ app.register_blueprint(payment_bp) app.register_blueprint(gst_release_bp) app.register_blueprint(excel_bp) app.register_blueprint(report_bp) -app.register_blueprint(pmc_report_bp) +# app.register_blueprint(pmc_report_bp) app.register_blueprint(hold_bp) # ---------------- Run App ---------------- diff --git a/model/FolderAndFile.py b/model/FolderAndFile.py index bf63550..30f5336 100644 --- a/model/FolderAndFile.py +++ b/model/FolderAndFile.py @@ -1,11 +1,12 @@ import os from flask import current_app -# ----------------------------- -# BASE FOLDER Class -# ----------------------------- + class FolderAndFile: + # ----------------------------- + # BASE FOLDER METHODS + # ----------------------------- @staticmethod def get_download_folder(): folder = os.path.join(current_app.root_path, "static", "downloads") diff --git a/model/GST.py b/model/GST.py index 21c220e..71da41e 100644 --- a/model/GST.py +++ b/model/GST.py @@ -10,7 +10,7 @@ class GST: invoices_rows = invoice_crud.GetAllData(storedproc="GetAllInvoicesBasic") if not invoice_crud.isSuccess: - return [] + return [] # Could also log invoice_crud.resultMessage invoices = [ dict( @@ -25,16 +25,16 @@ class GST: gst_rows = gst_crud.GetAllData(storedproc="GetAllGSTReleasesBasic") if not gst_crud.isSuccess: - return [] + return [] # Could also log gst_crud.resultMessage gst_invoice_nos = { - g[2] + g[2] # Invoice_No is at index 2 for g in gst_rows if g[2] } gst_basic_amounts = { - float(g[3]) + float(g[3]) # Basic_Amount at index 3 for g in gst_rows if g[3] is not None } diff --git a/model/Invoice.py b/model/Invoice.py index 4e0843a..3501717 100644 --- a/model/Invoice.py +++ b/model/Invoice.py @@ -1,4 +1,6 @@ + import config +import mysql.connector # ------------------- Helper Functions ------------------- def clear_results(cursor): @@ -69,7 +71,22 @@ def get_all_villages(): def insert_invoice(data, village_id): def operation(cursor): # Insert invoice - cursor.callproc('InsertInvoice', [ + # cursor.callproc('InsertInvoice', [ + # data.get('pmc_no'), + # village_id, + # data.get('work_type'), + # data.get('invoice_details'), + # data.get('invoice_date'), + # data.get('invoice_no'), + # *get_numeric_values(data), + # data.get('subcontractor_id') + + # ]) + # invoice_row = fetch_one(cursor) + # if not invoice_row: + # raise Exception("Invoice ID not returned") + # invoice_id = invoice_row.get('invoice_id') + cursor.callproc('SaveInvoice', [ data.get('pmc_no'), village_id, data.get('work_type'), @@ -77,14 +94,27 @@ def insert_invoice(data, village_id): data.get('invoice_date'), data.get('invoice_no'), *get_numeric_values(data), - data.get('subcontractor_id') - + data.get('subcontractor_id'), + 0 ]) - invoice_row = fetch_one(cursor) - if not invoice_row: - raise Exception("Invoice ID not returned") - invoice_id = invoice_row.get('invoice_id') + invoice_id = None + for result in cursor.stored_results(): + row = result.fetchone() + if row: + invoice_id = row['invoice_id'] + # # Insert inpayment + # cursor.callproc('InsertInpayment', [ + # data.get('pmc_no'), + # village_id, + # data.get('work_type'), + # data.get('invoice_details'), + # data.get('invoice_date'), + # data.get('invoice_no'), + # *get_numeric_values(data), + # data.get('subcontractor_id') + # ]) + # clear_results(cursor) return invoice_id return execute_db_operation(operation) @@ -129,6 +159,18 @@ def update_invoice(data, invoice_id): clear_results(cursor) execute_db_operation(operation) +# def update_inpayment(data): +# def operation(cursor): +# cursor.callproc('UpdateInpayment', [ +# data.get('work_type'), +# data.get('invoice_details'), +# data.get('invoice_date'), +# *get_numeric_values(data), +# data.get('pmc_no'), +# data.get('invoice_no') +# ]) +# clear_results(cursor) +# execute_db_operation(operation) def delete_invoice_data(invoice_id, user_id): def operation(cursor): @@ -140,24 +182,31 @@ def delete_invoice_data(invoice_id, user_id): if not record: raise Exception("Invoice not found") + # Use exact DB keys + pmc_no = record['PMC_No'] + invoice_no = record['Invoice_No'] # Delete invoice cursor.callproc("DeleteInvoice", (invoice_id,)) clear_results(cursor) + # Delete inpayment + # cursor.callproc('DeleteInpaymentByPMCInvoice', (pmc_no, invoice_no)) + # clear_results(cursor) + execute_db_operation(operation) # ------------------- Subcontractor Functions ------------------- -def assign_subcontractor(data, village_id): - def operation(cursor): - cursor.callproc('AssignSubcontractor', [ - data.get('pmc_no'), - data.get('subcontractor_id'), - village_id - ]) - clear_results(cursor) - execute_db_operation(operation) +# def assign_subcontractor(data, village_id): +# def operation(cursor): +# cursor.callproc('AssignSubcontractor', [ +# data.get('pmc_no'), +# data.get('subcontractor_id'), +# village_id +# ]) +# clear_results(cursor) +# execute_db_operation(operation) # ------------------- Hold Types Functions ------------------- diff --git a/model/PmcReport.py b/model/PmcReport.py index 5dd6fb9..b3067f7 100644 --- a/model/PmcReport.py +++ b/model/PmcReport.py @@ -1,275 +1,137 @@ -import openpyxl -from openpyxl.styles import Font import config from flask_login import current_user from model.Log import LogHelper -from model.Report import ReportHelper +from services.Generalservice import GeneralUse from model.FolderAndFile import FolderAndFile +from model.Report import ReportHelper class PmcReport: + data=[] - @staticmethod - def get_pmc_report(pmc_no): - connection = config.get_db_connection() - cursor = connection.cursor(dictionary=True, buffered=True) + # @staticmethod + # def get_pmc_report(pmc_no): - try: - pmc_info = ReportHelper.execute_sp(cursor, 'GetContractorInfoByPmcNo', [pmc_no], True) + # connection = config.get_db_connection() + # cursor = connection.cursor(dictionary=True, buffered=True) - if not pmc_info: - return None + # try: + # pmc_info = GeneralUse.execute_sp(cursor, 'GetContractorInfoByPmcNo', [pmc_no], True) + # cursor.callproc("Get_pmc_hold_types", (pmc_no, pmc_info["Contractor_Id"])) + # hold_types = next(cursor.stored_results()).fetchall() - cursor.callproc("Get_pmc_hold_types", (pmc_no, pmc_info["Contractor_Id"])) - hold_types = next(cursor.stored_results()).fetchall() + # # Extract hold_type_ids + # hold_type_ids = [ht['hold_type_id'] for ht in hold_types] - # Extract hold_type_ids - hold_type_ids = [ht['hold_type_id'] for ht in hold_types] + # invoices = [] + # hold_type_ids_str = ",".join(map(str, hold_type_ids)) + # cursor.callproc('GetInvoices_WithHold',[pmc_no, pmc_info["Contractor_Id"], hold_type_ids_str]) + # for result in cursor.stored_results(): + # invoices = result.fetchall() - invoices = [] - hold_amount_total = 0 - if hold_type_ids: - hold_type_ids_str = ",".join(map(str, hold_type_ids)) - cursor.callproc( - 'GetInvoices_WithHold', - [pmc_no, pmc_info["Contractor_Id"], hold_type_ids_str] - ) - else: - cursor.callproc( - 'GetInvoices_NoHold', - [pmc_no, pmc_info["Contractor_Id"]] - ) - for result in cursor.stored_results(): - invoices = result.fetchall() + # gst_rel = GeneralUse.execute_sp(cursor, 'GetGSTReleaseByPMC', [pmc_no]) + + # hold_release = GeneralUse.execute_sp(cursor, 'GetHoldReleaseByPMC', [pmc_no]) + + # credit_note = GeneralUse.execute_sp(cursor, 'GetCreditNoteByPMC', [pmc_no]) - if hold_type_ids: - hold_amount_total = sum(row.get('hold_amount', 0) or 0 for row in invoices) + # payments = GeneralUse.execute_sp(cursor, 'GetPaymentsByPMC', [pmc_no]) + + # totals = { + # "sum_invo_basic_amt": sum(row.get('Basic_Amount', 0) or 0 for row in invoices), + # "sum_invo_debit_amt": sum(row.get('Debit_Amount', 0) or 0 for row in invoices), + # "sum_invo_after_debit_amt": sum(row.get('After_Debit_Amount', 0) or 0 for row in invoices), + # "sum_invo_amt": sum(row.get('Amount', 0) or 0 for row in invoices), + # "sum_invo_gst_amt": sum(row.get('GST_Amount', 0) or 0 for row in invoices), + # "sum_invo_tds_amt": sum(row.get('TDS_Amount', 0) or 0 for row in invoices), + # "sum_invo_ds_amt": sum(row.get('SD_Amount', 0) or 0 for row in invoices), + # "sum_invo_on_commission": sum(row.get('On_Commission', 0) or 0 for row in invoices), + # "sum_invo_hydro_test": sum(row.get('Hydro_Testing', 0) or 0 for row in invoices), + # "sum_invo_gst_sd_amt": sum(row.get('GST_SD_Amount', 0) or 0 for row in invoices), + # "sum_invo_final_amt": sum(row.get('Final_Amount', 0) or 0 for row in invoices), + # "sum_invo_hold_amt": sum(row.get('hold_amount', 0) or 0 for row in invoices), + # "sum_gst_basic_amt": sum(row.get('basic_amount', 0) or 0 for row in gst_rel), + # "sum_gst_final_amt": sum(row.get('final_amount', 0) or 0 for row in gst_rel), + # "sum_pay_payment_amt": sum(row.get('Payment_Amount', 0) or 0 for row in payments), + # "sum_pay_tds_payment_amt": sum(row.get('TDS_Payment_Amount', 0) or 0 for row in payments), + # "sum_pay_total_amt": sum(row.get('Total_amount', 0) or 0 for row in payments) + # } - total_invo_final = sum(row.get('Final_Amount', 0) or 0 for row in invoices) + # return { + # "info": pmc_info, + # "invoices": invoices, + # "hold_types": hold_types, + # "gst_rel": gst_rel, + # "payments": payments, + # "credit_note": credit_note, + # "hold_release": hold_release, + # "total": totals + # } - # GST RELEASE - gst_rel = ReportHelper.execute_sp(cursor, 'GetGSTReleaseByPMC', [pmc_no]) - - total_gst_basic = sum(row.get('basic_amount', 0) or 0 for row in gst_rel) - total_gst_final = sum(row.get('final_amount', 0) or 0 for row in gst_rel) - - # ---------------- HOLD RELEASE ---------------- - hold_release = ReportHelper.execute_sp(cursor, 'GetHoldReleaseByPMC', [pmc_no]) - - # ---------------- CREDIT NOTE ---------------- - credit_note = ReportHelper.execute_sp(cursor, 'GetCreditNoteByPMC', [pmc_no]) - - # ---------------- PAYMENTS ---------------- - payments = ReportHelper.execute_sp(cursor, 'GetPaymentsByPMC', [pmc_no]) - - total_pay_amount = sum(row.get('Payment_Amount', 0) or 0 for row in payments) - total_pay_total = sum(row.get('Total_amount', 0) or 0 for row in payments) - - totals = { - "sum_invo_basic_amt": sum(row.get('Basic_Amount', 0) or 0 for row in invoices), - "sum_invo_debit_amt": sum(row.get('Debit_Amount', 0) or 0 for row in invoices), - "sum_invo_after_debit_amt": sum(row.get('After_Debit_Amount', 0) or 0 for row in invoices), - "sum_invo_amt": sum(row.get('Amount', 0) or 0 for row in invoices), - "sum_invo_gst_amt": sum(row.get('GST_Amount', 0) or 0 for row in invoices), - "sum_invo_tds_amt": sum(row.get('TDS_Amount', 0) or 0 for row in invoices), - "sum_invo_ds_amt": sum(row.get('SD_Amount', 0) or 0 for row in invoices), - "sum_invo_on_commission": sum(row.get('On_Commission', 0) or 0 for row in invoices), - "sum_invo_hydro_test": sum(row.get('Hydro_Testing', 0) or 0 for row in invoices), - "sum_invo_gst_sd_amt": sum(row.get('GST_SD_Amount', 0) or 0 for row in invoices), - "sum_invo_final_amt": total_invo_final, - "sum_invo_hold_amt": hold_amount_total, - "sum_gst_basic_amt": total_gst_basic, - "sum_gst_final_amt": total_gst_final, - "sum_pay_payment_amt": total_pay_amount, - "sum_pay_tds_payment_amt": sum(row.get('TDS_Payment_Amount', 0) or 0 for row in payments), - "sum_pay_total_amt": total_pay_total - } - - return { - "info": pmc_info, - "invoices": invoices, - "hold_types": hold_types, - "gst_rel": gst_rel, - "payments": payments, - "credit_note": credit_note, - "hold_release": hold_release, - "total": totals - } - - finally: - cursor.close() - connection.close() + # finally: + # cursor.close() + # connection.close() - @staticmethod - def download_pmc_report(pmc_no): + # @staticmethod + # def download_pmc_report(pmc_no): - connection = config.get_db_connection() - if not connection: - return None + # connection = config.get_db_connection() + # if not connection: + # return None - cursor = connection.cursor(dictionary=True) - try: - filename = f"PMC_Report_{pmc_no}.xlsx" + # cursor = connection.cursor(dictionary=True) - output_folder = FolderAndFile.get_download_folder() - output_file = FolderAndFile.get_download_path(filename) + # try: + # filename = f"PMC_Report_{pmc_no}.xlsx" - # ================= DATA FETCH ============= - contractor_info = ReportHelper.execute_sp(cursor, 'GetContractorDetailsByPMC', [pmc_no]) + # output_folder = FolderAndFile.get_download_folder() + # output_file = FolderAndFile.get_download_path(filename) - contractor_info = contractor_info[0] if contractor_info else None + # contractor_info = GeneralUse.execute_sp(cursor, 'GetContractorInfoByPmcNo', [pmc_no]) - if not contractor_info: - return None + # contractor_info = contractor_info[0] if contractor_info else None + # print("contractor_info:::",contractor_info) - hold_types = ReportHelper.execute_sp(cursor, 'GetHoldTypesByContractor',[contractor_info["Contractor_Id"]]) + # if not contractor_info: + # return None - hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types} + # hold_types = GeneralUse.execute_sp(cursor, 'GetHoldTypesByContractor',[contractor_info["Contractor_Id"]]) - invoices = ReportHelper.execute_sp(cursor, 'GetInvoicesAndGstReleaseByPmcNo', [pmc_no]) + # hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types} - credit_notes = ReportHelper.execute_sp(cursor, 'NewGetCreditNotesByPMCNo', [pmc_no]) + # invoices = GeneralUse.execute_sp(cursor, 'GetInvoicesByContractorOrPMCNo', [None,pmc_no]) - hold_amounts = ReportHelper.execute_sp(cursor, 'GetHoldAmountsByContractor',[contractor_info["Contractor_Id"]]) + # credit_notes = GeneralUse.execute_sp(cursor, 'NewGetCreditNotesByPMCNo', [pmc_no]) + # credit_note_map = {} + # for cn in credit_notes: + + # key = (str(cn['PMC_No']).strip()) + # credit_note_map.setdefault(key, []).append(cn) - gst_releases = ReportHelper.execute_sp(cursor, 'GetGSTReleaseDetailsByPMC', [pmc_no]) + # hold_amounts = GeneralUse.execute_sp(cursor, 'GetHoldAmountsByContractor', [contractor_info["Contractor_Id"]]) - # ================= DATA MAPPING ================= - hold_data = {} - for h in hold_amounts: - hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount'] + # gst_releases = GeneralUse.execute_sp(cursor, 'GetGSTReleaseDetailsByPMC', [pmc_no]) + # gst_release_map = {} + # for gr in gst_releases: + # key = (str(gr['PMC_No']).strip()) + # gst_release_map.setdefault(key, []).append(gr) - credit_note_map = {} - for cn in credit_notes: - pmc = cn.get("PMC_No") - if pmc: - credit_note_map.setdefault(pmc, []).append(cn) - - gst_map = {} - for gst in gst_releases: - pmc = gst.get("PMC_No") - if pmc: - gst_map.setdefault(pmc, []).append(gst) + # # ================= DATA MAPPING ================= + # hold_data = {} + # for h in hold_amounts: + # hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount'] - # ================= LOG ================= - LogHelper.log_action("Download PMC Report",f"User {current_user.id} Download PMC Report '{pmc_no}'") + # # ================= LOG ================= + # LogHelper.log_action("Download PMC Report",f"User {current_user.id} Download PMC Report '{pmc_no}'") - # ================= EXCEL ================= - workbook = openpyxl.Workbook() - sheet = workbook.active - sheet.title = "PMC Report" + # ReportHelper.generate_excel( + # 0, contractor_info, invoices, hold_types, hold_data, + # credit_note_map,gst_release_map, output_file) + + # return output_folder, filename - # HEADER INFO - sheet.append(["", "", "Laxmi Civil Engineering Services PVT. LTD."]) - sheet.append(["Contractor Name", contractor_info["Contractor_Name"]]) - sheet.append(["State", contractor_info["State_Name"]]) - sheet.append(["District", contractor_info["District_Name"]]) - sheet.append(["Block", contractor_info["Block_Name"]]) - sheet.append([]) + # finally: + # cursor.close() + # connection.close() - base_headers = [ - "PMC No", "Village", "Work Type", "Invoice Details", - "Invoice Date", "Invoice No", "Basic Amount", "Debit", "After Debit Amount", - "GST", "Amount", "TDS", "SD", "On Commission", "Hydro Testing", "GST SD Amount" - ] - - hold_headers = [ht['hold_type'] for ht in hold_types] - payment_headers = ["Final Amount", "Payment Amount", "TDS Payment", "Total Paid", "UTR"] - - headers = base_headers + hold_headers + payment_headers - sheet.append(headers) - for cell in sheet[sheet.max_row]: - cell.font = Font(bold=True) - - # ================= INVOICE ROWS ================= - for inv in invoices: - row = [ - pmc_no, - inv.get("Village_Name", ""), - inv.get("Work_Type", ""), - inv.get("Invoice_Details", ""), - inv.get("Invoice_Date", ""), - inv.get("invoice_no", ""), - inv.get("Basic_Amount", ""), - inv.get("Debit_Amount", ""), - inv.get("After_Debit_Amount", ""), - inv.get("GST_Amount", ""), - inv.get("Amount", ""), - inv.get("TDS_Amount", ""), - inv.get("SD_Amount", ""), - inv.get("On_Commission", ""), - inv.get("Hydro_Testing", ""), - inv.get("GST_SD_Amount", "") - ] - - # HOLD DATA - invoice_holds = hold_data.get(inv.get("Invoice_Id"), {}) - for ht_id in hold_type_map.keys(): - row.append(invoice_holds.get(ht_id, "")) - - # PAYMENT DATA - row += [ - inv.get("Final_Amount", ""), - inv.get("Payment_Amount", ""), - inv.get("TDS_Payment_Amount", ""), - inv.get("Total_Amount", ""), - inv.get("UTR", "") - ] - - row += ["", ""] - - sheet.append(row) - # ================= CREDIT NOTE ROWS ================= - for pmc, cn_list in credit_note_map.items(): - for cn in cn_list: - cn_row = [ - pmc_no, - "", "", "Credit Note", - "", cn.get("Invoice_No", ""), - cn.get("Basic_Amount", ""), - "", "", "", "", "", "", "", "", "", "", "" - ] - cn_row += [""] * len(hold_headers) - cn_row += [ - cn.get("Final_Amount", ""), - cn.get("Total_Amount", ""), - cn.get("UTR", "") - ] - sheet.append(cn_row) - - # ================= GST RELEASE ROWS ================= - for gst in gst_releases: - gst_row = [ - gst.get("PMC_No", ""), - "", "", "GST Release Note", - "", gst.get("Invoice_No", ""), - gst.get("Basic_Amount", ""), - "", "", "", "", "", "", "", "", "" - ] - gst_row += [""] * len(hold_headers) - gst_row += [ - gst.get("Final_Amount", ""), - "", - "", - gst.get("Total_Amount", ""), - gst.get("UTR", "") - ] - sheet.append(gst_row) - - # ================= AUTO WIDTH ================= - for col in sheet.columns: - max_len = max((len(str(cell.value)) for cell in col if cell.value), default=0) - sheet.column_dimensions[col[0].column_letter].width = max_len + 2 - - workbook.save(output_file) - workbook.close() - return output_folder, filename - - except Exception as e: - print(f"Error generating PMC report: {e}") - return None - - finally: - cursor.close() - connection.close() diff --git a/model/Report.py b/model/Report.py index 0b86544..da92bb1 100644 --- a/model/Report.py +++ b/model/Report.py @@ -1,11 +1,11 @@ import config from datetime import datetime from flask import send_file -import os import openpyxl from openpyxl.styles import Font, PatternFill from model.FolderAndFile import FolderAndFile +from services.Generalservice import GeneralUse class ReportHelper: isSuccess = False @@ -17,30 +17,6 @@ class ReportHelper: self.resultMessage = "" self.data = [] - @staticmethod - def execute_sp(cursor, proc_name, params=[], fetch_one=False): - cursor.callproc(proc_name, params) - return ( - ReportHelper.fetch_one_result(cursor) - if fetch_one else - ReportHelper.fetch_all_results(cursor) - ) - - @staticmethod - def fetch_all_results(cursor): - data = [] - for result in cursor.stored_results(): - data = result.fetchall() - return data - - - @staticmethod - def fetch_one_result(cursor): - data = None - for result in cursor.stored_results(): - data = result.fetchone() - return data - @staticmethod def search_contractor(request): @@ -60,10 +36,7 @@ class ReportHelper: cursor = connection.cursor(dictionary=True) try: - data = ReportHelper.execute_sp( - cursor, - "search_contractor_info", - [ + data = GeneralUse.execute_sp(cursor,"search_contractor_info",[ subcontractor_name or None, pmc_no or None, state or None, @@ -72,8 +45,7 @@ class ReportHelper: village or None, year_from or None, year_to or None - ] - ) + ]) except Exception as e: print(f"Error in search_contractor: {e}") @@ -85,69 +57,6 @@ class ReportHelper: return data - - @staticmethod - def get_contractor_report(contractor_id): - connection = config.get_db_connection() - cursor = connection.cursor(dictionary=True, buffered=True) - - try: - # Contractor Info (only one fetch) - contInfo = ReportHelper.execute_sp(cursor, 'GetContractorInfo', [contractor_id], True) - # Hold Types - hold_types = ReportHelper.execute_sp(cursor, 'GetContractorHoldTypes', [contractor_id]) - # Invoices - invoices = ReportHelper.execute_sp(cursor, 'GetContractorInvoices', [contractor_id]) - # GST Release - gst_rel = ReportHelper.execute_sp(cursor, 'GetGSTRelease', [contractor_id]) - # Hold Release - hold_release = ReportHelper.execute_sp(cursor, 'GetHoldRelease', [contractor_id]) - # Credit Note - credit_note = ReportHelper.execute_sp(cursor, 'GetCreditNote', [contractor_id]) - # Payments - payments = ReportHelper.execute_sp(cursor, 'GetPayments', [contractor_id]) - - # Totals - total = { - "sum_invo_basic_amt": float(sum(row['Basic_Amount'] or 0 for row in invoices)), - "sum_invo_debit_amt": float(sum(row['Debit_Amount'] or 0 for row in invoices)), - "sum_invo_after_debit_amt": float(sum(row['After_Debit_Amount'] or 0 for row in invoices)), - "sum_invo_amt": float(sum(row['Amount'] or 0 for row in invoices)), - "sum_invo_gst_amt": float(sum(row['GST_Amount'] or 0 for row in invoices)), - "sum_invo_tds_amt": float(sum(row['TDS_Amount'] or 0 for row in invoices)), - "sum_invo_ds_amt": float(sum(row['SD_Amount'] or 0 for row in invoices)), - "sum_invo_on_commission": float(sum(row['On_Commission'] or 0 for row in invoices)), - "sum_invo_hydro_test": float(sum(row['Hydro_Testing'] or 0 for row in invoices)), - "sum_invo_gst_sd_amt": float(sum(row['GST_SD_Amount'] or 0 for row in invoices)), - "sum_invo_final_amt": float(sum(row['Final_Amount'] or 0 for row in invoices)), - "sum_invo_hold_amt": float(sum(row['hold_amount'] or 0 for row in invoices)), - - "sum_gst_basic_amt": float(sum(row['basic_amount'] or 0 for row in gst_rel)), - "sum_gst_final_amt": float(sum(row['final_amount'] or 0 for row in gst_rel)), - - "sum_pay_payment_amt": float(sum(row['Payment_Amount'] or 0 for row in payments)), - "sum_pay_tds_payment_amt": float(sum(row['TDS_Payment_Amount'] or 0 for row in payments)), - "sum_pay_total_amt": float(sum(row['Total_amount'] or 0 for row in payments)) - } - - current_date = datetime.now().strftime('%Y-%m-%d') - - finally: - cursor.close() - connection.close() - - return { - "contInfo": contInfo, - "invoices": invoices, - "hold_types": hold_types, - "gst_rel": gst_rel, - "payments": payments, - "credit_note": credit_note, - "hold_release": hold_release, - "total": total, - "current_date": current_date - } - @staticmethod def get_contractor_info(contractor_id): @@ -156,10 +65,11 @@ class ReportHelper: return contractor.contInfo if contractor.contInfo else None + # call this method for excel formate written @staticmethod def generate_excel(contractor_id, contInfo, invoices, hold_types, hold_data, credit_note_map, gst_release_map, output_file): - + workbook = openpyxl.Workbook() sheet = workbook.active sheet.title = "Contractor Report" @@ -196,8 +106,7 @@ class ReportHelper: inv["invoice_no"].replace(" ", "") if inv["invoice_no"] else "" if inv["invoice_no"] not in (None, "", 0) else "" - ) - + ) key = (pmc_no) # Yellow separator @@ -284,7 +193,13 @@ class ReportHelper: cn_row += [""] * len(hold_headers) - cn_row += [cn.get("Final_Amount", ""),"","",cn.get("Total_Amount", ""),cn.get("UTR", "")] + cn_row += [ + cn.get("Final_Amount", ""), + "", + "", + cn.get("Total_Amount", ""), + cn.get("UTR", "") + ] sheet.append(cn_row) @@ -294,53 +209,4 @@ class ReportHelper: workbook.save(output_file) - @staticmethod - def create_contractor_report(contractor_id): - fileName = f"Contractor_Report_{contractor_id}.xlsx" - output_file = FolderAndFile.get_download_path(filename=fileName) - - # Fetch Data - contInfo = ReportHelper.get_contractor_info(contractor_id) - if not contInfo: - return None, "No contractor found" - - connection = config.get_db_connection() - cursor = connection.cursor(dictionary=True, buffered=True) - - hold_types = ReportHelper.execute_sp(cursor, 'HoldTypesByContractorId', [contractor_id]) - invoices = ReportHelper.execute_sp(cursor, 'FetchInvoicesByContractor', [contractor_id]) - hold_amounts = ReportHelper.execute_sp(cursor, 'HoldAmountsByContractorId', [contractor_id]) - hold_data = {} - for h in hold_amounts: - hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount'] - - - # -------- Credit Note MAP -------- - credit_note_raw = ReportHelper.execute_sp(cursor, 'GetCreditNotesByContractor', [contractor_id]) - credit_note_map = {} - for cn in credit_note_raw: - key = ( - str(cn['PMC_No']).strip() - ) - credit_note_map.setdefault(key, []).append(cn) - - # -------- GST MAP -------- - gst_release_raw = ReportHelper.execute_sp(cursor, 'GstReleasesByContractorId', [contractor_id]) - gst_release_map = {} - for gr in gst_release_raw: - key = ( - str(gr['PMC_No']).strip() - ) - gst_release_map.setdefault(key, []).append(gr) - - # Generate Excel - ReportHelper.generate_excel( - contractor_id, contInfo, invoices, hold_types, hold_data, - credit_note_map, gst_release_map, output_file - ) - - return output_file, None - - - diff --git a/model/Utilities.py b/model/Utilities.py index 4bc4262..d6e352a 100644 --- a/model/Utilities.py +++ b/model/Utilities.py @@ -9,10 +9,11 @@ class ItemCRUDType(Enum): HoldType = 5 Subcontractor = 6 GSTRelease = 7 + Invoice = 8 class RegEx: - patternAlphabetOnly = "^[A-Za-z ]+$" - allPattern = "^(?!\s*$).+" + patternAlphabetOnly = r"^[A-Za-z ]+$" + allPattern = r"^(?!\s*$).+" class ResponseHandler: diff --git a/services/Generalservice.py b/services/Generalservice.py new file mode 100644 index 0000000..8e698cc --- /dev/null +++ b/services/Generalservice.py @@ -0,0 +1,30 @@ + + + +class GeneralUse: + data=[] + + @staticmethod + def execute_sp(cursor, proc_name, params=[], fetch_one=False): + cursor.callproc(proc_name, params) + return ( + GeneralUse.fetch_one_result(cursor) + if fetch_one else + GeneralUse.fetch_all_results(cursor) + ) + + @staticmethod + def fetch_all_results(cursor): + data = [] + for result in cursor.stored_results(): + data = result.fetchall() + return data + + + @staticmethod + def fetch_one_result(cursor): + data = None + for result in cursor.stored_results(): + data = result.fetchone() + return data + diff --git a/services/ReportService.py b/services/ReportService.py new file mode 100644 index 0000000..5c0ce37 --- /dev/null +++ b/services/ReportService.py @@ -0,0 +1,177 @@ +import config + +from model.FolderAndFile import FolderAndFile +from services.Generalservice import GeneralUse +from model.Report import ReportHelper + +from decimal import Decimal +def safe_decimal(value): + if value is None: + return Decimal(0) + return Decimal(value) + + +class ReportService: + + + def __init__(self, contractor_id=None, pmc_no=None): + self.contractor_id = contractor_id + self.pmc_no = pmc_no + + self.contInfo = None + self.hold_types = [] + self.invoices = [] + + self.hold_amounts = [] + self.hold_data = {} + + self.credit_note_raw = [] + self.credit_note_map = {} + + self.gst_release_raw = [] + self.gst_release_map = {} + + self.output_file = None + + # ---------------- LOAD DATA ---------------- + def load_data(self): + connection = config.get_db_connection() + cursor = connection.cursor(dictionary=True, buffered=True) + + try: + # ---------- CONTRACTOR ---------- + if self.contractor_id: + self.contInfo = GeneralUse.execute_sp(cursor, 'GetContractorInfo', [self.contractor_id], True) + self.hold_types = GeneralUse.execute_sp(cursor, 'HoldTypesByContractorId', [self.contractor_id]) + self.invoices = GeneralUse.execute_sp(cursor, 'GetInvoicesByContractorOrPMCNo', [self.contractor_id, None]) + + # ---------- PMC ---------- + elif self.pmc_no: + self.contInfo = GeneralUse.execute_sp(cursor, 'GetContractorInfoByPmcNo', [self.pmc_no], True) + self.contractor_id = self.contInfo["Contractor_Id"] + + self.hold_types = GeneralUse.execute_sp(cursor, 'GetHoldTypesByContractor', [self.contractor_id]) + self.invoices = GeneralUse.execute_sp(cursor, 'GetInvoicesByContractorOrPMCNo', [None, self.pmc_no]) + + # ---------- COMMON ---------- + self.hold_amounts = GeneralUse.execute_sp(cursor, 'GetHoldAmountsByContractor', [self.contractor_id]) + self.credit_note_raw = GeneralUse.execute_sp(cursor, 'GetCreditNotesByContractor', [self.contractor_id]) + self.gst_release_raw = GeneralUse.execute_sp(cursor, 'GetGSTRelease', [self.contractor_id]) + + + self.prepare_maps() + self.total = self.calculate_totals() + + finally: + cursor.close() + connection.close() + + return self + + # ---------------- MAPS ---------------- + def prepare_maps(self): + # HOLD MAP + for h in self.hold_amounts: + self.hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount'] + + # CREDIT MAP + for cn in self.credit_note_raw: + key = str(cn.get('PMC_No') or cn.get('pmc_no')).strip() + self.credit_note_map.setdefault(key, []).append(cn) + + # GST MAP (FIXED) + for gr in self.gst_release_raw: + pmc_value = gr.get('PMC_No') or gr.get('pmc_no') or gr.get('PMC_NO') + + if not pmc_value: + continue # skip if missing + + key = str(pmc_value).strip() + self.gst_release_map.setdefault(key, []).append(gr) + + # ---------------- calculate total ---------------- + def calculate_totals(self): + total = { + "sum_invo_basic_amt": Decimal(0), + "sum_invo_debit_amt": Decimal(0), + "sum_invo_after_debit_amt": Decimal(0), + "sum_invo_gst_amt": Decimal(0), + "sum_invo_amt": Decimal(0), + "sum_invo_tds_amt": Decimal(0), + "sum_invo_ds_amt": Decimal(0), + "sum_invo_on_commission": Decimal(0), + "sum_invo_hydro_test": Decimal(0), + "sum_invo_hold_amt": Decimal(0), + "sum_invo_gst_sd_amt": Decimal(0), + "sum_invo_final_amt": Decimal(0), + + "sum_gst_basic_amt": Decimal(0), + "sum_gst_final_amt": Decimal(0), + + "sum_pay_payment_amt": Decimal(0), + "sum_pay_tds_payment_amt": Decimal(0), + "sum_pay_total_amt": Decimal(0) + } + + # ---------- INVOICE ---------- + for inv in self.invoices: + total["sum_invo_basic_amt"] += safe_decimal(inv.get("Basic_Amount")) + total["sum_invo_debit_amt"] += safe_decimal(inv.get("Debit_Amount")) + total["sum_invo_after_debit_amt"] += safe_decimal(inv.get("After_Debit_Amount")) + total["sum_invo_gst_amt"] += safe_decimal(inv.get("GST_Amount")) + total["sum_invo_amt"] += safe_decimal(inv.get("Amount")) + total["sum_invo_tds_amt"] += safe_decimal(inv.get("TDS_Amount")) + total["sum_invo_ds_amt"] += safe_decimal(inv.get("SD_Amount")) + total["sum_invo_on_commission"] += safe_decimal(inv.get("On_Commission")) + total["sum_invo_hydro_test"] += safe_decimal(inv.get("Hydro_Testing")) + total["sum_invo_gst_sd_amt"] += safe_decimal(inv.get("GST_SD_Amount")) + total["sum_invo_final_amt"] += safe_decimal(inv.get("Final_Amount")) + total["sum_invo_hold_amt"] += safe_decimal(inv.get("hold_amount")) + + # ---------- GST ---------- + for gst in self.gst_release_raw: + total["sum_gst_basic_amt"] += safe_decimal(gst.get("basic_amount")) + total["sum_gst_final_amt"] += safe_decimal(gst.get("final_amount")) + + # ---------- PAYMENTS ---------- + if hasattr(self, "payments"): + for pay in self.payments: + total["sum_pay_payment_amt"] += safe_decimal(pay.get("Payment_Amount")) + total["sum_pay_tds_payment_amt"] += safe_decimal(pay.get("TDS_Payment_Amount")) + total["sum_pay_total_amt"] += safe_decimal(pay.get("Total_amount")) + + return total + + + # ---------------- WEB DATA ---------------- + def get_web_data(self): + return { + "contInfo": self.contInfo, + "invoices": self.invoices, + "hold_types": self.hold_types, + "credit_note": self.credit_note_raw, + "gst_rel": self.gst_release_raw, + "total": self.total + } + + # ---------------- DOWNLOAD ---------------- + def download_excel(self): + + if not self.contInfo: + return None, "No data found" + + filename = f"Report_{self.contractor_id or self.pmc_no}.xlsx" + self.output_file = FolderAndFile.get_download_path(filename=filename) + + ReportHelper.generate_excel( + self.contractor_id or 0, + self.contInfo, + self.invoices, + self.hold_types, + self.hold_data, + self.credit_note_map, + self.gst_release_map, + self.output_file + ) + + return self.output_file, None \ No newline at end of file diff --git a/static/images/icons/male_profile.jpg b/static/images/icons/male_profile.jpg new file mode 100644 index 0000000..5030590 Binary files /dev/null and b/static/images/icons/male_profile.jpg differ diff --git a/static/js/searchContractor.js b/static/js/searchContractor.js index bb0251c..38e03fe 100644 --- a/static/js/searchContractor.js +++ b/static/js/searchContractor.js @@ -1,43 +1,57 @@ -$(document).ready(function () { - function fetchResults() { - let formData = $('#search-form').serialize(); +document.addEventListener("DOMContentLoaded", function () { - $.ajax({ - type: 'POST', - url: '/search_contractor', - data: formData, - success: function (data) { - let tableBody = $('#result-table tbody'); - tableBody.empty(); + const form = document.getElementById("search-form"); + const tableBody = document.querySelector("#result-table tbody"); - if (data.length === 0) { - tableBody.append('No data found'); - } else { - data.forEach(function (row) { - tableBody.append(` - - ${row.Contractor_Name} - ${row.PMC_No} - ${row.State_Name} - ${row.District_Name} - ${row.Block_Name} - ${row.Village_Name} - - `); - }); - } - }, - error: function (xhr) { - alert(xhr.responseJSON.error); - } + function fetchData(page = 1) { + const formData = new FormData(form); + formData.append("page", page); + + fetch("/search_contractor", { + method: "POST", + body: formData + }) + .then(res => res.json()) + .then(res => { + tableBody.innerHTML = ""; + + res.data.forEach(row => { + + const tr = document.createElement("tr"); + + tr.innerHTML = ` + + ${row.Contractor_Name} + + + ${row.PMC_No} + + ${row.State_Name} + ${row.District_Name} + ${row.Block_Name} + ${row.Village_Name} + `; + + tableBody.appendChild(tr); + }); }); + } + + // Auto search + form.addEventListener("input", () => fetchData()); + + // Click Contractor + document.addEventListener("click", function (e) { + if (e.target.classList.contains("contractor-link")) { + const id = e.target.dataset.id; + window.location.href = `/contractor_report/${id}`; } - $('#search-form input').on('keyup change', function () { - fetchResults(); - }); + if (e.target.classList.contains("pmc-link")) { + const pmc = e.target.dataset.pmc; + window.location.href = `/pmc_report/${pmc}`; + } }); -window.onload = function () { - document.getElementById('subcontractor_name').focus(); - }; \ No newline at end of file + fetchData(); +}); \ No newline at end of file diff --git a/templates/pmc_report.html b/templates/pmc_report.html index f80ebae..23f3c0f 100644 --- a/templates/pmc_report.html +++ b/templates/pmc_report.html @@ -1,7 +1,6 @@ - - {% extends 'base.html' %} {% block content %} + @@ -9,332 +8,337 @@ + -
-

PMC Report

+
+

PMC Report

-
-

Contractor Details

-
-
- - +
+

Contractor Details

+
+
+ + +
+
+ + +
-
- - +
+
+ + +
+
+ + +
+
+ + +
-
-
-
- - -
-
- - -
-
- - -
-
-
-
- - +
+
+ + +
+
+ + +
-
- - +

PMC Report for PMC No: {{ contInfo.PMC_No}}

+
+
+ + +
+
+ + +
+
+ + +
-
-

PMC Report for PMC No: {{ info.PMC_No}}

-
-
- - -
-
- - -
-
- - -
-
-
-
- - -
-
- - +
+
+ + +
+
+ + +
-
-

Invoice Details

- - - - - - - - - - - - - - - - - - +

Invoice Details

+
PMC NoVillage NameWork TypeInvoice DetailsInvoice DateInvoice NoBasic AmountDebitAfter Debit AmtGST (18%)AmountTDS (1%)SD (5%)On CommissionHydro Testing
+ + + + + + + + + + + + + + + + + - - {% set hold_types = invoices | map(attribute='hold_type') | reject('none') | unique | list %} - {% for hold in hold_types %} - - {% endfor %} + + {% set hold_types = invoices | map(attribute='hold_type') | reject('none') | unique | list %} + {% for hold in hold_types %} + + {% endfor %} - - - - - - {% if invoices %} - {% for invoice in invoices %} - - - - - - - - - - - - - - - - + + + + + + {% if invoices %} + {% for invoice in invoices %} + + + + + + + + + + + + + + + + + + + {% for hold in hold_types %} + + {% endfor %} + + + + + + {% endfor %} + + + + + + + + + + + + {% set hold_types = invoices | map(attribute='hold_type') | unique | list %} + {% for hold in hold_types %} + + {% endfor %} + + + - - {% for hold in hold_types %} - + + {% endif %} - - {% endfor %} + +
PMC NoVillage NameWork TypeInvoice DetailsInvoice DateInvoice NoBasic AmountDebitAfter Debit AmtGST (18%)AmountTDS (1%)SD (5%)On CommissionHydro Testing{{ hold }}{{ hold }}GST SD (18%)Final Amount
{{ invoice.PMC_No }}{{ invoice.Village_Name.capitalize() if invoice.Village_Name else '' }}{{ invoice.Work_Type }}{{ invoice.Invoice_Details }}{{ invoice.Invoice_Date }}{{ invoice.Invoice_No }}{{ invoice.Basic_Amount }}{{ invoice.Debit_Amount }}{{ invoice.After_Debit_Amount }}{{ invoice.GST_Amount }}{{ invoice.Amount }}{{ invoice.TDS_Amount }}{{ invoice.SD_Amount }}{{ invoice.On_Commission }}{{ invoice.Hydro_Testing }}GST SD (18%)Final Amount
{{ invoice.PMC_No }}{{ invoice.Village_Name.capitalize() if invoice.Village_Name else '' }}{{ invoice.Work_Type }}{{ invoice.Invoice_Details }}{{ invoice.Invoice_Date }}{{ invoice.Invoice_No }}{{ invoice.Basic_Amount }}{{ invoice.Debit_Amount }}{{ invoice.After_Debit_Amount }}{{ invoice.GST_Amount }}{{ invoice.Amount }}{{ invoice.TDS_Amount }}{{ invoice.SD_Amount }}{{ invoice.On_Commission }}{{ invoice.Hydro_Testing }} + {% if invoice.hold_type == hold %} + {{ invoice.hold_amount }} + {% else %} + 0 + {% endif %} + {{ invoice.GST_SD_Amount }}{{ invoice.Final_Amount }}
Total{{total["sum_invo_basic_amt"]}}{{total["sum_invo_debit_amt"]}}{{total["sum_invo_after_debit_amt"]}}{{total["sum_invo_gst_amt"]}}{{total["sum_invo_amt"]}}{{total["sum_invo_tds_amt"]}}{{total["sum_invo_ds_amt"]}}{{total["sum_invo_on_commission"]}}{{total["sum_invo_hydro_test"]}}{{total["sum_invo_hold_amt"]}}{{total["sum_invo_gst_sd_amt"]}}{{total["sum_invo_final_amt"]}}
- {% if invoice.hold_type == hold %} - {{ invoice.hold_amount }} {% else %} - 0 +
No invoices found.
+

Hold Release

+ + + + + + + + + + + + + {%if hold_release%} + {%for hold in hold_release%} + + + + + + + + + {%endfor%} + {%else%} + + + + {%endif%} + +
PMC NoInvoice NoInvoice DetailsBasic AmountTotal AmountUTR
{{ hold['PMC_No'] }}{{ hold['Invoice_No'] }}{{ hold['Invoice_Details'] }}{{ hold['Basic_Amount'] }}{{ hold['Total_Amount'] }}{{ hold['UTR'] }}
No data present
- {{ invoice.GST_SD_Amount }} - {{ invoice.Final_Amount }} - +
+

GST Release Note Details

+ + + + + + + + + + + + + {% if gst_rel %} + {% for gst in gst_rel %} + + + + + + + + + {% endfor %} + + - {% endfor %} - - - - - - - - - - - - {% set hold_types = invoices | map(attribute='hold_type') | unique | list %} - {% for hold in hold_types %} - - {% endfor %} - - - + + + + {% else %} + + + + {% endif %} + +
PMC NoInvoice NoBasic AmountFinal AmountTotal_AmountUTR
{{ gst.pmc_no }}{{ gst.Invoice_No }}{{ gst.Basic_Amount }}{{ gst.Final_Amount }}{{ gst.Total_Amount }}{{ gst.UTR }}
Total
Total{{total["sum_invo_basic_amt"]}}{{total["sum_invo_debit_amt"]}}{{total["sum_invo_after_debit_amt"]}}{{total["sum_invo_gst_amt"]}}{{total["sum_invo_amt"]}}{{total["sum_invo_tds_amt"]}}{{total["sum_invo_ds_amt"]}}{{total["sum_invo_on_commission"]}}{{total["sum_invo_hydro_test"]}}{{total["sum_invo_hold_amt"]}}{{total["sum_invo_gst_sd_amt"]}}{{total["sum_invo_final_amt"]}}
{{total["sum_gst_basic_amt"]}}{{total["sum_gst_final_amt"]}}
No GST release found.
- {% else %} - No invoices found. - - {% endif %} - - -

Hold Release

- - - - - - - - - - - - - {%if hold_release%} - {%for hold in hold_release%} - - - - - - - - - {%endfor%} - {%else%} - - - - {%endif%} - -
PMC NoInvoice NoInvoice DetailsBasic AmountTotal AmountUTR
{{ hold['PMC_No'] }}{{ hold['Invoice_No'] }}{{ hold['Invoice_Details'] }}{{ hold['Basic_Amount'] }}{{ hold['Total_Amount'] }}{{ hold['UTR'] }}
No data present
- -
-

GST Release Note Details

- - - - - - - - - - - {% if gst_rel %} - {% for gst in gst_rel %} - - - - - - - {% endfor %} - - - - - - - {% else %} - - - - {% endif %} - -
PMC NoInvoice NoBasic AmountFinal Amount
{{ gst.pmc_no }}{{ gst.invoice_no }}{{ gst.basic_amount }}{{ gst.final_amount }}
Total{{total["sum_gst_basic_amt"]}}{{total["sum_gst_final_amt"]}}
No GST release found.
- -

Credit Details

- - - - - - - - - - - - + + + + + + + + + + + + - {% if credit_note %} - {% for credit in credit_note %} - - - - - - - - - - - - + {% if credit_note %} + {% for credit in credit_note %} + + + + + + + + + + + + - - {% endfor %} + + {% endfor %} - {% else %} - - - - {% endif %} + {% else %} + + + + {% endif %} - +
PMC NoInvoice DetailsBasic AmountDebitAfter Debit AmtGST AmountAmountFinal AmountPayment AmountTotal AmountUTR
PMC NoInvoice DetailsBasic AmountDebitAfter Debit AmtGST AmountAmountFinal AmountPayment AmountTotal AmountUTR
{{ credit["PMC_No"] }}{{ credit["Invoice_Details"] }}{{ credit["Basic_Amount"] }}{{ credit["Debit_Amount"] }}{{ credit["After_Debit_Amount"] }}{{ credit["GST_Amount"] }}{{ credit["Amount"] }}{{ credit["Final_Amount"] }}{{ credit["Payment_Amount"] }}{{ credit["Total_Amount"] }}{{ credit["UTR"] }}
{{ credit["PMC_No"] }}{{ credit["Invoice_Details"] }}{{ credit["Basic_Amount"] }}{{ credit["Debit_Amount"] }}{{ credit["After_Debit_Amount"] }}{{ credit["GST_Amount"] }}{{ credit["Amount"] }}{{ credit["Final_Amount"] }}{{ credit["Payment_Amount"] }}{{ credit["Total_Amount"] }}{{ credit["UTR"] }}
No Credit note found.
No Credit note found.
-
-

Payment Details

- - - - - - - - - - - - - {% if payments %} - {% for pay in payments %} - - - - - - - - - {% endfor %} - - - - - - - - {% else %} +
+

Payment Details

+
PMC NoInvoice NoAmountTDS Amount @ 1% on BASIC AMOUNTTotal Amount PaidUTR
{{ pay.pmc_no }}{{ pay.invoice_no }}{{ pay.Payment_Amount }}{{ pay.TDS_Payment_Amount }}{{ pay.Total_amount }}{{ pay.utr}}
Total{{total["sum_pay_payment_amt"]}}{{total["sum_pay_tds_payment_amt"]}}{{total["sum_pay_total_amt"]}}
+ + + + + + + + + + + + {% if invoices %} + {% for pay in invoices %} + + + + + + + + + {% endfor %} + + + + + + + + {% else %} - - - - {% endif %} + + + + {% endif %} - -
PMC NoInvoice NoAmountTDS Amount @ 1% on BASIC AMOUNTTotal Amount PaidUTR
{{ pay.PMC_No }}{{ pay.invoice_no }}{{ pay.Payment_Amount }}{{ pay.TDS_Payment_Amount }}{{ pay.Total_Amount }}{{ pay.UTR}}
Total{{total["sum_pay_payment_amt"]}}{{total["sum_pay_tds_payment_amt"]}}{{total["sum_pay_total_amt"]}}
No payment found.
No payment found.
+ + - - - + + + {% endblock %} \ No newline at end of file diff --git a/templates/report.html b/templates/report.html index de53ef8..e0e744b 100644 --- a/templates/report.html +++ b/templates/report.html @@ -1,5 +1,6 @@ {% extends 'base.html' %} {% block content %} + @@ -7,102 +8,104 @@ + -
-

Search Contractor Report

-
-
-
-
- - +
+

Search Contractor Report

+
+ +
+
+ + +
+
+ + +
-
- - +
+
+ + +
+
+ + +
-
-
-
- - +
+
+ + +
+
+ + +
-
- - +
+
+ + +
+
+ + +
-
-
-
- - -
-
- - -
-
-
-
- - -
-
- - -
-
- + + -

Contractor List

- - - - - - - - - - - - - - -
Contractor Name - - PMC NoState - - District - - Block - - Village - -
+

Contractor List

+ + + + + + + + + + + + + + +
Contractor Name + + PMC NoState + + District + + Block + + Village + +
+
-
{% endblock %} \ No newline at end of file diff --git a/templates/show_excel_file.html b/templates/show_excel_file.html index 19b8903..ee380e6 100644 --- a/templates/show_excel_file.html +++ b/templates/show_excel_file.html @@ -58,8 +58,9 @@ - - + + + diff --git a/templates/subcontractor_report.html b/templates/subcontractor_report.html index e1f5001..c08d677 100644 --- a/templates/subcontractor_report.html +++ b/templates/subcontractor_report.html @@ -1,8 +1,6 @@ - - - {% extends 'base.html' %} {% block content %} + @@ -10,363 +8,343 @@ + -
-

Contractor Report

+
+

Contractor Report

-
-

Contractor Details

-
-
- - +
+

Contractor Details

+
+
+ + +
+
+ + +
-
- - +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
-
-
- - -
-
- - -
-
- - -
-
-
-
- - - -
-
- - -
-
-
-
- - -
-
- - -
-
- - -
-
-
- -

Total

- - - - - - - - - - - - - {% if hold_types %} - - {% for hold in hold_types %} - - - {% endfor %} - - {% endif %} - - - - -
{{current_date}}
Advance / Suplus{{total["sum_invo_final_amt"]+total["sum_gst_final_amt"]-total["sum_pay_total_amt"]}}
{{ hold.hold_type }}{{total["sum_invo_hold_amt"]}}
Amount With TDS{{total["sum_invo_tds_amt"]}}
- - - - - - - - - -

Invoice Details

- - - - - - - - - - - - - - - - - - + + + + + + + + - - {% set hold_types = invoices | map(attribute='hold_type') | unique | list %} - {% for hold in hold_types %} - - {% endfor %} - - - - - - {% if invoices %} - {% for invoice in invoices %} - - - - - - - - - - - - - - - - +

Invoice Details

+
PMC NoVillage NameWork TypeInvoice DetailsInvoice DateInvoice NoBasic AmountDebitAfter Debit AmtGST (18%)AmountTDS (1%)SD (5%)On CommissionHydro Testing{{ hold }}GST SD (18%)Final Amount
{{ invoice.PMC_No }}{{ invoice.Village_Name.capitalize() }}{{ invoice.Work_Type }}{{ invoice.Invoice_Details }}{{ invoice.Invoice_Date }}{{ invoice.Invoice_No }}{{ invoice.Basic_Amount }}{{ invoice.Debit_Amount }}{{ invoice.After_Debit_Amount }}{{ invoice.GST_Amount }}{{ invoice.Amount }}{{ invoice.TDS_Amount }}{{ invoice.SD_Amount }}{{ invoice.On_Commission }}{{ invoice.Hydro_Testing }}
+ + + + + + + + + + + + + + + + + + + + {% set hold_types = invoices | map(attribute='hold_type') | unique | list %} + {% for hold in hold_types %} + + {% endfor %} + + + + + + + {% if invoices %} + {% for invoice in invoices %} + + + + + + + + + + + + + + + + + + + {% set hold_types = invoices | map(attribute='hold_type') | unique | list %} + {% for hold in hold_types %} + + {% endfor %} + + + + + + {% endfor %} + + + + + + + + + + + + + + {% set hold_types = invoices | map(attribute='hold_type') | unique | list %} + {% for hold in hold_types %} + + {% endfor %} + + + + - - {% set hold_types = invoices | map(attribute='hold_type') | unique | list %} - {% for hold in hold_types %} - + + {% endif %} - - {% endfor %} + +
PMC NoVillage NameWork TypeInvoice DetailsInvoice DateInvoice NoBasic AmountDebitAfter Debit AmtGST (18%)AmountTDS (1%)SD (5%)On CommissionHydro Testing{{ hold }}GST SD (18%)Final Amount
{{ invoice.PMC_No }}{{ invoice.Village_Name}}{{ invoice.Work_Type }}{{ invoice.Invoice_Details }}{{ invoice.Invoice_Date }}{{ invoice.Invoice_No }}{{ invoice.Basic_Amount }}{{ invoice.Debit_Amount }}{{ invoice.After_Debit_Amount }}{{ invoice.GST_Amount }}{{ invoice.Amount }}{{ invoice.TDS_Amount }}{{ invoice.SD_Amount }}{{ invoice.On_Commission }}{{ invoice.Hydro_Testing }} + {% if invoice.hold_type == hold %} + {{ invoice.hold_amount }} + {% else %} + 0.00 + {% endif %} + {{ invoice.GST_SD_Amount }}{{ invoice.Final_Amount }}
Total{{total["sum_invo_basic_amt"]}}{{total["sum_invo_debit_amt"]}}{{total["sum_invo_after_debit_amt"]}}{{total["sum_invo_gst_amt"]}}{{total["sum_invo_amt"]}}{{total["sum_invo_tds_amt"]}}{{total["sum_invo_ds_amt"]}}{{total["sum_invo_on_commission"]}}{{total["sum_invo_hydro_test"]}}{{total["sum_invo_hold_amt"]}}{{total["sum_invo_gst_sd_amt"]}}{{total["sum_invo_final_amt"]}}
- {% if invoice.hold_type == hold %} - {{ invoice.hold_amount }} {% else %} - 0.00 +
No invoices found.
- {{ invoice.GST_SD_Amount }} - {{ invoice.Final_Amount }} - +

Hold Release

+ + + + + + + + + + + + + {% if hold_release %} + {% for hold in hold_release %} + + + + + + + + + {% endfor %} + {% else %} + + + + {% endif %} + +
PMC NoInvoice NoInvoice DetailsBasic AmountTotal AmountUTR
{{ hold['PMC_No'] }}{{ hold['Invoice_No'] }}{{ hold['Invoice_Details'] }}{{ hold['Basic_Amount'] }}{{ hold['Total_Amount'] }}{{ hold['UTR'] }}
No data present
+
- {% endfor %} - Total - {{total["sum_invo_basic_amt"]}} - {{total["sum_invo_debit_amt"]}} - {{total["sum_invo_after_debit_amt"]}} - {{total["sum_invo_gst_amt"]}} - {{total["sum_invo_amt"]}} - {{total["sum_invo_tds_amt"]}} - {{total["sum_invo_ds_amt"]}} - {{total["sum_invo_on_commission"]}} - {{total["sum_invo_hydro_test"]}} - - {% set hold_types = invoices | map(attribute='hold_type') | unique | list %} - {% for hold in hold_types %} - {{total["sum_invo_hold_amt"]}} - {% endfor %} - - {{total["sum_invo_gst_sd_amt"]}} - {{total["sum_invo_final_amt"]}} +

Credit Details

+ + + + + + + + + + + + + + - {% else %} - - - - {% endif %} - -
PMC NoInvoice DetailsBasic AmountDebitAfter Debit AmtGST AmountAmountFinal AmountPayment AmountTotal AmountUTR
No invoices found.
+ -

Hold Release

- - - - - - - - - - - - - {% if hold_release %} - {% for hold in hold_release %} - - - - - - - - - {% endfor %} - {% else %} - - - - {% endif %} - -
PMC NoInvoice NoInvoice DetailsBasic AmountTotal AmountUTR
{{ hold['PMC_No'] }}{{ hold['Invoice_No'] }}{{ hold['Invoice_Details'] }}{{ hold['Basic_Amount'] }}{{ hold['Total_Amount'] }}{{ hold['UTR'] }}
No data present
-
+ {% if credit_note %} + {% for credit in credit_note %} + + {{ credit["PMC_No"] }} + {{ credit["Invoice_Details"] }} + {{ credit["Basic_Amount"] }} + {{ credit["Debit_Amount"] }} + {{ credit["After_Debit_Amount"] }} + {{ credit["GST_Amount"] }} + {{ credit["Amount"] }} + {{ credit["Final_Amount"] }} + {{ credit["Payment_Amount"] }} + {{ credit["Total_Amount"] }} + {{ credit["UTR"] }} - -

Credit Details

- - - - - - - - - - - - - - - + + {% endfor %} - - - {% if credit_note %} - {% for credit in credit_note %} - - - - - - - - - - - - + {% else %} + + + + {% endif %} - - {% endfor %} - - {% else %} - - - - {% endif %} + +
PMC NoInvoice DetailsBasic AmountDebitAfter Debit AmtGST AmountAmountFinal AmountPayment AmountTotal AmountUTR
{{ credit["PMC_No"] }}{{ credit["Invoice_Details"] }}{{ credit["Basic_Amount"] }}{{ credit["Debit_Amount"] }}{{ credit["After_Debit_Amount"] }}{{ credit["GST_Amount"] }}{{ credit["Amount"] }}{{ credit["Final_Amount"] }}{{ credit["Payment_Amount"] }}{{ credit["Total_Amount"] }}{{ credit["UTR"] }}
No Credit note found.
No Credit note found.
+

GST Release Note Details

+ + + + + + + + + + - -
PMC NoInvoice NoBasic AmountFinal AmountTotal AmountUTR
-

GST Release Note Details

- - - - - - - - + + + {% if gst_rel %} + {% for gst in gst_rel %} + + + + + + + + + {% endfor %} + + + + + + + {% else %} + + + + {% endif %} + +
PMC NoInvoice NoBasic AmountFinal Amount
{{ gst.pmc_no }}{{ gst.Invoice_No }}{{ gst.Basic_Amount }}{{ gst.Final_Amount }}{{ gst.Total_Amount }}{{ gst.UTR }}
Total{{total["sum_gst_basic_amt"]}}{{total["sum_gst_final_amt"]}}
No GST release found.
- - - {% if gst_rel %} - {% for gst in gst_rel %} - - {{ gst.pmc_no }} - {{ gst.invoice_no }} - {{ gst.basic_amount }} - {{ gst.final_amount }} - - {% endfor %} - - Total +
+

Payment Details

+ + + + + + + + + + + + + {% if invoices %} + {% for pay in invoices %} + + + + + + + + + {% endfor %} - - - - {% else %} - - - - {% endif %} - -
PMC NoInvoice NoAmountTDS Amount @ 1% on BASIC AMOUNTTotal Amount PaidUTR
{{ pay.PMC_No }}{{ pay.invoice_no }}{{ pay.Payment_Amount }}{{ pay.TDS_Payment_Amount }}{{ pay.Total_Amount }}{{ pay.UTR}}
{{total["sum_gst_basic_amt"]}}{{total["sum_gst_final_amt"]}}
No GST release found.
+ + Total + {{total["sum_pay_payment_amt"]}} + {{total["sum_pay_tds_payment_amt"]}} + {{total["sum_pay_total_amt"]}} + + + {% else %} + + + No payment found. + + {% endif %} + + + -
-

Payment Details

- - - - - - - - - - - - - {% if payments %} - {% for pay in payments %} - - - - - - - - - {% endfor %} - - - - - - - - - {% else %} - - - - - {% endif %} - - -
PMC NoInvoice NoAmountTDS Amount @ 1% on BASIC AMOUNTTotal Amount PaidUTR
{{ pay.pmc_no }}{{ pay.invoice_no }}{{ pay.Payment_Amount }}{{ pay.TDS_Payment_Amount }}{{ pay.Total_amount }}{{ pay.utr}}
Total{{total["sum_pay_payment_amt"]}}{{total["sum_pay_tds_payment_amt"]}}{{total["sum_pay_total_amt"]}}
No payment found.
- - - Download Report -
+ Download + Report +
{% endblock %} \ No newline at end of file