pankaj-dev #20

Merged
pjpatil12 merged 2 commits from pankaj-dev into main 2026-04-03 06:43:43 +00:00
28 changed files with 505 additions and 700 deletions
Showing only changes of commit 0b72adef7d - Show all commits

View File

@@ -6,7 +6,6 @@ from model.Log import LogHelper
auth_bp = Blueprint('auth', __name__) auth_bp = Blueprint('auth', __name__)
@auth_bp.route('/login', methods=['GET', 'POST']) @auth_bp.route('/login', methods=['GET', 'POST'])
def login(): def login():

View File

@@ -152,19 +152,17 @@ def show_table(filename):
) )
# save Excel data # save Excel data
@excel_bp.route('/save_data', methods=['POST']) @excel_bp.route('/save_data', methods=['POST'])
def save_data(): def save_data():
# Extract form data # Extract form data
subcontractor_id = request.form.get("subcontractor_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") block_id = request.form.get("block_data")
variables = request.form.getlist('variables[]')
hold_columns = request.form.get("hold_columns") hold_columns = request.form.get("hold_columns")
hold_counter = request.form.get("hold_counter")
if not data: if not data:
return jsonify({"error": "No data provided to save"}), 400 return jsonify({"error": "No data provided to save"}), 400
if data: if data:
connection = config.get_db_connection() connection = config.get_db_connection()
cursor = connection.cursor() cursor = connection.cursor()
@@ -174,7 +172,7 @@ def save_data():
"PMC_No": entry.get("PMC_No"), "PMC_No": entry.get("PMC_No"),
"Invoice_Details": entry.get("Invoice_Details", ''), "Invoice_Details": entry.get("Invoice_Details", ''),
"Work_Type": 'none', "Work_Type": 'none',
"Invoice_Date": entry.get("Invoice_Date").strftime('%Y-%m-%d') if entry.get( "In oice_Date": entry.get("Invoice_Date").strftime('%Y-%m-%d') if entry.get(
"Invoice_Date") else None, "Invoice_Date") else None,
"Invoice_No": entry.get("Invoice_No", ''), "Invoice_No": entry.get("Invoice_No", ''),
"Basic_Amount": entry.get("Basic_Amount", 0.00), "Basic_Amount": entry.get("Basic_Amount", 0.00),
@@ -229,7 +227,6 @@ def save_data():
else: else:
work_type = " ".join(words[:work_pos + 1]) work_type = " ".join(words[:work_pos + 1])
if Invoice_Details and 'village' in Invoice_Details.lower() and 'work' in Invoice_Details.lower(): 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: if block_id and village_name:
village_id = None village_id = None
cursor.callproc("GetVillageId", (block_id, village_name)) cursor.callproc("GetVillageId", (block_id, village_name))
@@ -242,12 +239,7 @@ def save_data():
for result in cursor.stored_results(): for result in cursor.stored_results():
result = result.fetchone() result = result.fetchone()
village_id = result[0] if result else None 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 = ( args = (
PMC_No, village_id, work_type, Invoice_Details, Invoice_Date, Invoice_No, PMC_No, village_id, work_type, Invoice_Details, Invoice_Date, Invoice_No,
Basic_Amount, Debit_Amount, After_Debit_Amount, Amount, GST_Amount, TDS_Amount, Basic_Amount, Debit_Amount, After_Debit_Amount, Amount, GST_Amount, TDS_Amount,
@@ -255,22 +247,24 @@ def save_data():
subcontractor_id, 0 subcontractor_id, 0
) )
print("All invoice Details ",args)
results = cursor.callproc('SaveInvoice', args) results = cursor.callproc('SaveInvoice', args)
invoice_id = results[-1] invoice_id = results[-1]
print("invoice id from the excel ", invoice_id)
cursor.callproc("SavePayment",( PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount,Total_Amount, UTR,invoice_id))
if isinstance(hold_columns, str): if isinstance(hold_columns, str):
hold_columns = ast.literal_eval(hold_columns) hold_columns = ast.literal_eval(hold_columns)
if isinstance(hold_columns, list) and all(isinstance(hold, dict) for hold in hold_columns): if isinstance(hold_columns, list) and all(isinstance(hold, dict) for hold in hold_columns):
for hold in hold_columns: for hold in hold_columns:
print(f"Processing hold: {hold}")
hold_column_name = hold.get('column_name') # Get column name hold_column_name = hold.get('column_name')
hold_type_id = hold.get('hold_type_id') # Get hold_type_id hold_type_id = hold.get('hold_type_id')
if hold_column_name: if hold_column_name:
hold_amount = entry.get( hold_amount = entry.get(
hold_column_name) # Get the value for that specific hold column hold_column_name)
if hold_amount is not None: if hold_amount is not None:
print(f"Processing hold type: {hold_column_name}, Hold Amount: {hold_amount}")
hold_join_data = { hold_join_data = {
"Contractor_Id": subcontractor_id, "Contractor_Id": subcontractor_id,
"Invoice_Id": invoice_id, "Invoice_Id": invoice_id,
@@ -287,10 +281,9 @@ def save_data():
print(f"Invalid hold entry: {hold}") print(f"Invalid hold entry: {hold}")
else: else:
print("Hold columns data is not a valid list of dictionaries.") 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']): 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( cursor.callproc(
'AddCreditNoteFromExcel', 'AddCreditNoteFromExcel',
[ [
@@ -299,7 +292,7 @@ def save_data():
subcontractor_id, Invoice_No subcontractor_id, Invoice_No
] ]
) )
#-----------------------------------------------Hold Amount---------------------------------------------------------------------- #--------------------------Hold Amount-------------------------------------------------
# Step 1: Normalize Invoice_Details: lowercase, trim, remove extra spaces # Step 1: Normalize Invoice_Details: lowercase, trim, remove extra spaces
normalized_details = re.sub(r'\s+', ' ', Invoice_Details.strip()).lower() normalized_details = re.sub(r'\s+', ' ', Invoice_Details.strip()).lower()
# Step 2: Define lowercase keywords # Step 2: Define lowercase keywords
@@ -315,52 +308,57 @@ def save_data():
] ]
# Step 3: Matching condition # Step 3: Matching condition
if any(kw in normalized_details for kw in keywords): 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( cursor.callproc(
'AddHoldReleaseFromExcel', 'AddHoldReleaseFromExcel',
[PMC_No, Invoice_No, Invoice_Details, Basic_Amount, Final_Amount, UTR, subcontractor_id] [PMC_No, Invoice_No, Invoice_Details, Basic_Amount, Final_Amount, UTR, subcontractor_id]
) )
connection.commit() 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( elif Invoice_Details and any(
keyword in Invoice_Details.lower() for keyword in ['gst', 'release', 'note']): keyword in Invoice_Details.lower() for keyword in ['gst', 'release', 'gst release note']):
print("Gst rels :", PMC_No, Invoice_No, Basic_Amount, Final_Amount,Total_Amount,UTR, subcontractor_id) # print("Gst rels :", PMC_No, Invoice_No, Basic_Amount, Final_Amount,Total_Amount,UTR, subcontractor_id)
cursor.callproc( cursor.callproc(
'AddGSTReleaseFromExcel', 'AddGSTReleaseFromExcel',
[PMC_No, Invoice_No, Basic_Amount, Final_Amount, Total_Amount, UTR, subcontractor_id] [PMC_No, Invoice_No, Basic_Amount, Final_Amount, Total_Amount, UTR, subcontractor_id]
) )
if PMC_No and Total_Amount and UTR: # --------------------------------------
print("Payment :", PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR ) # If no village/work detected, only PMC/Payment
cursor.callproc("SavePayment",(PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR )) if not (Invoice_Details and 'village' in Invoice_Details.lower() and 'work' in Invoice_Details.lower()):
if not village_id: # ---------- Only PMC / Payment rows ----------
village_id = None if PMC_No and not Invoice_No and UTR :
cursor.callproc('InsertOrUpdateInPayment', (
PMC_No, cursor.execute(
village_id, """
work_type, INSERT INTO invoice (PMC_No,Contractor_Id) VALUES (%s, %s);
Invoice_Details, """,
Invoice_Date, (PMC_No, subcontractor_id)
Invoice_No, )
Basic_Amount, connection.commit()
Debit_Amount,
After_Debit_Amount, cursor.execute(
Amount, "SELECT invoice_id FROM invoice WHERE PMC_No=%s AND Contractor_Id =%s ORDER BY invoice_id DESC LIMIT 1",
GST_Amount, (PMC_No, subcontractor_id)
TDS_Amount, )
SD_Amount, row = cursor.fetchone()
On_Commission, invoice_id = row[0] if row else None
Hydro_Testing,
0, # insert payment
GST_SD_Amount, cursor.callproc(
Final_Amount, "SavePayment",
Payment_Amount, (
TDS_Payment_Amount, PMC_No,
Total_Amount, Invoice_No,
UTR, Payment_Amount,
subcontractor_id TDS_Payment_Amount,
)) Total_Amount,
UTR,
invoice_id
)
)
connection.commit() connection.commit()
return jsonify({"success": "Data saved successfully!"}), 200 return jsonify({"success": "Data saved successfully!"}), 200
except Exception as e: except Exception as e:
@@ -370,4 +368,3 @@ def save_data():
cursor.close() cursor.close()
connection.close() connection.close()
return render_template('index.html') return render_template('index.html')
# ---------------------- Report --------------------------------

