189 lines
5.5 KiB
Python
189 lines
5.5 KiB
Python
|
|
import pytest
|
||
|
|
import pytest_asyncio
|
||
|
|
from decimal import Decimal
|
||
|
|
from datetime import date, datetime
|
||
|
|
from tortoise.contrib.test import initializer, finalizer
|
||
|
|
from rbox.models import User
|
||
|
|
from rbox.billing.models import (
|
||
|
|
SubscriptionPlan, UserSubscription, UsageRecord, UsageAggregate,
|
||
|
|
Invoice, InvoiceLineItem, PricingConfig, PaymentMethod, BillingEvent
|
||
|
|
)
|
||
|
|
|
||
|
|
@pytest.fixture(scope="module")
|
||
|
|
def event_loop():
|
||
|
|
import asyncio
|
||
|
|
loop = asyncio.get_event_loop_policy().new_event_loop()
|
||
|
|
yield loop
|
||
|
|
loop.close()
|
||
|
|
|
||
|
|
@pytest_asyncio.fixture(scope="module", autouse=True)
|
||
|
|
async def initialize_tests():
|
||
|
|
initializer(["rbox.models", "rbox.billing.models"], db_url="sqlite://:memory:")
|
||
|
|
yield
|
||
|
|
await finalizer()
|
||
|
|
|
||
|
|
@pytest_asyncio.fixture
|
||
|
|
async def test_user():
|
||
|
|
user = await User.create(
|
||
|
|
username="testuser",
|
||
|
|
email="test@example.com",
|
||
|
|
hashed_password="hashed_password_here",
|
||
|
|
is_active=True
|
||
|
|
)
|
||
|
|
yield user
|
||
|
|
await user.delete()
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_subscription_plan_creation():
|
||
|
|
plan = await SubscriptionPlan.create(
|
||
|
|
name="starter",
|
||
|
|
display_name="Starter Plan",
|
||
|
|
description="Basic storage plan",
|
||
|
|
storage_gb=100,
|
||
|
|
bandwidth_gb=100,
|
||
|
|
price_monthly=Decimal("5.00"),
|
||
|
|
price_yearly=Decimal("50.00")
|
||
|
|
)
|
||
|
|
|
||
|
|
assert plan.name == "starter"
|
||
|
|
assert plan.storage_gb == 100
|
||
|
|
assert plan.price_monthly == Decimal("5.00")
|
||
|
|
await plan.delete()
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_user_subscription_creation(test_user):
|
||
|
|
subscription = await UserSubscription.create(
|
||
|
|
user=test_user,
|
||
|
|
billing_type="pay_as_you_go",
|
||
|
|
status="active"
|
||
|
|
)
|
||
|
|
|
||
|
|
assert subscription.user_id == test_user.id
|
||
|
|
assert subscription.billing_type == "pay_as_you_go"
|
||
|
|
assert subscription.status == "active"
|
||
|
|
await subscription.delete()
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_usage_record_creation(test_user):
|
||
|
|
usage = await UsageRecord.create(
|
||
|
|
user=test_user,
|
||
|
|
record_type="storage",
|
||
|
|
amount_bytes=1024 * 1024 * 100,
|
||
|
|
resource_type="file",
|
||
|
|
resource_id=1,
|
||
|
|
idempotency_key="test_key_123"
|
||
|
|
)
|
||
|
|
|
||
|
|
assert usage.user_id == test_user.id
|
||
|
|
assert usage.record_type == "storage"
|
||
|
|
assert usage.amount_bytes == 1024 * 1024 * 100
|
||
|
|
await usage.delete()
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_usage_aggregate_creation(test_user):
|
||
|
|
aggregate = await UsageAggregate.create(
|
||
|
|
user=test_user,
|
||
|
|
date=date.today(),
|
||
|
|
storage_bytes_avg=1024 * 1024 * 500,
|
||
|
|
storage_bytes_peak=1024 * 1024 * 600,
|
||
|
|
bandwidth_up_bytes=1024 * 1024 * 50,
|
||
|
|
bandwidth_down_bytes=1024 * 1024 * 100
|
||
|
|
)
|
||
|
|
|
||
|
|
assert aggregate.user_id == test_user.id
|
||
|
|
assert aggregate.storage_bytes_avg == 1024 * 1024 * 500
|
||
|
|
await aggregate.delete()
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_invoice_creation(test_user):
|
||
|
|
invoice = await Invoice.create(
|
||
|
|
user=test_user,
|
||
|
|
invoice_number="INV-000001-202311",
|
||
|
|
period_start=date(2023, 11, 1),
|
||
|
|
period_end=date(2023, 11, 30),
|
||
|
|
subtotal=Decimal("10.00"),
|
||
|
|
tax=Decimal("0.00"),
|
||
|
|
total=Decimal("10.00"),
|
||
|
|
status="draft"
|
||
|
|
)
|
||
|
|
|
||
|
|
assert invoice.user_id == test_user.id
|
||
|
|
assert invoice.invoice_number == "INV-000001-202311"
|
||
|
|
assert invoice.total == Decimal("10.00")
|
||
|
|
await invoice.delete()
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_invoice_line_item_creation(test_user):
|
||
|
|
invoice = await Invoice.create(
|
||
|
|
user=test_user,
|
||
|
|
invoice_number="INV-000002-202311",
|
||
|
|
period_start=date(2023, 11, 1),
|
||
|
|
period_end=date(2023, 11, 30),
|
||
|
|
subtotal=Decimal("10.00"),
|
||
|
|
tax=Decimal("0.00"),
|
||
|
|
total=Decimal("10.00"),
|
||
|
|
status="draft"
|
||
|
|
)
|
||
|
|
|
||
|
|
line_item = await InvoiceLineItem.create(
|
||
|
|
invoice=invoice,
|
||
|
|
description="Storage usage",
|
||
|
|
quantity=Decimal("100.000000"),
|
||
|
|
unit_price=Decimal("0.100000"),
|
||
|
|
amount=Decimal("10.0000"),
|
||
|
|
item_type="storage"
|
||
|
|
)
|
||
|
|
|
||
|
|
assert line_item.invoice_id == invoice.id
|
||
|
|
assert line_item.description == "Storage usage"
|
||
|
|
assert line_item.amount == Decimal("10.0000")
|
||
|
|
await line_item.delete()
|
||
|
|
await invoice.delete()
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_pricing_config_creation(test_user):
|
||
|
|
config = await PricingConfig.create(
|
||
|
|
config_key="storage_per_gb_month",
|
||
|
|
config_value=Decimal("0.0045"),
|
||
|
|
description="Storage cost per GB per month",
|
||
|
|
unit="per_gb_month",
|
||
|
|
updated_by=test_user
|
||
|
|
)
|
||
|
|
|
||
|
|
assert config.config_key == "storage_per_gb_month"
|
||
|
|
assert config.config_value == Decimal("0.0045")
|
||
|
|
await config.delete()
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_payment_method_creation(test_user):
|
||
|
|
payment_method = await PaymentMethod.create(
|
||
|
|
user=test_user,
|
||
|
|
stripe_payment_method_id="pm_test_123",
|
||
|
|
type="card",
|
||
|
|
is_default=True,
|
||
|
|
last4="4242",
|
||
|
|
brand="visa",
|
||
|
|
exp_month=12,
|
||
|
|
exp_year=2025
|
||
|
|
)
|
||
|
|
|
||
|
|
assert payment_method.user_id == test_user.id
|
||
|
|
assert payment_method.last4 == "4242"
|
||
|
|
assert payment_method.is_default is True
|
||
|
|
await payment_method.delete()
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_billing_event_creation(test_user):
|
||
|
|
event = await BillingEvent.create(
|
||
|
|
user=test_user,
|
||
|
|
event_type="invoice_created",
|
||
|
|
stripe_event_id="evt_test_123",
|
||
|
|
data={"invoice_id": 1},
|
||
|
|
processed=False
|
||
|
|
)
|
||
|
|
|
||
|
|
assert event.user_id == test_user.id
|
||
|
|
assert event.event_type == "invoice_created"
|
||
|
|
assert event.processed is False
|
||
|
|
await event.delete()
|