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

1"""Suggestion model for suggest-edit workflow.""" 

2 

3from datetime import datetime 

4from typing import Any, Optional 

5 

6from sqlalchemy import DateTime, Integer, JSON, String, Text 

7from sqlalchemy.orm import Mapped, mapped_column 

8 

9from idx_api.models.base import Base 

10 

11 

12class Suggestion(Base): 

13 """Suggestions for changes to existing records. 

14 

15 Used for the suggest-edit pattern where non-admin users can propose 

16 changes that require approval from admins or brokers. 

17 """ 

18 

19 __tablename__ = "suggestions" 

20 

21 id: Mapped[int] = mapped_column(primary_key=True) 

22 

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) 

26 

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: "..." } } 

32 

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 

36 

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) 

41 

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)) 

45 

46 def __repr__(self) -> str: 

47 return f"<Suggestion(id={self.id}, target={self.target_table}:{self.target_id}, status='{self.status}')>"