diff --git a/app/config.py b/app/config.py index ece5bed..8203a71 100644 --- a/app/config.py +++ b/app/config.py @@ -1,6 +1,4 @@ import os -# project base url -BASE_DIR = os.path.abspath(os.path.dirname(__file__)) class Config: # secret key @@ -23,7 +21,4 @@ class Config: ) SQLALCHEMY_TRACK_MODIFICATIONS = False - # uploads folder path - UPLOAD_FOLDER = os.path.join(BASE_DIR, "static", "uploads") - # file extension - ALLOWED_EXTENSIONS = {"xlsx", "xls", "csv"} + \ No newline at end of file diff --git a/app/routes/dashboard.py b/app/routes/dashboard.py index af6f6d7..72ea392 100644 --- a/app/routes/dashboard.py +++ b/app/routes/dashboard.py @@ -76,39 +76,171 @@ def subcontractor_dashboard(): subcontractors=subcontractors ) - -# API FOR CHART DATA -@dashboard_bp.route("/api/subcontractor-chart") -def subcontractor_chart(): +# ✅ API: Get Unique RA Bills +@dashboard_bp.route("/api/get-ra-bills") +def get_ra_bills(): subcontractor_id = request.args.get("subcontractor") category = request.args.get("category") + + if not subcontractor_id or not category: + return {"ra_bills": []} + + match category: + + case "trench_excavation": + results = db.session.query( + TrenchExcavation.RA_Bill_No + ).filter( + TrenchExcavation.subcontractor_id == subcontractor_id + ).distinct().order_by(TrenchExcavation.RA_Bill_No).all() + + # (Add others same pattern later) + case _: + results = [] + + ra_bills = [r[0] for r in results if r[0]] + + return {"ra_bills": ra_bills} + + +# API FOR CHART DATA +# @dashboard_bp.route("/api/subcontractor-chart") +# def subcontractor_chart(): + +# subcontractor_id = request.args.get("subcontractor") +# category = request.args.get("category") +# ra_bill = request.args.get("ra_bill") + +# labels = [] +# values = [] + +# match category: + +# # ✅ Trench +# case "trench_excavation": +# query = db.session.query( +# TrenchExcavation.excavation_category, +# func.sum(TrenchExcavation.Total) +# ) + +# if subcontractor_id: +# query = query.filter(TrenchExcavation.subcontractor_id == subcontractor_id) + +# if ra_bill: +# query = query.filter(TrenchExcavation.RA_Bill_No == ra_bill) + +# results = query.group_by(TrenchExcavation.excavation_category).all() + +# # ✅ Manhole +# case "manhole_excavation": +# query = db.session.query( +# ManholeExcavation.excavation_category, +# func.sum(ManholeExcavation.Total) +# ) + +# if subcontractor_id: +# query = query.filter(ManholeExcavation.subcontractor_id == subcontractor_id) + +# if ra_bill: +# query = query.filter(ManholeExcavation.RA_Bill_No == ra_bill) + +# results = query.group_by(ManholeExcavation.excavation_category).all() + +# case _: +# results = [] + +# for r in results: +# labels.append(r[0]) +# values.append(float(r[1] or 0)) + +# return jsonify({ +# "labels": labels, +# "values": values +# }) + + + + +@dashboard_bp.route("/api/trench-analysis") +def trench_analysis(): + + subcontractor_id = request.args.get("subcontractor") ra_bill = request.args.get("ra_bill") - query = db.session.query( - TrenchExcavation.excavation_category, - func.sum(TrenchExcavation.Total) - ) + query = TrenchExcavation.query if subcontractor_id: query = query.filter(TrenchExcavation.subcontractor_id == subcontractor_id) - if category: - query = query.filter(TrenchExcavation.subcontractor_id == subcontractor_id) - if ra_bill: query = query.filter(TrenchExcavation.RA_Bill_No == ra_bill) - results = query.group_by(TrenchExcavation.excavation_category).all() + data = query.all() - labels = [] - values = [] + result = { + "Soft Murum": {"depth": 0, "qty": 0}, + "Hard Murum": {"depth": 0, "qty": 0}, + "Soft Rock": {"depth": 0, "qty": 0}, + "Hard Rock": {"depth": 0, "qty": 0}, + } - for r in results: - labels.append(r[0]) - values.append(float(r[1] or 0)) + for r in data: + + # Soft Murum + result["Soft Murum"]["depth"] += ( + (r.Soft_Murum_0_to_1_5 or 0) + + (r.Soft_Murum_1_5_to_3_0 or 0) + + (r.Soft_Murum_3_0_to_4_5 or 0) + ) + result["Soft Murum"]["qty"] += ( + (r.Soft_Murum_0_to_1_5_total or 0) + + (r.Soft_Murum_1_5_to_3_0_total or 0) + + (r.Soft_Murum_3_0_to_4_5_total or 0) + ) + + # Hard Murum + result["Hard Murum"]["depth"] += ( + (r.Hard_Murum_0_to_1_5 or 0) + + (r.Hard_Murum_1_5_to_3_0 or 0) + ) + result["Hard Murum"]["qty"] += ( + (r.Hard_Murum_0_to_1_5_total or 0) + + (r.Hard_Murum_1_5_and_above_total or 0) + ) + + # Soft Rock + result["Soft Rock"]["depth"] += ( + (r.Soft_Rock_0_to_1_5 or 0) + + (r.Soft_Rock_1_5_to_3_0 or 0) + ) + result["Soft Rock"]["qty"] += ( + (r.Soft_Rock_0_to_1_5_total or 0) + + (r.Soft_Rock_1_5_and_above_total or 0) + ) + + # Hard Rock + result["Hard Rock"]["depth"] += ( + (r.Hard_Rock_0_to_1_5 or 0) + + (r.Hard_Rock_1_5_to_3_0 or 0) + + (r.Hard_Rock_3_0_to_4_5 or 0) + + (r.Hard_Rock_4_5_to_6_0 or 0) + + (r.Hard_Rock_6_0_to_7_5 or 0) + ) + result["Hard Rock"]["qty"] += ( + (r.Hard_Rock_0_to_1_5_total or 0) + + (r.Hard_Rock_1_5_to_3_0_total or 0) + + (r.Hard_Rock_3_0_to_4_5_total or 0) + + (r.Hard_Rock_4_5_to_6_0_total or 0) + + (r.Hard_Rock_6_0_to_7_5_total or 0) + ) + + labels = list(result.keys()) + depth = [result[k]["depth"] for k in labels] + qty = [result[k]["qty"] for k in labels] return jsonify({ "labels": labels, - "values": values + "depth": depth, + "qty": qty }) \ No newline at end of file diff --git a/app/services/file_service.py b/app/services/file_service.py index 206ec1c..791485e 100644 --- a/app/services/file_service.py +++ b/app/services/file_service.py @@ -1,10 +1,10 @@ +from app import db import os import pandas as pd from werkzeug.utils import secure_filename from app.utils.file_utils import ensure_upload_folder - -from app.config import Config -from app import db +from app.utils.file_utils import get_uploads_folder +from app.utils.file_utils import ALLOWED_EXTENSIONS # Subcontractor models import from app.models.trench_excavation_model import TrenchExcavation @@ -24,7 +24,7 @@ class FileService: # ---------------- COMMON HELPERS ---------------- def allowed_file(self, filename): - return ("." in filename and filename.rsplit(".", 1)[1].lower() in Config.ALLOWED_EXTENSIONS) + return ("." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS) def normalize(self, val): if val is None or pd.isna(val): @@ -52,8 +52,9 @@ class FileService: return False, "Invalid file type! Allowed: CSV, XLSX, XLS" ensure_upload_folder() + path = get_uploads_folder() - folder = os.path.join(Config.UPLOAD_FOLDER, f"sub_{subcontractor_id}") + folder = os.path.join(path, f"sub_{subcontractor_id}") os.makedirs(folder, exist_ok=True) filename = secure_filename(file.filename) @@ -310,7 +311,6 @@ class FileService: db.session.commit() - # ---------------- CLIENT FILE UPLOAD ---------------- def handle_client_file_upload(self, file, RA_Bill_No): @@ -324,8 +324,9 @@ class FileService: return False, "Invalid file type! Allowed: CSV, XLSX, XLS" ensure_upload_folder() + path = get_uploads_folder() - folder = os.path.join(Config.UPLOAD_FOLDER, f"Client_Bill_{RA_Bill_No}") + folder = os.path.join(path, f"Client_Bill_{RA_Bill_No}") os.makedirs(folder, exist_ok=True) filename = secure_filename(file.filename) diff --git a/app/templates/subcontractor_dashboard.html b/app/templates/subcontractor_dashboard.html index 8a05ffc..2d54c5e 100644 --- a/app/templates/subcontractor_dashboard.html +++ b/app/templates/subcontractor_dashboard.html @@ -1,33 +1,31 @@ {% extends "base.html" %} {% block content %} -
+
-

Subcontractor Dashboard

+

RA Bill Dashboard

+
+
+