Files
negareh-api/src/modules/admin/providers/admin.service.ts
T
2026-02-26 09:29:16 +03:30

152 lines
4.4 KiB
TypeScript

import { BadRequestException, ConflictException, Injectable, NotFoundException } from '@nestjs/common';
import { Admin } from '../entities/admin.entity';
import { Role } from '../../roles/entities/role.entity';
import { EntityManager } from '@mikro-orm/postgresql';
import { UpdateAdminDto } from '../dto/update-admin.dto';
import { CreateAdminDto } from '../dto/create-admin.dto';
import { AdminRepository } from '../repositories/admin.repository';
import { RoleRepository } from 'src/modules/roles/respository/role.repository';
import { PermissionEnum } from 'src/common/enums/permission.enum';
@Injectable()
export class AdminService {
constructor(
private readonly adminRepository: AdminRepository,
private readonly roleRepository: RoleRepository,
private readonly em: EntityManager,
) { }
async create(dto: CreateAdminDto) {
const { phone, firstName, lastName, roleId } = dto;
const currentAdmin = await this.adminRepository.findOne({
phone,
}, { filters: { notDeleted: false } });
if (currentAdmin && !currentAdmin.deletedAt) {
throw new BadRequestException('This phone number is already used');
}
if (currentAdmin && currentAdmin.deletedAt) {
currentAdmin.deletedAt = undefined;
await this.em.flush();
return currentAdmin;
}
const role = await this.roleRepository.findOne({ id: roleId });
if (!role) {
throw new BadRequestException('Role not found');
}
const admin = this.em.create(Admin, {
phone,
firstName,
lastName,
role,
});
await this.em.persistAndFlush(admin);
return admin;
}
async findByPhone(phone: string): Promise<Admin | null> {
return this.adminRepository.findOne({ phone });
}
async findById(adminId: string): Promise<Admin | null> {
const admin = await this.adminRepository.findOne(
{ id: adminId },
{ populate: ['role', 'role.permissions'] },
);
return admin;
}
async findAll(): Promise<Admin[]> {
return this.adminRepository.find({}, { populate: ['role'] });
}
async update(adminId: string, dto: UpdateAdminDto): Promise<Admin> {
const admin = await this.adminRepository.findOne(
{ id: adminId },
{ populate: ['role'] },
);
if (!admin) {
throw new NotFoundException('Admin not found');
}
const { roleId, ...rest } = dto;
// Update scalar fields (firstName, lastName, phone)
if (rest.firstName !== undefined) {
admin.firstName = rest.firstName;
}
if (rest.lastName !== undefined) {
admin.lastName = rest.lastName;
}
if (rest.phone !== undefined && rest.phone !== admin.phone) {
const exists = await this.adminRepository.findOne({ phone: rest.phone,id: { $ne: adminId } });
if (exists) {
throw new ConflictException('This Phone Number is already taken');
}
admin.phone = rest.phone;
}
// Update role if roleId is provided
if (roleId) {
const role = await this.em.findOne(Role, { id: roleId, isSystem: false });
if (!role) {
throw new NotFoundException('Role not found');
}
admin.role = role
}
await this.em.persistAndFlush(admin);
return admin;
}
async softDelete(adminId: string): Promise<void> {
const admin = await this.adminRepository.findOne({ id: adminId });
if (!admin) {
throw new NotFoundException('Admin role not found');
}
admin.deletedAt = new Date()
return this.em.flush();
}
async findOrFail(adminId: string) {
const admin = await this.findById(adminId)
if (!admin) {
throw new BadRequestException("Admin not found")
}
return admin
}
async findByIds(adminIds: string[]) {
const admins = await this.adminRepository.find({
id: { $in: adminIds }
})
if (adminIds.length !== admins.length) {
throw new BadRequestException("some admins not found")
}
return admins
}
async hasPermissions(adminId: string, permissionNames: PermissionEnum[]): Promise<PermissionEnum[]> {
if (permissionNames.length === 0) return []
const admin = await this.adminRepository.findOne(
{ id: adminId },
{ populate: ['role', 'role.permissions'] },
)
if (!admin?.role?.permissions) return []
const adminPermissionNames = new Set(
admin.role.permissions.getItems().map((p) => p.name),
)
return permissionNames.filter((name) => adminPermissionNames.has(name))
}
}