From 674a3f1f76dd4a4d3b0fb10efb340c4556e2e6e4 Mon Sep 17 00:00:00 2001 From: in seong Park <123macanic@naver.com> Date: Thu, 10 Oct 2024 13:43:03 +0900 Subject: [PATCH 1/3] =?UTF-8?q?Feat:=20Ether=20CRUD=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ether/controller/EtherController.java | 76 +++++++++++++++++++ .../ether/dto/EtherRegistRequestDTO.java | 12 +++ .../ether/dto/EtherUpdateRequestDTO.java | 14 ++++ .../devlinkbackend/ether/entity/Ether.java | 50 ++++++++++++ .../ether/repository/EtherRepository.java | 13 ++++ .../ether/service/EtherService.java | 58 ++++++++++++++ .../devlinkbackend/oauth2/entity/User.java | 16 ++++ 7 files changed, 239 insertions(+) create mode 100644 src/main/java/com/mtvs/devlinkbackend/ether/controller/EtherController.java create mode 100644 src/main/java/com/mtvs/devlinkbackend/ether/dto/EtherRegistRequestDTO.java create mode 100644 src/main/java/com/mtvs/devlinkbackend/ether/dto/EtherUpdateRequestDTO.java create mode 100644 src/main/java/com/mtvs/devlinkbackend/ether/entity/Ether.java create mode 100644 src/main/java/com/mtvs/devlinkbackend/ether/repository/EtherRepository.java create mode 100644 src/main/java/com/mtvs/devlinkbackend/ether/service/EtherService.java diff --git a/src/main/java/com/mtvs/devlinkbackend/ether/controller/EtherController.java b/src/main/java/com/mtvs/devlinkbackend/ether/controller/EtherController.java new file mode 100644 index 0000000..c0d909d --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/ether/controller/EtherController.java @@ -0,0 +1,76 @@ +package com.mtvs.devlinkbackend.ether.controller; + +import com.mtvs.devlinkbackend.config.JwtUtil; +import com.mtvs.devlinkbackend.ether.dto.EtherRegistRequestDTO; +import com.mtvs.devlinkbackend.ether.dto.EtherUpdateRequestDTO; +import com.mtvs.devlinkbackend.ether.entity.Ether; +import com.mtvs.devlinkbackend.ether.service.EtherService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/ether") +public class EtherController { + private final EtherService etherService; + private final JwtUtil jwtUtil; + + public EtherController(EtherService etherService, JwtUtil jwtUtil) { + this.etherService = etherService; + this.jwtUtil = jwtUtil; + } + + // Create + @PostMapping + public ResponseEntity registEther( + @RequestBody EtherRegistRequestDTO etherRegistRequestDTO, + @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { + + String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + Ether newEther = etherService.registEther(etherRegistRequestDTO, accountId); + return ResponseEntity.ok(newEther); + } + + // Read - Find by Ether ID + @GetMapping("/{etherId}") + public ResponseEntity findEtherByEtherId(@PathVariable Long etherId) { + Ether ether = etherService.findEtherByEtherId(etherId); + return ether != null ? ResponseEntity.ok(ether) : ResponseEntity.notFound().build(); + } + + // Read - Find by Account ID + @GetMapping("/account") + public ResponseEntity> findEthersByAccountId( + @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { + + String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + List ethers = etherService.findEthersByAccountId(accountId); + return ResponseEntity.ok(ethers); + } + + // Read - Find by Reason + @GetMapping("/reason/{reason}") + public ResponseEntity> findEthersByReason(@PathVariable String reason) { + List ethers = etherService.findEthersByReason(reason); + return ResponseEntity.ok(ethers); + } + + // Update + @PutMapping + public ResponseEntity updateEther(@RequestBody EtherUpdateRequestDTO etherUpdateRequestDTO) { + try { + Ether updatedEther = etherService.updateEther(etherUpdateRequestDTO); + return ResponseEntity.ok(updatedEther); + } catch (IllegalArgumentException e) { + return ResponseEntity.badRequest().body(null); + } + } + + // Delete + @DeleteMapping("/{etherId}") + public ResponseEntity deleteEtherByEtherId(@PathVariable Long etherId) { + etherService.deleteEtherByEtherId(etherId); + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/com/mtvs/devlinkbackend/ether/dto/EtherRegistRequestDTO.java b/src/main/java/com/mtvs/devlinkbackend/ether/dto/EtherRegistRequestDTO.java new file mode 100644 index 0000000..33235bb --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/ether/dto/EtherRegistRequestDTO.java @@ -0,0 +1,12 @@ +package com.mtvs.devlinkbackend.ether.dto; + +import lombok.*; + +@Getter @Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString +public class EtherRegistRequestDTO { + private Long amount; + private String reason; +} diff --git a/src/main/java/com/mtvs/devlinkbackend/ether/dto/EtherUpdateRequestDTO.java b/src/main/java/com/mtvs/devlinkbackend/ether/dto/EtherUpdateRequestDTO.java new file mode 100644 index 0000000..575b8af --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/ether/dto/EtherUpdateRequestDTO.java @@ -0,0 +1,14 @@ +package com.mtvs.devlinkbackend.ether.dto; + +import lombok.*; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString +public class EtherUpdateRequestDTO { + private Long etherId; + private Long amount; + private String reason; +} diff --git a/src/main/java/com/mtvs/devlinkbackend/ether/entity/Ether.java b/src/main/java/com/mtvs/devlinkbackend/ether/entity/Ether.java new file mode 100644 index 0000000..f9ab298 --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/ether/entity/Ether.java @@ -0,0 +1,50 @@ +package com.mtvs.devlinkbackend.ether.entity; + +import jakarta.persistence.*; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; + +import java.time.LocalDateTime; + +@Table(name = "ETHER") +@Entity(name = "ETHER") +@NoArgsConstructor +public class Ether { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "ETHER_ID") + private Long etherId; + + @Column(name = "AMOUNT") + private Long amount; + + @Column(name = "REASON") + private String reason; + + @CreationTimestamp + @Column(name = "CREATED_AT", updatable = false) + private LocalDateTime createdAt; + + @UpdateTimestamp + @Column(name = "MODIFIED_AT") + private LocalDateTime modifiedAt; + + @Column(name = "ACCOUNT_ID") + private String accountId; + + public Ether(String accountId, String reason, Long amount) { + this.accountId = accountId; + this.reason = reason; + this.amount = amount; + } + + public void setAmount(Long amount) { + this.amount = amount; + } + + public void setReason(String reason) { + this.reason = reason; + } +} diff --git a/src/main/java/com/mtvs/devlinkbackend/ether/repository/EtherRepository.java b/src/main/java/com/mtvs/devlinkbackend/ether/repository/EtherRepository.java new file mode 100644 index 0000000..4010eef --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/ether/repository/EtherRepository.java @@ -0,0 +1,13 @@ +package com.mtvs.devlinkbackend.ether.repository; + +import com.mtvs.devlinkbackend.ether.entity.Ether; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface EtherRepository extends JpaRepository { + public List findEthersByAccountId(String accountId); + public List findEthersByReason(String reason); +} diff --git a/src/main/java/com/mtvs/devlinkbackend/ether/service/EtherService.java b/src/main/java/com/mtvs/devlinkbackend/ether/service/EtherService.java new file mode 100644 index 0000000..fb77172 --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/ether/service/EtherService.java @@ -0,0 +1,58 @@ +package com.mtvs.devlinkbackend.ether.service; + +import com.mtvs.devlinkbackend.ether.dto.EtherRegistRequestDTO; +import com.mtvs.devlinkbackend.ether.dto.EtherUpdateRequestDTO; +import com.mtvs.devlinkbackend.ether.entity.Ether; +import com.mtvs.devlinkbackend.ether.repository.EtherRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Optional; + +@Service +public class EtherService { + private final EtherRepository etherRepository; + + public EtherService(EtherRepository etherRepository) { + this.etherRepository = etherRepository; + } + + @Transactional + public Ether registEther(EtherRegistRequestDTO etherRegistRequestDTO, String accountId) { + return etherRepository.save( + new Ether( + accountId, + etherRegistRequestDTO.getReason(), + etherRegistRequestDTO.getAmount()) + ); + } + + public Ether findEtherByEtherId(Long etherId) { + return etherRepository.findById(etherId).orElse(null); + } + + public List findEthersByAccountId(String accountId) { + return etherRepository.findEthersByAccountId(accountId); + } + + public List findEthersByReason(String reason) { + return etherRepository.findEthersByReason(reason); + } + + @Transactional + public Ether updateEther(EtherUpdateRequestDTO etherUpdateRequestDTO) { + Optional ether = etherRepository.findById(etherUpdateRequestDTO.getEtherId()); + if(ether.isPresent()) { + Ether foundEther = ether.get(); + foundEther.setReason(etherUpdateRequestDTO.getReason()); + foundEther.setAmount(etherUpdateRequestDTO.getAmount()); + return foundEther; + } else + throw new IllegalArgumentException("잘못된 Ether Id로 호출, ETHER_ID : " + etherUpdateRequestDTO.getEtherId()); + } + + public void deleteEtherByEtherId(Long etherId) { + etherRepository.deleteById(etherId); + } +} diff --git a/src/main/java/com/mtvs/devlinkbackend/oauth2/entity/User.java b/src/main/java/com/mtvs/devlinkbackend/oauth2/entity/User.java index bcb0b58..d710168 100644 --- a/src/main/java/com/mtvs/devlinkbackend/oauth2/entity/User.java +++ b/src/main/java/com/mtvs/devlinkbackend/oauth2/entity/User.java @@ -2,6 +2,10 @@ import jakarta.persistence.*; import lombok.Getter; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; + +import java.time.LocalDateTime; @Table(name = "USER") @Entity(name = "USER") @@ -11,12 +15,24 @@ public class User { @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "USER_ID") private Long userId; + @Column(name = "ACCOUNT_ID", unique = true) private String accountId; + @Column(name = "EMAIL") private String email; + @Column(name = "USER_NAME") private String userName; + + @CreationTimestamp + @Column(name = "CREATED_AT", updatable = false) + private LocalDateTime createdAt; + + @UpdateTimestamp + @Column(name = "MODIFIED_AT") + private LocalDateTime modifiedAt; + @Column(name = "REFRESH_TOKEN") private String refreshToken; // 추후 추가 정보 필요시 Entity에 Column 추가 예정 From 4ba3e606f52b61ba7344069a1075afeef0ca61f8 Mon Sep 17 00:00:00 2001 From: in seong Park <123macanic@naver.com> Date: Thu, 10 Oct 2024 13:53:38 +0900 Subject: [PATCH 2/3] =?UTF-8?q?Test:=20Ether=20CRUD=20TestCode=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../devlinkbackend/ether/EtherCRUDTest.java | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/test/java/com/mtvs/devlinkbackend/ether/EtherCRUDTest.java diff --git a/src/test/java/com/mtvs/devlinkbackend/ether/EtherCRUDTest.java b/src/test/java/com/mtvs/devlinkbackend/ether/EtherCRUDTest.java new file mode 100644 index 0000000..af47872 --- /dev/null +++ b/src/test/java/com/mtvs/devlinkbackend/ether/EtherCRUDTest.java @@ -0,0 +1,95 @@ +package com.mtvs.devlinkbackend.ether; + +import com.mtvs.devlinkbackend.ether.dto.EtherRegistRequestDTO; +import com.mtvs.devlinkbackend.ether.dto.EtherUpdateRequestDTO; +import com.mtvs.devlinkbackend.ether.service.EtherService; +import com.mtvs.devlinkbackend.question.dto.QuestionRegistRequestDTO; +import com.mtvs.devlinkbackend.question.dto.QuestionUpdateRequestDTO; +import com.mtvs.devlinkbackend.question.service.QuestionService; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; + +import java.util.stream.Stream; + +@SpringBootTest +@Transactional +public class EtherCRUDTest { + @Autowired + private EtherService etherService; + + private static Stream newEther() { + return Stream.of( + Arguments.of(new EtherRegistRequestDTO(10L, "이유0"), "계정1"), + Arguments.of(new EtherRegistRequestDTO(100L, "이유00"), "계정2") + ); + } + + private static Stream modifiedEther() { + return Stream.of( + Arguments.of(new EtherUpdateRequestDTO(1L,200L, "이유0")), + Arguments.of(new EtherUpdateRequestDTO(2L,500L , "이유00")) + ); + } + + @DisplayName("에테르 이력 추가 테스트") + @ParameterizedTest + @MethodSource("newEther") + @Order(0) + public void testCreateEther(EtherRegistRequestDTO etherRegistRequestDTO, String accountId) { + Assertions.assertDoesNotThrow(() -> etherService.registEther(etherRegistRequestDTO, accountId)); + } + + @DisplayName("PK로 에테르 이력 조회 테스트") + @ValueSource(longs = {1,2}) + @ParameterizedTest + @Order(1) + public void testFindEtherByEtherId(long etherId) { + Assertions.assertDoesNotThrow(() -> + System.out.println("Ether = " + etherService.findEtherByEtherId(etherId))); + } + + @DisplayName("계정 ID에 따른 에테르 이력 조회 테스트") + @ValueSource(strings = {"계정1", "계정2"}) + @ParameterizedTest + @Order(3) + public void testFindEthersByAccountId(String accountId) { + Assertions.assertDoesNotThrow(() -> + System.out.println("Ether = " + etherService.findEthersByAccountId(accountId))); + } + + @DisplayName("지급 이유에 따른 에테르 이력 조회 테스트") + @ValueSource(strings = {"Salary Bonus", "Expense Compensation"}) + @ParameterizedTest + @Order(4) + public void testFindEthersByReason(String reason) { + Assertions.assertDoesNotThrow(() -> + System.out.println("Ether = " + etherService.findEthersByReason(reason))); + } + + @DisplayName("에테르 이력 수정 테스트") + @MethodSource("modifiedEther") + @ParameterizedTest + @Order(5) + public void testUpdateQuestion(EtherUpdateRequestDTO etherUpdateRequestDTO) { + Assertions.assertDoesNotThrow(() -> + System.out.println(etherService.updateEther(etherUpdateRequestDTO))); + } + + @DisplayName("에테르 이력 삭제 테스트") + @ValueSource(longs = {0,1}) + @ParameterizedTest + @Order(6) + public void testDeleteEther(long etherId) { + Assertions.assertDoesNotThrow(() -> + etherService.deleteEtherByEtherId(etherId)); + } +} From 35538d41b36dbcbe295298a4564a1c7ed939b651 Mon Sep 17 00:00:00 2001 From: in seong Park <123macanic@naver.com> Date: Thu, 10 Oct 2024 13:55:20 +0900 Subject: [PATCH 3/3] Refactor: PUT mapping -> PATCH mapping --- .../mtvs/devlinkbackend/ether/controller/EtherController.java | 2 +- .../devlinkbackend/question/controller/QuestionController.java | 2 +- .../mtvs/devlinkbackend/reply/controller/ReplyController.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/mtvs/devlinkbackend/ether/controller/EtherController.java b/src/main/java/com/mtvs/devlinkbackend/ether/controller/EtherController.java index c0d909d..8eab829 100644 --- a/src/main/java/com/mtvs/devlinkbackend/ether/controller/EtherController.java +++ b/src/main/java/com/mtvs/devlinkbackend/ether/controller/EtherController.java @@ -57,7 +57,7 @@ public ResponseEntity> findEthersByReason(@PathVariable String reaso } // Update - @PutMapping + @PatchMapping public ResponseEntity updateEther(@RequestBody EtherUpdateRequestDTO etherUpdateRequestDTO) { try { Ether updatedEther = etherService.updateEther(etherUpdateRequestDTO); diff --git a/src/main/java/com/mtvs/devlinkbackend/question/controller/QuestionController.java b/src/main/java/com/mtvs/devlinkbackend/question/controller/QuestionController.java index 10ac287..7169b22 100644 --- a/src/main/java/com/mtvs/devlinkbackend/question/controller/QuestionController.java +++ b/src/main/java/com/mtvs/devlinkbackend/question/controller/QuestionController.java @@ -65,7 +65,7 @@ public ResponseEntity> getQuestionsByAccountIdWithPaging( } // Update a question by ID - @PutMapping("/{id}") + @PatchMapping("/{id}") public ResponseEntity updateQuestion( @RequestBody QuestionUpdateRequestDTO questionUpdateRequestDTO, @RequestHeader(name = "Authorization") String accessToken) throws Exception { diff --git a/src/main/java/com/mtvs/devlinkbackend/reply/controller/ReplyController.java b/src/main/java/com/mtvs/devlinkbackend/reply/controller/ReplyController.java index e9d26e7..1314eae 100644 --- a/src/main/java/com/mtvs/devlinkbackend/reply/controller/ReplyController.java +++ b/src/main/java/com/mtvs/devlinkbackend/reply/controller/ReplyController.java @@ -53,7 +53,7 @@ public ResponseEntity> findRepliesByAccountId( return ResponseEntity.ok(replies); } - @PutMapping + @PatchMapping public ResponseEntity updateReply( @RequestBody ReplyUpdateRequestDTO replyUpdateRequestDTO, @RequestHeader(name = "Authorization") String token) throws Exception {