mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-08 11:17:27 +00:00
feat(modelling): drop the plan_recommendations m2m
Stop writing the m2m (remove create_plan_recommendations + its call, the bulk link insert and the now-dead plan_ids_by_index, and the plan_recommendations delete in delete_property_batch) and remove the PlanRecommendationRow model + its shim alias and the test_export fixture inserts. Measures now link to their Plan solely via recommendation.plan_id (writers set it, readers join on it). The live drop of the plan_recommendations table is the FE-owned Drizzle migration documented in docs/migrations/recommendation-plan-id.md, sequenced after the read-cut + backfill. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
af5dbe325d
commit
b97d06882f
5 changed files with 10 additions and 99 deletions
|
|
@ -17,7 +17,6 @@ from backend.app.db.models.recommendations import (
|
|||
PlanModel,
|
||||
Recommendation,
|
||||
RecommendationMaterials,
|
||||
PlanRecommendations,
|
||||
ScenarioModel,
|
||||
)
|
||||
from backend.app.db.models.portfolio import PropertyModel
|
||||
|
|
@ -236,23 +235,6 @@ def create_recommendation_material(
|
|||
return new_recommendation_material.id
|
||||
|
||||
|
||||
def create_plan_recommendations(session: Session, plan_id, recommendation_ids):
|
||||
"""
|
||||
This function will create records for the plan_recommendation in the database.
|
||||
:param session: The database session
|
||||
:param plan_id: ID of the plan
|
||||
:param recommendation_ids: list of recommendation IDs
|
||||
"""
|
||||
|
||||
# Prepare a list of dictionaries for bulk insert
|
||||
data = [
|
||||
{"plan_id": plan_id, "recommendation_id": rid} for rid in recommendation_ids
|
||||
]
|
||||
|
||||
# Bulk insert using SQLAlchemy's core API
|
||||
session.execute(insert(PlanRecommendations).values(data))
|
||||
|
||||
|
||||
def upload_recommendations(
|
||||
session: Session, recommendations_to_upload, property_id, new_plan_id
|
||||
):
|
||||
|
|
@ -320,10 +302,6 @@ def upload_recommendations(
|
|||
# flush the changes to get the newly created IDs
|
||||
session.flush()
|
||||
|
||||
create_plan_recommendations(
|
||||
session, plan_id=new_plan_id, recommendation_ids=uploaded_recommendation_ids
|
||||
)
|
||||
|
||||
# Commit the transaction
|
||||
session.commit()
|
||||
|
||||
|
|
@ -348,7 +326,6 @@ def bulk_upload_recommendations_and_materials(
|
|||
# ---------------------------------------------------------
|
||||
recommendation_rows = []
|
||||
parts_by_index = []
|
||||
plan_ids_by_index = []
|
||||
|
||||
for rec in recommendation_payload:
|
||||
recommendation_rows.append(
|
||||
|
|
@ -375,7 +352,6 @@ def bulk_upload_recommendations_and_materials(
|
|||
)
|
||||
|
||||
parts_by_index.append(rec["parts"])
|
||||
plan_ids_by_index.append(rec["plan_id"])
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# 2. Insert recommendations and get IDs
|
||||
|
|
@ -407,18 +383,8 @@ def bulk_upload_recommendations_and_materials(
|
|||
if materials_rows:
|
||||
session.execute(insert(RecommendationMaterials).values(materials_rows))
|
||||
|
||||
# ---------------------------------------------------------
|
||||
# 4. Insert plan ↔ recommendation links
|
||||
# ---------------------------------------------------------
|
||||
plan_recommendation_rows = [
|
||||
{
|
||||
"plan_id": plan_id,
|
||||
"recommendation_id": recommendation_id,
|
||||
}
|
||||
for plan_id, recommendation_id in zip(plan_ids_by_index, recommendation_ids)
|
||||
]
|
||||
|
||||
session.execute(insert(PlanRecommendations).values(plan_recommendation_rows))
|
||||
# Recommendations carry their plan via recommendation.plan_id (set above) —
|
||||
# the plan_recommendations m2m is retired (ADR-0017 amendment).
|
||||
|
||||
|
||||
def chunked(iterable, size=100):
|
||||
|
|
@ -457,21 +423,6 @@ def delete_property_batch(session: Session, property_ids: list[int]):
|
|||
params,
|
||||
)
|
||||
|
||||
# --------------------------------------------------
|
||||
# plan_recommendations (via plan)
|
||||
# --------------------------------------------------
|
||||
session.execute(
|
||||
text(
|
||||
"""
|
||||
DELETE FROM plan_recommendations pr
|
||||
USING plan p
|
||||
WHERE pr.plan_id = p.id
|
||||
AND p.property_id = ANY(:property_ids)
|
||||
"""
|
||||
),
|
||||
params,
|
||||
)
|
||||
|
||||
# --------------------------------------------------
|
||||
# funding_package_measures
|
||||
# --------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -30,17 +30,17 @@ from backend.app.db.models.portfolio import Portfolio, PortfolioGoal, PropertyMo
|
|||
from infrastructure.postgres.modelling import (
|
||||
PlanRow,
|
||||
PlanType,
|
||||
PlanRecommendationRow,
|
||||
RecommendationMaterialRow,
|
||||
RecommendationRow,
|
||||
)
|
||||
|
||||
# Legacy names → the single SQLModel definitions now in
|
||||
# `infrastructure/postgres/modelling/`.
|
||||
# `infrastructure/postgres/modelling/`. The `plan_recommendations` m2m is
|
||||
# retired (ADR-0017 amendment) — measures link to their Plan via
|
||||
# `recommendation.plan_id`.
|
||||
Recommendation = RecommendationRow
|
||||
RecommendationMaterials = RecommendationMaterialRow
|
||||
PlanModel = PlanRow
|
||||
PlanRecommendations = PlanRecommendationRow
|
||||
PlanTypeEnum = PlanType
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ from backend.app.db.models.portfolio import (
|
|||
from backend.app.db.models.recommendations import (
|
||||
PlanModel,
|
||||
Recommendation,
|
||||
PlanRecommendations,
|
||||
RecommendationMaterials,
|
||||
)
|
||||
from backend.app.db.models.materials import Material
|
||||
|
|
@ -189,18 +188,9 @@ def test_default_export_integration(db_session):
|
|||
db_session.bulk_save_objects(recs)
|
||||
db_session.flush()
|
||||
|
||||
# ----------------------------------------
|
||||
# 6) Insert PlanRecommendations
|
||||
# ----------------------------------------
|
||||
links = [
|
||||
PlanRecommendations(
|
||||
plan_id=row.plan_id,
|
||||
recommendation_id=row.recommendation_id,
|
||||
)
|
||||
for row in plan_recs_df.itertuples(index=False)
|
||||
]
|
||||
|
||||
db_session.bulk_save_objects(links)
|
||||
# Recommendations are linked to their plan by recommendation.plan_id (set
|
||||
# above from plan_recs_df) — the plan_recommendations m2m is retired
|
||||
# (ADR-0017 amendment).
|
||||
db_session.commit()
|
||||
logger.info("Inserted all data in %.2f seconds", time.perf_counter() - db_load_t0)
|
||||
|
||||
|
|
@ -628,17 +618,8 @@ def test_solar_with_battery_example(db_session):
|
|||
db_session.add(rec)
|
||||
db_session.flush()
|
||||
|
||||
# -------------------------------------------------
|
||||
# Link Plan -> Recommendation
|
||||
# -------------------------------------------------
|
||||
for row in plan_recs_df.itertuples(index=False):
|
||||
db_session.add(
|
||||
PlanRecommendations(
|
||||
plan_id=row.plan_id,
|
||||
recommendation_id=row.recommendation_id,
|
||||
)
|
||||
)
|
||||
db_session.flush()
|
||||
# Plan ↔ Recommendation link is recommendation.plan_id (set above) — the
|
||||
# plan_recommendations m2m is retired (ADR-0017 amendment).
|
||||
|
||||
# -------------------------------------------------
|
||||
# Insert Material (includes_battery=True)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ One canonical SQLModel per physical table — `plan`, `recommendation`,
|
|||
|
||||
from infrastructure.postgres.modelling.plan_table import PlanRow, PlanType
|
||||
from infrastructure.postgres.modelling.recommendation_table import (
|
||||
PlanRecommendationRow,
|
||||
RecommendationMaterialRow,
|
||||
RecommendationRow,
|
||||
)
|
||||
|
|
@ -20,5 +19,4 @@ __all__ = [
|
|||
"PlanType",
|
||||
"RecommendationRow",
|
||||
"RecommendationMaterialRow",
|
||||
"PlanRecommendationRow",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -118,22 +118,3 @@ class RecommendationMaterialRow(SQLModel, table=True):
|
|||
),
|
||||
)
|
||||
estimated_cost: Optional[float] = Field(default=None)
|
||||
|
||||
|
||||
class PlanRecommendationRow(SQLModel, table=True):
|
||||
"""The legacy ``plan_recommendations`` m2m — **being retired** (ADR-0017
|
||||
amendment). Kept as an intra-cluster SQLModel row only for the transition
|
||||
window while readers/writers move onto ``recommendation.plan_id``; dropped
|
||||
once no caller remains. Both FKs are intra-cluster."""
|
||||
|
||||
__tablename__: ClassVar[str] = "plan_recommendations" # pyright: ignore[reportIncompatibleVariableOverride]
|
||||
|
||||
id: Optional[int] = Field(default=None, primary_key=True)
|
||||
plan_id: int = Field(
|
||||
sa_column=Column(BigInteger, ForeignKey("plan.id"), nullable=False)
|
||||
)
|
||||
recommendation_id: int = Field(
|
||||
sa_column=Column(
|
||||
BigInteger, ForeignKey("recommendation.id"), nullable=False
|
||||
)
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue