Jelajahi Sumber

增强收入记录服务,添加日期格式验证和时间范围检查,优化查询构建逻辑,确保数据统计的准确性和完整性。

wuyi 3 bulan lalu
induk
melakukan
3bb946d9e7
1 mengubah file dengan 82 tambahan dan 45 penghapusan
  1. 82 45
      src/services/income-records.service.ts

+ 82 - 45
src/services/income-records.service.ts

@@ -192,8 +192,17 @@ export class IncomeRecordsService {
       throw new Error('开始时间和结束时间都是必须的')
     }
 
+    // 验证日期格式
     const start = new Date(startDate)
     const end = new Date(endDate)
+    
+    if (isNaN(start.getTime()) || isNaN(end.getTime())) {
+      throw new Error('日期格式不正确')
+    }
+    
+    if (start > end) {
+      throw new Error('开始时间不能晚于结束时间')
+    }
 
     // 生成日期数组
     const dates: string[] = []
@@ -203,18 +212,15 @@ export class IncomeRecordsService {
       currentDate.setDate(currentDate.getDate() + 1)
     }
 
-    // 设置时间范围为整天
-    start.setHours(0, 0, 0, 0)
-    end.setHours(23, 59, 59, 999)
-
-    const agentStats = await this.incomeRecordsRepository
+    // 构建基础查询条件
+    let queryBuilder = this.incomeRecordsRepository
       .createQueryBuilder('record')
       .select([
         'record.agentId as agentId',
-        "DATE_FORMAT(CONVERT_TZ(record.createdAt, '+00:00', '+08:00'), '%Y-%m-%d') as date",
-        'CAST(SUM(CASE WHEN record.incomeType = :tipType THEN CAST(record.incomeAmount AS DECIMAL(10,5)) ELSE 0 END) AS DECIMAL(10,5)) as tipAmount',
-        'CAST(SUM(CASE WHEN record.incomeType = :commissionType THEN CAST(record.incomeAmount AS DECIMAL(10,5)) ELSE 0 END) AS DECIMAL(10,5)) as commissionAmount',
-        'CAST(SUM(CAST(record.incomeAmount AS DECIMAL(10,5))) AS DECIMAL(10,5)) as totalAmount'
+        'DATE(record.createdAt) as date',
+        'SUM(CASE WHEN record.incomeType = :tipType THEN record.incomeAmount ELSE 0 END) as tipAmount',
+        'SUM(CASE WHEN record.incomeType = :commissionType THEN record.incomeAmount ELSE 0 END) as commissionAmount',
+        'SUM(record.incomeAmount) as totalAmount'
       ])
       .where('record.createdAt >= :start', { start })
       .andWhere('record.createdAt <= :end', { end })
@@ -222,58 +228,89 @@ export class IncomeRecordsService {
       .andWhere('record.status = :status', { status: true })
       .setParameter('tipType', IncomeType.TIP)
       .setParameter('commissionType', IncomeType.COMMISSION)
-      .andWhere(agentId ? 'record.agentId = :agentId' : '1=1', { agentId })
-      .andWhere(userId ? 'record.userId = :userId' : '1=1', { userId })
       .groupBy('record.agentId')
-      .addGroupBy("DATE_FORMAT(CONVERT_TZ(record.createdAt, '+00:00', '+08:00'), '%Y-%m-%d')")
+      .addGroupBy('DATE(record.createdAt)')
       .orderBy('record.agentId', 'ASC')
       .addOrderBy('date', 'ASC')
-      .getRawMany()
-
-    // 按代理商分组处理数据
-    const agentMap = new Map<
-      number,
-      {
-        agentId: number
-        data: number[]
-        tip: number[]
-        commission: number[]
-      }
-    >()
 
-    // 初始化每个代理商的数据数组
+    // 添加可选的过滤条件
+    if (agentId) {
+      queryBuilder = queryBuilder.andWhere('record.agentId = :agentId', { agentId })
+    }
+
+    if (userId) {
+      queryBuilder = queryBuilder.andWhere('record.userId = :userId', { userId })
+    }
+
+    // 执行聚合查询
+    const agentStats = await queryBuilder.getRawMany()
+
+    // 获取所有涉及的代理商ID
+    const agentIds = [...new Set(agentStats.map(stat => stat.agentId))].sort((a, b) => a - b)
+
+    // 构建代理商数据映射
+    const agentDataMap = new Map<number, Map<string, { tip: number; commission: number; total: number }>>()
+
+    // 初始化所有代理商的数据结构
+    agentIds.forEach(id => {
+      agentDataMap.set(id, new Map())
+    })
+
+    // 填充统计数据
     agentStats.forEach(stat => {
-      if (!agentMap.has(stat.agentId)) {
-        agentMap.set(stat.agentId, {
-          agentId: stat.agentId,
-          data: dates.map(() => 0),
-          tip: dates.map(() => 0),
-          commission: dates.map(() => 0)
-        })
-      }
+      const agentId = stat.agentId
+      const date = stat.date
+      const tipAmount = Number(stat.tipAmount) || 0
+      const commissionAmount = Number(stat.commissionAmount) || 0
+      const totalAmount = Number(stat.totalAmount) || 0
+
+      const dateMap = agentDataMap.get(agentId)!
+      dateMap.set(date, {
+        tip: tipAmount,
+        commission: commissionAmount,
+        total: totalAmount
+      })
+    })
 
-      const dateIndex = dates.indexOf(stat.date)
-      if (dateIndex !== -1) {
-        const agent = agentMap.get(stat.agentId)!
-        agent.data[dateIndex] = Number(stat.totalAmount)
-        agent.tip[dateIndex] = Number(stat.tipAmount)
-        agent.commission[dateIndex] = Number(stat.commissionAmount)
+    // 构建返回数据
+    const agents: Array<{
+      agentId: number
+      data: number[]
+      tip: number[]
+      commission: number[]
+    }> = []
+
+    agentIds.forEach(agentId => {
+      const dateMap = agentDataMap.get(agentId)!
+      const agentData = {
+        agentId,
+        data: dates.map(date => {
+          const dayStats = dateMap.get(date)
+          return dayStats ? Number(dayStats.total.toFixed(5)) : 0
+        }),
+        tip: dates.map(date => {
+          const dayStats = dateMap.get(date)
+          return dayStats ? Number(dayStats.tip.toFixed(5)) : 0
+        }),
+        commission: dates.map(date => {
+          const dayStats = dateMap.get(date)
+          return dayStats ? Number(dayStats.commission.toFixed(5)) : 0
+        })
       }
+      agents.push(agentData)
     })
 
-    const agents = Array.from(agentMap.values())
-
-    // 计算每天的总收入
+    // 计算每天的总计
     const total = dates.map((_, index) => {
-      return agents.reduce((sum, agent) => sum + agent.data[index], 0)
+      return Number(agents.reduce((sum, agent) => sum + agent.data[index], 0).toFixed(5))
     })
 
     const totalTip = dates.map((_, index) => {
-      return agents.reduce((sum, agent) => sum + agent.tip[index], 0)
+      return Number(agents.reduce((sum, agent) => sum + agent.tip[index], 0).toFixed(5))
     })
 
     const totalCommission = dates.map((_, index) => {
-      return agents.reduce((sum, agent) => sum + agent.commission[index], 0)
+      return Number(agents.reduce((sum, agent) => sum + agent.commission[index], 0).toFixed(5))
     })
 
     return {