NEST.js

NEST 소프트 딜리트

늘곰's 2023. 10. 1. 15:58

resolver

제품 삭제

  /* 프로덕트 삭제 */
  @Mutation(() => Boolean)
  deleteProduct(
    @Args('productId') productId: string, //
  ): Promise<boolean> {
    return this.productsService.delete({ productId });
  }

service 

import { Injectable, UnprocessableEntityException } from '@nestjs/common';
import { Repository } from 'typeorm';
import { Product } from './entities/product.entity';
import { InjectRepository } from '@nestjs/typeorm';
import {
  IProductsServiceCreate,
  IProductsServiceFindOne,
  IProductsServiceUpdate,
  IproductsServiceCheckSoldOut,
} from './interfaces/products-service.interface';

@Injectable()
export class ProductsService {
  constructor(
    @InjectRepository(Product)
    private readonly productsRepository: Repository<Product>, //
  ) {}

  findAll(): Promise<Product[]> {
    return this.productsRepository.find();
  }

  findOne({ productId }: IProductsServiceFindOne): Promise<Product> {
    return this.productsRepository.findOne({ where: { id: productId } });
  }

  // async await 를 안달아도  nest 에서는 resolver 에서 알아서 await가 적용되어진다.
  // express 는 async await 달아줘야함
  // Promise 는 외부에 요청을 해야되서 시간이 걸리는 로직때 사용
  create({ createProductInput }: IProductsServiceCreate): Promise<Product> {
    const result = this.productsRepository.save({
      ...createProductInput,

      // 하나하나 직접 나열하는 방식식
      // name: '마우스',
      // description: '좋은 마우스',
      // price: 10000,

      //resilt 안에는 무엇이 있는가?
      // result = {
      // id : uuid
      // name : '마우스'
      // description : '좋은 마우스'
      // price : 10000
      // }
    });

    return result;
  }

  async update({
    productId,
    updateProductInput,
  }: IProductsServiceUpdate): Promise<Product> {
    // 기존에 있는 내용을 재사용해서 , 로직을 통일하자
    const product = await this.findOne({ productId });

    //검증은 서비스에서 한다
    this.cheakSoldOut({ product });

    //
    // this.productsRepository.create //DB 접속과 관련이 없음  등록을 위한 빈 객체를 만드는 것
    // this.productsRepository.insert  // 결과를 객체로 못 돌려받는 등록방법
    // this.productsRepository.update   // 결과를 객체로 못 돌려받는 수정방법
    // this.productsRepository.save  //save 는 안에 id 가 없으면 등록 , 있으면 수정으로 작동
    // 등록된 결과를 const resilt 에 저장해서 브라우저에 보내줄 수있음 수정된 내용을 다시 조회하지않아도됨
    //

    const result = this.productsRepository.save({
      ...product, // 스프레드  / 수정 후 수정되지 않은 다른 결과값까지 모두 객체로 돌려받고 싶을때
      ...updateProductInput, //
    });
    return result;
  }

  // 에러 : 아에 실행이 안되는것
  // 버그 : 작동의 되는데 의도하지 않고 다르게 작동
  // 예외 : 데이터를 수정하려고하는데 db가 꺼져있다 같이 예외적인 내용
  // cheakSoldOut 을 함수로 만드는 이유  => 수정 삭제 등 같은 검증 로직 사용
  cheakSoldOut({ product }: IproductsServiceCheckSoldOut): void {
    //좀더 간소화
    if (product.isSoldOut) {
      throw new UnprocessableEntityException('이미 판매 완료된 상품입니다.');
    }

    //같은에러 메세지 표시
    // if (product.isSoldOut) {
    //   throw new HttpException(
    //     '이미 판매 완료된 상품입니다.',
    //     HttpStatus.UNPROCESSABLE_ENTITY,
    //   );
    // }
  }

  async delete({ productId }: IproductsServiceDelete): Promise<boolean> {
    //1. 실제 삭제 방법
    // const result = await this.productsRepository.delete({ id: productId });
    // return result.affected ? true : false;

    //2 . 소프트 삭제(직접 구현) - isDeleted
    //this.productsRepository.update({ id: productId }, { isDeleted: true });

    // 3. 소프트 삭제(직접 구현) - deletedAt 비워져있으면 삭제 안된 것 들어가 있으면 삭제 된것
    //this.productsRepository.update({ id: productId }, { deletedAt: new Date() });

    //4. 소프트 삭제(TypeOrm 제공) -softRemove
    //this.productsRepository.softRemove({ id: productId });
    // 단점 : id로만 삭제 가능
    // 장점 : 여러 id 한번에 지우기 가능 .softRemove([{id : 1}, {id : 2}, {id : 3}]);

    //5. 소프트 삭제(TypeOrm 제공) -softDelete
    const result = await this.productsRepository.softDelete({ id: productId });
    //  단점 : 한번에 하나씩만 지울 수 있음
    //  장점 : 다른 컬럼으로도 삭제가능 name , title 등등

    return result.affected ? true : false;
  }
} // class 닫는 중괄호

interface IproductsServiceDelete {
  productId: string;
}

entity

  @CreateDateColumn() // 데이터 등록시 등록시간 자동으로 추가
  createdAt: Date;

  @UpdateDateColumn() // 데이터 수정시 수정시간 자동으로 추가
  updatedAt: Date;

  @DeleteDateColumn() //소프트 삭제 시간 기록
  deletedAt: Date;