View File

@@ -1,10 +1,10 @@
# routes/gst_release_routes.py
from flask import Blueprint, render_template, request, redirect, url_for, flash from flask import Blueprint, render_template, request, redirect, url_for, flash
from flask_login import login_required from flask_login import login_required
from model.gst_release import GSTRelease from model.gst_release import GSTRelease
from model.Log import LogHelper from model.Log import LogHelper
gst_release_bp = Blueprint('gst_release_bp', __name__) gst_release_bp = Blueprint('gst_release_bp', __name__)
gst_service = GSTRelease() gst_service = GSTRelease()
# ---------------- ADD GST RELEASE ---------------- # ---------------- ADD GST RELEASE ----------------

View File

@@ -14,7 +14,7 @@ def add_hold_type():
if request.method == 'POST': if request.method == 'POST':
hold.AddHoldType(request) 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")) return redirect(url_for("hold_types.add_hold_type"))
# GET request → show data # GET request → show data
@@ -42,10 +42,10 @@ def edit_hold_type(id):
hold = HoldTypes() hold = HoldTypes()
if request.method == 'POST': if request.method == 'POST':
hold.EditHoldType(request, id) # ✅ hold.EditHoldType(request, id)
return hold.resultMessage return hold.resultMessage
hold_data = hold.GetHoldTypeByID(id) # ✅ hold_data = hold.GetHoldTypeByID(id)
return render_template( return render_template(
"edit_hold_type.html", "edit_hold_type.html",
@@ -59,7 +59,7 @@ def edit_hold_type(id):
def delete_hold_type(id): def delete_hold_type(id):
hold = HoldTypes() hold = HoldTypes()
hold.DeleteHoldType(request, id) # ✅ hold.DeleteHoldType(request, id)
return redirect(url_for("hold_types.add_hold_type")) return redirect(url_for("hold_types.add_hold_type"))

View File

@@ -1,8 +1,3 @@
# controllers/invoice_controller.py
from flask import Blueprint, request, jsonify, render_template from flask import Blueprint, request, jsonify, render_template
from flask_login import login_required, current_user from flask_login import login_required, current_user
from model.Invoice import * from model.Invoice import *
@@ -83,7 +78,6 @@ def edit_invoice(invoice_id):
if request.method == 'POST': if request.method == 'POST':
data = request.form data = request.form
update_invoice(data, invoice_id) update_invoice(data, invoice_id)
update_inpayment(data)
log_action("Edit invoice", f"edited invoice '{invoice_id}'") log_action("Edit invoice", f"edited invoice '{invoice_id}'")
return jsonify({"status": "success", "message": "Invoice updated successfully"}), 200 return jsonify({"status": "success", "message": "Invoice updated successfully"}), 200

View File

@@ -28,8 +28,7 @@ def add_payment():
utr = request.form['utr'] utr = request.form['utr']
LogHelper.log_action("Add Payment", f"User {current_user.id} Add Payment '{pmc_no}'") LogHelper.log_action("Add Payment", f"User {current_user.id} Add Payment '{pmc_no}'")
Paymentmodel.insert_payment(pmc_no, invoice_no, amount, tds_amount, total_amount, utr) 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')) return redirect(url_for('payment_bp.add_payment'))
@@ -71,7 +70,6 @@ def edit_payment(payment_id):
LogHelper.log_action("Edit Payment", f"User {current_user.id} Edit Payment '{pmc_no}'") 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) Paymentmodel.call_update_payment_proc(payment_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr)
# Update inpayment
connection = Paymentmodel.get_connection() connection = Paymentmodel.get_connection()
cursor = connection.cursor() cursor = connection.cursor()
cursor.callproc( cursor.callproc(

View File

@@ -37,4 +37,5 @@ def download_pmc_report(pmc_no):
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)

View File

@@ -1,10 +1,9 @@
from flask import Blueprint, render_template, request, jsonify from flask import Blueprint, render_template, request, jsonify,send_file
from flask_login import login_required, current_user from flask_login import login_required, current_user
from model.Report import ReportHelper from model.Report import ReportHelper
from model.Log import LogHelper from model.Log import LogHelper
report_bp = Blueprint("report", __name__) report_bp = Blueprint("report", __name__)
@@ -46,8 +45,10 @@ def contractor_report(contractor_id):
# ---------------- Contractor Download Report by contractor id ---------------- # ---------------- Contractor Download Report by contractor id ----------------
@report_bp.route('/download_report/<int:contractor_id>') @report_bp.route('/download_report/<int:contractor_id>')
@login_required
def download_report(contractor_id): def download_report(contractor_id):
output_file, error = ReportHelper.create_contractor_report(contractor_id)
if error:
return error, 404
return ReportHelper().download_report(contractor_id=contractor_id) return send_file(output_file, as_attachment=True)

View File

@@ -3,17 +3,12 @@ from flask_login import login_required
from model.Subcontractor import Subcontractor from model.Subcontractor import Subcontractor
from model.Utilities import HtmlHelper, ResponseHandler from model.Utilities import HtmlHelper, ResponseHandler
subcontractor_bp = Blueprint('subcontractor', __name__) subcontractor_bp = Blueprint('subcontractor', __name__)
# ----------------------------------------------------------
# LIST + ADD # LIST + ADD
# ----------------------------------------------------------
@subcontractor_bp.route('/subcontractor', methods=['GET', 'POST']) @subcontractor_bp.route('/subcontractor', methods=['GET', 'POST'])
@login_required @login_required
def subcontract(): def subcontract():
sub = Subcontractor() sub = Subcontractor()
# ---------------- GET ---------------- # ---------------- GET ----------------
@@ -31,27 +26,22 @@ def subcontract():
if request.method == 'POST': if request.method == 'POST':
sub.AddSubcontractor(request) sub.AddSubcontractor(request)
if not sub.isSuccess: if not sub.isSuccess:
return HtmlHelper.json_response( return HtmlHelper.json_response(
ResponseHandler.add_failure("Subcontractor"), 500 ResponseHandler.add_failure("Subcontractor"), 500
) )
# Reload list after insert
subcontractor = sub.GetAllSubcontractors(request) subcontractor = sub.GetAllSubcontractors(request)
return render_template('add_subcontractor.html', subcontractor=subcontractor) return render_template('add_subcontractor.html', subcontractor=subcontractor)
# ----------------------------------------------------------
# EDIT # EDIT
# ----------------------------------------------------------
@subcontractor_bp.route('/edit_subcontractor/<int:id>', methods=['GET', 'POST']) @subcontractor_bp.route('/edit_subcontractor/<int:id>', methods=['GET', 'POST'])
@login_required @login_required
def edit_subcontractor(id): def edit_subcontractor(id):
sub = Subcontractor() sub = Subcontractor()
# Fetch data # Fetch data
subcontractor = sub.GetSubcontractorByID(id) subcontractor = sub.GetSubcontractorByID(id)
@@ -75,9 +65,7 @@ def edit_subcontractor(id):
return render_template('edit_subcontractor.html', subcontractor=subcontractor) return render_template('edit_subcontractor.html', subcontractor=subcontractor)
# ----------------------------------------------------------
# DELETE # DELETE
# ----------------------------------------------------------
@subcontractor_bp.route('/deleteSubContractor/<int:id>', methods=['GET', 'POST']) @subcontractor_bp.route('/deleteSubContractor/<int:id>', methods=['GET', 'POST'])
@login_required @login_required
def deleteSubContractor(id): def deleteSubContractor(id):

View File

@@ -1,7 +1,3 @@
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify
from flask_login import login_required from flask_login import login_required
@@ -89,15 +85,14 @@ def delete_village(village_id):
village = Village() village = Village()
village.DeleteVillage(request=request, village_id=village_id) 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 raw_msg = village.resultMessage
if isinstance(raw_msg, tuple): if isinstance(raw_msg, tuple):
# e.g., (<Response ...>, 200)
msg = "Village deleted successfully!" msg = "Village deleted successfully!"
elif hasattr(raw_msg, 'get_data'): elif hasattr(raw_msg, 'get_data'):
# Flask Response object # Flask Response object
msg = raw_msg.get_data(as_text=True) # get raw text msg = raw_msg.get_data(as_text=True)
else: else:
# fallback # fallback
msg = str(raw_msg) if raw_msg else "Village deleted successfully!" msg = str(raw_msg) if raw_msg else "Village deleted successfully!"
@@ -135,7 +130,6 @@ def edit_village(village_id):
) )
else: else:
# ✅ FIXED HERE (removed request)
village_data = village.GetVillageByID(id=village_id) village_data = village.GetVillageByID(id=village_id)
if not village.isSuccess: if not village.isSuccess:

View File

@@ -1,16 +1,6 @@
from flask import Blueprint, render_template, request, redirect, url_for, jsonify
from model.Utilities import RegEx, ResponseHandler, HtmlHelper, ItemCRUDType from model.Utilities import RegEx, ResponseHandler, HtmlHelper, ItemCRUDType
from model.Log import LogData, LogHelper from model.Log import LogData, LogHelper
from model.ItemCRUD import ItemCRUD
import os
import config
import re
import mysql.connector
from mysql.connector import Error
from model.ItemCRUD import ItemCRUD, itemCRUDMapping
class Block: class Block:
@@ -22,9 +12,7 @@ class Block:
self.isSuccess = False self.isSuccess = False
self.resultMessage = "" self.resultMessage = ""
# ----------------------------------------------------------
# Add Block # Add Block
# ----------------------------------------------------------
def AddBlock(self, request): def AddBlock(self, request):
block = ItemCRUD(itemType=ItemCRUDType.Block) block = ItemCRUD(itemType=ItemCRUDType.Block)
@@ -37,17 +25,7 @@ class Block:
self.resultMessage = block.resultMessage self.resultMessage = block.resultMessage
return return
# ---------------------------------------------------------- # Get All Blocks
# Get All Blocks
# ----------------------------------------------------------
# def GetAllBlocks(self):
# block = ItemCRUD(itemType=ItemCRUDType.Block)
# blocksdata = block.GetAllData(request=request, storedproc="GetAllBlock")
# self.isSuccess = block.isSuccess
# self.resultMessage = block.resultMessage
# return blocksdata
def GetAllBlocks(self, request): def GetAllBlocks(self, request):
block = ItemCRUD(itemType=ItemCRUDType.Block) block = ItemCRUD(itemType=ItemCRUDType.Block)
@@ -57,18 +35,8 @@ class Block:
self.resultMessage = block.resultMessage self.resultMessage = block.resultMessage
return blocksdata return blocksdata
# ----------------------------------------------------------
# Check Block Exists # Check Block Exists
# ----------------------------------------------------------
# def CheckBlock(self, request):
# block = ItemCRUD(itemType=ItemCRUDType.Block)
# block_name = request.json.get('block_Name', '').strip()
# district_id = request.json.get('district_Id')
# result = block.CheckItem(request=request, parentid=district_id, childname=block_name, storedprocfetch="GetBlockByNameAndDistrict")
# self.isSuccess = block.isSuccess
# self.resultMessage = block.resultMessage
# return result
def CheckBlock(self, request): def CheckBlock(self, request):
block = ItemCRUD(itemType=ItemCRUDType.Block) block = ItemCRUD(itemType=ItemCRUDType.Block)
data = request.get_json(silent=True) or request.form data = request.get_json(silent=True) or request.form
@@ -85,24 +53,7 @@ class Block:
self.resultMessage = block.resultMessage self.resultMessage = block.resultMessage
return result return result
# ----------------------------------------------------------
# Get Block By ID # Get Block By ID
# ----------------------------------------------------------
# def GetBlockByID(self, id):
# block = ItemCRUD(itemType=ItemCRUDType.Village)
# blockdata = block.GetAllData(id=id,storedproc="GetBlockDataByID")
# self.isSuccess = block.isSuccess
# self.resultMessage = block.resultMessage
# print("akash"+blockdata)
# return blockdata
# def GetBlockByID(self,request,id):
# block = ItemCRUD(itemType=ItemCRUDType.Block)
# blockdata = block.GetDataByID(request=request,id=id,storedproc="GetBlockDataByID")
# self.isSuccess = block.isSuccess
# self.resultMessage = block.resultMessage
# return blockdata
def GetBlockByID(self, id): def GetBlockByID(self, id):
block = ItemCRUD(itemType=ItemCRUDType.Block) block = ItemCRUD(itemType=ItemCRUDType.Block)
@@ -116,20 +67,8 @@ class Block:
self.resultMessage = block.resultMessage self.resultMessage = block.resultMessage
return blockdata return blockdata
# ----------------------------------------------------------
# Update Block # Update Block
# ----------------------------------------------------------
# def EditBlock(self, request, block_id):
# block = ItemCRUD(itemType=ItemCRUDType.Block)
# district_id = request.form.get('district_Id')
# block_name = request.form.get('block_Name', '').strip()
# block.EditItem(request=request, childid=block_id, parentid=district_id, childname=block_name, storedprocadd="UpdateBlockById" )
# self.isSuccess = block.isSuccess
# self.resultMessage = block.resultMessage
# return
def EditBlock(self, request, block_id): def EditBlock(self, request, block_id):
block = ItemCRUD(itemType=ItemCRUDType.Block) block = ItemCRUD(itemType=ItemCRUDType.Block)
@@ -149,9 +88,8 @@ class Block:
self.resultMessage = block.resultMessage self.resultMessage = block.resultMessage
return return
# ----------------------------------------------------------
# Delete Block # Delete Block
# ---------------------------------------------------------
def DeleteBlock(self,request, id): def DeleteBlock(self,request, id):
block = ItemCRUD(itemType=ItemCRUDType.Block) block = ItemCRUD(itemType=ItemCRUDType.Block)

View File

@@ -1,10 +1,5 @@
from mysql.connector import Error from mysql.connector import Error
import config import config
from datetime import datetime
class ContractorInfo: class ContractorInfo:
def __init__(self, contractor_id): def __init__(self, contractor_id):

View File

@@ -1,12 +1,11 @@
import os import os
from flask import current_app from flask import current_app
# -----------------------------
# BASE FOLDER Class
# -----------------------------
class FolderAndFile: class FolderAndFile:
# -----------------------------
# BASE FOLDER METHODS
# -----------------------------
@staticmethod @staticmethod
def get_download_folder(): def get_download_folder():
folder = os.path.join(current_app.root_path, "static", "downloads") folder = os.path.join(current_app.root_path, "static", "downloads")

View File

