sub-cont model validations

This commit is contained in:
2026-01-17 15:41:26 +05:30
parent e4837b203a
commit 8cba86323e
3 changed files with 152 additions and 74 deletions

View File

@@ -167,6 +167,7 @@ def client_vs_all_subcontractor():
qty_cols = [...] # (Keep your existing list) qty_cols = [...] # (Keep your existing list)
mh_dc_qty_cols = [...] # (Keep your existing list) mh_dc_qty_cols = [...] # (Keep your existing list)
mh_lay_qty_cols =[...]
def aggregate_df(df, group_cols, sum_cols): def aggregate_df(df, group_cols, sum_cols):
if df.empty: if df.empty:
@@ -183,10 +184,11 @@ def client_vs_all_subcontractor():
df_sub_tr_grp = aggregate_df(contractorBill.df_tr, ["Location", "MH_NO"], qty_cols) df_sub_tr_grp = aggregate_df(contractorBill.df_tr, ["Location", "MH_NO"], qty_cols)
df_sub_mh_grp = aggregate_df(contractorBill.df_mh, ["Location", "MH_NO"], qty_cols) df_sub_mh_grp = aggregate_df(contractorBill.df_mh, ["Location", "MH_NO"], qty_cols)
df_sub_dc_grp = aggregate_df(contractorBill.df_dc, ["Location", "MH_NO"], mh_dc_qty_cols) df_sub_dc_grp = aggregate_df(contractorBill.df_dc, ["Location", "MH_NO"], mh_dc_qty_cols)
df_sub_lay_grp = aggregate_df(contractorBill.df_dc, ["Location", "MH_NO"], mh_lay_qty_cols)
# --- FINAL MERGE LOGIC --- # --- FINAL MERGE LOGIC ---
# We check if "Location" exists in the client data. If not, we add it to prevent the KeyError. # We check if "Location" exists in the client data. If not, we add it to prevent the KeyError.
for df_client in [clientBill.df_tr, clientBill.df_mh, clientBill.df_dc]: for df_client in [clientBill.df_tr, clientBill.df_mh, clientBill.df_dc, clientBill.df_laying ]:
if not df_client.empty and "Location" not in df_client.columns: if not df_client.empty and "Location" not in df_client.columns:
df_client["Location"] = "Unknown" df_client["Location"] = "Unknown"
@@ -194,6 +196,7 @@ def client_vs_all_subcontractor():
df_tr_cmp = clientBill.df_tr.merge(df_sub_tr_grp, on=["Location", "MH_NO"], how="left", suffixes=("_Client", "_Sub")) df_tr_cmp = clientBill.df_tr.merge(df_sub_tr_grp, on=["Location", "MH_NO"], how="left", suffixes=("_Client", "_Sub"))
df_mh_cmp = clientBill.df_mh.merge(df_sub_mh_grp, on=["Location", "MH_NO"], how="left", suffixes=("_Client", "_Sub")) df_mh_cmp = clientBill.df_mh.merge(df_sub_mh_grp, on=["Location", "MH_NO"], how="left", suffixes=("_Client", "_Sub"))
df_dc_cmp = clientBill.df_dc.merge(df_sub_dc_grp, on=["Location", "MH_NO"], how="left", suffixes=("_Client", "_Sub")) df_dc_cmp = clientBill.df_dc.merge(df_sub_dc_grp, on=["Location", "MH_NO"], how="left", suffixes=("_Client", "_Sub"))
df_lay_cmp = clientBill.df_laying.merge(df_sub_lay_grp, on=["Location", "MH_NO"], how="left", suffixes=("_Client", "_Sub"))
except KeyError as e: except KeyError as e:
flash(f"Merge Error: Missing column {str(e)}. Check if 'Location' is defined in your database models.", "danger") flash(f"Merge Error: Missing column {str(e)}. Check if 'Location' is defined in your database models.", "danger")
return render_template("generate_comparison_client_vs_subcont.html", tables=tables, ra_val=ra_val) return render_template("generate_comparison_client_vs_subcont.html", tables=tables, ra_val=ra_val)
@@ -203,6 +206,7 @@ def client_vs_all_subcontractor():
tables["tr"] = df_tr_cmp.to_html(classes='table table-striped table-hover table-sm', index=False) tables["tr"] = df_tr_cmp.to_html(classes='table table-striped table-hover table-sm', index=False)
tables["mh"] = df_mh_cmp.to_html(classes='table table-striped table-hover table-sm', index=False) tables["mh"] = df_mh_cmp.to_html(classes='table table-striped table-hover table-sm', index=False)
tables["dc"] = df_dc_cmp.to_html(classes='table table-striped table-hover table-sm', index=False) tables["dc"] = df_dc_cmp.to_html(classes='table table-striped table-hover table-sm', index=False)
tables["laying"] = df_lay_cmp.to_html(classes='table table-striped table-hover table-sm', index=False)
return render_template("client_report.html", tables=tables, ra_val=ra_val) return render_template("client_report.html", tables=tables, ra_val=ra_val)

