create project and create model and dashboard
This commit is contained in:
47
app/__init__.py
Normal file
47
app/__init__.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
from flask import Flask
|
||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
from app.config import Config
|
||||||
|
|
||||||
|
db = SQLAlchemy()
|
||||||
|
|
||||||
|
def create_app():
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.config.from_object(Config)
|
||||||
|
|
||||||
|
db.init_app(app)
|
||||||
|
|
||||||
|
# Register Blueprints
|
||||||
|
from app.routes.dashboard import dashboard_bp
|
||||||
|
from app.routes.file_import import file_import_bp
|
||||||
|
# from app.routes.user import user_bp
|
||||||
|
|
||||||
|
app.register_blueprint(dashboard_bp)
|
||||||
|
app.register_blueprint(file_import_bp)
|
||||||
|
# app.register_blueprint(user_bp)
|
||||||
|
|
||||||
|
from app.routes.subcontractor_routes import subcontractor_bp
|
||||||
|
app.register_blueprint(subcontractor_bp)
|
||||||
|
|
||||||
|
return app
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# from flask import Flask
|
||||||
|
# from app.config import Config
|
||||||
|
|
||||||
|
# def create_app():
|
||||||
|
# app = Flask(__name__)
|
||||||
|
# app.config.from_object(Config)
|
||||||
|
|
||||||
|
# # Register Blueprints
|
||||||
|
# from app.routes.dashboard import dashboard_bp
|
||||||
|
# from app.routes.file_import import file_import_bp
|
||||||
|
# from app.routes.user import user_bp
|
||||||
|
|
||||||
|
# app.register_blueprint(dashboard_bp)
|
||||||
|
# app.register_blueprint(file_import_bp)
|
||||||
|
# app.register_blueprint(user_bp)
|
||||||
|
|
||||||
|
# return app
|
||||||
BIN
app/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
app/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/__pycache__/app.cpython-313.pyc
Normal file
BIN
app/__pycache__/app.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/__pycache__/config.cpython-313.pyc
Normal file
BIN
app/__pycache__/config.cpython-313.pyc
Normal file
Binary file not shown.
24
app/config.py
Normal file
24
app/config.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
|
||||||
|
SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:root@localhost/comparisondb"
|
||||||
|
|
||||||
|
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||||
|
SECRET_KEY = "secret123"
|
||||||
|
|
||||||
|
UPLOAD_FOLDER = "app/static/uploads/"
|
||||||
|
ALLOWED_EXTENSIONS = {"xlsx", "xls", "csv"}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# class Config:
|
||||||
|
# SECRET_KEY = os.getenv("SECRET_KEY", "dev_key_12345")
|
||||||
|
|
||||||
|
# UPLOAD_FOLDER = "app/static/uploads/"
|
||||||
|
# ALLOWED_EXTENSIONS = {"xlsx", "xls", "csv"}
|
||||||
|
|
||||||
|
# DB_HOST = "localhost"
|
||||||
|
# DB_USER = "root"
|
||||||
|
# DB_PASSWORD = "root"
|
||||||
|
# DB_NAME = "comparisondb"
|
||||||
0
app/logs/app.log
Normal file
0
app/logs/app.log
Normal file
0
app/models/__init__.py
Normal file
0
app/models/__init__.py
Normal file
BIN
app/models/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
app/models/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/models/__pycache__/subcontractor_model.cpython-313.pyc
Normal file
BIN
app/models/__pycache__/subcontractor_model.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/models/__pycache__/trench_excavation_model.cpython-313.pyc
Normal file
BIN
app/models/__pycache__/trench_excavation_model.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/models/__pycache__/user_model.cpython-313.pyc
Normal file
BIN
app/models/__pycache__/user_model.cpython-313.pyc
Normal file
Binary file not shown.
0
app/models/manhole_excavation_model.py
Normal file
0
app/models/manhole_excavation_model.py
Normal file
21
app/models/subcontractor_model.py
Normal file
21
app/models/subcontractor_model.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
from app import db
|
||||||
|
# from app.services.db_service import db
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
class Subcontractor(db.Model):
|
||||||
|
__tablename__ = "subcontractors"
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
subcontractor_name = db.Column(db.String(255), nullable=False)
|
||||||
|
address = db.Column(db.String(500))
|
||||||
|
gst_no = db.Column(db.String(50))
|
||||||
|
pan_no = db.Column(db.String(50))
|
||||||
|
mobile_no = db.Column(db.String(20))
|
||||||
|
email_id = db.Column(db.String(150))
|
||||||
|
contact_person = db.Column(db.String(150))
|
||||||
|
status = db.Column(db.String(20), default="Active")
|
||||||
|
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<Subcontractor {self.subcontractor_name}>"
|
||||||
|
|
||||||
73
app/models/trench_excavation_model.py
Normal file
73
app/models/trench_excavation_model.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
from app import db
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
class TrenchExcavation(db.Model):
|
||||||
|
__tablename__ = "trench_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="trench_records")
|
||||||
|
|
||||||
|
# Basic Fields
|
||||||
|
Location = db.Column(db.String(255))
|
||||||
|
MH_NO = db.Column(db.String(100))
|
||||||
|
CC_length = db.Column(db.Float)
|
||||||
|
Invert_Level = db.Column(db.Float)
|
||||||
|
MH_Top_Level = db.Column(db.Float)
|
||||||
|
Ground_Level = db.Column(db.Float)
|
||||||
|
ID_of_MH_m = db.Column(db.Float)
|
||||||
|
Actual_Trench_Length = db.Column(db.Float)
|
||||||
|
Pipe_Dia_mm = db.Column(db.Float)
|
||||||
|
|
||||||
|
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)
|
||||||
|
Width_4_5_to_6_0 = db.Column(db.Float)
|
||||||
|
|
||||||
|
Upto_IL_Depth = db.Column(db.Float)
|
||||||
|
Cutting_Depth = db.Column(db.Float)
|
||||||
|
Avg_Depth = 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"<TrenchExcavation {self.Location}>"
|
||||||
21
app/models/user_model.py
Normal file
21
app/models/user_model.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# from app.services.db_service import db
|
||||||
|
# from werkzeug.security import generate_password_hash, check_password_hash
|
||||||
|
|
||||||
|
# class User(db.Model):
|
||||||
|
# id = db.Column(db.Integer, primary_key=True)
|
||||||
|
# name = db.Column(db.String(120))
|
||||||
|
# email = db.Column(db.String(120), unique=True)
|
||||||
|
# password_hash = db.Column(db.String(255))
|
||||||
|
|
||||||
|
# def set_password(self, password):
|
||||||
|
# self.password_hash = generate_password_hash(password)
|
||||||
|
|
||||||
|
# def check_password(self, password):
|
||||||
|
# return check_password_hash(self.password_hash, password)
|
||||||
|
|
||||||
|
|
||||||
|
class User:
|
||||||
|
def __init__(self, id, name, email):
|
||||||
|
self.id = id
|
||||||
|
self.name = name
|
||||||
|
self.email = email
|
||||||
0
app/routes/__init__.py
Normal file
0
app/routes/__init__.py
Normal file
BIN
app/routes/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
app/routes/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/routes/__pycache__/auth.cpython-313.pyc
Normal file
BIN
app/routes/__pycache__/auth.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/routes/__pycache__/dashboard.cpython-313.pyc
Normal file
BIN
app/routes/__pycache__/dashboard.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/routes/__pycache__/file_import.cpython-313.pyc
Normal file
BIN
app/routes/__pycache__/file_import.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/routes/__pycache__/subcontractor_routes.cpython-313.pyc
Normal file
BIN
app/routes/__pycache__/subcontractor_routes.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/routes/__pycache__/user.cpython-313.pyc
Normal file
BIN
app/routes/__pycache__/user.cpython-313.pyc
Normal file
Binary file not shown.
31
app/routes/auth.py
Normal file
31
app/routes/auth.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
from flask import Blueprint, request, render_template, redirect, flash, session
|
||||||
|
from app.services.user_service import UserService
|
||||||
|
|
||||||
|
auth_bp = Blueprint("auth", __name__, url_prefix="/auth")
|
||||||
|
|
||||||
|
# LOGIN PAGE
|
||||||
|
@auth_bp.route("/login", methods=["GET", "POST"])
|
||||||
|
def login():
|
||||||
|
if request.method == "POST":
|
||||||
|
user = UserService.validate_login(
|
||||||
|
request.form["email"],
|
||||||
|
request.form["password"]
|
||||||
|
)
|
||||||
|
if user:
|
||||||
|
session["user_id"] = user.id
|
||||||
|
return redirect("/dashboard")
|
||||||
|
flash("Invalid credentials", "danger")
|
||||||
|
return render_template("login.html")
|
||||||
|
|
||||||
|
# REGISTER API ONLY
|
||||||
|
@auth_bp.route("/register", methods=["POST"])
|
||||||
|
def register():
|
||||||
|
data = request.json
|
||||||
|
UserService.register_user(data["name"], data["email"], data["password"])
|
||||||
|
return {"message": "User registered successfully"}, 201
|
||||||
|
|
||||||
|
# LOGOUT
|
||||||
|
@auth_bp.route("/logout")
|
||||||
|
def logout():
|
||||||
|
session.clear()
|
||||||
|
return redirect("/auth/login")
|
||||||
8
app/routes/dashboard.py
Normal file
8
app/routes/dashboard.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
from flask import Blueprint, render_template
|
||||||
|
|
||||||
|
dashboard_bp = Blueprint("dashboard", __name__)
|
||||||
|
|
||||||
|
@dashboard_bp.route("/")
|
||||||
|
@dashboard_bp.route("/dashboard")
|
||||||
|
def dashboard():
|
||||||
|
return render_template("dashboard.html", title="Dashboard")
|
||||||
21
app/routes/file_import.py
Normal file
21
app/routes/file_import.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
from flask import Blueprint, render_template, request, flash
|
||||||
|
from app.services.file_service import FileService
|
||||||
|
from app.models.subcontractor_model import Subcontractor
|
||||||
|
|
||||||
|
file_import_bp = Blueprint("file_import", __name__, url_prefix="/file")
|
||||||
|
|
||||||
|
@file_import_bp.route("/import", methods=["GET", "POST"])
|
||||||
|
def import_file():
|
||||||
|
subcontractors = Subcontractor.query.all()
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
file = request.files.get("file")
|
||||||
|
subcontractor_id = request.form.get("subcontractor_id")
|
||||||
|
file_type = request.form.get("file_type")
|
||||||
|
|
||||||
|
service = FileService()
|
||||||
|
success, msg = service.handle_file_upload(file, subcontractor_id, file_type)
|
||||||
|
|
||||||
|
flash(msg, "success" if success else "danger")
|
||||||
|
|
||||||
|
return render_template("file_import.html", title="File Import", subcontractors=subcontractors)
|
||||||
64
app/routes/subcontractor_routes.py
Normal file
64
app/routes/subcontractor_routes.py
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
from flask import Blueprint, render_template, request, redirect, flash
|
||||||
|
from app import db
|
||||||
|
from app.models.subcontractor_model import Subcontractor
|
||||||
|
|
||||||
|
subcontractor_bp = Blueprint("subcontractor", __name__, url_prefix="/subcontractor")
|
||||||
|
|
||||||
|
# ---------------- ADD -----------------
|
||||||
|
@subcontractor_bp.route("/add")
|
||||||
|
def add_subcontractor():
|
||||||
|
return render_template("subcontractor/add.html")
|
||||||
|
|
||||||
|
@subcontractor_bp.route("/save", methods=["POST"])
|
||||||
|
def save_subcontractor():
|
||||||
|
subcontractor = Subcontractor(
|
||||||
|
subcontractor_name=request.form.get("subcontractor_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")
|
||||||
|
return redirect("/subcontractor/list")
|
||||||
|
|
||||||
|
# ---------------- LIST -----------------
|
||||||
|
@subcontractor_bp.route("/list")
|
||||||
|
def subcontractor_list():
|
||||||
|
subcontractors = Subcontractor.query.all()
|
||||||
|
return render_template("subcontractor/list.html", subcontractors=subcontractors)
|
||||||
|
|
||||||
|
# ---------------- EDIT -----------------
|
||||||
|
@subcontractor_bp.route("/edit/<int:id>")
|
||||||
|
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"])
|
||||||
|
def update_subcontractor(id):
|
||||||
|
subcontractor = Subcontractor.query.get_or_404(id)
|
||||||
|
|
||||||
|
subcontractor.subcontractor_name = request.form.get("subcontractor_name")
|
||||||
|
subcontractor.contact_person = request.form.get("contact_person")
|
||||||
|
subcontractor.mobile_no = request.form.get("mobile_no")
|
||||||
|
subcontractor.email_id = request.form.get("email_id")
|
||||||
|
subcontractor.gst_no = request.form.get("gst_no")
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
flash("Subcontractor updated successfully!", "success")
|
||||||
|
return redirect("/subcontractor/list")
|
||||||
|
|
||||||
|
# ---------------- DELETE -----------------
|
||||||
|
@subcontractor_bp.route("/delete/<int:id>")
|
||||||
|
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")
|
||||||
9
app/routes/user.py
Normal file
9
app/routes/user.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
from flask import Blueprint, render_template
|
||||||
|
from app.services.user_service import UserService
|
||||||
|
|
||||||
|
user_bp = Blueprint("user", __name__, url_prefix="/user")
|
||||||
|
|
||||||
|
@user_bp.route("/list")
|
||||||
|
def list_users():
|
||||||
|
users = UserService().get_all_users()
|
||||||
|
return render_template("users.html", users=users, title="Users")
|
||||||
0
app/services/__init__.py
Normal file
0
app/services/__init__.py
Normal file
BIN
app/services/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
app/services/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/services/__pycache__/db_service.cpython-313.pyc
Normal file
BIN
app/services/__pycache__/db_service.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/services/__pycache__/file_service.cpython-313.pyc
Normal file
BIN
app/services/__pycache__/file_service.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/services/__pycache__/user_service.cpython-313.pyc
Normal file
BIN
app/services/__pycache__/user_service.cpython-313.pyc
Normal file
Binary file not shown.
19
app/services/db_service.py
Normal file
19
app/services/db_service.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
from flask_migrate import Migrate
|
||||||
|
|
||||||
|
db = SQLAlchemy()
|
||||||
|
migrate = Migrate()
|
||||||
|
|
||||||
|
|
||||||
|
# import mysql.connector
|
||||||
|
# from app.config import Config
|
||||||
|
|
||||||
|
# class DBService:
|
||||||
|
|
||||||
|
# def connect(self):
|
||||||
|
# return mysql.connector.connect(
|
||||||
|
# host=Config.DB_HOST,
|
||||||
|
# user=Config.DB_USER,
|
||||||
|
# password=Config.DB_PASSWORD,
|
||||||
|
# database=Config.DB_NAME
|
||||||
|
# )
|
||||||
103
app/services/file_service.py
Normal file
103
app/services/file_service.py
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
# 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.utils.file_utils import ensure_upload_folder
|
||||||
|
|
||||||
|
|
||||||
|
class FileService:
|
||||||
|
|
||||||
|
def allowed_file(self, filename):
|
||||||
|
return "." in filename and filename.rsplit(".", 1)[1].lower() in Config.ALLOWED_EXTENSIONS
|
||||||
|
|
||||||
|
def handle_file_upload(self, file, subcontractor_id, file_type):
|
||||||
|
|
||||||
|
if not subcontractor_id:
|
||||||
|
return False, "Please select subcontractor."
|
||||||
|
if not file_type:
|
||||||
|
return False, "Please select file type."
|
||||||
|
if not file or file.filename == "":
|
||||||
|
return False, "No file selected."
|
||||||
|
if not self.allowed_file(file.filename):
|
||||||
|
return False, "Invalid file type! Allowed: CSV, XLSX, XLS"
|
||||||
|
|
||||||
|
ensure_upload_folder()
|
||||||
|
|
||||||
|
folder = os.path.join(Config.UPLOAD_FOLDER, f"sub_{subcontractor_id}")
|
||||||
|
os.makedirs(folder, exist_ok=True)
|
||||||
|
|
||||||
|
filename = secure_filename(file.filename)
|
||||||
|
filepath = os.path.join(folder, filename)
|
||||||
|
file.save(filepath)
|
||||||
|
|
||||||
|
try:
|
||||||
|
df = pd.read_csv(filepath) if filename.endswith(".csv") else pd.read_excel(filepath)
|
||||||
|
|
||||||
|
print("\n=== Uploaded File Preview ===")
|
||||||
|
print(df.head())
|
||||||
|
print("=============================\n")
|
||||||
|
|
||||||
|
if file_type == "trench_excavation":
|
||||||
|
return self.process_trench_excavation(df, subcontractor_id)
|
||||||
|
|
||||||
|
return True, "File uploaded successfully."
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"Processing failed: {e}"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# CLEAN & SAVE TRENCH EXCAVATION DATA
|
||||||
|
def process_trench_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(TrenchExcavation, 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 = TrenchExcavation(
|
||||||
|
subcontractor_id=subcontractor_id,
|
||||||
|
**record_data
|
||||||
|
)
|
||||||
|
|
||||||
|
db.session.add(record)
|
||||||
|
saved_count += 1
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
return True, f"Trench Excavation data saved successfully. Total rows: {saved_count}"
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
db.session.rollback()
|
||||||
|
return False, f"Trench Excavation Save Failed: {e}"
|
||||||
47
app/services/user_service.py
Normal file
47
app/services/user_service.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# from app.models.user_model import User
|
||||||
|
# from app.services.db_service import db
|
||||||
|
# import logging
|
||||||
|
|
||||||
|
# class UserService:
|
||||||
|
|
||||||
|
# @staticmethod
|
||||||
|
# def register_user(name, email, password):
|
||||||
|
# user = User(name=name, email=email)
|
||||||
|
# user.set_password(password)
|
||||||
|
# db.session.add(user)
|
||||||
|
# db.session.commit()
|
||||||
|
# logging.info(f"New user registered: {email}")
|
||||||
|
# return user
|
||||||
|
|
||||||
|
# @staticmethod
|
||||||
|
# def validate_login(email, password):
|
||||||
|
# user = User.query.filter_by(email=email).first()
|
||||||
|
# if user and user.check_password(password):
|
||||||
|
# logging.info(f"Login success: {email}")
|
||||||
|
# return user
|
||||||
|
# logging.warning(f"Login failed for: {email}")
|
||||||
|
# return None
|
||||||
|
|
||||||
|
# @staticmethod
|
||||||
|
# def get_all_users():
|
||||||
|
# return User.query.all()
|
||||||
|
|
||||||
|
|
||||||
|
from app.services.db_service import DBService
|
||||||
|
from app.models.user_model import User
|
||||||
|
|
||||||
|
class UserService:
|
||||||
|
|
||||||
|
def get_all_users(self):
|
||||||
|
db = DBService().connect()
|
||||||
|
cursor = db.cursor(dictionary=True)
|
||||||
|
|
||||||
|
cursor.execute("SELECT id, name, email FROM users")
|
||||||
|
rows = cursor.fetchall()
|
||||||
|
|
||||||
|
users = [User(**row) for row in rows]
|
||||||
|
|
||||||
|
cursor.close()
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
return users
|
||||||
35
app/static/css/subcontractor.css
Normal file
35
app/static/css/subcontractor.css
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
body {
|
||||||
|
background: #f5f7fa;
|
||||||
|
font-family: Arial;
|
||||||
|
padding: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
width: 420px;
|
||||||
|
padding: 20px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
margin-top: 10px;
|
||||||
|
display: block;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
input,
|
||||||
|
textarea {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 10px 20px;
|
||||||
|
background: #0055ff;
|
||||||
|
color: #fff;
|
||||||
|
border: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
BIN
app/static/uploads/sub_3/test_comparison.xlsx
Normal file
BIN
app/static/uploads/sub_3/test_comparison.xlsx
Normal file
Binary file not shown.
BIN
app/static/uploads/sub_4/testing11.xlsx
Normal file
BIN
app/static/uploads/sub_4/testing11.xlsx
Normal file
Binary file not shown.
64
app/templates/base.html
Normal file
64
app/templates/base.html
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{{ title if title else "IndustryBase" }}</title>
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body style="background:#f5f7fa;">
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="navbar-brand" href="/">LCEPL</a>
|
||||||
|
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navMenu">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="collapse navbar-collapse" id="navMenu">
|
||||||
|
<ul class="navbar-nav ms-auto">
|
||||||
|
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/dashboard">Dashboard</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/file/import">File Import</a></li>
|
||||||
|
<!-- <li class="nav-item"><a class="nav-link" href="/user/list">Users</a></li> -->
|
||||||
|
<!-- <li class="nav-item"><a class="nav-link" href="/subcontractor/add">Subcontractor</a></li> -->
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#">Subcontractor</a>
|
||||||
|
|
||||||
|
<ul class="dropdown-menu dropdown-menu-dark">
|
||||||
|
<li><a class="dropdown-item" href="/subcontractor/add">Add Subcontractor</a></li>
|
||||||
|
<li><a class="dropdown-item" href="/subcontractor/list">Subcontractor List</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="/user/list">Users</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="container mt-3">
|
||||||
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||||
|
{% for category, message in messages %}
|
||||||
|
<div class="alert alert-{{ category }} alert-dismissible fade show">
|
||||||
|
{{ message }}
|
||||||
|
<button class="btn-close" data-bs-dismiss="alert"></button>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endwith %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container mt-4">
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
10
app/templates/dashboard.html
Normal file
10
app/templates/dashboard.html
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2 class="mb-4">Dashboard</h2>
|
||||||
|
|
||||||
|
<div class="card p-4 shadow-sm">
|
||||||
|
<h5>Welcome to Comparison Project</h5>
|
||||||
|
<p>This is dashboard panel.</p>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
39
app/templates/file_import.html
Normal file
39
app/templates/file_import.html
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2 class="mb-4">File Import</h2>
|
||||||
|
|
||||||
|
<div class="card p-4 shadow-sm">
|
||||||
|
|
||||||
|
<form method="POST" enctype="multipart/form-data">
|
||||||
|
|
||||||
|
<!-- 1. SELECT SUBCONTRACTOR -->
|
||||||
|
<label class="form-label">Select Subcontractor</label>
|
||||||
|
<select name="subcontractor_id" id="subcontractor_id" class="form-select mb-3" required>
|
||||||
|
<option value="">-- Select Subcontractor --</option>
|
||||||
|
|
||||||
|
{% for sc in subcontractors %}
|
||||||
|
<option value="{{ sc.id }}">{{ sc.subcontractor_name }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 2. FILE TYPE (MODEL NAME) -->
|
||||||
|
<label class="form-label">Select File Type</label>
|
||||||
|
<select name="file_type" id="file_type" class="form-select mb-3" required>
|
||||||
|
<option value="">-- Select File Type --</option>
|
||||||
|
<option value="subcontractor_sheet">Subcontractor Sheet</option>
|
||||||
|
<option value="trench_excavation">Trench Excavation (Tr.Ex)</option>
|
||||||
|
<option value="item_rate_sheet">Item Rate Sheet</option>
|
||||||
|
<option value="billing_sheet">Billing Sheet</option>
|
||||||
|
<option value="comparison_sheet">Comparison Sheet</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 3. FILE UPLOAD -->
|
||||||
|
<label class="form-label">Choose File</label>
|
||||||
|
<input type="file" name="file" class="form-control mb-3" required>
|
||||||
|
|
||||||
|
<button class="btn btn-primary w-100">Upload</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
28
app/templates/list_user.html
Normal file
28
app/templates/list_user.html
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2 class="mb-4">Users List</h2>
|
||||||
|
|
||||||
|
<div class="card p-4 shadow-sm">
|
||||||
|
<table class="table table-bordered table-striped">
|
||||||
|
<thead class="table-dark">
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Email</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{% for user in users %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ user.id }}</td>
|
||||||
|
<td>{{ user.name }}</td>
|
||||||
|
<td>{{ user.email }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
17
app/templates/login.html
Normal file
17
app/templates/login.html
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<h2 class="mb-4">Login</h2>
|
||||||
|
|
||||||
|
<div class="card p-4 shadow-sm">
|
||||||
|
<form method="POST">
|
||||||
|
|
||||||
|
<label>Email:</label>
|
||||||
|
<input type="email" name="email" class="form-control mb-3" required>
|
||||||
|
|
||||||
|
<label>Password:</label>
|
||||||
|
<input type="password" name="password" class="form-control mb-3" required>
|
||||||
|
|
||||||
|
<button class="btn btn-success">Login</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
20
app/templates/register.html
Normal file
20
app/templates/register.html
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<h2 class="mb-4">User Registration</h2>
|
||||||
|
|
||||||
|
<div class="card p-4 shadow-sm">
|
||||||
|
<form method="POST">
|
||||||
|
|
||||||
|
<label>Name:</label>
|
||||||
|
<input type="text" name="name" class="form-control mb-3" required>
|
||||||
|
|
||||||
|
<label>Email:</label>
|
||||||
|
<input type="email" name="email" class="form-control mb-3" required>
|
||||||
|
|
||||||
|
<label>Password:</label>
|
||||||
|
<input type="password" name="password" class="form-control mb-3" required>
|
||||||
|
|
||||||
|
<button class="btn btn-primary">Register</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
40
app/templates/subcontractor/add.html
Normal file
40
app/templates/subcontractor/add.html
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="card shadow-sm p-4">
|
||||||
|
|
||||||
|
<h4 class="mb-3">Add New Subcontractor</h4>
|
||||||
|
|
||||||
|
<form action="/subcontractor/save" method="POST">
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Subcontractor Name</label>
|
||||||
|
<input type="text" class="form-control" name="subcontractor_name" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Contact Person</label>
|
||||||
|
<input type="text" class="form-control" name="contact_person">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Mobile</label>
|
||||||
|
<input type="text" class="form-control" name="mobile_no">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Email</label>
|
||||||
|
<input type="email" class="form-control" name="email_id">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">GST No</label>
|
||||||
|
<input type="text" class="form-control" name="gst_no">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="btn btn-success">Save</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
41
app/templates/subcontractor/edit.html
Normal file
41
app/templates/subcontractor/edit.html
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="card shadow-sm p-4">
|
||||||
|
<h4 class="mb-3">Edit Subcontractor</h4>
|
||||||
|
|
||||||
|
<form action="/subcontractor/update/{{ subcontractor.id }}" method="POST">
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Subcontractor Name</label>
|
||||||
|
<input type="text" class="form-control" name="subcontractor_name"
|
||||||
|
value="{{ subcontractor.subcontractor_name }}" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Contact Person</label>
|
||||||
|
<input type="text" class="form-control" name="contact_person" value="{{ subcontractor.contact_person }}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Mobile</label>
|
||||||
|
<input type="text" class="form-control" name="mobile_no" value="{{ subcontractor.mobile_no }}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Email</label>
|
||||||
|
<input type="email" class="form-control" name="email_id" value="{{ subcontractor.email_id }}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">GST No</label>
|
||||||
|
<input type="text" class="form-control" name="gst_no" value="{{ subcontractor.gst_no }}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="btn btn-success">Update</button>
|
||||||
|
<a href="/subcontractor/list" class="btn btn-secondary">Back</a>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
38
app/templates/subcontractor/list.html
Normal file
38
app/templates/subcontractor/list.html
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="card shadow-sm p-4">
|
||||||
|
<h4 class="mb-3">Subcontractor List</h4>
|
||||||
|
|
||||||
|
<table class="table table-bordered table-striped">
|
||||||
|
<thead class="table-dark">
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Mobile</th>
|
||||||
|
<th>Email</th>
|
||||||
|
<th>GST No</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{% for s in subcontractors %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ s.id }}</td>
|
||||||
|
<td>{{ s.subcontractor_name }}</td>
|
||||||
|
<td>{{ s.mobile_no }}</td>
|
||||||
|
<td>{{ s.email_id }}</td>
|
||||||
|
<td>{{ s.gst_no }}</td>
|
||||||
|
<td>
|
||||||
|
<a href="/subcontractor/edit/{{ s.id }}" class="btn btn-sm btn-warning">Edit</a>
|
||||||
|
<a href="/subcontractor/delete/{{ s.id }}" class="btn btn-sm btn-danger"
|
||||||
|
onclick="return confirm('Are you sure?')">Delete</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
28
app/templates/users.htm
Normal file
28
app/templates/users.htm
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h2 class="mb-4">Users List</h2>
|
||||||
|
|
||||||
|
<div class="card p-4 shadow-sm">
|
||||||
|
<table class="table table-bordered table-striped">
|
||||||
|
<thead class="table-dark">
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Email</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{% for user in users %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ user.id }}</td>
|
||||||
|
<td>{{ user.name }}</td>
|
||||||
|
<td>{{ user.email }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
BIN
app/utils/__pycache__/file_utils.cpython-313.pyc
Normal file
BIN
app/utils/__pycache__/file_utils.cpython-313.pyc
Normal file
Binary file not shown.
6
app/utils/file_utils.py
Normal file
6
app/utils/file_utils.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import os
|
||||||
|
from app.config import Config
|
||||||
|
|
||||||
|
def ensure_upload_folder():
|
||||||
|
if not os.path.exists(Config.UPLOAD_FOLDER):
|
||||||
|
os.makedirs(Config.UPLOAD_FOLDER)
|
||||||
2
app/utils/helpers.py
Normal file
2
app/utils/helpers.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
def is_logged_in(session):
|
||||||
|
return session.get("user_id") is not None
|
||||||
BIN
instance/comparisondb.db
Normal file
BIN
instance/comparisondb.db
Normal file
Binary file not shown.
200
logs/app.log
Normal file
200
logs/app.log
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
2025-12-09 13:11:05,606 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5000
|
||||||
|
2025-12-09 13:11:05,607 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 13:11:05,608 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:11:06,239 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:11:06,240 | INFO | * Debugger PIN: 105-645-384
|
||||||
|
2025-12-09 13:11:48,880 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5000
|
||||||
|
2025-12-09 13:11:48,881 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 13:11:48,882 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:11:49,519 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:11:49,521 | INFO | * Debugger PIN: 105-645-384
|
||||||
|
2025-12-09 13:12:05,727 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\services\\user_service.py', reloading
|
||||||
|
2025-12-09 13:12:05,826 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:12:06,499 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:12:06,501 | INFO | * Debugger PIN: 105-645-384
|
||||||
|
2025-12-09 13:12:09,545 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\config.py', reloading
|
||||||
|
2025-12-09 13:12:09,654 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:12:10,286 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:12:10,288 | INFO | * Debugger PIN: 105-645-384
|
||||||
|
2025-12-09 13:12:12,311 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\routes\\auth.py', reloading
|
||||||
|
2025-12-09 13:12:12,407 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:12:13,071 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:12:13,072 | INFO | * Debugger PIN: 105-645-384
|
||||||
|
2025-12-09 13:12:16,128 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\config.py', reloading
|
||||||
|
2025-12-09 13:12:16,257 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:12:16,898 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:12:16,900 | INFO | * Debugger PIN: 105-645-384
|
||||||
|
2025-12-09 13:12:20,944 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\routes\\user.py', reloading
|
||||||
|
2025-12-09 13:12:21,042 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:12:21,719 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:12:21,721 | INFO | * Debugger PIN: 105-645-384
|
||||||
|
2025-12-09 13:12:23,762 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\routes\\file_import.py', reloading
|
||||||
|
2025-12-09 13:12:23,870 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:12:24,505 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:12:24,507 | INFO | * Debugger PIN: 105-645-384
|
||||||
|
2025-12-09 13:12:27,561 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\services\\__init__.py', reloading
|
||||||
|
2025-12-09 13:12:27,670 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:12:28,294 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:12:28,296 | INFO | * Debugger PIN: 105-645-384
|
||||||
|
2025-12-09 13:12:31,336 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\services\\db_service.py', reloading
|
||||||
|
2025-12-09 13:12:31,448 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:12:32,097 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:12:32,099 | INFO | * Debugger PIN: 105-645-384
|
||||||
|
2025-12-09 13:13:05,662 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\config.py', reloading
|
||||||
|
2025-12-09 13:13:05,773 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:13:06,466 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:13:06,469 | INFO | * Debugger PIN: 105-645-384
|
||||||
|
2025-12-09 13:13:10,944 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5000
|
||||||
|
2025-12-09 13:13:10,944 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 13:13:10,945 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:13:11,623 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:13:11,625 | INFO | * Debugger PIN: 105-645-384
|
||||||
|
2025-12-09 13:14:11,295 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\run.py', reloading
|
||||||
|
2025-12-09 13:14:11,393 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:14:12,004 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:14:12,006 | INFO | * Debugger PIN: 105-645-384
|
||||||
|
2025-12-09 13:14:32,108 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5001
|
||||||
|
2025-12-09 13:14:32,109 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 13:14:32,110 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:14:32,699 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:14:32,701 | INFO | * Debugger PIN: 105-645-384
|
||||||
|
2025-12-09 13:15:58,632 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\run.py', reloading
|
||||||
|
2025-12-09 13:15:58,733 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:15:59,415 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:15:59,416 | INFO | * Debugger PIN: 105-645-384
|
||||||
|
2025-12-09 13:16:03,475 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\run.py', reloading
|
||||||
|
2025-12-09 13:16:03,583 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:16:04,204 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:16:04,206 | INFO | * Debugger PIN: 105-645-384
|
||||||
|
2025-12-09 13:16:33,504 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\run.py', reloading
|
||||||
|
2025-12-09 13:16:33,605 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:16:34,213 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:16:34,215 | INFO | * Debugger PIN: 105-645-384
|
||||||
|
2025-12-09 13:16:41,815 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5000
|
||||||
|
2025-12-09 13:16:41,816 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 13:18:12,302 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5000
|
||||||
|
2025-12-09 13:18:12,302 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 13:22:07,114 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5001
|
||||||
|
2025-12-09 13:22:07,114 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 13:22:07,116 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:22:07,935 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:22:07,937 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 13:23:21,204 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\run.py', reloading
|
||||||
|
2025-12-09 13:23:21,305 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:24:06,973 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5001
|
||||||
|
2025-12-09 13:24:06,973 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 13:24:06,974 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:24:07,689 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:24:07,691 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 13:24:36,315 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\app.py', reloading
|
||||||
|
2025-12-09 13:24:36,418 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:24:37,074 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:24:37,076 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 13:26:54,442 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\__init__.py', reloading
|
||||||
|
2025-12-09 13:26:54,543 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:26:59,170 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5001
|
||||||
|
2025-12-09 13:26:59,170 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 13:26:59,171 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:26:59,827 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:26:59,829 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 13:28:47,631 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\__init__.py', reloading
|
||||||
|
2025-12-09 13:28:47,747 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:28:48,478 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:28:48,480 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 13:28:51,150 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5001
|
||||||
|
2025-12-09 13:28:51,151 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 13:28:51,153 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:28:51,788 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:28:51,790 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 13:28:54,904 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\__init__.py', reloading
|
||||||
|
2025-12-09 13:28:55,010 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:28:55,608 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:28:55,610 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 13:28:56,644 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\__init__.py', reloading
|
||||||
|
2025-12-09 13:28:56,752 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:29:04,454 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5001
|
||||||
|
2025-12-09 13:29:04,454 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 13:29:04,455 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:29:05,096 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:29:05,098 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 13:30:01,657 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5001
|
||||||
|
2025-12-09 13:30:01,657 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 13:30:01,658 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:30:02,278 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:30:02,280 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 13:30:27,872 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5001
|
||||||
|
2025-12-09 13:30:27,872 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 13:30:27,873 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:30:28,474 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:30:28,476 | INFO | * Debugger PIN: 105-645-384
|
||||||
|
2025-12-09 13:33:22,709 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5001
|
||||||
|
2025-12-09 13:33:22,709 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 13:33:22,710 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:33:23,778 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:33:23,781 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 13:33:29,939 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\services\\db_service.py', reloading
|
||||||
|
2025-12-09 13:33:30,080 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:33:44,462 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5001
|
||||||
|
2025-12-09 13:33:44,462 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 13:33:44,464 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:33:45,216 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:33:45,218 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 13:35:23,298 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5001
|
||||||
|
2025-12-09 13:35:23,299 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 13:35:23,301 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:35:24,098 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:35:24,100 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 13:38:25,991 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\__init__.py', reloading
|
||||||
|
2025-12-09 13:38:26,126 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:38:27,120 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:38:27,122 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 13:38:37,386 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\config.py', reloading
|
||||||
|
2025-12-09 13:38:37,513 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:38:38,297 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:38:38,300 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 13:38:45,485 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\run.py', reloading
|
||||||
|
2025-12-09 13:38:45,605 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:38:46,348 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:38:46,350 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 13:38:55,109 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5001
|
||||||
|
2025-12-09 13:38:55,109 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 13:38:55,110 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:38:55,959 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:38:55,961 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 13:39:27,813 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\__init__.py', reloading
|
||||||
|
2025-12-09 13:39:27,937 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:39:28,684 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:39:28,687 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 13:40:00,602 | INFO | * Detected change in 'C:\\Work\\lcepl_Projects\\Comparison Project\\app\\__init__.py', reloading
|
||||||
|
2025-12-09 13:40:00,728 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:40:01,428 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:40:01,430 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 13:40:21,531 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5001
|
||||||
|
2025-12-09 13:40:21,531 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 13:40:21,533 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 13:40:22,307 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 13:40:22,309 | INFO | * Debugger PIN: 697-115-033
|
||||||
|
2025-12-09 14:03:58,363 | INFO | [31m[1mWARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.[0m
|
||||||
|
* Running on http://127.0.0.1:5001
|
||||||
|
2025-12-09 14:03:58,363 | INFO | [33mPress CTRL+C to quit[0m
|
||||||
|
2025-12-09 14:03:58,364 | INFO | * Restarting with stat
|
||||||
|
2025-12-09 14:03:59,038 | WARNING | * Debugger is active!
|
||||||
|
2025-12-09 14:03:59,041 | INFO | * Debugger PIN: 697-115-033
|
||||||
7
requirements.txt
Normal file
7
requirements.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Flask
|
||||||
|
pandas
|
||||||
|
openpyxl
|
||||||
|
xlrd
|
||||||
|
Werkzeug
|
||||||
|
python-dotenv
|
||||||
|
cryptography
|
||||||
Reference in New Issue
Block a user