File size: 4,524 Bytes
c353d4b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
from fastapi import APIRouter
from typing import List
from datetime import datetime, timedelta
from decimal import Decimal
from tortoise.functions import Sum

from App.Payments.Model import Payment
from App.Users.Model import User
from .Schema import (
    RevenueMetricsResponse,
    RecurringUserResponse,
)

metrics_router = APIRouter(tags=["Metrics"])


# Helper function to get the start of the week, month, and day
def get_time_frames():
    today = datetime.now()
    start_of_day = today.replace(hour=0, minute=0, second=0, microsecond=0)
    start_of_week = start_of_day - timedelta(
        days=start_of_day.weekday()
    )  # Start of the current week (Monday)
    start_of_month = start_of_day.replace(
        day=1, hour=0, minute=0, second=0, microsecond=0
    )  # Start of the current month

    return start_of_day, start_of_week, start_of_month


@metrics_router.get("/metrics/revenue/daily", response_model=RevenueMetricsResponse)
async def get_daily_revenue():
    start_of_day, _, _ = get_time_frames()

    # Sum up the payments made today using Tortoise ORM's annotate and values
    revenue_data = (
        await Payment.filter(created_time__gte=start_of_day)
        .annotate(total_revenue=Sum("amount"))
        .values("total_revenue")
    )

    if revenue_data and revenue_data[0]["total_revenue"] is not None:
        total_revenue = revenue_data[0]["total_revenue"]
    else:
        total_revenue = Decimal("0.00")

    return RevenueMetricsResponse(
        period="daily",
        revenue=float(total_revenue),
    )


@metrics_router.get("/metrics/revenue/weekly", response_model=RevenueMetricsResponse)
async def get_weekly_revenue():
    _, start_of_week, _ = get_time_frames()

    # Sum up the payments made in the current week
    revenue_data = (
        await Payment.filter(created_time__gte=start_of_week)
        .annotate(total_revenue=Sum("amount"))
        .values("total_revenue")
    )

    if revenue_data and revenue_data[0]["total_revenue"] is not None:
        total_revenue = revenue_data[0]["total_revenue"]
    else:
        total_revenue = Decimal("0.00")

    return RevenueMetricsResponse(
        period="weekly",
        revenue=float(total_revenue),
    )


@metrics_router.get("/metrics/revenue/monthly", response_model=RevenueMetricsResponse)
async def get_monthly_revenue():
    _, _, start_of_month = get_time_frames()

    # Sum up the payments made in the current month
    revenue_data = (
        await Payment.filter(created_time__gte=start_of_month)
        .annotate(total_revenue=Sum("amount"))
        .values("total_revenue")
    )

    if revenue_data and revenue_data[0]["total_revenue"] is not None:
        total_revenue = revenue_data[0]["total_revenue"]
    else:
        total_revenue = Decimal("0.00")

    return RevenueMetricsResponse(
        period="monthly",
        revenue=float(total_revenue),
    )


@metrics_router.get(
    "/metrics/recurring-users", response_model=List[RecurringUserResponse]
)
async def get_recurring_users():
    # Get the start of the day and 6 days ago (total of 7 days including today)
    start_of_day, _, _ = get_time_frames()
    seven_days_ago = start_of_day - timedelta(days=6)

    # Find all payments in the last 7 days
    payments = await Payment.filter(created_time__gte=seven_days_ago).values(
        "user_id", "created_time"
    )

    # Initialize a dictionary to hold payment dates per user
    user_payment_dates = {}

    # Collect payment dates per user
    for payment in payments:
        user_id = payment["user_id"]
        payment_date = payment["created_time"].date()

        if user_id not in user_payment_dates:
            user_payment_dates[user_id] = set()

        user_payment_dates[user_id].add(payment_date)

    # Calculate the set of dates we expect payments on
    expected_dates = set((start_of_day - timedelta(days=i)).date() for i in range(7))

    # Filter users who have made payments on each expected date
    recurring_users = [
        user_id
        for user_id, payment_dates in user_payment_dates.items()
        if payment_dates == expected_dates
    ]

    # Fetch user details for recurring users
    recurring_user_details = await User.filter(id__in=recurring_users).all()

    return [
        RecurringUserResponse(
            user_id=str(user.id),
            username=user.username,  # Adjust this field based on your User model
            email=user.email,  # Adjust as necessary
        )
        for user in recurring_user_details
    ]