| 1 | import type { AccountGroup } from '@yikart/mongodb' |
| 2 | import { Injectable } from '@nestjs/common' |
| 3 | import { AppException, ResponseCode } from '@yikart/common' |
| 4 | import { AccountGroupRepository, AccountRepository, Transactional } from '@yikart/mongodb' |
| 5 | import { ChannelAccountGroupCreateDto, ChannelAccountGroupUpdateDto } from './account-group.dto' |
| 6 | |
| 7 | @Injectable() |
| 8 | export class AccountGroupService { |
| 9 | constructor( |
| 10 | private readonly accountRepository: AccountRepository, |
| 11 | private readonly accountGroupRepository: AccountGroupRepository, |
| 12 | ) {} |
| 13 | |
| 14 | async create(userId: string, data: ChannelAccountGroupCreateDto): Promise<AccountGroup> { |
| 15 | return this.accountGroupRepository.createAccountGroup({ |
| 16 | ...data, |
| 17 | userId, |
| 18 | }) |
| 19 | } |
| 20 | |
| 21 | async update(userId: string, groupId: string, data: ChannelAccountGroupUpdateDto): Promise<AccountGroup> { |
| 22 | const group = await this.getOwnedGroup(userId, groupId) |
| 23 | const updated = await this.accountGroupRepository.updateAccountGroup(group.id, data) |
| 24 | if (!updated) { |
| 25 | throw new AppException(ResponseCode.AccountGroupNotFound) |
| 26 | } |
| 27 | return { ...group, ...data } |
| 28 | } |
| 29 | |
| 30 | @Transactional() |
| 31 | async deleteMany(userId: string, groupIds: string[]): Promise<boolean> { |
| 32 | const groups = await this.accountGroupRepository.getAccountGorupListByIds(groupIds, userId) |
| 33 | const defaultGroup = await this.accountGroupRepository.getDefaultGroup(userId) |
| 34 | if (groups.some(group => group.isDefault || group.id === defaultGroup.id)) { |
| 35 | throw new AppException(ResponseCode.AccountGroupNotFound, { |
| 36 | reasonCode: 'default_group_delete_not_allowed', |
| 37 | }) |
| 38 | } |
| 39 | for (const group of groups) { |
| 40 | await this.accountRepository.updateManyToDefaultGroup(userId, group.id, defaultGroup.id) |
| 41 | } |
| 42 | return this.accountGroupRepository.deleteAccountGroup(groupIds, userId) |
| 43 | } |
| 44 | |
| 45 | async list(userId: string): Promise<AccountGroup[]> { |
| 46 | const groups = await this.accountGroupRepository.getAccountGroup(userId) |
| 47 | return groups |
| 48 | .sort((a, b) => (a.rank ?? 0) - (b.rank ?? 0)) |
| 49 | } |
| 50 | |
| 51 | @Transactional() |
| 52 | async sortAccounts(userId: string, groupId: string, list: { id: string, rank: number }[]): Promise<boolean> { |
| 53 | await this.getOwnedGroup(userId, groupId) |
| 54 | const ids = list.map(item => item.id) |
| 55 | if (new Set(ids).size !== ids.length) { |
| 56 | throw new AppException(ResponseCode.ValidationFailed) |
| 57 | } |
| 58 | |
| 59 | const accounts = await this.accountRepository.listByUserIdAndIds(userId, ids) |
| 60 | const accountMap = new Map(accounts.map(account => [account.id, account])) |
| 61 | for (const id of ids) { |
| 62 | const account = accountMap.get(id) |
| 63 | if (!account || account.groupId !== groupId) { |
| 64 | throw new AppException(ResponseCode.AccountNotFound) |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | const updated = await this.accountRepository.updateManyRankByIds(userId, groupId, list) |
| 69 | if (!updated) { |
| 70 | throw new AppException(ResponseCode.AccountNotFound) |
| 71 | } |
| 72 | return true |
| 73 | } |
| 74 | |
| 75 | async findOneById(id: string) { |
| 76 | return this.accountGroupRepository.getById(id) |
| 77 | } |
| 78 | |
| 79 | async getDefaultGroup(userId: string): Promise<AccountGroup> { |
| 80 | return this.accountGroupRepository.getDefaultGroup(userId) |
| 81 | } |
| 82 | |
| 83 | async getAccountGroup(userId: string): Promise<AccountGroup[]> { |
| 84 | return this.accountGroupRepository.getAccountGroup(userId) |
| 85 | } |
| 86 | |
| 87 | async sortRank(userId: string, list: { id: string, rank: number }[]): Promise<boolean> { |
| 88 | return this.accountGroupRepository.sortRank(userId, list) |
| 89 | } |
| 90 | |
| 91 | async getAccountGroupByName(userId: string, name: string): Promise<AccountGroup[]> { |
| 92 | return this.accountGroupRepository.getAccountGroupByName(userId, name) |
| 93 | } |
| 94 | |
| 95 | private async getOwnedGroup(userId: string, groupId: string): Promise<AccountGroup> { |
| 96 | const groups = await this.accountGroupRepository.getAccountGorupListByIds([groupId], userId) |
| 97 | const group = groups[0] |
| 98 | if (!group) { |
| 99 | throw new AppException(ResponseCode.AccountGroupNotFound) |
| 100 | } |
| 101 | return group |
| 102 | } |
| 103 | } |
| 104 |