Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] Room 생성 API #20

Merged
merged 8 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
11 changes: 11 additions & 0 deletions src/main/java/com/telepigeon/server/annotation/UserId.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.telepigeon.server.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface UserId {
}
32 changes: 32 additions & 0 deletions src/main/java/com/telepigeon/server/controller/RoomController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.telepigeon.server.controller;

import com.telepigeon.server.annotation.UserId;
import com.telepigeon.server.domain.Room;
import com.telepigeon.server.dto.room.request.RoomCreateDto;
import com.telepigeon.server.service.room.RoomService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.net.URI;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1")
public class RoomController {
private final RoomService roomService;

@PostMapping("/rooms")
public ResponseEntity<Void> createRoom(
@UserId Long userId,
@Valid @RequestBody RoomCreateDto roomCreateDto
) {
Room createdRoom = roomService.createRoom(roomCreateDto);
URI location = URI.create("/rooms/" + createdRoom.getId());
return ResponseEntity.created(location).build();
}
}
16 changes: 16 additions & 0 deletions src/main/java/com/telepigeon/server/domain/Profile.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.telepigeon.server.dto.type.Gender;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

Expand Down Expand Up @@ -46,4 +47,19 @@ public class Profile {
@JoinColumn(name="room_id")
private Room room;

@Builder
private Profile(Users user, Room room) {
this.user = user;
this.room = room;
}

public static Profile create(
Users user,
Room room
) {
return Profile.builder()
.user(user)
.room(room)
.build();
}
}
24 changes: 24 additions & 0 deletions src/main/java/com/telepigeon/server/domain/Room.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package com.telepigeon.server.domain;

import com.telepigeon.server.dto.room.request.RoomCreateDto;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;

