| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- // oms/src/controllers/messageRecordController.ts
- import { Request, Response } from "express";
- import { isObjectIdOrHexString } from "mongoose";
- import { MessageRecord, IMessageRecord } from "../models/messageRecordModel";
- import { MessageRecordService } from "../services/messageRecordService";
- class MessageRecordController {
- private messageRecordService: MessageRecordService;
- constructor() {
- this.messageRecordService = new MessageRecordService();
- }
- /**
- * @route POST /api/message-record
- * @desc Creates a new message record
- * @access Private
- */
- public createRecord = async (req: Request, res: Response): Promise<Response> => {
- try {
- const newRecord = new MessageRecord(req.body);
- await newRecord.save();
- return res.status(201).json({ success: true, data: newRecord });
- } catch (error: any) {
- console.error("Error creating message record:", error);
- return res.status(500).json({ success: false, message: "Server error", error: error.message });
- }
- };
- /**
- * @route GET /api/message-records
- * @desc Retrieves all message records with pagination and optional filters
- * @access Private
- */
- public getPaginatedRecords = async (req: Request, res: Response): Promise<Response> => {
- const { page = 1, limit = 30, uid, activityName, templateName, strategyName, status, startDate, endDate } = req.query;
- const pageNum = parseInt(page as string, 10);
- const limitNum = parseInt(limit as string, 10);
- // 动态构建查询过滤器
- const filters: any = {};
- if (uid) {
- filters.uid = uid;
- }
- if (status) {
- const statusNum = parseInt(status as string, 10);
- if (!isNaN(statusNum)) {
- filters.status = statusNum;
- }
- }
- if (activityName) {
- filters.activityName = activityName;
- }
- if (strategyName) {
- filters.strategyName = strategyName;
- }
- if (templateName) {
- filters.templateName = templateName;
- }
- // 定义所有可查询的日期字段
- const dateQueryKeys: (keyof IMessageRecord)[] = ["plannedSendAt", "actualSendAt", "deliveredAt", "openedAt", "createdAt", "updatedAt"];
- // 遍历所有日期字段,处理单个日期或日期范围
- dateQueryKeys.forEach((key) => {
- const queryValue = req.query[key as string] as string;
- if (queryValue) {
- const dates = queryValue.split(",");
- if (dates.length === 2) {
- const startDate = new Date(dates[0]);
- const endDate = new Date(dates[1]);
- // 确保日期有效
- if (!isNaN(startDate.getTime()) && !isNaN(endDate.getTime())) {
- filters[key] = {
- $gte: startDate,
- $lte: endDate,
- };
- } else {
- console.warn(`[API] Invalid date range format for ${key}: ${queryValue}. Skipping.`);
- }
- } else {
- // 如果不是范围,则按单个日期精确匹配
- const singleDate = new Date(queryValue);
- if (!isNaN(singleDate.getTime())) {
- filters[key] = singleDate;
- }
- }
- }
- });
- // 保留对原有startDate/endDate参数的兼容性,并将其应用于createdAt
- if (startDate || endDate) {
- // 确保 createdAt 过滤器不存在冲突,如果已通过范围查询设置,则跳过
- if (!filters.createdAt) {
- filters.createdAt = {};
- }
- if (startDate) {
- filters.createdAt.$gte = new Date(startDate as string);
- }
- if (endDate) {
- filters.createdAt.$lte = new Date(endDate as string);
- }
- }
- try {
- const records = await MessageRecord.find(filters)
- .sort({ createdAt: -1 })
- .skip((pageNum - 1) * limitNum)
- .limit(limitNum);
- const total = await MessageRecord.countDocuments(filters);
- return res.status(200).json({
- success: true,
- data: records,
- pagination: {
- total,
- page: pageNum,
- limit: limitNum,
- totalPages: Math.ceil(total / limitNum),
- },
- });
- } catch (error: any) {
- console.error("Error fetching paginated records:", error);
- return res.status(500).json({ success: false, message: "Server error", error: error.message });
- }
- };
- /**
- * @route GET /api/message-records/user/:uid
- * @desc Retrieves message records by user UID
- * @access Private
- */
- public getRecordsByUid = async (req: Request, res: Response): Promise<Response> => {
- try {
- const records = await MessageRecord.find({ uid: req.params.uid }).sort({ createdAt: -1 });
- if (!records || records.length === 0) {
- return res.status(404).json({ success: false, message: "No records found for this user" });
- }
- return res.status(200).json({ success: true, data: records });
- } catch (error: any) {
- console.error("Error fetching records by user UID:", error);
- return res.status(500).json({ success: false, message: "Server error", error: error.message });
- }
- };
- /**
- * @route GET /api/message-record/:id
- * @desc Retrieves a single message record by ID
- * @access Private
- */
- public getRecordById = async (req: Request, res: Response): Promise<Response> => {
- try {
- // 检查 id 是否是有效的 ObjectId 格式
- if (!isObjectIdOrHexString(req.params.id)) {
- return res.status(400).json({ success: false, message: "Invalid record ID" });
- }
- const record = await MessageRecord.findById(req.params.id);
- if (!record) {
- return res.status(404).json({ success: false, message: "Message record not found" });
- }
- return res.status(200).json({ success: true, data: record });
- } catch (error: any) {
- console.error("Error fetching message record by ID:", error);
- return res.status(500).json({ success: false, message: "Server error", error: error.message });
- }
- };
- /**
- * @route PUT /api/message-record/:id
- * @desc Updates the status of a message record
- * @access Private
- */
- public updateRecord = async (req: Request, res: Response): Promise<Response> => {
- try {
- // 检查 id 是否是有效的 ObjectId 格式
- if (!isObjectIdOrHexString(req.params.id)) {
- return res.status(400).json({ success: false, message: "Invalid record ID" });
- }
- const updatedRecord = await MessageRecord.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true });
- if (!updatedRecord) {
- return res.status(404).json({ success: false, message: "Message record not found" });
- }
- return res.status(200).json({ success: true, data: updatedRecord });
- } catch (error: any) {
- console.error("Error updating message record:", error);
- return res.status(500).json({ success: false, message: "Server error", error: error.message });
- }
- };
- /**
- * @route GET /api/message/statistics/overall
- * @desc Retrieves overall message push statistics
- * @access Private
- */
- public getOverallStatistics = async (req: Request, res: Response): Promise<Response> => {
- try {
- const stats = await this.messageRecordService.getOverallStatistics();
- return res.status(200).json({ success: true, data: stats });
- } catch (error: any) {
- console.error("Error fetching overall statistics:", error);
- return res.status(500).json({ success: false, message: "Server error", error: error.message });
- }
- };
- /**
- * @route GET /api/message/statistics/by-activity
- * @desc Retrieves message push statistics grouped by activity
- * @access Private
- */
- public getStatisticsByActivity = async (req: Request, res: Response): Promise<Response> => {
- try {
- const stats = await this.messageRecordService.getStatisticsByActivity();
- return res.status(200).json({ success: true, data: stats });
- } catch (error: any) {
- console.error("Error fetching statistics by activity:", error);
- return res.status(500).json({ success: false, message: "Server error", error: error.message });
- }
- };
- /**
- * @route GET /api/message/statistics/by-strategy
- * @desc Retrieves message push statistics grouped by strategy
- * @access Private
- */
- public getStatisticsByStrategy = async (req: Request, res: Response): Promise<Response> => {
- try {
- const stats = await this.messageRecordService.getStatisticsByStrategy();
- return res.status(200).json({ success: true, data: stats });
- } catch (error: any) {
- console.error("Error fetching statistics by strategy:", error);
- return res.status(500).json({ success: false, message: "Server error", error: error.message });
- }
- };
- /**
- * @route GET /api/message/statistics/by-template
- * @desc Retrieves message push statistics grouped by template
- * @access Private
- */
- public getStatisticsByTemplate = async (req: Request, res: Response): Promise<Response> => {
- try {
- const stats = await this.messageRecordService.getStatisticsByTemplate();
- return res.status(200).json({ success: true, data: stats });
- } catch (error: any) {
- console.error("Error fetching statistics by strategy:", error);
- return res.status(500).json({ success: false, message: "Server error", error: error.message });
- }
- };
- /**
- * @route GET /api/message/statistics/daily-trends
- * @desc Retrieves daily sent trend statistics
- * @access Private
- */
- public getDailySentTrends = async (req: Request, res: Response): Promise<Response> => {
- try {
- const stats = await this.messageRecordService.getDailySentTrends();
- return res.status(200).json({ success: true, data: stats });
- } catch (error: any) {
- console.error("Error fetching daily sent trends:", error);
- return res.status(500).json({ success: false, message: "Server error", error: error.message });
- }
- };
- }
- export default new MessageRecordController();
|