Local postgres within devcontainer, plus fixes so data loads into db

This commit is contained in:
Daniel Roth 2026-01-29 16:11:16 +00:00
parent 67ea36348e
commit d83d73c129
7 changed files with 68 additions and 24 deletions

View file

@ -9,10 +9,20 @@ services:
command: sleep infinity
volumes:
- ../../:/workspaces/model
networks:
- model-net
networks:
model-net:
driver: bridge
db:
image: postgres:17.4
restart: unless-stopped
ports:
- 5432:5432
environment:
- PGDATABASE=tech_team_local_db
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=makingwarmerhomes
volumes:
- postgres-data-two:/var/lib/postgresql/data
volumes:
postgres-data-two:

22
backend/.env.local Normal file
View file

@ -0,0 +1,22 @@
DB_HOST=db
DB_PORT=5432
DB_NAME=tech_team_local_db
DB_USERNAME=postgres
DB_PASSWORD=makingwarmerhomes
#not used
GOOGLE_SOLAR_API_KEY="test"
SAP_PREDICTIONS_BUCKET="test"
CARBON_PREDICTIONS_BUCKET="test"
HEAT_PREDICTIONS_BUCKET="test"
HEATING_KWH_PREDICTIONS_BUCKET="test"
HOTWATER_KWH_PREDICTIONS_BUCKET="test"
API_KEY="test"
ENVIRONMENT="test"
SECRET_KEY="test"
PLAN_TRIGGER_BUCKET="test"
DATA_BUCKET="test"
EPC_AUTH_TOKEN="test"
ENGINE_SQS_URL="test"
ENERGY_ASSESSMENTS_BUCKET="test"

View file

@ -42,7 +42,7 @@ class Settings(BaseSettings):
AWS_DEFAULT_REGION: Optional[str] = None
class Config:
env_file = "backend/.env"
env_file = "backend/.env.local"
@lru_cache()

View file

@ -18,12 +18,14 @@ ElementTypeDb = SqlEnum(
ElementType,
name="element_type",
native_enum=True,
values_callable=lambda enum: [e.value for e in enum],
)
AspectTypeDb = SqlEnum(
AspectType,
name="aspect_type",
native_enum=True,
values_callable=lambda enum: [a.value for a in enum],
)

View file

@ -21,7 +21,8 @@ def main() -> None:
/ "2026_01_06 - Peabody - Stock Condition Data - Survey Records - D Lower.xlsx"
)
# filepaths = [lbwf_path, peabody_path]
filepaths = [lbwf_path]
# filepaths = [lbwf_path]
filepaths = [peabody_path]
for fp in filepaths:
with fp.open("rb") as f:

View file

@ -3,17 +3,22 @@ from openpyxl import Workbook, load_workbook
from collections import defaultdict
from backend.condition.parsing.parser import Parser
from backend.condition.parsing.records.peabody.peabody_asset_condition import PeabodyAssetCondition
from backend.condition.parsing.records.peabody.peabody_asset_condition import (
PeabodyAssetCondition,
)
from backend.condition.parsing.records.peabody.peabody_property import PeabodyProperty
from utils.logger import setup_logger
logger = setup_logger()
class PeabodyParser(Parser):
def parse(self, file_stream: BinaryIO) -> Any:
wb: Workbook = load_workbook(file_stream)
address_to_uprn_map: Dict[str, int] = PeabodyParser._generate_address_to_uprn_dict(wb)
address_to_uprn_map: Dict[str, int] = (
PeabodyParser._generate_address_to_uprn_dict(wb)
)
assets = self._parse_assets(wb)
return self._group_assets_into_properties(
@ -21,7 +26,6 @@ class PeabodyParser(Parser):
address_to_uprn_map=address_to_uprn_map,
)
@staticmethod
def _parse_assets(wb: Workbook) -> List[PeabodyAssetCondition]:
assets_sheet = wb["Survey Records - D & Lower"]
@ -33,24 +37,28 @@ class PeabodyParser(Parser):
assets: List[PeabodyAssetCondition] = []
for row in asset_rows:
try:
asset = PeabodyParser._map_row_to_asset_record(row, asset_header_indexes)
asset = PeabodyParser._map_row_to_asset_record(
row, asset_header_indexes
)
if not asset.is_block_level:
# Block-level condition surveys are out of scope for now
# until we have a wider think on how to handle block
assets.append(asset) # TODO: handle block-level assets
# until we have a wider think on how to handle block
assets.append(asset) # TODO: handle block-level assets
except Exception as e:
logger.error(f"Error mapping Peabody row to asset record: {e}")
continue
return assets
@staticmethod
def _group_assets_into_properties(
assets: List[PeabodyAssetCondition],
address_to_uprn_map: Dict[str, int],
) -> List[PeabodyProperty]:
assets_by_address: DefaultDict[str, List[PeabodyAssetCondition]] = defaultdict(list)
assets_by_address: DefaultDict[str, List[PeabodyAssetCondition]] = defaultdict(
list
)
for asset in assets:
if asset.full_address is None:
@ -62,6 +70,7 @@ class PeabodyParser(Parser):
properties: List[PeabodyProperty] = []
for address, grouped_assets in assets_by_address.items():
uprn = address_to_uprn_map.get(address)
if uprn is None:
@ -77,7 +86,6 @@ class PeabodyParser(Parser):
return properties
@staticmethod
def _map_row_to_asset_record(
row: Any | Tuple[object | None, ...],
@ -108,14 +116,16 @@ class PeabodyParser(Parser):
rows: Iterator[Tuple[object | None, ...]] = sheet.iter_rows(values_only=True)
headers = next(rows)
header_indexes: Dict[str, int] = PeabodyParser._get_column_indexes_by_name(headers)
header_indexes: Dict[str, int] = PeabodyParser._get_column_indexes_by_name(
headers
)
address_idx = header_indexes["full_address"]
address_to_uprn: Dict[str, int] = {}
# Generate random UPRNs for now
next_uprn = 1 # TODO: get real UPRNs
next_uprn = 1 # TODO: get real UPRNs
for row in rows:
address = row[address_idx]
@ -131,10 +141,9 @@ class PeabodyParser(Parser):
return address_to_uprn
@staticmethod
def _get_column_indexes_by_name(
headers: Tuple[object | None, ...]
headers: Tuple[object | None, ...],
) -> Dict[str, int]:
index: Dict[str, int] = {}
@ -142,4 +151,4 @@ class PeabodyParser(Parser):
if isinstance(header, str):
index[header] = i
return index
return index

View file

@ -17,7 +17,7 @@ logger = setup_logger()
class ConditionPostgres:
def bulk_insert_surveys(
surveys: List[PropertyConditionSurvey], batch_size: Optional[int] = 100
self, surveys: List[PropertyConditionSurvey], batch_size: Optional[int] = 100
) -> None:
logger.info(
f"Preparing to load {len(surveys)} property surveys to Postgres. Mapping to SQLModel objects..."