final payment reconciliation
This commit is contained in:
@@ -1,14 +1,4 @@
|
||||
from flask import Blueprint, render_template, request, redirect, url_for, jsonify
|
||||
|
||||
from model.Utilities import RegEx, ResponseHandler, HtmlHelper, ItemCRUDType
|
||||
from model.Log import LogData, LogHelper
|
||||
|
||||
import os
|
||||
import config
|
||||
import re
|
||||
|
||||
import mysql.connector
|
||||
from mysql.connector import Error
|
||||
|
||||
from model.ItemCRUD import ItemCRUD, itemCRUDMapping
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from mysql.connector import Error
|
||||
import config
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class ContractorInfo:
|
||||
@@ -24,39 +23,39 @@ class ContractorInfo:
|
||||
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('GetHoldAmountsAndHoldTypeByCtr', [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
|
||||
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('GetHoldAmountsAndHoldTypeByCtr', [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()
|
||||
# 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
|
||||
# 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()
|
||||
except Error as e:
|
||||
print(f"Error fetching contractor data: {e}")
|
||||
finally:
|
||||
if connection.is_connected():
|
||||
connection.close()
|
||||
|
||||
# return data
|
||||
return data
|
||||
|
||||
@@ -33,7 +33,7 @@ class HoldTypes:
|
||||
self.isSuccess = hold.isSuccess
|
||||
self.resultMessage = hold.resultMessage
|
||||
|
||||
# ✅ Convert tuple → dictionary
|
||||
# Convert tuple → dictionary
|
||||
data = []
|
||||
for row in rows:
|
||||
data.append({
|
||||
@@ -51,7 +51,7 @@ class HoldTypes:
|
||||
self.isSuccess = hold.isSuccess
|
||||
self.resultMessage = hold.resultMessage
|
||||
|
||||
# ✅ Convert tuple → dictionary
|
||||
#Convert tuple → dictionary
|
||||
if row:
|
||||
return {
|
||||
"hold_type_id": row[0],
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
import config
|
||||
from datetime import datetime
|
||||
from flask import send_file
|
||||
import openpyxl
|
||||
from openpyxl.styles import Font, PatternFill
|
||||
from model.excel import excel
|
||||
|
||||
from model.FolderAndFile import FolderAndFile
|
||||
|
||||
class ReportHelper:
|
||||
isSuccess = False
|
||||
|
||||
@@ -6,18 +6,18 @@ from decimal import Decimal
|
||||
class UnifiedReportService:
|
||||
|
||||
# Static variable to cache report data
|
||||
_cached_report_data = None
|
||||
_cached_contractor_id = None
|
||||
_cached_pmc_no = None
|
||||
# _cached_report_data = None
|
||||
# _cached_contractor_id = None
|
||||
# _cached_pmc_no = None
|
||||
|
||||
@staticmethod
|
||||
def get_report(contractor_id=None, pmc_no=None):
|
||||
|
||||
# If cached and same request, return cached data
|
||||
if (UnifiedReportService._cached_report_data and
|
||||
contractor_id == UnifiedReportService._cached_contractor_id and
|
||||
pmc_no == UnifiedReportService._cached_pmc_no):
|
||||
return UnifiedReportService._cached_report_data
|
||||
# if (UnifiedReportService._cached_report_data and
|
||||
# contractor_id == UnifiedReportService._cached_contractor_id and
|
||||
# pmc_no == UnifiedReportService._cached_pmc_no):
|
||||
# return UnifiedReportService._cached_report_data
|
||||
|
||||
connection = config.get_db_connection()
|
||||
cursor = connection.cursor(dictionary=True, buffered=True)
|
||||
@@ -42,25 +42,16 @@ class UnifiedReportService:
|
||||
# ================= INVOICES =================
|
||||
if pmc_no:
|
||||
invoices = ReportHelper.execute_sp(cursor,'GetInvoicesByContractorOrPMCNo',[None, pmc_no]) or []
|
||||
|
||||
credit_notes = ReportHelper.execute_sp(cursor,'NewGetCreditNotesByPMCNo',[pmc_no]) or []
|
||||
|
||||
gst_rel = ReportHelper.execute_sp(cursor,'GetGSTReleaseDetailsByPMC',[pmc_no]) or []
|
||||
|
||||
payments = ReportHelper.execute_sp(cursor,'GetPaymentsByPMC',[pmc_no]) or []
|
||||
|
||||
else:
|
||||
invoices = ReportHelper.execute_sp(cursor,'GetInvoicesByContractorOrPMCNo',[contractor_id, None]) or []
|
||||
|
||||
credit_notes = ReportHelper.execute_sp(cursor,'GetCreditNotesByContractor',[contractor_id]) or []
|
||||
|
||||
gst_rel = ReportHelper.execute_sp(cursor,'GstReleasesByContractorId',[contractor_id]) or []
|
||||
|
||||
payments = ReportHelper.execute_sp(cursor,'GetPayments',[contractor_id]) or []
|
||||
|
||||
print(payments)
|
||||
|
||||
|
||||
# ================= HOLD AMOUNTS =================
|
||||
hold_amounts = ReportHelper.execute_sp(cursor,'GetHoldAmountsByContractor',[contractor_id]) or []
|
||||
|
||||
@@ -99,9 +90,11 @@ class UnifiedReportService:
|
||||
"sum_gst_final_amt": sum(r.get("Final_Amount", 0) or 0 for r in gst_rel),
|
||||
"sum_gst_total_amt": sum(r.get("Total_Amount", 0) or 0 for r in gst_rel),
|
||||
"sum_pay_total_amt": sum(Decimal(r.get("Total_amount") or 0) for r in payments),
|
||||
"sum_pay_payment_amt": sum(Decimal(r.get("Payment_Amount") or 0) for r in payments), # same as above if you want
|
||||
"sum_pay_payment_amt": sum(Decimal(r.get("Payment_Amount") or 0) for r in payments),
|
||||
"sum_pay_tds_payment_amt": sum(Decimal(r.get("TDS_Payment_Amount") or 0) for r in payments),
|
||||
|
||||
"sum_credit_basic_amt": sum(Decimal(c.get("Basic_Amount") or 0) for c in credit_notes),
|
||||
"sum_credit_final_amt": sum(Decimal(c.get("Final_Amount") or 0) for c in credit_notes),
|
||||
"sum_credit_total_amt": sum(Decimal(c.get("Total_Amount") or 0) for c in credit_notes),
|
||||
}
|
||||
|
||||
# Prepare final report
|
||||
@@ -119,10 +112,10 @@ class UnifiedReportService:
|
||||
"total": total
|
||||
}
|
||||
|
||||
# Cache the report
|
||||
UnifiedReportService._cached_report_data = report_data
|
||||
UnifiedReportService._cached_contractor_id = contractor_id
|
||||
UnifiedReportService._cached_pmc_no = pmc_no
|
||||
# # Cache the report
|
||||
# UnifiedReportService._cached_report_data = report_data
|
||||
# UnifiedReportService._cached_contractor_id = contractor_id
|
||||
# UnifiedReportService._cached_pmc_no = pmc_no
|
||||
|
||||
return report_data
|
||||
|
||||
@@ -155,6 +148,7 @@ class UnifiedReportService:
|
||||
report_data["credit_note_map"],
|
||||
report_data["gst_release_map"],
|
||||
report_data["payments"],
|
||||
report_data["total"],
|
||||
output_file
|
||||
)
|
||||
|
||||
|
||||
@@ -13,14 +13,14 @@ class Village:
|
||||
def __init__(self):
|
||||
self.isSuccess = False
|
||||
self.resultMessage = ""
|
||||
self.response = {} # ✅ ADDED
|
||||
self.response = {}
|
||||
self.village = ItemCRUD(itemType=ItemCRUDType.Village)
|
||||
|
||||
# 🔹 Helper: sync status
|
||||
def _set_status(self, village):
|
||||
self.isSuccess = village.isSuccess
|
||||
|
||||
# ✅ UPDATED (safe handling)
|
||||
# UPDATED (safe handling)
|
||||
if hasattr(village, "response"):
|
||||
self.response = village.response
|
||||
self.resultMessage = village.response.get("message", "")
|
||||
@@ -75,7 +75,7 @@ class Village:
|
||||
block_id, village_name = self._get_form_data(request)
|
||||
|
||||
if not village_name:
|
||||
self.response = ResponseHandler.invalid_name("village") # ✅ UPDATED
|
||||
self.response = ResponseHandler.invalid_name("village")
|
||||
self.resultMessage = self.response["message"]
|
||||
self.isSuccess = False
|
||||
return None
|
||||
@@ -85,7 +85,7 @@ class Village:
|
||||
request=request,
|
||||
parentid=block_id,
|
||||
childname=village_name,
|
||||
storedprocfetch="GetVillageByNameAndBlock" # Change GetVillageByNameAndBlocks to GetVillageByNameAndBlock
|
||||
storedprocfetch="GetVillageByNameAndBlock"
|
||||
)
|
||||
self._set_status(self.village)
|
||||
return result
|
||||
@@ -113,7 +113,7 @@ class Village:
|
||||
block_id, village_name = self._get_form_data(request)
|
||||
|
||||
if not village_name:
|
||||
self.response = ResponseHandler.invalid_name("village") # ✅ UPDATED
|
||||
self.response = ResponseHandler.invalid_name("village")
|
||||
self.resultMessage = self.response["message"]
|
||||
self.isSuccess = False
|
||||
return
|
||||
@@ -176,7 +176,6 @@ class Village:
|
||||
print(f"Error fetching blocks: {e}")
|
||||
self.isSuccess = False
|
||||
|
||||
# ✅ FIXED (removed jsonify response)
|
||||
self.response = ResponseHandler.fetch_failure("block")
|
||||
self.resultMessage = self.response["message"]
|
||||
|
||||
|
||||
@@ -1,28 +1,13 @@
|
||||
import openpyxl
|
||||
from openpyxl.styles import Font, PatternFill
|
||||
import config
|
||||
from flask_login import current_user
|
||||
from model.Log import LogHelper
|
||||
|
||||
# from model.Report import ReportHelper
|
||||
|
||||
from model.FolderAndFile import FolderAndFile
|
||||
|
||||
class excel:
|
||||
|
||||
@staticmethod
|
||||
# def generate_excel(contractor_id, contInfo, invoices, hold_types, hold_data,
|
||||
# credit_note_map, gst_release_map, output_file):
|
||||
def generate_excel(
|
||||
contractor_id,
|
||||
info,
|
||||
invoices,
|
||||
hold_types,
|
||||
hold_data,
|
||||
credit_note_map,
|
||||
gst_release_map,
|
||||
payments,
|
||||
output_file
|
||||
):
|
||||
def generate_excel(contractor_id,info, invoices, hold_types, hold_data, credit_note_map, gst_release_map, payments,total,output_file):
|
||||
|
||||
workbook = openpyxl.Workbook()
|
||||
sheet = workbook.active
|
||||
@@ -62,7 +47,6 @@ class excel:
|
||||
else ""
|
||||
)
|
||||
|
||||
# key = (pmc_no, invoice_no)
|
||||
key = (pmc_no)
|
||||
|
||||
# Yellow separator
|
||||
@@ -161,5 +145,43 @@ class excel:
|
||||
|
||||
appended_credit_keys.add(key)
|
||||
|
||||
# total calculation
|
||||
hold_totals = {ht['hold_type_id']: 0 for ht in hold_types}
|
||||
|
||||
for inv in invoices:
|
||||
invoice_holds = hold_data.get(inv["Invoice_Id"], {})
|
||||
for ht_id in hold_totals:
|
||||
hold_totals[ht_id] += invoice_holds.get(ht_id, 0) or 0
|
||||
|
||||
totalrow = ["Total","-","-","-","-","-",total.get('sum_invo_basic_amt', 0)+total.get('sum_gst_basic_amt')+ total.get('sum_credit_basic_amt'),
|
||||
total.get('sum_invo_debit_amt', 0), total.get('sum_invo_after_debit_amt', 0),total.get('sum_invo_gst_amt', 0),total.get('sum_invo_amt', 0),
|
||||
total.get('sum_invo_tds_amt', 0),total.get('sum_invo_ds_amt', 0),total.get('sum_invo_on_commission', 0), total.get('sum_invo_hydro_test', 0),
|
||||
total.get('sum_invo_gst_sd_amt', 0)]
|
||||
|
||||
for ht in hold_types:
|
||||
totalrow.append(hold_totals.get(ht['hold_type_id'], 0))
|
||||
|
||||
totalrow += [ total.get('sum_invo_final_amt', 0)+ total.get('sum_gst_final_amt', 0) + total.get('sum_credit_final_amt', 0),"","",
|
||||
total.get('sum_pay_total_amt', 0)+ total.get('sum_gst_total_amt', 0) + total.get('sum_credit_total_amt', 0)]
|
||||
|
||||
|
||||
sheet.append(totalrow)
|
||||
# Apply style (color + bold)
|
||||
for cell in sheet[sheet.max_row]:
|
||||
cell.fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid") # Yellow
|
||||
cell.font = Font(bold=True)
|
||||
|
||||
# summary report
|
||||
sheet.append([""])
|
||||
sheet.append([""])
|
||||
sheet.append(["","","Summary Report","",""])
|
||||
summary1 = ["", "Advance / Suplus" , total.get('sum_pay_total_amt', 0)+ total.get('sum_gst_total_amt', 0) + total.get('sum_credit_total_amt', 0)]
|
||||
summary2 = ["", "Hold Amt", total["sum_invo_hold_amt"]]
|
||||
summary3 = ["", "Amount With TDS", total["sum_invo_tds_amt"]]
|
||||
sheet.append(summary1)
|
||||
sheet.append(summary2)
|
||||
sheet.append(summary3)
|
||||
|
||||
|
||||
# SAVE ONCE AT END
|
||||
workbook.save(output_file)
|
||||
@@ -14,12 +14,6 @@ class GSTRelease:
|
||||
try:
|
||||
gst = ItemCRUD(itemType=ItemCRUDType.GSTRelease)
|
||||
|
||||
# Print the full form data
|
||||
print("===== DEBUG: FORM DATA =====")
|
||||
for key, value in request.form.items():
|
||||
print(f"{key} : {value}")
|
||||
print("=============================")
|
||||
|
||||
data = {
|
||||
"PMC_No": request.form.get("PMC_No", "").strip(),
|
||||
"Invoice_No": request.form.get("Invoice_No", "").strip(),
|
||||
@@ -30,10 +24,6 @@ class GSTRelease:
|
||||
"Contractor_ID": int(request.form.get("Contractor_ID", 0) or 0)
|
||||
}
|
||||
|
||||
print("===== DEBUG: PARSED DATA =====")
|
||||
print(data)
|
||||
print("==============================")
|
||||
|
||||
# Add GST Release
|
||||
gst.AddItem(
|
||||
request=request,
|
||||
@@ -42,8 +32,6 @@ class GSTRelease:
|
||||
storedprocadd="AddGSTReleaseFromExcel"
|
||||
)
|
||||
|
||||
print(f"AddItem result: isSuccess={gst.isSuccess}, message={gst.resultMessage}")
|
||||
|
||||
self.isSuccess = gst.isSuccess
|
||||
self.resultMessage = str(gst.resultMessage)
|
||||
|
||||
@@ -69,10 +57,6 @@ class GSTRelease:
|
||||
"p_gst_release_id": gst_release_id
|
||||
}
|
||||
|
||||
print("===== DEBUG: UPDATE DATA =====")
|
||||
print(data)
|
||||
print("==============================")
|
||||
|
||||
# Call your stored procedure
|
||||
gst.EditItem(
|
||||
request=request,
|
||||
|
||||
Reference in New Issue
Block a user