import { ConflictException, Injectable, NotFoundException } from '@nestjs/common'; import { InjectRepository } from '@mikro-orm/nestjs'; import { EntityRepository } from '@mikro-orm/core'; import { Admin } from '../entities/admin.entity'; import { Role } from '../../../roles/entities/role.entity'; import { Shop } from ../../..shops/entities/shop.entity'; import { EntityManager } from '@mikro-orm/postgresql'; import { CacheService } from '../../../utils/cache.service'; import { CreateMyRestaurantAdminDto } from '../dto/create-my-shop-admin.dto'; import { UpdateAdminDto } from '../dto/update-admin.dto'; import { AdminRole } from '../entities/adminRole.entity'; import { normalizePhone } from '../../../utils/phone.util'; @Injectable() export class AdminService { constructor( @InjectRepository(Admin) private readonly adminRepository: EntityRepository, @InjectRepository(AdminRole) private readonly adminRoleRepository: EntityRepository, private readonly em: EntityManager, private readonly cacheService: CacheService, ) {} async findByPhone(phone: string): Promise { const normalizedPhone = normalizePhone(phone); return this.adminRepository.findOne({ phone: normalizedPhone }); } async findById(adminId: string, restId: string): Promise { const admin = await this.adminRepository.findOne( { id: adminId, roles: { shop: { id: restId } } }, { populate: ['roles', 'roles.role'] }, ); return admin; } async findAllByRestaurantId(restId: string): Promise { return this.adminRepository.find({ roles: { shop: { id: restId } } }, { populate: ['roles', 'roles.role'] }); } async createAdminForMyRestaurant(restId: string, dto: CreateMyRestaurantAdminDto) { const { phone, firstName, lastName, roleId } = dto; const normalizedPhone = normalizePhone(phone); let admin: Admin | null = null; admin = await this.adminRepository.findOne({ phone: normalizedPhone, }); if (!admin) { admin = this.adminRepository.create({ phone: normalizedPhone, firstName, lastName, }); await this.em.persistAndFlush(admin); } const role = await this.em.findOne(Role, { id: roleId, isSystem: false }); if (!role) throw new NotFoundException('Role not found'); const shop = await this.em.findOne(Shop, { id: restId }); if (!shop) throw new NotFoundException('Shop not found'); let adminRole = await this.adminRoleRepository.findOne({ admin: admin, shop: shop, }); if (!adminRole) { adminRole = this.adminRoleRepository.create({ admin: admin, role, shop, }); } else { adminRole.role = role; } await this.em.persistAndFlush(adminRole); return admin; } async createAdminForRestaurantBySuperAdmin(restId: string, dto: CreateMyRestaurantAdminDto) { const { phone, firstName, lastName, roleId } = dto; const normalizedPhone = normalizePhone(phone); let admin: Admin | null = null; admin = await this.adminRepository.findOne({ phone: normalizedPhone, }); if (!admin) { admin = this.adminRepository.create({ phone: normalizedPhone, firstName, lastName, }); await this.em.persistAndFlush(admin); } const role = await this.em.findOne(Role, { id: roleId }); if (!role) throw new NotFoundException('Role* not found' + roleId); const shop = await this.em.findOne(Shop, { id: restId }); if (!shop) throw new NotFoundException('Shop not found'); let adminRole = await this.adminRoleRepository.findOne({ admin: admin, shop: shop, }); if (!adminRole) { adminRole = this.adminRoleRepository.create({ admin: admin, role, shop, }); } else { adminRole.role = role; } await this.em.persistAndFlush(adminRole); return admin; } async getAdminsForRestaurantBySuperAdmin(restId: string): Promise { const shop = await this.em.findOne(Shop, { id: restId }); if (!shop) throw new NotFoundException('Shop not found'); return this.adminRepository.find({ roles: { shop: shop } }, { populate: ['roles', 'roles.role'] }); } async update(adminId: string, restId: string, dto: UpdateAdminDto): Promise { const admin = await this.adminRepository.findOne( { id: adminId, roles: { shop: { id: restId } } }, { populate: ['roles', 'roles.role', 'roles.shop'] }, ); 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 normalizedPhone = normalizePhone(rest.phone); const exists = await this.adminRepository.findOne({ phone: normalizedPhone }); if (exists) { throw new ConflictException('This Phone Number is already taken'); } admin.phone = normalizedPhone; } // 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'); } // Find existing AdminRole for this admin and shop const existingAdminRole = await this.em.findOne(AdminRole, { admin: { id: adminId }, shop: { id: restId }, }); if (existingAdminRole) { // Update existing role existingAdminRole.role = role; } else { const shop = await this.em.findOne(Shop, { id: restId }); if (!shop) throw new NotFoundException('Shop not found'); // Create new AdminRole const newAdminRole = this.em.create(AdminRole, { admin, role, shop, }); admin.roles.add(newAdminRole); } } await this.em.persistAndFlush(admin); return admin; } async remove(adminId: string, restId: string): Promise { const adminRole = await this.adminRoleRepository.findOne({ admin: { id: adminId }, shop: { id: restId } }); if (!adminRole) { throw new NotFoundException('Admin role not found'); } return this.em.removeAndFlush(adminRole); } }