feat: 添加 points_audit_ledger 及 JSON 字段 Pydantic Schema 约束
This commit is contained in:
@@ -6,8 +6,10 @@ from .auth_user import AuthUser
|
||||
from .invite_code import InviteCode
|
||||
from .llm import Llm
|
||||
from .llm_factory import LlmFactory
|
||||
from .points_audit_ledger import PointsAuditLedger
|
||||
from .points_ledger import PointsLedger
|
||||
from .profile import Profile
|
||||
from .register_bonus_claims import RegisterBonusClaims
|
||||
from .system_agents import SystemAgents
|
||||
from .user_points import UserPoints
|
||||
|
||||
@@ -18,8 +20,10 @@ __all__ = [
|
||||
"InviteCode",
|
||||
"Llm",
|
||||
"LlmFactory",
|
||||
"PointsAuditLedger",
|
||||
"PointsLedger",
|
||||
"Profile",
|
||||
"RegisterBonusClaims",
|
||||
"SystemAgents",
|
||||
"UserPoints",
|
||||
]
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from decimal import Decimal
|
||||
|
||||
from sqlalchemy import (
|
||||
BigInteger,
|
||||
CheckConstraint,
|
||||
Index,
|
||||
Integer,
|
||||
JSON,
|
||||
Numeric,
|
||||
SmallInteger,
|
||||
String,
|
||||
Text,
|
||||
UniqueConstraint,
|
||||
text,
|
||||
)
|
||||
from sqlalchemy.dialects.postgresql import JSONB, UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from core.db.base import Base, TimestampMixin
|
||||
|
||||
|
||||
class PointsAuditLedger(TimestampMixin, Base):
|
||||
__tablename__ = "points_audit_ledger"
|
||||
__table_args__ = (
|
||||
CheckConstraint(
|
||||
"amount >= 0", name="ck_points_audit_ledger_amount_non_negative"
|
||||
),
|
||||
CheckConstraint(
|
||||
"direction in (1, 0, -1)", name="ck_points_audit_ledger_direction_valid"
|
||||
),
|
||||
CheckConstraint(
|
||||
"balance_after >= 0",
|
||||
name="ck_points_audit_ledger_balance_after_non_negative",
|
||||
),
|
||||
CheckConstraint(
|
||||
"change_type in ('register', 'consume', 'grant', 'adjust')",
|
||||
name="ck_points_audit_ledger_change_type",
|
||||
),
|
||||
CheckConstraint(
|
||||
"biz_type is null or biz_type = 'chat'",
|
||||
name="ck_points_audit_ledger_biz_type",
|
||||
),
|
||||
CheckConstraint(
|
||||
"billed_to in ('user', 'platform')",
|
||||
name="ck_points_audit_ledger_billed_to",
|
||||
),
|
||||
CheckConstraint(
|
||||
"jsonb_typeof(metadata) = 'object'",
|
||||
name="ck_points_audit_ledger_metadata_object",
|
||||
),
|
||||
UniqueConstraint("event_id", name="uq_points_audit_ledger_event_id"),
|
||||
Index(
|
||||
"ix_points_audit_ledger_user_id_created_at",
|
||||
"user_id_snapshot",
|
||||
text("created_at DESC"),
|
||||
),
|
||||
Index(
|
||||
"ix_points_audit_ledger_change_type_created_at",
|
||||
"change_type",
|
||||
text("created_at DESC"),
|
||||
),
|
||||
)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
primary_key=True,
|
||||
default=uuid.uuid4,
|
||||
)
|
||||
event_id: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
user_id_snapshot: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
user_email_snapshot: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
change_type: Mapped[str] = mapped_column(String(16), nullable=False)
|
||||
biz_type: Mapped[str | None] = mapped_column(String(16), nullable=True)
|
||||
biz_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), nullable=True)
|
||||
direction: Mapped[int] = mapped_column(SmallInteger, nullable=False)
|
||||
amount: Mapped[int] = mapped_column(BigInteger, nullable=False)
|
||||
balance_after: Mapped[int] = mapped_column(BigInteger, nullable=False)
|
||||
billed_to: Mapped[str] = mapped_column(String(16), nullable=False)
|
||||
run_id: Mapped[str | None] = mapped_column(String(128), nullable=True)
|
||||
request_id: Mapped[str | None] = mapped_column(String(128), nullable=True)
|
||||
input_tokens: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
||||
output_tokens: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
||||
cost: Mapped[Decimal] = mapped_column(Numeric(12, 6), nullable=False, default=0)
|
||||
metadata_json: Mapped[dict[str, object]] = mapped_column(
|
||||
"metadata",
|
||||
JSON().with_variant(JSONB, "postgresql"),
|
||||
nullable=False,
|
||||
server_default=text("'{}'::jsonb"),
|
||||
default=dict,
|
||||
)
|
||||
@@ -0,0 +1,33 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
|
||||
from sqlalchemy import ForeignKey, String, Text, UniqueConstraint
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from core.db.base import Base, TimestampMixin
|
||||
|
||||
|
||||
class RegisterBonusClaims(TimestampMixin, Base):
|
||||
__tablename__ = "register_bonus_claims"
|
||||
__table_args__ = (
|
||||
UniqueConstraint("email_hash", name="uq_register_bonus_claims_email_hash"),
|
||||
UniqueConstraint(
|
||||
"grant_event_id", name="uq_register_bonus_claims_grant_event_id"
|
||||
),
|
||||
)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
primary_key=True,
|
||||
default=uuid.uuid4,
|
||||
)
|
||||
email_hash: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
user_email_snapshot: Mapped[str] = mapped_column(Text, nullable=False)
|
||||
first_user_id: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
ForeignKey("auth.users.id", ondelete="SET NULL"),
|
||||
nullable=True,
|
||||
)
|
||||
grant_event_id: Mapped[str] = mapped_column(String(64), nullable=False)
|
||||
Reference in New Issue
Block a user