sub-cont model validations
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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():
|
||||||
|
# 1. Get and clean the name from the form
|
||||||
|
name = request.form.get("subcontractor_name", "").strip()
|
||||||
|
|
||||||
|
# 2. Basic validation: Ensure the name isn't empty
|
||||||
|
if not name:
|
||||||
|
flash("Subcontractor name cannot be empty.", "danger")
|
||||||
|
return redirect("/subcontractor/add")
|
||||||
|
|
||||||
|
# 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 = Subcontractor(
|
||||||
subcontractor_name=request.form.get("subcontractor_name"),
|
subcontractor_name=name,
|
||||||
contact_person=request.form.get("contact_person"),
|
contact_person=request.form.get("contact_person"),
|
||||||
mobile_no=request.form.get("mobile_no"),
|
mobile_no=request.form.get("mobile_no"),
|
||||||
email_id=request.form.get("email_id"),
|
email_id=request.form.get("email_id"),
|
||||||
gst_no=request.form.get("gst_no")
|
gst_no=request.form.get("gst_no")
|
||||||
)
|
)
|
||||||
|
|
||||||
db.session.add(subcontractor)
|
db.session.add(subcontractor)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
flash("Subcontractor added successfully!", "success")
|
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")
|
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")
|
||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user