mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
Merge pull request #1080 from Hestia-Homes/feature/magicplan_uploaded_file_id
Include uploaded file ID on MagicPlan plan
This commit is contained in:
commit
cc6b64ee2b
5 changed files with 71 additions and 12 deletions
|
|
@ -14,15 +14,15 @@ from backend.app.db.models.magic_plan import (
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def save_plan(session: Session, plan: Plan) -> None:
|
def save_plan(session: Session, plan: Plan, uploaded_file_id: int) -> None:
|
||||||
plan_id: int = _upsert_plan(session, plan)
|
plan_id: int = _upsert_plan(session, plan, uploaded_file_id)
|
||||||
_delete_children(session, plan_id)
|
_delete_children(session, plan_id)
|
||||||
floor_ids: list[int] = _insert_floors(session, plan.floors, plan_id)
|
floor_ids: list[int] = _insert_floors(session, plan.floors, plan_id)
|
||||||
room_ids: list[int] = _insert_rooms(session, plan.floors, floor_ids)
|
room_ids: list[int] = _insert_rooms(session, plan.floors, floor_ids)
|
||||||
_insert_windows_and_doors(session, plan.floors, room_ids)
|
_insert_windows_and_doors(session, plan.floors, room_ids)
|
||||||
|
|
||||||
|
|
||||||
def _upsert_plan(session: Session, plan: Plan) -> int:
|
def _upsert_plan(session: Session, plan: Plan, uploaded_file_id: int) -> int:
|
||||||
stmt = (
|
stmt = (
|
||||||
pg_insert(MagicPlanPlanModel)
|
pg_insert(MagicPlanPlanModel)
|
||||||
.values(
|
.values(
|
||||||
|
|
@ -30,6 +30,7 @@ def _upsert_plan(session: Session, plan: Plan) -> int:
|
||||||
name=plan.name,
|
name=plan.name,
|
||||||
address=plan.address,
|
address=plan.address,
|
||||||
postcode=plan.postcode,
|
postcode=plan.postcode,
|
||||||
|
uploaded_file_id=uploaded_file_id,
|
||||||
)
|
)
|
||||||
.on_conflict_do_update(
|
.on_conflict_do_update(
|
||||||
index_elements=["magic_plan_uid"],
|
index_elements=["magic_plan_uid"],
|
||||||
|
|
@ -37,6 +38,7 @@ def _upsert_plan(session: Session, plan: Plan) -> int:
|
||||||
"name": plan.name,
|
"name": plan.name,
|
||||||
"address": plan.address,
|
"address": plan.address,
|
||||||
"postcode": plan.postcode,
|
"postcode": plan.postcode,
|
||||||
|
"uploaded_file_id": uploaded_file_id,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.returning(col(MagicPlanPlanModel.id))
|
.returning(col(MagicPlanPlanModel.id))
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ def _count(session: Session, model: type[SQLModel]) -> int:
|
||||||
|
|
||||||
def test_plan_row_present_after_save(db_session: Session, domain_plan: Plan) -> None:
|
def test_plan_row_present_after_save(db_session: Session, domain_plan: Plan) -> None:
|
||||||
# Act
|
# Act
|
||||||
save_plan(db_session, domain_plan)
|
save_plan(db_session, domain_plan, 1)
|
||||||
# Assert
|
# Assert
|
||||||
assert _count(db_session, MagicPlanPlanModel) == 1
|
assert _count(db_session, MagicPlanPlanModel) == 1
|
||||||
|
|
||||||
|
|
@ -45,7 +45,7 @@ def test_floor_count_matches_domain(db_session: Session, domain_plan: Plan) -> N
|
||||||
# Arrange
|
# Arrange
|
||||||
expected = len(domain_plan.floors)
|
expected = len(domain_plan.floors)
|
||||||
# Act
|
# Act
|
||||||
save_plan(db_session, domain_plan)
|
save_plan(db_session, domain_plan, 1)
|
||||||
# Assert
|
# Assert
|
||||||
assert _count(db_session, MagicPlanFloorModel) == expected
|
assert _count(db_session, MagicPlanFloorModel) == expected
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ def test_room_count_matches_domain(db_session: Session, domain_plan: Plan) -> No
|
||||||
# Arrange
|
# Arrange
|
||||||
expected = sum(len(f.rooms) for f in domain_plan.floors)
|
expected = sum(len(f.rooms) for f in domain_plan.floors)
|
||||||
# Act
|
# Act
|
||||||
save_plan(db_session, domain_plan)
|
save_plan(db_session, domain_plan, 1)
|
||||||
# Assert
|
# Assert
|
||||||
assert _count(db_session, MagicPlanRoomModel) == expected
|
assert _count(db_session, MagicPlanRoomModel) == expected
|
||||||
|
|
||||||
|
|
@ -63,7 +63,7 @@ def test_window_count_matches_domain(db_session: Session, domain_plan: Plan) ->
|
||||||
# Arrange
|
# Arrange
|
||||||
expected = sum(len(r.windows) for f in domain_plan.floors for r in f.rooms)
|
expected = sum(len(r.windows) for f in domain_plan.floors for r in f.rooms)
|
||||||
# Act
|
# Act
|
||||||
save_plan(db_session, domain_plan)
|
save_plan(db_session, domain_plan, 1)
|
||||||
# Assert
|
# Assert
|
||||||
assert _count(db_session, MagicPlanWindowModel) == expected
|
assert _count(db_session, MagicPlanWindowModel) == expected
|
||||||
|
|
||||||
|
|
@ -72,15 +72,15 @@ def test_door_count_matches_domain(db_session: Session, domain_plan: Plan) -> No
|
||||||
# Arrange
|
# Arrange
|
||||||
expected = sum(len(r.doors) for f in domain_plan.floors for r in f.rooms)
|
expected = sum(len(r.doors) for f in domain_plan.floors for r in f.rooms)
|
||||||
# Act
|
# Act
|
||||||
save_plan(db_session, domain_plan)
|
save_plan(db_session, domain_plan, 1)
|
||||||
# Assert
|
# Assert
|
||||||
assert _count(db_session, MagicPlanDoorModel) == expected
|
assert _count(db_session, MagicPlanDoorModel) == expected
|
||||||
|
|
||||||
|
|
||||||
def test_save_plan_idempotent(db_session: Session, domain_plan: Plan) -> None:
|
def test_save_plan_idempotent(db_session: Session, domain_plan: Plan) -> None:
|
||||||
# Act — call twice within the same session
|
# Act — call twice within the same session
|
||||||
save_plan(db_session, domain_plan)
|
save_plan(db_session, domain_plan, 1)
|
||||||
save_plan(db_session, domain_plan)
|
save_plan(db_session, domain_plan, 1)
|
||||||
# Assert — same row counts as a single call
|
# Assert — same row counts as a single call
|
||||||
assert _count(db_session, MagicPlanPlanModel) == 1
|
assert _count(db_session, MagicPlanPlanModel) == 1
|
||||||
assert _count(db_session, MagicPlanFloorModel) == len(domain_plan.floors)
|
assert _count(db_session, MagicPlanFloorModel) == len(domain_plan.floors)
|
||||||
|
|
@ -93,3 +93,23 @@ def test_save_plan_idempotent(db_session: Session, domain_plan: Plan) -> None:
|
||||||
assert _count(db_session, MagicPlanDoorModel) == sum(
|
assert _count(db_session, MagicPlanDoorModel) == sum(
|
||||||
len(r.doors) for f in domain_plan.floors for r in f.rooms
|
len(r.doors) for f in domain_plan.floors for r in f.rooms
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_uploaded_file_id_stored_after_save(db_session: Session, domain_plan: Plan) -> None:
|
||||||
|
# Act
|
||||||
|
save_plan(db_session, domain_plan, 1)
|
||||||
|
# Assert
|
||||||
|
row = db_session.execute(select(MagicPlanPlanModel)).scalar_one()
|
||||||
|
assert row.uploaded_file_id == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_save_plan_updates_uploaded_file_id_on_reingest(
|
||||||
|
db_session: Session, domain_plan: Plan
|
||||||
|
) -> None:
|
||||||
|
# Arrange
|
||||||
|
save_plan(db_session, domain_plan, 1)
|
||||||
|
# Act
|
||||||
|
save_plan(db_session, domain_plan, 2)
|
||||||
|
# Assert
|
||||||
|
row = db_session.execute(select(MagicPlanPlanModel)).scalar_one()
|
||||||
|
assert row.uploaded_file_id == 2
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ class MagicPlanPlanModel(SQLModel, table=True):
|
||||||
name: Optional[str] = None
|
name: Optional[str] = None
|
||||||
address: Optional[str] = None
|
address: Optional[str] = None
|
||||||
postcode: Optional[str] = None
|
postcode: Optional[str] = None
|
||||||
|
uploaded_file_id: Optional[int] = Field(default=None)
|
||||||
|
|
||||||
|
|
||||||
class MagicPlanFloorModel(SQLModel, table=True):
|
class MagicPlanFloorModel(SQLModel, table=True):
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import gzip
|
import gzip
|
||||||
import json
|
import json
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from typing import Optional
|
from typing import Optional, cast
|
||||||
|
|
||||||
from datatypes.magicplan.api.response import MagicPlanPlan, PlanSummary
|
from datatypes.magicplan.api.response import MagicPlanPlan, PlanSummary
|
||||||
from datatypes.magicplan.domain.mapper import map_plan
|
from datatypes.magicplan.domain.mapper import map_plan
|
||||||
|
|
@ -55,8 +55,9 @@ class MagicPlanService:
|
||||||
)
|
)
|
||||||
|
|
||||||
with db_session() as session:
|
with db_session() as session:
|
||||||
save_plan(session, plan)
|
|
||||||
session.add(uploaded_file)
|
session.add(uploaded_file)
|
||||||
|
session.flush()
|
||||||
|
save_plan(session, plan, cast(int, uploaded_file.id))
|
||||||
|
|
||||||
return plan
|
return plan
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -271,3 +271,38 @@ def test_run_creates_uploaded_file_record(
|
||||||
assert uploaded_file.s3_upload_timestamp is not None
|
assert uploaded_file.s3_upload_timestamp is not None
|
||||||
assert uploaded_file.uprn == 100023336956
|
assert uploaded_file.uprn == 100023336956
|
||||||
assert uploaded_file.hubspot_deal_id == "deal-789"
|
assert uploaded_file.hubspot_deal_id == "deal-789"
|
||||||
|
|
||||||
|
|
||||||
|
def test_run_passes_flushed_uploaded_file_id_to_save_plan(
|
||||||
|
mock_client: MagicMock,
|
||||||
|
plan_summary: PlanSummary,
|
||||||
|
) -> None:
|
||||||
|
# Arrange
|
||||||
|
mock_client.get_plans.return_value = [plan_summary]
|
||||||
|
service = _make_service(mock_client)
|
||||||
|
mock_session = MagicMock()
|
||||||
|
added_objects: list = []
|
||||||
|
|
||||||
|
mock_session.add.side_effect = added_objects.append
|
||||||
|
|
||||||
|
def simulate_flush() -> None:
|
||||||
|
for obj in added_objects:
|
||||||
|
if isinstance(obj, UploadedFile):
|
||||||
|
obj.id = 42
|
||||||
|
|
||||||
|
mock_session.flush.side_effect = simulate_flush
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"backend.magic_plan.magic_plan_service.find_matching_plan",
|
||||||
|
return_value=plan_summary,
|
||||||
|
), patch("backend.magic_plan.magic_plan_service.save_plan") as mock_save, patch(
|
||||||
|
"backend.magic_plan.magic_plan_service.db_session"
|
||||||
|
) as mock_db, patch(
|
||||||
|
"backend.magic_plan.magic_plan_service.save_data_to_s3"
|
||||||
|
):
|
||||||
|
mock_db.return_value.__enter__.return_value = mock_session
|
||||||
|
# Act
|
||||||
|
service.run(_make_request())
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
assert mock_save.call_args[0][2] == 42
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue