diff --git a/src/modules/product/controllers/product.controller.ts b/src/modules/product/controllers/product.controller.ts index 7baf00f..812ce2d 100644 --- a/src/modules/product/controllers/product.controller.ts +++ b/src/modules/product/controllers/product.controller.ts @@ -24,6 +24,9 @@ import { UpdateCategoryDto } from '../dto/update-category.dto'; import { AttributeService } from '../providers/attribute.service'; import { CreateAttributeDto } from '../dto/create-attribute.dto'; import { UpdateAttributeDto } from '../dto/update-attribute.dto'; +import { CreateAttributeValueDto } from '../dto/create-attribute-value.dto'; +import { AttributeValueService } from '../providers/attribute-value.service'; +import { UpdateAttributeValueDto } from '../dto/update-attribute-value.dto'; @ApiTags('products') @Controller() @@ -32,6 +35,7 @@ export class productController { private readonly productService: ProductService, private readonly categoryService: CategoryService, private readonly attributeService: AttributeService, + private readonly attributeValueService: AttributeValueService, ) { } @@ -169,7 +173,7 @@ export class productController { // @UseGuards(AdminAuthGuard) @ApiBearerAuth() @Permissions(Permission.MANAGE_productS) - @ApiOperation({ summary: 'Create a new category' }) + @ApiOperation({ summary: 'Create a new attribute' }) @ApiParam({ name: 'id', required: true }) @ApiBody({ type: CreateAttributeDto }) createAttribute(@Param('id') id: string, @Body() dto: CreateAttributeDto) { @@ -190,7 +194,7 @@ export class productController { // @UseGuards(AdminAuthGuard) @ApiBearerAuth() @Permissions(Permission.MANAGE_productS) - @ApiOperation({ summary: 'Get a category by id' }) + @ApiOperation({ summary: 'Get a attribute by id' }) @ApiParam({ name: 'id', required: true }) findAttributeById(@Param('id') id: string) { return this.attributeService.findById(+id); @@ -216,4 +220,57 @@ export class productController { removeAttribute(@Param('id') id: string,) { return this.attributeService.remove(+id); } + + /*=========================== Attibute Values==========================*/ + @Post('admin/product/attribute/:id/value') + // @UseGuards(AdminAuthGuard) + @ApiBearerAuth() + @Permissions(Permission.MANAGE_productS) + @ApiOperation({ summary: 'Create a new attribute value' }) + @ApiParam({ name: 'id', required: true }) + @ApiBody({ type: CreateAttributeValueDto }) + createAttributeValue(@Param('id') id: string, @Body() dto: CreateAttributeValueDto) { + return this.attributeValueService.create(+id, dto); + } + + @Get('admin/products/attributes/:id/values') + // @UseGuards(AdminAuthGuard) + @ApiBearerAuth() + @Permissions(Permission.MANAGE_productS) + @ApiParam({ name: 'id', required: true }) + @ApiOperation({ summary: 'Get list of attribute values' }) + async findtAttributeValue(@Param('id') id: string) { + return this.attributeValueService.findAll(+id); + } + + @Get('admin/products/attributes/value/:id') + // @UseGuards(AdminAuthGuard) + @ApiBearerAuth() + @Permissions(Permission.MANAGE_productS) + @ApiOperation({ summary: 'Get a attribute value by id' }) + @ApiParam({ name: 'id', required: true }) + findAttributeValueById(@Param('id') id: string) { + return this.attributeValueService.findById(+id); + } + + @Patch('admin/products/attributes/value/:id') + // @UseGuards(AdminAuthGuard) + @ApiBearerAuth() + @Permissions(Permission.MANAGE_productS) + @ApiOperation({ summary: 'Update a attribute value' }) + @ApiParam({ name: 'id', required: true }) + @ApiBody({ type: UpdateAttributeValueDto }) + updateAttributeValue(@Param('id') id: string, @Body() dto: UpdateAttributeValueDto) { + return this.attributeValueService.update(+id, dto); + } + + @Delete('admin/products/attributes/value/:id') + // @UseGuards(AdminAuthGuard) + @ApiBearerAuth() + @Permissions(Permission.MANAGE_productS) + @ApiOperation({ summary: 'Delete (soft) a attribute value' }) + @ApiParam({ name: 'id', required: true }) + removeAttributeValue(@Param('id') id: string,) { + return this.attributeValueService.remove(+id); + } } diff --git a/src/modules/product/dto/create-attribute-value.dto.ts b/src/modules/product/dto/create-attribute-value.dto.ts new file mode 100644 index 0000000..451101f --- /dev/null +++ b/src/modules/product/dto/create-attribute-value.dto.ts @@ -0,0 +1,17 @@ +import { IsString, IsOptional, IsInt, Min } from 'class-validator'; +import { ApiPropertyOptional, ApiProperty } from '@nestjs/swagger'; +import { Type } from 'class-transformer'; + +export class CreateAttributeValueDto { + @IsString() + @ApiProperty({ example: 'سلفون' }) + value: string; + + + @IsOptional() + @IsInt() + @Min(0) + @Type(() => Number) + @ApiPropertyOptional({ example: 1 }) + order?: number; +} diff --git a/src/modules/product/dto/update-attribute-value.dto.ts b/src/modules/product/dto/update-attribute-value.dto.ts new file mode 100644 index 0000000..cec18f4 --- /dev/null +++ b/src/modules/product/dto/update-attribute-value.dto.ts @@ -0,0 +1,5 @@ +import { PartialType } from '@nestjs/swagger'; +import { CreateAttributeValueDto } from './create-attribute-value.dto'; + +export class UpdateAttributeValueDto extends + PartialType(CreateAttributeValueDto) { } diff --git a/src/modules/product/entities/attribute-value.entity.ts b/src/modules/product/entities/attribute-value.entity.ts index 1f2dddc..4a287fd 100644 --- a/src/modules/product/entities/attribute-value.entity.ts +++ b/src/modules/product/entities/attribute-value.entity.ts @@ -1,8 +1,9 @@ -import { Entity, Property, ManyToOne, PrimaryKey } from '@mikro-orm/core'; +import { Entity, Property, ManyToOne, PrimaryKey, Unique } from '@mikro-orm/core'; import { BaseEntity } from '../../../common/entities/base.entity'; // import { Attribute } from './attribute.entity'; @Entity({ tableName: 'attribute_values' }) +@Unique({ properties: ['value', 'attributeId'] }) export class AttributeValue extends BaseEntity { @PrimaryKey({ autoincrement: true, type: 'bigint' }) id: bigint; diff --git a/src/modules/product/entities/attribute.entity.ts b/src/modules/product/entities/attribute.entity.ts index 47930ab..985a1c6 100644 --- a/src/modules/product/entities/attribute.entity.ts +++ b/src/modules/product/entities/attribute.entity.ts @@ -15,7 +15,7 @@ export class Attribute extends BaseEntity { children?: Attribute[] @PrimaryKey({ type: 'bigint', autoincrement: true }) - id: number; + id: bigint; @Property() name: string; diff --git a/src/modules/product/product.module.ts b/src/modules/product/product.module.ts index 1ce43a0..89b5b83 100644 --- a/src/modules/product/product.module.ts +++ b/src/modules/product/product.module.ts @@ -14,6 +14,8 @@ import { CategoryRepository } from './repositories/category.repository'; import { CategoryService } from './providers/category.service'; import { AttributeRepository } from './repositories/attribute.repository'; import { AttributeService } from './providers/attribute.service'; +import { AttributeValueRepository } from './repositories/attribute-value.repository'; +import { AttributeValueService } from './providers/attribute-value.service'; @Module({ imports: [ @@ -25,7 +27,10 @@ import { AttributeService } from './providers/attribute.service'; controllers: [productController,], providers: [ProductService, ProductRepository, CategoryRepository, CategoryService, - AttributeRepository, AttributeService], + AttributeRepository, AttributeService, + AttributeValueRepository, + AttributeValueService + ], exports: [ProductRepository, CategoryRepository, CategoryService, AttributeRepository, AttributeService], diff --git a/src/modules/product/providers/attribute-value.service.ts b/src/modules/product/providers/attribute-value.service.ts new file mode 100644 index 0000000..8c4976c --- /dev/null +++ b/src/modules/product/providers/attribute-value.service.ts @@ -0,0 +1,78 @@ +import { BadGatewayException, Injectable, NotFoundException } from '@nestjs/common'; +import { EntityManager } from '@mikro-orm/postgresql'; +import { RequiredEntityData } from '@mikro-orm/core'; +import { AttributeValueRepository } from '../repositories/attribute-value.repository'; +import { AttributeRepository } from '../repositories/attribute.repository'; +import { AttributeValue } from '../entities/attribute-value.entity'; +import { CreateAttributeValueDto } from '../dto/create-attribute-value.dto'; +import { UpdateAttributeValueDto } from '../dto/update-attribute-value.dto'; + +@Injectable() +export class AttributeValueService { + + constructor( + private readonly attributeValueRepository: AttributeValueRepository, + private readonly attributeRepository: AttributeRepository, + private readonly em: EntityManager, + ) { } + + async create(attributeId: number, dto: CreateAttributeValueDto) { + + const attribute = await this.attributeRepository.findOne({ id: attributeId }) + if (!attribute) { + throw new BadGatewayException('attribute not found') + } + + const data: RequiredEntityData = { + attributeId: attribute.id, + value: dto.value, + order: dto.order, + }; + + const attributeValue = this.attributeValueRepository.create(data) + + await this.em.persistAndFlush(attributeValue) + + return attributeValue + + } + + async update(attributeValueId: number, dto: UpdateAttributeValueDto) { + + const attributeValue = await this.attributeValueRepository.findOne({ id: attributeValueId }) + + if (!attributeValue) { + throw new NotFoundException('Attribute value not found'); + } + + this.attributeValueRepository.assign(attributeValue, dto) + + this.em.persistAndFlush(attributeValue) + + return attributeValue + + } + + findAll(attributeId: number) { + return this.attributeValueRepository.find({ attributeId }); + } + + async findById(attributeValueId: number): Promise { + const attributeValue = await this.attributeValueRepository.findOne({ id: attributeValueId }); + + if (!attributeValue) throw new NotFoundException('Attribute value not found'); + return attributeValue; + } + + async remove(id: number): Promise { + const attributeValue = await this.findById(id); + if (!attributeValue) { + throw new NotFoundException('attribute value not found'); + } + + attributeValue.deletedAt = new Date(); + return await this.em.persistAndFlush(attributeValue); + + } + +} diff --git a/src/modules/product/repositories/attribute-value.repository.ts b/src/modules/product/repositories/attribute-value.repository.ts new file mode 100644 index 0000000..63e4c22 --- /dev/null +++ b/src/modules/product/repositories/attribute-value.repository.ts @@ -0,0 +1,11 @@ +import { Injectable } from '@nestjs/common'; +import { EntityManager, EntityRepository } from '@mikro-orm/postgresql'; +import { AttributeValue } from '../entities/attribute-value.entity'; + + +@Injectable() +export class AttributeValueRepository extends EntityRepository { + constructor(readonly em: EntityManager) { + super(em, AttributeValue); + } +}