244 lines
7.2 KiB
Python
244 lines
7.2 KiB
Python
import matplotlib
|
|
matplotlib.use("Agg")
|
|
|
|
from flask import Blueprint, render_template, session, redirect, url_for, jsonify, request
|
|
import matplotlib.pyplot as plt
|
|
import io
|
|
import base64
|
|
from app.utils.plot_utils import plot_to_base64
|
|
from app.services.dashboard_service import DashboardService
|
|
from sqlalchemy import func
|
|
from app import db
|
|
from app.models.trench_excavation_model import TrenchExcavation
|
|
from app.models.manhole_excavation_model import ManholeExcavation
|
|
from app.models.laying_model import Laying
|
|
|
|
from app.models.subcontractor_model import Subcontractor
|
|
|
|
dashboard_bp = Blueprint("dashboard", __name__, url_prefix="/dashboard")
|
|
|
|
|
|
@dashboard_bp.route("/")
|
|
def dashboard():
|
|
if not session.get("user_id"):
|
|
return redirect(url_for("auth.login"))
|
|
return render_template("dashboard.html", title="Business Intelligence Dashboard")
|
|
|
|
|
|
@dashboard_bp.route("/api/live-stats")
|
|
def live_stats():
|
|
try:
|
|
# 1. Overall Volume
|
|
t_count = TrenchExcavation.query.count()
|
|
m_count = ManholeExcavation.query.count()
|
|
l_count = Laying.query.count()
|
|
|
|
# 2. Location Distribution (Business reach)
|
|
loc_results = db.session.query(
|
|
TrenchExcavation.Location,
|
|
func.count(TrenchExcavation.id)
|
|
).group_by(TrenchExcavation.Location).all()
|
|
|
|
# 3. Work Timeline (Business productivity trend)
|
|
# Assuming your models have a 'created_at' field
|
|
timeline_results = db.session.query(
|
|
func.date(TrenchExcavation.created_at),
|
|
func.count(TrenchExcavation.id)
|
|
).group_by(func.date(TrenchExcavation.created_at)).order_by(func.date(TrenchExcavation.created_at)).all()
|
|
|
|
return jsonify({
|
|
"summary": {
|
|
"trench": t_count,
|
|
"manhole": m_count,
|
|
"laying": l_count,
|
|
"total": t_count + m_count + l_count
|
|
},
|
|
"locations": {row[0]: row[1] for row in loc_results if row[0]},
|
|
"timeline": {str(row[0]): row[1] for row in timeline_results}
|
|
})
|
|
except Exception as e:
|
|
return jsonify({"error": str(e)}), 500
|
|
|
|
|
|
|
|
|
|
# subcontractor dashboard
|
|
@dashboard_bp.route("/subcontractor_dashboard")
|
|
def subcontractor_dashboard():
|
|
|
|
if not session.get("user_id"):
|
|
return redirect(url_for("auth.login"))
|
|
|
|
subcontractors = Subcontractor.query.all()
|
|
|
|
return render_template(
|
|
"subcontractor_dashboard.html",
|
|
subcontractors=subcontractors
|
|
)
|
|
|
|
# ✅ API: Get Unique RA Bills
|
|
@dashboard_bp.route("/api/get-ra-bills")
|
|
def get_ra_bills():
|
|
|
|
subcontractor_id = request.args.get("subcontractor")
|
|
category = request.args.get("category")
|
|
|
|
if not subcontractor_id or not category:
|
|
return {"ra_bills": []}
|
|
|
|
match category:
|
|
|
|
case "trench_excavation":
|
|
results = db.session.query(
|
|
TrenchExcavation.RA_Bill_No
|
|
).filter(
|
|
TrenchExcavation.subcontractor_id == subcontractor_id
|
|
).distinct().order_by(TrenchExcavation.RA_Bill_No).all()
|
|
|
|
# (Add others same pattern later)
|
|
case _:
|
|
results = []
|
|
|
|
ra_bills = [r[0] for r in results if r[0]]
|
|
|
|
return {"ra_bills": ra_bills}
|
|
|
|
|
|
# API FOR CHART DATA
|
|
# @dashboard_bp.route("/api/subcontractor-chart")
|
|
# def subcontractor_chart():
|
|
|
|
# subcontractor_id = request.args.get("subcontractor")
|
|
# category = request.args.get("category")
|
|
# ra_bill = request.args.get("ra_bill")
|
|
|
|
# labels = []
|
|
# values = []
|
|
|
|
# match category:
|
|
|
|
# # ✅ Trench
|
|
# case "trench_excavation":
|
|
# query = db.session.query(
|
|
# TrenchExcavation.excavation_category,
|
|
# func.sum(TrenchExcavation.Total)
|
|
# )
|
|
|
|
# if subcontractor_id:
|
|
# query = query.filter(TrenchExcavation.subcontractor_id == subcontractor_id)
|
|
|
|
# if ra_bill:
|
|
# query = query.filter(TrenchExcavation.RA_Bill_No == ra_bill)
|
|
|
|
# results = query.group_by(TrenchExcavation.excavation_category).all()
|
|
|
|
# # ✅ Manhole
|
|
# case "manhole_excavation":
|
|
# query = db.session.query(
|
|
# ManholeExcavation.excavation_category,
|
|
# func.sum(ManholeExcavation.Total)
|
|
# )
|
|
|
|
# if subcontractor_id:
|
|
# query = query.filter(ManholeExcavation.subcontractor_id == subcontractor_id)
|
|
|
|
# if ra_bill:
|
|
# query = query.filter(ManholeExcavation.RA_Bill_No == ra_bill)
|
|
|
|
# results = query.group_by(ManholeExcavation.excavation_category).all()
|
|
|
|
# case _:
|
|
# results = []
|
|
|
|
# for r in results:
|
|
# labels.append(r[0])
|
|
# values.append(float(r[1] or 0))
|
|
|
|
# return jsonify({
|
|
# "labels": labels,
|
|
# "values": values
|
|
# })
|
|
|
|
|
|
@dashboard_bp.route("/api/trench-analysis")
|
|
def trench_analysis():
|
|
|
|
subcontractor_id = request.args.get("subcontractor")
|
|
ra_bill = request.args.get("ra_bill")
|
|
|
|
query = TrenchExcavation.query
|
|
|
|
if subcontractor_id:
|
|
query = query.filter(TrenchExcavation.subcontractor_id == subcontractor_id)
|
|
|
|
if ra_bill:
|
|
query = query.filter(TrenchExcavation.RA_Bill_No == ra_bill)
|
|
|
|
data = query.all()
|
|
|
|
result = {
|
|
"Soft Murum": {"depth": 0, "qty": 0},
|
|
"Hard Murum": {"depth": 0, "qty": 0},
|
|
"Soft Rock": {"depth": 0, "qty": 0},
|
|
"Hard Rock": {"depth": 0, "qty": 0},
|
|
}
|
|
|
|
for r in data:
|
|
|
|
# Soft Murum
|
|
result["Soft Murum"]["depth"] += (
|
|
(r.Soft_Murum_0_to_1_5 or 0) +
|
|
(r.Soft_Murum_1_5_to_3_0 or 0) +
|
|
(r.Soft_Murum_3_0_to_4_5 or 0)
|
|
)
|
|
result["Soft Murum"]["qty"] += (
|
|
(r.Soft_Murum_0_to_1_5_total or 0) +
|
|
(r.Soft_Murum_1_5_to_3_0_total or 0) +
|
|
(r.Soft_Murum_3_0_to_4_5_total or 0)
|
|
)
|
|
|
|
# Hard Murum
|
|
result["Hard Murum"]["depth"] += (
|
|
(r.Hard_Murum_0_to_1_5 or 0) +
|
|
(r.Hard_Murum_1_5_to_3_0 or 0)
|
|
)
|
|
result["Hard Murum"]["qty"] += (
|
|
(r.Hard_Murum_0_to_1_5_total or 0) +
|
|
(r.Hard_Murum_1_5_and_above_total or 0)
|
|
)
|
|
|
|
# Soft Rock
|
|
result["Soft Rock"]["depth"] += (
|
|
(r.Soft_Rock_0_to_1_5 or 0) +
|
|
(r.Soft_Rock_1_5_to_3_0 or 0)
|
|
)
|
|
result["Soft Rock"]["qty"] += (
|
|
(r.Soft_Rock_0_to_1_5_total or 0) +
|
|
(r.Soft_Rock_1_5_and_above_total or 0)
|
|
)
|
|
|
|
# Hard Rock
|
|
result["Hard Rock"]["depth"] += (
|
|
(r.Hard_Rock_0_to_1_5 or 0) +
|
|
(r.Hard_Rock_1_5_to_3_0 or 0) +
|
|
(r.Hard_Rock_3_0_to_4_5 or 0) +
|
|
(r.Hard_Rock_4_5_to_6_0 or 0) +
|
|
(r.Hard_Rock_6_0_to_7_5 or 0)
|
|
)
|
|
result["Hard Rock"]["qty"] += (
|
|
(r.Hard_Rock_0_to_1_5_total or 0) +
|
|
(r.Hard_Rock_1_5_to_3_0_total or 0) +
|
|
(r.Hard_Rock_3_0_to_4_5_total or 0) +
|
|
(r.Hard_Rock_4_5_to_6_0_total or 0) +
|
|
(r.Hard_Rock_6_0_to_7_5_total or 0)
|
|
)
|
|
|
|
labels = list(result.keys())
|
|
depth = [result[k]["depth"] for k in labels]
|
|
qty = [result[k]["qty"] for k in labels]
|
|
|
|
return jsonify({
|
|
"labels": labels,
|
|
"depth": depth,
|
|
"qty": qty
|
|
}) |