Skip to content

Commit

Permalink
[feat] Room 생성 API
Browse files Browse the repository at this point in the history
[feat] Room 생성 API
  • Loading branch information
kmjenny committed May 20, 2024
2 parents 3714941 + 1c0147b commit f064969
Show file tree
Hide file tree
Showing 17 changed files with 339 additions and 1 deletion.
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)
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{
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,9 @@
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);
boolean existsByCode(String code);
}
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(final Room room) {
return roomRepository.save(room);
}
}
59 changes: 59 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,59 @@
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";
Random random = new Random();
String code;

do {
StringBuilder codeBuilder = new StringBuilder();
for (int i = 0; i < 10; i++) {
int index = random.nextInt(characters.length());
codeBuilder.append(characters.charAt(index));
}
code = codeBuilder.toString();
} while (roomRepository.existsByCode(code));


return code;
}
}
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);
}

}

0 comments on commit f064969

Please sign in to comment.