From 2d7d146ec3f1fd688f42b1a0f9faf26bfa811e90 Mon Sep 17 00:00:00 2001 From: pjpatil12 Date: Fri, 31 Jul 2026 16:43:38 +0530 Subject: [PATCH] All model filter are work and show bar chat and data table. --- app/routes/dashboard.py | 346 ++++++++++++++++++++- app/services/comparison_service.py | 326 +++++++++---------- app/templates/subcontractor_dashboard.html | 86 +++-- 3 files changed, 546 insertions(+), 212 deletions(-) diff --git a/app/routes/dashboard.py b/app/routes/dashboard.py index d546819..20953f1 100644 --- a/app/routes/dashboard.py +++ b/app/routes/dashboard.py @@ -22,6 +22,9 @@ from app.models.laying_model import Laying # 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 dashboard_bp = Blueprint("dashboard", __name__, url_prefix="/dashboard") @@ -71,7 +74,6 @@ def live_stats(): - # subcontractor dashboard @dashboard_bp.route("/subcontractor_dashboard") @login_required @@ -137,7 +139,8 @@ def get_ra_bills(): def total(records, field): 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(): subcontractor_id = request.args.get("subcontractor", "").strip() @@ -175,7 +178,6 @@ def trench_analysis(): if sub_keys: client_query = client_query.filter( - tuple_( func.upper(func.trim(TrenchExcavationClient.MH_NO)), func.upper(func.trim(TrenchExcavationClient.Location)) @@ -186,7 +188,144 @@ def trench_analysis(): 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"), @@ -269,8 +408,207 @@ def trench_analysis(): ] 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] + }) + + + \ No newline at end of file diff --git a/app/services/comparison_service.py b/app/services/comparison_service.py index 228005a..afb7064 100644 --- a/app/services/comparison_service.py +++ b/app/services/comparison_service.py @@ -1,204 +1,204 @@ -from collections import defaultdict -import pandas as pd -from app.utils.regex_utils import RegularExpression +# from collections import defaultdict +# import pandas as pd +# from app.utils.regex_utils import RegularExpression -class ComparisonService: +# class ComparisonService: - TRENCH_MAPPING = [ - { - "label": "Marshi 0 to 1.5", - "client": "Client_Marshi_Muddy_Slushy_0_to_1_5_total", - "sub": None - }, - { - "label": "Marshi 1.5 to 3.0", - "client": "Client_Marshi_Muddy_Slushy_1_5_to_3_0_total", - "sub": None - }, - { - "label": "Marshi 3.0 to 4.5", - "client": "Client_Marshi_Muddy_Slushy_3_0_to_4_5_total", - "sub": None - }, - { - "label": "Soft Murum 0 to 1.5", - "client": "Client_Soft_Murum_0_to_1_5_total", - "sub": "Sub_Soft_Murum_0_to_1_5_total" - }, - { - "label": "Soft Murum 1.5 to 3.0", - "client": "Client_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", - "client": "Client_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", - "client": "Client_Hard_Murum_0_to_1_5_total", - "sub": "Sub_Hard_Murum_0_to_1_5_total" - }, - { - "label": "Hard Murum 1.5+", - "client": "Client_Hard_Murum_1_5_to_3_0_total", - "sub": "Sub_Hard_Murum_1_5_and_above_total" - }, - { - "label": "Soft Rock 0 to 1.5", - "client": "Client_Soft_Rock_0_to_1_5_total", - "sub": "Sub_Soft_Rock_0_to_1_5_total" - }, - { - "label": "Soft Rock 1.5+", - "client": "Client_Soft_Rock_1_5_to_3_0_total", - "sub": "Sub_Soft_Rock_1_5_and_above_total" - }, - { - "label": "Hard Rock 0 to 1.5", - "client": "Client_Hard_Rock_0_to_1_5_total", - "sub": "Sub_Hard_Rock_0_to_1_5_total" - }, - { - "label": "Hard Rock 1.5 to 3.0", - "client": "Client_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", - "client": "Client_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", - "client": "Client_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", - "client": "Client_Hard_Rock_6_0_to_7_5_total", - "sub": "Sub_Hard_Rock_6_0_to_7_5_total" - } - ] +# TRENCH_MAPPING = [ +# { +# "label": "Marshi 0 to 1.5", +# "client": "Client_Marshi_Muddy_Slushy_0_to_1_5_total", +# "sub": None +# }, +# { +# "label": "Marshi 1.5 to 3.0", +# "client": "Client_Marshi_Muddy_Slushy_1_5_to_3_0_total", +# "sub": None +# }, +# { +# "label": "Marshi 3.0 to 4.5", +# "client": "Client_Marshi_Muddy_Slushy_3_0_to_4_5_total", +# "sub": None +# }, +# { +# "label": "Soft Murum 0 to 1.5", +# "client": "Client_Soft_Murum_0_to_1_5_total", +# "sub": "Sub_Soft_Murum_0_to_1_5_total" +# }, +# { +# "label": "Soft Murum 1.5 to 3.0", +# "client": "Client_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", +# "client": "Client_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", +# "client": "Client_Hard_Murum_0_to_1_5_total", +# "sub": "Sub_Hard_Murum_0_to_1_5_total" +# }, +# { +# "label": "Hard Murum 1.5+", +# "client": "Client_Hard_Murum_1_5_to_3_0_total", +# "sub": "Sub_Hard_Murum_1_5_and_above_total" +# }, +# { +# "label": "Soft Rock 0 to 1.5", +# "client": "Client_Soft_Rock_0_to_1_5_total", +# "sub": "Sub_Soft_Rock_0_to_1_5_total" +# }, +# { +# "label": "Soft Rock 1.5+", +# "client": "Client_Soft_Rock_1_5_to_3_0_total", +# "sub": "Sub_Soft_Rock_1_5_and_above_total" +# }, +# { +# "label": "Hard Rock 0 to 1.5", +# "client": "Client_Hard_Rock_0_to_1_5_total", +# "sub": "Sub_Hard_Rock_0_to_1_5_total" +# }, +# { +# "label": "Hard Rock 1.5 to 3.0", +# "client": "Client_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", +# "client": "Client_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", +# "client": "Client_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", +# "client": "Client_Hard_Rock_6_0_to_7_5_total", +# "sub": "Sub_Hard_Rock_6_0_to_7_5_total" +# } +# ] - @staticmethod - def normalize_key(value): - if value is None: - return "" - return str(value).strip().upper() +# @staticmethod +# def normalize_key(value): +# if value is None: +# return "" +# return str(value).strip().upper() - @classmethod - def make_lookup(cls, rows, key_field): - """ - Create lookup dictionary using: - (Location, MH_NO) - """ +# @classmethod +# def make_lookup(cls, rows, key_field): +# """ +# Create lookup dictionary using: +# (Location, MH_NO) +# """ - lookup = defaultdict(list) +# lookup = defaultdict(list) - for row in rows: +# for row in rows: - location = cls.normalize_key(row.get("Location")) - key = cls.normalize_key(row.get(key_field)) +# location = cls.normalize_key(row.get("Location")) +# key = cls.normalize_key(row.get(key_field)) - if location and key: - lookup[(location, key)].append(row) +# if location and key: +# lookup[(location, key)].append(row) - return lookup +# return lookup - @classmethod - def build_comparison(cls, client_rows, subcontractor_rows, key_field="MH_NO"): +# @classmethod +# def build_comparison(cls, client_rows, subcontractor_rows, key_field="MH_NO"): - subcontractor_lookup = cls.make_lookup( - subcontractor_rows, - key_field - ) +# subcontractor_lookup = cls.make_lookup( +# subcontractor_rows, +# 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")) - key = cls.normalize_key(client.get(key_field)) +# location = cls.normalize_key(client.get("Location")) +# key = cls.normalize_key(client.get(key_field)) - if not location or not key: - continue +# if not location or not key: +# continue - rows = subcontractor_lookup.get((location, key)) +# rows = subcontractor_lookup.get((location, key)) - if not rows: - continue +# if not rows: +# continue - index = used[(location, key)] +# index = used[(location, key)] - if index >= len(rows): - continue +# if index >= len(rows): +# continue - subcontractor = rows[index] +# subcontractor = rows[index] - used[(location, key)] += 1 +# used[(location, key)] += 1 - client_total = sum( - float(v or 0) - for k, v in client.items() - if k.endswith("_total") - or RegularExpression.D_RANGE_PATTERN.match(k) - or RegularExpression.PIPE_MM_PATTERN.match(k) - ) +# client_total = sum( +# float(v or 0) +# for k, v in client.items() +# if k.endswith("_total") +# or RegularExpression.D_RANGE_PATTERN.match(k) +# or RegularExpression.PIPE_MM_PATTERN.match(k) +# ) - subcontractor_total = sum( - float(v or 0) - for k, v in subcontractor.items() - if k.endswith("_total") - or RegularExpression.D_RANGE_PATTERN.match(k) - or RegularExpression.PIPE_MM_PATTERN.match(k) - ) +# subcontractor_total = sum( +# float(v or 0) +# for k, v in subcontractor.items() +# if k.endswith("_total") +# or RegularExpression.D_RANGE_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( - client_total - subcontractor_total, - 2 - ) - } +# "Difference": round( +# client_total - subcontractor_total, +# 2 +# ) +# } - # Client Columns - for column, value in client.items(): +# # Client Columns +# for column, value in client.items(): - if column in [ - "id", - "created_at" - ]: - continue +# if column in [ +# "id", +# "created_at" +# ]: +# continue - row[f"Client_{column}"] = value +# row[f"Client_{column}"] = value - # Subcontractor Columns - for column, value in subcontractor.items(): +# # Subcontractor Columns +# for column, value in subcontractor.items(): - if column in [ - "id", - "created_at", - "subcontractor_id" - ]: - continue +# if column in [ +# "id", +# "created_at", +# "subcontractor_id" +# ]: +# continue - row[f"Sub_{column}"] = value +# row[f"Sub_{column}"] = value - output.append(row) +# output.append(row) - return pd.DataFrame(output) \ No newline at end of file +# return pd.DataFrame(output) \ No newline at end of file diff --git a/app/templates/subcontractor_dashboard.html b/app/templates/subcontractor_dashboard.html index ffdd8aa..d5f9732 100644 --- a/app/templates/subcontractor_dashboard.html +++ b/app/templates/subcontractor_dashboard.html @@ -57,54 +57,43 @@
- -
- -
- - + +

- + - + @@ -116,7 +105,7 @@
-
-
-
-
- - - @@ -164,22 +146,16 @@ - - -
Sr No Strata Type & DepthSub Contractor Qty Difference
-
-
- @@ -239,7 +215,6 @@ /* Search */ function loadDashboard() { - const subcontractor = document.getElementById("subcontractor").value; const category = document.getElementById("category").value; @@ -249,14 +224,36 @@ 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(data => { - console.log(data); - drawBar(data); drawTable(data); - }) .catch(err => console.error(err)); @@ -301,7 +298,7 @@ plugins: { title: { display: true, - text: "Excavation Comparison" + text: data.title }, legend: { position: "bottom" @@ -320,7 +317,7 @@ beginAtZero: true, title: { display: true, - text: "Excavation Qty (Cum)" + text: data.y_title } } } @@ -334,18 +331,17 @@ let html=''; for(let i=0;i ${i + 1} ${data.labels[i]} ${data.client_qty[i]} ${data.sub_qty[i]} - - ${data.client_qty[i]- data.sub_qty[i]} - - + ${diff.toFixed(2)} `;