# Module: DataAccess/Models ## Purpose Database entity classes that map directly to PostgreSQL tables via Dapper. Property names use PascalCase; column mapping is done with SQL aliases in repository queries. ## Public Interface ### TileEntity Maps to `tiles` table. - `Id` (Guid) — AZ-503: deterministic UUIDv5 of `{tile_zoom}/{tile_x}/{tile_y}/{source}/{flight_id or '00000000-0000-0000-0000-000000000000'}` under namespace `Uuidv5.TileNamespace`. Stable across re-ingests; preserved on UPSERT conflict. - `TileZoom` (int), `TileX` (int), `TileY` (int) - `Latitude`, `Longitude` (double), `TileSizeMeters` (double), `TileSizePixels` (int) - `ImageType` (string), `MapsVersion` (string?), `Version` (int) — `MapsVersion`/`Version` are vestigial post-AZ-484 (kept nullable for backward compatibility; no longer part of the unique key) - `Source` (string) — AZ-484 producer wire value, defaults to `TileSourceConverter.GoogleMapsWireValue` (`"google_maps"`). Stored as plain string (not the `TileSource` enum) due to Dapper issue #259 — see `_docs/LESSONS.md` L-001. Convert via `SatelliteProvider.Common.Enums.TileSourceConverter.{ToWireValue,FromWireValue}`. - `CapturedAt` (DateTime, UTC) — AZ-484 imagery acquisition timestamp; drives the most-recent-across-sources selection. - `FilePath` (string), `CreatedAt`, `UpdatedAt` (DateTime) - `FlightId` (Guid?) — AZ-503: optional flight identifier. `null` for Google Maps tiles; populated from `UavTileMetadata.FlightId` on UAV uploads. Part of the AZ-503 UPSERT conflict key via `COALESCE(flight_id, '00000000-0000-0000-0000-000000000000'::uuid)`, so two flights uploading the same `(z, x, y)` cell produce two separate rows. - `LocationHash` (Guid) — AZ-503 `NOT NULL`: deterministic UUIDv5 of `{tile_zoom}/{tile_x}/{tile_y}` under `Uuidv5.TileNamespace`. Identical across flights and sources for the same cell. Backfilled in migration 014 via a `pg_temp.uuidv5` PL/pgSQL function; subsequent inserts compute it in the application layer (`TileService` + `UavTileUploadHandler`). Reserved for AZ-505's Leaflet covering index (`POST /tiles/inventory`) — not yet on a unique constraint. - `ContentSha256` (byte[]?) — AZ-503: SHA-256 digest of the JPEG body. Application code enforces `NOT NULL` for new writes via `TileService.BuildTileEntity` (Google Maps) and `UavTileUploadHandler.PersistAsync` (UAV). The DB column is `bytea NULL` because legacy pre-migration rows could not be backfilled reliably from disk (file paths are volatile). See `batch_02_cycle5_report.md` "Low maintainability finding" for the rationale. - `LegacyId` (Guid?) — AZ-503: pre-migration `id` value, populated by migration 014 from every existing row's `id`. Preserves random-`Guid` provenance for one cycle (per AZ-503 Risk 1 mitigation) so external references to the old id can still be diagnosed before deletion. ### RegionEntity Maps to `regions` table. - `Id` (Guid), `Latitude`, `Longitude` (double), `SizeMeters` (double) - `ZoomLevel` (int), `Status` (string: "queued"/"processing"/"completed"/"failed") - `CsvFilePath`, `SummaryFilePath` (string?) - `TilesDownloaded`, `TilesReused` (int), `StitchTiles` (bool) - `CreatedAt`, `UpdatedAt` (DateTime) ### RouteEntity Maps to `routes` table. - `Id` (Guid), `Name` (string), `Description` (string?) - `RegionSizeMeters` (double), `ZoomLevel` (int) - `TotalDistanceMeters` (double), `TotalPoints` (int) - `RequestMaps`, `MapsReady`, `CreateTilesZip` (bool) - `CsvFilePath`, `SummaryFilePath`, `StitchedImagePath`, `TilesZipPath` (string?) - `CreatedAt`, `UpdatedAt` (DateTime) ### RoutePointEntity Maps to `route_points` table. - `Id` (Guid), `RouteId` (Guid), `SequenceNumber` (int) - `Latitude`, `Longitude` (double), `PointType` (string) - `SegmentIndex` (int), `DistanceFromPrevious` (double?) - `CreatedAt` (DateTime) ## Internal Logic Plain POCOs with no logic. ## Dependencies None. ## Consumers - All repository implementations (TileRepository, RegionRepository, RouteRepository) - `TileService` — creates `TileEntity` instances for persistence - `RegionService` — creates/updates `RegionEntity` - `RouteService` — creates `RouteEntity` and `RoutePointEntity` - `RouteProcessingService` — reads entities from repositories - `GoogleMapsDownloaderV2.GetTilesWithMetadataAsync` — accepts `IEnumerable` to check existing tiles ## Data Models These ARE the data model. ## Configuration None. ## External Integrations None. ## Security None. ## Tests No dedicated tests.