[TIL] 개인 과제

최하온·2024년 3월 14일
0

TIL

목록 보기
47/71
post-thumbnail

✅ 필수 기능 구현 리스트

  • 로그인 / 회원가입
  • 프로필 보기
  • 새 공연 등록
  • 공연 목록 보기
  • 공연 검색하기
  • 공연 상세보기
  • 예매 확인하기

🏆 보너스 기능 구현 리스트

  • 공연의 좌석 예매 정보 확인하기
  • 좌석을 지정하여 예매하기
  • 동시성 처리하기
  • 예매 취소하기
  • 테스트 코드 내용 채우기

erd의 수정이 약간 있다.

  • 기존 TicketReservation으로 병합.
  • 좌석 지정 예매를 위한 Performance에 좌석별 Limit 추가

공연 생성

  1. 공연 생성 시 Limit 수 대로 등급별 좌석 생성
  async createPerformance(
    createPerformanceDto: CreatePerformanceDto,
    id: number,
  ) {
    await this.findUser(id); // 유저 찾기
    const performance: Performance = this.performanceRepository.create({
      ...createPerformanceDto,
      userId: +id,
    }); // 공연 생성 후
    await this.performanceRepository.save(performance); // 저장
    await this.setSeat(performance.id); // 좌석생성
    return performance;
  }
// 좌석 생성
			// ...
      // 1. 공연의 좌석 만들기
      let setSeatStandard: Array<any> = [];
      let setSeatRoyal: Array<any> = [];
      let setSeatvip: Array<any> = [];

	  // 좌석 생성 class
      class SeatSet {
			// ...
      }
      // 스탠다드
      for (let i = 0; i < performance.standardLimit; i++) {
        const standard = new SeatSet(
          performance.id,
          i + 1,
          'STANDARD',
          performance.price,
        );
        setSeatStandard.push(standard);
        
        await this.seatRepository.insert({
          performanceId: setSeatStandard[i].performanceId,
          seatNum: setSeatStandard[i].seatNum,
          grade: setSeatStandard[i].grade,
          seatPrice: setSeatStandard[i].price,
        });
      }
      // ...

🚨Issue occuring


seatRepository에 저장이 안 됨.

💦What I tried


save, create를 사용

💡How solve issue


insert 사용

📃What I learned new


create는 생성만 해주므로 save를 같이 사용.
insert는 기본키나 유효성 검사 등을 하지않고 지정한 데이터를 데이터베이스에 직접적으로 추가하므로 유의해서 사용해야함

예매 하기, 환불

/**예매하기 transaction */
	// 예매 하려는 좌석 확인
      let matchingSeat;
      for (const seat of seats) {
        if (
          seat.seatNum == createReservationDto.seatNum &&
          seat.grade === createReservationDto.grade
        ) {
          matchingSeat = seat;
          break;
        }
      }
      if (!matchingSeat) {
        throw new NotFoundException('해당하는 좌석이 없습니다.');
      }

      const user = await this.performanceService.getUserAndPoints(userId);
      const point = await this.pointRepository.findOne({where: { userId }});
      if (point.total < matchingSeat.seatPrice) {
        throw new BadRequestException('포인트가 부족합니다.');
      }

   	// 포인트 확인 후 좌석 예매 완료
	// 추후 환불 시 다시 데이터를 돌리기 위해 softDelete 사용
      this.seatRepository.softDelete(matchingSeat);
	// 유저의 포인트에서 선택한 시트의 가격 빼주기
      const totalPoint = point.total - matchingSeat.seatPrice;
      point.total = totalPoint;

      await queryRunner.manager.save(point);

      const reservation = await this.reservationRepository.create({
        userId: user.id,
        performanceId: createReservationDto.performanceId,
        seatId: matchingSeat.id,
        price: matchingSeat.seatPrice,
      });
      await queryRunner.manager.save(reservation);

      await queryRunner.commitTransaction();
      return matchingSeat;
    } catch (err) {
      console.log(err);
      await queryRunner.rollbackTransaction();
    } finally {
      await queryRunner.release();
    }
  }

🚨Issue occuring


save를 사용한 저장

💡How solve issue


  1. entity class 자체를 save의 인자로 넘겨주고있었음
  2. 인스턴스에 수정된 프로퍼티를 할당해주지 않음

🤔Realization


더 고민해봐야할 것
1. 격리 수준을 준 것만으로 동시성 문제가 해결이 되는가?
2. 3시간 전에만 환불이 가능하게는 어떻게 해야할까?
3. 커스텀 데코레이터

0개의 댓글