chore: reformat code style with consistent quotes, trailing commas, and spacing across auth, billing, and models
This commit is contained in:
@@ -2,14 +2,17 @@ from datetime import datetime, date, timedelta, timezone
|
||||
from decimal import Decimal
|
||||
from typing import Optional
|
||||
from calendar import monthrange
|
||||
from .models import Invoice, InvoiceLineItem, PricingConfig, UsageAggregate, UserSubscription
|
||||
from .models import Invoice, InvoiceLineItem, PricingConfig, UserSubscription
|
||||
from .usage_tracker import UsageTracker
|
||||
from .stripe_client import StripeClient
|
||||
from ..models import User
|
||||
|
||||
|
||||
class InvoiceGenerator:
|
||||
@staticmethod
|
||||
async def generate_monthly_invoice(user: User, year: int, month: int) -> Optional[Invoice]:
|
||||
async def generate_monthly_invoice(
|
||||
user: User, year: int, month: int
|
||||
) -> Optional[Invoice]:
|
||||
period_start = date(year, month, 1)
|
||||
days_in_month = monthrange(year, month)[1]
|
||||
period_end = date(year, month, days_in_month)
|
||||
@@ -19,19 +22,24 @@ class InvoiceGenerator:
|
||||
pricing = await PricingConfig.all()
|
||||
pricing_dict = {p.config_key: p.config_value for p in pricing}
|
||||
|
||||
storage_price_per_gb = pricing_dict.get('storage_per_gb_month', Decimal('0.0045'))
|
||||
bandwidth_price_per_gb = pricing_dict.get('bandwidth_egress_per_gb', Decimal('0.009'))
|
||||
free_storage_gb = pricing_dict.get('free_tier_storage_gb', Decimal('15'))
|
||||
free_bandwidth_gb = pricing_dict.get('free_tier_bandwidth_gb', Decimal('15'))
|
||||
tax_rate = pricing_dict.get('tax_rate_default', Decimal('0'))
|
||||
storage_price_per_gb = pricing_dict.get(
|
||||
"storage_per_gb_month", Decimal("0.0045")
|
||||
)
|
||||
bandwidth_price_per_gb = pricing_dict.get(
|
||||
"bandwidth_egress_per_gb", Decimal("0.009")
|
||||
)
|
||||
free_storage_gb = pricing_dict.get("free_tier_storage_gb", Decimal("15"))
|
||||
free_bandwidth_gb = pricing_dict.get("free_tier_bandwidth_gb", Decimal("15"))
|
||||
tax_rate = pricing_dict.get("tax_rate_default", Decimal("0"))
|
||||
|
||||
storage_gb = Decimal(str(usage['storage_gb_avg']))
|
||||
bandwidth_gb = Decimal(str(usage['bandwidth_down_gb']))
|
||||
storage_gb = Decimal(str(usage["storage_gb_avg"]))
|
||||
bandwidth_gb = Decimal(str(usage["bandwidth_down_gb"]))
|
||||
|
||||
billable_storage = max(Decimal('0'), storage_gb - free_storage_gb)
|
||||
billable_bandwidth = max(Decimal('0'), bandwidth_gb - free_bandwidth_gb)
|
||||
billable_storage = max(Decimal("0"), storage_gb - free_storage_gb)
|
||||
billable_bandwidth = max(Decimal("0"), bandwidth_gb - free_bandwidth_gb)
|
||||
|
||||
import math
|
||||
|
||||
billable_storage_rounded = Decimal(math.ceil(float(billable_storage)))
|
||||
billable_bandwidth_rounded = Decimal(math.ceil(float(billable_bandwidth)))
|
||||
|
||||
@@ -65,9 +73,9 @@ class InvoiceGenerator:
|
||||
"usage": usage,
|
||||
"pricing": {
|
||||
"storage_per_gb": float(storage_price_per_gb),
|
||||
"bandwidth_per_gb": float(bandwidth_price_per_gb)
|
||||
}
|
||||
}
|
||||
"bandwidth_per_gb": float(bandwidth_price_per_gb),
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if billable_storage_rounded > 0:
|
||||
@@ -78,7 +86,10 @@ class InvoiceGenerator:
|
||||
unit_price=storage_price_per_gb,
|
||||
amount=storage_cost,
|
||||
item_type="storage",
|
||||
metadata={"avg_gb": float(storage_gb), "free_gb": float(free_storage_gb)}
|
||||
metadata={
|
||||
"avg_gb": float(storage_gb),
|
||||
"free_gb": float(free_storage_gb),
|
||||
},
|
||||
)
|
||||
|
||||
if billable_bandwidth_rounded > 0:
|
||||
@@ -89,7 +100,10 @@ class InvoiceGenerator:
|
||||
unit_price=bandwidth_price_per_gb,
|
||||
amount=bandwidth_cost,
|
||||
item_type="bandwidth",
|
||||
metadata={"total_gb": float(bandwidth_gb), "free_gb": float(free_bandwidth_gb)}
|
||||
metadata={
|
||||
"total_gb": float(bandwidth_gb),
|
||||
"free_gb": float(free_bandwidth_gb),
|
||||
},
|
||||
)
|
||||
|
||||
if subscription and subscription.stripe_customer_id:
|
||||
@@ -100,7 +114,7 @@ class InvoiceGenerator:
|
||||
"amount": item.amount,
|
||||
"currency": "usd",
|
||||
"description": item.description,
|
||||
"metadata": item.metadata or {}
|
||||
"metadata": item.metadata or {},
|
||||
}
|
||||
for item in line_items
|
||||
]
|
||||
@@ -109,7 +123,7 @@ class InvoiceGenerator:
|
||||
customer_id=subscription.stripe_customer_id,
|
||||
description=f"MyWebdav Usage Invoice for {period_start.strftime('%B %Y')}",
|
||||
line_items=stripe_line_items,
|
||||
metadata={"mywebdav_invoice_id": str(invoice.id)}
|
||||
metadata={"mywebdav_invoice_id": str(invoice.id)},
|
||||
)
|
||||
|
||||
invoice.stripe_invoice_id = stripe_invoice.id
|
||||
@@ -135,8 +149,11 @@ class InvoiceGenerator:
|
||||
|
||||
# Send invoice email
|
||||
from ..mail import queue_email
|
||||
|
||||
line_items = await invoice.line_items.all()
|
||||
items_text = "\n".join([f"- {item.description}: ${item.amount}" for item in line_items])
|
||||
items_text = "\n".join(
|
||||
[f"- {item.description}: ${item.amount}" for item in line_items]
|
||||
)
|
||||
body = f"""Dear {invoice.user.username},
|
||||
|
||||
Your invoice {invoice.invoice_number} for the period {invoice.period_start} to {invoice.period_end} is now available.
|
||||
@@ -174,7 +191,7 @@ The MyWebdav Team
|
||||
to_email=invoice.user.email,
|
||||
subject=f"Your MyWebdav Invoice {invoice.invoice_number}",
|
||||
body=body,
|
||||
html=html
|
||||
html=html,
|
||||
)
|
||||
|
||||
return invoice
|
||||
|
||||
+31
-17
@@ -1,8 +1,8 @@
|
||||
from tortoise import fields, models
|
||||
from decimal import Decimal
|
||||
|
||||
|
||||
class SubscriptionPlan(models.Model):
|
||||
id = fields.IntField(pk=True)
|
||||
id = fields.IntField(primary_key=True)
|
||||
name = fields.CharField(max_length=100, unique=True)
|
||||
display_name = fields.CharField(max_length=255)
|
||||
description = fields.TextField(null=True)
|
||||
@@ -18,10 +18,13 @@ class SubscriptionPlan(models.Model):
|
||||
class Meta:
|
||||
table = "subscription_plans"
|
||||
|
||||
|
||||
class UserSubscription(models.Model):
|
||||
id = fields.IntField(pk=True)
|
||||
id = fields.IntField(primary_key=True)
|
||||
user = fields.ForeignKeyField("models.User", related_name="subscription")
|
||||
plan = fields.ForeignKeyField("billing.SubscriptionPlan", related_name="subscriptions", null=True)
|
||||
plan = fields.ForeignKeyField(
|
||||
"billing.SubscriptionPlan", related_name="subscriptions", null=True
|
||||
)
|
||||
billing_type = fields.CharField(max_length=20, default="pay_as_you_go")
|
||||
stripe_customer_id = fields.CharField(max_length=255, unique=True, null=True)
|
||||
stripe_subscription_id = fields.CharField(max_length=255, unique=True, null=True)
|
||||
@@ -35,14 +38,15 @@ class UserSubscription(models.Model):
|
||||
class Meta:
|
||||
table = "user_subscriptions"
|
||||
|
||||
|
||||
class UsageRecord(models.Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
id = fields.BigIntField(primary_key=True)
|
||||
user = fields.ForeignKeyField("models.User", related_name="usage_records")
|
||||
record_type = fields.CharField(max_length=50, index=True)
|
||||
record_type = fields.CharField(max_length=50, db_index=True)
|
||||
amount_bytes = fields.BigIntField()
|
||||
resource_type = fields.CharField(max_length=50, null=True)
|
||||
resource_id = fields.IntField(null=True)
|
||||
timestamp = fields.DatetimeField(auto_now_add=True, index=True)
|
||||
timestamp = fields.DatetimeField(auto_now_add=True, db_index=True)
|
||||
idempotency_key = fields.CharField(max_length=255, unique=True, null=True)
|
||||
metadata = fields.JSONField(null=True)
|
||||
|
||||
@@ -50,8 +54,9 @@ class UsageRecord(models.Model):
|
||||
table = "usage_records"
|
||||
indexes = [("user_id", "record_type", "timestamp")]
|
||||
|
||||
|
||||
class UsageAggregate(models.Model):
|
||||
id = fields.IntField(pk=True)
|
||||
id = fields.IntField(primary_key=True)
|
||||
user = fields.ForeignKeyField("models.User", related_name="usage_aggregates")
|
||||
date = fields.DateField()
|
||||
storage_bytes_avg = fields.BigIntField(default=0)
|
||||
@@ -64,8 +69,9 @@ class UsageAggregate(models.Model):
|
||||
table = "usage_aggregates"
|
||||
unique_together = (("user", "date"),)
|
||||
|
||||
|
||||
class Invoice(models.Model):
|
||||
id = fields.IntField(pk=True)
|
||||
id = fields.IntField(primary_key=True)
|
||||
user = fields.ForeignKeyField("models.User", related_name="invoices")
|
||||
invoice_number = fields.CharField(max_length=50, unique=True)
|
||||
stripe_invoice_id = fields.CharField(max_length=255, unique=True, null=True)
|
||||
@@ -75,10 +81,10 @@ class Invoice(models.Model):
|
||||
tax = fields.DecimalField(max_digits=10, decimal_places=4, default=0)
|
||||
total = fields.DecimalField(max_digits=10, decimal_places=4)
|
||||
currency = fields.CharField(max_length=3, default="USD")
|
||||
status = fields.CharField(max_length=50, default="draft", index=True)
|
||||
status = fields.CharField(max_length=50, default="draft", db_index=True)
|
||||
due_date = fields.DateField(null=True)
|
||||
paid_at = fields.DatetimeField(null=True)
|
||||
created_at = fields.DatetimeField(auto_now_add=True, index=True)
|
||||
created_at = fields.DatetimeField(auto_now_add=True, db_index=True)
|
||||
updated_at = fields.DatetimeField(auto_now=True)
|
||||
metadata = fields.JSONField(null=True)
|
||||
|
||||
@@ -86,8 +92,9 @@ class Invoice(models.Model):
|
||||
table = "invoices"
|
||||
indexes = [("user_id", "status", "created_at")]
|
||||
|
||||
|
||||
class InvoiceLineItem(models.Model):
|
||||
id = fields.IntField(pk=True)
|
||||
id = fields.IntField(primary_key=True)
|
||||
invoice = fields.ForeignKeyField("billing.Invoice", related_name="line_items")
|
||||
description = fields.TextField()
|
||||
quantity = fields.DecimalField(max_digits=15, decimal_places=6)
|
||||
@@ -100,20 +107,24 @@ class InvoiceLineItem(models.Model):
|
||||
class Meta:
|
||||
table = "invoice_line_items"
|
||||
|
||||
|
||||
class PricingConfig(models.Model):
|
||||
id = fields.IntField(pk=True)
|
||||
id = fields.IntField(primary_key=True)
|
||||
config_key = fields.CharField(max_length=100, unique=True)
|
||||
config_value = fields.DecimalField(max_digits=10, decimal_places=6)
|
||||
description = fields.TextField(null=True)
|
||||
unit = fields.CharField(max_length=50, null=True)
|
||||
updated_by = fields.ForeignKeyField("models.User", related_name="pricing_updates", null=True)
|
||||
updated_by = fields.ForeignKeyField(
|
||||
"models.User", related_name="pricing_updates", null=True
|
||||
)
|
||||
updated_at = fields.DatetimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
table = "pricing_config"
|
||||
|
||||
|
||||
class PaymentMethod(models.Model):
|
||||
id = fields.IntField(pk=True)
|
||||
id = fields.IntField(primary_key=True)
|
||||
user = fields.ForeignKeyField("models.User", related_name="payment_methods")
|
||||
stripe_payment_method_id = fields.CharField(max_length=255)
|
||||
type = fields.CharField(max_length=50)
|
||||
@@ -128,9 +139,12 @@ class PaymentMethod(models.Model):
|
||||
class Meta:
|
||||
table = "payment_methods"
|
||||
|
||||
|
||||
class BillingEvent(models.Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
user = fields.ForeignKeyField("models.User", related_name="billing_events", null=True)
|
||||
id = fields.BigIntField(primary_key=True)
|
||||
user = fields.ForeignKeyField(
|
||||
"models.User", related_name="billing_events", null=True
|
||||
)
|
||||
event_type = fields.CharField(max_length=100)
|
||||
stripe_event_id = fields.CharField(max_length=255, unique=True, null=True)
|
||||
data = fields.JSONField(null=True)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
from apscheduler.triggers.cron import CronTrigger
|
||||
from datetime import datetime, date, timedelta
|
||||
import asyncio
|
||||
|
||||
from .usage_tracker import UsageTracker
|
||||
from .invoice_generator import InvoiceGenerator
|
||||
@@ -9,6 +8,7 @@ from ..models import User
|
||||
|
||||
scheduler = AsyncIOScheduler()
|
||||
|
||||
|
||||
async def aggregate_daily_usage_for_all_users():
|
||||
users = await User.filter(is_active=True).all()
|
||||
yesterday = date.today() - timedelta(days=1)
|
||||
@@ -19,6 +19,7 @@ async def aggregate_daily_usage_for_all_users():
|
||||
except Exception as e:
|
||||
print(f"Failed to aggregate usage for user {user.id}: {e}")
|
||||
|
||||
|
||||
async def generate_monthly_invoices():
|
||||
now = datetime.now()
|
||||
last_month = now.month - 1 if now.month > 1 else 12
|
||||
@@ -28,19 +29,22 @@ async def generate_monthly_invoices():
|
||||
|
||||
for user in users:
|
||||
try:
|
||||
invoice = await InvoiceGenerator.generate_monthly_invoice(user, year, last_month)
|
||||
invoice = await InvoiceGenerator.generate_monthly_invoice(
|
||||
user, year, last_month
|
||||
)
|
||||
if invoice:
|
||||
await InvoiceGenerator.finalize_invoice(invoice)
|
||||
except Exception as e:
|
||||
print(f"Failed to generate invoice for user {user.id}: {e}")
|
||||
|
||||
|
||||
def start_scheduler():
|
||||
scheduler.add_job(
|
||||
aggregate_daily_usage_for_all_users,
|
||||
CronTrigger(hour=1, minute=0),
|
||||
id="aggregate_daily_usage",
|
||||
name="Aggregate daily usage for all users",
|
||||
replace_existing=True
|
||||
replace_existing=True,
|
||||
)
|
||||
|
||||
scheduler.add_job(
|
||||
@@ -48,10 +52,11 @@ def start_scheduler():
|
||||
CronTrigger(day=1, hour=2, minute=0),
|
||||
id="generate_monthly_invoices",
|
||||
name="Generate monthly invoices",
|
||||
replace_existing=True
|
||||
replace_existing=True,
|
||||
)
|
||||
|
||||
scheduler.start()
|
||||
|
||||
|
||||
def stop_scheduler():
|
||||
scheduler.shutdown()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import stripe
|
||||
from decimal import Decimal
|
||||
from typing import Optional, Dict, Any
|
||||
from typing import Dict
|
||||
from ..settings import settings
|
||||
|
||||
|
||||
class StripeClient:
|
||||
@staticmethod
|
||||
def _ensure_api_key():
|
||||
@@ -11,13 +11,12 @@ class StripeClient:
|
||||
stripe.api_key = settings.STRIPE_SECRET_KEY
|
||||
else:
|
||||
raise ValueError("Stripe API key not configured")
|
||||
|
||||
@staticmethod
|
||||
async def create_customer(email: str, name: str, metadata: Dict = None) -> str:
|
||||
StripeClient._ensure_api_key()
|
||||
customer = stripe.Customer.create(
|
||||
email=email,
|
||||
name=name,
|
||||
metadata=metadata or {}
|
||||
email=email, name=name, metadata=metadata or {}
|
||||
)
|
||||
return customer.id
|
||||
|
||||
@@ -26,7 +25,7 @@ class StripeClient:
|
||||
amount: int,
|
||||
currency: str = "usd",
|
||||
customer_id: str = None,
|
||||
metadata: Dict = None
|
||||
metadata: Dict = None,
|
||||
) -> stripe.PaymentIntent:
|
||||
StripeClient._ensure_api_key()
|
||||
return stripe.PaymentIntent.create(
|
||||
@@ -34,32 +33,29 @@ class StripeClient:
|
||||
currency=currency,
|
||||
customer=customer_id,
|
||||
metadata=metadata or {},
|
||||
automatic_payment_methods={"enabled": True}
|
||||
automatic_payment_methods={"enabled": True},
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
async def create_invoice(
|
||||
customer_id: str,
|
||||
description: str,
|
||||
line_items: list,
|
||||
metadata: Dict = None
|
||||
customer_id: str, description: str, line_items: list, metadata: Dict = None
|
||||
) -> stripe.Invoice:
|
||||
StripeClient._ensure_api_key()
|
||||
for item in line_items:
|
||||
stripe.InvoiceItem.create(
|
||||
customer=customer_id,
|
||||
amount=int(item['amount'] * 100),
|
||||
currency=item.get('currency', 'usd'),
|
||||
description=item['description'],
|
||||
metadata=item.get('metadata', {})
|
||||
amount=int(item["amount"] * 100),
|
||||
currency=item.get("currency", "usd"),
|
||||
description=item["description"],
|
||||
metadata=item.get("metadata", {}),
|
||||
)
|
||||
|
||||
invoice = stripe.Invoice.create(
|
||||
customer=customer_id,
|
||||
description=description,
|
||||
auto_advance=True,
|
||||
collection_method='charge_automatically',
|
||||
metadata=metadata or {}
|
||||
collection_method="charge_automatically",
|
||||
metadata=metadata or {},
|
||||
)
|
||||
|
||||
return invoice
|
||||
@@ -76,18 +72,15 @@ class StripeClient:
|
||||
|
||||
@staticmethod
|
||||
async def attach_payment_method(
|
||||
payment_method_id: str,
|
||||
customer_id: str
|
||||
payment_method_id: str, customer_id: str
|
||||
) -> stripe.PaymentMethod:
|
||||
StripeClient._ensure_api_key()
|
||||
payment_method = stripe.PaymentMethod.attach(
|
||||
payment_method_id,
|
||||
customer=customer_id
|
||||
payment_method_id, customer=customer_id
|
||||
)
|
||||
|
||||
stripe.Customer.modify(
|
||||
customer_id,
|
||||
invoice_settings={'default_payment_method': payment_method_id}
|
||||
customer_id, invoice_settings={"default_payment_method": payment_method_id}
|
||||
)
|
||||
|
||||
return payment_method
|
||||
@@ -95,22 +88,15 @@ class StripeClient:
|
||||
@staticmethod
|
||||
async def list_payment_methods(customer_id: str, type: str = "card"):
|
||||
StripeClient._ensure_api_key()
|
||||
return stripe.PaymentMethod.list(
|
||||
customer=customer_id,
|
||||
type=type
|
||||
)
|
||||
return stripe.PaymentMethod.list(customer=customer_id, type=type)
|
||||
|
||||
@staticmethod
|
||||
async def create_subscription(
|
||||
customer_id: str,
|
||||
price_id: str,
|
||||
metadata: Dict = None
|
||||
customer_id: str, price_id: str, metadata: Dict = None
|
||||
) -> stripe.Subscription:
|
||||
StripeClient._ensure_api_key()
|
||||
return stripe.Subscription.create(
|
||||
customer=customer_id,
|
||||
items=[{'price': price_id}],
|
||||
metadata=metadata or {}
|
||||
customer=customer_id, items=[{"price": price_id}], metadata=metadata or {}
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import uuid
|
||||
from datetime import datetime, date, timezone
|
||||
from decimal import Decimal
|
||||
from typing import Optional
|
||||
from tortoise.transactions import in_transaction
|
||||
from .models import UsageRecord, UsageAggregate
|
||||
from ..models import User
|
||||
|
||||
|
||||
class UsageTracker:
|
||||
@staticmethod
|
||||
async def track_storage(
|
||||
@@ -13,7 +12,7 @@ class UsageTracker:
|
||||
amount_bytes: int,
|
||||
resource_type: str = None,
|
||||
resource_id: int = None,
|
||||
metadata: dict = None
|
||||
metadata: dict = None,
|
||||
):
|
||||
idempotency_key = f"storage_{user.id}_{datetime.now(timezone.utc).timestamp()}_{uuid.uuid4().hex[:8]}"
|
||||
|
||||
@@ -24,7 +23,7 @@ class UsageTracker:
|
||||
resource_type=resource_type,
|
||||
resource_id=resource_id,
|
||||
idempotency_key=idempotency_key,
|
||||
metadata=metadata
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@@ -34,7 +33,7 @@ class UsageTracker:
|
||||
direction: str = "down",
|
||||
resource_type: str = None,
|
||||
resource_id: int = None,
|
||||
metadata: dict = None
|
||||
metadata: dict = None,
|
||||
):
|
||||
record_type = f"bandwidth_{direction}"
|
||||
idempotency_key = f"{record_type}_{user.id}_{datetime.now(timezone.utc).timestamp()}_{uuid.uuid4().hex[:8]}"
|
||||
@@ -46,7 +45,7 @@ class UsageTracker:
|
||||
resource_type=resource_type,
|
||||
resource_id=resource_id,
|
||||
idempotency_key=idempotency_key,
|
||||
metadata=metadata
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@@ -61,24 +60,26 @@ class UsageTracker:
|
||||
user=user,
|
||||
record_type="storage",
|
||||
timestamp__gte=start_of_day,
|
||||
timestamp__lte=end_of_day
|
||||
timestamp__lte=end_of_day,
|
||||
).all()
|
||||
|
||||
storage_avg = sum(r.amount_bytes for r in storage_records) // max(len(storage_records), 1)
|
||||
storage_avg = sum(r.amount_bytes for r in storage_records) // max(
|
||||
len(storage_records), 1
|
||||
)
|
||||
storage_peak = max((r.amount_bytes for r in storage_records), default=0)
|
||||
|
||||
bandwidth_up = await UsageRecord.filter(
|
||||
user=user,
|
||||
record_type="bandwidth_up",
|
||||
timestamp__gte=start_of_day,
|
||||
timestamp__lte=end_of_day
|
||||
timestamp__lte=end_of_day,
|
||||
).all()
|
||||
|
||||
bandwidth_down = await UsageRecord.filter(
|
||||
user=user,
|
||||
record_type="bandwidth_down",
|
||||
timestamp__gte=start_of_day,
|
||||
timestamp__lte=end_of_day
|
||||
timestamp__lte=end_of_day,
|
||||
).all()
|
||||
|
||||
total_up = sum(r.amount_bytes for r in bandwidth_up)
|
||||
@@ -92,8 +93,8 @@ class UsageTracker:
|
||||
"storage_bytes_avg": storage_avg,
|
||||
"storage_bytes_peak": storage_peak,
|
||||
"bandwidth_up_bytes": total_up,
|
||||
"bandwidth_down_bytes": total_down
|
||||
}
|
||||
"bandwidth_down_bytes": total_down,
|
||||
},
|
||||
)
|
||||
|
||||
if not created:
|
||||
@@ -108,6 +109,7 @@ class UsageTracker:
|
||||
@staticmethod
|
||||
async def get_current_storage(user: User) -> int:
|
||||
from ..models import File
|
||||
|
||||
files = await File.filter(owner=user, is_deleted=False).all()
|
||||
return sum(f.size for f in files)
|
||||
|
||||
@@ -121,9 +123,7 @@ class UsageTracker:
|
||||
end_date = date(year, month, last_day)
|
||||
|
||||
aggregates = await UsageAggregate.filter(
|
||||
user=user,
|
||||
date__gte=start_date,
|
||||
date__lte=end_date
|
||||
user=user, date__gte=start_date, date__lte=end_date
|
||||
).all()
|
||||
|
||||
if not aggregates:
|
||||
@@ -132,7 +132,7 @@ class UsageTracker:
|
||||
"storage_gb_peak": 0,
|
||||
"bandwidth_up_gb": 0,
|
||||
"bandwidth_down_gb": 0,
|
||||
"total_bandwidth_gb": 0
|
||||
"total_bandwidth_gb": 0,
|
||||
}
|
||||
|
||||
storage_avg = sum(a.storage_bytes_avg for a in aggregates) / len(aggregates)
|
||||
@@ -145,5 +145,5 @@ class UsageTracker:
|
||||
"storage_gb_peak": round(storage_peak / (1024**3), 4),
|
||||
"bandwidth_up_gb": round(bandwidth_up / (1024**3), 4),
|
||||
"bandwidth_down_gb": round(bandwidth_down / (1024**3), 4),
|
||||
"total_bandwidth_gb": round((bandwidth_up + bandwidth_down) / (1024**3), 4)
|
||||
"total_bandwidth_gb": round((bandwidth_up + bandwidth_down) / (1024**3), 4),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user