Files
makemd/server/src/api/controllers/OrderController.ts
wurenzhi 2748456d8a refactor(services): 重构服务文件结构,将服务按功能分类到不同目录
- 将服务文件按功能分类到core、ai、analytics、security等目录
- 修复logger导入路径问题,统一使用相对路径
- 更新相关文件的导入路径引用
- 添加新的批量操作组件导出文件
- 修复dashboard页面中的类型错误
- 添加dotenv依赖到package.json
2026-03-25 13:46:26 +08:00

368 lines
13 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Request, Response } from 'express';
import { logger } from '../../utils/logger';
import { ConsumerOrderService, ConsumerOrder } from '../../domains/Trade/ConsumerOrderService';
import { OrderService } from '../../services/order/OrderService';
/**
* [BIZ_OPS_01] 多平台订单 Webhook 接收器 (Order Webhook Receiver)
* @description 接收来自不同平台 (Amazon, AliExpress, Shopify, TikTok) 的订单 Webhook 推送,
* 并将其映射为系统统一的 cf_order 模型进行入库处理。
*/
export class OrderController {
/**
* 平台 Webhook 入口
* POST /api/v1/orders/webhook/:platform
*/
static async handlePlatformWebhook(req: Request, res: Response) {
const { platform } = req.params;
const payload = req.body;
const tenantId = req.headers['x-tenant-id'] as string || 'default-tenant';
const shopId = req.headers['x-shop-id'] as string || 'default-shop';
logger.info(`[OrderWebhook] Received webhook from platform: ${platform} for Tenant: ${tenantId}`);
try {
// 1. 根据不同平台解析 Payload (Mapping)
const normalizedOrder = OrderService.mapPlatformPayloadToOrder(platform as string, payload, tenantId, shopId);
if (!normalizedOrder) {
return res.status(400).json({ success: false, error: `Unsupported or invalid payload for platform: ${platform}` });
}
// 2. 调用 ConsumerOrderService 进行同步
const orderId = await ConsumerOrderService.syncPlatformOrder(normalizedOrder);
logger.info(`[OrderWebhook] Successfully synced order ${normalizedOrder.platform_order_id} to internal ID: ${orderId}`);
// 3. 返回平台要求的 200 OK
return res.json({ success: true, orderId });
} catch (err: any) {
logger.error(`[OrderWebhook] Webhook handling failed for ${platform}: ${err.message}`);
return res.status(500).json({ success: false, error: 'Internal server error' });
}
}
/**
* 手动触发同步 (API 入口)
* POST /api/v1/orders/sync
*/
static async triggerManualSync(req: Request, res: Response) {
try {
const { platform, shopId } = req.body;
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
logger.info(`[OrderSync] Manual sync triggered for Platform: ${platform}, Shop: ${shopId}`);
// 此处应调用各平台 Connector 的 supportsOrderPull 能力
// 示例Mock 拉取成功
res.json({ success: true, message: `Manual sync triggered for ${platform}` });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 获取订单统计
* GET /api/v1/orders/stats
*/
static async getStats(req: Request, res: Response) {
try {
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
const stats = await ConsumerOrderService.getOrderStats(tenantId);
res.json({ success: true, data: stats });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 创建订单
* POST /api/v1/orders
*/
static async createOrder(req: Request, res: Response) {
try {
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
const orderData = { ...req.body, tenant_id: tenantId };
const orderId = await OrderService.createOrder(orderData);
res.json({ success: true, orderId });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 获取订单详情
* GET /api/v1/orders/:id
*/
static async getOrderById(req: Request, res: Response) {
try {
const { id } = req.params;
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
const order = await OrderService.getOrderById(id as string, tenantId);
if (order) {
res.json({ success: true, data: order });
} else {
res.status(404).json({ success: false, error: 'Order not found' });
}
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 更新订单
* PUT /api/v1/orders/:id
*/
static async updateOrder(req: Request, res: Response) {
try {
const { id } = req.params;
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
await OrderService.updateOrder(id as string, tenantId, req.body);
res.json({ success: true, message: 'Order updated successfully' });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 删除订单
* DELETE /api/v1/orders/:id
*/
static async deleteOrder(req: Request, res: Response) {
try {
const { id } = req.params;
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
await OrderService.deleteOrder(id as string, tenantId);
res.json({ success: true, message: 'Order deleted successfully' });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 获取订单列表
* GET /api/v1/orders
*/
static async getOrders(req: Request, res: Response) {
try {
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
const params = {
page: parseInt(req.query.page as string) || 1,
pageSize: parseInt(req.query.pageSize as string) || 20,
status: req.query.status as string,
platform: req.query.platform as string,
startDate: req.query.startDate as string,
endDate: req.query.endDate as string,
};
const result = await OrderService.getOrders(tenantId, params);
res.json({ success: true, data: result });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 批量更新订单
* PUT /api/v1/orders/batch
*/
static async batchUpdateOrders(req: Request, res: Response) {
try {
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
const { orderIds, updates } = req.body;
const result = await OrderService.batchUpdateOrders(tenantId, orderIds, updates);
res.json({ success: true, data: result });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 订单状态流转
* POST /api/v1/orders/:id/status
*/
static async transitionOrderStatus(req: Request, res: Response) {
try {
const { id } = req.params;
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
const { status, reason } = req.body;
await OrderService.transitionOrderStatus(tenantId, id as string, status, reason);
res.json({ success: true, message: 'Order status updated successfully' });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 批量审核订单
* POST /api/v1/orders/batch/audit
*/
static async batchAuditOrders(req: Request, res: Response) {
try {
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
const { orderIds } = req.body;
const result = await OrderService.batchAuditOrders(tenantId, orderIds);
res.json({ success: true, data: result });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 批量发货
* POST /api/v1/orders/batch/ship
*/
static async batchShipOrders(req: Request, res: Response) {
try {
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
const { orderIds } = req.body;
const result = await OrderService.batchShipOrders(tenantId, orderIds);
res.json({ success: true, data: result });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 标记订单为异常
* POST /api/v1/orders/:id/exception
*/
static async markOrderAsException(req: Request, res: Response) {
try {
const { id } = req.params;
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
const { reason } = req.body;
await OrderService.markOrderAsException(tenantId, id as string, reason);
res.json({ success: true, message: 'Order marked as exception' });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 自动改派订单
* POST /api/v1/orders/:id/reroute
*/
static async autoRerouteOrder(req: Request, res: Response) {
try {
const { id } = req.params;
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
await OrderService.autoRerouteOrder(tenantId, id as string);
res.json({ success: true, message: 'Order rerouted successfully' });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 重试异常订单
* POST /api/v1/orders/:id/retry
*/
static async retryExceptionOrder(req: Request, res: Response) {
try {
const { id } = req.params;
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
await OrderService.retryExceptionOrder(tenantId, id as string);
res.json({ success: true, message: 'Order retried successfully' });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 取消订单
* POST /api/v1/orders/:id/cancel
*/
static async cancelOrder(req: Request, res: Response) {
try {
const { id } = req.params;
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
const { reason } = req.body;
await OrderService.cancelOrder(tenantId, id as string, reason);
res.json({ success: true, message: 'Order cancelled successfully' });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 申请退款
* POST /api/v1/orders/:id/refund
*/
static async requestRefund(req: Request, res: Response) {
try {
const { id } = req.params;
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
const { reason, amount } = req.body;
const refundId = await OrderService.requestRefund(tenantId, id as string, reason, amount);
res.json({ success: true, refundId });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 审批退款
* POST /api/v1/orders/refund/:id/approve
*/
static async approveRefund(req: Request, res: Response) {
try {
const { id } = req.params;
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
const { approved, note } = req.body;
await OrderService.approveRefund(tenantId, id as string, approved, note);
res.json({ success: true, message: 'Refund processed successfully' });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 申请售后
* POST /api/v1/orders/:id/after-sales
*/
static async requestAfterSales(req: Request, res: Response) {
try {
const { id } = req.params;
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
const { type, reason, items } = req.body;
const serviceId = await OrderService.requestAfterSales(tenantId, id as string, type, reason, items);
res.json({ success: true, serviceId });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 处理售后申请
* POST /api/v1/orders/after-sales/:id/process
*/
static async processAfterSales(req: Request, res: Response) {
try {
const { id } = req.params;
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
const { action, note } = req.body;
await OrderService.processAfterSales(tenantId, id as string, action, note);
res.json({ success: true, message: 'After-sales service processed successfully' });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
/**
* 完成订单
* POST /api/v1/orders/:id/complete
*/
static async completeOrder(req: Request, res: Response) {
try {
const { id } = req.params;
const { tenantId } = (req as any).traceContext || { tenantId: 'default-tenant' };
await OrderService.completeOrder(tenantId, id as string);
res.json({ success: true, message: 'Order completed successfully' });
} catch (err: any) {
res.status(500).json({ success: false, error: err.message });
}
}
}