View File

@@ -10,21 +10,42 @@ subcontractor_bp = Blueprint("subcontractor", __name__, url_prefix="/subcontract
@login_required @login_required
def add_subcontractor(): def add_subcontractor():
return render_template("subcontractor/add.html") return render_template("subcontractor/add.html")
@subcontractor_bp.route("/save", methods=["POST"]) @subcontractor_bp.route("/save", methods=["POST"])
@login_required @login_required
def save_subcontractor(): def save_subcontractor():
subcontractor = Subcontractor( # 1. Get and clean the name from the form
subcontractor_name=request.form.get("subcontractor_name"), name = request.form.get("subcontractor_name", "").strip()
contact_person=request.form.get("contact_person"),
mobile_no=request.form.get("mobile_no"), # 2. Basic validation: Ensure the name isn't empty
email_id=request.form.get("email_id"), if not name:
gst_no=request.form.get("gst_no") flash("Subcontractor name cannot be empty.", "danger")
) return redirect("/subcontractor/add")
db.session.add(subcontractor)
db.session.commit() # 3. Check if a subcontractor with this name already exists
existing_sub = Subcontractor.query.filter_by(subcontractor_name=name).first()
if existing_sub:
flash(f"Subcontractor with name '{name}' already exists!", "danger")
return redirect("/subcontractor/add")
# 4. If no duplicate is found, proceed to save
try:
subcontractor = Subcontractor(
subcontractor_name=name,
contact_person=request.form.get("contact_person"),
mobile_no=request.form.get("mobile_no"),
email_id=request.form.get("email_id"),
gst_no=request.form.get("gst_no")
)
db.session.add(subcontractor)
db.session.commit()
flash("Subcontractor added successfully!", "success")
except Exception as e:
db.session.rollback()
flash("An error occurred while saving. Please try again.", "danger")
flash("Subcontractor added successfully!", "success")
return redirect("/subcontractor/list") return redirect("/subcontractor/list")
# ---------------- LIST ----------------- # ---------------- LIST -----------------
@@ -46,12 +67,19 @@ def edit_subcontractor(id):
@login_required @login_required
def update_subcontractor(id): def update_subcontractor(id):
subcontractor = Subcontractor.query.get_or_404(id) subcontractor = Subcontractor.query.get_or_404(id)
new_name = request.form.get("subcontractor_name")
subcontractor.subcontractor_name = request.form.get("subcontractor_name") # Check if the new name is taken by someone ELSE (not this current ID)
subcontractor.contact_person = request.form.get("contact_person") duplicate = Subcontractor.query.filter(
subcontractor.mobile_no = request.form.get("mobile_no") Subcontractor.subcontractor_name == new_name,
subcontractor.email_id = request.form.get("email_id") Subcontractor.id != id
subcontractor.gst_no = request.form.get("gst_no") ).first()
if duplicate:
flash("Another subcontractor already uses this name.", "danger")
return redirect(f"/subcontractor/edit/{id}")
subcontractor.subcontractor_name = new_name
db.session.commit() db.session.commit()
@@ -69,3 +97,95 @@ def delete_subcontractor(id):
flash("Subcontractor deleted successfully!", "success") flash("Subcontractor deleted successfully!", "success")
return redirect("/subcontractor/list") return redirect("/subcontractor/list")
from flask import Blueprint, render_template, request, redirect, flash
from app import db
from app.models.subcontractor_model import Subcontractor
from app.utils.helpers import login_required
subcontractor_bp = Blueprint("subcontractor", __name__, url_prefix="/subcontractor")
# ---------------- ADD -----------------
@subcontractor_bp.route("/add")
@login_required
def add_subcontractor():
return render_template("subcontractor/add.html")
@subcontractor_bp.route("/save", methods=["POST"])
@login_required
def save_subcontractor():
name = request.form.get("subcontractor_name", "").strip()
if not name:
flash("Subcontractor name cannot be empty.", "danger")
return redirect("/subcontractor/add")
existing_sub = Subcontractor.query.filter_by(subcontractor_name=name).first()
if existing_sub:
flash(f"Subcontractor with name '{name}' already exists!", "danger")
return redirect("/subcontractor/add")
try:
subcontractor = Subcontractor(
subcontractor_name=name,
contact_person=request.form.get("contact_person"),
mobile_no=request.form.get("mobile_no"),
email_id=request.form.get("email_id"),
gst_no=request.form.get("gst_no")
)
db.session.add(subcontractor)
db.session.commit()
flash("Subcontractor added successfully!", "success")
except Exception as e:
db.session.rollback()
flash("An error occurred while saving. Please try again.", "danger")
return redirect("/subcontractor/list")
# ---------------- LIST -----------------
@subcontractor_bp.route("/list")
@login_required
def subcontractor_list():
subcontractors = Subcontractor.query.all()
return render_template("subcontractor/list.html", subcontractors=subcontractors)
# ---------------- EDIT -----------------
@subcontractor_bp.route("/edit/<int:id>")
@login_required
def edit_subcontractor(id):
subcontractor = Subcontractor.query.get_or_404(id)
return render_template("subcontractor/edit.html", subcontractor=subcontractor)
# ---------------- UPDATE -----------------
@subcontractor_bp.route("/update/<int:id>", methods=["POST"])
@login_required
def update_subcontractor(id):
subcontractor = Subcontractor.query.get_or_404(id)
new_name = request.form.get("subcontractor_name")
# Check if the new name is taken by someone ELSE (not this current ID)
duplicate = Subcontractor.query.filter(
Subcontractor.subcontractor_name == new_name,
Subcontractor.id != id
).first()
if duplicate:
flash("Another subcontractor already uses this name.", "danger")
return redirect(f"/subcontractor/edit/{id}")
subcontractor.subcontractor_name = new_name
db.session.commit()
flash("Subcontractor updated successfully!", "success")
return redirect("/subcontractor/list")
# ---------------- DELETE -----------------
@subcontractor_bp.route("/delete/<int:id>")
@login_required
def delete_subcontractor(id):
subcontractor = Subcontractor.query.get_or_404(id)
db.session.delete(subcontractor)
db.session.commit()
flash("Subcontractor deleted successfully!", "success")
return redirect("/subcontractor/list")

View File

@@ -1,34 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block content %} {% block content %}
<<<<<<< HEAD
<div class="container mt-4">
<<<<<<< HEAD
<h2 class="mb-4">Generate Subcontractor Report</h2>
=======
<h2 class="mb-4 text-center">Generate Subcontractor Report</h2>
>>>>>>> pankaj-dev
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
)
{% endfor %}
{% endif %}
{% endwith %}
<<<<<<< HEAD
<div class="card p-4 shadow-sm">
<form method="POST">
=======
<div class="card p-4 shadow-sm mx-auto" style="max-width: 600px;">
<form method="POST" id="reportForm">
>>>>>>> pankaj-dev
=======
<div class="container my-4"> <div class="container my-4">
<h2 class="text-center mb-4">Generate Subcontractor Report</h2> <h2 class="text-center mb-4">Generate Subcontractor Report</h2>
@@ -37,25 +9,11 @@
<div class="card shadow-sm p-3 p-md-4 mx-auto" style="max-width:600px;"> <div class="card shadow-sm p-3 p-md-4 mx-auto" style="max-width:600px;">
<form method="POST"> <form method="POST">
>>>>>>> pankaj-dev
<div class="mb-3"> <div class="mb-3">
<label class="form-label fw-semibold">Select Subcontractor</label> <label class="form-label fw-semibold">Select Subcontractor</label>
<select name="subcontractor_id" class="form-select" required> <select name="subcontractor_id" class="form-select" required>
<option value="">-- Select Subcontractor --</option> <option value="">-- Select Subcontractor --</option>
{% for sc in subcontractors %} {% for sc in subcontractors %}
<<<<<<< HEAD
<option value="{{ sc.id }}">{{ sc.subcontractor_name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">RA Bill Number</label>
<input type="text" name="ra_bill_no" class="form-control" placeholder="e.g. 01" required>
</div>
<button type="submit" class="btn btn-primary w-100">Generate Excel Report</button>
=======
<option value="{{ sc.id }}" {% if selected_sc_id==sc.id|string %}selected{% endif %}> <option value="{{ sc.id }}" {% if selected_sc_id==sc.id|string %}selected{% endif %}>
{{ sc.subcontractor_name }} {{ sc.subcontractor_name }}
</option> </option>
@@ -89,11 +47,7 @@
</button> </button>
</div> </div>
</div> </div>
<<<<<<< HEAD
>>>>>>> pankaj-dev
=======
>>>>>>> pankaj-dev
</form> </form>
</div> </div>