|
@@ -192,8 +192,17 @@ export class IncomeRecordsService {
|
|
|
throw new Error('开始时间和结束时间都是必须的')
|
|
throw new Error('开始时间和结束时间都是必须的')
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 验证日期格式
|
|
|
const start = new Date(startDate)
|
|
const start = new Date(startDate)
|
|
|
const end = new Date(endDate)
|
|
const end = new Date(endDate)
|
|
|
|
|
+
|
|
|
|
|
+ if (isNaN(start.getTime()) || isNaN(end.getTime())) {
|
|
|
|
|
+ throw new Error('日期格式不正确')
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (start > end) {
|
|
|
|
|
+ throw new Error('开始时间不能晚于结束时间')
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// 生成日期数组
|
|
// 生成日期数组
|
|
|
const dates: string[] = []
|
|
const dates: string[] = []
|
|
@@ -203,18 +212,15 @@ export class IncomeRecordsService {
|
|
|
currentDate.setDate(currentDate.getDate() + 1)
|
|
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')
|
|
.createQueryBuilder('record')
|
|
|
.select([
|
|
.select([
|
|
|
'record.agentId as agentId',
|
|
'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 })
|
|
.where('record.createdAt >= :start', { start })
|
|
|
.andWhere('record.createdAt <= :end', { end })
|
|
.andWhere('record.createdAt <= :end', { end })
|
|
@@ -222,58 +228,89 @@ export class IncomeRecordsService {
|
|
|
.andWhere('record.status = :status', { status: true })
|
|
.andWhere('record.status = :status', { status: true })
|
|
|
.setParameter('tipType', IncomeType.TIP)
|
|
.setParameter('tipType', IncomeType.TIP)
|
|
|
.setParameter('commissionType', IncomeType.COMMISSION)
|
|
.setParameter('commissionType', IncomeType.COMMISSION)
|
|
|
- .andWhere(agentId ? 'record.agentId = :agentId' : '1=1', { agentId })
|
|
|
|
|
- .andWhere(userId ? 'record.userId = :userId' : '1=1', { userId })
|
|
|
|
|
.groupBy('record.agentId')
|
|
.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')
|
|
.orderBy('record.agentId', 'ASC')
|
|
|
.addOrderBy('date', '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 => {
|
|
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) => {
|
|
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) => {
|
|
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) => {
|
|
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 {
|
|
return {
|