diff --git a/loan/build.gradle b/loan/build.gradle index 3ec45666..09c12d29 100644 --- a/loan/build.gradle +++ b/loan/build.gradle @@ -21,6 +21,8 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.modelmapper:modelmapper:3.1.0' + compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' runtimeOnly 'com.mysql:mysql-connector-j' diff --git a/loan/src/main/java/com/example/loan/config/ModelMapperConfig.java b/loan/src/main/java/com/example/loan/config/ModelMapperConfig.java new file mode 100644 index 00000000..59fdc0a0 --- /dev/null +++ b/loan/src/main/java/com/example/loan/config/ModelMapperConfig.java @@ -0,0 +1,18 @@ +package com.example.loan.config; + +import org.modelmapper.ModelMapper; +import org.modelmapper.convention.MatchingStrategies; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ModelMapperConfig { + + @Bean + public ModelMapper modelMapper() { + ModelMapper modelMapper = new ModelMapper(); + modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); + modelMapper.getConfiguration().setSkipNullEnabled(true); + return modelMapper; + } +} \ No newline at end of file diff --git a/loan/src/main/java/com/example/loan/controller/CounselController.java b/loan/src/main/java/com/example/loan/controller/CounselController.java new file mode 100644 index 00000000..ba65a8ea --- /dev/null +++ b/loan/src/main/java/com/example/loan/controller/CounselController.java @@ -0,0 +1,24 @@ +package com.example.loan.controller; + +import com.example.loan.dto.CounselDto; +import com.example.loan.dto.ResponseDto; +import com.example.loan.service.CounselService; +import lombok.RequiredArgsConstructor; +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; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/counsels") +public class CounselController extends AbstractController { + + private final CounselService counselService; + + @PostMapping + public ResponseDto create(@RequestBody CounselDto.Request request) { + return ok(counselService.create(request)); + } + +} diff --git a/loan/src/main/java/com/example/loan/dto/CounselDto.java b/loan/src/main/java/com/example/loan/dto/CounselDto.java new file mode 100644 index 00000000..1d623268 --- /dev/null +++ b/loan/src/main/java/com/example/loan/dto/CounselDto.java @@ -0,0 +1,43 @@ +package com.example.loan.dto; + +import lombok.*; + +import java.time.LocalDateTime; + +public class CounselDto { + + @NoArgsConstructor + @AllArgsConstructor + @Getter + @Builder + public static class Request { + + private String name; + private String cellPhone; + private String email; + private String memo; + private String address; + private String addressDetail; + private String zipCode; + } + + @NoArgsConstructor + @AllArgsConstructor + @Builder + @Getter + @Setter + public static class Response { + + private Long counselId; + private String name; + private String cellPhone; + private String email; + private String memo; + private String address; + private String addressDetail; + private String zipCode; + private LocalDateTime appliedAt; + private LocalDateTime createdAt; + private LocalDateTime updatedAt; + } +} diff --git a/loan/src/main/java/com/example/loan/repository/CounselRepository.java b/loan/src/main/java/com/example/loan/repository/CounselRepository.java new file mode 100644 index 00000000..510a669f --- /dev/null +++ b/loan/src/main/java/com/example/loan/repository/CounselRepository.java @@ -0,0 +1,9 @@ +package com.example.loan.repository; + +import com.example.loan.domain.Counsel; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface CounselRepository extends JpaRepository { +} diff --git a/loan/src/main/java/com/example/loan/service/CounselService.java b/loan/src/main/java/com/example/loan/service/CounselService.java new file mode 100644 index 00000000..e8a962e5 --- /dev/null +++ b/loan/src/main/java/com/example/loan/service/CounselService.java @@ -0,0 +1,8 @@ +package com.example.loan.service; + +import com.example.loan.dto.CounselDto; + +public interface CounselService { + + CounselDto.Response create(CounselDto.Request request); +} diff --git a/loan/src/main/java/com/example/loan/service/CounselServiceImpl.java b/loan/src/main/java/com/example/loan/service/CounselServiceImpl.java new file mode 100644 index 00000000..cb87f041 --- /dev/null +++ b/loan/src/main/java/com/example/loan/service/CounselServiceImpl.java @@ -0,0 +1,28 @@ +package com.example.loan.service; + +import com.example.loan.domain.Counsel; +import com.example.loan.dto.CounselDto; +import com.example.loan.repository.CounselRepository; +import lombok.RequiredArgsConstructor; +import org.modelmapper.ModelMapper; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; + +@Service +@RequiredArgsConstructor +public class CounselServiceImpl implements CounselService { + + private final CounselRepository counselRepository; + + private final ModelMapper modelMapper; + + @Override + public CounselDto.Response create(CounselDto.Request request) { + Counsel counsel = modelMapper.map(request, Counsel.class); + counsel.setAppliedAt(LocalDateTime.now()); + + Counsel created = counselRepository.save(counsel); + return modelMapper.map(created, CounselDto.Response.class); + } +} diff --git a/loan/src/test/java/com/example/loan/service/CounselServiceTest.java b/loan/src/test/java/com/example/loan/service/CounselServiceTest.java new file mode 100644 index 00000000..c1d5a3bc --- /dev/null +++ b/loan/src/test/java/com/example/loan/service/CounselServiceTest.java @@ -0,0 +1,60 @@ +package com.example.loan.service; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.when; + +import com.example.loan.domain.Counsel; +import com.example.loan.dto.CounselDto; +import com.example.loan.repository.CounselRepository; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentMatchers; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; +import org.modelmapper.ModelMapper; + +@ExtendWith(MockitoExtension.class) +class CounselServiceTest { + + @InjectMocks + CounselServiceImpl counselService; + + @Mock + private CounselRepository counselRepository; + + @Spy + private ModelMapper modelMapper; + + @Test + void Should_ReturnResponseOfNewCounselEntity_When_RequestCounsel() { + Counsel entity = Counsel.builder() + .name("kim") + .cellPhone("010-1234-1234") + .email("email@email.com") + .memo("대출 해줭") + .zipCode("12345") + .address("서울특별시") + .addressDetail("101동 101호") + .build(); + + CounselDto.Request request = CounselDto.Request.builder() + .name("kim") + .cellPhone("010-1234-1234") + .email("email@email.com") + .memo("대출 해줭") + .zipCode("12345") + .address("서울특별시") + .addressDetail("101동 101호") + .build(); + + + when(counselRepository.save(ArgumentMatchers.any(Counsel.class))).thenReturn(entity); + + CounselDto.Response actual = counselService.create(request); + + assertThat(actual.getName()).isSameAs(entity.getName()); + } +} \ No newline at end of file