Compare commits
3 Commits
8ab1b69033
...
laxmi-dev
| Author | SHA1 | Date | |
|---|---|---|---|
| 82bedc3117 | |||
| cb68e454bc | |||
| 675301df7f |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,8 +1,8 @@
|
||||
from flask import Blueprint, render_template, request, redirect, url_for
|
||||
# routes/gst_release_routes.py
|
||||
from flask import Blueprint, render_template, request, redirect, url_for, flash
|
||||
from flask_login import login_required
|
||||
from model.gst_release import GSTRelease
|
||||
from model.Log import LogHelper
|
||||
from flask import flash, current_app
|
||||
|
||||
gst_release_bp = Blueprint('gst_release_bp', __name__)
|
||||
gst_service = GSTRelease()
|
||||
@@ -13,7 +13,7 @@ gst_service = GSTRelease()
|
||||
def add_gst_release():
|
||||
if request.method == 'POST':
|
||||
gst_service.AddGSTRelease(request)
|
||||
LogHelper.log_action("Add GST Release", f"User added GST release")
|
||||
LogHelper.log_action("Add GST Release", "User added GST release")
|
||||
flash(gst_service.resultMessage, 'success' if gst_service.isSuccess else 'error')
|
||||
return redirect(url_for('gst_release_bp.add_gst_release'))
|
||||
|
||||
@@ -30,7 +30,7 @@ def edit_gst_release(gst_release_id):
|
||||
|
||||
if request.method == 'POST':
|
||||
gst_service.EditGSTRelease(request, gst_release_id)
|
||||
LogHelper.log_action("Edit GST Release", f"User edited GST release")
|
||||
LogHelper.log_action("Edit GST Release", "User edited GST release")
|
||||
flash(gst_service.resultMessage, 'success' if gst_service.isSuccess else 'error')
|
||||
return redirect(url_for('gst_release_bp.add_gst_release'))
|
||||
|
||||
@@ -40,7 +40,7 @@ def edit_gst_release(gst_release_id):
|
||||
@gst_release_bp.route('/delete_gst_release/<int:gst_release_id>', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def delete_gst_release(gst_release_id):
|
||||
gst_service.DeleteGSTRelease(gst_release_id) # remove request
|
||||
LogHelper.log_action("Delete GST Release", f"User deleted GST release")
|
||||
gst_service.DeleteGSTRelease(gst_release_id)
|
||||
LogHelper.log_action("Delete GST Release", "User deleted GST release")
|
||||
flash(gst_service.resultMessage, 'success' if gst_service.isSuccess else 'error')
|
||||
return redirect(url_for('gst_release_bp.add_gst_release'))
|
||||
@@ -10,21 +10,21 @@ hold_bp = Blueprint("hold_types", __name__)
|
||||
@hold_bp.route('/add_hold_type', methods=['GET','POST'])
|
||||
@login_required
|
||||
def add_hold_type():
|
||||
hold = HoldTypes()
|
||||
|
||||
hold = HoldTypes()
|
||||
|
||||
if request.method == 'POST':
|
||||
hold.AddHoldType(request)
|
||||
# ✅ Always redirect to same page (NO JSON)
|
||||
return redirect(url_for("hold_types.add_hold_type"))
|
||||
hold.AddHoldType(request) # ✅
|
||||
return hold.resultMessage
|
||||
|
||||
# GET request → show data
|
||||
hold_types = hold.GetAllHoldTypes()
|
||||
hold_types = hold.GetAllHoldTypes() # ✅
|
||||
|
||||
return render_template(
|
||||
"add_hold_type.html",
|
||||
Hold_Types_data=hold_types
|
||||
)
|
||||
|
||||
|
||||
# ---------------- CHECK HOLD TYPE (OPTIONAL LIKE BLOCK) ----------------
|
||||
@hold_bp.route('/check_hold_type', methods=['POST'])
|
||||
@login_required
|
||||
|
||||
@@ -83,29 +83,17 @@ def check_village():
|
||||
return village.CheckVillage(request=request)
|
||||
|
||||
|
||||
# ------------------------- Delete Village -------------------------
|
||||
@village_bp.route('/delete_village/<int:village_id>')
|
||||
@login_required
|
||||
def delete_village(village_id):
|
||||
|
||||
village = Village()
|
||||
village.DeleteVillage(request=request, village_id=village_id)
|
||||
|
||||
# ✅ Convert resultMessage to string if it's a Response or tuple
|
||||
raw_msg = village.resultMessage
|
||||
flash(village.resultMessage, "success" if village.isSuccess else "error")
|
||||
return redirect(url_for('village.add_village'))
|
||||
|
||||
if isinstance(raw_msg, tuple):
|
||||
# e.g., (<Response ...>, 200)
|
||||
msg = "Village deleted successfully!"
|
||||
elif hasattr(raw_msg, 'get_data'):
|
||||
# Flask Response object
|
||||
msg = raw_msg.get_data(as_text=True) # get raw text
|
||||
else:
|
||||
# fallback
|
||||
msg = str(raw_msg) if raw_msg else "Village deleted successfully!"
|
||||
|
||||
return jsonify({
|
||||
"status": "success" if village.isSuccess else "error",
|
||||
"message": msg
|
||||
})
|
||||
|
||||
# ------------------------- Edit Village -------------------------
|
||||
@village_bp.route('/edit_village/<int:village_id>', methods=['GET', 'POST'])
|
||||
|
||||
@@ -6,7 +6,6 @@ import config
|
||||
import re
|
||||
import mysql.connector
|
||||
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Mapping Class
|
||||
# ----------------------------------------------------------
|
||||
@@ -23,10 +22,11 @@ class itemCRUDMapping:
|
||||
self.name = "Hold Type"
|
||||
elif itemType is ItemCRUDType.Subcontractor:
|
||||
self.name = "Subcontractor"
|
||||
elif itemType.name == "GSTRelease":
|
||||
self.name = "GSTRelease"
|
||||
else:
|
||||
self.name = "Item"
|
||||
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Generic CRUD Class
|
||||
# ----------------------------------------------------------
|
||||
@@ -93,13 +93,47 @@ class ItemCRUD:
|
||||
|
||||
try:
|
||||
# ======================================================
|
||||
# SUBCONTRACTOR (MULTI-FIELD)
|
||||
# GSTRelease MULTI-FIELD
|
||||
# ======================================================
|
||||
if data:
|
||||
if self.itemCRUDType.name == "GSTRelease" and data:
|
||||
|
||||
# Duplicate check (PMC_No + Invoice_No)
|
||||
if storedprocfetch:
|
||||
cursor.callproc(storedprocfetch, (data['PMC_No'], data['Invoice_No']))
|
||||
existing_item = None
|
||||
for rs in cursor.stored_results():
|
||||
existing_item = rs.fetchone()
|
||||
if existing_item:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = HtmlHelper.json_response(
|
||||
ResponseHandler.already_exists(self.itemCRUDMapping.name), 409
|
||||
)
|
||||
return
|
||||
|
||||
# Insert GSTRelease
|
||||
cursor.callproc(storedprocadd, (
|
||||
data['PMC_No'],
|
||||
data['Invoice_No'],
|
||||
data['Basic_Amount'],
|
||||
data['Final_Amount'],
|
||||
data['Total_Amount'],
|
||||
data['UTR'],
|
||||
data['Contractor_ID']
|
||||
))
|
||||
connection.commit()
|
||||
|
||||
self.isSuccess = True
|
||||
self.resultMessage = HtmlHelper.json_response(
|
||||
ResponseHandler.add_success(self.itemCRUDMapping.name), 200
|
||||
)
|
||||
return
|
||||
|
||||
# ======================================================
|
||||
# SUBCONTRACTOR MULTI-FIELD
|
||||
# ======================================================
|
||||
if self.itemCRUDType.name == "Subcontractor" and data:
|
||||
|
||||
# Duplicate check
|
||||
cursor.callproc(storedprocfetch, (data['Contractor_Name'],))
|
||||
|
||||
existing_item = None
|
||||
for rs in cursor.stored_results():
|
||||
existing_item = rs.fetchone()
|
||||
@@ -111,7 +145,6 @@ class ItemCRUD:
|
||||
)
|
||||
return
|
||||
|
||||
# Insert
|
||||
cursor.callproc(storedprocadd, (
|
||||
data['Contractor_Name'],
|
||||
data['Address'],
|
||||
@@ -123,26 +156,24 @@ class ItemCRUD:
|
||||
data['GST_No'],
|
||||
data['Contractor_password']
|
||||
))
|
||||
|
||||
connection.commit()
|
||||
|
||||
self.isSuccess = True
|
||||
self.resultMessage = HtmlHelper.json_response(
|
||||
ResponseHandler.add_success(self.itemCRUDMapping.name), 200
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
# ======================================================
|
||||
# NORMAL (Village / Block / State)
|
||||
# NORMAL SINGLE-FIELD (Village / Block / State)
|
||||
# ======================================================
|
||||
if not re.match(RegEx.allPattern, childname):
|
||||
if not re.match(RegEx.patternAlphabetOnly, childname):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = HtmlHelper.json_response(
|
||||
ResponseHandler.invalid_name(self.itemCRUDMapping.name), 400
|
||||
)
|
||||
return
|
||||
|
||||
# Duplicate check
|
||||
if parentid is None:
|
||||
cursor.callproc(storedprocfetch, (childname,))
|
||||
else:
|
||||
@@ -159,17 +190,14 @@ class ItemCRUD:
|
||||
)
|
||||
return
|
||||
|
||||
# Insert
|
||||
if parentid is None:
|
||||
cursor.callproc(storedprocadd, (childname,))
|
||||
else:
|
||||
cursor.callproc(storedprocadd, (childname, parentid))
|
||||
|
||||
connection.commit()
|
||||
|
||||
self.isSuccess = True
|
||||
self.resultMessage = HtmlHelper.json_response(
|
||||
|
||||
ResponseHandler.add_success(self.itemCRUDMapping.name), 200
|
||||
)
|
||||
|
||||
@@ -199,9 +227,33 @@ class ItemCRUD:
|
||||
|
||||
try:
|
||||
# ======================================================
|
||||
# SUBCONTRACTOR (MULTI-FIELD)
|
||||
# GSTRelease MULTI-FIELD
|
||||
# ======================================================
|
||||
if data:
|
||||
if self.itemCRUDType.name == "GSTRelease" and data:
|
||||
|
||||
cursor.callproc(storedprocupdate, (
|
||||
childid,
|
||||
data['PMC_No'],
|
||||
data['Invoice_No'],
|
||||
data['Basic_Amount'],
|
||||
data['Final_Amount'],
|
||||
data['Total_Amount'],
|
||||
data['UTR'],
|
||||
data['Contractor_ID']
|
||||
))
|
||||
connection.commit()
|
||||
|
||||
self.isSuccess = True
|
||||
self.resultMessage = HtmlHelper.json_response(
|
||||
ResponseHandler.update_success(self.itemCRUDMapping.name), 200
|
||||
)
|
||||
return
|
||||
|
||||
# ======================================================
|
||||
# SUBCONTRACTOR MULTI-FIELD
|
||||
# ======================================================
|
||||
if self.itemCRUDType.name == "Subcontractor" and data:
|
||||
|
||||
cursor.callproc(storedprocupdate, (
|
||||
childid,
|
||||
data['Contractor_Name'],
|
||||
@@ -214,9 +266,7 @@ class ItemCRUD:
|
||||
data['GST_No'],
|
||||
data['Contractor_password']
|
||||
))
|
||||
|
||||
connection.commit()
|
||||
|
||||
self.isSuccess = True
|
||||
self.resultMessage = HtmlHelper.json_response(
|
||||
ResponseHandler.update_success(self.itemCRUDMapping.name), 200
|
||||
@@ -224,9 +274,9 @@ class ItemCRUD:
|
||||
return
|
||||
|
||||
# ======================================================
|
||||
# NORMAL
|
||||
# NORMAL SINGLE-FIELD
|
||||
# ======================================================
|
||||
if not re.match(RegEx.allPattern, childname):
|
||||
if not re.match(RegEx.patternAlphabetOnly, childname):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ResponseHandler.update_failure(self.itemCRUDMapping.name)['message']
|
||||
return
|
||||
@@ -237,7 +287,6 @@ class ItemCRUD:
|
||||
cursor.callproc(storedprocupdate, (childid, parentid, childname))
|
||||
|
||||
connection.commit()
|
||||
|
||||
self.isSuccess = True
|
||||
self.resultMessage = ResponseHandler.update_success(self.itemCRUDMapping.name)['message']
|
||||
|
||||
@@ -259,20 +308,15 @@ class ItemCRUD:
|
||||
|
||||
data = []
|
||||
connection = config.get_db_connection()
|
||||
|
||||
if not connection:
|
||||
return []
|
||||
|
||||
cursor = connection.cursor()
|
||||
|
||||
try:
|
||||
cursor.callproc(storedproc)
|
||||
|
||||
for result in cursor.stored_results():
|
||||
data = result.fetchall()
|
||||
|
||||
self.isSuccess = True
|
||||
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error fetching {self.itemCRUDMapping.name}: {e}")
|
||||
self.isSuccess = False
|
||||
@@ -280,7 +324,6 @@ class ItemCRUD:
|
||||
ResponseHandler.fetch_failure(self.itemCRUDMapping.name), 500
|
||||
)
|
||||
return []
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
@@ -298,13 +341,10 @@ class ItemCRUD:
|
||||
|
||||
try:
|
||||
cursor.callproc(storedproc, (id,))
|
||||
|
||||
for rs in cursor.stored_results():
|
||||
data = rs.fetchone()
|
||||
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error fetching {self.itemCRUDMapping.name}: {e}")
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
@@ -324,7 +364,7 @@ class ItemCRUD:
|
||||
f"User {current_user.id} checked '{childname}'"
|
||||
)
|
||||
|
||||
if not re.match(RegEx.allPattern, childname):
|
||||
if not re.match(RegEx.patternAlphabetOnly, childname):
|
||||
return HtmlHelper.json_response(
|
||||
ResponseHandler.invalid_name(self.itemCRUDMapping.name), 400
|
||||
)
|
||||
@@ -353,7 +393,6 @@ class ItemCRUD:
|
||||
return HtmlHelper.json_response(
|
||||
ResponseHandler.fetch_failure(self.itemCRUDMapping.name), 500
|
||||
)
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
@@ -8,11 +8,10 @@ class ItemCRUDType(Enum):
|
||||
State = 4
|
||||
HoldType = 5
|
||||
Subcontractor = 6
|
||||
|
||||
GSTRelease = 7
|
||||
|
||||
class RegEx:
|
||||
patternAlphabetOnly = "^[A-Za-z ]+$"
|
||||
allPattern = "^(?!\s*$).+"
|
||||
|
||||
|
||||
class ResponseHandler:
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,109 +1,8 @@
|
||||
# from flask import request
|
||||
# from model.ItemCRUD import ItemCRUD
|
||||
# from model.Utilities import ItemCRUDType
|
||||
|
||||
# class GSTRelease:
|
||||
# """CRUD operations for GST Release using ItemCRUD"""
|
||||
|
||||
# def __init__(self):
|
||||
# self.isSuccess = False
|
||||
# self.resultMessage = ""
|
||||
|
||||
# # ------------------- Add GST Release -------------------
|
||||
# def AddGSTRelease(self, request):
|
||||
# pmc_no = request.form.get('PMC_No', '').strip()
|
||||
# invoice_no = request.form.get('invoice_No', '').strip()
|
||||
|
||||
# gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||
# gst.AddItem(
|
||||
# request=request,
|
||||
# parentid=None,
|
||||
# childname=f"{pmc_no}-{invoice_no}",
|
||||
# storedprocfetch="CheckGSTReleaseExists",
|
||||
# storedprocadd="AddGSTReleaseFromExcel" # your stored procedure handles extra fields
|
||||
# )
|
||||
|
||||
# self.isSuccess = gst.isSuccess
|
||||
# self.resultMessage = str(gst.resultMessage)
|
||||
|
||||
# # ------------------- Get All GST Releases -------------------
|
||||
# def GetAllGSTReleases(self):
|
||||
# gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||
# # Pass request=None for fetch
|
||||
# rows = gst.GetAllData(request=None, storedproc="GetAllGSTReleases")
|
||||
|
||||
# self.isSuccess = gst.isSuccess
|
||||
# self.resultMessage = str(gst.resultMessage)
|
||||
|
||||
# data = []
|
||||
# for row in rows:
|
||||
# data.append({
|
||||
# "gst_release_id": row[0],
|
||||
# "pmc_no": row[1],
|
||||
# "invoice_no": row[2],
|
||||
# "basic_amount": row[3],
|
||||
# "final_amount": row[4],
|
||||
# "total_amount": row[5],
|
||||
# "utr": row[6],
|
||||
# "contractor_id": row[7]
|
||||
# })
|
||||
# return data
|
||||
|
||||
# # ------------------- Get GST Release By ID -------------------
|
||||
# def GetGSTReleaseByID(self, gst_release_id):
|
||||
# gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||
# row = gst.GetDataByID(gst_release_id, request=None, storedproc="GetGSTReleaseById")
|
||||
|
||||
# self.isSuccess = gst.isSuccess
|
||||
# self.resultMessage = str(gst.resultMessage)
|
||||
|
||||
# if row:
|
||||
# return {
|
||||
# "gst_release_id": row[0],
|
||||
# "pmc_no": row[1],
|
||||
# "invoice_no": row[2],
|
||||
# "basic_amount": row[3],
|
||||
# "final_amount": row[4],
|
||||
# "total_amount": row[5],
|
||||
# "utr": row[6],
|
||||
# "contractor_id": row[7]
|
||||
# }
|
||||
# return None
|
||||
|
||||
# # ------------------- Edit GST Release -------------------
|
||||
# def EditGSTRelease(self, request, gst_release_id):
|
||||
# pmc_no = request.form.get('PMC_No', '').strip()
|
||||
# invoice_no = request.form.get('invoice_No', '').strip()
|
||||
|
||||
# gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||
# gst.EditItem(
|
||||
# request=request,
|
||||
# childid=gst_release_id,
|
||||
# parentid=None,
|
||||
# childname=f"{pmc_no}-{invoice_no}",
|
||||
# storedprocupdate="UpdateGSTRelease" # stored procedure handles extra fields
|
||||
# )
|
||||
|
||||
# self.isSuccess = gst.isSuccess
|
||||
# self.resultMessage = str(gst.resultMessage)
|
||||
|
||||
# # ------------------- Delete GST Release -------------------
|
||||
# def DeleteGSTRelease(self, gst_release_id):
|
||||
# gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||
# gst.DeleteItem(
|
||||
# itemID=gst_release_id,
|
||||
# request=None,
|
||||
# storedprocDelete="DeleteGSTReleaseById"
|
||||
# )
|
||||
|
||||
# self.isSuccess = gst.isSuccess
|
||||
# self.resultMessage = str(gst.resultMessage)
|
||||
|
||||
# model/gst_release.py
|
||||
from flask import request, jsonify
|
||||
from model.ItemCRUD import ItemCRUD
|
||||
from model.Utilities import ItemCRUDType
|
||||
|
||||
|
||||
class GSTRelease:
|
||||
|
||||
def __init__(self):
|
||||
@@ -125,12 +24,19 @@ class GSTRelease:
|
||||
"Contractor_ID": int(request.form.get("Contractor_ID", 0) or 0)
|
||||
}
|
||||
|
||||
# Add GST Release
|
||||
gst.AddItem(
|
||||
request=request,
|
||||
data=data,
|
||||
storedprocfetch="CheckGSTReleaseExists",
|
||||
storedprocadd="AddGSTReleaseFromExcel"
|
||||
)
|
||||
|
||||
# Check if addition was successful
|
||||
if gst.isSuccess:
|
||||
print(f"GST Release Added: {data}")
|
||||
else:
|
||||
print(f"Failed to add GST Release: {gst.resultMessage}")
|
||||
|
||||
self.isSuccess = gst.isSuccess
|
||||
self.resultMessage = str(gst.resultMessage)
|
||||
@@ -198,7 +104,6 @@ class GSTRelease:
|
||||
def GetAllGSTReleases(self):
|
||||
try:
|
||||
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||
|
||||
rows = gst.GetAllData(None, "GetAllGSTReleases")
|
||||
|
||||
data = []
|
||||
@@ -224,7 +129,6 @@ class GSTRelease:
|
||||
def GetGSTReleaseByID(self, gst_release_id):
|
||||
try:
|
||||
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||
|
||||
row = gst.GetDataByID(gst_release_id, "GetGSTReleaseById")
|
||||
|
||||
if row:
|
||||
|
||||
@@ -3,7 +3,7 @@ $(document).ready(function () {
|
||||
let holdType = $(this).val().replace(/^\s+/, "");
|
||||
$(this).val(holdType);
|
||||
|
||||
let reg = /^.+$/; // all pattern allow
|
||||
let reg = /^[A-Za-z]/;
|
||||
|
||||
if (!reg.test(holdType)) {
|
||||
$("#holdTypeMessage").text("Hold Type must start with a letter.").css("color", "red");
|
||||
|
||||
@@ -1,250 +1,264 @@
|
||||
|
||||
|
||||
window.onload = function () {
|
||||
if (document.getElementById('Village_Name')) {
|
||||
document.getElementById('Village_Name').focus();
|
||||
}
|
||||
document.getElementById('Village_Name').focus();
|
||||
};
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
// ✅ RUN ONLY IF THIS PAGE HAS FORM/TABLE
|
||||
if ($('#addForm').length && $('#addTable').length) {
|
||||
// 🔥 RESTORE VIEW MODE AFTER RELOAD
|
||||
var viewMode = localStorage.getItem("viewMode");
|
||||
|
||||
// ✅ DEFAULT VIEW → SHOW FORM
|
||||
if (viewMode === "table") {
|
||||
$('#addForm').hide();
|
||||
$('#addTable').show();
|
||||
} else {
|
||||
$('#addForm').show();
|
||||
$('#addTable').hide();
|
||||
}
|
||||
|
||||
|
||||
// 🔥 BUTTON TOGGLE LOGIC
|
||||
|
||||
$('#addButton').click(function () {
|
||||
$('#addForm').show();
|
||||
$('#addTable').hide();
|
||||
|
||||
localStorage.setItem("viewMode", "form");
|
||||
});
|
||||
|
||||
// 🔥 BUTTON TOGGLE
|
||||
$('#addButton').click(function () {
|
||||
$('#addForm').show();
|
||||
$('#addTable').hide();
|
||||
});
|
||||
$('#displayButton').click(function () {
|
||||
$('#addForm').hide();
|
||||
$('#addTable').show();
|
||||
|
||||
$('#displayButton').click(function () {
|
||||
$('#addForm').hide();
|
||||
$('#addTable').show();
|
||||
});
|
||||
}
|
||||
localStorage.setItem("viewMode", "table");
|
||||
});
|
||||
|
||||
|
||||
// ===============================
|
||||
// STATE → DISTRICT
|
||||
// ===============================
|
||||
if ($('#state_Id').length) {
|
||||
$('#state_Id').change(function () {
|
||||
|
||||
$('#state_Id').change(function () {
|
||||
var stateId = $(this).val();
|
||||
|
||||
var stateId = $(this).val();
|
||||
|
||||
if (stateId) {
|
||||
|
||||
$.ajax({
|
||||
url: '/get_districts/' + stateId,
|
||||
type: 'GET',
|
||||
|
||||
success: function (data) {
|
||||
|
||||
var districtDropdown = $('#district_Id');
|
||||
|
||||
districtDropdown.empty();
|
||||
districtDropdown.append('<option value="" disabled selected>Select District</option>');
|
||||
|
||||
data.forEach(function (district) {
|
||||
districtDropdown.append(
|
||||
'<option value="' + district.id + '">' + district.name + '</option>'
|
||||
);
|
||||
});
|
||||
|
||||
districtDropdown.prop('disabled', false);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// ===============================
|
||||
// DISTRICT → BLOCK
|
||||
// ===============================
|
||||
if ($('#district_Id').length) {
|
||||
|
||||
$('#district_Id').change(function () {
|
||||
|
||||
var districtId = $(this).val();
|
||||
|
||||
if (districtId) {
|
||||
|
||||
$.ajax({
|
||||
url: '/get_blocks/' + districtId,
|
||||
type: 'GET',
|
||||
|
||||
success: function (data) {
|
||||
|
||||
var blockDropdown = $('#block_Id');
|
||||
|
||||
blockDropdown.empty();
|
||||
blockDropdown.append('<option value="" disabled selected>Select Block</option>');
|
||||
|
||||
data.forEach(function (block) {
|
||||
blockDropdown.append(
|
||||
'<option value="' + block.id + '">' + block.name + '</option>'
|
||||
);
|
||||
});
|
||||
|
||||
blockDropdown.prop('disabled', false);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// ===============================
|
||||
// VILLAGE NAME VALIDATION
|
||||
// ===============================
|
||||
if ($('#Village_Name').length) {
|
||||
|
||||
$('#Village_Name').on('input', function () {
|
||||
|
||||
var villageName = $(this).val();
|
||||
var validPattern = /^[A-Za-z ]*$/;
|
||||
|
||||
if (!validPattern.test(villageName)) {
|
||||
|
||||
$('#villageMessage')
|
||||
.text('Only letters and spaces are allowed!')
|
||||
.css('color', 'red');
|
||||
|
||||
$('#submitVillage').prop('disabled', true);
|
||||
|
||||
} else {
|
||||
|
||||
$('#villageMessage').text('');
|
||||
$('#submitVillage').prop('disabled', false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// ===============================
|
||||
// CHECK DUPLICATE VILLAGE
|
||||
// ===============================
|
||||
if ($('#Village_Name').length && $('#block_Id').length) {
|
||||
|
||||
$('#Village_Name, #block_Id').on('change keyup', function () {
|
||||
|
||||
var blockId = $('#block_Id').val();
|
||||
var villageName = $('#Village_Name').val().trim();
|
||||
|
||||
if (blockId && villageName) {
|
||||
|
||||
$.ajax({
|
||||
url: '/check_village',
|
||||
type: 'POST',
|
||||
|
||||
data: {
|
||||
block_Id: blockId,
|
||||
Village_Name: villageName
|
||||
},
|
||||
|
||||
success: function (response) {
|
||||
|
||||
if (response.status === 'exists') {
|
||||
|
||||
$('#villageMessage')
|
||||
.text(response.message)
|
||||
.css('color', 'red');
|
||||
|
||||
$('#submitVillage').prop('disabled', true);
|
||||
|
||||
} else {
|
||||
|
||||
$('#villageMessage')
|
||||
.text(response.message)
|
||||
.css('color', 'green');
|
||||
|
||||
$('#submitVillage').prop('disabled', false);
|
||||
}
|
||||
},
|
||||
|
||||
error: function () {
|
||||
|
||||
$('#villageMessage')
|
||||
.text('Error checking village name')
|
||||
.css('color', 'red');
|
||||
|
||||
$('#submitVillage').prop('disabled', true);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// ===============================
|
||||
// ADD VILLAGE (SAFE SCOPE FIX)
|
||||
// ===============================
|
||||
if ($('#villageForm').length) {
|
||||
|
||||
$('#villageForm').submit(function (event) {
|
||||
|
||||
event.preventDefault();
|
||||
if (stateId) {
|
||||
|
||||
$.ajax({
|
||||
url: '/add_village',
|
||||
url: '/get_districts/' + stateId,
|
||||
type: 'GET',
|
||||
|
||||
success: function (data) {
|
||||
|
||||
var districtDropdown = $('#district_Id');
|
||||
|
||||
districtDropdown.empty();
|
||||
districtDropdown.append('<option value="" disabled selected>Select District</option>');
|
||||
|
||||
data.forEach(function (district) {
|
||||
|
||||
districtDropdown.append(
|
||||
'<option value="' + district.id + '">' + district.name + '</option>'
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
districtDropdown.prop('disabled', false);
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
// DISTRICT → BLOCK
|
||||
$('#district_Id').change(function () {
|
||||
|
||||
var districtId = $(this).val();
|
||||
|
||||
if (districtId) {
|
||||
|
||||
$.ajax({
|
||||
url: '/get_blocks/' + districtId,
|
||||
type: 'GET',
|
||||
|
||||
success: function (data) {
|
||||
|
||||
var blockDropdown = $('#block_Id');
|
||||
|
||||
blockDropdown.empty();
|
||||
blockDropdown.append('<option value="" disabled selected>Select Block</option>');
|
||||
|
||||
data.forEach(function (block) {
|
||||
|
||||
blockDropdown.append(
|
||||
'<option value="' + block.id + '">' + block.name + '</option>'
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
blockDropdown.prop('disabled', false);
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
// VILLAGE NAME VALIDATION
|
||||
$('#Village_Name').on('input', function () {
|
||||
|
||||
var villageName = $(this).val();
|
||||
var validPattern = /^[A-Za-z ]*$/;
|
||||
|
||||
if (!validPattern.test(villageName)) {
|
||||
|
||||
$('#villageMessage')
|
||||
.text('Only letters and spaces are allowed!')
|
||||
.css('color', 'red');
|
||||
|
||||
$('#submitVillage').prop('disabled', true);
|
||||
|
||||
} else {
|
||||
|
||||
$('#villageMessage').text('');
|
||||
$('#submitVillage').prop('disabled', false);
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
// CHECK DUPLICATE VILLAGE
|
||||
$('#Village_Name, #block_Id').on('change keyup', function () {
|
||||
|
||||
var blockId = $('#block_Id').val();
|
||||
var villageName = $('#Village_Name').val().trim();
|
||||
|
||||
if (blockId && villageName) {
|
||||
|
||||
$.ajax({
|
||||
|
||||
url: '/check_village',
|
||||
type: 'POST',
|
||||
data: $(this).serialize(),
|
||||
|
||||
data: {
|
||||
block_Id: blockId,
|
||||
Village_Name: villageName
|
||||
},
|
||||
|
||||
success: function (response) {
|
||||
|
||||
if (response && response.status === 'success') {
|
||||
if (response.status === 'exists') {
|
||||
|
||||
alert(response.message || 'Village added successfully!');
|
||||
$('#villageMessage')
|
||||
.text(response.message)
|
||||
.css('color', 'red');
|
||||
|
||||
// ✅ clear form
|
||||
$('#villageForm')[0].reset();
|
||||
|
||||
// ✅ switch to table
|
||||
$('#addForm').hide();
|
||||
$('#addTable').show();
|
||||
|
||||
// optional refresh
|
||||
location.reload();
|
||||
$('#submitVillage').prop('disabled', true);
|
||||
|
||||
} else {
|
||||
alert(response.message || 'Error adding village. Please try again.');
|
||||
|
||||
$('#villageMessage')
|
||||
.text(response.message)
|
||||
.css('color', 'green');
|
||||
|
||||
$('#submitVillage').prop('disabled', false);
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
error: function () {
|
||||
alert('An error occurred. Please try again.');
|
||||
|
||||
$('#villageMessage')
|
||||
.text('Error checking village name')
|
||||
.css('color', 'red');
|
||||
|
||||
$('#submitVillage').prop('disabled', true);
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
// ADD VILLAGE
|
||||
$('#villageForm').submit(function (event) {
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
$.ajax({
|
||||
|
||||
url: '/add_village',
|
||||
type: 'POST',
|
||||
data: $(this).serialize(),
|
||||
|
||||
success: function (response) {
|
||||
|
||||
if (response.status === 'success') {
|
||||
|
||||
alert('Village added successfully!');
|
||||
location.reload();
|
||||
|
||||
} else {
|
||||
|
||||
alert(response.message || 'Error adding village. Please try again.');
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
error: function () {
|
||||
|
||||
alert('An error occurred. Please try again.');
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
// 🔥 DELETE FUNCTION (UPDATED)
|
||||
function deleteVillage(villageId) {
|
||||
|
||||
if (!confirm("Are you sure you want to delete this village?")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// ===============================
|
||||
// DELETE FUNCTION (SAFE)
|
||||
// ===============================
|
||||
function deleteVillage(villageId, element) {
|
||||
if (!confirm("Are you sure you want to delete this village?")) return;
|
||||
// ✅ save that user is on table
|
||||
localStorage.setItem("viewMode", "table");
|
||||
|
||||
$.ajax({
|
||||
url: '/delete_village/' + villageId,
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
success: function (response) {
|
||||
alert(response.message); // ✅ now shows "Village deleted successfully!"
|
||||
if (element) $(element).closest("tr").remove();
|
||||
|
||||
success: function () {
|
||||
|
||||
setTimeout(function () {
|
||||
|
||||
alert("Village deleted successfully!");
|
||||
|
||||
// reload but stay on table
|
||||
location.reload();
|
||||
|
||||
}, 1000);
|
||||
|
||||
},
|
||||
|
||||
error: function () {
|
||||
alert("Error deleting village. Please try again.");
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
@@ -68,50 +68,49 @@
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<!-- GST Release History Table -->
|
||||
<div id="addTable" style="display: none;">
|
||||
<div class="search-container">
|
||||
<h2>GST Release History</h2>
|
||||
<input type="text" id="searchBar" placeholder="Searching..." onkeyup="searchTable()">
|
||||
<input type="text" id="searchBar" placeholder="Search..." onkeyup="searchTable()">
|
||||
</div>
|
||||
<table id="sortableTable" border="1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="sortable-header">GST_Release_Id</th>
|
||||
<th class="sortable-header">PMC_No</th>
|
||||
<th>Invoice_No</th>
|
||||
<th>Basic_Amount</th>
|
||||
<th>Final_Amount</th>
|
||||
<th>Total_Amount</th>
|
||||
<th>UTR</th>
|
||||
<th>Update</th>
|
||||
<th>Delete</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="sortable-header">GST_Release_Id</th>
|
||||
<th class="sortable-header">PMC_No</th>
|
||||
<th>Invoice_No</th>
|
||||
<th>Basic_Amount</th>
|
||||
<th>Final_Amount</th>
|
||||
<th>Total_Amount</th>
|
||||
<th>UTR</th>
|
||||
<th>Update</th>
|
||||
<th>Delete</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for gst_rel in gst_releases %}
|
||||
<tr>
|
||||
<td>{{ gst_rel[0] }}</td>
|
||||
<td>{{ gst_rel[1] }}</td>
|
||||
<td>{{ gst_rel[2] }}</td>
|
||||
<td>{{ gst_rel[3] }}</td>
|
||||
<td>{{ gst_rel[4] }}</td>
|
||||
<td>{{ gst_rel[5] }}</td>
|
||||
<td>{{ gst_rel[6] }}</td>
|
||||
<td>
|
||||
<a href="/edit_gst_release/{{ gst_rel[0] }}">
|
||||
<img src="{{ url_for('static', filename='images/icons/pen_blue_icon.png') }}" alt="Edit"
|
||||
class="icon">
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="/delete_gst_release/{{ gst_rel[0] }}"
|
||||
onclick="return confirm('Are you sure you want to delete this GST Release?')">
|
||||
<img src="{{ url_for('static', filename='images/icons/bin_red_icon.png') }}" alt="Delete"
|
||||
class="icon">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% for gst_rel in gst_releases %}
|
||||
<tr>
|
||||
<td>{{ gst_rel.gst_release_id }}</td>
|
||||
<td>{{ gst_rel.pmc_no }}</td>
|
||||
<td>{{ gst_rel.invoice_no }}</td>
|
||||
<td>{{ gst_rel.basic_amount }}</td>
|
||||
<td>{{ gst_rel.final_amount }}</td>
|
||||
<td>{{ gst_rel.total_amount }}</td>
|
||||
<td>{{ gst_rel.utr }}</td>
|
||||
<td>
|
||||
<a href="{{ url_for('gst_release_bp.edit_gst_release', gst_release_id=gst_rel.gst_release_id) }}">
|
||||
<img src="{{ url_for('static', filename='images/icons/pen_blue_icon.png') }}" alt="Edit" class="icon">
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ url_for('gst_release_bp.delete_gst_release', gst_release_id=gst_rel.gst_release_id) }}"
|
||||
onclick="return confirm('Are you sure you want to delete this GST Release?')">
|
||||
<img src="{{ url_for('static', filename='images/icons/bin_red_icon.png') }}" alt="Delete" class="icon">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -1,73 +1,59 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
|
||||
<head>
|
||||
<title>Manage Hold Types</title>
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<!-- <script src="{{ url_for('static', filename='js/hold_types.js') }}"></script> -->
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}">
|
||||
<script src="{{ url_for('static', filename='js/search_on_table.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/search_on_table.js') }}"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="button-container">
|
||||
<button id="addButton" class="action-button">Add</button>
|
||||
<button id="displayButton" class="action-button">Display</button>
|
||||
</div>
|
||||
<div class="button-container">
|
||||
<button id="addButton" class="action-button">Add</button>
|
||||
<button id="displayButton" class="action-button">Display</button>
|
||||
</div>
|
||||
|
||||
<div id="addForm">
|
||||
<h2>Add Hold Types</h2>
|
||||
<form id="holdTypeForm" method="POST" action="{{ url_for('hold_types.add_hold_type') }}">
|
||||
<label>Enter Hold Amount Type:</label>
|
||||
<input type="text" id="hold_type" name="hold_type" placeholder="Enter Type" required>
|
||||
<span id="holdTypeMessage"></span>
|
||||
<button type="submit" value="Add Hold Type" id="successPopup">Add Hold Type</button>
|
||||
</form>
|
||||
</div>
|
||||
<div id="addForm">
|
||||
<h2>Add Hold Types</h2>
|
||||
<form id="holdTypeForm" method="POST" action="{{ url_for('hold_types.add_hold_type') }}">
|
||||
<label>Enter Hold Amount Type:</label>
|
||||
<input type="text" id="hold_type" name="hold_type" placeholder="Enter Type" required>
|
||||
<span id="holdTypeMessage"></span>
|
||||
<button type="submit" value="Add Hold Type" id="successPopup">Add Hold Type</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<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">
|
||||
Hold Type
|
||||
<span class="sort-buttons">
|
||||
<span class="sort-asc">⬆️</span>
|
||||
<span class="sort-desc">⬇️</span>
|
||||
</span>
|
||||
</th>
|
||||
<th>Update</th>
|
||||
<th>Delete</th>
|
||||
</tr>
|
||||
{% for htd in Hold_Types_data %}
|
||||
<tr>
|
||||
<td>{{ htd['hold_type_id'] }}</td>
|
||||
<td>{{ htd['hold_type'] }}</td>
|
||||
<td><a href="{{ url_for('hold_types.edit_hold_type', id=htd['hold_type_id']) }}">Edit</a></td>
|
||||
<td><button class="delete-button" data-id="{{ htd['hold_type_id'] }}">Delete</button></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
<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">
|
||||
Hold Type
|
||||
<span class="sort-buttons">
|
||||
<span class="sort-asc">⬆️</span>
|
||||
<span class="sort-desc">⬇️</span>
|
||||
</span>
|
||||
</th>
|
||||
<th>Update</th>
|
||||
<th>Delete</th>
|
||||
</tr>
|
||||
{% for htd in Hold_Types_data %}
|
||||
<tr>
|
||||
<td>{{ htd['hold_type_id'] }}</td>
|
||||
<td>{{ htd['hold_type'] }}</td>
|
||||
<td style="text-align:center;">
|
||||
<a href="{{ url_for('hold_types.edit_hold_type', id=htd['hold_type_id']) }}">
|
||||
<img src="{{ url_for('static', filename='images/icons/pen_blue_icon.png') }}" alt="Edit"
|
||||
class="icon">
|
||||
</a>
|
||||
</td>
|
||||
|
||||
<td style="text-align:center;">
|
||||
<a href="{{ url_for('hold_types.delete_hold_type', id=htd['hold_type_id']) }}"
|
||||
onclick="return confirm('Are you sure you want to delete this hold type?');">
|
||||
|
||||
<img src="{{ url_for('static', filename='images/icons/bin_red_icon.png') }}" alt="Delete"
|
||||
class="icon">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
<a href="/">Back to Dashboard</a>
|
||||
</div>
|
||||
<a href="/">Back to Dashboard</a>
|
||||
</div>
|
||||
</body>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -1,129 +1,99 @@
|
||||
{% extends 'base.html' %} {% block content %}
|
||||
{% extends 'base.html' %}
|
||||
{% block content %}
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Village Management</title>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="{{ url_for('static', filename='css/style.css') }}"
|
||||
/>
|
||||
<script src="{{ url_for('static', filename='js/village.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/search_on_table.js') }}"></script>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Village Management</title>
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}">
|
||||
<script src="{{ url_for('static', filename='js/village.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/search_on_table.js') }}"></script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Button Container to Center Buttons -->
|
||||
<div class="button-container">
|
||||
|
||||
<!-- Button Container to Center Buttons -->
|
||||
<div class="button-container">
|
||||
<button id="addButton" class="action-button">Add</button>
|
||||
<button id="displayButton" class="action-button">Display</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="addForm" style="display: none">
|
||||
<div id="addForm" style="display: none;">
|
||||
<div class="container">
|
||||
<div class="form-block">
|
||||
<h2>Add a New Village</h2>
|
||||
<form id="villageForm" method="POST">
|
||||
<label for="state_Id">State:</label>
|
||||
<select id="state_Id" name="state_Id" required>
|
||||
<option value="" disabled selected>Select State</option>
|
||||
{% for state in states %}
|
||||
<option value="{{ state[0] }}">{{ state[1] }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<div class="form-block">
|
||||
<h2>Add a New Village</h2>
|
||||
<form id="villageForm" method="POST">
|
||||
<label for="state_Id">State:</label>
|
||||
<select id="state_Id" name="state_Id" required>
|
||||
<option value="" disabled selected>Select State</option>
|
||||
{% for state in states %}
|
||||
<option value="{{ state[0] }}">{{ state[1] }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<label for="district_Id">District:</label>
|
||||
<select id="district_Id" name="district_Id" required disabled>
|
||||
<option value="" disabled selected>Select District</option>
|
||||
</select>
|
||||
|
||||
<label for="district_Id">District:</label>
|
||||
<select id="district_Id" name="district_Id" required disabled>
|
||||
<option value="" disabled selected>Select District</option>
|
||||
</select>
|
||||
<label for="block_Id">Block:</label>
|
||||
<select id="block_Id" name="block_Id" required disabled>
|
||||
<option value="" disabled selected>Select Block</option>
|
||||
</select>
|
||||
|
||||
<label for="block_Id">Block:</label>
|
||||
<select id="block_Id" name="block_Id" required disabled>
|
||||
<option value="" disabled selected>Select Block</option>
|
||||
</select>
|
||||
<label for="Village_Name">Village Name:</label>
|
||||
<input type="text" id="Village_Name" name="Village_Name" placeholder="Enter Village Name" required>
|
||||
<span id="villageMessage"></span>
|
||||
|
||||
<label for="Village_Name">Village Name:</label>
|
||||
<input
|
||||
type="text"
|
||||
id="Village_Name"
|
||||
name="Village_Name"
|
||||
placeholder="Enter Village Name"
|
||||
required
|
||||
/>
|
||||
<span id="villageMessage"></span>
|
||||
|
||||
<button type="submit" id="submitVillage" disabled>Add Village</button>
|
||||
</form>
|
||||
</div>
|
||||
<button type="submit" id="submitVillage" disabled>Add Village</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="addTable" style="display: none">
|
||||
<div id="addTable" style="display: none;">
|
||||
<div class="search-container">
|
||||
<h2>Display Villages</h2>
|
||||
<input
|
||||
type="text"
|
||||
id="searchBar"
|
||||
placeholder="Searching..."
|
||||
onkeyup="searchTable()"
|
||||
/>
|
||||
<h2>Display Villages</h2>
|
||||
<input type="text" id="searchBar" placeholder="Searching..." onkeyup="searchTable()">
|
||||
</div>
|
||||
|
||||
<table id="sortableTable" border="1">
|
||||
<tr>
|
||||
<th>Village Sr No</th>
|
||||
<th class="sortable-header">
|
||||
Village Name
|
||||
<span class="sort-buttons">
|
||||
<span class="sort-asc">⬆️</span>
|
||||
<span class="sort-desc">⬇️</span>
|
||||
</span>
|
||||
</th>
|
||||
<th class="sortable-header">
|
||||
Block Name
|
||||
<span class="sort-buttons">
|
||||
<span class="sort-asc">⬆️</span>
|
||||
<span class="sort-desc">⬇️</span>
|
||||
</span>
|
||||
</th>
|
||||
<th>Update</th>
|
||||
<th>Delete</th>
|
||||
</tr>
|
||||
{% for village in villages %}
|
||||
<tr>
|
||||
<td>{{ village[0] }}</td>
|
||||
<td>{{ village[1] }}</td>
|
||||
<td>{{ village[2] }}</td>
|
||||
<td>
|
||||
<a
|
||||
href="{{ url_for('village.edit_village', village_id=village[0]) }}"
|
||||
>
|
||||
<img
|
||||
src="{{ url_for('static', filename='images/icons/pen_blue_icon.png') }}"
|
||||
alt="Edit"
|
||||
class="icon"
|
||||
/>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="javascript:void(0);"
|
||||
onclick="deleteVillage({{ village[0] }}, this)">
|
||||
<tr>
|
||||
<th>Village Sr No</th>
|
||||
<th class="sortable-header">
|
||||
Village Name
|
||||
<span class="sort-buttons">
|
||||
<span class="sort-asc">⬆️</span>
|
||||
<span class="sort-desc">⬇️</span>
|
||||
</span></th>
|
||||
<th class="sortable-header">Block Name
|
||||
<span class="sort-buttons">
|
||||
<span class="sort-asc">⬆️</span>
|
||||
<span class="sort-desc">⬇️</span>
|
||||
</span></th>
|
||||
<th>Update</th>
|
||||
<th>Delete</th>
|
||||
</tr>
|
||||
{% for village in villages %}
|
||||
<tr>
|
||||
<td>{{ village[0] }}</td>
|
||||
<td>{{ village[1] }}</td>
|
||||
<td>{{ village[2] }}</td>
|
||||
<td>
|
||||
<a href="{{ url_for('village.edit_village', village_id=village[0]) }}">
|
||||
<img src="{{ url_for('static', filename='images/icons/pen_blue_icon.png') }}" alt="Edit"
|
||||
class="icon">
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="#"
|
||||
onclick="deleteVillage({{ village[0] }}); return false;">
|
||||
<img src="{{ url_for('static', filename='images/icons/bin_red_icon.png') }}"
|
||||
class="icon">
|
||||
alt="Delete" class="icon">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
<!-- Flash Alerts -->
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
<script>
|
||||
{% for category, message in messages %}
|
||||
alert("{{ message }}");
|
||||
{% endfor %}
|
||||
</script>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
</body>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<head>
|
||||
<title>Edit Hold Type</title>
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}">
|
||||
@@ -10,10 +10,10 @@
|
||||
|
||||
<body>
|
||||
<h2>Edit Hold Type</h2>
|
||||
<form id="updateHoldTypeForm" method="POST">
|
||||
<input type="hidden" id="hold_type_id" value="{{ hold_type.hold_type_id }}">
|
||||
<form id="updateHoldTypeForm">
|
||||
<input type="hidden" id="hold_type_id" value="{{ hold_type[0] }}">
|
||||
<label for="edit_hold_type">Hold Type:</label>
|
||||
<input type="text" id="edit_hold_type" name="hold_type" value="{{ hold_type.hold_type }}" required>
|
||||
<input type="text" id="edit_hold_type" name="hold_type" value="{{ hold_type[1] }}" required>
|
||||
<button type="submit">Update</button>
|
||||
<a href="{{ url_for('hold_types.add_hold_type') }}"></a>
|
||||
</form>
|
||||
@@ -37,7 +37,7 @@
|
||||
formData.append('hold_type', newHoldType);
|
||||
|
||||
$.ajax({
|
||||
url: '/edit_hold_type/' + holdTypeId,
|
||||
url: '/update_hold_type/' + holdTypeId,
|
||||
method: 'POST',
|
||||
data: formData,
|
||||
processData: false,
|
||||
@@ -54,4 +54,9 @@
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
{% block content %}
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title>Edit Invoice</title>
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/invoice.css') }}">
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style1.css') }}">
|
||||
@@ -12,174 +12,158 @@
|
||||
|
||||
<body>
|
||||
|
||||
<div id="editForm">
|
||||
<h2>Edit Invoice</h2>
|
||||
<div id="editForm">
|
||||
<h2>Edit Invoice</h2>
|
||||
|
||||
<!-- Success Alert Box -->
|
||||
<div id="invoiceSuccessAlert" class="success-alert" style="display:none;">
|
||||
Invoice successfully updated!
|
||||
</div>
|
||||
|
||||
<form id="invoiceForm" action="{{ url_for('invoice.edit_invoice', invoice_id=invoice.Invoice_Id) }}"
|
||||
method="POST">
|
||||
|
||||
<!-- Subcontractor Field -->
|
||||
<div class="row1">
|
||||
<div>
|
||||
<label for="subcontractor">Subcontractor Name:</label>
|
||||
<input class="form-control" list="subcontractor_list" id="subcontractor" name="subcontractor"
|
||||
value="{{ invoice.Contractor_Name }}" placeholder="Type to search..." required>
|
||||
<input type="hidden" id="subcontractor_id" name="subcontractor_id"
|
||||
value="{{ invoice.Subcontractor_Id }}">
|
||||
<datalist id="subcontractor_list"></datalist>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Village and PMC No Fields -->
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="village">Village Name:</label>
|
||||
<input type="text" id="village" name="village" value="{{ invoice.Village_Name }}" required />
|
||||
<datalist id="village_list"></datalist>
|
||||
</div>
|
||||
<div>
|
||||
<label for="pmc_no">PMC No:</label>
|
||||
<input type="text" id="pmc_no" name="pmc_no" value="{{ invoice.PMC_No }}" required />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Work Type and Invoice Details -->
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="work_type">Work Type:</label>
|
||||
<input type="text" id="work_type" name="work_type" value="{{ invoice.Work_Type }}" required />
|
||||
</div>
|
||||
<div>
|
||||
<label for="invoice_details">Invoice Details:</label>
|
||||
<textarea id="invoice_details" name="invoice_details"
|
||||
required>{{ invoice.Invoice_Details }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Invoice No and Invoice Date -->
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="invoice_no">Invoice No:</label>
|
||||
<input type="text" id="invoice_no" name="invoice_no" value="{{ invoice.invoice_no }}" required />
|
||||
</div>
|
||||
<div>
|
||||
<label for="invoice_date">Invoice Date:</label>
|
||||
<input type="date" id="invoice_date" name="invoice_date" value="{{ invoice.Invoice_Date }}"
|
||||
required />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Amount Fields -->
|
||||
<div class="row3">
|
||||
<div>
|
||||
<label for="basic_amount">Basic Amount:</label>
|
||||
<input type="number" step="0.01" id="basic_amount" name="basic_amount"
|
||||
value="{{ invoice.Basic_Amount }}" required />
|
||||
</div>
|
||||
<div>
|
||||
<label for="debit_amount">Debit Amount:</label>
|
||||
<input type="number" step="0.01" id="debit_amount" name="debit_amount"
|
||||
value="{{ invoice.Debit_Amount }}" required />
|
||||
</div>
|
||||
<div>
|
||||
<label for="after_debit_amount">After Debit Amount:</label>
|
||||
<input type="number" step="0.01" id="after_debit_amount" name="after_debit_amount"
|
||||
value="{{ invoice.After_Debit_Amount }}" required />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- GST, TDS, and Other Amounts -->
|
||||
<div class="row3">
|
||||
<div>
|
||||
<label for="amount">Amount:</label>
|
||||
<input type="number" step="0.01" id="amount" name="amount" value="{{ invoice.Amount }}" required />
|
||||
</div>
|
||||
<div>
|
||||
<label for="gst_amount">GST Amount:</label>
|
||||
<input type="number" step="0.01" id="gst_amount" name="gst_amount" value="{{ invoice.GST_Amount }}"
|
||||
required />
|
||||
</div>
|
||||
<div>
|
||||
<label for="tds_amount">TDS Amount:</label>
|
||||
<input type="number" step="0.01" id="tds_amount" name="tds_amount" value="{{ invoice.TDS_Amount }}"
|
||||
required />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SD, On Commission, Hydro Testing -->
|
||||
<div class="row3">
|
||||
<div>
|
||||
<label for="sd_amount">SD Amount:</label>
|
||||
<input type="number" step="0.01" id="sd_amount" name="sd_amount" value="{{ invoice.SD_Amount }}"
|
||||
required />
|
||||
</div>
|
||||
<div>
|
||||
<label for="on_commission">On Commission:</label>
|
||||
<input type="number" step="0.01" id="on_commission" name="on_commission"
|
||||
value="{{ invoice.On_Commission }}" required />
|
||||
</div>
|
||||
<div>
|
||||
<label for="hydro_testing">Hydro Testing:</label>
|
||||
<input type="number" step="0.01" id="hydro_testing" name="hydro_testing"
|
||||
value="{{ invoice.Hydro_Testing }}" required />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hold Amount Section -->
|
||||
<div id="hold_amount_container">
|
||||
{% set seen_types = [] %}
|
||||
{% for hold in invoice.hold_amounts %}
|
||||
{% if hold.hold_type not in seen_types %}
|
||||
{% set _ = seen_types.append(hold.hold_type) %}
|
||||
<div class="hold-amount-row">
|
||||
<label for="hold_type_{{ loop.index }}">Hold Type:</label>
|
||||
<input type="text" id="hold_type_{{ loop.index }}" name="hold_type[]" value="{{ hold.hold_type }}"
|
||||
required />
|
||||
<label for="hold_amount_{{ loop.index }}">Hold Amount:</label>
|
||||
<input type="number" step="0.01" id="hold_amount_{{ loop.index }}" name="hold_amount[]"
|
||||
value="{{ hold.hold_amount }}" required />
|
||||
<button type="button" class="remove-hold-amount">Remove</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="hold-row">
|
||||
<button type="button" id="add_hold_amount" class="button">+ Add Hold Amount</button>
|
||||
</div>
|
||||
|
||||
<!-- Final Amounts -->
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="gst_sd_amount">GST SD Amount:</label>
|
||||
<input type="number" step="0.01" id="gst_sd_amount" name="gst_sd_amount"
|
||||
value="{{ invoice.GST_SD_Amount }}" required />
|
||||
</div>
|
||||
<div>
|
||||
<label for="final_amount">Final Amount:</label>
|
||||
<input type="number" step="0.01" id="final_amount" name="final_amount"
|
||||
value="{{ invoice.Final_Amount }}" required />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<button type="submit" class="button">Update</button>
|
||||
</form>
|
||||
<!-- Success Alert Box -->
|
||||
<div id="invoiceSuccessAlert" class="success-alert" style="display:none;">
|
||||
Invoice successfully updated!
|
||||
</div>
|
||||
|
||||
<!-- JS for dynamic hold amount rows -->
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
// Add new hold amount row
|
||||
$("#add_hold_amount").click(function () {
|
||||
const index = $("#hold_amount_container .hold-amount-row").length;
|
||||
const newRow = `
|
||||
<form id="invoiceForm" action="{{ url_for('invoice.edit_invoice', invoice_id=invoice.Invoice_Id) }}" method="POST">
|
||||
|
||||
<!-- Subcontractor Field -->
|
||||
<div class="row1">
|
||||
<div>
|
||||
<label for="subcontractor">Subcontractor Name:</label>
|
||||
<input class="form-control" list="subcontractor_list" id="subcontractor" name="subcontractor"
|
||||
value="{{ invoice.Contractor_Name }}" placeholder="Type to search..." required>
|
||||
<input type="hidden" id="subcontractor_id" name="subcontractor_id" value="{{ invoice.Subcontractor_Id }}">
|
||||
<datalist id="subcontractor_list"></datalist>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Village and PMC No Fields -->
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="village">Village Name:</label>
|
||||
<input type="text" id="village" name="village" value="{{ invoice.Village_Name }}" required/>
|
||||
<datalist id="village_list"></datalist>
|
||||
</div>
|
||||
<div>
|
||||
<label for="pmc_no">PMC No:</label>
|
||||
<input type="text" id="pmc_no" name="pmc_no" value="{{ invoice.PMC_No }}" required/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Work Type and Invoice Details -->
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="work_type">Work Type:</label>
|
||||
<input type="text" id="work_type" name="work_type" value="{{ invoice.Work_Type }}" required/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="invoice_details">Invoice Details:</label>
|
||||
<textarea id="invoice_details" name="invoice_details" required>{{ invoice.Invoice_Details }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Invoice No and Invoice Date -->
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="invoice_no">Invoice No:</label>
|
||||
<input type="text" id="invoice_no" name="invoice_no" value="{{ invoice.Invoice_No }}" required/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="invoice_date">Invoice Date:</label>
|
||||
<input type="date" id="invoice_date" name="invoice_date" value="{{ invoice.Invoice_Date }}" required/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Amount Fields -->
|
||||
<div class="row3">
|
||||
<div>
|
||||
<label for="basic_amount">Basic Amount:</label>
|
||||
<input type="number" step="0.01" id="basic_amount" name="basic_amount" value="{{ invoice.Basic_Amount }}" required/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="debit_amount">Debit Amount:</label>
|
||||
<input type="number" step="0.01" id="debit_amount" name="debit_amount" value="{{ invoice.Debit_Amount }}" required/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="after_debit_amount">After Debit Amount:</label>
|
||||
<input type="number" step="0.01" id="after_debit_amount" name="after_debit_amount" value="{{ invoice.After_Debit_Amount }}" required/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- GST, TDS, and Other Amounts -->
|
||||
<div class="row3">
|
||||
<div>
|
||||
<label for="amount">Amount:</label>
|
||||
<input type="number" step="0.01" id="amount" name="amount" value="{{ invoice.Amount }}" required/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="gst_amount">GST Amount:</label>
|
||||
<input type="number" step="0.01" id="gst_amount" name="gst_amount" value="{{ invoice.GST_Amount }}" required/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="tds_amount">TDS Amount:</label>
|
||||
<input type="number" step="0.01" id="tds_amount" name="tds_amount" value="{{ invoice.TDS_Amount }}" required/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SD, On Commission, Hydro Testing -->
|
||||
<div class="row3">
|
||||
<div>
|
||||
<label for="sd_amount">SD Amount:</label>
|
||||
<input type="number" step="0.01" id="sd_amount" name="sd_amount" value="{{ invoice.SD_Amount }}" required/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="on_commission">On Commission:</label>
|
||||
<input type="number" step="0.01" id="on_commission" name="on_commission" value="{{ invoice.On_Commission }}" required/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="hydro_testing">Hydro Testing:</label>
|
||||
<input type="number" step="0.01" id="hydro_testing" name="hydro_testing" value="{{ invoice.Hydro_Testing }}" required/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hold Amount Section -->
|
||||
<div id="hold_amount_container">
|
||||
{% set seen_types = [] %}
|
||||
{% for hold in invoice.hold_amounts %}
|
||||
{% if hold.hold_type not in seen_types %}
|
||||
{% set _ = seen_types.append(hold.hold_type) %}
|
||||
<div class="hold-amount-row">
|
||||
<label for="hold_type_{{ loop.index }}">Hold Type:</label>
|
||||
<input type="text" id="hold_type_{{ loop.index }}" name="hold_type[]" value="{{ hold.hold_type }}" required/>
|
||||
<label for="hold_amount_{{ loop.index }}">Hold Amount:</label>
|
||||
<input type="number" step="0.01" id="hold_amount_{{ loop.index }}" name="hold_amount[]" value="{{ hold.hold_amount }}" required/>
|
||||
<button type="button" class="remove-hold-amount">Remove</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="hold-row">
|
||||
<button type="button" id="add_hold_amount" class="button">+ Add Hold Amount</button>
|
||||
</div>
|
||||
|
||||
<!-- Final Amounts -->
|
||||
<div class="row2">
|
||||
<div>
|
||||
<label for="gst_sd_amount">GST SD Amount:</label>
|
||||
<input type="number" step="0.01" id="gst_sd_amount" name="gst_sd_amount" value="{{ invoice.GST_SD_Amount }}" required/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="final_amount">Final Amount:</label>
|
||||
<input type="number" step="0.01" id="final_amount" name="final_amount" value="{{ invoice.Final_Amount }}" required/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<button type="submit" class="button">Update</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- JS for dynamic hold amount rows -->
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Add new hold amount row
|
||||
$("#add_hold_amount").click(function() {
|
||||
const index = $("#hold_amount_container .hold-amount-row").length;
|
||||
const newRow = `
|
||||
<div class="hold-amount-row">
|
||||
<label for="hold_type_${index}">Hold Type:</label>
|
||||
<input type="text" id="hold_type_${index}" name="hold_type[]" required/>
|
||||
@@ -188,36 +172,36 @@
|
||||
<button type="button" class="remove-hold-amount">Remove</button>
|
||||
</div>
|
||||
`;
|
||||
$("#hold_amount_container").append(newRow);
|
||||
});
|
||||
$("#hold_amount_container").append(newRow);
|
||||
});
|
||||
|
||||
// Remove hold amount row
|
||||
$(document).on("click", ".remove-hold-amount", function () {
|
||||
$(this).closest(".hold-amount-row").remove();
|
||||
});
|
||||
// Remove hold amount row
|
||||
$(document).on("click", ".remove-hold-amount", function() {
|
||||
$(this).closest(".hold-amount-row").remove();
|
||||
});
|
||||
|
||||
// Submit form via AJAX
|
||||
$("#invoiceForm").submit(function (e) {
|
||||
e.preventDefault();
|
||||
// Submit form via AJAX
|
||||
$("#invoiceForm").submit(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: $(this).attr("action"),
|
||||
data: $(this).serialize(),
|
||||
success: function (response) {
|
||||
if (response.status === "success") {
|
||||
$("#invoiceSuccessAlert").fadeIn().delay(3000).fadeOut();
|
||||
alert("Invoice updated successfully!"); // <-- Popup alert
|
||||
}
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: $(this).attr("action"),
|
||||
data: $(this).serialize(),
|
||||
success: function(response) {
|
||||
if(response.status === "success") {
|
||||
$("#invoiceSuccessAlert").fadeIn().delay(3000).fadeOut();
|
||||
alert("Invoice updated successfully!"); // <-- Popup alert
|
||||
}
|
||||
|
||||
},
|
||||
error: function (xhr) {
|
||||
alert("Error: " + xhr.responseJSON.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
error: function(xhr) {
|
||||
alert("Error: " + xhr.responseJSON.message);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
{% endblock %}
|
||||
@@ -28,17 +28,25 @@
|
||||
|
||||
<button type="submit">Update Village</button>
|
||||
</form>
|
||||
<!-- Flash Messages (hidden, used for JS popup) -->
|
||||
<div id="flash-messages-container" style="display:none;">
|
||||
</div>
|
||||
|
||||
<!-- Flash Message (Hidden, used for JS popup) -->
|
||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
<div class="flash-message" data-category="{{ category }}">{{ message }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if messages %}
|
||||
{% for category, message in messages %}
|
||||
<div id="flash-message" data-category="{{ category }}" style="display:none;">{{ message }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
window.onload = function () {
|
||||
const flash = document.getElementById('flash-message');
|
||||
if (flash && flash.innerText.trim() !== "") {
|
||||
alert(flash.innerText);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user