import { Body, Controller, Get, Param, Post, Request, Sse, UsePipes, UseGuards, type MessageEvent, } from "@nestjs/common"; import { Throttle, ThrottlerGuard } from "@nestjs/throttler"; import { OrderOrchestrator } from "./services/order-orchestrator.service"; import type { RequestWithUser } from "@bff/modules/auth/auth.types"; import { Logger } from "nestjs-pino"; import { ZodValidationPipe } from "@customer-portal/validation/nestjs"; import { createOrderRequestSchema, orderCreateResponseSchema, sfOrderIdParamSchema, type CreateOrderRequest, type SfOrderIdParam, } from "@customer-portal/domain/orders"; import { apiSuccessResponseSchema } from "@customer-portal/domain/common"; import { Observable } from "rxjs"; import { OrderEventsService } from "./services/order-events.service"; import { SalesforceReadThrottleGuard } from "@bff/integrations/salesforce/guards/salesforce-read-throttle.guard"; import { SalesforceWriteThrottleGuard } from "@bff/integrations/salesforce/guards/salesforce-write-throttle.guard"; @Controller("orders") @UseGuards(ThrottlerGuard) export class OrdersController { constructor( private orderOrchestrator: OrderOrchestrator, private readonly orderEvents: OrderEventsService, private readonly logger: Logger ) {} private readonly createOrderResponseSchema = apiSuccessResponseSchema(orderCreateResponseSchema); @Post() @UseGuards(SalesforceWriteThrottleGuard) @Throttle({ default: { limit: 5, ttl: 60 } }) // 5 order creations per minute @UsePipes(new ZodValidationPipe(createOrderRequestSchema)) async create(@Request() req: RequestWithUser, @Body() body: CreateOrderRequest) { this.logger.log( { userId: req.user?.id, orderType: body.orderType, skuCount: body.skus?.length || 0, }, "Order creation request received" ); try { const result = await this.orderOrchestrator.createOrder(req.user.id, body); return this.createOrderResponseSchema.parse({ success: true, data: result }); } catch (error) { this.logger.error( { error: error instanceof Error ? error.message : String(error), userId: req.user?.id, orderType: body.orderType, }, "Order creation failed" ); throw error; } } @Get("user") @UseGuards(SalesforceReadThrottleGuard) async getUserOrders(@Request() req: RequestWithUser) { return this.orderOrchestrator.getOrdersForUser(req.user.id); } @Get(":sfOrderId") @UsePipes(new ZodValidationPipe(sfOrderIdParamSchema)) @UseGuards(SalesforceReadThrottleGuard) async get(@Request() req: RequestWithUser, @Param() params: SfOrderIdParam) { return this.orderOrchestrator.getOrder(params.sfOrderId); } @Sse(":sfOrderId/events") @UsePipes(new ZodValidationPipe(sfOrderIdParamSchema)) streamOrderUpdates(@Param() params: SfOrderIdParam): Observable { return this.orderEvents.subscribe(params.sfOrderId); } // Note: Order provisioning has been moved to SalesforceProvisioningController // This controller now focuses only on customer-facing order operations }