optimize and add new service of get report and download report.
This commit is contained in:
@@ -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():
|
||||
@@ -157,12 +159,14 @@ def show_table(filename):
|
||||
def save_data():
|
||||
# Extract form data
|
||||
subcontractor_id = request.form.get("subcontractor_data")
|
||||
state_id = request.form.get("state_data")
|
||||
district_id = request.form.get("district_data")
|
||||
block_id = request.form.get("block_data")
|
||||
variables = request.form.getlist('variables[]')
|
||||
hold_columns = request.form.get("hold_columns")
|
||||
|
||||
hold_counter = request.form.get("hold_counter")
|
||||
if not data:
|
||||
return jsonify({"error": "No data provided to save"}), 400
|
||||
|
||||
if data:
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor()
|
||||
@@ -172,7 +176,7 @@ def save_data():
|
||||
"PMC_No": entry.get("PMC_No"),
|
||||
"Invoice_Details": entry.get("Invoice_Details", ''),
|
||||
"Work_Type": 'none',
|
||||
"In oice_Date": entry.get("Invoice_Date").strftime('%Y-%m-%d') if entry.get(
|
||||
"Invoice_Date": entry.get("Invoice_Date").strftime('%Y-%m-%d') if entry.get(
|
||||
"Invoice_Date") else None,
|
||||
"Invoice_No": entry.get("Invoice_No", ''),
|
||||
"Basic_Amount": entry.get("Basic_Amount", 0.00),
|
||||
@@ -227,6 +231,7 @@ def save_data():
|
||||
else:
|
||||
work_type = " ".join(words[:work_pos + 1])
|
||||
if Invoice_Details and 'village' in Invoice_Details.lower() and 'work' in Invoice_Details.lower():
|
||||
# print("village_name ::", village_name, "|| work_type ::", work_type)
|
||||
if block_id and village_name:
|
||||
village_id = None
|
||||
cursor.callproc("GetVillageId", (block_id, village_name))
|
||||
@@ -239,6 +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)
|
||||
|
||||
args = (
|
||||
PMC_No, village_id, work_type, Invoice_Details, Invoice_Date, Invoice_No,
|
||||
@@ -247,24 +257,39 @@ def save_data():
|
||||
subcontractor_id, 0
|
||||
)
|
||||
|
||||
# print("All invoice Details ",args)
|
||||
# add subcontarctor id in invoice table
|
||||
results = cursor.callproc('SaveInvoice', args)
|
||||
invoice_id = results[-1]
|
||||
print("**************************************************************")
|
||||
print(invoice_id)
|
||||
print("**************************************************************")
|
||||
cursor.callproc(
|
||||
"SavePayment",
|
||||
(
|
||||
PMC_No,
|
||||
Invoice_No, # required
|
||||
Payment_Amount,
|
||||
TDS_Payment_Amount,
|
||||
Total_Amount,
|
||||
UTR,
|
||||
invoice_id # last
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
cursor.callproc("SavePayment",( PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount,Total_Amount, UTR,invoice_id))
|
||||
|
||||
# print("invoice id from the excel ", invoice_id)
|
||||
if isinstance(hold_columns, str):
|
||||
hold_columns = ast.literal_eval(hold_columns)
|
||||
if isinstance(hold_columns, list) and all(isinstance(hold, dict) for hold in hold_columns):
|
||||
for hold in hold_columns:
|
||||
|
||||
hold_column_name = hold.get('column_name')
|
||||
hold_type_id = hold.get('hold_type_id')
|
||||
# print(f"Processing hold: {hold}")
|
||||
hold_column_name = hold.get('column_name') # Get column name
|
||||
hold_type_id = hold.get('hold_type_id') # Get hold_type_id
|
||||
if hold_column_name:
|
||||
hold_amount = entry.get(
|
||||
hold_column_name)
|
||||
hold_column_name) # Get the value for that specific hold column
|
||||
if hold_amount is not None:
|
||||
|
||||
# print(f"Processing hold type: {hold_column_name}, Hold Amount: {hold_amount}")
|
||||
hold_join_data = {
|
||||
"Contractor_Id": subcontractor_id,
|
||||
"Invoice_Id": invoice_id,
|
||||
@@ -281,9 +306,10 @@ def save_data():
|
||||
print(f"Invalid hold entry: {hold}")
|
||||
else:
|
||||
print("Hold columns data is not a valid list of dictionaries.")
|
||||
#-------------------------Credit Note--------------------------------------------------
|
||||
#---------------------------------------------Credit Note---------------------------------------------------------------------------
|
||||
elif any(keyword in Invoice_Details.lower() for keyword in ['credit note','logging report']):
|
||||
|
||||
# print("Credit note found:", PMC_No, Invoice_No, Basic_Amount, Debit_Amount, Final_Amount,
|
||||
# After_Debit_Amount, GST_Amount, Amount, Final_Amount, Payment_Amount, Total_Amount, UTR, Invoice_No)
|
||||
cursor.callproc(
|
||||
'AddCreditNoteFromExcel',
|
||||
[
|
||||
@@ -292,7 +318,7 @@ def save_data():
|
||||
subcontractor_id, Invoice_No
|
||||
]
|
||||
)
|
||||
#--------------------------Hold Amount-------------------------------------------------
|
||||
#-----------------------------------------------Hold Amount----------------------------------------------------------------------
|
||||
# Step 1: Normalize Invoice_Details: lowercase, trim, remove extra spaces
|
||||
normalized_details = re.sub(r'\s+', ' ', Invoice_Details.strip()).lower()
|
||||
# Step 2: Define lowercase keywords
|
||||
@@ -308,13 +334,13 @@ def save_data():
|
||||
]
|
||||
# Step 3: Matching condition
|
||||
if any(kw in normalized_details for kw in keywords):
|
||||
# print(" Match found. Inserting hold release for:", Invoice_Details)
|
||||
# print("✅ Match found. Inserting hold release for:", Invoice_Details)
|
||||
cursor.callproc(
|
||||
'AddHoldReleaseFromExcel',
|
||||
[PMC_No, Invoice_No, Invoice_Details, Basic_Amount, Final_Amount, UTR, subcontractor_id]
|
||||
)
|
||||
connection.commit()
|
||||
# print(" Hold release inserted for:", PMC_No, Invoice_Details)
|
||||
# print("✅ Hold release inserted for:", PMC_No, Invoice_Details)
|
||||
#------------------------------------------------------------------------------------------------------------------
|
||||
elif Invoice_Details and any(
|
||||
keyword in Invoice_Details.lower() for keyword in ['gst', 'release', 'gst release note']):
|
||||
@@ -327,30 +353,48 @@ def save_data():
|
||||
# --------------------------------------
|
||||
# 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)
|
||||
|
||||
cursor.execute(
|
||||
"""
|
||||
INSERT INTO invoice (PMC_No,Contractor_Id) VALUES (%s, %s);
|
||||
""",
|
||||
(PMC_No, subcontractor_id)
|
||||
)
|
||||
connection.commit()
|
||||
# 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
|
||||
|
||||
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()
|
||||
# # 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,
|
||||
Invoice_No, # required
|
||||
Payment_Amount,
|
||||
TDS_Payment_Amount,
|
||||
Total_Amount,
|
||||
@@ -359,6 +403,39 @@ def save_data():
|
||||
)
|
||||
)
|
||||
|
||||
# if PMC_No and Total_Amount and UTR:
|
||||
# print("Payment :", PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR )
|
||||
|
||||
# Add inoice id in payment table
|
||||
# cursor.callproc("SavePayment",(PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR, invoice_id))
|
||||
|
||||
# if not village_id:
|
||||
# village_id = None
|
||||
# cursor.callproc('InsertOrUpdateInPayment', (
|
||||
# PMC_No,
|
||||
# village_id,
|
||||
# work_type,
|
||||
# Invoice_Details,
|
||||
# Invoice_Date,
|
||||
# Invoice_No,
|
||||
# Basic_Amount,
|
||||
# Debit_Amount,
|
||||
# After_Debit_Amount,
|
||||
# Amount,
|
||||
# GST_Amount,
|
||||
# TDS_Amount,
|
||||
# SD_Amount,
|
||||
# On_Commission,
|
||||
# Hydro_Testing,
|
||||
# 0,
|
||||
# GST_SD_Amount,
|
||||
# Final_Amount,
|
||||
# Payment_Amount,
|
||||
# TDS_Payment_Amount,
|
||||
# Total_Amount,
|
||||
# UTR,f
|
||||
# subcontractor_id
|
||||
# ))
|
||||
connection.commit()
|
||||
return jsonify({"success": "Data saved successfully!"}), 200
|
||||
except Exception as e:
|
||||
@@ -368,3 +445,4 @@ def save_data():
|
||||
cursor.close()
|
||||
connection.close()
|
||||
return render_template('index.html')
|
||||
# ---------------------- Report --------------------------------
|
||||
@@ -1,10 +1,10 @@
|
||||
# routes/gst_release_routes.py
|
||||
from flask import Blueprint, render_template, request, redirect, url_for, flash
|
||||
from flask_login import login_required
|
||||
from model.gst_release import GSTRelease
|
||||
from model.Log import LogHelper
|
||||
|
||||
gst_release_bp = Blueprint('gst_release_bp', __name__)
|
||||
|
||||
gst_service = GSTRelease()
|
||||
|
||||
# ---------------- ADD GST RELEASE ----------------
|
||||
|
||||
@@ -5,16 +5,16 @@ from model.GST import GST
|
||||
|
||||
hold_bp = Blueprint("hold_types", __name__)
|
||||
|
||||
|
||||
hold = HoldTypes()
|
||||
# ---------------- ADD HOLD TYPE ----------------
|
||||
@hold_bp.route('/add_hold_type', methods=['GET','POST'])
|
||||
@login_required
|
||||
def add_hold_type():
|
||||
hold = HoldTypes()
|
||||
# hold = HoldTypes()
|
||||
|
||||
if request.method == 'POST':
|
||||
hold.AddHoldType(request)
|
||||
# Always redirect to same page (NO JSON)
|
||||
# ✅ Always redirect to same page (NO JSON)
|
||||
return redirect(url_for("hold_types.add_hold_type"))
|
||||
|
||||
# GET request → show data
|
||||
@@ -30,7 +30,7 @@ def add_hold_type():
|
||||
@login_required
|
||||
def check_hold_type():
|
||||
|
||||
hold = HoldTypes()
|
||||
# hold = HoldTypes()
|
||||
return hold.CheckHoldType(request) # if exists
|
||||
|
||||
|
||||
@@ -39,13 +39,13 @@ def check_hold_type():
|
||||
@login_required
|
||||
def edit_hold_type(id):
|
||||
|
||||
hold = HoldTypes()
|
||||
# hold = HoldTypes()
|
||||
|
||||
if request.method == 'POST':
|
||||
hold.EditHoldType(request, id)
|
||||
hold.EditHoldType(request, id) # ✅
|
||||
return hold.resultMessage
|
||||
|
||||
hold_data = hold.GetHoldTypeByID(id)
|
||||
hold_data = hold.GetHoldTypeByID(id) # ✅
|
||||
|
||||
return render_template(
|
||||
"edit_hold_type.html",
|
||||
@@ -58,8 +58,8 @@ def edit_hold_type(id):
|
||||
@login_required
|
||||
def delete_hold_type(id):
|
||||
|
||||
hold = HoldTypes()
|
||||
hold.DeleteHoldType(request, id)
|
||||
# hold = HoldTypes()
|
||||
hold.DeleteHoldType(request, id) # ✅
|
||||
|
||||
return redirect(url_for("hold_types.add_hold_type"))
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# controllers/invoice_controller.py
|
||||
|
||||
from flask import Blueprint, request, jsonify, render_template
|
||||
from flask_login import login_required, current_user
|
||||
from model.Invoice import *
|
||||
@@ -35,7 +37,11 @@ def add_invoice():
|
||||
|
||||
village_id = village_result['Village_Id']
|
||||
invoice_id = insert_invoice(data, village_id)
|
||||
assign_subcontractor(data, village_id)
|
||||
# assign_subcontractor(data, village_id)
|
||||
print("********************************************************************")
|
||||
print("Manully added invoice id :",invoice_id)
|
||||
print("********************************************************************")
|
||||
|
||||
insert_hold_types(data, invoice_id)
|
||||
|
||||
log_action("Add invoice", f"added invoice '{data.get('pmc_no')}'")
|
||||
@@ -78,6 +84,7 @@ def edit_invoice(invoice_id):
|
||||
if request.method == 'POST':
|
||||
data = request.form
|
||||
update_invoice(data, invoice_id)
|
||||
# update_inpayment(data)
|
||||
log_action("Edit invoice", f"edited invoice '{invoice_id}'")
|
||||
return jsonify({"status": "success", "message": "Invoice updated successfully"}), 200
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ def add_payment():
|
||||
|
||||
LogHelper.log_action("Add Payment", f"User {current_user.id} Add Payment '{pmc_no}'")
|
||||
Paymentmodel.insert_payment(subcontractor_id,pmc_no, invoice_no, amount, tds_amount, total_amount, utr)
|
||||
# Paymentmodel.update_inpayment(subcontractor_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr)
|
||||
|
||||
return redirect(url_for('payment_bp.add_payment'))
|
||||
|
||||
@@ -70,15 +71,14 @@ def edit_payment(payment_id):
|
||||
LogHelper.log_action("Edit Payment", f"User {current_user.id} Edit Payment '{pmc_no}'")
|
||||
Paymentmodel.call_update_payment_proc(payment_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr)
|
||||
|
||||
connection = Paymentmodel.get_connection()
|
||||
cursor = connection.cursor()
|
||||
cursor.callproc(
|
||||
'UpdateInpaymentByPMCInvoiceUTR',
|
||||
[amount, tds_amount, total_amount, pmc_no, invoice_no, utr]
|
||||
)
|
||||
connection.commit()
|
||||
cursor.close()
|
||||
connection.close()
|
||||
# Update inpayment
|
||||
# connection = Paymentmodel.get_connection()
|
||||
# cursor = connection.cursor()
|
||||
# cursor.callproc('UpdateInpaymentByPMCInvoiceUTR',[amount, tds_amount, total_amount, pmc_no, invoice_no, utr])
|
||||
|
||||
# connection.commit()
|
||||
# cursor.close()
|
||||
# connection.close()
|
||||
|
||||
return redirect(url_for('payment_bp.add_payment'))
|
||||
|
||||
|
||||
@@ -1,41 +1,40 @@
|
||||
from flask import Blueprint, render_template, send_from_directory
|
||||
from flask_login import login_required
|
||||
# from flask import Blueprint, render_template, send_from_directory
|
||||
# from flask_login import login_required
|
||||
# from model.PmcReport import PmcReport
|
||||
|
||||
from model.PmcReport import PmcReport
|
||||
# pmc_report_bp = Blueprint("pmc_report", __name__)
|
||||
|
||||
pmc_report_bp = Blueprint("pmc_report", __name__)
|
||||
# # ---------------- Contractor Report by pmc no ----------------
|
||||
# @pmc_report_bp.route("/pmc_report/<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,12 +1,10 @@
|
||||
from flask import Blueprint, render_template, request, jsonify, send_file
|
||||
from flask_login import login_required, current_user
|
||||
|
||||
from services.ReportService import ReportService
|
||||
from model.Report import ReportHelper
|
||||
from model.Log import LogHelper
|
||||
|
||||
report_bp = Blueprint("report", __name__)
|
||||
|
||||
|
||||
# ---------------- Report Page ----------------
|
||||
@report_bp.route("/report")
|
||||
@login_required
|
||||
@@ -19,36 +17,70 @@ def report_page():
|
||||
@login_required
|
||||
def search_contractor():
|
||||
|
||||
subcontractor_name = request.form.get("subcontractor_name")
|
||||
|
||||
LogHelper.log_action(
|
||||
"Search Contractor",
|
||||
f"User {current_user.id} searched contractor '{subcontractor_name}'"
|
||||
)
|
||||
|
||||
data = ReportHelper.search_contractor(request)
|
||||
|
||||
return jsonify(data)
|
||||
# Pagination (basic)
|
||||
page = int(request.form.get("page", 1))
|
||||
per_page = 20
|
||||
|
||||
start = (page - 1) * per_page
|
||||
end = start + per_page
|
||||
|
||||
paginated_data = data[start:end]
|
||||
|
||||
return jsonify({
|
||||
"data": paginated_data,
|
||||
"total": len(data)
|
||||
})
|
||||
|
||||
# ---------------- Contractor Report by contractor id ----------------
|
||||
@report_bp.route('/contractor_report/<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 ----------------
|
||||
@report_bp.route('/download_report/<int:contractor_id>')
|
||||
@login_required
|
||||
def download_report(contractor_id):
|
||||
output_file, error = ReportHelper.create_contractor_report(contractor_id)
|
||||
|
||||
service = ReportService(contractor_id=contractor_id).load_data()
|
||||
|
||||
file, error = service.download_excel()
|
||||
|
||||
if error:
|
||||
return error, 404
|
||||
|
||||
return send_file(output_file, as_attachment=True)
|
||||
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':
|
||||
|
||||
|
||||
@@ -3,12 +3,17 @@ from flask_login import login_required
|
||||
from model.Subcontractor import Subcontractor
|
||||
from model.Utilities import HtmlHelper, ResponseHandler
|
||||
|
||||
|
||||
subcontractor_bp = Blueprint('subcontractor', __name__)
|
||||
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# LIST + ADD
|
||||
# ----------------------------------------------------------
|
||||
@subcontractor_bp.route('/subcontractor', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def subcontract():
|
||||
|
||||
sub = Subcontractor()
|
||||
|
||||
# ---------------- GET ----------------
|
||||
@@ -26,22 +31,27 @@ def subcontract():
|
||||
if request.method == 'POST':
|
||||
|
||||
sub.AddSubcontractor(request)
|
||||
|
||||
if not sub.isSuccess:
|
||||
return HtmlHelper.json_response(
|
||||
ResponseHandler.add_failure("Subcontractor"), 500
|
||||
)
|
||||
|
||||
# Reload list after insert
|
||||
subcontractor = sub.GetAllSubcontractors(request)
|
||||
|
||||
return render_template('add_subcontractor.html', subcontractor=subcontractor)
|
||||
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# EDIT
|
||||
# ----------------------------------------------------------
|
||||
@subcontractor_bp.route('/edit_subcontractor/<int:id>', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def edit_subcontractor(id):
|
||||
|
||||
sub = Subcontractor()
|
||||
|
||||
# Fetch data
|
||||
subcontractor = sub.GetSubcontractorByID(id)
|
||||
|
||||
@@ -65,7 +75,9 @@ def edit_subcontractor(id):
|
||||
return render_template('edit_subcontractor.html', subcontractor=subcontractor)
|
||||
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# DELETE
|
||||
# ----------------------------------------------------------
|
||||
@subcontractor_bp.route('/deleteSubContractor/<int:id>', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def deleteSubContractor(id):
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify
|
||||
from flask_login import login_required
|
||||
|
||||
@@ -7,14 +11,14 @@ from model.State import State
|
||||
|
||||
# Create Blueprint
|
||||
village_bp = Blueprint('village', __name__)
|
||||
|
||||
village = Village()
|
||||
|
||||
# ------------------------- Add Village -------------------------
|
||||
@village_bp.route('/add_village', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def add_village():
|
||||
|
||||
village = Village()
|
||||
# village = Village()
|
||||
|
||||
if request.method == 'POST':
|
||||
village.AddVillage(request=request)
|
||||
@@ -75,24 +79,25 @@ def get_blocks(district_id):
|
||||
@village_bp.route('/check_village', methods=['POST'])
|
||||
@login_required
|
||||
def check_village():
|
||||
village = Village()
|
||||
# village = Village()
|
||||
return village.CheckVillage(request=request)
|
||||
|
||||
|
||||
@village_bp.route('/delete_village/<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
|
||||
# ✅ Convert resultMessage to string if it's a Response or tuple
|
||||
raw_msg = village.resultMessage
|
||||
|
||||
if isinstance(raw_msg, tuple):
|
||||
# e.g., (<Response ...>, 200)
|
||||
msg = "Village deleted successfully!"
|
||||
elif hasattr(raw_msg, 'get_data'):
|
||||
# Flask Response object
|
||||
msg = raw_msg.get_data(as_text=True)
|
||||
msg = raw_msg.get_data(as_text=True) # get raw text
|
||||
else:
|
||||
# fallback
|
||||
msg = str(raw_msg) if raw_msg else "Village deleted successfully!"
|
||||
@@ -107,7 +112,7 @@ def delete_village(village_id):
|
||||
@login_required
|
||||
def edit_village(village_id):
|
||||
|
||||
village = Village()
|
||||
# village = Village()
|
||||
|
||||
if request.method == 'POST':
|
||||
|
||||
@@ -130,6 +135,7 @@ def edit_village(village_id):
|
||||
)
|
||||
|
||||
else:
|
||||
# ✅ FIXED HERE (removed request)
|
||||
village_data = village.GetVillageByID(id=village_id)
|
||||
|
||||
if not village.isSuccess:
|
||||
|
||||
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,11 +1,12 @@
|
||||
import os
|
||||
from flask import current_app
|
||||
|
||||
# -----------------------------
|
||||
# BASE FOLDER Class
|
||||
# -----------------------------
|
||||
|
||||
class FolderAndFile:
|
||||
|
||||
# -----------------------------
|
||||
# BASE FOLDER METHODS
|
||||
# -----------------------------
|
||||
@staticmethod
|
||||
def get_download_folder():
|
||||
folder = os.path.join(current_app.root_path, "static", "downloads")
|
||||
|
||||
@@ -10,7 +10,7 @@ class GST:
|
||||
invoices_rows = invoice_crud.GetAllData(storedproc="GetAllInvoicesBasic")
|
||||
|
||||
if not invoice_crud.isSuccess:
|
||||
return []
|
||||
return [] # Could also log invoice_crud.resultMessage
|
||||
|
||||
invoices = [
|
||||
dict(
|
||||
@@ -25,16 +25,16 @@ class GST:
|
||||
gst_rows = gst_crud.GetAllData(storedproc="GetAllGSTReleasesBasic")
|
||||
|
||||
if not gst_crud.isSuccess:
|
||||
return []
|
||||
return [] # Could also log gst_crud.resultMessage
|
||||
|
||||
gst_invoice_nos = {
|
||||
g[2]
|
||||
g[2] # Invoice_No is at index 2
|
||||
for g in gst_rows
|
||||
if g[2]
|
||||
}
|
||||
|
||||
gst_basic_amounts = {
|
||||
float(g[3])
|
||||
float(g[3]) # Basic_Amount at index 3
|
||||
for g in gst_rows
|
||||
if g[3] is not None
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
import config
|
||||
import mysql.connector
|
||||
|
||||
# ------------------- Helper Functions -------------------
|
||||
def clear_results(cursor):
|
||||
@@ -69,7 +71,22 @@ def get_all_villages():
|
||||
def insert_invoice(data, village_id):
|
||||
def operation(cursor):
|
||||
# Insert invoice
|
||||
cursor.callproc('InsertInvoice', [
|
||||
# cursor.callproc('InsertInvoice', [
|
||||
# data.get('pmc_no'),
|
||||
# village_id,
|
||||
# data.get('work_type'),
|
||||
# data.get('invoice_details'),
|
||||
# data.get('invoice_date'),
|
||||
# data.get('invoice_no'),
|
||||
# *get_numeric_values(data),
|
||||
# data.get('subcontractor_id')
|
||||
|
||||
# ])
|
||||
# invoice_row = fetch_one(cursor)
|
||||
# if not invoice_row:
|
||||
# raise Exception("Invoice ID not returned")
|
||||
# invoice_id = invoice_row.get('invoice_id')
|
||||
cursor.callproc('SaveInvoice', [
|
||||
data.get('pmc_no'),
|
||||
village_id,
|
||||
data.get('work_type'),
|
||||
@@ -77,14 +94,27 @@ def insert_invoice(data, village_id):
|
||||
data.get('invoice_date'),
|
||||
data.get('invoice_no'),
|
||||
*get_numeric_values(data),
|
||||
data.get('subcontractor_id')
|
||||
|
||||
data.get('subcontractor_id'),
|
||||
0
|
||||
])
|
||||
invoice_row = fetch_one(cursor)
|
||||
if not invoice_row:
|
||||
raise Exception("Invoice ID not returned")
|
||||
invoice_id = invoice_row.get('invoice_id')
|
||||
invoice_id = None
|
||||
for result in cursor.stored_results():
|
||||
row = result.fetchone()
|
||||
if row:
|
||||
invoice_id = row['invoice_id']
|
||||
|
||||
# # Insert inpayment
|
||||
# cursor.callproc('InsertInpayment', [
|
||||
# data.get('pmc_no'),
|
||||
# village_id,
|
||||
# data.get('work_type'),
|
||||
# data.get('invoice_details'),
|
||||
# data.get('invoice_date'),
|
||||
# data.get('invoice_no'),
|
||||
# *get_numeric_values(data),
|
||||
# data.get('subcontractor_id')
|
||||
# ])
|
||||
# clear_results(cursor)
|
||||
return invoice_id
|
||||
|
||||
return execute_db_operation(operation)
|
||||
@@ -129,6 +159,18 @@ def update_invoice(data, invoice_id):
|
||||
clear_results(cursor)
|
||||
execute_db_operation(operation)
|
||||
|
||||
# def update_inpayment(data):
|
||||
# def operation(cursor):
|
||||
# cursor.callproc('UpdateInpayment', [
|
||||
# data.get('work_type'),
|
||||
# data.get('invoice_details'),
|
||||
# data.get('invoice_date'),
|
||||
# *get_numeric_values(data),
|
||||
# data.get('pmc_no'),
|
||||
# data.get('invoice_no')
|
||||
# ])
|
||||
# clear_results(cursor)
|
||||
# execute_db_operation(operation)
|
||||
|
||||
def delete_invoice_data(invoice_id, user_id):
|
||||
def operation(cursor):
|
||||
@@ -140,24 +182,31 @@ def delete_invoice_data(invoice_id, user_id):
|
||||
if not record:
|
||||
raise Exception("Invoice not found")
|
||||
|
||||
# Use exact DB keys
|
||||
pmc_no = record['PMC_No']
|
||||
invoice_no = record['Invoice_No']
|
||||
|
||||
# Delete invoice
|
||||
cursor.callproc("DeleteInvoice", (invoice_id,))
|
||||
clear_results(cursor)
|
||||
|
||||
# Delete inpayment
|
||||
# cursor.callproc('DeleteInpaymentByPMCInvoice', (pmc_no, invoice_no))
|
||||
# clear_results(cursor)
|
||||
|
||||
execute_db_operation(operation)
|
||||
|
||||
|
||||
# ------------------- Subcontractor Functions -------------------
|
||||
def assign_subcontractor(data, village_id):
|
||||
def operation(cursor):
|
||||
cursor.callproc('AssignSubcontractor', [
|
||||
data.get('pmc_no'),
|
||||
data.get('subcontractor_id'),
|
||||
village_id
|
||||
])
|
||||
clear_results(cursor)
|
||||
execute_db_operation(operation)
|
||||
# def assign_subcontractor(data, village_id):
|
||||
# def operation(cursor):
|
||||
# cursor.callproc('AssignSubcontractor', [
|
||||
# data.get('pmc_no'),
|
||||
# data.get('subcontractor_id'),
|
||||
# village_id
|
||||
# ])
|
||||
# clear_results(cursor)
|
||||
# execute_db_operation(operation)
|
||||
|
||||
|
||||
# ------------------- Hold Types Functions -------------------
|
||||
|
||||
@@ -1,275 +1,137 @@
|
||||
import openpyxl
|
||||
from openpyxl.styles import Font
|
||||
import config
|
||||
from flask_login import current_user
|
||||
from model.Log import LogHelper
|
||||
|
||||
from model.Report import ReportHelper
|
||||
from services.Generalservice import GeneralUse
|
||||
from model.FolderAndFile import FolderAndFile
|
||||
from model.Report import ReportHelper
|
||||
|
||||
class PmcReport:
|
||||
data=[]
|
||||
|
||||
@staticmethod
|
||||
def get_pmc_report(pmc_no):
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor(dictionary=True, buffered=True)
|
||||
# @staticmethod
|
||||
# def get_pmc_report(pmc_no):
|
||||
|
||||
try:
|
||||
pmc_info = ReportHelper.execute_sp(cursor, 'GetContractorInfoByPmcNo', [pmc_no], True)
|
||||
# connection = config.get_db_connection()
|
||||
# cursor = connection.cursor(dictionary=True, buffered=True)
|
||||
|
||||
if not pmc_info:
|
||||
return None
|
||||
# try:
|
||||
# pmc_info = GeneralUse.execute_sp(cursor, 'GetContractorInfoByPmcNo', [pmc_no], True)
|
||||
# cursor.callproc("Get_pmc_hold_types", (pmc_no, pmc_info["Contractor_Id"]))
|
||||
# hold_types = next(cursor.stored_results()).fetchall()
|
||||
|
||||
cursor.callproc("Get_pmc_hold_types", (pmc_no, pmc_info["Contractor_Id"]))
|
||||
hold_types = next(cursor.stored_results()).fetchall()
|
||||
# # Extract hold_type_ids
|
||||
# hold_type_ids = [ht['hold_type_id'] for ht in hold_types]
|
||||
|
||||
# Extract hold_type_ids
|
||||
hold_type_ids = [ht['hold_type_id'] for ht in hold_types]
|
||||
# invoices = []
|
||||
# hold_type_ids_str = ",".join(map(str, hold_type_ids))
|
||||
# cursor.callproc('GetInvoices_WithHold',[pmc_no, pmc_info["Contractor_Id"], hold_type_ids_str])
|
||||
# for result in cursor.stored_results():
|
||||
# invoices = result.fetchall()
|
||||
|
||||
invoices = []
|
||||
hold_amount_total = 0
|
||||
if hold_type_ids:
|
||||
hold_type_ids_str = ",".join(map(str, hold_type_ids))
|
||||
cursor.callproc(
|
||||
'GetInvoices_WithHold',
|
||||
[pmc_no, pmc_info["Contractor_Id"], hold_type_ids_str]
|
||||
)
|
||||
else:
|
||||
cursor.callproc(
|
||||
'GetInvoices_NoHold',
|
||||
[pmc_no, pmc_info["Contractor_Id"]]
|
||||
)
|
||||
for result in cursor.stored_results():
|
||||
invoices = result.fetchall()
|
||||
# gst_rel = GeneralUse.execute_sp(cursor, 'GetGSTReleaseByPMC', [pmc_no])
|
||||
|
||||
if hold_type_ids:
|
||||
hold_amount_total = sum(row.get('hold_amount', 0) or 0 for row in invoices)
|
||||
# hold_release = GeneralUse.execute_sp(cursor, 'GetHoldReleaseByPMC', [pmc_no])
|
||||
|
||||
total_invo_final = sum(row.get('Final_Amount', 0) or 0 for row in invoices)
|
||||
# credit_note = GeneralUse.execute_sp(cursor, 'GetCreditNoteByPMC', [pmc_no])
|
||||
|
||||
# GST RELEASE
|
||||
gst_rel = ReportHelper.execute_sp(cursor, 'GetGSTReleaseByPMC', [pmc_no])
|
||||
# payments = GeneralUse.execute_sp(cursor, 'GetPaymentsByPMC', [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)
|
||||
# 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 ----------------
|
||||
hold_release = ReportHelper.execute_sp(cursor, 'GetHoldReleaseByPMC', [pmc_no])
|
||||
# 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
|
||||
# }
|
||||
|
||||
# ---------------- CREDIT NOTE ----------------
|
||||
credit_note = ReportHelper.execute_sp(cursor, 'GetCreditNoteByPMC', [pmc_no])
|
||||
|
||||
# ---------------- PAYMENTS ----------------
|
||||
payments = ReportHelper.execute_sp(cursor, 'GetPaymentsByPMC', [pmc_no])
|
||||
|
||||
total_pay_amount = sum(row.get('Payment_Amount', 0) or 0 for row in payments)
|
||||
total_pay_total = sum(row.get('Total_amount', 0) or 0 for row in payments)
|
||||
|
||||
totals = {
|
||||
"sum_invo_basic_amt": sum(row.get('Basic_Amount', 0) or 0 for row in invoices),
|
||||
"sum_invo_debit_amt": sum(row.get('Debit_Amount', 0) or 0 for row in invoices),
|
||||
"sum_invo_after_debit_amt": sum(row.get('After_Debit_Amount', 0) or 0 for row in invoices),
|
||||
"sum_invo_amt": sum(row.get('Amount', 0) or 0 for row in invoices),
|
||||
"sum_invo_gst_amt": sum(row.get('GST_Amount', 0) or 0 for row in invoices),
|
||||
"sum_invo_tds_amt": sum(row.get('TDS_Amount', 0) or 0 for row in invoices),
|
||||
"sum_invo_ds_amt": sum(row.get('SD_Amount', 0) or 0 for row in invoices),
|
||||
"sum_invo_on_commission": sum(row.get('On_Commission', 0) or 0 for row in invoices),
|
||||
"sum_invo_hydro_test": sum(row.get('Hydro_Testing', 0) or 0 for row in invoices),
|
||||
"sum_invo_gst_sd_amt": sum(row.get('GST_SD_Amount', 0) or 0 for row in invoices),
|
||||
"sum_invo_final_amt": total_invo_final,
|
||||
"sum_invo_hold_amt": hold_amount_total,
|
||||
"sum_gst_basic_amt": total_gst_basic,
|
||||
"sum_gst_final_amt": total_gst_final,
|
||||
"sum_pay_payment_amt": total_pay_amount,
|
||||
"sum_pay_tds_payment_amt": sum(row.get('TDS_Payment_Amount', 0) or 0 for row in payments),
|
||||
"sum_pay_total_amt": total_pay_total
|
||||
}
|
||||
|
||||
return {
|
||||
"info": pmc_info,
|
||||
"invoices": invoices,
|
||||
"hold_types": hold_types,
|
||||
"gst_rel": gst_rel,
|
||||
"payments": payments,
|
||||
"credit_note": credit_note,
|
||||
"hold_release": hold_release,
|
||||
"total": totals
|
||||
}
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
# finally:
|
||||
# cursor.close()
|
||||
# connection.close()
|
||||
|
||||
|
||||
@staticmethod
|
||||
def download_pmc_report(pmc_no):
|
||||
# @staticmethod
|
||||
# def download_pmc_report(pmc_no):
|
||||
|
||||
connection = config.get_db_connection()
|
||||
if not connection:
|
||||
return None
|
||||
# connection = config.get_db_connection()
|
||||
# if not connection:
|
||||
# return None
|
||||
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
try:
|
||||
filename = f"PMC_Report_{pmc_no}.xlsx"
|
||||
# cursor = connection.cursor(dictionary=True)
|
||||
|
||||
output_folder = FolderAndFile.get_download_folder()
|
||||
output_file = FolderAndFile.get_download_path(filename)
|
||||
# try:
|
||||
# filename = f"PMC_Report_{pmc_no}.xlsx"
|
||||
|
||||
# ================= DATA FETCH =============
|
||||
contractor_info = ReportHelper.execute_sp(cursor, 'GetContractorDetailsByPMC', [pmc_no])
|
||||
# output_folder = FolderAndFile.get_download_folder()
|
||||
# output_file = FolderAndFile.get_download_path(filename)
|
||||
|
||||
contractor_info = contractor_info[0] if contractor_info else None
|
||||
# contractor_info = GeneralUse.execute_sp(cursor, 'GetContractorInfoByPmcNo', [pmc_no])
|
||||
|
||||
if not contractor_info:
|
||||
return None
|
||||
# contractor_info = contractor_info[0] if contractor_info else None
|
||||
# print("contractor_info:::",contractor_info)
|
||||
|
||||
hold_types = ReportHelper.execute_sp(cursor, 'GetHoldTypesByContractor',[contractor_info["Contractor_Id"]])
|
||||
# if not contractor_info:
|
||||
# return None
|
||||
|
||||
hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types}
|
||||
# hold_types = GeneralUse.execute_sp(cursor, 'GetHoldTypesByContractor',[contractor_info["Contractor_Id"]])
|
||||
|
||||
invoices = ReportHelper.execute_sp(cursor, 'GetInvoicesAndGstReleaseByPmcNo', [pmc_no])
|
||||
# hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types}
|
||||
|
||||
credit_notes = ReportHelper.execute_sp(cursor, 'NewGetCreditNotesByPMCNo', [pmc_no])
|
||||
# invoices = GeneralUse.execute_sp(cursor, 'GetInvoicesByContractorOrPMCNo', [None,pmc_no])
|
||||
|
||||
hold_amounts = ReportHelper.execute_sp(cursor, 'GetHoldAmountsByContractor',[contractor_info["Contractor_Id"]])
|
||||
# credit_notes = GeneralUse.execute_sp(cursor, 'NewGetCreditNotesByPMCNo', [pmc_no])
|
||||
# credit_note_map = {}
|
||||
# for cn in credit_notes:
|
||||
|
||||
gst_releases = ReportHelper.execute_sp(cursor, 'GetGSTReleaseDetailsByPMC', [pmc_no])
|
||||
# key = (str(cn['PMC_No']).strip())
|
||||
# credit_note_map.setdefault(key, []).append(cn)
|
||||
|
||||
# ================= DATA MAPPING =================
|
||||
hold_data = {}
|
||||
for h in hold_amounts:
|
||||
hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
||||
# hold_amounts = GeneralUse.execute_sp(cursor, 'GetHoldAmountsByContractor', [contractor_info["Contractor_Id"]])
|
||||
|
||||
credit_note_map = {}
|
||||
for cn in credit_notes:
|
||||
pmc = cn.get("PMC_No")
|
||||
if pmc:
|
||||
credit_note_map.setdefault(pmc, []).append(cn)
|
||||
# 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)
|
||||
|
||||
gst_map = {}
|
||||
for gst in gst_releases:
|
||||
pmc = gst.get("PMC_No")
|
||||
if pmc:
|
||||
gst_map.setdefault(pmc, []).append(gst)
|
||||
# # ================= DATA MAPPING =================
|
||||
# hold_data = {}
|
||||
# for h in hold_amounts:
|
||||
# hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
||||
|
||||
# ================= LOG =================
|
||||
LogHelper.log_action("Download PMC Report",f"User {current_user.id} Download PMC Report '{pmc_no}'")
|
||||
# # ================= LOG =================
|
||||
# LogHelper.log_action("Download PMC Report",f"User {current_user.id} Download PMC Report '{pmc_no}'")
|
||||
|
||||
# ================= EXCEL =================
|
||||
workbook = openpyxl.Workbook()
|
||||
sheet = workbook.active
|
||||
sheet.title = "PMC Report"
|
||||
# ReportHelper.generate_excel(
|
||||
# 0, contractor_info, invoices, hold_types, hold_data,
|
||||
# credit_note_map,gst_release_map, output_file)
|
||||
|
||||
# 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([])
|
||||
# return output_folder, filename
|
||||
|
||||
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"
|
||||
]
|
||||
# finally:
|
||||
# cursor.close()
|
||||
# connection.close()
|
||||
|
||||
hold_headers = [ht['hold_type'] for ht in hold_types]
|
||||
payment_headers = ["Final Amount", "Payment Amount", "TDS Payment", "Total Paid", "UTR"]
|
||||
|
||||
headers = base_headers + hold_headers + payment_headers
|
||||
sheet.append(headers)
|
||||
for cell in sheet[sheet.max_row]:
|
||||
cell.font = Font(bold=True)
|
||||
|
||||
# ================= INVOICE ROWS =================
|
||||
for inv in invoices:
|
||||
row = [
|
||||
pmc_no,
|
||||
inv.get("Village_Name", ""),
|
||||
inv.get("Work_Type", ""),
|
||||
inv.get("Invoice_Details", ""),
|
||||
inv.get("Invoice_Date", ""),
|
||||
inv.get("invoice_no", ""),
|
||||
inv.get("Basic_Amount", ""),
|
||||
inv.get("Debit_Amount", ""),
|
||||
inv.get("After_Debit_Amount", ""),
|
||||
inv.get("GST_Amount", ""),
|
||||
inv.get("Amount", ""),
|
||||
inv.get("TDS_Amount", ""),
|
||||
inv.get("SD_Amount", ""),
|
||||
inv.get("On_Commission", ""),
|
||||
inv.get("Hydro_Testing", ""),
|
||||
inv.get("GST_SD_Amount", "")
|
||||
]
|
||||
|
||||
# HOLD DATA
|
||||
invoice_holds = hold_data.get(inv.get("Invoice_Id"), {})
|
||||
for ht_id in hold_type_map.keys():
|
||||
row.append(invoice_holds.get(ht_id, ""))
|
||||
|
||||
# PAYMENT DATA
|
||||
row += [
|
||||
inv.get("Final_Amount", ""),
|
||||
inv.get("Payment_Amount", ""),
|
||||
inv.get("TDS_Payment_Amount", ""),
|
||||
inv.get("Total_Amount", ""),
|
||||
inv.get("UTR", "")
|
||||
]
|
||||
|
||||
row += ["", ""]
|
||||
|
||||
sheet.append(row)
|
||||
# ================= CREDIT NOTE ROWS =================
|
||||
for pmc, cn_list in credit_note_map.items():
|
||||
for cn in cn_list:
|
||||
cn_row = [
|
||||
pmc_no,
|
||||
"", "", "Credit Note",
|
||||
"", cn.get("Invoice_No", ""),
|
||||
cn.get("Basic_Amount", ""),
|
||||
"", "", "", "", "", "", "", "", "", "", ""
|
||||
]
|
||||
cn_row += [""] * len(hold_headers)
|
||||
cn_row += [
|
||||
cn.get("Final_Amount", ""),
|
||||
cn.get("Total_Amount", ""),
|
||||
cn.get("UTR", "")
|
||||
]
|
||||
sheet.append(cn_row)
|
||||
|
||||
# ================= GST RELEASE ROWS =================
|
||||
for gst in gst_releases:
|
||||
gst_row = [
|
||||
gst.get("PMC_No", ""),
|
||||
"", "", "GST Release Note",
|
||||
"", gst.get("Invoice_No", ""),
|
||||
gst.get("Basic_Amount", ""),
|
||||
"", "", "", "", "", "", "", "", ""
|
||||
]
|
||||
gst_row += [""] * len(hold_headers)
|
||||
gst_row += [
|
||||
gst.get("Final_Amount", ""),
|
||||
"",
|
||||
"",
|
||||
gst.get("Total_Amount", ""),
|
||||
gst.get("UTR", "")
|
||||
]
|
||||
sheet.append(gst_row)
|
||||
|
||||
# ================= AUTO WIDTH =================
|
||||
for col in sheet.columns:
|
||||
max_len = max((len(str(cell.value)) for cell in col if cell.value), default=0)
|
||||
sheet.column_dimensions[col[0].column_letter].width = max_len + 2
|
||||
|
||||
workbook.save(output_file)
|
||||
workbook.close()
|
||||
return output_folder, filename
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error generating PMC report: {e}")
|
||||
return None
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
156
model/Report.py
156
model/Report.py
@@ -1,11 +1,11 @@
|
||||
import config
|
||||
from datetime import datetime
|
||||
from flask import send_file
|
||||
import os
|
||||
import openpyxl
|
||||
from openpyxl.styles import Font, PatternFill
|
||||
|
||||
from model.FolderAndFile import FolderAndFile
|
||||
from services.Generalservice import GeneralUse
|
||||
|
||||
class ReportHelper:
|
||||
isSuccess = False
|
||||
@@ -17,30 +17,6 @@ class ReportHelper:
|
||||
self.resultMessage = ""
|
||||
self.data = []
|
||||
|
||||
@staticmethod
|
||||
def execute_sp(cursor, proc_name, params=[], fetch_one=False):
|
||||
cursor.callproc(proc_name, params)
|
||||
return (
|
||||
ReportHelper.fetch_one_result(cursor)
|
||||
if fetch_one else
|
||||
ReportHelper.fetch_all_results(cursor)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def fetch_all_results(cursor):
|
||||
data = []
|
||||
for result in cursor.stored_results():
|
||||
data = result.fetchall()
|
||||
return data
|
||||
|
||||
|
||||
@staticmethod
|
||||
def fetch_one_result(cursor):
|
||||
data = None
|
||||
for result in cursor.stored_results():
|
||||
data = result.fetchone()
|
||||
return data
|
||||
|
||||
|
||||
@staticmethod
|
||||
def search_contractor(request):
|
||||
@@ -60,10 +36,7 @@ class ReportHelper:
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
||||
try:
|
||||
data = ReportHelper.execute_sp(
|
||||
cursor,
|
||||
"search_contractor_info",
|
||||
[
|
||||
data = GeneralUse.execute_sp(cursor,"search_contractor_info",[
|
||||
subcontractor_name or None,
|
||||
pmc_no or None,
|
||||
state or None,
|
||||
@@ -72,8 +45,7 @@ class ReportHelper:
|
||||
village or None,
|
||||
year_from or None,
|
||||
year_to or None
|
||||
]
|
||||
)
|
||||
])
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error in search_contractor: {e}")
|
||||
@@ -86,69 +58,6 @@ class ReportHelper:
|
||||
return data
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_contractor_report(contractor_id):
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor(dictionary=True, buffered=True)
|
||||
|
||||
try:
|
||||
# Contractor Info (only one fetch)
|
||||
contInfo = ReportHelper.execute_sp(cursor, 'GetContractorInfo', [contractor_id], True)
|
||||
# Hold Types
|
||||
hold_types = ReportHelper.execute_sp(cursor, 'GetContractorHoldTypes', [contractor_id])
|
||||
# Invoices
|
||||
invoices = ReportHelper.execute_sp(cursor, 'GetContractorInvoices', [contractor_id])
|
||||
# GST Release
|
||||
gst_rel = ReportHelper.execute_sp(cursor, 'GetGSTRelease', [contractor_id])
|
||||
# Hold Release
|
||||
hold_release = ReportHelper.execute_sp(cursor, 'GetHoldRelease', [contractor_id])
|
||||
# Credit Note
|
||||
credit_note = ReportHelper.execute_sp(cursor, 'GetCreditNote', [contractor_id])
|
||||
# Payments
|
||||
payments = ReportHelper.execute_sp(cursor, 'GetPayments', [contractor_id])
|
||||
|
||||
# Totals
|
||||
total = {
|
||||
"sum_invo_basic_amt": float(sum(row['Basic_Amount'] or 0 for row in invoices)),
|
||||
"sum_invo_debit_amt": float(sum(row['Debit_Amount'] or 0 for row in invoices)),
|
||||
"sum_invo_after_debit_amt": float(sum(row['After_Debit_Amount'] or 0 for row in invoices)),
|
||||
"sum_invo_amt": float(sum(row['Amount'] or 0 for row in invoices)),
|
||||
"sum_invo_gst_amt": float(sum(row['GST_Amount'] or 0 for row in invoices)),
|
||||
"sum_invo_tds_amt": float(sum(row['TDS_Amount'] or 0 for row in invoices)),
|
||||
"sum_invo_ds_amt": float(sum(row['SD_Amount'] or 0 for row in invoices)),
|
||||
"sum_invo_on_commission": float(sum(row['On_Commission'] or 0 for row in invoices)),
|
||||
"sum_invo_hydro_test": float(sum(row['Hydro_Testing'] or 0 for row in invoices)),
|
||||
"sum_invo_gst_sd_amt": float(sum(row['GST_SD_Amount'] or 0 for row in invoices)),
|
||||
"sum_invo_final_amt": float(sum(row['Final_Amount'] or 0 for row in invoices)),
|
||||
"sum_invo_hold_amt": float(sum(row['hold_amount'] or 0 for row in invoices)),
|
||||
|
||||
"sum_gst_basic_amt": float(sum(row['basic_amount'] or 0 for row in gst_rel)),
|
||||
"sum_gst_final_amt": float(sum(row['final_amount'] or 0 for row in gst_rel)),
|
||||
|
||||
"sum_pay_payment_amt": float(sum(row['Payment_Amount'] or 0 for row in payments)),
|
||||
"sum_pay_tds_payment_amt": float(sum(row['TDS_Payment_Amount'] or 0 for row in payments)),
|
||||
"sum_pay_total_amt": float(sum(row['Total_amount'] or 0 for row in payments))
|
||||
}
|
||||
|
||||
current_date = datetime.now().strftime('%Y-%m-%d')
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
return {
|
||||
"contInfo": contInfo,
|
||||
"invoices": invoices,
|
||||
"hold_types": hold_types,
|
||||
"gst_rel": gst_rel,
|
||||
"payments": payments,
|
||||
"credit_note": credit_note,
|
||||
"hold_release": hold_release,
|
||||
"total": total,
|
||||
"current_date": current_date
|
||||
}
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_contractor_info(contractor_id):
|
||||
from model.ContractorInfo import ContractorInfo
|
||||
@@ -156,6 +65,7 @@ class ReportHelper:
|
||||
return contractor.contInfo if contractor.contInfo else None
|
||||
|
||||
|
||||
# call this method for excel formate written
|
||||
@staticmethod
|
||||
def generate_excel(contractor_id, contInfo, invoices, hold_types, hold_data,
|
||||
credit_note_map, gst_release_map, output_file):
|
||||
@@ -197,7 +107,6 @@ class ReportHelper:
|
||||
if inv["invoice_no"] not in (None, "", 0)
|
||||
else ""
|
||||
)
|
||||
|
||||
key = (pmc_no)
|
||||
|
||||
# Yellow separator
|
||||
@@ -284,7 +193,13 @@ class ReportHelper:
|
||||
|
||||
cn_row += [""] * len(hold_headers)
|
||||
|
||||
cn_row += [cn.get("Final_Amount", ""),"","",cn.get("Total_Amount", ""),cn.get("UTR", "")]
|
||||
cn_row += [
|
||||
cn.get("Final_Amount", ""),
|
||||
"",
|
||||
"",
|
||||
cn.get("Total_Amount", ""),
|
||||
cn.get("UTR", "")
|
||||
]
|
||||
|
||||
sheet.append(cn_row)
|
||||
|
||||
@@ -294,53 +209,4 @@ class ReportHelper:
|
||||
workbook.save(output_file)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def create_contractor_report(contractor_id):
|
||||
fileName = f"Contractor_Report_{contractor_id}.xlsx"
|
||||
output_file = FolderAndFile.get_download_path(filename=fileName)
|
||||
|
||||
# Fetch Data
|
||||
contInfo = ReportHelper.get_contractor_info(contractor_id)
|
||||
if not contInfo:
|
||||
return None, "No contractor found"
|
||||
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor(dictionary=True, buffered=True)
|
||||
|
||||
hold_types = ReportHelper.execute_sp(cursor, 'HoldTypesByContractorId', [contractor_id])
|
||||
invoices = ReportHelper.execute_sp(cursor, 'FetchInvoicesByContractor', [contractor_id])
|
||||
hold_amounts = ReportHelper.execute_sp(cursor, 'HoldAmountsByContractorId', [contractor_id])
|
||||
hold_data = {}
|
||||
for h in hold_amounts:
|
||||
hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
||||
|
||||
|
||||
# -------- Credit Note MAP --------
|
||||
credit_note_raw = ReportHelper.execute_sp(cursor, 'GetCreditNotesByContractor', [contractor_id])
|
||||
credit_note_map = {}
|
||||
for cn in credit_note_raw:
|
||||
key = (
|
||||
str(cn['PMC_No']).strip()
|
||||
)
|
||||
credit_note_map.setdefault(key, []).append(cn)
|
||||
|
||||
# -------- GST MAP --------
|
||||
gst_release_raw = ReportHelper.execute_sp(cursor, 'GstReleasesByContractorId', [contractor_id])
|
||||
gst_release_map = {}
|
||||
for gr in gst_release_raw:
|
||||
key = (
|
||||
str(gr['PMC_No']).strip()
|
||||
)
|
||||
gst_release_map.setdefault(key, []).append(gr)
|
||||
|
||||
# Generate Excel
|
||||
ReportHelper.generate_excel(
|
||||
contractor_id, contInfo, invoices, hold_types, hold_data,
|
||||
credit_note_map, gst_release_map, output_file
|
||||
)
|
||||
|
||||
return output_file, None
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
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
|
||||
|
||||
177
services/ReportService.py
Normal file
177
services/ReportService.py
Normal file
@@ -0,0 +1,177 @@
|
||||
import config
|
||||
|
||||
from model.FolderAndFile import FolderAndFile
|
||||
from services.Generalservice import GeneralUse
|
||||
from model.Report import ReportHelper
|
||||
|
||||
from decimal import Decimal
|
||||
def safe_decimal(value):
|
||||
if value is None:
|
||||
return Decimal(0)
|
||||
return Decimal(value)
|
||||
|
||||
|
||||
class ReportService:
|
||||
|
||||
|
||||
def __init__(self, contractor_id=None, pmc_no=None):
|
||||
self.contractor_id = contractor_id
|
||||
self.pmc_no = pmc_no
|
||||
|
||||
self.contInfo = None
|
||||
self.hold_types = []
|
||||
self.invoices = []
|
||||
|
||||
self.hold_amounts = []
|
||||
self.hold_data = {}
|
||||
|
||||
self.credit_note_raw = []
|
||||
self.credit_note_map = {}
|
||||
|
||||
self.gst_release_raw = []
|
||||
self.gst_release_map = {}
|
||||
|
||||
self.output_file = None
|
||||
|
||||
# ---------------- LOAD DATA ----------------
|
||||
def load_data(self):
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor(dictionary=True, buffered=True)
|
||||
|
||||
try:
|
||||
# ---------- CONTRACTOR ----------
|
||||
if self.contractor_id:
|
||||
self.contInfo = GeneralUse.execute_sp(cursor, 'GetContractorInfo', [self.contractor_id], True)
|
||||
self.hold_types = GeneralUse.execute_sp(cursor, 'HoldTypesByContractorId', [self.contractor_id])
|
||||
self.invoices = GeneralUse.execute_sp(cursor, 'GetInvoicesByContractorOrPMCNo', [self.contractor_id, None])
|
||||
|
||||
# ---------- PMC ----------
|
||||
elif self.pmc_no:
|
||||
self.contInfo = GeneralUse.execute_sp(cursor, 'GetContractorInfoByPmcNo', [self.pmc_no], True)
|
||||
self.contractor_id = self.contInfo["Contractor_Id"]
|
||||
|
||||
self.hold_types = GeneralUse.execute_sp(cursor, 'GetHoldTypesByContractor', [self.contractor_id])
|
||||
self.invoices = GeneralUse.execute_sp(cursor, 'GetInvoicesByContractorOrPMCNo', [None, self.pmc_no])
|
||||
|
||||
# ---------- COMMON ----------
|
||||
self.hold_amounts = GeneralUse.execute_sp(cursor, 'GetHoldAmountsByContractor', [self.contractor_id])
|
||||
self.credit_note_raw = GeneralUse.execute_sp(cursor, 'GetCreditNotesByContractor', [self.contractor_id])
|
||||
self.gst_release_raw = GeneralUse.execute_sp(cursor, 'GetGSTRelease', [self.contractor_id])
|
||||
|
||||
|
||||
self.prepare_maps()
|
||||
self.total = self.calculate_totals()
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
return self
|
||||
|
||||
# ---------------- MAPS ----------------
|
||||
def prepare_maps(self):
|
||||
# HOLD MAP
|
||||
for h in self.hold_amounts:
|
||||
self.hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
||||
|
||||
# CREDIT MAP
|
||||
for cn in self.credit_note_raw:
|
||||
key = str(cn.get('PMC_No') or cn.get('pmc_no')).strip()
|
||||
self.credit_note_map.setdefault(key, []).append(cn)
|
||||
|
||||
# GST MAP (FIXED)
|
||||
for gr in self.gst_release_raw:
|
||||
pmc_value = gr.get('PMC_No') or gr.get('pmc_no') or gr.get('PMC_NO')
|
||||
|
||||
if not pmc_value:
|
||||
continue # skip if missing
|
||||
|
||||
key = str(pmc_value).strip()
|
||||
self.gst_release_map.setdefault(key, []).append(gr)
|
||||
|
||||
# ---------------- calculate total ----------------
|
||||
def calculate_totals(self):
|
||||
total = {
|
||||
"sum_invo_basic_amt": Decimal(0),
|
||||
"sum_invo_debit_amt": Decimal(0),
|
||||
"sum_invo_after_debit_amt": Decimal(0),
|
||||
"sum_invo_gst_amt": Decimal(0),
|
||||
"sum_invo_amt": Decimal(0),
|
||||
"sum_invo_tds_amt": Decimal(0),
|
||||
"sum_invo_ds_amt": Decimal(0),
|
||||
"sum_invo_on_commission": Decimal(0),
|
||||
"sum_invo_hydro_test": Decimal(0),
|
||||
"sum_invo_hold_amt": Decimal(0),
|
||||
"sum_invo_gst_sd_amt": Decimal(0),
|
||||
"sum_invo_final_amt": Decimal(0),
|
||||
|
||||
"sum_gst_basic_amt": Decimal(0),
|
||||
"sum_gst_final_amt": Decimal(0),
|
||||
|
||||
"sum_pay_payment_amt": Decimal(0),
|
||||
"sum_pay_tds_payment_amt": Decimal(0),
|
||||
"sum_pay_total_amt": Decimal(0)
|
||||
}
|
||||
|
||||
# ---------- INVOICE ----------
|
||||
for inv in self.invoices:
|
||||
total["sum_invo_basic_amt"] += safe_decimal(inv.get("Basic_Amount"))
|
||||
total["sum_invo_debit_amt"] += safe_decimal(inv.get("Debit_Amount"))
|
||||
total["sum_invo_after_debit_amt"] += safe_decimal(inv.get("After_Debit_Amount"))
|
||||
total["sum_invo_gst_amt"] += safe_decimal(inv.get("GST_Amount"))
|
||||
total["sum_invo_amt"] += safe_decimal(inv.get("Amount"))
|
||||
total["sum_invo_tds_amt"] += safe_decimal(inv.get("TDS_Amount"))
|
||||
total["sum_invo_ds_amt"] += safe_decimal(inv.get("SD_Amount"))
|
||||
total["sum_invo_on_commission"] += safe_decimal(inv.get("On_Commission"))
|
||||
total["sum_invo_hydro_test"] += safe_decimal(inv.get("Hydro_Testing"))
|
||||
total["sum_invo_gst_sd_amt"] += safe_decimal(inv.get("GST_SD_Amount"))
|
||||
total["sum_invo_final_amt"] += safe_decimal(inv.get("Final_Amount"))
|
||||
total["sum_invo_hold_amt"] += safe_decimal(inv.get("hold_amount"))
|
||||
|
||||
# ---------- GST ----------
|
||||
for gst in self.gst_release_raw:
|
||||
total["sum_gst_basic_amt"] += safe_decimal(gst.get("basic_amount"))
|
||||
total["sum_gst_final_amt"] += safe_decimal(gst.get("final_amount"))
|
||||
|
||||
# ---------- PAYMENTS ----------
|
||||
if hasattr(self, "payments"):
|
||||
for pay in self.payments:
|
||||
total["sum_pay_payment_amt"] += safe_decimal(pay.get("Payment_Amount"))
|
||||
total["sum_pay_tds_payment_amt"] += safe_decimal(pay.get("TDS_Payment_Amount"))
|
||||
total["sum_pay_total_amt"] += safe_decimal(pay.get("Total_amount"))
|
||||
|
||||
return total
|
||||
|
||||
|
||||
# ---------------- WEB DATA ----------------
|
||||
def get_web_data(self):
|
||||
return {
|
||||
"contInfo": self.contInfo,
|
||||
"invoices": self.invoices,
|
||||
"hold_types": self.hold_types,
|
||||
"credit_note": self.credit_note_raw,
|
||||
"gst_rel": self.gst_release_raw,
|
||||
"total": self.total
|
||||
}
|
||||
|
||||
# ---------------- DOWNLOAD ----------------
|
||||
def download_excel(self):
|
||||
|
||||
if not self.contInfo:
|
||||
return None, "No data found"
|
||||
|
||||
filename = f"Report_{self.contractor_id or self.pmc_no}.xlsx"
|
||||
self.output_file = FolderAndFile.get_download_path(filename=filename)
|
||||
|
||||
ReportHelper.generate_excel(
|
||||
self.contractor_id or 0,
|
||||
self.contInfo,
|
||||
self.invoices,
|
||||
self.hold_types,
|
||||
self.hold_data,
|
||||
self.credit_note_map,
|
||||
self.gst_release_map,
|
||||
self.output_file
|
||||
)
|
||||
|
||||
return self.output_file, None
|
||||
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>
|
||||
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>
|
||||
</tr>
|
||||
`);
|
||||
`;
|
||||
|
||||
tableBody.appendChild(tr);
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
alert(xhr.responseJSON.error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$('#search-form input').on('keyup change', function () {
|
||||
fetchResults();
|
||||
});
|
||||
// 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}`;
|
||||
}
|
||||
|
||||
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,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,6 +8,7 @@
|
||||
<!-- <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">
|
||||
@@ -19,64 +19,64 @@
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="subcontractor">Subcontractor Name:</label>
|
||||
<input type="text" id="subcontractor" name="subcontractor" value="{{ info.Contractor_Name }}"
|
||||
<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>{{ info.Address }}</textarea>
|
||||
<textarea id="Address" name="Address" readonly>{{ contInfo.Address }}</textarea>
|
||||
</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/>
|
||||
<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="{{ info.Mobile_No }}" readonly/>
|
||||
<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="{{ info.Email }}" readonly/>
|
||||
<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="{{ info.GST_Registration_Type }}" readonly/>
|
||||
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="{{ info.GST_No }}" readonly/>
|
||||
<input type="text" id="GST_No" name="GST_No" value="{{ contInfo.GST_No }}" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<h2>PMC Report for PMC No: {{ info.PMC_No}}</h2>
|
||||
<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="{{ info.State_Name }}" readonly/>
|
||||
<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="{{ info.District_Name }}" readonly/>
|
||||
<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="{{ info.Block_Name }}" readonly/>
|
||||
<input type="text" id="Block" name="Block" value="{{ contInfo.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/>
|
||||
<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="{{ info.Village_Name.capitalize() }}" readonly/>
|
||||
value="{{ contInfo.Village_Name.capitalize() }}" readonly />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -216,6 +216,8 @@
|
||||
<th>Invoice No</th>
|
||||
<th>Basic Amount</th>
|
||||
<th>Final Amount</th>
|
||||
<th>Total_Amount</th>
|
||||
<th>UTR</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -223,9 +225,11 @@
|
||||
{% 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.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>
|
||||
@@ -305,15 +309,15 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if payments %}
|
||||
{% for pay in payments %}
|
||||
{% if invoices %}
|
||||
{% for pay in invoices %}
|
||||
<tr>
|
||||
<td>{{ pay.pmc_no }}</td>
|
||||
<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>
|
||||
<td>{{ pay.Total_Amount }}</td>
|
||||
<td>{{ pay.UTR}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
@@ -333,7 +337,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="/download_pmc_report/{{ info.PMC_No}}">
|
||||
<a href="/download_pmc_report/{{ contInfo.PMC_No}}">
|
||||
<button class="download-btn">Download PMC Report</button>
|
||||
</a>
|
||||
</body>
|
||||
|
||||
@@ -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,6 +8,7 @@
|
||||
<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">
|
||||
@@ -53,6 +55,7 @@
|
||||
<input type="date" id="year_to" name="year_to">
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" onclick="fetchData()">Search</button>
|
||||
</form>
|
||||
|
||||
<h2>Contractor List</h2>
|
||||
|
||||
@@ -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,6 +8,7 @@
|
||||
<!-- <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>
|
||||
@@ -69,32 +68,6 @@
|
||||
</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>
|
||||
{% for hold in hold_types %}
|
||||
<th>{{ hold.hold_type }}</th>
|
||||
<td>{{total["sum_invo_hold_amt"]}}</td>
|
||||
{% 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>-->
|
||||
@@ -141,7 +114,7 @@
|
||||
{% for invoice in invoices %}
|
||||
<tr>
|
||||
<td>{{ invoice.PMC_No }}</td>
|
||||
<td>{{ invoice.Village_Name.capitalize() }}</td>
|
||||
<td>{{ invoice.Village_Name}}</td>
|
||||
<td>{{ invoice.Work_Type }}</td>
|
||||
<td>{{ invoice.Invoice_Details }}</td>
|
||||
<td>{{ invoice.Invoice_Date }}</td>
|
||||
@@ -293,6 +266,8 @@
|
||||
<th>Invoice No</th>
|
||||
<th>Basic Amount</th>
|
||||
<th>Final Amount</th>
|
||||
<th>Total Amount</th>
|
||||
<th>UTR</th>
|
||||
</tr>
|
||||
|
||||
|
||||
@@ -302,9 +277,11 @@
|
||||
{% 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.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>
|
||||
@@ -336,15 +313,15 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if payments %}
|
||||
{% for pay in payments %}
|
||||
{% if invoices %}
|
||||
{% for pay in invoices %}
|
||||
<tr>
|
||||
<td>{{ pay.pmc_no }}</td>
|
||||
<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>
|
||||
<td>{{ pay.Total_Amount }}</td>
|
||||
<td>{{ pay.UTR}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
@@ -366,7 +343,8 @@
|
||||
</table>
|
||||
|
||||
|
||||
<a href="{{ url_for('report.download_report', contractor_id=contractor_id) }}" class="download-btn">Download Report</a>
|
||||
<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