@@ -10,7 +10,7 @@ class GST:
invoices_rows = invoice_crud.GetAllData(storedproc="GetAllInvoicesBasic") invoices_rows = invoice_crud.GetAllData(storedproc="GetAllInvoicesBasic")
if not invoice_crud.isSuccess: if not invoice_crud.isSuccess:
return [] # Could also log invoice_crud.resultMessage return []
invoices = [ invoices = [
dict( dict(
@@ -25,16 +25,16 @@ class GST:
gst_rows = gst_crud.GetAllData(storedproc="GetAllGSTReleasesBasic") gst_rows = gst_crud.GetAllData(storedproc="GetAllGSTReleasesBasic")
if not gst_crud.isSuccess: if not gst_crud.isSuccess:
return [] # Could also log gst_crud.resultMessage return []
gst_invoice_nos = { gst_invoice_nos = {
g[2] # Invoice_No is at index 2 g[2]
for g in gst_rows for g in gst_rows
if g[2] if g[2]
} }
gst_basic_amounts = { gst_basic_amounts = {
float(g[3]) # Basic_Amount at index 3 float(g[3])
for g in gst_rows for g in gst_rows
if g[3] is not None if g[3] is not None
} }

View File

@@ -3,7 +3,6 @@ from model.ItemCRUD import ItemCRUD
from model.Utilities import ItemCRUDType from model.Utilities import ItemCRUDType
class HoldTypes: class HoldTypes:
"""CRUD operations for Hold Types using ItemCRUD"""
def __init__(self): def __init__(self):
self.isSuccess = False self.isSuccess = False
@@ -33,7 +32,7 @@ class HoldTypes:
self.isSuccess = hold.isSuccess self.isSuccess = hold.isSuccess
self.resultMessage = hold.resultMessage self.resultMessage = hold.resultMessage
# Convert tuple → dictionary # Convert tuple → dictionary
data = [] data = []
for row in rows: for row in rows:
data.append({ data.append({
@@ -51,7 +50,7 @@ class HoldTypes:
self.isSuccess = hold.isSuccess self.isSuccess = hold.isSuccess
self.resultMessage = hold.resultMessage self.resultMessage = hold.resultMessage
# Convert tuple → dictionary # Convert tuple → dictionary
if row: if row:
return { return {
"hold_type_id": row[0], "hold_type_id": row[0],

View File

@@ -1,6 +1,4 @@
import config import config
import mysql.connector
# ------------------- Helper Functions ------------------- # ------------------- Helper Functions -------------------
def clear_results(cursor): def clear_results(cursor):
@@ -78,25 +76,15 @@ def insert_invoice(data, village_id):
data.get('invoice_details'), data.get('invoice_details'),
data.get('invoice_date'), data.get('invoice_date'),
data.get('invoice_no'), data.get('invoice_no'),
*get_numeric_values(data) *get_numeric_values(data),
data.get('subcontractor_id')
]) ])
invoice_row = fetch_one(cursor) invoice_row = fetch_one(cursor)
if not invoice_row: if not invoice_row:
raise Exception("Invoice ID not returned") raise Exception("Invoice ID not returned")
invoice_id = invoice_row.get('invoice_id') invoice_id = invoice_row.get('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 invoice_id
return execute_db_operation(operation) return execute_db_operation(operation)
@@ -141,18 +129,6 @@ def update_invoice(data, invoice_id):
clear_results(cursor) clear_results(cursor)
execute_db_operation(operation) 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 delete_invoice_data(invoice_id, user_id):
def operation(cursor): def operation(cursor):
@@ -164,18 +140,11 @@ def delete_invoice_data(invoice_id, user_id):
if not record: if not record:
raise Exception("Invoice not found") raise Exception("Invoice not found")
# Use exact DB keys
pmc_no = record['PMC_No']
invoice_no = record['Invoice_No']
# Delete invoice # Delete invoice
cursor.callproc("DeleteInvoice", (invoice_id,)) cursor.callproc("DeleteInvoice", (invoice_id,))
clear_results(cursor) clear_results(cursor)
# Delete inpayment
cursor.callproc('DeleteInpaymentByPMCInvoice', (pmc_no, invoice_no))
clear_results(cursor)
execute_db_operation(operation) execute_db_operation(operation)

View File

@@ -232,14 +232,13 @@ class ItemCRUD:
if self.itemCRUDType.name == "GSTRelease" and data: if self.itemCRUDType.name == "GSTRelease" and data:
cursor.callproc(storedprocupdate, ( cursor.callproc(storedprocupdate, (
childid, data['p_pmc_no'], # PMC_No
data['PMC_No'], data['p_invoice_no'], # Invoice_No
data['Invoice_No'], data['p_basic_amount'], # Basic_Amount
data['Basic_Amount'], data['p_final_amount'], # Final_Amount
data['Final_Amount'], data['p_total_amount'], # Total_Amount
data['Total_Amount'], data['p_utr'], # UTR
data['UTR'], data['p_gst_release_id']# GST_Release_Id
data['Contractor_ID']
)) ))
connection.commit() connection.commit()

View File

@@ -1,5 +1,4 @@
import os import os
from flask import current_app
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
from datetime import datetime from datetime import datetime

View File

@@ -1,5 +1,5 @@
import openpyxl import openpyxl
from openpyxl.styles import Font, PatternFill from openpyxl.styles import Font
import config import config
from flask_login import current_user from flask_login import current_user
from model.Log import LogHelper from model.Log import LogHelper
@@ -11,14 +11,10 @@ class PmcReport:
@staticmethod @staticmethod
def get_pmc_report(pmc_no): def get_pmc_report(pmc_no):
connection = config.get_db_connection() connection = config.get_db_connection()
cursor = connection.cursor(dictionary=True, buffered=True) cursor = connection.cursor(dictionary=True, buffered=True)
try: try:
# cursor.callproc("GetContractorInfoByPmcNo", (pmc_no,))
# pmc_info = next(cursor.stored_results()).fetchone()
pmc_info = ReportHelper.execute_sp(cursor, 'GetContractorInfoByPmcNo', [pmc_no], True) pmc_info = ReportHelper.execute_sp(cursor, 'GetContractorInfoByPmcNo', [pmc_no], True)
if not pmc_info: if not pmc_info:
@@ -51,44 +47,20 @@ class PmcReport:
total_invo_final = sum(row.get('Final_Amount', 0) or 0 for row in invoices) total_invo_final = sum(row.get('Final_Amount', 0) or 0 for row in invoices)
# GST RELEASE # GST RELEASE
# cursor.callproc('GetGSTReleaseByPMC', [pmc_no])
# gst_rel = []
# for result in cursor.stored_results():
# gst_rel = result.fetchall()
gst_rel = ReportHelper.execute_sp(cursor, 'GetGSTReleaseByPMC', [pmc_no]) 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_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) total_gst_final = sum(row.get('final_amount', 0) or 0 for row in gst_rel)
# ---------------- HOLD RELEASE ---------------- # ---------------- HOLD RELEASE ----------------
# cursor.callproc('GetHoldReleaseByPMC', [pmc_no])
# hold_release = []
# for result in cursor.stored_results():
# hold_release = result.fetchall()
hold_release = ReportHelper.execute_sp(cursor, 'GetHoldReleaseByPMC', [pmc_no]) hold_release = ReportHelper.execute_sp(cursor, 'GetHoldReleaseByPMC', [pmc_no])
# ---------------- CREDIT NOTE ---------------- # ---------------- CREDIT NOTE ----------------
# cursor.callproc('GetCreditNoteByPMC', [pmc_no])
# credit_note = []
# for result in cursor.stored_results():
# credit_note = result.fetchall()
credit_note = ReportHelper.execute_sp(cursor, 'GetCreditNoteByPMC', [pmc_no]) credit_note = ReportHelper.execute_sp(cursor, 'GetCreditNoteByPMC', [pmc_no])
payments = ReportHelper.execute_sp(cursor, 'GetPaymentsByPMC', [pmc_no])
# ---------------- PAYMENTS ---------------- # ---------------- PAYMENTS ----------------
# cursor.callproc('GetPaymentsByPMC', [pmc_no]) payments = ReportHelper.execute_sp(cursor, 'GetPaymentsByPMC', [pmc_no])
# payments = []
# for result in cursor.stored_results():
# payments = result.fetchall()
total_pay_amount = sum(row.get('Payment_Amount', 0) or 0 for row in payments) 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) total_pay_total = sum(row.get('Total_amount', 0) or 0 for row in payments)
@@ -137,51 +109,51 @@ class PmcReport:
return None return None
cursor = connection.cursor(dictionary=True) cursor = connection.cursor(dictionary=True)
try: try:
# filename
filename = f"PMC_Report_{pmc_no}.xlsx" filename = f"PMC_Report_{pmc_no}.xlsx"
output_folder = FolderAndFile.get_download_folder() output_folder = FolderAndFile.get_download_folder()
output_file = FolderAndFile.get_download_path(filename) output_file = FolderAndFile.get_download_path(filename)
# ================= DATA FETCH ================= # ================= DATA FETCH =============
contractor_info = ReportHelper.execute_sp(cursor, 'GetContractorDetailsByPMC', [pmc_no])
contractor_info = ReportHelper.execute_sp(cursor, 'GetContractorDetailsByPMC', [pmc_no], "one") contractor_info = contractor_info[0] if contractor_info else None
if not contractor_info: if not contractor_info:
return None return None
hold_types = ReportHelper.execute_sp(cursor, 'GetHoldTypesByContractor', [contractor_info["Contractor_Id"]]) hold_types = ReportHelper.execute_sp(cursor, 'GetHoldTypesByContractor',[contractor_info["Contractor_Id"]])
hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types} hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types}
invoices = ReportHelper.execute_sp(cursor, 'GetInvoicesAndGstReleaseByPmcNo', [pmc_no]) invoices = ReportHelper.execute_sp(cursor, 'GetInvoicesAndGstReleaseByPmcNo', [pmc_no])
credit_notes = ReportHelper.execute_sp(cursor, 'GetCreditNoteByContractor', [contractor_info["Contractor_Id"]]) credit_notes = ReportHelper.execute_sp(cursor, 'NewGetCreditNotesByPMCNo', [pmc_no])
hold_amounts = ReportHelper.execute_sp(cursor, 'GetHoldAmountsByContractor', [contractor_info["Contractor_Id"]]) hold_amounts = ReportHelper.execute_sp(cursor, 'GetHoldAmountsByContractor',[contractor_info["Contractor_Id"]])
all_payments = ReportHelper.execute_sp(cursor, 'GetAllPaymentsByPMC', [pmc_no])
gst_releases = ReportHelper.execute_sp(cursor, 'GetGSTReleaseDetailsByPMC', [pmc_no]) gst_releases = ReportHelper.execute_sp(cursor, 'GetGSTReleaseDetailsByPMC', [pmc_no])
# ================= DATA MAPPING ================= # ================= DATA MAPPING =================
hold_data = {} hold_data = {}
for h in hold_amounts: for h in hold_amounts:
hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount'] hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
payments_map = {} credit_note_map = {}
for pay in all_payments: for cn in credit_notes:
if pay['invoice_no']: pmc = cn.get("PMC_No")
payments_map.setdefault(pay['invoice_no'], []).append(pay) 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)
# ================= LOG ================= # ================= LOG =================
LogHelper.log_action( LogHelper.log_action("Download PMC Report",f"User {current_user.id} Download PMC Report '{pmc_no}'")
"Download PMC Report",
f"User {current_user.id} Download PMC Report '{pmc_no}'"
)
# ================= EXCEL ================= # ================= EXCEL =================
workbook = openpyxl.Workbook() workbook = openpyxl.Workbook()
@@ -197,83 +169,101 @@ class PmcReport:
sheet.append([]) sheet.append([])
base_headers = [ base_headers = [
"PMC No","Village","Work Type","Invoice Details","Invoice Date","Invoice No", "PMC No", "Village", "Work Type", "Invoice Details",
"Basic Amount","Debit","After Debit Amount","GST","Amount","TDS", "Invoice Date", "Invoice No", "Basic Amount", "Debit", "After Debit Amount",
"SD","On Commission","Hydro Testing","GST SD Amount" "GST", "Amount", "TDS", "SD", "On Commission", "Hydro Testing", "GST SD Amount"
] ]
hold_headers = [ht['hold_type'] for ht in hold_types] hold_headers = [ht['hold_type'] for ht in hold_types]
payment_headers = ["Final Amount", "Payment Amount", "TDS Payment", "Total Paid", "UTR"]
payment_headers = [ headers = base_headers + hold_headers + payment_headers
"Final Amount","Payment Amount","TDS Payment","Total Paid","UTR"
]
headers = base_headers + hold_headers + payment_headers
sheet.append(headers) sheet.append(headers)
# STYLE
for cell in sheet[sheet.max_row]: for cell in sheet[sheet.max_row]:
cell.font = Font(bold=True) cell.font = Font(bold=True)
# DATA # ================= INVOICE ROWS =================
seen_invoices = set()
for inv in invoices: for inv in invoices:
invoice_no = inv["Invoice_No"]
payments = payments_map.get(invoice_no, [])
if invoice_no in seen_invoices:
continue
seen_invoices.add(invoice_no)
first_payment = payments[0] if payments else None
row = [ row = [
pmc_no, pmc_no,
inv["Village_Name"], inv.get("Village_Name", ""),
inv["Work_Type"], inv.get("Work_Type", ""),
inv["Invoice_Details"], inv.get("Invoice_Details", ""),
inv["Invoice_Date"], inv.get("Invoice_Date", ""),
invoice_no, inv.get("invoice_no", ""),
inv["Basic_Amount"], inv.get("Basic_Amount", ""),
inv["Debit_Amount"], inv.get("Debit_Amount", ""),
inv["After_Debit_Amount"], inv.get("After_Debit_Amount", ""),
inv["GST_Amount"], inv.get("GST_Amount", ""),
inv["Amount"], inv.get("Amount", ""),
inv["TDS_Amount"], inv.get("TDS_Amount", ""),
inv["SD_Amount"], inv.get("SD_Amount", ""),
inv["On_Commission"], inv.get("On_Commission", ""),
inv["Hydro_Testing"], inv.get("Hydro_Testing", ""),
inv["GST_SD_Amount"] inv.get("GST_SD_Amount", "")
] ]
# HOLD DATA # HOLD DATA
invoice_holds = hold_data.get(inv["Invoice_Id"], {}) invoice_holds = hold_data.get(inv.get("Invoice_Id"), {})
for ht_id in hold_type_map.keys(): for ht_id in hold_type_map.keys():
row.append(invoice_holds.get(ht_id, "")) row.append(invoice_holds.get(ht_id, ""))
# PAYMENT DATA # PAYMENT DATA
row += [ row += [
inv["Final_Amount"], inv.get("Final_Amount", ""),
first_payment["Payment_Amount"] if first_payment else "", inv.get("Payment_Amount", ""),
first_payment["TDS_Payment_Amount"] if first_payment else "", inv.get("TDS_Payment_Amount", ""),
first_payment["Total_amount"] if first_payment else "", inv.get("Total_Amount", ""),
first_payment["UTR"] if first_payment else "" inv.get("UTR", "")
] ]
sheet.append(row) row += ["", ""]
# AUTO WIDTH 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: for col in sheet.columns:
max_len = max((len(str(cell.value)) for cell in col if cell.value), default=0) 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 sheet.column_dimensions[col[0].column_letter].width = max_len + 2
# SAVE
workbook.save(output_file) workbook.save(output_file)
workbook.close() workbook.close()
return output_folder, filename return output_folder, filename
except Exception as e: except Exception as e:
@@ -283,174 +273,3 @@ class PmcReport:
finally: finally:
cursor.close() cursor.close()
connection.close() connection.close()
# @staticmethod
# def download_pmc_report(pmc_no):
# connection = config.get_db_connection()
# cursor = connection.cursor(dictionary=True)
# # output_folder = "static/download"
# # output_file = os.path.join(output_folder, f"PMC_Report_{pmc_no}.xlsx")
# output_folder = FolderAndFile.get_download_folder
# filename = f"PMC_Report_{pmc_no}.xlsx"
# output_file = FolderAndFile.get_download_path(filename)
# try:
# cursor.callproc('GetContractorDetailsByPMC', [pmc_no])
# contractor_info = next(cursor.stored_results()).fetchone()
# if not contractor_info:
# return None
# cursor.callproc('GetHoldTypesByContractor', [contractor_info["Contractor_Id"]])
# hold_types = next(cursor.stored_results()).fetchall()
# hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types}
# cursor.callproc('GetInvoicesAndGstReleaseByPmcNo', [pmc_no])
# invoices = next(cursor.stored_results()).fetchall()
# cursor.callproc('GetCreditNoteByContractor',[contractor_info["Contractor_Id"]])
# credit_notes = []
# for result in cursor.stored_results():
# credit_notes = result.fetchall()
# credit_note_map = {}
# for cn in credit_notes:
# key = (cn["PMC_No"], cn["Invoice_No"])
# credit_note_map.setdefault(key, []).append(cn)
# cursor.callproc('GetHoldAmountsByContractor', [contractor_info["Contractor_Id"]])
# hold_amounts = next(cursor.stored_results()).fetchall()
# hold_data = {}
# for h in hold_amounts:
# hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
# cursor.callproc('GetAllPaymentsByPMC', [pmc_no])
# all_payments = next(cursor.stored_results()).fetchall()
# payments_map = {}
# extra_payments = []
# for pay in all_payments:
# if pay['invoice_no']:
# payments_map.setdefault(pay['invoice_no'], []).append(pay)
# else:
# extra_payments.append(pay)
# # ---------------- GST RELEASE DETAILS ----------------
# cursor.callproc('GetGSTReleaseDetailsByPMC', [pmc_no])
# gst_releases = []
# for result in cursor.stored_results():
# gst_releases = result.fetchall()
# gst_release_map = {}
# for gr in gst_releases:
# invoice_nos = []
# if gr['Invoice_No']:
# cleaned = gr['Invoice_No'].replace(' ', '')
# if '&' in cleaned:
# invoice_nos = cleaned.split('&')
# elif ',' in cleaned:
# invoice_nos = cleaned.split(',')
# else:
# invoice_nos = [cleaned]
# for inv_no in invoice_nos:
# gst_release_map.setdefault(inv_no, []).append(gr)
# LogHelper.log_action(
# "Download PMC Report",
# f"User {current_user.id} Download PMC Report '{pmc_no}'"
# )
# workbook = openpyxl.Workbook()
# sheet = workbook.active
# sheet.title = "PMC Report"
# sheet.append(["", "", "Laxmi Civil Engineering Services PVT. LTD."])
# sheet.append(["Contractor Name", contractor_info["Contractor_Name"], "", "GST No", contractor_info["GST_No"], "", "GST Type", contractor_info["GST_Registration_Type"]])
# sheet.append(["State", contractor_info["State_Name"], "", "PAN No", contractor_info["PAN_No"], "", "Address", contractor_info["Address"]])
# sheet.append(["District", contractor_info["District_Name"], "", "Mobile No", contractor_info["Mobile_No"]])
# sheet.append(["Block", contractor_info["Block_Name"], "", "Email", contractor_info["Email"]])
# sheet.append([])
# base_headers = [
# "PMC No","Village","Work Type","Invoice Details","Invoice Date","Invoice No",
# "Basic Amount","Debit","After Debit Amount","GST (18%)","Amount","TDS (1%)",
# "SD (5%)","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"
# ]
# sheet.append(base_headers + hold_headers + payment_headers)
# header_fill = PatternFill(start_color="ADD8E6",end_color="ADD8E6",fill_type="solid")
# header_font = Font(bold=True)
# for cell in sheet[sheet.max_row]:
# cell.font = header_font
# cell.fill = header_fill
# seen_invoices = set()
# processed_payments = set()
# for inv in invoices:
# invoice_no = inv["Invoice_No"]
# payments = payments_map.get(invoice_no, [])
# if invoice_no not in seen_invoices:
# seen_invoices.add(invoice_no)
# first_payment = payments[0] if payments else None
# row = [
# pmc_no, inv["Village_Name"], inv["Work_Type"],
# inv["Invoice_Details"], inv["Invoice_Date"], invoice_no,
# inv["Basic_Amount"], inv["Debit_Amount"],
# inv["After_Debit_Amount"], inv["GST_Amount"],
# inv["Amount"], inv["TDS_Amount"], inv["SD_Amount"],
# inv["On_Commission"], inv["Hydro_Testing"], inv["GST_SD_Amount"]
# ]
# invoice_holds = hold_data.get(inv["Invoice_Id"], {})
# for ht_id in hold_type_map.keys():
# row.append(invoice_holds.get(ht_id, ""))
# row += [
# inv["Final_Amount"],
# first_payment["Payment_Amount"] if first_payment else "",
# first_payment["TDS_Payment_Amount"] if first_payment else "",
# first_payment["Total_amount"] if first_payment else "",
# first_payment["UTR"] if first_payment else ""
# ]
# sheet.append(row)
# workbook.save(output_file)
# workbook.close()
# return output_folder, filename
# finally:
# cursor.close()
# connection.close()

View File

@@ -1,8 +1,9 @@
import config import config
from datetime import datetime from datetime import datetime
from flask import send_file from flask import send_file
import os
import openpyxl import openpyxl
from openpyxl.styles import Font from openpyxl.styles import Font, PatternFill
from model.FolderAndFile import FolderAndFile from model.FolderAndFile import FolderAndFile
@@ -147,129 +148,199 @@ class ReportHelper:
"current_date": current_date "current_date": current_date
} }
@staticmethod @staticmethod
def download_report(contractor_id): def get_contractor_info(contractor_id):
try: from model.ContractorInfo import ContractorInfo
connection = config.get_db_connection() contractor = ContractorInfo(contractor_id)
cursor = connection.cursor(dictionary=True) return contractor.contInfo if contractor.contInfo else None
# -------- Contractor Info --------
contInfo = ReportHelper.execute_sp(cursor, 'GetContractorInfo', [contractor_id], True)
if not contInfo: @staticmethod
return "No contractor found", 404 def generate_excel(contractor_id, contInfo, invoices, hold_types, hold_data,
credit_note_map, gst_release_map, output_file):
# -------- Invoice Data -------- workbook = openpyxl.Workbook()
cursor.callproc('FetchInvoicesByContractor', [contractor_id]) sheet = workbook.active
sheet.title = "Contractor Report"
invoices = [] # Contractor Info
for result in cursor.stored_results(): for field, value in contInfo.items():
invoices.extend(result.fetchall()) sheet.append([field.replace("_", " "), value])
sheet.append([])
if not invoices: # Headers
return "No invoice data found" base_headers = ["PMC No", "Village", "Work Type", "Invoice Details", "Invoice Date", "Invoice No",
"Basic Amount", "Debit", "After Debit Amount", "GST (18%)", "Amount", "TDS (1%)",
"SD (5%)", "On Commission", "Hydro Testing", "GST SD Amount"]
# -------- Create Workbook -------- hold_headers = [ht['hold_type'] for ht in hold_types]
workbook = openpyxl.Workbook()
sheet = workbook.active
sheet.title = "Contractor Report"
# ================= CONTRACTOR DETAILS ================= payment_headers = ["Final Amount", "Payment Amount", "TDS Payment", "Total Paid", "UTR"]
sheet.append(["SUB CONTRACTOR DETAILS"])
sheet.cell(row=sheet.max_row, column=1).font = Font(bold=True)
sheet.append([])
sheet.append(["Name", contInfo.get("Contractor_Name") or ""]) all_headers = base_headers + hold_headers + payment_headers
sheet.append(["Mobile No", contInfo.get("Mobile_No") or ""]) sheet.append(all_headers)
sheet.append(["Email", contInfo.get("Email") or ""])
sheet.append(["Village", contInfo.get("Village_Name") or ""])
sheet.append(["Block", contInfo.get("Block_Name") or ""])
sheet.append(["District", contInfo.get("District_Name") or ""])
sheet.append(["State", contInfo.get("State_Name") or ""])
sheet.append(["Address", contInfo.get("Address") or ""])
sheet.append(["GST No", contInfo.get("GST_No") or ""])
sheet.append(["PAN No", contInfo.get("PAN_No") or ""])
sheet.append([])
sheet.append([])
# ================= TABLE HEADERS ================= for cell in sheet[sheet.max_row]:
headers = [ cell.font = Font(bold=True)
"PMC No", "Village", "Invoice No", "Invoice Date", "Work Type","Invoice_Details", cell.fill = PatternFill(start_color="ADD8E6", end_color="ADD8E6", fill_type="solid")
"Basic Amount", "Debit Amount", "After Debit Amount",
"Amount", "GST Amount", "TDS Amount", "SD Amount", processed_gst_releases = set()
"On Commission", "Hydro Testing", "Hold Amount", appended_credit_keys = set()
"GST SD Amount", "Final Amount", previous_pmc_no = None
"Payment Amount", "TDS Payment",
"Total Amount", "UTR" for inv in invoices:
pmc_no = str(inv["PMC_No"]).strip()
invoice_no = (
inv["invoice_no"].replace(" ", "") if inv["invoice_no"] else ""
if inv["invoice_no"] not in (None, "", 0)
else ""
)
key = (pmc_no)
# Yellow separator
if previous_pmc_no and pmc_no != previous_pmc_no:
sheet.append([""] * len(all_headers))
yellow_fill = PatternFill(start_color="FFFF99", end_color="FFFF99", fill_type="solid")
for cell in sheet[sheet.max_row]:
cell.fill = yellow_fill
previous_pmc_no = pmc_no
# Invoice Row
row = [
pmc_no,
inv.get("Village_Name", ""),
inv.get("Work_Type", ""),
inv.get("Invoice_Details", ""),
inv.get("Invoice_Date", ""),
# inv.get("invoice_no",""),
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", "")
] ]
sheet.append(headers)
for col in range(1, len(headers) + 1):
sheet.cell(row=sheet.max_row, column=col).font = Font(bold=True)
# ================= DATA ================= # Hold values
total_final = 0 invoice_holds = hold_data.get(inv["Invoice_Id"], {})
total_payment = 0 for ht_id in [ht['hold_type_id'] for ht in hold_types]:
total_amount = 0 row.append(invoice_holds.get(ht_id, ""))
for inv in invoices: # Payment values
row = [ row += [
inv.get("PMC_No"), inv.get("Final_Amount", ""),
inv.get("Village_Name"), inv.get("Payment_Amount", ""),
inv.get("invoice_no"), inv.get("TDS_Payment_Amount", ""),
inv.get("Invoice_Date"), inv.get("Total_Amount", ""),
inv.get("Work_Type"), inv.get("UTR", "")
inv.get("Invoice_Details"), ]
inv.get("Basic_Amount"),
inv.get("Debit_Amount"),
inv.get("After_Debit_Amount"),
inv.get("Amount"),
inv.get("GST_Amount"),
inv.get("TDS_Amount"),
inv.get("SD_Amount"),
inv.get("On_Commission"),
inv.get("Hydro_Testing"),
inv.get("Hold_Amount"),
inv.get("GST_SD_Amount"),
inv.get("Final_Amount"),
inv.get("Payment_Amount"),
inv.get("TDS_Payment_Amount"),
inv.get("Total_Amount"),
inv.get("UTR")
]
total_final += float(inv.get("Final_Amount") or 0) sheet.append(row)
total_payment += float(inv.get("Payment_Amount") or 0)
total_amount += float(inv.get("Total_Amount") or 0)
sheet.append(row) # GST Releases
if key in gst_release_map and key not in processed_gst_releases:
for gr in gst_release_map[key]:
gst_row = [
pmc_no, "", "", "GST Release Note", "", gr.get("Invoice_No", ""),
gr.get("Basic_Amount", ""), "", "", "", "", "", "", "", "", ""
]
# ================= TOTAL ROW ================= gst_row += [""] * len(hold_headers)
sheet.append([])
sheet.append([ gst_row += [
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", gr.get("Final_Amount", ""),
"TOTAL", "",
total_final, "",
total_payment, gr.get("Total_Amount", ""),
"", gr.get("UTR", "")
total_amount, ]
""
]) sheet.append(gst_row)
processed_gst_releases.add(key)
# Credit Notes
if key in credit_note_map and key not in appended_credit_keys:
for cn in credit_note_map[key]:
cn_row = [
pmc_no, "", "", cn.get("Invoice_Details", "Credit Note"), "",
cn.get("Invoice_No", ""),
cn.get("Basic_Amount", ""),
cn.get("Debit_Amount", ""),
cn.get("After_Debit_Amount", ""),
cn.get("GST_Amount", ""),
cn.get("Amount", ""),
"", "", "", "", ""
]
cn_row += [""] * len(hold_headers)
cn_row += [cn.get("Final_Amount", ""),"","",cn.get("Total_Amount", ""),cn.get("UTR", "")]
sheet.append(cn_row)
appended_credit_keys.add(key)
# SAVE ONCE AT END
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
# ================= AUTO WIDTH =================
for column in sheet.columns:
max_length = 0
column_letter = column[0].column_letter
for cell in column:
if cell.value:
max_length = max(max_length, len(str(cell.value)))
sheet.column_dimensions[column_letter].width = max_length + 2
# ================= SAVE FILE =================
filename = f"Contractor_Report_{contInfo.get('Contractor_Name')}.xlsx"
output_file = FolderAndFile.get_download_path(filename)
workbook.save(output_file)
return send_file(output_file, as_attachment=True)
except Exception as e:
return str(e)

