7454 lines
326 KiB
Python
7454 lines
326 KiB
Python
|
||
from decimal import Decimal
|
||
|
||
from flask import Flask, render_template, request, redirect, url_for, send_from_directory, flash, jsonify, json
|
||
import mysql.connector
|
||
from mysql.connector import Error
|
||
import config
|
||
import openpyxl
|
||
import os
|
||
import re
|
||
import ast
|
||
from datetime import datetime
|
||
import pandas as pd
|
||
from openpyxl.styles import Font
|
||
|
||
# this is server
|
||
app = Flask(__name__)
|
||
app.secret_key = '9f2a1b8c4d6e7f0123456789abcdef01'
|
||
|
||
str_pattern_reg = "^[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 f"Failed to fetch {entity}"
|
||
|
||
|
||
# Helper: JSON Response Formatter
|
||
def json_response(message_obj, status_code):
|
||
return jsonify(message_obj), status_code
|
||
|
||
|
||
# this is Index page OR Home page..
|
||
@app.route('/')
|
||
def index():
|
||
return render_template('index.html')
|
||
|
||
|
||
# this is Profile page ..
|
||
@app.route('/admin_profile', methods=['GET', 'POST'])
|
||
def admin_profile():
|
||
return render_template('admin_profile.html')
|
||
|
||
|
||
# ------------------------- State controller ------------------------------------------
|
||
@app.route('/add_state', methods=['GET', 'POST'])
|
||
def add_state():
|
||
connection = config.get_db_connection()
|
||
statedata = []
|
||
|
||
if connection:
|
||
cursor = connection.cursor()
|
||
if request.method == 'POST':
|
||
state_name = request.form['state_Name'].strip()
|
||
|
||
if not re.match(str_pattern_reg, state_name):
|
||
return json_response(ResponseHandler.invalid_name("state"), 400)
|
||
|
||
try:
|
||
# cursor.execute("SELECT * FROM states WHERE State_Name = %s", (state_name,))
|
||
# if cursor.fetchone():
|
||
# return json_response(ResponseHandler.already_exists("state"), 409)
|
||
|
||
cursor.callproc("CheckStateExists", (state_name,))
|
||
for data in cursor.stored_results():
|
||
existing_state = data.fetchone()
|
||
|
||
if existing_state:
|
||
return json_response(ResponseHandler.already_exists("state"), 409)
|
||
|
||
# cursor.execute("call SaveState (%s)", (state_name,))
|
||
cursor.callproc("SaveState", (state_name,))
|
||
connection.commit()
|
||
return json_response(ResponseHandler.add_success("state"), 200)
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Error inserting state: {e}")
|
||
return json_response(ResponseHandler.add_failure("state"), 500)
|
||
|
||
try:
|
||
# cursor.execute("SELECT State_ID, State_Name FROM states")
|
||
# statedata = cursor.fetchall()
|
||
cursor.callproc("GetAllStates")
|
||
for res in cursor.stored_results():
|
||
statedata = res.fetchall()
|
||
except mysql.connector.Error as e:
|
||
print(f"Error fetching states: {e}")
|
||
return ResponseHandler.fetch_failure("states"), 500
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return render_template('add_state.html', statedata=statedata)
|
||
|
||
|
||
# AJAX route to check state existence
|
||
@app.route('/check_state', methods=['POST'])
|
||
def check_state():
|
||
connection = config.get_db_connection()
|
||
|
||
if connection:
|
||
cursor = connection.cursor()
|
||
state_name = request.json.get('state_Name', '').strip()
|
||
|
||
if not re.match(str_pattern_reg, state_name):
|
||
return 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:
|
||
return json_response(ResponseHandler.already_exists("state"), 409)
|
||
else:
|
||
return json_response(ResponseHandler.is_available("state"), 200)
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Error checking state: {e}")
|
||
return json_response(ResponseHandler.add_failure("state"), 500)
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
|
||
# Delete State
|
||
@app.route('/delete_state/<int:id>', methods=['GET'])
|
||
def deleteState(id):
|
||
connection = config.get_db_connection()
|
||
cursor = connection.cursor()
|
||
|
||
try:
|
||
# cursor.execute("DELETE FROM states WHERE State_ID = %s", (id,))
|
||
cursor.callproc('DeleteState', (id,))
|
||
connection.commit()
|
||
# For API response
|
||
# return json_response(ResponseHandler.delete_success("state"), 200)
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Error deleting data: {e}")
|
||
return json_response(ResponseHandler.delete_failure("state"), 500)
|
||
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return redirect(url_for('add_state'))
|
||
|
||
|
||
# Edit State
|
||
@app.route('/edit_state/<int:id>', methods=['GET', 'POST'])
|
||
def editState(id):
|
||
connection = config.get_db_connection()
|
||
cursor = connection.cursor()
|
||
# str_pattern_reg = r"^[A-Za-z\s]+$"
|
||
|
||
if request.method == 'POST':
|
||
state_name = request.form['state_Name'].strip()
|
||
|
||
if not re.match(str_pattern_reg, state_name):
|
||
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()
|
||
return redirect(url_for('add_state'))
|
||
except mysql.connector.Error as e:
|
||
print(f"Error updating data: {e}")
|
||
return ResponseHandler.add_failure("state"), 500
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
try:
|
||
# cursor.execute("SELECT * FROM states WHERE State_ID = %s", (id,))
|
||
# state = cursor.fetchone()
|
||
cursor.callproc("GetStateByID", (id,))
|
||
for result in cursor.stored_results():
|
||
state = result.fetchone()
|
||
if state is None:
|
||
return "State not found", 404
|
||
except mysql.connector.Error as e:
|
||
print(f"Error retrieving data: {e}")
|
||
return ResponseHandler.fetch_failure("state"), 500
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return render_template('edit_state.html', state=state)
|
||
|
||
|
||
# -------- end State controller -----------
|
||
|
||
# ------------------------- District controller ------------------------------------------
|
||
@app.route('/add_district', methods=['GET', 'POST'])
|
||
def add_district():
|
||
connection = config.get_db_connection()
|
||
districtdata = []
|
||
states = []
|
||
|
||
if connection:
|
||
cursor = connection.cursor()
|
||
|
||
try:
|
||
# cursor.execute("SELECT State_ID, State_Name FROM states")
|
||
# states = cursor.fetchall()
|
||
cursor.callproc("GetAllStates")
|
||
for res in cursor.stored_results():
|
||
states = res.fetchall()
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Error fetching states: {e}")
|
||
return ResponseHandler.fetch_failure("states"), 500
|
||
|
||
if request.method == 'POST':
|
||
district_name = request.form['district_Name'].strip()
|
||
state_id = request.form['state_Id']
|
||
|
||
if not re.match(str_pattern_reg, district_name):
|
||
return json_response(ResponseHandler.invalid_name("district"), 400)
|
||
|
||
try:
|
||
# cursor.execute("SELECT * FROM districts WHERE District_Name = %s AND State_Id = %s",
|
||
# (district_name, state_id))
|
||
cursor.callproc("GetDistrictByNameAndState", (district_name, state_id))
|
||
for data in cursor.stored_results():
|
||
rs = data.fetchone()
|
||
if rs:
|
||
return json_response(ResponseHandler.already_exists("district"), 409)
|
||
|
||
cursor.callproc('SaveDistrict', (district_name, state_id))
|
||
connection.commit()
|
||
|
||
return json_response(ResponseHandler.add_success("district"), 200)
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Error inserting district: {e}")
|
||
return json_response(ResponseHandler.add_failure("district"), 500)
|
||
|
||
try:
|
||
# cursor.execute("SELECT d.District_id, d.District_Name, s.State_Name, s.State_Id FROM districts d JOIN states s ON d.State_Id = s.State_ID")
|
||
# districtdata = cursor.fetchall()
|
||
cursor.callproc("GetAllDistricts")
|
||
for dis in cursor.stored_results():
|
||
districtdata = dis.fetchall()
|
||
except mysql.connector.Error as e:
|
||
print(f"Error fetching districts: {e}")
|
||
return ResponseHandler.fetch_failure("districts"), 500
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return render_template('add_district.html', districtdata=districtdata, states=states)
|
||
|
||
|
||
# AJAX route to check district existence
|
||
@app.route('/check_district', methods=['POST'])
|
||
def check_district():
|
||
connection = config.get_db_connection()
|
||
|
||
if connection:
|
||
cursor = connection.cursor()
|
||
district_name = request.json.get('district_Name', '').strip()
|
||
state_id = request.json.get('state_Id', '')
|
||
|
||
if not re.match(str_pattern_reg, district_name):
|
||
return json_response(ResponseHandler.invalid_name("district"), 400)
|
||
|
||
try:
|
||
# cursor.execute("SELECT * FROM districts WHERE District_Name = %s AND State_Id = %s",
|
||
# (district_name, state_id))
|
||
# existing_district = cursor.fetchone()
|
||
cursor.callproc("GetDistrictByNameAndState", (district_name, state_id,))
|
||
for result in cursor.stored_results():
|
||
existing_district = result.fetchone()
|
||
|
||
if existing_district:
|
||
return json_response(ResponseHandler.already_exists("district"), 409)
|
||
else:
|
||
return json_response(ResponseHandler.is_available("district"), 200)
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Error checking district: {e}")
|
||
return json_response(ResponseHandler.add_failure("district"), 500)
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
|
||
# this is delete District method by id..
|
||
@app.route('/delete_district/<int:district_id>', methods=['GET', 'POST'])
|
||
def delete_district(district_id):
|
||
connection = config.get_db_connection()
|
||
|
||
if connection:
|
||
cursor = connection.cursor()
|
||
try:
|
||
# cursor.execute("DELETE FROM districts WHERE District_id = %s", (district_id,))
|
||
cursor.callproc("DeleteDistrict", (district_id,))
|
||
connection.commit()
|
||
except mysql.connector.Error as e:
|
||
print(f"Error deleting district: {e}")
|
||
return json_response(ResponseHandler.delete_failure("district"), 500)
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return redirect('/add_district')
|
||
|
||
|
||
# this is update District page by id ..
|
||
@app.route('/edit_district/<int:district_id>', methods=['GET', 'POST'])
|
||
def edit_district(district_id):
|
||
connection = config.get_db_connection()
|
||
districtdata = []
|
||
states = []
|
||
|
||
if connection:
|
||
cursor = connection.cursor()
|
||
|
||
# Retrieve all states for dropdown
|
||
try:
|
||
# cursor.execute("SELECT State_ID, State_Name FROM states")
|
||
# states = cursor.fetchall()
|
||
cursor.callproc("GetAllStates")
|
||
for res in cursor.stored_results():
|
||
states = res.fetchall()
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Error fetching states: {e}")
|
||
return ResponseHandler.fetch_failure("states"), 500
|
||
|
||
# Retrieve district info
|
||
try:
|
||
# cursor.execute("SELECT District_Name, State_Id FROM districts WHERE District_id = %s", (district_id,))
|
||
# districtdata = cursor.fetchone()
|
||
cursor.callproc("GetDistrictDataByID", (district_id,))
|
||
for rs in cursor.stored_results():
|
||
districtdata = rs.fetchone()
|
||
except mysql.connector.Error as e:
|
||
print(f"Error fetching district data: {e}")
|
||
return ResponseHandler.fetch_failure("district"), 500
|
||
|
||
# Handle update
|
||
if request.method == 'POST':
|
||
district_name = request.form['district_Name']
|
||
state_id = request.form['state_Id']
|
||
|
||
try:
|
||
# cursor.execute( "UPDATE districts SET District_Name = %s, State_Id = %s WHERE District_id = %s",
|
||
# (district_name, state_id, district_id) )
|
||
|
||
cursor.callproc("UpdateDistrict", (district_id, state_id, district_name,))
|
||
connection.commit()
|
||
except mysql.connector.Error as e:
|
||
print(f"Error updating district: {e}")
|
||
return ResponseHandler.update_failure("district"), 500
|
||
return redirect('/add_district')
|
||
|
||
return render_template('edit_district.html', districtdata=districtdata, states=states)
|
||
|
||
|
||
# --------- end District controller -------------
|
||
|
||
# ------------------------- Block controller ------------------------------------------
|
||
@app.route('/add_block', methods=['GET', 'POST'])
|
||
def add_block():
|
||
connection = config.get_db_connection()
|
||
block_data = []
|
||
states = []
|
||
|
||
if connection:
|
||
cursor = connection.cursor()
|
||
try:
|
||
# cursor.execute("SELECT State_ID, State_Name FROM states")
|
||
# states = cursor.fetchall()
|
||
cursor.callproc("GetAllStates")
|
||
for res in cursor.stored_results():
|
||
states = res.fetchall()
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Error fetching states: {e}")
|
||
return json_response(ResponseHandler.fetch_failure("states"), 500)
|
||
|
||
if request.method == 'POST':
|
||
block_name = request.form['block_Name'].strip()
|
||
district_id = request.form['district_Id']
|
||
|
||
if not re.match(str_pattern_reg, block_name):
|
||
return json_response(ResponseHandler.invalid_name("block"), 400)
|
||
|
||
try:
|
||
# cursor.execute("SELECT * FROM blocks WHERE Block_Name = %s AND District_id = %s",
|
||
# (block_name, district_id))
|
||
# existing_block = cursor.fetchone()
|
||
cursor.callproc("GetBlockByNameAndDistrict", (block_name, district_id,))
|
||
for rs in cursor.stored_results():
|
||
existing_block = rs.fetchone()
|
||
|
||
if existing_block:
|
||
return json_response(ResponseHandler.already_exists("block"), 409)
|
||
|
||
cursor.callproc('SaveBlock', (block_name, district_id))
|
||
connection.commit()
|
||
|
||
return json_response(ResponseHandler.add_success("block"), 200)
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Error adding block: {e}")
|
||
return json_response(ResponseHandler.add_failure("block"), 500)
|
||
|
||
# Fetch all blocks to display
|
||
try:
|
||
# cursor.execute(
|
||
# """SELECT b.Block_Id, b.Block_Name, d.District_Name
|
||
# FROM blocks b
|
||
# JOIN districts d ON b.District_id = d.District_id"""
|
||
# )
|
||
# block_data = cursor.fetchall()
|
||
cursor.callproc("GetAllBlocks")
|
||
for blocks in cursor.stored_results():
|
||
block_data = blocks.fetchall()
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Error fetching blocks: {e}")
|
||
return json_response(ResponseHandler.fetch_failure("blocks"), 500)
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
return render_template('add_block.html', block_data=block_data, states=states)
|
||
|
||
|
||
# check block
|
||
@app.route('/check_block', methods=['POST'])
|
||
def check_block():
|
||
connection = config.get_db_connection()
|
||
cursor = connection.cursor()
|
||
block_name = request.json.get('block_Name', '').strip()
|
||
district_id = request.json.get('district_Id', '')
|
||
|
||
if not re.match(str_pattern_reg, block_name):
|
||
return json_response(ResponseHandler.invalid_name("block"), 400)
|
||
|
||
# cursor.execute("SELECT * FROM blocks WHERE Block_Name = %s AND District_id = %s", (block_name, district_id))
|
||
# existing_block = cursor.fetchone()
|
||
cursor.callproc("GetBlockByNameAndDistrict", (block_name, district_id))
|
||
for rs in cursor.stored_results():
|
||
existing_block = rs.fetchone()
|
||
|
||
if existing_block:
|
||
return json_response(ResponseHandler.already_exists("block"), 409)
|
||
|
||
return json_response(ResponseHandler.is_available("block"), 200)
|
||
|
||
|
||
# update block by id
|
||
# @app.route('/edit_block/<int:block_id>', methods=['GET', 'POST'])
|
||
# def edit_block(block_id):
|
||
# connection = config.get_db_connection()
|
||
# block_data, states, districts = [], [], []
|
||
#
|
||
# if connection:
|
||
# cursor = connection.cursor()
|
||
# try:
|
||
# # cursor.execute("SELECT State_ID, State_Name FROM states")
|
||
# # states = cursor.fetchall()
|
||
# cursor.callproc("GetAllStates")
|
||
# for res in cursor.stored_results():
|
||
# states = res.fetchall()
|
||
#
|
||
# # cursor.execute("SELECT Block_Name, District_id FROM blocks WHERE Block_Id = %s", (block_id,))
|
||
# # block_data = cursor.fetchone()
|
||
# cursor.callproc("GetBlockById",(block_id,))
|
||
# for block in cursor.stored_results():
|
||
# block_data = block.fetchone()
|
||
#
|
||
# except mysql.connector.Error as e:
|
||
# print(f"Error fetching block data: {e}")
|
||
# return json_response(ResponseHandler.fetch_failure("block data"), 500)
|
||
#
|
||
# if request.method == 'POST':
|
||
# block_name = request.form['block_Name']
|
||
# district_id = request.form['district_Id']
|
||
#
|
||
# try:
|
||
# # cursor.execute("UPDATE blocks SET Block_Name = %s, District_id = %s WHERE Block_Id = %s",
|
||
# # (block_name, district_id, block_id))
|
||
#
|
||
# cursor.callproc("UpdateBlock",(block_id,block_name, district_id))
|
||
# connection.commit()
|
||
# except mysql.connector.Error as e:
|
||
# print(f"Error updating block: {e}")
|
||
# return json_response(ResponseHandler.update_failure("block"), 500)
|
||
#
|
||
# return redirect('/add_block')
|
||
#
|
||
# try:
|
||
# # cursor.execute("SELECT District_id, District_Name FROM districts")
|
||
# # districts = cursor.fetchall()
|
||
#
|
||
# cursor.callproc("GetAllDistricts")
|
||
# for dis in cursor.stored_results():
|
||
# districts = dis.fetchall()
|
||
#
|
||
# except mysql.connector.Error as e:
|
||
# print(f"Error fetching districts: {e}")
|
||
# return json_response(ResponseHandler.fetch_failure("districts"), 500)
|
||
#
|
||
# return render_template('edit_block.html', block_data=block_data, states=states, districts=districts)
|
||
|
||
@app.route('/edit_block/<int:block_id>', methods=['GET', 'POST'])
|
||
def edit_block(block_id):
|
||
connection = config.get_db_connection()
|
||
block_data = []
|
||
states = []
|
||
districts = []
|
||
|
||
if connection:
|
||
cursor = connection.cursor()
|
||
# Retrieve all states
|
||
try:
|
||
# cursor.execute("SELECT State_ID, State_Name FROM states")
|
||
# states = cursor.fetchall()
|
||
cursor.callproc("GetAllStates")
|
||
for rs in cursor.stored_results():
|
||
states = rs.fetchall()
|
||
except mysql.connector.Error as e:
|
||
print(f"Error fetching states: {e}")
|
||
return "Failed to fetch states", 500
|
||
|
||
# Retrieve block data
|
||
try:
|
||
# cursor.execute("SELECT Block_Name, District_id FROM blocks WHERE Block_Id = %s", (block_id,))
|
||
# block_data = cursor.fetchone()
|
||
cursor.callproc("GetBlockDataByID", (block_id,))
|
||
for rs in cursor.stored_results():
|
||
block_data = rs.fetchone()
|
||
except mysql.connector.Error as e:
|
||
print(f"Error fetching block data: {e}")
|
||
return "Failed to fetch block data", 500
|
||
|
||
# Handle POST request
|
||
if request.method == 'POST':
|
||
block_name = request.form['block_Name']
|
||
district_id = request.form['district_Id']
|
||
try:
|
||
# cursor.execute("UPDATE blocks SET Block_Name = %s, District_id = %s WHERE Block_Id = %s",
|
||
# (block_name, district_id, block_id))
|
||
cursor.callproc("UpdateBlockById", (block_name, district_id, block_id,))
|
||
connection.commit()
|
||
flash("Block updated successfully!", "success")
|
||
return redirect(url_for('add_block', block_id=block_id))
|
||
except mysql.connector.Error as e:
|
||
print(f"Error updating blocks: {e}")
|
||
return "Failed to update blocks", 500
|
||
|
||
# Retrieve districts for the dropdown
|
||
try:
|
||
# cursor.execute("SELECT District_id, District_Name FROM districts")
|
||
# districts = cursor.fetchall()
|
||
cursor.callproc("GetAllDistrictsData")
|
||
for rs in cursor.stored_results():
|
||
districts = rs.fetchall()
|
||
except mysql.connector.Error as e:
|
||
print(f"Error fetching districts: {e}")
|
||
return "Failed to fetch districts", 500
|
||
|
||
return render_template('edit_block.html', block_data=block_data, states=states, districts=districts)
|
||
|
||
|
||
|
||
|
||
|
||
|
||
# delete block by id
|
||
@app.route('/delete_block/<int:block_id>', methods=['GET', 'POST'])
|
||
def delete_block(block_id):
|
||
connection = config.get_db_connection()
|
||
|
||
if connection:
|
||
cursor = connection.cursor()
|
||
try:
|
||
# cursor.execute("DELETE FROM blocks WHERE Block_Id = %s", (block_id,))
|
||
cursor.callproc("DeleteBlock", (block_id,))
|
||
connection.commit()
|
||
except mysql.connector.Error as e:
|
||
print(f"Error deleting block: {e}")
|
||
return json_response(ResponseHandler.add_failure("block"), 500)
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return redirect('/add_block')
|
||
|
||
|
||
# this is get district all data by using state id ..
|
||
@app.route('/get_districts/<int:state_id>', methods=['GET'])
|
||
def get_districts(state_id):
|
||
connection = config.get_db_connection()
|
||
districts = []
|
||
|
||
if connection:
|
||
cursor = connection.cursor()
|
||
try:
|
||
# cursor.execute("SELECT District_id, District_Name FROM districts WHERE State_Id = %s", (state_id,))
|
||
# districts = cursor.fetchall()
|
||
|
||
cursor.callproc("GetDistrictsByStateId", (state_id,))
|
||
for dis in cursor.stored_results():
|
||
districts = dis.fetchall()
|
||
except mysql.connector.Error as e:
|
||
print(f"Error fetching districts: {e}")
|
||
return json_response(ResponseHandler.fetch_failure("districts"), 500)
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return jsonify({
|
||
"districts": [{"District_id": d[0], "District_Name": d[1]} for d in districts]
|
||
})
|
||
|
||
|
||
# ----------- end Block controller -----------------
|
||
|
||
# ------------------------- Village controller ------------------------------------------
|
||
# Route to add a village
|
||
@app.route('/add_village', methods=['GET', 'POST'])
|
||
def add_village():
|
||
connection = config.get_db_connection()
|
||
cursor = connection.cursor()
|
||
states = []
|
||
villages = []
|
||
|
||
try:
|
||
# Fetch all states
|
||
# cursor.execute("SELECT State_ID, State_Name FROM states")
|
||
# states = cursor.fetchall()
|
||
|
||
cursor.callproc("GetAllStates")
|
||
for res in cursor.stored_results():
|
||
states = res.fetchall()
|
||
|
||
# Fetch all villages with their block names
|
||
# cursor.execute("""
|
||
# SELECT v.Village_Id, v.Village_Name, b.Block_Name
|
||
# FROM villages v
|
||
# JOIN blocks b ON v.Block_Id = b.Block_Id
|
||
# """)
|
||
# villages = cursor.fetchall()
|
||
cursor.callproc("GetAllVillages")
|
||
for result in cursor.stored_results():
|
||
villages = result.fetchall()
|
||
|
||
if request.method == 'POST':
|
||
block_id = request.form.get('block_Id')
|
||
village_name = request.form.get('Village_Name', '').strip()
|
||
|
||
if not block_id:
|
||
return json_response(ResponseHandler.add_failure("block"), 400)
|
||
|
||
if not re.match(str_pattern_reg, village_name):
|
||
return json_response(ResponseHandler.invalid_name("village"), 400)
|
||
|
||
# Check if the village already exists in the block
|
||
# cursor.execute("SELECT * FROM villages WHERE Village_Name = %s AND Block_Id = %s", (village_name, block_id))
|
||
# existing_village = cursor.fetchone()
|
||
cursor.callproc("GetVillageByNameAndBlock", (village_name, block_id,))
|
||
for rs in cursor.stored_results():
|
||
existing_village = rs.fetchone()
|
||
if existing_village:
|
||
return json_response(ResponseHandler.already_exists("village"), 409)
|
||
|
||
# Insert new village
|
||
cursor.callproc('SaveVillage', (village_name, block_id))
|
||
connection.commit()
|
||
|
||
return json_response(ResponseHandler.add_success("village"), 200)
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Database Error: {e}")
|
||
return json_response(ResponseHandler.add_failure("village"), 500)
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return render_template('add_village.html', states=states, villages=villages)
|
||
|
||
|
||
# get block by district id
|
||
@app.route('/get_blocks/<int:district_id>', methods=['GET'])
|
||
def get_blocks(district_id):
|
||
connection = config.get_db_connection()
|
||
cursor = connection.cursor()
|
||
blocks = []
|
||
|
||
try:
|
||
# cursor.execute("SELECT Block_Id, Block_Name FROM blocks WHERE District_id = %s", (district_id,))
|
||
# blocks = cursor.fetchall()
|
||
cursor.callproc("GetBlocksByDistrict", (district_id,))
|
||
for rs in cursor.stored_results():
|
||
blocks = rs.fetchall()
|
||
except mysql.connector.Error as e:
|
||
print(f"Error fetching blocks: {e}")
|
||
return json_response({"error": "Failed to fetch blocks"}, 500)
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return jsonify({"blocks": [{"Block_Id": block[0], "Block_Name": block[1]} for block in blocks]})
|
||
|
||
|
||
# check village
|
||
@app.route('/check_village', methods=['POST'])
|
||
def check_village():
|
||
connection = config.get_db_connection()
|
||
cursor = connection.cursor()
|
||
|
||
block_id = request.form.get('block_Id')
|
||
village_name = request.form.get('Village_Name', '').strip()
|
||
|
||
# Validate village name
|
||
if not re.match(str_pattern_reg, village_name):
|
||
return json_response(ResponseHandler.invalid_name("village"), 400)
|
||
|
||
if not block_id or not village_name:
|
||
return json_response({'status': 'error', 'message': 'Block and Village Name are required!'}, 400)
|
||
|
||
# cursor.execute("SELECT * FROM villages WHERE Village_Name = %s AND Block_Id = %s", (village_name, block_id))
|
||
# existing_village = cursor.fetchone()
|
||
cursor.callproc("GetVillageByNameAndBlocks", (village_name, block_id))
|
||
for rs in cursor.stored_results():
|
||
existing_village = rs.fetchone()
|
||
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
if existing_village:
|
||
return json_response(ResponseHandler.already_exists("village"), 409)
|
||
else:
|
||
return json_response(ResponseHandler.is_available("village"), 200)
|
||
|
||
|
||
# update village
|
||
# @app.route('/edit_village/<int:village_id>', methods=['GET', 'POST'])
|
||
# def edit_village(village_id):
|
||
# connection = config.get_db_connection()
|
||
# village_data = None
|
||
# blocks = []
|
||
#
|
||
# try:
|
||
# cursor = connection.cursor()
|
||
# # Fetch village details
|
||
# # cursor.execute("SELECT Village_Name, Block_Id FROM villages WHERE Village_Id = %s", (village_id,))
|
||
# # village_data = cursor.fetchone()
|
||
# cursor.callproc("GetVillageById", (village_id,))
|
||
# for result in cursor.stored_results():
|
||
# village_data = result.fetchone()
|
||
#
|
||
# # Fetch all blocks for dropdown
|
||
# # cursor.execute("SELECT Block_Id, Block_Name FROM blocks")
|
||
# # blocks = cursor.fetchall()
|
||
#
|
||
# cursor.callproc("GetAllBlocks")
|
||
# for result in cursor.stored_results():
|
||
# blocks = result.fetchall()
|
||
#
|
||
# if request.method == 'POST':
|
||
# village_name = request.form['Village_Name']
|
||
# block_id = request.form['block_Id']
|
||
#
|
||
# if not re.match(str_pattern_reg, village_name):
|
||
# return json_response(ResponseHandler.invalid_name("village"), 400)
|
||
#
|
||
# # cursor.execute("UPDATE villages SET Village_Name = %s, Block_Id = %s WHERE Village_Id = %s",
|
||
# # (village_name, block_id, village_id))
|
||
#
|
||
# cursor.callproc("UpdateVillage", (village_id, village_name, block_id,))
|
||
#
|
||
# connection.commit()
|
||
# return json_response(ResponseHandler.update_success("village"), 200)
|
||
#
|
||
# except mysql.connector.Error as e:
|
||
# print(f"Error: {e}")
|
||
# return json_response(ResponseHandler.update_failure("village"), 500)
|
||
# finally:
|
||
# if cursor:
|
||
# cursor.close()
|
||
# if connection:
|
||
# connection.close()
|
||
#
|
||
# return render_template('edit_village.html', village_data=village_data, blocks=blocks)
|
||
|
||
@app.route('/edit_village/<int:village_id>', methods=['GET', 'POST'])
|
||
def edit_village(village_id):
|
||
connection = config.get_db_connection()
|
||
village_data = None
|
||
blocks = []
|
||
|
||
try:
|
||
cursor = connection.cursor()
|
||
# # Fetch village details
|
||
# cursor.execute("SELECT Village_Name, Block_Id FROM villages WHERE Village_Id = %s", (village_id,))
|
||
# village_data = cursor.fetchone()
|
||
cursor.callproc("GetVillageDetailsById", (village_id,))
|
||
for rs in cursor.stored_results():
|
||
village_data = rs.fetchone()
|
||
# Fetch all blocks for dropdown
|
||
# cursor.execute("SELECT Block_Id, Block_Name FROM blocks")
|
||
# blocks = cursor.fetchall()
|
||
cursor.callproc('GetAllBlocks')
|
||
for result in cursor.stored_results():
|
||
blocks = result.fetchall()
|
||
|
||
if request.method == 'POST':
|
||
village_name = request.form['Village_Name']
|
||
block_id = request.form['block_Id']
|
||
|
||
if not re.match("^[A-Za-z ]+$", village_name):
|
||
flash("Invalid village name! Only letters and spaces allowed.", "error")
|
||
return redirect(url_for('edit_village', village_id=village_id))
|
||
|
||
cursor.execute("UPDATE villages SET Village_Name = %s, Block_Id = %s WHERE Village_Id = %s",
|
||
(village_name, block_id, village_id))
|
||
connection.commit()
|
||
flash("Village updated successfully!", "success")
|
||
return redirect(url_for('edit_village', village_id=village_id))
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Error: {e}")
|
||
return "Failed to process request", 500
|
||
finally:
|
||
if cursor:
|
||
cursor.close()
|
||
if connection:
|
||
connection.close()
|
||
|
||
return render_template('edit_village.html', village_data=village_data, blocks=blocks)
|
||
|
||
|
||
# delete village
|
||
@app.route('/delete_village/<int:village_id>', methods=['GET', 'POST'])
|
||
def delete_village(village_id):
|
||
connection = config.get_db_connection()
|
||
cursor = connection.cursor()
|
||
|
||
try:
|
||
# cursor.execute("DELETE FROM villages WHERE Village_Id = %s", (village_id,))
|
||
cursor.callproc("DeleteVillage", (village_id,))
|
||
connection.commit()
|
||
# return json_response(ResponseHandler.delete_success("village"), 200)
|
||
except mysql.connector.Error as e:
|
||
print(f"Error: {e}")
|
||
return json_response(ResponseHandler.add_failure("village"), 500)
|
||
finally:
|
||
if cursor:
|
||
cursor.close()
|
||
if connection:
|
||
connection.close()
|
||
|
||
return redirect(url_for('add_village'))
|
||
|
||
|
||
# ---- end Village controller ---------------------
|
||
|
||
|
||
# -------------------------------- Invoice controller ------------------------------------------
|
||
@app.route('/add_invoice', methods=['GET', 'POST'])
|
||
def add_invoice():
|
||
connection = config.get_db_connection()
|
||
if not connection:
|
||
return jsonify({"status": "error", "message": "Database connection failed"}), 500
|
||
|
||
if request.method == 'POST':
|
||
try:
|
||
cursor = connection.cursor(dictionary=True)
|
||
|
||
# Get the village name from the form
|
||
village_name = request.form.get('village')
|
||
print("village name", village_name)
|
||
|
||
# Query the database to get the corresponding Village_Id based on the village name
|
||
# cursor.execute("SELECT Village_Id FROM villages WHERE Village_Name = %s", (village_name,))
|
||
# village_result = cursor.fetchone()
|
||
cursor.callproc("GetVillageIdByName", (village_name,))
|
||
for rs in cursor.stored_results():
|
||
village_result = rs.fetchone()
|
||
|
||
if not village_result:
|
||
return jsonify({"status": "error", "message": f"Village '{village_name}' not found"}), 400
|
||
|
||
village_id = village_result['Village_Id']
|
||
|
||
# Fetch form data
|
||
pmc_no = request.form.get('pmc_no')
|
||
work_type = request.form.get('work_type')
|
||
invoice_details = request.form.get('invoice_details')
|
||
invoice_date = request.form.get('invoice_date')
|
||
invoice_no = request.form.get('invoice_no')
|
||
basic_amount = request.form.get('basic_amount')
|
||
debit_amount = request.form.get('debit_amount')
|
||
after_debit_amount = request.form.get('after_debit_amount')
|
||
amount = request.form.get('amount')
|
||
gst_amount = request.form.get('gst_amount')
|
||
tds_amount = request.form.get('tds_amount')
|
||
sd_amount = request.form.get('sd_amount')
|
||
on_commission = request.form.get('on_commission')
|
||
hydro_testing = request.form.get('hydro_testing')
|
||
gst_sd_amount = request.form.get('gst_sd_amount')
|
||
final_amount = request.form.get('final_amount')
|
||
|
||
# insert_invoice_query = '''
|
||
# INSERT INTO invoice (
|
||
# PMC_No, Village_Id, Work_Type, Invoice_Details, Invoice_Date, Invoice_No,
|
||
# Basic_Amount, Debit_Amount, After_Debit_Amount, Amount, GST_Amount, TDS_Amount,
|
||
# SD_Amount, On_Commission, Hydro_Testing, GST_SD_Amount, Final_Amount
|
||
# ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||
# '''
|
||
# invoice_values = (
|
||
# pmc_no, village_id, work_type, invoice_details, invoice_date, invoice_no,
|
||
# basic_amount, debit_amount, after_debit_amount, amount, gst_amount, tds_amount,
|
||
# sd_amount, on_commission, hydro_testing, gst_sd_amount, final_amount
|
||
# )
|
||
# cursor.execute(insert_invoice_query, invoice_values)
|
||
# connection.commit()
|
||
# invoice_id = cursor.lastrowid
|
||
cursor.callproc('InsertInvoice', [
|
||
pmc_no, village_id, work_type, invoice_details, invoice_date, invoice_no,
|
||
basic_amount, debit_amount, after_debit_amount, amount, gst_amount, tds_amount,
|
||
sd_amount, on_commission, hydro_testing, gst_sd_amount, final_amount])
|
||
|
||
for result in cursor.stored_results():
|
||
invoice_id = result.fetchone()['invoice_id']
|
||
connection.commit()
|
||
|
||
print("This is the invocie id from the invoice table ", invoice_id)
|
||
|
||
# Insert into assign_subcontractors table
|
||
# subcontractor_id = request.form.get('subcontractor_id')
|
||
# insert_assign_query = '''
|
||
# INSERT INTO assign_subcontractors (PMC_no, Contractor_Id, Village_Id)
|
||
# VALUES (%s, %s, %s)
|
||
# '''
|
||
# cursor.execute(insert_assign_query, (pmc_no, subcontractor_id, village_id))
|
||
# connection.commit()
|
||
subcontractor_id = request.form.get('subcontractor_id')
|
||
cursor.callproc('AssignSubcontractor', [pmc_no, subcontractor_id, village_id])
|
||
connection.commit()
|
||
|
||
# Insert Hold Amounts into invoice_subcontractor_hold_join table
|
||
hold_types = request.form.getlist('hold_type[]')
|
||
hold_amounts = request.form.getlist('hold_amount[]')
|
||
hold_count = 0
|
||
|
||
for hold_type, hold_amount in zip(hold_types, hold_amounts):
|
||
# cursor.execute("SELECT hold_type_id FROM hold_types WHERE hold_type = %s", (hold_type,))
|
||
# hold_type_result = cursor.fetchone()
|
||
cursor.callproc('GetHoldTypeIdByName', [hold_type])
|
||
for result in cursor.stored_results():
|
||
hold_type_result = result.fetchone()
|
||
print("hold type from invoice ", hold_type_result)
|
||
if not hold_type_result:
|
||
return jsonify({"status": "error", "message": f"Invalid Hold Type: {hold_type}"}), 400
|
||
hold_type_id = hold_type_result['hold_type_id']
|
||
# insert_hold_query = '''
|
||
# INSERT INTO invoice_subcontractor_hold_join (Contractor_Id, Invoice_Id, hold_type_id, hold_amount)
|
||
# VALUES (%s, %s, %s, %s)
|
||
# '''
|
||
# cursor.execute(insert_hold_query, (subcontractor_id, invoice_id, hold_type_id, hold_amount))
|
||
# hold_count += 1
|
||
|
||
# connection.commit()
|
||
cursor.callproc('InsertInvoiceSubcontractorHold', [
|
||
subcontractor_id, invoice_id, hold_type_id, hold_amount
|
||
])
|
||
connection.commit()
|
||
hold_count += 1
|
||
print("Hold count from the invoice", hold_count)
|
||
connection.commit()
|
||
|
||
return jsonify({"status": "success", "message": "Invoice added successfully"}), 201
|
||
|
||
except mysql.connector.Error as e:
|
||
connection.rollback()
|
||
return jsonify({"status": "error", "message": f"Failed to add invoice: {str(e)}"}), 500
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
# GET request: fetch and display all invoices (all fields) along with the form
|
||
try:
|
||
cursor = connection.cursor(dictionary=True)
|
||
# cursor.execute("SELECT * FROM view_invoice_details")
|
||
# invoices = cursor.fetchall()
|
||
cursor.callproc('GetAllInvoiceDetails')
|
||
for result in cursor.stored_results():
|
||
invoices = result.fetchall()
|
||
|
||
villages = []
|
||
cursor.callproc("GetAllVillages")
|
||
for result in cursor.stored_results():
|
||
villages = result.fetchall()
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Error: {e}")
|
||
invoices = []
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return render_template('add_invoice.html', invoices=invoices, villages=villages)
|
||
|
||
|
||
# search subcontraactor to assing invoice
|
||
@app.route('/search_subcontractor', methods=['POST'])
|
||
def search_subcontractor():
|
||
connection = config.get_db_connection()
|
||
if not connection:
|
||
return json_response(ResponseHandler.fetch_failure("database connection"), 500)
|
||
|
||
sub_query = request.form.get("query")
|
||
try:
|
||
cursor = connection.cursor(dictionary=True)
|
||
# cursor.execute(
|
||
# "SELECT Contractor_Id, Contractor_Name FROM subcontractors WHERE Contractor_Name LIKE %s",
|
||
# (f"%{sub_query}%",)
|
||
# )
|
||
# results = cursor.fetchall()
|
||
cursor.callproc('SearchContractorsByName', [sub_query])
|
||
for result in cursor.stored_results():
|
||
results = result.fetchall()
|
||
print(results)
|
||
if not results:
|
||
return "<li>No subcontractor found</li>"
|
||
|
||
output = "".join(
|
||
f"<li data-id='{row['Contractor_Id']}'>{row['Contractor_Name']}</li>"
|
||
for row in results
|
||
)
|
||
print("Ajax Call for subcontractor", output)
|
||
return output
|
||
|
||
except mysql.connector.Error as e:
|
||
return json_response(ResponseHandler.fetch_failure(f"Search failed: {str(e)}"), 500)
|
||
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
|
||
# get hold types
|
||
@app.route('/get_hold_types', methods=['GET'])
|
||
def get_hold_types():
|
||
connection = config.get_db_connection()
|
||
try:
|
||
cursor = connection.cursor(dictionary=True)
|
||
# cursor.execute("SELECT hold_type_id, hold_type FROM hold_types")
|
||
# hold_types = cursor.fetchall()
|
||
|
||
cursor.callproc("GetAllHoldTypes")
|
||
for hold in cursor.stored_results():
|
||
hold_types = hold.fetchall()
|
||
|
||
return jsonify(hold_types)
|
||
except mysql.connector.Error as e:
|
||
return ResponseHandler.fetch_failure({str(e)}), 500
|
||
# return jsonify({"status": "error", "message": f"Failed to fetch hold types: {str(e)}"}), 500
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
|
||
# update invoice by id
|
||
|
||
@app.route('/edit_invoice/<int:invoice_id>', methods=['GET', 'POST'])
|
||
def edit_invoice(invoice_id):
|
||
connection = config.get_db_connection()
|
||
if not connection:
|
||
return jsonify({"status": "error", "message": "Database connection failed"}), 500
|
||
|
||
cursor = connection.cursor(dictionary=True)
|
||
|
||
if request.method == 'POST':
|
||
try:
|
||
# Fetch updated form data
|
||
subcontractor_id = request.form.get('subcontractor_id', '').strip()
|
||
subcontractor_id = int(subcontractor_id) if subcontractor_id else None
|
||
|
||
village_name = request.form.get('village')
|
||
# cursor.execute("SELECT Village_Id FROM villages WHERE Village_Name = %s", (village_name,))
|
||
# village_result = cursor.fetchone()
|
||
cursor.callproc("GetVillageIdByName", (village_name,))
|
||
for rs in cursor.stored_results():
|
||
village_result = rs.fetchone()
|
||
if not village_result:
|
||
return jsonify({"status": "error", "message": "Invalid Village Name"}), 400
|
||
village_id = village_result['Village_Id']
|
||
|
||
pmc_no = request.form.get('pmc_no')
|
||
work_type = request.form.get('work_type')
|
||
invoice_details = request.form.get('invoice_details')
|
||
invoice_date = request.form.get('invoice_date')
|
||
invoice_no = request.form.get('invoice_no')
|
||
|
||
# Convert numeric fields properly
|
||
numeric_fields = {
|
||
"basic_amount": request.form.get('basic_amount'),
|
||
"debit_amount": request.form.get('debit_amount'),
|
||
"after_debit_amount": request.form.get('after_debit_amount'),
|
||
"amount": request.form.get('amount'),
|
||
"gst_amount": request.form.get('gst_amount'),
|
||
"tds_amount": request.form.get('tds_amount'),
|
||
"sd_amount": request.form.get('sd_amount'),
|
||
"on_commission": request.form.get('on_commission'),
|
||
"hydro_testing": request.form.get('hydro_testing'),
|
||
"gst_sd_amount": request.form.get('gst_sd_amount'),
|
||
"final_amount": request.form.get('final_amount'),
|
||
}
|
||
numeric_fields = {k: float(v) if v else 0 for k, v in numeric_fields.items()}
|
||
|
||
# # Update invoice
|
||
# update_invoice_query = '''
|
||
# UPDATE invoice
|
||
# SET PMC_No=%s, Village_Id=%s, Work_Type=%s, Invoice_Details=%s, Invoice_Date=%s,
|
||
# Invoice_No=%s, Basic_Amount=%s, Debit_Amount=%s, After_Debit_Amount=%s,
|
||
# Amount=%s, GST_Amount=%s, TDS_Amount=%s, SD_Amount=%s, On_Commission=%s,
|
||
# Hydro_Testing=%s, GST_SD_Amount=%s, Final_Amount=%s
|
||
# WHERE Invoice_Id=%s
|
||
# '''
|
||
# invoice_values = (
|
||
# pmc_no, village_id, work_type, invoice_details, invoice_date, invoice_no,
|
||
# *numeric_fields.values(), invoice_id
|
||
# )
|
||
# cursor.execute(update_invoice_query, invoice_values)
|
||
# connection.commit()
|
||
cursor.callproc('UpdateInvoice', [
|
||
pmc_no, village_id, work_type, invoice_details, invoice_date, invoice_no,
|
||
*numeric_fields.values(), invoice_id
|
||
])
|
||
connection.commit()
|
||
|
||
# Handle holds
|
||
hold_types = request.form.getlist('hold_type[]')
|
||
hold_amounts = request.form.getlist('hold_amount[]')
|
||
|
||
for hold_type, hold_amount in zip(hold_types, hold_amounts):
|
||
if not hold_type:
|
||
continue # skip empty hold types
|
||
|
||
# Get or insert hold type
|
||
# cursor.execute("SELECT hold_type_id FROM hold_types WHERE hold_type = %s", (hold_type,))
|
||
# hold_type_result = cursor.fetchone()
|
||
cursor.callproc('GetHoldTypeIdByName', [hold_type])
|
||
for result in cursor.stored_results():
|
||
hold_type_result = result.fetchone()
|
||
|
||
# if not hold_type_result:
|
||
# cursor.execute("INSERT INTO hold_types (hold_type) VALUES (%s)", (hold_type,))
|
||
# connection.commit()
|
||
# hold_type_id = cursor.lastrowid
|
||
# else:
|
||
# hold_type_id = hold_type_result['hold_type_id']
|
||
|
||
if not hold_type_result:
|
||
# Call stored procedure to insert and return new ID
|
||
cursor.callproc('InsertHoldType', [hold_type, 0])
|
||
for result in cursor.stored_results():
|
||
pass # advance past any results
|
||
cursor.execute("SELECT @_InsertHoldType_1")
|
||
hold_type_id = cursor.fetchone()[0]
|
||
print("if not hold type result anish:", hold_type_id)
|
||
else:
|
||
hold_type_id = hold_type_result['hold_type_id']
|
||
print("if hold type result anish:", hold_type_id)
|
||
|
||
hold_amount = float(hold_amount) if hold_amount else 0
|
||
|
||
# Check if join exists
|
||
# cursor.execute("""
|
||
# SELECT join_id FROM invoice_subcontractor_hold_join
|
||
# WHERE Invoice_Id = %s AND Contractor_Id = %s AND hold_type_id = %s
|
||
# """, (invoice_id, subcontractor_id, hold_type_id))
|
||
# join_result = cursor.fetchone()
|
||
cursor.callproc('GetHoldJoinId', [invoice_id, subcontractor_id, hold_type_id])
|
||
for result in cursor.stored_results():
|
||
join_result = result.fetchone()
|
||
|
||
if join_result:
|
||
# cursor.execute("""
|
||
# UPDATE invoice_subcontractor_hold_join
|
||
# SET hold_amount = %s
|
||
# WHERE join_id = %s
|
||
# """, (hold_amount, join_result['join_id']))
|
||
cursor.callproc('UpdateHoldAmountByJoinId', [hold_amount, join_result['join_id']])
|
||
connection.commit()
|
||
|
||
else:
|
||
# cursor.execute("""
|
||
# INSERT INTO invoice_subcontractor_hold_join (Contractor_Id, Invoice_Id, hold_type_id, hold_amount)
|
||
# VALUES (%s, %s, %s, %s)
|
||
# """, (subcontractor_id, invoice_id, hold_type_id, hold_amount))
|
||
cursor.callproc('InsertInvoiceSubcontractorHold', [
|
||
subcontractor_id, invoice_id, hold_type_id, hold_amount
|
||
])
|
||
connection.commit()
|
||
|
||
connection.commit()
|
||
return jsonify({"status": "success", "message": "Invoice updated successfully"}), 200
|
||
|
||
except mysql.connector.Error as e:
|
||
connection.rollback()
|
||
return jsonify({"status": "error", "message": f"Failed to update invoice: {str(e)}"}), 500
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
# ------------------ GET Request ------------------
|
||
|
||
try:
|
||
# Fetch invoice data
|
||
# cursor.execute(
|
||
# """SELECT i.*, s.Contractor_Name, v.Village_Name
|
||
# FROM invoice i
|
||
# LEFT JOIN assign_subcontractors a ON i.PMC_No = a.PMC_no AND i.Village_Id = a.Village_Id
|
||
# LEFT JOIN subcontractors s ON a.Contractor_Id = s.Contractor_Id
|
||
# LEFT JOIN villages v ON i.Village_Id = v.Village_Id
|
||
# WHERE i.Invoice_Id = %s""", (invoice_id,)
|
||
# )
|
||
# invoice = cursor.fetchone()
|
||
cursor.callproc('GetInvoiceDetailsById', [invoice_id])
|
||
for result in cursor.stored_results():
|
||
invoice = result.fetchone()
|
||
|
||
if not invoice:
|
||
return jsonify({"status": "error", "message": "Invoice not found"}), 404
|
||
|
||
# Important! Clear unread result issue
|
||
while cursor.nextset():
|
||
pass
|
||
|
||
# Fetch hold amounts
|
||
# cursor.execute(
|
||
# """SELECT h.hold_type, ihj.hold_amount
|
||
# FROM invoice_subcontractor_hold_join ihj
|
||
# JOIN hold_types h ON ihj.hold_type_id = h.hold_type_id
|
||
# WHERE ihj.Invoice_Id = %s""", (invoice_id,)
|
||
# )
|
||
# hold_amounts = cursor.fetchall()
|
||
# invoice["hold_amounts"] = hold_amounts
|
||
cursor.callproc('GetHoldAmountsByInvoiceId', [invoice_id])
|
||
for result in cursor.stored_results():
|
||
hold_amounts = result.fetchall()
|
||
|
||
invoice["hold_amounts"] = hold_amounts
|
||
|
||
|
||
except mysql.connector.Error as e:
|
||
return jsonify({"status": "error", "message": f"Database error: {str(e)}"}), 500
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return render_template('edit_invoice.html', invoice=invoice)
|
||
|
||
|
||
# delete invoice by id
|
||
@app.route('/delete_invoice/<int:invoice_id>', methods=['GET'])
|
||
def delete_invoice(invoice_id):
|
||
connection = config.get_db_connection()
|
||
if not connection:
|
||
return json_response(ResponseHandler.fetch_failure("invoice"), 500)
|
||
|
||
try:
|
||
cursor = connection.cursor()
|
||
# cursor.execute("DELETE FROM invoice WHERE Invoice_Id = %s", (invoice_id,))
|
||
|
||
cursor.callproc("DeleteInvoice", (invoice_id,))
|
||
connection.commit()
|
||
|
||
# Check if the invoice was actually deleted
|
||
if cursor.rowcount == 0:
|
||
return json_response(ResponseHandler.fetch_failure("invoice"), 404)
|
||
|
||
return redirect(url_for('add_invoice'))
|
||
|
||
except mysql.connector.Error as e:
|
||
print("Error deleting invoice:", e)
|
||
return json_response(ResponseHandler.delete_failure("invoice"), 500)
|
||
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
|
||
# ---------- end Invoice controller ------------------
|
||
|
||
|
||
# ----------------------------- Payment controller ------------------------------------------
|
||
# this is Payment Page to add data
|
||
# @app.route('/add_payment', methods=['GET', 'POST'])
|
||
# def add_payment():
|
||
# connection = config.get_db_connection()
|
||
# payments = [] # List to hold payment history
|
||
#
|
||
# if not connection:
|
||
# return json_response(ResponseHandler.fetch_failure("payment"), 500)
|
||
#
|
||
# try:
|
||
# cursor = connection.cursor()
|
||
#
|
||
# # Retrieve payment history
|
||
# # cursor.execute(
|
||
# # "SELECT Payment_Id, PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR FROM payment"
|
||
# # )
|
||
# # payments = cursor.fetchall()
|
||
# 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}")
|
||
# return json_response(ResponseHandler.fetch_failure("payment"), 500)
|
||
# finally:
|
||
# cursor.close()
|
||
#
|
||
# if request.method == 'POST':
|
||
# pmc_no = request.form['PMC_No']
|
||
# invoice_no = request.form['invoice_No']
|
||
# amount = request.form['Payment_Amount']
|
||
# tds_amount = request.form['TDS_Payment_Amount']
|
||
# total_amount = request.form['total_amount']
|
||
# utr = request.form['utr']
|
||
#
|
||
# try:
|
||
# cursor = connection.cursor()
|
||
# cursor.callproc('SavePayment', (
|
||
# pmc_no, invoice_no, amount, tds_amount, total_amount, utr
|
||
# ))
|
||
# connection.commit()
|
||
# return redirect(url_for('add_payment')) # Redirect to add_payment page to reload the form
|
||
# except mysql.connector.Error as e:
|
||
# print(f"Error inserting payment: {e}")
|
||
# return json_response(ResponseHandler.add_failure("payment"), 500)
|
||
# finally:
|
||
# cursor.close()
|
||
# connection.close()
|
||
#
|
||
# return render_template('add_payment.html', payments=payments)
|
||
|
||
@app.route('/add_payment', methods=['GET', 'POST'])
|
||
def add_payment():
|
||
connection = config.get_db_connection()
|
||
payments = []
|
||
|
||
if connection:
|
||
cursor = connection.cursor()
|
||
|
||
try:
|
||
# cursor.execute(
|
||
# "SELECT Payment_Id, PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR FROM payment"
|
||
# )
|
||
# payments = cursor.fetchall()
|
||
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}")
|
||
return "Failed to fetch payment history", 500
|
||
finally:
|
||
cursor.close()
|
||
|
||
if request.method == 'POST':
|
||
pmc_no = request.form['PMC_No']
|
||
invoice_no = request.form['invoice_No']
|
||
amount = request.form['Payment_Amount']
|
||
tds_amount = request.form['TDS_Payment_Amount']
|
||
total_amount = request.form['total_amount']
|
||
utr = request.form['utr']
|
||
|
||
try:
|
||
cursor = connection.cursor()
|
||
# cursor.execute('''INSERT INTO payment (PMC_No, invoice_no, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR)
|
||
# VALUES (%s, %s, %s, %s, %s, %s)''',
|
||
# (pmc_no, invoice_no, amount, tds_amount, total_amount, utr))
|
||
# connection.commit()
|
||
cursor.callproc('InsertPayments', [
|
||
pmc_no, invoice_no, amount, tds_amount, total_amount, utr
|
||
])
|
||
connection.commit()
|
||
|
||
return redirect(url_for('add_payment'))
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Error inserting payment: {e}")
|
||
return "Failed to add payment", 500
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return render_template('add_payment.html', payments=payments)
|
||
|
||
|
||
@app.route('/get_pmc_nos_by_subcontractor/<subcontractorId>')
|
||
def get_pmc_nos_by_subcontractor(subcontractorId):
|
||
connection = config.get_db_connection()
|
||
cur = connection.cursor()
|
||
print(subcontractorId)
|
||
# query = """
|
||
# SELECT DISTINCT i.PMC_No
|
||
# FROM invoice i
|
||
# JOIN assign_subcontractors a ON i.PMC_No = a.PMC_no
|
||
# JOIN subcontractors s ON a.Contractor_Id = s.Contractor_Id
|
||
# WHERE s.Contractor_Id=%s;
|
||
# """
|
||
# cur.execute(query, (subcontractorId,))
|
||
# results = cur.fetchall()
|
||
cur.callproc('GetDistinctPMCNoByContractorId', [subcontractorId])
|
||
for result in cur.stored_results():
|
||
results = result.fetchall()
|
||
|
||
print(results)
|
||
pmc_nos = [row[0] for row in results]
|
||
cur.close()
|
||
return jsonify({'pmc_nos': pmc_nos})
|
||
|
||
|
||
# Edit Payment Route
|
||
@app.route('/edit_payment/<int:payment_id>', methods=['GET', 'POST'])
|
||
def edit_payment(payment_id):
|
||
connection = config.get_db_connection()
|
||
payment_data = {} # To hold the payment data for the given ID
|
||
|
||
if not connection:
|
||
return json_response(ResponseHandler.fetch_failure("payment"), 500)
|
||
|
||
try:
|
||
cursor = connection.cursor()
|
||
|
||
# Fetch the existing payment data for the given payment_id
|
||
# cursor.execute(
|
||
# "SELECT Payment_Id, PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR FROM payment WHERE Payment_Id = %s",
|
||
# (payment_id,)
|
||
# )
|
||
# payment_data = cursor.fetchone()
|
||
|
||
cursor.callproc("GetPaymentById", (payment_id,))
|
||
for result in cursor.stored_results():
|
||
payment_data = result.fetchone()
|
||
|
||
# Handle POST request to update the payment
|
||
if request.method == 'POST':
|
||
pmc_no = request.form['PMC_No']
|
||
invoice_no = request.form['invoice_No']
|
||
amount = request.form['Payment_Amount']
|
||
tds_amount = request.form['TDS_Payment_Amount']
|
||
total_amount = request.form['total_amount']
|
||
utr = request.form['utr']
|
||
|
||
try:
|
||
# cursor.execute('''UPDATE payment SET PMC_No=%s, Invoice_No=%s, Payment_Amount=%s, TDS_Payment_Amount=%s,
|
||
# Total_Amount=%s, UTR=%s WHERE Payment_Id=%s''',
|
||
# (pmc_no, invoice_no, amount, tds_amount, total_amount, utr, payment_id))
|
||
|
||
cursor.callproc("UpdatePayment",
|
||
(payment_id, pmc_no, invoice_no, amount, tds_amount, total_amount, utr,))
|
||
connection.commit()
|
||
|
||
return redirect(url_for('add_payment')) # Redirect to add_payment page to view the updated list
|
||
except mysql.connector.Error as e:
|
||
print(f"Error updating payment: {e}")
|
||
return json_response(ResponseHandler.update_failure("payment"), 500)
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Error fetching payment data: {e}")
|
||
return json_response(ResponseHandler.fetch_failure("payment"), 500)
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return render_template('edit_payment.html', payment_data=payment_data)
|
||
|
||
|
||
# Delete Payment Route
|
||
@app.route('/delete_payment/<int:payment_id>', methods=['GET', 'POST'])
|
||
def delete_payment(payment_id):
|
||
connection = config.get_db_connection()
|
||
if not connection:
|
||
return json_response(ResponseHandler.fetch_failure("payment"), 500)
|
||
try:
|
||
cursor = connection.cursor()
|
||
# cursor.execute("DELETE FROM payment WHERE Payment_Id = %s", (payment_id,))
|
||
|
||
cursor.callproc("DeletePayment", (payment_id,))
|
||
connection.commit()
|
||
# Check if any rows were deleted
|
||
if cursor.rowcount == 0:
|
||
return json_response(ResponseHandler.fetch_failure("payment"), 404)
|
||
return redirect(url_for('add_payment')) # Redirect back to the add_payment page
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Error deleting payment: {e}")
|
||
return json_response(ResponseHandler.delete_failure("payment"), 500)
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
|
||
# --- end Payment controller -----------
|
||
|
||
# ------------------------- GST Release controller ------------------------------------------
|
||
@app.route('/add_gst_release', methods=['GET', 'POST'])
|
||
def add_gst_release():
|
||
connection = config.get_db_connection()
|
||
gst_releases = [] # List to hold GST Release history
|
||
invoices = [] # List to hold invoices for the dropdown
|
||
|
||
if not connection:
|
||
return json_response(ResponseHandler.fetch_failure("GST Release"), 500)
|
||
|
||
try:
|
||
cursor = connection.cursor()
|
||
|
||
# Retrieve GST Release history
|
||
# cursor.execute("SELECT GST_Release_Id, PMC_No, Invoice_No, Basic_Amount, Final_Amount FROM gst_release")
|
||
# gst_releases = cursor.fetchall()
|
||
|
||
cursor.callproc("GetAllGSTReleases")
|
||
for result in cursor.stored_results():
|
||
gst_releases = result.fetchall()
|
||
|
||
if request.method == 'POST':
|
||
pmc_no = request.form['PMC_No']
|
||
invoice_no = request.form['invoice_No']
|
||
basic_amount = request.form['basic_amount']
|
||
final_amount = request.form['final_amount']
|
||
|
||
cursor.callproc('SaveGSTRelease', (
|
||
pmc_no, invoice_no, basic_amount, final_amount
|
||
))
|
||
connection.commit()
|
||
|
||
return redirect(url_for('add_gst_release')) # Redirect to add_gst_release page
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Error: {e}")
|
||
return json_response(ResponseHandler.add_failure("GST Release"), 500)
|
||
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return render_template('add_gst_release.html', invoices=invoices, gst_releases=gst_releases)
|
||
|
||
|
||
# update gst Release by id
|
||
@app.route('/edit_gst_release/<int:gst_release_id>', methods=['GET', 'POST'])
|
||
def edit_gst_release(gst_release_id):
|
||
connection = config.get_db_connection()
|
||
gst_release_data = {} # To hold the GST release data for the given ID
|
||
invoices = [] # List to hold invoices for the dropdown
|
||
|
||
if not connection:
|
||
return json_response(ResponseHandler.fetch_failure("GST Release"), 500)
|
||
|
||
try:
|
||
cursor = connection.cursor()
|
||
|
||
# Fetch the existing GST release data for the given gst_release_id
|
||
# cursor.execute(
|
||
# "SELECT GST_Release_Id, PMC_No, Invoice_No, Basic_Amount, Final_Amount FROM gst_release WHERE GST_Release_Id = %s",
|
||
# (gst_release_id,)
|
||
# )
|
||
# gst_release_data = cursor.fetchone()
|
||
|
||
cursor.callproc("GetGSTReleaseById", (gst_release_id,))
|
||
for result in cursor.stored_results():
|
||
gst_release_data = result.fetchone()
|
||
|
||
if request.method == 'POST':
|
||
pmc_id = request.form['PMC_No']
|
||
invoice_no = request.form['invoice_No']
|
||
basic_amount = request.form['basic_amount']
|
||
final_amount = request.form['final_amount']
|
||
|
||
try:
|
||
# cursor.execute('''UPDATE gst_release SET PMC_No=%s, Invoice_No=%s, Basic_Amount=%s, Final_Amount=%s
|
||
# WHERE GST_Release_Id=%s''',
|
||
# (pmc_id, invoice_no, basic_amount, final_amount, gst_release_id))
|
||
|
||
cursor.callproc("UpdateGSTRelease", (gst_release_id, pmc_id, invoice_no, basic_amount, final_amount))
|
||
|
||
connection.commit()
|
||
|
||
return redirect(url_for('add_gst_release')) # Redirect to the page to view the updated list
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Error updating GST Release: {e}")
|
||
return json_response(ResponseHandler.update_failure("GST Release"), 500)
|
||
|
||
except mysql.connector.Error as e:
|
||
print(f"Error fetching GST Release data: {e}")
|
||
return json_response(ResponseHandler.fetch_failure("GST Release"), 500)
|
||
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return render_template('edit_gst_release.html', gst_release_data=gst_release_data, invoices=invoices)
|
||
|
||
|
||
# delete gst release by id
|
||
@app.route('/delete_gst_release/<int:gst_release_id>', methods=['GET', 'POST'])
|
||
def delete_gst_release(gst_release_id):
|
||
connection = config.get_db_connection()
|
||
if not connection:
|
||
return json_response(ResponseHandler.fetch_failure("GST Release"), 500)
|
||
try:
|
||
cursor = connection.cursor()
|
||
# cursor.execute("DELETE FROM gst_release WHERE GST_Release_Id = %s", (gst_release_id,))
|
||
cursor.callproc("DeleteGSTRelease", (gst_release_id,))
|
||
connection.commit()
|
||
# Check if any rows were deleted
|
||
if cursor.rowcount == 0:
|
||
return json_response(ResponseHandler.fetch_failure("GST Release"), 404)
|
||
return redirect(url_for('add_gst_release')) # Redirect to the add_gst_release page
|
||
except mysql.connector.Error as e:
|
||
print(f"Error deleting GST Release: {e}")
|
||
return json_response(ResponseHandler.delete_failure("GST Release"), 500)
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
|
||
# --- end GST Release controller -----
|
||
|
||
# ------------------------- Subcontractor controller ------------------------------------------
|
||
@app.route('/subcontractor', methods=['GET', 'POST'])
|
||
def subcontract():
|
||
connection = config.get_db_connection()
|
||
subcontractor = []
|
||
|
||
if not connection:
|
||
return json_response(ResponseHandler.fetch_failure("Subcontractor"), 500)
|
||
|
||
try:
|
||
cursor = connection.cursor()
|
||
|
||
if request.method == 'GET':
|
||
try:
|
||
# cursor.execute('SELECT * FROM subcontractors;')
|
||
# subcontractor = cursor.fetchall() # Fetch the current subcontractor list
|
||
# connection.commit()
|
||
cursor.callproc('GetAllSubcontractors')
|
||
for result in cursor.stored_results():
|
||
subcontractor = result.fetchall()
|
||
|
||
except Error as e:
|
||
print(f"Error fetching data: {e}")
|
||
return json_response(ResponseHandler.fetch_failure("Subcontractor"), 500)
|
||
|
||
if request.method == 'POST':
|
||
contractor_data = {
|
||
'Contractor_Name': request.form['Contractor_Name'],
|
||
'Address': request.form['Address'],
|
||
'Mobile_No': request.form['Mobile_No'],
|
||
'PAN_No': request.form['PAN_No'],
|
||
'Email': request.form['Email'],
|
||
'Gender': request.form['Gender'],
|
||
'GST_Registration_Type': request.form['GST_Registration_Type'],
|
||
'GST_No': request.form['GST_No'],
|
||
'Contractor_password': request.form['Contractor_password'],
|
||
}
|
||
|
||
try:
|
||
cursor.callproc('SaveContractor', (
|
||
contractor_data['Contractor_Name'],
|
||
contractor_data['Address'],
|
||
contractor_data['Mobile_No'],
|
||
contractor_data['PAN_No'],
|
||
contractor_data['Email'],
|
||
contractor_data['Gender'],
|
||
contractor_data['GST_Registration_Type'],
|
||
contractor_data['GST_No'],
|
||
contractor_data['Contractor_password']
|
||
))
|
||
connection.commit()
|
||
|
||
# Re-fetch subcontractors after inserting the new one
|
||
# cursor.execute('SELECT * FROM subcontractors')
|
||
# subcontractor = cursor.fetchall()
|
||
cursor.callproc('GetAllSubcontractors')
|
||
for result in cursor.stored_results():
|
||
subcontractor = result.fetchall()
|
||
|
||
|
||
except Error as e:
|
||
print(f"Error inserting data: {e}")
|
||
return json_response(ResponseHandler.add_failure("Subcontractor"), 500)
|
||
|
||
except Error as e:
|
||
print(f"Error handling subcontractor data: {e}")
|
||
return json_response(ResponseHandler.fetch_failure("Subcontractor"), 500)
|
||
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return render_template('add_subcontractor.html', subcontractor=subcontractor)
|
||
|
||
|
||
# update subcontractor by id
|
||
@app.route('/edit_subcontractor/<int:id>', methods=['GET', 'POST'])
|
||
def edit_subcontractor(id):
|
||
connection = config.get_db_connection()
|
||
|
||
if not connection:
|
||
return json_response(ResponseHandler.fetch_failure("Subcontractor"), 500)
|
||
|
||
try:
|
||
cursor = connection.cursor()
|
||
subcontractor = None
|
||
|
||
# Fetch existing subcontractor data by ID
|
||
# cursor.execute('SELECT * FROM subcontractors WHERE Contractor_Id = %s', (id,))
|
||
# subcontractor = cursor.fetchone()
|
||
|
||
cursor.callproc("GetSubcontractorById", (id,))
|
||
for contractors in cursor.stored_results():
|
||
subcontractor = contractors.fetchone()
|
||
|
||
if not subcontractor:
|
||
return json_response(ResponseHandler.fetch_failure("Subcontractor"), 404)
|
||
|
||
if request.method == 'POST':
|
||
updated_data = {
|
||
'Contractor_Name': request.form['Contractor_Name'],
|
||
'Address': request.form['Address'],
|
||
'Mobile_No': request.form['Mobile_No'],
|
||
'PAN_No': request.form['PAN_No'],
|
||
'Email': request.form['Email'],
|
||
'Gender': request.form['Gender'],
|
||
'GST_Registration_Type': request.form['GST_Registration_Type'],
|
||
'GST_No': request.form['GST_No'],
|
||
'Contractor_password': request.form['Contractor_password'],
|
||
'id': id
|
||
}
|
||
|
||
try:
|
||
# cursor.execute("""UPDATE subcontractors SET
|
||
# Contractor_Name=%(Contractor_Name)s,
|
||
# Address=%(Address)s,
|
||
# Mobile_No=%(Mobile_No)s,
|
||
# PAN_No=%(PAN_No)s,
|
||
# Email=%(Email)s,
|
||
# Gender=%(Gender)s,
|
||
# GST_Registration_Type=%(GST_Registration_Type)s,
|
||
# GST_No=%(GST_No)s,
|
||
# Contractor_password=%(Contractor_password)s
|
||
# WHERE Contractor_Id=%(id)s""", updated_data)
|
||
|
||
cursor.callproc("UpdateSubcontractor", (
|
||
id,
|
||
updated_data['Contractor_Name'],
|
||
updated_data['Address'],
|
||
updated_data['Mobile_No'],
|
||
updated_data['PAN_No'],
|
||
updated_data['Email'],
|
||
updated_data['Gender'],
|
||
updated_data['GST_Registration_Type'],
|
||
updated_data['GST_No'],
|
||
updated_data['Contractor_password']
|
||
))
|
||
connection.commit()
|
||
return redirect(url_for('subcontract'))
|
||
|
||
except Error as e:
|
||
print(f"Error updating subcontractor: {e}")
|
||
return json_response(ResponseHandler.update_failure("Subcontractor"), 500)
|
||
|
||
except Error as e:
|
||
print(f"Error fetching subcontractor data: {e}")
|
||
return json_response(ResponseHandler.fetch_failure("Subcontractor"), 500)
|
||
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return render_template('edit_subcontractor.html', subcontractor=subcontractor)
|
||
|
||
|
||
# delete Sub-Contractor methods by id ..
|
||
# @app.route('/deleteSubContractor/<int:id>', methods=['GET', 'POST'])
|
||
# def deleteSubContractor(id):
|
||
# connection = config.get_db_connection()
|
||
|
||
# if not connection:
|
||
# return json_response(ResponseHandler.fetch_failure("Subcontractor"), 500)
|
||
|
||
# try:
|
||
# cursor = connection.cursor()
|
||
|
||
# # cursor.execute("DELETE FROM subcontractors WHERE Contractor_Id = %s", (id,))
|
||
# cursor.callproc("DeleteSubcontractor", (id,))
|
||
# connection.commit()
|
||
|
||
# # Check if any row was deleted (subcontractor found)
|
||
# if cursor.rowcount == 0:
|
||
# return json_response(ResponseHandler.fetch_failure("Subcontractor"), 404)
|
||
|
||
# except Error as e:
|
||
# print(f"Error deleting subcontractor: {e}")
|
||
# return json_response(ResponseHandler.delete_failure("Subcontractor"), 500)
|
||
|
||
# finally:
|
||
# cursor.close()
|
||
# connection.close()
|
||
|
||
# return redirect(url_for('subcontract'))
|
||
@app.route('/deleteSubContractor/<int:id>', methods=['GET', 'POST'])
|
||
def deleteSubContractor(id):
|
||
connection = config.get_db_connection()
|
||
|
||
if not connection:
|
||
return json_response(ResponseHandler.fetch_failure("Subcontractor"), 500)
|
||
|
||
try:
|
||
cursor = connection.cursor()
|
||
|
||
# Optional: check if subcontractor exists before attempting delete
|
||
cursor.execute("SELECT 1 FROM subcontractors WHERE Contractor_Id = %s", (id,))
|
||
if cursor.fetchone() is None:
|
||
return json_response(ResponseHandler.fetch_failure("Subcontractor not found"), 404)
|
||
|
||
# Call stored procedure to delete subcontractor and related records
|
||
cursor.callproc("DeleteSubcontractor", (id,))
|
||
connection.commit()
|
||
|
||
# Retrieve result from procedure (SELECT ROW_COUNT())
|
||
affected_rows = 0
|
||
for result in cursor.stored_results():
|
||
row = result.fetchone()
|
||
affected_rows = row[0] if row else 0
|
||
|
||
if affected_rows == 0:
|
||
return json_response(ResponseHandler.fetch_failure("Subcontractor not deleted"), 404)
|
||
|
||
except Error as e:
|
||
print(f"Error deleting subcontractor: {e}")
|
||
return json_response(ResponseHandler.delete_failure("Subcontractor"), 500)
|
||
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return redirect(url_for('subcontract')) # redirect to subcontractor list page
|
||
|
||
|
||
# ------------------------------- Show Report Subcontractor ---------------------
|
||
|
||
UPLOAD_FOLDER = 'uploads'
|
||
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
|
||
|
||
if not os.path.exists(UPLOAD_FOLDER):
|
||
os.makedirs(UPLOAD_FOLDER)
|
||
|
||
|
||
# Upload Excel file html page
|
||
@app.route('/upload_excel_file', methods=['GET', 'POST'])
|
||
def upload():
|
||
if request.method == 'POST':
|
||
file = request.files['file']
|
||
if file and file.filename.endswith('.xlsx'):
|
||
filepath = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
|
||
file.save(filepath)
|
||
return redirect(url_for('show_table', filename=file.filename))
|
||
return render_template('uploadExcelFile.html')
|
||
|
||
|
||
# Show excel data in tables6
|
||
# @app.route('/show_table/<filename>')
|
||
# def show_table(filename):
|
||
# global data
|
||
# data = []
|
||
#
|
||
# filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
||
# wb = openpyxl.load_workbook(filepath, data_only=True)
|
||
# sheet = wb.active
|
||
#
|
||
# # Extract key file information from the first 4 rows
|
||
# file_info = {
|
||
# "Subcontractor": sheet.cell(row=1, column=2).value,
|
||
# "State": sheet.cell(row=2, column=2).value,
|
||
# "District": sheet.cell(row=3, column=2).value,
|
||
# "Block": sheet.cell(row=4, column=2).value,
|
||
# }
|
||
#
|
||
# errors = []
|
||
# subcontractor_data = None
|
||
# state_data = None
|
||
# district_data = None
|
||
# block_data = None
|
||
#
|
||
# # Database connection
|
||
# connection = config.get_db_connection()
|
||
# if connection:
|
||
# try:
|
||
# cursor = connection.cursor(dictionary=True)
|
||
#
|
||
# # Validate State
|
||
# # cursor.execute("SELECT State_ID, State_Name FROM states WHERE State_Name = %s", (file_info['State'],))
|
||
# # state_data = cursor.fetchone()
|
||
# cursor.callproc('GetStateByName', [file_info['State']])
|
||
# for result in cursor.stored_results():
|
||
# state_data = result.fetchone()
|
||
#
|
||
# if not state_data:
|
||
# errors.append(f"State '{file_info['State']}' is not valid. Please add it.")
|
||
#
|
||
# # Validate District
|
||
# if state_data:
|
||
# # cursor.execute(
|
||
# # "SELECT District_ID, District_Name FROM districts WHERE District_Name = %s AND State_ID = %s",
|
||
# # (file_info['District'], state_data['State_ID'])
|
||
# # )
|
||
# # district_data = cursor.fetchone()
|
||
# cursor.callproc('GetDistrictByNameAndStates', [file_info['District'], state_data['State_ID']])
|
||
# for result in cursor.stored_results():
|
||
# district_data = result.fetchone()
|
||
#
|
||
# if not district_data:
|
||
# errors.append(
|
||
# f"District '{file_info['District']}' is not valid under state '{file_info['State']}'.")
|
||
#
|
||
# # Validate Block
|
||
# if district_data:
|
||
# # cursor.execute(
|
||
# # "SELECT Block_Id, Block_Name FROM blocks WHERE Block_Name = %s AND District_ID = %s",
|
||
# # (file_info['Block'], district_data['District_ID'])
|
||
# # )
|
||
# # block_data = cursor.fetchone()
|
||
# cursor.callproc('GetBlockByNameAndDistricts', [file_info['Block'], district_data['District_ID']])
|
||
# for result in cursor.stored_results():
|
||
# block_data = result.fetchone()
|
||
#
|
||
# if not block_data:
|
||
# errors.append(
|
||
# f"Block '{file_info['Block']}' is not valid under district '{file_info['District']}'.")
|
||
#
|
||
# # old code
|
||
# # # Validate Subcontractor
|
||
# # cursor.execute("SELECT Contractor_Id, Contractor_Name FROM SubContractors WHERE Contractor_Name = %s",
|
||
# # (file_info['Subcontractor'],))
|
||
# # subcontractor_data = cursor.fetchone()
|
||
# cursor.callproc('GetSubcontractorByName', [file_info['Subcontractor']])
|
||
# for result in cursor.stored_results():
|
||
# subcontractor_data = result.fetchone()
|
||
#
|
||
# if not subcontractor_data:
|
||
# # cursor.execute("INSERT INTO subcontractors (Contractor_Name) VALUES (%s)",
|
||
# # (file_info['Subcontractor'],))
|
||
# # connection.commit()
|
||
# cursor.callproc('InsertSubcontractor', [file_info['Subcontractor']])
|
||
# connection.commit()
|
||
#
|
||
# # cursor.execute("SELECT Contractor_Id, Contractor_Name FROM SubContractors WHERE Contractor_Name = %s",
|
||
# # (file_info['Subcontractor'],))
|
||
# # subcontractor_data = cursor.fetchone()
|
||
# cursor.callproc('GetSubcontractorByName', [file_info['Subcontractor']])
|
||
# for result in cursor.stored_results():
|
||
# subcontractor_data = result.fetchone()
|
||
#
|
||
# # new code
|
||
# # cursor.callproc('ValidateAndInsertSubcontractor', (file_info['Subcontractor'], 0, ''))
|
||
# #
|
||
# # for con in cursor.stored_results():
|
||
# # subcontractor_data = con.fetchone()
|
||
# # print("subcon:",subcontractor_data)
|
||
# #
|
||
# # print("subcontractor_data",subcontractor_data)
|
||
#
|
||
# # Get hold types data from database (for faster lookup)
|
||
# # cursor.execute("SELECT hold_type_id, hold_type FROM hold_types")
|
||
# # hold_types_data = cursor.fetchall()
|
||
#
|
||
# cursor.callproc("GetAllHoldTypes")
|
||
# for ht in cursor.stored_results():
|
||
# hold_types_data = ht.fetchall()
|
||
#
|
||
# hold_types_lookup = {row['hold_type'].lower(): row['hold_type_id'] for row in hold_types_data if
|
||
# row['hold_type']}
|
||
#
|
||
# cursor.close()
|
||
# except mysql.connector.Error as e:
|
||
# print(f"Database error: {e}")
|
||
# return "Database operation failed", 500
|
||
# finally:
|
||
# connection.close()
|
||
#
|
||
# # Extract dynamic variable names from row 5 and detect "hold" columns
|
||
# variables = {}
|
||
# hold_columns = []
|
||
# hold_counter = 0
|
||
#
|
||
# for j in range(1, sheet.max_column + 1):
|
||
# col_value = sheet.cell(row=5, column=j).value
|
||
# if col_value:
|
||
# variables[col_value] = j # Store column name with its position
|
||
#
|
||
# # Check if the column header contains the word 'hold'
|
||
# if 'hold' in str(col_value).lower():
|
||
# hold_counter += 1
|
||
# # Lookup hold type id from database
|
||
# hold_type_key = str(col_value).lower().strip()
|
||
# hold_type_id = hold_types_lookup.get(hold_type_key, None)
|
||
# hold_columns.append({
|
||
# 'column_name': col_value,
|
||
# 'column_number': j,
|
||
# 'hold_type_id': hold_type_id
|
||
# })
|
||
#
|
||
# # Extract data dynamically based on row numbers
|
||
# for i in range(6, sheet.max_row + 1):
|
||
# row_data = {}
|
||
# if sheet.cell(row=i, column=1).value:
|
||
# row_data["Row Number"] = i # Store row number
|
||
# for var_name, col_num in variables.items():
|
||
# row_data[var_name] = sheet.cell(row=i, column=col_num).value
|
||
# # Check if at least 4 non-empty cells exist in the row
|
||
# if sum(1 for value in row_data.values() if value) >= 4:
|
||
# data.append(row_data)
|
||
#
|
||
# # For debugging or console output, you can print the hold columns info
|
||
# for hold in hold_columns:
|
||
# if hold['hold_type_id']:
|
||
# print(
|
||
# f" if Column: {hold['column_name']}, Column Number: {hold['column_number']}, Hold Type ID: {hold['hold_type_id']}")
|
||
# else:
|
||
# errors.append(
|
||
# f"Hold Type not added ! Column name '{hold['column_name']}'.")
|
||
# print(
|
||
# f" else Column: {hold['column_name']}, Column Number: {hold['column_number']}, Hold Type ID: {hold['hold_type_id']}")
|
||
#
|
||
# return render_template(
|
||
# 'show_excel_file.html',
|
||
# file_info=file_info,
|
||
# variables=variables,
|
||
# data=data,
|
||
# subcontractor_data=subcontractor_data,
|
||
# state_data=state_data,
|
||
# district_data=district_data,
|
||
# block_data=block_data,
|
||
# errors=errors,
|
||
# hold_columns=hold_columns,
|
||
# hold_counter=hold_counter
|
||
# )
|
||
|
||
@app.route('/show_table/<filename>')
|
||
def show_table(filename):
|
||
global data
|
||
data = []
|
||
|
||
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
||
wb = openpyxl.load_workbook(filepath, data_only=True)
|
||
sheet = wb.active
|
||
|
||
file_info = {
|
||
"Subcontractor": sheet.cell(row=1, column=2).value,
|
||
"State": sheet.cell(row=2, column=2).value,
|
||
"District": sheet.cell(row=3, column=2).value,
|
||
"Block": sheet.cell(row=4, column=2).value,
|
||
}
|
||
|
||
errors = []
|
||
subcontractor_data = None
|
||
state_data = None
|
||
district_data = None
|
||
block_data = None
|
||
|
||
connection = config.get_db_connection()
|
||
if connection:
|
||
try:
|
||
cursor = connection.cursor(dictionary=True)
|
||
|
||
print(f"Calling GetStateByName with: {file_info['State']}")
|
||
cursor.callproc('GetStateByName', [file_info['State']])
|
||
for result in cursor.stored_results():
|
||
state_data = result.fetchone()
|
||
|
||
if not state_data:
|
||
errors.append(f"State '{file_info['State']}' is not valid. Please add it.")
|
||
|
||
if state_data:
|
||
print(f"Calling GetDistrictByNameAndStates with: {file_info['District']}, {state_data['State_ID']}")
|
||
cursor.callproc('GetDistrictByNameAndStates', [file_info['District'], state_data['State_ID']])
|
||
for result in cursor.stored_results():
|
||
district_data = result.fetchone()
|
||
|
||
if not district_data:
|
||
errors.append(f"District '{file_info['District']}' is not valid under state '{file_info['State']}'.")
|
||
|
||
if district_data:
|
||
print(f"Calling GetBlockByNameAndDistricts with: {file_info['Block']}, {district_data['District_ID']}")
|
||
cursor.callproc('GetBlockByNameAndDistricts', [file_info['Block'], district_data['District_ID']])
|
||
for result in cursor.stored_results():
|
||
block_data = result.fetchone()
|
||
|
||
if not block_data:
|
||
errors.append(f"Block '{file_info['Block']}' is not valid under district '{file_info['District']}'.")
|
||
|
||
print(f"Calling GetSubcontractorByName with: {file_info['Subcontractor']}")
|
||
cursor.callproc('GetSubcontractorByName', [file_info['Subcontractor']])
|
||
for result in cursor.stored_results():
|
||
subcontractor_data = result.fetchone()
|
||
|
||
if not subcontractor_data:
|
||
print(f"Inserting subcontractor: {file_info['Subcontractor']}")
|
||
cursor.callproc('InsertSubcontractor', [file_info['Subcontractor']])
|
||
connection.commit()
|
||
print(f"Calling GetSubcontractorByName again with: {file_info['Subcontractor']}")
|
||
cursor.callproc('GetSubcontractorByName', [file_info['Subcontractor']])
|
||
for result in cursor.stored_results():
|
||
subcontractor_data = result.fetchone()
|
||
|
||
print("Calling GetAllHoldTypes")
|
||
cursor.callproc("GetAllHoldTypes")
|
||
hold_types_data = []
|
||
for ht in cursor.stored_results():
|
||
hold_types_data = ht.fetchall()
|
||
|
||
hold_types_lookup = {row['hold_type'].lower(): row['hold_type_id'] for row in hold_types_data if row['hold_type']}
|
||
|
||
cursor.close()
|
||
except mysql.connector.Error as e:
|
||
print(f"Database error: {e}")
|
||
return f"Database operation failed: {e}", 500
|
||
finally:
|
||
connection.close()
|
||
|
||
variables = {}
|
||
hold_columns = []
|
||
hold_counter = 0
|
||
|
||
for j in range(1, sheet.max_column + 1):
|
||
col_value = sheet.cell(row=5, column=j).value
|
||
if col_value:
|
||
variables[col_value] = j
|
||
if 'hold' in str(col_value).lower():
|
||
hold_counter += 1
|
||
hold_type_key = str(col_value).lower().strip()
|
||
hold_type_id = hold_types_lookup.get(hold_type_key, None)
|
||
hold_columns.append({
|
||
'column_name': col_value,
|
||
'column_number': j,
|
||
'hold_type_id': hold_type_id
|
||
})
|
||
|
||
for i in range(6, sheet.max_row + 1):
|
||
row_data = {}
|
||
if sheet.cell(row=i, column=1).value:
|
||
row_data["Row Number"] = i
|
||
for var_name, col_num in variables.items():
|
||
row_data[var_name] = sheet.cell(row=i, column=col_num).value
|
||
if sum(1 for value in row_data.values() if value) >= 4:
|
||
data.append(row_data)
|
||
|
||
for hold in hold_columns:
|
||
if hold['hold_type_id']:
|
||
print(f" if Column: {hold['column_name']}, Column Number: {hold['column_number']}, Hold Type ID: {hold['hold_type_id']}")
|
||
else:
|
||
errors.append(f"Hold Type not added ! Column name '{hold['column_name']}'.")
|
||
print(f" else Column: {hold['column_name']}, Column Number: {hold['column_number']}, Hold Type ID: {hold['hold_type_id']}")
|
||
|
||
return render_template(
|
||
'show_excel_file.html',
|
||
file_info=file_info,
|
||
variables=variables,
|
||
data=data,
|
||
subcontractor_data=subcontractor_data,
|
||
state_data=state_data,
|
||
district_data=district_data,
|
||
block_data=block_data,
|
||
errors=errors,
|
||
hold_columns=hold_columns,
|
||
hold_counter=hold_counter
|
||
)
|
||
|
||
# Show excel data in tables6
|
||
# @app.route('/show_table/<filename>')
|
||
# def show_table(filename):
|
||
# global data
|
||
# data = []
|
||
#
|
||
# filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
|
||
# wb = openpyxl.load_workbook(filepath, data_only=True)
|
||
# sheet = wb.active
|
||
#
|
||
# # Extract key file information from the first 4 rows
|
||
# file_info = {
|
||
# "Subcontractor": sheet.cell(row=1, column=2).value,
|
||
# "State": sheet.cell(row=2, column=2).value,
|
||
# "District": sheet.cell(row=3, column=2).value,
|
||
# "Block": sheet.cell(row=4, column=2).value,
|
||
# }
|
||
#
|
||
# errors = []
|
||
# subcontractor_data = None
|
||
# state_data = None
|
||
# district_data = None
|
||
# block_data = None
|
||
#
|
||
# # Database connection
|
||
# connection = config.get_db_connection()
|
||
# if connection:
|
||
# try:
|
||
# cursor = connection.cursor(dictionary=True)
|
||
#
|
||
# # Validate State
|
||
# cursor.execute("SELECT State_ID, State_Name FROM states WHERE State_Name = %s", (file_info['State'],))
|
||
# state_data = cursor.fetchone()
|
||
# if not state_data:
|
||
# errors.append(f"State '{file_info['State']}' is not valid. Please add it.")
|
||
#
|
||
# # Validate District
|
||
# if state_data:
|
||
# cursor.execute(
|
||
# "SELECT District_ID, District_Name FROM districts WHERE District_Name = %s AND State_ID = %s",
|
||
# (file_info['District'], state_data['State_ID'])
|
||
# )
|
||
# district_data = cursor.fetchone()
|
||
# if not district_data:
|
||
# errors.append(
|
||
# f"District '{file_info['District']}' is not valid under state '{file_info['State']}'.")
|
||
#
|
||
# # Validate Block
|
||
# if district_data:
|
||
# cursor.execute(
|
||
# "SELECT Block_Id, Block_Name FROM blocks WHERE Block_Name = %s AND District_ID = %s",
|
||
# (file_info['Block'], district_data['District_ID'])
|
||
# )
|
||
# block_data = cursor.fetchone()
|
||
# if not block_data:
|
||
# errors.append(
|
||
# f"Block '{file_info['Block']}' is not valid under district '{file_info['District']}'.")
|
||
#
|
||
#
|
||
# # old code
|
||
# # # Validate Subcontractor
|
||
# cursor.execute("SELECT Contractor_Id, Contractor_Name FROM subcontractors WHERE Contractor_Name = %s",
|
||
# (file_info['Subcontractor'],))
|
||
# subcontractor_data = cursor.fetchone()
|
||
#
|
||
# if not subcontractor_data:
|
||
# cursor.execute("INSERT INTO subcontractors (Contractor_Name) VALUES (%s)",
|
||
# (file_info['Subcontractor'],))
|
||
# connection.commit()
|
||
# cursor.execute("SELECT Contractor_Id, Contractor_Name FROM subcontractors WHERE Contractor_Name = %s",
|
||
# (file_info['Subcontractor'],))
|
||
# subcontractor_data = cursor.fetchone()
|
||
#
|
||
# # new code
|
||
# # cursor.callproc('ValidateAndInsertSubcontractor', (file_info['Subcontractor'], 0, ''))
|
||
# #
|
||
# # for con in cursor.stored_results():
|
||
# # subcontractor_data = con.fetchone()
|
||
# # print("subcon:",subcontractor_data)
|
||
# #
|
||
# # print("subcontractor_data",subcontractor_data)
|
||
#
|
||
# # Get hold types data from database (for faster lookup)
|
||
# # cursor.execute("SELECT hold_type_id, hold_type FROM hold_types")
|
||
# # hold_types_data = cursor.fetchall()
|
||
#
|
||
# cursor.callproc("GetAllHoldTypes")
|
||
# for ht in cursor.stored_results():
|
||
# hold_types_data = ht.fetchall()
|
||
#
|
||
#
|
||
# hold_types_lookup = {row['hold_type'].lower(): row['hold_type_id'] for row in hold_types_data if row['hold_type']}
|
||
#
|
||
#
|
||
# cursor.close()
|
||
# except mysql.connector.Error as e:
|
||
# print(f"Database error: {e}")
|
||
#
|
||
# # return "Database operation failed", 500
|
||
# return f"{e}",500
|
||
# finally:
|
||
# connection.close()
|
||
#
|
||
# # Extract dynamic variable names from row 5 and detect "hold" columns
|
||
# variables = {}
|
||
# hold_columns = []
|
||
# hold_counter = 0
|
||
#
|
||
# for j in range(1, sheet.max_column + 1):
|
||
# col_value = sheet.cell(row=5, column=j).value
|
||
# if col_value:
|
||
# variables[col_value] = j # Store column name with its position
|
||
#
|
||
# # Check if the column header contains the word 'hold'
|
||
# if 'hold' in str(col_value).lower():
|
||
# hold_counter += 1
|
||
# # Lookup hold type id from database
|
||
# hold_type_key = str(col_value).lower().strip()
|
||
# hold_type_id = hold_types_lookup.get(hold_type_key, None)
|
||
# hold_columns.append({
|
||
# 'column_name': col_value,
|
||
# 'column_number': j,
|
||
# 'hold_type_id': hold_type_id
|
||
# })
|
||
#
|
||
# # Extract data dynamically based on row numbers
|
||
# for i in range(6, sheet.max_row + 1):
|
||
# row_data = {}
|
||
# if sheet.cell(row=i, column=1).value:
|
||
# row_data["Row Number"] = i # Store row number
|
||
# for var_name, col_num in variables.items():
|
||
# row_data[var_name] = sheet.cell(row=i, column=col_num).value
|
||
# # Check if at least 4 non-empty cells exist in the row
|
||
# if sum(1 for value in row_data.values() if value) >= 4:
|
||
# data.append(row_data)
|
||
#
|
||
# # For debugging or console output, you can print the hold columns info
|
||
# for hold in hold_columns:
|
||
# if hold['hold_type_id']:
|
||
# print(
|
||
# f" if Column: {hold['column_name']}, Column Number: {hold['column_number']}, Hold Type ID: {hold['hold_type_id']}")
|
||
# else:
|
||
# errors.append(
|
||
# f"Hold Type not added ! Column name '{hold['column_name']}'.")
|
||
# print(
|
||
# f" else Column: {hold['column_name']}, Column Number: {hold['column_number']}, Hold Type ID: {hold['hold_type_id']}")
|
||
#
|
||
# return render_template(
|
||
# 'show_excel_file.html',
|
||
# file_info=file_info,
|
||
# variables=variables,
|
||
# data=data,
|
||
# subcontractor_data=subcontractor_data,
|
||
# state_data=state_data,
|
||
# district_data=district_data,
|
||
# block_data=block_data,
|
||
# errors=errors,
|
||
# hold_columns=hold_columns,
|
||
# hold_counter=hold_counter
|
||
# )
|
||
|
||
# save Excel data
|
||
@app.route('/save_data', methods=['POST'])
|
||
def save_data():
|
||
# Extract form data
|
||
subcontractor_id = request.form.get("subcontractor_data")
|
||
state_id = request.form.get("state_data")
|
||
district_id = request.form.get("district_data")
|
||
block_id = request.form.get("block_data")
|
||
|
||
variables = request.form.getlist('variables[]')
|
||
hold_columns = request.form.get("hold_columns")
|
||
hold_counter = request.form.get("hold_counter")
|
||
|
||
# print("Info: ", subcontractor_id, state_id, district_id, block_id)
|
||
|
||
if not data:
|
||
return jsonify({"error": "No data provided to save"}), 400
|
||
|
||
if data:
|
||
# print("Total number of entries in data:", len(data))
|
||
|
||
connection = config.get_db_connection()
|
||
cursor = connection.cursor()
|
||
|
||
try:
|
||
for entry in data:
|
||
save_data = {
|
||
"PMC_No": entry.get("PMC_No"),
|
||
"Invoice_Details": entry.get("Invoice_Details", ''),
|
||
"Work_Type": 'none',
|
||
"Invoice_Date": entry.get("Invoice_Date").strftime('%Y-%m-%d') if entry.get(
|
||
"Invoice_Date") else None,
|
||
"Invoice_No": entry.get("Invoice_No", ''),
|
||
"Basic_Amount": entry.get("Basic_Amount", 0.00),
|
||
"Debit_Amount": entry.get("Debit_Amount", 0.00),
|
||
"After_Debit_Amount": entry.get("After_Debit_Amount", 0.00),
|
||
"Amount": entry.get("Amount", 0.00),
|
||
"GST_Amount": entry.get("GST_Amount", 0.00),
|
||
"TDS_Amount": entry.get("TDS_Amount", 0.00),
|
||
"SD_Amount": entry.get("SD_Amount", 0.00),
|
||
"On_Commission": entry.get("On_Commission", 0.00),
|
||
"Hydro_Testing": entry.get("Hydro_Testing", 0.00),
|
||
"Hold_Amount": 0,
|
||
"GST_SD_Amount": entry.get("GST_SD_Amount", 0.00),
|
||
"Final_Amount": entry.get("Final_Amount", 0.00),
|
||
"Payment_Amount": entry.get("Payment_Amount", 0.00),
|
||
"Total_Amount": entry.get("Total_Amount", 0.00),
|
||
"TDS_Payment_Amount": entry.get("TDS_Payment_Amount", 0.00),
|
||
"UTR": entry.get("UTR", ''),
|
||
}
|
||
|
||
village_name, work_type = None, None
|
||
village_id = 0
|
||
|
||
PMC_No = save_data.get('PMC_No')
|
||
Invoice_Details = save_data.get('Invoice_Details')
|
||
Invoice_Date = save_data.get('Invoice_Date')
|
||
Invoice_No = save_data.get('Invoice_No')
|
||
Basic_Amount = save_data.get('Basic_Amount')
|
||
Debit_Amount = save_data.get('Debit_Amount')
|
||
After_Debit_Amount = save_data.get('After_Debit_Amount')
|
||
Amount = save_data.get('Amount')
|
||
GST_Amount = save_data.get('GST_Amount')
|
||
TDS_Amount = save_data.get('TDS_Amount')
|
||
SD_Amount = save_data.get('SD_Amount')
|
||
On_Commission = save_data.get('On_Commission')
|
||
Hydro_Testing = save_data.get('Hydro_Testing')
|
||
GST_SD_Amount = save_data.get('GST_SD_Amount')
|
||
Final_Amount = save_data.get('Final_Amount')
|
||
|
||
Payment_Amount = save_data.get('Payment_Amount')
|
||
Total_Amount = save_data.get('Total_Amount')
|
||
TDS_Payment_Amount = save_data.get('TDS_Payment_Amount')
|
||
UTR = save_data.get('UTR')
|
||
|
||
if Invoice_Details:
|
||
words = Invoice_Details.lower().split()
|
||
if 'village' in words:
|
||
village_pos = words.index('village')
|
||
village_name = " ".join(words[:village_pos])
|
||
if 'work' in words:
|
||
work_pos = words.index('work')
|
||
if village_name:
|
||
work_type = " ".join(words[village_pos + 1:work_pos + 1])
|
||
else:
|
||
work_type = " ".join(words[:work_pos + 1])
|
||
|
||
if Invoice_Details and 'village' in Invoice_Details.lower() and 'work' in Invoice_Details.lower():
|
||
print("village_name ::", village_name, "|| work_type ::", work_type)
|
||
if block_id and village_name:
|
||
village_id = None
|
||
# cursor.execute("SELECT Village_Id FROM villages WHERE Block_Id = %s AND Village_Name = %s",(block_id, village_name))
|
||
# result = cursor.fetchone()
|
||
cursor.callproc("GetVillageId", (block_id, village_name))
|
||
for result in cursor.stored_results():
|
||
result = result.fetchone()
|
||
village_id = result[0] if result else None
|
||
|
||
if not village_id:
|
||
# cursor.execute("INSERT INTO villages (Village_Name, Block_Id) VALUES (%s, %s)", (village_name, block_id))
|
||
|
||
cursor.callproc("SaveVillage", (village_name, block_id))
|
||
# cursor.execute("SELECT Village_Id FROM villages WHERE Block_Id = %s AND Village_Name = %s",(block_id, village_name))
|
||
# result = cursor.fetchone()
|
||
cursor.callproc("GetVillageId", (block_id, village_name))
|
||
for result in cursor.stored_results():
|
||
result = result.fetchone()
|
||
village_id = result[0] if result else None
|
||
|
||
print("village_id :", village_id)
|
||
print("block_id :", block_id)
|
||
print("invoice :", PMC_No, village_id, work_type, Invoice_Details, Invoice_Date, Invoice_No,
|
||
Basic_Amount, Debit_Amount, After_Debit_Amount, Amount, GST_Amount, TDS_Amount,
|
||
SD_Amount, On_Commission, Hydro_Testing, GST_SD_Amount, Final_Amount)
|
||
#
|
||
# cursor.execute("SET @p_invoice_id = 0")
|
||
# cursor.callproc("SaveInvoice", (
|
||
# PMC_No, village_id, work_type, Invoice_Details, Invoice_Date, Invoice_No,
|
||
# Basic_Amount, Debit_Amount, After_Debit_Amount, Amount, GST_Amount, TDS_Amount,
|
||
# SD_Amount, On_Commission, Hydro_Testing, GST_SD_Amount, Final_Amount,
|
||
# subcontractor_id, "@p_invoice_id"
|
||
# ))
|
||
# cursor.execute("SELECT @p_invoice_id")
|
||
# invoice_id = cursor.fetchone()[0]
|
||
|
||
args = (
|
||
PMC_No, village_id, work_type, Invoice_Details, Invoice_Date, Invoice_No,
|
||
Basic_Amount, Debit_Amount, After_Debit_Amount, Amount, GST_Amount, TDS_Amount,
|
||
SD_Amount, On_Commission, Hydro_Testing, GST_SD_Amount, Final_Amount,
|
||
subcontractor_id, 0
|
||
)
|
||
# for result in cursor.stored_results():
|
||
# invoice_id = result.fetchone()['invoice_id']
|
||
results = cursor.callproc('SaveInvoice', args)
|
||
# cursor.callproc("SaveInvoice",args)
|
||
# for re in cursor.stored_results():
|
||
invoice_id = results[-1]
|
||
|
||
print("invoice id from the excel ", invoice_id)
|
||
|
||
if isinstance(hold_columns, str):
|
||
hold_columns = ast.literal_eval(hold_columns)
|
||
|
||
# Check if hold_columns is actually a list of dictionaries
|
||
if isinstance(hold_columns, list) and all(isinstance(hold, dict) for hold in hold_columns):
|
||
for hold in hold_columns:
|
||
print(f"Processing hold: {hold}")
|
||
hold_column_name = hold.get('column_name') # Get column name
|
||
hold_type_id = hold.get('hold_type_id') # Get hold_type_id
|
||
|
||
if hold_column_name:
|
||
hold_amount = entry.get(
|
||
hold_column_name) # Get the value for that specific hold column
|
||
if hold_amount is not None:
|
||
print(f"Processing hold type: {hold_column_name}, Hold Amount: {hold_amount}")
|
||
|
||
# Insert into the invoice_subcontractor_hold_join table
|
||
hold_join_data = {
|
||
"Contractor_Id": subcontractor_id,
|
||
"Invoice_Id": invoice_id,
|
||
"hold_type_id": hold_type_id,
|
||
"hold_amount": hold_amount
|
||
}
|
||
|
||
# insert_hold_query = """INSERT INTO invoice_subcontractor_hold_join (Contractor_Id, Invoice_Id, hold_type_id, hold_amount)
|
||
# VALUES (%(Contractor_Id)s, %(Invoice_Id)s, %(hold_type_id)s, %(hold_amount)s);
|
||
# """
|
||
# cursor.execute(insert_hold_query, hold_join_data)
|
||
# print(f"Inserted hold join data: {hold_join_data}")
|
||
cursor.callproc('InsertHoldJoinData', [
|
||
hold_join_data['Contractor_Id'], hold_join_data['Invoice_Id'],
|
||
hold_join_data['hold_type_id'], hold_join_data['hold_amount']
|
||
])
|
||
connection.commit()
|
||
print(f"Inserted hold join data: {hold_join_data}")
|
||
|
||
|
||
else:
|
||
print(f"Invalid hold entry: {hold}")
|
||
else:
|
||
print("Hold columns data is not a valid list of dictionaries.")
|
||
#---------------------------------------------Credit Note---------------------------------------------------------------------------
|
||
elif any(keyword in Invoice_Details.lower() for keyword in ['credit note']):
|
||
print("Credit note found:", PMC_No, Invoice_No, Basic_Amount, Debit_Amount, Final_Amount,
|
||
After_Debit_Amount, GST_Amount, Amount, Final_Amount, Payment_Amount, Total_Amount, UTR, Invoice_No)
|
||
cursor.execute(
|
||
"""INSERT INTO credit_note (PMC_No, Invoice_Details, Basic_Amount, Debit_Amount, After_Debit_Amount, GST_Amount, Amount, Final_Amount, Payment_Amount, Total_Amount, UTR, Contractor_Id, invoice_no) VALUES (%s,%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s,%s)""",
|
||
( PMC_No, Invoice_Details, Basic_Amount, Debit_Amount, After_Debit_Amount, GST_Amount, Amount, Final_Amount, Payment_Amount, Total_Amount, UTR, subcontractor_id, Invoice_No))
|
||
#-----------------------------------------------Hold Amount----------------------------------------------------------------------
|
||
elif Invoice_Details and any(keyword in Invoice_Details.lower() for keyword in
|
||
['excess hold', 'ht', 'hold release amount']):
|
||
|
||
cursor.execute("""
|
||
INSERT INTO hold_release (
|
||
PMC_No, Invoice_No, Invoice_Details, Basic_Amount, Total_Amount, UTR,Contractor_Id
|
||
) VALUES (%s, %s, %s, %s, %s, %s,%s)
|
||
""", (
|
||
PMC_No, Invoice_No, Invoice_Details, Basic_Amount, Final_Amount, UTR, subcontractor_id))
|
||
print("Hold amount release from excel file:", PMC_No, Invoice_Details)
|
||
#------------------------------------------------------------------------------------------------------------------
|
||
elif Invoice_Details and any(
|
||
keyword in Invoice_Details.lower() for keyword in ['gst', 'release', 'note']):
|
||
print("Gst rels :", PMC_No, Invoice_No, Basic_Amount, Final_Amount)
|
||
cursor.callproc("SaveGSTRelease", (PMC_No, Invoice_No, Basic_Amount, Final_Amount))
|
||
# cursor.execute(
|
||
# """INSERT INTO gst_release (PMC_No, Invoice_No, Basic_Amount, Final_Amount) VALUES (%s,%s, %s, %s)""",
|
||
# (PMC_No, Invoice_No, Basic_Amount, Final_Amount))
|
||
|
||
# insert_payment = """INSERT INTO payment (PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR) VALUES (%s, %s, %s, %s, %s, %s)"""
|
||
# cursor.execute(insert_payment,
|
||
# (PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR))
|
||
|
||
if PMC_No and Total_Amount and UTR:
|
||
print("Payment :", PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR)
|
||
# insert_payment = """INSERT INTO payment (PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR) VALUES (%s, %s, %s, %s, %s, %s)"""
|
||
# cursor.execute(insert_payment,
|
||
# (PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR))
|
||
|
||
cursor.callproc("SavePayment",
|
||
(PMC_No, Invoice_No, Payment_Amount, TDS_Payment_Amount, Total_Amount, UTR))
|
||
|
||
connection.commit()
|
||
return jsonify({"success": "Data saved successfully!"}), 200
|
||
# return render_template('uploadExcelFile.html')
|
||
except Exception as e:
|
||
connection.rollback()
|
||
return jsonify({"error": f"An unexpected error occurred: {e}"}), 500
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return render_template('index.html')
|
||
|
||
|
||
# ---------------------- Report --------------------------------
|
||
# call repor page
|
||
@app.route('/report')
|
||
def report_page():
|
||
return render_template('report.html')
|
||
|
||
|
||
# Search list multiples input and search reports
|
||
@app.route('/search_contractor', methods=['POST'])
|
||
def search_contractor():
|
||
connection = config.get_db_connection()
|
||
cursor = connection.cursor(dictionary=True)
|
||
|
||
subcontractor_name = request.form.get('subcontractor_name')
|
||
pmc_no = request.form.get('pmc_no')
|
||
state = request.form.get('state')
|
||
district = request.form.get('district')
|
||
block = request.form.get('block')
|
||
village = request.form.get('village')
|
||
year_from = request.form.get('year_from')
|
||
year_to = request.form.get('year_to')
|
||
|
||
conditions = []
|
||
params = []
|
||
|
||
if subcontractor_name:
|
||
conditions.append("LOWER(s.Contractor_Name) LIKE LOWER(%s)")
|
||
params.append(f"%{subcontractor_name}%")
|
||
if pmc_no:
|
||
conditions.append("i.PMC_No = %s")
|
||
params.append(pmc_no)
|
||
if state:
|
||
conditions.append("LOWER(st.State_Name) LIKE LOWER(%s)")
|
||
params.append(f"%{state}%")
|
||
if district:
|
||
conditions.append("LOWER(d.District_Name) LIKE LOWER(%s)")
|
||
params.append(f"%{district}%")
|
||
if block:
|
||
conditions.append("LOWER(b.Block_Name) LIKE LOWER(%s)")
|
||
params.append(f"%{block}%")
|
||
if village:
|
||
conditions.append("LOWER(v.Village_Name) LIKE LOWER(%s)")
|
||
params.append(f"%{village}%")
|
||
if year_from and year_to:
|
||
conditions.append("i.Invoice_Date BETWEEN %s AND %s")
|
||
params.append(year_from)
|
||
params.append(year_to)
|
||
|
||
if not conditions:
|
||
return jsonify({"error": "At least one field is required for search."}), 400
|
||
|
||
# query = f"""
|
||
# SELECT DISTINCT s.Contractor_Id, s.Contractor_Name, i.PMC_No, st.State_Name,
|
||
# d.District_Name, b.Block_Name, v.Village_Name
|
||
# FROM subcontractors s
|
||
# INNER JOIN assign_subcontractors asg ON s.Contractor_Id = asg.Contractor_Id
|
||
# INNER JOIN villages v ON asg.Village_Id = v.Village_Id
|
||
# INNER JOIN invoice i ON i.Village_Id = asg.Village_Id AND i.PMC_No = asg.PMC_No
|
||
# LEFT JOIN blocks b ON v.Block_Id = b.Block_Id
|
||
# LEFT JOIN districts d ON b.District_id = d.District_id
|
||
# LEFT JOIN states st ON d.State_Id = st.State_Id
|
||
# WHERE {' AND '.join(conditions)}
|
||
# ORDER BY s.Contractor_Name ASC, i.PMC_No ASC
|
||
# """
|
||
# cursor.execute(query, tuple(params))
|
||
# data = cursor.fetchall()
|
||
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
|
||
])
|
||
|
||
for result in cursor.stored_results():
|
||
data = result.fetchall()
|
||
|
||
return jsonify(data)
|
||
|
||
|
||
|
||
# @app.route('/contractor_report/<int:contractor_id>')
|
||
# def contractor_report(contractor_id):
|
||
# connection = config.get_db_connection()
|
||
# cursor = connection.cursor(dictionary=True, buffered=True)
|
||
#
|
||
# try:
|
||
# # Fetch contractor details
|
||
# cursor.execute("""
|
||
# SELECT DISTINCT s.Contractor_Name, st.State_Name, d.District_Name, b.Block_Name,
|
||
# s.Mobile_No, s.GST_Registration_Type, s.GST_No,s.PAN_No,s.Email,s.Address
|
||
# FROM subcontractors s
|
||
# LEFT JOIN assign_subcontractors asg ON s.Contractor_Id = asg.Contractor_Id
|
||
# LEFT JOIN villages v ON asg.Village_Id = v.Village_Id
|
||
# LEFT JOIN blocks b ON v.Block_Id = b.Block_Id
|
||
# LEFT JOIN districts d ON b.District_id = d.District_id
|
||
# LEFT JOIN states st ON d.State_Id = st.State_Id
|
||
# WHERE s.Contractor_Id = %s
|
||
# """, (contractor_id,))
|
||
# contInfo = cursor.fetchone()
|
||
#
|
||
# # cursor.callproc('GetContractorInfoById', [contractor_id])
|
||
# # contInfo = next(cursor.stored_results()).fetchone()
|
||
#
|
||
# # Fetch distinct hold types present in invoices for the contractor
|
||
# cursor.execute("""
|
||
# SELECT DISTINCT ht.hold_type_id, ht.hold_type
|
||
# FROM invoice_subcontractor_hold_join h
|
||
# JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
# JOIN invoice i ON h.Invoice_Id = i.Invoice_Id
|
||
# WHERE h.Contractor_Id = %s
|
||
# """, (contractor_id,))
|
||
# hold_types = cursor.fetchall()
|
||
# # cursor.callproc('GetHoldTypesByContId', [contractor_id])
|
||
# # hold_types = next(cursor.stored_results()).fetchall()
|
||
#
|
||
# # Fetch all invoices for the contractor, with optional hold information
|
||
# query = """
|
||
# SELECT DISTINCT i.PMC_No, v.Village_Name, i.Work_Type, i.Invoice_Details,
|
||
# i.Invoice_Date, i.Invoice_No, i.Basic_Amount, i.Debit_Amount,
|
||
# i.After_Debit_Amount, i.Amount, i.GST_Amount, i.TDS_Amount, i.SD_Amount,
|
||
# i.On_Commission, i.Hydro_Testing, i.GST_SD_Amount,
|
||
# i.Final_Amount, h.hold_amount, ht.hold_type
|
||
# FROM invoice i
|
||
# LEFT JOIN villages v ON i.Village_Id = v.Village_Id
|
||
# LEFT JOIN assign_subcontractors asg ON v.Village_Id = asg.Village_Id
|
||
# LEFT JOIN subcontractors s ON asg.Contractor_Id = s.Contractor_Id
|
||
# LEFT JOIN invoice_subcontractor_hold_join h ON i.Invoice_Id = h.Invoice_Id AND h.Contractor_Id = s.Contractor_Id
|
||
# LEFT JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
# WHERE s.Contractor_Id = %s
|
||
# ORDER BY i.PMC_No ASC;
|
||
# """
|
||
# cursor.execute(query, (contractor_id,))
|
||
# invoices = cursor.fetchall()
|
||
#
|
||
# # cursor.callproc('GetInvoicesWithHoldByContId', [contractor_id])
|
||
# # invoices = next(cursor.stored_results()).fetchall()
|
||
#
|
||
# gst_query = """select pmc_no,invoice_no,basic_amount,final_amount from gst_release where pmc_no in
|
||
# (select distinct pmc_no from assign_subcontractors where Contractor_Id= %s ) ORDER BY pmc_no ASC """
|
||
# cursor.execute(gst_query, (contractor_id,))
|
||
# gst_rel = cursor.fetchall()
|
||
#
|
||
# # cursor.callproc('GetGstReleaseBycontId', [contractor_id])
|
||
# # gst_rel = next(cursor.stored_results()).fetchall()
|
||
#
|
||
# pay_query = """select pmc_no,invoice_no,Payment_Amount,TDS_Payment_Amount,Total_amount,utr from payment where pmc_no in
|
||
# (select distinct pmc_no from assign_subcontractors where Contractor_Id=%s ) ORDER BY pmc_no ASC """
|
||
# cursor.execute(pay_query, (contractor_id,))
|
||
# payments = cursor.fetchall()
|
||
# # cursor.callproc('GetPaymentsByContId', [contractor_id])
|
||
# # payments = next(cursor.stored_results()).fetchall()
|
||
#
|
||
# 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')
|
||
#
|
||
# except Exception as e:
|
||
# print(f"Error fetching contractor report: {e}")
|
||
# return "An error occurred while fetching contractor report", 500
|
||
#
|
||
# finally:
|
||
# cursor.close()
|
||
# connection.close()
|
||
#
|
||
# return render_template('subcontractor_report.html', contInfo=contInfo, contractor_id=contractor_id,
|
||
# invoices=invoices,
|
||
# hold_types=hold_types, gst_rel=gst_rel, payments=payments, total=total,
|
||
# current_date=current_date)
|
||
|
||
# @app.route('/contractor_report/<int:contractor_id>')
|
||
# def contractor_report(contractor_id):
|
||
# connection = config.get_db_connection()
|
||
# cursor = connection.cursor(dictionary=True, buffered=True)
|
||
|
||
# try:
|
||
# # Fetch contractor details
|
||
# cursor.execute("""
|
||
# SELECT DISTINCT s.Contractor_Name, st.State_Name, d.District_Name, b.Block_Name,
|
||
# s.Mobile_No, s.GST_Registration_Type, s.GST_No,s.PAN_No,s.Email,s.Address
|
||
# FROM subcontractors s
|
||
# LEFT JOIN assign_subcontractors asg ON s.Contractor_Id = asg.Contractor_Id
|
||
# LEFT JOIN villages v ON asg.Village_Id = v.Village_Id
|
||
# LEFT JOIN blocks b ON v.Block_Id = b.Block_Id
|
||
# LEFT JOIN districts d ON b.District_id = d.District_id
|
||
# LEFT JOIN states st ON d.State_Id = st.State_Id
|
||
# WHERE s.Contractor_Id = %s
|
||
# """, (contractor_id,))
|
||
# contInfo = cursor.fetchone()
|
||
|
||
# # # Fetch distinct hold types present in invoices for the contractor
|
||
# cursor.execute("""
|
||
# SELECT DISTINCT ht.hold_type_id, ht.hold_type
|
||
# FROM invoice_subcontractor_hold_join h
|
||
# JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
# JOIN invoice i ON h.Invoice_Id = i.Invoice_Id
|
||
# WHERE h.Contractor_Id = %s
|
||
# """, (contractor_id,))
|
||
# hold_types = cursor.fetchall()
|
||
# # cursor.callproc('GetDistinctHoldTypesInInvoicesByContractor', [contractor_id])
|
||
|
||
# # for result in cursor.stored_results():
|
||
# # hold_types = result.fetchall()
|
||
|
||
# # # Fetch all invoices for the contractor, with optional hold information
|
||
|
||
# query = """
|
||
# SELECT DISTINCT i.PMC_No, v.Village_Name, i.Work_Type, i.Invoice_Details,
|
||
# i.Invoice_Date, i.Invoice_No, i.Basic_Amount, i.Debit_Amount,
|
||
# i.After_Debit_Amount, i.Amount, i.GST_Amount, i.TDS_Amount, i.SD_Amount,
|
||
# i.On_Commission, i.Hydro_Testing, i.GST_SD_Amount,
|
||
# i.Final_Amount, h.hold_amount, ht.hold_type
|
||
# FROM assign_subcontractors asg
|
||
# INNER JOIN villages v ON asg.Village_Id = v.Village_Id
|
||
# INNER JOIN invoice i ON i.Village_Id = v.Village_Id AND i.PMC_No = asg.PMC_No
|
||
# LEFT JOIN subcontractors s ON asg.Contractor_Id = s.Contractor_Id
|
||
# LEFT JOIN invoice_subcontractor_hold_join h ON i.Invoice_Id = h.Invoice_Id AND h.Contractor_Id = asg.Contractor_Id
|
||
# LEFT JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
# WHERE asg.Contractor_Id = %s
|
||
# ORDER BY i.PMC_No ASC;
|
||
# """
|
||
# cursor.execute(query, (contractor_id,))
|
||
# invoices = cursor.fetchall()
|
||
|
||
# # cursor.callproc("GetInvoicesWithHoldInfoByContractor", [contractor_id])
|
||
# # for result in cursor.stored_results():
|
||
# # invoices = result.fetchall()
|
||
|
||
# gst_query = """select pmc_no,invoice_no,basic_amount,final_amount from gst_release where pmc_no in
|
||
# (select distinct pmc_no from assign_subcontractors where Contractor_Id= %s ) ORDER BY pmc_no ASC """
|
||
# cursor.execute(gst_query, (contractor_id,))
|
||
# gst_rel = cursor.fetchall()
|
||
# # cursor.callproc('GetGSTReleasesByContractor', [contractor_id])
|
||
|
||
# # for result in cursor.stored_results():
|
||
# # gst_rel = result.fetchall()
|
||
|
||
# pay_query = """select pmc_no,invoice_no,Payment_Amount,TDS_Payment_Amount,Total_amount,utr from payment where pmc_no in
|
||
# (select distinct pmc_no from assign_subcontractors where Contractor_Id=%s ) ORDER BY pmc_no ASC """
|
||
# cursor.execute(pay_query, (contractor_id,))
|
||
# payments = cursor.fetchall()
|
||
# # cursor.callproc('GetPaymentsByContractor', [contractor_id])
|
||
|
||
# # for result in cursor.stored_results():
|
||
# # payments = result.fetchall()
|
||
|
||
# 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')
|
||
|
||
# except Exception as e:
|
||
# print(f"Error fetching contractor report: {e}")
|
||
# return "An error occurred while fetching contractor report", 500
|
||
|
||
# finally:
|
||
# cursor.close()
|
||
# connection.close()
|
||
|
||
# return render_template('subcontractor_report.html', contInfo=contInfo, contractor_id=contractor_id,
|
||
# invoices=invoices,
|
||
# hold_types=hold_types, gst_rel=gst_rel, payments=payments, total=total,
|
||
# current_date=current_date)
|
||
|
||
from flask import render_template
|
||
from datetime import datetime
|
||
import config
|
||
|
||
@app.route('/contractor_report/<int:contractor_id>')
|
||
def contractor_report(contractor_id):
|
||
connection = config.get_db_connection()
|
||
cursor = connection.cursor(dictionary=True, buffered=True)
|
||
|
||
try:
|
||
# Contractor details
|
||
cursor.execute("""
|
||
SELECT DISTINCT s.Contractor_Name, st.State_Name, d.District_Name, b.Block_Name,
|
||
s.Mobile_No, s.GST_Registration_Type, s.GST_No, s.PAN_No, s.Email, s.Address
|
||
FROM subcontractors s
|
||
LEFT JOIN assign_subcontractors asg ON s.Contractor_Id = asg.Contractor_Id
|
||
LEFT JOIN villages v ON asg.Village_Id = v.Village_Id
|
||
LEFT JOIN blocks b ON v.Block_Id = b.Block_Id
|
||
LEFT JOIN districts d ON b.District_id = d.District_id
|
||
LEFT JOIN states st ON d.State_Id = st.State_Id
|
||
WHERE s.Contractor_Id = %s
|
||
""", (contractor_id,))
|
||
contInfo = cursor.fetchone()
|
||
|
||
# Hold types
|
||
cursor.execute("""
|
||
SELECT DISTINCT ht.hold_type_id, ht.hold_type
|
||
FROM invoice_subcontractor_hold_join h
|
||
JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
JOIN invoice i ON h.Invoice_Id = i.Invoice_Id
|
||
WHERE h.Contractor_Id = %s
|
||
""", (contractor_id,))
|
||
hold_types = cursor.fetchall()
|
||
|
||
# Invoices
|
||
cursor.execute("""
|
||
SELECT DISTINCT i.PMC_No, v.Village_Name, i.Work_Type, i.Invoice_Details,
|
||
i.Invoice_Date, i.Invoice_No, i.Basic_Amount, i.Debit_Amount,
|
||
i.After_Debit_Amount, i.Amount, i.GST_Amount, i.TDS_Amount, i.SD_Amount,
|
||
i.On_Commission, i.Hydro_Testing, i.GST_SD_Amount,
|
||
i.Final_Amount, h.hold_amount, ht.hold_type
|
||
FROM assign_subcontractors asg
|
||
INNER JOIN villages v ON asg.Village_Id = v.Village_Id
|
||
INNER JOIN invoice i ON i.Village_Id = v.Village_Id AND i.PMC_No = asg.PMC_No
|
||
LEFT JOIN invoice_subcontractor_hold_join h ON i.Invoice_Id = h.Invoice_Id AND h.Contractor_Id = asg.Contractor_Id
|
||
LEFT JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
WHERE asg.Contractor_Id = %s
|
||
ORDER BY i.PMC_No ASC
|
||
""", (contractor_id,))
|
||
invoices = cursor.fetchall()
|
||
|
||
# GST Release
|
||
cursor.execute("""
|
||
SELECT gr.pmc_no, gr.invoice_no, gr.basic_amount, gr.final_amount
|
||
FROM gst_release gr
|
||
INNER JOIN (
|
||
SELECT DISTINCT i.PMC_No, i.Invoice_No
|
||
FROM invoice i
|
||
JOIN assign_subcontractors a ON i.PMC_No = a.PMC_No AND i.Village_Id = a.Village_Id
|
||
WHERE a.Contractor_Id = %s
|
||
) x ON gr.pmc_no = x.PMC_No AND gr.invoice_no = x.Invoice_No
|
||
ORDER BY gr.pmc_no ASC
|
||
""", (contractor_id,))
|
||
gst_rel = cursor.fetchall()
|
||
#Hold
|
||
# Hold Release
|
||
cursor.execute("SELECT * FROM hold_release WHERE Contractor_Id=%s", (contractor_id,))
|
||
hold_release = cursor.fetchall()
|
||
print(hold_release)
|
||
|
||
#Credit Note
|
||
|
||
cursor.execute("select * from credit_note where Contractor_Id=%s",(contractor_id,))
|
||
credit_note=cursor.fetchall()
|
||
print(credit_note)
|
||
# Payments (include valid matches and payments with pmc_no but invoice_no is NULL)
|
||
cursor.execute("""
|
||
SELECT p.pmc_no, p.invoice_no, p.Payment_Amount, p.TDS_Payment_Amount, p.Total_amount, p.utr
|
||
FROM payment p
|
||
WHERE
|
||
EXISTS (
|
||
SELECT 1
|
||
FROM invoice i
|
||
JOIN assign_subcontractors a ON i.PMC_No = a.PMC_No AND i.Village_Id = a.Village_Id
|
||
WHERE a.Contractor_Id = %s
|
||
AND i.PMC_No = p.pmc_no AND i.Invoice_No = p.invoice_no
|
||
)
|
||
OR (
|
||
p.invoice_no IS NULL
|
||
AND EXISTS (
|
||
SELECT 1
|
||
FROM assign_subcontractors a
|
||
WHERE a.Contractor_Id = %s
|
||
AND a.PMC_No = p.pmc_no
|
||
)
|
||
)
|
||
ORDER BY p.pmc_no ASC
|
||
""", (contractor_id, contractor_id))
|
||
payments = cursor.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')
|
||
|
||
except Exception as e:
|
||
print(f"Error fetching contractor report: {e}")
|
||
return "An error occurred while fetching contractor report", 500
|
||
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return render_template('subcontractor_report.html',
|
||
contInfo=contInfo,
|
||
contractor_id=contractor_id,
|
||
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)
|
||
|
||
|
||
|
||
|
||
|
||
|
||
# -----------------------------download contractor report---------------------------------
|
||
# @app.route('/download_report/<int:contractor_id>')
|
||
# def download_report(contractor_id):
|
||
# connection = config.get_db_connection()
|
||
# cursor = connection.cursor(dictionary=True)
|
||
#
|
||
# output_folder = "static/download"
|
||
# output_file = os.path.join(output_folder, f"Contractor_Report_{contractor_id}.xlsx")
|
||
#
|
||
# if not os.path.exists(output_folder):
|
||
# os.makedirs(output_folder)
|
||
#
|
||
# try:
|
||
# # Fetch Contractor Details
|
||
# # cursor.execute("""
|
||
# # SELECT DISTINCT s.Contractor_Name, st.State_Name, d.District_Name, b.Block_Name,
|
||
# # s.Mobile_No, s.GST_Registration_Type, s.GST_No, s.PAN_No, s.Email, s.Address
|
||
# # FROM subcontractors s
|
||
# # LEFT JOIN assign_subcontractors asg ON s.Contractor_Id = asg.Contractor_Id
|
||
# # LEFT JOIN villages v ON asg.Village_Id = v.Village_Id
|
||
# # LEFT JOIN blocks b ON v.Block_Id = b.Block_Id
|
||
# # LEFT JOIN districts d ON b.District_id = d.District_id
|
||
# # LEFT JOIN states st ON d.State_Id = st.State_Id
|
||
# # WHERE s.Contractor_Id = %s
|
||
# # """, (contractor_id,))
|
||
# # contInfo = cursor.fetchone()
|
||
# cursor.callproc('GetContractorInfoById', [contractor_id])
|
||
# contInfo = next(cursor.stored_results()).fetchone()
|
||
#
|
||
# if not contInfo:
|
||
# return "No contractor found", 404
|
||
#
|
||
# # Fetch distinct hold types present for the contractor
|
||
# cursor.execute("""
|
||
# SELECT DISTINCT ht.hold_type_id, ht.hold_type
|
||
# FROM invoice_subcontractor_hold_join h
|
||
# JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
# WHERE h.Contractor_Id = %s
|
||
# """, (contractor_id,))
|
||
# hold_types = cursor.fetchall()
|
||
# hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types}
|
||
#
|
||
# # Fetch Invoices & GST Releases
|
||
# cursor.execute("""
|
||
# SELECT DISTINCT i.Invoice_Id, i.PMC_No, v.Village_Name, i.Work_Type, i.Invoice_Details,
|
||
# i.Invoice_Date, i.Invoice_No, i.Basic_Amount, i.Debit_Amount,
|
||
# i.After_Debit_Amount, i.GST_Amount, i.Amount, i.TDS_Amount, i.SD_Amount,
|
||
# i.On_Commission, i.Hydro_Testing, i.GST_SD_Amount, i.Final_Amount,
|
||
# g.pmc_no AS gst_pmc_no, g.invoice_no AS gst_invoice_no,
|
||
# g.basic_amount AS gst_basic_amount, g.final_amount AS gst_final_amount
|
||
# FROM invoice i
|
||
# LEFT JOIN assign_subcontractors asg ON i.PMC_No = asg.PMC_No
|
||
# LEFT JOIN villages v ON i.Village_Id = v.Village_Id
|
||
# LEFT JOIN gst_release g ON i.PMC_No = g.pmc_no AND i.Invoice_No = g.invoice_no
|
||
# WHERE asg.Contractor_Id = %s
|
||
# """, (contractor_id,))
|
||
# invoices = cursor.fetchall()
|
||
#
|
||
# # Fetch Hold Amounts separately
|
||
# cursor.execute("""
|
||
# SELECT h.Invoice_Id, ht.hold_type_id, h.hold_amount
|
||
# FROM invoice_subcontractor_hold_join h
|
||
# JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
# WHERE h.Contractor_Id = %s
|
||
# """, (contractor_id,))
|
||
# hold_amounts = cursor.fetchall()
|
||
#
|
||
# # Create a mapping of invoice_id to hold amounts by type
|
||
# hold_data = {}
|
||
# for h in hold_amounts:
|
||
# hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
||
#
|
||
# # Extract unique PMC numbers for payments
|
||
# pmc_numbers = tuple(set(inv['PMC_No'] for inv in invoices if inv['PMC_No'] is not None))
|
||
#
|
||
# # Fetch all Payments for the PMC numbers (including those with null invoice_no)
|
||
# payments_map = {}
|
||
# extra_payments_map = {} # Now using a map to organize extra payments by PMC
|
||
# if pmc_numbers:
|
||
# # First get payments with invoice_no
|
||
# query = f"""
|
||
# SELECT pmc_no, invoice_no, Payment_Amount, TDS_Payment_Amount, Total_amount, UTR
|
||
# FROM payment
|
||
# WHERE pmc_no IN ({','.join(['%s'] * len(pmc_numbers))})
|
||
# AND invoice_no IS NOT NULL
|
||
# ORDER BY pmc_no, invoice_no
|
||
# """
|
||
# cursor.execute(query, pmc_numbers)
|
||
# payments = cursor.fetchall()
|
||
#
|
||
# # Organize payments by PMC No & Invoice No
|
||
# for pay in payments:
|
||
# key = (pay['pmc_no'], pay['invoice_no'])
|
||
# if key not in payments_map:
|
||
# payments_map[key] = []
|
||
# payments_map[key].append(pay)
|
||
#
|
||
# # Then get extra payments (null invoice_no) and organize by PMC
|
||
# query = f"""
|
||
# SELECT pmc_no, invoice_no, Payment_Amount, TDS_Payment_Amount, Total_amount, UTR
|
||
# FROM payment
|
||
# WHERE pmc_no IN ({','.join(['%s'] * len(pmc_numbers))})
|
||
# AND invoice_no IS NULL
|
||
# ORDER BY pmc_no
|
||
# """
|
||
# cursor.execute(query, pmc_numbers)
|
||
# extra_payments = cursor.fetchall()
|
||
#
|
||
# for pay in extra_payments:
|
||
# if pay['pmc_no'] not in extra_payments_map:
|
||
# extra_payments_map[pay['pmc_no']] = []
|
||
# extra_payments_map[pay['pmc_no']].append(pay)
|
||
#
|
||
# # Create Excel workbook
|
||
# workbook = openpyxl.Workbook()
|
||
# sheet = workbook.active
|
||
# sheet.title = "Contractor Report"
|
||
#
|
||
# # Write Contractor Details
|
||
# sheet.append(["", "", "Laxmi Civil Engineering Services PVT. LTD.", "", ""])
|
||
# sheet.append(
|
||
# ["Contractor Name", contInfo["Contractor_Name"], " ", "GST No", contInfo["GST_No"], " ", "GST Type",
|
||
# contInfo["GST_Registration_Type"]])
|
||
# sheet.append(
|
||
# ["State", contInfo["State_Name"], " ", "PAN No", contInfo["PAN_No"], " ", "Address", contInfo["Address"]])
|
||
# sheet.append(["District", contInfo["District_Name"], " ", "Mobile No", contInfo["Mobile_No"]])
|
||
# sheet.append(["Block", contInfo["Block_Name"], " ", "Email", contInfo["Email"]])
|
||
# sheet.append([])
|
||
#
|
||
# # Table Headers - include all hold types as separate columns
|
||
# 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)
|
||
#
|
||
# seen_invoices = set()
|
||
# seen_gst_notes = set()
|
||
# processed_payments = set() # Track which payments we've processed
|
||
#
|
||
# # Process invoices grouped by PMC No
|
||
# pmc_groups = {}
|
||
# for inv in invoices:
|
||
# pmc_no = inv["PMC_No"]
|
||
# if pmc_no not in pmc_groups:
|
||
# pmc_groups[pmc_no] = []
|
||
# pmc_groups[pmc_no].append(inv)
|
||
#
|
||
# # Process each PMC group separately
|
||
# for pmc_no, pmc_invoices in pmc_groups.items():
|
||
# # Process all invoices for this PMC first
|
||
# for inv in pmc_invoices:
|
||
# invoice_no = inv["Invoice_No"]
|
||
# payments = payments_map.get((pmc_no, invoice_no), [])
|
||
#
|
||
# # Process invoice row with first payment (if exists)
|
||
# if (pmc_no, invoice_no) not in seen_invoices:
|
||
# seen_invoices.add((pmc_no, invoice_no))
|
||
# first_payment = payments[0] if len(payments) > 0 else None
|
||
#
|
||
# # Base invoice data
|
||
# 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"]
|
||
# ]
|
||
#
|
||
# # Add hold amounts for each hold type
|
||
# invoice_holds = hold_data.get(inv["Invoice_Id"], {})
|
||
# for ht_id in hold_type_map.keys():
|
||
# row.append(invoice_holds.get(ht_id, ""))
|
||
#
|
||
# # Add payment information
|
||
# 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)
|
||
#
|
||
# if first_payment:
|
||
# payment_id = f"{pmc_no}-{invoice_no}-{first_payment['Payment_Amount']}-{first_payment.get('UTR', '')}"
|
||
# processed_payments.add(payment_id)
|
||
#
|
||
# # Process GST release if exists (only if we have a matching GST record)
|
||
# if inv["gst_pmc_no"] and (inv["gst_pmc_no"], inv["gst_invoice_no"]) not in seen_gst_notes:
|
||
# seen_gst_notes.add((inv["gst_pmc_no"], inv["gst_invoice_no"]))
|
||
#
|
||
# # Find the payment that matches this GST release
|
||
# gst_payment = None
|
||
# for payment in payments[1:]: # Skip first payment (already used for invoice)
|
||
# if payment['invoice_no'] == inv["gst_invoice_no"]:
|
||
# gst_payment = payment
|
||
# break
|
||
#
|
||
# # GST release row
|
||
# row = [
|
||
# pmc_no, "", "", "GST Release Note", "", inv["gst_invoice_no"],
|
||
# inv["gst_basic_amount"], "", "", "", "", "", "", "", "", "" # Empty GST SD Amount
|
||
# ]
|
||
#
|
||
# # Empty holds for GST release
|
||
# row += ["" for _ in hold_headers]
|
||
#
|
||
# # Add payment information
|
||
# row += [
|
||
# inv["gst_final_amount"],
|
||
# gst_payment["Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["TDS_Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["Total_amount"] if gst_payment else "",
|
||
# gst_payment["UTR"] if gst_payment else ""
|
||
# ]
|
||
#
|
||
# sheet.append(row)
|
||
#
|
||
# if gst_payment:
|
||
# payment_id = f"{pmc_no}-{inv['gst_invoice_no']}-{gst_payment['Payment_Amount']}-{gst_payment.get('UTR', '')}"
|
||
# processed_payments.add(payment_id)
|
||
#
|
||
# # Process remaining payments as extra payments
|
||
# for payment in payments[1:]:
|
||
# payment_id = f"{pmc_no}-{payment['invoice_no']}-{payment['Payment_Amount']}-{payment.get('UTR', '')}"
|
||
# if payment_id not in processed_payments:
|
||
# row = [
|
||
# pmc_no, "", "", "", "", payment['invoice_no'],
|
||
# "", "", "", "", "", "", "", "", "", "" # Empty GST SD Amount
|
||
# ]
|
||
#
|
||
# # Empty holds for extra payments
|
||
# row += ["" for _ in hold_headers]
|
||
#
|
||
# # Add payment information
|
||
# row += [
|
||
# "",
|
||
# payment["Payment_Amount"],
|
||
# payment["TDS_Payment_Amount"],
|
||
# payment["Total_amount"],
|
||
# payment["UTR"]
|
||
# ]
|
||
#
|
||
# sheet.append(row)
|
||
# processed_payments.add(payment_id)
|
||
#
|
||
# # Process extra payments for this PMC (null invoice_no) immediately after the PMC's invoices
|
||
# if pmc_no in extra_payments_map:
|
||
# for payment in extra_payments_map[pmc_no]:
|
||
# payment_id = f"{pmc_no}-null-{payment['Payment_Amount']}-{payment.get('UTR', '')}"
|
||
# if payment_id not in processed_payments:
|
||
# row = [
|
||
# pmc_no, "", "", "", "", "",
|
||
# "", "", "", "", "", "", "", "", "", "" # Empty GST SD Amount
|
||
# ]
|
||
#
|
||
# # Empty holds for null invoice payments
|
||
# row += ["" for _ in hold_headers]
|
||
#
|
||
# # Add payment information
|
||
# row += [
|
||
# "",
|
||
# payment["Payment_Amount"],
|
||
# payment["TDS_Payment_Amount"],
|
||
# payment["Total_amount"],
|
||
# payment["UTR"]
|
||
# ]
|
||
#
|
||
# sheet.append(row)
|
||
# processed_payments.add(payment_id)
|
||
#
|
||
# workbook.save(output_file)
|
||
# workbook.close()
|
||
# finally:
|
||
# cursor.close()
|
||
# connection.close()
|
||
# from openpyxl.styles import Font
|
||
#
|
||
# # Initialize totals
|
||
# total_basic_amount = 0
|
||
# total_tds_amount = 0
|
||
# total_sd_amount = 0
|
||
# total_on_commission = 0
|
||
# total_hold_amount = 0
|
||
# total_final_amount = 0
|
||
# total_total_amount = 0 # Sum of all Total Amounts from payment data
|
||
#
|
||
# # Iterate through rows to calculate totals
|
||
# for row in sheet.iter_rows(min_row=2, max_row=sheet.max_row, values_only=True):
|
||
# try:
|
||
# total_basic_amount += float(row[6] or 0) # Basic_Amount
|
||
# total_tds_amount += float(row[11] or 0) # TDS_Amount
|
||
# total_sd_amount += float(row[12] or 0) # SD_Amount
|
||
# total_on_commission += float(row[13] or 0) # On_Commission
|
||
# total_final_amount += float(row[-5] or 0) # Final_Amount
|
||
# total_total_amount += float(row[-2] or 0) # Total_Amount (from payments)
|
||
#
|
||
# # Sum of hold amounts (dynamically calculated based on hold_headers)
|
||
# hold_start_col = len(base_headers) # First column where hold types start
|
||
# hold_end_col = hold_start_col + len(hold_headers) # Last column where hold types end
|
||
# total_hold_amount += sum(float(row[i] or 0) for i in range(hold_start_col, hold_end_col))
|
||
#
|
||
# except ValueError:
|
||
# continue # Skip if non-numeric values cause errors
|
||
#
|
||
# # Append the totals row at the bottom of the sheet
|
||
# totals_row = [
|
||
# "TOTAL", "", "", "", "", "", # Empty values for non-numeric columns
|
||
# total_basic_amount, "", "", "", "", total_tds_amount, total_sd_amount,
|
||
# total_on_commission, "", "", # Empty GST SD Amount
|
||
# ]
|
||
#
|
||
# # Add empty placeholders for hold types
|
||
# totals_row += [total_hold_amount] + [""] * (len(hold_headers) - 1)
|
||
#
|
||
# # Add totals for Final Amount and Total Amount
|
||
# totals_row += [
|
||
# total_final_amount, "", "", total_total_amount, "" # UTR column remains empty
|
||
# ]
|
||
#
|
||
# # Append totals row to sheet
|
||
# sheet.append([])
|
||
# sheet.append(totals_row)
|
||
#
|
||
# # Make the totals row bold
|
||
# for cell in sheet[sheet.max_row]:
|
||
# cell.font = Font(bold=True)
|
||
#
|
||
# sheet.append([])
|
||
# sheet.append([])
|
||
# sheet.append([])
|
||
# sheet.append([])
|
||
# sheet.append(["This is Generated by LCEPL Application.."])
|
||
#
|
||
# # Save workbook after modifications
|
||
# workbook.save(output_file)
|
||
# workbook.close()
|
||
#
|
||
# return send_from_directory(output_folder, f"Contractor_Report_{contractor_id}.xlsx", as_attachment=True)
|
||
from openpyxl import Workbook
|
||
|
||
# # Download report by contractor id
|
||
# # Download report by contractor id
|
||
from flask import send_from_directory
|
||
|
||
import config
|
||
|
||
|
||
# -----------------------PMC Report---------------------------
|
||
# @app.route('/download_report/<int:contractor_id>')
|
||
# def download_report(contractor_id):
|
||
# connection = config.get_db_connection()
|
||
# cursor = connection.cursor(dictionary=True)
|
||
|
||
# output_folder = "static/download"
|
||
# output_file = os.path.join(output_folder, f"Contractor_Report_{contractor_id}.xlsx")
|
||
|
||
# if not os.path.exists(output_folder):
|
||
# os.makedirs(output_folder)
|
||
|
||
# try:
|
||
# # Fetch Contractor Details
|
||
# cursor.execute("""
|
||
# SELECT DISTINCT s.Contractor_Name, st.State_Name, d.District_Name, b.Block_Name,
|
||
# s.Mobile_No, s.GST_Registration_Type, s.GST_No, s.PAN_No, s.Email, s.Address
|
||
# FROM subcontractors s
|
||
# LEFT JOIN assign_subcontractors asg ON s.Contractor_Id = asg.Contractor_Id
|
||
# LEFT JOIN villages v ON asg.Village_Id = v.Village_Id
|
||
# LEFT JOIN blocks b ON v.Block_Id = b.Block_Id
|
||
# LEFT JOIN districts d ON b.District_id = d.District_id
|
||
# LEFT JOIN states st ON d.State_Id = st.State_Id
|
||
# WHERE s.Contractor_Id = %s
|
||
# """, (contractor_id,))
|
||
# contInfo = cursor.fetchone()
|
||
|
||
# if not contInfo:
|
||
# return "No contractor found", 404
|
||
|
||
# # # Fetch distinct hold types present for the contractor
|
||
# # cursor.execute("""
|
||
# # SELECT DISTINCT ht.hold_type_id, ht.hold_type
|
||
# # FROM invoice_subcontractor_hold_join h
|
||
# # JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
# # WHERE h.Contractor_Id = %s
|
||
# # """, (contractor_id,))
|
||
# # hold_types = cursor.fetchall()
|
||
# cursor.callproc('GetDistinctHoldTypesByContractor', [contractor_id])
|
||
|
||
# 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}
|
||
|
||
# # # Fetch Invoices & GST Releases
|
||
# # cursor.execute("""
|
||
# # SELECT DISTINCT i.Invoice_Id, i.PMC_No, v.Village_Name, i.Work_Type, i.Invoice_Details,
|
||
# # i.Invoice_Date, i.Invoice_No, i.Basic_Amount, i.Debit_Amount,
|
||
# # i.After_Debit_Amount, i.GST_Amount, i.Amount, i.TDS_Amount, i.SD_Amount,
|
||
# # i.On_Commission, i.Hydro_Testing, i.GST_SD_Amount, i.Final_Amount,
|
||
# # g.pmc_no AS gst_pmc_no, g.invoice_no AS gst_invoice_no,
|
||
# # g.basic_amount AS gst_basic_amount, g.final_amount AS gst_final_amount
|
||
# # FROM invoice i
|
||
# # LEFT JOIN assign_subcontractors asg ON i.PMC_No = asg.PMC_No
|
||
# # LEFT JOIN villages v ON i.Village_Id = v.Village_Id
|
||
# # LEFT JOIN gst_release g ON i.PMC_No = g.pmc_no AND i.Invoice_No = g.invoice_no
|
||
# # WHERE asg.Contractor_Id = %s
|
||
# # """, (contractor_id,))
|
||
# # invoices = cursor.fetchall()
|
||
# cursor.callproc('GetInvoicesAndGSTReleasesByContractor', [contractor_id])
|
||
|
||
# for result in cursor.stored_results():
|
||
# invoices = result.fetchall()
|
||
|
||
# # # Fetch Hold Amounts separately
|
||
# # cursor.execute("""
|
||
# # SELECT h.Invoice_Id, ht.hold_type_id, h.hold_amount
|
||
# # FROM invoice_subcontractor_hold_join h
|
||
# # JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
# # WHERE h.Contractor_Id = %s
|
||
# # """, (contractor_id,))
|
||
# # hold_amounts = cursor.fetchall()
|
||
# cursor.callproc('GetHoldAmountsByContractors', [contractor_id])
|
||
|
||
# for result in cursor.stored_results():
|
||
# hold_amounts = result.fetchall()
|
||
|
||
# # Create a mapping of invoice_id to hold amounts by type
|
||
# hold_data = {}
|
||
# for h in hold_amounts:
|
||
# hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
||
|
||
# # Extract unique PMC numbers for payments
|
||
# pmc_numbers = tuple(set(inv['PMC_No'] for inv in invoices if inv['PMC_No'] is not None))
|
||
|
||
# # Fetch all Payments for the PMC numbers (including those with null invoice_no)
|
||
# payments_map = {}
|
||
# extra_payments_map = {} # Now using a map to organize extra payments by PMC
|
||
# if pmc_numbers:
|
||
# # First get payments with invoice_no
|
||
# query = f"""
|
||
# SELECT pmc_no, invoice_no, Payment_Amount, TDS_Payment_Amount, Total_amount, UTR
|
||
# FROM payment
|
||
# WHERE pmc_no IN ({','.join(['%s'] * len(pmc_numbers))})
|
||
# AND invoice_no IS NOT NULL
|
||
# ORDER BY pmc_no, invoice_no
|
||
# """
|
||
# cursor.execute(query, pmc_numbers)
|
||
# payments = cursor.fetchall()
|
||
|
||
# # Organize payments by PMC No & Invoice No
|
||
# for pay in payments:
|
||
# key = (pay['pmc_no'], pay['invoice_no'])
|
||
# if key not in payments_map:
|
||
# payments_map[key] = []
|
||
# payments_map[key].append(pay)
|
||
|
||
# # Then get extra payments (null invoice_no) and organize by PMC
|
||
# query = f"""
|
||
# SELECT pmc_no, invoice_no, Payment_Amount, TDS_Payment_Amount, Total_amount, UTR
|
||
# FROM payment
|
||
# WHERE pmc_no IN ({','.join(['%s'] * len(pmc_numbers))})
|
||
# AND invoice_no IS NULL
|
||
# ORDER BY pmc_no
|
||
# """
|
||
# cursor.execute(query, pmc_numbers)
|
||
# extra_payments = cursor.fetchall()
|
||
|
||
# for pay in extra_payments:
|
||
# if pay['pmc_no'] not in extra_payments_map:
|
||
# extra_payments_map[pay['pmc_no']] = []
|
||
# extra_payments_map[pay['pmc_no']].append(pay)
|
||
|
||
# # Create Excel workbook
|
||
# workbook = openpyxl.Workbook()
|
||
# sheet = workbook.active
|
||
# sheet.title = "Contractor Report"
|
||
|
||
# # Write Contractor Details
|
||
# sheet.append(["Contractor Name", contInfo["Contractor_Name"]])
|
||
# sheet.append(["State", contInfo["State_Name"]])
|
||
# sheet.append(["District", contInfo["District_Name"]])
|
||
# sheet.append(["Block", contInfo["Block_Name"]])
|
||
# sheet.append(["Mobile No", contInfo["Mobile_No"]])
|
||
# sheet.append(["GST Type", contInfo["GST_Registration_Type"]])
|
||
# sheet.append(["GST No", contInfo["GST_No"]])
|
||
# sheet.append(["PAN No", contInfo["PAN_No"]])
|
||
# sheet.append(["Email", contInfo["Email"]])
|
||
# sheet.append(["Address", contInfo["Address"]])
|
||
# sheet.append([])
|
||
|
||
# # Table Headers - include all hold types as separate columns
|
||
# 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)
|
||
|
||
# seen_invoices = set()
|
||
# seen_gst_notes = set()
|
||
# processed_payments = set() # Track which payments we've processed
|
||
|
||
# # Process invoices grouped by PMC No
|
||
# pmc_groups = {}
|
||
# for inv in invoices:
|
||
# pmc_no = inv["PMC_No"]
|
||
# if pmc_no not in pmc_groups:
|
||
# pmc_groups[pmc_no] = []
|
||
# pmc_groups[pmc_no].append(inv)
|
||
|
||
# # Process each PMC group separately
|
||
# for pmc_no, pmc_invoices in pmc_groups.items():
|
||
# # Process all invoices for this PMC first
|
||
# for inv in pmc_invoices:
|
||
# invoice_no = inv["Invoice_No"]
|
||
# payments = payments_map.get((pmc_no, invoice_no), [])
|
||
|
||
# # Process invoice row with first payment (if exists)
|
||
# if (pmc_no, invoice_no) not in seen_invoices:
|
||
# seen_invoices.add((pmc_no, invoice_no))
|
||
# first_payment = payments[0] if len(payments) > 0 else None
|
||
|
||
# # Base invoice data
|
||
# 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"]
|
||
# ]
|
||
|
||
# # Add hold amounts for each hold type
|
||
# invoice_holds = hold_data.get(inv["Invoice_Id"], {})
|
||
# for ht_id in hold_type_map.keys():
|
||
# row.append(invoice_holds.get(ht_id, ""))
|
||
|
||
# # Add payment information
|
||
# 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)
|
||
|
||
# if first_payment:
|
||
# payment_id = f"{pmc_no}-{invoice_no}-{first_payment['Payment_Amount']}-{first_payment.get('UTR', '')}"
|
||
# processed_payments.add(payment_id)
|
||
|
||
# # Process GST release if exists (only if we have a matching GST record)
|
||
# if inv["gst_pmc_no"] and (inv["gst_pmc_no"], inv["gst_invoice_no"]) not in seen_gst_notes:
|
||
# seen_gst_notes.add((inv["gst_pmc_no"], inv["gst_invoice_no"]))
|
||
|
||
# # Find the payment that matches this GST release
|
||
# gst_payment = None
|
||
# for payment in payments[1:]: # Skip first payment (already used for invoice)
|
||
# if payment['invoice_no'] == inv["gst_invoice_no"]:
|
||
# gst_payment = payment
|
||
# break
|
||
|
||
# # GST release row
|
||
# row = [
|
||
# pmc_no, "", "", "GST Release Note", "", inv["gst_invoice_no"],
|
||
# inv["gst_basic_amount"], "", "", "", "", "", "", "", "", "" # Empty GST SD Amount
|
||
# ]
|
||
|
||
# # Empty holds for GST release
|
||
# row += ["" for _ in hold_headers]
|
||
|
||
# # Add payment information
|
||
# row += [
|
||
# inv["gst_final_amount"],
|
||
# gst_payment["Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["TDS_Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["Total_amount"] if gst_payment else "",
|
||
# gst_payment["UTR"] if gst_payment else ""
|
||
# ]
|
||
|
||
# sheet.append(row)
|
||
|
||
# if gst_payment:
|
||
# payment_id = f"{pmc_no}-{inv['gst_invoice_no']}-{gst_payment['Payment_Amount']}-{gst_payment.get('UTR', '')}"
|
||
# processed_payments.add(payment_id)
|
||
|
||
# # Process remaining payments as extra payments
|
||
# for payment in payments[1:]:
|
||
# payment_id = f"{pmc_no}-{payment['invoice_no']}-{payment['Payment_Amount']}-{payment.get('UTR', '')}"
|
||
# if payment_id not in processed_payments:
|
||
# row = [
|
||
# pmc_no, "", "", "", "", payment['invoice_no'],
|
||
# "", "", "", "", "", "", "", "", "", "" # Empty GST SD Amount
|
||
# ]
|
||
|
||
# # Empty holds for extra payments
|
||
# row += ["" for _ in hold_headers]
|
||
|
||
# # Add payment information
|
||
# row += [
|
||
# "",
|
||
# payment["Payment_Amount"],
|
||
# payment["TDS_Payment_Amount"],
|
||
# payment["Total_amount"],
|
||
# payment["UTR"]
|
||
# ]
|
||
|
||
# sheet.append(row)
|
||
# processed_payments.add(payment_id)
|
||
|
||
# # Process extra payments for this PMC (null invoice_no) immediately after the PMC's invoices
|
||
# if pmc_no in extra_payments_map:
|
||
# for payment in extra_payments_map[pmc_no]:
|
||
# payment_id = f"{pmc_no}-null-{payment['Payment_Amount']}-{payment.get('UTR', '')}"
|
||
# if payment_id not in processed_payments:
|
||
# row = [
|
||
# pmc_no, "", "", "", "", "",
|
||
# "", "", "", "", "", "", "", "", "", "" # Empty GST SD Amount
|
||
# ]
|
||
|
||
# # Empty holds for null invoice payments
|
||
# row += ["" for _ in hold_headers]
|
||
|
||
# # Add payment information
|
||
# row += [
|
||
# "",
|
||
# payment["Payment_Amount"],
|
||
# payment["TDS_Payment_Amount"],
|
||
# payment["Total_amount"],
|
||
# payment["UTR"]
|
||
# ]
|
||
|
||
|
||
# sheet.append(row)
|
||
# processed_payments.add(payment_id)
|
||
|
||
# workbook.save(output_file)
|
||
# workbook.close()
|
||
# finally:
|
||
# cursor.close()
|
||
# connection.close()
|
||
# from openpyxl.styles import Font
|
||
|
||
# # Initialize totals
|
||
# total_basic_amount = 0
|
||
# total_tds_amount = 0
|
||
# total_sd_amount = 0
|
||
# total_on_commission = 0
|
||
# total_hold_amount = 0
|
||
# total_final_amount = 0
|
||
# total_total_amount = 0 # Sum of all Total Amounts from payment data
|
||
|
||
# # Iterate through rows to calculate totals
|
||
# for row in sheet.iter_rows(min_row=2, max_row=sheet.max_row, values_only=True):
|
||
# try:
|
||
# total_basic_amount += float(row[6] or 0) # Basic_Amount
|
||
# total_tds_amount += float(row[11] or 0) # TDS_Amount
|
||
# total_sd_amount += float(row[12] or 0) # SD_Amount
|
||
# total_on_commission += float(row[13] or 0) # On_Commission
|
||
# total_final_amount += float(row[-5] or 0) # Final_Amount
|
||
# total_total_amount += float(row[-2] or 0) # Total_Amount (from payments)
|
||
|
||
# # Sum of hold amounts (dynamically calculated based on hold_headers)
|
||
# hold_start_col = len(base_headers) # First column where hold types start
|
||
# hold_end_col = hold_start_col + len(hold_headers) # Last column where hold types end
|
||
# total_hold_amount += sum(float(row[i] or 0) for i in range(hold_start_col, hold_end_col))
|
||
|
||
# except ValueError:
|
||
# continue # Skip if non-numeric values cause errors
|
||
|
||
# # Append the totals row at the bottom of the sheet
|
||
# totals_row = [
|
||
# "TOTAL", "", "", "", "", "", # Empty values for non-numeric columns
|
||
# total_basic_amount, "", "", "", "", total_tds_amount, total_sd_amount,
|
||
# total_on_commission, "", "", # Empty GST SD Amount
|
||
# ]
|
||
|
||
# # Add empty placeholders for hold types
|
||
# totals_row += [total_hold_amount] + [""] * (len(hold_headers) - 1)
|
||
|
||
# # Add totals for Final Amount and Total Amount
|
||
# totals_row += [
|
||
# total_final_amount, "", "", total_total_amount, "" # UTR column remains empty
|
||
# ]
|
||
|
||
# # Append totals row to sheet
|
||
# sheet.append([])
|
||
# sheet.append(totals_row)
|
||
|
||
# # Make the totals row bold
|
||
# for cell in sheet[sheet.max_row]:
|
||
# cell.font = Font(bold=True)
|
||
|
||
# # Save workbook after modifications
|
||
# workbook.save(output_file)
|
||
# workbook.close()
|
||
|
||
# return send_from_directory(output_folder, f"Contractor_Report_{contractor_id}.xlsx", as_attachment=True)
|
||
|
||
# @app.route('/download_report/<int:contractor_id>')
|
||
# def download_report(contractor_id):
|
||
# connection = config.get_db_connection()
|
||
# cursor = connection.cursor(dictionary=True)
|
||
#
|
||
# output_folder = "static/download"
|
||
# output_file = os.path.join(output_folder, f"Contractor_Report_{contractor_id}.xlsx")
|
||
#
|
||
# if not os.path.exists(output_folder):
|
||
# os.makedirs(output_folder)
|
||
#
|
||
# try:
|
||
# # Fetch Contractor Details
|
||
# # cursor.execute("""
|
||
# # SELECT DISTINCT s.Contractor_Name, st.State_Name, d.District_Name, b.Block_Name,
|
||
# # s.Mobile_No, s.GST_Registration_Type, s.GST_No, s.PAN_No, s.Email, s.Address
|
||
# # FROM subcontractors s
|
||
# # LEFT JOIN assign_subcontractors asg ON s.Contractor_Id = asg.Contractor_Id
|
||
# # LEFT JOIN villages v ON asg.Village_Id = v.Village_Id
|
||
# # LEFT JOIN blocks b ON v.Block_Id = b.Block_Id
|
||
# # LEFT JOIN districts d ON b.District_id = d.District_id
|
||
# # LEFT JOIN states st ON d.State_Id = st.State_Id
|
||
# # WHERE s.Contractor_Id = %s
|
||
# # """, (contractor_id,))
|
||
# # contInfo = cursor.fetchone()
|
||
# cursor.callproc('GetContractorInfoId', [contractor_id])
|
||
# for result in cursor.stored_results():
|
||
# contInfo = result.fetchone()
|
||
#
|
||
# if not contInfo:
|
||
# return "No contractor found", 404
|
||
#
|
||
# # # Fetch distinct hold types present for the contractor
|
||
# # cursor.execute("""
|
||
# # SELECT DISTINCT ht.hold_type_id, ht.hold_type
|
||
# # FROM invoice_subcontractor_hold_join h
|
||
# # JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
# # WHERE h.Contractor_Id = %s
|
||
# # """, (contractor_id,))
|
||
# # hold_types = cursor.fetchall()
|
||
# cursor.callproc('GetDistinctHoldTypesByContractor', [contractor_id])
|
||
#
|
||
# 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}
|
||
#
|
||
# # # Fetch Invoices & GST Releases
|
||
# # cursor.execute("""
|
||
# # SELECT DISTINCT i.Invoice_Id, i.PMC_No, v.Village_Name, i.Work_Type, i.Invoice_Details,
|
||
# # i.Invoice_Date, i.Invoice_No, i.Basic_Amount, i.Debit_Amount,
|
||
# # i.After_Debit_Amount, i.GST_Amount, i.Amount, i.TDS_Amount, i.SD_Amount,
|
||
# # i.On_Commission, i.Hydro_Testing, i.GST_SD_Amount, i.Final_Amount,
|
||
# # g.pmc_no AS gst_pmc_no, g.invoice_no AS gst_invoice_no,
|
||
# # g.basic_amount AS gst_basic_amount, g.final_amount AS gst_final_amount
|
||
# # FROM invoice i
|
||
# # LEFT JOIN assign_subcontractors asg ON i.PMC_No = asg.PMC_No
|
||
# # LEFT JOIN villages v ON i.Village_Id = v.Village_Id
|
||
# # LEFT JOIN gst_release g ON i.PMC_No = g.pmc_no AND i.Invoice_No = g.invoice_no
|
||
# # WHERE asg.Contractor_Id = %s
|
||
# # """, (contractor_id,))
|
||
# # invoices = cursor.fetchall()
|
||
# cursor.callproc('GetInvoicesAndGSTReleasesByContractor', [contractor_id])
|
||
#
|
||
# for result in cursor.stored_results():
|
||
# invoices = result.fetchall()
|
||
#
|
||
# # # Fetch Hold Amounts separately
|
||
# # cursor.execute("""
|
||
# # SELECT h.Invoice_Id, ht.hold_type_id, h.hold_amount
|
||
# # FROM invoice_subcontractor_hold_join h
|
||
# # JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
# # WHERE h.Contractor_Id = %s
|
||
# # """, (contractor_id,))
|
||
# # hold_amounts = cursor.fetchall()
|
||
# cursor.callproc('GetHoldAmountsByContractors', [contractor_id])
|
||
#
|
||
# for result in cursor.stored_results():
|
||
# hold_amounts = result.fetchall()
|
||
#
|
||
# # Create a mapping of invoice_id to hold amounts by type
|
||
# hold_data = {}
|
||
# for h in hold_amounts:
|
||
# hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
||
#
|
||
# # Extract unique PMC numbers for payments
|
||
# pmc_numbers = tuple(set(inv['PMC_No'] for inv in invoices if inv['PMC_No'] is not None))
|
||
#
|
||
# # Fetch all Payments for the PMC numbers (including those with null invoice_no)
|
||
# payments_map = {}
|
||
# extra_payments_map = {} # Now using a map to organize extra payments by PMC
|
||
# if pmc_numbers:
|
||
# # # First get payments with invoice_no
|
||
# # query = f"""
|
||
# # SELECT pmc_no, invoice_no, Payment_Amount, TDS_Payment_Amount, Total_amount, UTR
|
||
# # FROM payment
|
||
# # WHERE pmc_no IN ({','.join(['%s'] * len(pmc_numbers))})
|
||
# # AND invoice_no IS NOT NULL
|
||
# # ORDER BY pmc_no, invoice_no
|
||
# # """
|
||
# # cursor.execute(query, pmc_numbers)
|
||
# # payments = cursor.fetchall()
|
||
#
|
||
# pmc_list_str = ','.join(str(pmc) for pmc in pmc_numbers)
|
||
# # e.g. 'PMC001,PMC002,PMC003'
|
||
# cursor.callproc('GetPaymentsByPmcNosWithInvoice', [pmc_list_str])
|
||
#
|
||
# for result in cursor.stored_results():
|
||
# payments = result.fetchall()
|
||
#
|
||
# print("payments by procedure:", payments)
|
||
# # Organize payments by PMC No & Invoice No
|
||
# for pay in payments:
|
||
# key = (pay['pmc_no'], pay['invoice_no'])
|
||
# if key not in payments_map:
|
||
# payments_map[key] = []
|
||
# payments_map[key].append(pay)
|
||
#
|
||
# # Then get extra payments (null invoice_no) and organize by PMC
|
||
# # query = f"""
|
||
# # SELECT pmc_no, invoice_no, Payment_Amount, TDS_Payment_Amount, Total_amount, UTR
|
||
# # FROM payment
|
||
# # WHERE pmc_no IN ({','.join(['%s'] * len(pmc_numbers))})
|
||
# # AND invoice_no IS NULL
|
||
# # ORDER BY pmc_no
|
||
# # """
|
||
# # cursor.execute(query, pmc_numbers)
|
||
# # extra_payments = cursor.fetchall()
|
||
# pmc_list_str = ','.join(str(pmc) for pmc in pmc_numbers)
|
||
# cursor.callproc('GetExtraPaymentsByPmcNos', [pmc_list_str])
|
||
#
|
||
# for result in cursor.stored_results():
|
||
# extra_payments = result.fetchall()
|
||
# print(
|
||
# "-----------------------------------------------------------------------------------------Extra Payment---------------------------------------------------------------")
|
||
# print("Extra payment from produre", extra_payments)
|
||
#
|
||
# for pay in extra_payments:
|
||
# if pay['pmc_no'] not in extra_payments_map:
|
||
# extra_payments_map[pay['pmc_no']] = []
|
||
# extra_payments_map[pay['pmc_no']].append(pay)
|
||
# print(
|
||
# "-----------------------------------------------------------------------------------------Extra Payment MAP --------------------------------------------------------------")
|
||
# print("Extra payment MAp from produre", extra_payments_map)
|
||
# # Create Excel workbook
|
||
# workbook = openpyxl.Workbook()
|
||
# sheet = workbook.active
|
||
# sheet.title = "Contractor Report"
|
||
#
|
||
# # Write Contractor Details
|
||
# sheet.append(["Contractor Name", contInfo["Contractor_Name"]])
|
||
# sheet.append(["State", contInfo["State_Name"]])
|
||
# sheet.append(["District", contInfo["District_Name"]])
|
||
# sheet.append(["Block", contInfo["Block_Name"]])
|
||
# sheet.append(["Mobile No", contInfo["Mobile_No"]])
|
||
# sheet.append(["GST Type", contInfo["GST_Registration_Type"]])
|
||
# sheet.append(["GST No", contInfo["GST_No"]])
|
||
# sheet.append(["PAN No", contInfo["PAN_No"]])
|
||
# sheet.append(["Email", contInfo["Email"]])
|
||
# sheet.append(["Address", contInfo["Address"]])
|
||
# sheet.append([])
|
||
#
|
||
# # Table Headers - include all hold types as separate columns
|
||
# 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)
|
||
#
|
||
# seen_invoices = set()
|
||
# seen_gst_notes = set()
|
||
# processed_payments = set() # Track which payments we've processed
|
||
#
|
||
# # Process invoices grouped by PMC No
|
||
# pmc_groups = {}
|
||
# for inv in invoices:
|
||
# pmc_no = inv["PMC_No"]
|
||
# if pmc_no not in pmc_groups:
|
||
# pmc_groups[pmc_no] = []
|
||
# pmc_groups[pmc_no].append(inv)
|
||
#
|
||
# # Process each PMC group separately
|
||
# for pmc_no, pmc_invoices in pmc_groups.items():
|
||
# # Process all invoices for this PMC first
|
||
# for inv in pmc_invoices:
|
||
# invoice_no = inv["Invoice_No"]
|
||
# payments = payments_map.get((pmc_no, invoice_no), [])
|
||
#
|
||
# # Process invoice row with first payment (if exists)
|
||
# if (pmc_no, invoice_no) not in seen_invoices:
|
||
# seen_invoices.add((pmc_no, invoice_no))
|
||
# first_payment = payments[0] if len(payments) > 0 else None
|
||
#
|
||
# # Base invoice data
|
||
# 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"]
|
||
# ]
|
||
#
|
||
# # Add hold amounts for each hold type
|
||
# invoice_holds = hold_data.get(inv["Invoice_Id"], {})
|
||
# for ht_id in hold_type_map.keys():
|
||
# row.append(invoice_holds.get(ht_id, ""))
|
||
#
|
||
# # Add payment information
|
||
# 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)
|
||
#
|
||
# if first_payment:
|
||
# payment_id = f"{pmc_no}-{invoice_no}-{first_payment['Payment_Amount']}-{first_payment.get('UTR', '')}"
|
||
# processed_payments.add(payment_id)
|
||
#
|
||
# # Process GST release if exists (only if we have a matching GST record)
|
||
# if inv["gst_pmc_no"] and (inv["gst_pmc_no"], inv["gst_invoice_no"]) not in seen_gst_notes:
|
||
# seen_gst_notes.add((inv["gst_pmc_no"], inv["gst_invoice_no"]))
|
||
#
|
||
# # Find the payment that matches this GST release
|
||
# gst_payment = None
|
||
# for payment in payments[1:]: # Skip first payment (already used for invoice)
|
||
# if payment['invoice_no'] == inv["gst_invoice_no"]:
|
||
# gst_payment = payment
|
||
# break
|
||
#
|
||
# # GST release row
|
||
# row = [
|
||
# pmc_no, "", "", "GST Release Note", "", inv["gst_invoice_no"],
|
||
# inv["gst_basic_amount"], "", "", "", "", "", "", "", "", "" # Empty GST SD Amount
|
||
# ]
|
||
#
|
||
# # Empty holds for GST release
|
||
# row += ["" for _ in hold_headers]
|
||
#
|
||
# # Add payment information
|
||
# row += [
|
||
# inv["gst_final_amount"],
|
||
# gst_payment["Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["TDS_Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["Total_amount"] if gst_payment else "",
|
||
# gst_payment["UTR"] if gst_payment else ""
|
||
# ]
|
||
#
|
||
# sheet.append(row)
|
||
#
|
||
# if gst_payment:
|
||
# payment_id = f"{pmc_no}-{inv['gst_invoice_no']}-{gst_payment['Payment_Amount']}-{gst_payment.get('UTR', '')}"
|
||
# processed_payments.add(payment_id)
|
||
#
|
||
# # Process remaining payments as extra payments
|
||
# for payment in payments[1:]:
|
||
# payment_id = f"{pmc_no}-{payment['invoice_no']}-{payment['Payment_Amount']}-{payment.get('UTR', '')}"
|
||
# if payment_id not in processed_payments:
|
||
# row = [
|
||
# pmc_no, "", "", "", "", payment['invoice_no'],
|
||
# "", "", "", "", "", "", "", "", "", "" # Empty GST SD Amount
|
||
# ]
|
||
#
|
||
# # Empty holds for extra payments
|
||
# row += ["" for _ in hold_headers]
|
||
#
|
||
# # Add payment information
|
||
# row += [
|
||
# "",
|
||
# payment["Payment_Amount"],
|
||
# payment["TDS_Payment_Amount"],
|
||
# payment["Total_amount"],
|
||
# payment["UTR"]
|
||
# ]
|
||
#
|
||
# sheet.append(row)
|
||
# processed_payments.add(payment_id)
|
||
#
|
||
# # Process extra payments for this PMC (null invoice_no) immediately after the PMC's invoices
|
||
# if pmc_no in extra_payments_map:
|
||
# for payment in extra_payments_map[pmc_no]:
|
||
# payment_id = f"{pmc_no}-null-{payment['Payment_Amount']}-{payment.get('UTR', '')}"
|
||
# if payment_id not in processed_payments:
|
||
# row = [
|
||
# pmc_no, "", "", "", "", "",
|
||
# "", "", "", "", "", "", "", "", "", "" # Empty GST SD Amount
|
||
# ]
|
||
#
|
||
# # Empty holds for null invoice payments
|
||
# row += ["" for _ in hold_headers]
|
||
#
|
||
# # Add payment information
|
||
# row += [
|
||
# "",
|
||
# payment["Payment_Amount"],
|
||
# payment["TDS_Payment_Amount"],
|
||
# payment["Total_amount"],
|
||
# payment["UTR"]
|
||
# ]
|
||
#
|
||
# sheet.append(row)
|
||
# processed_payments.add(payment_id)
|
||
#
|
||
# workbook.save(output_file)
|
||
# workbook.close()
|
||
# finally:
|
||
# cursor.close()
|
||
# connection.close()
|
||
# from openpyxl.styles import Font
|
||
#
|
||
# # Initialize totals
|
||
# total_basic_amount = 0
|
||
# total_tds_amount = 0
|
||
# total_sd_amount = 0
|
||
# total_on_commission = 0
|
||
# total_hold_amount = 0
|
||
# total_final_amount = 0
|
||
# total_total_amount = 0 # Sum of all Total Amounts from payment data
|
||
#
|
||
# # Iterate through rows to calculate totals
|
||
# for row in sheet.iter_rows(min_row=2, max_row=sheet.max_row, values_only=True):
|
||
# try:
|
||
# total_basic_amount += float(row[6] or 0) # Basic_Amount
|
||
# total_tds_amount += float(row[11] or 0) # TDS_Amount
|
||
# total_sd_amount += float(row[12] or 0) # SD_Amount
|
||
# total_on_commission += float(row[13] or 0) # On_Commission
|
||
# total_final_amount += float(row[-5] or 0) # Final_Amount
|
||
# total_total_amount += float(row[-2] or 0) # Total_Amount (from payments)
|
||
#
|
||
# # Sum of hold amounts (dynamically calculated based on hold_headers)
|
||
# hold_start_col = len(base_headers) # First column where hold types start
|
||
# hold_end_col = hold_start_col + len(hold_headers) # Last column where hold types end
|
||
# total_hold_amount += sum(float(row[i] or 0) for i in range(hold_start_col, hold_end_col))
|
||
#
|
||
# except ValueError:
|
||
# continue # Skip if non-numeric values cause errors
|
||
#
|
||
# # Append the totals row at the bottom of the sheet
|
||
# totals_row = [
|
||
# "TOTAL", "", "", "", "", "", # Empty values for non-numeric columns
|
||
# total_basic_amount, "", "", "", "", total_tds_amount, total_sd_amount,
|
||
# total_on_commission, "", "", # Empty GST SD Amount
|
||
# ]
|
||
# if hold_headers:
|
||
# totals_row += [total_hold_amount] + [""] * (len(hold_headers) - 1)
|
||
#
|
||
# # Add empty placeholders for hold types
|
||
# # totals_row += [total_hold_amount] + [""] * (len(hold_headers) - 1)
|
||
#
|
||
# # Add totals for Final Amount and Total Amount
|
||
# totals_row += [
|
||
# total_final_amount, "", "", total_total_amount, "" # UTR column remains empty
|
||
# ]
|
||
#
|
||
# # Append totals row to sheet
|
||
# sheet.append([])
|
||
# sheet.append(totals_row)
|
||
# total_hold_amount=Decimal('0.00')
|
||
# for d in invoices:
|
||
# total_hold_amount = total_hold_amount + d.get('SD_Amount', Decimal('0.00')) + d.get('On_Commission',
|
||
# Decimal(
|
||
# '0.00')) + d.get(
|
||
# 'Hydro_Testing', Decimal('0.00'))
|
||
# #new coded for summary chart added
|
||
# for data in hold_amounts:
|
||
# total_hold_amount = total_hold_amount + data.get('hold_amount', Decimal('0.00'))
|
||
# print("Total Hold Amount after adding the hold amount ", total_hold_amount)
|
||
#
|
||
#
|
||
# from datetime import datetime
|
||
#
|
||
# # Add payment information
|
||
#
|
||
# # Get today's date with weekday
|
||
# today_date = datetime.today().strftime('%A, %Y-%m-%d')
|
||
#
|
||
# # Add headers (optional)
|
||
# sheet.append(["Contractor Name", contInfo["Contractor_Name"]])
|
||
# sheet.append(["Date", today_date])
|
||
# sheet.append(["Description", "Amount"])
|
||
#
|
||
# # Add your values
|
||
# sheet.append(["Advance/Surplus", str( total_final_amount - total_total_amount)])
|
||
# sheet.append(["Total Hold Amount", str(total_hold_amount)])
|
||
# sheet.append(["Amount With TDS", str(total_tds_amount)])
|
||
# #new added code end here for summary chart
|
||
#
|
||
# # Make the totals row bold
|
||
# for cell in sheet[sheet.max_row]:
|
||
# cell.font = Font(bold=True)
|
||
#
|
||
# # Save workbook after modifications
|
||
# workbook.save(output_file)
|
||
# workbook.close()
|
||
#
|
||
# return send_from_directory(output_folder, f"Contractor_Report_{contractor_id}.xlsx", as_attachment=True)
|
||
|
||
from flask import send_from_directory
|
||
import os
|
||
import openpyxl
|
||
from openpyxl.styles import Font, PatternFill
|
||
from decimal import Decimal
|
||
from datetime import datetime
|
||
|
||
from flask import send_from_directory
|
||
import os
|
||
import openpyxl
|
||
from openpyxl.styles import Font, PatternFill
|
||
from decimal import Decimal
|
||
from datetime import datetime
|
||
|
||
# @app.route('/download_report/<int:contractor_id>')
|
||
# def download_report(contractor_id):
|
||
# connection = config.get_db_connection()
|
||
# cursor = connection.cursor(dictionary=True)
|
||
|
||
# output_folder = "static/download"
|
||
# output_file = os.path.join(output_folder, f"Contractor_Report_{contractor_id}.xlsx")
|
||
|
||
# if not os.path.exists(output_folder):
|
||
# os.makedirs(output_folder)
|
||
|
||
# try:
|
||
# # Fetch Contractor Info
|
||
# cursor.callproc('GetContractorInfoId', [contractor_id])
|
||
# for result in cursor.stored_results():
|
||
# contInfo = result.fetchone()
|
||
# if not contInfo:
|
||
# return "No contractor found", 404
|
||
|
||
# # Fetch Hold Types
|
||
# cursor.callproc('GetDistinctHoldTypesByContractor', [contractor_id])
|
||
# 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}
|
||
|
||
# # Fetch Invoices
|
||
# cursor.callproc('GetInvoicesAndGSTReleasesByContractor', [contractor_id])
|
||
# for result in cursor.stored_results():
|
||
# invoices = result.fetchall()
|
||
|
||
# # Fetch Hold Amounts
|
||
# cursor.callproc('GetHoldAmountsByContractors', [contractor_id])
|
||
# for result in cursor.stored_results():
|
||
# hold_amounts = result.fetchall()
|
||
# hold_data = {}
|
||
# for h in hold_amounts:
|
||
# hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
||
|
||
# # Extract PMC numbers
|
||
# pmc_numbers = tuple(set(inv['PMC_No'] for inv in invoices if inv['PMC_No'] is not None))
|
||
|
||
# payments_map = {}
|
||
# extra_payments_map = {}
|
||
# if pmc_numbers:
|
||
# pmc_list_str = ','.join(str(pmc) for pmc in pmc_numbers)
|
||
# cursor.callproc('GetPaymentsByPmcNosWithInvoice', [pmc_list_str])
|
||
# for result in cursor.stored_results():
|
||
# payments = result.fetchall()
|
||
# for pay in payments:
|
||
# key = (pay['pmc_no'], pay['invoice_no'])
|
||
# payments_map.setdefault(key, []).append(pay)
|
||
|
||
# cursor.callproc('GetExtraPaymentsByPmcNos', [pmc_list_str])
|
||
# for result in cursor.stored_results():
|
||
# extra_payments = result.fetchall()
|
||
# for pay in extra_payments:
|
||
# extra_payments_map.setdefault(pay['pmc_no'], []).append(pay)
|
||
|
||
# # Create Excel Workbook
|
||
# workbook = openpyxl.Workbook()
|
||
# sheet = workbook.active
|
||
# sheet.title = "Contractor Report"
|
||
|
||
# # Write Contractor Info
|
||
# sheet.append(["Contractor Name", contInfo["Contractor_Name"]])
|
||
# sheet.append(["State", contInfo["State_Name"]])
|
||
# sheet.append(["District", contInfo["District_Name"]])
|
||
# sheet.append(["Block", contInfo["Block_Name"]])
|
||
# sheet.append(["Mobile No", contInfo["Mobile_No"]])
|
||
# sheet.append(["GST Type", contInfo["GST_Registration_Type"]])
|
||
# sheet.append(["GST No", contInfo["GST_No"]])
|
||
# sheet.append(["PAN No", contInfo["PAN_No"]])
|
||
# sheet.append(["Email", contInfo["Email"]])
|
||
# sheet.append(["Address", contInfo["Address"]])
|
||
# sheet.append([])
|
||
|
||
# # Table Headers
|
||
# 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"]
|
||
# all_headers = base_headers + hold_headers + payment_headers
|
||
|
||
# sheet.append(all_headers)
|
||
|
||
# # Style the 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()
|
||
# seen_gst_notes = set()
|
||
# processed_payments = set()
|
||
# pmc_groups = {}
|
||
# for inv in invoices:
|
||
# pmc_groups.setdefault(inv["PMC_No"], []).append(inv)
|
||
|
||
# for pmc_no, pmc_invoices in pmc_groups.items():
|
||
# for inv in pmc_invoices:
|
||
# invoice_no = inv["Invoice_No"]
|
||
# payments = payments_map.get((pmc_no, invoice_no), [])
|
||
|
||
# if (pmc_no, invoice_no) not in seen_invoices:
|
||
# seen_invoices.add((pmc_no, 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:
|
||
# 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)
|
||
# if first_payment:
|
||
# payment_id = f"{pmc_no}-{invoice_no}-{first_payment['Payment_Amount']}-{first_payment.get('UTR', '')}"
|
||
# processed_payments.add(payment_id)
|
||
|
||
# # GST Notes
|
||
# if inv["gst_pmc_no"] and (inv["gst_pmc_no"], inv["gst_invoice_no"]) not in seen_gst_notes:
|
||
# seen_gst_notes.add((inv["gst_pmc_no"], inv["gst_invoice_no"]))
|
||
# gst_payment = None
|
||
# for payment in payments[1:]:
|
||
# if payment['invoice_no'] == inv["gst_invoice_no"]:
|
||
# gst_payment = payment
|
||
# break
|
||
# row = [pmc_no, "", "", "GST Release Note", "", inv["gst_invoice_no"],
|
||
# inv["gst_basic_amount"], "", "", "", "", "", "", "", "", ""]
|
||
# row += ["" for _ in hold_headers]
|
||
# row += [
|
||
# inv["gst_final_amount"],
|
||
# gst_payment["Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["TDS_Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["Total_amount"] if gst_payment else "",
|
||
# gst_payment["UTR"] if gst_payment else ""
|
||
# ]
|
||
# sheet.append(row)
|
||
# if gst_payment:
|
||
# payment_id = f"{pmc_no}-{inv['gst_invoice_no']}-{gst_payment['Payment_Amount']}-{gst_payment.get('UTR', '')}"
|
||
# processed_payments.add(payment_id)
|
||
|
||
# for payment in payments[1:]:
|
||
# payment_id = f"{pmc_no}-{payment['invoice_no']}-{payment['Payment_Amount']}-{payment.get('UTR', '')}"
|
||
# if payment_id not in processed_payments:
|
||
# row = [pmc_no, "", "", "", "", payment['invoice_no'], "", "", "", "", "", "", "", "", "", ""]
|
||
# row += ["" for _ in hold_headers]
|
||
# row += [
|
||
# "",
|
||
# payment["Payment_Amount"],
|
||
# payment["TDS_Payment_Amount"],
|
||
# payment["Total_amount"],
|
||
# payment["UTR"]
|
||
# ]
|
||
# sheet.append(row)
|
||
# processed_payments.add(payment_id)
|
||
|
||
# # Extra payments (null invoice)
|
||
# for payment in extra_payments_map.get(pmc_no, []):
|
||
# payment_id = f"{pmc_no}-null-{payment['Payment_Amount']}-{payment.get('UTR', '')}"
|
||
# if payment_id not in processed_payments:
|
||
# row = [pmc_no, "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""]
|
||
# row += ["" for _ in hold_headers]
|
||
# row += [
|
||
# "",
|
||
# payment["Payment_Amount"],
|
||
# payment["TDS_Payment_Amount"],
|
||
# payment["Total_amount"],
|
||
# payment["UTR"]
|
||
# ]
|
||
# sheet.append(row)
|
||
# processed_payments.add(payment_id)
|
||
|
||
# # Totals Calculation
|
||
# total_basic_amount = total_tds_amount = total_sd_amount = total_on_commission = 0
|
||
# total_hold_amount = total_final_amount = total_total_amount = 0
|
||
|
||
# for row in sheet.iter_rows(min_row=13, max_row=sheet.max_row, values_only=True):
|
||
# try:
|
||
# total_basic_amount += float(row[6] or 0)
|
||
# total_tds_amount += float(row[11] or 0)
|
||
# total_sd_amount += float(row[12] or 0)
|
||
# total_on_commission += float(row[13] or 0)
|
||
# total_final_amount += float(row[-5] or 0)
|
||
# total_total_amount += float(row[-2] or 0)
|
||
# hold_start_col = len(base_headers)
|
||
# hold_end_col = hold_start_col + len(hold_headers)
|
||
# total_hold_amount += sum(float(row[i] or 0) for i in range(hold_start_col, hold_end_col))
|
||
# except ValueError:
|
||
# continue
|
||
|
||
# # Totals Row
|
||
# sheet.append([])
|
||
# totals_row = [
|
||
# "TOTAL", "", "", "", "", "", total_basic_amount, "", "", "", "", total_tds_amount,
|
||
# total_sd_amount, total_on_commission, "", ""
|
||
# ]
|
||
# if total_hold_amount:
|
||
# totals_row += [total_hold_amount] + [""] * (len(hold_headers) - 1)
|
||
|
||
# totals_row += [total_final_amount, "", "", total_total_amount, ""]
|
||
# sheet.append(totals_row)
|
||
|
||
# for cell in sheet[sheet.max_row]:
|
||
# cell.font = Font(bold=True)
|
||
|
||
# # Summary Section
|
||
# today_date = datetime.today().strftime('%A, %Y-%m-%d')
|
||
# sheet.append([])
|
||
# sheet.append(["Contractor Name", contInfo["Contractor_Name"]])
|
||
# sheet.append(["Date", today_date])
|
||
# sheet.append(["Description", "Amount"])
|
||
# sheet.append(["Advance/Surplus", str(total_final_amount - total_total_amount)])
|
||
# sheet.append(["Total Hold Amount", str(Decimal(total_hold_amount))])
|
||
# sheet.append(["Amount With TDS", str(total_tds_amount)])
|
||
|
||
# # Auto adjust column widths
|
||
# for col in sheet.columns:
|
||
# max_length = 0
|
||
# col_letter = openpyxl.utils.get_column_letter(col[0].column)
|
||
# for cell in col:
|
||
# try:
|
||
# if cell.value:
|
||
# max_length = max(max_length, len(str(cell.value)))
|
||
# except:
|
||
# pass
|
||
# sheet.column_dimensions[col_letter].width = max_length + 2
|
||
|
||
# workbook.save(output_file)
|
||
# workbook.close()
|
||
|
||
# finally:
|
||
# cursor.close()
|
||
# connection.close()
|
||
|
||
# return send_from_directory(output_folder, f"Contractor_Report_{contractor_id}.xlsx", as_attachment=True)
|
||
from flask import send_from_directory
|
||
from decimal import Decimal
|
||
from datetime import datetime
|
||
import os
|
||
import openpyxl
|
||
from openpyxl.styles import Font, PatternFill
|
||
import config
|
||
|
||
|
||
# @app.route('/download_report/<int:contractor_id>')
|
||
# def download_report(contractor_id):
|
||
# connection = config.get_db_connection()
|
||
# cursor = connection.cursor(dictionary=True, buffered=True)
|
||
#
|
||
# output_folder = "static/download"
|
||
# output_file = os.path.join(output_folder, f"Contractor_Report_{contractor_id}.xlsx")
|
||
# os.makedirs(output_folder, exist_ok=True)
|
||
#
|
||
# try:
|
||
# # Contractor Info
|
||
# cursor.execute("""
|
||
# SELECT DISTINCT s.Contractor_Name, st.State_Name, d.District_Name, b.Block_Name,
|
||
# s.Mobile_No, s.GST_Registration_Type, s.GST_No, s.PAN_No, s.Email, s.Address
|
||
# FROM subcontractors s
|
||
# LEFT JOIN assign_subcontractors asg ON s.Contractor_Id = asg.Contractor_Id
|
||
# LEFT JOIN villages v ON asg.Village_Id = v.Village_Id
|
||
# LEFT JOIN blocks b ON v.Block_Id = b.Block_Id
|
||
# LEFT JOIN districts d ON b.District_id = d.District_id
|
||
# LEFT JOIN states st ON d.State_Id = st.State_Id
|
||
# WHERE s.Contractor_Id = %s
|
||
# """, (contractor_id,))
|
||
# contInfo = cursor.fetchone()
|
||
# if not contInfo:
|
||
# return "No contractor found", 404
|
||
#
|
||
# # Hold Types
|
||
# cursor.execute("""
|
||
# SELECT DISTINCT ht.hold_type_id, ht.hold_type
|
||
# FROM invoice_subcontractor_hold_join h
|
||
# JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
# JOIN invoice i ON h.Invoice_Id = i.Invoice_Id
|
||
# WHERE h.Contractor_Id = %s
|
||
# """, (contractor_id,))
|
||
# hold_types = cursor.fetchall()
|
||
# hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types}
|
||
#
|
||
# # Invoices
|
||
# cursor.execute("""
|
||
# SELECT DISTINCT i.PMC_No, v.Village_Name, i.Work_Type, i.Invoice_Details,
|
||
# i.Invoice_Date, i.Invoice_No, i.Basic_Amount, i.Debit_Amount,
|
||
# i.After_Debit_Amount, i.GST_Amount, i.Amount, i.TDS_Amount, i.SD_Amount,
|
||
# i.On_Commission, i.Hydro_Testing, i.GST_SD_Amount,
|
||
# i.Final_Amount, i.Invoice_Id
|
||
# FROM assign_subcontractors asg
|
||
# INNER JOIN villages v ON asg.Village_Id = v.Village_Id
|
||
# INNER JOIN invoice i ON i.Village_Id = v.Village_Id AND i.PMC_No = asg.PMC_No
|
||
# WHERE asg.Contractor_Id = %s
|
||
# ORDER BY i.PMC_No ASC, i.Invoice_No ASC
|
||
# """, (contractor_id,))
|
||
# invoices = cursor.fetchall()
|
||
#
|
||
# # Hold Amounts
|
||
# cursor.execute("""
|
||
# SELECT h.Invoice_Id, h.hold_type_id, h.hold_amount
|
||
# FROM invoice_subcontractor_hold_join h
|
||
# JOIN invoice i ON h.Invoice_Id = i.Invoice_Id
|
||
# WHERE h.Contractor_Id = %s
|
||
# """, (contractor_id,))
|
||
# hold_amounts = cursor.fetchall()
|
||
# hold_data = {}
|
||
# for h in hold_amounts:
|
||
# hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
||
#
|
||
# # GST Release query - Modified to get all GST releases for the contractor
|
||
# cursor.execute("""
|
||
# SELECT gr.pmc_no, gr.invoice_no, gr.basic_amount, gr.final_amount
|
||
# FROM gst_release gr
|
||
# WHERE gr.pmc_no IN (
|
||
# SELECT DISTINCT a.PMC_No
|
||
# FROM assign_subcontractors a
|
||
# WHERE a.Contractor_Id = %s
|
||
# )
|
||
# ORDER BY gr.pmc_no ASC
|
||
# """, (contractor_id,))
|
||
# gst_rel = cursor.fetchall()
|
||
#
|
||
# gst_rel_map = {}
|
||
# for gr in gst_rel:
|
||
# invoice_nos = []
|
||
# if gr['invoice_no']:
|
||
# if ',' in gr['invoice_no']:
|
||
# invoice_nos = [x.strip() for x in gr['invoice_no'].replace(' ', '').split(',')]
|
||
# elif '&' in gr['invoice_no']:
|
||
# invoice_nos = [x.strip() for x in gr['invoice_no'].split('&')]
|
||
# else:
|
||
# invoice_nos = [gr['invoice_no'].strip()]
|
||
#
|
||
# # Map each individual invoice to the GST release
|
||
# for inv_no in invoice_nos:
|
||
# key = (gr['pmc_no'], inv_no)
|
||
# if key not in gst_rel_map:
|
||
# gst_rel_map[key] = {
|
||
# 'basic_amount': gr['basic_amount'],
|
||
# 'final_amount': gr['final_amount'],
|
||
# 'invoice_no': gr['invoice_no'],
|
||
# 'all_invoice_nos': invoice_nos
|
||
# }
|
||
#
|
||
# # Also map the combined invoice number if it's a combined release
|
||
# if len(invoice_nos) > 1:
|
||
# combined_key = (gr['pmc_no'], gr['invoice_no'])
|
||
# gst_rel_map[combined_key] = {
|
||
# 'basic_amount': gr['basic_amount'],
|
||
# 'final_amount': gr['final_amount'],
|
||
# 'invoice_no': gr['invoice_no'],
|
||
# 'all_invoice_nos': invoice_nos
|
||
# }
|
||
#
|
||
# # GST Release Payments - Updated to include Payment_Amount and TDS_Payment_Amount
|
||
# cursor.execute("""
|
||
# SELECT p.pmc_no, p.invoice_no, p.Payment_Amount, p.TDS_Payment_Amount, p.Total_amount, p.utr
|
||
# FROM payment p
|
||
# JOIN gst_release gr ON p.pmc_no = gr.pmc_no AND (
|
||
# p.invoice_no = gr.invoice_no
|
||
# OR (gr.invoice_no LIKE '%,%' AND FIND_IN_SET(p.invoice_no, REPLACE(gr.invoice_no, ' ', '')) > 0)
|
||
# OR (gr.invoice_no LIKE '%&%' AND (
|
||
# p.invoice_no = SUBSTRING_INDEX(gr.invoice_no, '&', 1)
|
||
# OR p.invoice_no = SUBSTRING_INDEX(gr.invoice_no, '&', -1)
|
||
# OR (gr.invoice_no LIKE '%&%&%' AND p.invoice_no = SUBSTRING_INDEX(SUBSTRING_INDEX(gr.invoice_no, '&', 2), '&', -1))
|
||
# ))
|
||
# )
|
||
# WHERE gr.pmc_no IN (
|
||
# SELECT DISTINCT i.PMC_No
|
||
# FROM invoice i
|
||
# JOIN assign_subcontractors a ON i.PMC_No = a.PMC_No AND i.Village_Id = a.Village_Id
|
||
# WHERE a.Contractor_Id = %s
|
||
# )
|
||
# AND p.Total_amount != 0
|
||
# """, (contractor_id,))
|
||
# gst_payments = cursor.fetchall()
|
||
#
|
||
# gst_payment_map = {}
|
||
# for pay in gst_payments:
|
||
# key = (pay['pmc_no'], pay['invoice_no'])
|
||
# gst_payment_map[key] = {
|
||
# 'Payment_Amount': pay['Payment_Amount'],
|
||
# 'TDS_Payment_Amount': pay['TDS_Payment_Amount'],
|
||
# 'Total_amount': pay['Total_amount'],
|
||
# 'utr': pay['utr']
|
||
# }
|
||
# # Also map to the combined invoice number if it exists
|
||
# for gr_key, gr_val in gst_rel_map.items():
|
||
# if pay['pmc_no'] == gr_key[0] and pay['invoice_no'] in gr_val['all_invoice_nos']:
|
||
# combined_key = (pay['pmc_no'], gr_val['invoice_no'])
|
||
# gst_payment_map[combined_key] = {
|
||
# 'Payment_Amount': pay['Payment_Amount'],
|
||
# 'TDS_Payment_Amount': pay['TDS_Payment_Amount'],
|
||
# 'Total_amount': pay['Total_amount'],
|
||
# 'utr': pay['utr']
|
||
# }
|
||
#
|
||
# # Invoice Payments - Updated to include Payment_Amount and TDS_Payment_Amount
|
||
# cursor.execute("""
|
||
# SELECT p.pmc_no, p.invoice_no, p.Payment_Amount, p.TDS_Payment_Amount, p.Total_amount, p.utr
|
||
# FROM payment p
|
||
# INNER JOIN (
|
||
# SELECT DISTINCT i.PMC_No, i.Invoice_No
|
||
# FROM invoice i
|
||
# JOIN assign_subcontractors a ON i.PMC_No = a.PMC_No AND i.Village_Id = a.Village_Id
|
||
# WHERE a.Contractor_Id = %s
|
||
# ) x ON p.pmc_no = x.PMC_No AND p.invoice_no = x.Invoice_No
|
||
# ORDER BY p.pmc_no ASC
|
||
# """, (contractor_id,))
|
||
# payments = cursor.fetchall()
|
||
# payments_map = {}
|
||
# for pay in payments:
|
||
# key = (pay['pmc_no'], pay['invoice_no'])
|
||
# payments_map.setdefault(key, []).append({
|
||
# 'Payment_Amount': pay['Payment_Amount'],
|
||
# 'TDS_Payment_Amount': pay['TDS_Payment_Amount'],
|
||
# 'Total_amount': pay['Total_amount'],
|
||
# 'utr': pay['utr']
|
||
# })
|
||
#
|
||
# # Extra Payments (no invoice_no) - Updated to include Payment_Amount and TDS_Payment_Amount
|
||
# cursor.execute("""
|
||
# SELECT pmc_no, Payment_Amount, TDS_Payment_Amount, Total_amount, utr
|
||
# FROM payment
|
||
# WHERE (invoice_no IS NULL OR invoice_no = '')
|
||
# AND Total_amount != 0
|
||
# AND pmc_no IS NOT NULL
|
||
# """)
|
||
# extra_payments_raw = cursor.fetchall()
|
||
# extra_payments_map = {}
|
||
# for pay in extra_payments_raw:
|
||
# extra_payments_map.setdefault(pay['pmc_no'], []).append({
|
||
# 'Payment_Amount': pay['Payment_Amount'],
|
||
# 'TDS_Payment_Amount': pay['TDS_Payment_Amount'],
|
||
# 'Total_amount': pay['Total_amount'],
|
||
# 'utr': pay['utr']
|
||
# })
|
||
#
|
||
# # Credit Note
|
||
# # Credit Note Fetch
|
||
# cursor.execute("""
|
||
# SELECT PMC_No, Invoice_Details, Basic_Amount, Debit_Amount, After_Debit_Amount,
|
||
# GST_Amount, Amount, Final_Amount, Payment_Amount, Total_Amount, UTR, Invoice_No
|
||
# FROM credit_note
|
||
# WHERE Contractor_Id = %s
|
||
# """, (contractor_id,))
|
||
#
|
||
# credit_notes = cursor.fetchall()
|
||
#
|
||
# # Build map by (PMC_No, Invoice_No)
|
||
# credit_note_map = {}
|
||
# for cn in credit_notes:
|
||
# key = (cn["PMC_No"], cn["Invoice_No"]) # Use correct casing!
|
||
# credit_note_map.setdefault(key, []).append(cn)
|
||
#
|
||
# # Track already appended credit notes
|
||
# appended_credit_keys = set()
|
||
#
|
||
# # Excel Workbook
|
||
# workbook = openpyxl.Workbook()
|
||
# sheet = workbook.active
|
||
# sheet.title = "Contractor Report"
|
||
#
|
||
# # Contractor Info section
|
||
# for field, value in contInfo.items():
|
||
# sheet.append([field.replace("_", " "), value])
|
||
# 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]
|
||
# # Updated payment headers to include Payment Amount and TDS Payment
|
||
# payment_headers = ["Final Amount", "Payment Amount", "TDS Payment", "Total Paid", "UTR"]
|
||
# all_headers = base_headers + hold_headers + payment_headers
|
||
# sheet.append(all_headers)
|
||
# for cell in sheet[sheet.max_row]:
|
||
# cell.font = Font(bold=True)
|
||
# cell.fill = PatternFill(start_color="ADD8E6", end_color="ADD8E6", fill_type="solid")
|
||
#
|
||
# # Track which GST releases we've already processed
|
||
# processed_gst_releases = set()
|
||
#
|
||
# # Data Rows
|
||
# for inv in invoices:
|
||
# pmc_no = inv["PMC_No"]
|
||
# invoice_no = inv["Invoice_No"]
|
||
#
|
||
# 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:
|
||
# row.append(invoice_holds.get(ht_id, ""))
|
||
#
|
||
# payment = payments_map.get((pmc_no, invoice_no), [None])[0]
|
||
# row += [
|
||
# inv["Final_Amount"],
|
||
# payment["Payment_Amount"] if payment else "",
|
||
# payment["TDS_Payment_Amount"] if payment else "",
|
||
# payment["Total_amount"] if payment else "",
|
||
# payment["utr"] if payment and payment["utr"] else ""
|
||
# ]
|
||
# sheet.append(row)
|
||
#
|
||
# # GST Release row - only show after the last invoice in the sequence
|
||
# if (pmc_no, invoice_no) in gst_rel_map:
|
||
# gr = gst_rel_map[(pmc_no, invoice_no)]
|
||
#
|
||
# # Check if this is the last invoice in the sequence
|
||
# if invoice_no == gr['all_invoice_nos'][-1] and gr['invoice_no'] not in processed_gst_releases:
|
||
# processed_gst_releases.add(gr['invoice_no'])
|
||
#
|
||
# # Find matching payment if it exists
|
||
# gst_payment = gst_payment_map.get((pmc_no, gr['invoice_no']), None)
|
||
# if not gst_payment:
|
||
# # Try matching with individual invoice numbers
|
||
# for inv_no in gr['all_invoice_nos']:
|
||
# if (pmc_no, inv_no) in gst_payment_map:
|
||
# gst_payment = gst_payment_map[(pmc_no, inv_no)]
|
||
# break
|
||
#
|
||
# gst_row = [
|
||
# pmc_no, "", "", "GST Release Note", "", gr["invoice_no"],
|
||
# gr["basic_amount"], "", "", "", "", "", "", "", "", ""
|
||
# ]
|
||
# gst_row += ["" for _ in hold_headers]
|
||
# gst_row += [
|
||
# gr["final_amount"],
|
||
# gst_payment["Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["TDS_Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["Total_amount"] if gst_payment else "",
|
||
# gst_payment["utr"] if gst_payment and gst_payment.get("utr") else ""
|
||
# ]
|
||
# sheet.append(gst_row)
|
||
#
|
||
# # Extra Payments (once per pmc_no)
|
||
# if pmc_no in extra_payments_map:
|
||
# for extra in extra_payments_map[pmc_no]:
|
||
# extra_row = [
|
||
# pmc_no, "", "", " ", "", "", "", "", "", "", "", "", "", "", "", ""
|
||
# ]
|
||
# extra_row += ["" for _ in hold_headers]
|
||
# extra_row += [
|
||
# "",
|
||
# extra['Payment_Amount'],
|
||
# extra['TDS_Payment_Amount'],
|
||
# extra['Total_amount'],
|
||
# extra['utr'] if extra['utr'] else ""
|
||
# ]
|
||
# sheet.append(extra_row)
|
||
# del extra_payments_map[pmc_no]
|
||
#
|
||
# # Now add any GST releases that weren't associated with any invoices
|
||
# for gr in gst_rel:
|
||
# if gr['invoice_no'] not in processed_gst_releases:
|
||
# pmc_no = gr['pmc_no']
|
||
# invoice_no = gr['invoice_no']
|
||
#
|
||
# # Find matching payment if it exists
|
||
# gst_payment = gst_payment_map.get((pmc_no, invoice_no), None)
|
||
#
|
||
# gst_row = [
|
||
# pmc_no, "", "", "GST Release Note", "", invoice_no,
|
||
# gr["basic_amount"], "", "", "", "", "", "", "", "", ""
|
||
# ]
|
||
# gst_row += ["" for _ in hold_headers]
|
||
# gst_row += [
|
||
# gr["final_amount"],
|
||
# gst_payment["Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["TDS_Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["Total_amount"] if gst_payment else "",
|
||
# gst_payment["utr"] if gst_payment and gst_payment.get("utr") else ""
|
||
# ]
|
||
# sheet.append(gst_row)
|
||
# processed_gst_releases.add(invoice_no)
|
||
# # Credit Note row(s)
|
||
#
|
||
# # Track already appended credit notes
|
||
# appended_credit_keys = set()
|
||
#
|
||
# # While writing invoices
|
||
# key = (pmc_no, invoice_no)
|
||
# if key in credit_note_map and key not in appended_credit_keys:
|
||
# for cn in credit_note_map[key]:
|
||
# credit_row = [
|
||
# pmc_no, "", "", cn.get("Invoice_Details", "Credit Note"), "", cn.get("Invoice_No", ""),
|
||
# cn.get("Basic_Amount", ""), cn.get("Debit_Amount", ""),
|
||
# cn.get("After_Debit_Amount", ""), cn.get("GST_Amount", ""), cn.get("Amount", ""), "", "",
|
||
# "",
|
||
# "", ""
|
||
# ]
|
||
# credit_row += ["" for _ in hold_headers]
|
||
# credit_row += [
|
||
# cn.get("Final_Amount", ""),
|
||
# cn.get("Total_Amount", ""),
|
||
# cn.get("UTR", "")
|
||
# ]
|
||
# sheet.append(credit_row)
|
||
# appended_credit_keys.add(key)
|
||
#
|
||
# # Totals row (NO UTR totals, UTR blank)
|
||
# total_basic_amount = total_tds_amount = total_sd_amount = total_on_commission = 0
|
||
# total_final_amount = total_total_amount = total_hold_amount = 0
|
||
# for row in sheet.iter_rows(min_row=13, max_row=sheet.max_row, values_only=True):
|
||
# try:
|
||
# desc = row[3]
|
||
# if desc == " ":
|
||
# total_total_amount += float(row[-2] or 0)
|
||
# continue
|
||
#
|
||
# total_basic_amount += float(row[6] or 0)
|
||
# total_tds_amount += float(row[11] or 0)
|
||
# total_sd_amount += float(row[12] or 0)
|
||
# total_on_commission += float(row[13] or 0)
|
||
# total_final_amount += float(row[-5] or 0) # Changed to -5 for Final Amount
|
||
# total_total_amount += float(row[-2] or 0)
|
||
# # sum holds
|
||
# total_hold_amount += sum(
|
||
# float(row[i] or 0) for i in range(len(base_headers), len(base_headers) + len(hold_headers)))
|
||
# except Exception:
|
||
# pass
|
||
#
|
||
# totals_row = [
|
||
# "Total", "", "", "", "", "", total_basic_amount, "", "", "", "", total_tds_amount,
|
||
# total_sd_amount, total_on_commission, "", ""
|
||
# ]
|
||
# totals_row += [total_hold_amount for _ in hold_headers]
|
||
# totals_row += [total_final_amount, "", "", total_total_amount,
|
||
# ""] # UTR blank, Payment Amount and TDS Payment blank
|
||
# sheet.append([])
|
||
# sheet.append(totals_row)
|
||
# for cell in sheet[sheet.max_row]:
|
||
# cell.font = Font(bold=True)
|
||
#
|
||
# # Summary Section
|
||
# today_date = datetime.today().strftime('%A, %Y-%m-%d')
|
||
# sheet.append([])
|
||
# sheet.append(["Contractor Name", contInfo["Contractor_Name"]])
|
||
# sheet.append(["Date", today_date])
|
||
# sheet.append(["Description", "Amount"])
|
||
# sheet.append(["Advance/Surplus", str(total_final_amount - total_total_amount)])
|
||
# sheet.append(["Total Hold Amount", str(Decimal(total_hold_amount))])
|
||
# sheet.append(["Amount With TDS", str(total_tds_amount)])
|
||
#
|
||
# # Auto adjust column widths
|
||
# for col in sheet.columns:
|
||
# max_length = 0
|
||
# col_letter = openpyxl.utils.get_column_letter(col[0].column)
|
||
# for cell in col:
|
||
# try:
|
||
# if cell.value:
|
||
# max_length = max(max_length, len(str(cell.value)))
|
||
# except:
|
||
# pass
|
||
# sheet.column_dimensions[col_letter].width = max_length + 2
|
||
#
|
||
# workbook.save(output_file)
|
||
# workbook.close()
|
||
#
|
||
# finally:
|
||
# cursor.close()
|
||
# connection.close()
|
||
#
|
||
# return send_from_directory(output_folder, f"Contractor_Report_{contractor_id}.xlsx", as_attachment=True)
|
||
@app.route('/download_report/<int:contractor_id>')
|
||
def download_report(contractor_id):
|
||
connection = config.get_db_connection()
|
||
cursor = connection.cursor(dictionary=True, buffered=True)
|
||
|
||
output_folder = "static/download"
|
||
output_file = os.path.join(output_folder, f"Contractor_Report_{contractor_id}.xlsx")
|
||
os.makedirs(output_folder, exist_ok=True)
|
||
|
||
try:
|
||
# Contractor Info
|
||
cursor.execute("""
|
||
SELECT DISTINCT s.Contractor_Name,
|
||
st.State_Name,
|
||
d.District_Name,
|
||
b.Block_Name,
|
||
s.Mobile_No,
|
||
s.GST_Registration_Type,
|
||
s.GST_No,
|
||
s.PAN_No,
|
||
s.Email,
|
||
s.Address
|
||
FROM subcontractors s
|
||
LEFT JOIN assign_subcontractors asg ON s.Contractor_Id = asg.Contractor_Id
|
||
LEFT JOIN villages v ON asg.Village_Id = v.Village_Id
|
||
LEFT JOIN blocks b ON v.Block_Id = b.Block_Id
|
||
LEFT JOIN districts d ON b.District_id = d.District_id
|
||
LEFT JOIN states st ON d.State_Id = st.State_Id
|
||
WHERE s.Contractor_Id = %s
|
||
""", (contractor_id,))
|
||
contInfo = cursor.fetchone()
|
||
if not contInfo:
|
||
return "No contractor found", 404
|
||
|
||
# Hold Types
|
||
cursor.execute("""
|
||
SELECT DISTINCT ht.hold_type_id, ht.hold_type
|
||
FROM invoice_subcontractor_hold_join h
|
||
JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
JOIN invoice i ON h.Invoice_Id = i.Invoice_Id
|
||
WHERE h.Contractor_Id = %s
|
||
""", (contractor_id,))
|
||
hold_types = cursor.fetchall()
|
||
hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types}
|
||
|
||
# Invoices
|
||
cursor.execute("""
|
||
SELECT DISTINCT i.PMC_No,
|
||
v.Village_Name,
|
||
i.Work_Type,
|
||
i.Invoice_Details,
|
||
i.Invoice_Date,
|
||
i.Invoice_No,
|
||
i.Basic_Amount,
|
||
i.Debit_Amount,
|
||
i.After_Debit_Amount,
|
||
i.GST_Amount,
|
||
i.Amount,
|
||
i.TDS_Amount,
|
||
i.SD_Amount,
|
||
i.On_Commission,
|
||
i.Hydro_Testing,
|
||
i.GST_SD_Amount,
|
||
i.Final_Amount,
|
||
i.Invoice_Id
|
||
FROM assign_subcontractors asg
|
||
INNER JOIN villages v ON asg.Village_Id = v.Village_Id
|
||
INNER JOIN invoice i ON i.Village_Id = v.Village_Id AND i.PMC_No = asg.PMC_No
|
||
WHERE asg.Contractor_Id = %s
|
||
ORDER BY i.PMC_No ASC, i.Invoice_No ASC
|
||
""", (contractor_id,))
|
||
invoices = cursor.fetchall()
|
||
|
||
# Hold Amounts
|
||
cursor.execute("""
|
||
SELECT h.Invoice_Id, h.hold_type_id, h.hold_amount
|
||
FROM invoice_subcontractor_hold_join h
|
||
JOIN invoice i ON h.Invoice_Id = i.Invoice_Id
|
||
WHERE h.Contractor_Id = %s
|
||
""", (contractor_id,))
|
||
hold_amounts = cursor.fetchall()
|
||
hold_data = {}
|
||
for h in hold_amounts:
|
||
hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
||
|
||
# GST Release query - Modified to get all GST releases for the contractor
|
||
cursor.execute("""
|
||
SELECT gr.pmc_no, gr.invoice_no, gr.basic_amount, gr.final_amount
|
||
FROM gst_release gr
|
||
WHERE gr.pmc_no IN (SELECT DISTINCT a.PMC_No
|
||
FROM assign_subcontractors a
|
||
WHERE a.Contractor_Id = %s)
|
||
ORDER BY gr.pmc_no ASC
|
||
""", (contractor_id,))
|
||
gst_rel = cursor.fetchall()
|
||
|
||
gst_rel_map = {}
|
||
for gr in gst_rel:
|
||
invoice_nos = []
|
||
if gr['invoice_no']:
|
||
if ',' in gr['invoice_no']:
|
||
invoice_nos = [x.strip() for x in gr['invoice_no'].replace(' ', '').split(',')]
|
||
elif '&' in gr['invoice_no']:
|
||
invoice_nos = [x.strip() for x in gr['invoice_no'].split('&')]
|
||
else:
|
||
invoice_nos = [gr['invoice_no'].strip()]
|
||
|
||
# Map each individual invoice to the GST release
|
||
for inv_no in invoice_nos:
|
||
key = (gr['pmc_no'], inv_no)
|
||
if key not in gst_rel_map:
|
||
gst_rel_map[key] = {
|
||
'basic_amount': gr['basic_amount'],
|
||
'final_amount': gr['final_amount'],
|
||
'invoice_no': gr['invoice_no'],
|
||
'all_invoice_nos': invoice_nos
|
||
}
|
||
|
||
# Also map the combined invoice number if it's a combined release
|
||
if len(invoice_nos) > 1:
|
||
combined_key = (gr['pmc_no'], gr['invoice_no'])
|
||
gst_rel_map[combined_key] = {
|
||
'basic_amount': gr['basic_amount'],
|
||
'final_amount': gr['final_amount'],
|
||
'invoice_no': gr['invoice_no'],
|
||
'all_invoice_nos': invoice_nos
|
||
}
|
||
|
||
# GST Release Payments - Updated to include Payment_Amount and TDS_Payment_Amount
|
||
cursor.execute("""
|
||
SELECT p.pmc_no, p.invoice_no, p.Payment_Amount, p.TDS_Payment_Amount, p.Total_amount, p.utr
|
||
FROM payment p
|
||
JOIN gst_release gr ON p.pmc_no = gr.pmc_no AND (
|
||
p.invoice_no = gr.invoice_no
|
||
OR
|
||
(gr.invoice_no LIKE '%,%' AND FIND_IN_SET(p.invoice_no, REPLACE(gr.invoice_no, ' ', '')) > 0)
|
||
OR (gr.invoice_no LIKE '%&%' AND (
|
||
p.invoice_no = SUBSTRING_INDEX(gr.invoice_no, '&', 1)
|
||
OR p.invoice_no = SUBSTRING_INDEX(gr.invoice_no, '&', -1)
|
||
OR (gr.invoice_no LIKE '%&%&%' AND
|
||
p.invoice_no = SUBSTRING_INDEX(SUBSTRING_INDEX(gr.invoice_no, '&', 2), '&', -1))
|
||
))
|
||
)
|
||
WHERE gr.pmc_no IN (SELECT DISTINCT i.PMC_No
|
||
FROM invoice i
|
||
JOIN assign_subcontractors a
|
||
ON i.PMC_No = a.PMC_No AND i.Village_Id = a.Village_Id
|
||
WHERE a.Contractor_Id = %s)
|
||
AND p.Total_amount != 0
|
||
""", (contractor_id,))
|
||
gst_payments = cursor.fetchall()
|
||
|
||
gst_payment_map = {}
|
||
for pay in gst_payments:
|
||
key = (pay['pmc_no'], pay['invoice_no'])
|
||
gst_payment_map[key] = {
|
||
'Payment_Amount': pay['Payment_Amount'],
|
||
'TDS_Payment_Amount': pay['TDS_Payment_Amount'],
|
||
'Total_amount': pay['Total_amount'],
|
||
'utr': pay['utr']
|
||
}
|
||
# Also map to the combined invoice number if it exists
|
||
for gr_key, gr_val in gst_rel_map.items():
|
||
if pay['pmc_no'] == gr_key[0] and pay['invoice_no'] in gr_val['all_invoice_nos']:
|
||
combined_key = (pay['pmc_no'], gr_val['invoice_no'])
|
||
gst_payment_map[combined_key] = {
|
||
'Payment_Amount': pay['Payment_Amount'],
|
||
'TDS_Payment_Amount': pay['TDS_Payment_Amount'],
|
||
'Total_amount': pay['Total_amount'],
|
||
'utr': pay['utr']
|
||
}
|
||
|
||
# Invoice Payments - Updated to include Payment_Amount and TDS_Payment_Amount
|
||
cursor.execute("""
|
||
SELECT p.pmc_no, p.invoice_no, p.Payment_Amount, p.TDS_Payment_Amount, p.Total_amount, p.utr
|
||
FROM payment p
|
||
INNER JOIN (SELECT DISTINCT i.PMC_No, i.Invoice_No
|
||
FROM invoice i
|
||
JOIN assign_subcontractors a
|
||
ON i.PMC_No = a.PMC_No AND i.Village_Id = a.Village_Id
|
||
WHERE a.Contractor_Id = %s) x
|
||
ON p.pmc_no = x.PMC_No AND p.invoice_no = x.Invoice_No
|
||
ORDER BY p.pmc_no ASC
|
||
""", (contractor_id,))
|
||
payments = cursor.fetchall()
|
||
payments_map = {}
|
||
for pay in payments:
|
||
key = (pay['pmc_no'], pay['invoice_no'])
|
||
payments_map.setdefault(key, []).append({
|
||
'Payment_Amount': pay['Payment_Amount'],
|
||
'TDS_Payment_Amount': pay['TDS_Payment_Amount'],
|
||
'Total_amount': pay['Total_amount'],
|
||
'utr': pay['utr']
|
||
})
|
||
# Fetch hold_release data
|
||
cursor.execute("""
|
||
SELECT *
|
||
FROM hold_release
|
||
WHERE Contractor_Id = %s
|
||
""", (contractor_id,))
|
||
hold_releases = cursor.fetchall()
|
||
hold_release_map = {}
|
||
for hr in hold_releases:
|
||
invoice_nos = [i.strip() for i in str(hr['Invoice_No']).split('&')]
|
||
for inv_no in invoice_nos:
|
||
key = (hr['PMC_No'], inv_no)
|
||
hold_release_map.setdefault(key, []).append(hr)
|
||
# Credit Note
|
||
# Credit Note Fetch
|
||
cursor.execute("""
|
||
SELECT PMC_No,
|
||
Invoice_Details,
|
||
Basic_Amount,
|
||
Debit_Amount,
|
||
After_Debit_Amount,
|
||
GST_Amount,
|
||
Amount,
|
||
Final_Amount,
|
||
Payment_Amount,
|
||
Total_Amount,
|
||
UTR,
|
||
Invoice_No
|
||
FROM credit_note
|
||
WHERE Contractor_Id = %s
|
||
""", (contractor_id,))
|
||
|
||
credit_notes = cursor.fetchall()
|
||
|
||
# Build map by (PMC_No, Invoice_No)
|
||
credit_note_map = {}
|
||
for cn in credit_notes:
|
||
key = (cn["PMC_No"], cn["Invoice_No"]) # Use correct casing!
|
||
credit_note_map.setdefault(key, []).append(cn)
|
||
print("Credit_note_map:",credit_note_map)
|
||
# Track already appended credit notes
|
||
appended_credit_keys = set()
|
||
#print("appended_credit_keys",appended_credit_keys)
|
||
|
||
|
||
# Extra Payments (no invoice_no) - Updated to include Payment_Amount and TDS_Payment_Amount
|
||
cursor.execute("""
|
||
SELECT pmc_no, Payment_Amount, TDS_Payment_Amount, Total_amount, utr
|
||
FROM payment
|
||
WHERE (invoice_no IS NULL OR invoice_no = '')
|
||
AND Total_amount != 0
|
||
AND pmc_no IS NOT NULL
|
||
""")
|
||
extra_payments_raw = cursor.fetchall()
|
||
extra_payments_map = {}
|
||
for pay in extra_payments_raw:
|
||
extra_payments_map.setdefault(pay['pmc_no'], []).append({
|
||
'Payment_Amount': pay['Payment_Amount'],
|
||
'TDS_Payment_Amount': pay['TDS_Payment_Amount'],
|
||
'Total_amount': pay['Total_amount'],
|
||
'utr': pay['utr']
|
||
})
|
||
|
||
# Excel Workbook
|
||
workbook = openpyxl.Workbook()
|
||
sheet = workbook.active
|
||
sheet.title = "Contractor Report"
|
||
|
||
# Contractor Info section
|
||
for field, value in contInfo.items():
|
||
sheet.append([field.replace("_", " "), value])
|
||
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]
|
||
# Updated payment headers to include Payment Amount and TDS Payment
|
||
payment_headers = ["Final Amount", "Payment Amount", "TDS Payment", "Total Paid", "UTR"]
|
||
all_headers = base_headers + hold_headers + payment_headers
|
||
sheet.append(all_headers)
|
||
for cell in sheet[sheet.max_row]:
|
||
cell.font = Font(bold=True)
|
||
cell.fill = PatternFill(start_color="ADD8E6", end_color="ADD8E6", fill_type="solid")
|
||
|
||
# Track which GST releases we've already processed
|
||
processed_gst_releases = set()
|
||
|
||
# Data Rows
|
||
for inv in invoices:
|
||
pmc_no = inv["PMC_No"]
|
||
invoice_no = inv["Invoice_No"]
|
||
|
||
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:
|
||
row.append(invoice_holds.get(ht_id, ""))
|
||
|
||
payment = payments_map.get((pmc_no, invoice_no), [None])[0]
|
||
row += [
|
||
inv["Final_Amount"],
|
||
payment["Payment_Amount"] if payment else "",
|
||
payment["TDS_Payment_Amount"] if payment else "",
|
||
payment["Total_amount"] if payment else "",
|
||
payment["utr"] if payment and payment["utr"] else ""
|
||
]
|
||
sheet.append(row)
|
||
|
||
# GST Release row - only show after the last invoice in the sequence
|
||
if (pmc_no, invoice_no) in gst_rel_map:
|
||
gr = gst_rel_map[(pmc_no, invoice_no)]
|
||
|
||
# Check if this is the last invoice in the sequence
|
||
if invoice_no == gr['all_invoice_nos'][-1] and gr['invoice_no'] not in processed_gst_releases:
|
||
processed_gst_releases.add(gr['invoice_no'])
|
||
|
||
# Find matching payment if it exists
|
||
gst_payment = gst_payment_map.get((pmc_no, gr['invoice_no']), None)
|
||
if not gst_payment:
|
||
# Try matching with individual invoice numbers
|
||
for inv_no in gr['all_invoice_nos']:
|
||
if (pmc_no, inv_no) in gst_payment_map:
|
||
gst_payment = gst_payment_map[(pmc_no, inv_no)]
|
||
break
|
||
|
||
gst_row = [
|
||
pmc_no, "", "", "GST Release Note", "", gr["invoice_no"],
|
||
gr["basic_amount"], "", "", "", "", "", "", "", "", ""
|
||
]
|
||
gst_row += ["" for _ in hold_headers]
|
||
gst_row += [
|
||
gr["final_amount"],
|
||
gst_payment["Payment_Amount"] if gst_payment else "",
|
||
gst_payment["TDS_Payment_Amount"] if gst_payment else "",
|
||
gst_payment["Total_amount"] if gst_payment else "",
|
||
gst_payment["utr"] if gst_payment and gst_payment.get("utr") else ""
|
||
]
|
||
sheet.append(gst_row)
|
||
# Hold Release row(s)
|
||
if (pmc_no, invoice_no) in hold_release_map:
|
||
for hr in hold_release_map[(pmc_no, invoice_no)]:
|
||
hr_row = [
|
||
pmc_no, "", "", hr["Invoice_Details"], "", hr["Invoice_No"],
|
||
hr.get("Basic_Amount", ""), "", "", "", "", "", "", "", "", "","",""
|
||
]
|
||
hr_row += ["" for _ in hold_headers]
|
||
hr_row += [
|
||
hr.get("Final_Amount", ""),
|
||
hr.get("Total_Amount", ""),
|
||
hr.get("UTR", "")
|
||
]
|
||
sheet.append(hr_row)
|
||
# Extra Payments (once per pmc_no)
|
||
if pmc_no in extra_payments_map:
|
||
for extra in extra_payments_map[pmc_no]:
|
||
extra_row = [
|
||
pmc_no, "", "", " ", "", "", "", "", "", "", "", "", "", "", "", ""
|
||
]
|
||
extra_row += ["" for _ in hold_headers]
|
||
extra_row += [
|
||
"",
|
||
extra['Payment_Amount'],
|
||
extra['TDS_Payment_Amount'],
|
||
extra['Total_amount'],
|
||
extra['utr'] if extra['utr'] else ""
|
||
]
|
||
sheet.append(extra_row)
|
||
del extra_payments_map[pmc_no]
|
||
|
||
# Now add any GST releases that weren't associated with any invoices
|
||
for gr in gst_rel:
|
||
if gr['invoice_no'] not in processed_gst_releases:
|
||
pmc_no = gr['pmc_no']
|
||
invoice_no = gr['invoice_no']
|
||
|
||
# Find matching payment if it exists
|
||
gst_payment = gst_payment_map.get((pmc_no, invoice_no), None)
|
||
|
||
gst_row = [
|
||
pmc_no, "", "", "GST Release Note", "", invoice_no,
|
||
gr["basic_amount"], "", "", "", "", "", "", "", "", ""
|
||
]
|
||
gst_row += ["" for _ in hold_headers]
|
||
gst_row += [
|
||
gr["final_amount"],
|
||
gst_payment["Payment_Amount"] if gst_payment else "",
|
||
gst_payment["TDS_Payment_Amount"] if gst_payment else "",
|
||
gst_payment["Total_amount"] if gst_payment else "",
|
||
gst_payment["utr"] if gst_payment and gst_payment.get("utr") else ""
|
||
]
|
||
sheet.append(gst_row)
|
||
processed_gst_releases.add(invoice_no)
|
||
# Credit Note row(s)
|
||
|
||
# # Track already appended credit notes
|
||
appended_credit_keys = set()
|
||
|
||
sheet.append(row)
|
||
|
||
# ➕ Add this block right here:
|
||
key = (pmc_no, invoice_no)
|
||
if key in credit_note_map and key not in appended_credit_keys:
|
||
for cn in credit_note_map[key]:
|
||
credit_row = [
|
||
pmc_no, "", "", cn.get("Invoice_Details", "Credit Note"), "", cn.get("Invoice_No", ""),
|
||
cn.get("Basic_Amount", ""), cn.get("Debit_Amount", ""),
|
||
cn.get("After_Debit_Amount", ""), cn.get("GST_Amount", ""), cn.get("Amount", ""), "", "", "",
|
||
"", ""
|
||
]
|
||
credit_row += ["" for _ in hold_headers]
|
||
credit_row += [
|
||
cn.get("Final_Amount", ""), "", "", cn.get("Total_Amount", ""),
|
||
cn.get("UTR", "")
|
||
]
|
||
sheet.append(credit_row)
|
||
appended_credit_keys.add(key)
|
||
|
||
|
||
|
||
|
||
# Totals row (NO UTR totals, UTR blank)
|
||
total_basic_amount = total_tds_amount = total_sd_amount = total_on_commission = 0
|
||
total_final_amount = total_total_amount = total_hold_amount = 0
|
||
for row in sheet.iter_rows(min_row=13, max_row=sheet.max_row, values_only=True):
|
||
try:
|
||
desc = row[3]
|
||
if desc == " ":
|
||
total_total_amount += float(row[-2] or 0)
|
||
continue
|
||
|
||
total_basic_amount += float(row[6] or 0)
|
||
total_tds_amount += float(row[11] or 0)
|
||
total_sd_amount += float(row[12] or 0)
|
||
total_on_commission += float(row[13] or 0)
|
||
total_final_amount += float(row[-5] or 0) # Changed to -5 for Final Amount
|
||
total_total_amount += float(row[-2] or 0)
|
||
# sum holds
|
||
total_hold_amount += sum(
|
||
float(row[i] or 0) for i in range(len(base_headers), len(base_headers) + len(hold_headers)))
|
||
except Exception:
|
||
pass
|
||
|
||
totals_row = [
|
||
"Total", "", "", "", "", "", total_basic_amount, "", "", "", "", total_tds_amount,
|
||
total_sd_amount, total_on_commission, "", ""
|
||
]
|
||
totals_row += [total_hold_amount for _ in hold_headers]
|
||
totals_row += [total_final_amount, "", "", total_total_amount,
|
||
""] # UTR blank, Payment Amount and TDS Payment blank
|
||
sheet.append([])
|
||
sheet.append(totals_row)
|
||
for cell in sheet[sheet.max_row]:
|
||
cell.font = Font(bold=True)
|
||
|
||
# Summary Section
|
||
today_date = datetime.today().strftime('%A, %Y-%m-%d')
|
||
sheet.append([])
|
||
sheet.append(["Contractor Name", contInfo["Contractor_Name"]])
|
||
sheet.append(["Date", today_date])
|
||
sheet.append(["Description", "Amount"])
|
||
sheet.append(["Advance/Surplus", str(total_final_amount - total_total_amount)])
|
||
sheet.append(["Total Hold Amount", str(Decimal(total_hold_amount))])
|
||
sheet.append(["Amount With TDS", str(total_tds_amount)])
|
||
|
||
# Auto adjust column widths
|
||
for col in sheet.columns:
|
||
max_length = 0
|
||
col_letter = openpyxl.utils.get_column_letter(col[0].column)
|
||
for cell in col:
|
||
try:
|
||
if cell.value:
|
||
max_length = max(max_length, len(str(cell.value)))
|
||
except:
|
||
pass
|
||
sheet.column_dimensions[col_letter].width = max_length + 2
|
||
|
||
workbook.save(output_file)
|
||
workbook.close()
|
||
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return send_from_directory(output_folder, f"Contractor_Report_{contractor_id}.xlsx", as_attachment=True)
|
||
# @app.route('/download_report/<int:contractor_id>')
|
||
# def download_report(contractor_id):
|
||
# connection = config.get_db_connection()
|
||
# cursor = connection.cursor(dictionary=True, buffered=True)
|
||
#
|
||
# output_folder = "static/download"
|
||
# output_file = os.path.join(output_folder, f"Contractor_Report_{contractor_id}.xlsx")
|
||
# os.makedirs(output_folder, exist_ok=True)
|
||
#
|
||
# try:
|
||
# # Contractor Info
|
||
# cursor.execute("""
|
||
# SELECT DISTINCT s.Contractor_Name, st.State_Name, d.District_Name, b.Block_Name,
|
||
# s.Mobile_No, s.GST_Registration_Type, s.GST_No, s.PAN_No, s.Email, s.Address
|
||
# FROM subcontractors s
|
||
# LEFT JOIN assign_subcontractors asg ON s.Contractor_Id = asg.Contractor_Id
|
||
# LEFT JOIN villages v ON asg.Village_Id = v.Village_Id
|
||
# LEFT JOIN blocks b ON v.Block_Id = b.Block_Id
|
||
# LEFT JOIN districts d ON b.District_id = d.District_id
|
||
# LEFT JOIN states st ON d.State_Id = st.State_Id
|
||
# WHERE s.Contractor_Id = %s
|
||
# """, (contractor_id,))
|
||
# contInfo = cursor.fetchone()
|
||
# if not contInfo:
|
||
# return "No contractor found", 404
|
||
#
|
||
# # Hold Types
|
||
# cursor.execute("""
|
||
# SELECT DISTINCT ht.hold_type_id, ht.hold_type
|
||
# FROM invoice_subcontractor_hold_join h
|
||
# JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
# JOIN invoice i ON h.Invoice_Id = i.Invoice_Id
|
||
# WHERE h.Contractor_Id = %s
|
||
# """, (contractor_id,))
|
||
# hold_types = cursor.fetchall()
|
||
# hold_type_map = {ht['hold_type_id']: ht['hold_type'] for ht in hold_types}
|
||
#
|
||
# # Invoices
|
||
# cursor.execute("""
|
||
# SELECT DISTINCT i.PMC_No, v.Village_Name, i.Work_Type, i.Invoice_Details,
|
||
# i.Invoice_Date, i.Invoice_No, i.Basic_Amount, i.Debit_Amount,
|
||
# i.After_Debit_Amount, i.GST_Amount, i.Amount, i.TDS_Amount, i.SD_Amount,
|
||
# i.On_Commission, i.Hydro_Testing, i.GST_SD_Amount,
|
||
# i.Final_Amount, i.Invoice_Id
|
||
# FROM assign_subcontractors asg
|
||
# INNER JOIN villages v ON asg.Village_Id = v.Village_Id
|
||
# INNER JOIN invoice i ON i.Village_Id = v.Village_Id AND i.PMC_No = asg.PMC_No
|
||
# WHERE asg.Contractor_Id = %s
|
||
# ORDER BY i.PMC_No ASC
|
||
# """, (contractor_id,))
|
||
# invoices = cursor.fetchall()
|
||
#
|
||
# # Hold Amounts
|
||
# cursor.execute("""
|
||
# SELECT h.Invoice_Id, h.hold_type_id, h.hold_amount
|
||
# FROM invoice_subcontractor_hold_join h
|
||
# JOIN invoice i ON h.Invoice_Id = i.Invoice_Id
|
||
# WHERE h.Contractor_Id = %s
|
||
# """, (contractor_id,))
|
||
# hold_amounts = cursor.fetchall()
|
||
# hold_data = {}
|
||
# for h in hold_amounts:
|
||
# hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
||
#
|
||
# # GST Release
|
||
# cursor.execute("""
|
||
# SELECT gr.pmc_no, gr.invoice_no, gr.basic_amount, gr.final_amount
|
||
# FROM gst_release gr
|
||
# INNER JOIN (
|
||
# SELECT DISTINCT i.PMC_No, i.Invoice_No
|
||
# FROM invoice i
|
||
# JOIN assign_subcontractors a ON i.PMC_No = a.PMC_No AND i.Village_Id = a.Village_Id
|
||
# WHERE a.Contractor_Id = %s
|
||
# ) x ON gr.pmc_no = x.PMC_No AND gr.invoice_no = x.Invoice_No
|
||
# ORDER BY gr.pmc_no ASC
|
||
# """, (contractor_id,))
|
||
# gst_rel = cursor.fetchall()
|
||
# gst_rel_map = {(gr['pmc_no'], gr['invoice_no']): gr for gr in gst_rel}
|
||
# #
|
||
#
|
||
#
|
||
#
|
||
#
|
||
#
|
||
# #Credit Note
|
||
# # Credit Note Fetch
|
||
# cursor.execute("""
|
||
# SELECT PMC_No, Invoice_Details, Basic_Amount, Debit_Amount, After_Debit_Amount,
|
||
# GST_Amount, Amount, Final_Amount, Payment_Amount, Total_Amount, UTR, Invoice_No
|
||
# FROM credit_note
|
||
# WHERE Contractor_Id = %s
|
||
# """, (contractor_id,))
|
||
#
|
||
# credit_notes = cursor.fetchall()
|
||
#
|
||
# # Build map by (PMC_No, Invoice_No)
|
||
# credit_note_map = {}
|
||
# for cn in credit_notes:
|
||
# key = (cn["PMC_No"], cn["Invoice_No"]) # Use correct casing!
|
||
# credit_note_map.setdefault(key, []).append(cn)
|
||
#
|
||
# # Track already appended credit notes
|
||
# appended_credit_keys = set()
|
||
#
|
||
#
|
||
#
|
||
#
|
||
#
|
||
#
|
||
# # Invoice Payments
|
||
# cursor.execute("""
|
||
# SELECT p.pmc_no, p.invoice_no, p.Total_amount, p.utr
|
||
# FROM payment p
|
||
# INNER JOIN (
|
||
# SELECT DISTINCT i.PMC_No, i.Invoice_No
|
||
# FROM invoice i
|
||
# JOIN assign_subcontractors a ON i.PMC_No = a.PMC_No AND i.Village_Id = a.Village_Id
|
||
# WHERE a.Contractor_Id = %s
|
||
# ) x ON p.pmc_no = x.PMC_No AND p.invoice_no = x.Invoice_No
|
||
# ORDER BY p.pmc_no ASC
|
||
# """, (contractor_id,))
|
||
# payments = cursor.fetchall()
|
||
# payments_map = {}
|
||
# for pay in payments:
|
||
# key = (pay['pmc_no'], pay['invoice_no'])
|
||
# payments_map.setdefault(key, []).append(pay)
|
||
#
|
||
# #Credit Note Fetch-----------------------------------------------------------------------------
|
||
#
|
||
#
|
||
# # GST Release Payments
|
||
# cursor.execute("""
|
||
# SELECT p.pmc_no, p.invoice_no, p.Total_amount, p.utr
|
||
# FROM payment p
|
||
# INNER JOIN gst_release gr ON p.pmc_no = gr.pmc_no AND p.invoice_no = gr.invoice_no
|
||
# WHERE gr.invoice_no IS NOT NULL AND gr.pmc_no IS NOT NULL
|
||
# AND p.Total_amount != 0
|
||
# """)
|
||
# gst_payments = cursor.fetchall()
|
||
# gst_payment_map = {}
|
||
# for pay in gst_payments:
|
||
# key = (pay['pmc_no'], pay['invoice_no'])
|
||
# gst_payment_map[key] = pay
|
||
#
|
||
# # Extra Payments (no invoice_no)
|
||
# cursor.execute("""
|
||
# SELECT pmc_no, Total_amount, utr
|
||
# FROM payment
|
||
# WHERE (invoice_no IS NULL OR invoice_no = '')
|
||
# AND Total_amount != 0
|
||
# AND pmc_no IS NOT NULL
|
||
# """)
|
||
# extra_payments_raw = cursor.fetchall()
|
||
# extra_payments_map = {}
|
||
# for pay in extra_payments_raw:
|
||
# extra_payments_map.setdefault(pay['pmc_no'], []).append(pay)
|
||
#
|
||
# # Excel Workbook
|
||
# workbook = openpyxl.Workbook()
|
||
# sheet = workbook.active
|
||
# sheet.title = "Contractor Report"
|
||
#
|
||
# # Contractor Info section
|
||
# for field, value in contInfo.items():
|
||
# sheet.append([field.replace("_", " "), value])
|
||
# 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", "Total Paid", "UTR"]
|
||
# all_headers = base_headers + hold_headers + payment_headers
|
||
# sheet.append(all_headers)
|
||
# for cell in sheet[sheet.max_row]:
|
||
# cell.font = Font(bold=True)
|
||
# cell.fill = PatternFill(start_color="ADD8E6", end_color="ADD8E6", fill_type="solid")
|
||
#
|
||
# # Data Rows
|
||
# for inv in invoices:
|
||
# pmc_no = inv["PMC_No"]
|
||
# invoice_no = inv["Invoice_No"]
|
||
#
|
||
# 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:
|
||
# row.append(invoice_holds.get(ht_id, ""))
|
||
#
|
||
# payment = payments_map.get((pmc_no, invoice_no), [None])[0]
|
||
# row += [
|
||
# inv["Final_Amount"],
|
||
# payment["Total_amount"] if payment else "",
|
||
# payment["utr"] if payment and payment["utr"] else "" # UTR only display, no total
|
||
# ]
|
||
# sheet.append(row)
|
||
#
|
||
# # GST Release row
|
||
# if (pmc_no, invoice_no) in gst_rel_map:
|
||
# gr = gst_rel_map[(pmc_no, invoice_no)]
|
||
# gst_payment = gst_payment_map.get((pmc_no, invoice_no))
|
||
#
|
||
# gst_row = [
|
||
# pmc_no, "", "", "GST Release Note", "", gr["invoice_no"],
|
||
# gr["basic_amount"], "", "", "", "", "", "", "", "", ""
|
||
# ]
|
||
# gst_row += ["" for _ in hold_headers]
|
||
# gst_row += [
|
||
# gr["final_amount"],
|
||
# gst_payment["Total_amount"] if gst_payment else "",
|
||
# gst_payment["utr"] if gst_payment and gst_payment["utr"] else ""
|
||
# ]
|
||
# sheet.append(gst_row)
|
||
# # Credit Note row(s)
|
||
#
|
||
# # Track already appended credit notes
|
||
# appended_credit_keys = set()
|
||
#
|
||
# # While writing invoices
|
||
# key = (pmc_no, invoice_no)
|
||
# if key in credit_note_map and key not in appended_credit_keys:
|
||
# for cn in credit_note_map[key]:
|
||
# credit_row = [
|
||
# pmc_no, "", "", cn.get("Invoice_Details", "Credit Note"), "", cn.get("Invoice_No",""),
|
||
# cn.get("Basic_Amount", ""), cn.get("Debit_Amount", ""),
|
||
# cn.get("After_Debit_Amount", ""), cn.get("GST_Amount", ""), cn.get("Amount", ""), "", "", "",
|
||
# "", ""
|
||
# ]
|
||
# credit_row += ["" for _ in hold_headers]
|
||
# credit_row += [
|
||
# cn.get("Final_Amount", ""),
|
||
# cn.get("Total_Amount", ""),
|
||
# cn.get("UTR", "")
|
||
# ]
|
||
# sheet.append(credit_row)
|
||
# appended_credit_keys.add(key)
|
||
#
|
||
#
|
||
# # Extra Payments (once per pmc_no)
|
||
# if pmc_no in extra_payments_map:
|
||
# for extra in extra_payments_map[pmc_no]:
|
||
# extra_row = [
|
||
# pmc_no, "", "", " ", "", "", "", "", "", "", "", "", "", "", "", ""
|
||
# ]
|
||
# extra_row += ["" for _ in hold_headers]
|
||
# extra_row += ["", extra['Total_amount'], extra['utr'] if extra['utr'] else ""]
|
||
# sheet.append(extra_row)
|
||
# del extra_payments_map[pmc_no]
|
||
#
|
||
# # Totals row (NO UTR totals, UTR blank)
|
||
# total_basic_amount = total_tds_amount = total_sd_amount = total_on_commission = 0
|
||
# total_final_amount = total_total_amount = total_hold_amount = 0
|
||
# for row in sheet.iter_rows(min_row=13, max_row=sheet.max_row, values_only=True):
|
||
# try:
|
||
# desc = row[3]
|
||
# if desc == " ":
|
||
# total_total_amount += float(row[-2] or 0)
|
||
# continue
|
||
#
|
||
# total_basic_amount += float(row[6] or 0)
|
||
# total_tds_amount += float(row[11] or 0)
|
||
# total_sd_amount += float(row[12] or 0)
|
||
# total_on_commission += float(row[13] or 0)
|
||
# total_final_amount += float(row[-3] or 0)
|
||
# total_total_amount += float(row[-2] or 0)
|
||
# # sum holds
|
||
# total_hold_amount += sum(float(row[i] or 0) for i in range(len(base_headers), len(base_headers) + len(hold_headers)))
|
||
#
|
||
# # DO NOT sum UTR column (row[-1]) — skip it
|
||
# except Exception:
|
||
# pass
|
||
#
|
||
# totals_row = [
|
||
# "Total", "", "", "", "", "", total_basic_amount, "", "", "", "", total_tds_amount,
|
||
# total_sd_amount, total_on_commission, "", ""
|
||
# ]
|
||
# totals_row += [total_hold_amount for _ in hold_headers]
|
||
# totals_row += [total_final_amount, total_total_amount, ""] # UTR blank
|
||
# sheet.append([])
|
||
# sheet.append(totals_row)
|
||
# for cell in sheet[sheet.max_row]:
|
||
# cell.font = Font(bold=True)
|
||
#
|
||
# # Summary Section
|
||
# today_date = datetime.today().strftime('%A, %Y-%m-%d')
|
||
# sheet.append([])
|
||
# sheet.append(["Contractor Name", contInfo["Contractor_Name"]])
|
||
# sheet.append(["Date", today_date])
|
||
# sheet.append(["Description", "Amount"])
|
||
# sheet.append(["Advance/Surplus", str(total_final_amount - total_total_amount)])
|
||
# sheet.append(["Total Hold Amount", str(Decimal(total_hold_amount))])
|
||
# sheet.append(["Amount With TDS", str(total_tds_amount)])
|
||
#
|
||
# # Auto adjust column widths
|
||
# for col in sheet.columns:
|
||
# max_length = 0
|
||
# col_letter = openpyxl.utils.get_column_letter(col[0].column)
|
||
# for cell in col:
|
||
# try:
|
||
# if cell.value:
|
||
# max_length = max(max_length, len(str(cell.value)))
|
||
# except:
|
||
# pass
|
||
# sheet.column_dimensions[col_letter].width = max_length + 2
|
||
#
|
||
# workbook.save(output_file)
|
||
# workbook.close()
|
||
#
|
||
# finally:
|
||
# cursor.close()
|
||
# connection.close()
|
||
#
|
||
# return send_from_directory(output_folder, f"Contractor_Report_{contractor_id}.xlsx", as_attachment=True)
|
||
# @app.route('/download_report/<int:contractor_id>')
|
||
# def download_report(contractor_id):
|
||
# connection = config.get_db_connection()
|
||
# cursor = connection.cursor(dictionary=True)
|
||
#
|
||
# output_folder = "static/download"
|
||
# output_file = os.path.join(output_folder, f"Contractor_Report_{contractor_id}.xlsx")
|
||
#
|
||
# if not os.path.exists(output_folder):
|
||
# os.makedirs(output_folder)
|
||
#
|
||
# try:
|
||
# # Fetch Contractor Info
|
||
# cursor.callproc('GetContractorInfoId', [contractor_id])
|
||
# for result in cursor.stored_results():
|
||
# contInfo = result.fetchone()
|
||
# if not contInfo:
|
||
# return "No contractor found", 404
|
||
#
|
||
# # Fetch Hold Types
|
||
# cursor.callproc('GetDistinctHoldTypesByContractor', [contractor_id])
|
||
# 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}
|
||
#
|
||
# # Fetch Invoices
|
||
# cursor.callproc('GetInvoicesAndGSTReleasesByContractor', [contractor_id])
|
||
# for result in cursor.stored_results():
|
||
# invoices = result.fetchall()
|
||
#
|
||
# # Fetch Hold Amounts
|
||
# cursor.callproc('GetHoldAmountsByContractors', [contractor_id])
|
||
# for result in cursor.stored_results():
|
||
# hold_amounts = result.fetchall()
|
||
# hold_data = {}
|
||
# for h in hold_amounts:
|
||
# hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
||
#
|
||
# # Extract PMC numbers
|
||
# pmc_numbers = tuple(set(inv['PMC_No'] for inv in invoices if inv['PMC_No'] is not None))
|
||
#
|
||
# payments_map = {}
|
||
# extra_payments_map = {}
|
||
# if pmc_numbers:
|
||
# pmc_list_str = ','.join(str(pmc) for pmc in pmc_numbers)
|
||
# cursor.callproc('GetPaymentsByPmcNosWithInvoice', [pmc_list_str])
|
||
# for result in cursor.stored_results():
|
||
# payments = result.fetchall()
|
||
# for pay in payments:
|
||
# key = (pay['pmc_no'], pay['invoice_no'])
|
||
# payments_map.setdefault(key, []).append(pay)
|
||
#
|
||
# cursor.callproc('GetExtraPaymentsByPmcNos', [pmc_list_str])
|
||
# for result in cursor.stored_results():
|
||
# extra_payments = result.fetchall()
|
||
# for pay in extra_payments:
|
||
# extra_payments_map.setdefault(pay['pmc_no'], []).append(pay)
|
||
#
|
||
# # Create Excel Workbook
|
||
# workbook = openpyxl.Workbook()
|
||
# sheet = workbook.active
|
||
# sheet.title = "Contractor Report"
|
||
#
|
||
# # Write Contractor Info
|
||
# sheet.append(["Contractor Name", contInfo["Contractor_Name"]])
|
||
# sheet.append(["State", contInfo["State_Name"]])
|
||
# sheet.append(["District", contInfo["District_Name"]])
|
||
# sheet.append(["Block", contInfo["Block_Name"]])
|
||
# sheet.append(["Mobile No", contInfo["Mobile_No"]])
|
||
# sheet.append(["GST Type", contInfo["GST_Registration_Type"]])
|
||
# sheet.append(["GST No", contInfo["GST_No"]])
|
||
# sheet.append(["PAN No", contInfo["PAN_No"]])
|
||
# sheet.append(["Email", contInfo["Email"]])
|
||
# sheet.append(["Address", contInfo["Address"]])
|
||
# sheet.append([])
|
||
#
|
||
# # Table Headers
|
||
# 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"]
|
||
# all_headers = base_headers + hold_headers + payment_headers
|
||
#
|
||
# sheet.append(all_headers)
|
||
#
|
||
# # Style the 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()
|
||
# seen_gst_notes = set()
|
||
# processed_payments = set()
|
||
# pmc_groups = {}
|
||
# for inv in invoices:
|
||
# pmc_groups.setdefault(inv["PMC_No"], []).append(inv)
|
||
#
|
||
# for pmc_no, pmc_invoices in pmc_groups.items():
|
||
# for inv in pmc_invoices:
|
||
# invoice_no = inv["Invoice_No"]
|
||
# payments = payments_map.get((pmc_no, invoice_no), [])
|
||
#
|
||
# if (pmc_no, invoice_no) not in seen_invoices:
|
||
# seen_invoices.add((pmc_no, 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:
|
||
# 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)
|
||
# if first_payment:
|
||
# payment_id = f"{pmc_no}-{invoice_no}-{first_payment['Payment_Amount']}-{first_payment.get('UTR', '')}"
|
||
# processed_payments.add(payment_id)
|
||
#
|
||
# # GST Notes
|
||
# if inv["gst_pmc_no"] and (inv["gst_pmc_no"], inv["gst_invoice_no"]) not in seen_gst_notes:
|
||
# seen_gst_notes.add((inv["gst_pmc_no"], inv["gst_invoice_no"]))
|
||
# gst_payment = None
|
||
# for payment in payments[1:]:
|
||
# if payment['invoice_no'] == inv["gst_invoice_no"]:
|
||
# gst_payment = payment
|
||
# break
|
||
# row = [pmc_no, "", "", "GST Release Note", "", inv["gst_invoice_no"],
|
||
# inv["gst_basic_amount"], "", "", "", "", "", "", "", "", ""]
|
||
# row += ["" for _ in hold_headers]
|
||
# row += [
|
||
# inv["gst_final_amount"],
|
||
# gst_payment["Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["TDS_Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["Total_amount"] if gst_payment else "",
|
||
# gst_payment["UTR"] if gst_payment else ""
|
||
# ]
|
||
# sheet.append(row)
|
||
# if gst_payment:
|
||
# payment_id = f"{pmc_no}-{inv['gst_invoice_no']}-{gst_payment['Payment_Amount']}-{gst_payment.get('UTR', '')}"
|
||
# processed_payments.add(payment_id)
|
||
#
|
||
# for payment in payments[1:]:
|
||
# payment_id = f"{pmc_no}-{payment['invoice_no']}-{payment['Payment_Amount']}-{payment.get('UTR', '')}"
|
||
# if payment_id not in processed_payments:
|
||
# row = [pmc_no, "", "", "", "", payment['invoice_no'], "", "", "", "", "", "", "", "", "", ""]
|
||
# row += ["" for _ in hold_headers]
|
||
# row += [
|
||
# "",
|
||
# payment["Payment_Amount"],
|
||
# payment["TDS_Payment_Amount"],
|
||
# payment["Total_amount"],
|
||
# payment["UTR"]
|
||
# ]
|
||
# sheet.append(row)
|
||
# processed_payments.add(payment_id)
|
||
#
|
||
# # Extra payments (null invoice)
|
||
# for payment in extra_payments_map.get(pmc_no, []):
|
||
# payment_id = f"{pmc_no}-null-{payment['Payment_Amount']}-{payment.get('UTR', '')}"
|
||
# if payment_id not in processed_payments:
|
||
# row = [pmc_no, "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""]
|
||
# row += ["" for _ in hold_headers]
|
||
# row += [
|
||
# "",
|
||
# payment["Payment_Amount"],
|
||
# payment["TDS_Payment_Amount"],
|
||
# payment["Total_amount"],
|
||
# payment["UTR"]
|
||
# ]
|
||
# sheet.append(row)
|
||
# processed_payments.add(payment_id)
|
||
#
|
||
# # Totals Calculation
|
||
# total_basic_amount = total_tds_amount = total_sd_amount = total_on_commission = 0
|
||
# total_hold_amount = total_final_amount = total_total_amount = 0
|
||
#
|
||
# for row in sheet.iter_rows(min_row=13, max_row=sheet.max_row, values_only=True):
|
||
# try:
|
||
# total_basic_amount += float(row[6] or 0)
|
||
# total_tds_amount += float(row[11] or 0)
|
||
# total_sd_amount += float(row[12] or 0)
|
||
# total_on_commission += float(row[13] or 0)
|
||
# total_final_amount += float(row[-5] or 0)
|
||
# total_total_amount += float(row[-2] or 0)
|
||
# hold_start_col = len(base_headers)
|
||
# hold_end_col = hold_start_col + len(hold_headers)
|
||
# total_hold_amount += sum(float(row[i] or 0) for i in range(hold_start_col, hold_end_col))
|
||
# except ValueError:
|
||
# continue
|
||
#
|
||
# # Totals Row
|
||
# sheet.append([])
|
||
# totals_row = [
|
||
# "TOTAL", "", "", "", "", "", total_basic_amount, "", "", "", "", total_tds_amount,
|
||
# total_sd_amount, total_on_commission, "", ""
|
||
# ]
|
||
# totals_row += [total_hold_amount] + [""] * (len(hold_headers) - 1)
|
||
# totals_row += [total_final_amount, "", "", total_total_amount, ""]
|
||
# sheet.append(totals_row)
|
||
#
|
||
# for cell in sheet[sheet.max_row]:
|
||
# cell.font = Font(bold=True)
|
||
#
|
||
# # Summary Section
|
||
# today_date = datetime.today().strftime('%A, %Y-%m-%d')
|
||
# sheet.append([])
|
||
# sheet.append(["Contractor Name", contInfo["Contractor_Name"]])
|
||
# sheet.append(["Date", today_date])
|
||
# sheet.append(["Description", "Amount"])
|
||
# sheet.append(["Advance/Surplus", str(total_final_amount - total_total_amount)])
|
||
# sheet.append(["Total Hold Amount", str(Decimal(total_hold_amount))])
|
||
# sheet.append(["Amount With TDS", str(total_tds_amount)])
|
||
#
|
||
# # Auto adjust column widths
|
||
# for col in sheet.columns:
|
||
# max_length = 0
|
||
# col_letter = openpyxl.utils.get_column_letter(col[0].column)
|
||
# for cell in col:
|
||
# try:
|
||
# if cell.value:
|
||
# max_length = max(max_length, len(str(cell.value)))
|
||
# except:
|
||
# pass
|
||
# sheet.column_dimensions[col_letter].width = max_length + 2
|
||
#
|
||
# workbook.save(output_file)
|
||
# workbook.close()
|
||
#
|
||
# finally:
|
||
# cursor.close()
|
||
# connection.close()
|
||
#
|
||
# return send_from_directory(output_folder, f"Contractor_Report_{contractor_id}.xlsx", as_attachment=True)
|
||
|
||
|
||
# show report by pmc no
|
||
|
||
|
||
@app.route('/pmc_report/<pmc_no>')
|
||
def pmc_report(pmc_no):
|
||
connection = config.get_db_connection()
|
||
cursor = connection.cursor(dictionary=True, buffered=True)
|
||
|
||
try:
|
||
# 1. Fetch PMC info using stored procedure
|
||
# cursor.execute("""
|
||
# SELECT DISTINCT a.PMC_No, a.Village_Id, v.Village_Name, b.Block_Name,
|
||
# d.District_Name, s.State_Name, sc.Contractor_Id, sc.Contractor_Name,
|
||
# sc.Address, sc.Mobile_No, sc.PAN_No, sc.Email, sc.Gender,
|
||
# sc.GST_Registration_Type, sc.GST_No
|
||
# FROM assign_subcontractors a
|
||
# INNER JOIN villages v ON a.Village_Id = v.Village_Id
|
||
# INNER JOIN blocks b ON v.Block_Id = b.Block_Id
|
||
# INNER JOIN districts d ON b.District_id = d.District_id
|
||
# INNER JOIN states s ON d.State_Id = s.State_Id
|
||
# INNER JOIN subcontractors sc ON a.Contractor_Id = sc.Contractor_Id
|
||
# WHERE a.pmc_no = %s
|
||
# """, (pmc_no,))
|
||
# pmc_info = cursor.fetchone()
|
||
|
||
cursor.callproc("GetContractorInfoByPmcNo", (pmc_no,))
|
||
pmc_info = next(cursor.stored_results()).fetchone()
|
||
|
||
if not pmc_info:
|
||
return "No PMC found with this number", 404
|
||
|
||
# 2. Fetch hold types using stored procedure
|
||
# cursor.execute("""
|
||
# SELECT DISTINCT ht.hold_type_id, ht.hold_type
|
||
# FROM invoice_subcontractor_hold_join h
|
||
# JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
# JOIN invoice i ON h.Invoice_Id = i.Invoice_Id
|
||
# JOIN assign_subcontractors a ON i.PMC_No = a.PMC_No
|
||
# WHERE a.PMC_No = %s AND a.Contractor_Id = %s
|
||
# """, (pmc_no, pmc_info["Contractor_Id"]))
|
||
# hold_types = cursor.fetchall()
|
||
cursor.callproc("Get_pmc_hold_types", (pmc_no, pmc_info["Contractor_Id"]))
|
||
hold_types = next(cursor.stored_results()).fetchall()
|
||
hold_type_ids = [ht['hold_type_id'] for ht in hold_types]
|
||
|
||
# 3. Initialize invoice data
|
||
invoices = []
|
||
hold_amount_total = 0
|
||
|
||
# 4. Build invoice query
|
||
if hold_type_ids:
|
||
placeholders = ','.join(['%s'] * len(hold_type_ids))
|
||
query = f"""
|
||
SELECT DISTINCT i.PMC_No, v.Village_Name, i.Work_Type, i.Invoice_Details,
|
||
i.Invoice_Date, i.Invoice_No, i.Basic_Amount, i.Debit_Amount,
|
||
i.After_Debit_Amount, i.Amount, i.GST_Amount, i.TDS_Amount, i.SD_Amount,
|
||
i.On_Commission, i.Hydro_Testing, i.GST_SD_Amount,
|
||
i.Final_Amount, h.hold_amount, ht.hold_type
|
||
FROM invoice i
|
||
LEFT JOIN villages v ON i.Village_Id = v.Village_Id
|
||
LEFT JOIN assign_subcontractors a ON i.PMC_No = a.PMC_No
|
||
LEFT JOIN invoice_subcontractor_hold_join h ON i.Invoice_Id = h.Invoice_Id
|
||
LEFT JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
WHERE a.PMC_No = %s AND a.Contractor_Id = %s
|
||
AND (ht.hold_type_id IS NULL OR ht.hold_type_id IN ({placeholders}))
|
||
ORDER BY i.Invoice_Date, i.Invoice_No
|
||
"""
|
||
params = [pmc_no, pmc_info["Contractor_Id"]] + hold_type_ids
|
||
else:
|
||
query = """
|
||
SELECT DISTINCT i.PMC_No, v.Village_Name, i.Work_Type, i.Invoice_Details,
|
||
i.Invoice_Date, i.Invoice_No, i.Basic_Amount, i.Debit_Amount,
|
||
i.After_Debit_Amount, i.Amount, i.GST_Amount, i.TDS_Amount, i.SD_Amount,
|
||
i.On_Commission, i.Hydro_Testing, i.GST_SD_Amount, i.Final_Amount
|
||
FROM invoice i
|
||
LEFT JOIN villages v ON i.Village_Id = v.Village_Id
|
||
LEFT JOIN assign_subcontractors a ON i.PMC_No = a.PMC_No
|
||
WHERE a.PMC_No = %s AND a.Contractor_Id = %s
|
||
ORDER BY i.Invoice_Date, i.Invoice_No
|
||
"""
|
||
params = [pmc_no, pmc_info["Contractor_Id"]]
|
||
|
||
cursor.execute(query, params)
|
||
invoices = cursor.fetchall()
|
||
|
||
if hold_type_ids:
|
||
hold_amount_total = sum(row.get('hold_amount', 0) or 0 for row in invoices)
|
||
|
||
# 5. Totals from invoices
|
||
total_invo_final = sum(row.get('Final_Amount', 0) or 0 for row in invoices)
|
||
|
||
# 6. GST release
|
||
cursor.execute("""
|
||
SELECT pmc_no, invoice_no, basic_amount, final_amount
|
||
FROM gst_release
|
||
WHERE pmc_no = %s
|
||
ORDER BY invoice_no ASC
|
||
""", (pmc_no,))
|
||
gst_rel = cursor.fetchall()
|
||
# gst_rel = cursor.fetchall()
|
||
# cursor.callproc('GetGSTReleaseByPMC', [pmc_no])
|
||
#
|
||
# # Fetch results
|
||
# 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 Amount
|
||
cursor.execute("""select * from hold_release where pmc_no=%s""", (pmc_no,))
|
||
hold_release = cursor.fetchall()
|
||
print("All Hold Release ", hold_release)
|
||
|
||
# Credit Note
|
||
|
||
cursor.execute("select * from credit_note where pmc_no=%s", (pmc_no,))
|
||
credit_note = cursor.fetchall()
|
||
print(credit_note)
|
||
|
||
# 7. Payments
|
||
cursor.execute("""
|
||
SELECT pmc_no, invoice_no, Payment_Amount, TDS_Payment_Amount, Total_amount, utr
|
||
FROM payment
|
||
WHERE pmc_no = %s
|
||
ORDER BY invoice_no ASC
|
||
""", (pmc_no,))
|
||
payments = cursor.fetchall()
|
||
# cursor.callproc('GetPaymentByPMC', [pmc_no])
|
||
#
|
||
# 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)
|
||
|
||
# 8. Final totals dictionary
|
||
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
|
||
}
|
||
|
||
except Exception as e:
|
||
print(f"Error fetching PMC report: {e}")
|
||
return "An error occurred while fetching PMC report", 500
|
||
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return render_template(
|
||
'pmc_report.html',
|
||
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
|
||
)
|
||
|
||
|
||
# # Download report by PMC No
|
||
# @app.route('/download_pmc_report/<pmc_no>')
|
||
# 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:
|
||
# # # Fetch Contractor Details using PMC No
|
||
# # cursor.execute("""
|
||
# # SELECT DISTINCT s.Contractor_Id, s.Contractor_Name, st.State_Name, d.District_Name, b.Block_Name,
|
||
# # s.Mobile_No, s.GST_Registration_Type, s.GST_No, s.PAN_No, s.Email, s.Address
|
||
# # FROM subcontractors s
|
||
# # LEFT JOIN assign_subcontractors asg ON s.Contractor_Id = asg.Contractor_Id
|
||
# # LEFT JOIN villages v ON asg.Village_Id = v.Village_Id
|
||
# # LEFT JOIN blocks b ON v.Block_Id = b.Block_Id
|
||
# # LEFT JOIN districts d ON b.District_id = d.District_id
|
||
# # LEFT JOIN states st ON d.State_Id = st.State_Id
|
||
# # WHERE asg.PMC_No = %s
|
||
# # """, (pmc_no,))
|
||
# # contractor_info = cursor.fetchone()
|
||
# cursor.callproc('GetContractorDetailsByPMC', [pmc_no])
|
||
|
||
# # Now fetch the result:
|
||
# for result in cursor.stored_results():
|
||
# contractor_info = result.fetchone()
|
||
|
||
# if not contractor_info:
|
||
# return "No contractor found for this PMC No", 404
|
||
|
||
# # # Fetch distinct hold types present for the contractor
|
||
# # cursor.execute("""
|
||
# # SELECT DISTINCT ht.hold_type_id, ht.hold_type
|
||
# # FROM invoice_subcontractor_hold_join h
|
||
# # JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
# # WHERE h.Contractor_Id = %s
|
||
# # """, (contractor_info["Contractor_Id"],))
|
||
# # hold_types = cursor.fetchall()
|
||
# cursor.callproc('GetHoldTypesByContractor', [contractor_info["Contractor_Id"]])
|
||
|
||
# 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}
|
||
|
||
# # # # Fetch Invoices & GST Releases
|
||
# # cursor.execute("""
|
||
# # SELECT DISTINCT i.Invoice_Id, i.PMC_No, v.Village_Name, i.Work_Type, i.Invoice_Details,
|
||
# # i.Invoice_Date, i.Invoice_No, i.Basic_Amount, i.Debit_Amount,
|
||
# # i.After_Debit_Amount, i.GST_Amount, i.Amount, i.TDS_Amount, i.SD_Amount,
|
||
# # i.On_Commission, i.Hydro_Testing, i.GST_SD_Amount, i.Final_Amount,
|
||
# # g.pmc_no AS gst_pmc_no, g.invoice_no AS gst_invoice_no,
|
||
# # g.basic_amount AS gst_basic_amount, g.final_amount AS gst_final_amount
|
||
# # FROM invoice i
|
||
# # LEFT JOIN assign_subcontractors asg ON i.PMC_No = asg.PMC_No
|
||
# # LEFT JOIN villages v ON i.Village_Id = v.Village_Id
|
||
# # LEFT JOIN gst_release g ON i.PMC_No = g.pmc_no AND i.Invoice_No = g.invoice_no
|
||
# # WHERE asg.PMC_No = %s
|
||
# # ORDER BY i.Invoice_Date, i.Invoice_No
|
||
# # """, (pmc_no,))
|
||
# # invoices = cursor.fetchall()
|
||
|
||
# cursor.callproc('GetInvoicesAndGstReleaseByPmcNo', [pmc_no])
|
||
|
||
# for result in cursor.stored_results():
|
||
# invoices = result.fetchall()
|
||
# print("pmc_report invoice data:",invoices)
|
||
|
||
# # cursor.callproc('GetInvoicesAndGSTReleasesByPMC', [pmc_no])
|
||
|
||
# # for result in cursor.stored_results():
|
||
# # invoices = result.fetchall()
|
||
|
||
# # # Fetch Hold Amounts separately
|
||
# # cursor.execute("""
|
||
# # SELECT h.Invoice_Id, ht.hold_type_id, h.hold_amount
|
||
# # FROM invoice_subcontractor_hold_join h
|
||
# # JOIN hold_types ht ON h.hold_type_id = ht.hold_type_id
|
||
# # WHERE h.Contractor_Id = %s
|
||
# # """, (contractor_info["Contractor_Id"],))
|
||
# # hold_amounts = cursor.fetchall()
|
||
# cursor.callproc('GetHoldAmountsByContractor', [contractor_info["Contractor_Id"]])
|
||
|
||
# for result in cursor.stored_results():
|
||
# hold_amounts = result.fetchall()
|
||
|
||
# # Create a mapping of invoice_id to hold amounts by type
|
||
# hold_data = {}
|
||
# for h in hold_amounts:
|
||
# hold_data.setdefault(h['Invoice_Id'], {})[h['hold_type_id']] = h['hold_amount']
|
||
|
||
# # # Fetch all Payments for the PMC number
|
||
# # cursor.execute("""
|
||
# # SELECT pmc_no, invoice_no, Payment_Amount, TDS_Payment_Amount, Total_amount, UTR
|
||
# # FROM payment
|
||
# # WHERE pmc_no = %s
|
||
# # ORDER BY invoice_no
|
||
# # """, (pmc_no,))
|
||
# # all_payments = cursor.fetchall()
|
||
# cursor.callproc('GetAllPaymentsByPMC', [pmc_no])
|
||
|
||
# for result in cursor.stored_results():
|
||
# all_payments = result.fetchall()
|
||
|
||
# # Organize payments by Invoice No (both regular and GST release notes)
|
||
# payments_map = {}
|
||
# extra_payments = []
|
||
# for pay in all_payments:
|
||
# if pay['invoice_no']:
|
||
# key = pay['invoice_no']
|
||
# if key not in payments_map:
|
||
# payments_map[key] = []
|
||
# payments_map[key].append(pay)
|
||
# else:
|
||
# extra_payments.append(pay)
|
||
|
||
# # Create Excel workbook
|
||
# workbook = openpyxl.Workbook()
|
||
# sheet = workbook.active
|
||
# sheet.title = "PMC Report"
|
||
|
||
# # Write Contractor Details
|
||
# 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([])
|
||
|
||
# # Table Headers - include all hold types as separate columns
|
||
# 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)
|
||
|
||
# seen_invoices = set()
|
||
# seen_gst_notes = set()
|
||
# processed_payments = set()
|
||
|
||
# # Process invoices
|
||
# for inv in invoices:
|
||
# invoice_no = inv["Invoice_No"]
|
||
# payments = payments_map.get(invoice_no, [])
|
||
|
||
# # Process invoice row with first payment (if exists)
|
||
# if invoice_no not in seen_invoices:
|
||
# seen_invoices.add(invoice_no)
|
||
# first_payment = payments[0] if len(payments) > 0 else None
|
||
|
||
# # Base invoice data
|
||
# 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"]
|
||
# ]
|
||
|
||
# # Add hold amounts for each hold type
|
||
# invoice_holds = hold_data.get(inv["Invoice_Id"], {})
|
||
# for ht_id in hold_type_map.keys():
|
||
# row.append(invoice_holds.get(ht_id, ""))
|
||
|
||
# # Add payment information
|
||
# 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)
|
||
|
||
# if first_payment:
|
||
# payment_id = f"{invoice_no}-{first_payment['Payment_Amount']}-{first_payment.get('UTR', '')}"
|
||
# processed_payments.add(payment_id)
|
||
|
||
# # Process GST release if exists (only if we have a matching GST record)
|
||
# if inv["gst_pmc_no"] and inv["gst_invoice_no"] and inv["gst_invoice_no"] not in seen_gst_notes:
|
||
# seen_gst_notes.add(inv["gst_invoice_no"])
|
||
|
||
# # Find the payment that matches this GST release
|
||
# gst_payment = None
|
||
# for payment in payments[1:]: # Skip first payment (already used for invoice)
|
||
# if payment['invoice_no'] == inv["gst_invoice_no"]:
|
||
# gst_payment = payment
|
||
# break
|
||
|
||
# # If no payment found in the invoice's payments, check all payments
|
||
# if not gst_payment:
|
||
# gst_payments = payments_map.get(inv["gst_invoice_no"], [])
|
||
# if gst_payments:
|
||
# gst_payment = gst_payments[0]
|
||
|
||
# # GST release row
|
||
# row = [
|
||
# pmc_no, "", "", "GST Release Note", "", inv["gst_invoice_no"],
|
||
# inv["gst_basic_amount"], "", "", "", "", "", "", "", "", "" # Empty GST SD Amount
|
||
# ]
|
||
|
||
# # Empty holds for GST release
|
||
# row += ["" for _ in hold_headers]
|
||
|
||
# # Add payment information
|
||
# row += [
|
||
# inv["gst_final_amount"],
|
||
# gst_payment["Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["TDS_Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["Total_amount"] if gst_payment else "",
|
||
# gst_payment["UTR"] if gst_payment else ""
|
||
# ]
|
||
|
||
# sheet.append(row)
|
||
|
||
# if gst_payment:
|
||
# payment_id = f"{inv['gst_invoice_no']}-{gst_payment['Payment_Amount']}-{gst_payment.get('UTR', '')}"
|
||
# processed_payments.add(payment_id)
|
||
|
||
# # Process remaining payments as extra payments
|
||
# for payment in payments[1:]:
|
||
# payment_id = f"{payment['invoice_no']}-{payment['Payment_Amount']}-{payment.get('UTR', '')}"
|
||
# if payment_id not in processed_payments:
|
||
# row = [
|
||
# pmc_no, "", "", "", "", payment['invoice_no'],
|
||
# "", "", "", "", "", "", "", "", "", "" # Empty GST SD Amount
|
||
# ]
|
||
|
||
# # Empty holds for extra payments
|
||
# row += ["" for _ in hold_headers]
|
||
|
||
# # Add payment information
|
||
# row += [
|
||
# "",
|
||
# payment["Payment_Amount"],
|
||
# payment["TDS_Payment_Amount"],
|
||
# payment["Total_amount"],
|
||
# payment["UTR"]
|
||
# ]
|
||
|
||
# sheet.append(row)
|
||
# processed_payments.add(payment_id)
|
||
|
||
# # Process extra payments (null invoice_no)
|
||
# for payment in extra_payments:
|
||
# payment_id = f"null-{payment['Payment_Amount']}-{payment.get('UTR', '')}"
|
||
# if payment_id not in processed_payments:
|
||
# row = [
|
||
# pmc_no, "", "", "", "", "",
|
||
# "", "", "", "", "", "", "", "", "", "" # Empty GST SD Amount
|
||
# ]
|
||
|
||
# # Empty holds for null invoice payments
|
||
# row += ["" for _ in hold_headers]
|
||
|
||
# # Add payment information
|
||
# row += [
|
||
# "",
|
||
# payment["Payment_Amount"],
|
||
# payment["TDS_Payment_Amount"],
|
||
# payment["Total_amount"],
|
||
# payment["UTR"]
|
||
# ]
|
||
|
||
# sheet.append(row)
|
||
# processed_payments.add(payment_id)
|
||
|
||
# # Calculate totals
|
||
# total_basic_amount = 0
|
||
# total_tds_amount = 0
|
||
# total_sd_amount = 0
|
||
# total_on_commission = 0
|
||
# total_hold_amount = 0
|
||
# total_final_amount = 0
|
||
# total_payment_amount = 0
|
||
# total_tds_payment_amount = 0
|
||
# total_total_paid = 0
|
||
|
||
# for row in sheet.iter_rows(min_row=2, max_row=sheet.max_row, values_only=True):
|
||
# try:
|
||
# total_basic_amount += float(row[6] or 0) # Basic_Amount
|
||
# total_tds_amount += float(row[11] or 0) # TDS_Amount
|
||
# total_sd_amount += float(row[12] or 0) # SD_Amount
|
||
# total_on_commission += float(row[13] or 0) # On_Commission
|
||
# total_final_amount += float(row[-5] or 0) # Final_Amount
|
||
# total_payment_amount += float(row[-4] or 0) # Payment_Amount
|
||
# total_tds_payment_amount += float(row[-3] or 0) # TDS_Payment
|
||
# total_total_paid += float(row[-2] or 0) # Total_Paid
|
||
|
||
# # Sum of hold amounts
|
||
# hold_start_col = len(base_headers)
|
||
# hold_end_col = hold_start_col + len(hold_headers)
|
||
# total_hold_amount += sum(float(row[i] or 0) for i in range(hold_start_col, hold_end_col))
|
||
# except (ValueError, IndexError, TypeError):
|
||
# continue
|
||
|
||
# # Append totals row
|
||
# totals_row = [
|
||
# "TOTAL", "", "", "", "", "",
|
||
# total_basic_amount, "", "", "", "", total_tds_amount, total_sd_amount,
|
||
# total_on_commission, "", "", # Empty GST SD Amount
|
||
# ]
|
||
|
||
# # Add hold totals
|
||
# totals_row += [total_hold_amount] + [""] * (len(hold_headers) - 1)
|
||
|
||
# # Add payment totals
|
||
# totals_row += [
|
||
# total_final_amount,
|
||
# total_payment_amount,
|
||
# total_tds_payment_amount,
|
||
# total_total_paid,
|
||
# "" # UTR column remains empty
|
||
# ]
|
||
|
||
# sheet.append([])
|
||
# sheet.append(totals_row)
|
||
|
||
# # Make totals row bold
|
||
# for cell in sheet[sheet.max_row]:
|
||
# cell.font = Font(bold=True)
|
||
|
||
# # Save Excel file
|
||
# workbook.save(output_file)
|
||
# workbook.close()
|
||
|
||
# finally:
|
||
# cursor.close()
|
||
# connection.close()
|
||
|
||
# return send_from_directory(output_folder, f"PMC_Report_{pmc_no}.xlsx", as_attachment=True)
|
||
|
||
|
||
|
||
# @app.route('/download_pmc_report/<pmc_no>')
|
||
# 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])
|
||
#
|
||
# for result in cursor.stored_results():
|
||
# contractor_info = result.fetchone()
|
||
#
|
||
# if not contractor_info:
|
||
# return "No contractor found for this PMC No", 404
|
||
#
|
||
# cursor.callproc('GetHoldTypesByContractor', [contractor_info["Contractor_Id"]])
|
||
#
|
||
# 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}
|
||
#
|
||
# cursor.callproc('GetInvoicesAndGstReleaseByPmcNo', [pmc_no])
|
||
#
|
||
# for result in cursor.stored_results():
|
||
# invoices = result.fetchall()
|
||
# total_tds=Decimal('0.00')
|
||
# final_amount=Decimal('0.00')
|
||
# # total_hold_amount=Decimal('0.00')
|
||
# for data in invoices:
|
||
# total_tds=total_tds+data.get('TDS_Amount',Decimal('0.00'))
|
||
# final_amount=final_amount+data.get('Final_Amount',Decimal('0.00'))
|
||
#
|
||
# cursor.callproc('GetHoldAmountsByContractor', [contractor_info["Contractor_Id"]])
|
||
#
|
||
# for result in cursor.stored_results():
|
||
# hold_amounts = result.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])
|
||
#
|
||
# for result in cursor.stored_results():
|
||
# all_payments = result.fetchall()
|
||
# total_amount=Decimal('0.00')
|
||
# for d in all_payments:
|
||
# total_amount=total_amount+ d.get('Total_Amount',Decimal('0.00'))
|
||
# total_amount_paid= final_amount- total_amount;
|
||
# payments_map = {}
|
||
# extra_payments = []
|
||
# for pay in all_payments:
|
||
# if pay['invoice_no']:
|
||
# key = pay['invoice_no']
|
||
# if key not in payments_map:
|
||
# payments_map[key] = []
|
||
# payments_map[key].append(pay)
|
||
# else:
|
||
# extra_payments.append(pay)
|
||
#
|
||
# workbook = openpyxl.Workbook()
|
||
# sheet = workbook.active
|
||
# sheet.title = "PMC Report"
|
||
#
|
||
# # Write Contractor Details
|
||
# 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([])
|
||
#
|
||
# # Table Headers - include all hold types as separate columns
|
||
# 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)
|
||
#
|
||
# seen_invoices = set()
|
||
# seen_gst_notes = set()
|
||
# processed_payments = set()
|
||
#
|
||
# # Process invoices
|
||
# for inv in invoices:
|
||
# invoice_no = inv["Invoice_No"]
|
||
# payments = payments_map.get(invoice_no, [])
|
||
#
|
||
# # Process invoice row with first payment (if exists)
|
||
# if invoice_no not in seen_invoices:
|
||
# seen_invoices.add(invoice_no)
|
||
# first_payment = payments[0] if len(payments) > 0 else None
|
||
#
|
||
# # Base invoice data
|
||
# 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"]
|
||
# ]
|
||
#
|
||
# # Add hold amounts for each hold type
|
||
# invoice_holds = hold_data.get(inv["Invoice_Id"], {})
|
||
# for ht_id in hold_type_map.keys():
|
||
# row.append(invoice_holds.get(ht_id, ""))
|
||
#
|
||
# # Add payment information
|
||
# 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)
|
||
#
|
||
# if first_payment:
|
||
# payment_id = f"{invoice_no}-{first_payment['Payment_Amount']}-{first_payment.get('UTR', '')}"
|
||
# processed_payments.add(payment_id)
|
||
#
|
||
# # Process GST release if exists (only if we have a matching GST record)
|
||
# if inv["gst_pmc_no"] and inv["gst_invoice_no"] and inv["gst_invoice_no"] not in seen_gst_notes:
|
||
# seen_gst_notes.add(inv["gst_invoice_no"])
|
||
#
|
||
# # Find the payment that matches this GST release
|
||
# gst_payment = None
|
||
# for payment in payments[1:]: # Skip first payment (already used for invoice)
|
||
# if payment['invoice_no'] == inv["gst_invoice_no"]:
|
||
# gst_payment = payment
|
||
# break
|
||
#
|
||
# # If no payment found in the invoice's payments, check all payments
|
||
# if not gst_payment:
|
||
# gst_payments = payments_map.get(inv["gst_invoice_no"], [])
|
||
# if gst_payments:
|
||
# gst_payment = gst_payments[0]
|
||
#
|
||
# # GST release row (this will be in the same row, after the invoice information)
|
||
# gst_row = [
|
||
# pmc_no, "", "", "GST Release Note", "", inv["gst_invoice_no"],
|
||
# inv["gst_basic_amount"], "", "", "", "", "", "", "", "", "" # Empty GST SD Amount
|
||
# ]
|
||
#
|
||
# # Empty holds for GST release
|
||
# gst_row += ["" for _ in hold_headers]
|
||
#
|
||
# # Add GST payment information (same columns as invoice payment information)
|
||
# gst_row += [
|
||
# inv["gst_final_amount"],
|
||
# gst_payment["Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["TDS_Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["Total_amount"] if gst_payment else "",
|
||
# gst_payment["UTR"] if gst_payment else ""
|
||
# ]
|
||
#
|
||
# sheet.append(gst_row)
|
||
#
|
||
# if gst_payment:
|
||
# payment_id = f"{inv['gst_invoice_no']}-{gst_payment['Payment_Amount']}-{gst_payment.get('UTR', '')}"
|
||
# processed_payments.add(payment_id)
|
||
#
|
||
# # Process remaining payments as extra payments (if any)
|
||
# for payment in payments[1:]:
|
||
# payment_id = f"{payment['invoice_no']}-{payment['Payment_Amount']}-{payment.get('UTR', '')}"
|
||
# if payment_id not in processed_payments:
|
||
# row = [
|
||
# pmc_no, "", "", "", "", payment['invoice_no'],
|
||
# "", "", "", "", "", "", "", "", "", "" # Empty GST SD Amount
|
||
# ]
|
||
#
|
||
# # Empty holds for extra payments
|
||
# row += ["" for _ in hold_headers]
|
||
#
|
||
# # Add payment information
|
||
# row += [
|
||
# "",
|
||
# payment["Payment_Amount"],
|
||
# payment["TDS_Payment_Amount"],
|
||
# payment["Total_amount"],
|
||
# payment["UTR"]
|
||
# ]
|
||
#
|
||
# sheet.append(row)
|
||
# processed_payments.add(payment_id)
|
||
#
|
||
# # Process extra payments (null invoice_no)
|
||
# for payment in extra_payments:
|
||
# payment_id = f"null-{payment['Payment_Amount']}-{payment.get('UTR', '')}"
|
||
# if payment_id not in processed_payments:
|
||
# row = [
|
||
# pmc_no, "", "", "", "", "",
|
||
# "", "", "", "", "", "", "", "", "", "" # Empty GST SD Amount
|
||
# ]
|
||
#
|
||
# # Empty holds for null invoice payments
|
||
# row += ["" for _ in hold_headers]
|
||
#
|
||
# # Add payment information
|
||
# row += [
|
||
# "",
|
||
# payment["Payment_Amount"],
|
||
# payment["TDS_Payment_Amount"],
|
||
# payment["Total_amount"],
|
||
# payment["UTR"]
|
||
# ]
|
||
#
|
||
# sheet.append(row)
|
||
# processed_payments.add(payment_id)
|
||
#
|
||
# # Calculate totals
|
||
# total_basic_amount = 0
|
||
# total_tds_amount = 0
|
||
# total_sd_amount = 0
|
||
# total_on_commission = 0
|
||
# total_hold_amount = 0
|
||
# total_final_amount = 0
|
||
# total_payment_amount = 0
|
||
# total_tds_payment_amount = 0
|
||
# total_total_paid = 0
|
||
#
|
||
# for row in sheet.iter_rows(min_row=2, max_row=sheet.max_row, values_only=True):
|
||
# try:
|
||
# total_basic_amount += float(row[6] or 0) # Basic_Amount
|
||
# total_tds_amount += float(row[11] or 0) # TDS_Amount
|
||
# total_sd_amount += float(row[12] or 0) # SD_Amount
|
||
# total_on_commission += float(row[13] or 0) # On_Commission
|
||
# total_final_amount += float(row[-5] or 0) # Final_Amount
|
||
# total_payment_amount += float(row[-4] or 0) # Payment_Amount
|
||
# total_tds_payment_amount += float(row[-3] or 0) # TDS_Payment
|
||
# total_total_paid += float(row[-2] or 0) # Total_Paid
|
||
#
|
||
# # Sum of hold amounts
|
||
# hold_start_col = len(base_headers)
|
||
# hold_end_col = hold_start_col + len(hold_headers)
|
||
# total_hold_amount += sum(float(row[i] or 0) for i in range(hold_start_col, hold_end_col))
|
||
# except (ValueError, IndexError, TypeError):
|
||
# continue
|
||
#
|
||
# # Append totals row
|
||
# totals_row = [
|
||
# "TOTAL", "", "", "", "", "",
|
||
# total_basic_amount, "", "", "", "", total_tds_amount, total_sd_amount,
|
||
# total_on_commission, "", "", # Empty GST SD Amount
|
||
# ]
|
||
# if hold_headers:
|
||
# totals_row += [total_hold_amount] + [""] * (len(hold_headers) - 1)
|
||
#
|
||
# # Add payment totals
|
||
# totals_row += [
|
||
# total_final_amount,
|
||
# total_payment_amount,
|
||
# total_tds_payment_amount,
|
||
# total_total_paid,
|
||
# "" # UTR column remains empty
|
||
# ]
|
||
#
|
||
# sheet.append([])
|
||
# sheet.append(totals_row)
|
||
# #new code added for small chart---summary
|
||
# total_hold_amount=Decimal('0.00')
|
||
# for d in invoices:
|
||
# total_hold_amount = total_hold_amount + d.get('SD_Amount', Decimal('0.00')) + d.get('On_Commission',
|
||
# Decimal(
|
||
# '0.00')) + d.get(
|
||
# 'Hydro_Testing', Decimal('0.00'))
|
||
# for data in hold_amounts:
|
||
# total_hold_amount = total_hold_amount + data.get('hold_amount', Decimal('0.00'))
|
||
# print("Total Hold Amount after adding the hold amount ", total_hold_amount)
|
||
#
|
||
# # Add payment information
|
||
# # Get today's date
|
||
# today_date = datetime.today().strftime('%A,%Y-%m-%d')
|
||
# # Add headers (optional)
|
||
# sheet.append(["Contractor Name", contractor_info["Contractor_Name"]])
|
||
# sheet.append(["Date", today_date])
|
||
# sheet.append(["Description", "Amount"])
|
||
# # Add your values
|
||
# sheet.append(["Advance/Surplus", str(total_final_amount-total_payment_amount)])
|
||
# sheet.append(["Total Hold Amount", str(total_hold_amount)])
|
||
# sheet.append(["Amount With TDS", str(total_tds_payment_amount)])
|
||
# # new coded ended here for summary chart
|
||
# # Make totals row bold
|
||
# for cell in sheet[sheet.max_row]:
|
||
# cell.font = Font(bold=True)
|
||
#
|
||
# # Save Excel file
|
||
# workbook.save(output_file)
|
||
# workbook.close()
|
||
#
|
||
# finally:
|
||
# cursor.close()
|
||
# connection.close()
|
||
#
|
||
# return send_from_directory(output_folder, f"PMC_Report_{pmc_no}.xlsx", as_attachment=True)
|
||
|
||
# @app.route('/download_pmc_report/<pmc_no>')
|
||
# 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 "No contractor found for this PMC No", 404
|
||
#
|
||
# 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('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)
|
||
#
|
||
# workbook = openpyxl.Workbook()
|
||
# sheet = workbook.active
|
||
# sheet.title = "PMC Report"
|
||
#
|
||
# # Write contractor header
|
||
# 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)
|
||
# # Style the 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()
|
||
# seen_gst_notes = 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)
|
||
#
|
||
# if first_payment:
|
||
# processed_payments.add(f"{invoice_no}-{first_payment['Payment_Amount']}-{first_payment.get('UTR', '')}")
|
||
#
|
||
# if inv["gst_pmc_no"] and inv["gst_invoice_no"] and inv["gst_invoice_no"] not in seen_gst_notes:
|
||
# seen_gst_notes.add(inv["gst_invoice_no"])
|
||
# gst_payment = None
|
||
# for payment in payments[1:]:
|
||
# if payment['invoice_no'] == inv["gst_invoice_no"]:
|
||
# gst_payment = payment
|
||
# break
|
||
# if not gst_payment:
|
||
# gst_payment = payments_map.get(inv["gst_invoice_no"], [None])[0]
|
||
#
|
||
# gst_row = [
|
||
# pmc_no, "", "", "GST Release Note", "", inv["gst_invoice_no"],
|
||
# inv["gst_basic_amount"], "", "", "", "", "", "", "", "", ""
|
||
# ]
|
||
# gst_row += ["" for _ in hold_headers]
|
||
# gst_row += [
|
||
# inv["gst_final_amount"],
|
||
# gst_payment["Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["TDS_Payment_Amount"] if gst_payment else "",
|
||
# gst_payment["Total_amount"] if gst_payment else "",
|
||
# gst_payment["UTR"] if gst_payment else ""
|
||
# ]
|
||
# sheet.append(gst_row)
|
||
# if gst_payment:
|
||
# processed_payments.add(f"{inv['gst_invoice_no']}-{gst_payment['Payment_Amount']}-{gst_payment.get('UTR', '')}")
|
||
#
|
||
# for payment in payments[1:]:
|
||
# payment_id = f"{payment['invoice_no']}-{payment['Payment_Amount']}-{payment.get('UTR', '')}"
|
||
# if payment_id not in processed_payments:
|
||
# row = [pmc_no, "", "", "", "", payment['invoice_no']] + [""] * 10
|
||
# row += ["" for _ in hold_headers]
|
||
# row += [
|
||
# "", payment["Payment_Amount"], payment["TDS_Payment_Amount"],
|
||
# payment["Total_amount"], payment["UTR"]
|
||
# ]
|
||
# sheet.append(row)
|
||
# processed_payments.add(payment_id)
|
||
#
|
||
# for payment in extra_payments:
|
||
# row = [pmc_no, "", "", "", "", ""] + [""] * 10
|
||
# row += ["" for _ in hold_headers]
|
||
# row += [
|
||
# "", payment["Payment_Amount"], payment["TDS_Payment_Amount"],
|
||
# payment["Total_amount"], payment["UTR"]
|
||
# ]
|
||
# sheet.append(row)
|
||
#
|
||
# # Totals
|
||
# total_basic_amount = Decimal('0.00')
|
||
# total_tds_amount = Decimal('0.00')
|
||
# total_sd_amount = Decimal('0.00')
|
||
# total_on_commission = Decimal('0.00')
|
||
# total_final_amount = Decimal('0.00')
|
||
# total_payment_amount = Decimal('0.00')
|
||
# total_tds_payment_amount = Decimal('0.00')
|
||
# total_total_paid = Decimal('0.00')
|
||
# total_hold_amount_dynamic = Decimal('0.00')
|
||
#
|
||
# for row in sheet.iter_rows(min_row=8, max_row=sheet.max_row, values_only=True):
|
||
# try:
|
||
# total_basic_amount += Decimal(str(row[6] or 0))
|
||
# total_tds_amount += Decimal(str(row[11] or 0))
|
||
# total_sd_amount += Decimal(str(row[12] or 0))
|
||
# total_on_commission += Decimal(str(row[13] or 0))
|
||
# total_final_amount += Decimal(str(row[-5] or 0))
|
||
# total_payment_amount += Decimal(str(row[-4] or 0))
|
||
# total_tds_payment_amount += Decimal(str(row[-3] or 0))
|
||
# total_total_paid += Decimal(str(row[-2] or 0))
|
||
#
|
||
# for i in range(len(base_headers), len(base_headers) + len(hold_headers)):
|
||
# total_hold_amount_dynamic += Decimal(str(row[i] or 0))
|
||
# except:
|
||
# continue
|
||
#
|
||
# totals_row = [
|
||
# "TOTAL", "", "", "", "", "",
|
||
# total_basic_amount, "", "", "", "", total_tds_amount, total_sd_amount,
|
||
# total_on_commission, "", ""
|
||
# ]
|
||
# totals_row += [total_hold_amount_dynamic] + [""] * (len(hold_headers) - 1)
|
||
# totals_row += [
|
||
# total_final_amount,
|
||
# total_payment_amount,
|
||
# total_tds_payment_amount,
|
||
# total_total_paid,
|
||
# ""
|
||
# ]
|
||
#
|
||
# sheet.append([])
|
||
# sheet.append(totals_row)
|
||
#
|
||
# # Summary
|
||
# summary_hold = Decimal('0.00')
|
||
# for d in invoices:
|
||
# summary_hold += Decimal(str(d.get('SD_Amount', 0.00))) + Decimal(str(d.get('On_Commission', 0.00))) + Decimal(str(d.get('Hydro_Testing', 0.00)))
|
||
# for h in hold_amounts:
|
||
# summary_hold += Decimal(str(h.get('hold_amount', 0.00)))
|
||
#
|
||
# sheet.append([])
|
||
# today = datetime.today().strftime('%A, %Y-%m-%d')
|
||
# sheet.append(["Contractor Name", contractor_info["Contractor_Name"]])
|
||
# sheet.append(["Date", today])
|
||
# sheet.append(["Description", "Amount"])
|
||
# sheet.append(["Advance/Surplus", str(total_final_amount - total_payment_amount)])
|
||
# sheet.append(["Total Hold Amount", str(summary_hold)])
|
||
# sheet.append(["Amount With TDS", str(total_payment_amount + total_tds_payment_amount)])
|
||
#
|
||
# for cell in sheet[sheet.max_row]:
|
||
# cell.font = Font(bold=True)
|
||
#
|
||
# workbook.save(output_file)
|
||
# workbook.close()
|
||
#
|
||
# finally:
|
||
# cursor.close()
|
||
# connection.close()
|
||
#
|
||
# return send_from_directory(output_folder, f"PMC_Report_{pmc_no}.xlsx", as_attachment=True)
|
||
|
||
|
||
@app.route('/download_pmc_report/<pmc_no>')
|
||
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 "No contractor found for this PMC No", 404
|
||
|
||
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()
|
||
|
||
# Credit Note
|
||
# Credit Note Fetch
|
||
cursor.execute("""
|
||
SELECT PMC_No, Invoice_Details, Basic_Amount, Debit_Amount, After_Debit_Amount,
|
||
GST_Amount, Amount, Final_Amount, Payment_Amount, Total_Amount, UTR, Invoice_No
|
||
FROM credit_note
|
||
WHERE Contractor_Id = %s
|
||
""", (pmc_no,))
|
||
|
||
credit_notes = cursor.fetchall()
|
||
|
||
|
||
# Build map by (PMC_No, Invoice_No)
|
||
credit_note_map = {}
|
||
for cn in credit_notes:
|
||
key = (cn["PMC_No"], cn["Invoice_No"]) # Use correct casing!
|
||
credit_note_map.setdefault(key, []).append(cn)
|
||
|
||
# Track already appended credit notes
|
||
appended_credit_keys = set()
|
||
|
||
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)
|
||
|
||
|
||
|
||
workbook = openpyxl.Workbook()
|
||
sheet = workbook.active
|
||
sheet.title = "PMC Report"
|
||
|
||
# Write contractor header
|
||
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)
|
||
# Style the 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()
|
||
seen_gst_notes = 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)
|
||
|
||
if first_payment:
|
||
processed_payments.add(f"{invoice_no}-{first_payment['Payment_Amount']}-{first_payment.get('UTR', '')}")
|
||
|
||
if inv["gst_pmc_no"] and inv["gst_invoice_no"] and inv["gst_invoice_no"] not in seen_gst_notes:
|
||
seen_gst_notes.add(inv["gst_invoice_no"])
|
||
gst_payment = None
|
||
for payment in payments[1:]:
|
||
if payment['invoice_no'] == inv["gst_invoice_no"]:
|
||
gst_payment = payment
|
||
break
|
||
if not gst_payment:
|
||
gst_payment = payments_map.get(inv["gst_invoice_no"], [None])[0]
|
||
|
||
gst_row = [
|
||
pmc_no, "", "", "GST Release Note", "", inv["gst_invoice_no"],
|
||
inv["gst_basic_amount"], "", "", "", "", "", "", "", "", ""
|
||
]
|
||
gst_row += ["" for _ in hold_headers]
|
||
gst_row += [
|
||
inv["gst_final_amount"],
|
||
gst_payment["Payment_Amount"] if gst_payment else "",
|
||
gst_payment["TDS_Payment_Amount"] if gst_payment else "",
|
||
gst_payment["Total_amount"] if gst_payment else "",
|
||
gst_payment["UTR"] if gst_payment else ""
|
||
]
|
||
sheet.append(gst_row)
|
||
if gst_payment:
|
||
processed_payments.add(f"{inv['gst_invoice_no']}-{gst_payment['Payment_Amount']}-{gst_payment.get('UTR', '')}")
|
||
|
||
for payment in payments[1:]:
|
||
payment_id = f"{payment['invoice_no']}-{payment['Payment_Amount']}-{payment.get('UTR', '')}"
|
||
if payment_id not in processed_payments:
|
||
row = [pmc_no, "", "", "", "", payment['invoice_no']] + [""] * 10
|
||
row += ["" for _ in hold_headers]
|
||
row += [
|
||
"", payment["Payment_Amount"], payment["TDS_Payment_Amount"],
|
||
payment["Total_amount"], payment["UTR"]
|
||
]
|
||
sheet.append(row)
|
||
processed_payments.add(payment_id)
|
||
|
||
for payment in extra_payments:
|
||
row = [pmc_no, "", "", "", "", ""] + [""] * 10
|
||
row += ["" for _ in hold_headers]
|
||
row += [
|
||
"", payment["Payment_Amount"], payment["TDS_Payment_Amount"],
|
||
payment["Total_amount"], payment["UTR"]
|
||
]
|
||
sheet.append(row)
|
||
|
||
# Credit Note row(s)
|
||
|
||
# Track already appended credit notes
|
||
appended_credit_keys = set()
|
||
|
||
# While writing invoices
|
||
key = (pmc_no, invoice_no)
|
||
if key in credit_note_map and key not in appended_credit_keys:
|
||
for cn in credit_note_map[key]:
|
||
credit_row = [
|
||
pmc_no, "", "", cn.get("Invoice_Details", "Credit Note"), "", cn.get("Invoice_No", ""),
|
||
cn.get("Basic_Amount", ""), cn.get("Debit_Amount", ""),
|
||
cn.get("After_Debit_Amount", ""), cn.get("GST_Amount", ""), cn.get("Amount", ""), "", "", "",
|
||
"", ""
|
||
]
|
||
credit_row += ["" for _ in hold_headers]
|
||
credit_row += [
|
||
cn.get("Final_Amount", ""),
|
||
cn.get("Total_Amount", ""),
|
||
cn.get("UTR", "")
|
||
]
|
||
|
||
sheet.append(credit_row)
|
||
|
||
appended_credit_keys.add(key)
|
||
|
||
# Totals
|
||
total_basic_amount = Decimal('0.00')
|
||
total_tds_amount = Decimal('0.00')
|
||
total_sd_amount = Decimal('0.00')
|
||
total_on_commission = Decimal('0.00')
|
||
total_final_amount = Decimal('0.00')
|
||
total_payment_amount = Decimal('0.00')
|
||
total_tds_payment_amount = Decimal('0.00')
|
||
total_total_paid = Decimal('0.00')
|
||
total_hold_amount_dynamic = Decimal('0.00')
|
||
|
||
for row in sheet.iter_rows(min_row=8, max_row=sheet.max_row, values_only=True):
|
||
try:
|
||
total_basic_amount += Decimal(str(row[6] or 0))
|
||
total_tds_amount += Decimal(str(row[11] or 0))
|
||
total_sd_amount += Decimal(str(row[12] or 0))
|
||
total_on_commission += Decimal(str(row[13] or 0))
|
||
total_final_amount += Decimal(str(row[-5] or 0))
|
||
total_payment_amount += Decimal(str(row[-4] or 0))
|
||
total_tds_payment_amount += Decimal(str(row[-3] or 0))
|
||
total_total_paid += Decimal(str(row[-2] or 0))
|
||
|
||
for i in range(len(base_headers), len(base_headers) + len(hold_headers)):
|
||
total_hold_amount_dynamic += Decimal(str(row[i] or 0))
|
||
except:
|
||
continue
|
||
|
||
totals_row = [
|
||
"TOTAL", "", "", "", "", "",
|
||
total_basic_amount, "", "", "", "", total_tds_amount, total_sd_amount,
|
||
total_on_commission, "", ""
|
||
]
|
||
if total_hold_amount_dynamic:
|
||
totals_row += [total_hold_amount_dynamic] + [""] * (len(hold_headers) - 1)
|
||
totals_row += [
|
||
total_final_amount,
|
||
total_payment_amount,
|
||
total_tds_payment_amount,
|
||
total_total_paid,
|
||
""
|
||
]
|
||
|
||
sheet.append([])
|
||
sheet.append(totals_row)
|
||
|
||
# Summary
|
||
# summary_hold = Decimal('0.00')
|
||
# for d in invoices:
|
||
# summary_hold += Decimal(str(d.get('SD_Amount', 0))) + Decimal(str(d.get('On_Commission', 0))) + Decimal(str(d.get('Hydro_Testing', 0)))
|
||
# for h in hold_amounts:
|
||
# summary_hold += Decimal(str(h.get('hold_amount', 0)))
|
||
|
||
sheet.append([])
|
||
today = datetime.today().strftime('%A, %Y-%m-%d')
|
||
sheet.append(["Contractor Name", contractor_info["Contractor_Name"]])
|
||
sheet.append(["Date", today])
|
||
sheet.append(["Description", "Amount"])
|
||
sheet.append(["Advance/Surplus", str(total_final_amount - total_total_paid)])
|
||
sheet.append(["Total Hold Amount", str(total_hold_amount_dynamic)])
|
||
sheet.append(["Amount With TDS", str(total_tds_amount)])
|
||
|
||
for cell in sheet[sheet.max_row]:
|
||
cell.font = Font(bold=True)
|
||
|
||
workbook.save(output_file)
|
||
workbook.close()
|
||
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return send_from_directory(output_folder, f"PMC_Report_{pmc_no}.xlsx", as_attachment=True)
|
||
|
||
# --------- Hold Types Controller --------------------------------------------
|
||
# Route to Add a New Hold Type
|
||
@app.route('/add_hold_type', methods=['POST', 'GET'])
|
||
def add_hold_type():
|
||
connection = config.get_db_connection()
|
||
cursor = connection.cursor(dictionary=True)
|
||
|
||
try:
|
||
# Fetch all hold types using the stored procedure
|
||
cursor.callproc("GetAllHoldTypes")
|
||
hold_types = []
|
||
for hold in cursor.stored_results():
|
||
hold_types = hold.fetchall()
|
||
|
||
if request.method == 'POST':
|
||
hold_type = request.form.get('hold_type', '').strip()
|
||
|
||
# Validation: Must start with a letter
|
||
if not hold_type or not hold_type[0].isalpha():
|
||
return jsonify({"status": "error", "message": "Hold Type must start with a letter."}), 400
|
||
|
||
# Validation: Check if it already exists (case-insensitive)
|
||
# cursor.execute("SELECT COUNT(*) AS count FROM hold_types WHERE LOWER(hold_type) = LOWER(%s)", (hold_type,))
|
||
# if cursor.fetchone()['count'] > 0:
|
||
# return jsonify({"status": "error", "message": "This Hold Type already exists."}), 400
|
||
# Call the procedure to check if the hold_type exists
|
||
|
||
cursor.callproc('CheckHoldTypeExists', [hold_type])
|
||
|
||
try:
|
||
# Insert new hold type into the database
|
||
# cursor.execute("INSERT INTO hold_types (hold_type) VALUES (%s)", (hold_type,))
|
||
# connection.commit()
|
||
cursor.callproc('SaveHoldType', [hold_type])
|
||
connection.commit()
|
||
|
||
return jsonify({"status": "success", "message": "Hold Type added successfully!"}), 201
|
||
except mysql.connector.Error as e:
|
||
connection.rollback()
|
||
return jsonify({"status": "error", "message": f"Database error: {str(e)}"}), 500
|
||
|
||
except mysql.connector.Error as e:
|
||
return jsonify({"status": "error", "message": f"Database error: {str(e)}"}), 500
|
||
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return render_template('add_hold_type.html', Hold_Types_data=hold_types)
|
||
|
||
|
||
# Route to Update Hold Type
|
||
# @app.route('/update_hold_type/<int:id>', methods=['POST', 'GET'])
|
||
# def update_hold_type(id):
|
||
# # GET request: Show the form with the current hold type
|
||
# if request.method == 'GET':
|
||
# connection = config.get_db_connection()
|
||
# cursor = connection.cursor()
|
||
# # cursor.execute("SELECT * FROM hold_types WHERE hold_type_id = %s", (id,))
|
||
# # hold_type = cursor.fetchone()
|
||
#
|
||
# cursor.callproc("GetHoldTypesById", (id,))
|
||
# for hold in cursor.stored_results():
|
||
# hold_type = hold.fetchone()
|
||
#
|
||
# cursor.close()
|
||
# connection.close()
|
||
#
|
||
# if not hold_type:
|
||
# return jsonify({'status': 'error', 'message': 'Hold Type not found.'}), 404
|
||
#
|
||
# return render_template('edit_hold_type.html', hold_type=hold_type)
|
||
#
|
||
# # POST request: Update the hold type
|
||
# if request.method == 'POST':
|
||
# new_hold_type = request.form.get('hold_type').strip()
|
||
#
|
||
# # Validation: Must start with a letter
|
||
# if not new_hold_type or not new_hold_type[0].isalpha():
|
||
# return jsonify(ResponseHandler.invalid_name('Hold Type')), 400
|
||
#
|
||
# connection = config.get_db_connection()
|
||
# cursor = connection.cursor()
|
||
#
|
||
# try:
|
||
# # Check if the hold type exists before updating
|
||
# # cursor.execute("SELECT * FROM hold_types WHERE hold_type_id = %s", (id,))
|
||
# # hold_type = cursor.fetchone()
|
||
# cursor.callproc("GetHoldTypesById", (id,))
|
||
# for hold in cursor.stored_results():
|
||
# hold_type = hold.fetchone()
|
||
#
|
||
# if not hold_type:
|
||
# return jsonify({'status': 'error', 'message': 'Hold Type not found.'}), 404
|
||
#
|
||
# # Update the hold type
|
||
# # cursor.execute("UPDATE hold_types SET hold_type = %s WHERE hold_type_id = %s", (new_hold_type, id))
|
||
# cursor.callproc("UpdateHoldTypeById", (id,new_hold_type))
|
||
# connection.commit()
|
||
# return jsonify(ResponseHandler.update_success('Hold Type'))
|
||
#
|
||
# except mysql.connector.Error as e:
|
||
# connection.rollback()
|
||
# return jsonify(ResponseHandler.update_failure('Hold Type')), 500
|
||
# finally:
|
||
# cursor.close()
|
||
# connection.close()
|
||
|
||
|
||
@app.route('/update_hold_type/<int:id>', methods=['GET', 'POST'])
|
||
def update_hold_type(id):
|
||
connection = config.get_db_connection()
|
||
cursor = connection.cursor()
|
||
|
||
if request.method == 'GET':
|
||
cursor.callproc("GetHoldTypesById", (id,))
|
||
for hold in cursor.stored_results():
|
||
hold_type = hold.fetchone()
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
if not hold_type:
|
||
flash('Hold Type not found.', 'error')
|
||
return redirect(url_for('add_hold_type'))
|
||
|
||
return render_template('edit_hold_type.html', hold_type=hold_type)
|
||
|
||
elif request.method == 'POST':
|
||
new_hold_type = request.form.get('hold_type', '').strip()
|
||
|
||
if not new_hold_type or not new_hold_type[0].isalpha():
|
||
flash('Invalid hold type name. Must start with a letter.', 'error')
|
||
return redirect(url_for('add_hold_type'))
|
||
|
||
try:
|
||
cursor.callproc("GetHoldTypesById", (id,))
|
||
for h in cursor.stored_results():
|
||
hold_type = h.fetchone()
|
||
|
||
if not hold_type:
|
||
flash('Hold Type not found.', 'error')
|
||
return redirect(url_for('add_hold_type'))
|
||
|
||
cursor.callproc("UpdateHoldTypeById", (id, new_hold_type))
|
||
connection.commit()
|
||
flash('Hold Type updated successfully!', 'success')
|
||
|
||
except mysql.connector.Error as e:
|
||
connection.rollback()
|
||
flash('Failed to update Hold Type.', 'error')
|
||
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
return redirect(url_for('add_hold_type'))
|
||
|
||
|
||
|
||
# Route to Delete Hold Type
|
||
@app.route('/delete_hold_type/<int:id>', methods=['POST'])
|
||
def delete_hold_type(id):
|
||
connection = config.get_db_connection()
|
||
cursor = connection.cursor()
|
||
|
||
try:
|
||
# cursor.execute("SELECT * FROM hold_types WHERE hold_type_id = %s", (id,))
|
||
# hold_type = cursor.fetchone()
|
||
cursor.callproc("GetHoldTypesById", (id,))
|
||
for hold in cursor.stored_results():
|
||
hold_type = hold.fetchone()
|
||
|
||
if not hold_type:
|
||
return jsonify({'status': 'error', 'message': 'Hold Type not found.'}), 404
|
||
|
||
# Proceed with deletion
|
||
# cursor.execute("DELETE FROM hold_types WHERE hold_type_id = %s", (id,))
|
||
cursor.callproc("DeleteHoldType", (id,))
|
||
connection.commit()
|
||
return jsonify(ResponseHandler.delete_success('Hold Type'))
|
||
|
||
except mysql.connector.Error as e:
|
||
return jsonify(ResponseHandler.delete_failure('Hold Type')), 500
|
||
finally:
|
||
cursor.close()
|
||
connection.close()
|
||
|
||
|
||
# -- end hold types controlller --------------------
|
||
|
||
|
||
if __name__ == '__main__':
|
||
app.run(host='0.0.0.0', port=5000, debug=True)
|
||
|