@Entity
@Getter
Expand All @@ -21,4 +24,25 @@ public class Room {
private String code;

private LocalDateTime createdAt;

@OneToMany(mappedBy="room", cascade=CascadeType.ALL, fetch=FetchType.LAZY)
tkdwns414 marked this conversation as resolved.
Show resolved Hide resolved
private List<Profile> profiles;

@Builder
private Room(String name, String code, LocalDateTime createdAt) {
this.name = name;
this.code = code;
this.createdAt = createdAt;
}

public static Room create(
RoomCreateDto createDto,
String code
) {
return Room.builder()
.name(createDto.name())
.code(code)
.createdAt(LocalDateTime.now())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.telepigeon.server.dto.room.request;

import com.telepigeon.server.domain.Room;
import jakarta.annotation.Nullable;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

public record RoomCreateDto(
@NotNull @Size(max=8, min=2)
String name
) {
public static RoomCreateDto of(Room room) {
return new RoomCreateDto(String.valueOf(room.getName()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.telepigeon.server.exception;

import com.telepigeon.server.exception.code.NotFoundErrorCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public class NotFoundException extends RuntimeException{
kmjenny marked this conversation as resolved.
Show resolved Hide resolved
private final NotFoundErrorCode errorCode;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
@AllArgsConstructor
public enum NotFoundErrorCode implements DefaultErrorCode{
NOT_FOUND_END_POINT(HttpStatus.NOT_FOUND, "error", "존재하지 않는 API입니다."),
ROOM_NOT_FOUND(HttpStatus.NOT_FOUND, "error", "존재하지 않는 방입니다."),
USER_NOT_FOUND(HttpStatus.NOT_FOUND, "error", "존재하지 않는 사용자입니다."),
;

@JsonIgnore
private final HttpStatus httpStatus;
private final String code;
private final String message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.telepigeon.server.repository;

import com.telepigeon.server.domain.Profile;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ProfileRepository extends JpaRepository<Profile, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.telepigeon.server.repository;

import com.telepigeon.server.domain.Room;
import org.springframework.data.jpa.repository.JpaRepository;

public interface RoomRepository extends JpaRepository<Room, Long> {
boolean existsByName(String name);
}
12 changes: 12 additions & 0 deletions src/main/java/com/telepigeon/server/repository/UserRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.telepigeon.server.repository;

import com.telepigeon.server.domain.Users;
import com.telepigeon.server.exception.NotFoundException;
import com.telepigeon.server.exception.code.NotFoundErrorCode;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<Users, Long> {
default Users findByIdOrThrow(Long id) {
return findById(id).orElseThrow(() -> new NotFoundException(NotFoundErrorCode.USER_NOT_FOUND));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.telepigeon.server.service.profile;

import com.telepigeon.server.domain.Profile;
import com.telepigeon.server.repository.ProfileRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class ProfileSaver {

private final ProfileRepository profileRepository;

public Profile save(Profile profile) {
return profileRepository.save(profile);
}
}
17 changes: 17 additions & 0 deletions src/main/java/com/telepigeon/server/service/room/RoomRemover.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.telepigeon.server.service.room;

import com.telepigeon.server.domain.Room;
import com.telepigeon.server.repository.RoomRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class RoomRemover {

private final RoomRepository roomRepository;

public void remove(final Room room) {
roomRepository.delete(room);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.telepigeon.server.service.room;

import com.telepigeon.server.domain.Room;
import com.telepigeon.server.exception.NotFoundException;
import com.telepigeon.server.exception.code.NotFoundErrorCode;
import com.telepigeon.server.repository.RoomRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class RoomRetriever {

private final RoomRepository roomRepository;

public boolean existsByName(String name) {
return roomRepository.existsByName(name);
}

public Room findById(final long id) {
return roomRepository.findById(id)
.orElseThrow(() -> new NotFoundException(NotFoundErrorCode.ROOM_NOT_FOUND));
}
}
17 changes: 17 additions & 0 deletions src/main/java/com/telepigeon/server/service/room/RoomSaver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.telepigeon.server.service.room;

import com.telepigeon.server.domain.Room;
import com.telepigeon.server.repository.RoomRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class RoomSaver {

private final RoomRepository roomRepository;

public Room save(Room room) {
kmjenny marked this conversation as resolved.
Show resolved Hide resolved
return roomRepository.save(room);
}
}
54 changes: 54 additions & 0 deletions src/main/java/com/telepigeon/server/service/room/RoomService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.telepigeon.server.service.room;

import com.telepigeon.server.domain.Profile;
import com.telepigeon.server.domain.Room;
import com.telepigeon.server.domain.Users;
import com.telepigeon.server.dto.room.request.RoomCreateDto;
import com.telepigeon.server.repository.RoomRepository;
import com.telepigeon.server.repository.UserRepository;
import com.telepigeon.server.service.profile.ProfileSaver;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.Random;

@Service
@RequiredArgsConstructor
public class RoomService {

private final RoomRepository roomRepository;
private final RoomSaver roomSaver;
private final RoomRetriever roomRetriever;
private final RoomRemover roomRemover;
private final UserRepository userRepository;
private final ProfileSaver profileSaver;

@Transactional
public Room createRoom(final RoomCreateDto roomCreateDto){
// Users user = userRepository.findByIdOrThrow(userId);

String code = createCode();

Room room = Room.create(roomCreateDto, code);
Room savedRoom = roomSaver.save(room);

// Profile profile = Profile.create(user, savedRoom);
// Profile savedProfile = profileSaver.save(profile);

return savedRoom;
}

private String createCode() {
String characters = "abcdefghijklmnopqrstuvwxyz0123456789";
StringBuilder codeBuilder = new StringBuilder();

Random random = new Random();
for (int i = 0; i < 10; i++) {
int index = random.nextInt(characters.length());
codeBuilder.append(characters.charAt(index));
kmjenny marked this conversation as resolved.
Show resolved Hide resolved
}

return codeBuilder.toString();
}
}
2 changes: 1 addition & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ spring:
datasource:
url: jdbc:mysql://localhost:3306/TelePigeon
username: root
password:
password: ${DB_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
Expand Down
24 changes: 24 additions & 0 deletions src/test/java/com/telepigeon/server/roomTest/RoomDomainTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.telepigeon.server.roomTest;

import com.telepigeon.server.domain.Room;
import com.telepigeon.server.dto.room.request.RoomCreateDto;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

public class RoomDomainTest {

@Test
@DisplayName("Room 생성")
public void createRoomTest() {
Room room = Room.create(new RoomCreateDto("name"), "code");
Assertions.assertNotNull(room);
}

@Test
@DisplayName("Room 생성 확인")
public void checkCreateRoomTest() {
Room room = Room.create(new RoomCreateDto("name"), "code");
Assertions.assertEquals(room.getName(), "name");
}
}
40 changes: 40 additions & 0 deletions src/test/java/com/telepigeon/server/roomTest/RoomServiceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.telepigeon.server.roomTest;

import com.telepigeon.server.domain.Room;
import com.telepigeon.server.dto.room.request.RoomCreateDto;
import com.telepigeon.server.repository.RoomRepository;
import com.telepigeon.server.service.room.RoomRetriever;
import com.telepigeon.server.service.room.RoomSaver;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.Mockito;

public class RoomServiceTest {

@Mock
private RoomRepository roomRepository = Mockito.mock(RoomRepository.class);

@Test
@DisplayName("Room DB에 저장 확인")
public void checkRoomInDB() {
RoomSaver roomSaver = new RoomSaver(roomRepository);
Room room = Room.create(new RoomCreateDto("name"), "code");
Mockito.doAnswer(invocation -> room).when(roomRepository).save(room);
Room room1 = roomSaver.save(room);
Assertions.assertEquals(room.getName(), room1.getName());
}

@Test
@DisplayName("Room DB에서 꺼내오기 확인")
public void checkRoomToDB() {
RoomRetriever roomRetriever = new RoomRetriever(roomRepository);
Room room = Room.create(new RoomCreateDto("name"), "code");
Mockito.doAnswer(invocation -> true).when(roomRepository).existsByName(room.getName());
RoomCreateDto roomCreateDto = RoomCreateDto.of(room);
boolean isCheck = roomRetriever.existsByName(roomCreateDto.name());
Assertions.assertTrue(isCheck);
}

}