From 608006d9774c32cfd2faf229989c21f1f67774dd Mon Sep 17 00:00:00 2001 From: Daniel Roth Date: Tue, 9 Jun 2026 13:29:11 +0000 Subject: [PATCH] reapply conditional formatting to populated file --- .../d1_ventilation_template.xlsx | Bin 15658 -> 16133 bytes orchestration/audit_generator_orchestrator.py | 26 ++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/applications/audit_generator/d1_ventilation_template.xlsx b/applications/audit_generator/d1_ventilation_template.xlsx index 057da026fc51d3b5e3abe2ca43732e8d8252c1d3..f42272e0efd71fa3f688a21288d2489580d83029 100644 GIT binary patch delta 7483 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 Jyz`-u zYBOgMy`99b!G z@0#YFVjE0KJZhjSZ>DOJps>A$5|F)CMqj)dk|MMzm(1Ngm^(0EXA87%pg1xw17GqH z6?{q=ZU_atBNzCXT2cBO-EK`ecBnl5c6<1^d)^zjO_JJdMMtah0f^q$!r4|Lr8T1K z-qZJI)fhtbEc@JSyRnm*wI&9~cRa{7&1r$bc^BWysE}*wdb+|d_r@ziV=qf{#V0sB zH1=RHwB}<5*N$?i!N7J0Spd;ZV_#d9BQw{~^K~#s=B~Bl)3lo}^A5iU^XE){S~ml= zejzO(fsW-FrxE!KI1p^E<16<4Z3JvLFFD+hB*?3#z#E&Vu1A(RGd%bqKaZv5vu-f9 zk2!U$Io@zc42_IN%m(MY*s#u}DjUkdD0u@hucS_mC75~weWlf{8)Cuz3^Ov)Dexd` zt|xtEw&ynGE>S}zKR0ZfdYe$AqYU%j@S%YcE(sN-Y=qkMT$p*cp2LQiS$deVnUaZ@ z$r9`|%t9lSV~pWsLrH|Mm08g@l0(_K4Wa3&X?q=##HeY|bC0^h+UFikdw*=23mw16 zCZ@{*x*fPXR(ktNm{_Lj-rE!vO|3?e476L)YMY2*zM?WI6jph=iYnK^!{W(Gyju5A z(~hf!R2if6yN&Ua!3edd{;G{j1&2z>84%K_^?g$G_Ta=V8k>X|jHQBwHNk%-?Q|i#H3SB z;Xj|mhwz3r2^#wOTHqP1*f%xxZ|MK{G;FtlkXaUGWy#dkgW&~R2uC6x9aV+vHZ!=)HAQNcF6 zUz*~r87^N+N$1TC+^~LtVrbL(GvjysRjCwysg&1XtY?P zi>1`w?m6Qjlm0oZQZsXe!Y&SN@>k6pX-mh1ibH4pZ92rsT7x-5TQNp=c9#(b zWYm0w#>ivQVTr~_5=uF;$LKbQd$4LZydE+v?I0tzQ&`NgeQesnZ8$}dr%;t4{>`=h z^VPtG6gVE_^&DWW7c61w(y>K(Ff>oTWRAR?$IORr6r|zd|FC@d*L?qBiF$yAv{exp zF(IJl1mS-1A{;BiAEwmP63d+zglA~eorQ%A52+uZ^_h!vXq`I&JG>T?NrZzlUFrvi=PS1_MM!AV25=LPUKKdrsbb zEL8MV!!x`HM@+2J%7XCzAEOaSp-FY`4uZa_7x;lLT1tS7{s#C(djL#`|4#zIhyR(t z>VhyNR%vNjjG;qHbn(-chdR;%lxTWlIWK<*f;JVc@vF>{Z6|r9?d^D_Q^FDX5RPgF zmU_XTf&<^x4RUs?AFfXA9;BmbF}5?8oP<4T6fu54%Nba={&v zlN5`<#qPp@6}GO0uqS;6mWJDFW*Qw;1hwtAXqq{Nd1;x(>0%0S3Quk!ylO-6f*+uz zp(+Ev0@8x~BDC3FxWwk32cg5A*vwB)emP(n~w0AQ><|c@8)qX7V>RKT^R27W-pKV|IT9& zt`5v&4-DimQs~>>7%;T|sXeg!kzWA#MSI{s^?(RgvV%zCB&Z52)NsuDnt$v^P?3hJ z;NmBY-;E+-mRCCQnv^a1igbEA<}7j=ppPqG{^BJ$xc%saD|Vnp^6LsQ5D0H?afF4m11W*Eu6zZH z*X7C_M*X7CIKsl(a|3N$Bl8xGHJ8cLDai@k$izTs&o@S2ac3VT6t~mZC0e>Az^=MGeyz&(zTwDa_ynocv$)%|=+oi3zC6&Uy zvKl*nBT1<2soJsSv4ZMiz*E^8*L$K+{~nGrP-l#P%sN~D5sR)@b@fK=Xyxckwtmer z;6EEtk(pursCt}K)L7Qn)M>`^Z42vFQs&_R^jGk~x#6^^p*7}U9l04up~*m7)X z6m_8Vd!fYfbsH@=*GEf*?)-)ev0ks7JCJ;&yeqtXR!5GfRNVBG0P!Mo%o_)N8Fu0%zt?Azn z(`kl#fH?55{I44fb7yDT1;*d#v>T9mV-4BEb0=xX@E{$|-EaQ1CK4bDLc5eJFB;xr zKLGZF1O7Q?6 diff --git a/orchestration/audit_generator_orchestrator.py b/orchestration/audit_generator_orchestrator.py index 1cea614f..a22979c4 100644 --- a/orchestration/audit_generator_orchestrator.py +++ b/orchestration/audit_generator_orchestrator.py @@ -7,6 +7,10 @@ from pathlib import Path from typing import TYPE_CHECKING, Any, cast import openpyxl +from openpyxl.cell.rich_text import CellRichText, TextBlock +from openpyxl.cell.text import InlineFont +from openpyxl.formatting.rule import CellIsRule # type: ignore[reportUnknownVariableType] +from openpyxl.styles import Color, Font from domain.magicplan.models import Door, Plan, Room, Window from infrastructure.postgres.uploaded_file_table import ( @@ -23,6 +27,26 @@ _TEMPLATE_PATH = Path(__file__).parent.parent / "applications" / "audit_generato _SHEET_NAME = "D1 Ventilation" _DATA_START_ROW = 6 _MAX_ROWS = 50 +_Y_CF_RANGE = f"Y{_DATA_START_ROW}:Y{_DATA_START_ROW + _MAX_ROWS - 1}" +_Y_THRESHOLD = 7600 +_Y_HEADER = CellRichText( + TextBlock(InlineFont(b=True, sz=11, rFont="Aptos Narrow"), "Area (mm2)\n"), + TextBlock(InlineFont(b=True, sz=11, color=Color(rgb="FF0000"), rFont="Aptos Narrow"), "<"), + TextBlock(InlineFont(b=True, sz=11, rFont="Aptos Narrow"), " 7600 "), + TextBlock(InlineFont(b=True, sz=11, color=Color(rgb="196B24"), rFont="Aptos Narrow"), "<"), +) + + +def _apply_column_y_formatting(sheet: Any) -> None: + sheet.conditional_formatting.add( + _Y_CF_RANGE, + CellIsRule(operator="lessThan", formula=[str(_Y_THRESHOLD)], font=Font(color=Color(rgb="FF0000"))), + ) + sheet.conditional_formatting.add( + _Y_CF_RANGE, + CellIsRule(operator="greaterThan", formula=[str(_Y_THRESHOLD)], font=Font(color=Color(rgb="196B24"))), + ) + sheet["Y3"] = _Y_HEADER def _write_cell(sheet: Any, row: int, col: str, value: Any) -> None: @@ -75,6 +99,8 @@ def _populate_sheet(sheet: Any, plan: Plan) -> None: _write_cell(sheet, row, "X", vent.undercut_mm if vent else 0) # Y = formula =W*X — do not write + _apply_column_y_formatting(sheet) + def _serialise_workbook(wb: Any) -> bytes: buf = BytesIO()