83 lines
2.5 KiB
Python
83 lines
2.5 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import datetime, timezone
|
|
from uuid import uuid4
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
from packages.adapters.sqlalchemy_impl.models import PointsOrderModel
|
|
|
|
|
|
class SQLAlchemyPointsOrderRepository:
|
|
"""积分充值订单仓储."""
|
|
|
|
def __init__(self, session: Session):
|
|
self.session = session
|
|
|
|
def create(
|
|
self,
|
|
*,
|
|
user_id: str,
|
|
package_name: str,
|
|
points_amount: int,
|
|
price_cents: int,
|
|
original_price_cents: int,
|
|
discount: float = 1.0,
|
|
currency: str = "CNY",
|
|
payment_method: str | None = None,
|
|
expire_at: datetime | None = None,
|
|
) -> PointsOrderModel:
|
|
model = PointsOrderModel(
|
|
id=str(uuid4()),
|
|
user_id=user_id,
|
|
package_name=package_name,
|
|
points_amount=points_amount,
|
|
price_cents=price_cents,
|
|
currency=currency,
|
|
discount=discount,
|
|
original_price_cents=original_price_cents,
|
|
status="pending",
|
|
payment_method=payment_method,
|
|
expire_at=expire_at,
|
|
created_at=datetime.now(timezone.utc),
|
|
)
|
|
self.session.add(model)
|
|
self.session.flush()
|
|
return model
|
|
|
|
def get_by_id(self, order_id: str) -> PointsOrderModel | None:
|
|
return self.session.get(PointsOrderModel, order_id)
|
|
|
|
def update_status(
|
|
self,
|
|
order_id: str,
|
|
*,
|
|
status: str,
|
|
payment_id: str | None = None,
|
|
paid_at: datetime | None = None,
|
|
) -> PointsOrderModel | None:
|
|
model = self.session.get(PointsOrderModel, order_id)
|
|
if model is None:
|
|
return None
|
|
model.status = status
|
|
if payment_id is not None:
|
|
model.payment_id = payment_id
|
|
if paid_at is not None:
|
|
model.paid_at = paid_at
|
|
self.session.flush()
|
|
return model
|
|
|
|
def list_expired_pending(self, before: datetime | None = None) -> list[PointsOrderModel]:
|
|
"""查出 expire_at 已过仍处于 pending 状态的订单(可用于定时取消)."""
|
|
if before is None:
|
|
before = datetime.now(timezone.utc)
|
|
return (
|
|
self.session.query(PointsOrderModel)
|
|
.filter(
|
|
PointsOrderModel.status == "pending",
|
|
PointsOrderModel.expire_at.isnot(None),
|
|
PointsOrderModel.expire_at < before,
|
|
)
|
|
.all()
|
|
)
|