mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-14 18:05:48 +00:00
Merge pull request #254 from SyncrowIOT/SP-1180-be-create-tag-endpoint-fore-create-list-tags
Add Tag Module with CRUD operations
This commit is contained in:
@ -318,6 +318,19 @@ export class ControllerRoute {
|
||||
'Fetches a list of all products along with their associated device details';
|
||||
};
|
||||
};
|
||||
|
||||
static TAG = class {
|
||||
public static readonly ROUTE = 'tags';
|
||||
static ACTIONS = class {
|
||||
public static readonly CREATE_TAG_SUMMARY = 'Create a new tag';
|
||||
public static readonly CREATE_TAG_DESCRIPTION =
|
||||
'Creates a new tag and assigns it to a specific project and product.';
|
||||
public static readonly GET_TAGS_BY_PROJECT_SUMMARY =
|
||||
'Get tags by project';
|
||||
public static readonly GET_TAGS_BY_PROJECT_DESCRIPTION =
|
||||
'Retrieves a list of tags associated with a specific project.';
|
||||
};
|
||||
};
|
||||
static USER = class {
|
||||
public static readonly ROUTE = '/user';
|
||||
|
||||
|
@ -3,7 +3,7 @@ import { NewTagEntity } from '../entities';
|
||||
import { DataSource, Repository } from 'typeorm';
|
||||
|
||||
@Injectable()
|
||||
export class NewTagRepository extends Repository<NewTagRepository> {
|
||||
export class NewTagRepository extends Repository<NewTagEntity> {
|
||||
constructor(private dataSource: DataSource) {
|
||||
super(NewTagEntity, dataSource.createEntityManager());
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import { PermissionModule } from './permission/permission.module';
|
||||
import { RoleModule } from './role/role.module';
|
||||
import { TermsConditionsModule } from './terms-conditions/terms-conditions.module';
|
||||
import { PrivacyPolicyModule } from './privacy-policy/privacy-policy.module';
|
||||
import { TagModule } from './tags/tags.module';
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
@ -59,6 +60,7 @@ import { PrivacyPolicyModule } from './privacy-policy/privacy-policy.module';
|
||||
RoleModule,
|
||||
TermsConditionsModule,
|
||||
PrivacyPolicyModule,
|
||||
TagModule,
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
|
1
src/tags/controllers/index.ts
Normal file
1
src/tags/controllers/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './tags.controller';
|
42
src/tags/controllers/tags.controller.ts
Normal file
42
src/tags/controllers/tags.controller.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { Body, Controller, Get, Param, Post, UseGuards } from '@nestjs/common';
|
||||
import { TagService } from '../services/tags.service';
|
||||
import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger';
|
||||
import { JwtAuthGuard } from '../../../libs/common/src/guards/jwt.auth.guard';
|
||||
import { EnableDisableStatusEnum } from '@app/common/constants/days.enum';
|
||||
import { ControllerRoute } from '@app/common/constants/controller-route';
|
||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||
import { CreateTagDto } from '../dtos/tags.dto';
|
||||
import { GetTagsParam } from '../dtos/get-tags.param';
|
||||
|
||||
@ApiTags('Tag Module')
|
||||
@Controller({
|
||||
version: EnableDisableStatusEnum.ENABLED,
|
||||
path: ControllerRoute.TAG.ROUTE,
|
||||
})
|
||||
export class TagController {
|
||||
constructor(private readonly tagService: TagService) {}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post()
|
||||
@ApiOperation({
|
||||
summary: ControllerRoute.TAG.ACTIONS.CREATE_TAG_SUMMARY,
|
||||
description: ControllerRoute.TAG.ACTIONS.CREATE_TAG_DESCRIPTION,
|
||||
})
|
||||
async createTag(@Body() dto: CreateTagDto): Promise<BaseResponseDto> {
|
||||
return this.tagService.createTag(dto);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Get('project/:projectUuid')
|
||||
@ApiOperation({
|
||||
summary: ControllerRoute.TAG.ACTIONS.GET_TAGS_BY_PROJECT_SUMMARY,
|
||||
description: ControllerRoute.TAG.ACTIONS.GET_TAGS_BY_PROJECT_DESCRIPTION,
|
||||
})
|
||||
async getTagsByProject(
|
||||
@Param() params: GetTagsParam,
|
||||
): Promise<BaseResponseDto> {
|
||||
return this.tagService.getTagsByProjectUuid(params);
|
||||
}
|
||||
}
|
11
src/tags/dtos/get-tags.param.ts
Normal file
11
src/tags/dtos/get-tags.param.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsUUID } from 'class-validator';
|
||||
|
||||
export class GetTagsParam {
|
||||
@ApiProperty({
|
||||
description: 'UUID of the Project',
|
||||
example: 'd290f1ee-6c54-4b01-90e6-d701748f0851',
|
||||
})
|
||||
@IsUUID()
|
||||
projectUuid: string;
|
||||
}
|
1
src/tags/dtos/index.ts
Normal file
1
src/tags/dtos/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './tags.dto';
|
28
src/tags/dtos/tags.dto.ts
Normal file
28
src/tags/dtos/tags.dto.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { IsNotEmpty, IsUUID, IsString } from 'class-validator';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
|
||||
export class CreateTagDto {
|
||||
@ApiProperty({
|
||||
description: 'The name of the tag',
|
||||
example: 'New Tag',
|
||||
})
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
name: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'UUID of the product associated with the tag',
|
||||
example: '550e8400-e29b-41d4-a716-446655440000',
|
||||
})
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
productUuid: string;
|
||||
|
||||
@ApiProperty({
|
||||
description: 'UUID of the project associated with the tag',
|
||||
example: '123e4567-e89b-12d3-a456-426614174000',
|
||||
})
|
||||
@IsUUID()
|
||||
@IsNotEmpty()
|
||||
projectUuid: string;
|
||||
}
|
1
src/tags/services/index.ts
Normal file
1
src/tags/services/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './tags.service';
|
91
src/tags/services/tags.service.ts
Normal file
91
src/tags/services/tags.service.ts
Normal file
@ -0,0 +1,91 @@
|
||||
import { ProductRepository } from '@app/common/modules/product/repositories';
|
||||
import { ProjectRepository } from '@app/common/modules/project/repositiories';
|
||||
import { NewTagRepository } from '@app/common/modules/tag/repositories/tag-repository';
|
||||
import {
|
||||
Injectable,
|
||||
ConflictException,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { CreateTagDto } from '../dtos/tags.dto';
|
||||
import { ProductEntity } from '@app/common/modules/product/entities';
|
||||
import { ProjectEntity } from '@app/common/modules/project/entities';
|
||||
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||
import { NewTagEntity } from '@app/common/modules/tag';
|
||||
import { GetTagsParam } from '../dtos/get-tags.param';
|
||||
|
||||
@Injectable()
|
||||
export class TagService {
|
||||
constructor(
|
||||
private readonly tagRepository: NewTagRepository,
|
||||
private readonly productRepository: ProductRepository,
|
||||
private readonly projectRepository: ProjectRepository,
|
||||
) {}
|
||||
async getTagsByProjectUuid(params: GetTagsParam): Promise<BaseResponseDto> {
|
||||
const { projectUuid } = params;
|
||||
await this.getProjectByUuid(projectUuid);
|
||||
|
||||
const tags = await this.tagRepository.find({
|
||||
where: { project: { uuid: projectUuid } },
|
||||
relations: ['product', 'project'],
|
||||
});
|
||||
|
||||
return new SuccessResponseDto({
|
||||
message: `Tags retrieved successfully for project UUID: ${projectUuid}`,
|
||||
data: tags,
|
||||
});
|
||||
}
|
||||
|
||||
async createTag(dto: CreateTagDto): Promise<BaseResponseDto> {
|
||||
const { name, productUuid, projectUuid } = dto;
|
||||
|
||||
const product = await this.getProductByUuid(productUuid);
|
||||
const project = await this.getProjectByUuid(projectUuid);
|
||||
|
||||
await this.validateTagUniqueness(name, projectUuid);
|
||||
|
||||
const tag = this.tagRepository.create({
|
||||
name,
|
||||
product,
|
||||
project,
|
||||
} as Partial<NewTagEntity>);
|
||||
|
||||
await this.tagRepository.save(tag);
|
||||
|
||||
return new SuccessResponseDto({
|
||||
message: `Tag created successfully`,
|
||||
data: tag,
|
||||
});
|
||||
}
|
||||
|
||||
private async getProductByUuid(uuid: string): Promise<ProductEntity> {
|
||||
const product = await this.productRepository.findOne({ where: { uuid } });
|
||||
if (!product) {
|
||||
throw new NotFoundException(`Product with UUID ${uuid} not found.`);
|
||||
}
|
||||
return product;
|
||||
}
|
||||
|
||||
private async getProjectByUuid(uuid: string): Promise<ProjectEntity> {
|
||||
const project = await this.projectRepository.findOne({ where: { uuid } });
|
||||
if (!project) {
|
||||
throw new NotFoundException(`Project with UUID ${uuid} not found.`);
|
||||
}
|
||||
return project;
|
||||
}
|
||||
|
||||
private async validateTagUniqueness(
|
||||
name: string,
|
||||
projectUuid: string,
|
||||
): Promise<void> {
|
||||
const existingTag = await this.tagRepository.findOne({
|
||||
where: { name, project: { uuid: projectUuid } },
|
||||
});
|
||||
|
||||
if (existingTag) {
|
||||
throw new ConflictException(
|
||||
`Tag with name "${name}" already exists in this project.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
20
src/tags/tags.module.ts
Normal file
20
src/tags/tags.module.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { TagController } from './controllers';
|
||||
import { TagService } from './services';
|
||||
import { NewTagRepository } from '@app/common/modules/tag/repositories/tag-repository';
|
||||
import { ProductRepository } from '@app/common/modules/product/repositories';
|
||||
import { ProjectRepository } from '@app/common/modules/project/repositiories';
|
||||
|
||||
@Module({
|
||||
imports: [ConfigModule],
|
||||
controllers: [TagController],
|
||||
providers: [
|
||||
TagService,
|
||||
NewTagRepository,
|
||||
ProductRepository,
|
||||
ProjectRepository,
|
||||
],
|
||||
exports: [TagService],
|
||||
})
|
||||
export class TagModule {}
|
Reference in New Issue
Block a user