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

Add(.footprint) : 발자취 생성 기능 및 API 추가 #185

Merged
merged 13 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from 12 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package me.ajaja.module.footprint.adapter.in.web;

import static org.springframework.http.HttpStatus.*;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import lombok.RequiredArgsConstructor;
import me.ajaja.global.common.AjajaResponse;
import me.ajaja.global.security.annotation.Authorization;
import me.ajaja.global.util.SecurityUtil;
import me.ajaja.module.footprint.application.port.in.CreateFootprintUseCase;
import me.ajaja.module.footprint.dto.FootprintRequest;

@RestController
@RequiredArgsConstructor
public class CreateFootprintController {
private final CreateFootprintUseCase createFootprintUseCase;

@Authorization
@PostMapping("/footprints")
@ResponseStatus(CREATED)
public AjajaResponse<Void> createFootprint(@RequestBody FootprintRequest.Create request) {
Long userId = SecurityUtil.getUserId();
createFootprintUseCase.create(userId, request);
return AjajaResponse.ok();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package me.ajaja.module.footprint.application.port;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import lombok.RequiredArgsConstructor;
import me.ajaja.module.footprint.application.port.in.CreateFootprintUseCase;
import me.ajaja.module.footprint.application.port.out.CreateFootprintPort;
import me.ajaja.module.footprint.domain.Footprint;
import me.ajaja.module.footprint.domain.FootprintFactory;
import me.ajaja.module.footprint.dto.FootprintRequest;

@Service
@Transactional
@RequiredArgsConstructor
public class CreateFootprintService implements CreateFootprintUseCase {
private final FootprintFactory footprintFactory;
private final CreateFootprintPort createFootprintPort;

@Override
public void create(Long userId, FootprintRequest.Create param) {
Footprint footprint = footprintFactory.init(userId, param);
createFootprintPort.create(footprint);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package me.ajaja.module.footprint.application.port.in;

import me.ajaja.module.footprint.dto.FootprintRequest;

public interface CreateFootprintUseCase {
void create(Long userId, FootprintRequest.Create param);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@

public interface GetFootprintPort {
Footprint getFootprint(Long id);

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@

import org.springframework.stereotype.Component;

import me.ajaja.module.footprint.dto.FootprintParam;
import me.ajaja.module.footprint.dto.FootprintRequest;

@Component
public final class FootprintFactory {
public Footprint create(FootprintParam.Create param) {
public Footprint init(Long userId, FootprintRequest.Create param) {
return switch (param.getType()) {
case FREE -> new FreeFootprint(
param.getTarget(),
param.getWriter(),
Target.init(param.getTargetId()),
Writer.init(userId),
param.getType(),
param.getTitle(),
Title.init(param.getTitle()),
param.isVisible(),
param.getContent()
);
case KPT -> new KptFootprint(
param.getTarget(),
param.getWriter(),
Target.init(param.getTargetId()),
Writer.init(userId),
param.getType(),
param.getTitle(),
Title.init(param.getTitle()),
param.isVisible(),
param.getKeepContent(),
param.getProblemContent(),
Expand Down
9 changes: 4 additions & 5 deletions src/main/java/me/ajaja/module/footprint/domain/Target.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,14 @@

import java.beans.ConstructorProperties;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Getter;
import me.ajaja.global.common.SelfValidating;

@Getter
public class Target extends SelfValidating<Target> {
@NotNull
private final Long id;

@NotBlank
@Size(max = 20)
private final String title;

@ConstructorProperties({"id", "title"})
Expand All @@ -23,4 +18,8 @@ public Target(Long id, String title) {
this.title = title;
this.validateSelf();
}

public static Target init(Long id) {
return new Target(id, null);
}
}
4 changes: 4 additions & 0 deletions src/main/java/me/ajaja/module/footprint/domain/Title.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,8 @@ public Title(String title) {
this.title = title;
this.validateSelf();
}

public static Title init(String title) {
return new Title(title);
}
}
9 changes: 4 additions & 5 deletions src/main/java/me/ajaja/module/footprint/domain/Writer.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,14 @@

import java.beans.ConstructorProperties;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Getter;
import me.ajaja.global.common.SelfValidating;

@Getter
public class Writer extends SelfValidating<Writer> {
@NotNull
private final Long id;

@NotBlank
@Size(max = 20)
private final String nickname;

@ConstructorProperties({"id", "nickname"})
Expand All @@ -23,4 +18,8 @@ public Writer(Long id, String nickname) {
this.nickname = nickname;
this.validateSelf();
}

public static Writer init(Long id) {
return new Writer(id, null);
}
}
39 changes: 0 additions & 39 deletions src/main/java/me/ajaja/module/footprint/dto/FootprintParam.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package me.ajaja.module.footprint.dto;

import java.util.List;

import lombok.Data;
import me.ajaja.module.footprint.domain.Footprint;

public final class FootprintRequest {
@Data
public static class Create {
private final Long targetId;
private final Footprint.Type type;
private final String title;
private final boolean visible;
private final String content;
private final String keepContent;
private final String problemContent;
private final String tryContent;
private final List<String> tags;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import me.ajaja.module.feedback.application.LoadFeedbackInfoService;
import me.ajaja.module.feedback.application.LoadTotalAchieveService;
import me.ajaja.module.feedback.application.UpdateFeedbackService;
import me.ajaja.module.footprint.application.port.in.CreateFootprintUseCase;
import me.ajaja.module.plan.application.port.in.CreatePlanUseCase;
import me.ajaja.module.plan.application.port.in.DeletePlanUseCase;
import me.ajaja.module.plan.application.port.in.LoadPlanDetailUseCase;
Expand Down Expand Up @@ -70,6 +71,7 @@ public abstract class WebMvcTestSupport extends MonkeySupport {
protected static final String PLAN_END_POINT = "/plans";
protected static final String FEEDBACK_END_POINT = "/feedbacks";
protected static final String REMIND_END_POINT = "/reminds";
protected static final String FOOTPRINT_END_POINT = "/footprints";
protected static final String BEARER_TOKEN = "Bearer eyJhbGxMiJ9.eyJzWpvdyJ9.avFKonhbIIhEg8H1dycQkhQ";

@Autowired
Expand Down Expand Up @@ -171,4 +173,8 @@ protected static Stream<Arguments> authenticationFailResults() {
protected FindTargetRemindQuery findTargetRemindQuery;
@MockBean
protected SendTestRemindUseCase sendTestRemindUseCase;

// footprint
@MockBean
protected CreateFootprintUseCase createFootprintUseCase;
}
1 change: 1 addition & 0 deletions src/test/java/me/ajaja/common/util/ApiTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public enum ApiTag {
FEEDBACK("피드백 API"),
PLAN("계획 API"),
REMIND("리마인드 API"),
FOOTPRINT("발자취 API"),
USER("사용자 API");

final String content;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package me.ajaja.module.footprint.adapter.in.web;

import static me.ajaja.global.exception.ErrorCode.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import static org.springframework.http.HttpStatus.*;
import static org.springframework.http.MediaType.*;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import java.util.List;

import org.junit.jupiter.api.DisplayName;
import org.springframework.http.HttpHeaders;

import jakarta.validation.ConstraintViolationException;
import me.ajaja.common.annotation.ApiTest;
import me.ajaja.common.support.WebMvcTestSupport;
import me.ajaja.common.util.ApiTag;
import me.ajaja.common.util.RestDocument;
import me.ajaja.module.footprint.domain.Footprint;
import me.ajaja.module.footprint.dto.FootprintRequest;

class CreateFootprintControllerTest extends WebMvcTestSupport {

@ApiTest
@DisplayName("발자취 유형에 맞는 형식에 요청 값에 대해 발자취 생성에 성공한다.")
void createFootprint_Success_With_NoExceptions() throws Exception {
// given
FootprintRequest.Create request = sut.giveMeBuilder(FootprintRequest.Create.class)
.set("param.type", Footprint.Type.FREE)
.set("param.content", "contents")
.set("tags", List.of("tag1", "tag2"))
.sample();

doNothing().when(createFootprintUseCase).create(anyLong(), any());

// when
var result = mockMvc.perform(post(FOOTPRINT_END_POINT)
.header(HttpHeaders.AUTHORIZATION, BEARER_TOKEN)
.accept(APPLICATION_JSON)
.contentType(APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)));

// then
result.andExpect(status().isCreated());

// docs
result.andDo(RestDocument.builder()
.identifier("footprint-create-success")
.tag(ApiTag.FOOTPRINT)
.summary("발자취 생성 API")
.description("발자취 유형에 맞는 항목에 빈 문자가 아닌 상태로 요청할 떄 발자취 정보를 생성 합니다.")
.secured(true)
.result(result)
.generateDocs());
}

@ApiTest
@DisplayName("발자취 유형에 해당 하는 항목 값이 빈 문자일 때 대해 발자취 생성에 실패한다.")
void createFootprint_Fail_By_InvalidContents() throws Exception {
// given
FootprintRequest.Create request = sut.giveMeBuilder(FootprintRequest.Create.class)
.set("param.content", "")
.set("tags", List.of("tag1", "tag2"))
.sample();

doThrow(ConstraintViolationException.class).when(createFootprintUseCase)
.create(anyLong(), any());

// when
var result = mockMvc.perform(post(FOOTPRINT_END_POINT)
.header(HttpHeaders.AUTHORIZATION, BEARER_TOKEN)
.accept(APPLICATION_JSON)
.contentType(APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)));

result.andExpectAll(
status().isBadRequest(),
jsonPath("$.httpStatus").value(BAD_REQUEST.name()),
jsonPath("$.errorName").value(BEAN_VALIDATION_FAIL_EXCEPTION.name()),
jsonPath("$.errorMessage").value(BEAN_VALIDATION_FAIL_EXCEPTION.getMessage())
);
Hejow marked this conversation as resolved.
Show resolved Hide resolved

// docs
result.andDo(RestDocument.builder()
.identifier("footprint-create-fail-invalid-type-contents")
.tag(ApiTag.FOOTPRINT)
.secured(true)
.result(result)
.generateDocs());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import me.ajaja.common.support.JpaTestSupport;
import me.ajaja.module.footprint.domain.Footprint;
import me.ajaja.module.footprint.domain.FootprintFactory;
import me.ajaja.module.footprint.dto.FootprintParam;
import me.ajaja.module.footprint.dto.FootprintRequest;
import me.ajaja.module.footprint.mapper.FootprintMapperImpl;

@ContextConfiguration(classes = {CreateFootprintAdaptor.class, FootprintMapperImpl.class, FootprintFactory.class})
Expand All @@ -25,12 +25,15 @@ class CreateFootprintAdaptorTest extends JpaTestSupport {
@DisplayName("자유 형식 발자취 생성 매핑 기능 구현 테스트")
void create_FreeFootprint_Success() {
// given
FootprintParam.Create param = sut.giveMeBuilder(FootprintParam.Create.class)
Long userId = 1L;

FootprintRequest.Create param = sut.giveMeBuilder(FootprintRequest.Create.class)
.set("title", "title")
.set("type", Footprint.Type.FREE)
.set("content", "content")
.sample();

Footprint freeFootprint = footprintFactory.create(param);
Footprint freeFootprint = footprintFactory.init(userId, param);

// when
Long footprintEntityId = createFootprintAdaptor.create(freeFootprint);
Expand Down
Loading
Loading