Skip to content
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
7dd3764
test: Fake 객체 λ¦¬νŒ©ν† λ§
boyekim May 12, 2026
c884f2d
refactor: μ§€λ‚œ λ‚ μ§œ 및 μ‹œκ°„ μ˜ˆμ•½ λΆˆκ°€ μ˜ˆμ™Έ 처리
boyekim May 12, 2026
ccdd2de
refactor: 쀑볡 μ˜ˆμ•½ μ˜ˆμ™Έ 처리 μΆ”κ°€
boyekim May 12, 2026
96c1806
refactor: AdminReservationController 뢄리
boyekim May 12, 2026
853acd8
feat: μ‚¬μš©μž μ΄λ¦„μœΌλ‘œ μ˜ˆμ•½ 쑰회 κΈ°λŠ₯ μΆ”κ°€
boyekim May 12, 2026
a3a8fac
feat: μ‚¬μš©μž μ΄λ¦„μœΌλ‘œ μ˜ˆμ•½ μ‚­μ œ κΈ°λŠ₯ μΆ”κ°€
boyekim May 12, 2026
75541fa
refactor: μ‚¬μš©μž μ˜ˆμ•½ 쑰회 api url μˆ˜μ •
boyekim May 12, 2026
55b2aa8
refactor: μ—λŸ¬ ν¬λ§·νŒ… λˆ„λ½ ν•΄κ²°
boyekim May 12, 2026
5a9b56e
feat: μ˜ˆμ•½ μˆ˜μ • κΈ°λŠ₯ κ΅¬ν˜„
boyekim May 13, 2026
a1bc6ec
feat: μΆ”κ°€λœ κΈ°λŠ₯ ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œ μΆ”κ°€
boyekim May 14, 2026
58a4e85
refactor: 더미데이터 μˆ˜μ •
boyekim May 14, 2026
ea28c0e
docs: κΈ°λŠ₯ λͺ…μ„Έ μ—…λ°μ΄νŠΈ
boyekim May 14, 2026
f7f3535
refactor: `@Valid`둜 μž…λ ₯κ°’ 검증
boyekim May 14, 2026
30bbe9c
refactor: λΆˆν•„μš”ν•œ κ°œν–‰ μ‚­μ œ
boyekim May 14, 2026
ca09e57
refactor: ErrorCode 넀이밍 λ³€κ²½
boyekim May 14, 2026
af36d71
refactor: κ°€λŠ₯ μ‹œκ°„ 쑰회 api url μˆ˜μ •
boyekim May 14, 2026
248db1c
refactor: errors νŒ¨ν‚€μ§€ μΆ”κ°€
boyekim May 14, 2026
22eb9e0
refactor: μ—£μ§€μΌ€μ΄μŠ€ μ˜ˆμ™Έ μΆ”κ°€
boyekim May 16, 2026
33bfaaa
refactor: λΆˆν•„μš”ν•œ `@Transactional` μ–΄λ…Έν…Œμ΄μ…˜ μ‚­μ œ
boyekim May 16, 2026
07f4ed3
refactor: λΆˆν•„μš”ν•œ λ‘œκΉ… μ‚­μ œ
boyekim May 16, 2026
fc2b64d
refactor: λ©”μ„œλ“œ 넀이밍 λ³€κ²½
boyekim May 16, 2026
b199646
refactor: λ‚ μ§œμ™€ μ‹œκ°„ μΆ”μΆœ 둜직 μˆ˜μ •
boyekim May 16, 2026
62c27a9
refactor: μ‹œκ°„ 쑰회 μ‹œ theme id및 date id 검증 둜직 μΆ”κ°€
boyekim May 16, 2026
e84bd8a
refactor: 동일 μžλ£Œν˜• 검증 ν˜•νƒœ 톡일
boyekim May 16, 2026
54adb7b
test: ν…Œλ§ˆ ν…ŒμŠ€νŠΈ μΆ”κ°€
boyekim May 16, 2026
991c108
refactor: 쿼리문 μˆ˜μ •
boyekim May 16, 2026
71f01e8
test: ReservationControllerTest μΆ”κ°€
boyekim May 17, 2026
88d4f62
test: AdminReservationControllerTest μΆ”κ°€
boyekim May 17, 2026
3cb6be4
refactor: ReservationDate μ–΄λ“œλ―Ό 컨트둀러 뢄리
boyekim May 17, 2026
d823f2d
test: ReservationDate 컨트둀러 ν…ŒμŠ€νŠΈ μΆ”κ°€
boyekim May 17, 2026
0bf7829
refactor: ReservationTime μ–΄λ“œλ―Ό κΈ°λŠ₯ 뢄리
boyekim May 17, 2026
45a9695
test: ReservationTime 컨트둀러 ν…ŒμŠ€νŠΈ μΆ”κ°€
boyekim May 17, 2026
4fe8125
refactor: Theme 컨트둀러 κ΄€λ¦¬μž κΈ°λŠ₯ 뢄리
boyekim May 17, 2026
c574b71
refactor: ReservationTime νŒ¨ν‚€μ§€ μˆ˜μ •
boyekim May 17, 2026
82f6ff4
test: Theme 컨트둀러 ν…ŒμŠ€νŠΈ μΆ”κ°€
boyekim May 18, 2026
c799ec4
refactor: yml ν•„μš”ν•œ ν•„λ“œ μΆ”κ°€
boyekim May 18, 2026
de703ac
test: Theme e2e ν…ŒμŠ€νŠΈ μΆ”κ°€
boyekim May 18, 2026
3b1c672
test: ReservationTime e2e ν…ŒμŠ€νŠΈ μΆ”κ°€
boyekim May 18, 2026
5d2ff24
test: ReservationDate e2e ν…ŒμŠ€νŠΈ μΆ”κ°€
boyekim May 18, 2026
f0af145
test: Reservation e2e ν…ŒμŠ€νŠΈ μΆ”κ°€
boyekim May 18, 2026
877355c
refactor: ν…ŒμŠ€νŠΈ 넀이밍 μ»¨λ²€μ…˜ 톡일
boyekim May 18, 2026
c0697ab
refactor: λ©”μ„œλ“œ 넀이밍 μˆ˜μ •
boyekim May 18, 2026
4f236dd
feat: ν…ŒμŠ€νŠΈλ§ˆλ‹€ κ³ μœ ν•œ db 이름 μ‚¬μš©ν•˜λ„λ‘ yml μΆ”κ°€
boyekim May 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 59 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
- μ‚¬μš©μžλŠ” 이름, λ‚ μ§œ ID, μ‹œκ°„ ID, ν…Œλ§ˆ IDλ₯Ό μž…λ ₯ν•΄ μ˜ˆμ•½μ„ μƒμ„±ν•œλ‹€.
- μ˜ˆμ•½ 생성 μ‹œ 이름이 λΉ„μ–΄ 있으면 μ˜ˆμ™Έλ₯Ό λ°˜ν™˜ν•œλ‹€.
- μ˜ˆμ•½ 생성 μ‹œ λ‚ μ§œ, μ‹œκ°„, ν…Œλ§ˆ 값이 λˆ„λ½λ˜λ©΄ μ˜ˆμ™Έλ₯Ό λ°˜ν™˜ν•œλ‹€.
- μ‚¬μš©μžλŠ” μ΄λ¦„μœΌλ‘œ 본인의 μ˜ˆμ•½ λͺ©λ‘μ„ μ‘°νšŒν•œλ‹€.
- μ‚¬μš©μžλŠ” 본인의 μ˜ˆμ•½μ„ μ·¨μ†Œν•œλ‹€.
- μ‚¬μš©μžλŠ” 본인의 μ˜ˆμ•½ λ‚ μ§œμ™€ μ‹œκ°„μ„ λ³€κ²½ν•œλ‹€.
- μ˜ˆμ•½ λ³€κ²½ μ‹œ λ‚ μ§œμ™€ μ‹œκ°„μ΄ λͺ¨λ‘ λˆ„λ½λ˜λ©΄ μ˜ˆμ™Έλ₯Ό λ°˜ν™˜ν•œλ‹€.
- μ˜ˆμ•½ λ³€κ²½ μ‹œ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” λ‚ μ§œλ‚˜ μ‹œκ°„μ΄ μž…λ ₯되면 μ˜ˆμ™Έλ₯Ό λ°˜ν™˜ν•œλ‹€.
- μ˜ˆμ•½ λ³€κ²½ μ‹œ λ³€κ²½ν•˜λ €λŠ” λ‚ μ§œμ™€ μ‹œκ°„μ΄ ν˜„μž¬λ³΄λ‹€ 이전이면 μ˜ˆμ™Έλ₯Ό λ°˜ν™˜ν•œλ‹€.
- μ˜ˆμ•½ λ³€κ²½ μ‹œ 같은 λ‚ μ§œ, μ‹œκ°„, ν…Œλ§ˆμ˜ λ‹€λ₯Έ μ˜ˆμ•½μ΄ 이미 μ‘΄μž¬ν•˜λ©΄ μ˜ˆμ™Έλ₯Ό λ°˜ν™˜ν•œλ‹€.
- κ΄€λ¦¬μžλŠ” 전체 μ˜ˆμ•½ λͺ©λ‘μ„ μ‘°νšŒν•œλ‹€.
- κ΄€λ¦¬μžλŠ” μ˜ˆμ•½ ID둜 μ˜ˆμ•½μ„ μ‚­μ œν•œλ‹€.

