|
@@ -35,33 +35,33 @@ export class IncomeRecordsService {
|
|
|
|
|
|
|
|
async findAll(query: ListIncomeRecordsQuery): Promise<PaginationResponse<IncomeRecords>> {
|
|
async findAll(query: ListIncomeRecordsQuery): Promise<PaginationResponse<IncomeRecords>> {
|
|
|
const { page, size, teamId, userId, agentName, incomeType, orderType, payChannel, startDate, endDate } = query
|
|
const { page, size, teamId, userId, agentName, incomeType, orderType, payChannel, startDate, endDate } = query
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
const where: any = {}
|
|
const where: any = {}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (teamId) {
|
|
if (teamId) {
|
|
|
where.teamId = teamId
|
|
where.teamId = teamId
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (userId) {
|
|
if (userId) {
|
|
|
where.userId = userId
|
|
where.userId = userId
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (agentName) {
|
|
if (agentName) {
|
|
|
where.agentName = Like(`%${agentName}%`)
|
|
where.agentName = Like(`%${agentName}%`)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (incomeType) {
|
|
if (incomeType) {
|
|
|
where.incomeType = incomeType
|
|
where.incomeType = incomeType
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (orderType) {
|
|
if (orderType) {
|
|
|
where.orderType = orderType
|
|
where.orderType = orderType
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (payChannel) {
|
|
if (payChannel) {
|
|
|
where.payChannel = Like(`%${payChannel}%`)
|
|
where.payChannel = Like(`%${payChannel}%`)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (startDate && endDate) {
|
|
if (startDate && endDate) {
|
|
|
where.createdAt = Between(new Date(startDate), new Date(endDate))
|
|
where.createdAt = Between(new Date(startDate), new Date(endDate))
|
|
|
}
|
|
}
|
|
@@ -97,50 +97,116 @@ export class IncomeRecordsService {
|
|
|
await this.incomeRecordsRepository.delete(id)
|
|
await this.incomeRecordsRepository.delete(id)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- async getStatistics(startDate?: string, endDate?: string): Promise<{
|
|
|
|
|
- totalAmount: number
|
|
|
|
|
- totalCount: number
|
|
|
|
|
- byType: Record<IncomeType, { amount: number; count: number }>
|
|
|
|
|
- byOrderType: Record<OrderType, { amount: number; count: number }>
|
|
|
|
|
|
|
+ async getStatistics(
|
|
|
|
|
+ startDate?: string,
|
|
|
|
|
+ endDate?: string,
|
|
|
|
|
+ teamId?: number,
|
|
|
|
|
+ userId?: number
|
|
|
|
|
+ ): Promise<{
|
|
|
|
|
+ dates: string[]
|
|
|
|
|
+ teams: Array<{
|
|
|
|
|
+ teamId: number
|
|
|
|
|
+ data: number[]
|
|
|
|
|
+ tip: number[]
|
|
|
|
|
+ commission: number[]
|
|
|
|
|
+ }>
|
|
|
|
|
+ total: number[]
|
|
|
|
|
+ totalTip: number[]
|
|
|
|
|
+ totalCommission: number[]
|
|
|
}> {
|
|
}> {
|
|
|
- const where: any = {}
|
|
|
|
|
-
|
|
|
|
|
- if (startDate && endDate) {
|
|
|
|
|
- where.createdAt = Between(new Date(startDate), new Date(endDate))
|
|
|
|
|
|
|
+ if (!startDate || !endDate) {
|
|
|
|
|
+ throw new Error('开始时间和结束时间都是必须的')
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const records = await this.incomeRecordsRepository.find({
|
|
|
|
|
- where,
|
|
|
|
|
- select: ['incomeAmount', 'incomeType', 'orderType']
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ const start = new Date(startDate)
|
|
|
|
|
+ const end = new Date(endDate)
|
|
|
|
|
|
|
|
- const statistics = {
|
|
|
|
|
- totalAmount: 0,
|
|
|
|
|
- totalCount: records.length,
|
|
|
|
|
- byType: {} as Record<IncomeType, { amount: number; count: number }>,
|
|
|
|
|
- byOrderType: {} as Record<OrderType, { amount: number; count: number }>
|
|
|
|
|
|
|
+ // 生成日期数组
|
|
|
|
|
+ const dates: string[] = []
|
|
|
|
|
+ const currentDate = new Date(start)
|
|
|
|
|
+ while (currentDate <= end) {
|
|
|
|
|
+ dates.push(currentDate.toISOString().split('T')[0])
|
|
|
|
|
+ currentDate.setDate(currentDate.getDate() + 1)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 初始化统计对象
|
|
|
|
|
- Object.values(IncomeType).forEach(type => {
|
|
|
|
|
- statistics.byType[type] = { amount: 0, count: 0 }
|
|
|
|
|
|
|
+ // 设置时间范围为整天
|
|
|
|
|
+ start.setHours(0, 0, 0, 0)
|
|
|
|
|
+ end.setHours(23, 59, 59, 999)
|
|
|
|
|
+
|
|
|
|
|
+ const teamStats = await this.incomeRecordsRepository
|
|
|
|
|
+ .createQueryBuilder('record')
|
|
|
|
|
+ .select([
|
|
|
|
|
+ 'record.teamId as teamId',
|
|
|
|
|
+ "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'
|
|
|
|
|
+ ])
|
|
|
|
|
+ .where('record.createdAt >= :start', { start })
|
|
|
|
|
+ .andWhere('record.createdAt <= :end', { end })
|
|
|
|
|
+ .andWhere('record.delFlag = :delFlag', { delFlag: false })
|
|
|
|
|
+ .setParameter('tipType', IncomeType.TIP)
|
|
|
|
|
+ .setParameter('commissionType', IncomeType.COMMISSION)
|
|
|
|
|
+ .andWhere(teamId ? 'record.teamId = :teamId' : '1=1', { teamId })
|
|
|
|
|
+ .andWhere(userId ? 'record.userId = :userId' : '1=1', { userId })
|
|
|
|
|
+ .groupBy('record.teamId')
|
|
|
|
|
+ .addGroupBy("DATE_FORMAT(CONVERT_TZ(record.createdAt, '+00:00', '+08:00'), '%Y-%m-%d')")
|
|
|
|
|
+ .orderBy('record.teamId', 'ASC')
|
|
|
|
|
+ .addOrderBy('date', 'ASC')
|
|
|
|
|
+ .getRawMany()
|
|
|
|
|
+
|
|
|
|
|
+ // 按团队分组处理数据
|
|
|
|
|
+ const teamMap = new Map<
|
|
|
|
|
+ number,
|
|
|
|
|
+ {
|
|
|
|
|
+ teamId: number
|
|
|
|
|
+ data: number[]
|
|
|
|
|
+ tip: number[]
|
|
|
|
|
+ commission: number[]
|
|
|
|
|
+ }
|
|
|
|
|
+ >()
|
|
|
|
|
+
|
|
|
|
|
+ // 初始化每个团队的数据数组
|
|
|
|
|
+ teamStats.forEach(stat => {
|
|
|
|
|
+ if (!teamMap.has(stat.teamId)) {
|
|
|
|
|
+ teamMap.set(stat.teamId, {
|
|
|
|
|
+ teamId: stat.teamId,
|
|
|
|
|
+ data: dates.map(() => 0),
|
|
|
|
|
+ tip: dates.map(() => 0),
|
|
|
|
|
+ commission: dates.map(() => 0)
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const dateIndex = dates.indexOf(stat.date)
|
|
|
|
|
+ if (dateIndex !== -1) {
|
|
|
|
|
+ const team = teamMap.get(stat.teamId)!
|
|
|
|
|
+ team.data[dateIndex] = Number(stat.totalAmount)
|
|
|
|
|
+ team.tip[dateIndex] = Number(stat.tipAmount)
|
|
|
|
|
+ team.commission[dateIndex] = Number(stat.commissionAmount)
|
|
|
|
|
+ }
|
|
|
})
|
|
})
|
|
|
-
|
|
|
|
|
- Object.values(OrderType).forEach(type => {
|
|
|
|
|
- statistics.byOrderType[type] = { amount: 0, count: 0 }
|
|
|
|
|
|
|
+
|
|
|
|
|
+ const teams = Array.from(teamMap.values())
|
|
|
|
|
+
|
|
|
|
|
+ // 计算每天的总收入
|
|
|
|
|
+ const total = dates.map((_, index) => {
|
|
|
|
|
+ return teams.reduce((sum, team) => sum + team.data[index], 0)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ const totalTip = dates.map((_, index) => {
|
|
|
|
|
+ return teams.reduce((sum, team) => sum + team.tip[index], 0)
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- // 计算统计数据
|
|
|
|
|
- records.forEach(record => {
|
|
|
|
|
- statistics.totalAmount += Number(record.incomeAmount)
|
|
|
|
|
-
|
|
|
|
|
- statistics.byType[record.incomeType].amount += Number(record.incomeAmount)
|
|
|
|
|
- statistics.byType[record.incomeType].count += 1
|
|
|
|
|
-
|
|
|
|
|
- statistics.byOrderType[record.orderType].amount += Number(record.incomeAmount)
|
|
|
|
|
- statistics.byOrderType[record.orderType].count += 1
|
|
|
|
|
|
|
+ const totalCommission = dates.map((_, index) => {
|
|
|
|
|
+ return teams.reduce((sum, team) => sum + team.commission[index], 0)
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- return statistics
|
|
|
|
|
|
|
+ return {
|
|
|
|
|
+ dates,
|
|
|
|
|
+ teams,
|
|
|
|
|
+ total,
|
|
|
|
|
+ totalTip,
|
|
|
|
|
+ totalCommission
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|