feat: migrate getRevenueStats to fetch directly from Stripe API with database fallback

This commit is contained in:
pradeepkumar
2026-04-09 16:03:01 +05:30
parent eb6a78ead9
commit 92a29b664c

View File

@@ -1,12 +1,16 @@
import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { SubscriptionStatus } from '@prisma/client';
import { StripeService } from './stripe.service';
@Injectable()
export class SubscriptionService {
private readonly logger = new Logger(SubscriptionService.name);
constructor(private prisma: PrismaService) {}
constructor(
private prisma: PrismaService,
private stripeService: StripeService,
) {}
async getActivePlan(userId: string) {
return this.prisma.agentSubscription.findFirst({
@@ -129,6 +133,73 @@ export class SubscriptionService {
}
async getRevenueStats() {
try {
const stripe = this.stripeService.getStripe();
// Count active subscriptions from Stripe
let activeCount = 0;
let hasMore = true;
let startingAfter: string | undefined;
while (hasMore) {
const subs = await stripe.subscriptions.list({
status: 'active',
limit: 100,
...(startingAfter ? { starting_after: startingAfter } : {}),
});
activeCount += subs.data.length;
hasMore = subs.has_more;
if (subs.data.length > 0) {
startingAfter = subs.data[subs.data.length - 1].id;
}
}
// Total revenue: sum of all successful charges
let totalRevenueCents = 0;
hasMore = true;
startingAfter = undefined;
while (hasMore) {
const charges = await stripe.charges.list({
limit: 100,
...(startingAfter ? { starting_after: startingAfter } : {}),
});
totalRevenueCents += charges.data
.filter((c) => c.status === 'succeeded')
.reduce((sum, c) => sum + c.amount, 0);
hasMore = charges.has_more;
if (charges.data.length > 0) {
startingAfter = charges.data[charges.data.length - 1].id;
}
}
// Monthly revenue: charges from start of current month
const monthStart = new Date(new Date().getFullYear(), new Date().getMonth(), 1);
let monthlyRevenueCents = 0;
hasMore = true;
startingAfter = undefined;
while (hasMore) {
const charges = await stripe.charges.list({
limit: 100,
created: { gte: Math.floor(monthStart.getTime() / 1000) },
...(startingAfter ? { starting_after: startingAfter } : {}),
});
monthlyRevenueCents += charges.data
.filter((c) => c.status === 'succeeded')
.reduce((sum, c) => sum + c.amount, 0);
hasMore = charges.has_more;
if (charges.data.length > 0) {
startingAfter = charges.data[charges.data.length - 1].id;
}
}
return {
activeSubscriptions: activeCount,
totalRevenue: totalRevenueCents / 100,
monthlyRevenue: monthlyRevenueCents / 100,
};
} catch (error) {
this.logger.warn(`Failed to fetch stats from Stripe, falling back to DB: ${error.message}`);
// Fallback to local DB
const [activeCount, totalRevenue, monthlyRevenue] = await Promise.all([
this.prisma.agentSubscription.count({ where: { status: 'ACTIVE' } }),
this.prisma.payment.aggregate({
@@ -152,6 +223,7 @@ export class SubscriptionService {
monthlyRevenue: (monthlyRevenue._sum.amount || 0) / 100,
};
}
}
private async updateAgentSubscriptionStatus(userId: string, status: SubscriptionStatus) {
try {