From 682b973329219f02fdfed0de340fad9507da710d Mon Sep 17 00:00:00 2001 From: ilham Date: Mon, 6 Dec 2021 00:07:22 +0700 Subject: [PATCH] add: create crud product --- .../create-categories-product.dto.ts | 6 ++ .../update-categories-product.dto.ts | 6 ++ src/product/dto/create-product.dto.ts | 15 +++ .../create-sub-categories-product.dto.ts | 7 ++ .../update-sub-categories-product.dto.ts | 6 ++ ...y.entity.ts => product-category.entity.ts} | 2 +- ...ity.ts => product-history-price.entity.ts} | 0 ...tity.ts => product-sub-category.entity.ts} | 2 +- src/product/entities/product.entity.ts | 5 +- src/product/product-categories.service.ts | 100 ++++++++++++++++++ src/product/product-sub-categories.service.ts | 100 ++++++++++++++++++ src/product/product.controller.spec.ts | 20 ++++ src/product/product.controller.ts | 60 +++++++++++ src/product/product.module.ts | 10 ++ src/product/product.service.spec.ts | 18 ++++ src/product/product.service.ts | 51 +++++++++ 16 files changed, 404 insertions(+), 4 deletions(-) create mode 100644 src/product/dto/categories/create-categories-product.dto.ts create mode 100644 src/product/dto/categories/update-categories-product.dto.ts create mode 100644 src/product/dto/create-product.dto.ts create mode 100644 src/product/dto/sub-categories/create-sub-categories-product.dto.ts create mode 100644 src/product/dto/sub-categories/update-sub-categories-product.dto.ts rename src/product/entities/{productCategory.entity.ts => product-category.entity.ts} (87%) rename src/product/entities/{productHistoryPrice.entity.ts => product-history-price.entity.ts} (100%) rename src/product/entities/{productSubCategory.entity.ts => product-sub-category.entity.ts} (88%) create mode 100644 src/product/product-categories.service.ts create mode 100644 src/product/product-sub-categories.service.ts create mode 100644 src/product/product.controller.spec.ts create mode 100644 src/product/product.controller.ts create mode 100644 src/product/product.module.ts create mode 100644 src/product/product.service.spec.ts create mode 100644 src/product/product.service.ts diff --git a/src/product/dto/categories/create-categories-product.dto.ts b/src/product/dto/categories/create-categories-product.dto.ts new file mode 100644 index 0000000..e878820 --- /dev/null +++ b/src/product/dto/categories/create-categories-product.dto.ts @@ -0,0 +1,6 @@ +import { IsNotEmpty, IsUUID } from 'class-validator'; + +export class CreateCategoriesProductDto { + @IsNotEmpty() + name: string; +} diff --git a/src/product/dto/categories/update-categories-product.dto.ts b/src/product/dto/categories/update-categories-product.dto.ts new file mode 100644 index 0000000..fa2ba52 --- /dev/null +++ b/src/product/dto/categories/update-categories-product.dto.ts @@ -0,0 +1,6 @@ +import { PartialType } from '@nestjs/mapped-types'; +import { CreateCategoriesProductDto } from './create-categories-product.dto'; + +export class UpdateCategoriesProductDto extends PartialType( + CreateCategoriesProductDto, +) {} diff --git a/src/product/dto/create-product.dto.ts b/src/product/dto/create-product.dto.ts new file mode 100644 index 0000000..ed442af --- /dev/null +++ b/src/product/dto/create-product.dto.ts @@ -0,0 +1,15 @@ +import { IsNotEmpty, IsUUID } from 'class-validator'; + +export class CreateProductDto { + @IsNotEmpty() + name: string; + + @IsNotEmpty() + code: string; + + @IsNotEmpty() + status: string; + + @IsUUID() + subCategoriesId: string; +} diff --git a/src/product/dto/sub-categories/create-sub-categories-product.dto.ts b/src/product/dto/sub-categories/create-sub-categories-product.dto.ts new file mode 100644 index 0000000..6fb097d --- /dev/null +++ b/src/product/dto/sub-categories/create-sub-categories-product.dto.ts @@ -0,0 +1,7 @@ +import { IsNotEmpty, IsUUID } from 'class-validator'; +import { CreateCategoriesProductDto } from '../categories/create-categories-product.dto'; + +export class CreateSubCategoriesProductDto extends CreateCategoriesProductDto { + @IsUUID() + categoryId: string; +} diff --git a/src/product/dto/sub-categories/update-sub-categories-product.dto.ts b/src/product/dto/sub-categories/update-sub-categories-product.dto.ts new file mode 100644 index 0000000..f290ee2 --- /dev/null +++ b/src/product/dto/sub-categories/update-sub-categories-product.dto.ts @@ -0,0 +1,6 @@ +import { PartialType } from '@nestjs/mapped-types'; +import { CreateSubCategoriesProductDto } from '../sub-categories/create-sub-categories-product.dto'; + +export class UpdateSubCategoriesProductDto extends PartialType( + CreateSubCategoriesProductDto, +) {} diff --git a/src/product/entities/productCategory.entity.ts b/src/product/entities/product-category.entity.ts similarity index 87% rename from src/product/entities/productCategory.entity.ts rename to src/product/entities/product-category.entity.ts index 65e385c..86da379 100644 --- a/src/product/entities/productCategory.entity.ts +++ b/src/product/entities/product-category.entity.ts @@ -8,7 +8,7 @@ import { CreateDateColumn, OneToMany, } from 'typeorm'; -import { ProductSubCategories } from './productSubCategory.entity'; +import { ProductSubCategories } from './product-sub-category.entity'; import { BaseModel } from '../../config/basemodel.entity'; @Entity() diff --git a/src/product/entities/productHistoryPrice.entity.ts b/src/product/entities/product-history-price.entity.ts similarity index 100% rename from src/product/entities/productHistoryPrice.entity.ts rename to src/product/entities/product-history-price.entity.ts diff --git a/src/product/entities/productSubCategory.entity.ts b/src/product/entities/product-sub-category.entity.ts similarity index 88% rename from src/product/entities/productSubCategory.entity.ts rename to src/product/entities/product-sub-category.entity.ts index 4221d1a..ff50c6b 100644 --- a/src/product/entities/productSubCategory.entity.ts +++ b/src/product/entities/product-sub-category.entity.ts @@ -8,7 +8,7 @@ import { CreateDateColumn, ManyToOne, } from 'typeorm'; -import { ProductCategories } from './productCategory.entity'; +import { ProductCategories } from './product-category.entity'; import { BaseModel } from '../../config/basemodel.entity'; @Entity() diff --git a/src/product/entities/product.entity.ts b/src/product/entities/product.entity.ts index 51d0279..78b9696 100644 --- a/src/product/entities/product.entity.ts +++ b/src/product/entities/product.entity.ts @@ -7,8 +7,9 @@ import { VersionColumn, CreateDateColumn, OneToMany, + ManyToOne, } from 'typeorm'; -import { ProductSubCategories } from './productSubCategory.entity'; +import { ProductSubCategories } from './product-sub-category.entity'; import { BaseModel } from '../../config/basemodel.entity'; @Entity() @@ -25,7 +26,7 @@ export class Product extends BaseModel{ @Column() status: string; - @OneToMany( + @ManyToOne( () => ProductSubCategories, (subCategories) => subCategories.category, ) diff --git a/src/product/product-categories.service.ts b/src/product/product-categories.service.ts new file mode 100644 index 0000000..081a411 --- /dev/null +++ b/src/product/product-categories.service.ts @@ -0,0 +1,100 @@ +import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; +import { EntityNotFoundError, Repository } from 'typeorm'; +import { ProductCategories } from './entities/product-category.entity'; +import { InjectRepository } from '@nestjs/typeorm'; +import { CreateCategoriesProductDto } from './dto/categories/create-categories-product.dto'; +import { UpdateCategoriesProductDto } from './dto/categories/update-categories-product.dto'; + +@Injectable() +export class ProductCategoriesService { + constructor( + @InjectRepository(ProductCategories) + private productCategoriesRepository: Repository, + ) {} + + async create(CreateCategoriesProductDto: CreateCategoriesProductDto) { + const result = await this.productCategoriesRepository.insert( + CreateCategoriesProductDto, + ); + + return this.productCategoriesRepository.findOneOrFail( + result.identifiers[0].id, + ); + } + + findAll(page) { + return this.productCategoriesRepository.findAndCount({ + skip: page * 10, + take: 10, + order: { + version: 'DESC', + }, + }); + } + + async findOne(id: string) { + try { + return await this.productCategoriesRepository.findOneOrFail(id); + } catch (e) { + if (e instanceof EntityNotFoundError) { + throw new HttpException( + { + statusCode: HttpStatus.NOT_FOUND, + error: 'Data not found', + }, + HttpStatus.NOT_FOUND, + ); + } else { + throw e; + } + } + } + + async update( + id: string, + updateCategoriesProductDto: UpdateCategoriesProductDto, + ) { + try { + await this.productCategoriesRepository.findOneOrFail(id); + } catch (e) { + if (e instanceof EntityNotFoundError) { + throw new HttpException( + { + statusCode: HttpStatus.NOT_FOUND, + error: 'Data not found', + }, + HttpStatus.NOT_FOUND, + ); + } else { + throw e; + } + } + + const result = await this.productCategoriesRepository.update( + id, + updateCategoriesProductDto, + ); + + return this.productCategoriesRepository.findOneOrFail(id); + } + + async remove(id: string) { + try { + await this.productCategoriesRepository.findOneOrFail(id); + } catch (e) { + if (e instanceof EntityNotFoundError) { + throw new HttpException( + { + statusCode: HttpStatus.NOT_FOUND, + error: 'Data not found', + }, + HttpStatus.NOT_FOUND, + ); + } else { + throw e; + } + } + + await this.productCategoriesRepository.delete(id); + } +} diff --git a/src/product/product-sub-categories.service.ts b/src/product/product-sub-categories.service.ts new file mode 100644 index 0000000..6674eb0 --- /dev/null +++ b/src/product/product-sub-categories.service.ts @@ -0,0 +1,100 @@ +import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; +import { EntityNotFoundError, Repository } from 'typeorm'; +import { ProductSubCategories } from './entities/product-sub-category.entity'; +import { InjectRepository } from '@nestjs/typeorm'; +import { CreateSubCategoriesProductDto } from './dto/sub-categories/create-sub-categories-product.dto'; +import { UpdateSubCategoriesProductDto } from './dto/sub-categories/update-sub-categories-product.dto'; + +@Injectable() +export class ProductSubCategoriesService { + constructor( + @InjectRepository(ProductSubCategories) + private productSubCategoriesRepository: Repository, + ) {} + + async create(CreateCategoriesProductDto: CreateSubCategoriesProductDto) { + const result = await this.productSubCategoriesRepository.insert( + CreateCategoriesProductDto, + ); + + return this.productSubCategoriesRepository.findOneOrFail( + result.identifiers[0].id, + ); + } + + findAll(page) { + return this.productSubCategoriesRepository.findAndCount({ + skip: page * 10, + take: 10, + order: { + version: 'DESC', + }, + }); + } + + async findOne(id: string) { + try { + return await this.productSubCategoriesRepository.findOneOrFail(id); + } catch (e) { + if (e instanceof EntityNotFoundError) { + throw new HttpException( + { + statusCode: HttpStatus.NOT_FOUND, + error: 'Data not found', + }, + HttpStatus.NOT_FOUND, + ); + } else { + throw e; + } + } + } + + async update( + id: string, + updateCategoriesProductDto: UpdateSubCategoriesProductDto, + ) { + try { + await this.productSubCategoriesRepository.findOneOrFail(id); + } catch (e) { + if (e instanceof EntityNotFoundError) { + throw new HttpException( + { + statusCode: HttpStatus.NOT_FOUND, + error: 'Data not found', + }, + HttpStatus.NOT_FOUND, + ); + } else { + throw e; + } + } + + const result = await this.productSubCategoriesRepository.update( + id, + updateCategoriesProductDto, + ); + + return this.productSubCategoriesRepository.findOneOrFail(id); + } + + async remove(id: string) { + try { + await this.productSubCategoriesRepository.findOneOrFail(id); + } catch (e) { + if (e instanceof EntityNotFoundError) { + throw new HttpException( + { + statusCode: HttpStatus.NOT_FOUND, + error: 'Data not found', + }, + HttpStatus.NOT_FOUND, + ); + } else { + throw e; + } + } + + await this.productSubCategoriesRepository.delete(id); + } +} diff --git a/src/product/product.controller.spec.ts b/src/product/product.controller.spec.ts new file mode 100644 index 0000000..237e396 --- /dev/null +++ b/src/product/product.controller.spec.ts @@ -0,0 +1,20 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { ProductController } from './product.controller'; +import { ProductService } from './product.service'; + +describe('ProductController', () => { + let controller: ProductController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [ProductController], + providers: [ProductService], + }).compile(); + + controller = module.get(ProductController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/product/product.controller.ts b/src/product/product.controller.ts new file mode 100644 index 0000000..b00e6b2 --- /dev/null +++ b/src/product/product.controller.ts @@ -0,0 +1,60 @@ +import { + Controller, + Get, + Post, + Body, + Put, + Param, + Delete, + ParseUUIDPipe, + HttpStatus, Query, +} from '@nestjs/common'; +import { ProductService } from './product.service'; +import { ProductCategoriesService } from './product-categories.service'; +import { CreateCategoriesProductDto } from './dto/categories/create-categories-product.dto'; + +@Controller({ + path: 'product', + version: '1', +}) +export class ProductController { + constructor( + private readonly productService: ProductService, + private readonly productCategoriesService: ProductCategoriesService, + ) {} + + @Post('categories') + async createCategories( + @Body() createCategoriesProductDto: CreateCategoriesProductDto, + ) { + return { + data: await this.productCategoriesService.create( + createCategoriesProductDto, + ), + statusCode: HttpStatus.CREATED, + message: 'success', + }; + } + + @Get() + async findAll(@Query('page') page: number) { + const [data, count] = await this.productService.findAll(page); + + return { + data, + count, + statusCode: HttpStatus.OK, + message: 'success', + }; + } + + @Get(':id') + async findOne(@Param('id', ParseUUIDPipe) id: string) { + return { + data: await this.productService.findOne(id), + statusCode: HttpStatus.OK, + message: 'success', + }; + } + +} diff --git a/src/product/product.module.ts b/src/product/product.module.ts new file mode 100644 index 0000000..58e4c5a --- /dev/null +++ b/src/product/product.module.ts @@ -0,0 +1,10 @@ +import { Module } from '@nestjs/common'; +import { ProductService } from './product.service'; +import { ProductController } from './product.controller'; +import { ProductCategoriesService } from './product-categories.service'; + +@Module({ + controllers: [ProductController], + providers: [ProductService, ProductCategoriesService], +}) +export class ProductModule {} diff --git a/src/product/product.service.spec.ts b/src/product/product.service.spec.ts new file mode 100644 index 0000000..5b2a8f2 --- /dev/null +++ b/src/product/product.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { ProductService } from './product.service'; + +describe('ProductService', () => { + let service: ProductService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ProductService], + }).compile(); + + service = module.get(ProductService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/product/product.service.ts b/src/product/product.service.ts new file mode 100644 index 0000000..3b05d59 --- /dev/null +++ b/src/product/product.service.ts @@ -0,0 +1,51 @@ +import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; +import { EntityNotFoundError, Repository } from 'typeorm'; +import { Product } from './entities/product.entity'; +import { ProductCategories } from './entities/product-category.entity'; +import { ProductSubCategories } from './entities/product-sub-category.entity'; +import { InjectRepository } from '@nestjs/typeorm'; +import { CreateProductDto } from '../product/dto/create-product.dto'; +import { CreateCategoriesProductDto } from './dto/categories/create-categories-product.dto'; +import { CreateSubCategoriesProductDto } from './dto/sub-categories/create-sub-categories-product.dto'; + +@Injectable() +export class ProductService { + constructor( + @InjectRepository(Product) + private productRepository: Repository, + ) {} + + async create(createProductDto: CreateProductDto) { + const result = await this.productRepository.insert(createProductDto); + + return this.productRepository.findOneOrFail(result.identifiers[0].id); + } + + findAll(page) { + return this.productRepository.findAndCount({ + skip: page * 10, + take: 10, + order: { + version: 'DESC', + }, + }); + } + + async findOne(id: string) { + try { + return await this.productRepository.findOneOrFail(id); + } catch (e) { + if (e instanceof EntityNotFoundError) { + throw new HttpException( + { + statusCode: HttpStatus.NOT_FOUND, + error: 'Data not found', + }, + HttpStatus.NOT_FOUND, + ); + } else { + throw e; + } + } + } +}