Compare commits
12 Commits
d69f286364
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| b93509bd8a | |||
| e99d43139b | |||
| a202da621c | |||
| 5ae1fbe320 | |||
| 0ca1749757 | |||
| 7981ad0206 | |||
| 0ec878d2ec | |||
| 076f9ef2f1 | |||
| ecd944d637 | |||
| cd16c284ce | |||
| 4e5887b160 | |||
| 9163355924 |
@@ -7,12 +7,11 @@ from model.Block import Block
|
|||||||
from model.Utilities import HtmlHelper
|
from model.Utilities import HtmlHelper
|
||||||
|
|
||||||
block_bp = Blueprint('block', __name__)
|
block_bp = Blueprint('block', __name__)
|
||||||
|
block = Block()
|
||||||
# --- Add Block page -------
|
# --- Add Block page -------
|
||||||
@block_bp.route('/add_block', methods=['GET', 'POST'])
|
@block_bp.route('/add_block', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def add_block():
|
def add_block():
|
||||||
block = Block()
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
block.AddBlock(request)
|
block.AddBlock(request)
|
||||||
@@ -30,7 +29,7 @@ def add_block():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# ✅ NEW ROUTE (FIX FOR DISTRICT FETCH)
|
# get district
|
||||||
@block_bp.route('/get_districts/<int:state_id>')
|
@block_bp.route('/get_districts/<int:state_id>')
|
||||||
@login_required
|
@login_required
|
||||||
def get_districts(state_id):
|
def get_districts(state_id):
|
||||||
@@ -62,7 +61,6 @@ def get_districts(state_id):
|
|||||||
@login_required
|
@login_required
|
||||||
def check_block():
|
def check_block():
|
||||||
|
|
||||||
block = Block()
|
|
||||||
return block.CheckBlock(request)
|
return block.CheckBlock(request)
|
||||||
|
|
||||||
|
|
||||||
@@ -70,8 +68,6 @@ def check_block():
|
|||||||
@login_required
|
@login_required
|
||||||
def edit_block(block_id):
|
def edit_block(block_id):
|
||||||
|
|
||||||
block = Block()
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
block.EditBlock(request, block_id)
|
block.EditBlock(request, block_id)
|
||||||
block.resultMessage
|
block.resultMessage
|
||||||
@@ -90,7 +86,7 @@ def edit_block(block_id):
|
|||||||
for rs in cursor.stored_results():
|
for rs in cursor.stored_results():
|
||||||
states = rs.fetchall()
|
states = rs.fetchall()
|
||||||
|
|
||||||
cursor.callproc("GetAllDistrictsData")
|
cursor.callproc("GetAllDistricts")
|
||||||
for rs in cursor.stored_results():
|
for rs in cursor.stored_results():
|
||||||
districts = rs.fetchall()
|
districts = rs.fetchall()
|
||||||
|
|
||||||
@@ -111,7 +107,6 @@ def edit_block(block_id):
|
|||||||
@login_required
|
@login_required
|
||||||
def delete_block(block_id):
|
def delete_block(block_id):
|
||||||
|
|
||||||
block = Block()
|
|
||||||
block.DeleteBlock(request, block_id)
|
block.DeleteBlock(request, block_id)
|
||||||
|
|
||||||
return redirect(url_for('block.add_block'))
|
return redirect(url_for('block.add_block'))
|
||||||
@@ -5,12 +5,13 @@ from model.District import District
|
|||||||
from model.State import State
|
from model.State import State
|
||||||
|
|
||||||
district_bp = Blueprint('district', __name__)
|
district_bp = Blueprint('district', __name__)
|
||||||
|
district = District()
|
||||||
|
|
||||||
# ------- District page --------
|
# ------- District page --------
|
||||||
@district_bp.route('/add_district', methods=['GET', 'POST'])
|
@district_bp.route('/add_district', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def add_district():
|
def add_district():
|
||||||
district = District()
|
# district = District()
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
district.AddDistrict(request=request)
|
district.AddDistrict(request=request)
|
||||||
@@ -32,7 +33,7 @@ def add_district():
|
|||||||
@login_required
|
@login_required
|
||||||
def check_district():
|
def check_district():
|
||||||
|
|
||||||
district = District()
|
# district = District()
|
||||||
|
|
||||||
return district.CheckDistrict(request=request)
|
return district.CheckDistrict(request=request)
|
||||||
|
|
||||||
@@ -41,7 +42,7 @@ def check_district():
|
|||||||
@login_required
|
@login_required
|
||||||
def delete_district(district_id):
|
def delete_district(district_id):
|
||||||
|
|
||||||
district = District()
|
# district = District()
|
||||||
|
|
||||||
district.DeleteDistrict(request=request, district_id=district_id)
|
district.DeleteDistrict(request=request, district_id=district_id)
|
||||||
|
|
||||||
@@ -56,7 +57,7 @@ def delete_district(district_id):
|
|||||||
@login_required
|
@login_required
|
||||||
def edit_district(district_id):
|
def edit_district(district_id):
|
||||||
|
|
||||||
district = District()
|
# district = District()
|
||||||
state = State()
|
state = State()
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ def show_table(filename):
|
|||||||
errors.append(f"State '{file_info['State']}' is not valid. Please add it.")
|
errors.append(f"State '{file_info['State']}' is not valid. Please add it.")
|
||||||
|
|
||||||
if state_data:
|
if state_data:
|
||||||
cursor.callproc('GetDistrictByNameAndState', [file_info['District'], state_data['State_ID']]) # Change GetDistrictByNameAndStates to GetDistrictByNameAndState
|
cursor.callproc('GetDistrictByNameAndState', [file_info['District'], state_data['State_Id']]) # Change GetDistrictByNameAndStates to GetDistrictByNameAndState
|
||||||
for result in cursor.stored_results():
|
for result in cursor.stored_results():
|
||||||
district_data = result.fetchone()
|
district_data = result.fetchone()
|
||||||
if not district_data:
|
if not district_data:
|
||||||
@@ -84,7 +84,7 @@ def show_table(filename):
|
|||||||
subcontractor_data = result.fetchone()
|
subcontractor_data = result.fetchone()
|
||||||
|
|
||||||
if not subcontractor_data:
|
if not subcontractor_data:
|
||||||
cursor.callproc('InsertSubcontractor', [file_info['Subcontractor']])
|
cursor.callproc('SaveContractor', [file_info.get('Subcontractor'),None,None,None,None,None,None,None,None])
|
||||||
connection.commit()
|
connection.commit()
|
||||||
cursor.callproc('GetSubcontractorByName', [file_info['Subcontractor']])
|
cursor.callproc('GetSubcontractorByName', [file_info['Subcontractor']])
|
||||||
for result in cursor.stored_results():
|
for result in cursor.stored_results():
|
||||||
@@ -186,7 +186,7 @@ def save_data():
|
|||||||
"SD_Amount": entry.get("SD_Amount", 0.00),
|
"SD_Amount": entry.get("SD_Amount", 0.00),
|
||||||
"On_Commission": entry.get("On_Commission", 0.00),
|
"On_Commission": entry.get("On_Commission", 0.00),
|
||||||
"Hydro_Testing": entry.get("Hydro_Testing", 0.00),
|
"Hydro_Testing": entry.get("Hydro_Testing", 0.00),
|
||||||
"Hold_Amount": 0,
|
"Hold_Amount": entry.get("Hold_Amount", 0.00), # change
|
||||||
"GST_SD_Amount": entry.get("GST_SD_Amount", 0.00),
|
"GST_SD_Amount": entry.get("GST_SD_Amount", 0.00),
|
||||||
"Final_Amount": entry.get("Final_Amount", 0.00),
|
"Final_Amount": entry.get("Final_Amount", 0.00),
|
||||||
"Payment_Amount": entry.get("Payment_Amount", 0.00),
|
"Payment_Amount": entry.get("Payment_Amount", 0.00),
|
||||||
@@ -242,12 +242,7 @@ def save_data():
|
|||||||
for result in cursor.stored_results():
|
for result in cursor.stored_results():
|
||||||
result = result.fetchone()
|
result = result.fetchone()
|
||||||
village_id = result[0] if result else None
|
village_id = result[0] if result else None
|
||||||
# print("village_id :", village_id)
|
|
||||||
# print("block_id :", block_id)
|
|
||||||
# print("invoice :", PMC_No, village_id, work_type, Invoice_Details, Invoice_Date, Invoice_No,
|
|
||||||
# Basic_Amount, Debit_Amount, After_Debit_Amount, Amount, GST_Amount, TDS_Amount,
|
|
||||||
# SD_Amount, On_Commission, Hydro_Testing, GST_SD_Amount, Final_Amount)
|
|
||||||
|
|
||||||
args = (
|
args = (
|
||||||
PMC_No, village_id, work_type, Invoice_Details, Invoice_Date, Invoice_No,
|
PMC_No, village_id, work_type, Invoice_Details, Invoice_Date, Invoice_No,
|
||||||
Basic_Amount, Debit_Amount, After_Debit_Amount, Amount, GST_Amount, TDS_Amount,
|
Basic_Amount, Debit_Amount, After_Debit_Amount, Amount, GST_Amount, TDS_Amount,
|
||||||
@@ -255,27 +250,25 @@ def save_data():
|
|||||||
subcontractor_id, 0
|
subcontractor_id, 0
|
||||||
)
|
)
|
||||||
|
|
||||||
# print("All invoice Details ",args)
|
|
||||||
# add subcontarctor id in invoice table
|
# add subcontarctor id in invoice table
|
||||||
results = cursor.callproc('SaveInvoice', args)
|
results = cursor.callproc('SaveInvoice', args)
|
||||||
invoice_id = results[-1]
|
invoice_id = results[-1]
|
||||||
print("**************************************************************")
|
|
||||||
print(invoice_id)
|
|
||||||
print("**************************************************************")
|
|
||||||
cursor.callproc(
|
cursor.callproc(
|
||||||
"SavePayment",
|
"SavePayment",
|
||||||
(
|
(
|
||||||
PMC_No,
|
PMC_No,
|
||||||
Invoice_No, # required
|
Invoice_No,
|
||||||
Payment_Amount,
|
Payment_Amount,
|
||||||
TDS_Payment_Amount,
|
TDS_Payment_Amount,
|
||||||
Total_Amount,
|
Total_Amount,
|
||||||
UTR,
|
UTR,
|
||||||
invoice_id # last
|
invoice_id
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# print("invoice id from the excel ", invoice_id)
|
|
||||||
if isinstance(hold_columns, str):
|
if isinstance(hold_columns, str):
|
||||||
hold_columns = ast.literal_eval(hold_columns)
|
hold_columns = ast.literal_eval(hold_columns)
|
||||||
if isinstance(hold_columns, list) and all(isinstance(hold, dict) for hold in hold_columns):
|
if isinstance(hold_columns, list) and all(isinstance(hold, dict) for hold in hold_columns):
|
||||||
@@ -287,7 +280,7 @@ def save_data():
|
|||||||
hold_amount = entry.get(
|
hold_amount = entry.get(
|
||||||
hold_column_name) # Get the value for that specific hold column
|
hold_column_name) # Get the value for that specific hold column
|
||||||
if hold_amount is not None:
|
if hold_amount is not None:
|
||||||
# print(f"Processing hold type: {hold_column_name}, Hold Amount: {hold_amount}")
|
|
||||||
hold_join_data = {
|
hold_join_data = {
|
||||||
"Contractor_Id": subcontractor_id,
|
"Contractor_Id": subcontractor_id,
|
||||||
"Invoice_Id": invoice_id,
|
"Invoice_Id": invoice_id,
|
||||||
@@ -304,10 +297,8 @@ def save_data():
|
|||||||
print(f"Invalid hold entry: {hold}")
|
print(f"Invalid hold entry: {hold}")
|
||||||
else:
|
else:
|
||||||
print("Hold columns data is not a valid list of dictionaries.")
|
print("Hold columns data is not a valid list of dictionaries.")
|
||||||
#---------------------------------------------Credit Note---------------------------------------------------------------------------
|
#-----------------------------------Credit Note----------------------------------------------------------------
|
||||||
elif any(keyword in Invoice_Details.lower() for keyword in ['credit note','logging report']):
|
elif any(keyword in Invoice_Details.lower() for keyword in ['credit', 'logging report']):
|
||||||
# print("Credit note found:", PMC_No, Invoice_No, Basic_Amount, Debit_Amount, Final_Amount,
|
|
||||||
# After_Debit_Amount, GST_Amount, Amount, Final_Amount, Payment_Amount, Total_Amount, UTR, Invoice_No)
|
|
||||||
cursor.callproc(
|
cursor.callproc(
|
||||||
'AddCreditNoteFromExcel',
|
'AddCreditNoteFromExcel',
|
||||||
[
|
[
|
||||||
@@ -316,7 +307,7 @@ def save_data():
|
|||||||
subcontractor_id, Invoice_No
|
subcontractor_id, Invoice_No
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
#-----------------------------------------------Hold Amount----------------------------------------------------------------------
|
#---------------------------------------Hold Amount-----------------------------------------------------------
|
||||||
# Step 1: Normalize Invoice_Details: lowercase, trim, remove extra spaces
|
# Step 1: Normalize Invoice_Details: lowercase, trim, remove extra spaces
|
||||||
normalized_details = re.sub(r'\s+', ' ', Invoice_Details.strip()).lower()
|
normalized_details = re.sub(r'\s+', ' ', Invoice_Details.strip()).lower()
|
||||||
# Step 2: Define lowercase keywords
|
# Step 2: Define lowercase keywords
|
||||||
@@ -332,65 +323,33 @@ def save_data():
|
|||||||
]
|
]
|
||||||
# Step 3: Matching condition
|
# Step 3: Matching condition
|
||||||
if any(kw in normalized_details for kw in keywords):
|
if any(kw in normalized_details for kw in keywords):
|
||||||
# print("✅ Match found. Inserting hold release for:", Invoice_Details)
|
|
||||||
cursor.callproc(
|
cursor.callproc(
|
||||||
'AddHoldReleaseFromExcel',
|
'AddHoldReleaseFromExcel',
|
||||||
[PMC_No, Invoice_No, Invoice_Details, Basic_Amount, Final_Amount, UTR, subcontractor_id]
|
[PMC_No, Invoice_No, Invoice_Details, Basic_Amount, Final_Amount, UTR, subcontractor_id])
|
||||||
)
|
|
||||||
connection.commit()
|
connection.commit()
|
||||||
# print("✅ Hold release inserted for:", PMC_No, Invoice_Details)
|
|
||||||
#------------------------------------------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------------------------------------------
|
||||||
elif Invoice_Details and any(
|
elif Invoice_Details and any(
|
||||||
keyword in Invoice_Details.lower() for keyword in ['gst', 'release', 'gst release note']):
|
keyword in Invoice_Details.lower() for keyword in ['gst', 'release', 'gst release note']):
|
||||||
# print("Gst rels :", PMC_No, Invoice_No, Basic_Amount, Final_Amount,Total_Amount,UTR, subcontractor_id)
|
|
||||||
cursor.callproc(
|
cursor.callproc(
|
||||||
'AddGSTReleaseFromExcel',
|
'AddGSTReleaseFromExcel',
|
||||||
[PMC_No, Invoice_No, Basic_Amount, Final_Amount, Total_Amount, UTR, subcontractor_id]
|
[PMC_No, Invoice_No, Basic_Amount, Final_Amount, Total_Amount, UTR, subcontractor_id]
|
||||||
)
|
)
|
||||||
|
|
||||||
# --------------------------------------
|
# --------------------------------------
|
||||||
# If no village/work detected, only PMC/Payment
|
# 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()):
|
||||||
# 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 ----------
|
# ---------- Only PMC / Payment rows ----------
|
||||||
if PMC_No and not Invoice_No and UTR :
|
if PMC_No and not Invoice_No and UTR :
|
||||||
# print("No village/work, using PMC only :", PMC_No)
|
cursor.callproc("insertExtrapaymet",(PMC_No, subcontractor_id))
|
||||||
|
for result in cursor.stored_results():
|
||||||
# check invoice exists
|
row = result.fetchone()
|
||||||
# cursor.execute(
|
invoice_id = row[0] if row else None
|
||||||
# "SELECT invoice_id FROM invoice WHERE PMC_No=%s ORDER BY invoice_id DESC LIMIT 1",
|
|
||||||
# (PMC_No,)
|
|
||||||
# )
|
|
||||||
# row = cursor.fetchone()
|
|
||||||
# invoice_id = row[0] if row else None
|
|
||||||
|
|
||||||
# # insert invoice if not exists
|
|
||||||
|
|
||||||
# if not invoice_id:
|
|
||||||
print(" extra payment :", PMC_No,Total_Amount,UTR, subcontractor_id)
|
|
||||||
|
|
||||||
cursor.execute(
|
|
||||||
"""
|
|
||||||
INSERT INTO invoice (PMC_No,Contractor_Id) VALUES (%s, %s);
|
|
||||||
""",
|
|
||||||
(PMC_No, subcontractor_id)
|
|
||||||
)
|
|
||||||
connection.commit()
|
|
||||||
|
|
||||||
cursor.execute(
|
|
||||||
"SELECT invoice_id FROM invoice WHERE PMC_No=%s AND Contractor_Id =%s ORDER BY invoice_id DESC LIMIT 1",
|
|
||||||
(PMC_No, subcontractor_id)
|
|
||||||
)
|
|
||||||
row = cursor.fetchone()
|
|
||||||
invoice_id = row[0] if row else None
|
|
||||||
|
|
||||||
# insert payment
|
# insert payment
|
||||||
cursor.callproc(
|
cursor.callproc(
|
||||||
"SavePayment",
|
"SavePayment",
|
||||||
(
|
(
|
||||||
PMC_No,
|
PMC_No,
|
||||||
Invoice_No, # required
|
Invoice_No,
|
||||||
Payment_Amount,
|
Payment_Amount,
|
||||||
TDS_Payment_Amount,
|
TDS_Payment_Amount,
|
||||||
Total_Amount,
|
Total_Amount,
|
||||||
@@ -399,39 +358,6 @@ 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()
|
connection.commit()
|
||||||
return jsonify({"success": "Data saved successfully!"}), 200
|
return jsonify({"success": "Data saved successfully!"}), 200
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -441,4 +367,3 @@ def save_data():
|
|||||||
cursor.close()
|
cursor.close()
|
||||||
connection.close()
|
connection.close()
|
||||||
return render_template('index.html')
|
return render_template('index.html')
|
||||||
# ---------------------- Report --------------------------------
|
|
||||||
@@ -1,20 +1,18 @@
|
|||||||
from flask import Blueprint, render_template, request, jsonify, redirect, url_for
|
from flask import Blueprint, render_template, request, jsonify, redirect, url_for
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
from model.HoldTypes import HoldTypes
|
from model.HoldTypes import HoldTypes
|
||||||
from model.GST import GST
|
# from model.GST import GST
|
||||||
|
|
||||||
hold_bp = Blueprint("hold_types", __name__)
|
hold_bp = Blueprint("hold_types", __name__)
|
||||||
|
|
||||||
|
hold = HoldTypes()
|
||||||
# ---------------- ADD HOLD TYPE ----------------
|
# ---------------- ADD HOLD TYPE ----------------
|
||||||
@hold_bp.route('/add_hold_type', methods=['GET','POST'])
|
@hold_bp.route('/add_hold_type', methods=['GET','POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def add_hold_type():
|
def add_hold_type():
|
||||||
hold = HoldTypes()
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
hold.AddHoldType(request)
|
hold.AddHoldType(request)
|
||||||
# ✅ Always redirect to same page (NO JSON)
|
# Always redirect to same page (NO JSON)
|
||||||
return redirect(url_for("hold_types.add_hold_type"))
|
return redirect(url_for("hold_types.add_hold_type"))
|
||||||
|
|
||||||
# GET request → show data
|
# GET request → show data
|
||||||
@@ -30,7 +28,6 @@ def add_hold_type():
|
|||||||
@login_required
|
@login_required
|
||||||
def check_hold_type():
|
def check_hold_type():
|
||||||
|
|
||||||
hold = HoldTypes()
|
|
||||||
return hold.CheckHoldType(request) # if exists
|
return hold.CheckHoldType(request) # if exists
|
||||||
|
|
||||||
|
|
||||||
@@ -39,13 +36,11 @@ def check_hold_type():
|
|||||||
@login_required
|
@login_required
|
||||||
def edit_hold_type(id):
|
def edit_hold_type(id):
|
||||||
|
|
||||||
hold = HoldTypes()
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
hold.EditHoldType(request, id) # ✅
|
hold.EditHoldType(request, id)
|
||||||
return hold.resultMessage
|
return hold.resultMessage
|
||||||
|
|
||||||
hold_data = hold.GetHoldTypeByID(id) # ✅
|
hold_data = hold.GetHoldTypeByID(id)
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"edit_hold_type.html",
|
"edit_hold_type.html",
|
||||||
@@ -58,20 +53,18 @@ def edit_hold_type(id):
|
|||||||
@login_required
|
@login_required
|
||||||
def delete_hold_type(id):
|
def delete_hold_type(id):
|
||||||
|
|
||||||
hold = HoldTypes()
|
hold.DeleteHoldType(request, id)
|
||||||
hold.DeleteHoldType(request, id) # ✅
|
|
||||||
|
|
||||||
return redirect(url_for("hold_types.add_hold_type"))
|
return redirect(url_for("hold_types.add_hold_type"))
|
||||||
|
|
||||||
|
|
||||||
# ---------------- GST ----------------
|
# ---------------- GST ----------------
|
||||||
@hold_bp.route('/unreleased_gst')
|
# @hold_bp.route('/unreleased_gst')
|
||||||
@login_required
|
# @login_required
|
||||||
def unreleased_gst():
|
# def unreleased_gst():
|
||||||
|
|
||||||
data = GST.get_unreleased_gst()
|
# data = GST.get_unreleased_gst()
|
||||||
|
|
||||||
return render_template(
|
# return render_template(
|
||||||
"unreleased_gst.html",
|
# "unreleased_gst.html",
|
||||||
data=data
|
# data=data
|
||||||
)
|
# )
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
# controllers/invoice_controller.py
|
|
||||||
|
|
||||||
from flask import Blueprint, request, jsonify, render_template
|
from flask import Blueprint, request, jsonify, render_template
|
||||||
from flask_login import login_required, current_user
|
from flask_login import login_required, current_user
|
||||||
from model.Invoice import *
|
from model.Invoice import *
|
||||||
@@ -37,11 +35,7 @@ def add_invoice():
|
|||||||
|
|
||||||
village_id = village_result['Village_Id']
|
village_id = village_result['Village_Id']
|
||||||
invoice_id = insert_invoice(data, village_id)
|
invoice_id = insert_invoice(data, village_id)
|
||||||
# assign_subcontractor(data, village_id)
|
|
||||||
print("********************************************************************")
|
|
||||||
print("Manully added invoice id :",invoice_id)
|
|
||||||
print("********************************************************************")
|
|
||||||
|
|
||||||
insert_hold_types(data, invoice_id)
|
insert_hold_types(data, invoice_id)
|
||||||
|
|
||||||
log_action("Add invoice", f"added invoice '{data.get('pmc_no')}'")
|
log_action("Add invoice", f"added invoice '{data.get('pmc_no')}'")
|
||||||
@@ -84,7 +78,6 @@ def edit_invoice(invoice_id):
|
|||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
data = request.form
|
data = request.form
|
||||||
update_invoice(data, invoice_id)
|
update_invoice(data, invoice_id)
|
||||||
# update_inpayment(data)
|
|
||||||
log_action("Edit invoice", f"edited invoice '{invoice_id}'")
|
log_action("Edit invoice", f"edited invoice '{invoice_id}'")
|
||||||
return jsonify({"status": "success", "message": "Invoice updated successfully"}), 200
|
return jsonify({"status": "success", "message": "Invoice updated successfully"}), 200
|
||||||
|
|
||||||
|
|||||||
@@ -29,8 +29,7 @@ def add_payment():
|
|||||||
|
|
||||||
LogHelper.log_action("Add Payment", f"User {current_user.id} Add Payment '{pmc_no}'")
|
LogHelper.log_action("Add Payment", f"User {current_user.id} Add Payment '{pmc_no}'")
|
||||||
Paymentmodel.insert_payment(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'))
|
return redirect(url_for('payment_bp.add_payment'))
|
||||||
|
|
||||||
return render_template('add_payment.html', payments=payments)
|
return render_template('add_payment.html', payments=payments)
|
||||||
@@ -71,14 +70,6 @@ def edit_payment(payment_id):
|
|||||||
LogHelper.log_action("Edit Payment", f"User {current_user.id} Edit Payment '{pmc_no}'")
|
LogHelper.log_action("Edit Payment", f"User {current_user.id} Edit Payment '{pmc_no}'")
|
||||||
Paymentmodel.call_update_payment_proc(payment_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr)
|
Paymentmodel.call_update_payment_proc(payment_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr)
|
||||||
|
|
||||||
# Update inpayment
|
|
||||||
# connection = Paymentmodel.get_connection()
|
|
||||||
# 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'))
|
return redirect(url_for('payment_bp.add_payment'))
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
from flask import Blueprint, render_template, send_from_directory
|
from flask import Blueprint, render_template, send_from_directory,send_file
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
from model.PmcReport import PmcReport
|
from model.UnifiedReportService import UnifiedReportService
|
||||||
|
|
||||||
pmc_report_bp = Blueprint("pmc_report", __name__)
|
pmc_report_bp = Blueprint("pmc_report", __name__)
|
||||||
|
|
||||||
# ---------------- Contractor Report by pmc no ----------------
|
# ---------------- Contractor Report by pmc no ----------------
|
||||||
@pmc_report_bp.route("/pmc_report/<pmc_no>")
|
@pmc_report_bp.route("/pmc_report/<pmc_no>")
|
||||||
@login_required
|
@login_required
|
||||||
def pmc_report(pmc_no):
|
def pmc_report(pmc_no):
|
||||||
data = PmcReport.get_pmc_report(pmc_no)
|
data = UnifiedReportService.get_report(pmc_no=pmc_no)
|
||||||
if not data:
|
if not data:
|
||||||
return "No PMC found with this number", 404
|
return "No PMC found with this number", 404
|
||||||
|
|
||||||
@@ -17,6 +16,7 @@ def pmc_report(pmc_no):
|
|||||||
info=data["info"],
|
info=data["info"],
|
||||||
invoices=data["invoices"],
|
invoices=data["invoices"],
|
||||||
hold_types=data["hold_types"],
|
hold_types=data["hold_types"],
|
||||||
|
hold_data=data["hold_data"],
|
||||||
gst_rel=data["gst_rel"],
|
gst_rel=data["gst_rel"],
|
||||||
payments=data["payments"],
|
payments=data["payments"],
|
||||||
credit_note=data["credit_note"],
|
credit_note=data["credit_note"],
|
||||||
@@ -29,12 +29,9 @@ def pmc_report(pmc_no):
|
|||||||
@login_required
|
@login_required
|
||||||
def download_pmc_report(pmc_no):
|
def download_pmc_report(pmc_no):
|
||||||
|
|
||||||
result = PmcReport.download_pmc_report(pmc_no)
|
output_file = UnifiedReportService.download(pmc_no=pmc_no)
|
||||||
|
|
||||||
if not result:
|
if not output_file:
|
||||||
return "No contractor found for this PMC No", 404
|
return "No contractor found for this PMC No", 404
|
||||||
|
|
||||||
output_folder, file_name = result
|
return send_file(output_file, as_attachment=True)
|
||||||
|
|
||||||
return send_from_directory(output_folder, file_name, as_attachment=True)
|
|
||||||
|
|
||||||
@@ -4,8 +4,8 @@ from flask_login import login_required, current_user
|
|||||||
from model.Report import ReportHelper
|
from model.Report import ReportHelper
|
||||||
from model.Log import LogHelper
|
from model.Log import LogHelper
|
||||||
import os
|
import os
|
||||||
|
from model.UnifiedReportService import UnifiedReportService
|
||||||
|
|
||||||
DOWNLOAD_FOLDER = "static/download"
|
|
||||||
report_bp = Blueprint("report", __name__)
|
report_bp = Blueprint("report", __name__)
|
||||||
|
|
||||||
|
|
||||||
@@ -37,7 +37,8 @@ def search_contractor():
|
|||||||
@login_required
|
@login_required
|
||||||
def contractor_report(contractor_id):
|
def contractor_report(contractor_id):
|
||||||
|
|
||||||
data = ReportHelper.get_contractor_report(contractor_id)
|
# data = UnifiedReportService.get_report(contractor_id)
|
||||||
|
data = UnifiedReportService.get_report(contractor_id=contractor_id)
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
'subcontractor_report.html',
|
'subcontractor_report.html',
|
||||||
@@ -45,19 +46,13 @@ def contractor_report(contractor_id):
|
|||||||
**data
|
**data
|
||||||
)
|
)
|
||||||
|
|
||||||
# # ---------------- Contractor Download Report by contractor id ----------------
|
# ---------------- Contractor Download Report by contractor id ----------------
|
||||||
# @report_bp.route('/download_report/<int:contractor_id>')
|
|
||||||
# @login_required
|
|
||||||
# def download_report(contractor_id):
|
|
||||||
|
|
||||||
# return ReportHelper().download_report(contractor_id=contractor_id)
|
|
||||||
|
|
||||||
@report_bp.route('/download_report/<int:contractor_id>')
|
@report_bp.route('/download_report/<int:contractor_id>')
|
||||||
def download_report(contractor_id):
|
def download_report(contractor_id):
|
||||||
output_file, error = ReportHelper.create_contractor_report(contractor_id)
|
|
||||||
|
|
||||||
if error:
|
|
||||||
return error, 404
|
|
||||||
|
|
||||||
# Send the file to the user
|
file_path = UnifiedReportService.download(contractor_id=contractor_id)
|
||||||
return send_file(output_file, as_attachment=True)
|
|
||||||
|
if not file_path:
|
||||||
|
return "Report not found", 404
|
||||||
|
|
||||||
|
return send_file(file_path, as_attachment=True)
|
||||||
@@ -3,14 +3,12 @@ from flask_login import login_required
|
|||||||
from model.State import State
|
from model.State import State
|
||||||
|
|
||||||
state_bp = Blueprint('state', __name__)
|
state_bp = Blueprint('state', __name__)
|
||||||
|
state = State()
|
||||||
|
|
||||||
# ----- State page ------
|
# ----- State page ------
|
||||||
@state_bp.route('/add_state', methods=['GET', 'POST'])
|
@state_bp.route('/add_state', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def add_state():
|
def add_state():
|
||||||
|
|
||||||
state = State()
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
state.AddState(request=request)
|
state.AddState(request=request)
|
||||||
return state.resultMessage
|
return state.resultMessage
|
||||||
@@ -24,8 +22,6 @@ def add_state():
|
|||||||
@login_required
|
@login_required
|
||||||
def check_state():
|
def check_state():
|
||||||
|
|
||||||
state = State()
|
|
||||||
|
|
||||||
return state.CheckState(request=request)
|
return state.CheckState(request=request)
|
||||||
|
|
||||||
# ----- State delete by state id ------
|
# ----- State delete by state id ------
|
||||||
@@ -33,8 +29,6 @@ def check_state():
|
|||||||
@login_required
|
@login_required
|
||||||
def deleteState(id):
|
def deleteState(id):
|
||||||
|
|
||||||
state = State()
|
|
||||||
|
|
||||||
state.DeleteState(request=request, id=id)
|
state.DeleteState(request=request, id=id)
|
||||||
|
|
||||||
if not state.isSuccess:
|
if not state.isSuccess:
|
||||||
@@ -47,8 +41,6 @@ def deleteState(id):
|
|||||||
@login_required
|
@login_required
|
||||||
def editState(id):
|
def editState(id):
|
||||||
|
|
||||||
state = State()
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
|
|
||||||
state.EditState(request=request, id=id)
|
state.EditState(request=request, id=id)
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ subcontractor_bp = Blueprint('subcontractor', __name__)
|
|||||||
def subcontract():
|
def subcontract():
|
||||||
|
|
||||||
sub = Subcontractor()
|
sub = Subcontractor()
|
||||||
|
|
||||||
# ---------------- GET ----------------
|
# ---------------- GET ----------------
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
subcontractor = sub.GetAllSubcontractors(request)
|
subcontractor = sub.GetAllSubcontractors(request)
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify
|
from flask import Blueprint, render_template, request, redirect, url_for, flash, jsonify
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
|
|
||||||
@@ -11,14 +7,12 @@ from model.State import State
|
|||||||
|
|
||||||
# Create Blueprint
|
# Create Blueprint
|
||||||
village_bp = Blueprint('village', __name__)
|
village_bp = Blueprint('village', __name__)
|
||||||
|
village = Village()
|
||||||
|
|
||||||
# ------------------------- Add Village -------------------------
|
# ------------------------- Add Village -------------------------
|
||||||
@village_bp.route('/add_village', methods=['GET', 'POST'])
|
@village_bp.route('/add_village', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def add_village():
|
def add_village():
|
||||||
|
|
||||||
village = Village()
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
village.AddVillage(request=request)
|
village.AddVillage(request=request)
|
||||||
@@ -79,17 +73,17 @@ def get_blocks(district_id):
|
|||||||
@village_bp.route('/check_village', methods=['POST'])
|
@village_bp.route('/check_village', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def check_village():
|
def check_village():
|
||||||
village = Village()
|
|
||||||
return village.CheckVillage(request=request)
|
return village.CheckVillage(request=request)
|
||||||
|
|
||||||
|
|
||||||
@village_bp.route('/delete_village/<int:village_id>')
|
@village_bp.route('/delete_village/<int:village_id>')
|
||||||
@login_required
|
@login_required
|
||||||
def delete_village(village_id):
|
def delete_village(village_id):
|
||||||
village = Village()
|
|
||||||
village.DeleteVillage(request=request, village_id=village_id)
|
village.DeleteVillage(request=request, village_id=village_id)
|
||||||
|
|
||||||
# ✅ Convert resultMessage to string if it's a Response or tuple
|
# resultMessage to string if it's a Response or tuple
|
||||||
raw_msg = village.resultMessage
|
raw_msg = village.resultMessage
|
||||||
|
|
||||||
if isinstance(raw_msg, tuple):
|
if isinstance(raw_msg, tuple):
|
||||||
@@ -112,8 +106,6 @@ def delete_village(village_id):
|
|||||||
@login_required
|
@login_required
|
||||||
def edit_village(village_id):
|
def edit_village(village_id):
|
||||||
|
|
||||||
village = Village()
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
|
|
||||||
village.EditVillage(request=request, village_id=village_id)
|
village.EditVillage(request=request, village_id=village_id)
|
||||||
@@ -135,7 +127,6 @@ def edit_village(village_id):
|
|||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# ✅ FIXED HERE (removed request)
|
|
||||||
village_data = village.GetVillageByID(id=village_id)
|
village_data = village.GetVillageByID(id=village_id)
|
||||||
|
|
||||||
if not village.isSuccess:
|
if not village.isSuccess:
|
||||||
|
|||||||
1426
logs/activity.log
1426
logs/activity.log
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,4 @@
|
|||||||
from flask import Blueprint, render_template, request, redirect, url_for, jsonify
|
|
||||||
|
|
||||||
from model.Utilities import RegEx, ResponseHandler, HtmlHelper, ItemCRUDType
|
from model.Utilities import RegEx, ResponseHandler, HtmlHelper, ItemCRUDType
|
||||||
from model.Log import LogData, LogHelper
|
|
||||||
|
|
||||||
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, itemCRUDMapping
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from mysql.connector import Error
|
from mysql.connector import Error
|
||||||
import config
|
import config
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
|
|
||||||
class ContractorInfo:
|
class ContractorInfo:
|
||||||
@@ -31,7 +30,7 @@ class ContractorInfo:
|
|||||||
connection = config.get_db_connection()
|
connection = config.get_db_connection()
|
||||||
with connection.cursor(dictionary=True, buffered=True) as cursor:
|
with connection.cursor(dictionary=True, buffered=True) as cursor:
|
||||||
# Fetch Hold Types
|
# Fetch Hold Types
|
||||||
cursor.callproc('GetHoldTypesByContractor', [self.ID])
|
cursor.callproc('GetHoldAmountsAndHoldTypeByCtr', [self.ID])
|
||||||
hold_types = []
|
hold_types = []
|
||||||
for result in cursor.stored_results():
|
for result in cursor.stored_results():
|
||||||
hold_types = result.fetchall()
|
hold_types = result.fetchall()
|
||||||
|
|||||||
80
model/GST.py
80
model/GST.py
@@ -1,51 +1,51 @@
|
|||||||
from model.ItemCRUD import ItemCRUD
|
# from model.ItemCRUD import ItemCRUD
|
||||||
from model.Utilities import ItemCRUDType
|
# from model.Utilities import ItemCRUDType
|
||||||
|
|
||||||
class GST:
|
# class GST:
|
||||||
|
|
||||||
@staticmethod
|
# @staticmethod
|
||||||
def get_unreleased_gst():
|
# def get_unreleased_gst():
|
||||||
# Use ItemCRUD for Invoices
|
# # Use ItemCRUD for Invoices
|
||||||
invoice_crud = ItemCRUD(itemType=ItemCRUDType.Invoice)
|
# invoice_crud = ItemCRUD(itemType=ItemCRUDType.Invoice)
|
||||||
invoices_rows = invoice_crud.GetAllData(storedproc="GetAllInvoicesBasic")
|
# invoices_rows = invoice_crud.GetAllData(storedproc="GetAllInvoicesBasic")
|
||||||
|
|
||||||
if not invoice_crud.isSuccess:
|
# if not invoice_crud.isSuccess:
|
||||||
return [] # Could also log invoice_crud.resultMessage
|
# return [] # Could also log invoice_crud.resultMessage
|
||||||
|
|
||||||
invoices = [
|
# invoices = [
|
||||||
dict(
|
# dict(
|
||||||
Invoice_No=row[1],
|
# Invoice_No=row[1],
|
||||||
GST_SD_Amount=float(row[2]) if row[2] is not None else 0
|
# GST_SD_Amount=float(row[2]) if row[2] is not None else 0
|
||||||
)
|
# )
|
||||||
for row in invoices_rows
|
# for row in invoices_rows
|
||||||
]
|
# ]
|
||||||
|
|
||||||
# Use ItemCRUD for GST Releases
|
# # Use ItemCRUD for GST Releases
|
||||||
gst_crud = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
# gst_crud = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||||
gst_rows = gst_crud.GetAllData(storedproc="GetAllGSTReleasesBasic")
|
# gst_rows = gst_crud.GetAllData(storedproc="GetAllGSTReleasesBasic")
|
||||||
|
|
||||||
if not gst_crud.isSuccess:
|
# if not gst_crud.isSuccess:
|
||||||
return [] # Could also log gst_crud.resultMessage
|
# return [] # Could also log gst_crud.resultMessage
|
||||||
|
|
||||||
gst_invoice_nos = {
|
# gst_invoice_nos = {
|
||||||
g[2] # Invoice_No is at index 2
|
# g[2] # Invoice_No is at index 2
|
||||||
for g in gst_rows
|
# for g in gst_rows
|
||||||
if g[2]
|
# if g[2]
|
||||||
}
|
# }
|
||||||
|
|
||||||
gst_basic_amounts = {
|
# gst_basic_amounts = {
|
||||||
float(g[3]) # Basic_Amount at index 3
|
# float(g[3]) # Basic_Amount at index 3
|
||||||
for g in gst_rows
|
# for g in gst_rows
|
||||||
if g[3] is not None
|
# if g[3] is not None
|
||||||
}
|
# }
|
||||||
|
|
||||||
# Filter unreleased invoices
|
# # Filter unreleased invoices
|
||||||
unreleased = []
|
# unreleased = []
|
||||||
for inv in invoices:
|
# for inv in invoices:
|
||||||
match_by_invoice = inv['Invoice_No'] in gst_invoice_nos
|
# match_by_invoice = inv['Invoice_No'] in gst_invoice_nos
|
||||||
match_by_gst_amount = inv['GST_SD_Amount'] in gst_basic_amounts
|
# match_by_gst_amount = inv['GST_SD_Amount'] in gst_basic_amounts
|
||||||
|
|
||||||
if not (match_by_invoice or match_by_gst_amount):
|
# if not (match_by_invoice or match_by_gst_amount):
|
||||||
unreleased.append(inv)
|
# unreleased.append(inv)
|
||||||
|
|
||||||
return unreleased
|
# return unreleased
|
||||||
@@ -33,7 +33,7 @@ class HoldTypes:
|
|||||||
self.isSuccess = hold.isSuccess
|
self.isSuccess = hold.isSuccess
|
||||||
self.resultMessage = hold.resultMessage
|
self.resultMessage = hold.resultMessage
|
||||||
|
|
||||||
# ✅ Convert tuple → dictionary
|
# Convert tuple → dictionary
|
||||||
data = []
|
data = []
|
||||||
for row in rows:
|
for row in rows:
|
||||||
data.append({
|
data.append({
|
||||||
@@ -51,7 +51,7 @@ class HoldTypes:
|
|||||||
self.isSuccess = hold.isSuccess
|
self.isSuccess = hold.isSuccess
|
||||||
self.resultMessage = hold.resultMessage
|
self.resultMessage = hold.resultMessage
|
||||||
|
|
||||||
# ✅ Convert tuple → dictionary
|
#Convert tuple → dictionary
|
||||||
if row:
|
if row:
|
||||||
return {
|
return {
|
||||||
"hold_type_id": row[0],
|
"hold_type_id": row[0],
|
||||||
|
|||||||
@@ -70,22 +70,7 @@ def get_all_villages():
|
|||||||
# ------------------- Invoice Functions -------------------
|
# ------------------- Invoice Functions -------------------
|
||||||
def insert_invoice(data, village_id):
|
def insert_invoice(data, village_id):
|
||||||
def operation(cursor):
|
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),
|
|
||||||
# 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', [
|
cursor.callproc('SaveInvoice', [
|
||||||
data.get('pmc_no'),
|
data.get('pmc_no'),
|
||||||
village_id,
|
village_id,
|
||||||
@@ -103,18 +88,6 @@ def insert_invoice(data, village_id):
|
|||||||
if row:
|
if row:
|
||||||
invoice_id = row['invoice_id']
|
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 invoice_id
|
||||||
|
|
||||||
return execute_db_operation(operation)
|
return execute_db_operation(operation)
|
||||||
@@ -159,18 +132,6 @@ def update_invoice(data, invoice_id):
|
|||||||
clear_results(cursor)
|
clear_results(cursor)
|
||||||
execute_db_operation(operation)
|
execute_db_operation(operation)
|
||||||
|
|
||||||
# def update_inpayment(data):
|
|
||||||
# def operation(cursor):
|
|
||||||
# cursor.callproc('UpdateInpayment', [
|
|
||||||
# data.get('work_type'),
|
|
||||||
# data.get('invoice_details'),
|
|
||||||
# data.get('invoice_date'),
|
|
||||||
# *get_numeric_values(data),
|
|
||||||
# data.get('pmc_no'),
|
|
||||||
# data.get('invoice_no')
|
|
||||||
# ])
|
|
||||||
# clear_results(cursor)
|
|
||||||
# execute_db_operation(operation)
|
|
||||||
|
|
||||||
def delete_invoice_data(invoice_id, user_id):
|
def delete_invoice_data(invoice_id, user_id):
|
||||||
def operation(cursor):
|
def operation(cursor):
|
||||||
@@ -190,24 +151,10 @@ def delete_invoice_data(invoice_id, user_id):
|
|||||||
cursor.callproc("DeleteInvoice", (invoice_id,))
|
cursor.callproc("DeleteInvoice", (invoice_id,))
|
||||||
clear_results(cursor)
|
clear_results(cursor)
|
||||||
|
|
||||||
# Delete inpayment
|
|
||||||
# cursor.callproc('DeleteInpaymentByPMCInvoice', (pmc_no, invoice_no))
|
|
||||||
# clear_results(cursor)
|
|
||||||
|
|
||||||
execute_db_operation(operation)
|
execute_db_operation(operation)
|
||||||
|
|
||||||
|
|
||||||
# ------------------- 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)
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------- Hold Types Functions -------------------
|
# ------------------- Hold Types Functions -------------------
|
||||||
def insert_hold_types(data, invoice_id):
|
def insert_hold_types(data, invoice_id):
|
||||||
|
|||||||
@@ -332,7 +332,7 @@ class ItemCRUD:
|
|||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
# GET BY ID
|
# GET BY ID
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
def GetDataByID(self, id, storedproc):
|
def GetDataByID(self, id, storedproc):
|
||||||
|
|
||||||
data = None
|
data = None
|
||||||
connection = config.get_db_connection()
|
connection = config.get_db_connection()
|
||||||
|
|||||||
@@ -1,300 +1,185 @@
|
|||||||
import openpyxl
|
# import openpyxl
|
||||||
from openpyxl.styles import Font, PatternFill
|
# from openpyxl.styles import Font, PatternFill
|
||||||
import config
|
# import config
|
||||||
from flask_login import current_user
|
# from flask_login import current_user
|
||||||
from model.Log import LogHelper
|
# from model.Log import LogHelper
|
||||||
|
# from model.excel import excel
|
||||||
|
# from model.Report import ReportHelper
|
||||||
|
# from model.FolderAndFile import FolderAndFile
|
||||||
|
|
||||||
from model.Report import ReportHelper
|
# class PmcReport:
|
||||||
from model.FolderAndFile import FolderAndFile
|
|
||||||
|
|
||||||
class PmcReport:
|
# @staticmethod
|
||||||
|
# def get_pmc_report(pmc_no):
|
||||||
|
|
||||||
@staticmethod
|
# connection = config.get_db_connection()
|
||||||
def get_pmc_report(pmc_no):
|
# cursor = connection.cursor(dictionary=True, buffered=True)
|
||||||
|
|
||||||
connection = config.get_db_connection()
|
# try:
|
||||||
cursor = connection.cursor(dictionary=True, buffered=True)
|
# pmc_info = ReportHelper.execute_sp(cursor, 'GetContractorInfoByPmcNo', [pmc_no], True)
|
||||||
|
|
||||||
try:
|
# if not pmc_info:
|
||||||
pmc_info = ReportHelper.execute_sp(cursor, 'GetContractorInfoByPmcNo', [pmc_no], True)
|
# return None
|
||||||
|
|
||||||
if not pmc_info:
|
# cursor.callproc("Get_pmc_hold_types", (pmc_no, pmc_info["Contractor_Id"]))
|
||||||
return None
|
# hold_types = next(cursor.stored_results()).fetchall()
|
||||||
|
|
||||||
cursor.callproc("Get_pmc_hold_types", (pmc_no, pmc_info["Contractor_Id"]))
|
# # Extract hold_type_ids
|
||||||
hold_types = next(cursor.stored_results()).fetchall()
|
# hold_type_ids = [ht['hold_type_id'] for ht in hold_types]
|
||||||
|
|
||||||
# Extract hold_type_ids
|
# invoices = []
|
||||||
hold_type_ids = [ht['hold_type_id'] for ht in hold_types]
|
# hold_amount_total = 0
|
||||||
|
# hold_type_ids_str = ",".join(map(str, hold_type_ids))
|
||||||
invoices = []
|
# cursor.callproc(
|
||||||
hold_amount_total = 0
|
# 'GetInvoices_WithHold',
|
||||||
# if hold_type_ids:
|
# [pmc_no, pmc_info["Contractor_Id"], hold_type_ids_str]
|
||||||
# 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"]]
|
|
||||||
# )
|
|
||||||
|
|
||||||
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():
|
# for result in cursor.stored_results():
|
||||||
invoices = result.fetchall()
|
# invoices = result.fetchall()
|
||||||
|
|
||||||
if hold_type_ids:
|
# if hold_type_ids:
|
||||||
hold_amount_total = sum(row.get('hold_amount', 0) or 0 for row in invoices)
|
# 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)
|
# total_invo_final = sum(row.get('Final_Amount', 0) or 0 for row in invoices)
|
||||||
|
|
||||||
gst_rel = ReportHelper.execute_sp(cursor, 'GetGSTReleaseByPMC', [pmc_no])
|
# gst_rel = ReportHelper.execute_sp(cursor, 'GetGSTReleaseByPMC', [pmc_no])
|
||||||
total_gst_basic = sum(row.get('basic_amount', 0) or 0 for row in gst_rel)
|
# total_gst_basic = sum(row.get('basic_amount', 0) or 0 for row in gst_rel)
|
||||||
total_gst_final = sum(row.get('final_amount', 0) or 0 for row in gst_rel)
|
# total_gst_final = sum(row.get('final_amount', 0) or 0 for row in gst_rel)
|
||||||
|
|
||||||
hold_release = ReportHelper.execute_sp(cursor, 'GetHoldReleaseByPMC', [pmc_no])
|
# hold_release = ReportHelper.execute_sp(cursor, 'GetHoldReleaseByPMC', [pmc_no])
|
||||||
|
|
||||||
credit_note = ReportHelper.execute_sp(cursor, 'GetCreditNoteByPMC', [pmc_no])
|
# credit_note = ReportHelper.execute_sp(cursor, 'GetCreditNoteByPMC', [pmc_no])
|
||||||
|
|
||||||
payments = ReportHelper.execute_sp(cursor, 'GetPaymentsByPMC', [pmc_no])
|
# payments = ReportHelper.execute_sp(cursor, 'GetPaymentsByPMC', [pmc_no])
|
||||||
total_pay_amount = sum(row.get('Payment_Amount', 0) or 0 for row in payments)
|
# total_pay_amount = sum(row.get('Payment_Amount', 0) or 0 for row in payments)
|
||||||
total_pay_total = sum(row.get('Total_amount', 0) or 0 for row in payments)
|
# total_pay_total = sum(row.get('Total_amount', 0) or 0 for row in payments)
|
||||||
|
|
||||||
totals = {
|
# totals = {
|
||||||
"sum_invo_basic_amt": sum(row.get('Basic_Amount', 0) or 0 for row in invoices),
|
# "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_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_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_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_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_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_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_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_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_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_final_amt": total_invo_final,
|
||||||
"sum_invo_hold_amt": hold_amount_total,
|
# "sum_invo_hold_amt": hold_amount_total,
|
||||||
"sum_gst_basic_amt": total_gst_basic,
|
# "sum_gst_basic_amt": total_gst_basic,
|
||||||
"sum_gst_final_amt": total_gst_final,
|
# "sum_gst_final_amt": total_gst_final,
|
||||||
"sum_pay_payment_amt": total_pay_amount,
|
# "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_tds_payment_amt": sum(row.get('TDS_Payment_Amount', 0) or 0 for row in payments),
|
||||||
"sum_pay_total_amt": total_pay_total
|
# "sum_pay_total_amt": total_pay_total
|
||||||
}
|
# }
|
||||||
|
|
||||||
return {
|
# return {
|
||||||
"info": pmc_info,
|
# "info": pmc_info,
|
||||||
"invoices": invoices,
|
# "invoices": invoices,
|
||||||
"hold_types": hold_types,
|
# "hold_types": hold_types,
|
||||||
"gst_rel": gst_rel,
|
# "gst_rel": gst_rel,
|
||||||
"payments": payments,
|
# "payments": payments,
|
||||||
"credit_note": credit_note,
|
# "credit_note": credit_note,
|
||||||
"hold_release": hold_release,
|
# "hold_release": hold_release,
|
||||||
"total": totals
|
# "total": totals
|
||||||
}
|
# }
|
||||||
|
|
||||||
finally:
|
# finally:
|
||||||
cursor.close()
|
# cursor.close()
|
||||||
connection.close()
|
# connection.close()
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
# @staticmethod
|
||||||
def download_pmc_report(pmc_no):
|
# def download_pmc_report(pmc_no):
|
||||||
|
|
||||||
connection = config.get_db_connection()
|
# connection = config.get_db_connection()
|
||||||
if not connection:
|
# if not connection:
|
||||||
return None
|
# return None
|
||||||
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
# cursor = connection.cursor(dictionary=True)
|
||||||
|
|
||||||
try:
|
# try:
|
||||||
filename = f"PMC_Report_{pmc_no}.xlsx"
|
# filename = f"PMC_Report_{pmc_no}.xlsx"
|
||||||
|
|
||||||
output_folder = FolderAndFile.get_download_folder()
|
# output_folder = FolderAndFile.get_download_folder()
|
||||||
output_file = FolderAndFile.get_download_path(filename)
|
# output_file = FolderAndFile.get_download_path(filename)
|
||||||
|
|
||||||
# ================= DATA FETCH =================
|
# # ================= DATA FETCH =================
|
||||||
|
|
||||||
contractor_info = ReportHelper.execute_sp(
|
# contractor_info = ReportHelper.execute_sp(
|
||||||
cursor, 'GetContractorDetailsByPMC', [pmc_no]
|
# cursor, 'GetContractorInfoByPmcNo', [pmc_no]
|
||||||
)
|
# )
|
||||||
|
|
||||||
contractor_info = contractor_info[0] if contractor_info else None
|
# contractor_info = contractor_info[0] if contractor_info else None
|
||||||
print("contractor_info:::",contractor_info)
|
# print("contractor_info:::",contractor_info)
|
||||||
|
|
||||||
if not contractor_info:
|
# if not contractor_info:
|
||||||
return None
|
# return None
|
||||||
|
|
||||||
hold_types = ReportHelper.execute_sp(
|
# hold_types = ReportHelper.execute_sp(
|
||||||
cursor, 'GetHoldTypesByContractor',
|
# cursor, 'GetHoldTypesByContractor',
|
||||||
[contractor_info["Contractor_Id"]]
|
# [contractor_info["Contractor_Id"]]
|
||||||
)
|
# )
|
||||||
|
|
||||||
hold_type_map = {
|
# hold_type_map = {
|
||||||
ht['hold_type_id']: ht['hold_type'] for ht in hold_types
|
# ht['hold_type_id']: ht['hold_type'] for ht in hold_types
|
||||||
}
|
# }
|
||||||
|
|
||||||
invoices = ReportHelper.execute_sp(
|
# invoices = ReportHelper.execute_sp(
|
||||||
cursor, 'GetInvoicesByContractorOrPMCNo', [None,pmc_no]
|
# cursor, 'GetInvoicesByContractorOrPMCNo', [None,pmc_no]
|
||||||
)
|
# )
|
||||||
|
|
||||||
credit_notes = ReportHelper.execute_sp(
|
# credit_notes = ReportHelper.execute_sp(
|
||||||
cursor, 'NewGetCreditNotesByPMCNo', [pmc_no]
|
# cursor, 'NewGetCreditNotesByPMCNo', [pmc_no]
|
||||||
)
|
# )
|
||||||
|
# credit_note_map = {}
|
||||||
|
# for cn in credit_notes:
|
||||||
|
# key = (
|
||||||
|
# str(cn['PMC_No']).strip()
|
||||||
|
# )
|
||||||
|
# credit_note_map.setdefault(key, []).append(cn)
|
||||||
|
|
||||||
hold_amounts = ReportHelper.execute_sp(
|
# hold_amounts = ReportHelper.execute_sp(
|
||||||
cursor, 'GetHoldAmountsByContractor',
|
# cursor, 'GetHoldAmountsByContractor',
|
||||||
[contractor_info["Contractor_Id"]]
|
# [contractor_info["Contractor_Id"]]
|
||||||
)
|
# )
|
||||||
|
|
||||||
gst_releases = ReportHelper.execute_sp(
|
# gst_releases = ReportHelper.execute_sp(
|
||||||
cursor, 'GetGSTReleaseDetailsByPMC', [pmc_no]
|
# cursor, 'GetGSTReleaseDetailsByPMC', [pmc_no]
|
||||||
)
|
# )
|
||||||
|
# gst_release_map = {}
|
||||||
|
# for gr in gst_releases:
|
||||||
|
|
||||||
# ================= DATA MAPPING =================
|
# key = (
|
||||||
hold_data = {}
|
# str(gr['PMC_No']).strip()
|
||||||
for h in hold_amounts:
|
# )
|
||||||
hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
# gst_release_map.setdefault(key, []).append(gr)
|
||||||
|
|
||||||
credit_note_map = {}
|
# # ================= DATA MAPPING =================
|
||||||
for cn in credit_notes:
|
# hold_data = {}
|
||||||
pmc = cn.get("PMC_No")
|
# for h in hold_amounts:
|
||||||
if pmc:
|
# hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
||||||
credit_note_map.setdefault(pmc, []).append(cn)
|
|
||||||
|
|
||||||
gst_map = {}
|
|
||||||
for gst in gst_releases:
|
|
||||||
pmc = gst.get("PMC_No")
|
|
||||||
if pmc:
|
|
||||||
gst_map.setdefault(pmc, []).append(gst)
|
|
||||||
|
|
||||||
# ================= LOG =================
|
|
||||||
LogHelper.log_action(
|
|
||||||
"Download PMC Report",
|
|
||||||
f"User {current_user.id} Download PMC Report '{pmc_no}'"
|
|
||||||
)
|
|
||||||
|
|
||||||
# ================= EXCEL =================
|
# # ================= LOG =================
|
||||||
workbook = openpyxl.Workbook()
|
# LogHelper.log_action(
|
||||||
sheet = workbook.active
|
# "Download PMC Report",
|
||||||
sheet.title = "PMC Report"
|
# f"User {current_user.id} Download PMC Report '{pmc_no}'"
|
||||||
|
# )
|
||||||
|
|
||||||
# HEADER INFO
|
# excel.generate_excel(
|
||||||
sheet.append(["", "", "Laxmi Civil Engineering Services PVT. LTD."])
|
# 0, contractor_info, invoices, hold_types, hold_data,
|
||||||
sheet.append(["Contractor Name", contractor_info["Contractor_Name"]])
|
# credit_note_map,gst_release_map, output_file
|
||||||
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 = [
|
# return output_folder, filename
|
||||||
"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]
|
# except Exception as e:
|
||||||
payment_headers = ["Final Amount", "Payment Amount", "TDS Payment", "Total Paid", "UTR"]
|
# print(f"Error generating PMC report: {e}")
|
||||||
|
# return None
|
||||||
|
|
||||||
headers = base_headers + hold_headers + payment_headers
|
# finally:
|
||||||
sheet.append(headers)
|
# cursor.close()
|
||||||
for cell in sheet[sheet.max_row]:
|
# connection.close()
|
||||||
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", "")
|
|
||||||
]
|
|
||||||
|
|
||||||
# GST release placeholders (will add real GST below)
|
|
||||||
row += ["", ""]
|
|
||||||
|
|
||||||
sheet.append(row)
|
|
||||||
|
|
||||||
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()
|
|
||||||
|
|||||||
308
model/Report.py
308
model/Report.py
@@ -1,11 +1,4 @@
|
|||||||
import config
|
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
|
|
||||||
|
|
||||||
class ReportHelper:
|
class ReportHelper:
|
||||||
isSuccess = False
|
isSuccess = False
|
||||||
@@ -86,309 +79,12 @@ class ReportHelper:
|
|||||||
return data
|
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
|
@staticmethod
|
||||||
def get_contractor_info(contractor_id):
|
def get_contractor_info(contractor_id):
|
||||||
from model.ContractorInfo import ContractorInfo
|
from model.ContractorInfo import ContractorInfo
|
||||||
contractor = ContractorInfo(contractor_id)
|
contractor = ContractorInfo(contractor_id)
|
||||||
return contractor.contInfo if contractor.contInfo else None
|
return contractor.contInfo if contractor.contInfo else None
|
||||||
|
|
||||||
# @staticmethod
|
|
||||||
# def generate_excel(contractor_id, contInfo, invoices, hold_types, hold_data,
|
|
||||||
# extra_payments_map, credit_note_map, gst_release_map, output_file):
|
|
||||||
@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"
|
|
||||||
|
|
||||||
# Contractor Info
|
|
||||||
for field, value in contInfo.items():
|
|
||||||
sheet.append([field.replace("_", " "), value])
|
|
||||||
sheet.append([])
|
|
||||||
|
|
||||||
# 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"]
|
|
||||||
|
|
||||||
hold_headers = [ht['hold_type'] for ht in hold_types]
|
|
||||||
|
|
||||||
payment_headers = ["Final Amount", "Payment Amount", "TDS Payment", "Total Paid", "UTR"]
|
|
||||||
|
|
||||||
all_headers = base_headers + hold_headers + payment_headers
|
|
||||||
sheet.append(all_headers)
|
|
||||||
|
|
||||||
for cell in sheet[sheet.max_row]:
|
|
||||||
cell.font = Font(bold=True)
|
|
||||||
cell.fill = PatternFill(start_color="ADD8E6", end_color="ADD8E6", fill_type="solid")
|
|
||||||
|
|
||||||
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, invoice_no)
|
|
||||||
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", "")
|
|
||||||
]
|
|
||||||
|
|
||||||
# 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, ""))
|
|
||||||
|
|
||||||
# Payment values
|
|
||||||
row += [
|
|
||||||
inv.get("Final_Amount", ""),
|
|
||||||
inv.get("Payment_Amount", ""),
|
|
||||||
inv.get("TDS_Payment_Amount", ""),
|
|
||||||
inv.get("Total_Amount", ""),
|
|
||||||
inv.get("UTR", "")
|
|
||||||
]
|
|
||||||
|
|
||||||
sheet.append(row)
|
|
||||||
|
|
||||||
# # Extra Payments
|
|
||||||
# if pmc_no in extra_payments_map:
|
|
||||||
# for ep in extra_payments_map[pmc_no]:
|
|
||||||
# extra_row = [pmc_no] + [""] * (len(base_headers) - 1)
|
|
||||||
# extra_row += [""] * len(hold_headers)
|
|
||||||
# extra_row += [
|
|
||||||
# "",
|
|
||||||
# ep.get("Payment_Amount", ""),
|
|
||||||
# ep.get("TDS_Payment_Amount", ""),
|
|
||||||
# ep.get("Total_Amount", ""),
|
|
||||||
# ep.get("utr", "")
|
|
||||||
# ]
|
|
||||||
# sheet.append(extra_row)
|
|
||||||
|
|
||||||
# del extra_payments_map[pmc_no]
|
|
||||||
|
|
||||||
# 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", ""), "", "", "", "", "", "", "", "", ""
|
|
||||||
]
|
|
||||||
|
|
||||||
gst_row += [""] * len(hold_headers)
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def create_contractor_report(contractor_id):
|
|
||||||
# DOWNLOAD_FOLDER = os.path.join("static", "download")
|
|
||||||
# os.makedirs(DOWNLOAD_FOLDER, exist_ok=True)
|
|
||||||
fileName=f"Contractor_Report_{contractor_id}.xlsx"
|
|
||||||
# output_file = os.path.join(DOWNLOAD_FOLDER, )
|
|
||||||
|
|
||||||
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, 'GetInvoicesByContractorOrPMCNo', [contractor_id,None])
|
|
||||||
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']
|
|
||||||
# # # -------- Extra Payments MAP --------
|
|
||||||
# # extra_payments_raw = ReportHelper.execute_sp(cursor, 'GetExtraPayments')
|
|
||||||
# # extra_payments_map = {}
|
|
||||||
# # for ep in extra_payments_raw:
|
|
||||||
# # pmc = str(ep['pmc_no']).strip()
|
|
||||||
# # extra_payments_map.setdefault(pmc, []).append(ep)
|
|
||||||
|
|
||||||
# -------- 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(),
|
|
||||||
# str(cn['Invoice_No']).replace(" ", "") if cn['Invoice_No'] else ""
|
|
||||||
# )
|
|
||||||
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(),
|
|
||||||
# str(gr['Invoice_No']).replace(" ", "") if gr['Invoice_No'] else ""
|
|
||||||
# )
|
|
||||||
key = (
|
|
||||||
str(gr['PMC_No']).strip()
|
|
||||||
)
|
|
||||||
gst_release_map.setdefault(key, []).append(gr)
|
|
||||||
|
|
||||||
# print("GST MAP:", gst_release_map)
|
|
||||||
# Generate Excel
|
|
||||||
# ReportHelper.generate_excel(
|
|
||||||
# contractor_id, contInfo, invoices, hold_types, hold_data,
|
|
||||||
# extra_payments_map, credit_note_map, gst_release_map, output_file
|
|
||||||
# )
|
|
||||||
ReportHelper.generate_excel(
|
|
||||||
contractor_id, contInfo, invoices, hold_types, hold_data,
|
|
||||||
credit_note_map, gst_release_map, output_file
|
|
||||||
)
|
|
||||||
|
|
||||||
return output_file, None
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
155
model/UnifiedReportService.py
Normal file
155
model/UnifiedReportService.py
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
import config
|
||||||
|
from model.excel import excel
|
||||||
|
from model.Report import ReportHelper
|
||||||
|
from model.FolderAndFile import FolderAndFile
|
||||||
|
from decimal import Decimal
|
||||||
|
class UnifiedReportService:
|
||||||
|
|
||||||
|
# Static variable to cache report data
|
||||||
|
# _cached_report_data = None
|
||||||
|
# _cached_contractor_id = None
|
||||||
|
# _cached_pmc_no = None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_report(contractor_id=None, pmc_no=None):
|
||||||
|
|
||||||
|
# If cached and same request, return cached data
|
||||||
|
# if (UnifiedReportService._cached_report_data and
|
||||||
|
# contractor_id == UnifiedReportService._cached_contractor_id and
|
||||||
|
# pmc_no == UnifiedReportService._cached_pmc_no):
|
||||||
|
# return UnifiedReportService._cached_report_data
|
||||||
|
|
||||||
|
connection = config.get_db_connection()
|
||||||
|
cursor = connection.cursor(dictionary=True, buffered=True)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# ================= BASIC INFO =================
|
||||||
|
if contractor_id:
|
||||||
|
info = ReportHelper.execute_sp(cursor,'GetContractorInfo',[contractor_id],True)
|
||||||
|
else:
|
||||||
|
info = ReportHelper.execute_sp(cursor,'GetContractorInfoByPmcNo',[pmc_no],True)
|
||||||
|
|
||||||
|
|
||||||
|
contractor_id = info["Contractor_Id"] if info else None
|
||||||
|
|
||||||
|
if not info:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# ================= HOLD TYPES =================
|
||||||
|
hold_types = ReportHelper.execute_sp(cursor,'GetHoldTypesByContractor',[contractor_id]) or []
|
||||||
|
|
||||||
|
|
||||||
|
# ================= INVOICES =================
|
||||||
|
if pmc_no:
|
||||||
|
invoices = ReportHelper.execute_sp(cursor,'GetInvoicesByContractorOrPMCNo',[None, pmc_no]) or []
|
||||||
|
credit_notes = ReportHelper.execute_sp(cursor,'NewGetCreditNotesByPMCNo',[pmc_no]) or []
|
||||||
|
gst_rel = ReportHelper.execute_sp(cursor,'GetGSTReleaseDetailsByPMC',[pmc_no]) or []
|
||||||
|
payments = ReportHelper.execute_sp(cursor,'GetPaymentsByPMC',[pmc_no]) or []
|
||||||
|
|
||||||
|
else:
|
||||||
|
invoices = ReportHelper.execute_sp(cursor,'GetInvoicesByContractorOrPMCNo',[contractor_id, None]) or []
|
||||||
|
credit_notes = ReportHelper.execute_sp(cursor,'GetCreditNotesByContractor',[contractor_id]) or []
|
||||||
|
gst_rel = ReportHelper.execute_sp(cursor,'GstReleasesByContractorId',[contractor_id]) or []
|
||||||
|
payments = ReportHelper.execute_sp(cursor,'GetPayments',[contractor_id]) or []
|
||||||
|
|
||||||
|
# ================= HOLD AMOUNTS =================
|
||||||
|
hold_amounts = ReportHelper.execute_sp(cursor,'GetHoldAmountsByContractor',[contractor_id]) or []
|
||||||
|
|
||||||
|
hold_data = {}
|
||||||
|
for h in hold_amounts:
|
||||||
|
hold_data.setdefault(h["Invoice_Id"], {})[h["hold_type_id"]] = h["hold_amount"]
|
||||||
|
|
||||||
|
# ================= CREDIT NOTES =================
|
||||||
|
|
||||||
|
credit_note_map = {}
|
||||||
|
for cn in credit_notes:
|
||||||
|
key = str(cn.get("PMC_No")).strip()
|
||||||
|
credit_note_map.setdefault(key, []).append(cn)
|
||||||
|
|
||||||
|
# ================= GST RELEASE =================
|
||||||
|
gst_release_map = {}
|
||||||
|
for gr in gst_rel:
|
||||||
|
key = str(gr.get("PMC_No")).strip()
|
||||||
|
gst_release_map.setdefault(key, []).append(gr)
|
||||||
|
|
||||||
|
# ================= PAYMENTS =================
|
||||||
|
total = {
|
||||||
|
"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(r.get("Final_Amount", 0) or 0 for r in invoices),
|
||||||
|
"sum_invo_hold_amt": sum(r.get("hold_amount", 0) or 0 for r in hold_amounts),
|
||||||
|
"sum_gst_basic_amt": sum(r.get("Basic_Amount", 0) or 0 for r in gst_rel),
|
||||||
|
"sum_gst_final_amt": sum(r.get("Final_Amount", 0) or 0 for r in gst_rel),
|
||||||
|
"sum_gst_total_amt": sum(r.get("Total_Amount", 0) or 0 for r in gst_rel),
|
||||||
|
"sum_pay_total_amt": sum(Decimal(r.get("Total_amount") or 0) for r in payments),
|
||||||
|
"sum_pay_payment_amt": sum(Decimal(r.get("Payment_Amount") or 0) for r in payments),
|
||||||
|
"sum_pay_tds_payment_amt": sum(Decimal(r.get("TDS_Payment_Amount") or 0) for r in payments),
|
||||||
|
"sum_credit_basic_amt": sum(Decimal(c.get("Basic_Amount") or 0) for c in credit_notes),
|
||||||
|
"sum_credit_final_amt": sum(Decimal(c.get("Final_Amount") or 0) for c in credit_notes),
|
||||||
|
"sum_credit_total_amt": sum(Decimal(c.get("Total_Amount") or 0) for c in credit_notes),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Prepare final report
|
||||||
|
report_data = {
|
||||||
|
"info": info,
|
||||||
|
"invoices": invoices,
|
||||||
|
"hold_types": hold_types,
|
||||||
|
"payments": payments,
|
||||||
|
"hold_data": hold_data,
|
||||||
|
"hold_release": hold_data,
|
||||||
|
"credit_note_map": credit_note_map,
|
||||||
|
"credit_note": credit_notes,
|
||||||
|
"gst_release_map": gst_release_map,
|
||||||
|
"gst_rel": gst_rel,
|
||||||
|
"total": total
|
||||||
|
}
|
||||||
|
|
||||||
|
# # Cache the report
|
||||||
|
# UnifiedReportService._cached_report_data = report_data
|
||||||
|
# UnifiedReportService._cached_contractor_id = contractor_id
|
||||||
|
# UnifiedReportService._cached_pmc_no = pmc_no
|
||||||
|
|
||||||
|
return report_data
|
||||||
|
|
||||||
|
finally:
|
||||||
|
cursor.close()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
# ================= DOWNLOAD EXCEL =================
|
||||||
|
@staticmethod
|
||||||
|
def download(contractor_id=None, pmc_no=None):
|
||||||
|
# Use cached report if available
|
||||||
|
report_data = UnifiedReportService.get_report(contractor_id, pmc_no)
|
||||||
|
|
||||||
|
if not report_data:
|
||||||
|
return None
|
||||||
|
|
||||||
|
fileName = (
|
||||||
|
f"Contractor_Report_{contractor_id}.xlsx"
|
||||||
|
if contractor_id else f"PMC_Report_{pmc_no}.xlsx"
|
||||||
|
)
|
||||||
|
|
||||||
|
output_file = FolderAndFile.get_download_path(fileName)
|
||||||
|
|
||||||
|
excel.generate_excel(
|
||||||
|
contractor_id or 0,
|
||||||
|
report_data["info"],
|
||||||
|
report_data["invoices"],
|
||||||
|
report_data["hold_types"],
|
||||||
|
report_data["hold_data"],
|
||||||
|
report_data["credit_note_map"],
|
||||||
|
report_data["gst_release_map"],
|
||||||
|
report_data["payments"],
|
||||||
|
report_data["total"],
|
||||||
|
output_file
|
||||||
|
)
|
||||||
|
|
||||||
|
return output_file
|
||||||
@@ -9,6 +9,7 @@ class ItemCRUDType(Enum):
|
|||||||
HoldType = 5
|
HoldType = 5
|
||||||
Subcontractor = 6
|
Subcontractor = 6
|
||||||
GSTRelease = 7
|
GSTRelease = 7
|
||||||
|
Invoice = 8
|
||||||
|
|
||||||
class RegEx:
|
class RegEx:
|
||||||
patternAlphabetOnly = r"^[A-Za-z ]+$"
|
patternAlphabetOnly = r"^[A-Za-z ]+$"
|
||||||
|
|||||||
@@ -13,14 +13,14 @@ class Village:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.isSuccess = False
|
self.isSuccess = False
|
||||||
self.resultMessage = ""
|
self.resultMessage = ""
|
||||||
self.response = {} # ✅ ADDED
|
self.response = {}
|
||||||
self.village = ItemCRUD(itemType=ItemCRUDType.Village)
|
self.village = ItemCRUD(itemType=ItemCRUDType.Village)
|
||||||
|
|
||||||
# 🔹 Helper: sync status
|
# 🔹 Helper: sync status
|
||||||
def _set_status(self, village):
|
def _set_status(self, village):
|
||||||
self.isSuccess = village.isSuccess
|
self.isSuccess = village.isSuccess
|
||||||
|
|
||||||
# ✅ UPDATED (safe handling)
|
# UPDATED (safe handling)
|
||||||
if hasattr(village, "response"):
|
if hasattr(village, "response"):
|
||||||
self.response = village.response
|
self.response = village.response
|
||||||
self.resultMessage = village.response.get("message", "")
|
self.resultMessage = village.response.get("message", "")
|
||||||
@@ -75,7 +75,7 @@ class Village:
|
|||||||
block_id, village_name = self._get_form_data(request)
|
block_id, village_name = self._get_form_data(request)
|
||||||
|
|
||||||
if not village_name:
|
if not village_name:
|
||||||
self.response = ResponseHandler.invalid_name("village") # ✅ UPDATED
|
self.response = ResponseHandler.invalid_name("village")
|
||||||
self.resultMessage = self.response["message"]
|
self.resultMessage = self.response["message"]
|
||||||
self.isSuccess = False
|
self.isSuccess = False
|
||||||
return None
|
return None
|
||||||
@@ -85,7 +85,7 @@ class Village:
|
|||||||
request=request,
|
request=request,
|
||||||
parentid=block_id,
|
parentid=block_id,
|
||||||
childname=village_name,
|
childname=village_name,
|
||||||
storedprocfetch="GetVillageByNameAndBlock" # Change GetVillageByNameAndBlocks to GetVillageByNameAndBlock
|
storedprocfetch="GetVillageByNameAndBlock"
|
||||||
)
|
)
|
||||||
self._set_status(self.village)
|
self._set_status(self.village)
|
||||||
return result
|
return result
|
||||||
@@ -113,7 +113,7 @@ class Village:
|
|||||||
block_id, village_name = self._get_form_data(request)
|
block_id, village_name = self._get_form_data(request)
|
||||||
|
|
||||||
if not village_name:
|
if not village_name:
|
||||||
self.response = ResponseHandler.invalid_name("village") # ✅ UPDATED
|
self.response = ResponseHandler.invalid_name("village")
|
||||||
self.resultMessage = self.response["message"]
|
self.resultMessage = self.response["message"]
|
||||||
self.isSuccess = False
|
self.isSuccess = False
|
||||||
return
|
return
|
||||||
@@ -176,7 +176,6 @@ class Village:
|
|||||||
print(f"Error fetching blocks: {e}")
|
print(f"Error fetching blocks: {e}")
|
||||||
self.isSuccess = False
|
self.isSuccess = False
|
||||||
|
|
||||||
# ✅ FIXED (removed jsonify response)
|
|
||||||
self.response = ResponseHandler.fetch_failure("block")
|
self.response = ResponseHandler.fetch_failure("block")
|
||||||
self.resultMessage = self.response["message"]
|
self.resultMessage = self.response["message"]
|
||||||
|
|
||||||
|
|||||||
200
model/excel.py
Normal file
200
model/excel.py
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
import openpyxl
|
||||||
|
from openpyxl.styles import Font, PatternFill
|
||||||
|
from datetime import datetime
|
||||||
|
from decimal import Decimal
|
||||||
|
from model.FolderAndFile import FolderAndFile
|
||||||
|
|
||||||
|
class excel:
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def generate_excel(contractor_id,info, invoices, hold_types, hold_data, credit_note_map, gst_release_map, payments,total,output_file):
|
||||||
|
|
||||||
|
workbook = openpyxl.Workbook()
|
||||||
|
sheet = workbook.active
|
||||||
|
sheet.title = "Contractor Report"
|
||||||
|
|
||||||
|
# Contractor Info
|
||||||
|
for field, value in info.items():
|
||||||
|
sheet.append([field.replace("_", " "), value])
|
||||||
|
sheet.append([])
|
||||||
|
|
||||||
|
# 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"]
|
||||||
|
|
||||||
|
hold_headers = [ht['hold_type'] for ht in hold_types]
|
||||||
|
|
||||||
|
payment_headers = ["Final Amount", "Payment Amount", "TDS Payment", "Total Paid", "UTR"]
|
||||||
|
|
||||||
|
all_headers = base_headers + hold_headers + payment_headers
|
||||||
|
sheet.append(all_headers)
|
||||||
|
|
||||||
|
for cell in sheet[sheet.max_row]:
|
||||||
|
cell.font = Font(bold=True)
|
||||||
|
cell.fill = PatternFill(start_color="ADD8E6", end_color="ADD8E6", fill_type="solid")
|
||||||
|
|
||||||
|
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", "")
|
||||||
|
]
|
||||||
|
|
||||||
|
# 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, ""))
|
||||||
|
|
||||||
|
# Payment values
|
||||||
|
row += [
|
||||||
|
inv.get("Final_Amount", ""),
|
||||||
|
inv.get("Payment_Amount", ""),
|
||||||
|
inv.get("TDS_Payment_Amount", ""),
|
||||||
|
inv.get("Total_Amount", ""),
|
||||||
|
inv.get("UTR", "")
|
||||||
|
]
|
||||||
|
|
||||||
|
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", ""), "", "", "", "", "", "", "", "", "" ]
|
||||||
|
|
||||||
|
gst_row += [""] * len(hold_headers)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
# total calculation
|
||||||
|
hold_totals = {ht['hold_type_id']: 0 for ht in hold_types}
|
||||||
|
|
||||||
|
for inv in invoices:
|
||||||
|
invoice_holds = hold_data.get(inv["Invoice_Id"], {})
|
||||||
|
for ht_id in hold_totals:
|
||||||
|
hold_totals[ht_id] += invoice_holds.get(ht_id, 0) or 0
|
||||||
|
|
||||||
|
total_basic_amount = total.get('sum_invo_basic_amt', 0)+total.get('sum_gst_basic_amt')+ total.get('sum_credit_basic_amt')
|
||||||
|
total_final_amount = total.get('sum_invo_final_amt', 0)+ total.get('sum_gst_final_amt', 0) + total.get('sum_credit_final_amt', 0)
|
||||||
|
total_total_amount = total.get('sum_pay_total_amt', 0)+ total.get('sum_gst_total_amt', 0) + total.get('sum_credit_total_amt', 0)
|
||||||
|
|
||||||
|
# total row insert
|
||||||
|
totalrow = ["Total","-","-","-","-","-",total_basic_amount,
|
||||||
|
total.get('sum_invo_debit_amt', 0), total.get('sum_invo_after_debit_amt', 0),total.get('sum_invo_gst_amt', 0),total.get('sum_invo_amt', 0),
|
||||||
|
total.get('sum_invo_tds_amt', 0),total.get('sum_invo_ds_amt', 0),total.get('sum_invo_on_commission', 0), total.get('sum_invo_hydro_test', 0),
|
||||||
|
total.get('sum_invo_gst_sd_amt', 0)]
|
||||||
|
|
||||||
|
for ht in hold_types:
|
||||||
|
totalrow.append(hold_totals.get(ht['hold_type_id'], 0))
|
||||||
|
|
||||||
|
totalrow += [total_final_amount, "","", total_total_amount]
|
||||||
|
|
||||||
|
sheet.append(totalrow)
|
||||||
|
|
||||||
|
# Apply style (color + bold)
|
||||||
|
for cell in sheet[sheet.max_row]:
|
||||||
|
cell.fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid") # Yellow
|
||||||
|
cell.font = Font(bold=True)
|
||||||
|
|
||||||
|
# summary report
|
||||||
|
sheet.append([])
|
||||||
|
sheet.append(["Summary Report"])
|
||||||
|
today_date = datetime.today().strftime('%A, %Y-%m-%d')
|
||||||
|
sheet.append([])
|
||||||
|
sheet.append(["Contractor Name", info["Contractor_Name"]])
|
||||||
|
sheet.append(["Date", today_date])
|
||||||
|
sheet.append(["Description", "Amount"])
|
||||||
|
|
||||||
|
# Calculate surplus/advance
|
||||||
|
surplus_amount = total_final_amount - total_total_amount
|
||||||
|
sheet.append(["Advance/Surplus", str(surplus_amount)])
|
||||||
|
|
||||||
|
# Get the last appended row
|
||||||
|
current_row = sheet.max_row
|
||||||
|
cell = sheet.cell(row=current_row, column=2)
|
||||||
|
|
||||||
|
# Apply green fill if positive, red fill if negative
|
||||||
|
if surplus_amount >= 0:
|
||||||
|
fill_color = PatternFill(start_color="C6EFCE", end_color="C6EFCE", fill_type="solid") # Light green
|
||||||
|
else:
|
||||||
|
fill_color = PatternFill(start_color="FFC7CE", end_color="FFC7CE", fill_type="solid") # Light red
|
||||||
|
|
||||||
|
cell.fill = fill_color
|
||||||
|
# sheet.append(["Total Hold Amount", str(Decimal(total["sum_invo_hold_amt"]))])
|
||||||
|
for ht in hold_types:
|
||||||
|
sheet.append([ht['hold_type'], hold_totals.get(ht['hold_type_id'], 0)])
|
||||||
|
|
||||||
|
sheet.append(["Amount With TDS", str(total.get('sum_invo_tds_amt', 0))])
|
||||||
|
|
||||||
|
# Auto adjust column widths
|
||||||
|
for col in sheet.columns:
|
||||||
|
max_length = 0
|
||||||
|
col_letter = openpyxl.utils.get_column_letter(col[0].column)
|
||||||
|
for cell in col:
|
||||||
|
try:
|
||||||
|
if cell.value:
|
||||||
|
max_length = max(max_length, len(str(cell.value)))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
sheet.column_dimensions[col_letter].width = max_length + 2
|
||||||
|
|
||||||
|
# SAVE ONCE AT END
|
||||||
|
workbook.save(output_file)
|
||||||
@@ -14,12 +14,6 @@ class GSTRelease:
|
|||||||
try:
|
try:
|
||||||
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||||
|
|
||||||
# Print the full form data
|
|
||||||
print("===== DEBUG: FORM DATA =====")
|
|
||||||
for key, value in request.form.items():
|
|
||||||
print(f"{key} : {value}")
|
|
||||||
print("=============================")
|
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"PMC_No": request.form.get("PMC_No", "").strip(),
|
"PMC_No": request.form.get("PMC_No", "").strip(),
|
||||||
"Invoice_No": request.form.get("Invoice_No", "").strip(),
|
"Invoice_No": request.form.get("Invoice_No", "").strip(),
|
||||||
@@ -30,10 +24,6 @@ class GSTRelease:
|
|||||||
"Contractor_ID": int(request.form.get("Contractor_ID", 0) or 0)
|
"Contractor_ID": int(request.form.get("Contractor_ID", 0) or 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
print("===== DEBUG: PARSED DATA =====")
|
|
||||||
print(data)
|
|
||||||
print("==============================")
|
|
||||||
|
|
||||||
# Add GST Release
|
# Add GST Release
|
||||||
gst.AddItem(
|
gst.AddItem(
|
||||||
request=request,
|
request=request,
|
||||||
@@ -42,8 +32,6 @@ class GSTRelease:
|
|||||||
storedprocadd="AddGSTReleaseFromExcel"
|
storedprocadd="AddGSTReleaseFromExcel"
|
||||||
)
|
)
|
||||||
|
|
||||||
print(f"AddItem result: isSuccess={gst.isSuccess}, message={gst.resultMessage}")
|
|
||||||
|
|
||||||
self.isSuccess = gst.isSuccess
|
self.isSuccess = gst.isSuccess
|
||||||
self.resultMessage = str(gst.resultMessage)
|
self.resultMessage = str(gst.resultMessage)
|
||||||
|
|
||||||
@@ -69,10 +57,6 @@ class GSTRelease:
|
|||||||
"p_gst_release_id": gst_release_id
|
"p_gst_release_id": gst_release_id
|
||||||
}
|
}
|
||||||
|
|
||||||
print("===== DEBUG: UPDATE DATA =====")
|
|
||||||
print(data)
|
|
||||||
print("==============================")
|
|
||||||
|
|
||||||
# Call your stored procedure
|
# Call your stored procedure
|
||||||
gst.EditItem(
|
gst.EditItem(
|
||||||
request=request,
|
request=request,
|
||||||
|
|||||||
@@ -72,24 +72,6 @@ class Paymentmodel:
|
|||||||
if connection:
|
if connection:
|
||||||
connection.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
|
|
||||||
# try:
|
|
||||||
# cursor = connection.cursor()
|
|
||||||
# cursor.callproc('UpdateInpaymentRecord', [
|
|
||||||
# subcontractor_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr
|
|
||||||
# ])
|
|
||||||
# connection.commit()
|
|
||||||
# return True
|
|
||||||
# except mysql.connector.Error as e:
|
|
||||||
# print(f"Error updating inpayment: {e}")
|
|
||||||
# return False
|
|
||||||
# finally:
|
|
||||||
# cursor.close()
|
|
||||||
# connection.close()
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def fetch_payment_by_id(payment_id):
|
def fetch_payment_by_id(payment_id):
|
||||||
@@ -144,7 +126,7 @@ class Paymentmodel:
|
|||||||
try:
|
try:
|
||||||
cursor = connection.cursor(dictionary=True)
|
cursor = connection.cursor(dictionary=True)
|
||||||
# Fetch PMC & Invoice before deleting
|
# Fetch PMC & Invoice before deleting
|
||||||
cursor.callproc('GetPaymentPMCInvoiceById', [payment_id])
|
cursor.callproc('GetPaymentById', [payment_id])
|
||||||
record = {}
|
record = {}
|
||||||
for result in cursor.stored_results():
|
for result in cursor.stored_results():
|
||||||
record = result.fetchone() or {}
|
record = result.fetchone() or {}
|
||||||
@@ -155,9 +137,7 @@ class Paymentmodel:
|
|||||||
# Delete payment
|
# Delete payment
|
||||||
cursor.callproc("DeletePayment", (payment_id,))
|
cursor.callproc("DeletePayment", (payment_id,))
|
||||||
connection.commit()
|
connection.commit()
|
||||||
# Reset inpayment fields
|
|
||||||
# cursor.callproc("ResetInpayment", [pmc_no, invoice_no])
|
|
||||||
# connection.commit()
|
|
||||||
return True, pmc_no, invoice_no
|
return True, pmc_no, invoice_no
|
||||||
except mysql.connector.Error as e:
|
except mysql.connector.Error as e:
|
||||||
print(f"Error deleting payment: {e}")
|
print(f"Error deleting payment: {e}")
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ form {
|
|||||||
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
|
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
margin: auto;
|
||||||
gap: 15px;
|
gap: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
BIN
static/images/icons/male_profile.jpeg
Normal file
BIN
static/images/icons/male_profile.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
@@ -376,10 +376,12 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a
|
<!-- <a
|
||||||
href="javascript:void(0);"
|
href="javascript:void(0);"
|
||||||
onclick="deleteInvoice({{ invoice.Invoice_Id }}, this)"
|
onclick="deleteInvoice({{ invoice.Invoice_Id }}, this)"
|
||||||
>
|
> -->
|
||||||
|
<a href="javascript:void(0);"
|
||||||
|
onclick="deleteInvoice('{{ invoice.Invoice_Id }}', this)">
|
||||||
<img
|
<img
|
||||||
src="{{ url_for('static', filename='images/icons/bin_red_icon.png') }}"
|
src="{{ url_for('static', filename='images/icons/bin_red_icon.png') }}"
|
||||||
alt="Delete"
|
alt="Delete"
|
||||||
|
|||||||
@@ -1,147 +0,0 @@
|
|||||||
{% extends 'base.html' %}
|
|
||||||
{% block content %}
|
|
||||||
<head>
|
|
||||||
<title>Manage Purchases</title>
|
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="button-container">
|
|
||||||
<button id="addButton" class="action-button">Add Purchase</button>
|
|
||||||
<button id="displayButton" class="action-button">Display Purchases</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- ADD PURCHASE FORM -->
|
|
||||||
<!-- ADD PURCHASE FORM -->
|
|
||||||
<div id="addForm" style="display: none;">
|
|
||||||
<h2>Add Purchase Entry</h2>
|
|
||||||
<form action="/add_purchase_order" method="POST">
|
|
||||||
<label for="purchase_date">Purchase Date:</label><br>
|
|
||||||
<input type="date" id="purchase_date" name="purchase_date" required><br><br>
|
|
||||||
|
|
||||||
<label for="supplier_name">Supplier Name:</label><br>
|
|
||||||
<input type="text" id="supplier_name" name="supplier_name" required><br><br>
|
|
||||||
|
|
||||||
<label for="Purchase Order No">Purchase Order No:</label><br>
|
|
||||||
<input type="text" name="purchase_order_no" required><br><br>
|
|
||||||
|
|
||||||
<label for="unit">Item Name:</label><br>
|
|
||||||
<input type="text" id="item_name" name="item_name" required><br><br>
|
|
||||||
|
|
||||||
<label for="quantity">Quantity:</label><br>
|
|
||||||
<input type="number" id="quantity" name="quantity" step="1" required><br><br>
|
|
||||||
|
|
||||||
<label for="unit">Unit:</label><br>
|
|
||||||
<input type="text" id="unit" name="unit" required><br><br>
|
|
||||||
|
|
||||||
<label for="rate">Rate:</label><br>
|
|
||||||
<input type="number" step="0.01" id="rate" name="rate" required><br><br>
|
|
||||||
|
|
||||||
<label for="amount">Amount:</label><br>
|
|
||||||
<input type="number" step="0.01" id="amount" name="amount" readonly><br><br>
|
|
||||||
|
|
||||||
<!-- GST input -->
|
|
||||||
<label for="gst_percent">GST %:</label><br>
|
|
||||||
<input type="number" step="0.01" id="gst_percent"><br><br>
|
|
||||||
|
|
||||||
<label>GST Amount:</label><br>
|
|
||||||
<input type="number" step="0.01" id="GST_Amount" name="GST_Amount" readonly><br><br>
|
|
||||||
|
|
||||||
<!-- TDS input -->
|
|
||||||
<label for="tds_percent">TDS %:</label><br>
|
|
||||||
<input type="number" step="0.01" id="tds_percent"><br><br>
|
|
||||||
|
|
||||||
<label>TDS:</label><br>
|
|
||||||
<input type="number" step="0.01" id="TDS" name="TDS" readonly><br><br>
|
|
||||||
|
|
||||||
<label>Final Amount:</label><br>
|
|
||||||
<input type="number" step="0.01" id="final_amount" name="final_amount" readonly><br><br>
|
|
||||||
|
|
||||||
<input type="submit" value="Submit">
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- DISPLAY TABLE -->
|
|
||||||
<div id="displayTable" style="display: none;">
|
|
||||||
<h2>Purchase List</h2>
|
|
||||||
<table border="1">
|
|
||||||
<tr>
|
|
||||||
<th>ID</th>
|
|
||||||
<th>Purchase Date</th>
|
|
||||||
<th>Supplier Name</th>
|
|
||||||
<th>Purchase Order No</th>
|
|
||||||
<th>Item Name</th>
|
|
||||||
<th>Quantity</th>
|
|
||||||
<th>Unit</th>
|
|
||||||
<th>Rate</th>
|
|
||||||
<th>Amount</th>
|
|
||||||
<th>GST Amount</th>
|
|
||||||
<th>TDS</th>
|
|
||||||
<th>Final Amount</th>
|
|
||||||
<th>Edit</th>
|
|
||||||
<th>Delete</th>
|
|
||||||
</tr>
|
|
||||||
{% for purchase in purchases %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ purchase['purchase_id'] }}</td>
|
|
||||||
<td>{{ purchase['purchase_date'] }}</td>
|
|
||||||
<td>{{ purchase['supplier_name'] }}</td>
|
|
||||||
<td>{{ purchase['purchase_order_no'] }}</td>
|
|
||||||
<td>{{ purchase['item_name'] }}</td>
|
|
||||||
<td>{{ purchase['quantity'] }}</td>
|
|
||||||
<td>{{ purchase['unit'] }}</td>
|
|
||||||
<td>{{ purchase['rate'] }}</td>
|
|
||||||
<td>{{ purchase['amount'] }}</td>
|
|
||||||
<td>{{ purchase['GST_Amount'] }}</td>
|
|
||||||
<td>{{ purchase['TDS'] }}</td>
|
|
||||||
<td>{{ purchase['final_amount'] }}</td>
|
|
||||||
<td><a href="{{ url_for('update_purchase', id=purchase['purchase_id']) }}">Edit</a></td>
|
|
||||||
<td>
|
|
||||||
<form method="POST" action="{{ url_for('delete_purchase', id=purchase['purchase_id']) }}" style="display:inline;">
|
|
||||||
<button type="submit" onclick="return confirm('Are you sure?')">Delete</button>
|
|
||||||
</form>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
$(document).ready(function() {
|
|
||||||
$('#addButton').click(function() {
|
|
||||||
$('#addForm').toggle();
|
|
||||||
});
|
|
||||||
$('#displayButton').click(function() {
|
|
||||||
$('#displayTable').toggle();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<script>
|
|
||||||
function calculateAmounts() {
|
|
||||||
const qty = parseFloat(document.getElementById('quantity').value) || 0;
|
|
||||||
const rate = parseFloat(document.getElementById('rate').value) || 0;
|
|
||||||
const gstPercent = parseFloat(document.getElementById('gst_percent').value) || 0;
|
|
||||||
const tdsPercent = parseFloat(document.getElementById('tds_percent').value) || 0;
|
|
||||||
|
|
||||||
const amount = qty * rate;
|
|
||||||
document.getElementById('amount').value = amount.toFixed(2);
|
|
||||||
|
|
||||||
const gstAmount = (gstPercent / 100) * amount;
|
|
||||||
document.getElementById('GST_Amount').value = gstAmount.toFixed(2);
|
|
||||||
|
|
||||||
const tdsAmount = (tdsPercent / 100) * amount;
|
|
||||||
document.getElementById('TDS').value = tdsAmount.toFixed(2);
|
|
||||||
|
|
||||||
const finalAmount = amount + gstAmount - tdsAmount;
|
|
||||||
document.getElementById('final_amount').value = finalAmount.toFixed(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attach events
|
|
||||||
document.getElementById('quantity').addEventListener('input', calculateAmounts);
|
|
||||||
document.getElementById('rate').addEventListener('input', calculateAmounts);
|
|
||||||
document.getElementById('gst_percent').addEventListener('input', calculateAmounts);
|
|
||||||
document.getElementById('tds_percent').addEventListener('input', calculateAmounts);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
{% endblock %}
|
|
||||||
@@ -106,7 +106,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="javascript:void(0);"
|
<a href="javascript:void(0);"
|
||||||
onclick="deleteVillage({{ village[0] }}, this)">
|
onclick="deleteVillage('{{ village[0] }}', this)">
|
||||||
<img src="{{ url_for('static', filename='images/icons/bin_red_icon.png') }}"
|
<img src="{{ url_for('static', filename='images/icons/bin_red_icon.png') }}"
|
||||||
class="icon">
|
class="icon">
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -1,137 +0,0 @@
|
|||||||
{% extends 'base.html' %}
|
|
||||||
{% block content %}
|
|
||||||
<head>
|
|
||||||
<title>Manage Work Order</title>
|
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}">
|
|
||||||
|
|
||||||
</head>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="button-container">
|
|
||||||
<button id="addButton" class="action-button">Add</button>
|
|
||||||
<button id="displayButton" class="action-button">Display</button>
|
|
||||||
</div>
|
|
||||||
<form action="/submit_work_order" method="POST">
|
|
||||||
<div id="addForm" style="display: none;">
|
|
||||||
<h2>Create Work Order</h2>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Subcontractor Dropdown -->
|
|
||||||
<label for="subcontractor_id">Select Vender Name:</label><br>
|
|
||||||
<select name="vendor_name" id="vendor_name" required>
|
|
||||||
<option value="">-- Select Subcontractor --</option>
|
|
||||||
{% for sc in subcontractor %}
|
|
||||||
<option value="{{ sc.Contractor_Name }}">{{ sc.Contractor_Name }}</option>
|
|
||||||
{% endfor %}
|
|
||||||
</select><br><br>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<label for="work_order_number">Work Order Number:</label><br>
|
|
||||||
<input type="text" id="work_order_number" name="work_order_number" required><br><br>
|
|
||||||
|
|
||||||
<label for="work_order_amount">Work Order Amount</label><br>
|
|
||||||
<input type="number" step="0.01" id="work_order_amount" name="work_order_amount" required><br><br>
|
|
||||||
|
|
||||||
<label for="gst_amount">GST Amount:</label><br>
|
|
||||||
<input type="number" step="0.01" id="gst_amount" name="gst_amount" required><br><br>
|
|
||||||
|
|
||||||
<label for="tds_amount">TDS Amount:</label><br>
|
|
||||||
<input type="number" step="0.01" id="tds_amount" name="tds_amount" required><br><br>
|
|
||||||
|
|
||||||
<label for="security_deposit">Security Deposit:</label><br>
|
|
||||||
<input type="number" step="0.01" id="security_deposit" name="security_deposit" required><br><br>
|
|
||||||
|
|
||||||
<label for="sd_against_gst">SD Against GST:</label><br>
|
|
||||||
<input type="number" step="0.01" id="sd_against_gst" name="sd_against_gst" required><br><br>
|
|
||||||
|
|
||||||
<label for="final_total">Final Total:</label><br>
|
|
||||||
<input type="number" step="0.01" id="final_total" name="final_total" readonly><br><br>
|
|
||||||
|
|
||||||
<input type="submit" value="Submit">
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{# display data #}
|
|
||||||
<div id="addTable" style="display: none;">
|
|
||||||
{# <div class="search-container">#}
|
|
||||||
{# <h2>Hold Type List</h2>#}
|
|
||||||
{# <input type="text" id="searchBar" placeholder="Searching..." onkeyup="searchTable()">#}
|
|
||||||
{# </div>#}
|
|
||||||
<table id="sortableTable" border="1">
|
|
||||||
<tr>
|
|
||||||
<th>ID</th>
|
|
||||||
<th class="sortable-header">
|
|
||||||
Vender Name
|
|
||||||
{# <span class="sort-buttons">#}
|
|
||||||
{# <span class="sort-asc">⬆️</span>#}
|
|
||||||
{# <span class="sort-desc">⬇️</span>#}
|
|
||||||
{# </span>#}
|
|
||||||
</th>
|
|
||||||
<th>Work Order Type</th>
|
|
||||||
<th>Work Order Amount</th>
|
|
||||||
<th>BOQ Amount</th>
|
|
||||||
<th>Work Done Percentage</th>
|
|
||||||
<th>Update</th>
|
|
||||||
<th>Delete</th>
|
|
||||||
</tr>
|
|
||||||
{% for htd in wo %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ htd.work_order_id }}</td>
|
|
||||||
<td>{{ htd['vendor_name'] }}</td>
|
|
||||||
<td>{{ htd['work_order_type'] }}</td>
|
|
||||||
<td>{{ htd['work_order_amount'] }}</td>
|
|
||||||
<td>{{ htd['boq_amount'] }}</td>
|
|
||||||
<td>{{ htd['work_done_percentage'] }}</td>
|
|
||||||
<td>{{ htd['work_order_number'] }}</td>
|
|
||||||
<td>{{ htd['gst_amount'] }}</td>
|
|
||||||
<td>{{ htd['tds_amount'] }}</td>
|
|
||||||
<td>{{ htd[''] }}</td>
|
|
||||||
<td><a href="{{ url_for('update_work_order', id=htd['work_order_id']) }}">Edit</a></td>
|
|
||||||
<td>
|
|
||||||
<form action="{{ url_for('delete_work_order', id=htd['work_order_id']) }}" method="POST" style="display:inline;">
|
|
||||||
<button type="submit" onclick="return confirm('Are you sure you want to delete this work order?');" class="delete-button">Delete</button>
|
|
||||||
</form>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<a href="/">Back to Dashboard</a>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
$(document).ready(function () {
|
|
||||||
$('#displayButton').click(function () {
|
|
||||||
$('#addTable').toggle();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#addButton').click(function () {
|
|
||||||
$('#addForm').toggle();
|
|
||||||
|
|
||||||
// Bind input event handlers ONLY after form is shown
|
|
||||||
setTimeout(function () {
|
|
||||||
["work_order_amount", "gst_amount", "tds_amount", "security_deposit", "sd_against_gst"].forEach(function (id) {
|
|
||||||
document.getElementById(id).addEventListener("input", calculateFinalTotal);
|
|
||||||
});
|
|
||||||
}, 100); // Delay ensures elements are available in DOM
|
|
||||||
});
|
|
||||||
|
|
||||||
function calculateFinalTotal() {
|
|
||||||
const workOrderAmount = parseFloat(document.getElementById("work_order_amount").value) || 0;
|
|
||||||
const gstAmount = parseFloat(document.getElementById("gst_amount").value) || 0;
|
|
||||||
const tdsAmount = parseFloat(document.getElementById("tds_amount").value) || 0;
|
|
||||||
const securityDeposit = parseFloat(document.getElementById("security_deposit").value) || 0;
|
|
||||||
const sdAgainstGst = parseFloat(document.getElementById("sd_against_gst").value) || 0;
|
|
||||||
|
|
||||||
const finalTotal = workOrderAmount + gstAmount - (tdsAmount + securityDeposit + sdAgainstGst);
|
|
||||||
document.getElementById("final_total").value = finalTotal.toFixed(2);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head><title>Edit GRN</title>
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h2>Edit GRN</h2>
|
|
||||||
<form method="POST">
|
|
||||||
<label>GRN Date:</label>
|
|
||||||
<input type="date" name="grn_date" value="{{ grn['grn_date'] }}" required><br><br>
|
|
||||||
|
|
||||||
<label>Purchase ID:</label>
|
|
||||||
<input type="number" name="purchase_id" value="{{ grn['purchase_id'] }}" required><br><br>
|
|
||||||
|
|
||||||
<label>Supplier Name:</label>
|
|
||||||
<input type="text" name="supplier_name" value="{{ grn['supplier_name'] }}" required><br><br>
|
|
||||||
|
|
||||||
<label>Item Description:</label>
|
|
||||||
<input type="text" name="item_description" value="{{ grn['item_description'] }}" required><br><br>
|
|
||||||
|
|
||||||
<label>Received Quantity:</label>
|
|
||||||
<input type="number" name="received_quantity" value="{{ grn['received_quantity'] }}" required><br><br>
|
|
||||||
|
|
||||||
<label>Unit:</label>
|
|
||||||
<input type="text" name="unit" value="{{ grn['unit'] }}" required><br><br>
|
|
||||||
|
|
||||||
<label>Rate:</label>
|
|
||||||
<input type="number" step="0.01" name="rate" value="{{ grn['rate'] }}" required><br><br>
|
|
||||||
|
|
||||||
<label>Amount:</label>
|
|
||||||
<input type="number" step="0.01" name="amount" value="{{ grn['amount'] }}" required><br><br>
|
|
||||||
|
|
||||||
<label>Remarks:</label>
|
|
||||||
<input type="text" name="remarks" value="{{ grn['remarks'] }}"><br><br>
|
|
||||||
|
|
||||||
<input type="submit" value="Update GRN">
|
|
||||||
</form>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Edit Purchase</title>
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h2>Edit Purchase Order</h2>
|
|
||||||
<form method="POST">
|
|
||||||
<label>Purchase Date:</label>
|
|
||||||
<input type="date" name="purchase_date" value="{{ purchase['purchase_date'] }}" required><br><br>
|
|
||||||
|
|
||||||
<label>Supplier Name:</label>
|
|
||||||
<input type="text" name="supplier_name" value="{{ purchase['supplier_name'] }}" required><br><br>
|
|
||||||
|
|
||||||
<label>Purchase Order No:</label>
|
|
||||||
<input type="text" name="purchase_order_no" value="{{ purchase['purchase_order_no'] }}" required><br><br>
|
|
||||||
|
|
||||||
<label>Item Name:</label>
|
|
||||||
<input type="text" name="item_name" value="{{ purchase['item_name'] }}" required><br><br>
|
|
||||||
|
|
||||||
<label>Quantity:</label>
|
|
||||||
<input type="number" name="quantity" value="{{ purchase['quantity'] }}" required><br><br>
|
|
||||||
|
|
||||||
<label>Unit:</label>
|
|
||||||
<input type="text" name="unit" value="{{ purchase['unit'] }}" required><br><br>
|
|
||||||
|
|
||||||
<label>Rate:</label>
|
|
||||||
<input type="number" step="0.01" name="rate" value="{{ purchase['rate'] }}" required><br><br>
|
|
||||||
|
|
||||||
<label>Amount:</label>
|
|
||||||
<input type="number" step="0.01" name="amount" value="{{ purchase['amount'] }}" required><br><br>
|
|
||||||
|
|
||||||
|
|
||||||
<label>GST Amount:</label>
|
|
||||||
<input type="text" name="GST_Amount" value="{{ purchase['GST_Amount'] }}" required><br><br>
|
|
||||||
|
|
||||||
<label>TDS:</label>
|
|
||||||
<input type="number" step="0.01" name="TDS" value="{{ purchase['TDS'] }}" required><br><br>
|
|
||||||
|
|
||||||
<label>Final Amount:</label>
|
|
||||||
<input type="number" step="0.01" name="final_amount" value="{{ purchase['final_amount'] }}" required><br><br>
|
|
||||||
|
|
||||||
<input type="submit" value="Update">
|
|
||||||
</form>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>GRN Management</title>
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h2>Add GRN</h2>
|
|
||||||
<form method="POST" action="/add_grn">
|
|
||||||
<label>GRN Date:</label>
|
|
||||||
<input type="date" name="grn_date" required><br><br>
|
|
||||||
|
|
||||||
<label>Purchase ID:</label>
|
|
||||||
<input type="number" name="purchase_id" required><br><br>
|
|
||||||
{# <label for="purchase_id">Purchase Order:</label>#}
|
|
||||||
{# <select name="purchase_id" id="purchase_id" required>#}
|
|
||||||
{# {% for order in purchase_orders %}#}
|
|
||||||
{# <option value="{{ order['purchase_id'] }}">{{ order['supplier_name'] }}</option>#}
|
|
||||||
{# {% endfor %}#}
|
|
||||||
{#</select>#}
|
|
||||||
|
|
||||||
<label>Supplier Name:</label>
|
|
||||||
<input type="text" name="supplier_name" required><br><br>
|
|
||||||
|
|
||||||
<label>Item Description:</label>
|
|
||||||
<input type="text" name="item_description" required><br><br>
|
|
||||||
|
|
||||||
<label>Received Quantity:</label>
|
|
||||||
<input type="number" name="received_quantity" required><br><br>
|
|
||||||
|
|
||||||
<label>Unit:</label>
|
|
||||||
<input type="text" name="unit" required><br><br>
|
|
||||||
|
|
||||||
<label>Rate:</label>
|
|
||||||
<input type="number" step="0.01" name="rate" required><br><br>
|
|
||||||
|
|
||||||
<label>Amount:</label>
|
|
||||||
<input type="number" step="0.01" name="amount" required><br><br>
|
|
||||||
|
|
||||||
<label>Remarks:</label>
|
|
||||||
<input type="text" name="remarks"><br><br>
|
|
||||||
|
|
||||||
<input type="submit" value="Add GRN">
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<h2>All GRNs</h2>
|
|
||||||
<table border="1">
|
|
||||||
<tr>
|
|
||||||
<th>ID</th><th>Date</th><th>Purchase ID</th><th>Supplier</th><th>Item</th>
|
|
||||||
<th>Qty</th><th>Unit</th><th>Rate</th><th>Amount</th><th>Remarks</th><th>Actions</th>
|
|
||||||
</tr>
|
|
||||||
{% for grn in grns %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ grn[0] }}</td>
|
|
||||||
<td>{{ grn[1] }}</td>
|
|
||||||
<td>{{ grn[2] }}</td>
|
|
||||||
<td>{{ grn[3] }}</td>
|
|
||||||
<td>{{ grn[4] }}</td>
|
|
||||||
<td>{{ grn[5] }}</td>
|
|
||||||
<td>{{ grn[6] }}</td>
|
|
||||||
<td>{{ grn[7] }}</td>
|
|
||||||
<td>{{ grn[8] }}</td>
|
|
||||||
<td>{{ grn[9] }}</td>
|
|
||||||
<td style="white-space: nowrap;">
|
|
||||||
<a href="/update_grn/{{ grn['grn_id'] }}" style="margin-right: 10px;">Edit</a>
|
|
||||||
|
|
||||||
<form action="/delete_grn/{{ grn[0] }}" method="POST" style="display:inline;">
|
|
||||||
<button type="submit" onclick="return confirm('Are you sure you want to delete this GRN?')" style="background:none;border:none;color:blue;cursor:pointer;text-decoration:underline;">
|
|
||||||
Delete
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
<a href="/logout">Logout</a>
|
<a href="/logout">Logout</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="sidebar">
|
<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">
|
<ul class="nav-menu">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<div class="user-section">
|
<div class="user-section">
|
||||||
<img src="{{ url_for('static', filename='images/icons/male_profile.jpg') }}" alt="User Avatar">
|
<img src="{{ url_for('static', filename='images/icons/male_profile.jpeg') }}" alt="User Avatar">
|
||||||
<div class="user-info">
|
<div class="user-info">
|
||||||
<span>admin</span>
|
<span>admin</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -133,30 +133,7 @@
|
|||||||
<h2>Hold Types</h2>
|
<h2>Hold Types</h2>
|
||||||
<a class="btn" href="/add_hold_type">Go ➜</a>
|
<a class="btn" href="/add_hold_type">Go ➜</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
|
||||||
<h2>Work Order</h2>
|
|
||||||
<!-- <a class="btn" href="/add_work_order">Go ➜</a> -->
|
|
||||||
<a class="btn">Go ➜</a>
|
|
||||||
</div>
|
|
||||||
<!-- <div class="card">
|
|
||||||
<h2>Purchase Order</h2>
|
|
||||||
<a class="btn" href="/add_purchase_order">Go ➜</a>
|
|
||||||
</div> -->
|
|
||||||
<!-- <div class="card">
|
|
||||||
<h2>Goods Receive Note</h2>
|
|
||||||
<a class="btn" href="/add_grn">Go ➜</a>
|
|
||||||
</div> -->
|
|
||||||
<!-- <div class="card">
|
|
||||||
<h2>Unreleased GST</h2>
|
|
||||||
<a class="btn" href="/unreleased_gst">Go ➜</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{# <div class="card">#}
|
|
||||||
{# <h2>Hold Release </h2>#}
|
|
||||||
{# <a class="btn" href="/add_hold_release">Go ➜</a>#}
|
|
||||||
{# </div>#}
|
|
||||||
|
|
||||||
</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
@@ -9,332 +8,334 @@
|
|||||||
<!-- <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/style.css') }}">-->
|
||||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/subcontractor_report.css') }}">
|
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/subcontractor_report.css') }}">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h2>PMC Report</h2>
|
<h2>PMC Report</h2>
|
||||||
|
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<h2>Contractor Details</h2>
|
<h2>Contractor Details</h2>
|
||||||
<div class="row2">
|
<div class="row2">
|
||||||
<div>
|
<div>
|
||||||
<label for="subcontractor">Subcontractor Name:</label>
|
<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="{{ info.Contractor_Name }}"
|
||||||
readonly/>
|
readonly />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="Address">Address :</label>
|
||||||
|
<textarea id="Address" name="Address" readonly>{{ info.Address }}</textarea>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="row3">
|
||||||
<label for="Address">Address :</label>
|
<div>
|
||||||
<textarea id="Address" name="Address" readonly>{{ info.Address }}</textarea>
|
<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>
|
||||||
</div>
|
<div class="row2">
|
||||||
<div class="row3">
|
<div>
|
||||||
<div>
|
<label for="GST_Registration_Type">GST Registration Type :</label>
|
||||||
<label for="PAN_No">PAN No :</label>
|
<input type="text" id="GST_Registration_Type" name="GST_Registration_Type"
|
||||||
<input type="text" id="PAN_No" name="PAN_No" value="{{ info.PAN_No }}" readonly/>
|
value="{{ info.GST_Registration_Type }}" 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>
|
||||||
|
<div>
|
||||||
|
<label for="GST_No">GST No:</label>
|
||||||
|
<input type="text" id="GST_No" name="GST_No" value="{{ info.GST_No }}" readonly />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<h2>PMC Report for PMC No: {{ info.PMC_No}}</h2>
|
||||||
<label for="GST_No">GST No:</label>
|
<div class="row3">
|
||||||
<input type="text" id="GST_No" name="GST_No" value="{{ info.GST_No }}" readonly/>
|
<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>
|
||||||
</div>
|
<div class="row2">
|
||||||
<h2>PMC Report for PMC No: {{ info.PMC_No}}</h2>
|
<div>
|
||||||
<div class="row3">
|
<label for="PMC_No">PMC No:</label>
|
||||||
<div>
|
<input type="text" id="PMC_No" name="PMC_No" value="{{ info.PMC_No }}" readonly />
|
||||||
<label for="State">State :</label>
|
</div>
|
||||||
<input type="text" id="State" name="State" value="{{ info.State_Name }}" readonly/>
|
<div>
|
||||||
</div>
|
<label for="Village_Name">Village Name :</label>
|
||||||
<div>
|
<input type="text" id="Village_Name" name="Village_Name"
|
||||||
<label for="District">District :</label>
|
value="{{ info.Village_Name.capitalize() }}" readonly />
|
||||||
<input type="text" id="District" name="District" value="{{ info.District_Name }}" readonly/>
|
</div>
|
||||||
</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<table class="total-table">
|
||||||
|
<tr>
|
||||||
|
<th colspan="2">Summary</th>
|
||||||
|
</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>
|
||||||
|
<th>
|
||||||
|
{% for hold in hold_types %}
|
||||||
|
{{ hold.hold_type }} ||
|
||||||
|
{% endfor %}
|
||||||
|
</th>
|
||||||
|
<td colspan="{{hold_types|length }}">{{total["sum_invo_hold_amt"]}}</td>
|
||||||
|
|
||||||
<h3>Invoice Details</h3>
|
</tr>
|
||||||
<table>
|
{% endif %}
|
||||||
<thead>
|
<tr>
|
||||||
<tr>
|
<th>Amount With TDS</th>
|
||||||
<th>PMC No</th>
|
<td>{{total["sum_invo_tds_amt"]}}</td>
|
||||||
<th>Village Name</th>
|
</tr>
|
||||||
<th>Work Type</th>
|
</table>
|
||||||
<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 -->
|
<h3>Invoice Details</h3>
|
||||||
{% set hold_types = invoices | map(attribute='hold_type') | reject('none') | unique | list %}
|
<table border="1" cellpadding="5" cellspacing="0">
|
||||||
{% for hold in hold_types %}
|
<thead>
|
||||||
<th>{{ hold }}</th>
|
<tr>
|
||||||
{% endfor %}
|
<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>
|
||||||
|
|
||||||
<th>GST SD (18%)</th>
|
<!-- Dynamic Hold Types -->
|
||||||
<th>Final Amount</th>
|
{% for ht in hold_types %}
|
||||||
</tr>
|
<th>{{ ht.hold_type }}</th>
|
||||||
</thead>
|
{% endfor %}
|
||||||
<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 -->
|
<th>GST SD (18%)</th>
|
||||||
{% for hold in hold_types %}
|
<th>Final Amount</th>
|
||||||
<td>
|
</tr>
|
||||||
{% if invoice.hold_type == hold %}
|
</thead>
|
||||||
{{ invoice.hold_amount }}
|
<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>
|
||||||
|
|
||||||
|
<!-- Hold Amounts -->
|
||||||
|
{% for ht in hold_types %}
|
||||||
|
<td>{{ hold_data.get(invoice.Invoice_Id, {}).get(ht.hold_type_id, 0) }}</td>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<td>{{ invoice.GST_SD_Amount }}</td>
|
||||||
|
<td>{{ invoice.Final_Amount }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<!-- Total Row -->
|
||||||
|
<tr>
|
||||||
|
<th colspan="6">Total</th>
|
||||||
|
<th>{{ total.sum_invo_basic_amt }}</th>
|
||||||
|
<th>{{ total.get('sum_invo_debit_amt', 0) }}</th>
|
||||||
|
<th>{{ total.get('sum_invo_after_debit_amt', 0) }}</th>
|
||||||
|
<th>{{ total.get('sum_invo_gst_amt', 0) }}</th>
|
||||||
|
<th>{{ total.get('sum_invo_amt', 0) }}</th>
|
||||||
|
<th>{{ total.get('sum_invo_tds_amt', 0) }}</th>
|
||||||
|
<th>{{ total.get('sum_invo_ds_amt', 0) }}</th>
|
||||||
|
<th>{{ total.get('sum_invo_on_commission', 0) }}</th>
|
||||||
|
<th>{{ total.get('sum_invo_hydro_test', 0) }}</th>
|
||||||
|
|
||||||
|
{% if hold_types %}
|
||||||
|
<th colspan="{{hold_types|length }}">{{ total.sum_invo_hold_amt}}</th>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<th>{{ total.get('sum_invo_gst_sd_amt', 0) }}</th>
|
||||||
|
<th>{{ total.sum_invo_final_amt }}</th>
|
||||||
|
</tr>
|
||||||
{% else %}
|
{% else %}
|
||||||
0
|
<tr>
|
||||||
|
<td colspan="{{ 17 + hold_types|length }}">No invoices found.</td>
|
||||||
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</tbody>
|
||||||
{% endfor %}
|
</table>
|
||||||
|
|
||||||
<td>{{ invoice.GST_SD_Amount }}</td>
|
<br>
|
||||||
<td>{{ invoice.Final_Amount }}</td>
|
<h3>GST Release Note Details</h3>
|
||||||
</tr>
|
|
||||||
|
|
||||||
{% endfor %}
|
<table>
|
||||||
<tr>
|
<thead>
|
||||||
<th colspan="6">Total</th>
|
<tr>
|
||||||
<th>{{total["sum_invo_basic_amt"]}}</th>
|
<th>PMC No</th>
|
||||||
<th>{{total["sum_invo_debit_amt"]}}</th>
|
<th>Invoice No</th>
|
||||||
<th>{{total["sum_invo_after_debit_amt"]}}</th>
|
<th>Basic Amount</th>
|
||||||
<th>{{total["sum_invo_gst_amt"]}}</th>
|
<th>Final Amount</th>
|
||||||
<th>{{total["sum_invo_amt"]}}</th>
|
<th>UTR</th>
|
||||||
<th>{{total["sum_invo_tds_amt"]}}</th>
|
</tr>
|
||||||
<th>{{total["sum_invo_ds_amt"]}}</th>
|
</thead>
|
||||||
<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>
|
|
||||||
|
|
||||||
{% else %}
|
<tbody>
|
||||||
<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>
|
{% if gst_rel %}
|
||||||
<h3>GST Release Note Details</h3>
|
{% for gst in gst_rel %}
|
||||||
<table>
|
<tr>
|
||||||
<thead>
|
<td>{{ gst.PMC_No }}</td>
|
||||||
<tr>
|
<td>{{ gst.invoice_no }}</td>
|
||||||
<th>PMC No</th>
|
<td>{{ gst.Basic_Amount }}</td>
|
||||||
<th>Invoice No</th>
|
<td>{{ gst.Final_Amount }}</td>
|
||||||
<th>Basic Amount</th>
|
<td>{{gst.UTR}}</td>
|
||||||
<th>Final Amount</th>
|
</TD>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
{% endfor %}
|
||||||
<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>
|
<tr>
|
||||||
<th>{{total["sum_gst_final_amt"]}}</th>
|
<th colspan="2">Total</th>
|
||||||
</tr>
|
|
||||||
{% else %}
|
|
||||||
<tr>
|
|
||||||
<td colspan="4">No GST release found.</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<tr>
|
<th>{{ total["sum_gst_basic_amt"] }}</th>
|
||||||
|
|
||||||
|
<th>{{ total["sum_gst_final_amt"] }}</th>
|
||||||
|
<th></th>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="5">No GST release found.</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<tr>
|
||||||
<h3>Credit Details</h3>
|
<h3>Credit Details</h3>
|
||||||
</tr>
|
</tr>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>PMC No</th>
|
<th>PMC No</th>
|
||||||
<th>Invoice Details</th>
|
<th>Invoice Details</th>
|
||||||
<th>Basic Amount</th>
|
<th>Basic Amount</th>
|
||||||
<th>Debit</th>
|
<th>Debit</th>
|
||||||
<th>After Debit Amt</th>
|
<th>After Debit Amt</th>
|
||||||
<th>GST Amount</th>
|
<th>GST Amount</th>
|
||||||
<th>Amount</th>
|
<th>Amount</th>
|
||||||
<th>Final Amount</th>
|
<th>Final Amount</th>
|
||||||
<th>Payment Amount</th>
|
<th>Payment Amount</th>
|
||||||
<th>Total Amount</th>
|
<th>Total Amount</th>
|
||||||
<th>UTR</th>
|
<th>UTR</th>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{% if credit_note %}
|
{% if credit_note %}
|
||||||
{% for credit in credit_note %}
|
{% for credit in credit_note %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ credit["PMC_No"] }}</td>
|
<td>{{ credit["PMC_No"] }}</td>
|
||||||
<td>{{ credit["Invoice_Details"] }}</td>
|
<td>{{ credit["Invoice_Details"] }}</td>
|
||||||
<td>{{ credit["Basic_Amount"] }}</td>
|
<td>{{ credit["Basic_Amount"] }}</td>
|
||||||
<td>{{ credit["Debit_Amount"] }}</td>
|
<td>{{ credit["Debit_Amount"] }}</td>
|
||||||
<td>{{ credit["After_Debit_Amount"] }}</td>
|
<td>{{ credit["After_Debit_Amount"] }}</td>
|
||||||
<td>{{ credit["GST_Amount"] }}</td>
|
<td>{{ credit["GST_Amount"] }}</td>
|
||||||
<td>{{ credit["Amount"] }}</td>
|
<td>{{ credit["Amount"] }}</td>
|
||||||
<td>{{ credit["Final_Amount"] }}</td>
|
<td>{{ credit["Final_Amount"] }}</td>
|
||||||
<td>{{ credit["Payment_Amount"] }}</td>
|
<td>{{ credit["Payment_Amount"] }}</td>
|
||||||
<td>{{ credit["Total_Amount"] }}</td>
|
<td>{{ credit["Total_Amount"] }}</td>
|
||||||
<td>{{ credit["UTR"] }}</td>
|
<td>{{ credit["UTR"] }}</td>
|
||||||
|
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="11">No Credit note found.</td>
|
<td colspan="11">No Credit note found.</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
</thead>
|
</thead>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<h3>Payment Details</h3>
|
<h3>Payment Details</h3>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>PMC No</th>
|
<th>PMC No</th>
|
||||||
<th>Invoice No</th>
|
<th>Invoice No</th>
|
||||||
<th>Amount</th>
|
<th>Amount</th>
|
||||||
<th>TDS Amount @ 1% on BASIC AMOUNT</th>
|
<th>TDS Amount @ 1% on BASIC AMOUNT</th>
|
||||||
<th>Total Amount Paid</th>
|
<th>Total Amount Paid</th>
|
||||||
<th>UTR</th>
|
<th>UTR</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% if payments %}
|
{% if payments %}
|
||||||
{% for pay in payments %}
|
{% for pay in payments %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ pay.pmc_no }}</td>
|
<td>{{ pay.pmc_no }}</td>
|
||||||
<td>{{ pay.invoice_no }}</td>
|
<td>{{ pay.invoice_no }}</td>
|
||||||
<td>{{ pay.Payment_Amount }}</td>
|
<td>{{ pay.Payment_Amount }}</td>
|
||||||
<td>{{ pay.TDS_Payment_Amount }}</td>
|
<td>{{ pay.TDS_Payment_Amount }}</td>
|
||||||
<td>{{ pay.Total_amount }}</td>
|
<td>{{ pay.Total_amount }}</td>
|
||||||
<td>{{ pay.UTR}}</td>
|
<td>{{ pay.UTR}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="2">Total</th>
|
<th colspan="2">Total</th>
|
||||||
<th>{{total["sum_pay_payment_amt"]}}</th>
|
<th>{{total["sum_pay_payment_amt"]}}</th>
|
||||||
<th>{{total["sum_pay_tds_payment_amt"]}}</th>
|
<th>{{total["sum_pay_tds_payment_amt"]}}</th>
|
||||||
<th>{{total["sum_pay_total_amt"]}}</th>
|
<th>{{total["sum_pay_total_amt"]}}</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="6">No payment found.</td>
|
<td colspan="6">No payment found.</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<a href="/download_pmc_report/{{ info.PMC_No}}">
|
<a href="/download_pmc_report/{{ info.PMC_No}}">
|
||||||
<button class="download-btn">Download PMC Report</button>
|
<button class="download-btn">Download PMC Report</button>
|
||||||
</a>
|
</a>
|
||||||
</body>
|
</body>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Purchase Order</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,205 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Purchase Order Report</title>
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/subcontractor_report.css') }}">
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
|
|
||||||
<style>
|
|
||||||
h2.report-title {
|
|
||||||
font-size: 28px;
|
|
||||||
color: #1a73e8;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 20px;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
.filter-section {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
gap: 20px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
label {
|
|
||||||
font-weight: bold;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
padding: 6px;
|
|
||||||
}
|
|
||||||
#downloadBtn, #searchBtn {
|
|
||||||
padding: 10px 20px;
|
|
||||||
background-color: #4CAF50;
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
border-radius: 6px;
|
|
||||||
cursor: pointer;
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
#downloadBtn:hover, #searchBtn:hover {
|
|
||||||
background-color: #45a049;
|
|
||||||
}
|
|
||||||
table {
|
|
||||||
margin: 0 auto;
|
|
||||||
margin-top: 30px;
|
|
||||||
border-collapse: collapse;
|
|
||||||
width: 95%;
|
|
||||||
}
|
|
||||||
th, td {
|
|
||||||
padding: 10px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h2 class="report-title">Purchase Order Report</h2>
|
|
||||||
|
|
||||||
<div class="filter-section">
|
|
||||||
<div>
|
|
||||||
<label for="supplier_name">Select Supplier Name:</label>
|
|
||||||
<select id="supplier_name" name="supplier_name" style="width: 300px;"></select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label for="purchase_order_no">Select Purchase Order Number:</label>
|
|
||||||
<select id="purchase_order_no" name="purchase_order_no" style="width: 300px;"></select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button id="searchBtn">Search</button>
|
|
||||||
<button id="downloadBtn" style="display: none;">Download Report</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table border="1" id="purchaseorderTable" style="display: none;">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Purchase ID</th>
|
|
||||||
<th>Purchase Date</th>
|
|
||||||
<th>Supplier Name</th>
|
|
||||||
<th>Purchase Order No</th>
|
|
||||||
<th>Item Name</th>
|
|
||||||
<th>Quantity</th>
|
|
||||||
<th>Unit</th>
|
|
||||||
<th>Rate</th>
|
|
||||||
<th>Amount</th>
|
|
||||||
<th>GST Amount</th>
|
|
||||||
<th>TDS</th>
|
|
||||||
<th>Final Amount</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody></tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<!-- JS Scripts -->
|
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
|
||||||
<script>
|
|
||||||
$(document).ready(function () {
|
|
||||||
// Initialize Select2 for supplier_name
|
|
||||||
$('#supplier_name').select2({
|
|
||||||
placeholder: 'Search Supplier Name',
|
|
||||||
ajax: {
|
|
||||||
url: '/get_supplier_names',
|
|
||||||
data: function (params) {
|
|
||||||
return { q: params.term };
|
|
||||||
},
|
|
||||||
processResults: function (data) {
|
|
||||||
return {
|
|
||||||
results: data.map(name => ({ id: name, text: name }))
|
|
||||||
};
|
|
||||||
},
|
|
||||||
delay: 250,
|
|
||||||
cache: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Initialize Select2 for purchase_order_no
|
|
||||||
$('#purchase_order_no').select2({
|
|
||||||
placeholder: 'Search Purchase Order No',
|
|
||||||
ajax: {
|
|
||||||
url: '/get_purchase_order_numbers',
|
|
||||||
data: function (params) {
|
|
||||||
return {
|
|
||||||
q: params.term,
|
|
||||||
supplier_name: $('#supplier_name').val()
|
|
||||||
};
|
|
||||||
},
|
|
||||||
processResults: function (data) {
|
|
||||||
return {
|
|
||||||
results: data.map(no => ({ id: no, text: no }))
|
|
||||||
};
|
|
||||||
},
|
|
||||||
delay: 250,
|
|
||||||
cache: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Search button click
|
|
||||||
$('#searchBtn').click(function () {
|
|
||||||
let supplier = $('#supplier_name').val();
|
|
||||||
let poNumber = $('#purchase_order_no').val();
|
|
||||||
|
|
||||||
if (!supplier && !poNumber) {
|
|
||||||
alert("Please select Supplier or Purchase Order No or both.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: '/get_purchase_order_data',
|
|
||||||
data: {
|
|
||||||
supplier_name: supplier,
|
|
||||||
purchase_order_no: poNumber
|
|
||||||
},
|
|
||||||
success: function (data) {
|
|
||||||
let tbody = $('#purchaseorderTable tbody');
|
|
||||||
tbody.empty();
|
|
||||||
|
|
||||||
if (data.length > 0) {
|
|
||||||
$('#purchaseorderTable').show();
|
|
||||||
$('#downloadBtn').show();
|
|
||||||
|
|
||||||
data.forEach(function (row) {
|
|
||||||
tbody.append(`
|
|
||||||
<tr>
|
|
||||||
<td>${row.purchase_id}</td>
|
|
||||||
<td>${row.purchase_date}</td>
|
|
||||||
<td>${row.supplier_name}</td>
|
|
||||||
<td>${row.purchase_order_no}</td>
|
|
||||||
<td>${row.item_name}</td>
|
|
||||||
<td>${row.quantity}</td>
|
|
||||||
<td>${row.unit}</td>
|
|
||||||
<td>${row.rate}</td>
|
|
||||||
<td>${row.amount}</td>
|
|
||||||
<td>${row.GST_Amount}</td>
|
|
||||||
<td>${row.TDS}</td>
|
|
||||||
<td>${row.final_amount}</td>
|
|
||||||
</tr>
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
alert("No matching purchase orders found.");
|
|
||||||
$('#purchaseorderTable').hide();
|
|
||||||
$('#downloadBtn').hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Download report
|
|
||||||
$('#downloadBtn').click(function () {
|
|
||||||
let supplier = $('#supplier_name').val();
|
|
||||||
let poNumber = $('#purchase_order_no').val();
|
|
||||||
|
|
||||||
if (!supplier && !poNumber) {
|
|
||||||
alert("Please select filters before downloading.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let url = '/download_purchase_order_report?';
|
|
||||||
if (supplier) url += 'supplier_name=' + encodeURIComponent(supplier);
|
|
||||||
if (poNumber) url += '&purchase_order_no=' + encodeURIComponent(poNumber);
|
|
||||||
|
|
||||||
window.location.href = url;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
|
|
||||||
<!-- Hidden fields for other necessary information -->
|
<!-- Hidden fields for other necessary information -->
|
||||||
<input type="text" name="subcontractor_data" value="{{ subcontractor_data['Contractor_Id'] }}">
|
<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="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="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="block_data" value="{{ block_data['Block_Id'] }}">
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
@@ -10,363 +8,341 @@
|
|||||||
<!-- <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/style.css') }}">-->
|
||||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/subcontractor_report.css') }}">
|
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/subcontractor_report.css') }}">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h2>Contractor Report</h2>
|
<h2>Contractor Report</h2>
|
||||||
|
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<h2>Contractor Details</h2>
|
<h2>Contractor Details</h2>
|
||||||
<div class="row2">
|
<div class="row2">
|
||||||
<div>
|
<div>
|
||||||
<label for="subcontractor">Subcontractor Name:</label>
|
<label for="subcontractor">Subcontractor Name:</label>
|
||||||
<input type="text" id="subcontractor" name="subcontractor" value="{{ contInfo.Contractor_Name }}"
|
<input type="text" id="subcontractor" name="subcontractor" value="{{ info.Contractor_Name }}"
|
||||||
readonly/>
|
readonly />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="Address">Address :</label>
|
||||||
|
<textarea id="Address" name="Address" readonly>{{ info.Address }}</textarea>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="row3">
|
||||||
<label for="Address">Address :</label>
|
<div>
|
||||||
<textarea id="Address" name="Address" readonly>{{ contInfo.Address }}</textarea>
|
<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>
|
||||||
|
<div>
|
||||||
|
<label for="GST_No">GST No:</label>
|
||||||
|
<input type="text" id="GST_No" name="GST_No" value="{{ info.GST_No }}" readonly />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
</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>
|
<h3>Total</h3>
|
||||||
<div>
|
<table class="total-table">
|
||||||
<label for="GST_No">GST No:</label>
|
<tr>
|
||||||
<input type="text" id="GST_No" name="GST_No" value="{{ contInfo.GST_No }}" readonly/>
|
<th colspan="2">Summary</th>
|
||||||
</div>
|
</tr>
|
||||||
</div>
|
<tr>
|
||||||
<div class="row3">
|
<th>Advance / Suplus</th>
|
||||||
<div>
|
<td>{{total["sum_invo_final_amt"]+total["sum_gst_final_amt"]-total["sum_pay_total_amt"]}}</td>
|
||||||
<label for="State">State :</label>
|
</tr>
|
||||||
<input type="text" id="State" name="State" value="{{ contInfo.State_Name }}" readonly/>
|
{% if hold_types %}
|
||||||
</div>
|
<tr>
|
||||||
<div>
|
<th>
|
||||||
<label for="District">District :</label>
|
{% for hold in hold_types %}
|
||||||
<input type="text" id="District" name="District" value="{{ contInfo.District_Name }}" readonly/>
|
{{ hold.hold_type }} ||
|
||||||
</div>
|
{% endfor %}
|
||||||
<div>
|
</th>
|
||||||
<label for="Block">Block :</label>
|
<td colspan="{{hold_types|length }}">{{total["sum_invo_hold_amt"]}}</td>
|
||||||
<input type="text" id="Block" name="Block" value="{{ contInfo.Block_Name }}" readonly/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h3>Total</h3>
|
</tr>
|
||||||
<table class="total-table">
|
{% endif %}
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="2">{{current_date}}</th>
|
<th>Amount With TDS</th>
|
||||||
</tr>
|
<td>{{total["sum_invo_tds_amt"]}}</td>
|
||||||
<!-- <tr>-->
|
</tr>
|
||||||
<!-- <th>Total Hold Amounnt</th>-->
|
</table>
|
||||||
<!-- <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 %}-->
|
<!-- {% if hold_types %}-->
|
||||||
<!-- <h3>Hold Types</h3>-->
|
<!-- <h3>Hold Types</h3>-->
|
||||||
<!-- <ul>-->
|
<!-- <ul>-->
|
||||||
<!-- {% for hold in hold_types %}-->
|
<!-- {% for hold in hold_types %}-->
|
||||||
<!-- <li>{{ hold.hold_type }}</li>-->
|
<!-- <li>{{ hold.hold_type }}</li>-->
|
||||||
<!-- {% endfor %}-->
|
<!-- {% endfor %}-->
|
||||||
<!-- </ul>-->
|
<!-- </ul>-->
|
||||||
<!-- {% endif %}-->
|
<!-- {% endif %}-->
|
||||||
|
|
||||||
|
|
||||||
<h3>Invoice Details</h3>
|
<h3>Invoice Details</h3>
|
||||||
<table>
|
<table border="1" cellpadding="5" cellspacing="0">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>PMC No</th>
|
<th>PMC No</th>
|
||||||
<th>Village Name</th>
|
<th>Village Name</th>
|
||||||
<th>Work Type</th>
|
<th>Work Type</th>
|
||||||
<th>Invoice Details</th>
|
<th>Invoice Details</th>
|
||||||
<th>Invoice Date</th>
|
<th>Invoice Date</th>
|
||||||
<th>Invoice No</th>
|
<th>Invoice No</th>
|
||||||
<th>Basic Amount</th>
|
<th>Basic Amount</th>
|
||||||
<th>Debit</th>
|
<th>Debit</th>
|
||||||
<th>After Debit Amt</th>
|
<th>After Debit Amt</th>
|
||||||
<th>GST (18%)</th>
|
<th>GST (18%)</th>
|
||||||
<th>Amount</th>
|
<th>Amount</th>
|
||||||
<th>TDS (1%)</th>
|
<th>TDS (1%)</th>
|
||||||
<th>SD (5%)</th>
|
<th>SD (5%)</th>
|
||||||
<th>On Commission</th>
|
<th>On Commission</th>
|
||||||
<th>Hydro Testing</th>
|
<th>Hydro Testing</th>
|
||||||
|
|
||||||
<!-- Dynamic Hold Types -->
|
<!-- Dynamic Hold Types -->
|
||||||
{% set hold_types = invoices | map(attribute='hold_type') | unique | list %}
|
{% for ht in hold_types %}
|
||||||
{% for hold in hold_types %}
|
<th>{{ ht.hold_type }}</th>
|
||||||
<th>{{ hold }}</th>
|
{% endfor %}
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<th>GST SD (18%)</th>
|
<th>GST SD (18%)</th>
|
||||||
<th>Final Amount</th>
|
<th>Final Amount</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% if invoices %}
|
{% if invoices %}
|
||||||
{% for invoice in invoices %}
|
{% for invoice in invoices %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ invoice.PMC_No }}</td>
|
<td>{{ invoice.PMC_No }}</td>
|
||||||
<td>{{ invoice.Village_Name.capitalize() }}</td>
|
<td>{{ invoice.Village_Name }}</td>
|
||||||
<td>{{ invoice.Work_Type }}</td>
|
<td>{{ invoice.Work_Type }}</td>
|
||||||
<td>{{ invoice.Invoice_Details }}</td>
|
<td>{{ invoice.Invoice_Details }}</td>
|
||||||
<td>{{ invoice.Invoice_Date }}</td>
|
<td>{{ invoice.Invoice_Date }}</td>
|
||||||
<td>{{ invoice.Invoice_No }}</td>
|
<td>{{ invoice.invoice_no }}</td>
|
||||||
<td>{{ invoice.Basic_Amount }}</td>
|
<td>{{ invoice.Basic_Amount }}</td>
|
||||||
<td>{{ invoice.Debit_Amount }}</td>
|
<td>{{ invoice.Debit_Amount }}</td>
|
||||||
<td>{{ invoice.After_Debit_Amount }}</td>
|
<td>{{ invoice.After_Debit_Amount }}</td>
|
||||||
<td>{{ invoice.GST_Amount }}</td>
|
<td>{{ invoice.GST_Amount }}</td>
|
||||||
<td>{{ invoice.Amount }}</td>
|
<td>{{ invoice.Amount }}</td>
|
||||||
<td>{{ invoice.TDS_Amount }}</td>
|
<td>{{ invoice.TDS_Amount }}</td>
|
||||||
<td>{{ invoice.SD_Amount }}</td>
|
<td>{{ invoice.SD_Amount }}</td>
|
||||||
<td>{{ invoice.On_Commission }}</td>
|
<td>{{ invoice.On_Commission }}</td>
|
||||||
<td>{{ invoice.Hydro_Testing }}</td>
|
<td>{{ invoice.Hydro_Testing }}</td>
|
||||||
|
|
||||||
<!-- Dynamic Hold Amounts -->
|
<!-- Hold Amounts -->
|
||||||
{% set hold_types = invoices | map(attribute='hold_type') | unique | list %}
|
{% for ht in hold_types %}
|
||||||
{% for hold in hold_types %}
|
<td>{{ hold_data.get(invoice.Invoice_Id, {}).get(ht.hold_type_id, 0) }}</td>
|
||||||
<td>
|
{% endfor %}
|
||||||
{% if invoice.hold_type == hold %}
|
|
||||||
{{ invoice.hold_amount }}
|
<td>{{ invoice.GST_SD_Amount }}</td>
|
||||||
|
<td>{{ invoice.Final_Amount }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<!-- Total Row -->
|
||||||
|
<tr>
|
||||||
|
<th colspan="6">Total</th>
|
||||||
|
<th>{{ total.sum_invo_basic_amt }}</th>
|
||||||
|
<th>{{ total.get('sum_invo_debit_amt', 0) }}</th>
|
||||||
|
<th>{{ total.get('sum_invo_after_debit_amt', 0) }}</th>
|
||||||
|
<th>{{ total.get('sum_invo_gst_amt', 0) }}</th>
|
||||||
|
<th>{{ total.get('sum_invo_amt', 0) }}</th>
|
||||||
|
<th>{{ total.get('sum_invo_tds_amt', 0) }}</th>
|
||||||
|
<th>{{ total.get('sum_invo_ds_amt', 0) }}</th>
|
||||||
|
<th>{{ total.get('sum_invo_on_commission', 0) }}</th>
|
||||||
|
<th>{{ total.get('sum_invo_hydro_test', 0) }}</th>
|
||||||
|
|
||||||
|
{% if hold_types %}
|
||||||
|
<th colspan="{{hold_types|length }}">{{ total.sum_invo_hold_amt}}</th>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<th>{{ total.get('sum_invo_gst_sd_amt', 0) }}</th>
|
||||||
|
<th>{{ total.sum_invo_final_amt }}</th>
|
||||||
|
</tr>
|
||||||
{% else %}
|
{% else %}
|
||||||
0.00
|
<tr>
|
||||||
|
<td colspan="{{ 17 + hold_types|length }}">No invoices found.</td>
|
||||||
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</tbody>
|
||||||
{% endfor %}
|
</table>
|
||||||
|
|
||||||
<td>{{ invoice.GST_SD_Amount }}</td>
|
<br>
|
||||||
<td>{{ invoice.Final_Amount }}</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="6">Total</th>
|
<h3>Credit Details</h3>
|
||||||
<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>
|
</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>
|
||||||
<tr>
|
|
||||||
<td colspan="{{ 17 + hold_types|length }}">No invoices found.</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<h3>Hold Release</h3>
|
{% if credit_note %}
|
||||||
<table>
|
{% for credit in credit_note %}
|
||||||
<thead>
|
<tr>
|
||||||
<tr>
|
<td>{{ credit["PMC_No"] }}</td>
|
||||||
<th>PMC No</th>
|
<td>{{ credit["Invoice_Details"] }}</td>
|
||||||
<th>Invoice No</th>
|
<td>{{ credit["Basic_Amount"] }}</td>
|
||||||
<th>Invoice Details</th>
|
<td>{{ credit["Debit_Amount"] }}</td>
|
||||||
<th>Basic Amount</th>
|
<td>{{ credit["After_Debit_Amount"] }}</td>
|
||||||
<th>Total Amount</th>
|
<td>{{ credit["GST_Amount"] }}</td>
|
||||||
<th>UTR</th>
|
<td>{{ credit["Amount"] }}</td>
|
||||||
</tr>
|
<td>{{ credit["Final_Amount"] }}</td>
|
||||||
</thead>
|
<td>{{ credit["Payment_Amount"] }}</td>
|
||||||
<tbody>
|
<td>{{ credit["Total_Amount"] }}</td>
|
||||||
{% if hold_release %}
|
<td>{{ credit["UTR"] }}</td>
|
||||||
{% 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>
|
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
</tr>
|
||||||
<h3>Credit Details</h3>
|
{% endfor %}
|
||||||
</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>
|
{% else %}
|
||||||
|
<tr>
|
||||||
{% if credit_note %}
|
<td colspan="11">No Credit note found.</td>
|
||||||
{% for credit in credit_note %}
|
</tr>
|
||||||
<tr>
|
{% endif %}
|
||||||
<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>
|
</thead>
|
||||||
{% endfor %}
|
</table>
|
||||||
|
<h3>GST Release Note Details</h3>
|
||||||
|
|
||||||
{% else %}
|
<table>
|
||||||
<tr>
|
<thead>
|
||||||
<td colspan="11">No Credit note found.</td>
|
<tr>
|
||||||
</tr>
|
<th>PMC No</th>
|
||||||
{% endif %}
|
<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>
|
||||||
|
</TD>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th colspan="2">Total</th>
|
||||||
|
|
||||||
|
<th>{{ total["sum_gst_basic_amt"] }}</th>
|
||||||
|
|
||||||
|
<th>{{ total["sum_gst_final_amt"] }}</th>
|
||||||
|
<th>{{total["sum_gst_total_amt"]}}</th>
|
||||||
|
<th></th>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="5">No GST release found.</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
</thead>
|
<br>
|
||||||
</table>
|
<h3>Payment Details</h3>
|
||||||
<h3>GST Release Note Details</h3>
|
<table>
|
||||||
<table>
|
<thead>
|
||||||
<thead>
|
<tr>
|
||||||
<tr>
|
<th>PMC No</th>
|
||||||
<th>PMC No</th>
|
<th>Invoice No</th>
|
||||||
<th>Invoice No</th>
|
<th>Amount</th>
|
||||||
<th>Basic Amount</th>
|
<th>TDS Amount @ 1% on BASIC AMOUNT</th>
|
||||||
<th>Final Amount</th>
|
<th>Total Amount Paid</th>
|
||||||
</tr>
|
<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>
|
||||||
|
|
||||||
|
|
||||||
</thead>
|
<a href="{{ url_for('report.download_report', contractor_id=contractor_id) }}" class="download-btn">Download
|
||||||
<tbody>
|
Report</a>
|
||||||
{% if gst_rel %}
|
</div>
|
||||||
{% 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>
|
|
||||||
|
|
||||||
|
|
||||||
<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>
|
|
||||||
</body>
|
</body>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,209 +0,0 @@
|
|||||||
{% extends 'base.html' %}
|
|
||||||
{% block content %}
|
|
||||||
<head>
|
|
||||||
<title>Work Order Report</title>
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/subcontractor_report.css') }}">
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
|
|
||||||
<style>
|
|
||||||
h2.report-title {
|
|
||||||
font-size: 28px;
|
|
||||||
color: #1a73e8;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 20px;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
.filter-section {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
gap: 20px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
label {
|
|
||||||
font-weight: bold;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
padding: 6px;
|
|
||||||
}
|
|
||||||
#downloadBtn, #searchBtn {
|
|
||||||
padding: 10px 20px;
|
|
||||||
background-color: #4CAF50;
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
border-radius: 6px;
|
|
||||||
cursor: pointer;
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
#downloadBtn:hover, #searchBtn:hover {
|
|
||||||
background-color: #45a049;
|
|
||||||
}
|
|
||||||
table {
|
|
||||||
margin: 0 auto;
|
|
||||||
margin-top: 30px;
|
|
||||||
border-collapse: collapse;
|
|
||||||
width: 95%;
|
|
||||||
}
|
|
||||||
th, td {
|
|
||||||
padding: 10px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h2 class="report-title">Work Order Report</h2>
|
|
||||||
|
|
||||||
<div class="filter-section">
|
|
||||||
<div>
|
|
||||||
<label for="vendor_name">Select Vendor Name:</label>
|
|
||||||
<select id="vendor_name" name="vendor_name" style="width: 300px;"></select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label for="work_order_number">Select Work Order Number:</label>
|
|
||||||
<select id="work_order_number" name="work_order_number" style="width: 300px;"></select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button id="searchBtn">Search</button>
|
|
||||||
<button id="downloadBtn" style="display: none;">Download Report</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table border="1" id="workOrderTable" style="display: none;">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>ID</th>
|
|
||||||
<th>Vendor Name</th>
|
|
||||||
<th>Work Order Type</th>
|
|
||||||
<th>Amount</th>
|
|
||||||
<th>BOQ</th>
|
|
||||||
<th>Done %</th>
|
|
||||||
<th>GST</th>
|
|
||||||
<th>TDS</th>
|
|
||||||
<th>Security Deposit</th>
|
|
||||||
<th>SD GST</th>
|
|
||||||
<th>Final Total</th>
|
|
||||||
<th>TDS of GST</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody></tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<!-- JS Scripts -->
|
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
|
||||||
<script>
|
|
||||||
$(document).ready(function () {
|
|
||||||
$('#vendor_name, #work_order_number').select2({
|
|
||||||
placeholder: 'Search',
|
|
||||||
minimumInputLength: 1,
|
|
||||||
ajax: {
|
|
||||||
delay: 250,
|
|
||||||
dataType: 'json',
|
|
||||||
cache: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#vendor_name').select2({
|
|
||||||
placeholder: 'Search Vendor',
|
|
||||||
ajax: {
|
|
||||||
url: '/get_vendor_names',
|
|
||||||
data: function (params) {
|
|
||||||
return { q: params.term };
|
|
||||||
},
|
|
||||||
processResults: function (data) {
|
|
||||||
return {
|
|
||||||
results: data.map(v => ({ id: v, text: v }))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#work_order_number').select2({
|
|
||||||
placeholder: 'Search Work Order',
|
|
||||||
ajax: {
|
|
||||||
url: '/get_work_order_numbers',
|
|
||||||
data: function (params) {
|
|
||||||
return {
|
|
||||||
q: params.term,
|
|
||||||
vendor_name: $('#vendor_name').val()
|
|
||||||
};
|
|
||||||
},
|
|
||||||
processResults: function (data) {
|
|
||||||
return {
|
|
||||||
results: data.map(o => ({ id: o, text: o }))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Fetch and display table
|
|
||||||
$('#searchBtn').click(function () {
|
|
||||||
let vendor = $('#vendor_name').val();
|
|
||||||
let order = $('#work_order_number').val();
|
|
||||||
|
|
||||||
if (!vendor && !order) {
|
|
||||||
alert("Please select Vendor or Work Order Number or both.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: '/get_work_order_data',
|
|
||||||
data: {
|
|
||||||
vendor_name: vendor,
|
|
||||||
work_order_number: order
|
|
||||||
},
|
|
||||||
success: function (data) {
|
|
||||||
let tbody = $('#workOrderTable tbody');
|
|
||||||
tbody.empty();
|
|
||||||
|
|
||||||
if (data.length > 0) {
|
|
||||||
$('#workOrderTable').show();
|
|
||||||
$('#downloadBtn').show();
|
|
||||||
|
|
||||||
data.forEach(function (row) {
|
|
||||||
tbody.append(`
|
|
||||||
<tr>
|
|
||||||
<td>${row.work_order_id}</td>
|
|
||||||
<td>${row.vendor_name}</td>
|
|
||||||
<td>${row.work_order_type}</td>
|
|
||||||
<td>${row.work_order_amount}</td>
|
|
||||||
<td>${row.boq_amount}</td>
|
|
||||||
<td>${row.work_done_percentage}</td>
|
|
||||||
<td>${row.gst_amount}</td>
|
|
||||||
<td>${row.tds_amount}</td>
|
|
||||||
<td>${row.security_deposit}</td>
|
|
||||||
<td>${row.sd_against_gst}</td>
|
|
||||||
<td>${row.final_total}</td>
|
|
||||||
<td>${row.tds_of_gst}</td>
|
|
||||||
</tr>
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
alert("No data found for selected filters.");
|
|
||||||
$('#workOrderTable').hide();
|
|
||||||
$('#downloadBtn').hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Download report
|
|
||||||
$('#downloadBtn').click(function () {
|
|
||||||
let vendor = $('#vendor_name').val();
|
|
||||||
let order = $('#work_order_number').val();
|
|
||||||
|
|
||||||
if (!vendor && !order) {
|
|
||||||
alert("Please select filters before downloading.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let url = '/download_work_order_report?';
|
|
||||||
if (vendor) url += 'vendor_name=' + encodeURIComponent(vendor);
|
|
||||||
if (order) url += '&work_order_number=' + encodeURIComponent(order);
|
|
||||||
|
|
||||||
window.location.href = url;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,482 +0,0 @@
|
|||||||
|
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/add_purchase_order', methods=['GET', 'POST'])
|
|
||||||
def add_purchase_order():
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
|
||||||
# Fetch form fields
|
|
||||||
purchase_date = request.form.get('purchase_date')
|
|
||||||
supplier_name = request.form.get('supplier_name')
|
|
||||||
purchase_order_no = request.form.get('purchase_order_no')
|
|
||||||
item_name = request.form.get('item_name')
|
|
||||||
quantity = request.form.get('quantity')
|
|
||||||
unit = request.form.get('unit')
|
|
||||||
rate = request.form.get('rate')
|
|
||||||
amount = request.form.get('amount')
|
|
||||||
GST_Amount = request.form.get('GST_Amount')
|
|
||||||
TDS = request.form.get('TDS')
|
|
||||||
final_amount = request.form.get('final_amount')
|
|
||||||
LogHelper.log_action("Add purchase order", f"User {current_user.id} Added puirchase Order'{ purchase_order_no}'")
|
|
||||||
# Insert into database
|
|
||||||
insert_query = """
|
|
||||||
INSERT INTO purchase_order (
|
|
||||||
purchase_date, supplier_name, purchase_order_no, item_name, quantity, unit, rate, amount,
|
|
||||||
GST_Amount, TDS, final_amount
|
|
||||||
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
|
||||||
"""
|
|
||||||
cursor.execute(insert_query, (
|
|
||||||
purchase_date, supplier_name, purchase_order_no, item_name, quantity, unit, rate, amount,
|
|
||||||
GST_Amount, TDS, final_amount
|
|
||||||
))
|
|
||||||
connection.commit()
|
|
||||||
|
|
||||||
# ✅ Always fetch updated data
|
|
||||||
cursor.execute("SELECT * FROM purchase_order")
|
|
||||||
purchases = cursor.fetchall()
|
|
||||||
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
return render_template('add_purchase_order.html', purchases=purchases)
|
|
||||||
|
|
||||||
|
|
||||||
# Show all purchases
|
|
||||||
@app.route('/purchase_orders')
|
|
||||||
def show_purchase_orders():
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
cursor.execute("SELECT * FROM purchase_order")
|
|
||||||
purchases = cursor.fetchall()
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return render_template('add_purchase_order.html', purchases=purchases)
|
|
||||||
|
|
||||||
|
|
||||||
# Delete purchase order
|
|
||||||
@app.route('/delete_purchase/<int:id>', methods=['POST'])
|
|
||||||
def delete_purchase(id):
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor()
|
|
||||||
cursor.execute("DELETE FROM purchase_order WHERE purchase_id = %s", (id,))
|
|
||||||
connection.commit()
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
LogHelper.log_action("Delete purchase order", f"User {current_user.id} Deleted puirchase Order'{ id}'")
|
|
||||||
return render_template(('add_purchase_order.html'))
|
|
||||||
|
|
||||||
|
|
||||||
# Edit purchase order (form + update logic)
|
|
||||||
@app.route('/update_purchase/<int:id>', methods=['GET', 'POST'])
|
|
||||||
def update_purchase(id):
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
|
||||||
# ✅ Form submitted - update all fields
|
|
||||||
data = request.form
|
|
||||||
cursor.execute("""
|
|
||||||
UPDATE purchase_order
|
|
||||||
SET purchase_date = %s,
|
|
||||||
supplier_name = %s,
|
|
||||||
purchase_order_no = %s,
|
|
||||||
item_name = %s,
|
|
||||||
quantity = %s,
|
|
||||||
unit = %s,
|
|
||||||
rate = %s,
|
|
||||||
amount = %s,
|
|
||||||
GST_Amount = %s,
|
|
||||||
TDS = %s,
|
|
||||||
final_amount = %s
|
|
||||||
WHERE purchase_id = %s
|
|
||||||
""", (
|
|
||||||
data['purchase_date'], data['supplier_name'], data['purchase_order_no'], data['item_name'],
|
|
||||||
data['quantity'],
|
|
||||||
data['unit'], data['rate'], data['amount'], data['GST_Amount'], data['TDS'], data['final_amount'],
|
|
||||||
id
|
|
||||||
))
|
|
||||||
connection.commit()
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
LogHelper.log_action("Delete purchase order", f"User {current_user.id} Deleted puirchase Order'{ id}'")
|
|
||||||
return redirect(url_for('show_purchase_orders'))
|
|
||||||
|
|
||||||
# Show edit form
|
|
||||||
cursor.execute("SELECT * FROM purchase_order WHERE purchase_id = %s", (id,))
|
|
||||||
purchase = cursor.fetchone()
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return render_template('edit_purchase.html', purchase=purchase)
|
|
||||||
|
|
||||||
|
|
||||||
# SHOW all GRNs + ADD form
|
|
||||||
@app.route('/grn', methods=['GET'])
|
|
||||||
def grn_page():
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
# Fetch purchase orders for dropdown
|
|
||||||
cursor.execute("SELECT purchase_id, supplier_name FROM purchase_order")
|
|
||||||
purchase_orders = cursor.fetchall()
|
|
||||||
|
|
||||||
# Fetch all GRNs to display
|
|
||||||
cursor.execute("SELECT * FROM goods_receive_note")
|
|
||||||
grns = cursor.fetchall()
|
|
||||||
print(grns)
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
# Render the template with both datasets
|
|
||||||
return render_template('grn_form.html', purchase_orders=purchase_orders, grns=grns)
|
|
||||||
|
|
||||||
|
|
||||||
# ADD new GRN
|
|
||||||
@app.route('/add_grn', methods=['POST', 'GET'])
|
|
||||||
def add_grn():
|
|
||||||
data = request.form
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor()
|
|
||||||
query = """
|
|
||||||
INSERT INTO goods_receive_note
|
|
||||||
(grn_date, purchase_id, supplier_name, item_description, received_quantity, unit, rate, amount, remarks)
|
|
||||||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s) \
|
|
||||||
"""
|
|
||||||
cursor.execute(query, (
|
|
||||||
data.get('grn_date'),
|
|
||||||
data.get('purchase_id'),
|
|
||||||
data.get('supplier_name'),
|
|
||||||
data.get('item_description'),
|
|
||||||
data.get('received_quantity'),
|
|
||||||
data.get('unit'),
|
|
||||||
data.get('rate'),
|
|
||||||
data.get('amount'),
|
|
||||||
data.get('remarks')
|
|
||||||
))
|
|
||||||
connection.commit()
|
|
||||||
|
|
||||||
cursor.execute("SELECT * FROM goods_receive_note")
|
|
||||||
grns = cursor.fetchall()
|
|
||||||
print(grns)
|
|
||||||
query = "select * from purchase_order"
|
|
||||||
cursor.execute(query)
|
|
||||||
purchase_orders = cursor.fetchall()
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return render_template('grn_form.html', purchase_orders=purchase_orders, grns=grns)
|
|
||||||
|
|
||||||
|
|
||||||
# UPDATE GRN
|
|
||||||
@app.route('/update_grn/<int:grn_id>', methods=['GET', 'POST'])
|
|
||||||
def update_grn(grn_id):
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
|
||||||
data = request.form
|
|
||||||
query = """
|
|
||||||
UPDATE goods_receive_note
|
|
||||||
SET grn_date=%s, purchase_id=%s, supplier_name=%s, item_description=%s,
|
|
||||||
received_quantity=%s, unit=%s, rate=%s, amount=%s, remarks=%s
|
|
||||||
WHERE grn_id=%s
|
|
||||||
"""
|
|
||||||
cursor.execute(query, (
|
|
||||||
data['grn_date'], data['purchase_id'], data['supplier_name'],
|
|
||||||
data['item_description'], data['received_quantity'], data['unit'],
|
|
||||||
data['rate'], data['amount'], data['remarks'], grn_id
|
|
||||||
))
|
|
||||||
connection.commit()
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return redirect(url_for('grns'))
|
|
||||||
|
|
||||||
cursor.execute("SELECT * FROM goods_receive_note WHERE grn_id = %s", (grn_id,))
|
|
||||||
grn = cursor.fetchone()
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return render_template("edit_grn.html", grn=grn)
|
|
||||||
|
|
||||||
|
|
||||||
# DELETE GRN
|
|
||||||
@app.route('/delete_grn/<int:grn_id>', methods=['POST'])
|
|
||||||
def delete_grn(grn_id):
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor()
|
|
||||||
cursor.execute("DELETE FROM goods_receive_note WHERE grn_id = %s", (grn_id,))
|
|
||||||
connection.commit()
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return render_template("grn_form.html")
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/work_order_report', methods=['GET'])
|
|
||||||
def work_order_report():
|
|
||||||
return render_template('work_order_report.html')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ✅ Vendor Name Search (for Select2)
|
|
||||||
@app.route('/get_vendor_names')
|
|
||||||
def get_vendor_names():
|
|
||||||
query = request.args.get('q', '')
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor()
|
|
||||||
cursor.execute("SELECT DISTINCT vendor_name FROM work_order WHERE vendor_name LIKE %s", (f"%{query}%",))
|
|
||||||
vendors = [row[0] for row in cursor.fetchall()]
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return jsonify(vendors)
|
|
||||||
|
|
||||||
|
|
||||||
# ✅ Work Order Number Search (with or without vendor)
|
|
||||||
@app.route('/get_work_order_numbers')
|
|
||||||
def get_work_order_numbers():
|
|
||||||
vendor = request.args.get('vendor_name', '')
|
|
||||||
query = request.args.get('q', '')
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor()
|
|
||||||
|
|
||||||
if vendor:
|
|
||||||
cursor.execute(
|
|
||||||
"SELECT DISTINCT work_order_number FROM work_order WHERE vendor_name = %s AND work_order_number LIKE %s",
|
|
||||||
(vendor, f"%{query}%"))
|
|
||||||
else:
|
|
||||||
cursor.execute("SELECT DISTINCT work_order_number FROM work_order WHERE work_order_number LIKE %s",
|
|
||||||
(f"%{query}%",))
|
|
||||||
|
|
||||||
orders = [row[0] for row in cursor.fetchall()]
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return jsonify(orders)
|
|
||||||
|
|
||||||
|
|
||||||
# ✅ Get Work Order Data (Filtered)
|
|
||||||
@app.route('/get_work_order_data')
|
|
||||||
def get_work_order_data():
|
|
||||||
vendor = request.args.get('vendor_name')
|
|
||||||
order_number = request.args.get('work_order_number')
|
|
||||||
|
|
||||||
query = "SELECT * FROM work_order WHERE 1=1"
|
|
||||||
params = []
|
|
||||||
|
|
||||||
if vendor:
|
|
||||||
query += " AND vendor_name = %s"
|
|
||||||
params.append(vendor)
|
|
||||||
if order_number:
|
|
||||||
query += " AND work_order_number = %s"
|
|
||||||
params.append(order_number)
|
|
||||||
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
cursor.execute(query, tuple(params))
|
|
||||||
data = cursor.fetchall()
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return jsonify(data)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/download_work_order_report')
|
|
||||||
def download_work_order_report():
|
|
||||||
vendor_name = request.args.get('vendor_name')
|
|
||||||
work_order_number = request.args.get('work_order_number')
|
|
||||||
|
|
||||||
if work_order_number == "null":
|
|
||||||
work_order_number = None
|
|
||||||
|
|
||||||
query = "SELECT * FROM work_order WHERE 1=1"
|
|
||||||
params = []
|
|
||||||
|
|
||||||
if vendor_name:
|
|
||||||
query += " AND vendor_name = %s"
|
|
||||||
params.append(vendor_name)
|
|
||||||
if work_order_number:
|
|
||||||
query += " AND work_order_number = %s"
|
|
||||||
params.append(work_order_number)
|
|
||||||
|
|
||||||
conn = config.get_db_connection()
|
|
||||||
cursor = conn.cursor(dictionary=True)
|
|
||||||
cursor.execute(query, tuple(params))
|
|
||||||
data = cursor.fetchall()
|
|
||||||
cursor.close()
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
if not data:
|
|
||||||
return "No data found for the selected filters", 404
|
|
||||||
|
|
||||||
# Convert to DataFrame
|
|
||||||
df = pd.DataFrame(data)
|
|
||||||
|
|
||||||
output_path = 'static/downloads/work_order_report.xlsx'
|
|
||||||
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
|
||||||
df.to_excel(output_path, index=False, startrow=2) # Leave space for heading
|
|
||||||
|
|
||||||
# Load workbook for styling
|
|
||||||
wb = load_workbook(output_path)
|
|
||||||
ws = wb.active
|
|
||||||
|
|
||||||
# Add a merged title
|
|
||||||
title = "Work Order Report"
|
|
||||||
ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=len(df.columns))
|
|
||||||
title_cell = ws.cell(row=1, column=1)
|
|
||||||
title_cell.value = title
|
|
||||||
title_cell.font = Font(size=14, bold=True, color="1F4E78")
|
|
||||||
title_cell.alignment = Alignment(horizontal="center", vertical="center")
|
|
||||||
|
|
||||||
# Style header row (row 3 because data starts from row 3)
|
|
||||||
header_font = Font(bold=True)
|
|
||||||
for col_num, column_name in enumerate(df.columns, 1):
|
|
||||||
cell = ws.cell(row=3, column=col_num)
|
|
||||||
cell.font = header_font
|
|
||||||
cell.alignment = Alignment(horizontal="center", vertical="center")
|
|
||||||
# Optional: adjust column width
|
|
||||||
max_length = max(len(str(column_name)), 12)
|
|
||||||
ws.column_dimensions[get_column_letter(col_num)].width = max_length + 2
|
|
||||||
|
|
||||||
wb.save(output_path)
|
|
||||||
return send_file(output_path, as_attachment=True)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/purchase_order_report', methods=['GET'])
|
|
||||||
def purchase_order_report():
|
|
||||||
return render_template('purchase_order_report.html')
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/get_supplier_names')
|
|
||||||
def get_supplier_names():
|
|
||||||
query = request.args.get('q', '') # Get the search term from Select2
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor()
|
|
||||||
|
|
||||||
# Fetch distinct supplier names that match the search query
|
|
||||||
cursor.execute(
|
|
||||||
"SELECT supplier_name FROM purchase_order WHERE supplier_name LIKE %s",
|
|
||||||
(f"%{query}%",)
|
|
||||||
)
|
|
||||||
suppliers = [row[0] for row in cursor.fetchall()]
|
|
||||||
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return jsonify(suppliers)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/get_purchase_order_numbers')
|
|
||||||
def get_purchase_order_numbers():
|
|
||||||
supplier = request.args.get('supplier_name', '')
|
|
||||||
query = request.args.get('q', '')
|
|
||||||
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor()
|
|
||||||
|
|
||||||
if supplier:
|
|
||||||
cursor.execute("""
|
|
||||||
SELECT purchase_order_no
|
|
||||||
FROM purchase_order
|
|
||||||
WHERE supplier_name = %s AND purchase_order_no LIKE %s
|
|
||||||
""", (supplier, f"%{query}%"))
|
|
||||||
else:
|
|
||||||
cursor.execute("""
|
|
||||||
SELECT purchase_order_no
|
|
||||||
FROM purchase_order
|
|
||||||
WHERE purchase_order_no LIKE %s
|
|
||||||
""", (f"%{query}%",))
|
|
||||||
|
|
||||||
orders = [row[0] for row in cursor.fetchall()]
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return jsonify(orders)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/get_purchase_order_data')
|
|
||||||
def get_purchase_order_data():
|
|
||||||
supplier = request.args.get('supplier_name')
|
|
||||||
order_no = request.args.get('purchase_order_no')
|
|
||||||
|
|
||||||
query = "SELECT * FROM purchase_order WHERE 1=1"
|
|
||||||
params = []
|
|
||||||
|
|
||||||
if supplier:
|
|
||||||
query += " AND supplier_name = %s"
|
|
||||||
params.append(supplier)
|
|
||||||
if order_no:
|
|
||||||
query += " AND purchase_order_no = %s"
|
|
||||||
params.append(order_no)
|
|
||||||
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
cursor.execute(query, tuple(params))
|
|
||||||
data = cursor.fetchall()
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return jsonify(data)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/download_purchase_order_report')
|
|
||||||
def download_purchase_order_report():
|
|
||||||
supplier_name = request.args.get('supplier_name')
|
|
||||||
purchase_order_no = request.args.get('purchase_order_no')
|
|
||||||
|
|
||||||
if purchase_order_no == "null":
|
|
||||||
purchase_order_no = None
|
|
||||||
LogHelper.log_action("Download purchase order", f"User {current_user.id} Download puirchase Order'{ purchase_order_no}'")
|
|
||||||
query = "SELECT * FROM purchase_order WHERE 1=1"
|
|
||||||
params = []
|
|
||||||
|
|
||||||
if supplier_name:
|
|
||||||
query += " AND supplier_name = %s"
|
|
||||||
params.append(supplier_name)
|
|
||||||
if purchase_order_no:
|
|
||||||
query += " AND purchase_order_no = %s"
|
|
||||||
params.append(purchase_order_no)
|
|
||||||
|
|
||||||
conn = config.get_db_connection()
|
|
||||||
cursor = conn.cursor(dictionary=True)
|
|
||||||
cursor.execute(query, tuple(params))
|
|
||||||
data = cursor.fetchall()
|
|
||||||
cursor.close()
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
if not data:
|
|
||||||
return "No data found for the selected filters", 404
|
|
||||||
|
|
||||||
# Convert to DataFrame
|
|
||||||
df = pd.DataFrame(data)
|
|
||||||
|
|
||||||
output_path = 'static/downloads/purchase_order_report.xlsx'
|
|
||||||
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
|
||||||
|
|
||||||
df.to_excel(output_path, index=False, startrow=2) # Reserve space for heading
|
|
||||||
|
|
||||||
# Load workbook for styling
|
|
||||||
wb = load_workbook(output_path)
|
|
||||||
ws = wb.active
|
|
||||||
|
|
||||||
# Add a merged title
|
|
||||||
title = "Purchase Order Report"
|
|
||||||
ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=len(df.columns))
|
|
||||||
title_cell = ws.cell(row=1, column=1)
|
|
||||||
title_cell.value = title
|
|
||||||
title_cell.font = Font(size=14, bold=True, color="1F4E78")
|
|
||||||
title_cell.alignment = Alignment(horizontal="center", vertical="center")
|
|
||||||
|
|
||||||
# Style header row (row 3 because data starts from row 3)
|
|
||||||
header_font = Font(bold=True)
|
|
||||||
for col_num, column_name in enumerate(df.columns, 1):
|
|
||||||
cell = ws.cell(row=3, column=col_num)
|
|
||||||
cell.font = header_font
|
|
||||||
cell.alignment = Alignment(horizontal="center", vertical="center")
|
|
||||||
max_length = max(len(str(column_name)), 12)
|
|
||||||
ws.column_dimensions[get_column_letter(col_num)].width = max_length + 2
|
|
||||||
|
|
||||||
wb.save(output_path)
|
|
||||||
return send_file(output_path, as_attachment=True)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
app.run(host='0.0.0.0', port=5000, debug=True)
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
# -- end hold types controlller --------------------
|
|
||||||
|
|
||||||
# Route to display the HTML form
|
|
||||||
@app.route('/add_work_order', methods=['GET'])
|
|
||||||
def add_work_order():
|
|
||||||
# Add database connection
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
cursor.execute("SELECT Contractor_id, Contractor_Name FROM subcontractors") # Adjust table/column names as needed
|
|
||||||
subcontractor = cursor.fetchall()
|
|
||||||
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
return render_template('add_work_order.html', subcontractor=subcontractor) # This is your HTML form page
|
|
||||||
|
|
||||||
|
|
||||||
# Route to handle form submission (from action="/submit_work_order")
|
|
||||||
@app.route('/submit_work_order', methods=['POST', 'GET'])
|
|
||||||
def submit_work_order():
|
|
||||||
vendor_name = request.form['vendor_name']
|
|
||||||
work_order_type = request.form['work_order_type']
|
|
||||||
work_order_amount = request.form['work_order_amount']
|
|
||||||
boq_amount = request.form['boq_amount']
|
|
||||||
work_done_percentage = request.form['work_done_percentage']
|
|
||||||
work_order_number = request.form['work_order_number']
|
|
||||||
gst_amount = request.form['gst_amount']
|
|
||||||
tds_amount = request.form['tds_amount']
|
|
||||||
security_deposite = request.form['security_deposite']
|
|
||||||
sd_against_gst = request.form['sd_against_gst']
|
|
||||||
final_total = request.form['final_total']
|
|
||||||
tds_of_gst = request.form['tds_of_gst']
|
|
||||||
LogHelper.log_action("Submit Work Order", f"User {current_user.id} Submit Work Order'{ work_order_type}'")
|
|
||||||
# print("Good Morning How are U")
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
# print("Good morning and how are you")
|
|
||||||
insert_query = """
|
|
||||||
INSERT INTO work_order
|
|
||||||
(vendor_name, work_order_type, work_order_amount, boq_amount, work_done_percentage,work_order_number,gst_amount,tds_amount
|
|
||||||
,security_deposit,sd_against_gst,final_total,tds_of_gst)
|
|
||||||
VALUES (%s, %s, %s, %s, %s,%s,%s,%s,%s,%s,%s,%s)
|
|
||||||
"""
|
|
||||||
cursor.execute(insert_query,
|
|
||||||
(vendor_name, work_order_type, work_order_amount, boq_amount, work_done_percentage, work_order_number
|
|
||||||
, gst_amount, tds_amount, security_deposite, sd_against_gst, final_total, tds_of_gst))
|
|
||||||
connection.commit()
|
|
||||||
|
|
||||||
# ✅ Fetch all data after insert
|
|
||||||
select_query = "SELECT * FROM work_order"
|
|
||||||
cursor.execute(select_query)
|
|
||||||
wo = cursor.fetchall()
|
|
||||||
# print("The Work order data is ",wo)
|
|
||||||
print("The data from work order ", wo) # should now print the data properly
|
|
||||||
cursor.execute("SELECT Contractor_id, Contractor_Name FROM subcontractors") # Adjust table/column names as needed
|
|
||||||
subcontractor = cursor.fetchall()
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
return render_template('add_work_order.html', work_order_type=work_order_type, wo=wo, subcontractor=subcontractor)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/delete_work_order/<int:id>', methods=['POST'])
|
|
||||||
def delete_work_order(id):
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor()
|
|
||||||
cursor.execute("DELETE FROM work_order WHERE work_order_id = %s", (id,))
|
|
||||||
connection.commit()
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
LogHelper.log_action("delete Work Order", f"User {current_user.id} delete Work Order'{ id}'")
|
|
||||||
return jsonify({'success': True})
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/update_work_order/<int:id>', methods=['GET', 'POST'])
|
|
||||||
def update_work_order(id):
|
|
||||||
connection = config.get_db_connection()
|
|
||||||
cursor = connection.cursor(dictionary=True)
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
|
||||||
work_order_type = request.form['work_order_type']
|
|
||||||
work_order_amount = request.form['work_order_amount']
|
|
||||||
boq_amount = request.form['boq_amount']
|
|
||||||
work_done_percentage = request.form['work_done_percentage']
|
|
||||||
work_order_number = request.form['work_order_number']
|
|
||||||
gst_amount = request.form['gst_amount']
|
|
||||||
tds_amount = request.form['tds_amount']
|
|
||||||
security_deposite = request.form['security_deposite']
|
|
||||||
sd_against_gst = request.form['sd_against_gst']
|
|
||||||
final_amount = request.form['final_amount']
|
|
||||||
tds_of_gst = request.form['tds_of_gst']
|
|
||||||
update_query = """
|
|
||||||
UPDATE work_order
|
|
||||||
SET work_order_type = %s,
|
|
||||||
work_order_amount = %s,
|
|
||||||
boq_amount = %s,
|
|
||||||
work_done_percentage = %s,
|
|
||||||
work_order_number= %s,
|
|
||||||
gst_amount = %s,
|
|
||||||
tds_amount= %s,
|
|
||||||
security_deposite= %s,
|
|
||||||
sd_against_gst=%s,
|
|
||||||
final_amount= %s,
|
|
||||||
tds_of_gst=%s
|
|
||||||
WHERE work_order_id = %s
|
|
||||||
"""
|
|
||||||
cursor.execute(update_query, (
|
|
||||||
work_order_type, work_order_amount, boq_amount, work_done_percentage, work_order_number, gst_amount,
|
|
||||||
tds_amount, security_deposite, sd_against_gst, final_amount, tds_of_gst, id))
|
|
||||||
connection.commit()
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
|
|
||||||
# If GET request: fetch the existing record
|
|
||||||
cursor.execute("SELECT * FROM work_order WHERE work_order_id = %s", (id,))
|
|
||||||
work_order = cursor.fetchone()
|
|
||||||
cursor.close()
|
|
||||||
connection.close()
|
|
||||||
return render_template('update_work_order.html', work_order=work_order)
|
|
||||||
|
|
||||||
|
|
||||||
# Optional: Route to show a success message
|
|
||||||
@app.route('/success')
|
|
||||||
def success():
|
|
||||||
return "Work Order Submitted Successfully!"
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user