Spaces:
Sleeping
Sleeping
- Added support for RICS survey levels (1, 2, 3) in document uploads and reports, allowing for better tier management and retrieval filtering.
b76f199 | """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 | |
| 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) | |