From 5a9ed7fd8801427b04dc355ac3028e9027d286ab Mon Sep 17 00:00:00 2001 From: in seong Park <123macanic@naver.com> Date: Thu, 7 Nov 2024 14:53:45 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20Experience=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20CRUD=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExperienceCommandController.java | 65 +++++++++++++++++++ .../request/ExperienceRegistRequestDTO.java | 15 +++++ .../request/ExperienceUpdateRequestDTO.java | 15 +++++ .../command/model/entity/Experience.java | 52 +++++++++++++++ .../repository/ExperienceRepository.java | 9 +++ .../command/service/ExperienceService.java | 65 +++++++++++++++++++ .../controller/ExperienceQueryController.java | 46 +++++++++++++ .../response/ExperienceListResponseDTO.java | 15 +++++ .../response/ExperienceSingleResponseDTO.java | 13 ++++ .../repository/ExperienceViewRepository.java | 13 ++++ .../query/service/ExperienceViewService.java | 30 +++++++++ 11 files changed, 338 insertions(+) create mode 100644 src/main/java/com/mtvs/devlinkbackend/experience/command/controller/ExperienceCommandController.java create mode 100644 src/main/java/com/mtvs/devlinkbackend/experience/command/model/dto/request/ExperienceRegistRequestDTO.java create mode 100644 src/main/java/com/mtvs/devlinkbackend/experience/command/model/dto/request/ExperienceUpdateRequestDTO.java create mode 100644 src/main/java/com/mtvs/devlinkbackend/experience/command/model/entity/Experience.java create mode 100644 src/main/java/com/mtvs/devlinkbackend/experience/command/repository/ExperienceRepository.java create mode 100644 src/main/java/com/mtvs/devlinkbackend/experience/command/service/ExperienceService.java create mode 100644 src/main/java/com/mtvs/devlinkbackend/experience/query/controller/ExperienceQueryController.java create mode 100644 src/main/java/com/mtvs/devlinkbackend/experience/query/model/dto/response/ExperienceListResponseDTO.java create mode 100644 src/main/java/com/mtvs/devlinkbackend/experience/query/model/dto/response/ExperienceSingleResponseDTO.java create mode 100644 src/main/java/com/mtvs/devlinkbackend/experience/query/repository/ExperienceViewRepository.java create mode 100644 src/main/java/com/mtvs/devlinkbackend/experience/query/service/ExperienceViewService.java diff --git a/src/main/java/com/mtvs/devlinkbackend/experience/command/controller/ExperienceCommandController.java b/src/main/java/com/mtvs/devlinkbackend/experience/command/controller/ExperienceCommandController.java new file mode 100644 index 0000000..0aa7811 --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/experience/command/controller/ExperienceCommandController.java @@ -0,0 +1,65 @@ +package com.mtvs.devlinkbackend.experience.command.controller; + +import com.mtvs.devlinkbackend.experience.command.model.dto.request.ExperienceRegistRequestDTO; +import com.mtvs.devlinkbackend.experience.command.model.dto.request.ExperienceUpdateRequestDTO; +import com.mtvs.devlinkbackend.experience.command.service.ExperienceService; +import com.mtvs.devlinkbackend.experience.query.model.dto.response.ExperienceSingleResponseDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/api/experience") +public class ExperienceCommandController { + + private final ExperienceService experienceService; + + public ExperienceCommandController(ExperienceService experienceService) { + this.experienceService = experienceService; + } + + @Operation(summary = "새 활동 이력 이력 등록", description = "새 활동 이력 이력를 등록합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "성공적으로 등록됨"), + @ApiResponse(responseCode = "400", description = "잘못된 요청 데이터"), + @ApiResponse(responseCode = "401", description = "인증되지 않음") + }) + @PostMapping + public ResponseEntity registExperience( + @RequestBody ExperienceRegistRequestDTO experienceRegistRequestDTO) { + + ExperienceSingleResponseDTO newExperience = experienceService.registExperience(experienceRegistRequestDTO); + return ResponseEntity.ok(newExperience); + } + + @Operation(summary = "Experience 수정", description = "제공된 데이터를 기반으로 특정 Experience를 수정합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "성공적으로 수정됨"), + @ApiResponse(responseCode = "400", description = "잘못된 수정 데이터"), + @ApiResponse(responseCode = "401", description = "인증되지 않음") + }) + @PatchMapping + public ResponseEntity updateEther( + @RequestBody ExperienceUpdateRequestDTO experienceUpdateRequestDTO) { + try { + ExperienceSingleResponseDTO updatedExperience = experienceService.updateExperience(experienceUpdateRequestDTO); + return ResponseEntity.ok(updatedExperience); + } catch (IllegalArgumentException e) { + return ResponseEntity.badRequest().body(null); + } + } + + @Operation(summary = "Experience 삭제", description = "Experience ID를 사용하여 Experience를 삭제합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "204", description = "성공적으로 삭제됨"), + @ApiResponse(responseCode = "401", description = "인증되지 않음"), + @ApiResponse(responseCode = "404", description = "Ether를 찾을 수 없음") + }) + @DeleteMapping("/{expId}") + public ResponseEntity deleteEtherByEtherId(@PathVariable Long expId) { + experienceService.deleteExperienceByExpId(expId); + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/com/mtvs/devlinkbackend/experience/command/model/dto/request/ExperienceRegistRequestDTO.java b/src/main/java/com/mtvs/devlinkbackend/experience/command/model/dto/request/ExperienceRegistRequestDTO.java new file mode 100644 index 0000000..39979a9 --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/experience/command/model/dto/request/ExperienceRegistRequestDTO.java @@ -0,0 +1,15 @@ +package com.mtvs.devlinkbackend.experience.command.model.dto.request; + +import lombok.*; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString +public class ExperienceRegistRequestDTO { + private Long expId; + private Long userId; + private String cause; + private Integer amount; +} diff --git a/src/main/java/com/mtvs/devlinkbackend/experience/command/model/dto/request/ExperienceUpdateRequestDTO.java b/src/main/java/com/mtvs/devlinkbackend/experience/command/model/dto/request/ExperienceUpdateRequestDTO.java new file mode 100644 index 0000000..61261ca --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/experience/command/model/dto/request/ExperienceUpdateRequestDTO.java @@ -0,0 +1,15 @@ +package com.mtvs.devlinkbackend.experience.command.model.dto.request; + +import lombok.*; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString +public class ExperienceUpdateRequestDTO { + private Long expId; + private Long userId; + private String cause; + private Integer amount; +} diff --git a/src/main/java/com/mtvs/devlinkbackend/experience/command/model/entity/Experience.java b/src/main/java/com/mtvs/devlinkbackend/experience/command/model/entity/Experience.java new file mode 100644 index 0000000..009060b --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/experience/command/model/entity/Experience.java @@ -0,0 +1,52 @@ +package com.mtvs.devlinkbackend.experience.command.model.entity; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.hibernate.annotations.CreationTimestamp; +import org.hibernate.annotations.UpdateTimestamp; + +import java.time.LocalDateTime; + +@Table(name = "EXPERIENCE") +@Entity(name = "Experience") +@Getter +@NoArgsConstructor +public class Experience { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "EXP_ID") + private Long expId; + + @Column(name = "USER_ID") + private Long userId; + + @Column(name = "CAUSE") + private String cause; + + @Column(name = "AMOUNT") + private Integer amount; + + @CreationTimestamp + @Column(name = "CREATED_AT") + private LocalDateTime createdAt; + + @UpdateTimestamp + @Column(name = "MODIFIED_AT") + private LocalDateTime modifiedAt; + + public Experience(Long userId, String cause, Integer amount) { + this.userId = userId; + this.cause = cause; + this.amount = amount; + } + + public void setCause(String cause) { + this.cause = cause; + } + + public void setAmount(Integer amount) { + this.amount = amount; + } +} diff --git a/src/main/java/com/mtvs/devlinkbackend/experience/command/repository/ExperienceRepository.java b/src/main/java/com/mtvs/devlinkbackend/experience/command/repository/ExperienceRepository.java new file mode 100644 index 0000000..8287d23 --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/experience/command/repository/ExperienceRepository.java @@ -0,0 +1,9 @@ +package com.mtvs.devlinkbackend.experience.command.repository; + +import com.mtvs.devlinkbackend.experience.command.model.entity.Experience; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ExperienceRepository extends JpaRepository { +} diff --git a/src/main/java/com/mtvs/devlinkbackend/experience/command/service/ExperienceService.java b/src/main/java/com/mtvs/devlinkbackend/experience/command/service/ExperienceService.java new file mode 100644 index 0000000..eba5b05 --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/experience/command/service/ExperienceService.java @@ -0,0 +1,65 @@ +package com.mtvs.devlinkbackend.experience.command.service; + +import com.mtvs.devlinkbackend.experience.command.model.dto.request.ExperienceRegistRequestDTO; +import com.mtvs.devlinkbackend.experience.command.model.dto.request.ExperienceUpdateRequestDTO; +import com.mtvs.devlinkbackend.experience.command.model.entity.Experience; +import com.mtvs.devlinkbackend.experience.command.repository.ExperienceRepository; +import com.mtvs.devlinkbackend.experience.query.model.dto.response.ExperienceSingleResponseDTO; +import com.mtvs.devlinkbackend.experience.query.repository.ExperienceViewRepository; +import com.mtvs.devlinkbackend.user.command.model.entity.User; +import com.mtvs.devlinkbackend.user.query.service.UserViewService; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@Service +public class ExperienceService { + private final ExperienceRepository experienceRepository; + private final ExperienceViewRepository experienceViewRepository; + private final UserViewService userViewService; + + public ExperienceService(ExperienceRepository experienceRepository, ExperienceViewRepository experienceViewRepository, UserViewService userViewService) { + this.experienceRepository = experienceRepository; + this.experienceViewRepository = experienceViewRepository; + this.userViewService = userViewService; + } + + public ExperienceSingleResponseDTO registExperience(ExperienceRegistRequestDTO experienceRegistRequestDTO) { + User user = userViewService.findUserByUserId(experienceRegistRequestDTO.getUserId()).getData(); + if(user == null) + throw new IllegalArgumentException("잘못된 UserId로 접근중"); + user.setExperienceValue(user.getExperienceValue() + experienceRegistRequestDTO.getAmount()); + + return new ExperienceSingleResponseDTO(experienceRepository.save(new Experience( + experienceRegistRequestDTO.getUserId(), + experienceRegistRequestDTO.getCause(), + experienceRegistRequestDTO.getAmount() + ))); + } + + public ExperienceSingleResponseDTO updateExperience(ExperienceUpdateRequestDTO experienceUpdateRequestDTO) { + Optional experience = experienceViewRepository.findById(experienceUpdateRequestDTO.getExpId()); + if(experience.isEmpty()) + throw new IllegalArgumentException("잘못된 expId로 접근중"); + Experience foundExperience = experience.get(); + + + User user = userViewService.findUserByUserId(experienceUpdateRequestDTO.getUserId()).getData(); + if(user == null) { + throw new IllegalArgumentException("잘못된 UserId로 접근중"); + } + + Integer difference = experienceUpdateRequestDTO.getAmount() - foundExperience.getAmount(); + + user.setExperienceValue(user.getExperienceValue() + difference); + + foundExperience.setAmount(experienceUpdateRequestDTO.getAmount()); + foundExperience.setCause(experienceUpdateRequestDTO.getCause()); + + return new ExperienceSingleResponseDTO(foundExperience); + } + + public void deleteExperienceByExpId(Long expId) { + experienceRepository.deleteById(expId); + } +} diff --git a/src/main/java/com/mtvs/devlinkbackend/experience/query/controller/ExperienceQueryController.java b/src/main/java/com/mtvs/devlinkbackend/experience/query/controller/ExperienceQueryController.java new file mode 100644 index 0000000..e5cee00 --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/experience/query/controller/ExperienceQueryController.java @@ -0,0 +1,46 @@ +package com.mtvs.devlinkbackend.experience.query.controller; + +import com.mtvs.devlinkbackend.experience.query.model.dto.response.ExperienceListResponseDTO; +import com.mtvs.devlinkbackend.experience.query.model.dto.response.ExperienceSingleResponseDTO; +import com.mtvs.devlinkbackend.experience.query.service.ExperienceViewService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/api/experience") +public class ExperienceQueryController { + + private final ExperienceViewService experienceViewService; + + public ExperienceQueryController(ExperienceViewService experienceViewService) { + this.experienceViewService = experienceViewService; + } + + @Operation(summary = "Experience ID로 Ether 조회", description = "Experience ID를 사용하여 활동내역을 조회합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "성공적으로 찾음"), + @ApiResponse(responseCode = "401", description = "인증되지 않음"), + @ApiResponse(responseCode = "404", description = "찾을 수 없음") + }) + @GetMapping("/{expId}") + public ResponseEntity findExperienceByExpId(@PathVariable Long expId) { + ExperienceSingleResponseDTO experience = experienceViewService.findExperienceByExpId(expId); + return experience != null ? ResponseEntity.ok(experience) : ResponseEntity.notFound().build(); + } + + @Operation(summary = "사용자 ID로 활동 내역 목록 조회", description = "사용자 ID를 사용하여 관련된 모든 활동 내역들을 조회합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "성공적으로 찾음"), + @ApiResponse(responseCode = "401", description = "인증되지 않음") + }) + @GetMapping("/{userId}/list/{page}") + public ResponseEntity findExperiencesByUserId( + @PathVariable(name = "userId") Long userId, @PathVariable(name = "page") Integer page) { + + ExperienceListResponseDTO ethers = experienceViewService.findExperiencesByUserId(userId, page); + return ResponseEntity.ok(ethers); + } +} diff --git a/src/main/java/com/mtvs/devlinkbackend/experience/query/model/dto/response/ExperienceListResponseDTO.java b/src/main/java/com/mtvs/devlinkbackend/experience/query/model/dto/response/ExperienceListResponseDTO.java new file mode 100644 index 0000000..19c00c5 --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/experience/query/model/dto/response/ExperienceListResponseDTO.java @@ -0,0 +1,15 @@ +package com.mtvs.devlinkbackend.experience.query.model.dto.response; + +import com.mtvs.devlinkbackend.experience.command.model.entity.Experience; +import lombok.*; + +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString +public class ExperienceListResponseDTO { + private List data; +} diff --git a/src/main/java/com/mtvs/devlinkbackend/experience/query/model/dto/response/ExperienceSingleResponseDTO.java b/src/main/java/com/mtvs/devlinkbackend/experience/query/model/dto/response/ExperienceSingleResponseDTO.java new file mode 100644 index 0000000..946ec3f --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/experience/query/model/dto/response/ExperienceSingleResponseDTO.java @@ -0,0 +1,13 @@ +package com.mtvs.devlinkbackend.experience.query.model.dto.response; + +import com.mtvs.devlinkbackend.experience.command.model.entity.Experience; +import lombok.*; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString +public class ExperienceSingleResponseDTO { + private Experience data; +} diff --git a/src/main/java/com/mtvs/devlinkbackend/experience/query/repository/ExperienceViewRepository.java b/src/main/java/com/mtvs/devlinkbackend/experience/query/repository/ExperienceViewRepository.java new file mode 100644 index 0000000..582eb76 --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/experience/query/repository/ExperienceViewRepository.java @@ -0,0 +1,13 @@ +package com.mtvs.devlinkbackend.experience.query.repository; + +import com.mtvs.devlinkbackend.experience.command.model.entity.Experience; +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 ExperienceViewRepository extends JpaRepository { + List findAllByUserId(Long userId, Pageable pageable); +} diff --git a/src/main/java/com/mtvs/devlinkbackend/experience/query/service/ExperienceViewService.java b/src/main/java/com/mtvs/devlinkbackend/experience/query/service/ExperienceViewService.java new file mode 100644 index 0000000..bb31103 --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/experience/query/service/ExperienceViewService.java @@ -0,0 +1,30 @@ +package com.mtvs.devlinkbackend.experience.query.service; + +import com.mtvs.devlinkbackend.experience.query.model.dto.response.ExperienceListResponseDTO; +import com.mtvs.devlinkbackend.experience.query.model.dto.response.ExperienceSingleResponseDTO; +import com.mtvs.devlinkbackend.experience.query.repository.ExperienceViewRepository; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; + +@Service +public class ExperienceViewService { + + private final static Integer PAGE_SIZE = 15; + + private final ExperienceViewRepository experienceViewRepository; + + public ExperienceViewService(ExperienceViewRepository experienceViewRepository) { + this.experienceViewRepository = experienceViewRepository; + } + + public ExperienceSingleResponseDTO findExperienceByExpId(Long expId) { + return new ExperienceSingleResponseDTO(experienceViewRepository.findById(expId).orElse(null)); + } + + public ExperienceListResponseDTO findExperiencesByUserId(Long userId, Integer page) { + Pageable pageable = PageRequest.of(page, PAGE_SIZE, Sort.by("createdAt").ascending()); + return new ExperienceListResponseDTO(experienceViewRepository.findAllByUserId(userId, pageable)); + } +} From e02bdb18fb49f56119d1f46abb2f5f98465131c5 Mon Sep 17 00:00:00 2001 From: in seong Park <123macanic@naver.com> Date: Thu, 7 Nov 2024 16:34:54 +0900 Subject: [PATCH 2/3] =?UTF-8?q?Fix:=20StringListConverter=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20NullPointer=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../util/converter/StringListConverter.java | 16 +++++++++-- .../command/service/ExperienceService.java | 27 +++++++++++++------ .../user/command/model/entity/Dev.java | 2 +- .../command/repository/UserRepository.java | 2 ++ 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/mtvs/devlinkbackend/common/util/converter/StringListConverter.java b/src/main/java/com/mtvs/devlinkbackend/common/util/converter/StringListConverter.java index bee9f44..6e8bf32 100644 --- a/src/main/java/com/mtvs/devlinkbackend/common/util/converter/StringListConverter.java +++ b/src/main/java/com/mtvs/devlinkbackend/common/util/converter/StringListConverter.java @@ -6,7 +6,9 @@ import jakarta.persistence.Converter; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; @Converter @@ -16,6 +18,9 @@ public class StringListConverter implements AttributeConverter, Str @Override public String convertToDatabaseColumn(List attribute) { + if (attribute == null || attribute.isEmpty()) { + return "[]"; // 빈 리스트를 JSON 배열로 변환 + } try { return objectMapper.writeValueAsString(attribute); } catch (JsonProcessingException e) { @@ -25,10 +30,17 @@ public String convertToDatabaseColumn(List attribute) { @Override public List convertToEntityAttribute(String dbData) { + if (dbData == null || dbData.trim().isEmpty()) { + return Collections.emptyList(); // 빈 리스트 반환 + } try { - return Arrays.asList(objectMapper.readValue(dbData, String[].class)); + List resultList = objectMapper.readValue(dbData, List.class); + if (resultList == null || resultList.contains(null)) { + return Collections.emptyList(); // null이거나 null이 포함된 경우 빈 리스트 반환 + } + return resultList; } catch (IOException e) { throw new RuntimeException("Could not convert JSON to list", e); } } -} \ No newline at end of file +} diff --git a/src/main/java/com/mtvs/devlinkbackend/experience/command/service/ExperienceService.java b/src/main/java/com/mtvs/devlinkbackend/experience/command/service/ExperienceService.java index eba5b05..97e0b06 100644 --- a/src/main/java/com/mtvs/devlinkbackend/experience/command/service/ExperienceService.java +++ b/src/main/java/com/mtvs/devlinkbackend/experience/command/service/ExperienceService.java @@ -7,8 +7,10 @@ import com.mtvs.devlinkbackend.experience.query.model.dto.response.ExperienceSingleResponseDTO; import com.mtvs.devlinkbackend.experience.query.repository.ExperienceViewRepository; import com.mtvs.devlinkbackend.user.command.model.entity.User; +import com.mtvs.devlinkbackend.user.command.repository.UserRepository; import com.mtvs.devlinkbackend.user.query.service.UserViewService; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.Optional; @@ -17,26 +19,35 @@ public class ExperienceService { private final ExperienceRepository experienceRepository; private final ExperienceViewRepository experienceViewRepository; private final UserViewService userViewService; + private final UserRepository userRepository; - public ExperienceService(ExperienceRepository experienceRepository, ExperienceViewRepository experienceViewRepository, UserViewService userViewService) { + public ExperienceService(ExperienceRepository experienceRepository, ExperienceViewRepository experienceViewRepository, UserViewService userViewService, UserRepository userRepository) { this.experienceRepository = experienceRepository; this.experienceViewRepository = experienceViewRepository; this.userViewService = userViewService; + this.userRepository = userRepository; } + @Transactional public ExperienceSingleResponseDTO registExperience(ExperienceRegistRequestDTO experienceRegistRequestDTO) { User user = userViewService.findUserByUserId(experienceRegistRequestDTO.getUserId()).getData(); - if(user == null) - throw new IllegalArgumentException("잘못된 UserId로 접근중"); + if (user == null) { + throw new IllegalArgumentException("잘못된 UserId로 접근중"); + } + + // 경험치 업데이트 user.setExperienceValue(user.getExperienceValue() + experienceRegistRequestDTO.getAmount()); - return new ExperienceSingleResponseDTO(experienceRepository.save(new Experience( + // 경험치 생성 및 저장 + Experience experience = experienceRepository.save(new Experience( experienceRegistRequestDTO.getUserId(), experienceRegistRequestDTO.getCause(), experienceRegistRequestDTO.getAmount() - ))); + )); + return new ExperienceSingleResponseDTO(experience); } + @Transactional public ExperienceSingleResponseDTO updateExperience(ExperienceUpdateRequestDTO experienceUpdateRequestDTO) { Optional experience = experienceViewRepository.findById(experienceUpdateRequestDTO.getExpId()); if(experience.isEmpty()) @@ -45,9 +56,8 @@ public ExperienceSingleResponseDTO updateExperience(ExperienceUpdateRequestDTO e User user = userViewService.findUserByUserId(experienceUpdateRequestDTO.getUserId()).getData(); - if(user == null) { - throw new IllegalArgumentException("잘못된 UserId로 접근중"); - } + if(user == null) + throw new IllegalArgumentException("잘못된 UserId로 접근중"); Integer difference = experienceUpdateRequestDTO.getAmount() - foundExperience.getAmount(); @@ -59,6 +69,7 @@ public ExperienceSingleResponseDTO updateExperience(ExperienceUpdateRequestDTO e return new ExperienceSingleResponseDTO(foundExperience); } + @Transactional public void deleteExperienceByExpId(Long expId) { experienceRepository.deleteById(expId); } diff --git a/src/main/java/com/mtvs/devlinkbackend/user/command/model/entity/Dev.java b/src/main/java/com/mtvs/devlinkbackend/user/command/model/entity/Dev.java index f20d5b6..180b4db 100644 --- a/src/main/java/com/mtvs/devlinkbackend/user/command/model/entity/Dev.java +++ b/src/main/java/com/mtvs/devlinkbackend/user/command/model/entity/Dev.java @@ -16,7 +16,7 @@ @Table(name = "DEV") @Entity(name = "Dev") @Getter @Setter -@ToString(exclude = "user") +@ToString @NoArgsConstructor public class Dev { @Id diff --git a/src/main/java/com/mtvs/devlinkbackend/user/command/repository/UserRepository.java b/src/main/java/com/mtvs/devlinkbackend/user/command/repository/UserRepository.java index cd8b6c2..1c66489 100644 --- a/src/main/java/com/mtvs/devlinkbackend/user/command/repository/UserRepository.java +++ b/src/main/java/com/mtvs/devlinkbackend/user/command/repository/UserRepository.java @@ -2,7 +2,9 @@ import com.mtvs.devlinkbackend.user.command.model.entity.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +@Repository public interface UserRepository extends JpaRepository { void deleteByUserId(Long userId); } From 936689aca69d27a564a7f52546f2eb12e5d3dd0f Mon Sep 17 00:00:00 2001 From: in seong Park <123macanic@naver.com> Date: Thu, 7 Nov 2024 16:35:27 +0900 Subject: [PATCH 3/3] =?UTF-8?q?test:=20Experience=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20CRUD=20TestCode=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crud/ExperienceCRUDTest.java | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 src/test/java/com/mtvs/devlinkbackend/crud/ExperienceCRUDTest.java diff --git a/src/test/java/com/mtvs/devlinkbackend/crud/ExperienceCRUDTest.java b/src/test/java/com/mtvs/devlinkbackend/crud/ExperienceCRUDTest.java new file mode 100644 index 0000000..848b1c7 --- /dev/null +++ b/src/test/java/com/mtvs/devlinkbackend/crud/ExperienceCRUDTest.java @@ -0,0 +1,161 @@ +package com.mtvs.devlinkbackend.crud; + +import com.mtvs.devlinkbackend.experience.command.model.dto.request.ExperienceRegistRequestDTO; +import com.mtvs.devlinkbackend.experience.command.model.dto.request.ExperienceUpdateRequestDTO; +import com.mtvs.devlinkbackend.experience.command.service.ExperienceService; +import com.mtvs.devlinkbackend.experience.query.service.ExperienceViewService; +import com.mtvs.devlinkbackend.user.command.model.entity.User; +import com.mtvs.devlinkbackend.user.command.repository.UserRepository; +import com.mtvs.devlinkbackend.user.query.service.UserViewService; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@SpringBootTest +@Transactional +public class ExperienceCRUDTest { + + @Autowired + private ExperienceService experienceService; + + @Autowired + private ExperienceViewService experienceViewService; + + @Autowired + private UserViewService userViewService; + + @Autowired + private UserRepository userRepository; + + @BeforeEach + void setUp() { + // Create a user if none exists + if (userRepository.findAll().isEmpty()) { + User user = new User(); + user.setNickname("TestUser"); + user.setExperienceValue(0); + user = userRepository.save(user); + } + + List user = userRepository.findAll(); + } + + @Test + @DisplayName("Experience 등록 테스트") + void registExperienceTest() { + User user = userRepository.findAll().get(0); + assertThat(user).isNotNull(); + + ExperienceRegistRequestDTO requestDTO = new ExperienceRegistRequestDTO(1L, user.getUserId(), "Test Cause", 100); + var responseDTO = experienceService.registExperience(requestDTO); + + assertThat(responseDTO).isNotNull(); + assertThat(responseDTO.getData().getCause()).isEqualTo("Test Cause"); + user = userViewService.findUserByUserId(user.getUserId()).getData(); + assertThat(user.getExperienceValue()).isEqualTo(100); + } + + @Test + @DisplayName("잘못된 UserId로 Experience 등록 시도 테스트") + void registExperienceWithInvalidUserIdTest() { + ExperienceRegistRequestDTO requestDTO = new ExperienceRegistRequestDTO(1L,999L, "Test Cause", 100); + assertThatThrownBy(() -> experienceService.registExperience(requestDTO)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("잘못된 UserId로 접근중"); + } + + @Test + @DisplayName("Experience 수정 테스트") + void updateExperienceTest() { + User user = userRepository.findAll().get(0); + assertThat(user).isNotNull(); + + ExperienceRegistRequestDTO registRequestDTO = new ExperienceRegistRequestDTO(1L, user.getUserId(), "Initial Cause", 100); + var registResponseDTO = experienceService.registExperience(registRequestDTO); + + ExperienceUpdateRequestDTO updateRequestDTO = new ExperienceUpdateRequestDTO( + registResponseDTO.getData().getExpId(), + user.getUserId(), + "Updated Cause", + 200 + ); + + var updateResponseDTO = experienceService.updateExperience(updateRequestDTO); + assertThat(updateResponseDTO).isNotNull(); + assertThat(updateResponseDTO.getData().getCause()).isEqualTo("Updated Cause"); + assertThat(updateResponseDTO.getData().getAmount()).isEqualTo(200); + } + + @Test + @DisplayName("잘못된 ExperienceId로 Experience 수정 시도 테스트") + void updateExperienceWithInvalidExpIdTest() { + User user = userRepository.findAll().get(0); + assertThat(user).isNotNull(); + + ExperienceUpdateRequestDTO updateRequestDTO = new ExperienceUpdateRequestDTO(999L, user.getUserId(), "Updated Cause", 200); + assertThatThrownBy(() -> experienceService.updateExperience(updateRequestDTO)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("잘못된 expId로 접근중"); + } + + @Test + @DisplayName("잘못된 UserId로 Experience 수정 시도 테스트") + void updateExperienceWithInvalidUserIdTest() { + User user = userRepository.findAll().get(0); + assertThat(user).isNotNull(); + + ExperienceRegistRequestDTO registRequestDTO = new ExperienceRegistRequestDTO(1L,user.getUserId(), "Initial Cause", 100); + var registResponseDTO = experienceService.registExperience(registRequestDTO); + + ExperienceUpdateRequestDTO updateRequestDTO = new ExperienceUpdateRequestDTO( + registResponseDTO.getData().getExpId(), + 999L, // 잘못된 UserId + "Updated Cause", + 200 + ); + + assertThatThrownBy(() -> experienceService.updateExperience(updateRequestDTO)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("잘못된 UserId로 접근중"); + } + + @Test + @DisplayName("Experience 삭제 테스트") + void deleteExperienceTest() { + User user = userRepository.findAll().get(0); + assertThat(user).isNotNull(); + + ExperienceRegistRequestDTO requestDTO = new ExperienceRegistRequestDTO(1L,user.getUserId(), "Test Cause", 100); + var responseDTO = experienceService.registExperience(requestDTO); + + Long expId = 999L; + experienceService.deleteExperienceByExpId(expId); + + Assertions.assertNull(experienceViewService.findExperienceByExpId(expId).getData()); + } + + @Test + @DisplayName("UserId로 Experience 목록 조회 테스트") + void findExperiencesByUserIdTest() { + User user = userRepository.findAll().get(0); + assertThat(user).isNotNull(); + + ExperienceRegistRequestDTO requestDTO1 = new ExperienceRegistRequestDTO(1L, user.getUserId(), "Cause 1", 50); + ExperienceRegistRequestDTO requestDTO2 = new ExperienceRegistRequestDTO(2L, user.getUserId(), "Cause 2", 150); + experienceService.registExperience(requestDTO1); + experienceService.registExperience(requestDTO2); + + var experienceListDTO = experienceViewService.findExperiencesByUserId(user.getUserId(), 0); + assertThat(experienceListDTO).isNotNull(); + assertThat(experienceListDTO.getData()).hasSize(2); + } +}