from flask import Blueprint, render_template, request, send_file, flash from app.models.subcontractor_model import Subcontractor from app.models.trench_excavation_model import TrenchExcavation from app.models.tr_ex_client_model import TrenchExcavationClient from app import db import pandas as pd import io generate_report_bp = Blueprint("generate_report", __name__, url_prefix="/report") @generate_report_bp.route("/comparison_report", methods=["GET", "POST"]) def comparison_report(): subcontractors = Subcontractor.query.all() if request.method == "POST": subcontractor_id = request.form.get("subcontractor_id") if not subcontractor_id: flash("Please select a subcontractor.", "danger") return render_template("generate_comparison_report.html", subcontractors=subcontractors) subcontractor = Subcontractor.query.get_or_404(subcontractor_id) # Fetch data contractor_rows = TrenchExcavation.query.filter_by(subcontractor_id=subcontractor_id).all() client_rows = TrenchExcavationClient.query.filter_by(subcontractor_id=subcontractor_id).all() diff_rows = [] for row1, row2 in zip(client_rows, contractor_rows): total1 = ( (row1.Marshi_Muddy_Slushy_0_to_1_5_total or 0) + (row1.Marshi_Muddy_Slushy_1_5_to_3_0_total or 0) + (row1.Marshi_Muddy_Slushy_3_0_to_4_5_total or 0) + (row1.Soft_Murum_0_to_1_5_total or 0) + (row1.Soft_Murum_1_5_to_3_0_total or 0) + (row1.Soft_Murum_3_0_to_4_5_total or 0) + (row1.Hard_Murum_0_to_1_5_total or 0) + (row1.Hard_Murum_1_5_to_3_0_total or 0) + (row1.Hard_Murum_3_0_to_4_5_total or 0) + (row1.Soft_Rock_0_to_1_5_total or 0) + (row1.Soft_Rock_1_5_to_3_0_total or 0) + (row1.Soft_Rock_3_0_to_4_5_total or 0) + (row1.Hard_Rock_0_to_1_5_total or 0) + (row1.Hard_Rock_1_5_to_3_0_total or 0) + (row1.Hard_Rock_3_0_to_4_5_total or 0) + (row1.Hard_Rock_4_5_to_6_0_total or 0) + (row1.Hard_Rock_6_0_to_7_5_total or 0) ) total2 = ( (row2.Soft_Murum_0_to_1_5_total or 0) + (row2.Soft_Murum_1_5_to_3_0_total or 0) + (row2.Soft_Murum_3_0_to_4_5_total or 0) + (row2.Hard_Murum_0_to_1_5_total or 0) + (row2.Hard_Murum_1_5_and_above_total or 0) + (row2.Soft_Rock_0_to_1_5_total or 0) + (row2.Soft_Rock_1_5_and_above_total or 0) + (row2.Hard_Rock_0_to_1_5_total or 0) + (row2.Hard_Rock_1_5_and_above_total or 0) + (row2.Hard_Rock_4_5_to_6_0_total or 0) + (row2.Hard_Rock_6_0_to_7_5_total or 0) ) diff = total1 - total2 # ---- store for excel ---- diff_rows.append({ "Location": row1.Location, "Node No": row1.MH_NO, "Client Sum": round(total1, 2), "Subcontractor Sum": round(total2, 2), "Diff": round(diff, 2) }) # optional console print print( f"Location : {row1.Location} | " f"MH_NO : {row1.MH_NO} | " f"Client : {total1} | " f"Sub : {total2} | " f"Diff : {diff}" ) # Convert to DataFrame df_contractor = pd.DataFrame([r.__dict__ for r in contractor_rows]) df_client = pd.DataFrame([r.__dict__ for r in client_rows]) df_diff = pd.DataFrame(diff_rows, columns=["Location", "Node No", "Client Sum", "Subcontractor Sum", "Diff"]) # Drop unwanted columns drop_cols = ["id", "subcontractor_id", "created_at", "_sa_instance_state", "Remarks"] df_contractor.drop(columns=drop_cols, errors="ignore", inplace=True) df_client.drop(columns=drop_cols, errors="ignore", inplace=True) # Convert to numeric df_contractor = df_contractor.apply(pd.to_numeric, errors="coerce").fillna(0) df_client = df_client.apply(pd.to_numeric, errors="coerce").fillna(0) # EXPORT EXCEL output = io.BytesIO() file_name = f"{subcontractor.subcontractor_name}_Comparison_Report.xlsx" with pd.ExcelWriter(output, engine="xlsxwriter") as writer: df_contractor.to_excel(writer, index=False, sheet_name="Contractor_Data") df_client.to_excel(writer, index=False, sheet_name="Client_Data") df_diff.to_excel(writer, index=False, sheet_name="Diff") output.seek(0) return send_file( output, as_attachment=True, download_name=file_name, mimetype="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ) return render_template("generate_comparison_report.html", subcontractors=subcontractors)