1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
import logging
from fastapi import APIRouter, Depends, HTTPException, Request
from sqlalchemy import select
from src.auth import TokenAuth
from src.dto import Order, OrderCreate, Voucher
from src.orm import Voucher as DBVoucher
from src.settings import DBSession, PrintfulClient
router = APIRouter(prefix="/orders", tags=["Orders"], dependencies=[Depends(TokenAuth(allow_vouchers=True))])
log = logging.getLogger(__name__)
@router.post("/")
async def create_order(request: Request, db: DBSession, client: PrintfulClient, order: OrderCreate) -> Order | None:
"""
Create the order in printful and deduct the order cost from the voucher.
If the voucher does not have enough funds, the order is cancelled.
"""
resp = await client.post("/orders", json=order.as_printful_payload(), params={"confirm": False})
resp.raise_for_status()
submitted_order = Order.model_validate(resp.json()["result"])
voucher: Voucher = request.state.voucher
stmt = select(DBVoucher).where(DBVoucher.id == voucher.id).with_for_update()
db_voucher = await db.scalar(stmt)
if submitted_order.costs.total > db_voucher.balance:
await client.delete(f"/orders/{submitted_order.id}")
raise HTTPException(
status_code=400,
detail=f"Order totals {submitted_order.costs.total}, only {db_voucher.balance} remaining on voucher.",
)
db_voucher.balance = db_voucher.balance - submitted_order.costs.total
return submitted_order
|