diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f349a89 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +# Ignore folders +instance/ +static/uploads/ + +# Ignore files +.env + +# Ignore by type +*.log diff --git a/app/__pycache__/__init__.cpython-313.pyc b/app/__pycache__/__init__.cpython-313.pyc index ff00ddd..9535808 100644 Binary files a/app/__pycache__/__init__.cpython-313.pyc and b/app/__pycache__/__init__.cpython-313.pyc differ diff --git a/app/__pycache__/config.cpython-313.pyc b/app/__pycache__/config.cpython-313.pyc index 1e41384..a5e209a 100644 Binary files a/app/__pycache__/config.cpython-313.pyc and b/app/__pycache__/config.cpython-313.pyc differ diff --git a/app/models/__pycache__/__init__.cpython-313.pyc b/app/models/__pycache__/__init__.cpython-313.pyc index 6f4a5dd..169d989 100644 Binary files a/app/models/__pycache__/__init__.cpython-313.pyc and b/app/models/__pycache__/__init__.cpython-313.pyc differ diff --git a/app/models/__pycache__/manhole_domestic_chamber_model.cpython-313.pyc b/app/models/__pycache__/manhole_domestic_chamber_model.cpython-313.pyc new file mode 100644 index 0000000..4c27703 Binary files /dev/null and b/app/models/__pycache__/manhole_domestic_chamber_model.cpython-313.pyc differ diff --git a/app/models/__pycache__/manhole_excavation_model.cpython-313.pyc b/app/models/__pycache__/manhole_excavation_model.cpython-313.pyc new file mode 100644 index 0000000..b222504 Binary files /dev/null and b/app/models/__pycache__/manhole_excavation_model.cpython-313.pyc differ diff --git a/app/models/__pycache__/subcontractor_model.cpython-313.pyc b/app/models/__pycache__/subcontractor_model.cpython-313.pyc index e8dc042..12ec43f 100644 Binary files a/app/models/__pycache__/subcontractor_model.cpython-313.pyc and b/app/models/__pycache__/subcontractor_model.cpython-313.pyc differ diff --git a/app/models/__pycache__/trench_excavation_model.cpython-313.pyc b/app/models/__pycache__/trench_excavation_model.cpython-313.pyc index a0bd829..9eb233a 100644 Binary files a/app/models/__pycache__/trench_excavation_model.cpython-313.pyc and b/app/models/__pycache__/trench_excavation_model.cpython-313.pyc differ diff --git a/app/models/manhole_domestic_chamber_model.py b/app/models/manhole_domestic_chamber_model.py new file mode 100644 index 0000000..201b34e --- /dev/null +++ b/app/models/manhole_domestic_chamber_model.py @@ -0,0 +1,45 @@ +from app import db +from datetime import datetime + +class ManholeDomesticChamber(db.Model): + __tablename__ = "manhole_domestic_chamber" + + 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="manhole_domestic_chamber_records") + + # Basic Fields + Location = db.Column(db.String(255)) + Node_No = db.Column(db.String(100)) + Depth_of_MH = db.Column(db.Float) + + # Excavation categories + d_0_to_0_75 = db.Column(db.Float) + d_1_06_to_1_65 = db.Column(db.Float) + d_1_06_to_1_65 = db.Column(db.Float) + d_1_66_to_2_15 = db.Column(db.Float) + d_2_16_to_2_65 = db.Column(db.Float) + d_2_66_to_3_15 = db.Column(db.Float) + d_3_16_to_3_65= db.Column(db.Float) + d_3_66_to_4_15 = db.Column(db.Float) + d_4_16_to_4_65 = db.Column(db.Float) + d_4_66_to_5_15 = db.Column(db.Float) + d_5_16_to_5_65 = db.Column(db.Float) + + d_5_66_to_6_15 = db.Column(db.Float) + d_6_16_to_6_65 = db.Column(db.Float) + d_6_66_to_7_15 = db.Column(db.Float) + d_7_16_to_7_65 = db.Column(db.Float) + d_7_66_to_8_15 = db.Column(db.Float) + d_8_16_to_8_65 = db.Column(db.Float) + d_8_66_to_9_15 = db.Column(db.Float) + d_9_16_to_9_65 = db.Column(db.Float) + + Domestic_Chambers = db.Column(db.Float) + + created_at = db.Column(db.DateTime, default=datetime.utcnow) + + def __repr__(self): + return f"" diff --git a/app/models/manhole_excavation_model.py b/app/models/manhole_excavation_model.py index e69de29..7bd6c1d 100644 --- a/app/models/manhole_excavation_model.py +++ b/app/models/manhole_excavation_model.py @@ -0,0 +1,63 @@ +from app import db +from datetime import datetime + +class ManholeExcavation(db.Model): + __tablename__ = "manhole_excavation" + + 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="manhole_records") + + # Basic Fields + Location = db.Column(db.String(255)) + MH_NO = db.Column(db.String(100)) + + 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/routes/__pycache__/__init__.cpython-313.pyc b/app/routes/__pycache__/__init__.cpython-313.pyc index 772ec62..0662791 100644 Binary files a/app/routes/__pycache__/__init__.cpython-313.pyc and b/app/routes/__pycache__/__init__.cpython-313.pyc differ diff --git a/app/routes/__pycache__/dashboard.cpython-313.pyc b/app/routes/__pycache__/dashboard.cpython-313.pyc index 162cc5d..d65064f 100644 Binary files a/app/routes/__pycache__/dashboard.cpython-313.pyc and b/app/routes/__pycache__/dashboard.cpython-313.pyc differ diff --git a/app/routes/__pycache__/file_import.cpython-313.pyc b/app/routes/__pycache__/file_import.cpython-313.pyc index 8370c01..080be18 100644 Binary files a/app/routes/__pycache__/file_import.cpython-313.pyc and b/app/routes/__pycache__/file_import.cpython-313.pyc differ diff --git a/app/routes/__pycache__/subcontractor_routes.cpython-313.pyc b/app/routes/__pycache__/subcontractor_routes.cpython-313.pyc index 55b182e..f228f30 100644 Binary files a/app/routes/__pycache__/subcontractor_routes.cpython-313.pyc and b/app/routes/__pycache__/subcontractor_routes.cpython-313.pyc differ diff --git a/app/services/__pycache__/__init__.cpython-313.pyc b/app/services/__pycache__/__init__.cpython-313.pyc index be71a81..c4798cc 100644 Binary files a/app/services/__pycache__/__init__.cpython-313.pyc and b/app/services/__pycache__/__init__.cpython-313.pyc differ diff --git a/app/services/__pycache__/file_service.cpython-313.pyc b/app/services/__pycache__/file_service.cpython-313.pyc index 43b0dd9..5726a18 100644 Binary files a/app/services/__pycache__/file_service.cpython-313.pyc and b/app/services/__pycache__/file_service.cpython-313.pyc differ diff --git a/app/services/file_service.py b/app/services/file_service.py index 20d9929..0935831 100644 --- a/app/services/file_service.py +++ b/app/services/file_service.py @@ -1,11 +1,12 @@ -# app/services/file_service.py - import os import pandas as pd from werkzeug.utils import secure_filename from app.config import Config from app import db from app.models.trench_excavation_model import TrenchExcavation +from app.models.manhole_excavation_model import ManholeExcavation +from app.models.manhole_domestic_chamber_model import ManholeDomesticChamber + from app.utils.file_utils import ensure_upload_folder @@ -41,8 +42,18 @@ class FileService: print(df.head()) print("=============================\n") + # Trench Excavation save if file_type == "trench_excavation": return self.process_trench_excavation(df, subcontractor_id) + + # Manhole Excavation save + if file_type == "manhole_excavation": + return self.process_manhole_excavation(df, subcontractor_id) + + # Manhole and Domestic Chamber Construction save + if file_type == "manhole_domestic_chamber": + return self.process_manhole_excavation(df, subcontractor_id) + return True, "File uploaded successfully." @@ -51,7 +62,7 @@ class FileService: - # CLEAN & SAVE TRENCH EXCAVATION DATA + # Trench Excavation save method (TrenchExcavation model) def process_trench_excavation(self, df, subcontractor_id): # Clean column names (strip whitespace) @@ -101,3 +112,114 @@ class FileService: except Exception as e: db.session.rollback() return False, f"Trench Excavation Save Failed: {e}" + + + # Manhole Excavation save method (ManholeExcavation model) + def process_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(ManholeExcavation, 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 = ManholeExcavation( + subcontractor_id=subcontractor_id, + **record_data + ) + + db.session.add(record) + saved_count += 1 + + db.session.commit() + return True, f"Manhole Excavation data saved successfully. Total rows: {saved_count}" + + except Exception as e: + db.session.rollback() + return False, f"Manhole Excavation Save Failed: {e}" + + + # Manhole and Domestic Chamber Construction save method (ManholeDomesticChamber model) + def process_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(ManholeDomesticChamber, 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 = ManholeDomesticChamber( + subcontractor_id=subcontractor_id, + **record_data + ) + + db.session.add(record) + saved_count += 1 + + db.session.commit() + return True, f"Manhole Domestic Chamber Construction data saved successfully. Total rows: {saved_count}" + + except Exception as e: + db.session.rollback() + return False, f"Manhole Domestic Chamber Construction Save Failed: {e}" + + + + + + + \ No newline at end of file diff --git a/app/static/uploads/sub_4/MH__Dc.xlsx b/app/static/uploads/sub_4/MH__Dc.xlsx new file mode 100644 index 0000000..fda6952 Binary files /dev/null and b/app/static/uploads/sub_4/MH__Dc.xlsx differ diff --git a/app/static/uploads/sub_4/Mh_Ex.xlsx b/app/static/uploads/sub_4/Mh_Ex.xlsx new file mode 100644 index 0000000..49a1748 Binary files /dev/null and b/app/static/uploads/sub_4/Mh_Ex.xlsx differ diff --git a/app/static/uploads/sub_4/Tr.Ex.xlsx b/app/static/uploads/sub_4/Tr.Ex.xlsx new file mode 100644 index 0000000..9bcd2db Binary files /dev/null and b/app/static/uploads/sub_4/Tr.Ex.xlsx differ diff --git a/app/templates/base.html b/app/templates/base.html index 2169bd2..5110505 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -4,7 +4,7 @@ - {{ title if title else "IndustryBase" }} + {{ title if title else "ComparisonSoftware" }} diff --git a/app/templates/file_import.html b/app/templates/file_import.html index 211d753..68af913 100644 --- a/app/templates/file_import.html +++ b/app/templates/file_import.html @@ -21,11 +21,11 @@ diff --git a/app/utils/__pycache__/file_utils.cpython-313.pyc b/app/utils/__pycache__/file_utils.cpython-313.pyc index 495d14e..0908d0f 100644 Binary files a/app/utils/__pycache__/file_utils.cpython-313.pyc and b/app/utils/__pycache__/file_utils.cpython-313.pyc differ