[TIL] 24.03.14

sssujijjl·2024년 3월 14일

[TIL]

목록 보기
51/51
post-thumbnail

[공연 회차 생성]

  • 공연 회차 생성 + 해당 공연장의 회차별로 좌석도 생성해주었다.
export class CreateRoundDto extends PickType(Round, [
  "content",
  "datetime",
  "showId",
]) {
  @IsObject()
  @ValidateNested()
  seatPrices: Record<SeatClass, number>;
}

CreateRoundDto: 내용, 날짜와 시간, 공연 아이디, 좌석별 금액

  @UseGuards(AuthGuard("admin"))
  @Post(":showId")
  async createRound(
    @Body() createRoundDto: CreateRoundDto,
    @Param("showId") showId: number,
  ) {
    validate(createRoundDto);

    return await this.roundService.createRound(createRoundDto, +showId);
  }

Guard를 통해서 admin 권한을 가진 유저만 만들 수 있도록 해주었다.

async createRound(createRoundDto: CreateRoundDto, showId: number) {
    const queryRunner = this.dataSource.createQueryRunner();
    await queryRunner.connect();
    await queryRunner.startTransaction();

API 실행 중 실패하더라도 데이터베이스에 저장되지 않도록 트랜잭션을 이용하였다.

try {
      const seats = await this.findSeatsId(showId);
      

  async findSeatsId(showId: number) {
    const show = await this.showRepository.findOneBy({ id: showId });
    if (!show) {
      throw new NotFoundException("해당 공연을 찾을 수 없습니다.");
    }

    const hall = await this.hallRepository.findOne({
      where: { id: show.hallId },
      relations: ["seats"],
    });

    return hall.seats.map((seat) => ({
      id: seat.id,
      seatClass: seat.seatClass,
    }));
  }

해당 공연의 공연장을 조회하여 좌석의 아이디와 좌석의 등급을 찾아주었다.

createRoundDto.showId = showId;
const round = await queryRunner.manager.save(Round, createRoundDto);

showId도 추가해준 후, 해당 회차정보를 저장해주었다.

      const newRoundSeats = await this.createRoundSeat(
        seats,
        round.id,
        createRoundDto.seatPrices,
      );
      await queryRunner.manager.save(RoundSeat, newRoundSeats);

공연장의 좌석들과 회차 아이디, 금액으로 회차별 좌석을 생성해주었다.

  async createRoundSeat(
    seats: { id: number; seatClass: SeatClass }[],
    id: number,
    seatPrices: Record<SeatClass, number>,
  ) {
    const newRoundSeats = seats.map((seat) => {
      const newRoundSeat = new CreateRoundSeatDto();
      newRoundSeat.roundId = id;
      newRoundSeat.seatId = seat.id;
      newRoundSeat.price = seatPrices[seat.seatClass];
      return newRoundSeat;
    });
    return newRoundSeats;
  }

회차별 좌석을 위해서 새로운 회차별 좌석 배열을 만들어주었다.

      await queryRunner.commitTransaction();

      return round;
    } catch (error) {
      await queryRunner.rollbackTransaction();
      return { message: `${error}` };
    } finally {
      await queryRunner.release();
    }
  }

성공 후 해당 회차를 return 해주었다!

[설계 이유]

간단하게 이렇게 설계를 한 이유를 말해보자면

  • 좌석등급별 금액이 다름
  • 공연장이 같더라도 공연별로 금액이 다를 수 있음
  • 하나의 공연이 아닌 공연에 날짜와 시간별 회차
  • 회차 생성 시 회차별 좌석 생성

먼저 같은 공연장이라고 하더라도 어떤 공연을 하는지에 따라 좌석의 등급별로 금액이 다를 수 있다는 생각이 들어 각각의 좌석 금액과, 상태를 넣어주기 위하여 RoundSeat를 만들었다.

회차를 생성해주는 것은 각각 해야하지만, 해당 회차별 좌석을 따로 생성하는 것은 비효율적이라는 생각이 들어서 회차 생성 시 좌석별 금액을 넣어서 Round - RoundSeat를 같이 생성했다.

티켓 예매 시에 RoundSeat를 통해 해당 공연, 회차 정보, 좌석별 금액, 좌석의 상태를 통해
간편하게 확인 할 수 있도록 설계하였다.

0개의 댓글