2723 lines
70 KiB
Python
2723 lines
70 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.utils.helpers import login_required
|
|
from app.services.dashboard_service import DashboardService
|
|
from sqlalchemy import func
|
|
from app import db
|
|
from sqlalchemy import tuple_
|
|
|
|
# Subcontractor models import
|
|
from app.models.subcontractor_model import Subcontractor
|
|
from app.models.trench_excavation_model import TrenchExcavation
|
|
from app.models.manhole_excavation_model import ManholeExcavation
|
|
from app.models.manhole_domestic_chamber_model import ManholeDomesticChamber
|
|
from app.models.laying_model import Laying
|
|
from app.models.subcontractor_rate_model import SubcontractorRate
|
|
|
|
# client models import
|
|
from app.models.tr_ex_client_model import TrenchExcavationClient
|
|
from app.models.mh_ex_client_model import ManholeExcavationClient
|
|
from app.models.mh_dc_client_model import ManholeDomesticChamberClient
|
|
from app.models.laying_client_model import LayingClient
|
|
from app.models.client_rate_model import ClientRate
|
|
|
|
# Services
|
|
from app.services.subcontractor_rate_service import SubcontractorRateService
|
|
from app.services.client_rate_service import ClientRateService
|
|
|
|
|
|
|
|
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")
|
|
@login_required
|
|
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")
|
|
@login_required
|
|
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")
|
|
@login_required
|
|
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 "manhole_excavation":
|
|
results = db.session.query(
|
|
ManholeExcavation.RA_Bill_No
|
|
).filter(
|
|
ManholeExcavation.subcontractor_id == subcontractor_id
|
|
).distinct().order_by(ManholeExcavation.RA_Bill_No).all()
|
|
|
|
case "Manhole_Domestic_Chamber":
|
|
results = db.session.query(
|
|
ManholeDomesticChamber.RA_Bill_No
|
|
).filter(
|
|
ManholeDomesticChamber.subcontractor_id == subcontractor_id
|
|
).distinct().order_by(ManholeDomesticChamber.RA_Bill_No).all()
|
|
|
|
case "Laying":
|
|
results = db.session.query(
|
|
Laying.RA_Bill_No
|
|
).filter(
|
|
Laying.subcontractor_id == subcontractor_id
|
|
).distinct().order_by(Laying.RA_Bill_No).all()
|
|
|
|
ra_bills = [r[0] for r in results if r[0]]
|
|
|
|
return {"ra_bills": ra_bills}
|
|
|
|
|
|
def total(records, field):
|
|
return float(sum(getattr(r, field) or 0 for r in records))
|
|
|
|
# category= trench_excavation
|
|
# @dashboard_bp.route("/api/tr-analysis")
|
|
# def trench_analysis():
|
|
|
|
# subcontractor_id = request.args.get("subcontractor", "").strip()
|
|
# ra_bill = request.args.get("ra_bill", "").strip()
|
|
|
|
# # Convert "1,2,3" -> ["1", "2", "3"]
|
|
# ra_bill_list = []
|
|
# if ra_bill:
|
|
# ra_bill_list = [x.strip() for x in ra_bill.split(",") if x.strip()]
|
|
|
|
# # Subcontractor Query
|
|
# sub_query = TrenchExcavation.query
|
|
# if subcontractor_id:
|
|
# sub_query = sub_query.filter(
|
|
# TrenchExcavation.subcontractor_id == int(subcontractor_id)
|
|
# )
|
|
|
|
# if ra_bill_list:
|
|
# sub_query = sub_query.filter(
|
|
# TrenchExcavation.RA_Bill_No.in_(ra_bill_list)
|
|
# )
|
|
|
|
# sub_records = sub_query.all()
|
|
|
|
# sub_keys = [
|
|
# (
|
|
# (r.MH_NO or "").strip().upper(),
|
|
# (r.Location or "").strip().upper()
|
|
# )
|
|
# for r in sub_records
|
|
# ]
|
|
|
|
# client_query = TrenchExcavationClient.query
|
|
|
|
# if sub_keys:
|
|
|
|
# client_query = client_query.filter(
|
|
# tuple_(
|
|
# func.upper(func.trim(TrenchExcavationClient.MH_NO)),
|
|
# func.upper(func.trim(TrenchExcavationClient.Location))
|
|
# ).in_(sub_keys)
|
|
|
|
# )
|
|
|
|
# client_records = client_query.all()
|
|
|
|
# chart_data = [
|
|
# {
|
|
# "label": "Marshi 0 to 1.5",
|
|
# "client": total(client_records, "Marshi_Muddy_Slushy_0_to_1_5_total"),
|
|
# "sub": 0
|
|
# },
|
|
# {
|
|
# "label": "Marshi 1.5 to 3.0",
|
|
# "client": total(client_records, "Marshi_Muddy_Slushy_1_5_to_3_0_total"),
|
|
# "sub": 0
|
|
# },
|
|
# {
|
|
# "label": "Marshi 3.0 to 4.5",
|
|
# "client": total(client_records, "Marshi_Muddy_Slushy_3_0_to_4_5_total"),
|
|
# "sub": 0
|
|
# },
|
|
|
|
# {
|
|
# "label": "Soft Murum 0 to 1.5",
|
|
# "client": total(client_records, "Soft_Murum_0_to_1_5_total"),
|
|
# "sub": total(sub_records, "Soft_Murum_0_to_1_5_total")
|
|
# },
|
|
# {
|
|
# "label": "Soft Murum 1.5 to 3.0",
|
|
# "client": total(client_records, "Soft_Murum_1_5_to_3_0_total"),
|
|
# "sub": total(sub_records, "Soft_Murum_1_5_to_3_0_total")
|
|
# },
|
|
# {
|
|
# "label": "Soft Murum 3.0 to 4.5",
|
|
# "client": total(client_records, "Soft_Murum_3_0_to_4_5_total"),
|
|
# "sub": total(sub_records, "Soft_Murum_3_0_to_4_5_total")
|
|
# },
|
|
|
|
# {
|
|
# "label": "Hard Murum 0 to 1.5",
|
|
# "client": total(client_records, "Hard_Murum_0_to_1_5_total"),
|
|
# "sub": total(sub_records, "Hard_Murum_0_to_1_5_total")
|
|
# },
|
|
# {
|
|
# "label": "Hard Murum 1.5 to 3.0",
|
|
# "client": total(client_records, "Hard_Murum_1_5_to_3_0_total"),
|
|
# "sub": total(sub_records, "Hard_Murum_1_5_and_above_total")
|
|
# },
|
|
|
|
# {
|
|
# "label": "Soft Rock 0 to 1.5",
|
|
# "client": total(client_records, "Soft_Rock_0_to_1_5_total"),
|
|
# "sub": total(sub_records, "Soft_Rock_0_to_1_5_total")
|
|
# },
|
|
# {
|
|
# "label": "Soft Rock 1.5 to 3.0",
|
|
# "client": total(client_records, "Soft_Rock_1_5_to_3_0_total"),
|
|
# "sub": total(sub_records, "Soft_Rock_1_5_and_above_total")
|
|
# },
|
|
|
|
# {
|
|
# "label": "Hard Rock 0 to 1.5",
|
|
# "client": total(client_records, "Hard_Rock_0_to_1_5_total"),
|
|
# "sub": total(sub_records, "Hard_Rock_0_to_1_5_total")
|
|
# },
|
|
# {
|
|
# "label": "Hard Rock 1.5 to 3.0",
|
|
# "client": total(client_records, "Hard_Rock_1_5_to_3_0_total"),
|
|
# "sub": total(sub_records, "Hard_Rock_1_5_to_3_0_total")
|
|
# },
|
|
# {
|
|
# "label": "Hard Rock 3.0 to 4.5",
|
|
# "client": total(client_records, "Hard_Rock_3_0_to_4_5_total"),
|
|
# "sub": total(sub_records, "Hard_Rock_3_0_to_4_5_total")
|
|
# },
|
|
# {
|
|
# "label": "Hard Rock 4.5 to 6.0",
|
|
# "client": total(client_records, "Hard_Rock_4_5_to_6_0_total"),
|
|
# "sub": total(sub_records, "Hard_Rock_4_5_to_6_0_total")
|
|
# },
|
|
# {
|
|
# "label": "Hard Rock 6.0 to 7.5",
|
|
# "client": total(client_records, "Hard_Rock_6_0_to_7_5_total"),
|
|
# "sub": total(sub_records, "Hard_Rock_6_0_to_7_5_total")
|
|
# }
|
|
# ]
|
|
|
|
# return jsonify({
|
|
# "title": "Trench Excavation Comparison",
|
|
# "y_title": "Excavation Qty (Cum)",
|
|
# "labels": [x["label"] for x in chart_data],
|
|
# "client_qty": [x["client"] for x in chart_data],
|
|
# "sub_qty": [x["sub"] for x in chart_data]
|
|
# })
|
|
|
|
# # category = manhole_excavation
|
|
# @dashboard_bp.route("/api/mh-analysis")
|
|
# def manhole_analysis():
|
|
|
|
# subcontractor_id = request.args.get("subcontractor", "").strip()
|
|
# ra_bill = request.args.get("ra_bill", "").strip()
|
|
|
|
# # Convert "1,2,3" -> ["1", "2", "3"]
|
|
# ra_bill_list = []
|
|
# if ra_bill:
|
|
# ra_bill_list = [x.strip() for x in ra_bill.split(",") if x.strip()]
|
|
|
|
# # Subcontractor Query
|
|
# sub_query = ManholeExcavation.query
|
|
# if subcontractor_id:
|
|
# sub_query = sub_query.filter(
|
|
# ManholeExcavation.subcontractor_id == int(subcontractor_id)
|
|
# )
|
|
|
|
# if ra_bill_list:
|
|
# sub_query = sub_query.filter(
|
|
# ManholeExcavation.RA_Bill_No.in_(ra_bill_list)
|
|
# )
|
|
|
|
# sub_records = sub_query.all()
|
|
|
|
# sub_keys = [
|
|
# (
|
|
# (r.MH_NO or "").strip().upper(),
|
|
# (r.Location or "").strip().upper()
|
|
# )
|
|
# for r in sub_records
|
|
# ]
|
|
|
|
# client_query = ManholeExcavationClient.query
|
|
|
|
# if sub_keys:
|
|
|
|
# client_query = client_query.filter(
|
|
# tuple_(
|
|
# func.upper(func.trim(ManholeExcavationClient.MH_NO)),
|
|
# func.upper(func.trim(ManholeExcavationClient.Location))
|
|
# ).in_(sub_keys)
|
|
|
|
# )
|
|
|
|
# client_records = client_query.all()
|
|
|
|
# chart_data = [
|
|
# {
|
|
# "label": "Marshi 0 to 1.5",
|
|
# "client": total(client_records, "Marshi_Muddy_Slushy_0_to_1_5_total"),
|
|
# "sub": 0
|
|
# },
|
|
# {
|
|
# "label": "Marshi 1.5 to 3.0",
|
|
# "client": total(client_records, "Marshi_Muddy_Slushy_1_5_to_3_0_total"),
|
|
# "sub": 0
|
|
# },
|
|
# {
|
|
# "label": "Marshi 3.0 to 4.5",
|
|
# "client": total(client_records, "Marshi_Muddy_Slushy_3_0_to_4_5_total"),
|
|
# "sub": 0
|
|
# },
|
|
|
|
# {
|
|
# "label": "Soft Murum 0 to 1.5",
|
|
# "client": total(client_records, "Soft_Murum_0_to_1_5_total"),
|
|
# "sub": total(sub_records, "Soft_Murum_0_to_1_5_total")
|
|
# },
|
|
# {
|
|
# "label": "Soft Murum 1.5 to 3.0",
|
|
# "client": total(client_records, "Soft_Murum_1_5_to_3_0_total"),
|
|
# "sub": total(sub_records, "Soft_Murum_1_5_to_3_0_total")
|
|
# },
|
|
# {
|
|
# "label": "Soft Murum 3.0 to 4.5",
|
|
# "client": total(client_records, "Soft_Murum_3_0_to_4_5_total"),
|
|
# "sub": total(sub_records, "Soft_Murum_3_0_to_4_5_total")
|
|
# },
|
|
|
|
# {
|
|
# "label": "Hard Murum 0 to 1.5",
|
|
# "client": total(client_records, "Hard_Murum_0_to_1_5_total"),
|
|
# "sub": total(sub_records, "Hard_Murum_0_to_1_5_total")
|
|
# },
|
|
# {
|
|
# "label": "Hard Murum 1.5 to 3.0",
|
|
# "client": total(client_records, "Hard_Murum_1_5_to_3_0_total"),
|
|
# "sub": total(sub_records, "Hard_Murum_1_5_and_above_total")
|
|
# },
|
|
|
|
# {
|
|
# "label": "Soft Rock 0 to 1.5",
|
|
# "client": total(client_records, "Soft_Rock_0_to_1_5_total"),
|
|
# "sub": total(sub_records, "Soft_Rock_0_to_1_5_total")
|
|
# },
|
|
# {
|
|
# "label": "Soft Rock 1.5 to 3.0",
|
|
# "client": total(client_records, "Soft_Rock_1_5_to_3_0_total"),
|
|
# "sub": total(sub_records, "Soft_Rock_1_5_and_above_total")
|
|
# },
|
|
|
|
# {
|
|
# "label": "Hard Rock 0 to 1.5",
|
|
# "client": total(client_records, "Hard_Rock_0_to_1_5_total"),
|
|
# "sub": total(sub_records, "Hard_Rock_0_to_1_5_total")
|
|
# },
|
|
# {
|
|
# "label": "Hard Rock 1.5 to 3.0",
|
|
# "client": total(client_records, "Hard_Rock_1_5_to_3_0_total"),
|
|
# "sub": total(sub_records, "Hard_Rock_1_5_to_3_0_total")
|
|
# },
|
|
# {
|
|
# "label": "Hard Rock 3.0 to 4.5",
|
|
# "client": total(client_records, "Hard_Rock_3_0_to_4_5_total"),
|
|
# "sub": total(sub_records, "Hard_Rock_3_0_to_4_5_total")
|
|
# },
|
|
# {
|
|
# "label": "Hard Rock 4.5 to 6.0",
|
|
# "client": total(client_records, "Hard_Rock_4_5_to_6_0_total"),
|
|
# "sub": total(sub_records, "Hard_Rock_4_5_to_6_0_total")
|
|
# },
|
|
# {
|
|
# "label": "Hard Rock 6.0 to 7.5",
|
|
# "client": total(client_records, "Hard_Rock_6_0_to_7_5_total"),
|
|
# "sub": total(sub_records, "Hard_Rock_6_0_to_7_5_total")
|
|
# }
|
|
# ]
|
|
|
|
# return jsonify({
|
|
# "title": "Manhole Excavation Comparison",
|
|
# "y_title": "Manhole Qty (Nos)",
|
|
# "labels": [x["label"] for x in chart_data],
|
|
# "client_qty": [x["client"] for x in chart_data],
|
|
# "sub_qty": [x["sub"] for x in chart_data]
|
|
# })
|
|
|
|
|
|
|
|
# category = Manhole_Domestic_Chamber
|
|
# @dashboard_bp.route("/api/mdc-analysis")
|
|
# def Manhole_Domestic_Chamber_analysis():
|
|
|
|
# subcontractor_id = request.args.get("subcontractor", "").strip()
|
|
# ra_bill = request.args.get("ra_bill", "").strip()
|
|
|
|
# # Convert "1,2,3" -> ["1", "2", "3"]
|
|
# ra_bill_list = []
|
|
# if ra_bill:
|
|
# ra_bill_list = [x.strip() for x in ra_bill.split(",") if x.strip()]
|
|
|
|
# # Subcontractor Query
|
|
# sub_query = ManholeDomesticChamber.query
|
|
# if subcontractor_id:
|
|
# sub_query = sub_query.filter(
|
|
# ManholeDomesticChamber.subcontractor_id == int(subcontractor_id)
|
|
# )
|
|
|
|
# if ra_bill_list:
|
|
# sub_query = sub_query.filter(
|
|
# ManholeDomesticChamber.RA_Bill_No.in_(ra_bill_list)
|
|
# )
|
|
|
|
# sub_records = sub_query.all()
|
|
|
|
# sub_keys = [
|
|
# (
|
|
# (r.MH_NO or "").strip().upper(),
|
|
# (r.Location or "").strip().upper()
|
|
# )
|
|
# for r in sub_records
|
|
# ]
|
|
|
|
# client_query = ManholeDomesticChamberClient.query
|
|
|
|
# if sub_keys:
|
|
|
|
# client_query = client_query.filter(
|
|
# tuple_(
|
|
# func.upper(func.trim(ManholeDomesticChamberClient.MH_NO)),
|
|
# func.upper(func.trim(ManholeDomesticChamberClient.Location))
|
|
# ).in_(sub_keys)
|
|
|
|
# )
|
|
|
|
# client_records = client_query.all()
|
|
|
|
# chart_data = [
|
|
# {
|
|
# "label": "Depth of MH",
|
|
# "client": total(client_records, "Depth_of_MH"),
|
|
# "sub": total(sub_records, "Depth_of_MH")
|
|
# },
|
|
# {
|
|
# "label": "Domestic_Chambers Total",
|
|
# "client": total(client_records, "Total"),
|
|
# "sub": total(sub_records, "Total")
|
|
# }
|
|
# ]
|
|
|
|
# return jsonify({
|
|
# "title": "Domestic Chamber Comparison",
|
|
# "y_title": "Quantity (Nos)",
|
|
# "labels": [x["label"] for x in chart_data],
|
|
# "client_qty": [x["client"] for x in chart_data],
|
|
# "sub_qty": [x["sub"] for x in chart_data]
|
|
# })
|
|
|
|
|
|
|
|
# # category = Laying
|
|
# @dashboard_bp.route("/api/laying-analysis")
|
|
# def laying_analysis():
|
|
|
|
# subcontractor_id = request.args.get("subcontractor", "").strip()
|
|
# ra_bill = request.args.get("ra_bill", "").strip()
|
|
|
|
# # Convert "1,2,3" -> ["1", "2", "3"]
|
|
# ra_bill_list = []
|
|
# if ra_bill:
|
|
# ra_bill_list = [x.strip() for x in ra_bill.split(",") if x.strip()]
|
|
|
|
# # Subcontractor Query
|
|
# sub_query = Laying.query
|
|
# if subcontractor_id:
|
|
# sub_query = sub_query.filter(
|
|
# Laying.subcontractor_id == int(subcontractor_id)
|
|
# )
|
|
|
|
# if ra_bill_list:
|
|
# sub_query = sub_query.filter(
|
|
# Laying.RA_Bill_No.in_(ra_bill_list)
|
|
# )
|
|
|
|
# sub_records = sub_query.all()
|
|
|
|
# sub_keys = [
|
|
# (
|
|
# (r.MH_NO or "").strip().upper(),
|
|
# (r.Location or "").strip().upper()
|
|
# )
|
|
# for r in sub_records
|
|
# ]
|
|
|
|
# client_query = LayingClient.query
|
|
|
|
# if sub_keys:
|
|
|
|
# client_query = client_query.filter(
|
|
# tuple_(
|
|
# func.upper(func.trim(LayingClient.MH_NO)),
|
|
# func.upper(func.trim(LayingClient.Location))
|
|
# ).in_(sub_keys)
|
|
|
|
# )
|
|
|
|
# client_records = client_query.all()
|
|
|
|
# chart_data = [
|
|
# {
|
|
# "label": "150 mm",
|
|
# "client": total(client_records, "pipe_150_mm"),
|
|
# "sub": total(sub_records, "pipe_150_mm")
|
|
# },
|
|
# {
|
|
# "label": "200 mm",
|
|
# "client": total(client_records, "pipe_200_mm"),
|
|
# "sub": total(sub_records, "pipe_200_mm")
|
|
# },
|
|
# {
|
|
# "label": "250 mm",
|
|
# "client": total(client_records, "pipe_250_mm"),
|
|
# "sub": total(sub_records, "pipe_250_mm")
|
|
# },
|
|
|
|
# {
|
|
# "label": "300 mm",
|
|
# "client": total(client_records, "pipe_300_mm"),
|
|
# "sub": total(sub_records, "pipe_300_mm")
|
|
# },
|
|
# {
|
|
# "label": "350 mm",
|
|
# "client": total(client_records, "pipe_350_mm"),
|
|
# "sub": total(sub_records, "pipe_350_mm")
|
|
# },
|
|
|
|
# {
|
|
# "label": "400 mm",
|
|
# "client": total(client_records, "pipe_400_mm"),
|
|
# "sub": total(sub_records, "pipe_400_mm")
|
|
# },
|
|
# {
|
|
# "label": "450 mm",
|
|
# "client": total(client_records, "pipe_450_mm"),
|
|
# "sub": total(sub_records, "pipe_450_mm")
|
|
# },
|
|
|
|
# {
|
|
# "label": "500 mm",
|
|
# "client": total(client_records, "pipe_500_mm"),
|
|
# "sub": total(sub_records, "pipe_500_mm")
|
|
# },
|
|
# {
|
|
# "label": "600 mm",
|
|
# "client": total(client_records, "pipe_600_mm"),
|
|
# "sub": total(sub_records, "pipe_600_mm")
|
|
# },
|
|
# {
|
|
# "label": "700 mm",
|
|
# "client": total(client_records, "pipe_700_mm"),
|
|
# "sub": total(sub_records, "pipe_700_mm")
|
|
# },
|
|
# {
|
|
# "label": "900 mm",
|
|
# "client": total(client_records, "pipe_900_mm"),
|
|
# "sub": total(sub_records, "pipe_900_mm")
|
|
# },
|
|
# {
|
|
# "label": "1200 mm",
|
|
# "client": total(client_records, "pipe_1200_mm"),
|
|
# "sub": total(sub_records, "pipe_1200_mm")
|
|
# }
|
|
# ]
|
|
|
|
# return jsonify({
|
|
# "title": "Pipe Laying Comparison",
|
|
# "y_title": "Pipe Length (Mtr)",
|
|
# "labels": [x["label"] for x in chart_data],
|
|
# "client_qty": [x["client"] for x in chart_data],
|
|
# "sub_qty": [x["sub"] for x in chart_data]
|
|
# })
|
|
|
|
|
|
|
|
@dashboard_bp.route("/api/tr-analysis")
|
|
def trench_analysis():
|
|
|
|
# =========================================================
|
|
# CONSTANT
|
|
# =========================================================
|
|
CATEGORY = "trench_excavation"
|
|
|
|
# =========================================================
|
|
# REQUEST PARAMETERS
|
|
# =========================================================
|
|
subcontractor_id = request.args.get(
|
|
"subcontractor",
|
|
""
|
|
).strip()
|
|
|
|
ra_bill = request.args.get(
|
|
"ra_bill",
|
|
""
|
|
).strip()
|
|
|
|
# =========================================================
|
|
# VALIDATE SUBCONTRACTOR
|
|
# =========================================================
|
|
subcontractor_id_int = None
|
|
|
|
if subcontractor_id:
|
|
|
|
try:
|
|
subcontractor_id_int = int(subcontractor_id)
|
|
|
|
except ValueError:
|
|
return jsonify({
|
|
"success": False,
|
|
"message": "Invalid subcontractor."
|
|
}), 400
|
|
|
|
# =========================================================
|
|
# RA BILL LIST
|
|
# =========================================================
|
|
ra_bill_list = []
|
|
|
|
if ra_bill:
|
|
ra_bill_list = [
|
|
bill.strip()
|
|
for bill in ra_bill.split(",")
|
|
if bill.strip()
|
|
]
|
|
|
|
# =========================================================
|
|
# SUBCONTRACTOR QUERY
|
|
# =========================================================
|
|
sub_query = TrenchExcavation.query
|
|
|
|
if subcontractor_id_int:
|
|
|
|
sub_query = sub_query.filter(
|
|
TrenchExcavation.subcontractor_id
|
|
== subcontractor_id_int
|
|
)
|
|
|
|
if ra_bill_list:
|
|
|
|
sub_query = sub_query.filter(
|
|
TrenchExcavation.RA_Bill_No.in_(ra_bill_list)
|
|
)
|
|
|
|
sub_records = sub_query.all()
|
|
|
|
# =========================================================
|
|
# SUBCONTRACTOR KEYS
|
|
# =========================================================
|
|
sub_keys = [
|
|
(
|
|
(record.MH_NO or "").strip().upper(),
|
|
(record.Location or "").strip().upper()
|
|
)
|
|
for record in sub_records
|
|
]
|
|
|
|
# =========================================================
|
|
# CLIENT QUERY
|
|
# =========================================================
|
|
client_query = TrenchExcavationClient.query
|
|
|
|
if sub_keys:
|
|
|
|
client_query = client_query.filter(
|
|
tuple_(
|
|
func.upper(
|
|
func.trim(
|
|
TrenchExcavationClient.MH_NO
|
|
)
|
|
),
|
|
func.upper(
|
|
func.trim(
|
|
TrenchExcavationClient.Location
|
|
)
|
|
)
|
|
).in_(sub_keys)
|
|
)
|
|
|
|
client_records = client_query.all()
|
|
|
|
# =========================================================
|
|
# GET CLIENT RATES
|
|
#
|
|
# Matching:
|
|
# category = trench_excavation
|
|
# item_name = actual model field name
|
|
# =========================================================
|
|
client_rates = (
|
|
ClientRate.query
|
|
.filter(
|
|
func.lower(
|
|
func.trim(ClientRate.category)
|
|
) == CATEGORY.lower(),
|
|
|
|
func.lower(
|
|
func.trim(ClientRate.status)
|
|
) == "active"
|
|
)
|
|
.all()
|
|
)
|
|
|
|
# =========================================================
|
|
# GET SUBCONTRACTOR RATES
|
|
#
|
|
# Matching:
|
|
# subcontractor_id
|
|
# category = trench_excavation
|
|
# item_name = actual model field name
|
|
# =========================================================
|
|
sub_rates = []
|
|
|
|
if subcontractor_id_int:
|
|
|
|
sub_rates = (
|
|
SubcontractorRate.query
|
|
.filter(
|
|
SubcontractorRate.subcontractor_id
|
|
== subcontractor_id_int,
|
|
|
|
func.lower(
|
|
func.trim(
|
|
SubcontractorRate.category
|
|
)
|
|
) == CATEGORY.lower(),
|
|
|
|
func.lower(
|
|
func.trim(
|
|
SubcontractorRate.status
|
|
)
|
|
) == "active"
|
|
)
|
|
.all()
|
|
)
|
|
|
|
# =========================================================
|
|
# RATE MAP
|
|
#
|
|
# Example:
|
|
#
|
|
# Hard_Rock_6_0_to_7_5_total : 600
|
|
# Hard_Rock_4_5_to_6_0_total : 600
|
|
# =========================================================
|
|
client_rate_map = {
|
|
(rate.item_name or "").strip().lower():
|
|
float(rate.rate or 0)
|
|
for rate in client_rates
|
|
}
|
|
|
|
sub_rate_map = {
|
|
(rate.item_name or "").strip().lower():
|
|
float(rate.rate or 0)
|
|
for rate in sub_rates
|
|
}
|
|
|
|
# =========================================================
|
|
# TOTAL HELPER
|
|
# =========================================================
|
|
def total(records, field):
|
|
|
|
value = 0
|
|
|
|
for record in records:
|
|
|
|
field_value = getattr(
|
|
record,
|
|
field,
|
|
0
|
|
)
|
|
|
|
if field_value is not None:
|
|
value += float(field_value)
|
|
|
|
return round(value, 2)
|
|
|
|
# =========================================================
|
|
# TRECH MAPPING
|
|
#
|
|
# label = Dashboard display name
|
|
# field = Client/Subcontractor model field
|
|
# item_name = Rate Master item_name
|
|
#
|
|
# item_name intentionally uses the actual model field name.
|
|
# =========================================================
|
|
TRENCH_MAPPING = [
|
|
|
|
{
|
|
"label": "Marshi 0 to 1.5",
|
|
"field": "Marshi_Muddy_Slushy_0_to_1_5_total",
|
|
"item_name": "Marshi_Muddy_Slushy_0_to_1_5_total"
|
|
},
|
|
|
|
{
|
|
"label": "Marshi 1.5 to 3.0",
|
|
"field": "Marshi_Muddy_Slushy_1_5_to_3_0_total",
|
|
"item_name": "Marshi_Muddy_Slushy_1_5_to_3_0_total"
|
|
},
|
|
|
|
{
|
|
"label": "Marshi 3.0 to 4.5",
|
|
"field": "Marshi_Muddy_Slushy_3_0_to_4_5_total",
|
|
"item_name": "Marshi_Muddy_Slushy_3_0_to_4_5_total"
|
|
},
|
|
|
|
{
|
|
"label": "Soft Murum 0 to 1.5",
|
|
"field": "Soft_Murum_0_to_1_5_total",
|
|
"item_name": "Soft_Murum_0_to_1_5_total"
|
|
},
|
|
|
|
{
|
|
"label": "Soft Murum 1.5 to 3.0",
|
|
"field": "Soft_Murum_1_5_to_3_0_total",
|
|
"item_name": "Soft_Murum_1_5_to_3_0_total"
|
|
},
|
|
|
|
{
|
|
"label": "Soft Murum 3.0 to 4.5",
|
|
"field": "Soft_Murum_3_0_to_4_5_total",
|
|
"item_name": "Soft_Murum_3_0_to_4_5_total"
|
|
},
|
|
|
|
{
|
|
"label": "Hard Murum 0 to 1.5",
|
|
"field": "Hard_Murum_0_to_1_5_total",
|
|
"item_name": "Hard_Murum_0_to_1_5_total"
|
|
},
|
|
|
|
{
|
|
"label": "Hard Murum 1.5 to 3.0",
|
|
"field": "Hard_Murum_1_5_to_3_0_total",
|
|
"item_name": "Hard_Murum_1_5_to_3_0_total"
|
|
},
|
|
|
|
{
|
|
"label": "Soft Rock 0 to 1.5",
|
|
"field": "Soft_Rock_0_to_1_5_total",
|
|
"item_name": "Soft_Rock_0_to_1_5_total"
|
|
},
|
|
|
|
{
|
|
"label": "Soft Rock 1.5 to 3.0",
|
|
"field": "Soft_Rock_1_5_to_3_0_total",
|
|
"item_name": "Soft_Rock_1_5_to_3_0_total"
|
|
},
|
|
|
|
{
|
|
"label": "Hard Rock 0 to 1.5",
|
|
"field": "Hard_Rock_0_to_1_5_total",
|
|
"item_name": "Hard_Rock_0_to_1_5_total"
|
|
},
|
|
|
|
{
|
|
"label": "Hard Rock 1.5 to 3.0",
|
|
"field": "Hard_Rock_1_5_to_3_0_total",
|
|
"item_name": "Hard_Rock_1_5_to_3_0_total"
|
|
},
|
|
|
|
{
|
|
"label": "Hard Rock 3.0 to 4.5",
|
|
"field": "Hard_Rock_3_0_to_4_5_total",
|
|
"item_name": "Hard_Rock_3_0_to_4_5_total"
|
|
},
|
|
|
|
{
|
|
"label": "Hard Rock 4.5 to 6.0",
|
|
"field": "Hard_Rock_4_5_to_6_0_total",
|
|
"item_name": "Hard_Rock_4_5_to_6_0_total"
|
|
},
|
|
|
|
{
|
|
"label": "Hard Rock 6.0 to 7.5",
|
|
"field": "Hard_Rock_6_0_to_7_5_total",
|
|
"item_name": "Hard_Rock_6_0_to_7_5_total"
|
|
}
|
|
]
|
|
|
|
# =========================================================
|
|
# BUILD CHART DATA
|
|
# =========================================================
|
|
chart_data = []
|
|
|
|
for mapping in TRENCH_MAPPING:
|
|
|
|
field = mapping["field"]
|
|
|
|
client_qty = total(
|
|
client_records,
|
|
field
|
|
)
|
|
|
|
# -----------------------------------------------------
|
|
# SUBCONTRACTOR QUANTITY
|
|
# -----------------------------------------------------
|
|
sub_qty = 0
|
|
|
|
if sub_records:
|
|
|
|
sub_qty = total(
|
|
sub_records,
|
|
field
|
|
)
|
|
|
|
# -----------------------------------------------------
|
|
# RATE ITEM NAME
|
|
# -----------------------------------------------------
|
|
item_name = mapping["item_name"]
|
|
|
|
rate_key = item_name.strip().lower()
|
|
|
|
# -----------------------------------------------------
|
|
# CLIENT RATE
|
|
# -----------------------------------------------------
|
|
client_rate = client_rate_map.get(
|
|
rate_key,
|
|
0
|
|
)
|
|
|
|
# -----------------------------------------------------
|
|
# SUBCONTRACTOR RATE
|
|
# -----------------------------------------------------
|
|
sub_rate = sub_rate_map.get(
|
|
rate_key,
|
|
0
|
|
)
|
|
|
|
# -----------------------------------------------------
|
|
# AMOUNT
|
|
# -----------------------------------------------------
|
|
client_amount = (
|
|
client_qty * client_rate
|
|
)
|
|
|
|
sub_amount = (
|
|
sub_qty * sub_rate
|
|
)
|
|
|
|
# -----------------------------------------------------
|
|
# DIFFERENCES
|
|
# -----------------------------------------------------
|
|
qty_difference = (
|
|
client_qty - sub_qty
|
|
)
|
|
|
|
rate_difference = (
|
|
client_rate - sub_rate
|
|
)
|
|
|
|
amount_difference = (
|
|
client_amount - sub_amount
|
|
)
|
|
|
|
# -----------------------------------------------------
|
|
# FINAL ROW
|
|
# -----------------------------------------------------
|
|
chart_data.append({
|
|
|
|
"label": mapping["label"],
|
|
|
|
# Actual model field
|
|
"field": field,
|
|
|
|
# Rate Master item_name
|
|
"item_name": item_name,
|
|
|
|
# Quantity
|
|
"client": round(
|
|
client_qty,
|
|
2
|
|
),
|
|
|
|
"sub": round(
|
|
sub_qty,
|
|
2
|
|
),
|
|
|
|
# Rate
|
|
"client_rate": round(
|
|
client_rate,
|
|
2
|
|
),
|
|
|
|
"sub_rate": round(
|
|
sub_rate,
|
|
2
|
|
),
|
|
|
|
# Amount
|
|
"client_amount": round(
|
|
client_amount,
|
|
2
|
|
),
|
|
|
|
"sub_amount": round(
|
|
sub_amount,
|
|
2
|
|
),
|
|
|
|
# Difference
|
|
"qty_difference": round(
|
|
qty_difference,
|
|
2
|
|
),
|
|
|
|
"rate_difference": round(
|
|
rate_difference,
|
|
2
|
|
),
|
|
|
|
"amount_difference": round(
|
|
amount_difference,
|
|
2
|
|
)
|
|
})
|
|
|
|
# =========================================================
|
|
# RESPONSE
|
|
# =========================================================
|
|
return jsonify({
|
|
|
|
"success": True,
|
|
|
|
"title": "Trench Excavation Comparison",
|
|
|
|
"y_title": "Excavation Qty (Cum)",
|
|
|
|
# -----------------------------------------------------
|
|
# CHART
|
|
# -----------------------------------------------------
|
|
"labels": [
|
|
item["label"]
|
|
for item in chart_data
|
|
],
|
|
|
|
"client_qty": [
|
|
item["client"]
|
|
for item in chart_data
|
|
],
|
|
|
|
"sub_qty": [
|
|
item["sub"]
|
|
for item in chart_data
|
|
],
|
|
|
|
# -----------------------------------------------------
|
|
# RATE
|
|
# -----------------------------------------------------
|
|
"client_rate": [
|
|
item["client_rate"]
|
|
for item in chart_data
|
|
],
|
|
|
|
"sub_rate": [
|
|
item["sub_rate"]
|
|
for item in chart_data
|
|
],
|
|
|
|
# -----------------------------------------------------
|
|
# AMOUNT
|
|
# -----------------------------------------------------
|
|
"client_amount": [
|
|
item["client_amount"]
|
|
for item in chart_data
|
|
],
|
|
|
|
"sub_amount": [
|
|
item["sub_amount"]
|
|
for item in chart_data
|
|
],
|
|
|
|
# -----------------------------------------------------
|
|
# DIFFERENCE
|
|
# -----------------------------------------------------
|
|
"qty_difference": [
|
|
item["qty_difference"]
|
|
for item in chart_data
|
|
],
|
|
|
|
"rate_difference": [
|
|
item["rate_difference"]
|
|
for item in chart_data
|
|
],
|
|
|
|
"amount_difference": [
|
|
item["amount_difference"]
|
|
for item in chart_data
|
|
],
|
|
|
|
# -----------------------------------------------------
|
|
# COMPLETE ROW DATA
|
|
# Useful for table/export
|
|
# -----------------------------------------------------
|
|
"rows": chart_data
|
|
})
|
|
|
|
|
|
@dashboard_bp.route("/api/mh-analysis")
|
|
def manhole_analysis():
|
|
|
|
# =========================================================
|
|
# CATEGORY
|
|
# =========================================================
|
|
CATEGORY = "manhole_excavation"
|
|
|
|
# =========================================================
|
|
# REQUEST PARAMETERS
|
|
# =========================================================
|
|
subcontractor_id = request.args.get(
|
|
"subcontractor",
|
|
""
|
|
).strip()
|
|
|
|
ra_bill = request.args.get(
|
|
"ra_bill",
|
|
""
|
|
).strip()
|
|
|
|
# =========================================================
|
|
# VALIDATE SUBCONTRACTOR
|
|
# =========================================================
|
|
subcontractor_id_int = None
|
|
|
|
if subcontractor_id:
|
|
|
|
try:
|
|
subcontractor_id_int = int(
|
|
subcontractor_id
|
|
)
|
|
|
|
except ValueError:
|
|
|
|
return jsonify({
|
|
"success": False,
|
|
"message": "Invalid subcontractor."
|
|
}), 400
|
|
|
|
# =========================================================
|
|
# RA BILL LIST
|
|
# =========================================================
|
|
ra_bill_list = []
|
|
|
|
if ra_bill:
|
|
|
|
ra_bill_list = [
|
|
bill.strip()
|
|
for bill in ra_bill.split(",")
|
|
if bill.strip()
|
|
]
|
|
|
|
# =========================================================
|
|
# SUBCONTRACTOR QUERY
|
|
# =========================================================
|
|
sub_query = ManholeExcavation.query
|
|
|
|
if subcontractor_id_int:
|
|
|
|
sub_query = sub_query.filter(
|
|
ManholeExcavation.subcontractor_id
|
|
== subcontractor_id_int
|
|
)
|
|
|
|
if ra_bill_list:
|
|
|
|
sub_query = sub_query.filter(
|
|
ManholeExcavation.RA_Bill_No.in_(
|
|
ra_bill_list
|
|
)
|
|
)
|
|
|
|
sub_records = sub_query.all()
|
|
|
|
# =========================================================
|
|
# SUBCONTRACTOR KEYS
|
|
# MH_NO + LOCATION
|
|
# =========================================================
|
|
sub_keys = [
|
|
(
|
|
(record.MH_NO or "").strip().upper(),
|
|
(record.Location or "").strip().upper()
|
|
)
|
|
for record in sub_records
|
|
]
|
|
|
|
# =========================================================
|
|
# CLIENT QUERY
|
|
# =========================================================
|
|
client_query = ManholeExcavationClient.query
|
|
|
|
if sub_keys:
|
|
|
|
client_query = client_query.filter(
|
|
|
|
tuple_(
|
|
func.upper(
|
|
func.trim(
|
|
ManholeExcavationClient.MH_NO
|
|
)
|
|
),
|
|
|
|
func.upper(
|
|
func.trim(
|
|
ManholeExcavationClient.Location
|
|
)
|
|
)
|
|
|
|
).in_(sub_keys)
|
|
)
|
|
|
|
client_records = client_query.all()
|
|
|
|
# =========================================================
|
|
# GET CLIENT RATES
|
|
#
|
|
# Category:
|
|
# manhole_excavation
|
|
#
|
|
# item_name:
|
|
# actual model field name
|
|
# =========================================================
|
|
client_rates = (
|
|
ClientRate.query
|
|
.filter(
|
|
|
|
func.lower(
|
|
func.trim(
|
|
ClientRate.category
|
|
)
|
|
) == CATEGORY.lower(),
|
|
|
|
func.lower(
|
|
func.trim(
|
|
ClientRate.status
|
|
)
|
|
) == "active"
|
|
)
|
|
.all()
|
|
)
|
|
|
|
# =========================================================
|
|
# GET SUBCONTRACTOR RATES
|
|
#
|
|
# Selected Subcontractor
|
|
# +
|
|
# Category
|
|
# +
|
|
# Active
|
|
# =========================================================
|
|
sub_rates = []
|
|
|
|
if subcontractor_id_int:
|
|
|
|
sub_rates = (
|
|
SubcontractorRate.query
|
|
.filter(
|
|
|
|
SubcontractorRate.subcontractor_id
|
|
== subcontractor_id_int,
|
|
|
|
func.lower(
|
|
func.trim(
|
|
SubcontractorRate.category
|
|
)
|
|
) == CATEGORY.lower(),
|
|
|
|
func.lower(
|
|
func.trim(
|
|
SubcontractorRate.status
|
|
)
|
|
) == "active"
|
|
)
|
|
.all()
|
|
)
|
|
|
|
# =========================================================
|
|
# RATE MAP
|
|
#
|
|
# Example:
|
|
#
|
|
# hard_rock_0_to_1_5_total : 450
|
|
# hard_rock_1_5_to_3_0_total : 500
|
|
# =========================================================
|
|
|
|
client_rate_map = {
|
|
|
|
(rate.item_name or "")
|
|
.strip()
|
|
.lower():
|
|
|
|
float(rate.rate or 0)
|
|
|
|
for rate in client_rates
|
|
}
|
|
|
|
sub_rate_map = {
|
|
|
|
(rate.item_name or "")
|
|
.strip()
|
|
.lower():
|
|
|
|
float(rate.rate or 0)
|
|
|
|
for rate in sub_rates
|
|
}
|
|
|
|
# =========================================================
|
|
# TOTAL HELPER
|
|
# =========================================================
|
|
def total(records, field):
|
|
|
|
value = 0
|
|
|
|
for record in records:
|
|
|
|
field_value = getattr(
|
|
record,
|
|
field,
|
|
0
|
|
)
|
|
|
|
if field_value is not None:
|
|
|
|
value += float(
|
|
field_value
|
|
)
|
|
|
|
return round(value, 2)
|
|
|
|
# =========================================================
|
|
# MANHOLE MAPPING
|
|
#
|
|
# label:
|
|
# Dashboard display name
|
|
#
|
|
# field:
|
|
# Actual model field
|
|
#
|
|
# item_name:
|
|
# Rate Master item_name
|
|
#
|
|
# IMPORTANT:
|
|
# item_name must be the actual model field name.
|
|
# =========================================================
|
|
|
|
MANHOLE_MAPPING = [
|
|
|
|
{
|
|
"label": "Marshi 0 to 1.5",
|
|
"field":
|
|
"Marshi_Muddy_Slushy_0_to_1_5_total",
|
|
"item_name":
|
|
"Marshi_Muddy_Slushy_0_to_1_5_total"
|
|
},
|
|
|
|
{
|
|
"label": "Marshi 1.5 to 3.0",
|
|
"field":
|
|
"Marshi_Muddy_Slushy_1_5_to_3_0_total",
|
|
"item_name":
|
|
"Marshi_Muddy_Slushy_1_5_to_3_0_total"
|
|
},
|
|
|
|
{
|
|
"label": "Marshi 3.0 to 4.5",
|
|
"field":
|
|
"Marshi_Muddy_Slushy_3_0_to_4_5_total",
|
|
"item_name":
|
|
"Marshi_Muddy_Slushy_3_0_to_4_5_total"
|
|
},
|
|
|
|
{
|
|
"label": "Soft Murum 0 to 1.5",
|
|
"field":
|
|
"Soft_Murum_0_to_1_5_total",
|
|
"item_name":
|
|
"Soft_Murum_0_to_1_5_total"
|
|
},
|
|
|
|
{
|
|
"label": "Soft Murum 1.5 to 3.0",
|
|
"field":
|
|
"Soft_Murum_1_5_to_3_0_total",
|
|
"item_name":
|
|
"Soft_Murum_1_5_to_3_0_total"
|
|
},
|
|
|
|
{
|
|
"label": "Soft Murum 3.0 to 4.5",
|
|
"field":
|
|
"Soft_Murum_3_0_to_4_5_total",
|
|
"item_name":
|
|
"Soft_Murum_3_0_to_4_5_total"
|
|
},
|
|
|
|
{
|
|
"label": "Hard Murum 0 to 1.5",
|
|
"field":
|
|
"Hard_Murum_0_to_1_5_total",
|
|
"item_name":
|
|
"Hard_Murum_0_to_1_5_total"
|
|
},
|
|
|
|
{
|
|
"label": "Hard Murum 1.5 to 3.0",
|
|
"field":
|
|
"Hard_Murum_1_5_to_3_0_total",
|
|
"item_name":
|
|
"Hard_Murum_1_5_to_3_0_total"
|
|
},
|
|
|
|
{
|
|
"label": "Soft Rock 0 to 1.5",
|
|
"field":
|
|
"Soft_Rock_0_to_1_5_total",
|
|
"item_name":
|
|
"Soft_Rock_0_to_1_5_total"
|
|
},
|
|
|
|
{
|
|
"label": "Soft Rock 1.5 to 3.0",
|
|
"field":
|
|
"Soft_Rock_1_5_to_3_0_total",
|
|
"item_name":
|
|
"Soft_Rock_1_5_to_3_0_total"
|
|
},
|
|
|
|
{
|
|
"label": "Hard Rock 0 to 1.5",
|
|
"field":
|
|
"Hard_Rock_0_to_1_5_total",
|
|
"item_name":
|
|
"Hard_Rock_0_to_1_5_total"
|
|
},
|
|
|
|
{
|
|
"label": "Hard Rock 1.5 to 3.0",
|
|
"field":
|
|
"Hard_Rock_1_5_to_3_0_total",
|
|
"item_name":
|
|
"Hard_Rock_1_5_to_3_0_total"
|
|
},
|
|
|
|
{
|
|
"label": "Hard Rock 3.0 to 4.5",
|
|
"field":
|
|
"Hard_Rock_3_0_to_4_5_total",
|
|
"item_name":
|
|
"Hard_Rock_3_0_to_4_5_total"
|
|
},
|
|
|
|
{
|
|
"label": "Hard Rock 4.5 to 6.0",
|
|
"field":
|
|
"Hard_Rock_4_5_to_6_0_total",
|
|
"item_name":
|
|
"Hard_Rock_4_5_to_6_0_total"
|
|
},
|
|
|
|
{
|
|
"label": "Hard Rock 6.0 to 7.5",
|
|
"field":
|
|
"Hard_Rock_6_0_to_7_5_total",
|
|
"item_name":
|
|
"Hard_Rock_6_0_to_7_5_total"
|
|
}
|
|
]
|
|
|
|
# =========================================================
|
|
# BUILD CHART DATA
|
|
# =========================================================
|
|
chart_data = []
|
|
|
|
for mapping in MANHOLE_MAPPING:
|
|
|
|
field = mapping["field"]
|
|
|
|
# =====================================================
|
|
# CLIENT QUANTITY
|
|
# =====================================================
|
|
client_qty = total(
|
|
client_records,
|
|
field
|
|
)
|
|
|
|
# =====================================================
|
|
# SUBCONTRACTOR QUANTITY
|
|
# =====================================================
|
|
sub_qty = 0
|
|
|
|
if sub_records:
|
|
|
|
sub_qty = total(
|
|
sub_records,
|
|
field
|
|
)
|
|
|
|
# =====================================================
|
|
# RATE MASTER ITEM NAME
|
|
# =====================================================
|
|
item_name = mapping[
|
|
"item_name"
|
|
]
|
|
|
|
rate_key = (
|
|
item_name
|
|
.strip()
|
|
.lower()
|
|
)
|
|
|
|
# =====================================================
|
|
# CLIENT RATE
|
|
# =====================================================
|
|
client_rate = client_rate_map.get(
|
|
rate_key,
|
|
0
|
|
)
|
|
|
|
# =====================================================
|
|
# SUBCONTRACTOR RATE
|
|
# =====================================================
|
|
sub_rate = sub_rate_map.get(
|
|
rate_key,
|
|
0
|
|
)
|
|
|
|
# =====================================================
|
|
# AMOUNT
|
|
# =====================================================
|
|
client_amount = (
|
|
client_qty
|
|
* client_rate
|
|
)
|
|
|
|
sub_amount = (
|
|
sub_qty
|
|
* sub_rate
|
|
)
|
|
|
|
# =====================================================
|
|
# DIFFERENCE
|
|
# =====================================================
|
|
qty_difference = (
|
|
client_qty
|
|
- sub_qty
|
|
)
|
|
|
|
rate_difference = (
|
|
client_rate
|
|
- sub_rate
|
|
)
|
|
|
|
amount_difference = (
|
|
client_amount
|
|
- sub_amount
|
|
)
|
|
|
|
# =====================================================
|
|
# FINAL ROW
|
|
# =====================================================
|
|
chart_data.append({
|
|
|
|
# Display
|
|
"label":
|
|
mapping["label"],
|
|
|
|
# Actual model field
|
|
"field":
|
|
field,
|
|
|
|
# Rate Master item_name
|
|
"item_name":
|
|
item_name,
|
|
|
|
# Quantity
|
|
"client":
|
|
round(client_qty, 2),
|
|
|
|
"sub":
|
|
round(sub_qty, 2),
|
|
|
|
# Rate
|
|
"client_rate":
|
|
round(client_rate, 2),
|
|
|
|
"sub_rate":
|
|
round(sub_rate, 2),
|
|
|
|
# Amount
|
|
"client_amount":
|
|
round(client_amount, 2),
|
|
|
|
"sub_amount":
|
|
round(sub_amount, 2),
|
|
|
|
# Difference
|
|
"qty_difference":
|
|
round(qty_difference, 2),
|
|
|
|
"rate_difference":
|
|
round(rate_difference, 2),
|
|
|
|
"amount_difference":
|
|
round(amount_difference, 2)
|
|
})
|
|
|
|
# =========================================================
|
|
# RESPONSE
|
|
# =========================================================
|
|
return jsonify({
|
|
|
|
"success": True,
|
|
|
|
"title":
|
|
"Manhole Excavation Comparison",
|
|
|
|
"y_title":
|
|
"Manhole Qty (Nos)",
|
|
|
|
# =====================================================
|
|
# CHART DATA
|
|
# =====================================================
|
|
|
|
"labels": [
|
|
item["label"]
|
|
for item in chart_data
|
|
],
|
|
|
|
"client_qty": [
|
|
item["client"]
|
|
for item in chart_data
|
|
],
|
|
|
|
"sub_qty": [
|
|
item["sub"]
|
|
for item in chart_data
|
|
],
|
|
|
|
# =====================================================
|
|
# RATE DATA
|
|
# =====================================================
|
|
|
|
"client_rate": [
|
|
item["client_rate"]
|
|
for item in chart_data
|
|
],
|
|
|
|
"sub_rate": [
|
|
item["sub_rate"]
|
|
for item in chart_data
|
|
],
|
|
|
|
# =====================================================
|
|
# AMOUNT DATA
|
|
# =====================================================
|
|
|
|
"client_amount": [
|
|
item["client_amount"]
|
|
for item in chart_data
|
|
],
|
|
|
|
"sub_amount": [
|
|
item["sub_amount"]
|
|
for item in chart_data
|
|
],
|
|
|
|
# =====================================================
|
|
# DIFFERENCE DATA
|
|
# =====================================================
|
|
|
|
"qty_difference": [
|
|
item["qty_difference"]
|
|
for item in chart_data
|
|
],
|
|
|
|
"rate_difference": [
|
|
item["rate_difference"]
|
|
for item in chart_data
|
|
],
|
|
|
|
"amount_difference": [
|
|
item["amount_difference"]
|
|
for item in chart_data
|
|
],
|
|
|
|
# =====================================================
|
|
# COMPLETE TABLE ROWS
|
|
# =====================================================
|
|
|
|
"rows": chart_data
|
|
})
|
|
|
|
@dashboard_bp.route("/api/mdc-analysis")
|
|
def Manhole_Domestic_Chamber_analysis():
|
|
|
|
# =========================================================
|
|
# CATEGORY
|
|
# =========================================================
|
|
CATEGORY = "Manhole_Domestic_Chamber"
|
|
|
|
# =========================================================
|
|
# REQUEST PARAMETERS
|
|
# =========================================================
|
|
subcontractor_id = request.args.get(
|
|
"subcontractor",
|
|
""
|
|
).strip()
|
|
|
|
ra_bill = request.args.get(
|
|
"ra_bill",
|
|
""
|
|
).strip()
|
|
|
|
# =========================================================
|
|
# VALIDATE SUBCONTRACTOR
|
|
# =========================================================
|
|
subcontractor_id_int = None
|
|
|
|
if subcontractor_id:
|
|
|
|
try:
|
|
subcontractor_id_int = int(
|
|
subcontractor_id
|
|
)
|
|
|
|
except ValueError:
|
|
|
|
return jsonify({
|
|
"success": False,
|
|
"message": "Invalid subcontractor."
|
|
}), 400
|
|
|
|
# =========================================================
|
|
# RA BILL LIST
|
|
# =========================================================
|
|
ra_bill_list = []
|
|
|
|
if ra_bill:
|
|
|
|
ra_bill_list = [
|
|
x.strip()
|
|
for x in ra_bill.split(",")
|
|
if x.strip()
|
|
]
|
|
|
|
# =========================================================
|
|
# SUBCONTRACTOR QUERY
|
|
# =========================================================
|
|
sub_query = ManholeDomesticChamber.query
|
|
|
|
if subcontractor_id_int:
|
|
|
|
sub_query = sub_query.filter(
|
|
ManholeDomesticChamber.subcontractor_id
|
|
== subcontractor_id_int
|
|
)
|
|
|
|
if ra_bill_list:
|
|
|
|
sub_query = sub_query.filter(
|
|
ManholeDomesticChamber.RA_Bill_No.in_(
|
|
ra_bill_list
|
|
)
|
|
)
|
|
|
|
sub_records = sub_query.all()
|
|
|
|
# =========================================================
|
|
# MATCHING KEYS
|
|
# MH_NO + LOCATION
|
|
# =========================================================
|
|
sub_keys = [
|
|
(
|
|
(r.MH_NO or "").strip().upper(),
|
|
(r.Location or "").strip().upper()
|
|
)
|
|
for r in sub_records
|
|
]
|
|
|
|
# =========================================================
|
|
# CLIENT QUERY
|
|
# =========================================================
|
|
client_query = ManholeDomesticChamberClient.query
|
|
|
|
if sub_keys:
|
|
|
|
client_query = client_query.filter(
|
|
|
|
tuple_(
|
|
func.upper(
|
|
func.trim(
|
|
ManholeDomesticChamberClient.MH_NO
|
|
)
|
|
),
|
|
|
|
func.upper(
|
|
func.trim(
|
|
ManholeDomesticChamberClient.Location
|
|
)
|
|
)
|
|
|
|
).in_(sub_keys)
|
|
)
|
|
|
|
client_records = client_query.all()
|
|
|
|
# =========================================================
|
|
# GET CLIENT RATES
|
|
#
|
|
# Category:
|
|
# Manhole_Domestic_Chamber
|
|
# =========================================================
|
|
client_rates = (
|
|
ClientRate.query
|
|
.filter(
|
|
|
|
func.lower(
|
|
func.trim(
|
|
ClientRate.category
|
|
)
|
|
) == CATEGORY.lower(),
|
|
|
|
func.lower(
|
|
func.trim(
|
|
ClientRate.status
|
|
)
|
|
) == "active"
|
|
)
|
|
.all()
|
|
)
|
|
|
|
# =========================================================
|
|
# GET SUBCONTRACTOR RATES
|
|
#
|
|
# Selected subcontractor
|
|
# +
|
|
# Category
|
|
# +
|
|
# Active
|
|
# =========================================================
|
|
sub_rates = []
|
|
|
|
if subcontractor_id_int:
|
|
|
|
sub_rates = (
|
|
SubcontractorRate.query
|
|
.filter(
|
|
|
|
SubcontractorRate.subcontractor_id
|
|
== subcontractor_id_int,
|
|
|
|
func.lower(
|
|
func.trim(
|
|
SubcontractorRate.category
|
|
)
|
|
) == CATEGORY.lower(),
|
|
|
|
func.lower(
|
|
func.trim(
|
|
SubcontractorRate.status
|
|
)
|
|
) == "active"
|
|
)
|
|
.all()
|
|
)
|
|
|
|
# =========================================================
|
|
# CLIENT RATE MAP
|
|
# =========================================================
|
|
client_rate_map = {
|
|
|
|
(rate.item_name or "")
|
|
.strip()
|
|
.lower():
|
|
|
|
float(rate.rate or 0)
|
|
|
|
for rate in client_rates
|
|
}
|
|
|
|
# =========================================================
|
|
# SUBCONTRACTOR RATE MAP
|
|
# =========================================================
|
|
sub_rate_map = {
|
|
|
|
(rate.item_name or "")
|
|
.strip()
|
|
.lower():
|
|
|
|
float(rate.rate or 0)
|
|
|
|
for rate in sub_rates
|
|
}
|
|
|
|
# =========================================================
|
|
# TOTAL HELPER
|
|
# =========================================================
|
|
def total(records, field):
|
|
|
|
value = 0
|
|
|
|
for record in records:
|
|
|
|
field_value = getattr(
|
|
record,
|
|
field,
|
|
0
|
|
)
|
|
|
|
if field_value is not None:
|
|
|
|
value += float(
|
|
field_value
|
|
)
|
|
|
|
return round(value, 2)
|
|
|
|
# =========================================================
|
|
# MDC MAPPING
|
|
#
|
|
# label = Dashboard display name
|
|
# field = Actual model field
|
|
# item_name = Rate Master item_name
|
|
# =========================================================
|
|
MDC_MAPPING = [
|
|
|
|
{
|
|
"label": "Depth of MH",
|
|
|
|
"field":
|
|
"Depth_of_MH",
|
|
|
|
"item_name":
|
|
"Depth_of_MH"
|
|
},
|
|
|
|
{
|
|
"label": "Domestic Chambers Total",
|
|
|
|
"field":
|
|
"Total",
|
|
|
|
"item_name":
|
|
"Total"
|
|
}
|
|
]
|
|
|
|
# =========================================================
|
|
# BUILD DATA
|
|
# =========================================================
|
|
chart_data = []
|
|
|
|
for item in MDC_MAPPING:
|
|
|
|
field = item["field"]
|
|
|
|
item_name = item["item_name"]
|
|
|
|
# =====================================================
|
|
# QUANTITY
|
|
# =====================================================
|
|
client_qty = total(
|
|
client_records,
|
|
field
|
|
)
|
|
|
|
sub_qty = total(
|
|
sub_records,
|
|
field
|
|
)
|
|
|
|
# =====================================================
|
|
# RATE KEY
|
|
# =====================================================
|
|
rate_key = (
|
|
item_name
|
|
.strip()
|
|
.lower()
|
|
)
|
|
|
|
# =====================================================
|
|
# CLIENT RATE
|
|
# =====================================================
|
|
client_rate = client_rate_map.get(
|
|
rate_key,
|
|
0
|
|
)
|
|
|
|
# =====================================================
|
|
# SUBCONTRACTOR RATE
|
|
# =====================================================
|
|
sub_rate = sub_rate_map.get(
|
|
rate_key,
|
|
0
|
|
)
|
|
|
|
# =====================================================
|
|
# AMOUNT
|
|
# =====================================================
|
|
client_amount = (
|
|
client_qty
|
|
* client_rate
|
|
)
|
|
|
|
sub_amount = (
|
|
sub_qty
|
|
* sub_rate
|
|
)
|
|
|
|
# =====================================================
|
|
# DIFFERENCES
|
|
# =====================================================
|
|
qty_difference = (
|
|
client_qty
|
|
- sub_qty
|
|
)
|
|
|
|
rate_difference = (
|
|
client_rate
|
|
- sub_rate
|
|
)
|
|
|
|
amount_difference = (
|
|
client_amount
|
|
- sub_amount
|
|
)
|
|
|
|
# =====================================================
|
|
# FINAL ROW
|
|
# =====================================================
|
|
chart_data.append({
|
|
|
|
"label":
|
|
item["label"],
|
|
|
|
"field":
|
|
field,
|
|
|
|
"item_name":
|
|
item_name,
|
|
|
|
# Quantity
|
|
"client":
|
|
round(client_qty, 2),
|
|
|
|
"sub":
|
|
round(sub_qty, 2),
|
|
|
|
# Rate
|
|
"client_rate":
|
|
round(client_rate, 2),
|
|
|
|
"sub_rate":
|
|
round(sub_rate, 2),
|
|
|
|
# Amount
|
|
"client_amount":
|
|
round(client_amount, 2),
|
|
|
|
"sub_amount":
|
|
round(sub_amount, 2),
|
|
|
|
# Difference
|
|
"qty_difference":
|
|
round(qty_difference, 2),
|
|
|
|
"rate_difference":
|
|
round(rate_difference, 2),
|
|
|
|
"amount_difference":
|
|
round(amount_difference, 2)
|
|
})
|
|
|
|
# =========================================================
|
|
# RESPONSE
|
|
# =========================================================
|
|
return jsonify({
|
|
|
|
"success": True,
|
|
|
|
"title":
|
|
"Domestic Chamber Comparison",
|
|
|
|
"y_title":
|
|
"Quantity (Nos)",
|
|
|
|
# =====================================================
|
|
# CHART
|
|
# =====================================================
|
|
|
|
"labels": [
|
|
x["label"]
|
|
for x in chart_data
|
|
],
|
|
|
|
"client_qty": [
|
|
x["client"]
|
|
for x in chart_data
|
|
],
|
|
|
|
"sub_qty": [
|
|
x["sub"]
|
|
for x in chart_data
|
|
],
|
|
|
|
# =====================================================
|
|
# RATE
|
|
# =====================================================
|
|
|
|
"client_rate": [
|
|
x["client_rate"]
|
|
for x in chart_data
|
|
],
|
|
|
|
"sub_rate": [
|
|
x["sub_rate"]
|
|
for x in chart_data
|
|
],
|
|
|
|
# =====================================================
|
|
# AMOUNT
|
|
# =====================================================
|
|
|
|
"client_amount": [
|
|
x["client_amount"]
|
|
for x in chart_data
|
|
],
|
|
|
|
"sub_amount": [
|
|
x["sub_amount"]
|
|
for x in chart_data
|
|
],
|
|
|
|
# =====================================================
|
|
# DIFFERENCE
|
|
# =====================================================
|
|
|
|
"qty_difference": [
|
|
x["qty_difference"]
|
|
for x in chart_data
|
|
],
|
|
|
|
"rate_difference": [
|
|
x["rate_difference"]
|
|
for x in chart_data
|
|
],
|
|
|
|
"amount_difference": [
|
|
x["amount_difference"]
|
|
for x in chart_data
|
|
],
|
|
|
|
# Complete table data
|
|
"rows": chart_data
|
|
})
|
|
|
|
|
|
@dashboard_bp.route("/api/laying-analysis")
|
|
def laying_analysis():
|
|
|
|
# =========================================================
|
|
# CATEGORY
|
|
# =========================================================
|
|
CATEGORY = "Laying"
|
|
|
|
# =========================================================
|
|
# REQUEST PARAMETERS
|
|
# =========================================================
|
|
subcontractor_id = request.args.get(
|
|
"subcontractor",
|
|
""
|
|
).strip()
|
|
|
|
ra_bill = request.args.get(
|
|
"ra_bill",
|
|
""
|
|
).strip()
|
|
|
|
# =========================================================
|
|
# VALIDATE SUBCONTRACTOR
|
|
# =========================================================
|
|
subcontractor_id_int = None
|
|
|
|
if subcontractor_id:
|
|
|
|
try:
|
|
subcontractor_id_int = int(
|
|
subcontractor_id
|
|
)
|
|
|
|
except ValueError:
|
|
|
|
return jsonify({
|
|
"success": False,
|
|
"message": "Invalid subcontractor."
|
|
}), 400
|
|
|
|
# =========================================================
|
|
# RA BILL LIST
|
|
# =========================================================
|
|
ra_bill_list = []
|
|
|
|
if ra_bill:
|
|
|
|
ra_bill_list = [
|
|
x.strip()
|
|
for x in ra_bill.split(",")
|
|
if x.strip()
|
|
]
|
|
|
|
# =========================================================
|
|
# SUBCONTRACTOR QUERY
|
|
# =========================================================
|
|
sub_query = Laying.query
|
|
|
|
if subcontractor_id_int:
|
|
|
|
sub_query = sub_query.filter(
|
|
Laying.subcontractor_id
|
|
== subcontractor_id_int
|
|
)
|
|
|
|
if ra_bill_list:
|
|
|
|
sub_query = sub_query.filter(
|
|
Laying.RA_Bill_No.in_(
|
|
ra_bill_list
|
|
)
|
|
)
|
|
|
|
sub_records = sub_query.all()
|
|
|
|
# =========================================================
|
|
# MATCHING KEYS
|
|
# MH_NO + LOCATION
|
|
# =========================================================
|
|
sub_keys = [
|
|
(
|
|
(r.MH_NO or "").strip().upper(),
|
|
(r.Location or "").strip().upper()
|
|
)
|
|
for r in sub_records
|
|
]
|
|
|
|
# =========================================================
|
|
# CLIENT QUERY
|
|
# =========================================================
|
|
client_query = LayingClient.query
|
|
|
|
if sub_keys:
|
|
|
|
client_query = client_query.filter(
|
|
|
|
tuple_(
|
|
func.upper(
|
|
func.trim(
|
|
LayingClient.MH_NO
|
|
)
|
|
),
|
|
|
|
func.upper(
|
|
func.trim(
|
|
LayingClient.Location
|
|
)
|
|
)
|
|
|
|
).in_(sub_keys)
|
|
)
|
|
|
|
client_records = client_query.all()
|
|
|
|
# =========================================================
|
|
# GET CLIENT RATES
|
|
#
|
|
# Category = Laying
|
|
# =========================================================
|
|
client_rates = (
|
|
ClientRate.query
|
|
.filter(
|
|
|
|
func.lower(
|
|
func.trim(
|
|
ClientRate.category
|
|
)
|
|
) == CATEGORY.lower(),
|
|
|
|
func.lower(
|
|
func.trim(
|
|
ClientRate.status
|
|
)
|
|
) == "active"
|
|
)
|
|
.all()
|
|
)
|
|
|
|
# =========================================================
|
|
# GET SUBCONTRACTOR RATES
|
|
#
|
|
# Selected Subcontractor
|
|
# +
|
|
# Category = Laying
|
|
# +
|
|
# Active
|
|
# =========================================================
|
|
sub_rates = []
|
|
|
|
if subcontractor_id_int:
|
|
|
|
sub_rates = (
|
|
SubcontractorRate.query
|
|
.filter(
|
|
|
|
SubcontractorRate.subcontractor_id
|
|
== subcontractor_id_int,
|
|
|
|
func.lower(
|
|
func.trim(
|
|
SubcontractorRate.category
|
|
)
|
|
) == CATEGORY.lower(),
|
|
|
|
func.lower(
|
|
func.trim(
|
|
SubcontractorRate.status
|
|
)
|
|
) == "active"
|
|
)
|
|
.all()
|
|
)
|
|
|
|
# =========================================================
|
|
# CLIENT RATE MAP
|
|
# =========================================================
|
|
client_rate_map = {
|
|
|
|
(rate.item_name or "")
|
|
.strip()
|
|
.lower():
|
|
|
|
float(rate.rate or 0)
|
|
|
|
for rate in client_rates
|
|
}
|
|
|
|
# =========================================================
|
|
# SUBCONTRACTOR RATE MAP
|
|
# =========================================================
|
|
sub_rate_map = {
|
|
|
|
(rate.item_name or "")
|
|
.strip()
|
|
.lower():
|
|
|
|
float(rate.rate or 0)
|
|
|
|
for rate in sub_rates
|
|
}
|
|
|
|
# =========================================================
|
|
# TOTAL HELPER
|
|
# =========================================================
|
|
def total(records, field):
|
|
|
|
value = 0
|
|
|
|
for record in records:
|
|
|
|
field_value = getattr(
|
|
record,
|
|
field,
|
|
0
|
|
)
|
|
|
|
if field_value is not None:
|
|
|
|
value += float(
|
|
field_value
|
|
)
|
|
|
|
return round(value, 2)
|
|
|
|
# =========================================================
|
|
# LAYING MAPPING
|
|
#
|
|
# label:
|
|
# Dashboard display name
|
|
#
|
|
# field:
|
|
# Actual model field
|
|
#
|
|
# item_name:
|
|
# Rate Master item_name
|
|
# =========================================================
|
|
LAYING_MAPPING = [
|
|
|
|
{
|
|
"label": "150 mm",
|
|
"field": "pipe_150_mm",
|
|
"item_name": "pipe_150_mm"
|
|
},
|
|
|
|
{
|
|
"label": "200 mm",
|
|
"field": "pipe_200_mm",
|
|
"item_name": "pipe_200_mm"
|
|
},
|
|
|
|
{
|
|
"label": "250 mm",
|
|
"field": "pipe_250_mm",
|
|
"item_name": "pipe_250_mm"
|
|
},
|
|
|
|
{
|
|
"label": "300 mm",
|
|
"field": "pipe_300_mm",
|
|
"item_name": "pipe_300_mm"
|
|
},
|
|
|
|
{
|
|
"label": "350 mm",
|
|
"field": "pipe_350_mm",
|
|
"item_name": "pipe_350_mm"
|
|
},
|
|
|
|
{
|
|
"label": "400 mm",
|
|
"field": "pipe_400_mm",
|
|
"item_name": "pipe_400_mm"
|
|
},
|
|
|
|
{
|
|
"label": "450 mm",
|
|
"field": "pipe_450_mm",
|
|
"item_name": "pipe_450_mm"
|
|
},
|
|
|
|
{
|
|
"label": "500 mm",
|
|
"field": "pipe_500_mm",
|
|
"item_name": "pipe_500_mm"
|
|
},
|
|
|
|
{
|
|
"label": "600 mm",
|
|
"field": "pipe_600_mm",
|
|
"item_name": "pipe_600_mm"
|
|
},
|
|
|
|
{
|
|
"label": "700 mm",
|
|
"field": "pipe_700_mm",
|
|
"item_name": "pipe_700_mm"
|
|
},
|
|
|
|
{
|
|
"label": "900 mm",
|
|
"field": "pipe_900_mm",
|
|
"item_name": "pipe_900_mm"
|
|
},
|
|
|
|
{
|
|
"label": "1200 mm",
|
|
"field": "pipe_1200_mm",
|
|
"item_name": "pipe_1200_mm"
|
|
}
|
|
]
|
|
|
|
# =========================================================
|
|
# BUILD DATA
|
|
# =========================================================
|
|
chart_data = []
|
|
|
|
for item in LAYING_MAPPING:
|
|
|
|
field = item["field"]
|
|
|
|
item_name = item["item_name"]
|
|
|
|
# =====================================================
|
|
# QUANTITY
|
|
# =====================================================
|
|
client_qty = total(
|
|
client_records,
|
|
field
|
|
)
|
|
|
|
sub_qty = total(
|
|
sub_records,
|
|
field
|
|
)
|
|
|
|
# =====================================================
|
|
# RATE KEY
|
|
# =====================================================
|
|
rate_key = (
|
|
item_name
|
|
.strip()
|
|
.lower()
|
|
)
|
|
|
|
# =====================================================
|
|
# CLIENT RATE
|
|
# =====================================================
|
|
client_rate = client_rate_map.get(
|
|
rate_key,
|
|
0
|
|
)
|
|
|
|
# =====================================================
|
|
# SUBCONTRACTOR RATE
|
|
# =====================================================
|
|
sub_rate = sub_rate_map.get(
|
|
rate_key,
|
|
0
|
|
)
|
|
|
|
# =====================================================
|
|
# AMOUNT
|
|
# =====================================================
|
|
client_amount = (
|
|
client_qty
|
|
* client_rate
|
|
)
|
|
|
|
sub_amount = (
|
|
sub_qty
|
|
* sub_rate
|
|
)
|
|
|
|
# =====================================================
|
|
# DIFFERENCES
|
|
# =====================================================
|
|
qty_difference = (
|
|
client_qty
|
|
- sub_qty
|
|
)
|
|
|
|
rate_difference = (
|
|
client_rate
|
|
- sub_rate
|
|
)
|
|
|
|
amount_difference = (
|
|
client_amount
|
|
- sub_amount
|
|
)
|
|
|
|
# =====================================================
|
|
# FINAL ROW
|
|
# =====================================================
|
|
chart_data.append({
|
|
|
|
"label":
|
|
item["label"],
|
|
|
|
# Actual model field
|
|
"field":
|
|
field,
|
|
|
|
# Rate Master item_name
|
|
"item_name":
|
|
item_name,
|
|
|
|
# Quantity
|
|
"client":
|
|
round(client_qty, 2),
|
|
|
|
"sub":
|
|
round(sub_qty, 2),
|
|
|
|
# Rate
|
|
"client_rate":
|
|
round(client_rate, 2),
|
|
|
|
"sub_rate":
|
|
round(sub_rate, 2),
|
|
|
|
# Amount
|
|
"client_amount":
|
|
round(client_amount, 2),
|
|
|
|
"sub_amount":
|
|
round(sub_amount, 2),
|
|
|
|
# Difference
|
|
"qty_difference":
|
|
round(qty_difference, 2),
|
|
|
|
"rate_difference":
|
|
round(rate_difference, 2),
|
|
|
|
"amount_difference":
|
|
round(amount_difference, 2)
|
|
})
|
|
|
|
# =========================================================
|
|
# RESPONSE
|
|
# =========================================================
|
|
return jsonify({
|
|
|
|
"success": True,
|
|
|
|
"title":
|
|
"Pipe Laying Comparison",
|
|
|
|
"y_title":
|
|
"Pipe Length (Mtr)",
|
|
|
|
# =====================================================
|
|
# CHART DATA
|
|
# =====================================================
|
|
|
|
"labels": [
|
|
x["label"]
|
|
for x in chart_data
|
|
],
|
|
|
|
"client_qty": [
|
|
x["client"]
|
|
for x in chart_data
|
|
],
|
|
|
|
"sub_qty": [
|
|
x["sub"]
|
|
for x in chart_data
|
|
],
|
|
|
|
# =====================================================
|
|
# RATE DATA
|
|
# =====================================================
|
|
|
|
"client_rate": [
|
|
x["client_rate"]
|
|
for x in chart_data
|
|
],
|
|
|
|
"sub_rate": [
|
|
x["sub_rate"]
|
|
for x in chart_data
|
|
],
|
|
|
|
# =====================================================
|
|
# AMOUNT DATA
|
|
# =====================================================
|
|
|
|
"client_amount": [
|
|
x["client_amount"]
|
|
for x in chart_data
|
|
],
|
|
|
|
"sub_amount": [
|
|
x["sub_amount"]
|
|
for x in chart_data
|
|
],
|
|
|
|
# =====================================================
|
|
# DIFFERENCE DATA
|
|
# =====================================================
|
|
|
|
"qty_difference": [
|
|
x["qty_difference"]
|
|
for x in chart_data
|
|
],
|
|
|
|
"rate_difference": [
|
|
x["rate_difference"]
|
|
for x in chart_data
|
|
],
|
|
|
|
"amount_difference": [
|
|
x["amount_difference"]
|
|
for x in chart_data
|
|
],
|
|
|
|
# Complete table rows
|
|
"rows": chart_data
|
|
})
|
|
|
|
|
|
|