update code of dash and report of cont_client and devlp abstract of qty
This commit is contained in:
359
app/services/abstract_service.py
Normal file
359
app/services/abstract_service.py
Normal file
@@ -0,0 +1,359 @@
|
||||
from sqlalchemy import func
|
||||
from app import db
|
||||
|
||||
from app.models.subcontractor_model import Subcontractor
|
||||
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.models.laying_model import Laying
|
||||
|
||||
|
||||
class AbstractReportService:
|
||||
|
||||
def __init__(self, subcontractor_id=None, ra_bill_no=None):
|
||||
|
||||
self.subcontractor_id = subcontractor_id
|
||||
self.ra_bill_no = ra_bill_no
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# FILTER
|
||||
# ---------------------------------------------------------
|
||||
def filters(self):
|
||||
filters = {}
|
||||
|
||||
if self.subcontractor_id:
|
||||
filters["subcontractor_id"] = self.subcontractor_id
|
||||
|
||||
if self.ra_bill_no:
|
||||
filters["RA_Bill_No"] = self.ra_bill_no
|
||||
|
||||
return filters
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# CONTRACTOR
|
||||
# ---------------------------------------------------------
|
||||
def contractor_name(self):
|
||||
|
||||
if not self.subcontractor_id:
|
||||
return ""
|
||||
|
||||
contractor = Subcontractor.query.get(self.subcontractor_id)
|
||||
|
||||
if contractor:
|
||||
return contractor.subcontractor_name
|
||||
|
||||
return ""
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# WRITE ABSTRACT SHEET
|
||||
# ---------------------------------------------------------
|
||||
def generate(self, workbook):
|
||||
|
||||
worksheet = workbook.add_worksheet("Abstract")
|
||||
|
||||
title = workbook.add_format({
|
||||
"bold": True,
|
||||
"font_size": 16,
|
||||
"align": "center",
|
||||
"valign": "vcenter",
|
||||
"border": 1
|
||||
})
|
||||
|
||||
heading = workbook.add_format({
|
||||
"bold": True,
|
||||
"bg_color": "#D9EAD3",
|
||||
"border": 1,
|
||||
"align": "center"
|
||||
})
|
||||
|
||||
cell = workbook.add_format({"border": 1})
|
||||
number = workbook.add_format({"border": 1,"num_format": "#,##0.00"})
|
||||
|
||||
# -----------------------------------------------------
|
||||
# HEADER
|
||||
# -----------------------------------------------------
|
||||
worksheet.merge_range(
|
||||
"A1:D1",
|
||||
"ABSTRACT OF QUANTITY",
|
||||
title
|
||||
)
|
||||
|
||||
worksheet.write("A3", "Contractor", heading)
|
||||
worksheet.write("B3", self.contractor_name(), cell)
|
||||
|
||||
worksheet.write("C3", "RA Bill", heading)
|
||||
worksheet.write("D3", self.ra_bill_no or "", cell)
|
||||
|
||||
worksheet.write_row(
|
||||
"A5",
|
||||
[
|
||||
"Sr",
|
||||
"Description",
|
||||
"UOM",
|
||||
"Qty"
|
||||
],
|
||||
heading
|
||||
)
|
||||
|
||||
row = 5
|
||||
sr = 1
|
||||
|
||||
# -----------------------------------------------------
|
||||
# TRENCH
|
||||
# -----------------------------------------------------
|
||||
worksheet.write(row, 0, "")
|
||||
worksheet.write(row, 1, "TRENCH EXCAVATION", heading)
|
||||
|
||||
row += 1
|
||||
|
||||
for item in self.trench_summary():
|
||||
worksheet.write(row, 0, sr, cell)
|
||||
worksheet.write(row, 1, item["Description"], cell)
|
||||
worksheet.write(row, 2, item["UOM"], cell)
|
||||
worksheet.write(row, 3, item["Qty"], number)
|
||||
|
||||
sr += 1
|
||||
row += 1
|
||||
|
||||
# -----------------------------------------------------
|
||||
# MANHOLE
|
||||
# -----------------------------------------------------
|
||||
worksheet.write(row, 1, "MANHOLE EXCAVATION", heading)
|
||||
row += 1
|
||||
|
||||
for item in self.manhole_summary():
|
||||
worksheet.write(row, 0, sr, cell)
|
||||
worksheet.write(row, 1, item["Description"], cell)
|
||||
worksheet.write(row, 2, item["UOM"], cell)
|
||||
worksheet.write(row, 3, item["Qty"], number)
|
||||
|
||||
sr += 1
|
||||
row += 1
|
||||
|
||||
# -----------------------------------------------------
|
||||
# DOMESTIC CHAMBER
|
||||
# -----------------------------------------------------
|
||||
worksheet.write(row, 1, "DOMESTIC CHAMBER", heading)
|
||||
|
||||
row += 1
|
||||
|
||||
for item in self.domestic_summary():
|
||||
worksheet.write(row, 0, sr, cell)
|
||||
worksheet.write(row, 1, item["Description"], cell)
|
||||
worksheet.write(row, 2, item["UOM"], cell)
|
||||
worksheet.write(row, 3, item["Qty"], number)
|
||||
|
||||
sr += 1
|
||||
row += 1
|
||||
|
||||
# -----------------------------------------------------
|
||||
# PIPE LAYING
|
||||
# -----------------------------------------------------
|
||||
worksheet.write(row, 1, "PIPE LAYING", heading)
|
||||
row += 1
|
||||
|
||||
for item in self.laying_summary():
|
||||
worksheet.write(row, 0, sr, cell)
|
||||
worksheet.write(row, 1, item["Description"], cell)
|
||||
worksheet.write(row, 2, item["UOM"], cell)
|
||||
worksheet.write(row, 3, item["Qty"], number)
|
||||
|
||||
sr += 1
|
||||
row += 1
|
||||
|
||||
worksheet.set_column("A:A", 8)
|
||||
worksheet.set_column("B:B", 55)
|
||||
worksheet.set_column("C:C", 10)
|
||||
worksheet.set_column("D:D", 18)
|
||||
|
||||
# ============================================================
|
||||
# TRENCH
|
||||
# ============================================================
|
||||
def trench_summary(self):
|
||||
|
||||
f = self.filters()
|
||||
|
||||
data = [
|
||||
("Soft Murum 0-1.5 mm","Cum",TrenchExcavation.Soft_Murum_0_to_1_5_total),
|
||||
("Soft Murum 1.5-3.0 mm","Cum",TrenchExcavation.Soft_Murum_1_5_to_3_0_total),
|
||||
("Soft Murum 3.0-4.5 mm","Cum",TrenchExcavation.Soft_Murum_3_0_to_4_5_total),
|
||||
|
||||
("Hard Murum 0-1.5 mm","Cum",TrenchExcavation.Hard_Murum_0_to_1_5_total),
|
||||
("Hard Murum Above 1.5 mm","Cum",TrenchExcavation.Hard_Murum_1_5_and_above_total),
|
||||
|
||||
("Soft Rock 0-1.5 mm","Cum",TrenchExcavation.Soft_Rock_0_to_1_5_total),
|
||||
("Soft Rock Above 1.5 mm","Cum",TrenchExcavation.Soft_Rock_1_5_and_above_total),
|
||||
|
||||
("Hard Rock 0-1.5 mm","Cum",TrenchExcavation.Hard_Rock_0_to_1_5_total),
|
||||
("Hard Rock 1.5-3.0 mm","Cum",TrenchExcavation.Hard_Rock_1_5_to_3_0_total),
|
||||
("Hard Rock 3.0-4.5 mm","Cum",TrenchExcavation.Hard_Rock_3_0_to_4_5_total),
|
||||
("Hard Rock 4.5-6.0 mm","Cum",TrenchExcavation.Hard_Rock_4_5_to_6_0_total),
|
||||
("Hard Rock 6.0-7.5 mm","Cum",TrenchExcavation.Hard_Rock_6_0_to_7_5_total),
|
||||
]
|
||||
|
||||
return self.make_summary(data, TrenchExcavation, f)
|
||||
|
||||
# ============================================================
|
||||
# MANHOLE
|
||||
# ============================================================
|
||||
def manhole_summary(self):
|
||||
|
||||
f = self.filters()
|
||||
|
||||
data = [
|
||||
|
||||
("Soft Murum 0-1.5 mm","Cum",ManholeExcavation.Soft_Murum_0_to_1_5_total),
|
||||
("Soft Murum 1.5-3.0 mm","Cum",ManholeExcavation.Soft_Murum_1_5_to_3_0_total),
|
||||
("Soft Murum 3.0-4.5 mm","Cum",ManholeExcavation.Soft_Murum_3_0_to_4_5_total),
|
||||
|
||||
("Hard Murum 0-1.5 mm","Cum",ManholeExcavation.Hard_Murum_0_to_1_5_total),
|
||||
("Hard Murum Above 1.5 mm","Cum",ManholeExcavation.Hard_Murum_1_5_and_above_total),
|
||||
|
||||
("Soft Rock 0-1.5 mm","Cum",ManholeExcavation.Soft_Rock_0_to_1_5_total),
|
||||
("Soft Rock Above 1.5 mm","Cum",ManholeExcavation.Soft_Rock_1_5_and_above_total),
|
||||
|
||||
("Hard Rock 0-1.5 mm","Cum",ManholeExcavation.Hard_Rock_0_to_1_5_total),
|
||||
("Hard Rock 1.5-3.0 mm","Cum",ManholeExcavation.Hard_Rock_1_5_to_3_0_total),
|
||||
("Hard Rock 3.0-4.5 mm","Cum",ManholeExcavation.Hard_Rock_3_0_to_4_5_total),
|
||||
("Hard Rock 4.5-6.0 mm","Cum",ManholeExcavation.Hard_Rock_4_5_to_6_0_total),
|
||||
("Hard Rock 6.0-7.5 mm","Cum",ManholeExcavation.Hard_Rock_6_0_to_7_5_total),
|
||||
|
||||
]
|
||||
|
||||
return self.make_summary(data, ManholeExcavation, f)
|
||||
|
||||
# ============================================================
|
||||
# DOMESTIC CHAMBER
|
||||
# ============================================================
|
||||
def domestic_summary(self):
|
||||
f = self.filters()
|
||||
data = [
|
||||
("0-0.75 mm","Nos",ManholeDomesticChamber.d_0_to_0_75),
|
||||
("0.76-1.05 mm","Nos",ManholeDomesticChamber.d_0_76_to_1_05),
|
||||
("1.06-1.65 mm","Nos",ManholeDomesticChamber.d_1_06_to_1_65),
|
||||
("1.66-2.15 mm","Nos",ManholeDomesticChamber.d_1_66_to_2_15),
|
||||
("2.16-2.65 mm","Nos",ManholeDomesticChamber.d_2_16_to_2_65),
|
||||
("2.66-3.15 mm","Nos",ManholeDomesticChamber.d_2_66_to_3_15),
|
||||
("3.16-3.65 mm","Nos",ManholeDomesticChamber.d_3_16_to_3_65),
|
||||
("3.66-4.15 mm","Nos",ManholeDomesticChamber.d_3_66_to_4_15),
|
||||
("4.16-4.65 mm","Nos",ManholeDomesticChamber.d_4_16_to_4_65),
|
||||
("4.66-5.15 mm","Nos",ManholeDomesticChamber.d_4_66_to_5_15),
|
||||
("5.16-5.65 mm","Nos",ManholeDomesticChamber.d_5_16_to_5_65),
|
||||
("5.66-6.15 mm","Nos",ManholeDomesticChamber.d_5_66_to_6_15),
|
||||
("6.16-6.65 mm","Nos",ManholeDomesticChamber.d_6_16_to_6_65),
|
||||
("6.66-7.15 mm","Nos",ManholeDomesticChamber.d_6_66_to_7_15),
|
||||
("7.16-7.65 mm","Nos",ManholeDomesticChamber.d_7_16_to_7_65),
|
||||
("7.66-8.15 mm","Nos",ManholeDomesticChamber.d_7_66_to_8_15),
|
||||
("8.16-8.65 mm","Nos",ManholeDomesticChamber.d_8_16_to_8_65),
|
||||
("8.66-9.15 mm","Nos",ManholeDomesticChamber.d_8_66_to_9_15),
|
||||
("9.16-9.65 mm","Nos",ManholeDomesticChamber.d_9_16_to_9_65),
|
||||
]
|
||||
|
||||
return self.make_summary(data, ManholeDomesticChamber, f)
|
||||
|
||||
# ============================================================
|
||||
# PIPE LAYING
|
||||
# ============================================================
|
||||
def laying_summary(self):
|
||||
f = self.filters()
|
||||
data = [
|
||||
("150 mm Pipe","RM",Laying.pipe_150_mm),
|
||||
("200 mm Pipe","RM",Laying.pipe_200_mm),
|
||||
("250 mm Pipe","RM",Laying.pipe_250_mm),
|
||||
("300 mm Pipe","RM",Laying.pipe_300_mm),
|
||||
("350 mm Pipe","RM",Laying.pipe_350_mm),
|
||||
("400 mm Pipe","RM",Laying.pipe_400_mm),
|
||||
("450 mm Pipe","RM",Laying.pipe_450_mm),
|
||||
("500 mm Pipe","RM",Laying.pipe_500_mm),
|
||||
("600 mm Pipe","RM",Laying.pipe_600_mm),
|
||||
("700 mm Pipe","RM",Laying.pipe_700_mm),
|
||||
("900 mm Pipe","RM",Laying.pipe_900_mm),
|
||||
("1200 mm Pipe","RM",Laying.pipe_1200_mm),
|
||||
]
|
||||
return self.make_summary(data, Laying, f)
|
||||
|
||||
# ============================================================
|
||||
# COMMON SUMMARY
|
||||
# ============================================================
|
||||
def make_summary(self, items, model, filters):
|
||||
summary = []
|
||||
for desc, uom, column in items:
|
||||
qty = (db.session.query(func.sum(column)).filter_by(**filters).scalar())
|
||||
summary.append({
|
||||
"Description": desc,
|
||||
"UOM": uom,
|
||||
"Qty": float(qty or 0)
|
||||
})
|
||||
return summary
|
||||
|
||||
|
||||
def generate_html(self):
|
||||
|
||||
html = """
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered table-hover table-striped">
|
||||
<thead class="table-success">
|
||||
|
||||
<tr>
|
||||
<th colspan="4" class="text-center fs-4">
|
||||
ABSTRACT OF QUANTITY
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Contractor</th>
|
||||
<td>{}</td>
|
||||
|
||||
<th>RA Bill NO</th>
|
||||
<td>{}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th width="8%">Sr</th>
|
||||
<th>Description</th>
|
||||
<th width="10%">UOM</th>
|
||||
<th width="15%">Qty</th>
|
||||
</tr>
|
||||
|
||||
</thead>
|
||||
<tbody>
|
||||
""".format(
|
||||
self.contractor_name(),
|
||||
self.ra_bill_no or ""
|
||||
)
|
||||
|
||||
sr = 1
|
||||
sections = [
|
||||
("TRENCH EXCAVATION", self.trench_summary()),
|
||||
("MANHOLE EXCAVATION", self.manhole_summary()),
|
||||
("DOMESTIC CHAMBER", self.domestic_summary()),
|
||||
("PIPE LAYING", self.laying_summary())
|
||||
]
|
||||
|
||||
for title, rows in sections:
|
||||
html += f"""
|
||||
<tr class="table-secondary fw-bold">
|
||||
<td colspan="4">{title}</td>
|
||||
</tr>
|
||||
"""
|
||||
|
||||
for item in rows:
|
||||
html += f"""
|
||||
<tr>
|
||||
<td>{sr}</td>
|
||||
<td>{item['Description']}</td>
|
||||
<td>{item['UOM']}</td>
|
||||
<td class="text-end">
|
||||
{item['Qty']:.2f}
|
||||
</td>
|
||||
</tr>
|
||||
"""
|
||||
sr += 1
|
||||
|
||||
html += """
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
"""
|
||||
|
||||
return html
|
||||
@@ -2,9 +2,7 @@ from app import db
|
||||
import os
|
||||
import pandas as pd
|
||||
from werkzeug.utils import secure_filename
|
||||
from app.utils.file_utils import ensure_upload_folder
|
||||
from app.utils.file_utils import get_uploads_folder
|
||||
from app.utils.file_utils import ALLOWED_EXTENSIONS
|
||||
from app.utils.file_utils import ensure_upload_folder, get_uploads_folder, ALLOWED_EXTENSIONS
|
||||
|
||||
# Subcontractor models import
|
||||
from app.models.trench_excavation_model import TrenchExcavation
|
||||
@@ -25,7 +23,8 @@ class FileService:
|
||||
# ---------------- COMMON HELPERS ----------------
|
||||
def allowed_file(self, filename):
|
||||
return ("." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS)
|
||||
|
||||
|
||||
# data normalizations
|
||||
def normalize(self, val):
|
||||
if val is None or pd.isna(val):
|
||||
return None
|
||||
@@ -35,7 +34,8 @@ class FileService:
|
||||
return None
|
||||
|
||||
return val.upper()
|
||||
|
||||
|
||||
# --------------- Sub-contractor service --------------
|
||||
# ---------------- SUBCONTRACTOR FILE UPLOAD ----------------
|
||||
def handle_file_upload(self, file, subcontractor_id, RA_Bill_No):
|
||||
|
||||
@@ -76,7 +76,7 @@ class FileService:
|
||||
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
return False, f"Import failed: {e}"
|
||||
return False, f"Import failed: {e}"
|
||||
|
||||
# ---------------- Trench Excavation (Subcontractor) ----------------
|
||||
def process_trench_excavation(self, df, subcontractor_id, RA_Bill_No):
|
||||
@@ -310,7 +310,7 @@ class FileService:
|
||||
|
||||
db.session.commit()
|
||||
|
||||
|
||||
# --------------- Client service --------------
|
||||
# ---------------- CLIENT FILE UPLOAD ----------------
|
||||
def handle_client_file_upload(self, file, RA_Bill_No):
|
||||
|
||||
|
||||
@@ -5,75 +5,145 @@ from flask import request, session, has_request_context
|
||||
|
||||
|
||||
class RequestContextFilter(logging.Filter):
|
||||
"""Adds request information to every log record."""
|
||||
|
||||
def filter(self, record):
|
||||
|
||||
if has_request_context():
|
||||
record.user = session.get("user_email", "Anonymous")
|
||||
record.ip = request.remote_addr
|
||||
record.user = session.get("user_name", "Anonymous")
|
||||
record.ip = request.remote_addr or "Unknown"
|
||||
record.method = request.method
|
||||
record.url = request.url
|
||||
else:
|
||||
record.user = "System"
|
||||
record.ip = "N/A"
|
||||
record.method = "N/A"
|
||||
record.url = "N/A"
|
||||
record.ip = "-"
|
||||
record.method = "-"
|
||||
record.url = "-"
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class LoggerService:
|
||||
|
||||
@staticmethod
|
||||
def init_app(app):
|
||||
LOG_DIR = "logs"
|
||||
|
||||
if not os.path.exists("logs"):
|
||||
os.makedirs("logs")
|
||||
APP_LOG = "app.log"
|
||||
ERROR_LOG = "error.log"
|
||||
DEBUG_LOG = "debug.log"
|
||||
|
||||
MAX_BYTES = 10 * 1024 * 1024 # 10 MB
|
||||
BACKUP_COUNT = 10
|
||||
|
||||
@classmethod
|
||||
def init_app(cls, app):
|
||||
|
||||
os.makedirs(cls.LOG_DIR, exist_ok=True)
|
||||
|
||||
formatter = logging.Formatter(
|
||||
"%(asctime)s | %(levelname)s | "
|
||||
"User:%(user)s | IP:%(ip)s | "
|
||||
"Method:%(method)s | URL:%(url)s | "
|
||||
"%(message)s"
|
||||
fmt=(
|
||||
"%(asctime)s | "
|
||||
"%(levelname)-8s | "
|
||||
"User=%(user)s | "
|
||||
"IP=%(ip)s | "
|
||||
"%(method)s | "
|
||||
"%(url)s | "
|
||||
"%(message)s"
|
||||
),
|
||||
datefmt="%Y-%m-%d %H:%M:%S"
|
||||
)
|
||||
|
||||
# INFO LOG
|
||||
info_handler = RotatingFileHandler(
|
||||
"logs/app.log",
|
||||
maxBytes=5 * 1024 * 1024,
|
||||
backupCount=5
|
||||
)
|
||||
info_handler.setLevel(logging.INFO)
|
||||
info_handler.setFormatter(formatter)
|
||||
|
||||
# ERROR LOG
|
||||
error_handler = RotatingFileHandler(
|
||||
"logs/error.log",
|
||||
maxBytes=5 * 1024 * 1024,
|
||||
backupCount=5
|
||||
)
|
||||
error_handler.setLevel(logging.ERROR)
|
||||
error_handler.setFormatter(formatter)
|
||||
|
||||
# CONSOLE
|
||||
console_handler = logging.StreamHandler()
|
||||
console_handler.setLevel(logging.DEBUG)
|
||||
console_handler.setFormatter(formatter)
|
||||
|
||||
# 🔹 ADD FILTER (important)
|
||||
context_filter = RequestContextFilter()
|
||||
|
||||
info_handler.addFilter(context_filter)
|
||||
# Remove default handlers
|
||||
app.logger.handlers.clear()
|
||||
|
||||
# ==========================
|
||||
# Application Log
|
||||
# ==========================
|
||||
app_handler = RotatingFileHandler(
|
||||
os.path.join(cls.LOG_DIR, cls.APP_LOG),
|
||||
maxBytes=cls.MAX_BYTES,
|
||||
backupCount=cls.BACKUP_COUNT,
|
||||
encoding="utf-8"
|
||||
)
|
||||
|
||||
app_handler.setLevel(logging.INFO)
|
||||
app_handler.setFormatter(formatter)
|
||||
app_handler.addFilter(context_filter)
|
||||
|
||||
# ==========================
|
||||
# Error Log
|
||||
# ==========================
|
||||
error_handler = RotatingFileHandler(
|
||||
os.path.join(cls.LOG_DIR, cls.ERROR_LOG),
|
||||
maxBytes=cls.MAX_BYTES,
|
||||
backupCount=cls.BACKUP_COUNT,
|
||||
encoding="utf-8"
|
||||
)
|
||||
|
||||
error_handler.setLevel(logging.ERROR)
|
||||
error_handler.setFormatter(formatter)
|
||||
error_handler.addFilter(context_filter)
|
||||
|
||||
# ==========================
|
||||
# Debug Log
|
||||
# ==========================
|
||||
debug_handler = RotatingFileHandler(
|
||||
os.path.join(cls.LOG_DIR, cls.DEBUG_LOG),
|
||||
maxBytes=cls.MAX_BYTES,
|
||||
backupCount=cls.BACKUP_COUNT,
|
||||
encoding="utf-8"
|
||||
)
|
||||
|
||||
debug_handler.setLevel(logging.DEBUG)
|
||||
debug_handler.setFormatter(formatter)
|
||||
debug_handler.addFilter(context_filter)
|
||||
|
||||
# ==========================
|
||||
# Console Log
|
||||
# ==========================
|
||||
console_handler = logging.StreamHandler()
|
||||
|
||||
console_handler.setLevel(logging.INFO)
|
||||
console_handler.setFormatter(formatter)
|
||||
console_handler.addFilter(context_filter)
|
||||
|
||||
# ==========================
|
||||
# Logger Configuration
|
||||
# ==========================
|
||||
app.logger.setLevel(logging.DEBUG)
|
||||
|
||||
app.logger.addHandler(info_handler)
|
||||
app.logger.addHandler(app_handler)
|
||||
app.logger.addHandler(error_handler)
|
||||
app.logger.addHandler(debug_handler)
|
||||
app.logger.addHandler(console_handler)
|
||||
|
||||
# Log every request automatically
|
||||
# ==========================
|
||||
# Automatic Request Logging
|
||||
# ==========================
|
||||
@app.before_request
|
||||
def log_request():
|
||||
app.logger.info("Request Started")
|
||||
def before_request():
|
||||
app.logger.info("Request Started")
|
||||
|
||||
@app.after_request
|
||||
def after_request(response):
|
||||
app.logger.info(
|
||||
f"Request Completed | Status={response.status_code}"
|
||||
)
|
||||
return response
|
||||
|
||||
# ==========================
|
||||
# Exception Logging
|
||||
# ==========================
|
||||
@app.errorhandler(Exception)
|
||||
def log_exception(error):
|
||||
|
||||
app.logger.exception(
|
||||
f"Unhandled Exception: {str(error)}"
|
||||
)
|
||||
|
||||
raise error
|
||||
|
||||
app.logger.info("=" * 70)
|
||||
app.logger.info("Application Started Successfully")
|
||||
app.logger.info("=" * 70)
|
||||
@@ -1,5 +1,6 @@
|
||||
from app.models.user_model import User
|
||||
from app.services.db_service import db
|
||||
from flask import current_app
|
||||
|
||||
class UserService:
|
||||
|
||||
@@ -13,6 +14,7 @@ class UserService:
|
||||
|
||||
db.session.add(user)
|
||||
db.session.commit()
|
||||
current_app.logger.info("User list viewed")
|
||||
return user
|
||||
|
||||
@staticmethod
|
||||
|
||||
Reference in New Issue
Block a user