From 9193e35741f5f6601961f8bdb2e31b86188dbee5 Mon Sep 17 00:00:00 2001 From: Raymond Date: Tue, 9 Jul 2024 00:56:30 +0900 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20=ED=8F=BC,=20=EB=B8=94=EB=A1=9D=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/layer/config/ObjectMapperConfig.java | 29 +++++++++ .../java/org/layer/filter/LoggerFilter.java | 65 +++++++++++++++++++ .../java/org/layer/domain/BaseEntity.java | 25 +++++++ .../block/converter/BlockStyleConverter.java | 26 ++++++++ .../org/layer/domain/block/entity/Block.java | 36 ++++++++++ .../layer/domain/block/enums/BlockType.java | 35 ++++++++++ .../blockOption/entity/BlockOption.java | 29 +++++++++ .../converter/FormPublishedByConverter.java | 25 +++++++ .../org/layer/domain/form/entity/Form.java | 27 ++++---- .../domain/form/enums/FormPublishedBy.java | 16 +++++ 10 files changed, 302 insertions(+), 11 deletions(-) create mode 100644 layer-api/src/main/java/org/layer/config/ObjectMapperConfig.java create mode 100644 layer-api/src/main/java/org/layer/filter/LoggerFilter.java create mode 100644 layer-domain/src/main/java/org/layer/domain/BaseEntity.java create mode 100644 layer-domain/src/main/java/org/layer/domain/block/converter/BlockStyleConverter.java create mode 100644 layer-domain/src/main/java/org/layer/domain/block/entity/Block.java create mode 100644 layer-domain/src/main/java/org/layer/domain/block/enums/BlockType.java create mode 100644 layer-domain/src/main/java/org/layer/domain/blockOption/entity/BlockOption.java create mode 100644 layer-domain/src/main/java/org/layer/domain/form/converter/FormPublishedByConverter.java create mode 100644 layer-domain/src/main/java/org/layer/domain/form/enums/FormPublishedBy.java diff --git a/layer-api/src/main/java/org/layer/config/ObjectMapperConfig.java b/layer-api/src/main/java/org/layer/config/ObjectMapperConfig.java new file mode 100644 index 00000000..7047bd05 --- /dev/null +++ b/layer-api/src/main/java/org/layer/config/ObjectMapperConfig.java @@ -0,0 +1,29 @@ +package org.layer.config; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ObjectMapperConfig { + + @Bean + public ObjectMapper objectMapper(){ + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new Jdk8Module()); + objectMapper.registerModule(new JavaTimeModule()); + + objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false); + objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + + // 카멜 케이스 + objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategies.LowerCamelCaseStrategy()); + return objectMapper; + + } +} \ No newline at end of file diff --git a/layer-api/src/main/java/org/layer/filter/LoggerFilter.java b/layer-api/src/main/java/org/layer/filter/LoggerFilter.java new file mode 100644 index 00000000..67e72978 --- /dev/null +++ b/layer-api/src/main/java/org/layer/filter/LoggerFilter.java @@ -0,0 +1,65 @@ +package org.layer.filter; + +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.util.ContentCachingRequestWrapper; +import org.springframework.web.util.ContentCachingResponseWrapper; + +import java.io.IOException; + +@Component +@Slf4j +public class LoggerFilter implements Filter { + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + var req = new ContentCachingRequestWrapper((HttpServletRequest) request); + var res = new ContentCachingResponseWrapper((HttpServletResponse) response); + + chain.doFilter(req,res); + + // request 정보 + var headerNames = req.getHeaderNames(); + var headerValues = new StringBuilder(); + + headerNames.asIterator().forEachRemaining(headerKey -> { + var headerValue = req.getHeader(headerKey); + + headerValues + .append("[") + .append(headerKey) + .append(" : ") + .append(headerValue) + .append(" , ") + .append("] "); + }); + var requestBody = new String(req.getContentAsByteArray()); + var uri = req.getRequestURI(); + var method = req.getMethod(); + + log.info("[REQUEST] uri : {} , method : {} , header : {} , body : {}" ,uri,method, headerValues, requestBody); + + // response + var responseHeaderValues = new StringBuilder(); + res.getHeaderNames().forEach(headerKey -> { + var headerValue = res.getHeader(headerKey); + responseHeaderValues + .append("[") + .append(headerKey) + .append(" : ") + .append(headerValue) + .append(" ,") + .append("] "); + }); + + // var responseBody = new String(res.getContentAsByteArray()); + + log.info("[RESPONSE] uri : {} , method : {} , header : {} , body : {}",uri,method, responseHeaderValues); + + res.copyBodyToResponse(); + } +} + diff --git a/layer-domain/src/main/java/org/layer/domain/BaseEntity.java b/layer-domain/src/main/java/org/layer/domain/BaseEntity.java new file mode 100644 index 00000000..8eb74dba --- /dev/null +++ b/layer-domain/src/main/java/org/layer/domain/BaseEntity.java @@ -0,0 +1,25 @@ +package org.layer.domain; + +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.MappedSuperclass; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import java.time.LocalDateTime; + +@MappedSuperclass +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @CreatedDate + private LocalDateTime createdAt; + + @LastModifiedDate + private LocalDateTime updatedAt; +} \ No newline at end of file diff --git a/layer-domain/src/main/java/org/layer/domain/block/converter/BlockStyleConverter.java b/layer-domain/src/main/java/org/layer/domain/block/converter/BlockStyleConverter.java new file mode 100644 index 00000000..0607ba2a --- /dev/null +++ b/layer-domain/src/main/java/org/layer/domain/block/converter/BlockStyleConverter.java @@ -0,0 +1,26 @@ +package org.layer.domain.block.converter; + +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; +import org.layer.domain.block.enums.BlockType; + + +import java.util.stream.Stream; + +@Converter +public class BlockStyleConverter implements AttributeConverter { + + @Override + public String convertToDatabaseColumn(BlockType blockType) { + return blockType.getStyle(); + } + + @Override + public BlockType convertToEntityAttribute(String blockStyle) { + if(blockStyle == null){ + return null; + } + return Stream.of(BlockType.values()).filter(t -> t.getStyle().equals(blockStyle)).findFirst() + .orElseThrow(IllegalArgumentException::new); + } +} diff --git a/layer-domain/src/main/java/org/layer/domain/block/entity/Block.java b/layer-domain/src/main/java/org/layer/domain/block/entity/Block.java new file mode 100644 index 00000000..cfaf4317 --- /dev/null +++ b/layer-domain/src/main/java/org/layer/domain/block/entity/Block.java @@ -0,0 +1,36 @@ +package org.layer.domain.block.entity; + +import jakarta.persistence.*; +import jakarta.validation.constraints.NotNull; +import lombok.*; +import org.layer.domain.BaseEntity; +import org.layer.domain.block.converter.BlockStyleConverter; +import org.layer.domain.block.enums.BlockType; +import org.layer.domain.blockOption.entity.BlockOption; + +import java.util.HashSet; +import java.util.Set; + +@Getter +@Entity +@EqualsAndHashCode(callSuper = true) +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Block extends BaseEntity { + + /** + * Form RelationId + */ + @NotNull + private Long formId; + + private String label; + + @Column(length = 20) + @NotNull + @Convert(converter = BlockStyleConverter.class) + private BlockType style; + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "block", cascade = CascadeType.ALL, orphanRemoval = true) + private Set options = new HashSet<>(); +} diff --git a/layer-domain/src/main/java/org/layer/domain/block/enums/BlockType.java b/layer-domain/src/main/java/org/layer/domain/block/enums/BlockType.java new file mode 100644 index 00000000..5b8e0c74 --- /dev/null +++ b/layer-domain/src/main/java/org/layer/domain/block/enums/BlockType.java @@ -0,0 +1,35 @@ +package org.layer.domain.block.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum BlockType { + /** + * 질문(입력) 블록 종류 + * 1. 짧은 인풋 + * 2. 마크다운 + * 3. 레인저 + * 4. 콤보 박스 + * 5. 카드 + * 6. 숫자 인풋 + * + * 질문 블록 중 이산적인 블록 종류 + * 1. 레인저( 숫자 ) + * 2. 콤보 박스 + * 3. 카드 + * + */ + + PLAIN_TEXT("짧은 입력","plain_text","single"), + MARKDOWN("마크다운 입력","markdown","single"), + RANGER("범위 지정","range","multi"), + COMBOBOX("콤보 박스","combobox","multi"), + CARD("카드 선택 입력","card","multi"), + NUMBER("숫자 입력","number","single"); + + private String description; + private String style; + private String type; +} diff --git a/layer-domain/src/main/java/org/layer/domain/blockOption/entity/BlockOption.java b/layer-domain/src/main/java/org/layer/domain/blockOption/entity/BlockOption.java new file mode 100644 index 00000000..d8291454 --- /dev/null +++ b/layer-domain/src/main/java/org/layer/domain/blockOption/entity/BlockOption.java @@ -0,0 +1,29 @@ +package org.layer.domain.blockOption.entity; + +import jakarta.persistence.*; +import jakarta.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.layer.domain.BaseEntity; +import org.layer.domain.block.entity.Block; + +@Entity +@Table(name= "block_option", uniqueConstraints = { + @UniqueConstraint(columnNames = {"block_id", "value"}) +}) +@EqualsAndHashCode(callSuper = true) +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class BlockOption extends BaseEntity { + + private String label; + + @NotNull + private String value; + + @ManyToOne + @JoinColumn( name = "block_id") + private Block block; +} \ No newline at end of file diff --git a/layer-domain/src/main/java/org/layer/domain/form/converter/FormPublishedByConverter.java b/layer-domain/src/main/java/org/layer/domain/form/converter/FormPublishedByConverter.java new file mode 100644 index 00000000..82905a02 --- /dev/null +++ b/layer-domain/src/main/java/org/layer/domain/form/converter/FormPublishedByConverter.java @@ -0,0 +1,25 @@ +package org.layer.domain.form.converter; + +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; +import org.layer.domain.form.enums.FormPublishedBy; + +import java.util.stream.Stream; + +@Converter +public class FormPublishedByConverter implements AttributeConverter { + + @Override + public String convertToDatabaseColumn(FormPublishedBy formPublishType) { + return formPublishType.getCode(); + } + + @Override + public FormPublishedBy convertToEntityAttribute(final String code) { + if(code == null){ + return null; + } + return Stream.of(FormPublishedBy.values()).filter(t -> t.getCode().equals(code)).findFirst() + .orElseThrow(IllegalArgumentException::new); + } +} diff --git a/layer-domain/src/main/java/org/layer/domain/form/entity/Form.java b/layer-domain/src/main/java/org/layer/domain/form/entity/Form.java index e04e0d0e..12618c32 100644 --- a/layer-domain/src/main/java/org/layer/domain/form/entity/Form.java +++ b/layer-domain/src/main/java/org/layer/domain/form/entity/Form.java @@ -1,27 +1,32 @@ package org.layer.domain.form.entity; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.*; +import org.hibernate.annotations.ColumnDefault; +import org.layer.domain.BaseEntity; +import org.layer.domain.form.converter.FormPublishedByConverter; +import org.layer.domain.form.enums.FormPublishedBy; + @Getter @Entity +@EqualsAndHashCode(callSuper = true) +@AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class Form { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; +public class Form extends BaseEntity { private Long memberId; @NotNull private String title; + @Column(length = 10) + @ColumnDefault("1") + @Convert(converter = FormPublishedByConverter.class) + @NotNull + private FormPublishedBy formPublishedBy; + private String introduction; } diff --git a/layer-domain/src/main/java/org/layer/domain/form/enums/FormPublishedBy.java b/layer-domain/src/main/java/org/layer/domain/form/enums/FormPublishedBy.java new file mode 100644 index 00000000..58151fb3 --- /dev/null +++ b/layer-domain/src/main/java/org/layer/domain/form/enums/FormPublishedBy.java @@ -0,0 +1,16 @@ +package org.layer.domain.form.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum FormPublishedBy { + + ADMIN("관리자","0"), + PERSONAL("개인","1"); + ; + private String description; + private String code; + +} From 1c0fa4e5f1e635ec6cfebfe53e22273781f1aff1 Mon Sep 17 00:00:00 2001 From: mikekks Date: Tue, 9 Jul 2024 16:38:44 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20=ED=9A=8C=EA=B3=A0=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20Mock=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 7 +++++ .../retrospect/controller/RetrospectApi.java | 18 +++++++++++++ .../controller/RetrospectController.java | 27 +++++++++++++++++++ .../dto/request/RetrospectCreateRequest.java | 17 ++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 layer-api/src/main/java/org/layer/retrospect/controller/RetrospectApi.java create mode 100644 layer-api/src/main/java/org/layer/retrospect/controller/RetrospectController.java create mode 100644 layer-api/src/main/java/org/layer/retrospect/controller/dto/request/RetrospectCreateRequest.java diff --git a/build.gradle b/build.gradle index fa52532a..698b24bc 100644 --- a/build.gradle +++ b/build.gradle @@ -63,6 +63,7 @@ project(":layer-api") { implementation 'org.springframework.boot:spring-boot-starter' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-actuator' + implementation 'org.springframework.boot:spring-boot-starter-validation' //== jwt ==// implementation 'io.jsonwebtoken:jjwt-api:0.12.5' @@ -76,6 +77,12 @@ project(":layer-api") { implementation 'org.springframework.boot:spring-boot-starter-data-redis' testImplementation 'org.springframework.boot:spring-boot-starter-test' + + // swagger + implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0") + + // jpa + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' } jar.enabled = false diff --git a/layer-api/src/main/java/org/layer/retrospect/controller/RetrospectApi.java b/layer-api/src/main/java/org/layer/retrospect/controller/RetrospectApi.java new file mode 100644 index 00000000..1e5515ca --- /dev/null +++ b/layer-api/src/main/java/org/layer/retrospect/controller/RetrospectApi.java @@ -0,0 +1,18 @@ +package org.layer.retrospect.controller; + +import org.layer.retrospect.controller.dto.request.RetrospectCreateRequest; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; + +@Tag(name = "회고", description = "회고 관련 API") +public interface RetrospectApi { + + @Operation(summary = "회고 생성", description = "") + ResponseEntity createRetrospect(@PathVariable("spaceId") Long spaceId, + @RequestBody @Valid RetrospectCreateRequest request); +} diff --git a/layer-api/src/main/java/org/layer/retrospect/controller/RetrospectController.java b/layer-api/src/main/java/org/layer/retrospect/controller/RetrospectController.java new file mode 100644 index 00000000..fec3ed85 --- /dev/null +++ b/layer-api/src/main/java/org/layer/retrospect/controller/RetrospectController.java @@ -0,0 +1,27 @@ +package org.layer.retrospect.controller; + +import org.layer.retrospect.controller.dto.request.RetrospectCreateRequest; +import org.springframework.http.ResponseEntity; +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.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/space/{spaceId}/retrospect") +public class RetrospectController implements RetrospectApi { + + @Override + @PostMapping + public ResponseEntity createRetrospect(@PathVariable("spaceId") Long spaceId, + @RequestBody @Valid RetrospectCreateRequest request) { + + return ResponseEntity.ok(null); + } +} diff --git a/layer-api/src/main/java/org/layer/retrospect/controller/dto/request/RetrospectCreateRequest.java b/layer-api/src/main/java/org/layer/retrospect/controller/dto/request/RetrospectCreateRequest.java new file mode 100644 index 00000000..56a53cdf --- /dev/null +++ b/layer-api/src/main/java/org/layer/retrospect/controller/dto/request/RetrospectCreateRequest.java @@ -0,0 +1,17 @@ +package org.layer.retrospect.controller.dto.request; + +import java.util.List; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Size; + +@Schema(name = "RetrospectCreateRequest", description = "회고 생성 요청 Dto") +public record RetrospectCreateRequest( + + @Size(min = 1, max = 15) + @Schema(description = "회고 질문", example = "어려움을 느껴서 개선하고 싶은 점은 무엇인가요?") + List questions, + @Schema(description = "나의 회고 폼 추가 여부, true: 내 회고폼에 추가 O, false: 내 회고폼에 추가 X", example = "true") + boolean isMyForm +) { +} From 4e53cefc160518185b31325af6929e53921f36cc Mon Sep 17 00:00:00 2001 From: mikekks Date: Tue, 9 Jul 2024 16:39:14 +0900 Subject: [PATCH 3/7] =?UTF-8?q?chore:=20=EC=97=AC=EB=9F=AC=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=EC=97=90=EC=84=9C=20=EB=B9=88=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- layer-api/src/main/java/org/layer/LayerApplication.java | 6 ++++++ layer-external/src/main/java/org/layer/Main.java | 7 ------- layer-external/src/main/java/org/layer/external/dummy.txt | 0 3 files changed, 6 insertions(+), 7 deletions(-) delete mode 100644 layer-external/src/main/java/org/layer/Main.java create mode 100644 layer-external/src/main/java/org/layer/external/dummy.txt diff --git a/layer-api/src/main/java/org/layer/LayerApplication.java b/layer-api/src/main/java/org/layer/LayerApplication.java index 2ca6cb47..b727999b 100644 --- a/layer-api/src/main/java/org/layer/LayerApplication.java +++ b/layer-api/src/main/java/org/layer/LayerApplication.java @@ -3,8 +3,14 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @SpringBootApplication +@ComponentScan(basePackages = {"org.layer.common", "org.layer.api", "org.layer.domain", "org.layer.external"}) +@EnableJpaRepositories(basePackages = {"org.layer.domain"}) +@EntityScan(basePackages = {"org.layer.domain"}) public class LayerApplication { public static void main(String[] args) { SpringApplication.run(LayerApplication.class, args); diff --git a/layer-external/src/main/java/org/layer/Main.java b/layer-external/src/main/java/org/layer/Main.java deleted file mode 100644 index 33f0b2a8..00000000 --- a/layer-external/src/main/java/org/layer/Main.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.layer; - -public class Main { - public static void main(String[] args) { - System.out.println("Hello world!"); - } -} \ No newline at end of file diff --git a/layer-external/src/main/java/org/layer/external/dummy.txt b/layer-external/src/main/java/org/layer/external/dummy.txt new file mode 100644 index 00000000..e69de29b From a804c9592e91ed73c89324c38f5dd9d105597e93 Mon Sep 17 00:00:00 2001 From: mikekks Date: Tue, 9 Jul 2024 17:19:01 +0900 Subject: [PATCH 4/7] =?UTF-8?q?chore:=20dto=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/dto/RetrospectCreateServiceRequest.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 layer-api/src/main/java/org/layer/retrospect/service/dto/RetrospectCreateServiceRequest.java diff --git a/layer-api/src/main/java/org/layer/retrospect/service/dto/RetrospectCreateServiceRequest.java b/layer-api/src/main/java/org/layer/retrospect/service/dto/RetrospectCreateServiceRequest.java new file mode 100644 index 00000000..a8677ac5 --- /dev/null +++ b/layer-api/src/main/java/org/layer/retrospect/service/dto/RetrospectCreateServiceRequest.java @@ -0,0 +1,11 @@ +package org.layer.retrospect.service.dto; + +import java.util.List; + +public record RetrospectCreateServiceRequest( + String title, + Long spaceId, + List questions, + boolean isMyForm +) { +} From f9f4242a199a24798bd0f8269403d4e8d4d4077b Mon Sep 17 00:00:00 2001 From: mikekks Date: Tue, 9 Jul 2024 20:56:10 +0900 Subject: [PATCH 5/7] =?UTF-8?q?chore:=20BaseTimeEntity=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/layer/LayerApplication.java | 8 ++----- .../layer/domain/common/BaseTimeEntity.java | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 layer-domain/src/main/java/org/layer/domain/common/BaseTimeEntity.java diff --git a/layer-api/src/main/java/org/layer/LayerApplication.java b/layer-api/src/main/java/org/layer/LayerApplication.java index b727999b..86ed6aaa 100644 --- a/layer-api/src/main/java/org/layer/LayerApplication.java +++ b/layer-api/src/main/java/org/layer/LayerApplication.java @@ -3,14 +3,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; @SpringBootApplication -@ComponentScan(basePackages = {"org.layer.common", "org.layer.api", "org.layer.domain", "org.layer.external"}) -@EnableJpaRepositories(basePackages = {"org.layer.domain"}) -@EntityScan(basePackages = {"org.layer.domain"}) +@EnableJpaAuditing public class LayerApplication { public static void main(String[] args) { SpringApplication.run(LayerApplication.class, args); diff --git a/layer-domain/src/main/java/org/layer/domain/common/BaseTimeEntity.java b/layer-domain/src/main/java/org/layer/domain/common/BaseTimeEntity.java new file mode 100644 index 00000000..19dc5b08 --- /dev/null +++ b/layer-domain/src/main/java/org/layer/domain/common/BaseTimeEntity.java @@ -0,0 +1,23 @@ +package org.layer.domain.common; + +import java.time.LocalDateTime; + +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; +import lombok.Getter; + +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +@Getter +public abstract class BaseTimeEntity { + + @CreatedDate + public LocalDateTime createdAt; + + @LastModifiedDate + public LocalDateTime updatedAt; +} \ No newline at end of file From 836ac49e1fdc5ce6e90fe253a2cd69b82a208e6c Mon Sep 17 00:00:00 2001 From: mikekks Date: Tue, 9 Jul 2024 20:56:27 +0900 Subject: [PATCH 6/7] =?UTF-8?q?chore:=20BaseTimeEntity=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20enum=20=EC=BB=AC=EB=9F=BC=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/retrospect/entity/Retrospect.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/layer-domain/src/main/java/org/layer/domain/retrospect/entity/Retrospect.java b/layer-domain/src/main/java/org/layer/domain/retrospect/entity/Retrospect.java index 91d1135d..7f57b696 100644 --- a/layer-domain/src/main/java/org/layer/domain/retrospect/entity/Retrospect.java +++ b/layer-domain/src/main/java/org/layer/domain/retrospect/entity/Retrospect.java @@ -1,10 +1,15 @@ package org.layer.domain.retrospect.entity; +import org.layer.domain.common.BaseTimeEntity; + 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 lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import jakarta.validation.constraints.NotNull; @@ -12,7 +17,7 @@ @Getter @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) -public class Retrospect { +public class Retrospect extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -30,6 +35,15 @@ public class Retrospect { private String introduction; @NotNull + @Enumerated(EnumType.STRING) private RetrospectStatus retrospectStatus; + @Builder + public Retrospect(Long spaceId, Long formId, String title, String introduction, RetrospectStatus retrospectStatus) { + this.spaceId = spaceId; + this.formId = formId; + this.title = title; + this.introduction = introduction; + this.retrospectStatus = retrospectStatus; + } } From ab55faa53151d6c592cfe86cabd62c6797861b3c Mon Sep 17 00:00:00 2001 From: mikekks Date: Tue, 9 Jul 2024 20:58:01 +0900 Subject: [PATCH 7/7] =?UTF-8?q?feat:=20=ED=9A=8C=EA=B3=A0=20=ED=8F=BC=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 +++ .../controller/RetrospectController.java | 5 +++- .../dto/request/RetrospectCreateRequest.java | 17 +++++++----- .../retrospect/service/RetrospectService.java | 27 +++++++++++++++++++ 4 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 layer-api/src/main/java/org/layer/retrospect/service/RetrospectService.java diff --git a/build.gradle b/build.gradle index 698b24bc..5b11ee36 100644 --- a/build.gradle +++ b/build.gradle @@ -83,6 +83,9 @@ project(":layer-api") { // jpa implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + + // mysql + runtimeOnly 'com.mysql:mysql-connector-j' } jar.enabled = false diff --git a/layer-api/src/main/java/org/layer/retrospect/controller/RetrospectController.java b/layer-api/src/main/java/org/layer/retrospect/controller/RetrospectController.java index fec3ed85..b5378da8 100644 --- a/layer-api/src/main/java/org/layer/retrospect/controller/RetrospectController.java +++ b/layer-api/src/main/java/org/layer/retrospect/controller/RetrospectController.java @@ -1,12 +1,12 @@ package org.layer.retrospect.controller; import org.layer.retrospect.controller.dto.request.RetrospectCreateRequest; +import org.layer.retrospect.service.RetrospectService; import org.springframework.http.ResponseEntity; 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.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import jakarta.validation.Valid; @@ -17,11 +17,14 @@ @RequestMapping("/space/{spaceId}/retrospect") public class RetrospectController implements RetrospectApi { + private final RetrospectService retrospectService; + @Override @PostMapping public ResponseEntity createRetrospect(@PathVariable("spaceId") Long spaceId, @RequestBody @Valid RetrospectCreateRequest request) { + retrospectService.create(spaceId, request.formId(), request.title(), request.introduction()); return ResponseEntity.ok(null); } } diff --git a/layer-api/src/main/java/org/layer/retrospect/controller/dto/request/RetrospectCreateRequest.java b/layer-api/src/main/java/org/layer/retrospect/controller/dto/request/RetrospectCreateRequest.java index 56a53cdf..bdbcd9ff 100644 --- a/layer-api/src/main/java/org/layer/retrospect/controller/dto/request/RetrospectCreateRequest.java +++ b/layer-api/src/main/java/org/layer/retrospect/controller/dto/request/RetrospectCreateRequest.java @@ -1,17 +1,20 @@ package org.layer.retrospect.controller.dto.request; -import java.util.List; - import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; @Schema(name = "RetrospectCreateRequest", description = "회고 생성 요청 Dto") public record RetrospectCreateRequest( + @Schema(description = "회고 폼 id", example = "1") + @NotNull + Long formId, + @Schema(description = "회고 제목", example = "중간 발표 이후 회고") + @Size(min = 3) + String title, + @Schema(description = "회고 한줄 설명", example = "우리만의 KPT 회고") + @NotNull + String introduction - @Size(min = 1, max = 15) - @Schema(description = "회고 질문", example = "어려움을 느껴서 개선하고 싶은 점은 무엇인가요?") - List questions, - @Schema(description = "나의 회고 폼 추가 여부, true: 내 회고폼에 추가 O, false: 내 회고폼에 추가 X", example = "true") - boolean isMyForm ) { } diff --git a/layer-api/src/main/java/org/layer/retrospect/service/RetrospectService.java b/layer-api/src/main/java/org/layer/retrospect/service/RetrospectService.java new file mode 100644 index 00000000..2880e2a2 --- /dev/null +++ b/layer-api/src/main/java/org/layer/retrospect/service/RetrospectService.java @@ -0,0 +1,27 @@ +package org.layer.retrospect.service; + +import org.layer.domain.retrospect.entity.Retrospect; +import org.layer.domain.retrospect.entity.RetrospectStatus; +import org.layer.domain.retrospect.repository.RetrospectRepository; +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class RetrospectService { + + private final RetrospectRepository retrospectRepository; + + public void create(Long spaceId, Long formId, String title, String introduction){ + Retrospect retrospect = Retrospect.builder() + .title(title) + .formId(formId) + .spaceId(spaceId) + .introduction(introduction) + .retrospectStatus(RetrospectStatus.PROCEEDING) + .build(); + + retrospectRepository.save(retrospect); + } +}