|
|
@@ -0,0 +1,136 @@
|
|
|
+import { Repository, Like } from 'typeorm'
|
|
|
+import { FastifyInstance } from 'fastify'
|
|
|
+import { TeamMembers } from '../entities/team-members.entity'
|
|
|
+import { PaginationResponse } from '../dto/common.dto'
|
|
|
+import { CreateTeamMembersBody, UpdateTeamMembersBody, ListTeamMembersQuery } from '../dto/team-members.dto'
|
|
|
+import { UserService } from './user.service'
|
|
|
+import { UserRole } from '../entities/user.entity'
|
|
|
+
|
|
|
+export class TeamMembersService {
|
|
|
+ private teamMembersRepository: Repository<TeamMembers>
|
|
|
+ private userService: UserService
|
|
|
+
|
|
|
+ constructor(app: FastifyInstance) {
|
|
|
+ this.teamMembersRepository = app.dataSource.getRepository(TeamMembers)
|
|
|
+ this.userService = new UserService(app)
|
|
|
+ }
|
|
|
+
|
|
|
+ async create(data: CreateTeamMembersBody, creatorId: number): Promise<TeamMembers> {
|
|
|
+ const { password, teamUserId, ...teamMemberData } = data
|
|
|
+
|
|
|
+ const existingUser = await this.userService.findByName(teamMemberData.name)
|
|
|
+ if (existingUser) {
|
|
|
+ throw new Error('团队成员已存在')
|
|
|
+ }
|
|
|
+
|
|
|
+ const userPassword = password || 'password123'
|
|
|
+ const parentId = teamUserId || creatorId
|
|
|
+ const createdUser = await this.userService.create(userPassword, teamMemberData.name, UserRole.USER, parentId)
|
|
|
+
|
|
|
+ const teamMember = this.teamMembersRepository.create({
|
|
|
+ ...teamMemberData,
|
|
|
+ userId: createdUser.id
|
|
|
+ })
|
|
|
+ return this.teamMembersRepository.save(teamMember)
|
|
|
+ }
|
|
|
+
|
|
|
+ async findById(id: number): Promise<TeamMembers> {
|
|
|
+ return this.teamMembersRepository.findOneOrFail({ where: { id } })
|
|
|
+ }
|
|
|
+
|
|
|
+ async findAll(query: ListTeamMembersQuery): Promise<PaginationResponse<TeamMembers>> {
|
|
|
+ const { page, size, name, teamId, userId } = query
|
|
|
+
|
|
|
+ const where: any = {}
|
|
|
+
|
|
|
+ if (name) {
|
|
|
+ where.name = Like(`%${name}%`)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (teamId) {
|
|
|
+ where.teamId = teamId
|
|
|
+ }
|
|
|
+
|
|
|
+ if (userId) {
|
|
|
+ where.userId = userId
|
|
|
+ }
|
|
|
+
|
|
|
+ const [members, total] = await this.teamMembersRepository.findAndCount({
|
|
|
+ where,
|
|
|
+ skip: (Number(page) || 0) * (Number(size) || 20),
|
|
|
+ take: Number(size) || 20,
|
|
|
+ order: { createdAt: 'DESC' }
|
|
|
+ })
|
|
|
+
|
|
|
+ return {
|
|
|
+ content: members,
|
|
|
+ metadata: {
|
|
|
+ total: Number(total),
|
|
|
+ page: Number(page) || 0,
|
|
|
+ size: Number(size) || 20
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async update(data: UpdateTeamMembersBody): Promise<TeamMembers> {
|
|
|
+ const { id, ...updateData } = data
|
|
|
+ await this.teamMembersRepository.update(id, updateData)
|
|
|
+ return this.findById(id)
|
|
|
+ }
|
|
|
+
|
|
|
+ async delete(id: number): Promise<void> {
|
|
|
+ await this.teamMembersRepository.delete(id)
|
|
|
+ }
|
|
|
+
|
|
|
+ async updateRevenue(id: number, amount: number, type: 'total' | 'today'): Promise<TeamMembers> {
|
|
|
+ const member = await this.findById(id)
|
|
|
+
|
|
|
+ if (type === 'total') {
|
|
|
+ member.totalRevenue = Number(member.totalRevenue) + amount
|
|
|
+ } else {
|
|
|
+ member.todayRevenue = Number(member.todayRevenue) + amount
|
|
|
+ }
|
|
|
+
|
|
|
+ return this.teamMembersRepository.save(member)
|
|
|
+ }
|
|
|
+
|
|
|
+ async resetTodayRevenue(): Promise<void> {
|
|
|
+ await this.teamMembersRepository.update({}, { todayRevenue: 0 })
|
|
|
+ }
|
|
|
+
|
|
|
+ async getStatistics(): Promise<{
|
|
|
+ totalMembers: number
|
|
|
+ totalRevenue: number
|
|
|
+ todayRevenue: number
|
|
|
+ topMembers: Array<{ id: number; name: string; totalRevenue: number; todayRevenue: number }>
|
|
|
+ }> {
|
|
|
+ const members = await this.teamMembersRepository.find({
|
|
|
+ select: ['id', 'name', 'totalRevenue', 'todayRevenue']
|
|
|
+ })
|
|
|
+
|
|
|
+ const statistics = {
|
|
|
+ totalMembers: members.length,
|
|
|
+ totalRevenue: 0,
|
|
|
+ todayRevenue: 0,
|
|
|
+ topMembers: [] as Array<{ id: number; name: string; totalRevenue: number; todayRevenue: number }>
|
|
|
+ }
|
|
|
+
|
|
|
+ members.forEach(member => {
|
|
|
+ statistics.totalRevenue += Number(member.totalRevenue)
|
|
|
+ statistics.todayRevenue += Number(member.todayRevenue)
|
|
|
+ })
|
|
|
+
|
|
|
+ // 获取收入前5的成员
|
|
|
+ statistics.topMembers = members
|
|
|
+ .sort((a, b) => Number(b.totalRevenue) - Number(a.totalRevenue))
|
|
|
+ .slice(0, 5)
|
|
|
+ .map(member => ({
|
|
|
+ id: member.id,
|
|
|
+ name: member.name,
|
|
|
+ totalRevenue: Number(member.totalRevenue),
|
|
|
+ todayRevenue: Number(member.todayRevenue)
|
|
|
+ }))
|
|
|
+
|
|
|
+ return statistics
|
|
|
+ }
|
|
|
+}
|