feat(l1): FlowProposal l1_session_id source linkage (nullable source_session_id + exactly-one check)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,7 @@ if TYPE_CHECKING:
|
||||
from app.models.account import Account
|
||||
from app.models.tree import Tree
|
||||
from app.models.ai_session import AISession
|
||||
from app.models.l1_walk_session import L1WalkSession
|
||||
|
||||
|
||||
class FlowProposal(Base):
|
||||
@@ -56,6 +57,10 @@ class FlowProposal(Base):
|
||||
"linked_ticket_kind IS NULL OR linked_ticket_kind IN ('psa', 'internal')",
|
||||
name="ck_flow_proposals_linked_ticket_kind",
|
||||
),
|
||||
CheckConstraint(
|
||||
"(source_session_id IS NOT NULL) <> (l1_session_id IS NOT NULL)",
|
||||
name="ck_flow_proposals_exactly_one_source",
|
||||
),
|
||||
)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
@@ -73,10 +78,16 @@ class FlowProposal(Base):
|
||||
nullable=True,
|
||||
index=True,
|
||||
)
|
||||
source_session_id: Mapped[uuid.UUID] = mapped_column(
|
||||
source_session_id: Mapped[Optional[uuid.UUID]] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
ForeignKey("ai_sessions.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
nullable=True,
|
||||
index=True,
|
||||
)
|
||||
l1_session_id: Mapped[Optional[uuid.UUID]] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
ForeignKey("l1_walk_sessions.id", ondelete="SET NULL"),
|
||||
nullable=True,
|
||||
index=True,
|
||||
)
|
||||
|
||||
@@ -164,7 +175,17 @@ class FlowProposal(Base):
|
||||
# ── Relationships ──
|
||||
account: Mapped["Account"] = relationship("Account")
|
||||
team: Mapped[Optional["Team"]] = relationship("Team")
|
||||
source_session: Mapped["AISession"] = relationship("AISession")
|
||||
target_flow: Mapped[Optional["Tree"]] = relationship("Tree", foreign_keys=[target_flow_id])
|
||||
published_flow: Mapped[Optional["Tree"]] = relationship("Tree", foreign_keys=[published_flow_id])
|
||||
source_session: Mapped[Optional["AISession"]] = relationship("AISession")
|
||||
# Two FK paths exist between FlowProposal and L1WalkSession
|
||||
# (FlowProposal.l1_session_id here, L1WalkSession.flow_proposal_id there),
|
||||
# so each relationship must name its foreign_keys explicitly.
|
||||
l1_session: Mapped[Optional["L1WalkSession"]] = relationship(
|
||||
"L1WalkSession", foreign_keys="[FlowProposal.l1_session_id]"
|
||||
)
|
||||
target_flow: Mapped[Optional["Tree"]] = relationship(
|
||||
"Tree", foreign_keys=[target_flow_id]
|
||||
)
|
||||
published_flow: Mapped[Optional["Tree"]] = relationship(
|
||||
"Tree", foreign_keys=[published_flow_id]
|
||||
)
|
||||
reviewer: Mapped[Optional["User"]] = relationship("User")
|
||||
|
||||
Reference in New Issue
Block a user