Initial commit
This commit is contained in:
63
model/Auth.py
Normal file
63
model/Auth.py
Normal file
@@ -0,0 +1,63 @@
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
from flask_login import UserMixin
|
||||
from ldap3 import Server, Connection, ALL
|
||||
from ldap3.core.exceptions import LDAPBindError
|
||||
|
||||
# Load .env
|
||||
load_dotenv()
|
||||
|
||||
|
||||
class DefaultCredentials:
|
||||
username = os.getenv("DEFAULT_USERNAME")
|
||||
password = os.getenv("DEFAULT_PASSWORD")
|
||||
|
||||
|
||||
class LoginLDAP:
|
||||
|
||||
def __init__(self, request):
|
||||
|
||||
self.username = request.form.get("username", "").strip()
|
||||
self.password = request.form.get("password", "")
|
||||
|
||||
self.isDefaultCredentials = False
|
||||
self.isValidLogin = False
|
||||
self.errorMessage = ""
|
||||
|
||||
ldap_server = "ldap://localhost:389"
|
||||
ldap_user_dn = f"uid={self.username},ou=users,dc=lcepl,dc=org"
|
||||
|
||||
# fallback admin login
|
||||
if (
|
||||
self.username == DefaultCredentials.username
|
||||
and self.password == DefaultCredentials.password
|
||||
):
|
||||
self.isDefaultCredentials = True
|
||||
self.isValidLogin = True
|
||||
return
|
||||
|
||||
try:
|
||||
|
||||
server = Server(ldap_server, get_info=ALL)
|
||||
|
||||
conn = Connection(
|
||||
server,
|
||||
user=ldap_user_dn,
|
||||
password=self.password,
|
||||
auto_bind=True
|
||||
)
|
||||
|
||||
if conn.bound:
|
||||
self.isValidLogin = True
|
||||
|
||||
except LDAPBindError:
|
||||
self.errorMessage = "Invalid LDAP credentials"
|
||||
|
||||
except Exception as e:
|
||||
self.errorMessage = str(e)
|
||||
|
||||
|
||||
class User(UserMixin):
|
||||
|
||||
def __init__(self, username):
|
||||
self.id = username
|
||||
165
model/Block.py
Normal file
165
model/Block.py
Normal file
@@ -0,0 +1,165 @@
|
||||
from flask import Flask, render_template, request, redirect, url_for, send_from_directory, flash, jsonify, json
|
||||
from flask import current_app
|
||||
|
||||
from datetime import datetime
|
||||
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
|
||||
|
||||
from model.Utilities import RegEx, ResponseHandler, HtmlHelper, ItemCRUDType
|
||||
from model.Log import LogData, LogHelper
|
||||
|
||||
import os
|
||||
import config
|
||||
import re
|
||||
|
||||
import mysql.connector
|
||||
from mysql.connector import Error
|
||||
|
||||
from model.ItemCRUD import ItemCRUD, itemCRUDMapping
|
||||
|
||||
|
||||
class Block:
|
||||
|
||||
isSuccess = False
|
||||
resultMessage = ""
|
||||
|
||||
def __init__(self):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ""
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Add Block
|
||||
# ----------------------------------------------------------
|
||||
def AddBlock(self, request):
|
||||
|
||||
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||
|
||||
district_id = request.form.get('district_Id')
|
||||
block_name = request.form.get('block_Name', '').strip()
|
||||
|
||||
block.AddItem(request=request, parentid=district_id, childname=block_name, storedprocfetch="GetBlockByNameAndDistricts", storedprocadd="SaveBlock" )
|
||||
self.isSuccess = block.isSuccess
|
||||
self.resultMessage = block.resultMessage
|
||||
return
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Get All Blocks
|
||||
# ----------------------------------------------------------
|
||||
# def GetAllBlocks(self):
|
||||
|
||||
# block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||
# blocksdata = block.GetAllData(request=request, storedproc="GetAllBlock")
|
||||
# self.isSuccess = block.isSuccess
|
||||
# self.resultMessage = block.resultMessage
|
||||
# return blocksdata
|
||||
|
||||
def GetAllBlocks(self, request):
|
||||
|
||||
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||
blocksdata = block.GetAllData(request=request, storedproc="GetAllBlock")
|
||||
|
||||
self.isSuccess = block.isSuccess
|
||||
self.resultMessage = block.resultMessage
|
||||
return blocksdata
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Check Block Exists
|
||||
# ----------------------------------------------------------
|
||||
|
||||
# def CheckBlock(self, request):
|
||||
# block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||
# block_name = request.json.get('block_Name', '').strip()
|
||||
# district_id = request.json.get('district_Id')
|
||||
# result = block.CheckItem(request=request, parentid=district_id, childname=block_name, storedprocfetch="GetBlockByNameAndDistrict")
|
||||
# self.isSuccess = block.isSuccess
|
||||
# self.resultMessage = block.resultMessage
|
||||
# return result
|
||||
def CheckBlock(self, request):
|
||||
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||
data = request.get_json(silent=True) or request.form
|
||||
block_name = (data.get('block_Name') or '').strip()
|
||||
district_id = data.get('district_Id')
|
||||
|
||||
result = block.CheckItem(
|
||||
request=request,
|
||||
parentid=district_id,
|
||||
childname=block_name,
|
||||
storedprocfetch="GetBlockByNameAndDistrict"
|
||||
)
|
||||
self.isSuccess = block.isSuccess
|
||||
self.resultMessage = block.resultMessage
|
||||
return result
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Get Block By ID
|
||||
# ----------------------------------------------------------
|
||||
# def GetBlockByID(self, id):
|
||||
|
||||
# block = ItemCRUD(itemType=ItemCRUDType.Village)
|
||||
# blockdata = block.GetAllData(id=id,storedproc="GetBlockDataByID")
|
||||
# self.isSuccess = block.isSuccess
|
||||
# self.resultMessage = block.resultMessage
|
||||
# print("akash"+blockdata)
|
||||
# return blockdata
|
||||
|
||||
# def GetBlockByID(self,request,id):
|
||||
# block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||
# blockdata = block.GetDataByID(request=request,id=id,storedproc="GetBlockDataByID")
|
||||
# self.isSuccess = block.isSuccess
|
||||
# self.resultMessage = block.resultMessage
|
||||
# return blockdata
|
||||
def GetBlockByID(self, id):
|
||||
|
||||
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||
|
||||
blockdata = block.GetDataByID(
|
||||
id=id,
|
||||
storedproc="GetBlockDataByID"
|
||||
)
|
||||
|
||||
self.isSuccess = block.isSuccess
|
||||
self.resultMessage = block.resultMessage
|
||||
|
||||
return blockdata
|
||||
# ----------------------------------------------------------
|
||||
# Update Block
|
||||
# ----------------------------------------------------------
|
||||
# def EditBlock(self, request, block_id):
|
||||
|
||||
# block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||
|
||||
# district_id = request.form.get('district_Id')
|
||||
# block_name = request.form.get('block_Name', '').strip()
|
||||
|
||||
# block.EditItem(request=request, childid=block_id, parentid=district_id, childname=block_name, storedprocadd="UpdateBlockById" )
|
||||
# self.isSuccess = block.isSuccess
|
||||
# self.resultMessage = block.resultMessage
|
||||
# return
|
||||
def EditBlock(self, request, block_id):
|
||||
|
||||
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||
|
||||
district_id = request.form.get('district_Id')
|
||||
block_name = request.form.get('block_Name', '').strip()
|
||||
|
||||
block.EditItem(
|
||||
request=request,
|
||||
childid=block_id,
|
||||
parentid=district_id,
|
||||
childname=block_name,
|
||||
storedprocupdate="UpdateBlockById"
|
||||
)
|
||||
|
||||
self.isSuccess = block.isSuccess
|
||||
self.resultMessage = block.resultMessage
|
||||
return render_template('add_block.html')
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Delete Block
|
||||
# ---------------------------------------------------------
|
||||
def DeleteBlock(self,request, id):
|
||||
block = ItemCRUD(itemType=ItemCRUDType.Block)
|
||||
|
||||
block.DeleteItem(request=request,itemID=id, storedprocDelete="DeleteBlock")
|
||||
self.isSuccess = block.isSuccess
|
||||
self.resultMessage = block.resultMessage
|
||||
return
|
||||
136
model/ContractorInfo.py
Normal file
136
model/ContractorInfo.py
Normal file
@@ -0,0 +1,136 @@
|
||||
# import mysql.connector
|
||||
# from mysql.connector import Error
|
||||
# import config
|
||||
# import openpyxl
|
||||
# import os
|
||||
# import re
|
||||
# import ast
|
||||
# from datetime import datetime
|
||||
|
||||
|
||||
# class ContractorInfo:
|
||||
# ID = ""
|
||||
# contInfo = None
|
||||
# def __init__(self, id):
|
||||
# self.ID = id
|
||||
# print(id)
|
||||
# self.fetchData()
|
||||
|
||||
# def fetchData(self):
|
||||
# try:
|
||||
# connection = config.get_db_connection()
|
||||
# cursor = connection.cursor(dictionary=True, buffered=True)
|
||||
# print("here", flush=True)
|
||||
|
||||
# cursor.callproc('GetContractorInfoById', [self.ID])
|
||||
# for result in cursor.stored_results():
|
||||
# self.contInfo = result.fetchone()
|
||||
|
||||
# print(self.contInfo,flush=True)
|
||||
# finally:
|
||||
# cursor.close()
|
||||
# connection.close()
|
||||
|
||||
# def fetchalldata(self):
|
||||
|
||||
# try:
|
||||
# connection = config.get_db_connection()
|
||||
# cursor = connection.cursor(dictionary=True, buffered=True)
|
||||
# print("here", flush=True)
|
||||
|
||||
|
||||
# # ---------------- Hold Types ----------------
|
||||
# cursor = connection.cursor(dictionary=True)
|
||||
|
||||
# cursor.callproc('GetHoldTypesByContractor', [self.ID])
|
||||
|
||||
# hold_types = []
|
||||
# for result in cursor.stored_results():
|
||||
# hold_types = result.fetchall()
|
||||
# hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types}
|
||||
|
||||
# # ---------------- Invoices ----------------
|
||||
# cursor = connection.cursor(dictionary=True)
|
||||
|
||||
# cursor.callproc('GetInvoicesByContractor', [self.ID])
|
||||
|
||||
# invoices = []
|
||||
# for result in cursor.stored_results():
|
||||
# invoices = result.fetchall()
|
||||
|
||||
# # Remove duplicate invoices
|
||||
# invoice_ids_seen = set()
|
||||
# unique_invoices = []
|
||||
# for inv in invoices:
|
||||
# if inv["Invoice_Id"] not in invoice_ids_seen:
|
||||
# invoice_ids_seen.add(inv["Invoice_Id"])
|
||||
# unique_invoices.append(inv)
|
||||
# invoices = unique_invoices
|
||||
|
||||
# finally:
|
||||
# cursor.close()
|
||||
# connection.close()
|
||||
|
||||
|
||||
from mysql.connector import Error
|
||||
import config
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class ContractorInfo:
|
||||
def __init__(self, contractor_id):
|
||||
self.ID = contractor_id
|
||||
self.contInfo = None
|
||||
self.fetchData()
|
||||
|
||||
def fetchData(self):
|
||||
"""Fetch basic contractor info by ID."""
|
||||
try:
|
||||
connection = config.get_db_connection()
|
||||
with connection.cursor(dictionary=True, buffered=True) as cursor:
|
||||
cursor.callproc('GetContractorInfoById', [self.ID])
|
||||
# Get the first result set
|
||||
for result in cursor.stored_results():
|
||||
self.contInfo = result.fetchone()
|
||||
except Error as e:
|
||||
print(f"Error fetching contractor info: {e}")
|
||||
finally:
|
||||
if connection.is_connected():
|
||||
connection.close()
|
||||
|
||||
def fetchalldata(self):
|
||||
"""Fetch hold types and invoices for contractor."""
|
||||
data = {}
|
||||
try:
|
||||
connection = config.get_db_connection()
|
||||
with connection.cursor(dictionary=True, buffered=True) as cursor:
|
||||
# Fetch Hold Types
|
||||
cursor.callproc('GetHoldTypesByContractor', [self.ID])
|
||||
hold_types = []
|
||||
for result in cursor.stored_results():
|
||||
hold_types = result.fetchall()
|
||||
hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types}
|
||||
data['hold_types'] = hold_type_map
|
||||
|
||||
# Fetch Invoices
|
||||
cursor.callproc('GetInvoicesByContractor', [self.ID])
|
||||
invoices = []
|
||||
for result in cursor.stored_results():
|
||||
invoices = result.fetchall()
|
||||
|
||||
# Remove duplicate invoices
|
||||
seen_ids = set()
|
||||
unique_invoices = []
|
||||
for inv in invoices:
|
||||
if inv['Invoice_Id'] not in seen_ids:
|
||||
seen_ids.add(inv['Invoice_Id'])
|
||||
unique_invoices.append(inv)
|
||||
data['invoices'] = unique_invoices
|
||||
|
||||
except Error as e:
|
||||
print(f"Error fetching contractor data: {e}")
|
||||
finally:
|
||||
if connection.is_connected():
|
||||
connection.close()
|
||||
|
||||
return data
|
||||
100
model/District.py
Normal file
100
model/District.py
Normal file
@@ -0,0 +1,100 @@
|
||||
from flask import Flask, render_template, request, redirect, url_for, send_from_directory, flash, jsonify, json
|
||||
from flask import current_app
|
||||
|
||||
from datetime import datetime
|
||||
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
|
||||
|
||||
from model.Utilities import RegEx, ResponseHandler, HtmlHelper, ItemCRUDType
|
||||
from model.Log import LogData, LogHelper
|
||||
|
||||
import os
|
||||
import config
|
||||
import re
|
||||
|
||||
import mysql.connector
|
||||
from mysql.connector import Error
|
||||
|
||||
from model.ItemCRUD import ItemCRUD
|
||||
class District:
|
||||
|
||||
isSuccess = False
|
||||
resultMessage = ""
|
||||
|
||||
def __init__(self):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ""
|
||||
|
||||
|
||||
def EditDistrict(self, request, district_id):
|
||||
district = ItemCRUD(itemType=ItemCRUDType.District)
|
||||
|
||||
district_name = request.form['district_Name'].strip()
|
||||
state_id = request.form['state_Id']
|
||||
|
||||
district.EditItem(request=request, childid=district_id, parentid=state_id, childname=district_name,storedprocupdate="UpdateDistrict" )
|
||||
self.isSuccess = district.isSuccess
|
||||
self.resultMessage = district.resultMessage
|
||||
return
|
||||
|
||||
|
||||
def AddDistrict(self, request):
|
||||
|
||||
district = ItemCRUD(ItemCRUDType.District)
|
||||
|
||||
district_name = request.form['district_Name'].strip()
|
||||
state_id = request.form['state_Id']
|
||||
|
||||
district.AddItem(request=request, parentid=state_id, childname=district_name, storedprocfetch="GetDistrictByNameAndState", storedprocadd="SaveDistrict" )
|
||||
self.isSuccess = district.isSuccess
|
||||
self.resultMessage = district.resultMessage
|
||||
return
|
||||
|
||||
|
||||
|
||||
def GetAllDistricts(self, request):
|
||||
district = ItemCRUD(itemType=ItemCRUDType.District)
|
||||
districtsdata = district.GetAllData(request=request, storedproc="GetAllDistricts")
|
||||
self.isSuccess = district.isSuccess
|
||||
self.resultMessage = district.resultMessage
|
||||
return districtsdata
|
||||
|
||||
|
||||
def CheckDistrict(self, request):
|
||||
district = ItemCRUD(itemType=ItemCRUDType.District)
|
||||
district_name = request.json.get('district_Name', '').strip()
|
||||
state_id = request.json.get('state_Id', '')
|
||||
result = district.CheckItem(request=request, parentid=state_id, childname=district_name, storedprocfetch="GetDistrictByNameAndState")
|
||||
self.isSuccess = district.isSuccess
|
||||
self.resultMessage = district.resultMessage
|
||||
return result
|
||||
|
||||
|
||||
# def GetDistrictByID(self, request,district_id):
|
||||
# district = ItemCRUD(itemType=ItemCRUDType.District)
|
||||
# districtdata = district.GetAllData(id=district_id,storedproc="GetDistrictDataByID")
|
||||
# self.isSuccess = district.isSuccess
|
||||
# self.resultMessage = district.resultMessage
|
||||
# return districtdata
|
||||
def GetDistrictByID(self, request, district_id):
|
||||
district = ItemCRUD(itemType=ItemCRUDType.District)
|
||||
|
||||
districtdata = district.GetDataByID(
|
||||
id=district_id,
|
||||
storedproc="GetDistrictDataByID"
|
||||
)
|
||||
|
||||
if districtdata:
|
||||
self.isSuccess = True
|
||||
else:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = "District not found"
|
||||
|
||||
return districtdata
|
||||
|
||||
|
||||
#Delete District
|
||||
def DeleteDistrict(self, request, district_id):
|
||||
district = ItemCRUD(itemType=ItemCRUDType.District)
|
||||
district.DeleteItem(request=request,itemID=district_id,storedprocDelete="DeleteDistrict")
|
||||
self.isSuccess = district.isSuccess
|
||||
self.resultMessage = str(district.resultMessage)
|
||||
55
model/GST.py
Normal file
55
model/GST.py
Normal file
@@ -0,0 +1,55 @@
|
||||
import config
|
||||
|
||||
class GST:
|
||||
|
||||
@staticmethod
|
||||
def get_unreleased_gst():
|
||||
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
||||
try:
|
||||
# ----------- Invoices -----------
|
||||
cursor.callproc('GetAllInvoicesBasic')
|
||||
invoices = []
|
||||
for result in cursor.stored_results():
|
||||
invoices = result.fetchall()
|
||||
|
||||
|
||||
# ----------- GST Releases -----------
|
||||
cursor.callproc('GetAllGSTReleasesBasic')
|
||||
gst_releases = []
|
||||
for result in cursor.stored_results():
|
||||
gst_releases = result.fetchall()
|
||||
|
||||
gst_invoice_nos = {
|
||||
g['Invoice_No']
|
||||
for g in gst_releases
|
||||
if g['Invoice_No']
|
||||
}
|
||||
|
||||
gst_basic_amounts = {
|
||||
float(g['Basic_Amount'])
|
||||
for g in gst_releases
|
||||
if g['Basic_Amount'] is not None
|
||||
}
|
||||
|
||||
unreleased = []
|
||||
|
||||
for inv in invoices:
|
||||
|
||||
match_by_invoice = inv['Invoice_No'] in gst_invoice_nos
|
||||
|
||||
match_by_gst_amount = float(
|
||||
inv.get('GST_SD_Amount') or 0
|
||||
) in gst_basic_amounts
|
||||
|
||||
if not (match_by_invoice or match_by_gst_amount):
|
||||
unreleased.append(inv)
|
||||
|
||||
return unreleased
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
90
model/HoldTypes.py
Normal file
90
model/HoldTypes.py
Normal file
@@ -0,0 +1,90 @@
|
||||
from flask import request
|
||||
from model.ItemCRUD import ItemCRUD
|
||||
from model.Utilities import ItemCRUDType
|
||||
|
||||
class HoldTypes:
|
||||
"""CRUD operations for Hold Types using ItemCRUD"""
|
||||
|
||||
def __init__(self):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ""
|
||||
|
||||
# ------------------- Add Hold Type -------------------
|
||||
def AddHoldType(self, request):
|
||||
hold = ItemCRUD(itemType=ItemCRUDType.HoldType)
|
||||
hold_name = request.form.get('hold_type', '').strip()
|
||||
|
||||
hold.AddItem(
|
||||
request=request,
|
||||
parentid=None,
|
||||
childname=hold_name,
|
||||
storedprocfetch="CheckHoldTypeExists",
|
||||
storedprocadd="SaveHoldType"
|
||||
)
|
||||
|
||||
self.isSuccess = hold.isSuccess
|
||||
self.resultMessage = hold.resultMessage
|
||||
|
||||
# ------------------- Get All Hold Types -------------------
|
||||
def GetAllHoldTypes(self, request=None):
|
||||
hold = ItemCRUD(itemType=ItemCRUDType.HoldType)
|
||||
rows = hold.GetAllData(request=request, storedproc="GetAllHoldTypes")
|
||||
|
||||
self.isSuccess = hold.isSuccess
|
||||
self.resultMessage = hold.resultMessage
|
||||
|
||||
# ✅ Convert tuple → dictionary
|
||||
data = []
|
||||
for row in rows:
|
||||
data.append({
|
||||
"hold_type_id": row[0],
|
||||
"hold_type": row[1]
|
||||
})
|
||||
|
||||
return data
|
||||
|
||||
# ------------------- Get Hold Type By ID -------------------
|
||||
def GetHoldTypeByID(self, hold_type_id):
|
||||
hold = ItemCRUD(itemType=ItemCRUDType.HoldType)
|
||||
row = hold.GetDataByID(hold_type_id, storedproc="GetHoldTypesById")
|
||||
|
||||
self.isSuccess = hold.isSuccess
|
||||
self.resultMessage = hold.resultMessage
|
||||
|
||||
# ✅ Convert tuple → dictionary
|
||||
if row:
|
||||
return {
|
||||
"hold_type_id": row[0],
|
||||
"hold_type": row[1]
|
||||
}
|
||||
|
||||
return None
|
||||
|
||||
# ------------------- Update Hold Type -------------------
|
||||
def EditHoldType(self, request, hold_type_id):
|
||||
hold = ItemCRUD(itemType=ItemCRUDType.HoldType)
|
||||
hold_name = request.form.get('hold_type', '').strip()
|
||||
|
||||
hold.EditItem(
|
||||
request=request,
|
||||
childid=hold_type_id,
|
||||
parentid=None,
|
||||
childname=hold_name,
|
||||
storedprocupdate="UpdateHoldTypeById"
|
||||
)
|
||||
|
||||
self.isSuccess = hold.isSuccess
|
||||
self.resultMessage = hold.resultMessage
|
||||
|
||||
# ------------------- Delete Hold Type -------------------
|
||||
def DeleteHoldType(self, request, hold_type_id):
|
||||
hold = ItemCRUD(itemType=ItemCRUDType.HoldType)
|
||||
|
||||
hold.DeleteItem(
|
||||
request=request,
|
||||
itemID=hold_type_id,
|
||||
storedprocDelete="DeleteHoldType"
|
||||
)
|
||||
|
||||
self.isSuccess = hold.isSuccess
|
||||
self.resultMessage = hold.resultMessage
|
||||
235
model/Invoice.py
Normal file
235
model/Invoice.py
Normal file
@@ -0,0 +1,235 @@
|
||||
|
||||
import config
|
||||
import mysql.connector
|
||||
|
||||
# ------------------- Helper Functions -------------------
|
||||
def clear_results(cursor):
|
||||
"""Consume all stored results to prevent cursor issues."""
|
||||
for r in cursor.stored_results():
|
||||
r.fetchall()
|
||||
|
||||
def fetch_one(cursor):
|
||||
"""Fetch first row from stored results."""
|
||||
for result in cursor.stored_results():
|
||||
return result.fetchone()
|
||||
return None
|
||||
|
||||
def fetch_all(cursor):
|
||||
"""Fetch all rows from stored results."""
|
||||
data = []
|
||||
for result in cursor.stored_results():
|
||||
data.extend(result.fetchall())
|
||||
return data
|
||||
|
||||
def get_numeric_values(data):
|
||||
"""Return numeric fields for invoices safely."""
|
||||
return [
|
||||
float(data.get('basic_amount') or 0),
|
||||
float(data.get('debit_amount') or 0),
|
||||
float(data.get('after_debit_amount') or 0),
|
||||
float(data.get('amount') or 0),
|
||||
float(data.get('gst_amount') or 0),
|
||||
float(data.get('tds_amount') or 0),
|
||||
float(data.get('sd_amount') or 0),
|
||||
float(data.get('on_commission') or 0),
|
||||
float(data.get('hydro_testing') or 0),
|
||||
float(data.get('gst_sd_amount') or 0),
|
||||
float(data.get('final_amount') or 0),
|
||||
]
|
||||
|
||||
def execute_db_operation(operation_func):
|
||||
"""General DB operation wrapper with commit/rollback."""
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
try:
|
||||
result = operation_func(cursor)
|
||||
connection.commit()
|
||||
return result
|
||||
except Exception:
|
||||
connection.rollback()
|
||||
raise
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
|
||||
# ------------------- Village Functions -------------------
|
||||
def get_village_id(village_name):
|
||||
def operation(cursor):
|
||||
cursor.callproc("GetVillageIdByName", (village_name,))
|
||||
return fetch_one(cursor)
|
||||
return execute_db_operation(operation)
|
||||
|
||||
def get_all_villages():
|
||||
def operation(cursor):
|
||||
cursor.callproc("GetAllVillages")
|
||||
return fetch_all(cursor)
|
||||
return execute_db_operation(operation)
|
||||
|
||||
|
||||
# ------------------- Invoice Functions -------------------
|
||||
def insert_invoice(data, village_id):
|
||||
def operation(cursor):
|
||||
# Insert invoice
|
||||
cursor.callproc('InsertInvoice', [
|
||||
data.get('pmc_no'),
|
||||
village_id,
|
||||
data.get('work_type'),
|
||||
data.get('invoice_details'),
|
||||
data.get('invoice_date'),
|
||||
data.get('invoice_no'),
|
||||
*get_numeric_values(data)
|
||||
])
|
||||
invoice_row = fetch_one(cursor)
|
||||
if not invoice_row:
|
||||
raise Exception("Invoice ID not returned")
|
||||
invoice_id = invoice_row.get('invoice_id')
|
||||
|
||||
# Insert inpayment
|
||||
cursor.callproc('InsertInpayment', [
|
||||
data.get('pmc_no'),
|
||||
village_id,
|
||||
data.get('work_type'),
|
||||
data.get('invoice_details'),
|
||||
data.get('invoice_date'),
|
||||
data.get('invoice_no'),
|
||||
*get_numeric_values(data),
|
||||
data.get('subcontractor_id')
|
||||
])
|
||||
clear_results(cursor)
|
||||
return invoice_id
|
||||
|
||||
return execute_db_operation(operation)
|
||||
|
||||
def get_all_invoice_details():
|
||||
def operation(cursor):
|
||||
cursor.callproc('GetAllInvoiceDetails')
|
||||
return fetch_all(cursor)
|
||||
return execute_db_operation(operation)
|
||||
|
||||
def get_invoice_by_id(invoice_id):
|
||||
def operation(cursor):
|
||||
cursor.callproc('GetInvoiceDetailsById', [invoice_id])
|
||||
invoice = fetch_one(cursor)
|
||||
|
||||
cursor.callproc('GetHoldAmountsByInvoiceId', [invoice_id])
|
||||
hold_amounts = fetch_all(cursor)
|
||||
|
||||
if invoice:
|
||||
invoice["hold_amounts"] = hold_amounts
|
||||
return invoice
|
||||
return execute_db_operation(operation)
|
||||
|
||||
def update_invoice(data, invoice_id):
|
||||
def operation(cursor):
|
||||
cursor.callproc("GetVillageIdByName", (data.get('village'),))
|
||||
village = fetch_one(cursor)
|
||||
if not village:
|
||||
raise Exception("Village not found")
|
||||
village_id = village['Village_Id']
|
||||
|
||||
cursor.callproc('UpdateInvoice', [
|
||||
data.get('pmc_no'),
|
||||
village_id,
|
||||
data.get('work_type'),
|
||||
data.get('invoice_details'),
|
||||
data.get('invoice_date'),
|
||||
data.get('invoice_no'),
|
||||
*get_numeric_values(data),
|
||||
invoice_id
|
||||
])
|
||||
clear_results(cursor)
|
||||
execute_db_operation(operation)
|
||||
|
||||
def update_inpayment(data):
|
||||
def operation(cursor):
|
||||
cursor.callproc('UpdateInpayment', [
|
||||
data.get('work_type'),
|
||||
data.get('invoice_details'),
|
||||
data.get('invoice_date'),
|
||||
*get_numeric_values(data),
|
||||
data.get('pmc_no'),
|
||||
data.get('invoice_no')
|
||||
])
|
||||
clear_results(cursor)
|
||||
execute_db_operation(operation)
|
||||
|
||||
def delete_invoice_data(invoice_id, user_id):
|
||||
def operation(cursor):
|
||||
# Fetch PMC and Invoice_No from DB
|
||||
cursor.callproc('GetInvoicePMCById', (invoice_id,))
|
||||
record = {}
|
||||
for result in cursor.stored_results():
|
||||
record = result.fetchone() or {}
|
||||
if not record:
|
||||
raise Exception("Invoice not found")
|
||||
|
||||
# Use exact DB keys
|
||||
pmc_no = record['PMC_No']
|
||||
invoice_no = record['Invoice_No']
|
||||
|
||||
# Delete invoice
|
||||
cursor.callproc("DeleteInvoice", (invoice_id,))
|
||||
clear_results(cursor)
|
||||
|
||||
# Delete inpayment
|
||||
cursor.callproc('DeleteInpaymentByPMCInvoice', (pmc_no, invoice_no))
|
||||
clear_results(cursor)
|
||||
|
||||
execute_db_operation(operation)
|
||||
|
||||
|
||||
# ------------------- Subcontractor Functions -------------------
|
||||
def assign_subcontractor(data, village_id):
|
||||
def operation(cursor):
|
||||
cursor.callproc('AssignSubcontractor', [
|
||||
data.get('pmc_no'),
|
||||
data.get('subcontractor_id'),
|
||||
village_id
|
||||
])
|
||||
clear_results(cursor)
|
||||
execute_db_operation(operation)
|
||||
|
||||
|
||||
# ------------------- Hold Types Functions -------------------
|
||||
def insert_hold_types(data, invoice_id):
|
||||
def operation(cursor):
|
||||
hold_types = data.getlist('hold_type[]')
|
||||
hold_amounts = data.getlist('hold_amount[]')
|
||||
|
||||
for hold_type, hold_amount in zip(hold_types, hold_amounts):
|
||||
if not hold_type:
|
||||
continue
|
||||
|
||||
cursor.callproc('GetHoldTypeIdByName', [hold_type])
|
||||
hold_type_result = fetch_one(cursor)
|
||||
|
||||
if not hold_type_result:
|
||||
cursor.callproc('InsertHoldType', [hold_type, 0])
|
||||
cursor.execute("SELECT @_InsertHoldType_1")
|
||||
hold_type_id = cursor.fetchone()[0]
|
||||
else:
|
||||
hold_type_id = hold_type_result['hold_type_id']
|
||||
|
||||
cursor.callproc('InsertInvoiceSubcontractorHold', [
|
||||
data.get('subcontractor_id'),
|
||||
invoice_id,
|
||||
hold_type_id,
|
||||
float(hold_amount or 0)
|
||||
])
|
||||
clear_results(cursor)
|
||||
execute_db_operation(operation)
|
||||
|
||||
def get_all_hold_types():
|
||||
def operation(cursor):
|
||||
cursor.callproc("GetAllHoldTypes")
|
||||
return fetch_all(cursor)
|
||||
return execute_db_operation(operation)
|
||||
|
||||
|
||||
# ------------------- Contractor Functions -------------------
|
||||
def search_contractors(sub_query):
|
||||
def operation(cursor):
|
||||
cursor.callproc('SearchContractorsByName', [sub_query])
|
||||
return fetch_all(cursor)
|
||||
return execute_db_operation(operation)
|
||||
287
model/ItemCRUD.py
Normal file
287
model/ItemCRUD.py
Normal file
@@ -0,0 +1,287 @@
|
||||
from flask_login import current_user
|
||||
from model.Utilities import RegEx, ResponseHandler, HtmlHelper, ItemCRUDType
|
||||
from model.Log import LogHelper
|
||||
|
||||
import config
|
||||
import re
|
||||
import mysql.connector
|
||||
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Mapping Class
|
||||
# ----------------------------------------------------------
|
||||
class itemCRUDMapping:
|
||||
|
||||
def __init__(self, itemType):
|
||||
if itemType is ItemCRUDType.Village:
|
||||
self.name = "Village"
|
||||
elif itemType is ItemCRUDType.Block:
|
||||
self.name = "Block"
|
||||
elif itemType is ItemCRUDType.State:
|
||||
self.name = "State"
|
||||
elif itemType is ItemCRUDType.HoldType:
|
||||
self.name = "Hold Type"
|
||||
else:
|
||||
self.name = "Item"
|
||||
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# Generic CRUD Class
|
||||
# ----------------------------------------------------------
|
||||
class ItemCRUD:
|
||||
|
||||
def __init__(self, itemType):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ""
|
||||
self.itemCRUDType = itemType
|
||||
self.itemCRUDMapping = itemCRUDMapping(itemType)
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# DELETE
|
||||
# ----------------------------------------------------------
|
||||
def DeleteItem(self, request, itemID, storedprocDelete):
|
||||
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor()
|
||||
|
||||
LogHelper.log_action(
|
||||
f"Delete {self.itemCRUDMapping.name}",
|
||||
f"User {current_user.id} deleted {self.itemCRUDMapping.name} '{itemID}'"
|
||||
)
|
||||
|
||||
try:
|
||||
cursor.callproc(storedprocDelete, (itemID,))
|
||||
connection.commit()
|
||||
|
||||
self.isSuccess = True
|
||||
self.resultMessage = ResponseHandler.delete_success(self.itemCRUDMapping.name)['message']
|
||||
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error deleting {self.itemCRUDMapping.name}: {e}")
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ResponseHandler.delete_failure(self.itemCRUDMapping.name)['message']
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# ADD
|
||||
# ----------------------------------------------------------
|
||||
def AddItem(self, request, parentid, childname, storedprocfetch, storedprocadd):
|
||||
|
||||
connection = config.get_db_connection()
|
||||
if not connection:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = HtmlHelper.json_response(
|
||||
ResponseHandler.db_connection_failure(), 500
|
||||
)
|
||||
return
|
||||
|
||||
cursor = connection.cursor()
|
||||
|
||||
LogHelper.log_action(
|
||||
f"Add {self.itemCRUDMapping.name}",
|
||||
f"User {current_user.id} adding '{childname}'"
|
||||
)
|
||||
|
||||
# Validation
|
||||
if not re.match(RegEx.patternAlphabetOnly, childname):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = HtmlHelper.json_response(
|
||||
ResponseHandler.invalid_name(self.itemCRUDMapping.name), 400
|
||||
)
|
||||
return
|
||||
|
||||
try:
|
||||
# Call check procedure
|
||||
if parentid is None:
|
||||
cursor.callproc(storedprocfetch, (childname,))
|
||||
else:
|
||||
cursor.callproc(storedprocfetch, (childname, parentid))
|
||||
|
||||
# ✅ FIX: initialize variable
|
||||
existing_item = None
|
||||
|
||||
for rs in cursor.stored_results():
|
||||
existing_item = rs.fetchone()
|
||||
|
||||
# Check duplicate
|
||||
if existing_item:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = HtmlHelper.json_response(
|
||||
ResponseHandler.already_exists(self.itemCRUDMapping.name), 409
|
||||
)
|
||||
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
|
||||
)
|
||||
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Database Error: {e}")
|
||||
self.isSuccess = False
|
||||
self.resultMessage = HtmlHelper.json_response(
|
||||
ResponseHandler.add_failure(self.itemCRUDMapping.name), 500
|
||||
)
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# EDIT
|
||||
# ----------------------------------------------------------
|
||||
def EditItem(self, request, childid, parentid, childname, storedprocupdate):
|
||||
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor()
|
||||
|
||||
LogHelper.log_action(
|
||||
f"Edit {self.itemCRUDMapping.name}",
|
||||
f"User {current_user.id} edited '{childid}'"
|
||||
)
|
||||
|
||||
if not re.match(RegEx.patternAlphabetOnly, childname):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ResponseHandler.update_failure(self.itemCRUDMapping.name)['message']
|
||||
return
|
||||
|
||||
try:
|
||||
if parentid is None:
|
||||
cursor.callproc(storedprocupdate, (childid, childname))
|
||||
else:
|
||||
cursor.callproc(storedprocupdate, (childid, parentid, childname))
|
||||
|
||||
connection.commit()
|
||||
|
||||
self.isSuccess = True
|
||||
self.resultMessage = ResponseHandler.update_success(self.itemCRUDMapping.name)['message']
|
||||
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error updating {self.itemCRUDMapping.name}: {e}")
|
||||
self.isSuccess = False
|
||||
self.resultMessage = HtmlHelper.json_response(
|
||||
ResponseHandler.update_failure(self.itemCRUDMapping.name), 500
|
||||
)
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# GET ALL
|
||||
# ----------------------------------------------------------
|
||||
def GetAllData(self, request, storedproc):
|
||||
|
||||
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
|
||||
self.resultMessage = HtmlHelper.json_response(
|
||||
ResponseHandler.fetch_failure(self.itemCRUDMapping.name), 500
|
||||
)
|
||||
return []
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
return data
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# GET BY ID
|
||||
# ----------------------------------------------------------
|
||||
def GetDataByID(self, id, storedproc):
|
||||
|
||||
data = None
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor()
|
||||
|
||||
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()
|
||||
|
||||
return data
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# CHECK ITEM
|
||||
# ----------------------------------------------------------
|
||||
def CheckItem(self, request, parentid, childname, storedprocfetch):
|
||||
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor()
|
||||
|
||||
LogHelper.log_action(
|
||||
f"Check {self.itemCRUDMapping.name}",
|
||||
f"User {current_user.id} checked '{childname}'"
|
||||
)
|
||||
|
||||
if not re.match(RegEx.patternAlphabetOnly, childname):
|
||||
return HtmlHelper.json_response(
|
||||
ResponseHandler.invalid_name(self.itemCRUDMapping.name), 400
|
||||
)
|
||||
|
||||
try:
|
||||
if parentid is None:
|
||||
cursor.callproc(storedprocfetch, (childname,))
|
||||
else:
|
||||
cursor.callproc(storedprocfetch, (childname, parentid))
|
||||
|
||||
# ✅ FIX
|
||||
existing_item = None
|
||||
|
||||
for rs in cursor.stored_results():
|
||||
existing_item = rs.fetchone()
|
||||
|
||||
if existing_item:
|
||||
return HtmlHelper.json_response(
|
||||
ResponseHandler.already_exists(self.itemCRUDMapping.name), 409
|
||||
)
|
||||
|
||||
return HtmlHelper.json_response(
|
||||
ResponseHandler.is_available(self.itemCRUDMapping.name), 200
|
||||
)
|
||||
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error checking {self.itemCRUDMapping.name}: {e}")
|
||||
return HtmlHelper.json_response(
|
||||
ResponseHandler.fetch_failure(self.itemCRUDMapping.name), 500
|
||||
)
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
87
model/Log.py
Normal file
87
model/Log.py
Normal file
@@ -0,0 +1,87 @@
|
||||
from flask import Flask, render_template, request, redirect, url_for, send_from_directory, flash, jsonify, json
|
||||
from flask import current_app
|
||||
|
||||
from datetime import datetime
|
||||
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
|
||||
|
||||
import os
|
||||
|
||||
class LogHelper:
|
||||
@staticmethod
|
||||
def log_action(action, details=""):
|
||||
"""Log user actions with timestamp, user, action, and details."""
|
||||
logData = LogData()
|
||||
logData.WriteLog(action, details="")
|
||||
|
||||
class LogData:
|
||||
|
||||
filepath = ""
|
||||
timestamp = None
|
||||
|
||||
def __init__(self):
|
||||
self.filepath = os.path.join(current_app.root_path, 'activity.log')
|
||||
self.timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
if hasattr(current_user, "cn") and current_user.cn:
|
||||
self.user = current_user.cn
|
||||
elif hasattr(current_user, "username") and current_user.username:
|
||||
self.user = current_user.username
|
||||
elif hasattr(current_user, "sAMAccountName") and current_user.sAMAccountName:
|
||||
self.user = current_user.sAMAccountName
|
||||
else:
|
||||
self.user = "Unknown"
|
||||
|
||||
def WriteLog(self, action, details=""):
|
||||
"""Log user actions with timestamp, user, action, and details."""
|
||||
|
||||
with open(self.filepath, "a", encoding="utf-8") as f:
|
||||
f.write(
|
||||
f"Timestamp: {self.timestamp} | "
|
||||
f"User: {self.user} | "
|
||||
f"Action: {action} | "
|
||||
f"Details: {details}\n"
|
||||
)
|
||||
|
||||
|
||||
def GetActivitiesLog(self):
|
||||
logs = []
|
||||
|
||||
if os.path.exists(self.filepath):
|
||||
with open(self.filepath, 'r') as f:
|
||||
for line in f:
|
||||
parts = line.strip().split(" | ")
|
||||
if len(parts) == 4:
|
||||
logs.append({
|
||||
"timestamp": parts[0].replace("Timestamp:", "").strip(),
|
||||
"user": parts[1].replace("User:", "").strip(),
|
||||
"action": parts[2].replace("Action:", "").strip(),
|
||||
"details": parts[3].replace("Details:", "").strip()
|
||||
})
|
||||
return logs
|
||||
|
||||
def GetFilteredActivitiesLog(self, startDate, endDate, userName):
|
||||
|
||||
filtered_logs = self.GetActivitiesLog()
|
||||
|
||||
# Date filter
|
||||
if startDate or endDate:
|
||||
try:
|
||||
start_dt = datetime.strptime(startDate, "%Y-%m-%d") if startDate else datetime.min
|
||||
end_dt = datetime.strptime(endDate, "%Y-%m-%d") if endDate else datetime.max
|
||||
|
||||
|
||||
filtered_logs = [
|
||||
log for log in filtered_logs
|
||||
if start_dt <= datetime.strptime(log["timestamp"], "%Y-%m-%d %H:%M:%S") <= end_dt
|
||||
]
|
||||
|
||||
|
||||
except Exception as e:
|
||||
print("Date filter error:", e)
|
||||
#Why catching all exceptions? Need to handle specific exceptions
|
||||
|
||||
# Username filter
|
||||
if userName:
|
||||
filtered_logs = [log for log in filtered_logs if userName.lower() in log["user"].lower()]
|
||||
|
||||
return filtered_logs
|
||||
293
model/PmcReport.py
Normal file
293
model/PmcReport.py
Normal file
@@ -0,0 +1,293 @@
|
||||
import os
|
||||
import openpyxl
|
||||
from openpyxl.styles import Font, PatternFill
|
||||
from decimal import Decimal
|
||||
from datetime import datetime
|
||||
import config
|
||||
from flask_login import current_user
|
||||
from model.Log import LogHelper
|
||||
class PmcReport:
|
||||
|
||||
@staticmethod
|
||||
def get_pmc_report(pmc_no):
|
||||
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor(dictionary=True, buffered=True)
|
||||
|
||||
try:
|
||||
|
||||
cursor.callproc("GetContractorInfoByPmcNo", (pmc_no,))
|
||||
pmc_info = next(cursor.stored_results()).fetchone()
|
||||
|
||||
if not pmc_info:
|
||||
return None
|
||||
|
||||
cursor.callproc("Get_pmc_hold_types", (pmc_no, pmc_info["Contractor_Id"]))
|
||||
hold_types = next(cursor.stored_results()).fetchall()
|
||||
|
||||
# Extract hold_type_ids
|
||||
hold_type_ids = [ht['hold_type_id'] for ht in hold_types]
|
||||
|
||||
invoices = []
|
||||
hold_amount_total = 0
|
||||
if hold_type_ids:
|
||||
|
||||
hold_type_ids_str = ",".join(map(str, hold_type_ids))
|
||||
|
||||
cursor.callproc(
|
||||
'GetInvoices_WithHold',
|
||||
[pmc_no, pmc_info["Contractor_Id"], hold_type_ids_str]
|
||||
)
|
||||
else:
|
||||
|
||||
cursor.callproc(
|
||||
'GetInvoices_NoHold',
|
||||
[pmc_no, pmc_info["Contractor_Id"]]
|
||||
)
|
||||
for result in cursor.stored_results():
|
||||
invoices = result.fetchall()
|
||||
|
||||
if hold_type_ids:
|
||||
hold_amount_total = sum(row.get('hold_amount', 0) or 0 for row in invoices)
|
||||
|
||||
total_invo_final = sum(row.get('Final_Amount', 0) or 0 for row in invoices)
|
||||
|
||||
|
||||
# GST RELEASE
|
||||
cursor.callproc('GetGSTReleaseByPMC', [pmc_no])
|
||||
gst_rel = []
|
||||
for result in cursor.stored_results():
|
||||
gst_rel = result.fetchall()
|
||||
|
||||
total_gst_basic = sum(row.get('basic_amount', 0) or 0 for row in gst_rel)
|
||||
total_gst_final = sum(row.get('final_amount', 0) or 0 for row in gst_rel)
|
||||
|
||||
# ---------------- HOLD RELEASE ----------------
|
||||
cursor.callproc('GetHoldReleaseByPMC', [pmc_no])
|
||||
hold_release = []
|
||||
for result in cursor.stored_results():
|
||||
hold_release = result.fetchall()
|
||||
|
||||
|
||||
# ---------------- CREDIT NOTE ----------------
|
||||
cursor.callproc('GetCreditNoteByPMC', [pmc_no])
|
||||
credit_note = []
|
||||
for result in cursor.stored_results():
|
||||
credit_note = result.fetchall()
|
||||
|
||||
|
||||
# ---------------- PAYMENTS ----------------
|
||||
cursor.callproc('GetPaymentsByPMC', [pmc_no])
|
||||
payments = []
|
||||
for result in cursor.stored_results():
|
||||
payments = result.fetchall()
|
||||
|
||||
total_pay_amount = sum(row.get('Payment_Amount', 0) or 0 for row in payments)
|
||||
total_pay_total = sum(row.get('Total_amount', 0) or 0 for row in payments)
|
||||
|
||||
totals = {
|
||||
"sum_invo_basic_amt": sum(row.get('Basic_Amount', 0) or 0 for row in invoices),
|
||||
"sum_invo_debit_amt": sum(row.get('Debit_Amount', 0) or 0 for row in invoices),
|
||||
"sum_invo_after_debit_amt": sum(row.get('After_Debit_Amount', 0) or 0 for row in invoices),
|
||||
"sum_invo_amt": sum(row.get('Amount', 0) or 0 for row in invoices),
|
||||
"sum_invo_gst_amt": sum(row.get('GST_Amount', 0) or 0 for row in invoices),
|
||||
"sum_invo_tds_amt": sum(row.get('TDS_Amount', 0) or 0 for row in invoices),
|
||||
"sum_invo_ds_amt": sum(row.get('SD_Amount', 0) or 0 for row in invoices),
|
||||
"sum_invo_on_commission": sum(row.get('On_Commission', 0) or 0 for row in invoices),
|
||||
"sum_invo_hydro_test": sum(row.get('Hydro_Testing', 0) or 0 for row in invoices),
|
||||
"sum_invo_gst_sd_amt": sum(row.get('GST_SD_Amount', 0) or 0 for row in invoices),
|
||||
"sum_invo_final_amt": total_invo_final,
|
||||
"sum_invo_hold_amt": hold_amount_total,
|
||||
"sum_gst_basic_amt": total_gst_basic,
|
||||
"sum_gst_final_amt": total_gst_final,
|
||||
"sum_pay_payment_amt": total_pay_amount,
|
||||
"sum_pay_tds_payment_amt": sum(row.get('TDS_Payment_Amount', 0) or 0 for row in payments),
|
||||
"sum_pay_total_amt": total_pay_total
|
||||
}
|
||||
|
||||
return {
|
||||
"info": pmc_info,
|
||||
"invoices": invoices,
|
||||
"hold_types": hold_types,
|
||||
"gst_rel": gst_rel,
|
||||
"payments": payments,
|
||||
"credit_note": credit_note,
|
||||
"hold_release": hold_release,
|
||||
"total": totals
|
||||
}
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
|
||||
@staticmethod
|
||||
def download_pmc_report(pmc_no):
|
||||
|
||||
connection = config.get_db_connection()
|
||||
output_folder = "static/download"
|
||||
output_file = os.path.join(output_folder, f"PMC_Report_{pmc_no}.xlsx")
|
||||
|
||||
if not os.path.exists(output_folder):
|
||||
os.makedirs(output_folder)
|
||||
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
||||
try:
|
||||
|
||||
cursor.callproc('GetContractorDetailsByPMC', [pmc_no])
|
||||
contractor_info = next(cursor.stored_results()).fetchone()
|
||||
|
||||
if not contractor_info:
|
||||
return None
|
||||
|
||||
cursor.callproc('GetHoldTypesByContractor', [contractor_info["Contractor_Id"]])
|
||||
hold_types = next(cursor.stored_results()).fetchall()
|
||||
|
||||
hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types}
|
||||
|
||||
cursor.callproc('GetInvoicesAndGstReleaseByPmcNo', [pmc_no])
|
||||
invoices = next(cursor.stored_results()).fetchall()
|
||||
|
||||
cursor.callproc('GetCreditNoteByContractor',[contractor_info["Contractor_Id"]])
|
||||
|
||||
credit_notes = []
|
||||
for result in cursor.stored_results():
|
||||
credit_notes = result.fetchall()
|
||||
|
||||
credit_note_map = {}
|
||||
for cn in credit_notes:
|
||||
key = (cn["PMC_No"], cn["Invoice_No"])
|
||||
credit_note_map.setdefault(key, []).append(cn)
|
||||
|
||||
cursor.callproc('GetHoldAmountsByContractor', [contractor_info["Contractor_Id"]])
|
||||
hold_amounts = next(cursor.stored_results()).fetchall()
|
||||
|
||||
hold_data = {}
|
||||
for h in hold_amounts:
|
||||
hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
||||
|
||||
cursor.callproc('GetAllPaymentsByPMC', [pmc_no])
|
||||
all_payments = next(cursor.stored_results()).fetchall()
|
||||
|
||||
payments_map = {}
|
||||
extra_payments = []
|
||||
|
||||
for pay in all_payments:
|
||||
if pay['invoice_no']:
|
||||
payments_map.setdefault(pay['invoice_no'], []).append(pay)
|
||||
else:
|
||||
extra_payments.append(pay)
|
||||
|
||||
# ---------------- GST RELEASE DETAILS ----------------
|
||||
cursor.callproc('GetGSTReleaseDetailsByPMC', [pmc_no])
|
||||
|
||||
gst_releases = []
|
||||
for result in cursor.stored_results():
|
||||
gst_releases = result.fetchall()
|
||||
|
||||
gst_release_map = {}
|
||||
|
||||
for gr in gst_releases:
|
||||
|
||||
invoice_nos = []
|
||||
|
||||
if gr['Invoice_No']:
|
||||
|
||||
cleaned = gr['Invoice_No'].replace(' ', '')
|
||||
|
||||
if '&' in cleaned:
|
||||
invoice_nos = cleaned.split('&')
|
||||
|
||||
elif ',' in cleaned:
|
||||
invoice_nos = cleaned.split(',')
|
||||
|
||||
else:
|
||||
invoice_nos = [cleaned]
|
||||
|
||||
for inv_no in invoice_nos:
|
||||
gst_release_map.setdefault(inv_no, []).append(gr)
|
||||
|
||||
LogHelper.log_action(
|
||||
"Download PMC Report",
|
||||
f"User {current_user.id} Download PMC Report '{pmc_no}'"
|
||||
)
|
||||
|
||||
workbook = openpyxl.Workbook()
|
||||
sheet = workbook.active
|
||||
sheet.title = "PMC Report"
|
||||
|
||||
sheet.append(["", "", "Laxmi Civil Engineering Services PVT. LTD."])
|
||||
sheet.append(["Contractor Name", contractor_info["Contractor_Name"], "", "GST No", contractor_info["GST_No"], "", "GST Type", contractor_info["GST_Registration_Type"]])
|
||||
sheet.append(["State", contractor_info["State_Name"], "", "PAN No", contractor_info["PAN_No"], "", "Address", contractor_info["Address"]])
|
||||
sheet.append(["District", contractor_info["District_Name"], "", "Mobile No", contractor_info["Mobile_No"]])
|
||||
sheet.append(["Block", contractor_info["Block_Name"], "", "Email", contractor_info["Email"]])
|
||||
sheet.append([])
|
||||
|
||||
base_headers = [
|
||||
"PMC No","Village","Work Type","Invoice Details","Invoice Date","Invoice No",
|
||||
"Basic Amount","Debit","After Debit Amount","GST (18%)","Amount","TDS (1%)",
|
||||
"SD (5%)","On Commission","Hydro Testing","GST SD Amount"
|
||||
]
|
||||
|
||||
hold_headers = [ht['hold_type'] for ht in hold_types]
|
||||
|
||||
payment_headers = [
|
||||
"Final Amount","Payment Amount","TDS Payment","Total Paid","UTR"
|
||||
]
|
||||
|
||||
sheet.append(base_headers + hold_headers + payment_headers)
|
||||
|
||||
header_fill = PatternFill(start_color="ADD8E6",end_color="ADD8E6",fill_type="solid")
|
||||
header_font = Font(bold=True)
|
||||
|
||||
for cell in sheet[sheet.max_row]:
|
||||
cell.font = header_font
|
||||
cell.fill = header_fill
|
||||
|
||||
seen_invoices = set()
|
||||
processed_payments = set()
|
||||
|
||||
for inv in invoices:
|
||||
|
||||
invoice_no = inv["Invoice_No"]
|
||||
payments = payments_map.get(invoice_no, [])
|
||||
|
||||
if invoice_no not in seen_invoices:
|
||||
|
||||
seen_invoices.add(invoice_no)
|
||||
first_payment = payments[0] if payments else None
|
||||
|
||||
row = [
|
||||
pmc_no, inv["Village_Name"], inv["Work_Type"],
|
||||
inv["Invoice_Details"], inv["Invoice_Date"], invoice_no,
|
||||
inv["Basic_Amount"], inv["Debit_Amount"],
|
||||
inv["After_Debit_Amount"], inv["GST_Amount"],
|
||||
inv["Amount"], inv["TDS_Amount"], inv["SD_Amount"],
|
||||
inv["On_Commission"], inv["Hydro_Testing"], inv["GST_SD_Amount"]
|
||||
]
|
||||
|
||||
invoice_holds = hold_data.get(inv["Invoice_Id"], {})
|
||||
|
||||
for ht_id in hold_type_map.keys():
|
||||
row.append(invoice_holds.get(ht_id, ""))
|
||||
|
||||
row += [
|
||||
inv["Final_Amount"],
|
||||
first_payment["Payment_Amount"] if first_payment else "",
|
||||
first_payment["TDS_Payment_Amount"] if first_payment else "",
|
||||
first_payment["Total_amount"] if first_payment else "",
|
||||
first_payment["UTR"] if first_payment else ""
|
||||
]
|
||||
|
||||
sheet.append(row)
|
||||
|
||||
workbook.save(output_file)
|
||||
workbook.close()
|
||||
|
||||
return output_folder, f"PMC_Report_{pmc_no}.xlsx"
|
||||
|
||||
finally:
|
||||
|
||||
cursor.close()
|
||||
connection.close()
|
||||
116
model/Report.py
Normal file
116
model/Report.py
Normal file
@@ -0,0 +1,116 @@
|
||||
import config
|
||||
from datetime import datetime
|
||||
|
||||
class ReportHelper:
|
||||
|
||||
@staticmethod
|
||||
def search_contractor(subcontractor_name, pmc_no, state, district, block, village, year_from, year_to):
|
||||
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
||||
cursor.callproc("search_contractor_info", [
|
||||
subcontractor_name or None,
|
||||
pmc_no or None,
|
||||
state or None,
|
||||
district or None,
|
||||
block or None,
|
||||
village or None,
|
||||
year_from or None,
|
||||
year_to or None
|
||||
])
|
||||
|
||||
data = []
|
||||
for result in cursor.stored_results():
|
||||
data = result.fetchall()
|
||||
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
return data
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_contractor_report(contractor_id):
|
||||
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor(dictionary=True, buffered=True)
|
||||
|
||||
|
||||
try:
|
||||
# Contractor Info
|
||||
cursor.callproc('GetContractorInfo', [contractor_id])
|
||||
for result in cursor.stored_results():
|
||||
contInfo = result.fetchone()
|
||||
|
||||
# Hold Types
|
||||
cursor.callproc('GetContractorHoldTypes', [contractor_id])
|
||||
for result in cursor.stored_results():
|
||||
hold_types = result.fetchall()
|
||||
|
||||
# Invoices
|
||||
cursor.callproc('GetContractorInvoices', [contractor_id])
|
||||
for result in cursor.stored_results():
|
||||
invoices = result.fetchall()
|
||||
|
||||
# GST Release
|
||||
cursor.callproc('GetGSTRelease', [contractor_id])
|
||||
for result in cursor.stored_results():
|
||||
gst_rel = result.fetchall()
|
||||
|
||||
# Hold Release
|
||||
cursor.callproc('GetHoldRelease', [contractor_id])
|
||||
for result in cursor.stored_results():
|
||||
hold_release = result.fetchall()
|
||||
|
||||
# Credit Note
|
||||
cursor.callproc('GetCreditNote', [contractor_id])
|
||||
for result in cursor.stored_results():
|
||||
credit_note = result.fetchall()
|
||||
|
||||
# Payments
|
||||
cursor.callproc('GetPayments', [contractor_id])
|
||||
for result in cursor.stored_results():
|
||||
payments = result.fetchall()
|
||||
|
||||
|
||||
# Totals
|
||||
total = {
|
||||
"sum_invo_basic_amt": float(sum(row['Basic_Amount'] or 0 for row in invoices)),
|
||||
"sum_invo_debit_amt": float(sum(row['Debit_Amount'] or 0 for row in invoices)),
|
||||
"sum_invo_after_debit_amt": float(sum(row['After_Debit_Amount'] or 0 for row in invoices)),
|
||||
"sum_invo_amt": float(sum(row['Amount'] or 0 for row in invoices)),
|
||||
"sum_invo_gst_amt": float(sum(row['GST_Amount'] or 0 for row in invoices)),
|
||||
"sum_invo_tds_amt": float(sum(row['TDS_Amount'] or 0 for row in invoices)),
|
||||
"sum_invo_ds_amt": float(sum(row['SD_Amount'] or 0 for row in invoices)),
|
||||
"sum_invo_on_commission": float(sum(row['On_Commission'] or 0 for row in invoices)),
|
||||
"sum_invo_hydro_test": float(sum(row['Hydro_Testing'] or 0 for row in invoices)),
|
||||
"sum_invo_gst_sd_amt": float(sum(row['GST_SD_Amount'] or 0 for row in invoices)),
|
||||
"sum_invo_final_amt": float(sum(row['Final_Amount'] or 0 for row in invoices)),
|
||||
"sum_invo_hold_amt": float(sum(row['hold_amount'] or 0 for row in invoices)),
|
||||
|
||||
"sum_gst_basic_amt": float(sum(row['basic_amount'] or 0 for row in gst_rel)),
|
||||
"sum_gst_final_amt": float(sum(row['final_amount'] or 0 for row in gst_rel)),
|
||||
|
||||
"sum_pay_payment_amt": float(sum(row['Payment_Amount'] or 0 for row in payments)),
|
||||
"sum_pay_tds_payment_amt": float(sum(row['TDS_Payment_Amount'] or 0 for row in payments)),
|
||||
"sum_pay_total_amt": float(sum(row['Total_amount'] or 0 for row in payments))
|
||||
}
|
||||
|
||||
current_date = datetime.now().strftime('%Y-%m-%d')
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
return {
|
||||
"contInfo": contInfo,
|
||||
"invoices": invoices,
|
||||
"hold_types": hold_types,
|
||||
"gst_rel": gst_rel,
|
||||
"payments": payments,
|
||||
"credit_note": credit_note,
|
||||
"hold_release": hold_release,
|
||||
"total": total,
|
||||
"current_date": current_date
|
||||
}
|
||||
0
model/ReportGenerator.py
Normal file
0
model/ReportGenerator.py
Normal file
246
model/State.py
Normal file
246
model/State.py
Normal file
@@ -0,0 +1,246 @@
|
||||
from flask import Flask, render_template, request, redirect, url_for, send_from_directory, flash, jsonify, json
|
||||
from flask import current_app
|
||||
|
||||
from datetime import datetime
|
||||
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
|
||||
|
||||
from model.Utilities import RegEx, ResponseHandler, HtmlHelper, ItemCRUDType
|
||||
from model.Log import LogData, LogHelper
|
||||
|
||||
import os
|
||||
import config
|
||||
import re
|
||||
|
||||
import mysql.connector
|
||||
from mysql.connector import Error
|
||||
|
||||
class State:
|
||||
|
||||
isSuccess = False
|
||||
resultMessage = ""
|
||||
|
||||
def __init__(self):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ""
|
||||
|
||||
def AddState(self, request):
|
||||
"""Log user actions with timestamp, user, action, and details."""
|
||||
statedata = []
|
||||
|
||||
connection = config.get_db_connection()
|
||||
|
||||
if connection:
|
||||
cursor = connection.cursor()
|
||||
state_name = request.form['state_Name'].strip()
|
||||
LogHelper.log_action("Add State", f"User {current_user.id} added state '{state_name}'")
|
||||
|
||||
if not re.match(RegEx.patternAlphabetOnly, state_name):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = HtmlHelper.json_response(ResponseHandler.invalid_name("state"), 400)
|
||||
return
|
||||
|
||||
try:
|
||||
|
||||
cursor.callproc("CheckStateExists", (state_name,))
|
||||
for data in cursor.stored_results():
|
||||
existing_state = data.fetchone()
|
||||
|
||||
if existing_state:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = HtmlHelper.json_response(ResponseHandler.already_exists("state"), 409)
|
||||
return
|
||||
|
||||
# cursor.execute("call SaveState (%s)", (state_name,))
|
||||
cursor.callproc("SaveState", (state_name,))
|
||||
connection.commit()
|
||||
self.isSuccess = True
|
||||
self.resultMessage = HtmlHelper.json_response(ResponseHandler.add_success("state"), 200)
|
||||
return
|
||||
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error inserting state: {e}")
|
||||
self.isSuccess = False
|
||||
self.resultMessage = HtmlHelper.json_response(ResponseHandler.add_failure("state"), 500)
|
||||
return
|
||||
|
||||
#Need to make this seperate
|
||||
|
||||
|
||||
|
||||
def GetAllStates(self, request):
|
||||
"""Log user actions with timestamp, user, action, and details."""
|
||||
statedata = []
|
||||
connection = config.get_db_connection()
|
||||
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ""
|
||||
|
||||
if not connection:
|
||||
return []
|
||||
|
||||
cursor = connection.cursor()
|
||||
|
||||
try:
|
||||
cursor.callproc("GetAllStates")
|
||||
for res in cursor.stored_results():
|
||||
statedata = res.fetchall()
|
||||
self.isSuccess = True
|
||||
|
||||
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error fetching states: {e}")
|
||||
self.isSuccess = False
|
||||
self.resultMessage = HtmlHelper.json_response(ResponseHandler.fetch_failure("state"), 500)
|
||||
return []
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
return statedata
|
||||
|
||||
|
||||
|
||||
def CheckState(self, request):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ""
|
||||
|
||||
connection = config.get_db_connection()
|
||||
#connection closing needs to be verified
|
||||
if connection:
|
||||
cursor = connection.cursor()
|
||||
state_name = request.json.get('state_Name', '').strip()
|
||||
LogHelper.log_action("Check State", f"User {current_user.id} Checked state '{state_name}'")
|
||||
if not re.match(RegEx.patternAlphabetOnly, state_name):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = HtmlHelper.json_response(ResponseHandler.invalid_name("state"), 400)
|
||||
return HtmlHelper.json_response(ResponseHandler.invalid_name("state"), 400)
|
||||
|
||||
try:
|
||||
# cursor.execute("SELECT * FROM states WHERE State_Name = %s", (state_name,))
|
||||
# existing_state = cursor.fetchone()
|
||||
|
||||
cursor.callproc("CheckStateExists", (state_name,))
|
||||
for data in cursor.stored_results():
|
||||
existing_state = data.fetchone()
|
||||
|
||||
if existing_state:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = HtmlHelper.json_response(ResponseHandler.already_exists("state"), 409)
|
||||
return HtmlHelper.json_response(ResponseHandler.already_exists("state"), 409)
|
||||
else:
|
||||
self.isSuccess = True
|
||||
self.resultMessage = HtmlHelper.json_response(ResponseHandler.is_available("state"), 200)
|
||||
return HtmlHelper.json_response(ResponseHandler.is_available("state"), 200)
|
||||
|
||||
except mysql.connector.Error as e:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = HtmlHelper.json_response(ResponseHandler.add_failure("state"), 500)
|
||||
|
||||
print(f"Error checking state: {e}")
|
||||
return HtmlHelper.json_response(ResponseHandler.add_failure("state"), 500)
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
|
||||
|
||||
def DeleteState(self, request, id):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ""
|
||||
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor()
|
||||
LogHelper.log_action("Delete State", f"User {current_user.id} Deleted state '{id}'")
|
||||
try:
|
||||
cursor.callproc('DeleteState', (id,))
|
||||
connection.commit()
|
||||
|
||||
self.resultMessage = "Successfully Deleted"
|
||||
self.isSuccess = True
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error deleting data: {e}")
|
||||
self.isSuccess = False
|
||||
self.resultMessage = HtmlHelper.json_response(ResponseHandler.delete_failure("state"), 500)
|
||||
return HtmlHelper.json_response(ResponseHandler.delete_failure("state"), 500)
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
return self.resultMessage
|
||||
|
||||
|
||||
def EditState(self, request, id):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ""
|
||||
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor()
|
||||
# str_pattern_reg = r"^[A-Za-z\s]+$"
|
||||
|
||||
state_name = request.form['state_Name'].strip()
|
||||
LogHelper.log_action("Edit State", f"User {current_user.id} Edited state '{state_name}'")
|
||||
if not re.match(RegEx.patternAlphabetOnly, state_name):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ResponseHandler.invalid_name("state"), 400
|
||||
return ResponseHandler.invalid_name("state"), 400
|
||||
|
||||
try:
|
||||
# cursor.execute("UPDATE states SET State_Name = %s WHERE State_ID = %s", (state_name, id))
|
||||
cursor.callproc("UpdateStateById", (id, state_name))
|
||||
connection.commit()
|
||||
self.isSuccess = True
|
||||
self.resultMessage = "Successfully Edited"
|
||||
return redirect(url_for('state.add_state'))
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error updating data: {e}")
|
||||
self.isSuccess = True
|
||||
self.resultMessage = ResponseHandler.add_failure("state"), 500
|
||||
|
||||
return ResponseHandler.add_failure("state"), 500
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def GetStateByID(self, request, id):
|
||||
"""Log user actions with timestamp, user, action, and details."""
|
||||
statedata = []
|
||||
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ""
|
||||
|
||||
connection = config.get_db_connection()
|
||||
if not connection:
|
||||
return []
|
||||
cursor = connection.cursor()
|
||||
|
||||
try:
|
||||
cursor.callproc("GetStateByID", (id,))
|
||||
for res in cursor.stored_results():
|
||||
statedata = res.fetchone()
|
||||
|
||||
if statedata:
|
||||
self.isSuccess = True
|
||||
self.resultMessage = "Success in Fetching"
|
||||
else:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = "State Not Found"
|
||||
|
||||
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error fetching states: {e}")
|
||||
self.isSuccess = False
|
||||
self.resultMessage = HtmlHelper.json_response(ResponseHandler.fetch_failure("state"), 500)
|
||||
return []
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
return statedata
|
||||
|
||||
|
||||
131
model/Subcontractor.py
Normal file
131
model/Subcontractor.py
Normal file
@@ -0,0 +1,131 @@
|
||||
# model/Subcontractor.py
|
||||
|
||||
import config
|
||||
from model.Log import LogHelper
|
||||
from mysql.connector import Error
|
||||
|
||||
class Subcontractor:
|
||||
|
||||
@staticmethod
|
||||
def get_connection():
|
||||
return config.get_db_connection()
|
||||
|
||||
@staticmethod
|
||||
def get_all_subcontractors():
|
||||
connection = Subcontractor.get_connection()
|
||||
subcontractors = []
|
||||
if not connection:
|
||||
return None, "Database connection failed"
|
||||
try:
|
||||
cursor = connection.cursor()
|
||||
cursor.callproc('GetAllSubcontractors')
|
||||
for result in cursor.stored_results():
|
||||
subcontractors = result.fetchall()
|
||||
except Error as e:
|
||||
print(f"Error fetching subcontractors: {e}")
|
||||
return None, str(e)
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
return subcontractors, None
|
||||
|
||||
@staticmethod
|
||||
def get_subcontractor_by_id(id):
|
||||
connection = Subcontractor.get_connection()
|
||||
subcontractor = None
|
||||
if not connection:
|
||||
return None, "Database connection failed"
|
||||
try:
|
||||
cursor = connection.cursor()
|
||||
cursor.callproc("GetSubcontractorById", (id,))
|
||||
for result in cursor.stored_results():
|
||||
subcontractor = result.fetchone()
|
||||
except Error as e:
|
||||
print(f"Error fetching subcontractor: {e}")
|
||||
return None, str(e)
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
return subcontractor, None
|
||||
|
||||
@staticmethod
|
||||
def save_subcontractor(data):
|
||||
connection = Subcontractor.get_connection()
|
||||
if not connection:
|
||||
return "Database connection failed"
|
||||
try:
|
||||
cursor = connection.cursor()
|
||||
cursor.callproc('SaveContractor', (
|
||||
data['Contractor_Name'],
|
||||
data['Address'],
|
||||
data['Mobile_No'],
|
||||
data['PAN_No'],
|
||||
data['Email'],
|
||||
data['Gender'],
|
||||
data['GST_Registration_Type'],
|
||||
data['GST_No'],
|
||||
data['Contractor_password']
|
||||
))
|
||||
connection.commit()
|
||||
# Active log
|
||||
LogHelper.log_action("Add Subcontractor", f"Added subcontractor '{data['Contractor_Name']}'")
|
||||
except Error as e:
|
||||
print(f"Error inserting subcontractor: {e}")
|
||||
return str(e)
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def update_subcontractor(id, data):
|
||||
connection = Subcontractor.get_connection()
|
||||
if not connection:
|
||||
return "Database connection failed"
|
||||
try:
|
||||
cursor = connection.cursor()
|
||||
cursor.callproc('UpdateSubcontractor', (
|
||||
id,
|
||||
data['Contractor_Name'],
|
||||
data['Address'],
|
||||
data['Mobile_No'],
|
||||
data['PAN_No'],
|
||||
data['Email'],
|
||||
data['Gender'],
|
||||
data['GST_Registration_Type'],
|
||||
data['GST_No'],
|
||||
data['Contractor_password']
|
||||
))
|
||||
connection.commit()
|
||||
# Active log
|
||||
LogHelper.log_action("Edit Subcontractor", f"Edited subcontractor '{id}'")
|
||||
except Error as e:
|
||||
print(f"Error updating subcontractor: {e}")
|
||||
return str(e)
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def delete_subcontractor(id):
|
||||
connection = Subcontractor.get_connection()
|
||||
if not connection:
|
||||
return "Database connection failed", 0
|
||||
affected_rows = 0
|
||||
try:
|
||||
cursor = connection.cursor()
|
||||
cursor.callproc('DeleteSubcontractor', (id,))
|
||||
connection.commit()
|
||||
for result in cursor.stored_results():
|
||||
row = result.fetchone()
|
||||
affected_rows = row[0] if row else 0
|
||||
# Active log
|
||||
LogHelper.log_action("Delete Subcontractor", f"Deleted subcontractor '{id}'")
|
||||
except Error as e:
|
||||
print(f"Error deleting subcontractor: {e}")
|
||||
return str(e), 0
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
return None, affected_rows
|
||||
64
model/Utilities.py
Normal file
64
model/Utilities.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from flask import flash, jsonify, json
|
||||
from enum import Enum
|
||||
|
||||
class ItemCRUDType(Enum):
|
||||
Village = 1
|
||||
Block = 2
|
||||
District = 3
|
||||
State = 4
|
||||
HoldType = 5
|
||||
|
||||
class RegEx:
|
||||
patternAlphabetOnly = "^[A-Za-z ]+$"
|
||||
|
||||
|
||||
class ResponseHandler:
|
||||
@staticmethod
|
||||
def invalid_name(entity):
|
||||
return {'status': 'error', 'message': f'Invalid {entity} name. Only letters are allowed!'}
|
||||
|
||||
@staticmethod
|
||||
def already_exists(entity):
|
||||
return {'status': 'exists', 'message': f'{entity.capitalize()} already exists!'}
|
||||
|
||||
@staticmethod
|
||||
def add_success(entity):
|
||||
return {'status': 'success', 'message': f'{entity.capitalize()} added successfully!'}
|
||||
|
||||
@staticmethod
|
||||
def add_failure(entity):
|
||||
return {'status': 'error', 'message': f'Failed to add {entity}.'}
|
||||
|
||||
@staticmethod
|
||||
def is_available(entity):
|
||||
return {'status': 'available', 'message': f'{entity.capitalize()} name is available!'}
|
||||
|
||||
@staticmethod
|
||||
def delete_success(entity):
|
||||
return {'status': 'success', 'message': f'{entity.capitalize()} deleted successfully!'}
|
||||
|
||||
@staticmethod
|
||||
def delete_failure(entity):
|
||||
return {'status': 'error', 'message': f'Failed to delete {entity}.'}
|
||||
|
||||
@staticmethod
|
||||
def update_success(entity):
|
||||
return {'status': 'success', 'message': f'{entity.capitalize()} updated successfully!'}
|
||||
|
||||
@staticmethod
|
||||
def update_failure(entity):
|
||||
return {'status': 'error', 'message': f'Failed to update {entity}.'}
|
||||
|
||||
@staticmethod
|
||||
def fetch_failure(entity):
|
||||
return {'status': 'error', 'message': f'Failed to fetch {entity}.'}
|
||||
|
||||
|
||||
class HtmlHelper:
|
||||
# Helper: JSON Response Formatter
|
||||
|
||||
@staticmethod
|
||||
def json_response(message_obj, status_code):
|
||||
return jsonify(message_obj), status_code
|
||||
#May need to refactor further
|
||||
|
||||
173
model/Village.py
Normal file
173
model/Village.py
Normal file
@@ -0,0 +1,173 @@
|
||||
# return blocks
|
||||
from model.Utilities import ResponseHandler, HtmlHelper, ItemCRUDType
|
||||
import config
|
||||
import mysql.connector
|
||||
from model.ItemCRUD import ItemCRUD
|
||||
|
||||
|
||||
class Village:
|
||||
isSuccess = False
|
||||
resultMessage = ""
|
||||
|
||||
def __init__(self):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ""
|
||||
self.village = ItemCRUD(itemType=ItemCRUDType.Village)
|
||||
|
||||
# 🔹 Helper: sync status
|
||||
def _set_status(self, village):
|
||||
self.isSuccess = village.isSuccess
|
||||
self.resultMessage = village.resultMessage
|
||||
|
||||
# 🔹 Helper: get request data
|
||||
def _get_form_data(self, request):
|
||||
block_id = request.form.get('block_Id')
|
||||
village_name = request.form.get('Village_Name', '').strip()
|
||||
return block_id, village_name
|
||||
|
||||
def AddVillage(self, request):
|
||||
block_id, village_name = self._get_form_data(request)
|
||||
|
||||
if not village_name:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = "Village name cannot be empty"
|
||||
return
|
||||
|
||||
try:
|
||||
self.village.AddItem(
|
||||
request=request,
|
||||
parentid=block_id,
|
||||
childname=village_name,
|
||||
storedprocfetch="GetVillageByNameAndBlock",
|
||||
storedprocadd="SaveVillage"
|
||||
)
|
||||
self._set_status(self.village)
|
||||
|
||||
except Exception as e:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = str(e)
|
||||
|
||||
def GetAllVillages(self, request):
|
||||
|
||||
try:
|
||||
villagesdata = self.village.GetAllData(
|
||||
request=request,
|
||||
storedproc="GetAllVillages"
|
||||
)
|
||||
self._set_status(self.village)
|
||||
return villagesdata
|
||||
|
||||
except Exception as e:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = str(e)
|
||||
return []
|
||||
|
||||
def CheckVillage(self, request):
|
||||
block_id, village_name = self._get_form_data(request)
|
||||
|
||||
if not village_name:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = "Village name cannot be empty"
|
||||
return None
|
||||
|
||||
try:
|
||||
result = self.village.CheckItem(
|
||||
request=request,
|
||||
parentid=block_id,
|
||||
childname=village_name,
|
||||
storedprocfetch="GetVillageByNameAndBlocks"
|
||||
)
|
||||
self._set_status(self.village)
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = str(e)
|
||||
return None
|
||||
|
||||
def DeleteVillage(self, request, village_id):
|
||||
|
||||
try:
|
||||
self.village.DeleteItem(
|
||||
request=request,
|
||||
itemID=village_id,
|
||||
storedprocDelete="DeleteVillage"
|
||||
)
|
||||
self._set_status(self.village)
|
||||
|
||||
except Exception as e:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = str(e)
|
||||
|
||||
def EditVillage(self, request, village_id):
|
||||
block_id, village_name = self._get_form_data(request)
|
||||
|
||||
if not village_name:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = "Village name cannot be empty"
|
||||
return
|
||||
|
||||
try:
|
||||
self.village.EditItem(
|
||||
request=request,
|
||||
childid=village_id,
|
||||
parentid=block_id,
|
||||
childname=village_name,
|
||||
storedprocupdate="UpdateVillage"
|
||||
)
|
||||
self._set_status(self.village)
|
||||
|
||||
except Exception as e:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = str(e)
|
||||
|
||||
def GetVillageByID(self, id):
|
||||
|
||||
try:
|
||||
villagedetailsdata = self.village.GetDataByID(
|
||||
id=id,
|
||||
storedproc="GetVillageDetailsById"
|
||||
)
|
||||
|
||||
if villagedetailsdata:
|
||||
self.isSuccess = True
|
||||
else:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = "Village not found"
|
||||
|
||||
return villagedetailsdata
|
||||
|
||||
except Exception as e:
|
||||
self.isSuccess = False
|
||||
self.resultMessage = str(e)
|
||||
return None
|
||||
|
||||
def GetAllBlocks(self):
|
||||
blocks = []
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ""
|
||||
|
||||
connection = config.get_db_connection()
|
||||
if not connection:
|
||||
return []
|
||||
|
||||
try:
|
||||
with connection.cursor() as cursor:
|
||||
cursor.callproc('GetAllBlocks')
|
||||
|
||||
for result in cursor.stored_results():
|
||||
blocks.extend(result.fetchall())
|
||||
|
||||
self.isSuccess = True
|
||||
return blocks
|
||||
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error fetching blocks: {e}")
|
||||
self.isSuccess = False
|
||||
self.resultMessage = HtmlHelper.json_response(
|
||||
ResponseHandler.fetch_failure("block"), 500
|
||||
)
|
||||
return []
|
||||
|
||||
finally:
|
||||
connection.close()
|
||||
150
model/gst_release.py
Normal file
150
model/gst_release.py
Normal file
@@ -0,0 +1,150 @@
|
||||
import config
|
||||
import mysql.connector
|
||||
|
||||
class GSTReleasemodel:
|
||||
|
||||
@staticmethod
|
||||
def get_connection():
|
||||
connection = config.get_db_connection()
|
||||
if not connection:
|
||||
return None
|
||||
return connection
|
||||
|
||||
@staticmethod
|
||||
def fetch_all_gst_releases():
|
||||
connection = GSTReleasemodel.get_connection()
|
||||
gst_releases = []
|
||||
if connection:
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
||||
try:
|
||||
cursor.callproc('GetAllGSTReleases')
|
||||
|
||||
gst_releases = []
|
||||
for result in cursor.stored_results(): # change to procedure
|
||||
gst_releases = result.fetchall()
|
||||
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error fetching GST releases: {e}")
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
return gst_releases
|
||||
|
||||
@staticmethod
|
||||
def insert_gst_release(pmc_no, invoice_no, basic_amount, final_amount, total_amount, utr, contractor_id):
|
||||
connection = GSTReleasemodel.get_connection()
|
||||
if not connection:
|
||||
return False
|
||||
try:
|
||||
cursor = connection.cursor()
|
||||
|
||||
# Insert into gst_release
|
||||
cursor.callproc(
|
||||
'InsertGSTReleaseOnly',
|
||||
[pmc_no, invoice_no, basic_amount, final_amount, total_amount, utr, contractor_id]
|
||||
)
|
||||
|
||||
# Insert into inpayment
|
||||
cursor.callproc(
|
||||
'InsertInpaymentOnly',
|
||||
[pmc_no, invoice_no, basic_amount, final_amount, total_amount, utr, contractor_id]
|
||||
)
|
||||
|
||||
connection.commit()
|
||||
return True
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error inserting GST release: {e}")
|
||||
return False
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
@staticmethod
|
||||
def fetch_gst_release_by_id(gst_release_id):
|
||||
connection = GSTReleasemodel.get_connection()
|
||||
if not connection:
|
||||
return None
|
||||
data = {}
|
||||
try:
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
||||
cursor.callproc('GetGSTReleaseById', [gst_release_id])
|
||||
|
||||
for result in cursor.stored_results():
|
||||
data = result.fetchone()
|
||||
if data:
|
||||
# Convert to array for template
|
||||
data = [
|
||||
data.get('GST_Release_Id'),
|
||||
data.get('PMC_No'),
|
||||
data.get('Invoice_No'),
|
||||
data.get('Basic_Amount'),
|
||||
data.get('Final_Amount'),
|
||||
data.get('Total_Amount'),
|
||||
data.get('UTR')
|
||||
]
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error fetching GST release by id: {e}")
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
def update_gst_release(gst_release_id, pmc_no, invoice_no, basic_amount, final_amount, total_amount, utr):
|
||||
connection = GSTReleasemodel.get_connection()
|
||||
if not connection:
|
||||
return False
|
||||
try:
|
||||
cursor = connection.cursor()
|
||||
# Update gst_release
|
||||
cursor.callproc(
|
||||
'UpdateGSTRelease',
|
||||
[pmc_no, invoice_no, basic_amount, final_amount, total_amount, utr, gst_release_id]
|
||||
)
|
||||
# Update inpayment
|
||||
cursor.callproc(
|
||||
'UpdateInpaymentByUTR',
|
||||
[basic_amount, final_amount, total_amount, utr]
|
||||
)
|
||||
connection.commit()
|
||||
return True
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error updating GST release: {e}")
|
||||
return False
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
@staticmethod
|
||||
def delete_gst_release(gst_release_id):
|
||||
connection = GSTReleasemodel.get_connection()
|
||||
if not connection:
|
||||
return False, None
|
||||
try:
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
cursor.callproc('GetGSTReleaseUTRById', [gst_release_id])
|
||||
record = None
|
||||
for result in cursor.stored_results():
|
||||
record = result.fetchone()
|
||||
|
||||
if not record:
|
||||
return False, None
|
||||
|
||||
utr = record['UTR']
|
||||
|
||||
# Step 1: Delete gst_release
|
||||
cursor.callproc('DeleteGSTReleaseById', [gst_release_id])
|
||||
|
||||
# Step 2: Reset inpayment using UTR
|
||||
cursor.callproc('ResetInpaymentByUTR', [utr])
|
||||
|
||||
connection.commit()
|
||||
return True, utr
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error deleting GST release: {e}")
|
||||
return False, None
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
158
model/payment.py
Normal file
158
model/payment.py
Normal file
@@ -0,0 +1,158 @@
|
||||
import config
|
||||
import mysql.connector
|
||||
|
||||
class Paymentmodel:
|
||||
|
||||
@staticmethod
|
||||
def get_connection():
|
||||
connection = config.get_db_connection()
|
||||
if not connection:
|
||||
return None
|
||||
return connection
|
||||
|
||||
@staticmethod
|
||||
def fetch_all_payments():
|
||||
connection = Paymentmodel.get_connection()
|
||||
payments = []
|
||||
if connection:
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
try:
|
||||
cursor.callproc('GetAllPayments')
|
||||
for result in cursor.stored_results():
|
||||
payments = result.fetchall()
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error fetching payment history: {e}")
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
return payments
|
||||
|
||||
@staticmethod
|
||||
def insert_payment(pmc_no, invoice_no, amount, tds_amount, total_amount, utr):
|
||||
connection = Paymentmodel.get_connection()
|
||||
if not connection:
|
||||
return False
|
||||
try:
|
||||
cursor = connection.cursor()
|
||||
cursor.callproc('InsertPayments', [pmc_no, invoice_no, amount, tds_amount, total_amount, utr])
|
||||
connection.commit()
|
||||
return True
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error inserting payment: {e}")
|
||||
return False
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
@staticmethod
|
||||
def update_inpayment(subcontractor_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr):
|
||||
connection = Paymentmodel.get_connection()
|
||||
if not connection:
|
||||
return False
|
||||
try:
|
||||
cursor = connection.cursor()
|
||||
cursor.callproc('UpdateInpaymentRecord', [
|
||||
subcontractor_id,
|
||||
pmc_no,
|
||||
invoice_no,
|
||||
amount,
|
||||
tds_amount,
|
||||
total_amount,
|
||||
utr
|
||||
])
|
||||
connection.commit()
|
||||
return True
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error updating inpayment: {e}")
|
||||
return False
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
@staticmethod
|
||||
def fetch_payment_by_id(payment_id):
|
||||
connection = Paymentmodel.get_connection()
|
||||
if not connection:
|
||||
return None
|
||||
payment_data = {}
|
||||
try:
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
cursor.callproc("GetPaymentById", (payment_id,))
|
||||
for result in cursor.stored_results():
|
||||
payment_data = result.fetchone()
|
||||
# Convert to array for template
|
||||
if payment_data:
|
||||
payment_data = [
|
||||
payment_data.get('Payment_Id'),
|
||||
payment_data.get('PMC_No'),
|
||||
payment_data.get('Invoice_No'),
|
||||
payment_data.get('Payment_Amount'),
|
||||
payment_data.get('TDS_Payment_Amount'),
|
||||
payment_data.get('Total_Amount'),
|
||||
payment_data.get('UTR')
|
||||
]
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error fetching payment data: {e}")
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
return payment_data
|
||||
|
||||
@staticmethod
|
||||
def call_update_payment_proc(payment_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr):
|
||||
connection = Paymentmodel.get_connection()
|
||||
if not connection:
|
||||
return False
|
||||
try:
|
||||
cursor = connection.cursor()
|
||||
cursor.callproc("UpdatePayment", (payment_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr))
|
||||
connection.commit()
|
||||
return True
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error updating payment: {e}")
|
||||
return False
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
|
||||
@staticmethod
|
||||
def delete_payment(payment_id):
|
||||
"""
|
||||
Deletes a payment and resets the related inpayment fields in one go.
|
||||
Returns (success, pmc_no, invoice_no)
|
||||
"""
|
||||
connection = Paymentmodel.get_connection()
|
||||
if not connection:
|
||||
return False, None, None
|
||||
|
||||
try:
|
||||
cursor = connection.cursor(dictionary=True)
|
||||
|
||||
cursor.callproc('GetPaymentPMCInvoiceById', [payment_id])
|
||||
|
||||
record = {}
|
||||
for result in cursor.stored_results():
|
||||
record = result.fetchone() or {}
|
||||
if not record:
|
||||
return False, None, None
|
||||
|
||||
pmc_no = record['PMC_No']
|
||||
invoice_no = record['Invoice_No']
|
||||
|
||||
# Step 2: Delete the payment using the stored procedure
|
||||
cursor.callproc("DeletePayment", (payment_id,))
|
||||
connection.commit()
|
||||
|
||||
# Step 3: Reset inpayment fields using the stored procedure
|
||||
cursor.callproc("ResetInpayment", [pmc_no, invoice_no])
|
||||
connection.commit()
|
||||
|
||||
return True, pmc_no, invoice_no
|
||||
|
||||
except mysql.connector.Error as e:
|
||||
print(f"Error deleting payment: {e}")
|
||||
return False, None, None
|
||||
|
||||
finally:
|
||||
cursor.close()
|
||||
connection.close()
|
||||
Reference in New Issue
Block a user