delete temp prd file

This commit is contained in:
Daniel Roth 2026-05-11 15:42:53 +00:00
parent b1a089cb79
commit a863351eee

View file

@ -1,114 +0,0 @@
# PRD: Extract Domain Layer to Root-Level `domain/` Package
## Problem Statement
Domain objects (models, enums, mappers) shared across microservices are nested under `datatypes/epc/domain/` and `datatypes/magicplan/domain/`. This creates two problems:
1. **Misleading location**: "Datatypes" implies low-level type definitions, but these folders contain rich domain models and business logic (mappers, historic EPC matching, property data aggregation). New developers cannot discover the domain layer by inspection.
2. **False coupling**: Domain objects belonging to the whole system are buried inside a folder that also contains source-data representations (versioned RdSAP schemas, Elmhurst/Pashub survey shapes, MagicPlan API responses). The domain has no clear home — it is mixed with external data adapters.
## Solution
Extract all domain objects (domain models, domain vocabulary enums, mappers) into a dedicated root-level `domain/` package. The `datatypes/` package is repurposed to hold only external/source data shapes: RdSAP schemas, survey provider types, and third-party API response types.
The result is a clear, discoverable split:
- `domain/` — canonical domain models, vocabulary enums, and mappers owned by this system
- `datatypes/` — shapes that mirror external systems (schemas, surveys, API responses)
## User Stories
1. As a backend engineer, I want domain models to live in a top-level `domain/` package, so that I can find the canonical representation of an EPC or MagicPlan floor plan without navigating into `datatypes/`.
2. As a backend engineer, I want to import EPC domain models with `from domain.epc import ...`, so that the import path reflects the conceptual ownership of the type.
3. As a backend engineer, I want EPC vocabulary enums (wall descriptions, roof descriptions, fuel types, etc.) to live in `domain/epc/`, so that all domain vocabulary is co-located with domain models.
4. As a backend engineer adding a new microservice, I want a clear pattern for importing shared domain objects, so that I do not accidentally reach into `datatypes/` for domain types.
5. As a backend engineer, I want the `datatypes/` package to contain only source-data representations, so that I understand it as the anti-corruption layer and not as the domain.
6. As a backend engineer, I want mappers (which transform external shapes into domain models) to live alongside domain models in `domain/`, so that the translation between external and domain is easy to find.
7. As a backend engineer running tests, I want the pytest test paths to reflect the new `domain/` location, so that `pytest` discovers and runs all domain tests correctly.
8. As a backend engineer, I want no backwards-compatibility shims or re-export stubs left behind in `datatypes/`, so that there is one canonical import path for each domain type.
9. As a code reviewer, I want imports from `domain.*` to clearly signal "this is a domain concept", so that the distinction from `datatypes.*` (external data) is immediately readable.
10. As a backend engineer, I want internal references within moved files (e.g. mapper.py importing models.py) to be updated to their new paths, so that no moved module has a stale import.
## Implementation Decisions
### Package structure
A root-level `domain/` package is created alongside `datatypes/`. It contains two sub-packages mirroring the existing subdomain split:
- `domain/epc/` — all EPC domain objects
- `domain/magicplan/` — all MagicPlan domain objects
### What moves into `domain/epc/`
All of the following move from their current `datatypes/epc/` locations:
- EPC vocabulary enums: `construction_age_band`, `efficiency`, `floor`, `fuel`, `heating_controls`, `hotwater`, `main_heating`, `property_type_built_form`, `roof`, `walls`, `windows`
- EPC domain models and logic: `epc`, `epc_property_data`, `field_mappings`, `historic_epc`, `historic_epc_matching`, `mapper`
- Domain tests (currently under `datatypes/epc/domain/tests/`)
`domain/epc/__init__.py` re-exports all vocabulary enums (matching the current `datatypes/epc/__init__.py` interface) so call-sites using the package-level import continue to work after the path change.
### What moves into `domain/magicplan/`
- Domain models: `models` (Window, Door, Room, Floor, Plan dataclasses)
- Domain mapper: `mapper` (transforms MagicPlan API response into domain models)
- Domain tests (currently under `datatypes/magicplan/domain/tests/`)
### What stays in `datatypes/`
- `datatypes/epc/schema/` — versioned RdSAP XML schemas (17.0 through 21.0.1)
- `datatypes/epc/surveys/` — Elmhurst and Pashub site notes shapes
- `datatypes/epc/loaders/` — historic EPC loading logic
- `datatypes/magicplan/api/` — MagicPlan API response types
- `datatypes/datatypes.py` and `datatypes/enums.py` — pre-existing shared primitives (out of scope for this change)
### Mapper placement
Mappers live in `domain/` alongside the models they produce. This reflects the view that a mapper is the domain's intake port — the boundary at which external data becomes domain data — and belongs with the domain, not with the external shapes.
### Import path changes
| Old import | New import |
|---|---|
| `from datatypes.epc.domain.X import Y` | `from domain.epc.X import Y` |
| `from datatypes.epc.walls import Y` | `from domain.epc.walls import Y` |
| `from datatypes.epc import EpcWallDescriptions` | `from domain.epc import EpcWallDescriptions` |
| `from datatypes.magicplan.domain.models import Y` | `from domain.magicplan.models import Y` |
| `from datatypes.magicplan.domain.mapper import Y` | `from domain.magicplan.mapper import Y` |
Imports from `datatypes.epc.schema.*`, `datatypes.epc.surveys.*`, and `datatypes.magicplan.api.*` are unchanged.
### pytest.ini update
`testpaths` entries for `datatypes/epc/domain/tests` and `datatypes/magicplan/domain/tests` are replaced with `domain/epc/tests` and `domain/magicplan/tests`.
### No backwards-compatibility shims
`datatypes/epc/` enum files and `datatypes/epc/domain/` files are deleted after the move. No re-export stubs are left behind. All consumers are updated in the same change.
## Testing Decisions
A good test for this change verifies that the domain objects behave identically under their new import paths — not that the files were moved.
**Modules to test:**
- `domain/epc/` — existing tests from `datatypes/epc/domain/tests/` cover mapper (`test_from_rdsap_schema`, `test_from_site_notes`) and historic EPC matching (`test_historic_epc_matching`). These tests are moved verbatim; passing them confirms the domain logic is intact.
- `domain/magicplan/` — existing tests from `datatypes/magicplan/domain/tests/test_mapper.py` are moved verbatim.
**Prior art:** `datatypes/epc/domain/tests/` and `datatypes/magicplan/domain/tests/` are the direct prior art — same test patterns, same fixtures, relocated.
**Verification grep:** After the change, `grep -r "from datatypes.epc.domain" . --include="*.py"` and `grep -r "from datatypes.magicplan.domain" . --include="*.py"` should return zero results (excluding `__pycache__`).
## Out of Scope
- Moving `datatypes/datatypes.py` (`OpenUprnCoordinateData`) or `datatypes/enums.py` (`QuantityUnits`) — these are pre-existing and will be addressed in a future refactor.
- Renaming `datatypes/` to `external/` or any other name — out of scope for this change.
- Moving `datatypes/epc/schema/`, `datatypes/epc/surveys/`, `datatypes/epc/loaders/`, or `datatypes/magicplan/api/` — these are source-data shapes and stay in `datatypes/`.
- Adding new domain objects or changing domain logic — this is a structural move only.
- Introducing Python packaging (`setup.py`, `pyproject.toml`) changes beyond `pytest.ini`.
## Further Notes
- `pytest.ini` sets `pythonpath = .`, so `domain/` at the repo root will be importable immediately without additional configuration.
- `datatypes/epc/__init__.py` currently aggregates enum exports via `__all__`. The equivalent `domain/epc/__init__.py` should preserve this interface so call-sites using `from datatypes.epc import EpcWallDescriptions`-style imports need only a path change, not a restructuring.
- ~40 files across `backend/`, `etl/`, and `scripts/` import from `datatypes.epc.*` domain paths. ~10 files import from `datatypes.magicplan.domain.*`. A single `sed` pass or IDE rename refactor covers the bulk; the verification grep confirms completeness.