feat: migrate advisor investment goals

This commit is contained in:
Windows
2026-09-11 13:11:58 +08:00
parent acb9175e31
commit 60c4a49b9b
14 changed files with 903 additions and 27 deletions
@@ -0,0 +1,53 @@
"""Repository for investment goals and reviewed goal-book content."""
from datetime import datetime
from typing import cast
from sqlalchemy import select, update
from sqlalchemy.ext.asyncio import AsyncSession
from app.model.investment_goal import AdvisorInvestmentGoal, ClientFacingContent
class InvestmentGoalRepository:
def __init__(self, session: AsyncSession) -> None:
self.session = session
def add_goal(self, goal: AdvisorInvestmentGoal) -> None:
self.session.add(goal)
def add_goal_book(self, content: ClientFacingContent) -> None:
self.session.add(content)
async def goal(self, goal_no: str, *, lock: bool = False) -> AdvisorInvestmentGoal | None:
query = select(AdvisorInvestmentGoal).where(AdvisorInvestmentGoal.goal_no == goal_no)
if lock:
query = query.with_for_update()
return cast(AdvisorInvestmentGoal | None, await self.session.scalar(query))
async def latest_for_customer(self, customer_id: int) -> AdvisorInvestmentGoal | None:
return cast(AdvisorInvestmentGoal | None, await self.session.scalar(
select(AdvisorInvestmentGoal)
.where(
AdvisorInvestmentGoal.customer_id == customer_id,
AdvisorInvestmentGoal.status != "superseded",
)
.order_by(AdvisorInvestmentGoal.created_at.desc(), AdvisorInvestmentGoal.id.desc())
.limit(1)
))
async def goal_book(self, content_id: int) -> ClientFacingContent | None:
return await self.session.get(ClientFacingContent, content_id)
async def supersede_confirmed(
self, customer_id: int, except_goal_no: str, now: datetime
) -> None:
await self.session.execute(
update(AdvisorInvestmentGoal)
.where(
AdvisorInvestmentGoal.customer_id == customer_id,
AdvisorInvestmentGoal.status == "confirmed",
AdvisorInvestmentGoal.goal_no != except_goal_no,
)
.values(status="superseded", updated_at=now)
)
+1
View File
@@ -20,6 +20,7 @@ TABLES = frozenset(
"svc_handover_ticket",
"fin_knowledge_meta",
"profile_snapshots",
"client_facing_content",
}
)