Add Stripe controller routes and full Plans CRUD in backoffice
This commit is contained in:
parent
ee5a680468
commit
03827302e5
4 changed files with 175 additions and 7 deletions
|
|
@ -1,11 +1,30 @@
|
|||
import { Controller, Get, Param } from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation } from '@nestjs/swagger';
|
||||
import { PlansService } from './plans.service';
|
||||
import { Controller, Get, Post, Patch, Delete, Param, Body, NotFoundException } from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBody, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { PlansService, Plan } from './plans.service';
|
||||
|
||||
class CreatePlanDto {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
monthlyPrice: number;
|
||||
yearlyPrice: number;
|
||||
features: string[];
|
||||
popular?: boolean;
|
||||
}
|
||||
|
||||
class UpdatePlanDto {
|
||||
name?: string;
|
||||
description?: string;
|
||||
monthlyPrice?: number;
|
||||
yearlyPrice?: number;
|
||||
features?: string[];
|
||||
popular?: boolean;
|
||||
}
|
||||
|
||||
@ApiTags('Plans')
|
||||
@Controller('plans')
|
||||
export class PlansController {
|
||||
constructor(private readonly plansService: PlansService) {}
|
||||
constructor(private readonly plansService: PlansService) { }
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: 'Get all plans' })
|
||||
|
|
@ -16,6 +35,42 @@ export class PlansController {
|
|||
@Get(':id')
|
||||
@ApiOperation({ summary: 'Get plan by ID' })
|
||||
getPlanById(@Param('id') id: string) {
|
||||
return this.plansService.getPlanById(id);
|
||||
const plan = this.plansService.getPlanById(id);
|
||||
if (!plan) {
|
||||
throw new NotFoundException(`Plan with ID ${id} not found`);
|
||||
}
|
||||
return plan;
|
||||
}
|
||||
|
||||
@Post()
|
||||
@ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Create a new plan' })
|
||||
@ApiBody({ type: CreatePlanDto })
|
||||
createPlan(@Body() body: CreatePlanDto) {
|
||||
return this.plansService.createPlan(body);
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
@ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Update a plan' })
|
||||
@ApiBody({ type: UpdatePlanDto })
|
||||
updatePlan(@Param('id') id: string, @Body() body: UpdatePlanDto) {
|
||||
const plan = this.plansService.updatePlan(id, body);
|
||||
if (!plan) {
|
||||
throw new NotFoundException(`Plan with ID ${id} not found`);
|
||||
}
|
||||
return plan;
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
@ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Delete a plan' })
|
||||
deletePlan(@Param('id') id: string) {
|
||||
const deleted = this.plansService.deletePlan(id);
|
||||
if (!deleted) {
|
||||
throw new NotFoundException(`Plan with ID ${id} not found`);
|
||||
}
|
||||
return { message: `Plan ${id} deleted successfully` };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export interface Plan {
|
|||
|
||||
@Injectable()
|
||||
export class PlansService {
|
||||
private readonly plans: Plan[] = [
|
||||
private plans: Plan[] = [
|
||||
{
|
||||
id: 'starter',
|
||||
name: 'Starter',
|
||||
|
|
@ -53,7 +53,32 @@ export class PlansService {
|
|||
getAllPlans(): Plan[] {
|
||||
return this.plans;
|
||||
}
|
||||
|
||||
getPlanById(id: string): Plan | undefined {
|
||||
return this.plans.find((p) => p.id === id);
|
||||
}
|
||||
|
||||
createPlan(plan: Plan): Plan {
|
||||
this.plans.push(plan);
|
||||
return plan;
|
||||
}
|
||||
|
||||
updatePlan(id: string, updates: Partial<Plan>): Plan | undefined {
|
||||
const index = this.plans.findIndex((p) => p.id === id);
|
||||
if (index === -1) {
|
||||
return undefined;
|
||||
}
|
||||
this.plans[index] = { ...this.plans[index], ...updates };
|
||||
return this.plans[index];
|
||||
}
|
||||
|
||||
deletePlan(id: string): boolean {
|
||||
const index = this.plans.findIndex((p) => p.id === id);
|
||||
if (index === -1) {
|
||||
return false;
|
||||
}
|
||||
this.plans.splice(index, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
85
backoffice/src/stripe/stripe.controller.ts
Normal file
85
backoffice/src/stripe/stripe.controller.ts
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
import { Controller, Get, Post, Body, Param } from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiBody, ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { StripeService } from './stripe.service';
|
||||
|
||||
class CreateCustomerDto {
|
||||
email: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
class CreateSubscriptionDto {
|
||||
customerId: string;
|
||||
priceId: string;
|
||||
}
|
||||
|
||||
class CreateCheckoutDto {
|
||||
customerId: string;
|
||||
priceId: string;
|
||||
successUrl: string;
|
||||
cancelUrl: string;
|
||||
}
|
||||
|
||||
class BillingPortalDto {
|
||||
customerId: string;
|
||||
returnUrl: string;
|
||||
}
|
||||
|
||||
class CancelSubscriptionDto {
|
||||
subscriptionId: string;
|
||||
}
|
||||
|
||||
@ApiTags('Stripe')
|
||||
@ApiBearerAuth()
|
||||
@Controller('stripe')
|
||||
export class StripeController {
|
||||
constructor(private readonly stripeService: StripeService) { }
|
||||
|
||||
@Post('customers')
|
||||
@ApiOperation({ summary: 'Create a Stripe customer' })
|
||||
@ApiBody({ type: CreateCustomerDto })
|
||||
async createCustomer(@Body() body: CreateCustomerDto) {
|
||||
return this.stripeService.createCustomer(body.email, body.name);
|
||||
}
|
||||
|
||||
@Post('subscriptions')
|
||||
@ApiOperation({ summary: 'Create a subscription' })
|
||||
@ApiBody({ type: CreateSubscriptionDto })
|
||||
async createSubscription(@Body() body: CreateSubscriptionDto) {
|
||||
return this.stripeService.createSubscription(body.customerId, body.priceId);
|
||||
}
|
||||
|
||||
@Get('subscriptions/:customerId')
|
||||
@ApiOperation({ summary: 'List subscriptions for a customer' })
|
||||
async listSubscriptions(@Param('customerId') customerId: string) {
|
||||
return this.stripeService.listSubscriptions(customerId);
|
||||
}
|
||||
|
||||
@Post('subscriptions/cancel')
|
||||
@ApiOperation({ summary: 'Cancel a subscription' })
|
||||
@ApiBody({ type: CancelSubscriptionDto })
|
||||
async cancelSubscription(@Body() body: CancelSubscriptionDto) {
|
||||
return this.stripeService.cancelSubscription(body.subscriptionId);
|
||||
}
|
||||
|
||||
@Post('checkout')
|
||||
@ApiOperation({ summary: 'Create a checkout session' })
|
||||
@ApiBody({ type: CreateCheckoutDto })
|
||||
async createCheckoutSession(@Body() body: CreateCheckoutDto) {
|
||||
return this.stripeService.createCheckoutSession(
|
||||
body.customerId,
|
||||
body.priceId,
|
||||
body.successUrl,
|
||||
body.cancelUrl,
|
||||
);
|
||||
}
|
||||
|
||||
@Post('billing-portal')
|
||||
@ApiOperation({ summary: 'Create a billing portal session' })
|
||||
@ApiBody({ type: BillingPortalDto })
|
||||
async createBillingPortalSession(@Body() body: BillingPortalDto) {
|
||||
return this.stripeService.createBillingPortalSession(
|
||||
body.customerId,
|
||||
body.returnUrl,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,14 @@
|
|||
import { Module, Global } from '@nestjs/common';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { StripeService } from './stripe.service';
|
||||
import { StripeController } from './stripe.controller';
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
imports: [ConfigModule],
|
||||
controllers: [StripeController],
|
||||
providers: [StripeService],
|
||||
exports: [StripeService],
|
||||
})
|
||||
export class StripeModule {}
|
||||
export class StripeModule { }
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue