From 89328c90660680bff2438ccd64086f4bf0c30a29 Mon Sep 17 00:00:00 2001 From: pjpatil12 Date: Sat, 13 Dec 2025 18:50:27 +0530 Subject: [PATCH] client models and report commit --- app/__init__.py | 7 +- app/__pycache__/__init__.cpython-313.pyc | Bin 1153 -> 1289 bytes ...ole_domestic_chamber_model.cpython-313.pyc | Bin 3486 -> 3486 bytes .../mh_ex_client_model.cpython-313.pyc | Bin 0 -> 4671 bytes .../tr_ex_client_model.cpython-313.pyc | Bin 0 -> 6269 bytes .../trench_excavation_model.cpython-313.pyc | Bin 5390 -> 5392 bytes app/models/mh_dc_client_model.py | 45 ++++ app/models/mh_ex_client_model.py | 66 ++++++ app/models/tr_ex_client_model.py | 84 +++++++ app/models/trench_excavation_model.py | 1 + .../__pycache__/file_import.cpython-313.pyc | Bin 1502 -> 2366 bytes .../__pycache__/file_report.cpython-313.pyc | Bin 5301 -> 5301 bytes ...generate_comparison_report.cpython-313.pyc | Bin 0 -> 5163 bytes app/routes/file_import.py | 19 +- app/routes/generate_comparison_report.py | 218 ++++++++++++++++++ .../__pycache__/file_service.cpython-313.pyc | Bin 9246 -> 11387 bytes app/services/file_service.py | 108 ++++++++- app/templates/base.html | 34 ++- app/templates/file_import.html | 2 +- app/templates/file_import_client.html | 39 ++++ app/templates/generate_comparison_report.html | 39 ++++ 21 files changed, 645 insertions(+), 17 deletions(-) create mode 100644 app/models/__pycache__/mh_ex_client_model.cpython-313.pyc create mode 100644 app/models/__pycache__/tr_ex_client_model.cpython-313.pyc create mode 100644 app/models/mh_dc_client_model.py create mode 100644 app/models/mh_ex_client_model.py create mode 100644 app/models/tr_ex_client_model.py create mode 100644 app/routes/__pycache__/generate_comparison_report.cpython-313.pyc create mode 100644 app/routes/generate_comparison_report.py create mode 100644 app/templates/file_import_client.html create mode 100644 app/templates/generate_comparison_report.html diff --git a/app/__init__.py b/app/__init__.py index b589d00..caa5ea1 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -11,18 +11,19 @@ def create_app(): db.init_app(app) # Register Blueprints + # from app.routes.user import user_bp from app.routes.subcontractor_routes import subcontractor_bp from app.routes.dashboard import dashboard_bp from app.routes.file_import import file_import_bp - # from app.routes.user import user_bp from app.routes.file_report import file_report_bp + from app.routes.generate_comparison_report import generate_report_bp - + # app.register_blueprint(user_bp) app.register_blueprint(subcontractor_bp) app.register_blueprint(dashboard_bp) app.register_blueprint(file_import_bp) - # app.register_blueprint(user_bp) app.register_blueprint(file_report_bp) + app.register_blueprint(generate_report_bp) diff --git a/app/__pycache__/__init__.cpython-313.pyc b/app/__pycache__/__init__.cpython-313.pyc index e29c10b191ee4946ae5f6597f6f88df58e163cde..8433b70e26cbe17c878b3d0a34b6709aefb9f021 100644 GIT binary patch delta 341 zcmZqV?BwG8%*)Hg00hfCY%}X7@=j+gnz(egKrmx4n>W9gKpv|CLnuR#^5hgoMMmYx zZD4W*m^{U(pcbSI(uxW~Sxp%sA|S0Q44Ukd-!b}&Gu{$PPt8j$N-Rl@FG?-QFDi*o zD$o>~Y{#@&Lp8CWK(8pjv?R4y53VRVKer&UD6=>}530V1d-7W*301aR%s}Nu>_9t; zI6wp^hyeMah#N>0vjGW($tujgT#`T*NLg{uhId&^!N_CsHfCMf z8!YVCS)?wqNX@Xj!lDJ|U69tj!lF0%BeRPlKhTIGkXb7kiljhn2_SKc!zMRBr8Fni Ru1J1z7>hE8I3qt;761d$QuP1; delta 236 zcmeC=YUJeo%*)Hg00f@5tTWjr@=j-TnYeT}ODIE-{Nw^gMP+%A94ZK9GG&B_C@_H4 zZDCYol%IT!QGrE;L6dE=43j^jz~m;T&65+EMdVp;F((!j6tM$!6mftEP7ndIvX~V} zOrFK;%OwtEfD{y0P5#KN%g4sR>d1JP#qchR=~EWd$@(n1d=FUIud_&9WRaR-cZEf3 uawUt4A|Fsg5lH7sh9U_NTMS6t;;_lhPbtkwwJVaHe2+z$LyVChEDHeGF)t|q diff --git a/app/models/__pycache__/manhole_domestic_chamber_model.cpython-313.pyc b/app/models/__pycache__/manhole_domestic_chamber_model.cpython-313.pyc index cb81deb29d8de2cb50e96fb42d3eeec8253da6dc..0482c1c068234035c177e6e52a930f3521ed0a60 100644 GIT binary patch delta 20 acmbOyJx`kZGcPX}0}wDf+iv8Z%nJZB2n2Kh delta 20 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 N{saGmkn6R+{sbhF^~V4J literal 0 HcmV?d00001 diff --git a/app/models/__pycache__/trench_excavation_model.cpython-313.pyc b/app/models/__pycache__/trench_excavation_model.cpython-313.pyc index 9eb233a07a2df81a97081de24e5e75b0b73469df..35e6b01f6b785d1aeaf91129aa0f6b59e16ae04f 100644 GIT binary patch delta 68 zcmeCvnxMt|nU|M~0SIOb*=Ck+L^xQm+r;LTMe=@J&Kh_Uy3}O" diff --git a/app/models/mh_ex_client_model.py b/app/models/mh_ex_client_model.py new file mode 100644 index 0000000..ce67abd --- /dev/null +++ b/app/models/mh_ex_client_model.py @@ -0,0 +1,66 @@ +from app import db +from datetime import datetime + +class ManholeExcavationClient(db.Model): + __tablename__ = "mh_ex_client" + + id = db.Column(db.Integer, primary_key=True) + # Foreign Key to Subcontractor table + subcontractor_id = db.Column(db.Integer, db.ForeignKey("subcontractors.id"), nullable=False) + # Relationship for easy access (subcontractor.subcontractor_name) + subcontractor = db.relationship("Subcontractor", backref="mh_ex_records") + + # Basic Fields + Location = db.Column(db.String(255)) + MH_NO = db.Column(db.String(100)) + GL_m = db.Column(db.Float) + + + + Upto_IL_Depth = db.Column(db.Float) + Cutting_Depth = db.Column(db.Float) + ID_of_MH_m = db.Column(db.Float) + Ex_Dia_of_Manhole = db.Column(db.Float) + Area_of_Manhole = db.Column(db.Float) + + # Excavation categories + Soft_Murum_0_to_1_5 = db.Column(db.Float) + Soft_Murum_1_5_to_3_0 = db.Column(db.Float) + Soft_Murum_3_0_to_4_5 = db.Column(db.Float) + + Hard_Murum_0_to_1_5 = db.Column(db.Float) + Hard_Murum_1_5_to_3_0 = db.Column(db.Float) + + Soft_Rock_0_to_1_5 = db.Column(db.Float) + Soft_Rock_1_5_to_3_0 = db.Column(db.Float) + + Hard_Rock_0_to_1_5 = db.Column(db.Float) + Hard_Rock_1_5_to_3_0 = db.Column(db.Float) + Hard_Rock_3_0_to_4_5 = db.Column(db.Float) + Hard_Rock_4_5_to_6_0 = db.Column(db.Float) + Hard_Rock_6_0_to_7_5 = db.Column(db.Float) + + # Totals + Soft_Murum_0_to_1_5_total = db.Column(db.Float) + Soft_Murum_1_5_to_3_0_total = db.Column(db.Float) + Soft_Murum_3_0_to_4_5_total = db.Column(db.Float) + + Hard_Murum_0_to_1_5_total = db.Column(db.Float) + Hard_Murum_1_5_and_above_total = db.Column(db.Float) + + Soft_Rock_0_to_1_5_total = db.Column(db.Float) + Soft_Rock_1_5_and_above_total = db.Column(db.Float) + + Hard_Rock_0_to_1_5_total = db.Column(db.Float) + Hard_Rock_1_5_and_above_total = db.Column(db.Float) + Hard_Rock_3_0_to_4_5_total = db.Column(db.Float) + Hard_Rock_4_5_to_6_0_total = db.Column(db.Float) + Hard_Rock_6_0_to_7_5_total = db.Column(db.Float) + + Remarks = db.Column(db.String(500)) + Total = db.Column(db.Float) + + created_at = db.Column(db.DateTime, default=datetime.utcnow) + + def __repr__(self): + return f"" diff --git a/app/models/tr_ex_client_model.py b/app/models/tr_ex_client_model.py new file mode 100644 index 0000000..6438a0b --- /dev/null +++ b/app/models/tr_ex_client_model.py @@ -0,0 +1,84 @@ +from app import db +from datetime import datetime + +class TrenchExcavationClient(db.Model): + __tablename__ = "tr_ex_client" + + id = db.Column(db.Integer, primary_key=True) + # Foreign Key to Subcontractor table + subcontractor_id = db.Column(db.Integer, db.ForeignKey("subcontractors.id"), nullable=False) + # Relationship for easy access (subcontractor.subcontractor_name) + subcontractor = db.relationship("Subcontractor", backref="tr_ex_records") + + # Basic Fields + Location = db.Column(db.String(255)) + MH_NO = db.Column(db.String(100)) + CC_length = db.Column(db.Float) + Actual_Trench_Length = db.Column(db.Float) + Ground_Level = db.Column(db.Float) + Invert_Level = db.Column(db.Float) + Excavated_level = db.Column(db.Float) + Cutting_Depth = db.Column(db.Float) + Avg_Depth = db.Column(db.Float) + Pipe_Dia_mm = db.Column(db.Float) + + # width + Width_0_to_1_5 = db.Column(db.Float) + Width_1_5_to_3_0 = db.Column(db.Float) + Width_3_0_to_4_5 = db.Column(db.Float) + Width_4_5_to_6_0 = db.Column(db.Float) + + + # Excavation categories + Marshi_Muddy_Slushy_0_to_1_5 = db.Column(db.Float) + Marshi_Muddy_Slushy_1_5_to_3_0 = db.Column(db.Float) + Marshi_Muddy_Slushy_3_0_to_4_5 = db.Column(db.Float) + + Soft_Murum_0_to_1_5 = db.Column(db.Float) + Soft_Murum_1_5_to_3_0 = db.Column(db.Float) + Soft_Murum_3_0_to_4_5 = db.Column(db.Float) + + Hard_Murum_0_to_1_5 = db.Column(db.Float) + Hard_Murum_1_5_to_3_0 = db.Column(db.Float) + Hard_Murum_3_0_to_4_5 = db.Column(db.Float) + + Soft_Rock_0_to_1_5 = db.Column(db.Float) + Soft_Rock_1_5_to_3_0 = db.Column(db.Float) + Soft_Rock_3_0_to_4_5 = db.Column(db.Float) + + Hard_Rock_0_to_1_5 = db.Column(db.Float) + Hard_Rock_1_5_to_3_0 = db.Column(db.Float) + Hard_Rock_3_0_to_4_5 = db.Column(db.Float) + Hard_Rock_4_5_to_6_0 = db.Column(db.Float) + Hard_Rock_6_0_to_7_5 = db.Column(db.Float) + + # Totals + Marshi_Muddy_Slushy_0_to_1_5_total = db.Column(db.Float) + Marshi_Muddy_Slushy_1_5_to_3_0_total = db.Column(db.Float) + Marshi_Muddy_Slushy_3_0_to_4_5_total = db.Column(db.Float) + + Soft_Murum_0_to_1_5_total = db.Column(db.Float) + Soft_Murum_1_5_to_3_0_total = db.Column(db.Float) + Soft_Murum_3_0_to_4_5_total = db.Column(db.Float) + + Hard_Murum_0_to_1_5_total = db.Column(db.Float) + Hard_Murum_1_5_to_3_0_total = db.Column(db.Float) + Hard_Murum_3_0_to_4_5_total = db.Column(db.Float) + + Soft_Rock_0_to_1_5_total = db.Column(db.Float) + Soft_Rock_1_5_to_3_0_total = db.Column(db.Float) + Soft_Rock_3_0_to_4_5_total = db.Column(db.Float) + + Hard_Rock_0_to_1_5_total = db.Column(db.Float) + Hard_Rock_1_5_to_3_0_total = db.Column(db.Float) + Hard_Rock_3_0_to_4_5_total = db.Column(db.Float) + Hard_Rock_4_5_to_6_0_total = db.Column(db.Float) + Hard_Rock_6_0_to_7_5_total = db.Column(db.Float) + + Remarks = db.Column(db.String(500)) + Total = db.Column(db.Float) + + created_at = db.Column(db.DateTime, default=datetime.utcnow) + + def __repr__(self): + return f"" diff --git a/app/models/trench_excavation_model.py b/app/models/trench_excavation_model.py index 6df15ff..c8de958 100644 --- a/app/models/trench_excavation_model.py +++ b/app/models/trench_excavation_model.py @@ -21,6 +21,7 @@ class TrenchExcavation(db.Model): Actual_Trench_Length = db.Column(db.Float) Pipe_Dia_mm = db.Column(db.Float) + # width Width_0_to_2_5 = db.Column(db.Float) Width_2_5_to_3_0 = db.Column(db.Float) Width_3_0_to_4_5 = db.Column(db.Float) diff --git a/app/routes/__pycache__/file_import.cpython-313.pyc b/app/routes/__pycache__/file_import.cpython-313.pyc index 080be180f51275e4aa20164a15dfce24f1502356..433feb3403390f98696ed9047dc6df2a853055e2 100644 GIT binary patch delta 475 zcmcb|y-$emGcPX}0}!k-pbsthRQ! zjGvhqn5;f9@iOKzeo$aw61dJNdXZ7|f|%L{(H(3X_%8t2j1C`x@`Yffj*JjC*l+*~ C<$SLI delta 170 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 delta 903 zcmb7?O>7cD6vyY4vg|HyVJY7<7BH1Al+sq)Cba377CjiF(gTT>h?F!aLNll_X-#@k zFD8J!{{ z9?qnMb2qx=$OYKzVLx%6*bb<<30pfR<g991i=*YZLt6eIUuRPOuKSfLu#&J`R!71F)lQ4w~A-~f{?h(ou!cxeK z-*p|9OqVAsC9`xjLzpFm1#*0jOd2(xC;V>S43@&j#M$ujH}nypXjUUfdjCgMd+^TRM9I|gUq$WDYE-0j zM#QWJu%Ni59dT^F!+W8(=KGii2Z~gYMseCuaV$CIv!2K_d1=Z#O&G=PWTZ$@JV>zq z)=3sY6RQ~)xXrq~U@t>gO4*NgFT${W0lEc9*%#qUQEV%)pH4}JheyTMkv2;8wNjHO z@MrQl{z&=Lif~(XEm?mWcI4TsjkW8w${gPiAs|+B6c forward fill Location + if "Location" in df.columns: + df["Location"] = df["Location"].ffill() + df = df.dropna(how="all") # REMOVE empty rows + # Identify missing location rows before insert + missing_loc = df[df["Location"].isna() | (df["Location"].astype(str).str.strip() == "")] + if not missing_loc.empty: + return False, f"Error: Some rows have empty Location. Rows: {missing_loc.index.tolist()}" + saved_count = 0 + + try: + for index, row in df.iterrows(): + record_data = {} + # Insert only fields that exist in model + for col in df.columns: + if hasattr(TrenchExcavationClient, col): + value = row[col] + # Normalize empty values + if pd.isna(value) or str(value).strip() in ["", "-", "—", "nan", "NaN"]: + value = None + + record_data[col] = value + + record = TrenchExcavationClient( + subcontractor_id=subcontractor_id, + **record_data + ) + + db.session.add(record) + saved_count += 1 + + db.session.commit() + return True, f"Clinnt Tr Ex data saved successfully. Total rows: {saved_count}" + + except Exception as e: + db.session.rollback() + return False, f"Clinnt Tr Ex Save Failed: {e}" + + + # Manhole Excavation save method (ManholeExcavationClient model) + # def client_manhole_excavation(self, df, subcontractor_id): + # # Clean column names (strip whitespace) + # df.columns = [str(c).strip() for c in df.columns] + # # If the sheet has merged cells -> forward fill Location + # if "Location" in df.columns: + # df["Location"] = df["Location"].ffill() + + # # REMOVE empty rows + # df = df.dropna(how="all") + # # Identify missing location rows before insert + # missing_loc = df[df["Location"].isna() | (df["Location"].astype(str).str.strip() == "")] + # if not missing_loc.empty: + # return False, f"Error: Some rows have empty Location. Rows: {missing_loc.index.tolist()}" + + # saved_count = 0 + + # try: + # for index, row in df.iterrows(): + # record_data = {} + # # Insert only fields that exist in model + # for col in df.columns: + # if hasattr(ManholeExcavationClient, col): + # value = row[col] + + # # Normalize empty values + # if pd.isna(value) or str(value).strip() in ["", "-", "—", "nan", "NaN"]: + # value = None + + # record_data[col] = value + + # record = ManholeExcavationClient( + # subcontractor_id=subcontractor_id, + # **record_data + # ) + + # db.session.add(record) + # saved_count += 1 + + # db.session.commit() + # return True, f" Client Mh Ex. data saved successfully. Total rows: {saved_count}" + + # except Exception as e: + # db.session.rollback() + # return False, f"Client Mh Ex. Save Failed: {e}" diff --git a/app/templates/base.html b/app/templates/base.html index f77028f..89eaf69 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -24,17 +24,38 @@ @@ -61,5 +82,4 @@ - - + \ No newline at end of file diff --git a/app/templates/file_import.html b/app/templates/file_import.html index 68af913..e6bfbda 100644 --- a/app/templates/file_import.html +++ b/app/templates/file_import.html @@ -1,7 +1,7 @@ {% extends "base.html" %} {% block content %} -

File Import

+

Sub-Contractor File Import

diff --git a/app/templates/file_import_client.html b/app/templates/file_import_client.html new file mode 100644 index 0000000..189e856 --- /dev/null +++ b/app/templates/file_import_client.html @@ -0,0 +1,39 @@ +{% extends "base.html" %} + +{% block content %} +

Client File Import

+ +
+ +
+ + + + + + + + + + + + + + +
+ +
+{% endblock %} \ No newline at end of file diff --git a/app/templates/generate_comparison_report.html b/app/templates/generate_comparison_report.html new file mode 100644 index 0000000..073f963 --- /dev/null +++ b/app/templates/generate_comparison_report.html @@ -0,0 +1,39 @@ +{% extends "base.html" %} + +{% block content %} +
+ +

Subcontractor vs Client Comparison

+ + + {% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} + {% for category, message in messages %} + + {% endfor %} + {% endif %} + {% endwith %} + +
+ +
+ + + + + + +
+ +
+
+{% endblock %} \ No newline at end of file