1 Commits

Author SHA1 Message Date
dbeec9962d hold type updated , delete done by prajkta 2026-03-24 15:19:38 +05:30
41 changed files with 446 additions and 362 deletions

Binary file not shown.

View File

@@ -1,8 +1,8 @@
# routes/gst_release_routes.py
from flask import Blueprint, render_template, request, redirect, url_for, flash
from flask import Blueprint, render_template, request, redirect, url_for
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", "User added GST release")
LogHelper.log_action("Add GST Release", f"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", "User edited GST release")
LogHelper.log_action("Edit GST Release", f"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)
LogHelper.log_action("Delete GST Release", "User deleted GST release")
gst_service.DeleteGSTRelease(gst_release_id) # remove request
LogHelper.log_action("Delete GST Release", f"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'))

View File

@@ -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()
if request.method == 'POST':
hold.AddHoldType(request) # ✅
return hold.resultMessage
hold.AddHoldType(request)
# ✅ Always redirect to same page (NO JSON)
return redirect(url_for("hold_types.add_hold_type"))
hold_types = hold.GetAllHoldTypes() # ✅
# GET request → show data
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

View File

@@ -6,6 +6,7 @@ import config
import re
import mysql.connector
# ----------------------------------------------------------
# Mapping Class
# ----------------------------------------------------------
@@ -22,11 +23,10 @@ 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,47 +93,13 @@ class ItemCRUD:
try:
# ======================================================
# GSTRelease MULTI-FIELD
# SUBCONTRACTOR (MULTI-FIELD)
# ======================================================
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:
if data:
# Duplicate check
cursor.callproc(storedprocfetch, (data['Contractor_Name'],))
existing_item = None
for rs in cursor.stored_results():
existing_item = rs.fetchone()
@@ -145,6 +111,7 @@ class ItemCRUD:
)
return
# Insert
cursor.callproc(storedprocadd, (
data['Contractor_Name'],
data['Address'],
@@ -156,24 +123,26 @@ 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 SINGLE-FIELD (Village / Block / State)
# NORMAL (Village / Block / State)
# ======================================================
if not re.match(RegEx.patternAlphabetOnly, childname):
if not re.match(RegEx.allPattern, 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:
@@ -190,14 +159,17 @@ 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
)
@@ -227,33 +199,9 @@ class ItemCRUD:
try:
# ======================================================
# GSTRelease MULTI-FIELD
# SUBCONTRACTOR (MULTI-FIELD)
# ======================================================
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:
if data:
cursor.callproc(storedprocupdate, (
childid,
data['Contractor_Name'],
@@ -266,7 +214,9 @@ 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
@@ -274,9 +224,9 @@ class ItemCRUD:
return
# ======================================================
# NORMAL SINGLE-FIELD
# NORMAL
# ======================================================
if not re.match(RegEx.patternAlphabetOnly, childname):
if not re.match(RegEx.allPattern, childname):
self.isSuccess = False
self.resultMessage = ResponseHandler.update_failure(self.itemCRUDMapping.name)['message']
return
@@ -287,6 +237,7 @@ class ItemCRUD:
cursor.callproc(storedprocupdate, (childid, parentid, childname))
connection.commit()
self.isSuccess = True
self.resultMessage = ResponseHandler.update_success(self.itemCRUDMapping.name)['message']
@@ -308,15 +259,20 @@ 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
@@ -324,6 +280,7 @@ class ItemCRUD:
ResponseHandler.fetch_failure(self.itemCRUDMapping.name), 500
)
return []
finally:
cursor.close()
connection.close()
@@ -341,10 +298,13 @@ 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()
@@ -364,7 +324,7 @@ class ItemCRUD:
f"User {current_user.id} checked '{childname}'"
)
if not re.match(RegEx.patternAlphabetOnly, childname):
if not re.match(RegEx.allPattern, childname):
return HtmlHelper.json_response(
ResponseHandler.invalid_name(self.itemCRUDMapping.name), 400
)
@@ -393,6 +353,7 @@ class ItemCRUD:
return HtmlHelper.json_response(
ResponseHandler.fetch_failure(self.itemCRUDMapping.name), 500
)
finally:
cursor.close()
connection.close()

View File

@@ -8,10 +8,11 @@ class ItemCRUDType(Enum):
State = 4
HoldType = 5
Subcontractor = 6
GSTRelease = 7
class RegEx:
patternAlphabetOnly = "^[A-Za-z ]+$"
allPattern = "^(?!\s*$).+"
class ResponseHandler:

View File

@@ -1,8 +1,109 @@
# model/gst_release.py
# 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)
from flask import request, jsonify
from model.ItemCRUD import ItemCRUD
from model.Utilities import ItemCRUDType
class GSTRelease:
def __init__(self):
@@ -24,7 +125,6 @@ class GSTRelease:
"Contractor_ID": int(request.form.get("Contractor_ID", 0) or 0)
}
# Add GST Release
gst.AddItem(
request=request,
data=data,
@@ -32,12 +132,6 @@ class GSTRelease:
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)
@@ -104,6 +198,7 @@ class GSTRelease:
def GetAllGSTReleases(self):
try:
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
rows = gst.GetAllData(None, "GetAllGSTReleases")
data = []
@@ -129,6 +224,7 @@ class GSTRelease:
def GetGSTReleaseByID(self, gst_release_id):
try:
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
row = gst.GetDataByID(gst_release_id, "GetGSTReleaseById")
if row:

View File

@@ -3,7 +3,7 @@ $(document).ready(function () {
let holdType = $(this).val().replace(/^\s+/, "");
$(this).val(holdType);
let reg = /^[A-Za-z]/;
let reg = /^.+$/; // all pattern allow
if (!reg.test(holdType)) {
$("#holdTypeMessage").text("Hold Type must start with a letter.").css("color", "red");

View File

@@ -68,11 +68,10 @@
{% 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="Search..." onkeyup="searchTable()">
<input type="text" id="searchBar" placeholder="Searching..." onkeyup="searchTable()">
</div>
<table id="sortableTable" border="1">
<thead>
@@ -91,22 +90,24 @@
<tbody>
{% 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>{{ 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="{{ 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 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="{{ url_for('gst_release_bp.delete_gst_release', gst_release_id=gst_rel.gst_release_id) }}"
<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">
<img src="{{ url_for('static', filename='images/icons/bin_red_icon.png') }}" alt="Delete"
class="icon">
</a>
</td>
</tr>

View File

@@ -1,5 +1,6 @@
{% extends 'base.html' %}
{% block content %}
<head>
<title>Manage Hold Types</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
@@ -7,14 +8,15 @@
<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>
</head>
<body>
<div class="button-container">
<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">
<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>
@@ -22,9 +24,9 @@
<span id="holdTypeMessage"></span>
<button type="submit" value="Add Hold Type" id="successPopup">Add Hold Type</button>
</form>
</div>
</div>
<div id="addTable" style="display: none;">
<div id="addTable" style="display: none;">
<div class="search-container">
<h2>Hold Type List</h2>
<input type="text" id="searchBar" placeholder="Searching..." onkeyup="searchTable()">
@@ -46,14 +48,26 @@
<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>
<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>
</div>
</body>
{% endblock %}

View File

@@ -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">
<input type="hidden" id="hold_type_id" value="{{ hold_type[0] }}">
<form id="updateHoldTypeForm" method="POST">
<input type="hidden" id="hold_type_id" value="{{ hold_type.hold_type_id }}">
<label for="edit_hold_type">Hold Type:</label>
<input type="text" id="edit_hold_type" name="hold_type" value="{{ hold_type[1] }}" required>
<input type="text" id="edit_hold_type" name="hold_type" value="{{ hold_type.hold_type }}" 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: '/update_hold_type/' + holdTypeId,
url: '/edit_hold_type/' + holdTypeId,
method: 'POST',
data: formData,
processData: false,
@@ -55,8 +55,3 @@
});
</script>
{% endblock %}

View File

@@ -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,7 +12,7 @@
<body>
<div id="editForm">
<div id="editForm">
<h2>Edit Invoice</h2>
<!-- Success Alert Box -->
@@ -20,7 +20,8 @@
Invoice successfully updated!
</div>
<form id="invoiceForm" action="{{ url_for('invoice.edit_invoice', invoice_id=invoice.Invoice_Id) }}" method="POST">
<form id="invoiceForm" action="{{ url_for('invoice.edit_invoice', invoice_id=invoice.Invoice_Id) }}"
method="POST">
<!-- Subcontractor Field -->
<div class="row1">
@@ -28,7 +29,8 @@
<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 }}">
<input type="hidden" id="subcontractor_id" name="subcontractor_id"
value="{{ invoice.Subcontractor_Id }}">
<datalist id="subcontractor_list"></datalist>
</div>
</div>
@@ -37,12 +39,12 @@
<div class="row2">
<div>
<label for="village">Village Name:</label>
<input type="text" id="village" name="village" value="{{ invoice.Village_Name }}" required/>
<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/>
<input type="text" id="pmc_no" name="pmc_no" value="{{ invoice.PMC_No }}" required />
</div>
</div>
@@ -50,11 +52,12 @@
<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/>
<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>
<textarea id="invoice_details" name="invoice_details"
required>{{ invoice.Invoice_Details }}</textarea>
</div>
</div>
@@ -62,11 +65,12 @@
<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/>
<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/>
<input type="date" id="invoice_date" name="invoice_date" value="{{ invoice.Invoice_Date }}"
required />
</div>
</div>
@@ -74,15 +78,18 @@
<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/>
<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/>
<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/>
<input type="number" step="0.01" id="after_debit_amount" name="after_debit_amount"
value="{{ invoice.After_Debit_Amount }}" required />
</div>
</div>
@@ -90,15 +97,17 @@
<div class="row3">
<div>
<label for="amount">Amount:</label>
<input type="number" step="0.01" id="amount" name="amount" value="{{ invoice.Amount }}" required/>
<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/>
<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/>
<input type="number" step="0.01" id="tds_amount" name="tds_amount" value="{{ invoice.TDS_Amount }}"
required />
</div>
</div>
@@ -106,34 +115,39 @@
<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/>
<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/>
<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/>
<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">
<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/>
<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/>
<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>
<div class="hold-row">
@@ -144,24 +158,26 @@
<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/>
<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/>
<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>
</div>
<!-- JS for dynamic hold amount rows -->
<script>
$(document).ready(function() {
<!-- JS for dynamic hold amount rows -->
<script>
$(document).ready(function () {
// Add new hold amount row
$("#add_hold_amount").click(function() {
$("#add_hold_amount").click(function () {
const index = $("#hold_amount_container .hold-amount-row").length;
const newRow = `
<div class="hold-amount-row">
@@ -176,32 +192,32 @@ $(document).ready(function() {
});
// Remove hold amount row
$(document).on("click", ".remove-hold-amount", function() {
$(document).on("click", ".remove-hold-amount", function () {
$(this).closest(".hold-amount-row").remove();
});
// Submit form via AJAX
$("#invoiceForm").submit(function(e) {
$("#invoiceForm").submit(function (e) {
e.preventDefault();
$.ajax({
type: "POST",
url: $(this).attr("action"),
data: $(this).serialize(),
success: function(response) {
if(response.status === "success") {
success: function (response) {
if (response.status === "success") {
$("#invoiceSuccessAlert").fadeIn().delay(3000).fadeOut();
alert("Invoice updated successfully!"); // <-- Popup alert
}
},
error: function(xhr) {
error: function (xhr) {
alert("Error: " + xhr.responseJSON.message);
}
});
});
});
</script>
});
</script>
</body>
{% endblock %}