diff --git a/build.gradle b/build.gradle index 804845513..11f6d9943 100644 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' - implementation 'org.springframework.boot:spring-boot-starter-jdbc' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'dev.akkinoc.spring.boot:logback-access-spring-boot-starter:4.0.0' diff --git a/src/main/java/roomescape/auth/AuthService.java b/src/main/java/roomescape/auth/AuthService.java index cc5a2b8dd..f29f4e39a 100644 --- a/src/main/java/roomescape/auth/AuthService.java +++ b/src/main/java/roomescape/auth/AuthService.java @@ -3,6 +3,7 @@ import org.springframework.stereotype.Service; import roomescape.auth.dto.LoginResponse; import roomescape.member.domain.Member; +import roomescape.member.dto.MemberAuthInfo; @Service public class AuthService { @@ -13,11 +14,11 @@ public AuthService(JwtTokenProvider jwtTokenProvider) { this.jwtTokenProvider = jwtTokenProvider; } - public LoginResponse createToken(Member member) { + public LoginResponse createToken(MemberAuthInfo memberAuthInfo) { String accessToken = jwtTokenProvider.createToken( - member.getId(), - member.getName(), - member.getRole().name()); + memberAuthInfo.memberId(), + memberAuthInfo.name(), + memberAuthInfo.stringRole()); return new LoginResponse(accessToken); } diff --git a/src/main/java/roomescape/member/MemberController.java b/src/main/java/roomescape/member/MemberController.java index 0488f430e..f451a0a60 100644 --- a/src/main/java/roomescape/member/MemberController.java +++ b/src/main/java/roomescape/member/MemberController.java @@ -15,6 +15,7 @@ import roomescape.auth.dto.LoginRequest; import roomescape.auth.dto.LoginResponse; import roomescape.member.domain.Member; +import roomescape.member.dto.MemberAuthInfo; import roomescape.member.dto.MemberRequest; import roomescape.member.dto.MemberResponse; @@ -44,8 +45,9 @@ public ResponseEntity createMember(@RequestBody MemberRequest memberRequest) { @PostMapping("/login") public ResponseEntity login(@RequestBody LoginRequest loginRequest, HttpServletResponse httpServletResponse) { - Member member = memberService.getMemberWithLoginRequest(loginRequest); - LoginResponse loginResponse = authService.createToken(member); + MemberAuthInfo memberAuthInfo = memberService.getMemberWithLoginRequest( + loginRequest); + LoginResponse loginResponse = authService.createToken(memberAuthInfo); Cookie cookie = new Cookie("token", loginResponse.accessToken()); cookie.setHttpOnly(true); diff --git a/src/main/java/roomescape/member/MemberDao.java b/src/main/java/roomescape/member/MemberDao.java index 5517952e0..7cb00c570 100644 --- a/src/main/java/roomescape/member/MemberDao.java +++ b/src/main/java/roomescape/member/MemberDao.java @@ -1,74 +1,74 @@ -package roomescape.member; - -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.support.GeneratedKeyHolder; -import org.springframework.jdbc.support.KeyHolder; -import org.springframework.stereotype.Repository; -import roomescape.member.domain.Member; -import roomescape.member.domain.Role; - -@Repository -public class MemberDao { - - private JdbcTemplate jdbcTemplate; - - public MemberDao(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - public Member save(Member member) { - KeyHolder keyHolder = new GeneratedKeyHolder(); - jdbcTemplate.update(connection -> { - var ps = connection.prepareStatement( - "INSERT INTO member(name, email, password, role) VALUES (?, ?, ?, ?)", - new String[]{"id"}); - ps.setString(1, member.getName()); - ps.setString(2, member.getEmail()); - ps.setString(3, member.getPassword()); - ps.setString(4, member.getRole().name()); - return ps; - }, keyHolder); - - return new Member(keyHolder.getKey().longValue(), member.getName(), member.getEmail(), - Role.USER); - } - - public Member findByEmailAndPassword(String email, String password) { - return jdbcTemplate.queryForObject( - "SELECT id, name, email, role FROM member WHERE email = ? AND password = ?", - (rs, rowNum) -> new Member( - rs.getLong("id"), - rs.getString("name"), - rs.getString("email"), - Role.valueOf(rs.getString("role")) - ), - email, password - ); - } - - public Member findByName(String name) { - return jdbcTemplate.queryForObject( - "SELECT id, name, email, role FROM member WHERE name = ?", - (rs, rowNum) -> new Member( - rs.getLong("id"), - rs.getString("name"), - rs.getString("email"), - Role.valueOf(rs.getString("role")) - ), - name - ); - } - - public Member findById(Long id) { - return jdbcTemplate.queryForObject( - "SELECT id, name, email, role FROM member WHERE id = ?", - (rs, rowNum) -> new Member( - rs.getLong("id"), - rs.getString("name"), - rs.getString("email"), - Role.valueOf(rs.getString("role")) - ), - id - ); - } -} +//package roomescape.member; +// +//import org.springframework.jdbc.core.JdbcTemplate; +//import org.springframework.jdbc.support.GeneratedKeyHolder; +//import org.springframework.jdbc.support.KeyHolder; +//import org.springframework.stereotype.Repository; +//import roomescape.member.domain.Member; +//import roomescape.member.domain.Role; +// +//@Repository +//public class MemberDao { +// +// private JdbcTemplate jdbcTemplate; +// +// public MemberDao(JdbcTemplate jdbcTemplate) { +// this.jdbcTemplate = jdbcTemplate; +// } +// +// public Member save(Member member) { +// KeyHolder keyHolder = new GeneratedKeyHolder(); +// jdbcTemplate.update(connection -> { +// var ps = connection.prepareStatement( +// "INSERT INTO member(name, email, password, role) VALUES (?, ?, ?, ?)", +// new String[]{"id"}); +// ps.setString(1, member.getName()); +// ps.setString(2, member.getEmail()); +// ps.setString(3, member.getPassword()); +// ps.setString(4, member.getRole().name()); +// return ps; +// }, keyHolder); +// +// return new Member(keyHolder.getKey().longValue(), member.getName(), member.getEmail(), +// Role.USER); +// } +// +// public Member findByEmailAndPassword(String email, String password) { +// return jdbcTemplate.queryForObject( +// "SELECT id, name, email, role FROM member WHERE email = ? AND password = ?", +// (rs, rowNum) -> new Member( +// rs.getLong("id"), +// rs.getString("name"), +// rs.getString("email"), +// Role.valueOf(rs.getString("role")) +// ), +// email, password +// ); +// } +// +// public Member findByName(String name) { +// return jdbcTemplate.queryForObject( +// "SELECT id, name, email, role FROM member WHERE name = ?", +// (rs, rowNum) -> new Member( +// rs.getLong("id"), +// rs.getString("name"), +// rs.getString("email"), +// Role.valueOf(rs.getString("role")) +// ), +// name +// ); +// } +// +// public Member findById(Long id) { +// return jdbcTemplate.queryForObject( +// "SELECT id, name, email, role FROM member WHERE id = ?", +// (rs, rowNum) -> new Member( +// rs.getLong("id"), +// rs.getString("name"), +// rs.getString("email"), +// Role.valueOf(rs.getString("role")) +// ), +// id +// ); +// } +//} diff --git a/src/main/java/roomescape/member/MemberService.java b/src/main/java/roomescape/member/MemberService.java index e9dd53470..c8f233bdf 100644 --- a/src/main/java/roomescape/member/MemberService.java +++ b/src/main/java/roomescape/member/MemberService.java @@ -1,38 +1,46 @@ package roomescape.member; +import java.util.Optional; import org.springframework.stereotype.Service; import roomescape.auth.dto.LoginRequest; import roomescape.member.domain.Member; import roomescape.member.domain.Role; +import roomescape.member.dto.MemberAuthInfo; import roomescape.member.dto.MemberRequest; import roomescape.member.dto.MemberResponse; +import roomescape.member.repository.MemberRepository; @Service public class MemberService { - private MemberDao memberDao; + private MemberRepository memberRepository; - public MemberService(MemberDao memberDao) { - this.memberDao = memberDao; + public MemberService(MemberRepository memberRepository) { + this.memberRepository = memberRepository; } public MemberResponse createMember(MemberRequest memberRequest) { - Member member = memberDao.save(new Member(memberRequest.name(), memberRequest.email(), - memberRequest.password(), Role.USER)); + Member member = memberRepository.save( + new Member(memberRequest.name(), memberRequest.email(), + memberRequest.password(), Role.USER)); return new MemberResponse(member.getId(), member.getName(), member.getEmail()); } - public Member getMemberWithLoginRequest(LoginRequest loginRequest) { - return memberDao.findByEmailAndPassword( + public MemberAuthInfo getMemberWithLoginRequest(LoginRequest loginRequest) { + Optional memberOptional = memberRepository.findByEmailAndPassword( loginRequest.email(), loginRequest.password()); - } + Member member = memberOptional.orElseThrow(); + + return new MemberAuthInfo( + member.getId(), + member.getName(), + member.getRole().name() + ); - public Member findById(Long id) { - return memberDao.findById(id); } - public Member findByName(String name) { - return memberDao.findByName(name); + public Optional findByName(String name) { + return memberRepository.findByName(name); } } diff --git a/src/main/java/roomescape/member/domain/Member.java b/src/main/java/roomescape/member/domain/Member.java index b07249cb6..58b602eac 100644 --- a/src/main/java/roomescape/member/domain/Member.java +++ b/src/main/java/roomescape/member/domain/Member.java @@ -1,13 +1,35 @@ package roomescape.member.domain; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import java.util.HashSet; +import java.util.Set; +import roomescape.reservation.domain.Reservation; + +@Entity public class Member { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + private String name; + private String email; + private String password; + + @Enumerated(EnumType.STRING) private Role role; + @OneToMany(mappedBy = "member") + private Set reservations = new HashSet<>(); + public Member(Long id, String name, String email, Role role) { this.id = id; this.name = name; @@ -22,6 +44,10 @@ public Member(String name, String email, String password, Role role) { this.role = role; } + public Member() { + + } + public Long getId() { return id; } @@ -41,4 +67,8 @@ public String getPassword() { public Role getRole() { return role; } + + public Set getReservations() { + return reservations; + } } diff --git a/src/main/java/roomescape/member/dto/MemberAuthInfo.java b/src/main/java/roomescape/member/dto/MemberAuthInfo.java new file mode 100644 index 000000000..c05c8cf90 --- /dev/null +++ b/src/main/java/roomescape/member/dto/MemberAuthInfo.java @@ -0,0 +1,5 @@ +package roomescape.member.dto; + +public record MemberAuthInfo(Long memberId, String name, String stringRole) { + +} diff --git a/src/main/java/roomescape/member/repository/MemberRepository.java b/src/main/java/roomescape/member/repository/MemberRepository.java new file mode 100644 index 000000000..9d2c66592 --- /dev/null +++ b/src/main/java/roomescape/member/repository/MemberRepository.java @@ -0,0 +1,12 @@ +package roomescape.member.repository; + +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import roomescape.member.domain.Member; + +public interface MemberRepository extends JpaRepository { + + Optional findByName(String name); + + Optional findByEmailAndPassword(String email, String password); +} diff --git a/src/main/java/roomescape/reservation/ReservationController.java b/src/main/java/roomescape/reservation/ReservationController.java index 7066756f3..9a80200b3 100644 --- a/src/main/java/roomescape/reservation/ReservationController.java +++ b/src/main/java/roomescape/reservation/ReservationController.java @@ -15,8 +15,11 @@ import roomescape.member.domain.Member; import roomescape.member.domain.Role; import roomescape.member.MemberService; +import roomescape.reservation.dto.MyReservationResponse; import roomescape.reservation.dto.ReservationRequest; import roomescape.reservation.dto.ReservationResponse; +import roomescape.reservation.dto.WaitingRequest; +import roomescape.reservation.dto.WaitingResponse; @RestController public class ReservationController { @@ -35,6 +38,11 @@ public List list() { return reservationService.findAll(); } + @GetMapping("/reservations-mine") + public List getMyReservations(@LoginMember Member member) { + return reservationService.findByMember(member); + } + @PostMapping("/reservations") public ResponseEntity create(@RequestBody @Valid ReservationRequest reservationRequest, @LoginMember Member loginMember) { @@ -45,10 +53,24 @@ public ResponseEntity create(@RequestBody @Valid ReservationRequest reservationR .body(reservation); } - @DeleteMapping("/reservations/{id}") - public ResponseEntity delete(@PathVariable Long id) { - reservationService.deleteById(id); + public ResponseEntity delete(@PathVariable Long id, @LoginMember Member member) { + reservationService.deleteById(id, member); + return ResponseEntity.noContent().build(); + } + + @PostMapping("/waitings") + public ResponseEntity createWaiting(@RequestBody @Valid WaitingRequest waitingRequest, + @LoginMember Member loginMember) { + WaitingResponse waiting = reservationService.saveWaiting(waitingRequest, loginMember); + + return ResponseEntity.created(URI.create("/reservations/" + waiting.id())) + .body(waiting); + } + + @DeleteMapping("/waitings/cancel/{id}") + public ResponseEntity cancelWaiting(@PathVariable Long id, @LoginMember Member member) { + reservationService.deleteWaitingById(id, member); return ResponseEntity.noContent().build(); } @@ -57,7 +79,7 @@ private Member resolveReservationMember(ReservationRequest reservationRequest, Member member; if (loginMember.getRole() == Role.ADMIN && reservationRequest.name() != null) { - member = memberService.findByName(reservationRequest.name()); + member = memberService.findByName(reservationRequest.name()).orElseThrow(); return member; } return loginMember; diff --git a/src/main/java/roomescape/reservation/ReservationDao.java b/src/main/java/roomescape/reservation/ReservationDao.java deleted file mode 100644 index a910a46a4..000000000 --- a/src/main/java/roomescape/reservation/ReservationDao.java +++ /dev/null @@ -1,111 +0,0 @@ -package roomescape.reservation; - -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.support.GeneratedKeyHolder; -import org.springframework.jdbc.support.KeyHolder; -import org.springframework.stereotype.Repository; -import roomescape.reservation.domain.Reservation; -import roomescape.reservation.dto.ReservationRequest; -import roomescape.theme.domain.Theme; -import roomescape.time.domain.Time; - -import java.sql.PreparedStatement; -import java.util.List; - -@Repository -public class ReservationDao { - - private final JdbcTemplate jdbcTemplate; - - public ReservationDao(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - public List findAll() { - return jdbcTemplate.query( - "SELECT r.id AS reservation_id, r.name as reservation_name, r.date as reservation_date, " - + - "t.id AS theme_id, t.name AS theme_name, t.description AS theme_description, " - + - "ti.id AS time_id, ti.time_value AS time_value " + - "FROM reservation r " + - "JOIN theme t ON r.theme_id = t.id " + - "JOIN time ti ON r.time_id = ti.id", - - (rs, rowNum) -> new Reservation( - rs.getLong("reservation_id"), - rs.getString("reservation_name"), - rs.getString("reservation_date"), - new Time( - rs.getLong("time_id"), - rs.getString("time_value") - ), - new Theme( - rs.getLong("theme_id"), - rs.getString("theme_name"), - rs.getString("theme_description") - ))); - } - - public Reservation save(ReservationRequest reservationRequest, String name) { - KeyHolder keyHolder = new GeneratedKeyHolder(); - jdbcTemplate.update(connection -> { - PreparedStatement ps = connection.prepareStatement( - "INSERT INTO reservation(date, name, theme_id, time_id) VALUES (?, ?, ?, ?)", - new String[]{"id"}); - ps.setString(1, reservationRequest.date()); - ps.setString(2, name); - ps.setLong(3, reservationRequest.theme()); - ps.setLong(4, reservationRequest.time()); - return ps; - }, keyHolder); - - Time time = jdbcTemplate.queryForObject("SELECT * FROM time WHERE id = ?", - (rs, rowNum) -> new Time(rs.getLong("id"), rs.getString("time_value")), - reservationRequest.time()); - - Theme theme = jdbcTemplate.queryForObject("SELECT * FROM theme WHERE id = ?", - (rs, rowNum) -> new Theme(rs.getLong("id"), rs.getString("name"), - rs.getString("description")), - reservationRequest.theme()); - - return new Reservation( - keyHolder.getKey().longValue(), - name, - reservationRequest.date(), - time, - theme - ); - } - - public void deleteById(Long id) { - jdbcTemplate.update("DELETE FROM reservation WHERE id = ?", id); - } - - public List findByDateAndThemeId(String date, Long themeId) { - return jdbcTemplate.query( - "SELECT r.id AS reservation_id, r.name as reservation_name, r.date as reservation_date, " - + - "t.id AS theme_id, t.name AS theme_name, t.description AS theme_description, " - + - "ti.id AS time_id, ti.time_value AS time_value " + - "FROM reservation r " + - "JOIN theme t ON r.theme_id = t.id " + - "JOIN time ti ON r.time_id = ti.id " + - "WHERE r.date = ? AND r.theme_id = ?", - new Object[]{date, themeId}, - (rs, rowNum) -> new Reservation( - rs.getLong("reservation_id"), - rs.getString("reservation_name"), - rs.getString("reservation_date"), - new Time( - rs.getLong("time_id"), - rs.getString("time_value") - ), - new Theme( - rs.getLong("theme_id"), - rs.getString("theme_name"), - rs.getString("theme_description") - ))); - } -} diff --git a/src/main/java/roomescape/reservation/ReservationService.java b/src/main/java/roomescape/reservation/ReservationService.java index 4e9bb3b2d..fda73afd7 100644 --- a/src/main/java/roomescape/reservation/ReservationService.java +++ b/src/main/java/roomescape/reservation/ReservationService.java @@ -1,38 +1,136 @@ package roomescape.reservation; +import java.util.NoSuchElementException; +import java.util.stream.Stream; import org.springframework.stereotype.Service; import roomescape.member.domain.Member; +import roomescape.member.domain.Role; import roomescape.reservation.domain.Reservation; +import roomescape.reservation.domain.Waiting; +import roomescape.reservation.dto.MyReservationResponse; import roomescape.reservation.dto.ReservationRequest; import roomescape.reservation.dto.ReservationResponse; import java.util.List; +import roomescape.reservation.dto.WaitingRequest; +import roomescape.reservation.dto.WaitingResponse; +import roomescape.reservation.repository.ReservationRepository; +import roomescape.reservation.repository.WaitingRepository; +import roomescape.theme.domain.Theme; +import roomescape.theme.repository.ThemeRepository; +import roomescape.time.domain.Time; +import roomescape.time.repository.TimeRepository; @Service public class ReservationService { - private ReservationDao reservationDao; + private final ReservationRepository reservationRepository; + private final WaitingRepository waitingRepository; + private final TimeRepository timeRepository; + private final ThemeRepository themeRepository; - public ReservationService(ReservationDao reservationDao) { - this.reservationDao = reservationDao; + public ReservationService(ReservationRepository reservationRepository, + TimeRepository timeRepository, ThemeRepository themeRepository, + WaitingRepository waitingRepository) { + this.reservationRepository = reservationRepository; + this.timeRepository = timeRepository; + this.themeRepository = themeRepository; + this.waitingRepository = waitingRepository; } public ReservationResponse save(ReservationRequest reservationRequest, Member member) { - Reservation reservation = reservationDao.save(reservationRequest, member.getName()); + Time time = timeRepository.findById(reservationRequest.timeId()) + .orElseThrow(() -> new NoSuchElementException("time not found")); + Theme theme = themeRepository.findById(reservationRequest.themeId()) + .orElseThrow(() -> new NoSuchElementException("theme not found")); + + Reservation reservation = reservationRepository.save( + new Reservation( + reservationRequest.name(), + reservationRequest.date(), + time, + theme, + member + ) + ); return new ReservationResponse(reservation.getId(), member.getName(), reservation.getTheme().getName(), reservation.getDate(), reservation.getTime().getValue()); } - public void deleteById(Long id) { - reservationDao.deleteById(id); + public WaitingResponse saveWaiting(WaitingRequest waitingRequest, Member member) { + Time time = timeRepository.findById(waitingRequest.timeId()) + .orElseThrow(() -> new NoSuchElementException("time not found")); + Theme theme = themeRepository.findById(waitingRequest.themeId()) + .orElseThrow(() -> new NoSuchElementException("theme not found")); + + Waiting waiting = waitingRepository.save( + new Waiting( + waitingRequest.date(), + time, + theme, + member + ) + ); + + long rank = waitingRepository.countByDateAndTimeIdAndThemeIdAndIdLessThan( + waitingRequest.date(), + waitingRequest.timeId(), + waitingRequest.themeId(), + waiting.getId()); + + return new WaitingResponse( + waiting.getId(), + waiting.getTheme().getName(), + waiting.getDate(), + waiting.getTime().getValue(), + rank + ); + } + + public List findByMember(Member member) { + + Stream reservations = reservationRepository.findByMemberId( + member.getId()).stream() + .map(MyReservationResponse::ofReservation); + + Stream waitings = waitingRepository.findByMemberId( + member.getId()).stream() + .map(w -> { + long rank = waitingRepository.countByDateAndTimeIdAndThemeIdAndIdLessThan( + w.getDate(), w.getTime().getId(), w.getTheme().getId(), w.getId()) + 1; + return MyReservationResponse.ofWaiting(w, rank); + }); + + return Stream.concat(reservations, waitings).toList(); + } + + public void deleteById(Long id, Member member) { + Reservation reservation = reservationRepository.findById(id) + .orElseThrow(() -> new NoSuchElementException("reservation not found")); + + if (member.getRole() != Role.ADMIN && !reservation.getMember().getId().equals(member.getId())) { + throw new IllegalArgumentException("본인의 예약만 취소할 수 있습니다."); + } + + reservationRepository.deleteById(id); } public List findAll() { - return reservationDao.findAll().stream() + return reservationRepository.findAll().stream() .map(it -> new ReservationResponse(it.getId(), it.getName(), it.getTheme().getName(), it.getDate(), it.getTime().getValue())) .toList(); } + + public void deleteWaitingById(Long id, Member member) { + Waiting waiting = waitingRepository.findById(id) + .orElseThrow(() -> new NoSuchElementException("waiting not found")); + + if (member.getRole() != Role.ADMIN && !waiting.getMember().getId().equals(member.getId())) { + throw new IllegalArgumentException("본인의 예약대기만 취소할 수 있습니다."); + } + waitingRepository.deleteById(id); + } } diff --git a/src/main/java/roomescape/reservation/domain/Reservation.java b/src/main/java/roomescape/reservation/domain/Reservation.java index 37351db1d..95fd224f0 100644 --- a/src/main/java/roomescape/reservation/domain/Reservation.java +++ b/src/main/java/roomescape/reservation/domain/Reservation.java @@ -1,16 +1,36 @@ package roomescape.reservation.domain; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import roomescape.member.domain.Member; import roomescape.theme.domain.Theme; import roomescape.time.domain.Time; +@Entity public class Reservation { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + private String name; + private String date; + + @ManyToOne(fetch = FetchType.LAZY) private Time time; + + @ManyToOne(fetch = FetchType.LAZY) private Theme theme; + @ManyToOne(fetch = FetchType.LAZY) + private Member member; + + // 테스트 용도의 생성자? public Reservation(Long id, String name, String date, Time time, Theme theme) { this.id = id; this.name = name; @@ -19,11 +39,12 @@ public Reservation(Long id, String name, String date, Time time, Theme theme) { this.theme = theme; } - public Reservation(String name, String date, Time time, Theme theme) { + public Reservation(String name, String date, Time time, Theme theme, Member member) { this.name = name; this.date = date; this.time = time; this.theme = theme; + this.member = member; } public Reservation() { @@ -33,6 +54,10 @@ public Long getId() { return id; } + public Member getMember() { + return member; + } + public String getName() { return name; } diff --git a/src/main/java/roomescape/reservation/domain/Waiting.java b/src/main/java/roomescape/reservation/domain/Waiting.java new file mode 100644 index 000000000..c0dc94210 --- /dev/null +++ b/src/main/java/roomescape/reservation/domain/Waiting.java @@ -0,0 +1,69 @@ +package roomescape.reservation.domain; + +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import roomescape.member.domain.Member; +import roomescape.theme.domain.Theme; +import roomescape.time.domain.Time; + +@Entity +public class Waiting { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String date; + + @ManyToOne(fetch = FetchType.LAZY) + private Time time; + + @ManyToOne(fetch = FetchType.LAZY) + private Theme theme; + + @ManyToOne(fetch = FetchType.LAZY) + private Member member; + + public Waiting(Long id, String date, Time time, Theme theme, Member member) { + this.id = id; + this.date = date; + this.time = time; + this.theme = theme; + this.member = member; + } + + public Waiting(String date, Time time, Theme theme, Member member) { + this.date = date; + this.time = time; + this.theme = theme; + this.member = member; + } + + public Waiting() { + + } + + public Long getId() { + return id; + } + + public String getDate() { + return date; + } + + public Time getTime() { + return time; + } + + public Theme getTheme() { + return theme; + } + + public Member getMember() { + return member; + } +} diff --git a/src/main/java/roomescape/reservation/dto/MyReservationResponse.java b/src/main/java/roomescape/reservation/dto/MyReservationResponse.java new file mode 100644 index 000000000..e3d0870ff --- /dev/null +++ b/src/main/java/roomescape/reservation/dto/MyReservationResponse.java @@ -0,0 +1,26 @@ +package roomescape.reservation.dto; + +import roomescape.reservation.domain.Reservation; +import roomescape.reservation.domain.Waiting; + +public record MyReservationResponse( + Long reservationId, + String theme, + String date, + String time, + String status +) { + + public static MyReservationResponse ofReservation(Reservation reservation) { + return new MyReservationResponse( + reservation.getId(), reservation.getTheme().getName(), reservation.getDate(), + reservation.getTime().getValue(), "예약"); + } + + public static MyReservationResponse ofWaiting(Waiting waiting, long rank) { + return new MyReservationResponse( + waiting.getId(), waiting.getTheme().getName(), waiting.getDate(), + waiting.getTime().getValue(), + rank + "번째 예약대기"); + } +} diff --git a/src/main/java/roomescape/reservation/dto/ReservationRequest.java b/src/main/java/roomescape/reservation/dto/ReservationRequest.java index 2b31e6d22..d50e7c5c4 100644 --- a/src/main/java/roomescape/reservation/dto/ReservationRequest.java +++ b/src/main/java/roomescape/reservation/dto/ReservationRequest.java @@ -5,7 +5,7 @@ public record ReservationRequest( String name, @NotNull String date, - @NotNull Long theme, - @NotNull Long time + @NotNull Long themeId, + @NotNull Long timeId ) { } \ No newline at end of file diff --git a/src/main/java/roomescape/reservation/dto/ReservationResponse.java b/src/main/java/roomescape/reservation/dto/ReservationResponse.java index 6d573a739..8af28223f 100644 --- a/src/main/java/roomescape/reservation/dto/ReservationResponse.java +++ b/src/main/java/roomescape/reservation/dto/ReservationResponse.java @@ -1,4 +1,11 @@ package roomescape.reservation.dto; -public record ReservationResponse(Long id, String name, String theme, String date, String time) { +public record ReservationResponse( + Long id, + String name, + String theme, + String date, + String time +) { + } \ No newline at end of file diff --git a/src/main/java/roomescape/reservation/dto/WaitingRequest.java b/src/main/java/roomescape/reservation/dto/WaitingRequest.java new file mode 100644 index 000000000..3b2e78e65 --- /dev/null +++ b/src/main/java/roomescape/reservation/dto/WaitingRequest.java @@ -0,0 +1,11 @@ +package roomescape.reservation.dto; + +import org.jetbrains.annotations.NotNull; + +public record WaitingRequest ( + @NotNull String date, + @NotNull Long timeId, + @NotNull Long themeId +) { + +} diff --git a/src/main/java/roomescape/reservation/dto/WaitingResponse.java b/src/main/java/roomescape/reservation/dto/WaitingResponse.java new file mode 100644 index 000000000..c3955fc2b --- /dev/null +++ b/src/main/java/roomescape/reservation/dto/WaitingResponse.java @@ -0,0 +1,12 @@ +package roomescape.reservation.dto; + + +public record WaitingResponse ( + Long id, + String theme, + String date, + String time, + Long rank +) { + +} diff --git a/src/main/java/roomescape/reservation/repository/ReservationRepository.java b/src/main/java/roomescape/reservation/repository/ReservationRepository.java new file mode 100644 index 000000000..f17ebb04c --- /dev/null +++ b/src/main/java/roomescape/reservation/repository/ReservationRepository.java @@ -0,0 +1,12 @@ +package roomescape.reservation.repository; + +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import roomescape.reservation.domain.Reservation; + +public interface ReservationRepository extends JpaRepository { + + List findByDateAndThemeId(String date, Long themeId); + + List findByMemberId(Long memberId); +} diff --git a/src/main/java/roomescape/reservation/repository/WaitingRepository.java b/src/main/java/roomescape/reservation/repository/WaitingRepository.java new file mode 100644 index 000000000..cd9584678 --- /dev/null +++ b/src/main/java/roomescape/reservation/repository/WaitingRepository.java @@ -0,0 +1,16 @@ +package roomescape.reservation.repository; + +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import roomescape.reservation.domain.Waiting; + +public interface WaitingRepository extends JpaRepository { + + List findByMemberId(Long memberId); + + long countByDateAndTimeIdAndThemeIdAndIdLessThan( + String date, + Long timeId, + Long themeId, + Long id); +} diff --git a/src/main/java/roomescape/theme/ThemeController.java b/src/main/java/roomescape/theme/ThemeController.java index 918fde6c1..a7e6abee1 100644 --- a/src/main/java/roomescape/theme/ThemeController.java +++ b/src/main/java/roomescape/theme/ThemeController.java @@ -11,30 +11,31 @@ import java.net.URI; import java.util.List; import roomescape.theme.domain.Theme; +import roomescape.theme.repository.ThemeRepository; @RestController public class ThemeController { - private ThemeDao themeDao; + private ThemeRepository themeRepository; - public ThemeController(ThemeDao themeDao) { - this.themeDao = themeDao; + public ThemeController(ThemeRepository themeRepository) { + this.themeRepository = themeRepository; } @PostMapping("/themes") public ResponseEntity createTheme(@RequestBody Theme theme) { - Theme newTheme = themeDao.save(theme); + Theme newTheme = themeRepository.save(theme); return ResponseEntity.created(URI.create("/themes/" + newTheme.getId())).body(newTheme); } @GetMapping("/themes") public ResponseEntity> list() { - return ResponseEntity.ok(themeDao.findAll()); + return ResponseEntity.ok(themeRepository.findAll()); } @DeleteMapping("/themes/{id}") public ResponseEntity deleteTheme(@PathVariable Long id) { - themeDao.deleteById(id); + themeRepository.deleteById(id); return ResponseEntity.noContent().build(); } } diff --git a/src/main/java/roomescape/theme/ThemeDao.java b/src/main/java/roomescape/theme/ThemeDao.java index 267f2070e..20b78d1d4 100644 --- a/src/main/java/roomescape/theme/ThemeDao.java +++ b/src/main/java/roomescape/theme/ThemeDao.java @@ -1,45 +1,45 @@ -package roomescape.theme; - -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.support.GeneratedKeyHolder; -import org.springframework.jdbc.support.KeyHolder; -import org.springframework.stereotype.Repository; -import roomescape.theme.domain.Theme; - -import java.util.List; - -@Repository -public class ThemeDao { - - private JdbcTemplate jdbcTemplate; - - public ThemeDao(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - public List findAll() { - return jdbcTemplate.query("SELECT * FROM theme where deleted = false", - (rs, rowNum) -> new Theme( - rs.getLong("id"), - rs.getString("name"), - rs.getString("description") - )); - } - - public Theme save(Theme theme) { - KeyHolder keyHolder = new GeneratedKeyHolder(); - jdbcTemplate.update(connection -> { - var ps = connection.prepareStatement( - "INSERT INTO theme(name, description) VALUES (?, ?)", new String[]{"id"}); - ps.setString(1, theme.getName()); - ps.setString(2, theme.getDescription()); - return ps; - }, keyHolder); - - return new Theme(keyHolder.getKey().longValue(), theme.getName(), theme.getDescription()); - } - - public void deleteById(Long id) { - jdbcTemplate.update("UPDATE theme SET deleted = true WHERE id = ?", id); - } -} +//package roomescape.theme; +// +//import org.springframework.jdbc.core.JdbcTemplate; +//import org.springframework.jdbc.support.GeneratedKeyHolder; +//import org.springframework.jdbc.support.KeyHolder; +//import org.springframework.stereotype.Repository; +//import roomescape.theme.domain.Theme; +// +//import java.util.List; +// +//@Repository +//public class ThemeDao { +// +// private JdbcTemplate jdbcTemplate; +// +// public ThemeDao(JdbcTemplate jdbcTemplate) { +// this.jdbcTemplate = jdbcTemplate; +// } +// +// public List findAll() { +// return jdbcTemplate.query("SELECT * FROM theme where deleted = false", +// (rs, rowNum) -> new Theme( +// rs.getLong("id"), +// rs.getString("name"), +// rs.getString("description") +// )); +// } +// +// public Theme save(Theme theme) { +// KeyHolder keyHolder = new GeneratedKeyHolder(); +// jdbcTemplate.update(connection -> { +// var ps = connection.prepareStatement( +// "INSERT INTO theme(name, description) VALUES (?, ?)", new String[]{"id"}); +// ps.setString(1, theme.getName()); +// ps.setString(2, theme.getDescription()); +// return ps; +// }, keyHolder); +// +// return new Theme(keyHolder.getKey().longValue(), theme.getName(), theme.getDescription()); +// } +// +// public void deleteById(Long id) { +// jdbcTemplate.update("UPDATE theme SET deleted = true WHERE id = ?", id); +// } +//} diff --git a/src/main/java/roomescape/theme/domain/Theme.java b/src/main/java/roomescape/theme/domain/Theme.java index 94373f22a..107392a2c 100644 --- a/src/main/java/roomescape/theme/domain/Theme.java +++ b/src/main/java/roomescape/theme/domain/Theme.java @@ -1,11 +1,28 @@ package roomescape.theme.domain; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import java.util.HashSet; +import java.util.Set; +import roomescape.reservation.domain.Reservation; + +@Entity public class Theme { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + private String name; + private String description; + @OneToMany(mappedBy = "theme") + private Set reservations = new HashSet<>(); + public Theme() { } @@ -31,4 +48,8 @@ public String getName() { public String getDescription() { return description; } + + public Set getReservations() { + return reservations; + } } diff --git a/src/main/java/roomescape/theme/repository/ThemeRepository.java b/src/main/java/roomescape/theme/repository/ThemeRepository.java new file mode 100644 index 000000000..777e370ca --- /dev/null +++ b/src/main/java/roomescape/theme/repository/ThemeRepository.java @@ -0,0 +1,8 @@ +package roomescape.theme.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import roomescape.theme.domain.Theme; + +public interface ThemeRepository extends JpaRepository { + +} diff --git a/src/main/java/roomescape/time/TimeDao.java b/src/main/java/roomescape/time/TimeDao.java index 6beb6bf9c..d02f7c4a8 100644 --- a/src/main/java/roomescape/time/TimeDao.java +++ b/src/main/java/roomescape/time/TimeDao.java @@ -1,44 +1,44 @@ -package roomescape.time; - -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.support.GeneratedKeyHolder; -import org.springframework.jdbc.support.KeyHolder; -import org.springframework.stereotype.Repository; -import roomescape.time.domain.Time; - -import java.sql.PreparedStatement; -import java.util.List; - -@Repository -public class TimeDao { - - private final JdbcTemplate jdbcTemplate; - - public TimeDao(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - public List