update code of dash and report of cont_client and devlp abstract of qty

This commit is contained in:
2026-07-30 14:38:37 +05:30
parent 12b2032430
commit bf1df3a817
42 changed files with 3066 additions and 952 deletions

View 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