2025-10-27 17:24:53 +09:00
|
|
|
import { Body, Controller, Get, Param, Post, Request, UsePipes, UseGuards } from "@nestjs/common";
|
|
|
|
|
import { Throttle, ThrottlerGuard } from "@nestjs/throttler";
|
2025-08-27 20:01:46 +09:00
|
|
|
import { OrderOrchestrator } from "./services/order-orchestrator.service";
|
2025-09-17 18:43:43 +09:00
|
|
|
import type { RequestWithUser } from "@bff/modules/auth/auth.types";
|
2025-08-27 10:54:05 +09:00
|
|
|
import { Logger } from "nestjs-pino";
|
2025-11-04 13:28:36 +09:00
|
|
|
import { ZodValidationPipe } from "@customer-portal/validation/nestjs";
|
2025-10-02 17:19:39 +09:00
|
|
|
import {
|
|
|
|
|
createOrderRequestSchema,
|
2025-10-22 11:33:23 +09:00
|
|
|
orderCreateResponseSchema,
|
2025-10-02 17:19:39 +09:00
|
|
|
sfOrderIdParamSchema,
|
|
|
|
|
type CreateOrderRequest,
|
|
|
|
|
type SfOrderIdParam,
|
2025-10-03 15:09:19 +09:00
|
|
|
} from "@customer-portal/domain/orders";
|
2025-10-20 13:53:35 +09:00
|
|
|
import { apiSuccessResponseSchema } from "@customer-portal/domain/common";
|
2025-08-20 18:02:50 +09:00
|
|
|
|
2025-08-21 15:24:40 +09:00
|
|
|
@Controller("orders")
|
2025-10-27 17:24:53 +09:00
|
|
|
@UseGuards(ThrottlerGuard)
|
2025-08-20 18:02:50 +09:00
|
|
|
export class OrdersController {
|
2025-08-27 10:54:05 +09:00
|
|
|
constructor(
|
2025-08-27 20:01:46 +09:00
|
|
|
private orderOrchestrator: OrderOrchestrator,
|
2025-08-27 10:54:05 +09:00
|
|
|
private readonly logger: Logger
|
|
|
|
|
) {}
|
2025-08-20 18:02:50 +09:00
|
|
|
|
2025-10-22 11:33:23 +09:00
|
|
|
private readonly createOrderResponseSchema = apiSuccessResponseSchema(orderCreateResponseSchema);
|
2025-10-20 13:53:35 +09:00
|
|
|
|
2025-08-23 17:24:37 +09:00
|
|
|
@Post()
|
2025-10-29 15:54:45 +09:00
|
|
|
@Throttle({ default: { limit: 5, ttl: 60 } }) // 5 order creations per minute
|
2025-09-24 18:00:49 +09:00
|
|
|
@UsePipes(new ZodValidationPipe(createOrderRequestSchema))
|
|
|
|
|
async create(@Request() req: RequestWithUser, @Body() body: CreateOrderRequest) {
|
2025-08-28 16:57:57 +09:00
|
|
|
this.logger.log(
|
|
|
|
|
{
|
|
|
|
|
userId: req.user?.id,
|
2025-08-29 13:26:57 +09:00
|
|
|
orderType: body.orderType,
|
|
|
|
|
skuCount: body.skus?.length || 0,
|
2025-08-28 16:57:57 +09:00
|
|
|
},
|
|
|
|
|
"Order creation request received"
|
|
|
|
|
);
|
|
|
|
|
|
2025-08-27 20:01:46 +09:00
|
|
|
try {
|
2025-10-20 13:53:35 +09:00
|
|
|
const result = await this.orderOrchestrator.createOrder(req.user.id, body);
|
|
|
|
|
return this.createOrderResponseSchema.parse({ success: true, data: result });
|
2025-08-27 20:01:46 +09:00
|
|
|
} catch (error) {
|
2025-08-28 16:57:57 +09:00
|
|
|
this.logger.error(
|
|
|
|
|
{
|
|
|
|
|
error: error instanceof Error ? error.message : String(error),
|
|
|
|
|
userId: req.user?.id,
|
2025-08-29 13:26:57 +09:00
|
|
|
orderType: body.orderType,
|
2025-08-28 16:57:57 +09:00
|
|
|
},
|
|
|
|
|
"Order creation failed"
|
|
|
|
|
);
|
2025-08-27 20:01:46 +09:00
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Get("user")
|
|
|
|
|
async getUserOrders(@Request() req: RequestWithUser) {
|
|
|
|
|
return this.orderOrchestrator.getOrdersForUser(req.user.id);
|
2025-08-23 17:24:37 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Get(":sfOrderId")
|
2025-10-02 17:19:39 +09:00
|
|
|
@UsePipes(new ZodValidationPipe(sfOrderIdParamSchema))
|
|
|
|
|
async get(@Request() req: RequestWithUser, @Param() params: SfOrderIdParam) {
|
|
|
|
|
return this.orderOrchestrator.getOrder(params.sfOrderId);
|
2025-08-23 17:24:37 +09:00
|
|
|
}
|
|
|
|
|
|
2025-09-02 16:09:17 +09:00
|
|
|
// Note: Order provisioning has been moved to SalesforceProvisioningController
|
|
|
|
|
// This controller now focuses only on customer-facing order operations
|
2025-08-20 18:02:50 +09:00
|
|
|
}
|