All model filter are work and show bar chat and data table.
This commit is contained in:
@@ -22,6 +22,9 @@ from app.models.laying_model import Laying
|
|||||||
|
|
||||||
# client models import
|
# client models import
|
||||||
from app.models.tr_ex_client_model import TrenchExcavationClient
|
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
|
||||||
|
|
||||||
|
|
||||||
dashboard_bp = Blueprint("dashboard", __name__, url_prefix="/dashboard")
|
dashboard_bp = Blueprint("dashboard", __name__, url_prefix="/dashboard")
|
||||||
@@ -71,7 +74,6 @@ def live_stats():
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# subcontractor dashboard
|
# subcontractor dashboard
|
||||||
@dashboard_bp.route("/subcontractor_dashboard")
|
@dashboard_bp.route("/subcontractor_dashboard")
|
||||||
@login_required
|
@login_required
|
||||||
@@ -137,7 +139,8 @@ def get_ra_bills():
|
|||||||
def total(records, field):
|
def total(records, field):
|
||||||
return float(sum(getattr(r, field) or 0 for r in records))
|
return float(sum(getattr(r, field) or 0 for r in records))
|
||||||
|
|
||||||
@dashboard_bp.route("/api/trench-analysis")
|
# category= trench_excavation
|
||||||
|
@dashboard_bp.route("/api/tr-analysis")
|
||||||
def trench_analysis():
|
def trench_analysis():
|
||||||
|
|
||||||
subcontractor_id = request.args.get("subcontractor", "").strip()
|
subcontractor_id = request.args.get("subcontractor", "").strip()
|
||||||
@@ -175,7 +178,6 @@ def trench_analysis():
|
|||||||
if sub_keys:
|
if sub_keys:
|
||||||
|
|
||||||
client_query = client_query.filter(
|
client_query = client_query.filter(
|
||||||
|
|
||||||
tuple_(
|
tuple_(
|
||||||
func.upper(func.trim(TrenchExcavationClient.MH_NO)),
|
func.upper(func.trim(TrenchExcavationClient.MH_NO)),
|
||||||
func.upper(func.trim(TrenchExcavationClient.Location))
|
func.upper(func.trim(TrenchExcavationClient.Location))
|
||||||
@@ -186,7 +188,144 @@ def trench_analysis():
|
|||||||
client_records = client_query.all()
|
client_records = client_query.all()
|
||||||
|
|
||||||
chart_data = [
|
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",
|
"label": "Marshi 0 to 1.5",
|
||||||
"client": total(client_records, "Marshi_Muddy_Slushy_0_to_1_5_total"),
|
"client": total(client_records, "Marshi_Muddy_Slushy_0_to_1_5_total"),
|
||||||
@@ -269,8 +408,207 @@ def trench_analysis():
|
|||||||
]
|
]
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
|
"title": "Manhole Excavation Comparison",
|
||||||
|
"y_title": "Manhole Qty (Nos)",
|
||||||
"labels": [x["label"] for x in chart_data],
|
"labels": [x["label"] for x in chart_data],
|
||||||
"client_qty": [x["client"] for x in chart_data],
|
"client_qty": [x["client"] for x in chart_data],
|
||||||
"sub_qty": [x["sub"] 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]
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,204 +1,204 @@
|
|||||||
from collections import defaultdict
|
# from collections import defaultdict
|
||||||
import pandas as pd
|
# import pandas as pd
|
||||||
from app.utils.regex_utils import RegularExpression
|
# from app.utils.regex_utils import RegularExpression
|
||||||
|
|
||||||
|
|
||||||
class ComparisonService:
|
# class ComparisonService:
|
||||||
|
|
||||||
TRENCH_MAPPING = [
|
# TRENCH_MAPPING = [
|
||||||
{
|
# {
|
||||||
"label": "Marshi 0 to 1.5",
|
# "label": "Marshi 0 to 1.5",
|
||||||
"client": "Client_Marshi_Muddy_Slushy_0_to_1_5_total",
|
# "client": "Client_Marshi_Muddy_Slushy_0_to_1_5_total",
|
||||||
"sub": None
|
# "sub": None
|
||||||
},
|
# },
|
||||||
{
|
# {
|
||||||
"label": "Marshi 1.5 to 3.0",
|
# "label": "Marshi 1.5 to 3.0",
|
||||||
"client": "Client_Marshi_Muddy_Slushy_1_5_to_3_0_total",
|
# "client": "Client_Marshi_Muddy_Slushy_1_5_to_3_0_total",
|
||||||
"sub": None
|
# "sub": None
|
||||||
},
|
# },
|
||||||
{
|
# {
|
||||||
"label": "Marshi 3.0 to 4.5",
|
# "label": "Marshi 3.0 to 4.5",
|
||||||
"client": "Client_Marshi_Muddy_Slushy_3_0_to_4_5_total",
|
# "client": "Client_Marshi_Muddy_Slushy_3_0_to_4_5_total",
|
||||||
"sub": None
|
# "sub": None
|
||||||
},
|
# },
|
||||||
{
|
# {
|
||||||
"label": "Soft Murum 0 to 1.5",
|
# "label": "Soft Murum 0 to 1.5",
|
||||||
"client": "Client_Soft_Murum_0_to_1_5_total",
|
# "client": "Client_Soft_Murum_0_to_1_5_total",
|
||||||
"sub": "Sub_Soft_Murum_0_to_1_5_total"
|
# "sub": "Sub_Soft_Murum_0_to_1_5_total"
|
||||||
},
|
# },
|
||||||
{
|
# {
|
||||||
"label": "Soft Murum 1.5 to 3.0",
|
# "label": "Soft Murum 1.5 to 3.0",
|
||||||
"client": "Client_Soft_Murum_1_5_to_3_0_total",
|
# "client": "Client_Soft_Murum_1_5_to_3_0_total",
|
||||||
"sub": "Sub_Soft_Murum_1_5_to_3_0_total"
|
# "sub": "Sub_Soft_Murum_1_5_to_3_0_total"
|
||||||
},
|
# },
|
||||||
{
|
# {
|
||||||
"label": "Soft Murum 3.0 to 4.5",
|
# "label": "Soft Murum 3.0 to 4.5",
|
||||||
"client": "Client_Soft_Murum_3_0_to_4_5_total",
|
# "client": "Client_Soft_Murum_3_0_to_4_5_total",
|
||||||
"sub": "Sub_Soft_Murum_3_0_to_4_5_total"
|
# "sub": "Sub_Soft_Murum_3_0_to_4_5_total"
|
||||||
},
|
# },
|
||||||
{
|
# {
|
||||||
"label": "Hard Murum 0 to 1.5",
|
# "label": "Hard Murum 0 to 1.5",
|
||||||
"client": "Client_Hard_Murum_0_to_1_5_total",
|
# "client": "Client_Hard_Murum_0_to_1_5_total",
|
||||||
"sub": "Sub_Hard_Murum_0_to_1_5_total"
|
# "sub": "Sub_Hard_Murum_0_to_1_5_total"
|
||||||
},
|
# },
|
||||||
{
|
# {
|
||||||
"label": "Hard Murum 1.5+",
|
# "label": "Hard Murum 1.5+",
|
||||||
"client": "Client_Hard_Murum_1_5_to_3_0_total",
|
# "client": "Client_Hard_Murum_1_5_to_3_0_total",
|
||||||
"sub": "Sub_Hard_Murum_1_5_and_above_total"
|
# "sub": "Sub_Hard_Murum_1_5_and_above_total"
|
||||||
},
|
# },
|
||||||
{
|
# {
|
||||||
"label": "Soft Rock 0 to 1.5",
|
# "label": "Soft Rock 0 to 1.5",
|
||||||
"client": "Client_Soft_Rock_0_to_1_5_total",
|
# "client": "Client_Soft_Rock_0_to_1_5_total",
|
||||||
"sub": "Sub_Soft_Rock_0_to_1_5_total"
|
# "sub": "Sub_Soft_Rock_0_to_1_5_total"
|
||||||
},
|
# },
|
||||||
{
|
# {
|
||||||
"label": "Soft Rock 1.5+",
|
# "label": "Soft Rock 1.5+",
|
||||||
"client": "Client_Soft_Rock_1_5_to_3_0_total",
|
# "client": "Client_Soft_Rock_1_5_to_3_0_total",
|
||||||
"sub": "Sub_Soft_Rock_1_5_and_above_total"
|
# "sub": "Sub_Soft_Rock_1_5_and_above_total"
|
||||||
},
|
# },
|
||||||
{
|
# {
|
||||||
"label": "Hard Rock 0 to 1.5",
|
# "label": "Hard Rock 0 to 1.5",
|
||||||
"client": "Client_Hard_Rock_0_to_1_5_total",
|
# "client": "Client_Hard_Rock_0_to_1_5_total",
|
||||||
"sub": "Sub_Hard_Rock_0_to_1_5_total"
|
# "sub": "Sub_Hard_Rock_0_to_1_5_total"
|
||||||
},
|
# },
|
||||||
{
|
# {
|
||||||
"label": "Hard Rock 1.5 to 3.0",
|
# "label": "Hard Rock 1.5 to 3.0",
|
||||||
"client": "Client_Hard_Rock_1_5_to_3_0_total",
|
# "client": "Client_Hard_Rock_1_5_to_3_0_total",
|
||||||
"sub": "Sub_Hard_Rock_1_5_to_3_0_total"
|
# "sub": "Sub_Hard_Rock_1_5_to_3_0_total"
|
||||||
},
|
# },
|
||||||
{
|
# {
|
||||||
"label": "Hard Rock 3.0 to 4.5",
|
# "label": "Hard Rock 3.0 to 4.5",
|
||||||
"client": "Client_Hard_Rock_3_0_to_4_5_total",
|
# "client": "Client_Hard_Rock_3_0_to_4_5_total",
|
||||||
"sub": "Sub_Hard_Rock_3_0_to_4_5_total"
|
# "sub": "Sub_Hard_Rock_3_0_to_4_5_total"
|
||||||
},
|
# },
|
||||||
{
|
# {
|
||||||
"label": "Hard Rock 4.5 to 6.0",
|
# "label": "Hard Rock 4.5 to 6.0",
|
||||||
"client": "Client_Hard_Rock_4_5_to_6_0_total",
|
# "client": "Client_Hard_Rock_4_5_to_6_0_total",
|
||||||
"sub": "Sub_Hard_Rock_4_5_to_6_0_total"
|
# "sub": "Sub_Hard_Rock_4_5_to_6_0_total"
|
||||||
},
|
# },
|
||||||
{
|
# {
|
||||||
"label": "Hard Rock 6.0 to 7.5",
|
# "label": "Hard Rock 6.0 to 7.5",
|
||||||
"client": "Client_Hard_Rock_6_0_to_7_5_total",
|
# "client": "Client_Hard_Rock_6_0_to_7_5_total",
|
||||||
"sub": "Sub_Hard_Rock_6_0_to_7_5_total"
|
# "sub": "Sub_Hard_Rock_6_0_to_7_5_total"
|
||||||
}
|
# }
|
||||||
]
|
# ]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
# @staticmethod
|
||||||
def normalize_key(value):
|
# def normalize_key(value):
|
||||||
if value is None:
|
# if value is None:
|
||||||
return ""
|
# return ""
|
||||||
return str(value).strip().upper()
|
# return str(value).strip().upper()
|
||||||
|
|
||||||
@classmethod
|
# @classmethod
|
||||||
def make_lookup(cls, rows, key_field):
|
# def make_lookup(cls, rows, key_field):
|
||||||
"""
|
# """
|
||||||
Create lookup dictionary using:
|
# Create lookup dictionary using:
|
||||||
(Location, MH_NO)
|
# (Location, MH_NO)
|
||||||
"""
|
# """
|
||||||
|
|
||||||
lookup = defaultdict(list)
|
# lookup = defaultdict(list)
|
||||||
|
|
||||||
for row in rows:
|
# for row in rows:
|
||||||
|
|
||||||
location = cls.normalize_key(row.get("Location"))
|
# location = cls.normalize_key(row.get("Location"))
|
||||||
key = cls.normalize_key(row.get(key_field))
|
# key = cls.normalize_key(row.get(key_field))
|
||||||
|
|
||||||
if location and key:
|
# if location and key:
|
||||||
lookup[(location, key)].append(row)
|
# lookup[(location, key)].append(row)
|
||||||
|
|
||||||
return lookup
|
# return lookup
|
||||||
|
|
||||||
@classmethod
|
# @classmethod
|
||||||
def build_comparison(cls, client_rows, subcontractor_rows, key_field="MH_NO"):
|
# def build_comparison(cls, client_rows, subcontractor_rows, key_field="MH_NO"):
|
||||||
|
|
||||||
subcontractor_lookup = cls.make_lookup(
|
# subcontractor_lookup = cls.make_lookup(
|
||||||
subcontractor_rows,
|
# subcontractor_rows,
|
||||||
key_field
|
# key_field
|
||||||
)
|
# )
|
||||||
|
|
||||||
used = defaultdict(int)
|
# used = defaultdict(int)
|
||||||
|
|
||||||
output = []
|
# output = []
|
||||||
|
|
||||||
for client in client_rows:
|
# for client in client_rows:
|
||||||
|
|
||||||
location = cls.normalize_key(client.get("Location"))
|
# location = cls.normalize_key(client.get("Location"))
|
||||||
key = cls.normalize_key(client.get(key_field))
|
# key = cls.normalize_key(client.get(key_field))
|
||||||
|
|
||||||
if not location or not key:
|
# if not location or not key:
|
||||||
continue
|
# continue
|
||||||
|
|
||||||
rows = subcontractor_lookup.get((location, key))
|
# rows = subcontractor_lookup.get((location, key))
|
||||||
|
|
||||||
if not rows:
|
# if not rows:
|
||||||
continue
|
# continue
|
||||||
|
|
||||||
index = used[(location, key)]
|
# index = used[(location, key)]
|
||||||
|
|
||||||
if index >= len(rows):
|
# if index >= len(rows):
|
||||||
continue
|
# continue
|
||||||
|
|
||||||
subcontractor = rows[index]
|
# subcontractor = rows[index]
|
||||||
|
|
||||||
used[(location, key)] += 1
|
# used[(location, key)] += 1
|
||||||
|
|
||||||
client_total = sum(
|
# client_total = sum(
|
||||||
float(v or 0)
|
# float(v or 0)
|
||||||
for k, v in client.items()
|
# for k, v in client.items()
|
||||||
if k.endswith("_total")
|
# if k.endswith("_total")
|
||||||
or RegularExpression.D_RANGE_PATTERN.match(k)
|
# or RegularExpression.D_RANGE_PATTERN.match(k)
|
||||||
or RegularExpression.PIPE_MM_PATTERN.match(k)
|
# or RegularExpression.PIPE_MM_PATTERN.match(k)
|
||||||
)
|
# )
|
||||||
|
|
||||||
subcontractor_total = sum(
|
# subcontractor_total = sum(
|
||||||
float(v or 0)
|
# float(v or 0)
|
||||||
for k, v in subcontractor.items()
|
# for k, v in subcontractor.items()
|
||||||
if k.endswith("_total")
|
# if k.endswith("_total")
|
||||||
or RegularExpression.D_RANGE_PATTERN.match(k)
|
# or RegularExpression.D_RANGE_PATTERN.match(k)
|
||||||
or RegularExpression.PIPE_MM_PATTERN.match(k)
|
# or RegularExpression.PIPE_MM_PATTERN.match(k)
|
||||||
)
|
# )
|
||||||
|
|
||||||
row = {
|
# row = {
|
||||||
|
|
||||||
"Location": location,
|
# "Location": location,
|
||||||
|
|
||||||
key_field: key,
|
# key_field: key,
|
||||||
|
|
||||||
"Client_Total": round(client_total, 2),
|
# "Client_Total": round(client_total, 2),
|
||||||
|
|
||||||
"Subcontractor_Total": round(subcontractor_total, 2),
|
# "Subcontractor_Total": round(subcontractor_total, 2),
|
||||||
|
|
||||||
"Difference": round(
|
# "Difference": round(
|
||||||
client_total - subcontractor_total,
|
# client_total - subcontractor_total,
|
||||||
2
|
# 2
|
||||||
)
|
# )
|
||||||
}
|
# }
|
||||||
|
|
||||||
# Client Columns
|
# # Client Columns
|
||||||
for column, value in client.items():
|
# for column, value in client.items():
|
||||||
|
|
||||||
if column in [
|
# if column in [
|
||||||
"id",
|
# "id",
|
||||||
"created_at"
|
# "created_at"
|
||||||
]:
|
# ]:
|
||||||
continue
|
# continue
|
||||||
|
|
||||||
row[f"Client_{column}"] = value
|
# row[f"Client_{column}"] = value
|
||||||
|
|
||||||
# Subcontractor Columns
|
# # Subcontractor Columns
|
||||||
for column, value in subcontractor.items():
|
# for column, value in subcontractor.items():
|
||||||
|
|
||||||
if column in [
|
# if column in [
|
||||||
"id",
|
# "id",
|
||||||
"created_at",
|
# "created_at",
|
||||||
"subcontractor_id"
|
# "subcontractor_id"
|
||||||
]:
|
# ]:
|
||||||
continue
|
# continue
|
||||||
|
|
||||||
row[f"Sub_{column}"] = value
|
# row[f"Sub_{column}"] = value
|
||||||
|
|
||||||
output.append(row)
|
# output.append(row)
|
||||||
|
|
||||||
return pd.DataFrame(output)
|
# return pd.DataFrame(output)
|
||||||
@@ -57,54 +57,43 @@
|
|||||||
|
|
||||||
<!-- Contractor -->
|
<!-- Contractor -->
|
||||||
<div class="col-lg-4">
|
<div class="col-lg-4">
|
||||||
|
|
||||||
<label class="form-label fw-bold"> Subcontractor </label>
|
<label class="form-label fw-bold"> Subcontractor </label>
|
||||||
<select class="form-select" id="subcontractor">
|
<select class="form-select" id="subcontractor">
|
||||||
|
|
||||||
<option value="">--- select contractor ---</option>
|
<option value="">--- select contractor ---</option>
|
||||||
|
|
||||||
{% for s in subcontractors %}
|
{% for s in subcontractors %}
|
||||||
<option value="{{s.id}}">
|
<option value="{{s.id}}">
|
||||||
{{s.subcontractor_name}}
|
{{s.subcontractor_name}}
|
||||||
</option>
|
</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Category -->
|
<!-- Category -->
|
||||||
<div class="col-lg-4">
|
<div class="col-lg-4">
|
||||||
|
|
||||||
<label class="form-label fw-bold">Category</label>
|
<label class="form-label fw-bold">Category</label>
|
||||||
<select class="form-select" id="category">
|
<select class="form-select" id="category">
|
||||||
<option value="">--- select category ---</option>
|
<option value="">--- select category ---</option>
|
||||||
<option value="trench_excavation">Trench Excavation</option>
|
<option value="trench_excavation">Trench Excavation</option>
|
||||||
<option value="manhole_excavation">Manhole Excavation</option>
|
<option value="manhole_excavation">Manhole Excavation</option>
|
||||||
<option value="laying">Pipe Laying</option>
|
<option value="Manhole_Domestic_Chamber">Manhole Domestic Chamber</option>
|
||||||
|
<option value="Laying">Pipe Laying</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- RA Bill -->
|
<!-- RA Bill -->
|
||||||
<div class="col-lg-4">
|
<div class="col-lg-4">
|
||||||
<label class="form-label fw-bold">
|
<label class="form-label fw-bold"> RA Bills</label>
|
||||||
RA Bills
|
<select id="ra_bill" class="form-select" multiple></select>
|
||||||
</label>
|
|
||||||
<select id="ra_bill"
|
|
||||||
class="form-select"
|
|
||||||
multiple>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
<!-- Search button -->
|
||||||
<button class="btn btn-primary" id="searchBtn">
|
<button class="btn btn-primary" id="searchBtn">
|
||||||
<i class="bi bi-search"></i>Search
|
<i class="bi bi-search"></i>Search
|
||||||
</button>
|
</button>
|
||||||
|
<!-- Reset button -->
|
||||||
<button class="btn btn-secondary" id="resetBtn">
|
<button class="btn btn-secondary" id="resetBtn">
|
||||||
<i class="bi bi-arrow-clockwise"></i>Reset
|
<i class="bi bi-arrow-clockwise"></i>Reset
|
||||||
</button>
|
</button>
|
||||||
@@ -116,7 +105,7 @@
|
|||||||
|
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<ul class="nav nav-pills">
|
<ul class="nav nav-pills">
|
||||||
|
<!--Bar Chart Tab -->
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<button class="nav-link active"
|
<button class="nav-link active"
|
||||||
data-bs-toggle="tab"
|
data-bs-toggle="tab"
|
||||||
@@ -124,7 +113,8 @@
|
|||||||
<i class="bi bi-bar-chart"></i> Bar Chart
|
<i class="bi bi-bar-chart"></i> Bar Chart
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<!-- Data Table Tab -->
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<button class="nav-link"
|
<button class="nav-link"
|
||||||
data-bs-toggle="tab"
|
data-bs-toggle="tab"
|
||||||
@@ -132,31 +122,23 @@
|
|||||||
<i class="bi bi-table"></i> Data Table
|
<i class="bi bi-table"></i> Data Table
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
|
|
||||||
<!-- BAR TAB -->
|
<!-- BAR TAB -->
|
||||||
<div class="tab-pane fade show active" id="barTab">
|
<div class="tab-pane fade show active" id="barTab">
|
||||||
|
|
||||||
<div style="height:600px">
|
<div style="height:600px">
|
||||||
<canvas id="barChart"></canvas>
|
<canvas id="barChart"></canvas>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- TABLE TAB -->
|
<!-- TABLE TAB -->
|
||||||
<div class="tab-pane fade" id="tableTab">
|
<div class="tab-pane fade" id="tableTab">
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
|
|
||||||
<table class="table table-bordered table-hover" id="resultTable">
|
<table class="table table-bordered table-hover" id="resultTable">
|
||||||
|
|
||||||
<thead class="table-dark">
|
<thead class="table-dark">
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Sr No</th>
|
<th>Sr No</th>
|
||||||
<th>Strata Type & Depth</th>
|
<th>Strata Type & Depth</th>
|
||||||
@@ -164,22 +146,16 @@
|
|||||||
<th class="text-end">Sub Contractor Qty</th>
|
<th class="text-end">Sub Contractor Qty</th>
|
||||||
<th class="text-end">Difference</th>
|
<th class="text-end">Difference</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody></tbody>
|
<tbody></tbody>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
@@ -239,7 +215,6 @@
|
|||||||
|
|
||||||
/* Search */
|
/* Search */
|
||||||
function loadDashboard() {
|
function loadDashboard() {
|
||||||
|
|
||||||
const subcontractor = document.getElementById("subcontractor").value;
|
const subcontractor = document.getElementById("subcontractor").value;
|
||||||
const category = document.getElementById("category").value;
|
const category = document.getElementById("category").value;
|
||||||
|
|
||||||
@@ -249,14 +224,36 @@
|
|||||||
raBills = raBillChoice.getValue(true);
|
raBills = raBillChoice.getValue(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch(`/dashboard/api/trench-analysis?subcontractor=${subcontractor}&category=${category}&ra_bill=${raBills.join(",")}`)
|
let apiUrl = "";
|
||||||
|
|
||||||
|
switch (category) {
|
||||||
|
|
||||||
|
case "trench_excavation":
|
||||||
|
apiUrl = "/dashboard/api/tr-analysis";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "manhole_excavation":
|
||||||
|
apiUrl = "/dashboard/api/mh-analysis";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Manhole_Domestic_Chamber":
|
||||||
|
apiUrl = "/dashboard/api/mdc-analysis";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "Laying":
|
||||||
|
apiUrl = "/dashboard/api/laying-analysis";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
alert("Please select category");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(`${apiUrl}?subcontractor=${subcontractor}&category=${category}&ra_bill=${raBills.join(",")}`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
console.log(data);
|
|
||||||
|
|
||||||
drawBar(data);
|
drawBar(data);
|
||||||
drawTable(data);
|
drawTable(data);
|
||||||
|
|
||||||
})
|
})
|
||||||
.catch(err => console.error(err));
|
.catch(err => console.error(err));
|
||||||
|
|
||||||
@@ -301,7 +298,7 @@
|
|||||||
plugins: {
|
plugins: {
|
||||||
title: {
|
title: {
|
||||||
display: true,
|
display: true,
|
||||||
text: "Excavation Comparison"
|
text: data.title
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
position: "bottom"
|
position: "bottom"
|
||||||
@@ -320,7 +317,7 @@
|
|||||||
beginAtZero: true,
|
beginAtZero: true,
|
||||||
title: {
|
title: {
|
||||||
display: true,
|
display: true,
|
||||||
text: "Excavation Qty (Cum)"
|
text: data.y_title
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -334,18 +331,17 @@
|
|||||||
|
|
||||||
let html='';
|
let html='';
|
||||||
for(let i=0;i<data.labels.length;i++){
|
for(let i=0;i<data.labels.length;i++){
|
||||||
|
const clientQty = Number(data.client_qty[i] || 0);
|
||||||
|
const subQty = Number(data.sub_qty[i] || 0);
|
||||||
|
const diff = clientQty - subQty;
|
||||||
|
|
||||||
html+=`
|
html+=`
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="text-center">${i + 1}</td>
|
<td class="text-center">${i + 1}</td>
|
||||||
<td>${data.labels[i]}</td>
|
<td>${data.labels[i]}</td>
|
||||||
<td class="text-end">${data.client_qty[i]}</td>
|
<td class="text-end">${data.client_qty[i]}</td>
|
||||||
<td class="text-end">${data.sub_qty[i]}</td>
|
<td class="text-end">${data.sub_qty[i]}</td>
|
||||||
<td class="text-end fw-bold ${data.client_qty[i]- data.sub_qty[i] >= 0 ? 'text-success' : 'text-danger'}">
|
<td class="text-end fw-bold ${diff >= 0 ? 'text-success' : 'text-danger'}">${diff.toFixed(2)}</td>
|
||||||
${data.client_qty[i]- data.sub_qty[i]}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
`;
|
`;
|
||||||
|
|||||||
Reference in New Issue
Block a user