View File

@@ -1,7 +1,6 @@
from model.Utilities import ItemCRUDType from model.Utilities import ItemCRUDType
from model.ItemCRUD import ItemCRUD from model.ItemCRUD import ItemCRUD
class Subcontractor: class Subcontractor:
def __init__(self): def __init__(self):
self.isSuccess = False self.isSuccess = False

View File

@@ -13,14 +13,14 @@ class Village:
def __init__(self): def __init__(self):
self.isSuccess = False self.isSuccess = False
self.resultMessage = "" self.resultMessage = ""
self.response = {} # ✅ ADDED self.response = {}
self.village = ItemCRUD(itemType=ItemCRUDType.Village) self.village = ItemCRUD(itemType=ItemCRUDType.Village)
# 🔹 Helper: sync status # 🔹 Helper: sync status
def _set_status(self, village): def _set_status(self, village):
self.isSuccess = village.isSuccess self.isSuccess = village.isSuccess
# UPDATED (safe handling) # UPDATED (safe handling)
if hasattr(village, "response"): if hasattr(village, "response"):
self.response = village.response self.response = village.response
self.resultMessage = village.response.get("message", "") self.resultMessage = village.response.get("message", "")
@@ -37,7 +37,7 @@ class Village:
block_id, village_name = self._get_form_data(request) block_id, village_name = self._get_form_data(request)
if not village_name: if not village_name:
self.response = ResponseHandler.invalid_name("village") # ✅ UPDATED self.response = ResponseHandler.invalid_name("village")
self.resultMessage = self.response["message"] self.resultMessage = self.response["message"]
self.isSuccess = False self.isSuccess = False
return return
@@ -75,7 +75,7 @@ class Village:
block_id, village_name = self._get_form_data(request) block_id, village_name = self._get_form_data(request)
if not village_name: if not village_name:
self.response = ResponseHandler.invalid_name("village") # ✅ UPDATED self.response = ResponseHandler.invalid_name("village")
self.resultMessage = self.response["message"] self.resultMessage = self.response["message"]
self.isSuccess = False self.isSuccess = False
return None return None
@@ -113,7 +113,7 @@ class Village:
block_id, village_name = self._get_form_data(request) block_id, village_name = self._get_form_data(request)
if not village_name: if not village_name:
self.response = ResponseHandler.invalid_name("village") # ✅ UPDATED self.response = ResponseHandler.invalid_name("village")
self.resultMessage = self.response["message"] self.resultMessage = self.response["message"]
self.isSuccess = False self.isSuccess = False
return return
@@ -176,7 +176,7 @@ class Village:
print(f"Error fetching blocks: {e}") print(f"Error fetching blocks: {e}")
self.isSuccess = False self.isSuccess = False
# FIXED (removed jsonify response) # FIXED (removed jsonify response)
self.response = ResponseHandler.fetch_failure("block") self.response = ResponseHandler.fetch_failure("block")
self.resultMessage = self.response["message"] self.resultMessage = self.response["message"]

View File

@@ -8,12 +8,18 @@ class GSTRelease:
def __init__(self): def __init__(self):
self.isSuccess = False self.isSuccess = False
self.resultMessage = "" self.resultMessage = ""
# ------------------- Add GST Release ------------------- # ------------------- Add GST Release -------------------
def AddGSTRelease(self, request): def AddGSTRelease(self, request):
try: try:
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease) gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
# Print the full form data
print("===== DEBUG: FORM DATA =====")
for key, value in request.form.items():
print(f"{key} : {value}")
print("=============================")
data = { data = {
"PMC_No": request.form.get("PMC_No", "").strip(), "PMC_No": request.form.get("PMC_No", "").strip(),
"Invoice_No": request.form.get("Invoice_No", "").strip(), "Invoice_No": request.form.get("Invoice_No", "").strip(),
@@ -24,6 +30,10 @@ class GSTRelease:
"Contractor_ID": int(request.form.get("Contractor_ID", 0) or 0) "Contractor_ID": int(request.form.get("Contractor_ID", 0) or 0)
} }
print("===== DEBUG: PARSED DATA =====")
print(data)
print("==============================")
# Add GST Release # Add GST Release
gst.AddItem( gst.AddItem(
request=request, request=request,
@@ -31,12 +41,8 @@ class GSTRelease:
storedprocfetch="CheckGSTReleaseExists", storedprocfetch="CheckGSTReleaseExists",
storedprocadd="AddGSTReleaseFromExcel" storedprocadd="AddGSTReleaseFromExcel"
) )
# Check if addition was successful print(f"AddItem result: isSuccess={gst.isSuccess}, message={gst.resultMessage}")
if gst.isSuccess:
print(f"GST Release Added: {data}")
else:
print(f"Failed to add GST Release: {gst.resultMessage}")
self.isSuccess = gst.isSuccess self.isSuccess = gst.isSuccess
self.resultMessage = str(gst.resultMessage) self.resultMessage = str(gst.resultMessage)
@@ -48,20 +54,26 @@ class GSTRelease:
return jsonify({"success": self.isSuccess, "message": self.resultMessage}) return jsonify({"success": self.isSuccess, "message": self.resultMessage})
# ------------------- Edit GST Release -------------------
def EditGSTRelease(self, request, gst_release_id): def EditGSTRelease(self, request, gst_release_id):
try: try:
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease) gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
# Map form inputs to stored procedure parameters
data = { data = {
"PMC_No": request.form.get("PMC_No", "").strip(), "p_pmc_no": request.form.get("PMC_No", "").strip(),
"Invoice_No": request.form.get("Invoice_No", "").strip(), "p_invoice_no": request.form.get("invoice_no", "").strip(),
"Basic_Amount": float(request.form.get("Basic_Amount", 0) or 0), "p_basic_amount": float(request.form.get("Basic_Amount", 0) or 0),
"Final_Amount": float(request.form.get("Final_Amount", 0) or 0), "p_final_amount": float(request.form.get("Final_Amount", 0) or 0),
"Total_Amount": float(request.form.get("Total_Amount", 0) or 0), "p_total_amount": float(request.form.get("Total_Amount", 0) or 0),
"UTR": request.form.get("UTR", "").strip() "p_utr": request.form.get("UTR", "").strip(),
"p_gst_release_id": gst_release_id
} }
print("===== DEBUG: UPDATE DATA =====")
print(data)
print("==============================")
# Call your stored procedure
gst.EditItem( gst.EditItem(
request=request, request=request,
childid=gst_release_id, childid=gst_release_id,
@@ -77,8 +89,6 @@ class GSTRelease:
self.isSuccess = False self.isSuccess = False
self.resultMessage = str(e) self.resultMessage = str(e)
return jsonify({"success": self.isSuccess, "message": self.resultMessage})
# ------------------- Delete GST Release ------------------- # ------------------- Delete GST Release -------------------
def DeleteGSTRelease(self, gst_release_id): def DeleteGSTRelease(self, gst_release_id):
try: try:

View File

@@ -2,7 +2,6 @@ import config
import mysql.connector import mysql.connector
import config import config
import mysql.connector import mysql.connector
from enum import Enum
from model.Utilities import ItemCRUDType from model.Utilities import ItemCRUDType
class Paymentmodel: class Paymentmodel:
@@ -34,40 +33,44 @@ class Paymentmodel:
return payments return payments
@staticmethod @staticmethod
def insert_payment(pmc_no, invoice_no, amount, tds_amount, total_amount, utr): def insert_payment(subcontractor_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr):
connection = Paymentmodel.get_connection() connection = Paymentmodel.get_connection()
if not connection: if not connection:
return False return False
try:
cursor = connection.cursor()
cursor.callproc('InsertPayments', [pmc_no, invoice_no, amount, tds_amount, total_amount, utr])
connection.commit()
return True
except mysql.connector.Error as e:
print(f"Error inserting payment: {e}")
return False
finally:
cursor.close()
connection.close()
@staticmethod cursor = None
def update_inpayment(subcontractor_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr):
connection = Paymentmodel.get_connection()
if not connection:
return False
try: try:
cursor = connection.cursor() cursor = connection.cursor()
cursor.callproc('UpdateInpaymentRecord', [
subcontractor_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr cursor.callproc('GetInvoiceId', [subcontractor_id, pmc_no, invoice_no])
])
invoice_id = None
for result in cursor.stored_results():
row = result.fetchone()
if row:
invoice_id = row[0]
if not invoice_id:
return False
cursor.callproc(
'InsertPayments',
[pmc_no, invoice_no, amount, tds_amount, total_amount, utr, invoice_id]
)
connection.commit() connection.commit()
return True return True
except mysql.connector.Error as e:
print(f"Error updating inpayment: {e}") except Exception as e:
print(e)
return False return False
finally: finally:
cursor.close() if cursor:
connection.close() cursor.close()
if connection:
connection.close()
@staticmethod @staticmethod
def fetch_payment_by_id(payment_id): def fetch_payment_by_id(payment_id):
@@ -133,9 +136,7 @@ class Paymentmodel:
# Delete payment # Delete payment
cursor.callproc("DeletePayment", (payment_id,)) cursor.callproc("DeletePayment", (payment_id,))
connection.commit() connection.commit()
# Reset inpayment fields
cursor.callproc("ResetInpayment", [pmc_no, invoice_no])
connection.commit()
return True, pmc_no, invoice_no return True, pmc_no, invoice_no
except mysql.connector.Error as e: except mysql.connector.Error as e:
print(f"Error deleting payment: {e}") print(f"Error deleting payment: {e}")

View File

@@ -15,17 +15,21 @@
<button id="addButton" class="action-button">Add</button> <button id="addButton" class="action-button">Add</button>
<button id="displayButton" class="action-button">Display</button> <button id="displayButton" class="action-button">Display</button>
</div> </div>
<div id="addForm" style="display: none;"> <div id="addForm" style="display: none;">
<h2>Add GST Release</h2> <h2>Add GST Release</h2>
<form action="/add_gst_release" method="POST" onsubmit="showSuccessAlert(event)"> <form action="/add_gst_release" method="POST" onsubmit="showSuccessAlert(event)">
<div class="row1"> <div class="row1">
<div> <div>
<label for="subcontractor">Subcontractor Name:</label> <label for="subcontractor">Subcontractor Name:</label>
<input type="text" id="subcontractor" name="subcontractor" required autocomplete="off"/> <!-- Text input for user-friendly autocomplete -->
<input type="hidden" id="subcontractor_id" name="subcontractor_id"/> <input type="text" id="subcontractor" name="subcontractor" required autocomplete="off"/>
<div id="subcontractor_list" class="autocomplete-items"></div>
</div> <!-- Hidden input for backend; must match model's Contractor_ID -->
<input type="hidden" id="subcontractor_id" name="Contractor_ID"/>
<div id="subcontractor_list" class="autocomplete-items"></div>
</div>
</div> </div>
<label for="PMC_No">PMC No:</label><br> <label for="PMC_No">PMC No:</label><br>
@@ -37,19 +41,19 @@
</select><br><br> </select><br><br>
<label for="invoice_No">Invoice No:</label><br> <label for="invoice_No">Invoice No:</label><br>
<input type="text" id="invoice_No" name="invoice_No" required><br><br> <input type="text" id="invoice_No" name="Invoice_No" required><br><br>
<label for="basic_amount">Basic Amount:</label><br> <label for="basic_amount">Basic Amount:</label><br>
<input type="number" step="0.01" id="basic_amount" name="basic_amount" placeholder="₹ - 00.00" required><br><br> <input type="number" step="0.01" id="basic_amount" name="Basic_Amount" placeholder="₹ - 00.00" required><br><br>
<label for="final_amount">Final Amount:</label><br> <label for="final_amount">Final Amount:</label><br>
<input type="number" step="0.01" id="final_amount" name="final_amount" placeholder="₹ - 00.00" required><br><br> <input type="number" step="0.01" id="final_amount" name="Final_Amount" placeholder="₹ - 00.00" required><br><br>
<label for="total_amount">Total Amount:</label><br> <label for="total_amount">Total Amount:</label><br>
<input type="number" step="0.01" id="total_amount" name="total_amount" placeholder="₹ - 00.00" required><br><br> <input type="number" step="0.01" id="total_amount" name="Total_Amount" placeholder="₹ - 00.00" required><br><br>
<label for="utr">UTR:</label><br> <label for="utr">UTR:</label><br>
<input type="text" id="utr" name="utr" required><br><br> <input type="text" id="utr" name="UTR" required><br><br>
<button type="submit">Submit GST Release</button> <button type="submit">Submit GST Release</button>
</form> </form>
@@ -117,46 +121,61 @@
<script> <script>
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
// Handle subcontractor autocomplete
document.getElementById("subcontractor").addEventListener("input", function () { const subcontractorInput = document.getElementById("subcontractor");
const subcontractorIdInput = document.getElementById("subcontractor_id");
const subcontractorList = document.getElementById("subcontractor_list");
const pmcDropdown = document.getElementById("PMC_No");
const form = document.querySelector('form');
// --------------------------
// Subcontractor autocomplete
// --------------------------
subcontractorInput.addEventListener("input", function () {
const query = this.value; const query = this.value;
const list = document.getElementById("subcontractor_list");
if (query.length < 2) { if (query.length < 2) {
list.innerHTML = ''; subcontractorList.innerHTML = '';
subcontractorIdInput.value = ''; // reset hidden id
pmcDropdown.innerHTML = '<option value="">Select PMC No</option>'; // reset PMC dropdown
return; return;
} }
fetch(`/search_subcontractor?query=${encodeURIComponent(query)}`) fetch(`/search_subcontractor?query=${encodeURIComponent(query)}`)
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
list.innerHTML = ''; subcontractorList.innerHTML = '';
data.results.forEach(item => { data.results.forEach(item => {
const div = document.createElement("div"); const div = document.createElement("div");
div.setAttribute("data-id", item.id); div.setAttribute("data-id", item.id);
div.textContent = item.name; div.textContent = item.name;
list.appendChild(div); subcontractorList.appendChild(div);
}); });
}); });
}); });
// Handle subcontractor selection // --------------------------
document.getElementById("subcontractor_list").addEventListener("click", function (e) { // Subcontractor selection
// --------------------------
subcontractorList.addEventListener("click", function (e) {
const selectedId = e.target.getAttribute("data-id"); const selectedId = e.target.getAttribute("data-id");
const selectedName = e.target.textContent; const selectedName = e.target.textContent;
if (selectedId) { if (selectedId) {
document.getElementById("subcontractor_id").value = selectedId; // Set hidden field for backend
document.getElementById("subcontractor").value = selectedName; subcontractorIdInput.value = selectedId;
document.getElementById("subcontractor_list").innerHTML = "";
// Update PMC dropdown for selected subcontractor // Set text input to selected name
subcontractorInput.value = selectedName;
// Clear the autocomplete list
subcontractorList.innerHTML = "";
// Fetch and populate PMC dropdown
fetch(`/get_pmc_nos_by_subcontractor/${encodeURIComponent(selectedId)}`) fetch(`/get_pmc_nos_by_subcontractor/${encodeURIComponent(selectedId)}`)
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
const pmcDropdown = document.getElementById("PMC_No");
pmcDropdown.innerHTML = '<option value="">Select PMC No</option>'; pmcDropdown.innerHTML = '<option value="">Select PMC No</option>';
data.pmc_nos.forEach(pmc => { data.pmc_nos.forEach(pmc => {
const option = document.createElement("option"); const option = document.createElement("option");
option.value = pmc; option.value = pmc;
@@ -166,6 +185,22 @@ document.addEventListener('DOMContentLoaded', function() {
}); });
} }
}); });
// --------------------------
// Form submit validation
// --------------------------
form.addEventListener('submit', function(e) {
if (!subcontractorIdInput.value) {
e.preventDefault();
alert("Please select a subcontractor from the list.");
subcontractorInput.focus();
} else if (!pmcDropdown.value) {
e.preventDefault();
alert("Please select a PMC No.");
pmcDropdown.focus();
}
});
}); });
</script> </script>

