Spaces:
Sleeping
Sleeping
File size: 3,462 Bytes
b76f199 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | """Survey product tier → section templates, order, and export labelling.
Resolves :func:`get_template` and section order by ``Report.survey_level`` (1/2/3).
``None`` is treated as **Level 3** for template purposes (legacy reports).
"""
from __future__ import annotations
from dataclasses import dataclass
from typing import TYPE_CHECKING, Final
from app.templates.rics_templates import (
LEVEL_3_DOCX_TITLE,
LEVEL_3_PRODUCT_LABEL,
SectionTemplate,
get_level3_templates,
)
from app.templates.rics_templates_l1 import (
LEVEL1_GROUP_LABELS,
LEVEL1_TEMPLATES,
LEVEL_1_DOCX_TITLE,
LEVEL_1_PRODUCT_LABEL,
)
from app.templates.rics_templates_l2 import (
LEVEL2_GROUP_LABELS,
LEVEL2_TEMPLATES,
LEVEL_2_DOCX_TITLE,
LEVEL_2_PRODUCT_LABEL,
)
from app.templates.rics_templates import GROUP_LABELS as LEVEL3_GROUP_LABELS
if TYPE_CHECKING:
pass
@dataclass(frozen=True, slots=True)
class SurveyTemplatePack:
"""All metadata needed to render and generate a report for one RICS product tier."""
level: int
product_label: str
docx_title: str
section_order: tuple[str, ...]
group_labels: dict[str, str]
_by_code: dict[str, SectionTemplate]
def get(self, code: str) -> SectionTemplate | None:
return self._by_code.get(code)
def resolve_survey_level(survey_level: int | None) -> int:
"""Map DB ``survey_level`` to a pack id. ``None`` → 3 (Building Survey / legacy)."""
if survey_level is None:
return 3
return max(1, min(3, int(survey_level)))
def _build_pack(
level: int,
product_label: str,
docx_title: str,
templates: list[SectionTemplate],
group_labels: dict[str, str],
) -> SurveyTemplatePack:
by_code = {t.code: t for t in templates}
order = tuple(t.code for t in templates)
return SurveyTemplatePack(
level=level,
product_label=product_label,
docx_title=docx_title,
section_order=order,
group_labels=dict(group_labels),
_by_code=by_code,
)
_PACK1 = _build_pack(1, LEVEL_1_PRODUCT_LABEL, LEVEL_1_DOCX_TITLE, LEVEL1_TEMPLATES, LEVEL1_GROUP_LABELS)
_PACK2 = _build_pack(2, LEVEL_2_PRODUCT_LABEL, LEVEL_2_DOCX_TITLE, LEVEL2_TEMPLATES, LEVEL2_GROUP_LABELS)
_PACK3 = _build_pack(
3,
LEVEL_3_PRODUCT_LABEL,
LEVEL_3_DOCX_TITLE,
get_level3_templates(),
LEVEL3_GROUP_LABELS,
)
_SURVEY_PACKS: Final[dict[int, SurveyTemplatePack]] = {
1: _PACK1,
2: _PACK2,
3: _PACK3,
}
def get_survey_pack(survey_level: int | None) -> SurveyTemplatePack:
"""Return the template pack for ``survey_level`` (``None`` → Level 3)."""
return _SURVEY_PACKS[resolve_survey_level(survey_level)]
def get_template(code: str, survey_level: int | None = None) -> SectionTemplate | None:
"""Resolve a section template by code and survey product tier."""
return get_survey_pack(survey_level).get(code)
def section_order_for_survey(survey_level: int | None) -> list[str]:
"""Ordered section codes for export and UI."""
return list(get_survey_pack(survey_level).section_order)
# Union of every section code ever used across packs (API validation).
ALL_VALID_SECTION_CODES: frozenset[str] = frozenset(
set(_PACK1.section_order) | set(_PACK2.section_order) | set(_PACK3.section_order)
)
# Legacy export: Level 3 order only (many tests / callers expect full BS list length).
SECTION_ORDER_LEVEL3: list[str] = list(_PACK3.section_order)
|