feat(approval): add safe risk disposition workflow
This commit is contained in:
64
server/src/app/models/approval_action.py
Normal file
64
server/src/app/models/approval_action.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import CheckConstraint, DateTime, Index, String, UniqueConstraint, func
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
from sqlalchemy.types import JSON
|
||||
|
||||
from app.db.base_class import Base
|
||||
|
||||
|
||||
class ApprovalActionLedger(Base):
|
||||
"""审批类写动作的持久化幂等账本。"""
|
||||
|
||||
__tablename__ = "approval_action_ledgers"
|
||||
__table_args__ = (
|
||||
CheckConstraint(
|
||||
"action IN ('approve', 'return', 'pay')",
|
||||
name="ck_approval_action_ledger_action",
|
||||
),
|
||||
CheckConstraint(
|
||||
"(completed_at IS NULL AND result_status IS NULL "
|
||||
"AND result_approval_stage IS NULL) OR "
|
||||
"(completed_at IS NOT NULL AND result_status IS NOT NULL "
|
||||
"AND result_approval_stage IS NOT NULL)",
|
||||
name="ck_approval_action_ledger_completion",
|
||||
),
|
||||
UniqueConstraint(
|
||||
"tenant_id",
|
||||
"actor_id",
|
||||
"request_id",
|
||||
name="uq_approval_action_ledger_request",
|
||||
),
|
||||
Index(
|
||||
"ix_approval_action_ledger_claim_action",
|
||||
"tenant_id",
|
||||
"claim_id",
|
||||
"action",
|
||||
),
|
||||
)
|
||||
|
||||
id: Mapped[str] = mapped_column(
|
||||
String(36),
|
||||
primary_key=True,
|
||||
default=lambda: str(uuid.uuid4()),
|
||||
)
|
||||
tenant_id: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
actor_id: Mapped[str] = mapped_column(String(120), nullable=False)
|
||||
request_id: Mapped[str] = mapped_column(String(120), nullable=False)
|
||||
claim_id: Mapped[str] = mapped_column(String(36), nullable=False)
|
||||
action: Mapped[str] = mapped_column(String(20), nullable=False)
|
||||
payload_fingerprint: Mapped[str] = mapped_column(String(80), nullable=False)
|
||||
expected_status: Mapped[str] = mapped_column(String(30), nullable=False)
|
||||
expected_approval_stage: Mapped[str] = mapped_column(String(50), nullable=False)
|
||||
result_status: Mapped[str | None] = mapped_column(String(30), nullable=True)
|
||||
result_approval_stage: Mapped[str | None] = mapped_column(String(50), nullable=True)
|
||||
response_json: Mapped[dict[str, Any] | None] = mapped_column(JSON, nullable=True)
|
||||
completed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
||||
created_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True),
|
||||
server_default=func.now(),
|
||||
)
|
||||
Reference in New Issue
Block a user