Merge branch 'main' of https://gitea.lcepl.org/pjpatil12/Payment_Reconciliation into pankaj-dev
This commit is contained in:
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 flask_login import login_required
|
||||||
from model.gst_release import GSTRelease
|
from model.gst_release import GSTRelease
|
||||||
from model.Log import LogHelper
|
from model.Log import LogHelper
|
||||||
from flask import flash, current_app
|
|
||||||
|
|
||||||
gst_release_bp = Blueprint('gst_release_bp', __name__)
|
gst_release_bp = Blueprint('gst_release_bp', __name__)
|
||||||
gst_service = GSTRelease()
|
gst_service = GSTRelease()
|
||||||
@@ -13,7 +13,7 @@ gst_service = GSTRelease()
|
|||||||
def add_gst_release():
|
def add_gst_release():
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
gst_service.AddGSTRelease(request)
|
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')
|
flash(gst_service.resultMessage, 'success' if gst_service.isSuccess else 'error')
|
||||||
return redirect(url_for('gst_release_bp.add_gst_release'))
|
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':
|
if request.method == 'POST':
|
||||||
gst_service.EditGSTRelease(request, gst_release_id)
|
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')
|
flash(gst_service.resultMessage, 'success' if gst_service.isSuccess else 'error')
|
||||||
return redirect(url_for('gst_release_bp.add_gst_release'))
|
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'])
|
@gst_release_bp.route('/delete_gst_release/<int:gst_release_id>', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def delete_gst_release(gst_release_id):
|
def delete_gst_release(gst_release_id):
|
||||||
gst_service.DeleteGSTRelease(gst_release_id) # remove request
|
gst_service.DeleteGSTRelease(gst_release_id)
|
||||||
LogHelper.log_action("Delete GST Release", f"User deleted GST release")
|
LogHelper.log_action("Delete GST Release", "User deleted GST release")
|
||||||
flash(gst_service.resultMessage, 'success' if gst_service.isSuccess else 'error')
|
flash(gst_service.resultMessage, 'success' if gst_service.isSuccess else 'error')
|
||||||
return redirect(url_for('gst_release_bp.add_gst_release'))
|
return redirect(url_for('gst_release_bp.add_gst_release'))
|
||||||
@@ -6,7 +6,6 @@ import config
|
|||||||
import re
|
import re
|
||||||
import mysql.connector
|
import mysql.connector
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
# Mapping Class
|
# Mapping Class
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
@@ -23,10 +22,11 @@ class itemCRUDMapping:
|
|||||||
self.name = "Hold Type"
|
self.name = "Hold Type"
|
||||||
elif itemType is ItemCRUDType.Subcontractor:
|
elif itemType is ItemCRUDType.Subcontractor:
|
||||||
self.name = "Subcontractor"
|
self.name = "Subcontractor"
|
||||||
|
elif itemType.name == "GSTRelease":
|
||||||
|
self.name = "GSTRelease"
|
||||||
else:
|
else:
|
||||||
self.name = "Item"
|
self.name = "Item"
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
# Generic CRUD Class
|
# Generic CRUD Class
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
@@ -93,13 +93,47 @@ class ItemCRUD:
|
|||||||
|
|
||||||
try:
|
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'],))
|
cursor.callproc(storedprocfetch, (data['Contractor_Name'],))
|
||||||
|
|
||||||
existing_item = None
|
existing_item = None
|
||||||
for rs in cursor.stored_results():
|
for rs in cursor.stored_results():
|
||||||
existing_item = rs.fetchone()
|
existing_item = rs.fetchone()
|
||||||
@@ -111,7 +145,6 @@ class ItemCRUD:
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Insert
|
|
||||||
cursor.callproc(storedprocadd, (
|
cursor.callproc(storedprocadd, (
|
||||||
data['Contractor_Name'],
|
data['Contractor_Name'],
|
||||||
data['Address'],
|
data['Address'],
|
||||||
@@ -123,17 +156,16 @@ class ItemCRUD:
|
|||||||
data['GST_No'],
|
data['GST_No'],
|
||||||
data['Contractor_password']
|
data['Contractor_password']
|
||||||
))
|
))
|
||||||
|
|
||||||
connection.commit()
|
connection.commit()
|
||||||
|
|
||||||
self.isSuccess = True
|
self.isSuccess = True
|
||||||
self.resultMessage = HtmlHelper.json_response(
|
self.resultMessage = HtmlHelper.json_response(
|
||||||
ResponseHandler.add_success(self.itemCRUDMapping.name), 200
|
ResponseHandler.add_success(self.itemCRUDMapping.name), 200
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
# ======================================================
|
# ======================================================
|
||||||
# NORMAL (Village / Block / State)
|
# NORMAL SINGLE-FIELD (Village / Block / State)
|
||||||
# ======================================================
|
# ======================================================
|
||||||
if not re.match(RegEx.allPattern, childname):
|
if not re.match(RegEx.allPattern, childname):
|
||||||
self.isSuccess = False
|
self.isSuccess = False
|
||||||
@@ -142,7 +174,6 @@ class ItemCRUD:
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Duplicate check
|
|
||||||
if parentid is None:
|
if parentid is None:
|
||||||
cursor.callproc(storedprocfetch, (childname,))
|
cursor.callproc(storedprocfetch, (childname,))
|
||||||
else:
|
else:
|
||||||
@@ -159,17 +190,14 @@ class ItemCRUD:
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Insert
|
|
||||||
if parentid is None:
|
if parentid is None:
|
||||||
cursor.callproc(storedprocadd, (childname,))
|
cursor.callproc(storedprocadd, (childname,))
|
||||||
else:
|
else:
|
||||||
cursor.callproc(storedprocadd, (childname, parentid))
|
cursor.callproc(storedprocadd, (childname, parentid))
|
||||||
|
|
||||||
connection.commit()
|
connection.commit()
|
||||||
|
|
||||||
self.isSuccess = True
|
self.isSuccess = True
|
||||||
self.resultMessage = HtmlHelper.json_response(
|
self.resultMessage = HtmlHelper.json_response(
|
||||||
|
|
||||||
ResponseHandler.add_success(self.itemCRUDMapping.name), 200
|
ResponseHandler.add_success(self.itemCRUDMapping.name), 200
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -199,9 +227,33 @@ class ItemCRUD:
|
|||||||
|
|
||||||
try:
|
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, (
|
cursor.callproc(storedprocupdate, (
|
||||||
childid,
|
childid,
|
||||||
data['Contractor_Name'],
|
data['Contractor_Name'],
|
||||||
@@ -214,9 +266,7 @@ class ItemCRUD:
|
|||||||
data['GST_No'],
|
data['GST_No'],
|
||||||
data['Contractor_password']
|
data['Contractor_password']
|
||||||
))
|
))
|
||||||
|
|
||||||
connection.commit()
|
connection.commit()
|
||||||
|
|
||||||
self.isSuccess = True
|
self.isSuccess = True
|
||||||
self.resultMessage = HtmlHelper.json_response(
|
self.resultMessage = HtmlHelper.json_response(
|
||||||
ResponseHandler.update_success(self.itemCRUDMapping.name), 200
|
ResponseHandler.update_success(self.itemCRUDMapping.name), 200
|
||||||
@@ -224,7 +274,7 @@ class ItemCRUD:
|
|||||||
return
|
return
|
||||||
|
|
||||||
# ======================================================
|
# ======================================================
|
||||||
# NORMAL
|
# NORMAL SINGLE-FIELD
|
||||||
# ======================================================
|
# ======================================================
|
||||||
if not re.match(RegEx.allPattern, childname):
|
if not re.match(RegEx.allPattern, childname):
|
||||||
self.isSuccess = False
|
self.isSuccess = False
|
||||||
@@ -237,7 +287,6 @@ class ItemCRUD:
|
|||||||
cursor.callproc(storedprocupdate, (childid, parentid, childname))
|
cursor.callproc(storedprocupdate, (childid, parentid, childname))
|
||||||
|
|
||||||
connection.commit()
|
connection.commit()
|
||||||
|
|
||||||
self.isSuccess = True
|
self.isSuccess = True
|
||||||
self.resultMessage = ResponseHandler.update_success(self.itemCRUDMapping.name)['message']
|
self.resultMessage = ResponseHandler.update_success(self.itemCRUDMapping.name)['message']
|
||||||
|
|
||||||
@@ -259,20 +308,15 @@ class ItemCRUD:
|
|||||||
|
|
||||||
data = []
|
data = []
|
||||||
connection = config.get_db_connection()
|
connection = config.get_db_connection()
|
||||||
|
|
||||||
if not connection:
|
if not connection:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cursor.callproc(storedproc)
|
cursor.callproc(storedproc)
|
||||||
|
|
||||||
for result in cursor.stored_results():
|
for result in cursor.stored_results():
|
||||||
data = result.fetchall()
|
data = result.fetchall()
|
||||||
|
|
||||||
self.isSuccess = True
|
self.isSuccess = True
|
||||||
|
|
||||||
except mysql.connector.Error as e:
|
except mysql.connector.Error as e:
|
||||||
print(f"Error fetching {self.itemCRUDMapping.name}: {e}")
|
print(f"Error fetching {self.itemCRUDMapping.name}: {e}")
|
||||||
self.isSuccess = False
|
self.isSuccess = False
|
||||||
@@ -280,7 +324,6 @@ class ItemCRUD:
|
|||||||
ResponseHandler.fetch_failure(self.itemCRUDMapping.name), 500
|
ResponseHandler.fetch_failure(self.itemCRUDMapping.name), 500
|
||||||
)
|
)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
cursor.close()
|
cursor.close()
|
||||||
connection.close()
|
connection.close()
|
||||||
@@ -298,13 +341,10 @@ class ItemCRUD:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
cursor.callproc(storedproc, (id,))
|
cursor.callproc(storedproc, (id,))
|
||||||
|
|
||||||
for rs in cursor.stored_results():
|
for rs in cursor.stored_results():
|
||||||
data = rs.fetchone()
|
data = rs.fetchone()
|
||||||
|
|
||||||
except mysql.connector.Error as e:
|
except mysql.connector.Error as e:
|
||||||
print(f"Error fetching {self.itemCRUDMapping.name}: {e}")
|
print(f"Error fetching {self.itemCRUDMapping.name}: {e}")
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
cursor.close()
|
cursor.close()
|
||||||
connection.close()
|
connection.close()
|
||||||
@@ -353,7 +393,6 @@ class ItemCRUD:
|
|||||||
return HtmlHelper.json_response(
|
return HtmlHelper.json_response(
|
||||||
ResponseHandler.fetch_failure(self.itemCRUDMapping.name), 500
|
ResponseHandler.fetch_failure(self.itemCRUDMapping.name), 500
|
||||||
)
|
)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
cursor.close()
|
cursor.close()
|
||||||
connection.close()
|
connection.close()
|
||||||
@@ -8,7 +8,7 @@ class ItemCRUDType(Enum):
|
|||||||
State = 4
|
State = 4
|
||||||
HoldType = 5
|
HoldType = 5
|
||||||
Subcontractor = 6
|
Subcontractor = 6
|
||||||
|
GSTRelease = 7
|
||||||
|
|
||||||
class RegEx:
|
class RegEx:
|
||||||
patternAlphabetOnly = "^[A-Za-z ]+$"
|
patternAlphabetOnly = "^[A-Za-z ]+$"
|
||||||
|
|||||||
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
|
# model/gst_release.py
|
||||||
# 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 flask import request, jsonify
|
||||||
from model.ItemCRUD import ItemCRUD
|
from model.ItemCRUD import ItemCRUD
|
||||||
from model.Utilities import ItemCRUDType
|
from model.Utilities import ItemCRUDType
|
||||||
|
|
||||||
|
|
||||||
class GSTRelease:
|
class GSTRelease:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -125,6 +24,7 @@ class GSTRelease:
|
|||||||
"Contractor_ID": int(request.form.get("Contractor_ID", 0) or 0)
|
"Contractor_ID": int(request.form.get("Contractor_ID", 0) or 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Add GST Release
|
||||||
gst.AddItem(
|
gst.AddItem(
|
||||||
request=request,
|
request=request,
|
||||||
data=data,
|
data=data,
|
||||||
@@ -132,6 +32,12 @@ class GSTRelease:
|
|||||||
storedprocadd="AddGSTReleaseFromExcel"
|
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.isSuccess = gst.isSuccess
|
||||||
self.resultMessage = str(gst.resultMessage)
|
self.resultMessage = str(gst.resultMessage)
|
||||||
|
|
||||||
@@ -198,7 +104,6 @@ class GSTRelease:
|
|||||||
def GetAllGSTReleases(self):
|
def GetAllGSTReleases(self):
|
||||||
try:
|
try:
|
||||||
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||||
|
|
||||||
rows = gst.GetAllData(None, "GetAllGSTReleases")
|
rows = gst.GetAllData(None, "GetAllGSTReleases")
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
@@ -224,7 +129,6 @@ class GSTRelease:
|
|||||||
def GetGSTReleaseByID(self, gst_release_id):
|
def GetGSTReleaseByID(self, gst_release_id):
|
||||||
try:
|
try:
|
||||||
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||||
|
|
||||||
row = gst.GetDataByID(gst_release_id, "GetGSTReleaseById")
|
row = gst.GetDataByID(gst_release_id, "GetGSTReleaseById")
|
||||||
|
|
||||||
if row:
|
if row:
|
||||||
|
|||||||
@@ -1,62 +1,271 @@
|
|||||||
// Subcontractor autocomplete functionality
|
// $(document).ready(function () {
|
||||||
$(document).ready(function () {
|
// // ===============================
|
||||||
$("#subcontractor").keyup(function () {
|
// // FORM / TABLE TOGGLE
|
||||||
|
// // ===============================
|
||||||
|
// if ($('#addForm').length && $('#addTable').length) {
|
||||||
|
// $('#addForm').show();
|
||||||
|
// $('#addTable').hide();
|
||||||
|
|
||||||
|
// $('#addButton').click(function () {
|
||||||
|
// $('#addForm').show();
|
||||||
|
// $('#addTable').hide();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// $('#displayButton').click(function () {
|
||||||
|
// $('#addForm').hide();
|
||||||
|
// $('#addTable').show();
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // ===============================
|
||||||
|
// // Subcontractor autocomplete
|
||||||
|
// // ===============================
|
||||||
|
// $("#subcontractor").keyup(function () {
|
||||||
|
// let query = $(this).val();
|
||||||
|
// if (query !== "") {
|
||||||
|
// $.ajax({
|
||||||
|
// url: "/search_subcontractor",
|
||||||
|
// method: "POST",
|
||||||
|
// data: { query: query },
|
||||||
|
// success: function (data) {
|
||||||
|
// $("#subcontractor_list").fadeIn().html(data);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// } else {
|
||||||
|
// $("#subcontractor_list").fadeOut();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// $(document).on("click", "li", function () {
|
||||||
|
// $("#subcontractor").val($(this).text());
|
||||||
|
// $("#subcontractor_id").val($(this).attr("data-id"));
|
||||||
|
// $("#subcontractor_list").fadeOut();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// // Focus
|
||||||
|
// if (document.getElementById('subcontractor')) {
|
||||||
|
// document.getElementById('subcontractor').focus();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // ===============================
|
||||||
|
// // ADD INVOICE
|
||||||
|
// // ===============================
|
||||||
|
// if ($('#invoiceForm').length && window.location.href.includes('add_invoice')) {
|
||||||
|
// $("#invoiceForm").on("submit", function (e) {
|
||||||
|
// e.preventDefault();
|
||||||
|
// let formData = $(this).serialize();
|
||||||
|
|
||||||
|
// $.ajax({
|
||||||
|
// url: '/add_invoice',
|
||||||
|
// method: 'POST',
|
||||||
|
// data: formData,
|
||||||
|
// dataType: 'json',
|
||||||
|
// success: function (response) {
|
||||||
|
// if (response.status === "success") {
|
||||||
|
// alert(response.message || "Invoice added successfully!");
|
||||||
|
// $('#invoiceForm')[0].reset(); // clear form
|
||||||
|
// $('#addForm').hide();
|
||||||
|
// $('#addTable').show(); // switch to table
|
||||||
|
// location.reload(); // optional refresh
|
||||||
|
// } else {
|
||||||
|
// alert(response.message || "Error adding invoice.");
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// error: function (xhr) {
|
||||||
|
// alert(xhr.responseJSON?.message || "Submission failed. Please try again.");
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// // Example AJAX update function
|
||||||
|
// function updateInvoice(invoiceId, formElement) {
|
||||||
|
// const formData = $(formElement).serialize();
|
||||||
|
|
||||||
|
// $.ajax({
|
||||||
|
// url: '/update_invoice/' + invoiceId,
|
||||||
|
// method: 'POST',
|
||||||
|
// data: formData,
|
||||||
|
// dataType: 'json',
|
||||||
|
// success: function(response) {
|
||||||
|
// if(response.status === "success") {
|
||||||
|
// alert(response.message || "Invoice updated successfully!");
|
||||||
|
|
||||||
|
// // ✅ Hide Add Form, Show Table
|
||||||
|
// $('#addForm').hide();
|
||||||
|
// $('#addTable').show();
|
||||||
|
|
||||||
|
// // Optional: reload table or refresh page
|
||||||
|
// location.reload();
|
||||||
|
// } else {
|
||||||
|
// alert(response.message || "Update failed. Please try again.");
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// error: function(xhr) {
|
||||||
|
// alert(xhr.responseJSON?.message || "Error updating invoice.");
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // ===============================
|
||||||
|
// // DELETE INVOICE
|
||||||
|
// // ===============================
|
||||||
|
// function deleteInvoice(invoiceId, element) {
|
||||||
|
// if (!confirm("Are you sure you want to delete this invoice?")) return;
|
||||||
|
|
||||||
|
// $.ajax({
|
||||||
|
// url: '/delete_invoice/' + invoiceId,
|
||||||
|
// method: 'GET',
|
||||||
|
// dataType: 'json',
|
||||||
|
// success: function (response) {
|
||||||
|
// alert(response.message || "Invoice deleted successfully!");
|
||||||
|
// if (element) $(element).closest("tr").remove();
|
||||||
|
// },
|
||||||
|
// error: function (xhr) {
|
||||||
|
// alert(xhr.responseJSON?.message || "Error deleting invoice. Please try again.");
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
// ===============================
|
||||||
|
// FORM / TABLE TOGGLE
|
||||||
|
// ===============================
|
||||||
|
if ($('#addForm').length && $('#addTable').length) {
|
||||||
|
// Default: show form, hide table
|
||||||
|
$('#addForm').show();
|
||||||
|
$('#addTable').hide();
|
||||||
|
|
||||||
|
// ✅ Check URL hash to show table instead
|
||||||
|
if (window.location.hash === "#addTable") {
|
||||||
|
$('#addForm').hide();
|
||||||
|
$('#addTable').show();
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#addButton').click(function () {
|
||||||
|
$('#addForm').show();
|
||||||
|
$('#addTable').hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#displayButton').click(function () {
|
||||||
|
$('#addForm').hide();
|
||||||
|
$('#addTable').show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===============================
|
||||||
|
// Subcontractor autocomplete
|
||||||
|
// ===============================
|
||||||
|
$("#subcontractor").keyup(function () {
|
||||||
let query = $(this).val();
|
let query = $(this).val();
|
||||||
if (query !== "") {
|
if (query !== "") {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "/search_subcontractor",
|
url: "/search_subcontractor",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
data: { query: query },
|
data: { query: query },
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
$("#subcontractor_list").fadeIn().html(data);
|
$("#subcontractor_list").fadeIn().html(data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
$("#subcontractor_list").fadeOut();
|
$("#subcontractor_list").fadeOut();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).on("click", "li", function () {
|
$(document).on("click", "li", function () {
|
||||||
$("#subcontractor").val($(this).text());
|
$("#subcontractor").val($(this).text());
|
||||||
$("#subcontractor_id").val($(this).attr("data-id"));
|
$("#subcontractor_id").val($(this).attr("data-id"));
|
||||||
$("#subcontractor_list").fadeOut();
|
$("#subcontractor_list").fadeOut();
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Success Alert: show alert and reload after 3 seconds
|
// Focus
|
||||||
function showSuccessAlert() {
|
if (document.getElementById('subcontractor')) {
|
||||||
const alertBox = document.getElementById("invoiceSuccessAlert");
|
document.getElementById('subcontractor').focus();
|
||||||
alertBox.classList.add("show");
|
|
||||||
setTimeout(() => {
|
|
||||||
alertBox.classList.remove("show");
|
|
||||||
// Reload page or redirect after alert hides
|
|
||||||
window.location.href = '/add_invoice';
|
|
||||||
}, 3000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Submit form via AJAX
|
// ===============================
|
||||||
$("#invoiceForm").on("submit", function (e) {
|
// ADD INVOICE
|
||||||
e.preventDefault();
|
// ===============================
|
||||||
let formData = $(this).serialize();
|
if ($('#invoiceForm').length && window.location.href.includes('add_invoice')) {
|
||||||
$.ajax({
|
$("#invoiceForm").on("submit", function (e) {
|
||||||
url: '/add_invoice',
|
e.preventDefault();
|
||||||
method: 'POST',
|
let formData = $(this).serialize();
|
||||||
data: formData,
|
|
||||||
success: function (response) {
|
|
||||||
if(response.status === "success") {
|
|
||||||
showSuccessAlert();
|
|
||||||
} else {
|
|
||||||
alert(response.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function (xhr, status, error) {
|
|
||||||
alert("Submission failed: " + error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '/add_invoice',
|
||||||
|
method: 'POST',
|
||||||
|
data: formData,
|
||||||
|
dataType: 'json',
|
||||||
|
success: function (response) {
|
||||||
|
if (response.status === "success") {
|
||||||
|
alert(response.message || "Invoice added successfully!");
|
||||||
|
$('#invoiceForm')[0].reset(); // clear form
|
||||||
|
$('#addForm').hide();
|
||||||
|
$('#addTable').show(); // switch to table
|
||||||
|
location.reload(); // optional refresh
|
||||||
|
} else {
|
||||||
|
alert(response.message || "Error adding invoice.");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function (xhr) {
|
||||||
|
let msg = xhr.responseJSON?.message || "Submission failed. Please try again.";
|
||||||
|
alert(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===============================
|
||||||
|
// UPDATE INVOICE
|
||||||
|
// ===============================
|
||||||
|
function updateInvoice(invoiceId, formElement) {
|
||||||
|
const formData = $(formElement).serialize();
|
||||||
|
|
||||||
window.onload = function () {
|
$.ajax({
|
||||||
document.getElementById('subcontractor').focus();
|
url: '/update_invoice/' + invoiceId,
|
||||||
};
|
method: 'POST',
|
||||||
|
data: formData,
|
||||||
|
dataType: 'json',
|
||||||
|
success: function(response) {
|
||||||
|
if(response.status === "success") {
|
||||||
|
alert(response.message || "Invoice updated successfully!");
|
||||||
|
|
||||||
|
// Redirect to Add Invoice page's table part
|
||||||
|
window.location.href = "/add_invoice#addTable";
|
||||||
|
} else {
|
||||||
|
alert(response.message || "Update failed. Please try again.");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(xhr) {
|
||||||
|
let msg = xhr.responseJSON?.message || "Error updating invoice.";
|
||||||
|
alert(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
window.updateInvoice = updateInvoice; // make globally accessible
|
||||||
|
|
||||||
|
// ===============================
|
||||||
|
// DELETE INVOICE
|
||||||
|
// ===============================
|
||||||
|
function deleteInvoice(invoiceId, element) {
|
||||||
|
if (!confirm("Are you sure you want to delete this invoice?")) return;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '/delete_invoice/' + invoiceId,
|
||||||
|
method: 'GET',
|
||||||
|
dataType: 'json',
|
||||||
|
success: function (response) {
|
||||||
|
if (response.status === "success") {
|
||||||
|
alert(response.message || "Invoice deleted successfully!");
|
||||||
|
if (element) $(element).closest("tr").remove();
|
||||||
|
} else {
|
||||||
|
alert(response.message || "Error deleting invoice.");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function (xhr) {
|
||||||
|
let msg = xhr.responseJSON?.message || "Error deleting invoice. Please try again.";
|
||||||
|
alert(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
window.deleteInvoice = deleteInvoice; // make globally accessible
|
||||||
|
});
|
||||||
@@ -68,50 +68,49 @@
|
|||||||
{% endwith %}
|
{% endwith %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- GST Release History Table -->
|
||||||
<div id="addTable" style="display: none;">
|
<div id="addTable" style="display: none;">
|
||||||
<div class="search-container">
|
<div class="search-container">
|
||||||
<h2>GST Release History</h2>
|
<h2>GST Release History</h2>
|
||||||
<input type="text" id="searchBar" placeholder="Searching..." onkeyup="searchTable()">
|
<input type="text" id="searchBar" placeholder="Search..." onkeyup="searchTable()">
|
||||||
</div>
|
</div>
|
||||||
<table id="sortableTable" border="1">
|
<table id="sortableTable" border="1">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="sortable-header">GST_Release_Id</th>
|
<th class="sortable-header">GST_Release_Id</th>
|
||||||
<th class="sortable-header">PMC_No</th>
|
<th class="sortable-header">PMC_No</th>
|
||||||
<th>Invoice_No</th>
|
<th>Invoice_No</th>
|
||||||
<th>Basic_Amount</th>
|
<th>Basic_Amount</th>
|
||||||
<th>Final_Amount</th>
|
<th>Final_Amount</th>
|
||||||
<th>Total_Amount</th>
|
<th>Total_Amount</th>
|
||||||
<th>UTR</th>
|
<th>UTR</th>
|
||||||
<th>Update</th>
|
<th>Update</th>
|
||||||
<th>Delete</th>
|
<th>Delete</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for gst_rel in gst_releases %}
|
{% for gst_rel in gst_releases %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ gst_rel[0] }}</td>
|
<td>{{ gst_rel.gst_release_id }}</td>
|
||||||
<td>{{ gst_rel[1] }}</td>
|
<td>{{ gst_rel.pmc_no }}</td>
|
||||||
<td>{{ gst_rel[2] }}</td>
|
<td>{{ gst_rel.invoice_no }}</td>
|
||||||
<td>{{ gst_rel[3] }}</td>
|
<td>{{ gst_rel.basic_amount }}</td>
|
||||||
<td>{{ gst_rel[4] }}</td>
|
<td>{{ gst_rel.final_amount }}</td>
|
||||||
<td>{{ gst_rel[5] }}</td>
|
<td>{{ gst_rel.total_amount }}</td>
|
||||||
<td>{{ gst_rel[6] }}</td>
|
<td>{{ gst_rel.utr }}</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="/edit_gst_release/{{ gst_rel[0] }}">
|
<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"
|
<img src="{{ url_for('static', filename='images/icons/pen_blue_icon.png') }}" alt="Edit" class="icon">
|
||||||
class="icon">
|
</a>
|
||||||
</a>
|
</td>
|
||||||
</td>
|
<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?')">
|
||||||
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"
|
</a>
|
||||||
class="icon">
|
</td>
|
||||||
</a>
|
</tr>
|
||||||
</td>
|
{% endfor %}
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,176 +1,322 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %} {% block content %}
|
||||||
{% block content %}
|
|
||||||
<head xmlns="http://www.w3.org/1999/html">
|
<head xmlns="http://www.w3.org/1999/html">
|
||||||
<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" />
|
||||||
<title>Add Invoice</title>
|
<title>Add Invoice</title>
|
||||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/invoice.css') }}">
|
<link
|
||||||
<script src="{{ url_for('static', filename='js/invoice.js') }}"></script>
|
rel="stylesheet"
|
||||||
<script src="{{ url_for('static', filename='js/holdAmount.js') }}"></script>
|
type="text/css"
|
||||||
<script src="{{ url_for('static', filename='js/search_on_table.js') }}"></script>
|
href="{{ url_for('static', filename='css/invoice.css') }}"
|
||||||
|
/>
|
||||||
|
<script src="{{ url_for('static', filename='js/invoice.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/holdAmount.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/search_on_table.js') }}"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{% if success == 'true' %}
|
{% if success == 'true' %}
|
||||||
<div class="alert alert-success alert-dismissible fade show mt-3" role="alert">
|
<div
|
||||||
|
class="alert alert-success alert-dismissible fade show mt-3"
|
||||||
|
role="alert"
|
||||||
|
>
|
||||||
✅ Invoice added successfully!
|
✅ Invoice added successfully!
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
<button
|
||||||
</div>
|
type="button"
|
||||||
{% endif %}
|
class="btn-close"
|
||||||
|
data-bs-dismiss="alert"
|
||||||
|
aria-label="Close"
|
||||||
<!-- Flash Messages -->
|
></button>
|
||||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
</div>
|
||||||
{% if messages %}
|
|
||||||
<div class="flash-messages">
|
|
||||||
{% for category, message in messages %}
|
|
||||||
<div class="alert {{ category }}">{{ message }}</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endwith %}
|
|
||||||
|
|
||||||
<div class="button-container">
|
<!-- Flash Messages -->
|
||||||
|
{% with messages = get_flashed_messages(with_categories=true) %} {% if
|
||||||
|
messages %}
|
||||||
|
<div class="flash-messages">
|
||||||
|
{% for category, message in messages %}
|
||||||
|
<div class="alert {{ category }}">{{ message }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %} {% endwith %}
|
||||||
|
|
||||||
|
<div class="button-container">
|
||||||
<button id="addButton" class="action-button">Add</button>
|
<button id="addButton" class="action-button">Add</button>
|
||||||
<button id="displayButton" class="action-button">Display</button>
|
<button id="displayButton" class="action-button">Display</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="addForm" style="display: none;">
|
<div id="addForm" style="display: none">
|
||||||
<h2>Add Invoice</h2>
|
<h2>Add Invoice</h2>
|
||||||
|
|
||||||
<form id="invoiceForm" action="{{ url_for('invoice.add_invoice') }}" method="POST">
|
<form
|
||||||
<div class="row1">
|
id="invoiceForm"
|
||||||
<div>
|
action="{{ url_for('invoice.add_invoice') }}"
|
||||||
<label for="subcontractor">Subcontractor Name:</label>
|
method="POST"
|
||||||
<input type="text" id="subcontractor" name="subcontractor" required autocomplete="off"/>
|
>
|
||||||
<input type="hidden" id="subcontractor_id" name="subcontractor_id"/>
|
<div class="row1">
|
||||||
<div id="subcontractor_list"></div>
|
<div>
|
||||||
</div>
|
<label for="subcontractor">Subcontractor Name:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="subcontractor"
|
||||||
|
name="subcontractor"
|
||||||
|
required
|
||||||
|
autocomplete="off"
|
||||||
|
/>
|
||||||
|
<input type="hidden" id="subcontractor_id" name="subcontractor_id" />
|
||||||
|
<div id="subcontractor_list"></div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row2">
|
<div class="row2">
|
||||||
<div>
|
<div>
|
||||||
<label for="village">Village Name:</label>
|
<label for="village">Village Name:</label>
|
||||||
<select id="village" name="village" required>
|
<select id="village" name="village" required>
|
||||||
<option value="">-- Select Village --</option>
|
<option value="">-- Select Village --</option>
|
||||||
{% for village in villages %}
|
{% for village in villages %}
|
||||||
<option value="{{ village.Village_Name }}">{{ village.Village_Name }}</option>
|
<option value="{{ village.Village_Name }}">
|
||||||
{% endfor %}
|
{{ village.Village_Name }}
|
||||||
</select>
|
</option>
|
||||||
</div>
|
{% endfor %}
|
||||||
<div>
|
</select>
|
||||||
<label for="pmc_no">PMC No:</label>
|
|
||||||
<input type="text" id="pmc_no" name="pmc_no" required/>
|
|
||||||
<div id="pmc_no_list" class="autocomplete-list"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
<div class="row2">
|
<label for="pmc_no">PMC No:</label>
|
||||||
<div>
|
<input type="text" id="pmc_no" name="pmc_no" required />
|
||||||
<label for="work_type">Work Type:</label>
|
<div id="pmc_no_list" class="autocomplete-list"></div>
|
||||||
<input type="text" id="work_type" name="work_type" required/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="invoice_details">Invoice Details:</label>
|
|
||||||
<textarea id="invoice_details" name="invoice_details" required></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row2">
|
<div class="row2">
|
||||||
<div>
|
<div>
|
||||||
<label for="invoice_no">Invoice No:</label>
|
<label for="work_type">Work Type:</label>
|
||||||
<input type="text" id="invoice_no" name="invoice_no" required/>
|
<input type="text" id="work_type" name="work_type" required />
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="invoice_date">Invoice Date:</label>
|
|
||||||
<input type="date" id="invoice_date" name="invoice_date" required/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
<div class="row3">
|
<label for="invoice_details">Invoice Details:</label>
|
||||||
<div>
|
<textarea
|
||||||
<label for="basic_amount">Basic Amount:</label>
|
id="invoice_details"
|
||||||
<input type="number" step="0.01" id="basic_amount" name="basic_amount" placeholder="₹ - 00.00" required/>
|
name="invoice_details"
|
||||||
</div>
|
required
|
||||||
<div>
|
></textarea>
|
||||||
<label for="debit_amount">Debit Amount:</label>
|
|
||||||
<input type="number" step="0.01" id="debit_amount" name="debit_amount" placeholder="₹ - 00.00" 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" placeholder="₹ - 00.00" readonly required/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row3">
|
|
||||||
<div class="percentage-field">
|
|
||||||
<label for="gst_percentage">GST %:</label>
|
|
||||||
<input type="number" step="0.01" id="gst_percentage" name="gst_percentage" placeholder="%"/>
|
|
||||||
<label for="gst_amount">GST Amount:</label>
|
|
||||||
<input type="number" step="0.01" id="gst_amount" name="gst_amount" placeholder="₹ - 00.00" readonly required/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="amount">Amount:</label>
|
|
||||||
<input type="number" step="0.01" id="amount" name="amount" placeholder="₹ - 00.00" readonly required/>
|
|
||||||
</div>
|
|
||||||
<div class="percentage-field">
|
|
||||||
<label for="tds_percentage">TDS %:</label>
|
|
||||||
<input type="number" step="0.01" id="tds_percentage" name="tds_percentage" placeholder="%"/>
|
|
||||||
<label for="tds_amount">TDS Amount:</label>
|
|
||||||
<input type="number" step="0.01" id="tds_amount" name="tds_amount" placeholder="₹ - 00.00" readonly required/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row3">
|
|
||||||
<div class="percentage-field">
|
|
||||||
<label for="sd_percentage">SD %:</label>
|
|
||||||
<input type="number" step="0.01" id="sd_percentage" name="sd_percentage" placeholder="%"/>
|
|
||||||
<label for="sd_amount">SD Amount:</label>
|
|
||||||
<input type="number" step="0.01" id="sd_amount" name="sd_amount" placeholder="₹ - 00.00" readonly required>
|
|
||||||
</div>
|
|
||||||
<div class="percentage-field">
|
|
||||||
<label for="commission_percentage">On Commission %:</label>
|
|
||||||
<input type="number" step="0.01" id="commission_percentage" name="commission_percentage" placeholder="%"/>
|
|
||||||
<label for="on_commission">On Commission:</label>
|
|
||||||
<input type="number" step="0.01" id="on_commission" name="on_commission" placeholder="₹ - 00.00" readonly required>
|
|
||||||
</div>
|
|
||||||
<div class="percentage-field">
|
|
||||||
<label for="hydro_percentage">Hydro Testing %:</label>
|
|
||||||
<input type="number" step="0.01" id="hydro_percentage" name="hydro_percentage" placeholder="%"/>
|
|
||||||
<label for="hydro_testing">Hydro Testing:</label>
|
|
||||||
<input type="number" step="0.01" id="hydro_testing" name="hydro_testing" placeholder="₹ - 00.00" readonly required>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="hold-row">
|
|
||||||
<button type="button" id="add_hold_amount" class="button">+ Add Hold Amount</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Dynamically added hold amount fields -->
|
<div class="row2">
|
||||||
<div id="hold_amount_container"></div>
|
<div>
|
||||||
|
<label for="invoice_no">Invoice No:</label>
|
||||||
<div class="row2">
|
<input type="text" id="invoice_no" name="invoice_no" required />
|
||||||
<div>
|
|
||||||
<label for="gst_sd_amount">GST SD Amount:</label>
|
|
||||||
<input type="number" step="0.01" id="gst_sd_amount" name="gst_sd_amount" placeholder="₹ - 00.00" required/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="final_amount">Final Amount:</label>
|
|
||||||
<input type="number" step="0.01" id="final_amount" name="final_amount" placeholder="₹ - 00.00" required/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="invoice_date">Invoice Date:</label>
|
||||||
|
<input type="date" id="invoice_date" name="invoice_date" required />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="button">Submit</button>
|
<div class="row3">
|
||||||
|
<div>
|
||||||
|
<label for="basic_amount">Basic Amount:</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
id="basic_amount"
|
||||||
|
name="basic_amount"
|
||||||
|
placeholder="₹ - 00.00"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="debit_amount">Debit Amount:</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
id="debit_amount"
|
||||||
|
name="debit_amount"
|
||||||
|
placeholder="₹ - 00.00"
|
||||||
|
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"
|
||||||
|
placeholder="₹ - 00.00"
|
||||||
|
readonly
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row3">
|
||||||
|
<div class="percentage-field">
|
||||||
|
<label for="gst_percentage">GST %:</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
id="gst_percentage"
|
||||||
|
name="gst_percentage"
|
||||||
|
placeholder="%"
|
||||||
|
/>
|
||||||
|
<label for="gst_amount">GST Amount:</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
id="gst_amount"
|
||||||
|
name="gst_amount"
|
||||||
|
placeholder="₹ - 00.00"
|
||||||
|
readonly
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="amount">Amount:</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
id="amount"
|
||||||
|
name="amount"
|
||||||
|
placeholder="₹ - 00.00"
|
||||||
|
readonly
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="percentage-field">
|
||||||
|
<label for="tds_percentage">TDS %:</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
id="tds_percentage"
|
||||||
|
name="tds_percentage"
|
||||||
|
placeholder="%"
|
||||||
|
/>
|
||||||
|
<label for="tds_amount">TDS Amount:</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
id="tds_amount"
|
||||||
|
name="tds_amount"
|
||||||
|
placeholder="₹ - 00.00"
|
||||||
|
readonly
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row3">
|
||||||
|
<div class="percentage-field">
|
||||||
|
<label for="sd_percentage">SD %:</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
id="sd_percentage"
|
||||||
|
name="sd_percentage"
|
||||||
|
placeholder="%"
|
||||||
|
/>
|
||||||
|
<label for="sd_amount">SD Amount:</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
id="sd_amount"
|
||||||
|
name="sd_amount"
|
||||||
|
placeholder="₹ - 00.00"
|
||||||
|
readonly
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="percentage-field">
|
||||||
|
<label for="commission_percentage">On Commission %:</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
id="commission_percentage"
|
||||||
|
name="commission_percentage"
|
||||||
|
placeholder="%"
|
||||||
|
/>
|
||||||
|
<label for="on_commission">On Commission:</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
id="on_commission"
|
||||||
|
name="on_commission"
|
||||||
|
placeholder="₹ - 00.00"
|
||||||
|
readonly
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="percentage-field">
|
||||||
|
<label for="hydro_percentage">Hydro Testing %:</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
id="hydro_percentage"
|
||||||
|
name="hydro_percentage"
|
||||||
|
placeholder="%"
|
||||||
|
/>
|
||||||
|
<label for="hydro_testing">Hydro Testing:</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
id="hydro_testing"
|
||||||
|
name="hydro_testing"
|
||||||
|
placeholder="₹ - 00.00"
|
||||||
|
readonly
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="hold-row">
|
||||||
|
<button type="button" id="add_hold_amount" class="button">
|
||||||
|
+ Add Hold Amount
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Dynamically added hold amount fields -->
|
||||||
|
<div id="hold_amount_container"></div>
|
||||||
|
|
||||||
|
<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"
|
||||||
|
placeholder="₹ - 00.00"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="final_amount">Final Amount:</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
id="final_amount"
|
||||||
|
name="final_amount"
|
||||||
|
placeholder="₹ - 00.00"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="button">Submit</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="addTable" style="display: none;">
|
<div id="addTable" style="display: none">
|
||||||
<!-- Invoice Table Section -->
|
<!-- Invoice Table Section -->
|
||||||
<div class="search-container">
|
<div class="search-container">
|
||||||
<h2>Invoice List</h2>
|
<h2>Invoice List</h2>
|
||||||
<input type="text" id="searchBar" placeholder="Searching..." onkeyup="searchTable()">
|
<input
|
||||||
{% if invoices %}
|
type="text"
|
||||||
<table class="invoice-table">
|
id="searchBar"
|
||||||
|
placeholder="Searching..."
|
||||||
|
onkeyup="searchTable()"
|
||||||
|
/>
|
||||||
|
{% if invoices %}
|
||||||
|
<table class="invoice-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Invoice Id</th>
|
<th>Invoice Id</th>
|
||||||
<th>SubContractor Name</th>
|
<th>SubContractor Name</th>
|
||||||
<th>PMC No</th>
|
<th>PMC No</th>
|
||||||
@@ -192,11 +338,11 @@
|
|||||||
<th>Final Amount</th>
|
<th>Final Amount</th>
|
||||||
<th>Update</th>
|
<th>Update</th>
|
||||||
<th>Delete</th>
|
<th>Delete</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for invoice in invoices %}
|
{% for invoice in invoices %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ invoice.Invoice_Id }}</td>
|
<td>{{ invoice.Invoice_Id }}</td>
|
||||||
<td>{{ invoice.Contractor_Name }}</td>
|
<td>{{ invoice.Contractor_Name }}</td>
|
||||||
<td>{{ invoice.PMC_No }}</td>
|
<td>{{ invoice.PMC_No }}</td>
|
||||||
@@ -217,62 +363,77 @@
|
|||||||
<td>{{ invoice.GST_SD_Amount }}</td>
|
<td>{{ invoice.GST_SD_Amount }}</td>
|
||||||
<td>{{ invoice.Final_Amount }}</td>
|
<td>{{ invoice.Final_Amount }}</td>
|
||||||
<td>
|
<td>
|
||||||
<!-- Edit -->
|
<!-- Edit -->
|
||||||
<a href="{{ url_for('invoice.edit_invoice', invoice_id=invoice.Invoice_Id) }}">
|
<a
|
||||||
<img src="{{ url_for('static', filename='images/icons/pen_blue_icon.png') }}" alt="Edit" class="icon">
|
href="{{ url_for('invoice.edit_invoice', invoice_id=invoice.Invoice_Id) }}"
|
||||||
</a>
|
>
|
||||||
|
<img
|
||||||
|
src="{{ url_for('static', filename='images/icons/pen_blue_icon.png') }}"
|
||||||
|
alt="Edit"
|
||||||
|
class="icon edit-btn"
|
||||||
|
data-id="{{ invoice.Invoice_Id }}"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<!-- Delete -->
|
<a
|
||||||
<a href="{{ url_for('invoice.delete_invoice_route', invoice_id=invoice.Invoice_Id) }}" onclick="return confirm('Are you sure?')">
|
href="javascript:void(0);"
|
||||||
<img src="{{ url_for('static', filename='images/icons/bin_red_icon.png') }}" alt="Delete" class="icon">
|
onclick="deleteInvoice({{ invoice.Invoice_Id }}, this)"
|
||||||
</a>
|
>
|
||||||
|
<img
|
||||||
|
src="{{ url_for('static', filename='images/icons/bin_red_icon.png') }}"
|
||||||
|
alt="Delete"
|
||||||
|
class="icon"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>No invoices found.</p>
|
<p>No invoices found.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
// Get all the input fields
|
// Get all the input fields
|
||||||
const basicAmount = document.getElementById('basic_amount');
|
const basicAmount = document.getElementById("basic_amount");
|
||||||
const debitAmount = document.getElementById('debit_amount');
|
const debitAmount = document.getElementById("debit_amount");
|
||||||
const afterDebitAmount = document.getElementById('after_debit_amount');
|
const afterDebitAmount = document.getElementById("after_debit_amount");
|
||||||
const amount = document.getElementById('amount');
|
const amount = document.getElementById("amount");
|
||||||
|
|
||||||
// Percentage fields
|
// Percentage fields
|
||||||
const gstPercentage = document.getElementById('gst_percentage');
|
const gstPercentage = document.getElementById("gst_percentage");
|
||||||
const gstAmount = document.getElementById('gst_amount');
|
const gstAmount = document.getElementById("gst_amount");
|
||||||
const tdsPercentage = document.getElementById('tds_percentage');
|
const tdsPercentage = document.getElementById("tds_percentage");
|
||||||
const tdsAmount = document.getElementById('tds_amount');
|
const tdsAmount = document.getElementById("tds_amount");
|
||||||
const sdPercentage = document.getElementById('sd_percentage');
|
const sdPercentage = document.getElementById("sd_percentage");
|
||||||
const sdAmountInput = document.getElementById('sd_amount');
|
const sdAmountInput = document.getElementById("sd_amount");
|
||||||
const commissionPercentage = document.getElementById('commission_percentage');
|
const commissionPercentage = document.getElementById(
|
||||||
const onCommission = document.getElementById('on_commission');
|
"commission_percentage",
|
||||||
const hydroPercentage = document.getElementById('hydro_percentage');
|
);
|
||||||
const hydroTesting = document.getElementById('hydro_testing');
|
const onCommission = document.getElementById("on_commission");
|
||||||
const gstSdAmount = document.getElementById('gst_sd_amount');
|
const hydroPercentage = document.getElementById("hydro_percentage");
|
||||||
const finalAmount = document.getElementById('final_amount');
|
const hydroTesting = document.getElementById("hydro_testing");
|
||||||
|
const gstSdAmount = document.getElementById("gst_sd_amount");
|
||||||
|
const finalAmount = document.getElementById("final_amount");
|
||||||
|
|
||||||
// Calculate after debit amount when basic or debit amount changes
|
// Calculate after debit amount when basic or debit amount changes
|
||||||
function calculateAfterDebitAmount() {
|
function calculateAfterDebitAmount() {
|
||||||
const basic = parseFloat(basicAmount.value) || 0;
|
const basic = parseFloat(basicAmount.value) || 0;
|
||||||
const debit = parseFloat(debitAmount.value) || 0;
|
const debit = parseFloat(debitAmount.value) || 0;
|
||||||
const afterDebit = basic - debit;
|
const afterDebit = basic - debit;
|
||||||
afterDebitAmount.value = afterDebit.toFixed(2);
|
afterDebitAmount.value = afterDebit.toFixed(2);
|
||||||
calculateGST();
|
calculateGST();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate GST and Amount
|
// Calculate GST and Amount
|
||||||
function calculateGST() {
|
function calculateGST() {
|
||||||
const baseAmount = parseFloat(afterDebitAmount.value) || 0;
|
const baseAmount = parseFloat(afterDebitAmount.value) || 0;
|
||||||
|
|
||||||
if (gstPercentage.value) {
|
if (gstPercentage.value) {
|
||||||
const gstPerc = parseFloat(gstPercentage.value) || 0;
|
const gstPerc = parseFloat(gstPercentage.value) || 0;
|
||||||
const gstAmt = (baseAmount * gstPerc) / 100;
|
const gstAmt = (baseAmount * gstPerc) / 100;
|
||||||
gstAmount.value = gstAmt.toFixed(2);
|
gstAmount.value = gstAmt.toFixed(2);
|
||||||
@@ -280,91 +441,96 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
|
|
||||||
// Calculate Amount (After Debit + GST)
|
// Calculate Amount (After Debit + GST)
|
||||||
amount.value = (baseAmount + gstAmt).toFixed(2);
|
amount.value = (baseAmount + gstAmt).toFixed(2);
|
||||||
} else {
|
} else {
|
||||||
amount.value = baseAmount.toFixed(2);
|
amount.value = baseAmount.toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateOtherDeductions();
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateOtherDeductions();
|
// Calculate other deductions (TDS, SD, Commission, Hydro)
|
||||||
}
|
function calculateOtherDeductions() {
|
||||||
|
const baseAmount = parseFloat(afterDebitAmount.value) || 0;
|
||||||
|
|
||||||
// Calculate other deductions (TDS, SD, Commission, Hydro)
|
// Calculate TDS
|
||||||
function calculateOtherDeductions() {
|
if (tdsPercentage.value) {
|
||||||
const baseAmount = parseFloat(afterDebitAmount.value) || 0;
|
|
||||||
|
|
||||||
// Calculate TDS
|
|
||||||
if (tdsPercentage.value) {
|
|
||||||
const tdsPerc = parseFloat(tdsPercentage.value) || 0;
|
const tdsPerc = parseFloat(tdsPercentage.value) || 0;
|
||||||
const tdsAmt = (baseAmount * tdsPerc) / 100;
|
const tdsAmt = (baseAmount * tdsPerc) / 100;
|
||||||
tdsAmount.value = tdsAmt.toFixed(2);
|
tdsAmount.value = tdsAmt.toFixed(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate SD
|
// Calculate SD
|
||||||
if (sdPercentage.value) {
|
if (sdPercentage.value) {
|
||||||
const sdPerc = parseFloat(sdPercentage.value) || 0;
|
const sdPerc = parseFloat(sdPercentage.value) || 0;
|
||||||
const sdAmt = (baseAmount * sdPerc) / 100;
|
const sdAmt = (baseAmount * sdPerc) / 100;
|
||||||
sdAmountInput.value = sdAmt.toFixed(2);
|
sdAmountInput.value = sdAmt.toFixed(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate Commission
|
// Calculate Commission
|
||||||
if (commissionPercentage.value) {
|
if (commissionPercentage.value) {
|
||||||
const commPerc = parseFloat(commissionPercentage.value) || 0;
|
const commPerc = parseFloat(commissionPercentage.value) || 0;
|
||||||
const commAmt = (baseAmount * commPerc) / 100;
|
const commAmt = (baseAmount * commPerc) / 100;
|
||||||
onCommission.value = commAmt.toFixed(2);
|
onCommission.value = commAmt.toFixed(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate Hydro Testing
|
// Calculate Hydro Testing
|
||||||
if (hydroPercentage.value) {
|
if (hydroPercentage.value) {
|
||||||
const hydroPerc = parseFloat(hydroPercentage.value) || 0;
|
const hydroPerc = parseFloat(hydroPercentage.value) || 0;
|
||||||
const hydroAmt = (baseAmount * hydroPerc) / 100;
|
const hydroAmt = (baseAmount * hydroPerc) / 100;
|
||||||
hydroTesting.value = hydroAmt.toFixed(2);
|
hydroTesting.value = hydroAmt.toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateFinalAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateFinalAmount();
|
// Calculate final amount
|
||||||
}
|
function calculateFinalAmount() {
|
||||||
|
const amt = parseFloat(amount.value) || 0;
|
||||||
|
const tds = parseFloat(tdsAmount.value) || 0;
|
||||||
|
const sd = parseFloat(sdAmountInput.value) || 0;
|
||||||
|
const commission = parseFloat(onCommission.value) || 0;
|
||||||
|
const hydro = parseFloat(hydroTesting.value) || 0;
|
||||||
|
const gstSd = parseFloat(gstSdAmount.value) || 0;
|
||||||
|
|
||||||
// Calculate final amount
|
// Get hold amounts
|
||||||
function calculateFinalAmount() {
|
let totalHold = 0;
|
||||||
const amt = parseFloat(amount.value) || 0;
|
document
|
||||||
const tds = parseFloat(tdsAmount.value) || 0;
|
.querySelectorAll('input[name="hold_amount[]"]')
|
||||||
const sd = parseFloat(sdAmountInput.value) || 0;
|
.forEach((input) => {
|
||||||
const commission = parseFloat(onCommission.value) || 0;
|
totalHold += parseFloat(input.value) || 0;
|
||||||
const hydro = parseFloat(hydroTesting.value) || 0;
|
});
|
||||||
const gstSd = parseFloat(gstSdAmount.value) || 0;
|
|
||||||
|
|
||||||
// Get hold amounts
|
// Final Amount = Amount - TDS - SD - Commission - Hydro - GST SD - Hold Amounts
|
||||||
let totalHold = 0;
|
const final = amt - tds - sd - commission - hydro - gstSd - totalHold;
|
||||||
document.querySelectorAll('input[name="hold_amount[]"]').forEach(input => {
|
finalAmount.value = final.toFixed(2);
|
||||||
totalHold += parseFloat(input.value) || 0;
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// Final Amount = Amount - TDS - SD - Commission - Hydro - GST SD - Hold Amounts
|
// Add event listeners
|
||||||
const final = amt - tds - sd - commission - hydro - gstSd - totalHold;
|
basicAmount.addEventListener("input", calculateAfterDebitAmount);
|
||||||
finalAmount.value = final.toFixed(2);
|
debitAmount.addEventListener("input", calculateAfterDebitAmount);
|
||||||
}
|
|
||||||
|
|
||||||
// Add event listeners
|
// Percentage fields
|
||||||
basicAmount.addEventListener('input', calculateAfterDebitAmount);
|
gstPercentage.addEventListener("input", calculateGST);
|
||||||
debitAmount.addEventListener('input', calculateAfterDebitAmount);
|
tdsPercentage.addEventListener("input", calculateOtherDeductions);
|
||||||
|
sdPercentage.addEventListener("input", calculateOtherDeductions);
|
||||||
|
commissionPercentage.addEventListener(
|
||||||
|
"input",
|
||||||
|
calculateOtherDeductions,
|
||||||
|
);
|
||||||
|
hydroPercentage.addEventListener("input", calculateOtherDeductions);
|
||||||
|
|
||||||
// Percentage fields
|
// Listen for changes in hold amounts
|
||||||
gstPercentage.addEventListener('input', calculateGST);
|
document.addEventListener("holdAmountChanged", calculateFinalAmount);
|
||||||
tdsPercentage.addEventListener('input', calculateOtherDeductions);
|
});
|
||||||
sdPercentage.addEventListener('input', calculateOtherDeductions);
|
|
||||||
commissionPercentage.addEventListener('input', calculateOtherDeductions);
|
|
||||||
hydroPercentage.addEventListener('input', calculateOtherDeductions);
|
|
||||||
|
|
||||||
// Listen for changes in hold amounts
|
// Optional JS for auto-hiding flash
|
||||||
document.addEventListener('holdAmountChanged', calculateFinalAmount);
|
setTimeout(() => {
|
||||||
});
|
document
|
||||||
|
.querySelectorAll(".alert")
|
||||||
// Optional JS for auto-hiding flash
|
.forEach((el) => (el.style.display = "none"));
|
||||||
setTimeout(() => {
|
}, 5000);
|
||||||
document.querySelectorAll('.alert').forEach(el => el.style.display = 'none');
|
</script>
|
||||||
}, 5000);
|
</div>
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
Reference in New Issue
Block a user