Assist_Design/apps/bff/src/modules/subscriptions/subscriptions.controller.ts

210 lines
6.3 KiB
TypeScript

import {
Controller,
Get,
Post,
Param,
Query,
Body,
Request,
ParseIntPipe,
BadRequestException,
UsePipes,
} from "@nestjs/common";
import { SubscriptionsService } from "./subscriptions.service";
import { SimManagementService } from "./sim-management.service";
import {
Subscription,
SubscriptionList,
subscriptionQuerySchema,
type SubscriptionQuery,
} from "@customer-portal/domain/subscriptions";
import {
InvoiceList,
invoiceListQuerySchema,
type InvoiceListQuery,
} from "@customer-portal/domain/billing";
import {
simTopupRequestSchema,
simChangePlanRequestSchema,
simCancelRequestSchema,
simFeaturesRequestSchema,
type SimTopupRequest,
type SimChangePlanRequest,
type SimCancelRequest,
type SimFeaturesRequest,
} from "@customer-portal/domain/sim";
import { ZodValidationPipe } from "@bff/core/validation";
import type { RequestWithUser } from "@bff/modules/auth/auth.types";
@Controller("subscriptions")
export class SubscriptionsController {
constructor(
private readonly subscriptionsService: SubscriptionsService,
private readonly simManagementService: SimManagementService
) {}
@Get()
@UsePipes(new ZodValidationPipe(subscriptionQuerySchema))
async getSubscriptions(
@Request() req: RequestWithUser,
@Query() query: SubscriptionQuery
): Promise<SubscriptionList | Subscription[]> {
if (query.status) {
return this.subscriptionsService.getSubscriptionsByStatus(req.user.id, query.status);
}
return this.subscriptionsService.getSubscriptions(req.user.id);
}
@Get("active")
async getActiveSubscriptions(@Request() req: RequestWithUser): Promise<Subscription[]> {
return this.subscriptionsService.getActiveSubscriptions(req.user.id);
}
@Get("stats")
async getSubscriptionStats(@Request() req: RequestWithUser): Promise<{
total: number;
active: number;
completed: number;
cancelled: number;
}> {
return this.subscriptionsService.getSubscriptionStats(req.user.id);
}
@Get(":id")
async getSubscriptionById(
@Request() req: RequestWithUser,
@Param("id", ParseIntPipe) subscriptionId: number
): Promise<Subscription> {
if (subscriptionId <= 0) {
throw new BadRequestException("Subscription ID must be a positive number");
}
return this.subscriptionsService.getSubscriptionById(req.user.id, subscriptionId);
}
@Get(":id/invoices")
@UsePipes(new ZodValidationPipe(invoiceListQuerySchema))
async getSubscriptionInvoices(
@Request() req: RequestWithUser,
@Param("id", ParseIntPipe) subscriptionId: number,
@Query() query: InvoiceListQuery
): Promise<InvoiceList> {
if (subscriptionId <= 0) {
throw new BadRequestException("Subscription ID must be a positive number");
}
return this.subscriptionsService.getSubscriptionInvoices(req.user.id, subscriptionId, query);
}
// ==================== SIM Management Endpoints ====================
@Get(":id/sim/debug")
async debugSimSubscription(
@Request() req: RequestWithUser,
@Param("id", ParseIntPipe) subscriptionId: number
): Promise<Record<string, unknown>> {
return this.simManagementService.debugSimSubscription(req.user.id, subscriptionId);
}
@Get(":id/sim")
async getSimInfo(
@Request() req: RequestWithUser,
@Param("id", ParseIntPipe) subscriptionId: number
) {
return this.simManagementService.getSimInfo(req.user.id, subscriptionId);
}
@Get(":id/sim/details")
async getSimDetails(
@Request() req: RequestWithUser,
@Param("id", ParseIntPipe) subscriptionId: number
) {
return this.simManagementService.getSimDetails(req.user.id, subscriptionId);
}
@Get(":id/sim/usage")
async getSimUsage(
@Request() req: RequestWithUser,
@Param("id", ParseIntPipe) subscriptionId: number
) {
return this.simManagementService.getSimUsage(req.user.id, subscriptionId);
}
@Get(":id/sim/top-up-history")
async getSimTopUpHistory(
@Request() req: RequestWithUser,
@Param("id", ParseIntPipe) subscriptionId: number,
@Query("fromDate") fromDate: string,
@Query("toDate") toDate: string
) {
if (!fromDate || !toDate) {
throw new BadRequestException("fromDate and toDate are required");
}
return this.simManagementService.getSimTopUpHistory(req.user.id, subscriptionId, {
fromDate,
toDate,
});
}
@Post(":id/sim/top-up")
@UsePipes(new ZodValidationPipe(simTopupRequestSchema))
async topUpSim(
@Request() req: RequestWithUser,
@Param("id", ParseIntPipe) subscriptionId: number,
@Body() body: SimTopupRequest
) {
await this.simManagementService.topUpSim(req.user.id, subscriptionId, body);
return { success: true, message: "SIM top-up completed successfully" };
}
@Post(":id/sim/change-plan")
@UsePipes(new ZodValidationPipe(simChangePlanRequestSchema))
async changeSimPlan(
@Request() req: RequestWithUser,
@Param("id", ParseIntPipe) subscriptionId: number,
@Body() body: SimChangePlanRequest
) {
const result = await this.simManagementService.changeSimPlan(req.user.id, subscriptionId, body);
return {
success: true,
message: "SIM plan change completed successfully",
...result,
};
}
@Post(":id/sim/cancel")
@UsePipes(new ZodValidationPipe(simCancelRequestSchema))
async cancelSim(
@Request() req: RequestWithUser,
@Param("id", ParseIntPipe) subscriptionId: number,
@Body() body: SimCancelRequest
) {
await this.simManagementService.cancelSim(req.user.id, subscriptionId, body);
return { success: true, message: "SIM cancellation completed successfully" };
}
@Post(":id/sim/reissue-esim")
async reissueEsimProfile(
@Request() req: RequestWithUser,
@Param("id", ParseIntPipe) subscriptionId: number,
@Body() body: { newEid?: string } = {}
) {
await this.simManagementService.reissueEsimProfile(req.user.id, subscriptionId, body.newEid);
return { success: true, message: "eSIM profile reissue completed successfully" };
}
@Post(":id/sim/features")
@UsePipes(new ZodValidationPipe(simFeaturesRequestSchema))
async updateSimFeatures(
@Request() req: RequestWithUser,
@Param("id", ParseIntPipe) subscriptionId: number,
@Body() body: SimFeaturesRequest
) {
await this.simManagementService.updateSimFeatures(req.user.id, subscriptionId, body);
return { success: true, message: "SIM features updated successfully" };
}
}