Compare commits
6 Commits
1946a98d59
...
pankaj-dev
| Author | SHA1 | Date | |
|---|---|---|---|
| 055b272703 | |||
| 73cd97f3c8 | |||
| 0b72adef7d | |||
| 88e8771b51 | |||
| 6c74b5d3bf | |||
| 47ba78d72c |
@@ -6,7 +6,6 @@ from model.Log import LogHelper
|
||||
|
||||
auth_bp = Blueprint('auth', __name__)
|
||||
|
||||
|
||||
@auth_bp.route('/login', methods=['GET', 'POST'])
|
||||
def login():
|
||||
|
||||
|
||||
@@ -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'))
|
||||
@@ -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':
|
||||
|
||||
@@ -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():
|
||||
@@ -229,7 +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)
|
||||
# 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))
|
||||
@@ -242,11 +244,11 @@ 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)
|
||||
# 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,
|
||||
@@ -255,22 +257,39 @@ def save_data():
|
||||
subcontractor_id, 0
|
||||
)
|
||||
|
||||
print("All invoice Details ",args)
|
||||
# print("All invoice Details ",args)
|
||||
# add subcontarctor id in invoice table
|
||||
results = cursor.callproc('SaveInvoice', args)
|
||||
invoice_id = results[-1]
|
||||
print("invoice id from the excel ", 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:
|
||||
print(f"Processing hold: {hold}")
|
||||
# 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) # 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}")
|
||||
# print(f"Processing hold type: {hold_column_name}, Hold Amount: {hold_amount}")
|
||||
hold_join_data = {
|
||||
"Contractor_Id": subcontractor_id,
|
||||
"Invoice_Id": invoice_id,
|
||||
@@ -288,9 +307,9 @@ def save_data():
|
||||
else:
|
||||
print("Hold columns data is not a valid list of dictionaries.")
|
||||
#---------------------------------------------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)
|
||||
elif any(keyword in Invoice_Details.lower() for keyword in ['credit note','logging report','credit','Credit note Details']):
|
||||
# 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',
|
||||
[
|
||||
@@ -311,56 +330,113 @@ def save_data():
|
||||
'excess hold amount',
|
||||
'Multi to Single layer bill',
|
||||
'hold amount',
|
||||
'logging report'
|
||||
'logging report',
|
||||
'hold'
|
||||
]
|
||||
# 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', 'note']):
|
||||
print("Gst rels :", PMC_No, Invoice_No, Basic_Amount, Final_Amount,Total_Amount,UTR, subcontractor_id)
|
||||
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)
|
||||
cursor.callproc(
|
||||
'AddGSTReleaseFromExcel',
|
||||
[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 )
|
||||
cursor.callproc("SavePayment",(PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR ))
|
||||
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,
|
||||
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 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()
|
||||
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, # required
|
||||
Payment_Amount,
|
||||
TDS_Payment_Amount,
|
||||
Total_Amount,
|
||||
UTR,
|
||||
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:
|
||||
|
||||
@@ -5,12 +5,12 @@ 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)
|
||||
@@ -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,7 +39,7 @@ def check_hold_type():
|
||||
@login_required
|
||||
def edit_hold_type(id):
|
||||
|
||||
hold = HoldTypes()
|
||||
# hold = HoldTypes()
|
||||
|
||||
if request.method == 'POST':
|
||||
hold.EditHoldType(request, id) # ✅
|
||||
@@ -58,7 +58,7 @@ def edit_hold_type(id):
|
||||
@login_required
|
||||
def delete_hold_type(id):
|
||||
|
||||
hold = HoldTypes()
|
||||
# hold = HoldTypes()
|
||||
hold.DeleteHoldType(request, id) # ✅
|
||||
|
||||
return redirect(url_for("hold_types.add_hold_type"))
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
|
||||
|
||||
|
||||
# controllers/invoice_controller.py
|
||||
|
||||
from flask import Blueprint, request, jsonify, render_template
|
||||
@@ -40,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')}'")
|
||||
@@ -83,7 +84,7 @@ def edit_invoice(invoice_id):
|
||||
if request.method == 'POST':
|
||||
data = request.form
|
||||
update_invoice(data, invoice_id)
|
||||
update_inpayment(data)
|
||||
# update_inpayment(data)
|
||||
log_action("Edit invoice", f"edited invoice '{invoice_id}'")
|
||||
return jsonify({"status": "success", "message": "Invoice updated successfully"}), 200
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ def activity_log():
|
||||
end_date,
|
||||
user_name
|
||||
)
|
||||
|
||||
return render_template(
|
||||
"activity_log.html",
|
||||
logs=filtered_logs,
|
||||
|
||||
@@ -28,8 +28,8 @@ def add_payment():
|
||||
utr = request.form['utr']
|
||||
|
||||
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.update_inpayment(subcontractor_id, 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'))
|
||||
|
||||
@@ -72,15 +72,13 @@ def edit_payment(payment_id):
|
||||
Paymentmodel.call_update_payment_proc(payment_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr)
|
||||
|
||||
# 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()
|
||||
# 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'))
|
||||
|
||||
|
||||
@@ -1,40 +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/<pmc_no>")
|
||||
# @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/<pmc_no>")
|
||||
@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/<pmc_no>")
|
||||
# @login_required
|
||||
# def download_pmc_report(pmc_no):
|
||||
|
||||
# ---------------- Contractor Download Report by pmc no ----------------
|
||||
@pmc_report_bp.route("/download_pmc_report/<pmc_no>")
|
||||
@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)
|
||||
@@ -1,13 +1,10 @@
|
||||
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 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
|
||||
@@ -20,28 +17,45 @@ 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/<int:contractor_id>')
|
||||
@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/<pmc_no>")
|
||||
@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 ----------------
|
||||
@@ -49,5 +63,24 @@ def contractor_report(contractor_id):
|
||||
@login_required
|
||||
def download_report(contractor_id):
|
||||
|
||||
return ReportHelper().download_report(contractor_id=contractor_id)
|
||||
|
||||
service = ReportService(contractor_id=contractor_id).load_data()
|
||||
|
||||
file, error = service.download_excel()
|
||||
|
||||
if error:
|
||||
return error, 404
|
||||
|
||||
return send_file(file, as_attachment=True)
|
||||
|
||||
# ---------------- Contractor Download Report by pmc no ----------------
|
||||
@report_bp.route("/download_pmc_report/<pmc_no>")
|
||||
@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)
|
||||
@@ -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':
|
||||
|
||||
|
||||
@@ -11,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)
|
||||
@@ -79,14 +79,14 @@ 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/<int:village_id>')
|
||||
@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
|
||||
@@ -112,7 +112,7 @@ def delete_village(village_id):
|
||||
@login_required
|
||||
def edit_village(village_id):
|
||||
|
||||
village = Village()
|
||||
# village = Village()
|
||||
|
||||
if request.method == 'POST':
|
||||
|
||||
|
||||
4
main.py
4
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 ----------------
|
||||
|
||||
@@ -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.Log import LogData, LogHelper
|
||||
|
||||
import os
|
||||
import config
|
||||
import re
|
||||
|
||||
import mysql.connector
|
||||
from mysql.connector import Error
|
||||
|
||||
from model.ItemCRUD import ItemCRUD, itemCRUDMapping
|
||||
from model.ItemCRUD import ItemCRUD
|
||||
|
||||
|
||||
class Block:
|
||||
@@ -22,9 +12,7 @@ class Block:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ""
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Add Block
|
||||
# ----------------------------------------------------------
|
||||
def AddBlock(self, request):
|
||||
|
||||
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||
@@ -37,17 +25,7 @@ class Block:
|
||||
self.resultMessage = block.resultMessage
|
||||
return
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# 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
|
||||
|
||||
# Get All Blocks
|
||||
def GetAllBlocks(self, request):
|
||||
|
||||
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||
@@ -57,18 +35,8 @@ class Block:
|
||||
self.resultMessage = block.resultMessage
|
||||
return blocksdata
|
||||
|
||||
# ----------------------------------------------------------
|
||||
|
||||
# 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):
|
||||
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||
data = request.get_json(silent=True) or request.form
|
||||
@@ -85,24 +53,7 @@ class Block:
|
||||
self.resultMessage = block.resultMessage
|
||||
return result
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# 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):
|
||||
|
||||
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||
@@ -116,20 +67,8 @@ class Block:
|
||||
self.resultMessage = block.resultMessage
|
||||
|
||||
return blockdata
|
||||
# ----------------------------------------------------------
|
||||
|
||||
# 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):
|
||||
|
||||
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||
@@ -149,9 +88,8 @@ class Block:
|
||||
self.resultMessage = block.resultMessage
|
||||
return
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Delete Block
|
||||
# ---------------------------------------------------------
|
||||
|
||||
# Delete Block
|
||||
def DeleteBlock(self,request, id):
|
||||
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
|
||||
|
||||
|
||||
from mysql.connector import Error
|
||||
import config
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class ContractorInfo:
|
||||
def __init__(self, contractor_id):
|
||||
|
||||
@@ -27,13 +27,27 @@ class FolderAndFile:
|
||||
os.makedirs(folder, exist_ok=True)
|
||||
return folder
|
||||
|
||||
# -----------------------------
|
||||
# FILE PATH METHODS
|
||||
# -----------------------------
|
||||
@staticmethod
|
||||
def get_logs_folder():
|
||||
folder = os.path.join(current_app.root_path, "logs")
|
||||
|
||||
if not os.path.exists(folder):
|
||||
os.makedirs(folder)
|
||||
|
||||
os.makedirs(folder, exist_ok=True)
|
||||
return folder
|
||||
|
||||
# FILE PATH METHODS - download
|
||||
@staticmethod
|
||||
def get_download_path(filename):
|
||||
return os.path.join(FolderAndFile.get_download_folder(), filename)
|
||||
|
||||
|
||||
# FILE PATH METHODS - upload file
|
||||
@staticmethod
|
||||
def get_upload_path(filename):
|
||||
return os.path.join(FolderAndFile.get_upload_folder(), filename)
|
||||
return os.path.join(FolderAndFile.get_upload_folder(), filename)
|
||||
|
||||
# FILE PATH METHODS - activity log file
|
||||
@staticmethod
|
||||
def get_activity_log_path(filename):
|
||||
return os.path.join(FolderAndFile.get_logs_folder(), filename)
|
||||
@@ -3,7 +3,6 @@ from model.ItemCRUD import ItemCRUD
|
||||
from model.Utilities import ItemCRUDType
|
||||
|
||||
class HoldTypes:
|
||||
"""CRUD operations for Hold Types using ItemCRUD"""
|
||||
|
||||
def __init__(self):
|
||||
self.isSuccess = False
|
||||
@@ -33,7 +32,7 @@ class HoldTypes:
|
||||
self.isSuccess = hold.isSuccess
|
||||
self.resultMessage = hold.resultMessage
|
||||
|
||||
# ✅ Convert tuple → dictionary
|
||||
# Convert tuple → dictionary
|
||||
data = []
|
||||
for row in rows:
|
||||
data.append({
|
||||
@@ -51,7 +50,7 @@ class HoldTypes:
|
||||
self.isSuccess = hold.isSuccess
|
||||
self.resultMessage = hold.resultMessage
|
||||
|
||||
# ✅ Convert tuple → dictionary
|
||||
# Convert tuple → dictionary
|
||||
if row:
|
||||
return {
|
||||
"hold_type_id": row[0],
|
||||
|
||||
@@ -71,22 +71,22 @@ def get_all_villages():
|
||||
def insert_invoice(data, village_id):
|
||||
def operation(cursor):
|
||||
# Insert invoice
|
||||
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)
|
||||
])
|
||||
invoice_row = fetch_one(cursor)
|
||||
if not invoice_row:
|
||||
raise Exception("Invoice ID not returned")
|
||||
invoice_id = invoice_row.get('invoice_id')
|
||||
# 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')
|
||||
|
||||
# Insert inpayment
|
||||
cursor.callproc('InsertInpayment', [
|
||||
# ])
|
||||
# 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'),
|
||||
@@ -94,9 +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
|
||||
])
|
||||
clear_results(cursor)
|
||||
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)
|
||||
@@ -141,18 +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 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):
|
||||
@@ -173,22 +191,22 @@ def delete_invoice_data(invoice_id, user_id):
|
||||
clear_results(cursor)
|
||||
|
||||
# Delete inpayment
|
||||
cursor.callproc('DeleteInpaymentByPMCInvoice', (pmc_no, invoice_no))
|
||||
clear_results(cursor)
|
||||
# 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 -------------------
|
||||
|
||||
@@ -232,14 +232,13 @@ class ItemCRUD:
|
||||
if self.itemCRUDType.name == "GSTRelease" and data:
|
||||
|
||||
cursor.callproc(storedprocupdate, (
|
||||
childid,
|
||||
data['PMC_No'],
|
||||
data['Invoice_No'],
|
||||
data['Basic_Amount'],
|
||||
data['Final_Amount'],
|
||||
data['Total_Amount'],
|
||||
data['UTR'],
|
||||
data['Contractor_ID']
|
||||
data['p_pmc_no'], # PMC_No
|
||||
data['p_invoice_no'], # Invoice_No
|
||||
data['p_basic_amount'], # Basic_Amount
|
||||
data['p_final_amount'], # Final_Amount
|
||||
data['p_total_amount'], # Total_Amount
|
||||
data['p_utr'], # UTR
|
||||
data['p_gst_release_id']# GST_Release_Id
|
||||
))
|
||||
connection.commit()
|
||||
|
||||
|
||||
119
model/Log.py
119
model/Log.py
@@ -1,29 +1,40 @@
|
||||
import os
|
||||
from datetime import datetime
|
||||
from flask import current_app
|
||||
from flask_login import current_user
|
||||
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from model.FolderAndFile import FolderAndFile
|
||||
|
||||
class LogHelper:
|
||||
@staticmethod
|
||||
def log_action(action, details=""):
|
||||
"""Add a log entry."""
|
||||
log_data = LogData()
|
||||
log_data.add_log(action, details)
|
||||
|
||||
"""Log user actions with timestamp, user, action, and details."""
|
||||
logData = LogData()
|
||||
logData.WriteLog(action, details="")
|
||||
|
||||
class LogData:
|
||||
filepath = ""
|
||||
timestamp = None
|
||||
|
||||
def __init__(self):
|
||||
self.filepath = os.path.join(current_app.root_path, 'activity.log')
|
||||
self.filepath = FolderAndFile.get_activity_log_path('activity.log')
|
||||
self.timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
self.user = getattr(current_user, "cn", None) \
|
||||
or getattr(current_user, "username", None) \
|
||||
or getattr(current_user, "sAMAccountName", "Unknown")
|
||||
self.user = LogData.get_current_user()
|
||||
|
||||
|
||||
def add_log(self, action, details=""):
|
||||
"""Create/Add a log entry."""
|
||||
@staticmethod
|
||||
def get_current_user():
|
||||
if hasattr(current_user, "cn") and current_user.cn:
|
||||
return current_user.cn
|
||||
elif hasattr(current_user, "username") and current_user.username:
|
||||
return current_user.username
|
||||
elif hasattr(current_user, "sAMAccountName") and current_user.sAMAccountName:
|
||||
return current_user.sAMAccountName
|
||||
return "Unknown"
|
||||
|
||||
def WriteLog(self, action, details=""):
|
||||
"""Log user actions with timestamp, user, action, and details."""
|
||||
|
||||
with open(self.filepath, "a", encoding="utf-8") as f:
|
||||
f.write(
|
||||
f"Timestamp: {self.timestamp} | "
|
||||
@@ -32,73 +43,41 @@ class LogData:
|
||||
f"Details: {details}\n"
|
||||
)
|
||||
|
||||
def get_all_logs(self):
|
||||
"""Read all logs."""
|
||||
def GetActivitiesLog(self):
|
||||
logs = []
|
||||
|
||||
if os.path.exists(self.filepath):
|
||||
with open(self.filepath, 'r', encoding="utf-8") as f:
|
||||
with open(self.filepath, 'r') as f:
|
||||
for line in f:
|
||||
parts = line.strip().split(" | ")
|
||||
if len(parts) == 4:
|
||||
logs.append({
|
||||
"timestamp": parts[0].split(":", 1)[1].strip(),
|
||||
"user": parts[1].split(":", 1)[1].strip(),
|
||||
"action": parts[2].split(":", 1)[1].strip(),
|
||||
"details": parts[3].split(":", 1)[1].strip()
|
||||
"timestamp": parts[0].replace("Timestamp:", "").strip(),
|
||||
"user": parts[1].replace("User:", "").strip(),
|
||||
"action": parts[2].replace("Action:", "").strip(),
|
||||
"details": parts[3].replace("Details:", "").strip()
|
||||
})
|
||||
return logs
|
||||
|
||||
def get_filtered_logs(self, start_date=None, end_date=None, user_name=None):
|
||||
"""Filter logs by date and/or user."""
|
||||
logs = self.get_all_logs()
|
||||
def GetFilteredActivitiesLog(self, startDate, endDate, userName):
|
||||
filtered_logs = self.GetActivitiesLog()
|
||||
|
||||
# Filter by date
|
||||
if start_date or end_date:
|
||||
start_dt = datetime.strptime(start_date, "%Y-%m-%d") if start_date else datetime.min
|
||||
end_dt = datetime.strptime(end_date, "%Y-%m-%d") if end_date else datetime.max
|
||||
logs = [
|
||||
log for log in logs
|
||||
if start_dt <= datetime.strptime(log["timestamp"], "%Y-%m-%d %H:%M:%S") <= end_dt
|
||||
]
|
||||
# Date filter
|
||||
if startDate or endDate:
|
||||
try:
|
||||
start_dt = datetime.strptime(startDate, "%Y-%m-%d") if startDate else datetime.min
|
||||
end_dt = datetime.strptime(endDate, "%Y-%m-%d") if endDate else datetime.max
|
||||
|
||||
# Filter by username
|
||||
if user_name:
|
||||
logs = [log for log in logs if user_name.lower() in log.get("user", "").lower()]
|
||||
|
||||
return logs
|
||||
|
||||
def update_log(self, index, action=None, details=None):
|
||||
"""Update a specific log entry by index (0-based)."""
|
||||
logs = self.get_all_logs()
|
||||
if 0 <= index < len(logs):
|
||||
if action:
|
||||
logs[index]["action"] = action
|
||||
if details:
|
||||
logs[index]["details"] = details
|
||||
self._rewrite_logs_file(logs)
|
||||
return True
|
||||
return False
|
||||
|
||||
def delete_log(self, index):
|
||||
"""Delete a specific log entry by index (0-based)."""
|
||||
logs = self.get_all_logs()
|
||||
if 0 <= index < len(logs):
|
||||
logs.pop(index)
|
||||
self._rewrite_logs_file(logs)
|
||||
return True
|
||||
return False
|
||||
|
||||
# ------------------- INTERNAL HELPER -------------------
|
||||
|
||||
def _rewrite_logs_file(self, logs):
|
||||
"""Overwrite the log file with current logs."""
|
||||
with open(self.filepath, "w", encoding="utf-8") as f:
|
||||
for log in logs:
|
||||
f.write(
|
||||
f"Timestamp: {log['timestamp']} | "
|
||||
f"User: {log['user']} | "
|
||||
f"Action: {log['action']} | "
|
||||
f"Details: {log['details']}\n"
|
||||
)
|
||||
filtered_logs = [
|
||||
log for log in filtered_logs
|
||||
if start_dt <= datetime.strptime(log["timestamp"], "%Y-%m-%d %H:%M:%S") <= end_dt
|
||||
]
|
||||
|
||||
except Exception as e:
|
||||
print("Date filter error:", e)
|
||||
|
||||
# Username filter
|
||||
if userName:
|
||||
filtered_logs = [log for log in filtered_logs if userName.lower() in log["user"].lower()]
|
||||
|
||||
return filtered_logs
|
||||
@@ -1,456 +1,137 @@
|
||||
import openpyxl
|
||||
from openpyxl.styles import Font, PatternFill
|
||||
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):
|
||||
# @staticmethod
|
||||
# def get_pmc_report(pmc_no):
|
||||
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor(dictionary=True, buffered=True)
|
||||
# connection = config.get_db_connection()
|
||||
# cursor = connection.cursor(dictionary=True, buffered=True)
|
||||
|
||||
try:
|
||||
# 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("GetContractorInfoByPmcNo", (pmc_no,))
|
||||
# pmc_info = next(cursor.stored_results()).fetchone()
|
||||
pmc_info = ReportHelper.execute_sp(cursor, 'GetContractorInfoByPmcNo', [pmc_no], True)
|
||||
# # Extract hold_type_ids
|
||||
# hold_type_ids = [ht['hold_type_id'] for ht in hold_types]
|
||||
|
||||
if not pmc_info:
|
||||
return None
|
||||
# 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()
|
||||
|
||||
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]
|
||||
|
||||
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()
|
||||
|
||||
if hold_type_ids:
|
||||
hold_amount_total = sum(row.get('hold_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
|
||||
# cursor.callproc('GetGSTReleaseByPMC', [pmc_no])
|
||||
# gst_rel = []
|
||||
# for result in cursor.stored_results():
|
||||
# gst_rel = result.fetchall()
|
||||
# gst_rel = GeneralUse.execute_sp(cursor, 'GetGSTReleaseByPMC', [pmc_no])
|
||||
|
||||
# hold_release = GeneralUse.execute_sp(cursor, 'GetHoldReleaseByPMC', [pmc_no])
|
||||
|
||||
gst_rel = ReportHelper.execute_sp(cursor, 'GetGSTReleaseByPMC', [pmc_no])
|
||||
# credit_note = GeneralUse.execute_sp(cursor, 'GetCreditNoteByPMC', [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)
|
||||
# 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)
|
||||
# }
|
||||
|
||||
# ---------------- HOLD RELEASE ----------------
|
||||
# cursor.callproc('GetHoldReleaseByPMC', [pmc_no])
|
||||
# hold_release = []
|
||||
# for result in cursor.stored_results():
|
||||
# hold_release = result.fetchall()
|
||||
# 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
|
||||
# }
|
||||
|
||||
hold_release = ReportHelper.execute_sp(cursor, 'GetHoldReleaseByPMC', [pmc_no])
|
||||
# finally:
|
||||
# cursor.close()
|
||||
# connection.close()
|
||||
|
||||
# ---------------- 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])
|
||||
|
||||
payments = ReportHelper.execute_sp(cursor, 'GetPaymentsByPMC', [pmc_no])
|
||||
|
||||
|
||||
# ---------------- PAYMENTS ----------------
|
||||
# cursor.callproc('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_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()
|
||||
|
||||
|
||||
@staticmethod
|
||||
def download_pmc_report(pmc_no):
|
||||
|
||||
connection = config.get_db_connection()
|
||||
if not connection:
|
||||
return None
|
||||
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
||||
try:
|
||||
# filename
|
||||
filename = f"PMC_Report_{pmc_no}.xlsx"
|
||||
|
||||
output_folder = FolderAndFile.get_download_folder()
|
||||
output_file = FolderAndFile.get_download_path(filename)
|
||||
|
||||
# ================= DATA FETCH =================
|
||||
|
||||
contractor_info = ReportHelper.execute_sp(cursor, 'GetContractorDetailsByPMC', [pmc_no], "one")
|
||||
|
||||
if not contractor_info:
|
||||
return None
|
||||
|
||||
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}
|
||||
|
||||
invoices = ReportHelper.execute_sp(cursor, 'GetInvoicesAndGstReleaseByPmcNo', [pmc_no])
|
||||
|
||||
credit_notes = ReportHelper.execute_sp(cursor, 'GetCreditNoteByContractor', [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])
|
||||
|
||||
# ================= DATA MAPPING =================
|
||||
|
||||
hold_data = {}
|
||||
for h in hold_amounts:
|
||||
hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
||||
|
||||
payments_map = {}
|
||||
for pay in all_payments:
|
||||
if pay['invoice_no']:
|
||||
payments_map.setdefault(pay['invoice_no'], []).append(pay)
|
||||
|
||||
# ================= 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"
|
||||
|
||||
# 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([])
|
||||
|
||||
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)
|
||||
|
||||
# STYLE
|
||||
for cell in sheet[sheet.max_row]:
|
||||
cell.font = Font(bold=True)
|
||||
|
||||
# DATA
|
||||
seen_invoices = set()
|
||||
|
||||
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 = [
|
||||
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"]
|
||||
]
|
||||
|
||||
# HOLD DATA
|
||||
invoice_holds = hold_data.get(inv["Invoice_Id"], {})
|
||||
for ht_id in hold_type_map.keys():
|
||||
row.append(invoice_holds.get(ht_id, ""))
|
||||
|
||||
# PAYMENT DATA
|
||||
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)
|
||||
|
||||
# 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
|
||||
|
||||
# SAVE
|
||||
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()
|
||||
|
||||
# @staticmethod
|
||||
# def download_pmc_report(pmc_no):
|
||||
|
||||
# connection = config.get_db_connection()
|
||||
# if not connection:
|
||||
# return None
|
||||
|
||||
# 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:
|
||||
# filename = f"PMC_Report_{pmc_no}.xlsx"
|
||||
|
||||
# cursor.callproc('GetContractorDetailsByPMC', [pmc_no])
|
||||
# contractor_info = next(cursor.stored_results()).fetchone()
|
||||
# output_folder = FolderAndFile.get_download_folder()
|
||||
# output_file = FolderAndFile.get_download_path(filename)
|
||||
|
||||
# contractor_info = GeneralUse.execute_sp(cursor, 'GetContractorInfoByPmcNo', [pmc_no])
|
||||
|
||||
# contractor_info = contractor_info[0] if contractor_info else None
|
||||
# print("contractor_info:::",contractor_info)
|
||||
|
||||
# if not contractor_info:
|
||||
# return None
|
||||
|
||||
# cursor.callproc('GetHoldTypesByContractor', [contractor_info["Contractor_Id"]])
|
||||
# hold_types = next(cursor.stored_results()).fetchall()
|
||||
# hold_types = GeneralUse.execute_sp(cursor, 'GetHoldTypesByContractor',[contractor_info["Contractor_Id"]])
|
||||
|
||||
# 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()
|
||||
# invoices = GeneralUse.execute_sp(cursor, 'GetInvoicesByContractorOrPMCNo', [None,pmc_no])
|
||||
|
||||
# credit_notes = GeneralUse.execute_sp(cursor, 'NewGetCreditNotesByPMCNo', [pmc_no])
|
||||
# credit_note_map = {}
|
||||
# for cn in credit_notes:
|
||||
# key = (cn["PMC_No"], cn["Invoice_No"])
|
||||
|
||||
# key = (str(cn['PMC_No']).strip())
|
||||
# credit_note_map.setdefault(key, []).append(cn)
|
||||
|
||||
# cursor.callproc('GetHoldAmountsByContractor', [contractor_info["Contractor_Id"]])
|
||||
# hold_amounts = next(cursor.stored_results()).fetchall()
|
||||
# hold_amounts = GeneralUse.execute_sp(cursor, 'GetHoldAmountsByContractor', [contractor_info["Contractor_Id"]])
|
||||
|
||||
# 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)
|
||||
|
||||
# # ================= DATA MAPPING =================
|
||||
# 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()
|
||||
# # ================= LOG =================
|
||||
# LogHelper.log_action("Download PMC Report",f"User {current_user.id} Download PMC Report '{pmc_no}'")
|
||||
|
||||
# ReportHelper.generate_excel(
|
||||
# 0, contractor_info, invoices, hold_types, hold_data,
|
||||
# credit_note_map,gst_release_map, output_file)
|
||||
|
||||
# return output_folder, filename
|
||||
|
||||
# finally:
|
||||
|
||||
# cursor.close()
|
||||
# connection.close()
|
||||
# connection.close()
|
||||
|
||||
|
||||
335
model/Report.py
335
model/Report.py
@@ -2,9 +2,10 @@ import config
|
||||
from datetime import datetime
|
||||
from flask import send_file
|
||||
import openpyxl
|
||||
from openpyxl.styles import Font
|
||||
from openpyxl.styles import Font, PatternFill
|
||||
|
||||
from model.FolderAndFile import FolderAndFile
|
||||
from services.Generalservice import GeneralUse
|
||||
|
||||
class ReportHelper:
|
||||
isSuccess = False
|
||||
@@ -16,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):
|
||||
@@ -59,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,
|
||||
@@ -71,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}")
|
||||
@@ -84,192 +57,156 @@ 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 download_report(contractor_id):
|
||||
try:
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
def get_contractor_info(contractor_id):
|
||||
from model.ContractorInfo import ContractorInfo
|
||||
contractor = ContractorInfo(contractor_id)
|
||||
return contractor.contInfo if contractor.contInfo else None
|
||||
|
||||
# -------- Contractor Info --------
|
||||
contInfo = ReportHelper.execute_sp(cursor, 'GetContractorInfo', [contractor_id], True)
|
||||
|
||||
if not contInfo:
|
||||
return "No contractor found", 404
|
||||
# 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"
|
||||
|
||||
# -------- Invoice Data --------
|
||||
cursor.callproc('FetchInvoicesByContractor', [contractor_id])
|
||||
# Contractor Info
|
||||
for field, value in contInfo.items():
|
||||
sheet.append([field.replace("_", " "), value])
|
||||
sheet.append([])
|
||||
|
||||
invoices = []
|
||||
for result in cursor.stored_results():
|
||||
invoices.extend(result.fetchall())
|
||||
# Headers
|
||||
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"]
|
||||
|
||||
if not invoices:
|
||||
return "No invoice data found"
|
||||
hold_headers = [ht['hold_type'] for ht in hold_types]
|
||||
|
||||
# -------- Create Workbook --------
|
||||
workbook = openpyxl.Workbook()
|
||||
sheet = workbook.active
|
||||
sheet.title = "Contractor Report"
|
||||
payment_headers = ["Final Amount", "Payment Amount", "TDS Payment", "Total Paid", "UTR"]
|
||||
|
||||
# ================= CONTRACTOR DETAILS =================
|
||||
sheet.append(["SUB CONTRACTOR DETAILS"])
|
||||
sheet.cell(row=sheet.max_row, column=1).font = Font(bold=True)
|
||||
sheet.append([])
|
||||
all_headers = base_headers + hold_headers + payment_headers
|
||||
sheet.append(all_headers)
|
||||
|
||||
sheet.append(["Name", contInfo.get("Contractor_Name") or ""])
|
||||
sheet.append(["Mobile No", contInfo.get("Mobile_No") or ""])
|
||||
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([])
|
||||
for cell in sheet[sheet.max_row]:
|
||||
cell.font = Font(bold=True)
|
||||
cell.fill = PatternFill(start_color="ADD8E6", end_color="ADD8E6", fill_type="solid")
|
||||
|
||||
# ================= TABLE HEADERS =================
|
||||
headers = [
|
||||
"PMC No", "Village", "Invoice No", "Invoice Date", "Work Type","Invoice_Details",
|
||||
"Basic Amount", "Debit Amount", "After Debit Amount",
|
||||
"Amount", "GST Amount", "TDS Amount", "SD Amount",
|
||||
"On Commission", "Hydro Testing", "Hold Amount",
|
||||
"GST SD Amount", "Final Amount",
|
||||
"Payment Amount", "TDS Payment",
|
||||
"Total Amount", "UTR"
|
||||
processed_gst_releases = set()
|
||||
appended_credit_keys = set()
|
||||
previous_pmc_no = None
|
||||
|
||||
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 =================
|
||||
total_final = 0
|
||||
total_payment = 0
|
||||
total_amount = 0
|
||||
# Hold values
|
||||
invoice_holds = hold_data.get(inv["Invoice_Id"], {})
|
||||
for ht_id in [ht['hold_type_id'] for ht in hold_types]:
|
||||
row.append(invoice_holds.get(ht_id, ""))
|
||||
|
||||
for inv in invoices:
|
||||
row = [
|
||||
inv.get("PMC_No"),
|
||||
inv.get("Village_Name"),
|
||||
inv.get("invoice_no"),
|
||||
inv.get("Invoice_Date"),
|
||||
inv.get("Work_Type"),
|
||||
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")
|
||||
]
|
||||
# Payment values
|
||||
row += [
|
||||
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)
|
||||
total_payment += float(inv.get("Payment_Amount") or 0)
|
||||
total_amount += float(inv.get("Total_Amount") or 0)
|
||||
sheet.append(row)
|
||||
|
||||
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 =================
|
||||
sheet.append([])
|
||||
sheet.append([
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"TOTAL",
|
||||
total_final,
|
||||
total_payment,
|
||||
"",
|
||||
total_amount,
|
||||
""
|
||||
])
|
||||
gst_row += [""] * len(hold_headers)
|
||||
|
||||
# ================= 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
|
||||
gst_row += [
|
||||
gr.get("Final_Amount", ""),
|
||||
"",
|
||||
"",
|
||||
gr.get("Total_Amount", ""),
|
||||
gr.get("UTR", "")
|
||||
]
|
||||
|
||||
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)
|
||||
|
||||
# ================= 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)
|
||||
@@ -1,7 +1,6 @@
|
||||
from model.Utilities import ItemCRUDType
|
||||
from model.ItemCRUD import ItemCRUD
|
||||
|
||||
|
||||
class Subcontractor:
|
||||
def __init__(self):
|
||||
self.isSuccess = False
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -13,14 +13,14 @@ class Village:
|
||||
def __init__(self):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ""
|
||||
self.response = {} # ✅ ADDED
|
||||
self.response = {}
|
||||
self.village = ItemCRUD(itemType=ItemCRUDType.Village)
|
||||
|
||||
# 🔹 Helper: sync status
|
||||
def _set_status(self, village):
|
||||
self.isSuccess = village.isSuccess
|
||||
|
||||
# ✅ UPDATED (safe handling)
|
||||
# UPDATED (safe handling)
|
||||
if hasattr(village, "response"):
|
||||
self.response = village.response
|
||||
self.resultMessage = village.response.get("message", "")
|
||||
@@ -37,7 +37,7 @@ class Village:
|
||||
block_id, village_name = self._get_form_data(request)
|
||||
|
||||
if not village_name:
|
||||
self.response = ResponseHandler.invalid_name("village") # ✅ UPDATED
|
||||
self.response = ResponseHandler.invalid_name("village")
|
||||
self.resultMessage = self.response["message"]
|
||||
self.isSuccess = False
|
||||
return
|
||||
@@ -75,7 +75,7 @@ class Village:
|
||||
block_id, village_name = self._get_form_data(request)
|
||||
|
||||
if not village_name:
|
||||
self.response = ResponseHandler.invalid_name("village") # ✅ UPDATED
|
||||
self.response = ResponseHandler.invalid_name("village")
|
||||
self.resultMessage = self.response["message"]
|
||||
self.isSuccess = False
|
||||
return None
|
||||
@@ -113,7 +113,7 @@ class Village:
|
||||
block_id, village_name = self._get_form_data(request)
|
||||
|
||||
if not village_name:
|
||||
self.response = ResponseHandler.invalid_name("village") # ✅ UPDATED
|
||||
self.response = ResponseHandler.invalid_name("village")
|
||||
self.resultMessage = self.response["message"]
|
||||
self.isSuccess = False
|
||||
return
|
||||
@@ -176,7 +176,7 @@ class Village:
|
||||
print(f"Error fetching blocks: {e}")
|
||||
self.isSuccess = False
|
||||
|
||||
# ✅ FIXED (removed jsonify response)
|
||||
# FIXED (removed jsonify response)
|
||||
self.response = ResponseHandler.fetch_failure("block")
|
||||
self.resultMessage = self.response["message"]
|
||||
|
||||
|
||||
Binary file not shown.
@@ -8,12 +8,18 @@ class GSTRelease:
|
||||
def __init__(self):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ""
|
||||
|
||||
|
||||
# ------------------- Add GST Release -------------------
|
||||
def AddGSTRelease(self, request):
|
||||
try:
|
||||
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 = {
|
||||
"PMC_No": request.form.get("PMC_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)
|
||||
}
|
||||
|
||||
print("===== DEBUG: PARSED DATA =====")
|
||||
print(data)
|
||||
print("==============================")
|
||||
|
||||
# Add GST Release
|
||||
gst.AddItem(
|
||||
request=request,
|
||||
@@ -31,12 +41,8 @@ class GSTRelease:
|
||||
storedprocfetch="CheckGSTReleaseExists",
|
||||
storedprocadd="AddGSTReleaseFromExcel"
|
||||
)
|
||||
|
||||
# Check if addition was successful
|
||||
if gst.isSuccess:
|
||||
print(f"GST Release Added: {data}")
|
||||
else:
|
||||
print(f"Failed to add GST Release: {gst.resultMessage}")
|
||||
|
||||
print(f"AddItem result: isSuccess={gst.isSuccess}, message={gst.resultMessage}")
|
||||
|
||||
self.isSuccess = gst.isSuccess
|
||||
self.resultMessage = str(gst.resultMessage)
|
||||
@@ -48,20 +54,26 @@ class GSTRelease:
|
||||
|
||||
return jsonify({"success": self.isSuccess, "message": self.resultMessage})
|
||||
|
||||
# ------------------- Edit GST Release -------------------
|
||||
def EditGSTRelease(self, request, gst_release_id):
|
||||
try:
|
||||
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||
|
||||
# Map form inputs to stored procedure parameters
|
||||
data = {
|
||||
"PMC_No": request.form.get("PMC_No", "").strip(),
|
||||
"Invoice_No": request.form.get("Invoice_No", "").strip(),
|
||||
"Basic_Amount": float(request.form.get("Basic_Amount", 0) or 0),
|
||||
"Final_Amount": float(request.form.get("Final_Amount", 0) or 0),
|
||||
"Total_Amount": float(request.form.get("Total_Amount", 0) or 0),
|
||||
"UTR": request.form.get("UTR", "").strip()
|
||||
"p_pmc_no": request.form.get("PMC_No", "").strip(),
|
||||
"p_invoice_no": request.form.get("invoice_no", "").strip(),
|
||||
"p_basic_amount": float(request.form.get("Basic_Amount", 0) or 0),
|
||||
"p_final_amount": float(request.form.get("Final_Amount", 0) or 0),
|
||||
"p_total_amount": float(request.form.get("Total_Amount", 0) or 0),
|
||||
"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(
|
||||
request=request,
|
||||
childid=gst_release_id,
|
||||
@@ -77,8 +89,6 @@ class GSTRelease:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = str(e)
|
||||
|
||||
return jsonify({"success": self.isSuccess, "message": self.resultMessage})
|
||||
|
||||
# ------------------- Delete GST Release -------------------
|
||||
def DeleteGSTRelease(self, gst_release_id):
|
||||
try:
|
||||
|
||||
@@ -2,7 +2,6 @@ import config
|
||||
import mysql.connector
|
||||
import config
|
||||
import mysql.connector
|
||||
from enum import Enum
|
||||
from model.Utilities import ItemCRUDType
|
||||
|
||||
class Paymentmodel:
|
||||
@@ -34,40 +33,44 @@ class Paymentmodel:
|
||||
return payments
|
||||
|
||||
@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()
|
||||
if not connection:
|
||||
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
|
||||
def update_inpayment(subcontractor_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr):
|
||||
connection = Paymentmodel.get_connection()
|
||||
if not connection:
|
||||
return False
|
||||
cursor = None
|
||||
try:
|
||||
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()
|
||||
return True
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error updating inpayment: {e}")
|
||||
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return False
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
if cursor:
|
||||
cursor.close()
|
||||
if connection:
|
||||
connection.close()
|
||||
|
||||
|
||||
@staticmethod
|
||||
def fetch_payment_by_id(payment_id):
|
||||
@@ -133,9 +136,7 @@ class Paymentmodel:
|
||||
# Delete payment
|
||||
cursor.callproc("DeletePayment", (payment_id,))
|
||||
connection.commit()
|
||||
# Reset inpayment fields
|
||||
cursor.callproc("ResetInpayment", [pmc_no, invoice_no])
|
||||
connection.commit()
|
||||
|
||||
return True, pmc_no, invoice_no
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error deleting payment: {e}")
|
||||
|
||||
30
services/Generalservice.py
Normal file
30
services/Generalservice.py
Normal file
@@ -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
|
||||
|
||||
179
services/ReportService.py
Normal file
179
services/ReportService.py
Normal file
@@ -0,0 +1,179 @@
|
||||
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])
|
||||
self.gst_release_raw = GeneralUse.execute_sp(cursor, 'GetGSTRelease', [self.contractor_id])
|
||||
|
||||
# ---------- 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])
|
||||
self.gst_release_raw = GeneralUse.execute_sp(cursor, 'GetGSTReleaseDetailsByPMC', [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.pmc_no, 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
|
||||
BIN
static/images/icons/male_profile.jpg
Normal file
BIN
static/images/icons/male_profile.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
@@ -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('<tr><td colspan="6">No data found</td></tr>');
|
||||
} else {
|
||||
data.forEach(function (row) {
|
||||
tableBody.append(`
|
||||
<tr>
|
||||
<td><a href="/contractor_report/${row.Contractor_Id}" target="_blank">${row.Contractor_Name}</a></td>
|
||||
<td><a href="/pmc_report/${row.PMC_No}" target="_blank">${row.PMC_No}</a></td>
|
||||
<td>${row.State_Name}</td>
|
||||
<td>${row.District_Name}</td>
|
||||
<td>${row.Block_Name}</td>
|
||||
<td>${row.Village_Name}</td>
|
||||
</tr>
|
||||
`);
|
||||
});
|
||||
}
|
||||
},
|
||||
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 = `
|
||||
<td class="contractor-link" data-id="${row.Contractor_Id}">
|
||||
${row.Contractor_Name}
|
||||
</td>
|
||||
<td class="pmc-link" data-pmc="${row.PMC_No}">
|
||||
${row.PMC_No}
|
||||
</td>
|
||||
<td>${row.State_Name}</td>
|
||||
<td>${row.District_Name}</td>
|
||||
<td>${row.Block_Name}</td>
|
||||
<td>${row.Village_Name}</td>
|
||||
`;
|
||||
|
||||
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();
|
||||
};
|
||||
fetchData();
|
||||
});
|
||||
@@ -1,26 +1,23 @@
|
||||
|
||||
// Search on table using search inpute options
|
||||
function searchTable() {
|
||||
let input = document.getElementById("searchBar").value.toLowerCase();
|
||||
let rows = document.querySelectorAll("table tbody tr");
|
||||
let tables = document.querySelectorAll("table");
|
||||
|
||||
rows.forEach(row => {
|
||||
let blockName = row.cells[1].textContent.toLowerCase();
|
||||
let districtName = row.cells[2].textContent.toLowerCase();
|
||||
let villageName = row.cells[3].textContent.toLowerCase();
|
||||
tables.forEach(table => {
|
||||
let rows = table.querySelectorAll("tr");
|
||||
|
||||
if (blockName.includes(input) || districtName.includes(input)|| villageName.includes(input)) {
|
||||
row.style.display = "";
|
||||
} else {
|
||||
row.style.display = "none";
|
||||
}
|
||||
rows.forEach((row, index) => {
|
||||
if (index === 0) return; // header skip
|
||||
|
||||
let text = row.textContent.toLowerCase();
|
||||
|
||||
row.style.display = text.includes(input) ? "" : "none";
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Common Sorting Script for Tables
|
||||
function sortTable(n, dir) {
|
||||
var table, rows, switching, i, x, y, shouldSwitch;
|
||||
@@ -57,14 +54,14 @@ function sortTable(n, dir) {
|
||||
}
|
||||
|
||||
// Attach sorting functionality to all sortable tables
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
// Find all elements with the class "sortable-header"
|
||||
var sortableHeaders = document.querySelectorAll(".sortable-header");
|
||||
|
||||
sortableHeaders.forEach(function(header) {
|
||||
sortableHeaders.forEach(function (header) {
|
||||
// Attach click event for ascending sort
|
||||
if (header.querySelector(".sort-asc")) {
|
||||
header.querySelector(".sort-asc").addEventListener("click", function() {
|
||||
header.querySelector(".sort-asc").addEventListener("click", function () {
|
||||
var columnIndex = Array.from(header.parentNode.children).indexOf(header);
|
||||
sortTable(columnIndex, "asc");
|
||||
});
|
||||
@@ -72,7 +69,7 @@ document.addEventListener("DOMContentLoaded", function() {
|
||||
|
||||
// Attach click event for descending sort
|
||||
if (header.querySelector(".sort-desc")) {
|
||||
header.querySelector(".sort-desc").addEventListener("click", function() {
|
||||
header.querySelector(".sort-desc").addEventListener("click", function () {
|
||||
var columnIndex = Array.from(header.parentNode.children).indexOf(header);
|
||||
sortTable(columnIndex, "desc");
|
||||
});
|
||||
@@ -105,4 +102,31 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
displayButton.classList.add("active-button");
|
||||
addButton.classList.remove("active-button");
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
|
||||
let tables = document.querySelectorAll("table");
|
||||
|
||||
tables.forEach(table => {
|
||||
let header = table.querySelector("tr:first-child");
|
||||
|
||||
if (header) {
|
||||
header.style.position = "sticky";
|
||||
header.style.top = "0";
|
||||
header.style.background = "#fff";
|
||||
header.style.zIndex = "2";
|
||||
}
|
||||
|
||||
if (!table.parentElement.classList.contains("table-wrapper")) {
|
||||
let wrapper = document.createElement("div");
|
||||
wrapper.classList.add("table-wrapper");
|
||||
wrapper.style.maxHeight = "65vh"
|
||||
wrapper.style.overflowY = "auto";
|
||||
|
||||
table.parentNode.insertBefore(wrapper, table);
|
||||
wrapper.appendChild(table);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -15,17 +15,21 @@
|
||||
<button id="addButton" class="action-button">Add</button>
|
||||
<button id="displayButton" class="action-button">Display</button>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="addForm" style="display: none;">
|
||||
<h2>Add GST Release</h2>
|
||||
<form action="/add_gst_release" method="POST" onsubmit="showSuccessAlert(event)">
|
||||
<div class="row1">
|
||||
<div>
|
||||
<label for="subcontractor">Subcontractor Name:</label>
|
||||
<input type="text" id="subcontractor" name="subcontractor" required autocomplete="off"/>
|
||||
<input type="hidden" id="subcontractor_id" name="subcontractor_id"/>
|
||||
<div id="subcontractor_list" class="autocomplete-items"></div>
|
||||
</div>
|
||||
<div>
|
||||
<label for="subcontractor">Subcontractor Name:</label>
|
||||
<!-- Text input for user-friendly autocomplete -->
|
||||
<input type="text" id="subcontractor" name="subcontractor" required autocomplete="off"/>
|
||||
|
||||
<!-- 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>
|
||||
|
||||
<label for="PMC_No">PMC No:</label><br>
|
||||
@@ -37,19 +41,19 @@
|
||||
</select><br><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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
<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>
|
||||
</form>
|
||||
@@ -117,46 +121,61 @@
|
||||
|
||||
<script>
|
||||
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 list = document.getElementById("subcontractor_list");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
fetch(`/search_subcontractor?query=${encodeURIComponent(query)}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
list.innerHTML = '';
|
||||
subcontractorList.innerHTML = '';
|
||||
data.results.forEach(item => {
|
||||
const div = document.createElement("div");
|
||||
div.setAttribute("data-id", item.id);
|
||||
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 selectedName = e.target.textContent;
|
||||
|
||||
if (selectedId) {
|
||||
document.getElementById("subcontractor_id").value = selectedId;
|
||||
document.getElementById("subcontractor").value = selectedName;
|
||||
document.getElementById("subcontractor_list").innerHTML = "";
|
||||
// Set hidden field for backend
|
||||
subcontractorIdInput.value = selectedId;
|
||||
|
||||
// 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)}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const pmcDropdown = document.getElementById("PMC_No");
|
||||
pmcDropdown.innerHTML = '<option value="">Select PMC No</option>';
|
||||
|
||||
data.pmc_nos.forEach(pmc => {
|
||||
const option = document.createElement("option");
|
||||
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>
|
||||
|
||||
|
||||
@@ -9,37 +9,37 @@
|
||||
<body>
|
||||
<h2>Edit GST Release</h2>
|
||||
|
||||
<form action="/edit_gst_release/{{ gst_release_data[0] }}" 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>-->
|
||||
<form action="/edit_gst_release/{{ gst_release_data.gst_release_id }}" method="POST">
|
||||
|
||||
<!-- PMC Number -->
|
||||
<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>
|
||||
<input type="number" step="0.01" id="invoice_No" name="invoice_No" value="{{ gst_release_data[2] }}"
|
||||
required><br><br>
|
||||
<!-- Invoice Number -->
|
||||
<label for="invoice_no">Invoice No:</label><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>
|
||||
<input type="number" step="0.01" id="basic_amount" name="basic_amount" value="{{ gst_release_data[3] }}"
|
||||
required><br><br>
|
||||
<!-- Final Amount -->
|
||||
<label for="Final_Amount">Final Amount:</label><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>
|
||||
<input type="number" step="0.01" id="final_amount" name="final_amount" value="{{ gst_release_data[4] }}"
|
||||
required><br><br>
|
||||
<!-- Total Amount -->
|
||||
<label for="Total_Amount">Total Amount:</label><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>
|
||||
<input type="number" step="0.01" id="total_amount" name="total_amount" value="{{ gst_release_data[5] }}"
|
||||
required><br><br>
|
||||
<!-- UTR -->
|
||||
<label for="UTR">UTR:</label><br>
|
||||
<input type="text" id="UTR" name="UTR" value="{{ gst_release_data.utr }}" readonly required><br><br>
|
||||
|
||||
<label for="utr">UTR:</label><br>
|
||||
<input type="text" id="utr" name="utr" value="{{ gst_release_data[6] }}"
|
||||
required readonly><br><br>
|
||||
<!-- Hidden Contractor ID -->
|
||||
<input type="hidden" id="Contractor_ID" name="Contractor_ID" value="{{ gst_release_data.contractor_id }}">
|
||||
|
||||
<button type="submit">Update GST Release</button>
|
||||
</form>
|
||||
|
||||
|
||||
</body>
|
||||
{% endblock %}
|
||||
@@ -7,6 +7,7 @@
|
||||
<title>Edit Invoice</title>
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/invoice.css') }}">
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style1.css') }}">
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
</head>
|
||||
|
||||
@@ -204,15 +205,17 @@
|
||||
type: "POST",
|
||||
url: $(this).attr("action"),
|
||||
data: $(this).serialize(),
|
||||
dataType: 'json', // ensure JSON is returned
|
||||
success: function (response) {
|
||||
if (response.status === "success") {
|
||||
$("#invoiceSuccessAlert").fadeIn().delay(3000).fadeOut();
|
||||
alert("Invoice updated successfully!"); // <-- Popup alert
|
||||
}
|
||||
|
||||
// ✅ Redirect to Add Invoice page (table part visible)
|
||||
window.location.href = "{{ url_for('invoice.add_invoice') }}#addTable";
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
alert("Error: " + xhr.responseJSON.message);
|
||||
alert("Error: " + xhr.responseJSON?.message || "Something went wrong!");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<a href="/logout">Logout</a>
|
||||
</div>
|
||||
<div class="sidebar">
|
||||
<img src="https://lceplpmprod.btltech.xyz/assets/images/lcpl.png" alt="logo-image" class="logo">
|
||||
<img src="http://lceplpmprod.btltech.xyz/assets/images/lcpl.png" alt="logo-image" class="logo">
|
||||
|
||||
<ul class="nav-menu">
|
||||
<li class="nav-item">
|
||||
@@ -136,7 +136,7 @@
|
||||
<div class="card">
|
||||
<h2>Work Order</h2>
|
||||
<!-- <a class="btn" href="/add_work_order">Go ➜</a> -->
|
||||
<a class="btn">Go ➜</a>
|
||||
<a class="btn">Go ➜</a>
|
||||
</div>
|
||||
<!-- <div class="card">
|
||||
<h2>Purchase Order</h2>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
|
||||
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
@@ -9,332 +8,337 @@
|
||||
<!-- <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}">-->
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/subcontractor_report.css') }}">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
<h2>PMC Report</h2>
|
||||
<div class="container">
|
||||
<h2>PMC Report</h2>
|
||||
|
||||
<div class="info">
|
||||
<h2>Contractor Details</h2>
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="subcontractor">Subcontractor Name:</label>
|
||||
<input type="text" id="subcontractor" name="subcontractor" value="{{ info.Contractor_Name }}"
|
||||
readonly/>
|
||||
<div class="info">
|
||||
<h2>Contractor Details</h2>
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="subcontractor">Subcontractor Name:</label>
|
||||
<input type="text" id="subcontractor" name="subcontractor" value="{{ contInfo.Contractor_Name }}"
|
||||
readonly />
|
||||
</div>
|
||||
<div>
|
||||
<label for="Address">Address :</label>
|
||||
<textarea id="Address" name="Address" readonly>{{ contInfo.Address }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label for="Address">Address :</label>
|
||||
<textarea id="Address" name="Address" readonly>{{ info.Address }}</textarea>
|
||||
<div class="row3">
|
||||
<div>
|
||||
<label for="PAN_No">PAN No :</label>
|
||||
<input type="text" id="PAN_No" name="PAN_No" value="{{ contInfo.PAN_No }}" readonly />
|
||||
</div>
|
||||
<div>
|
||||
<label for="Mobile_No">Mobile Number :</label>
|
||||
<input type="text" id="Mobile_No" name="Mobile_No" value="{{ contInfo.Mobile_No }}" readonly />
|
||||
</div>
|
||||
<div>
|
||||
<label for="Email">Email :</label>
|
||||
<input type="text" id="Email" name="Email" value="{{ contInfo.Email }}" readonly />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row3">
|
||||
<div>
|
||||
<label for="PAN_No">PAN No :</label>
|
||||
<input type="text" id="PAN_No" name="PAN_No" value="{{ info.PAN_No }}" readonly/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="Mobile_No">Mobile Number :</label>
|
||||
<input type="text" id="Mobile_No" name="Mobile_No" value="{{ info.Mobile_No }}" readonly/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="Email">Email :</label>
|
||||
<input type="text" id="Email" name="Email" value="{{ info.Email }}" readonly/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="GST_Registration_Type">GST Registration Type :</label>
|
||||
<input type="text" id="GST_Registration_Type" name="GST_Registration_Type"
|
||||
value="{{ info.GST_Registration_Type }}" readonly/>
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="GST_Registration_Type">GST Registration Type :</label>
|
||||
<input type="text" id="GST_Registration_Type" name="GST_Registration_Type"
|
||||
value="{{ contInfo.GST_Registration_Type }}" readonly />
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<label for="GST_No">GST No:</label>
|
||||
<input type="text" id="GST_No" name="GST_No" value="{{ contInfo.GST_No }}" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label for="GST_No">GST No:</label>
|
||||
<input type="text" id="GST_No" name="GST_No" value="{{ info.GST_No }}" readonly/>
|
||||
<h2>PMC Report for PMC No: {{ contInfo.PMC_No}}</h2>
|
||||
<div class="row3">
|
||||
<div>
|
||||
<label for="State">State :</label>
|
||||
<input type="text" id="State" name="State" value="{{ contInfo.State_Name }}" readonly />
|
||||
</div>
|
||||
<div>
|
||||
<label for="District">District :</label>
|
||||
<input type="text" id="District" name="District" value="{{ contInfo.District_Name }}" readonly />
|
||||
</div>
|
||||
<div>
|
||||
<label for="Block">Block :</label>
|
||||
<input type="text" id="Block" name="Block" value="{{ contInfo.Block_Name }}" readonly />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2>PMC Report for PMC No: {{ info.PMC_No}}</h2>
|
||||
<div class="row3">
|
||||
<div>
|
||||
<label for="State">State :</label>
|
||||
<input type="text" id="State" name="State" value="{{ info.State_Name }}" readonly/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="District">District :</label>
|
||||
<input type="text" id="District" name="District" value="{{ info.District_Name }}" readonly/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="Block">Block :</label>
|
||||
<input type="text" id="Block" name="Block" value="{{ info.Block_Name }}" readonly/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="PMC_No">PMC No:</label>
|
||||
<input type="text" id="PMC_No" name="PMC_No" value="{{ info.PMC_No }}" readonly/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="Village_Name">Village Name :</label>
|
||||
<input type="text" id="Village_Name" name="Village_Name"
|
||||
value="{{ info.Village_Name.capitalize() }}" readonly/>
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="PMC_No">PMC No:</label>
|
||||
<input type="text" id="PMC_No" name="PMC_No" value="{{ contInfo.PMC_No }}" readonly />
|
||||
</div>
|
||||
<div>
|
||||
<label for="Village_Name">Village Name :</label>
|
||||
<input type="text" id="Village_Name" name="Village_Name"
|
||||
value="{{ contInfo.Village_Name.capitalize() }}" readonly />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h3>Invoice Details</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Village Name</th>
|
||||
<th>Work Type</th>
|
||||
<th>Invoice Details</th>
|
||||
<th>Invoice Date</th>
|
||||
<th>Invoice No</th>
|
||||
<th>Basic Amount</th>
|
||||
<th>Debit</th>
|
||||
<th>After Debit Amt</th>
|
||||
<th>GST (18%)</th>
|
||||
<th>Amount</th>
|
||||
<th>TDS (1%)</th>
|
||||
<th>SD (5%)</th>
|
||||
<th>On Commission</th>
|
||||
<th>Hydro Testing</th>
|
||||
<h3>Invoice Details</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Village Name</th>
|
||||
<th>Work Type</th>
|
||||
<th>Invoice Details</th>
|
||||
<th>Invoice Date</th>
|
||||
<th>Invoice No</th>
|
||||
<th>Basic Amount</th>
|
||||
<th>Debit</th>
|
||||
<th>After Debit Amt</th>
|
||||
<th>GST (18%)</th>
|
||||
<th>Amount</th>
|
||||
<th>TDS (1%)</th>
|
||||
<th>SD (5%)</th>
|
||||
<th>On Commission</th>
|
||||
<th>Hydro Testing</th>
|
||||
|
||||
<!-- Dynamic Hold Types -->
|
||||
{% set hold_types = invoices | map(attribute='hold_type') | reject('none') | unique | list %}
|
||||
{% for hold in hold_types %}
|
||||
<th>{{ hold }}</th>
|
||||
{% endfor %}
|
||||
<!-- Dynamic Hold Types -->
|
||||
{% set hold_types = invoices | map(attribute='hold_type') | reject('none') | unique | list %}
|
||||
{% for hold in hold_types %}
|
||||
<th>{{ hold }}</th>
|
||||
{% endfor %}
|
||||
|
||||
<th>GST SD (18%)</th>
|
||||
<th>Final Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if invoices %}
|
||||
{% for invoice in invoices %}
|
||||
<tr>
|
||||
<td>{{ invoice.PMC_No }}</td>
|
||||
<td>{{ invoice.Village_Name.capitalize() }}</td>
|
||||
<td>{{ invoice.Work_Type }}</td>
|
||||
<td>{{ invoice.Invoice_Details }}</td>
|
||||
<td>{{ invoice.Invoice_Date }}</td>
|
||||
<td>{{ invoice.Invoice_No }}</td>
|
||||
<td>{{ invoice.Basic_Amount }}</td>
|
||||
<td>{{ invoice.Debit_Amount }}</td>
|
||||
<td>{{ invoice.After_Debit_Amount }}</td>
|
||||
<td>{{ invoice.GST_Amount }}</td>
|
||||
<td>{{ invoice.Amount }}</td>
|
||||
<td>{{ invoice.TDS_Amount }}</td>
|
||||
<td>{{ invoice.SD_Amount }}</td>
|
||||
<td>{{ invoice.On_Commission }}</td>
|
||||
<td>{{ invoice.Hydro_Testing }}</td>
|
||||
<th>GST SD (18%)</th>
|
||||
<th>Final Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if invoices %}
|
||||
{% for invoice in invoices %}
|
||||
<tr>
|
||||
<td>{{ invoice.PMC_No }}</td>
|
||||
<td>{{ invoice.Village_Name.capitalize() if invoice.Village_Name else '' }}</td>
|
||||
<td>{{ invoice.Work_Type }}</td>
|
||||
<td>{{ invoice.Invoice_Details }}</td>
|
||||
<td>{{ invoice.Invoice_Date }}</td>
|
||||
<td>{{ invoice.invoice_no }}</td>
|
||||
<td>{{ invoice.Basic_Amount }}</td>
|
||||
<td>{{ invoice.Debit_Amount }}</td>
|
||||
<td>{{ invoice.After_Debit_Amount }}</td>
|
||||
<td>{{ invoice.GST_Amount }}</td>
|
||||
<td>{{ invoice.Amount }}</td>
|
||||
<td>{{ invoice.TDS_Amount }}</td>
|
||||
<td>{{ invoice.SD_Amount }}</td>
|
||||
<td>{{ invoice.On_Commission }}</td>
|
||||
<td>{{ invoice.Hydro_Testing }}</td>
|
||||
|
||||
<!-- Dynamic Hold Amounts -->
|
||||
{% for hold in hold_types %}
|
||||
<td>
|
||||
{% if invoice.hold_type == hold %}
|
||||
{{ invoice.hold_amount }}
|
||||
{% else %}
|
||||
0
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endfor %}
|
||||
|
||||
<td>{{ invoice.GST_SD_Amount }}</td>
|
||||
<td>{{ invoice.Final_Amount }}</td>
|
||||
</tr>
|
||||
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<th colspan="6">Total</th>
|
||||
<th>{{total["sum_invo_basic_amt"]}}</th>
|
||||
<th>{{total["sum_invo_debit_amt"]}}</th>
|
||||
<th>{{total["sum_invo_after_debit_amt"]}}</th>
|
||||
<th>{{total["sum_invo_gst_amt"]}}</th>
|
||||
<th>{{total["sum_invo_amt"]}}</th>
|
||||
<th>{{total["sum_invo_tds_amt"]}}</th>
|
||||
<th>{{total["sum_invo_ds_amt"]}}</th>
|
||||
<th>{{total["sum_invo_on_commission"]}}</th>
|
||||
<th>{{total["sum_invo_hydro_test"]}}</th>
|
||||
{% set hold_types = invoices | map(attribute='hold_type') | unique | list %}
|
||||
{% for hold in hold_types %}
|
||||
<th>{{total["sum_invo_hold_amt"]}}</th>
|
||||
{% endfor %}
|
||||
<th>{{total["sum_invo_gst_sd_amt"]}}</th>
|
||||
<th>{{total["sum_invo_final_amt"]}}</th>
|
||||
</tr>
|
||||
|
||||
<!-- Dynamic Hold Amounts -->
|
||||
{% for hold in hold_types %}
|
||||
<td>
|
||||
{% if invoice.hold_type == hold %}
|
||||
{{ invoice.hold_amount }}
|
||||
{% else %}
|
||||
0
|
||||
<tr>
|
||||
<td colspan="{{ 17 + hold_types|length }}">No invoices found.</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Hold Release</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Invoice No</th>
|
||||
<th>Invoice Details</th>
|
||||
<th>Basic Amount</th>
|
||||
<th>Total Amount</th>
|
||||
<th>UTR</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%if hold_release%}
|
||||
{%for hold in hold_release%}
|
||||
<tr>
|
||||
<td>{{ hold['PMC_No'] }}</td>
|
||||
<td>{{ hold['Invoice_No'] }}</td>
|
||||
<td>{{ hold['Invoice_Details'] }}</td>
|
||||
<td>{{ hold['Basic_Amount'] }}</td>
|
||||
<td>{{ hold['Total_Amount'] }}</td>
|
||||
<td>{{ hold['UTR'] }}</td>
|
||||
</tr>
|
||||
{%endfor%}
|
||||
{%else%}
|
||||
<tr>
|
||||
<td colspan="6" style="text-align:center;">No data present</td>
|
||||
</tr>
|
||||
{%endif%}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<td>{{ invoice.GST_SD_Amount }}</td>
|
||||
<td>{{ invoice.Final_Amount }}</td>
|
||||
</tr>
|
||||
<br>
|
||||
<h3>GST Release Note Details</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Invoice No</th>
|
||||
<th>Basic Amount</th>
|
||||
<th>Final Amount</th>
|
||||
<th>Total_Amount</th>
|
||||
<th>UTR</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if gst_rel %}
|
||||
{% for gst in gst_rel %}
|
||||
<tr>
|
||||
<td>{{ gst.PMC_No }}</td>
|
||||
<td>{{ gst.invoice_no }}</td>
|
||||
<td>{{ gst.Basic_Amount }}</td>
|
||||
<td>{{ gst.Final_Amount }}</td>
|
||||
<td>{{ gst.Total_Amount }}</td>
|
||||
<td>{{ gst.UTR }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<th colspan="2">Total</th>
|
||||
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<th colspan="6">Total</th>
|
||||
<th>{{total["sum_invo_basic_amt"]}}</th>
|
||||
<th>{{total["sum_invo_debit_amt"]}}</th>
|
||||
<th>{{total["sum_invo_after_debit_amt"]}}</th>
|
||||
<th>{{total["sum_invo_gst_amt"]}}</th>
|
||||
<th>{{total["sum_invo_amt"]}}</th>
|
||||
<th>{{total["sum_invo_tds_amt"]}}</th>
|
||||
<th>{{total["sum_invo_ds_amt"]}}</th>
|
||||
<th>{{total["sum_invo_on_commission"]}}</th>
|
||||
<th>{{total["sum_invo_hydro_test"]}}</th>
|
||||
{% set hold_types = invoices | map(attribute='hold_type') | unique | list %}
|
||||
{% for hold in hold_types %}
|
||||
<th>{{total["sum_invo_hold_amt"]}}</th>
|
||||
{% endfor %}
|
||||
<th>{{total["sum_invo_gst_sd_amt"]}}</th>
|
||||
<th>{{total["sum_invo_final_amt"]}}</th>
|
||||
</tr>
|
||||
<th>{{total["sum_gst_basic_amt"]}}</th>
|
||||
<th>{{total["sum_gst_final_amt"]}}</th>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="4">No GST release found.</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="{{ 17 + hold_types|length }}">No invoices found.</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Hold Release</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Invoice No</th>
|
||||
<th>Invoice Details</th>
|
||||
<th>Basic Amount</th>
|
||||
<th>Total Amount</th>
|
||||
<th>UTR</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{%if hold_release%}
|
||||
{%for hold in hold_release%}
|
||||
<tr>
|
||||
<td>{{ hold['PMC_No'] }}</td>
|
||||
<td>{{ hold['Invoice_No'] }}</td>
|
||||
<td>{{ hold['Invoice_Details'] }}</td>
|
||||
<td>{{ hold['Basic_Amount'] }}</td>
|
||||
<td>{{ hold['Total_Amount'] }}</td>
|
||||
<td>{{ hold['UTR'] }}</td>
|
||||
</tr>
|
||||
{%endfor%}
|
||||
{%else%}
|
||||
<tr>
|
||||
<td colspan="6" style="text-align:center;">No data present</td>
|
||||
</tr>
|
||||
{%endif%}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<br>
|
||||
<h3>GST Release Note Details</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Invoice No</th>
|
||||
<th>Basic Amount</th>
|
||||
<th>Final Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if gst_rel %}
|
||||
{% for gst in gst_rel %}
|
||||
<tr>
|
||||
<td>{{ gst.pmc_no }}</td>
|
||||
<td>{{ gst.invoice_no }}</td>
|
||||
<td>{{ gst.basic_amount }}</td>
|
||||
<td>{{ gst.final_amount }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<th colspan="2">Total</th>
|
||||
|
||||
<th>{{total["sum_gst_basic_amt"]}}</th>
|
||||
<th>{{total["sum_gst_final_amt"]}}</th>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="4">No GST release found.</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<tr>
|
||||
<h3>Credit Details</h3>
|
||||
</tr>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Invoice Details</th>
|
||||
<th>Basic Amount</th>
|
||||
<th>Debit</th>
|
||||
<th>After Debit Amt</th>
|
||||
<th>GST Amount</th>
|
||||
<th>Amount</th>
|
||||
<th>Final Amount</th>
|
||||
<th>Payment Amount</th>
|
||||
<th>Total Amount</th>
|
||||
<th>UTR</th>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Invoice Details</th>
|
||||
<th>Basic Amount</th>
|
||||
<th>Debit</th>
|
||||
<th>After Debit Amt</th>
|
||||
<th>GST Amount</th>
|
||||
<th>Amount</th>
|
||||
<th>Final Amount</th>
|
||||
<th>Payment Amount</th>
|
||||
<th>Total Amount</th>
|
||||
<th>UTR</th>
|
||||
|
||||
</tr>
|
||||
|
||||
{% if credit_note %}
|
||||
{% for credit in credit_note %}
|
||||
<tr>
|
||||
<td>{{ credit["PMC_No"] }}</td>
|
||||
<td>{{ credit["Invoice_Details"] }}</td>
|
||||
<td>{{ credit["Basic_Amount"] }}</td>
|
||||
<td>{{ credit["Debit_Amount"] }}</td>
|
||||
<td>{{ credit["After_Debit_Amount"] }}</td>
|
||||
<td>{{ credit["GST_Amount"] }}</td>
|
||||
<td>{{ credit["Amount"] }}</td>
|
||||
<td>{{ credit["Final_Amount"] }}</td>
|
||||
<td>{{ credit["Payment_Amount"] }}</td>
|
||||
<td>{{ credit["Total_Amount"] }}</td>
|
||||
<td>{{ credit["UTR"] }}</td>
|
||||
{% if credit_note %}
|
||||
{% for credit in credit_note %}
|
||||
<tr>
|
||||
<td>{{ credit["PMC_No"] }}</td>
|
||||
<td>{{ credit["Invoice_Details"] }}</td>
|
||||
<td>{{ credit["Basic_Amount"] }}</td>
|
||||
<td>{{ credit["Debit_Amount"] }}</td>
|
||||
<td>{{ credit["After_Debit_Amount"] }}</td>
|
||||
<td>{{ credit["GST_Amount"] }}</td>
|
||||
<td>{{ credit["Amount"] }}</td>
|
||||
<td>{{ credit["Final_Amount"] }}</td>
|
||||
<td>{{ credit["Payment_Amount"] }}</td>
|
||||
<td>{{ credit["Total_Amount"] }}</td>
|
||||
<td>{{ credit["UTR"] }}</td>
|
||||
|
||||
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="11">No Credit note found.</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="11">No Credit note found.</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</thead>
|
||||
</thead>
|
||||
</table>
|
||||
|
||||
<br>
|
||||
<h3>Payment Details</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Invoice No</th>
|
||||
<th>Amount</th>
|
||||
<th>TDS Amount @ 1% on BASIC AMOUNT</th>
|
||||
<th>Total Amount Paid</th>
|
||||
<th>UTR</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if payments %}
|
||||
{% for pay in payments %}
|
||||
<tr>
|
||||
<td>{{ pay.pmc_no }}</td>
|
||||
<td>{{ pay.invoice_no }}</td>
|
||||
<td>{{ pay.Payment_Amount }}</td>
|
||||
<td>{{ pay.TDS_Payment_Amount }}</td>
|
||||
<td>{{ pay.Total_amount }}</td>
|
||||
<td>{{ pay.utr}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<th colspan="2">Total</th>
|
||||
<th>{{total["sum_pay_payment_amt"]}}</th>
|
||||
<th>{{total["sum_pay_tds_payment_amt"]}}</th>
|
||||
<th>{{total["sum_pay_total_amt"]}}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
{% else %}
|
||||
<br>
|
||||
<h3>Payment Details</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Invoice No</th>
|
||||
<th>Amount</th>
|
||||
<th>TDS Amount @ 1% on BASIC AMOUNT</th>
|
||||
<th>Total Amount Paid</th>
|
||||
<th>UTR</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if invoices %}
|
||||
{% for pay in invoices %}
|
||||
<tr>
|
||||
<td>{{ pay.PMC_No }}</td>
|
||||
<td>{{ pay.invoice_no }}</td>
|
||||
<td>{{ pay.Payment_Amount }}</td>
|
||||
<td>{{ pay.TDS_Payment_Amount }}</td>
|
||||
<td>{{ pay.Total_Amount }}</td>
|
||||
<td>{{ pay.UTR}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<th colspan="2">Total</th>
|
||||
<th>{{total["sum_pay_payment_amt"]}}</th>
|
||||
<th>{{total["sum_pay_tds_payment_amt"]}}</th>
|
||||
<th>{{total["sum_pay_total_amt"]}}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
{% else %}
|
||||
|
||||
<tr>
|
||||
<td colspan="6">No payment found.</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<td colspan="6">No payment found.</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="/download_pmc_report/{{ info.PMC_No}}">
|
||||
<button class="download-btn">Download PMC Report</button>
|
||||
</a>
|
||||
<a href="/download_pmc_report/{{ contInfo.PMC_No}}">
|
||||
<button class="download-btn">Download PMC Report</button>
|
||||
</a>
|
||||
</body>
|
||||
{% endblock %}
|
||||
@@ -1,5 +1,6 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
@@ -7,102 +8,104 @@
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/report.css') }}">
|
||||
<script src="{{ url_for('static', filename='js/searchContractor.js') }}"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="report" class="page">
|
||||
<h2>Search Contractor Report</h2>
|
||||
<div>
|
||||
<form id="search-form">
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="subcontractor_name">Subcontractor Name:</label>
|
||||
<input type="text" id="subcontractor_name" name="subcontractor_name">
|
||||
<div id="report" class="page">
|
||||
<h2>Search Contractor Report</h2>
|
||||
<div>
|
||||
<form id="search-form">
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="subcontractor_name">Subcontractor Name:</label>
|
||||
<input type="text" id="subcontractor_name" name="subcontractor_name">
|
||||
</div>
|
||||
<div>
|
||||
<label for="pmc_no">PMC No:</label>
|
||||
<input type="text" id="pmc_no" name="pmc_no">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label for="pmc_no">PMC No:</label>
|
||||
<input type="text" id="pmc_no" name="pmc_no">
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="state">State:</label>
|
||||
<input type="text" id="state" name="state">
|
||||
</div>
|
||||
<div>
|
||||
<label for="district">District:</label>
|
||||
<input type="text" id="district" name="district">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="state">State:</label>
|
||||
<input type="text" id="state" name="state">
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="block">Block:</label>
|
||||
<input type="text" id="block" name="block">
|
||||
</div>
|
||||
<div>
|
||||
<label for="village">Village:</label>
|
||||
<input type="text" id="village" name="village">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label for="district">District:</label>
|
||||
<input type="text" id="district" name="district">
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="year_from">Year From:</label>
|
||||
<input type="date" id="year_from" name="year_from">
|
||||
</div>
|
||||
<div>
|
||||
<label for="year_to">Year To:</label>
|
||||
<input type="date" id="year_to" name="year_to">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="block">Block:</label>
|
||||
<input type="text" id="block" name="block">
|
||||
</div>
|
||||
<div>
|
||||
<label for="village">Village:</label>
|
||||
<input type="text" id="village" name="village">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="year_from">Year From:</label>
|
||||
<input type="date" id="year_from" name="year_from">
|
||||
</div>
|
||||
<div>
|
||||
<label for="year_to">Year To:</label>
|
||||
<input type="date" id="year_to" name="year_to">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<button type="button" onclick="fetchData()">Search</button>
|
||||
</form>
|
||||
|
||||
<h2>Contractor List</h2>
|
||||
<table border="1" id="result-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="sortable">Contractor Name
|
||||
<select>
|
||||
<option value="">🔽</option>
|
||||
<option value="asc">Ascending</option>
|
||||
<option value="desc">Descending</option>
|
||||
</select>
|
||||
</th>
|
||||
<th>PMC No</th>
|
||||
<th class="sortable">State
|
||||
<select>
|
||||
<option value="">🔽</option>
|
||||
<option value="asc">Ascending</option>
|
||||
<option value="desc">Descending</option>
|
||||
</select>
|
||||
</th>
|
||||
<th class="sortable">District
|
||||
<select>
|
||||
<option value="">🔽</option>
|
||||
<option value="asc">Ascending</option>
|
||||
<option value="desc">Descending</option>
|
||||
</select>
|
||||
</th>
|
||||
<th class="sortable">Block
|
||||
<select>
|
||||
<option value="">🔽</option>
|
||||
<option value="asc">Ascending</option>
|
||||
<option value="desc">Descending</option>
|
||||
</select>
|
||||
</th>
|
||||
<th class="sortable">Village
|
||||
<select>
|
||||
<option value="">🔽</option>
|
||||
<option value="asc">Ascending</option>
|
||||
<option value="desc">Descending</option>
|
||||
</select>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- Results will be dynamically populated -->
|
||||
</tbody>
|
||||
</table>
|
||||
<h2>Contractor List</h2>
|
||||
<table border="1" id="result-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="sortable">Contractor Name
|
||||
<select>
|
||||
<option value="">🔽</option>
|
||||
<option value="asc">Ascending</option>
|
||||
<option value="desc">Descending</option>
|
||||
</select>
|
||||
</th>
|
||||
<th>PMC No</th>
|
||||
<th class="sortable">State
|
||||
<select>
|
||||
<option value="">🔽</option>
|
||||
<option value="asc">Ascending</option>
|
||||
<option value="desc">Descending</option>
|
||||
</select>
|
||||
</th>
|
||||
<th class="sortable">District
|
||||
<select>
|
||||
<option value="">🔽</option>
|
||||
<option value="asc">Ascending</option>
|
||||
<option value="desc">Descending</option>
|
||||
</select>
|
||||
</th>
|
||||
<th class="sortable">Block
|
||||
<select>
|
||||
<option value="">🔽</option>
|
||||
<option value="asc">Ascending</option>
|
||||
<option value="desc">Descending</option>
|
||||
</select>
|
||||
</th>
|
||||
<th class="sortable">Village
|
||||
<select>
|
||||
<option value="">🔽</option>
|
||||
<option value="asc">Ascending</option>
|
||||
<option value="desc">Descending</option>
|
||||
</select>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- Results will be dynamically populated -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
{% endblock %}
|
||||
@@ -58,8 +58,9 @@
|
||||
|
||||
<!-- Hidden fields for other necessary information -->
|
||||
<input type="text" name="subcontractor_data" value="{{ subcontractor_data['Contractor_Id'] }}">
|
||||
<input type="text" name="state_data" value="{{ state_data['State_ID'] }}">
|
||||
<input type="text" name="district_data" value="{{ district_data['District_ID'] }}">
|
||||
<input type="text" name="state_data" value="{{ state_data['State_Id'] }}">
|
||||
<!-- <input type="text" name="district_data" value="{{ district_data['District_ID'] }}"> -->
|
||||
<input type="text" name="district_data" value="{{ district_data['District_id'] }}">
|
||||
<input type="text" name="block_data" value="{{ block_data['Block_Id'] }}">
|
||||
|
||||
<input type="text" name="file_info" value="{{ file_info }}">
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
|
||||
|
||||
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
@@ -10,363 +8,345 @@
|
||||
<!-- <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}">-->
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/subcontractor_report.css') }}">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<h2>Contractor Report</h2>
|
||||
<div class="container">
|
||||
<h2>Contractor Report</h2>
|
||||
|
||||
<div class="info">
|
||||
<h2>Contractor Details</h2>
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="subcontractor">Subcontractor Name:</label>
|
||||
<input type="text" id="subcontractor" name="subcontractor" value="{{ contInfo.Contractor_Name }}"
|
||||
readonly/>
|
||||
<div class="info">
|
||||
<h2>Contractor Details</h2>
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="subcontractor">Subcontractor Name:</label>
|
||||
<input type="text" id="subcontractor" name="subcontractor" value="{{ contInfo.Contractor_Name }}"
|
||||
readonly />
|
||||
</div>
|
||||
<div>
|
||||
<label for="Address">Address :</label>
|
||||
<textarea id="Address" name="Address" readonly>{{ contInfo.Address }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label for="Address">Address :</label>
|
||||
<textarea id="Address" name="Address" readonly>{{ contInfo.Address }}</textarea>
|
||||
<div class="row3">
|
||||
<div>
|
||||
<label for="PAN_No">PAN No :</label>
|
||||
<input type="text" id="PAN_No" name="PAN_No" value="{{ contInfo.PAN_No }}" readonly />
|
||||
</div>
|
||||
<div>
|
||||
<label for="Mobile_No">Mobile Number :</label>
|
||||
<input type="text" id="Mobile_No" name="Mobile_No" value="{{ contInfo.Mobile_No }}" readonly />
|
||||
</div>
|
||||
<div>
|
||||
<label for="Email">Email :</label>
|
||||
<input type="text" id="Email" name="Email" value="{{ contInfo.Email }}" readonly />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row3">
|
||||
<div>
|
||||
<label for="PAN_No">PAN No :</label>
|
||||
<input type="text" id="PAN_No" name="PAN_No" value="{{ contInfo.PAN_No }}" readonly/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="Mobile_No">Mobile Number :</label>
|
||||
<input type="text" id="Mobile_No" name="Mobile_No" value="{{ contInfo.Mobile_No }}" readonly/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="Email">Email :</label>
|
||||
<input type="text" id="Email" name="Email" value="{{ contInfo.Email }}" readonly/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="GST_Registration_Type">GST Registration Type :</label>
|
||||
<input type="text" id="GST_Registration_Type" name="GST_Registration_Type"
|
||||
value="{{ contInfo.GST_Registration_Type }}" readonly/>
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="GST_Registration_Type">GST Registration Type :</label>
|
||||
<input type="text" id="GST_Registration_Type" name="GST_Registration_Type"
|
||||
value="{{ contInfo.GST_Registration_Type }}" readonly />
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<label for="GST_No">GST No:</label>
|
||||
<input type="text" id="GST_No" name="GST_No" value="{{ contInfo.GST_No }}" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label for="GST_No">GST No:</label>
|
||||
<input type="text" id="GST_No" name="GST_No" value="{{ contInfo.GST_No }}" readonly/>
|
||||
<div class="row3">
|
||||
<div>
|
||||
<label for="State">State :</label>
|
||||
<input type="text" id="State" name="State" value="{{ contInfo.State_Name }}" readonly />
|
||||
</div>
|
||||
<div>
|
||||
<label for="District">District :</label>
|
||||
<input type="text" id="District" name="District" value="{{ contInfo.District_Name }}" readonly />
|
||||
</div>
|
||||
<div>
|
||||
<label for="Block">Block :</label>
|
||||
<input type="text" id="Block" name="Block" value="{{ contInfo.Block_Name }}" readonly />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row3">
|
||||
<div>
|
||||
<label for="State">State :</label>
|
||||
<input type="text" id="State" name="State" value="{{ contInfo.State_Name }}" readonly/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="District">District :</label>
|
||||
<input type="text" id="District" name="District" value="{{ contInfo.District_Name }}" readonly/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="Block">Block :</label>
|
||||
<input type="text" id="Block" name="Block" value="{{ contInfo.Block_Name }}" readonly/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Total</h3>
|
||||
<table class="total-table">
|
||||
<tr>
|
||||
<th colspan="2">{{current_date}}</th>
|
||||
</tr>
|
||||
<!-- <tr>-->
|
||||
<!-- <th>Total Hold Amounnt</th>-->
|
||||
<!-- <td>0</td>-->
|
||||
<!-- </tr>-->
|
||||
<tr>
|
||||
<th>Advance / Suplus</th>
|
||||
<td>{{total["sum_invo_final_amt"]+total["sum_gst_final_amt"]-total["sum_pay_total_amt"]}}</td>
|
||||
</tr>
|
||||
{% if hold_types %}
|
||||
<tr>
|
||||
|
||||
<!-- {% if hold_types %}
|
||||
<h3>Hold Types</h3>
|
||||
<ul>
|
||||
{% for hold in hold_types %}
|
||||
<th>{{ hold.hold_type }}</th>
|
||||
<td>{{total["sum_invo_hold_amt"]}}</td>
|
||||
<li>{{ hold.hold_type }}</li>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<th>Amount With TDS</th>
|
||||
<td>{{total["sum_invo_tds_amt"]}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- {% if hold_types %}-->
|
||||
<!-- <h3>Hold Types</h3>-->
|
||||
<!-- <ul>-->
|
||||
<!-- {% for hold in hold_types %}-->
|
||||
<!-- <li>{{ hold.hold_type }}</li>-->
|
||||
<!-- {% endfor %}-->
|
||||
<!-- </ul>-->
|
||||
<!-- {% endif %}-->
|
||||
</ul>
|
||||
{% endif %} -->
|
||||
|
||||
|
||||
<h3>Invoice Details</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Village Name</th>
|
||||
<th>Work Type</th>
|
||||
<th>Invoice Details</th>
|
||||
<th>Invoice Date</th>
|
||||
<th>Invoice No</th>
|
||||
<th>Basic Amount</th>
|
||||
<th>Debit</th>
|
||||
<th>After Debit Amt</th>
|
||||
<th>GST (18%)</th>
|
||||
<th>Amount</th>
|
||||
<th>TDS (1%)</th>
|
||||
<th>SD (5%)</th>
|
||||
<th>On Commission</th>
|
||||
<th>Hydro Testing</th>
|
||||
<h3>Invoice Details</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Village Name</th>
|
||||
<th>Work Type</th>
|
||||
<th>Invoice Details</th>
|
||||
<th>Invoice Date</th>
|
||||
<th>Invoice No</th>
|
||||
<th>Basic Amount</th>
|
||||
<th>Debit</th>
|
||||
<th>After Debit Amt</th>
|
||||
<th>GST (18%)</th>
|
||||
<th>Amount</th>
|
||||
<th>TDS (1%)</th>
|
||||
<th>SD (5%)</th>
|
||||
<th>On Commission</th>
|
||||
<th>Hydro Testing</th>
|
||||
|
||||
<!-- Dynamic Hold Types -->
|
||||
{% set hold_types = invoices | map(attribute='hold_type') | unique | list %}
|
||||
{% for hold in hold_types %}
|
||||
<th>{{ hold }}</th>
|
||||
{% endfor %}
|
||||
<!-- Dynamic Hold Types -->
|
||||
{% set hold_types = invoices | map(attribute='hold_type') | unique | list %}
|
||||
{% for hold in hold_types %}
|
||||
<th>{{ hold }}</th>
|
||||
{% endfor %}
|
||||
|
||||
<th>GST SD (18%)</th>
|
||||
<th>Final Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if invoices %}
|
||||
{% for invoice in invoices %}
|
||||
<tr>
|
||||
<td>{{ invoice.PMC_No }}</td>
|
||||
<td>{{ invoice.Village_Name.capitalize() }}</td>
|
||||
<td>{{ invoice.Work_Type }}</td>
|
||||
<td>{{ invoice.Invoice_Details }}</td>
|
||||
<td>{{ invoice.Invoice_Date }}</td>
|
||||
<td>{{ invoice.Invoice_No }}</td>
|
||||
<td>{{ invoice.Basic_Amount }}</td>
|
||||
<td>{{ invoice.Debit_Amount }}</td>
|
||||
<td>{{ invoice.After_Debit_Amount }}</td>
|
||||
<td>{{ invoice.GST_Amount }}</td>
|
||||
<td>{{ invoice.Amount }}</td>
|
||||
<td>{{ invoice.TDS_Amount }}</td>
|
||||
<td>{{ invoice.SD_Amount }}</td>
|
||||
<td>{{ invoice.On_Commission }}</td>
|
||||
<td>{{ invoice.Hydro_Testing }}</td>
|
||||
<th>GST SD (18%)</th>
|
||||
<th>Final Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if invoices %}
|
||||
{% for invoice in invoices %}
|
||||
<tr>
|
||||
<td>{{ invoice.PMC_No }}</td>
|
||||
<td>{{ invoice.Village_Name}}</td>
|
||||
<td>{{ invoice.Work_Type }}</td>
|
||||
<td>{{ invoice.Invoice_Details }}</td>
|
||||
<td>{{ invoice.Invoice_Date }}</td>
|
||||
<td>{{ invoice.invoice_no }}</td>
|
||||
<td>{{ invoice.Basic_Amount }}</td>
|
||||
<td>{{ invoice.Debit_Amount }}</td>
|
||||
<td>{{ invoice.After_Debit_Amount }}</td>
|
||||
<td>{{ invoice.GST_Amount }}</td>
|
||||
<td>{{ invoice.Amount }}</td>
|
||||
<td>{{ invoice.TDS_Amount }}</td>
|
||||
<td>{{ invoice.SD_Amount }}</td>
|
||||
<td>{{ invoice.On_Commission }}</td>
|
||||
<td>{{ invoice.Hydro_Testing }}</td>
|
||||
|
||||
<!-- Dynamic Hold Amounts -->
|
||||
{% set hold_types = invoices | map(attribute='hold_type') | unique | list %}
|
||||
{% for hold in hold_types %}
|
||||
<td>
|
||||
{% if invoice.hold_type == hold %}
|
||||
{{ invoice.hold_amount }}
|
||||
{% else %}
|
||||
0.00
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>hold.</td>
|
||||
{% endfor %}
|
||||
|
||||
<td>{{ invoice.GST_SD_Amount }}</td>
|
||||
<td>{{ invoice.Final_Amount }}</td>
|
||||
</tr>
|
||||
|
||||
{% endfor %}
|
||||
|
||||
<tr>
|
||||
<th colspan="6">Total</th>
|
||||
<th>{{total["sum_invo_basic_amt"]}}</th>
|
||||
<th>{{total["sum_invo_debit_amt"]}}</th>
|
||||
<th>{{total["sum_invo_after_debit_amt"]}}</th>
|
||||
<th>{{total["sum_invo_gst_amt"]}}</th>
|
||||
<th>{{total["sum_invo_amt"]}}</th>
|
||||
<th>{{total["sum_invo_tds_amt"]}}</th>
|
||||
<th>{{total["sum_invo_ds_amt"]}}</th>
|
||||
<th>{{total["sum_invo_on_commission"]}}</th>
|
||||
<th>{{total["sum_invo_hydro_test"]}}</th>
|
||||
|
||||
{% set hold_types = invoices | map(attribute='hold_type') | unique | list %}
|
||||
{% for hold in hold_types %}
|
||||
<th>{{total["sum_invo_hold_amt"]}}</th>
|
||||
{% endfor %}
|
||||
|
||||
<th>{{total["sum_invo_gst_sd_amt"]}}</th>
|
||||
<th>{{total["sum_invo_final_amt"]}}</th>
|
||||
</tr>
|
||||
|
||||
<!-- Dynamic Hold Amounts -->
|
||||
{% set hold_types = invoices | map(attribute='hold_type') | unique | list %}
|
||||
{% for hold in hold_types %}
|
||||
<td>
|
||||
{% if invoice.hold_type == hold %}
|
||||
{{ invoice.hold_amount }}
|
||||
{% else %}
|
||||
0.00
|
||||
<tr>
|
||||
<td colspan="{{ 17 + hold_types|length }}">No invoices found.</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<td>{{ invoice.GST_SD_Amount }}</td>
|
||||
<td>{{ invoice.Final_Amount }}</td>
|
||||
</tr>
|
||||
<h3>Hold Release</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Invoice No</th>
|
||||
<th>Invoice Details</th>
|
||||
<th>Basic Amount</th>
|
||||
<th>Total Amount</th>
|
||||
<th>UTR</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if hold_release %}
|
||||
{% for hold in hold_release %}
|
||||
<tr>
|
||||
<td>{{ hold['PMC_No'] }}</td>
|
||||
<td>{{ hold['Invoice_No'] }}</td>
|
||||
<td>{{ hold['Invoice_Details'] }}</td>
|
||||
<td>{{ hold['Basic_Amount'] }}</td>
|
||||
<td>{{ hold['Total_Amount'] }}</td>
|
||||
<td>{{ hold['UTR'] }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="6" style="text-align:center;">No data present</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
|
||||
{% endfor %}
|
||||
|
||||
<tr>
|
||||
<th colspan="6">Total</th>
|
||||
<th>{{total["sum_invo_basic_amt"]}}</th>
|
||||
<th>{{total["sum_invo_debit_amt"]}}</th>
|
||||
<th>{{total["sum_invo_after_debit_amt"]}}</th>
|
||||
<th>{{total["sum_invo_gst_amt"]}}</th>
|
||||
<th>{{total["sum_invo_amt"]}}</th>
|
||||
<th>{{total["sum_invo_tds_amt"]}}</th>
|
||||
<th>{{total["sum_invo_ds_amt"]}}</th>
|
||||
<th>{{total["sum_invo_on_commission"]}}</th>
|
||||
<th>{{total["sum_invo_hydro_test"]}}</th>
|
||||
|
||||
{% set hold_types = invoices | map(attribute='hold_type') | unique | list %}
|
||||
{% for hold in hold_types %}
|
||||
<th>{{total["sum_invo_hold_amt"]}}</th>
|
||||
{% endfor %}
|
||||
|
||||
<th>{{total["sum_invo_gst_sd_amt"]}}</th>
|
||||
<th>{{total["sum_invo_final_amt"]}}</th>
|
||||
<h3>Credit Details</h3>
|
||||
</tr>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Invoice Details</th>
|
||||
<th>Basic Amount</th>
|
||||
<th>Debit</th>
|
||||
<th>After Debit Amt</th>
|
||||
<th>GST Amount</th>
|
||||
<th>Amount</th>
|
||||
<th>Final Amount</th>
|
||||
<th>Payment Amount</th>
|
||||
<th>Total Amount</th>
|
||||
<th>UTR</th>
|
||||
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="{{ 17 + hold_types|length }}">No invoices found.</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
</tr>
|
||||
|
||||
<h3>Hold Release</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Invoice No</th>
|
||||
<th>Invoice Details</th>
|
||||
<th>Basic Amount</th>
|
||||
<th>Total Amount</th>
|
||||
<th>UTR</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if hold_release %}
|
||||
{% for hold in hold_release %}
|
||||
<tr>
|
||||
<td>{{ hold['PMC_No'] }}</td>
|
||||
<td>{{ hold['Invoice_No'] }}</td>
|
||||
<td>{{ hold['Invoice_Details'] }}</td>
|
||||
<td>{{ hold['Basic_Amount'] }}</td>
|
||||
<td>{{ hold['Total_Amount'] }}</td>
|
||||
<td>{{ hold['UTR'] }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="6" style="text-align:center;">No data present</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
{% if credit_note %}
|
||||
{% for credit in credit_note %}
|
||||
<tr>
|
||||
<td>{{ credit["PMC_No"] }}</td>
|
||||
<td>{{ credit["Invoice_Details"] }}</td>
|
||||
<td>{{ credit["Basic_Amount"] }}</td>
|
||||
<td>{{ credit["Debit_Amount"] }}</td>
|
||||
<td>{{ credit["After_Debit_Amount"] }}</td>
|
||||
<td>{{ credit["GST_Amount"] }}</td>
|
||||
<td>{{ credit["Amount"] }}</td>
|
||||
<td>{{ credit["Final_Amount"] }}</td>
|
||||
<td>{{ credit["Payment_Amount"] }}</td>
|
||||
<td>{{ credit["Total_Amount"] }}</td>
|
||||
<td>{{ credit["UTR"] }}</td>
|
||||
|
||||
|
||||
<tr>
|
||||
<h3>Credit Details</h3>
|
||||
</tr>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Invoice Details</th>
|
||||
<th>Basic Amount</th>
|
||||
<th>Debit</th>
|
||||
<th>After Debit Amt</th>
|
||||
<th>GST Amount</th>
|
||||
<th>Amount</th>
|
||||
<th>Final Amount</th>
|
||||
<th>Payment Amount</th>
|
||||
<th>Total Amount</th>
|
||||
<th>UTR</th>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</tr>
|
||||
|
||||
{% if credit_note %}
|
||||
{% for credit in credit_note %}
|
||||
<tr>
|
||||
<td>{{ credit["PMC_No"] }}</td>
|
||||
<td>{{ credit["Invoice_Details"] }}</td>
|
||||
<td>{{ credit["Basic_Amount"] }}</td>
|
||||
<td>{{ credit["Debit_Amount"] }}</td>
|
||||
<td>{{ credit["After_Debit_Amount"] }}</td>
|
||||
<td>{{ credit["GST_Amount"] }}</td>
|
||||
<td>{{ credit["Amount"] }}</td>
|
||||
<td>{{ credit["Final_Amount"] }}</td>
|
||||
<td>{{ credit["Payment_Amount"] }}</td>
|
||||
<td>{{ credit["Total_Amount"] }}</td>
|
||||
<td>{{ credit["UTR"] }}</td>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="11">No Credit note found.</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</thead>
|
||||
</table>
|
||||
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="11">No Credit note found.</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<h3>GST Release Note Details</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Invoice No</th>
|
||||
<th>Basic Amount</th>
|
||||
<th>Final Amount</th>
|
||||
<th>Total Amount</th>
|
||||
<th>UTR</th>
|
||||
</tr>
|
||||
|
||||
|
||||
</thead>
|
||||
</table>
|
||||
<h3>GST Release Note Details</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Invoice No</th>
|
||||
<th>Basic Amount</th>
|
||||
<th>Final Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if gst_rel %}
|
||||
{% for gst in gst_rel %}
|
||||
<tr>
|
||||
<td>{{ gst.pmc_no }}</td>
|
||||
<td>{{ gst.Invoice_No }}</td>
|
||||
<td>{{ gst.Basic_Amount }}</td>
|
||||
<td>{{ gst.Final_Amount }}</td>
|
||||
<td>{{ gst.Total_Amount }}</td>
|
||||
<td>{{ gst.UTR }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<th colspan="2">Total</th>
|
||||
|
||||
<th>{{total["sum_gst_basic_amt"]}}</th>
|
||||
<th>{{total["sum_gst_final_amt"]}}</th>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="4">No GST release found.</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if gst_rel %}
|
||||
{% for gst in gst_rel %}
|
||||
<tr>
|
||||
<td>{{ gst.pmc_no }}</td>
|
||||
<td>{{ gst.invoice_no }}</td>
|
||||
<td>{{ gst.basic_amount }}</td>
|
||||
<td>{{ gst.final_amount }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<th colspan="2">Total</th>
|
||||
<br>
|
||||
<h3>Payment Details</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Invoice No</th>
|
||||
<th>Amount</th>
|
||||
<th>TDS Amount @ 1% on BASIC AMOUNT</th>
|
||||
<th>Total Amount Paid</th>
|
||||
<th>UTR</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if invoices %}
|
||||
{% for pay in invoices %}
|
||||
<tr>
|
||||
<td>{{ pay.PMC_No }}</td>
|
||||
<td>{{ pay.invoice_no }}</td>
|
||||
<td>{{ pay.Payment_Amount }}</td>
|
||||
<td>{{ pay.TDS_Payment_Amount }}</td>
|
||||
<td>{{ pay.Total_Amount }}</td>
|
||||
<td>{{ pay.UTR}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
<th>{{total["sum_gst_basic_amt"]}}</th>
|
||||
<th>{{total["sum_gst_final_amt"]}}</th>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="4">No GST release found.</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
<tr>
|
||||
<th colspan="2">Total</th>
|
||||
<th>{{total["sum_pay_payment_amt"]}}</th>
|
||||
<th>{{total["sum_pay_tds_payment_amt"]}}</th>
|
||||
<th>{{total["sum_pay_total_amt"]}}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
{% else %}
|
||||
|
||||
<tr>
|
||||
<td colspan="6">No payment found.</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<br>
|
||||
<h3>Payment Details</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>PMC No</th>
|
||||
<th>Invoice No</th>
|
||||
<th>Amount</th>
|
||||
<th>TDS Amount @ 1% on BASIC AMOUNT</th>
|
||||
<th>Total Amount Paid</th>
|
||||
<th>UTR</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if payments %}
|
||||
{% for pay in payments %}
|
||||
<tr>
|
||||
<td>{{ pay.pmc_no }}</td>
|
||||
<td>{{ pay.invoice_no }}</td>
|
||||
<td>{{ pay.Payment_Amount }}</td>
|
||||
<td>{{ pay.TDS_Payment_Amount }}</td>
|
||||
<td>{{ pay.Total_amount }}</td>
|
||||
<td>{{ pay.utr}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
<tr>
|
||||
<th colspan="2">Total</th>
|
||||
<th>{{total["sum_pay_payment_amt"]}}</th>
|
||||
<th>{{total["sum_pay_tds_payment_amt"]}}</th>
|
||||
<th>{{total["sum_pay_total_amt"]}}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
{% else %}
|
||||
|
||||
<tr>
|
||||
<td colspan="6">No payment found.</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<a href="{{ url_for('report.download_report', contractor_id=contractor_id) }}" class="download-btn">Download Report</a>
|
||||
</div>
|
||||
<a href="{{ url_for('report.download_report', contractor_id=contractor_id) }}" class="download-btn">Download
|
||||
Report</a>
|
||||
</div>
|
||||
</body>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user