feat(sub): handling upgrade/downgrade
rw integration and /me endpoints are left
This commit is contained in:
@@ -1,8 +1,12 @@
|
||||
from datetime import UTC, datetime
|
||||
import math
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from config import cfg
|
||||
from core.deps import get_auth_context, get_pally_client
|
||||
from db.models.orders import OrderStatus
|
||||
from db.session import get_db
|
||||
from external.pally import PallyClient
|
||||
from repositories import AddonsRepository, PricingRepository
|
||||
@@ -13,6 +17,12 @@ from schemas.dto import AuthContext
|
||||
from schemas.invoices import InvoiceStatus
|
||||
from schemas.plans import OrderDetails
|
||||
from services.plans import calculate_price, get_pricing_model
|
||||
from services.subscriptions import (
|
||||
apply_order_now,
|
||||
deduct_order_balance,
|
||||
queue_order_for_later,
|
||||
should_apply_immediately,
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/orders")
|
||||
|
||||
@@ -29,32 +39,68 @@ async def checkout(
|
||||
invoices_repo = InvoiceRepository(session)
|
||||
orders_repo = OrderRepository(session)
|
||||
|
||||
pricing = await get_pricing_model(addons_repo, pricing_repo)
|
||||
price = math.ceil(await calculate_price(addons_repo=addons_repo, order=order, pricing=pricing))
|
||||
bonus_covered = min(ctx.user.balance, price)
|
||||
amount_to_pay = round(max(price - bonus_covered, 0), 2)
|
||||
now = datetime.now(UTC)
|
||||
|
||||
order_entry = await orders_repo.create(
|
||||
ctx.user.id,
|
||||
order.devices,
|
||||
order.duration_days,
|
||||
user_id=ctx.user.id,
|
||||
devices=order.devices,
|
||||
duration_days=order.duration_days,
|
||||
total_amount=price,
|
||||
balance_amount=bonus_covered,
|
||||
addons=order.addons,
|
||||
)
|
||||
|
||||
pricing = await get_pricing_model(addons_repo, pricing_repo)
|
||||
price = await calculate_price(addons_repo=addons_repo, order=order, pricing=pricing)
|
||||
bonus_covered = ctx.user.balance
|
||||
amount_to_pay = max(price - bonus_covered, cfg.minimal_deposit) if bonus_covered < price else 0
|
||||
|
||||
if amount_to_pay > 0:
|
||||
invoice = await invoices_repo.create(
|
||||
creator_id=ctx.user.id, amount=amount_to_pay, status=InvoiceStatus.ACTIVE
|
||||
await invoices_repo.create(
|
||||
creator_id=ctx.user.id,
|
||||
order_id=order_entry.id,
|
||||
amount=amount_to_pay,
|
||||
status=InvoiceStatus.ACTIVE,
|
||||
)
|
||||
with open("log.txt", "w") as f:
|
||||
f.write(
|
||||
" ".join((str(price), str(amount_to_pay), cfg.pally_shop_id, str(order_entry.id)))
|
||||
)
|
||||
bill = await pally.bills.create(
|
||||
float(amount_to_pay), cfg.pally_shop_id, order_id=str(order_entry.id)
|
||||
)
|
||||
|
||||
bill = await pally.bills.create(amount_to_pay, cfg.pally_shop_id, order_id=invoice.id)
|
||||
payment_link = bill.link_page_url
|
||||
if not payment_link:
|
||||
raise HTTPException(500, detail="failed to create invoice")
|
||||
else:
|
||||
await deduct_order_balance(
|
||||
session,
|
||||
user=ctx.user,
|
||||
order=order_entry,
|
||||
description=f"order {order_entry.id} paid from balance",
|
||||
)
|
||||
order_entry.status = OrderStatus.PAID
|
||||
if should_apply_immediately(
|
||||
subscription=ctx.user.subscription,
|
||||
order=order_entry,
|
||||
pricing=pricing,
|
||||
now=now,
|
||||
):
|
||||
await apply_order_now(
|
||||
session,
|
||||
user=ctx.user,
|
||||
order=order_entry,
|
||||
pricing=pricing,
|
||||
now=now,
|
||||
)
|
||||
else:
|
||||
await queue_order_for_later(
|
||||
order=order_entry, subscription=ctx.user.subscription, now=now
|
||||
)
|
||||
await session.commit()
|
||||
payment_link = None
|
||||
|
||||
return CheckoutResponse(
|
||||
order_id=order_entry.id,
|
||||
order_id=str(order_entry.id),
|
||||
total_amount=price,
|
||||
bonus_paid=bonus_covered,
|
||||
amount_to_pay=amount_to_pay,
|
||||
|
||||
Reference in New Issue
Block a user