Expand Down Expand Up @@ -101,7 +108,7 @@

```json
{
"name": "μΏ ν‚€",
"name": "보예",
"dateId": 1,
"timeId": 2,
"themeId": 3
Expand All @@ -113,7 +120,7 @@
```json
{
"id": 29,
"name": "μΏ ν‚€",
"name": "보예",
"date": "2026-05-01",
"time": "11:00",
"theme": {
Expand All @@ -124,6 +131,55 @@
}
```

#### `GET /reservations?name={name}`

- μ„€λͺ…: μ‚¬μš©μž μ΄λ¦„μœΌλ‘œ μ˜ˆμ•½ λͺ©λ‘ 쑰회
- 응닡 `200 OK`

```json
{
"name": "보예",
"reservation": [
{
"reservationId": 29,
"date": {
"id": 1,
"startWhen": "2026-05-01"
},
"time": {
"id": 2,
"startAt": "11:00"
},
"theme": {
"id": 3,
"name": "청좘물",
"content": "학ꡐ 배경인 ν…Œλ§ˆ μž…λ‹ˆλ‹€.",
"url": "/themes/youth"
}
}
]
}
```

#### `PATCH /reservations/{id}`

- μ„€λͺ…: μ‚¬μš©μž μ˜ˆμ•½ λ‚ μ§œμ™€ μ‹œκ°„ λ³€κ²½
- μš”μ²­ λ³Έλ¬Έ

```json
{
"startWhen": "2026-05-10",
"startAt": "15:00"
}
```

- 응닡 `204 No Content`

#### `DELETE /reservations/{id}`

- μ„€λͺ…: μ‚¬μš©μž μ˜ˆμ•½ μ·¨μ†Œ
- 응닡 `204 No Content`

#### `DELETE /admin/reservations/{id}`

- μ„€λͺ…: μ˜ˆμ•½ μ‚­μ œ
Expand Down Expand Up @@ -190,7 +246,7 @@

### μ˜ˆμ•½ μ‹œκ°„

#### `GET /times?themeId={themeId}&dateId={dateId}`
#### `GET /reservation-times/availability?themeId={themeId}&dateId={dateId}`

- μ„€λͺ…: νŠΉμ • ν…Œλ§ˆμ™€ λ‚ μ§œμ˜ μ˜ˆμ•½ κ°€λŠ₯ μ‹œκ°„ 쑰회
- 응닡 `200 OK`
Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-validation'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/roomescape/config/TimeConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package roomescape.config;

import java.time.Clock;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TimeConfig {

@Bean
public Clock clock() {
return Clock.systemDefaultZone();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.sql.Statement;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
Expand Down Expand Up @@ -85,7 +86,53 @@ select count(*)
from reservation
where theme_id = ?
""";
;
private static final String EXISTS_RESERVATION_BY_TIME_AND_DATE_AND_THEME_SQL =
"""
select exists(
select 1
from reservation r
where time_id = ? and date_id = ? and theme_id = ?
)
""";
private static final String EXISTS_OTHER_RESERVATION_BY_TIME_AND_DATE_AND_THEME_SQL =
"""
select exists(
select 1
from reservation r
where r.id <> ? and time_id = ? and date_id = ? and theme_id = ?
)
""";
private static final String FIND_BY_NAME_SQL =
"""
select r.id, r.name,
rd.id as date_id, rd.date,
rt.id as time_id, rt.start_at,
th.id as theme_id, th.name as theme_name, th.content as theme_content, th.url as theme_url
from reservation r
join reservation_date rd on r.date_id = rd.id
join reservation_time rt on r.time_id = rt.id
join theme th on r.theme_id = th.id
where r.name = ?
order by rd.date desc, rt.start_at desc, r.id desc
""";
private static final String FIND_BY_ID_SQL =
"""
select r.id, r.name,
rd.id as date_id, rd.date,
rt.id as time_id, rt.start_at,
th.id as theme_id, th.name as theme_name, th.content as theme_content, th.url as theme_url
from reservation r
join reservation_date rd on r.date_id = rd.id
join reservation_time rt on r.time_id = rt.id
join theme th on r.theme_id = th.id
where r.id = ?
""";
private static final String UPDATE_SQL =
"""
update reservation
set name = ?, date_id = ?, time_id = ?, theme_id = ?
where id = ?
""";

private final JdbcTemplate jdbcTemplate;

Expand Down Expand Up @@ -151,6 +198,58 @@ public int countByThemeId(Long themeId) {
return count;
}

@Override
public boolean existsReservation(Long timeId, Long dateId, Long themeId) {
Boolean exists = jdbcTemplate.queryForObject(
EXISTS_RESERVATION_BY_TIME_AND_DATE_AND_THEME_SQL,
Boolean.class,
timeId,
dateId,
themeId
);
return exists != null && exists;
}

@Override
public boolean existsOtherReservation(Long id, Long timeId, Long dateId, Long themeId) {
Boolean exists = jdbcTemplate.queryForObject(
EXISTS_OTHER_RESERVATION_BY_TIME_AND_DATE_AND_THEME_SQL,
Boolean.class,
id,
timeId,
dateId,
themeId
);
return exists != null && exists;
}
Comment on lines +202 to +224

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

두 λ©”μ„œλ“œ λͺ¨λ‘ 쑴재 μ—¬λΆ€λ§Œ νŒλ‹¨ν•˜λŠ”λ° μΏΌλ¦¬λŠ” countλ₯Ό μ“°λ„€μš”? EXISTS 쿼리가 μ˜λ„μ— 더 λ§žμ§€ μ•Šμ„κΉŒμš”?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

κ·ΈλŸ¬λ„€μš”..!! exist둜 λ³€κ²½ν•˜κ³ , 쿼리문 넀이밍도 μ˜λ„λ₯Ό 더 잘 λ‚˜νƒ€λ‚΄λ„λ‘ EXIST둜 λ³€κ²½ν•΄μ€¬μŠ΅λ‹ˆλ‹€.


@Override
public List<Reservation> findByName(String name) {
return jdbcTemplate.query(FIND_BY_NAME_SQL, reservationRowMapper(), name);
}

@Override
public Optional<Reservation> findById(Long id) {
List<Reservation> result = jdbcTemplate.query(FIND_BY_ID_SQL, reservationRowMapper(), id);
return result.stream().findFirst();
}

@Override
public Optional<Reservation> update(Long id, Reservation withoutId) {
int updatedCount = jdbcTemplate.update(
UPDATE_SQL,
withoutId.getName(),
withoutId.getDate().getId(),
withoutId.getTime().getId(),
withoutId.getTheme().getId(),
id
);
if (updatedCount == 0) {
return Optional.empty();
}
return findById(id);
}

private RowMapper<Reservation> reservationRowMapper() {
return (rs, rowNum) -> Reservation.of(
rs.getLong(COLUMN_ID),
Expand Down
19 changes: 12 additions & 7 deletions src/main/java/roomescape/domain/reservation/Reservation.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
import roomescape.domain.reservationtime.ReservationTime;
import roomescape.domain.theme.Theme;
import roomescape.support.exception.BadRequestException;
import roomescape.support.exception.ReservationErrorCode;
import roomescape.support.exception.ReservationTimeErrorCode;
import roomescape.support.exception.ThemeErrorCode;
import roomescape.support.exception.errors.ReservationErrors;
import roomescape.support.exception.errors.ReservationTimeErrors;
import roomescape.support.exception.errors.ThemeErrors;

@Getter
public class Reservation {

private static final int MAX_NAME_LENGTH = 10;

private final Long id;
private final String name;
private final ReservationDate date;
Expand Down Expand Up @@ -76,16 +78,19 @@ public static Reservation of(

private static void validate(String name, ReservationDate date, ReservationTime time, Theme theme) {
if (name == null || name.isBlank()) {
throw new BadRequestException(ReservationErrorCode.INVALID_RESERVATION_NAME);
throw new BadRequestException(ReservationErrors.INVALID_RESERVATION_NAME);
}
if (name.length() > MAX_NAME_LENGTH) {
throw new BadRequestException(ReservationErrors.INVALID_RESERVATION_NAME_LENGTH);
}
if (date == null) {
throw new BadRequestException(ReservationErrorCode.INVALID_RESERVATION_DATE);
throw new BadRequestException(ReservationErrors.INVALID_RESERVATION_DATE);
}
if (time == null) {
throw new BadRequestException(ReservationTimeErrorCode.INVALID_RESERVATION_TIME);
throw new BadRequestException(ReservationTimeErrors.INVALID_RESERVATION_TIME);
}
if (theme == null) {
throw new BadRequestException(ThemeErrorCode.INVALID_THEME);
throw new BadRequestException(ThemeErrors.INVALID_THEME);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,50 +1,63 @@
package roomescape.domain.reservation;

import jakarta.servlet.http.HttpServletRequest;
import java.util.List;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import roomescape.support.auth.AdminRequestValidator;
import roomescape.domain.reservation.dto.CreateReservationRequest;
import roomescape.domain.reservation.dto.CreateReservationResponse;
import roomescape.domain.reservation.dto.ReservationResponse;
import roomescape.domain.reservation.dto.UpdateReservationRequest;
import roomescape.domain.reservation.dto.UserReservationResponse;

@Validated
@RestController
@RequiredArgsConstructor
public class ReservationController {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

μ„œλΉ„μŠ€ ν…ŒμŠ€νŠΈμ˜ κ²½μš°μ—λŠ” 잘 μž‘μ„±ν•΄μ£Όμ…¨λŠ”λ° Controller ν˜Ήμ€ e2e ν…ŒμŠ€νŠΈλŠ” λ”°λ‘œ μ•ˆλ³΄μ΄λ„€μš”? λΉ„μ§€λ‹ˆμŠ€ 둜직이 μ–΄μ°¨ν”Ό μ„œλΉ„μŠ€μ—μ„œ ν…ŒμŠ€νŠΈκ°€ 됐닀고 μƒκ°ν•˜μ‹€ 수 도 μžˆλŠ”λ°, 각각의 관심사와 λŒ€μƒμ΄ μ‘°κΈˆμ€ λ‹€λ₯΄λ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. μ–΄λ–€ ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ“€μ΄ μžˆμ„ 수 μžˆμ„κΉŒμš”?


private final ReservationService reservationService;
private final AdminRequestValidator validator;

@GetMapping("/admin/reservations")
public ResponseEntity<List<ReservationResponse>> getAllReservation(HttpServletRequest request) {
if (validator.isUnauthorized(request)) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
List<ReservationResponse> response = reservationService.getAllReservations();
return ResponseEntity.ok(response);
}

@PostMapping("/reservations")
public ResponseEntity<CreateReservationResponse> createReservation(@RequestBody CreateReservationRequest request) {
request.validate();
public ResponseEntity<CreateReservationResponse> createReservation(
@Valid @RequestBody CreateReservationRequest request
) {
CreateReservationResponse response = reservationService.createReservation(request);
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}

@DeleteMapping("/admin/reservations/{id}")
public ResponseEntity<Void> deleteReservation(HttpServletRequest request, @PathVariable Long id) {
if (validator.isUnauthorized(request)) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
reservationService.deleteReservation(id);
@GetMapping("/reservations")
public ResponseEntity<UserReservationResponse> getUserReservations(
@RequestParam
@NotBlank(message = "μ˜ˆμ•½μž 이름은 ν•„μˆ˜ μž…λ ₯κ°’ μž…λ‹ˆλ‹€.")
String name
) {
UserReservationResponse response = reservationService.getUserReservations(name);
return ResponseEntity.ok(response);
}

@DeleteMapping("/reservations/{id}")
public ResponseEntity<Void> deleteUserReservation(
@PathVariable Long id
) {
reservationService.cancelUserReservation(id);
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}

@PatchMapping("/reservations/{id}")
public ResponseEntity<Void> updateReservation(
@PathVariable Long id,
@RequestBody UpdateReservationRequest request
) {
reservationService.updateReservation(id, request);
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import roomescape.domain.theme.Theme;

public interface ReservationRepository {
Expand All @@ -21,4 +22,14 @@ public interface ReservationRepository {
List<Theme> findPopularThemes(int rankLimit, LocalDate startDay, LocalDate today);

int countByThemeId(Long id);

boolean existsReservation(Long timeId, Long dateId, Long themeId);

boolean existsOtherReservation(Long id, Long timeId, Long dateId, Long themeId);

List<Reservation> findByName(String name);

Optional<Reservation> findById(Long id);

Optional<Reservation> update(Long id, Reservation withoutId);
}
Loading