View File

@@ -9,37 +9,37 @@
<body> <body>
<h2>Edit GST Release</h2> <h2>Edit GST Release</h2>
<form action="/edit_gst_release/{{ gst_release_data[0] }}" method="POST"> <form action="/edit_gst_release/{{ gst_release_data.gst_release_id }}" method="POST">
<!-- <label for="invoice_id">Invoice Id:</label><br>-->
<!-- <input type="number" id="invoice_id" name="invoice_id" value="{{ gst_release_data[0] }}" required><br><br>-->
<!-- PMC Number -->
<label for="PMC_No">PMC No :</label><br> <label for="PMC_No">PMC No :</label><br>
<input type="number" id="PMC_No" name="PMC_No" value="{{ gst_release_data[1] }}" required><br><br> <input type="text" id="PMC_No" name="PMC_No" value="{{ gst_release_data.pmc_no }}" required><br><br>
<label for="invoice_No">Invoice No:</label><br> <!-- Invoice Number -->
<input type="number" step="0.01" id="invoice_No" name="invoice_No" value="{{ gst_release_data[2] }}" <label for="invoice_no">Invoice No:</label><br>
required><br><br> <input type="text" id="invoice_no" name="invoice_no" value="{{ gst_release_data.invoice_no }}" required><br><br>
<!-- Basic Amount -->
<label for="Basic_Amount">Basic Amount:</label><br>
<input type="number" step="0.01" id="Basic_Amount" name="Basic_Amount" value="{{ gst_release_data.basic_amount }}" required><br><br>
<label for="basic_amount">Basic Amount:</label><br> <!-- Final Amount -->
<input type="number" step="0.01" id="basic_amount" name="basic_amount" value="{{ gst_release_data[3] }}" <label for="Final_Amount">Final Amount:</label><br>
required><br><br> <input type="number" step="0.01" id="Final_Amount" name="Final_Amount" value="{{ gst_release_data.final_amount }}" required><br><br>
<label for="final_amount">Final Amount:</label><br> <!-- Total Amount -->
<input type="number" step="0.01" id="final_amount" name="final_amount" value="{{ gst_release_data[4] }}" <label for="Total_Amount">Total Amount:</label><br>
required><br><br> <input type="number" step="0.01" id="Total_Amount" name="Total_Amount" value="{{ gst_release_data.total_amount }}" required><br><br>
<label for="total_amount">Total Amount:</label><br> <!-- UTR -->
<input type="number" step="0.01" id="total_amount" name="total_amount" value="{{ gst_release_data[5] }}" <label for="UTR">UTR:</label><br>
required><br><br> <input type="text" id="UTR" name="UTR" value="{{ gst_release_data.utr }}" readonly required><br><br>
<label for="utr">UTR:</label><br> <!-- Hidden Contractor ID -->
<input type="text" id="utr" name="utr" value="{{ gst_release_data[6] }}" <input type="hidden" id="Contractor_ID" name="Contractor_ID" value="{{ gst_release_data.contractor_id }}">
required readonly><br><br>
<button type="submit">Update GST Release</button> <button type="submit">Update GST Release</button>
</form> </form>
</body> </body>
{% endblock %} {% endblock %}

View File

@@ -118,7 +118,7 @@
{% for invoice in invoices %} {% for invoice in invoices %}
<tr> <tr>
<td>{{ invoice.PMC_No }}</td> <td>{{ invoice.PMC_No }}</td>
<td>{{ invoice.Village_Name.capitalize() }}</td> <td>{{ invoice.Village_Name.capitalize() if invoice.Village_Name else '' }}</td>
<td>{{ invoice.Work_Type }}</td> <td>{{ invoice.Work_Type }}</td>
<td>{{ invoice.Invoice_Details }}</td> <td>{{ invoice.Invoice_Details }}</td>
<td>{{ invoice.Invoice_Date }}</td> <td>{{ invoice.Invoice_Date }}</td>