Post

(feat) Get ticket sales

✅ How to get ticket sales

ticket sales= (total seats - remaining seats)/total seats * 100 remaining seats: schedule table에 있음 total seats of a cinema: cinema type table에 있음 한 영화에 대한 모든 schedule, 즉 schedule List가 주어짐

🟢 caculate total seats

schedule List에 있는 각각의 schedule에 대해 cinema type을 찾아서
cinema type table에 있는 total seats구하고 모두 더한다.

1
2
3
4
5
6
7
8
private int caculateTotalSeats(List<Schedule> scheduleList){
    //get total seats per cinema
    int totalSeats= scheduleList.stream()
            .map(schedule -> schedule.getCinemaType().getTotalSeats())
            .mapToInt(Integer::intValue)
            .sum();
    return totalSeats;
}

🟢 caculate ticket sales

이제 remaining seats를 구해야 한다.
두 가지 방법이 있겠으나..
첫 번째 방법이 더 효율적이지만
두 번째 방법도 각각의 RemainingSeats에 대해 무언가를 해줄 수 있다는 점에서 알아두는데 의의가 있다.

👍🏻 방법 1. mapToInt().sum()

1
2
3
4
int totalRemainingSeats= scheduleList.stream()
                    .map(Schedule::getRemainingSeats)
                    .mapToInt(Integer::intValue)
                    .sum();

👍🏻 방법 2. RemainingSeats를 구해 List로 만들고, List를 돌면서 더한다.

1
2
3
4
List<Integer> remainingSeatsList= scheduleList.stream().map(Schedule::getRemainingSeats).toList();
        int totalRemainingSeats= 0;
        for(int x: remainingSeatsList)  totalRemainingSeats +=x;
        int totalSeats= caculateTotalSeats(scheduleList);

☑️ 이제 마지막으로, ticket sales를 계산한다.

1
2
3
4
double ticketSales = ((double) (totalSeats - totalRemainingSeats)totalSeats * 100.0) ;
//show only until 소수점 첫째자리
double formattedTicketSales= Math.round(ticketSales*10.0)/10.0;
return formattedTicketSales;

🟢 Final Code

여러번 사용해서 다른 메소드에서 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private double caculateTicketSales(List<Schedule> scheduleList){
        //remaining seats(schedule) / total seats(cinema type) * 100
        //1. get List<schedule> to get remaining seats
        //2. for each schedule in list, get total seats from cinema type
        //3. do the math
        List<Integer> remainingSeatsList= scheduleList.stream().map(Schedule::getRemainingSeats).toList();
        int totalRemainingSeats= 0;
        for(int x: remainingSeatsList)  totalRemainingSeats +=x;
        int totalSeats= caculateTotalSeats(scheduleList);
        double ticketSales = ((double) (totalSeats - totalRemainingSeats) /totalSeats * 100.0) ;
        //show only until 소수점 첫째자리
        double formattedTicketSales= Math.round(ticketSales*10.0)/10.0;
        return formattedTicketSales;
}
private int caculateTotalSeats(List<Schedule> scheduleList){
        //get total seats per cinema
        int totalSeats= scheduleList.stream()
                .map(schedule -> schedule.getCinemaType().getTotalSeats())
                .mapToInt(Integer::intValue)
                .sum();
        return totalSeats;
}

🟢 Cleaner Code

💡 .mapToInt(Integer::intValue)를 안하면 sum()안 됨!!
💡 나누는 수가 0이 되지 않도록 주의하자.
if (totalSeats == 0) throw new NotFoundException 해서 예외 처리하기
🔴 double ticketSales= 를 구하는 식에서 계속 에러가 났다. ticketSales가 계속 0이 뜨는 것이다.
그 이유는 나누어지는 수가 먼저 (double)처리가 되어야 하기 떄문이었다.
double ticketSales= (double)((totalSeats- remainingSeats)/totalSeats)*100;
⭕️ double ticketSales= ((double) (totalSeats- remainingSeats)/totalSeats)*100;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        Page<Movie> moviePage= movieJpa.findAll(pageable);

   for(Movie movie: moviePage){
        //ticketSales
        List<Schedule> scheduleList= movie.getScheduleList();
        int remainingSeats= scheduleList.stream().mapToInt(Schedule::getRemainingSeats).sum();
        int totalSeats= scheduleList.stream().map(Schedule::getCinemaType).map(CinemaType::getTotalSeats).mapToInt(Integer::intValue).sum();
        if (totalSeats == 0) throw new NotFoundException("There are no total seats for this movie");

        //same code
        // int toalSeats= scheduleList.stream().map(schedule -> schedule.getCinemaType().getTotalSeat()).mapToInt(Integer::intValue).sum();
        double ticketSales=  ((double) (totalSeats- remainingSeats)/totalSeats)*100;
        double formattedTicketSales= (double) Math.round(ticketSales*10.0)/10.0;

        movie.setTicketSales(formattedTicketSales);
        movieJpa.save(movie);
   }

🟢 JPA에서 구하는 방법

movie table에 ticket_sales라는 field가 있음
따라서 ticket_sales를 구해서 movie table에 넣어주는(update해주는) JPQL

1
2
3
4
5
6
7
8
9
10
11
12
@Repository
public interface MovieJpa extends JpaRepository<Movie, Integer> {
    @Transactional
    @Modifying
    @Query(
            value = "UPDATE movie AS A " +
                    "INNER JOIN schedule AS B ON A.movie_id = B.movie_id " +
                    "INNER JOIN cinema_type AS C ON B.cinema_type_id = C.cinema_type_id " +
                    "SET A.ticket_sales = (1 - (B.remaining_seats / C.total_seats)) * 100 "
    , nativeQuery = true)
    void updateTicketSales();
}
This post is licensed under CC BY 4.0 by the author.