Coverage for src / idx_api / models / suggestion.py: 100%
21 statements
« prev ^ index » next coverage.py v7.13.1, created at 2025-12-28 11:09 -0700
« prev ^ index » next coverage.py v7.13.1, created at 2025-12-28 11:09 -0700
1"""Suggestion model for suggest-edit workflow."""
3from datetime import datetime
4from typing import Any, Optional
6from sqlalchemy import DateTime, Integer, JSON, String, Text
7from sqlalchemy.orm import Mapped, mapped_column
9from idx_api.models.base import Base
12class Suggestion(Base):
13 """Suggestions for changes to existing records.
15 Used for the suggest-edit pattern where non-admin users can propose
16 changes that require approval from admins or brokers.
17 """
19 __tablename__ = "suggestions"
21 id: Mapped[int] = mapped_column(primary_key=True)
23 # Target record information
24 target_table: Mapped[str] = mapped_column(String(50), nullable=False, index=True) # "broker", "agent", etc.
25 target_id: Mapped[int] = mapped_column(Integer, nullable=False, index=True)
27 # Suggestion details
28 suggestion_type: Mapped[str] = mapped_column(String(20), nullable=False) # "create", "update", "delete"
29 title: Mapped[str] = mapped_column(String(200), nullable=False) # Short description
30 description: Mapped[Optional[str]] = mapped_column(Text) # Detailed explanation
31 proposed_changes: Mapped[dict[str, Any]] = mapped_column(JSON, nullable=False) # { field: { old: "...", new: "..." } }
33 # Review workflow
34 reviewer_type: Mapped[str] = mapped_column(String(20), nullable=False, index=True) # "admin" or "broker"
35 status: Mapped[str] = mapped_column(String(20), default="pending", server_default="pending", index=True) # pending | approved | rejected
37 # User tracking
38 submitted_by_id: Mapped[Optional[int]] = mapped_column(Integer) # Keycloak user ID
39 reviewed_by_id: Mapped[Optional[int]] = mapped_column(Integer) # Keycloak user ID
40 review_notes: Mapped[Optional[str]] = mapped_column(Text)
42 # Timestamps
43 created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, default=datetime.utcnow)
44 reviewed_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
46 def __repr__(self) -> str:
47 return f"<Suggestion(id={self.id}, target={self.target_table}:{self.target_id}, status='{self.status}')>"