From 21ed63ca0f66dd708cbff1f48bd750b4d8e20984 Mon Sep 17 00:00:00 2001 From: hamid zarghami Date: Sun, 12 Jul 2026 19:40:03 +0330 Subject: [PATCH] dublicate excel --- .../dto/service-skill-duplicate-count.dto.ts | 6 ++++ src/services/services.controller.ts | 9 ++++++ src/services/services.service.ts | 28 ++++++++++++++++++- 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/services/dto/service-skill-duplicate-count.dto.ts diff --git a/src/services/dto/service-skill-duplicate-count.dto.ts b/src/services/dto/service-skill-duplicate-count.dto.ts new file mode 100644 index 0000000..9509c9a --- /dev/null +++ b/src/services/dto/service-skill-duplicate-count.dto.ts @@ -0,0 +1,6 @@ +import { ApiProperty } from '@nestjs/swagger'; + +export class ServiceSkillDuplicateCountDto { + @ApiProperty({ example: 3 }) + count: number; +} diff --git a/src/services/services.controller.ts b/src/services/services.controller.ts index 4255341..ff8ae97 100644 --- a/src/services/services.controller.ts +++ b/src/services/services.controller.ts @@ -36,6 +36,7 @@ import { CreateServiceSkillDto } from './dto/create-service-skill.dto'; import { CreateServiceDto } from './dto/create-service.dto'; import { ImportServiceSkillsResultDto } from './dto/import-service-skills-result.dto'; import { RemoveDuplicateServiceSkillsResultDto } from './dto/remove-duplicate-service-skills-result.dto'; +import { ServiceSkillDuplicateCountDto } from './dto/service-skill-duplicate-count.dto'; import { CreateSalonServiceDto, FindSalonServicesQueryDto, @@ -212,6 +213,14 @@ export class ServicesController { return this.servicesService.importSkillsFromExcel(serviceId, file, user); } + @Roles(UserRole.ADMIN) + @Permissions(PermissionCode.SERVICES_WRITE) + @ApiStandardOkResponse(ServiceSkillDuplicateCountDto) + @Get(':serviceId/skills/duplicates/count') + countDuplicateSkills(@Param('serviceId', ParseUUIDPipe) serviceId: string) { + return this.servicesService.countDuplicateSkills(serviceId); + } + @Roles(UserRole.ADMIN) @Permissions(PermissionCode.SERVICES_DELETE) @ApiStandardOkResponse(RemoveDuplicateServiceSkillsResultDto) diff --git a/src/services/services.service.ts b/src/services/services.service.ts index 278ab45..2bdaf0c 100644 --- a/src/services/services.service.ts +++ b/src/services/services.service.ts @@ -272,6 +272,26 @@ export class ServicesService { return { removed: duplicateIds.length }; } + async countDuplicateSkills(serviceId: string): Promise<{ count: number }> { + await this.ensureServiceExists(serviceId); + + const skills = await this.findSkills(serviceId); + const seenTitles = new Set(); + let count = 0; + + for (const skill of skills) { + const normalizedTitle = this.normalizeSkillTitle(skill.title); + if (seenTitles.has(normalizedTitle)) { + count += 1; + continue; + } + + seenTitles.add(normalizedTitle); + } + + return { count }; + } + async findSkills(serviceId: string): Promise { await this.ensureServiceExists(serviceId); return this.serviceSkillsRepository.find({ @@ -523,7 +543,13 @@ export class ServicesService { } private normalizeSkillTitle(title: string): string { - return normalizeDigits(title).trim().toLowerCase().replace(/\s+/g, ' '); + return normalizeDigits(title) + .trim() + .toLowerCase() + .replace(/[يى]/g, 'ی') + .replace(/ك/g, 'ک') + .replace(/\u200c/g, '') + .replace(/\s+/g, ' '); } private async ensureUniqueSkillTitle(