diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/controller/DebateController.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/controller/DebateController.java new file mode 100644 index 00000000..090a3114 --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/controller/DebateController.java @@ -0,0 +1,59 @@ +package com.rollthedice.backend.domain.debate.controller; + +import com.rollthedice.backend.domain.debate.dto.request.DebateMessageRequest; +import com.rollthedice.backend.domain.debate.dto.request.DebateRoomRequest; +import com.rollthedice.backend.domain.debate.dto.response.DebateMessageResponse; +import com.rollthedice.backend.domain.debate.dto.response.DebateRoomResponse; +import com.rollthedice.backend.domain.debate.service.DebateMessageService; +import com.rollthedice.backend.domain.debate.service.DebateRoomService; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("debates") +public class DebateController { + private final DebateRoomService debateRoomService; + private final DebateMessageService debateMessageService; + + @ResponseStatus(HttpStatus.CREATED) + @PostMapping("") + public void saveDebateRoom(@RequestBody @Valid final DebateRoomRequest request) { + debateRoomService.saveDebateRoom(request); + } + + @ResponseStatus(HttpStatus.OK) + @GetMapping("") + public List getDebateRooms(final Pageable pageable) { + return debateRoomService.getDebateRooms(pageable); + } + + @ResponseStatus(HttpStatus.NO_CONTENT) + @DeleteMapping("/{roomId}") + public void deleteDebateRoom(@PathVariable final Long roomId) { + debateRoomService.deleteDebateRoom(roomId); + } + + @ResponseStatus(HttpStatus.CREATED) + @PostMapping("/{roomId}/human") + public void saveHumanDebateMessage(@PathVariable final Long roomId, @RequestBody final DebateMessageRequest request) { + debateMessageService.saveHumanDebateMessage(roomId, request); + } + + @ResponseStatus(HttpStatus.CREATED) + @PostMapping("/{roomId}/ai") + public void saveAIDebateMessage(@PathVariable final Long roomId, @RequestBody final DebateMessageRequest request) { + debateMessageService.saveAIDebateMessage(roomId, request); + } + + @ResponseStatus(HttpStatus.OK) + @GetMapping("/{roomId}") + public List getDebateMessages(@PathVariable final Long roomId) { + return debateMessageService.getDebateMessages(roomId); + } +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/dto/request/DebateMessageRequest.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/dto/request/DebateMessageRequest.java new file mode 100644 index 00000000..405a1d84 --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/dto/request/DebateMessageRequest.java @@ -0,0 +1,33 @@ +package com.rollthedice.backend.domain.debate.dto.request; + +import com.rollthedice.backend.domain.debate.entity.DebateMessage; +import com.rollthedice.backend.domain.debate.entity.DebateRoom; +import com.rollthedice.backend.domain.debate.entity.SenderType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class DebateMessageRequest { + private String message; + + public DebateMessage toHumanMessageEntity(DebateRoom debateRoom) { + return DebateMessage.builder() + .message(this.message) + .senderType(SenderType.HUMAN) + .debateRoom(debateRoom) + .build(); + } + + public DebateMessage toAIMessageEntity(DebateRoom debateRoom) { + return DebateMessage.builder() + .message(this.message) + .senderType(SenderType.AI) + .debateRoom(debateRoom) + .build(); + } +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/dto/request/DebateRoomRequest.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/dto/request/DebateRoomRequest.java new file mode 100644 index 00000000..92f5bd0a --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/dto/request/DebateRoomRequest.java @@ -0,0 +1,15 @@ +package com.rollthedice.backend.domain.debate.dto.request; + +import com.rollthedice.backend.domain.debate.entity.DebateRoom; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class DebateRoomRequest { + private String topic; +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/dto/response/DebateMessageResponse.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/dto/response/DebateMessageResponse.java new file mode 100644 index 00000000..3e5ff3e5 --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/dto/response/DebateMessageResponse.java @@ -0,0 +1,16 @@ +package com.rollthedice.backend.domain.debate.dto.response; + +import com.rollthedice.backend.domain.debate.entity.SenderType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DebateMessageResponse { + private String message; + private SenderType senderType; +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/dto/response/DebateRoomResponse.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/dto/response/DebateRoomResponse.java new file mode 100644 index 00000000..64eae208 --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/dto/response/DebateRoomResponse.java @@ -0,0 +1,15 @@ +package com.rollthedice.backend.domain.debate.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DebateRoomResponse { + private Long id; + private String topic; +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/entity/DebateMessage.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/entity/DebateMessage.java new file mode 100644 index 00000000..91221c01 --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/entity/DebateMessage.java @@ -0,0 +1,35 @@ +package com.rollthedice.backend.domain.debate.entity; + +import com.rollthedice.backend.domain.member.entity.Member; +import com.rollthedice.backend.global.config.BaseTimeEntity; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class DebateMessage extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String message; + + @Enumerated(EnumType.STRING) + private SenderType senderType; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "debate_room_id") + private DebateRoom debateRoom; + + @Builder + public DebateMessage(String message, SenderType senderType, DebateRoom debateRoom) { + this.message = message; + this.senderType = senderType; + this.debateRoom = debateRoom; + } + +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/entity/DebateRoom.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/entity/DebateRoom.java new file mode 100644 index 00000000..1d2603f8 --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/entity/DebateRoom.java @@ -0,0 +1,30 @@ +package com.rollthedice.backend.domain.debate.entity; + +import com.rollthedice.backend.domain.member.entity.Member; +import com.rollthedice.backend.global.config.BaseTimeEntity; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class DebateRoom extends BaseTimeEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String topic; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + private Member member; + + @Builder + public DebateRoom(Member member, String topic) { + this.member = member; + this.topic = topic; + } +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/entity/SenderType.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/entity/SenderType.java new file mode 100644 index 00000000..6d7ecfac --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/entity/SenderType.java @@ -0,0 +1,9 @@ +package com.rollthedice.backend.domain.debate.entity; + +import lombok.Getter; + +@Getter +public enum SenderType { + HUMAN, + AI +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/mapper/DebateMessageMapper.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/mapper/DebateMessageMapper.java new file mode 100644 index 00000000..cffcb574 --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/mapper/DebateMessageMapper.java @@ -0,0 +1,12 @@ +package com.rollthedice.backend.domain.debate.mapper; + +import com.rollthedice.backend.domain.debate.dto.request.DebateMessageRequest; +import com.rollthedice.backend.domain.debate.dto.response.DebateMessageResponse; +import com.rollthedice.backend.domain.debate.entity.DebateMessage; +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; + +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +public interface DebateMessageMapper { + DebateMessageResponse toResponse(DebateMessage debateMessage); +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/mapper/DebateRoomMapper.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/mapper/DebateRoomMapper.java new file mode 100644 index 00000000..7e2f2bba --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/mapper/DebateRoomMapper.java @@ -0,0 +1,16 @@ +package com.rollthedice.backend.domain.debate.mapper; + +import com.rollthedice.backend.domain.debate.dto.request.DebateRoomRequest; +import com.rollthedice.backend.domain.debate.dto.response.DebateRoomResponse; +import com.rollthedice.backend.domain.debate.entity.DebateRoom; +import com.rollthedice.backend.domain.member.entity.Member; +import org.mapstruct.Mapper; +import org.mapstruct.MappingConstants; + +@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) +public interface DebateRoomMapper { + + DebateRoom toEntity(final Member member, final DebateRoomRequest request); + + DebateRoomResponse toResponse(final DebateRoom room); +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/repository/DebateRoomRepository.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/repository/DebateRoomRepository.java new file mode 100644 index 00000000..76ef494c --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/repository/DebateRoomRepository.java @@ -0,0 +1,14 @@ +package com.rollthedice.backend.domain.debate.repository; + +import com.rollthedice.backend.domain.debate.entity.DebateRoom; +import com.rollthedice.backend.domain.member.entity.Member; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface DebateRoomRepository extends JpaRepository { + List findAllByMember(Member member, Pageable pageable); +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/service/DebateMessageService.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/service/DebateMessageService.java new file mode 100644 index 00000000..3649fb78 --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/service/DebateMessageService.java @@ -0,0 +1,47 @@ +package com.rollthedice.backend.domain.debate.service; + +import com.rollthedice.backend.domain.debate.dto.request.DebateMessageRequest; +import com.rollthedice.backend.domain.debate.dto.response.DebateMessageResponse; +import com.rollthedice.backend.domain.debate.entity.DebateRoom; +import com.rollthedice.backend.domain.debate.mapper.DebateMessageMapper; +import com.rollthedice.backend.domain.debate.repository.DebateRoomRepository; +import com.rollthedice.backend.domain.news.repository.DebateMessageRepository; +import jakarta.persistence.EntityNotFoundException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +@Service +public class DebateMessageService { + private final DebateRoomRepository debateRoomRepository; + private final DebateMessageRepository debateMessageRepository; + private final DebateMessageMapper debateMessageMapper; + + @Transactional + public void saveHumanDebateMessage(final Long roomId, DebateMessageRequest request) { + debateMessageRepository.save(request.toHumanMessageEntity(getDebateRoom(roomId))); + } + + public void saveAIDebateMessage(Long roomId, DebateMessageRequest request) { + debateMessageRepository.save(request.toAIMessageEntity(getDebateRoom(roomId))); + } + + private DebateRoom getDebateRoom(final Long roomId) { + return debateRoomRepository.findById(roomId).orElseThrow(EntityNotFoundException::new); + } + + @Transactional + public void deleteAllDebateMessages(Long roomId) { + debateMessageRepository.deleteAllInBatchByDebateRoomId(roomId); + } + + public List getDebateMessages(Long roomId) { + return debateMessageRepository.findAllByDebateRoomId(roomId) + .stream().map(debateMessageMapper::toResponse) + .collect(Collectors.toList()); + } +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/service/DebateRoomService.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/service/DebateRoomService.java new file mode 100644 index 00000000..5a18f9a6 --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/service/DebateRoomService.java @@ -0,0 +1,45 @@ +package com.rollthedice.backend.domain.debate.service; + +import com.rollthedice.backend.domain.debate.dto.request.DebateRoomRequest; +import com.rollthedice.backend.domain.debate.dto.response.DebateRoomResponse; +import com.rollthedice.backend.domain.debate.mapper.DebateRoomMapper; +import com.rollthedice.backend.domain.debate.repository.DebateRoomRepository; +import com.rollthedice.backend.domain.member.entity.Member; +import com.rollthedice.backend.domain.member.query.AuthService; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +@Service +public class DebateRoomService { + private final AuthService authService; + private final DebateRoomMapper debateRoomMapper; + private final DebateRoomRepository debateRoomRepository; + private final DebateMessageService debateMessageService; + + + @Transactional + public void saveDebateRoom(DebateRoomRequest request) { + final Member member = authService.getMember(); + debateRoomRepository.save(debateRoomMapper.toEntity(member, request)); + } + + @Transactional(readOnly = true) + public List getDebateRooms(Pageable pageable) { + final Member member = authService.getMember(); + return debateRoomRepository.findAllByMember(member, pageable).stream() + .map(debateRoomMapper::toResponse) + .collect(Collectors.toList()); + } + + @Transactional + public void deleteDebateRoom(Long roomId) { + debateMessageService.deleteAllDebateMessages(roomId); + debateRoomRepository.deleteById(roomId); + } +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/news/repository/DebateMessageRepository.java b/backend/core/src/main/java/com/rollthedice/backend/domain/news/repository/DebateMessageRepository.java new file mode 100644 index 00000000..f2456e6f --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/news/repository/DebateMessageRepository.java @@ -0,0 +1,14 @@ +package com.rollthedice.backend.domain.news.repository; + +import com.rollthedice.backend.domain.debate.entity.DebateMessage; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface DebateMessageRepository extends JpaRepository { + void deleteAllInBatchByDebateRoomId(final Long id); + + List findAllByDebateRoomId(final Long id); +}