Merge branch 'main' of http://gitea.lcepl.org/pjpatil12/Comparison_Project into pankaj-dev
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import re
|
||||
from sqlalchemy import func
|
||||
from app import db
|
||||
|
||||
@@ -7,6 +8,13 @@ from app.models.manhole_excavation_model import ManholeExcavation
|
||||
from app.models.manhole_domestic_chamber_model import ManholeDomesticChamber
|
||||
from app.models.laying_model import Laying
|
||||
|
||||
from app.models.tr_ex_client_model import TrenchExcavationClient
|
||||
from app.models.mh_ex_client_model import ManholeExcavationClient
|
||||
from app.models.mh_dc_client_model import ManholeDomesticChamberClient
|
||||
from app.models.laying_client_model import LayingClient
|
||||
|
||||
from app.utils.regex_utils import RegularExpression
|
||||
|
||||
|
||||
class AbstractReportService:
|
||||
|
||||
@@ -356,4 +364,215 @@ class AbstractReportService:
|
||||
</div>
|
||||
"""
|
||||
|
||||
return html
|
||||
|
||||
|
||||
# ================================================================
|
||||
# CLIENT ABSTRACT REPORT
|
||||
def _format_range_text(raw):
|
||||
"""'6_0_to_7_5' -> '6.0-7.5' '0_to_1_5' -> '0-1.5'"""
|
||||
raw = re.sub(r'(\d+)_(\d+)', lambda m: f"{m.group(1)}.{m.group(2)}", raw)
|
||||
return raw.replace("_to_", "-")
|
||||
|
||||
|
||||
def _label_for_total_column(col_name):
|
||||
"""'Soft_Murum_0_to_1_5_total' -> 'Soft Murum 0-1.5 mm'"""
|
||||
value = col_name[:-6] if col_name.endswith("_total") else col_name
|
||||
|
||||
m = re.search(r'(\d[\d_]*_to_[\d_]+)$', value)
|
||||
if m:
|
||||
prefix = value[:m.start()].rstrip("_").replace("_", " ")
|
||||
range_text = _format_range_text(m.group(1))
|
||||
return f"{prefix} {range_text} mm".strip()
|
||||
|
||||
return value.replace("_", " ").title()
|
||||
|
||||
|
||||
def _label_for_d_range_column(col_name):
|
||||
"""'d_6_0_to_6_5' -> '6.0-6.5 mm'"""
|
||||
raw = col_name[2:] # strip leading "d_"
|
||||
return f"{_format_range_text(raw)} mm"
|
||||
|
||||
|
||||
def _label_for_pipe_column(col_name):
|
||||
"""'pipe_150_mm' -> '150 mm Dia'"""
|
||||
m = re.match(r"pipe_(\d+)_mm", col_name)
|
||||
if m:
|
||||
return f"{m.group(1)} mm Dia"
|
||||
return col_name.replace("_", " ").title()
|
||||
|
||||
|
||||
class ClientAbstractReportService:
|
||||
|
||||
def __init__(self, ra_bill_no=None):
|
||||
self.ra_bill_no = ra_bill_no
|
||||
|
||||
def filters(self):
|
||||
f = {}
|
||||
if self.ra_bill_no:
|
||||
f["RA_Bill_No"] = self.ra_bill_no
|
||||
return f
|
||||
|
||||
def _summary(self, model, matcher, uom, label_fn):
|
||||
f = self.filters()
|
||||
summary = []
|
||||
|
||||
for column in model.__table__.columns:
|
||||
if matcher(column.name):
|
||||
qty = (
|
||||
db.session.query(func.sum(getattr(model, column.name)))
|
||||
.filter_by(**f)
|
||||
.scalar()
|
||||
)
|
||||
summary.append({
|
||||
"Description": label_fn(column.name),
|
||||
"UOM": uom,
|
||||
"Qty": float(qty or 0)
|
||||
})
|
||||
|
||||
return summary
|
||||
|
||||
# ------------------------------------------------------------
|
||||
def trench_summary(self):
|
||||
return self._summary(
|
||||
TrenchExcavationClient,
|
||||
RegularExpression.STR_TOTAL_PATTERN.match,
|
||||
"Cum",
|
||||
_label_for_total_column
|
||||
)
|
||||
|
||||
def manhole_summary(self):
|
||||
return self._summary(
|
||||
ManholeExcavationClient,
|
||||
RegularExpression.STR_TOTAL_PATTERN.match,
|
||||
"Cum",
|
||||
_label_for_total_column
|
||||
)
|
||||
|
||||
def domestic_summary(self):
|
||||
return self._summary(
|
||||
ManholeDomesticChamberClient,
|
||||
RegularExpression.D_RANGE_PATTERN.match,
|
||||
"Nos",
|
||||
_label_for_d_range_column
|
||||
)
|
||||
|
||||
def laying_summary(self):
|
||||
return self._summary(
|
||||
LayingClient,
|
||||
RegularExpression.PIPE_MM_PATTERN.match,
|
||||
"RM",
|
||||
_label_for_pipe_column
|
||||
)
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# EXCEL 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"})
|
||||
|
||||
worksheet.merge_range("A1:D1", "ABSTRACT OF QUANTITY (CLIENT)", title)
|
||||
|
||||
worksheet.write("A3", "RA Bill No", heading)
|
||||
worksheet.write("B3", self.ra_bill_no or "", cell)
|
||||
|
||||
worksheet.write_row("A5", ["Sr", "Description", "UOM", "Qty"], heading)
|
||||
|
||||
row = 5
|
||||
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_text, rows in sections:
|
||||
worksheet.write(row, 1, title_text, heading)
|
||||
row += 1
|
||||
|
||||
for item in rows:
|
||||
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)
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# HTML (for web preview)
|
||||
# ------------------------------------------------------------
|
||||
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>RA Bill NO</th>
|
||||
<td colspan="3">{}</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.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_text, rows in sections:
|
||||
html += f"""
|
||||
<tr class="table-secondary fw-bold">
|
||||
<td colspan="4">{title_text}</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
|
||||
Reference in New Issue
Block a user