erd의 수정이 약간 있다.
Ticket
을 Reservation
으로 병합.Performance
에 좌석별 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,
});
}
// ...
seatRepository에 저장이 안 됨.
save, create를 사용
insert 사용
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();
}
}
save를 사용한 저장
더 고민해봐야할 것
1. 격리 수준을 준 것만으로 동시성 문제가 해결이 되는가?
2. 3시간 전에만 환불이 가능하게는 어떻게 해야할까?
3. 커스텀 데코레이터