diff --git a/api/api-booking/build.gradle b/api/api-booking/build.gradle index f9084532..d051eeb3 100644 --- a/api/api-booking/build.gradle +++ b/api/api-booking/build.gradle @@ -14,9 +14,8 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-redis' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' - - //TODO: security 의존성 core-security 에서 추가 implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'io.jsonwebtoken:jjwt-api:0.12.3' implementation 'io.jsonwebtoken:jjwt-impl:0.12.3' implementation 'io.jsonwebtoken:jjwt-jackson:0.12.3' diff --git a/api/api-booking/http/test.http b/api/api-booking/http/test.http new file mode 100644 index 00000000..d27ca3fa --- /dev/null +++ b/api/api-booking/http/test.http @@ -0,0 +1,57 @@ +### 세션 아이디 발급 +POST http://localhost:8082/api/v1/bookings/issue-session-id +#Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwic3ViIjoiam9obi5kb2VAZXhhbXBsZS5jb20iLCJpYXQiOjE3MDQ2OTE0OTEsImV4cCI6MTgwNDY4MzI5MSwiYXV0aG9yaXR5IjoiUk9MRV9VU0VSIn0.wFNSz2uwRa35jP1KihNlTOewVLgMMeg3ADQ5Kztl3QQ + +### 대기열 진입 +POST http://localhost:8082/api/v1/bookings/enter-queue +Content-Type: application/json +#Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwic3ViIjoiam9obi5kb2VAZXhhbXBsZS5jb20iLCJpYXQiOjE3MDQ2OTE0OTEsImV4cCI6MTgwNDY4MzI5MSwiYXV0aG9yaXR5IjoiUk9MRV9VU0VSIn0.wFNSz2uwRa35jP1KihNlTOewVLgMMeg3ADQ5Kztl3QQ +Booking-Session-Id: {세션아이디} + +{ + "eventId": 1 +} + +### 대기열 조회 +GET http://localhost:8082/api/v1/bookings/order-in-queue?eventId=1 +#Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwic3ViIjoiam9obi5kb2VAZXhhbXBsZS5jb20iLCJpYXQiOjE3MDQ2OTE0OTEsImV4cCI6MTgwNDY4MzI5MSwiYXV0aG9yaXR5IjoiUk9MRV9VU0VSIn0.wFNSz2uwRa35jP1KihNlTOewVLgMMeg3ADQ5Kztl3QQ +Booking-Session-Id: {세션아이디} + + +### 예매 토큰 발급 +POST http://localhost:8082/api/v1/bookings/issue-token +Content-Type: application/json +#Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwic3ViIjoiam9obi5kb2VAZXhhbXBsZS5jb20iLCJpYXQiOjE3MDQ2OTE0OTEsImV4cCI6MTgwNDY4MzI5MSwiYXV0aG9yaXR5IjoiUk9MRV9VU0VSIn0.wFNSz2uwRa35jP1KihNlTOewVLgMMeg3ADQ5Kztl3QQ +Booking-Session-Id: {세션아이디} + +{ + "eventId": 1 +} + +### 좌석 목록 조회 +GET http://localhost:8082/api/v1/seats?eventTimeId=1 +#Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwic3ViIjoiam9obi5kb2VAZXhhbXBsZS5jb20iLCJpYXQiOjE3MDQ2OTE0OTEsImV4cCI6MTgwNDY4MzI5MSwiYXV0aG9yaXR5IjoiUk9MRV9VU0VSIn0.wFNSz2uwRa35jP1KihNlTOewVLgMMeg3ADQ5Kztl3QQ +Booking-Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJib29raW5nIiwiaWF0IjoxNzA0NjkzNDQ4LCJleHAiOjE3MDQ2OTUyNDgsInNlc3Npb25JZCI6Ins_Pz8_P30ifQ.IFqm66RBlLw6ZVbogZdTvClpH2arxAfWTZ1-DNFtT-H7EH0OSYUoICgnpMjbI2aSObsdl1h3oVSQPw28XlmJzg + +### 예매 +POST http://localhost:8082/api/v1/bookings +Content-Type: application/json +#Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwic3ViIjoiam9obi5kb2VAZXhhbXBsZS5jb20iLCJpYXQiOjE3MDQ2OTE0OTEsImV4cCI6MTgwNDY4MzI5MSwiYXV0aG9yaXR5IjoiUk9MRV9VU0VSIn0.wFNSz2uwRa35jP1KihNlTOewVLgMMeg3ADQ5Kztl3QQ +Booking-Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJpc3MiOiJib29raW5nIiwiaWF0IjoxNzA0NjkzNDQ4LCJleHAiOjE3MDQ2OTUyNDgsInNlc3Npb25JZCI6Ins_Pz8_P30ifQ.IFqm66RBlLw6ZVbogZdTvClpH2arxAfWTZ1-DNFtT-H7EH0OSYUoICgnpMjbI2aSObsdl1h3oVSQPw28XlmJzg + +{ + "timeId": 1, + "seatIds": [3, 4], + "receiptType": "배송", + "buyerName": "이한나", + "buyerPhoneNumber": "010-1234-5678", + "deliveryAddress": { + "recipientName": "이한나", + "recipientPhoneNumber": "010-1234-5678", + "streetAddress": "서울시 강남구 테헤란로", + "detailAddress": "000동 000호", + "zipCode": "00000" + }, + "method": "카드" +} + diff --git a/api/api-booking/src/main/java/com/pgms/apibooking/config/SecurityConfig.java b/api/api-booking/src/main/java/com/pgms/apibooking/config/SecurityConfig.java index 1640e2ad..1f3db54b 100644 --- a/api/api-booking/src/main/java/com/pgms/apibooking/config/SecurityConfig.java +++ b/api/api-booking/src/main/java/com/pgms/apibooking/config/SecurityConfig.java @@ -34,9 +34,10 @@ public class SecurityConfig { @Bean public SecurityFilterChain bookingFilterChain(HttpSecurity http) throws Exception { List permitAllMatchers = List.of( + new AntPathRequestMatcher("/api/*/bookings/issue-session-id", HttpMethod.POST.toString()), new AntPathRequestMatcher("/api/*/bookings/enter-queue", HttpMethod.POST.toString()), new AntPathRequestMatcher("/api/*/bookings/order-in-queue", HttpMethod.GET.toString()), - new AntPathRequestMatcher("/api/*/bookings/issue-token", HttpMethod.GET.toString()) + new AntPathRequestMatcher("/api/*/bookings/issue-token", HttpMethod.POST.toString()) ); return http diff --git a/api/api-booking/src/main/java/com/pgms/apibooking/domain/booking/controller/BookingController.java b/api/api-booking/src/main/java/com/pgms/apibooking/domain/booking/controller/BookingController.java index 3c783d64..d6a9eac3 100644 --- a/api/api-booking/src/main/java/com/pgms/apibooking/domain/booking/controller/BookingController.java +++ b/api/api-booking/src/main/java/com/pgms/apibooking/domain/booking/controller/BookingController.java @@ -24,16 +24,16 @@ @Controller @RequestMapping("/api/v1/bookings") @RequiredArgsConstructor -public class BookingController { +public class BookingController { //TODO: 인증된 멤버 연동 private final BookingService bookingService; @PostMapping public ResponseEntity> createBooking( - @CurrentAccount Long memberId, + //@CurrentAccount Long memberId, @RequestBody @Valid BookingCreateRequest request, HttpServletRequest httpRequest) { - BookingCreateResponse createdBooking = bookingService.createBooking(request, memberId); + BookingCreateResponse createdBooking = bookingService.createBooking(request, 1L); ApiResponse response = ApiResponse.ok(createdBooking); URI location = UriComponentsBuilder .fromHttpUrl(httpRequest.getRequestURL().toString()) @@ -45,10 +45,10 @@ public ResponseEntity> createBooking( @PostMapping("/{id}/cancel") public ResponseEntity cancelBooking( - @CurrentAccount Long memberId, + //@CurrentAccount Long memberId, @PathVariable String id, @RequestBody @Valid BookingCancelRequest request) { - bookingService.cancelBooking(id, request, memberId); + bookingService.cancelBooking(id, request, 1L); return ResponseEntity.ok().build(); } diff --git a/api/api-booking/src/main/java/com/pgms/apibooking/domain/bookingqueue/controller/BookingQueueController.java b/api/api-booking/src/main/java/com/pgms/apibooking/domain/bookingqueue/controller/BookingQueueController.java index 93b17c2f..72f8007d 100644 --- a/api/api-booking/src/main/java/com/pgms/apibooking/domain/bookingqueue/controller/BookingQueueController.java +++ b/api/api-booking/src/main/java/com/pgms/apibooking/domain/bookingqueue/controller/BookingQueueController.java @@ -3,6 +3,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @@ -17,7 +18,6 @@ import com.pgms.apibooking.domain.bookingqueue.service.BookingQueueService; import com.pgms.coredomain.response.ApiResponse; -import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; @@ -35,32 +35,27 @@ public ResponseEntity> issueSessionId() { } @PostMapping("/enter-queue") - public ResponseEntity enterQueue(@RequestBody @Valid BookingQueueEnterRequest request, HttpServletRequest httpServletRequest) { - String bookingSessionId = getBookingSessionId(httpServletRequest); + public ResponseEntity enterQueue(@RequestBody @Valid BookingQueueEnterRequest request, @RequestAttribute("bookingSessionId") String bookingSessionId) { bookingQueueService.enterQueue(request, bookingSessionId); return ResponseEntity.ok().build(); } @GetMapping("/order-in-queue") - public ResponseEntity> getOrderInQueue(@RequestParam Long eventId) { + public ResponseEntity> getOrderInQueue(@RequestParam Long eventId, @RequestAttribute("bookingSessionId") String bookingSessionId) { ApiResponse response = - ApiResponse.ok(bookingQueueService.getOrderInQueue(eventId, null)); + ApiResponse.ok(bookingQueueService.getOrderInQueue(eventId, bookingSessionId)); return ResponseEntity.ok(response); } @PostMapping("/issue-token") - public ResponseEntity> issueToken(@RequestBody @Valid TokenIssueRequest request) { - ApiResponse response = ApiResponse.ok(bookingQueueService.issueToken(request, null)); + public ResponseEntity> issueToken(@RequestBody @Valid TokenIssueRequest request, @RequestAttribute("bookingSessionId") String bookingSessionId) { + ApiResponse response = ApiResponse.ok(bookingQueueService.issueToken(request, bookingSessionId)); return ResponseEntity.ok(response); } @PostMapping("/exit-queue") - public ResponseEntity exitQueue(@RequestBody @Valid BookingQueueExitRequest request) { - bookingQueueService.exitQueue(request, null); + public ResponseEntity exitQueue(@RequestBody @Valid BookingQueueExitRequest request, @RequestAttribute("bookingSessionId") String bookingSessionId) { + bookingQueueService.exitQueue(request, bookingSessionId); return ResponseEntity.ok().build(); } - - private String getBookingSessionId(HttpServletRequest httpServletRequest) { - return (String) httpServletRequest.getAttribute("bookingSessionId"); - } } diff --git a/api/api-booking/src/main/java/com/pgms/apibooking/domain/bookingqueue/service/BookingQueueService.java b/api/api-booking/src/main/java/com/pgms/apibooking/domain/bookingqueue/service/BookingQueueService.java index 379ae4f2..3bb3b2fd 100644 --- a/api/api-booking/src/main/java/com/pgms/apibooking/domain/bookingqueue/service/BookingQueueService.java +++ b/api/api-booking/src/main/java/com/pgms/apibooking/domain/bookingqueue/service/BookingQueueService.java @@ -4,16 +4,16 @@ import org.springframework.stereotype.Service; +import com.pgms.apibooking.common.exception.BookingErrorCode; +import com.pgms.apibooking.common.exception.BookingException; +import com.pgms.apibooking.common.jwt.BookingJwtPayload; +import com.pgms.apibooking.common.jwt.BookingJwtProvider; import com.pgms.apibooking.domain.bookingqueue.dto.request.BookingQueueEnterRequest; import com.pgms.apibooking.domain.bookingqueue.dto.request.BookingQueueExitRequest; import com.pgms.apibooking.domain.bookingqueue.dto.request.TokenIssueRequest; import com.pgms.apibooking.domain.bookingqueue.dto.response.OrderInQueueGetResponse; import com.pgms.apibooking.domain.bookingqueue.dto.response.SessionIdIssueResponse; import com.pgms.apibooking.domain.bookingqueue.dto.response.TokenIssueResponse; -import com.pgms.apibooking.common.exception.BookingErrorCode; -import com.pgms.apibooking.common.exception.BookingException; -import com.pgms.apibooking.common.jwt.BookingJwtPayload; -import com.pgms.apibooking.common.jwt.BookingJwtProvider; import com.pgms.apibooking.domain.bookingqueue.repository.BookingQueueRepository; import lombok.RequiredArgsConstructor; @@ -49,8 +49,6 @@ public TokenIssueResponse issueToken(TokenIssueRequest request, String sessionId BookingJwtPayload payload = new BookingJwtPayload(sessionId); String token = bookingJwtProvider.generateToken(payload); - bookingQueueRepository.remove(request.eventId(), sessionId); - return TokenIssueResponse.from(token); } diff --git a/batch/batch-booking/build.gradle b/batch/batch-booking/build.gradle new file mode 100644 index 00000000..44076dcb --- /dev/null +++ b/batch/batch-booking/build.gradle @@ -0,0 +1,15 @@ +// 실행가능한 jar로 생성하는 옵션, main이 없는 라이브러리에서는 false로 비활성화함 +// 스프링 부트 2.0 이상이라면 bootRepackage.enabled를 사용해야 함 +bootJar { enabled = true } + +// 외부에서 의존하기 위한 jar로 생성하는 옵션, main이 없는 라이브러리에서는 true로 비활성화함 +jar { enabled = false } + +dependencies { + implementation project(':core:core-domain'); + implementation project(':core:core-infra'); + + implementation 'org.springframework.boot:spring-boot-starter-batch' +} + +tasks.register("prepareKotlinBuildScriptModel") {} diff --git a/batch/batch-booking/gradle/wrapper/gradle-wrapper.jar b/batch/batch-booking/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..d64cd491 Binary files /dev/null and b/batch/batch-booking/gradle/wrapper/gradle-wrapper.jar differ diff --git a/batch/batch-booking/gradle/wrapper/gradle-wrapper.properties b/batch/batch-booking/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..1af9e093 --- /dev/null +++ b/batch/batch-booking/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/batch/batch-booking/src/main/java/com/pgms/batchbooking/BatchBookingApplication.java b/batch/batch-booking/src/main/java/com/pgms/batchbooking/BatchBookingApplication.java new file mode 100644 index 00000000..e9bf2f59 --- /dev/null +++ b/batch/batch-booking/src/main/java/com/pgms/batchbooking/BatchBookingApplication.java @@ -0,0 +1,15 @@ +package com.pgms.batchbooking; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@ComponentScan("com.pgms") +public class BatchBookingApplication { + + public static void main(String[] args) { + SpringApplication.run(BatchBookingApplication.class, args); + } + +} diff --git a/batch/batch-booking/src/main/java/com/pgms/batchbooking/seat/SeatReleaseConfig.java b/batch/batch-booking/src/main/java/com/pgms/batchbooking/seat/SeatReleaseConfig.java new file mode 100644 index 00000000..d5651ec4 --- /dev/null +++ b/batch/batch-booking/src/main/java/com/pgms/batchbooking/seat/SeatReleaseConfig.java @@ -0,0 +1,45 @@ +package com.pgms.batchbooking.seat; + +import org.springframework.batch.core.Job; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.job.builder.JobBuilder; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.step.builder.StepBuilder; +import org.springframework.batch.core.step.tasklet.Tasklet; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.PlatformTransactionManager; + +import com.pgms.coredomain.domain.booking.repository.TicketRepository; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Configuration +@RequiredArgsConstructor +@Slf4j +public class SeatReleaseConfig { + + private final JobRepository jobRepository; + private final PlatformTransactionManager transactionManager; + private final TicketRepository ticketRepository; + + @Bean + public Job seatReleaseJob() { + return new JobBuilder("seatReleaseJob", jobRepository) + .start(seatReleaseStep()) + .build(); + } + + @Bean + public Step seatReleaseStep(){ + return new StepBuilder("seatReleaseStep", jobRepository) + .tasklet(seatReleaseTasklet(), transactionManager) + .build(); + } + + @Bean + public Tasklet seatReleaseTasklet(){ + return new SeatReleaseTasklet(ticketRepository); + } +} diff --git a/batch/batch-booking/src/main/java/com/pgms/batchbooking/seat/SeatReleaseScheduler.java b/batch/batch-booking/src/main/java/com/pgms/batchbooking/seat/SeatReleaseScheduler.java new file mode 100644 index 00000000..c07fbc12 --- /dev/null +++ b/batch/batch-booking/src/main/java/com/pgms/batchbooking/seat/SeatReleaseScheduler.java @@ -0,0 +1,39 @@ +package com.pgms.batchbooking.seat; + +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecutionException; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +/* + * 테스트를 위한 스케줄러 + */ +@Component +@EnableScheduling +@RequiredArgsConstructor +@Slf4j +public class SeatReleaseScheduler { + + private final JobLauncher jobLauncher; + private final Job lockAdminJob; + + @Scheduled(cron = "0 0 0 * * ?") + public void runJob() { + try { + JobParameters jobParameters = new JobParametersBuilder() + .addLong("executedTime", System.currentTimeMillis()) + .toJobParameters(); + + jobLauncher.run(lockAdminJob, jobParameters); + } catch (JobExecutionException e) { + log.error("SeatReleaseScheduler error : ", e); + } + } +} diff --git a/batch/batch-booking/src/main/java/com/pgms/batchbooking/seat/SeatReleaseTasklet.java b/batch/batch-booking/src/main/java/com/pgms/batchbooking/seat/SeatReleaseTasklet.java new file mode 100644 index 00000000..9ddb97ff --- /dev/null +++ b/batch/batch-booking/src/main/java/com/pgms/batchbooking/seat/SeatReleaseTasklet.java @@ -0,0 +1,31 @@ +package com.pgms.batchbooking.seat; + +import java.time.LocalDateTime; +import java.util.List; + +import org.springframework.batch.core.StepContribution; +import org.springframework.batch.core.scope.context.ChunkContext; +import org.springframework.batch.core.step.tasklet.Tasklet; +import org.springframework.batch.repeat.RepeatStatus; +import org.springframework.transaction.annotation.Transactional; + +import com.pgms.coredomain.domain.booking.BookingStatus; +import com.pgms.coredomain.domain.booking.Ticket; +import com.pgms.coredomain.domain.booking.repository.TicketRepository; +import com.pgms.coredomain.domain.event.EventSeatStatus; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class SeatReleaseTasklet implements Tasklet{ + + private final TicketRepository ticketRepository; + + @Transactional + @Override + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { + List tickets = ticketRepository.findAll(LocalDateTime.now(), BookingStatus.WAITING_FOR_PAYMENT); + tickets.forEach(ticket -> ticket.getSeat().updateStatus(EventSeatStatus.AVAILABLE)); + return RepeatStatus.FINISHED; + } +} diff --git a/batch/batch-booking/src/main/resources/application.yml b/batch/batch-booking/src/main/resources/application.yml new file mode 100644 index 00000000..499aea89 --- /dev/null +++ b/batch/batch-booking/src/main/resources/application.yml @@ -0,0 +1,10 @@ +server: + port: 8086 + +spring: + profiles: + include: infra + active: dev + batch: + jdbc: + initialize-schema: always diff --git a/batch/batch-booking/src/test/java/com/pgms/batchbooking/BatchBookingApplicationTests.java b/batch/batch-booking/src/test/java/com/pgms/batchbooking/BatchBookingApplicationTests.java new file mode 100644 index 00000000..c5dcf54d --- /dev/null +++ b/batch/batch-booking/src/test/java/com/pgms/batchbooking/BatchBookingApplicationTests.java @@ -0,0 +1,13 @@ +package com.pgms.batchbooking; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class BatchBookingApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/core/core-domain/src/main/java/com/pgms/coredomain/domain/booking/repository/TicketRepository.java b/core/core-domain/src/main/java/com/pgms/coredomain/domain/booking/repository/TicketRepository.java index 5b58ce92..e6af011e 100644 --- a/core/core-domain/src/main/java/com/pgms/coredomain/domain/booking/repository/TicketRepository.java +++ b/core/core-domain/src/main/java/com/pgms/coredomain/domain/booking/repository/TicketRepository.java @@ -1,15 +1,26 @@ package com.pgms.coredomain.domain.booking.repository; +import java.time.LocalDateTime; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import com.pgms.coredomain.domain.booking.BookingStatus; import com.pgms.coredomain.domain.booking.Ticket; public interface TicketRepository extends JpaRepository { @Query("SELECT t FROM Ticket t WHERE t.booking.id = :bookingId") List findAllByBookingId(@Param("bookingId") String bookingId); + + @Query("SELECT tk FROM Ticket tk " + + "LEFT JOIN FETCH tk.booking b " + + "LEFT JOIN FETCH b.time tm " + + "LEFT JOIN FETCH tm.event e " + + "WHERE :datetime BETWEEN e.bookingStartedAt AND e.bookingEndedAt " + + "AND b.status = :bookingStatus ") + List findAll(@Param("datetime") LocalDateTime dateTime, + @Param("bookingStatus") BookingStatus bookingStatus); } diff --git a/settings.gradle b/settings.gradle index 3b87af68..a4d75a99 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,3 +8,4 @@ include 'core:core-infra' include 'core:core-security' include 'core:core-infra-es' include 'batch:batch-member' +include 'batch:batch-booking'