feat: add admin endpoints to list all subscription plans and sync plan details from Stripe
This commit is contained in:
@@ -191,6 +191,22 @@ export class StripeController {
|
|||||||
return this.subscriptionService.getRevenueStats();
|
return this.subscriptionService.getRevenueStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get('admin/plans')
|
||||||
|
@Roles(UserRole.ADMIN)
|
||||||
|
@ApiBearerAuth()
|
||||||
|
@ApiOperation({ summary: 'List all subscription plans including inactive (admin)' })
|
||||||
|
async getAdminPlans() {
|
||||||
|
return this.subscriptionService.getAllPlansAdmin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('admin/plans/:id/sync')
|
||||||
|
@Roles(UserRole.ADMIN)
|
||||||
|
@ApiBearerAuth()
|
||||||
|
@ApiOperation({ summary: 'Sync a plan from Stripe (refreshes amount/currency/interval/name/description)' })
|
||||||
|
async syncPlan(@Param('id') id: string) {
|
||||||
|
return this.subscriptionService.syncPlanFromStripe(id);
|
||||||
|
}
|
||||||
|
|
||||||
@Post('admin/plans')
|
@Post('admin/plans')
|
||||||
@Roles(UserRole.ADMIN)
|
@Roles(UserRole.ADMIN)
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
|
|||||||
@@ -97,6 +97,43 @@ export class SubscriptionService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getAllPlansAdmin() {
|
||||||
|
return this.prisma.subscriptionPlan.findMany({
|
||||||
|
orderBy: [{ isActive: 'desc' }, { sortOrder: 'asc' }],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async syncPlanFromStripe(planId: string) {
|
||||||
|
const plan = await this.prisma.subscriptionPlan.findUnique({ where: { id: planId } });
|
||||||
|
if (!plan) throw new Error('Plan not found');
|
||||||
|
|
||||||
|
const stripe = this.stripeService.getStripe();
|
||||||
|
const price = await stripe.prices.retrieve(plan.stripePriceId, { expand: ['product'] });
|
||||||
|
|
||||||
|
const amount = typeof price.unit_amount === 'number' ? price.unit_amount : plan.amount;
|
||||||
|
const currency = price.currency || plan.currency;
|
||||||
|
const interval = price.recurring?.interval || plan.interval;
|
||||||
|
const product = price.product as { name?: string; description?: string | null } | string | null;
|
||||||
|
|
||||||
|
const productName =
|
||||||
|
typeof product === 'object' && product && product.name ? product.name : plan.name;
|
||||||
|
const productDescription =
|
||||||
|
typeof product === 'object' && product && product.description !== undefined
|
||||||
|
? product.description
|
||||||
|
: plan.description;
|
||||||
|
|
||||||
|
return this.prisma.subscriptionPlan.update({
|
||||||
|
where: { id: planId },
|
||||||
|
data: {
|
||||||
|
amount,
|
||||||
|
currency,
|
||||||
|
interval,
|
||||||
|
name: productName,
|
||||||
|
description: productDescription,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async getPaymentHistory(userId: string) {
|
async getPaymentHistory(userId: string) {
|
||||||
return this.prisma.payment.findMany({
|
return this.prisma.payment.findMany({
|
||||||
where: { userId },
|
where: { userId },
|
||||||
|
|||||||
Reference in New Issue
Block a user