Skip to content

Commit

Permalink
Merge pull request #197 from chjcode/feat/user-setting-color
Browse files Browse the repository at this point in the history
Feat/user setting color
  • Loading branch information
chjcode authored Sep 26, 2024
2 parents 58f0aa5 + 11ccf66 commit 2e401ff
Show file tree
Hide file tree
Showing 12 changed files with 230 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package chzzk.grassdiary.domain.color.controller;

import chzzk.grassdiary.domain.color.dto.ColorCodeResponseDTO;
import chzzk.grassdiary.domain.color.service.ColorCodeService;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/colors")
@Tag(name = "색상 컨트롤러")
public class ColorCodeController {

private final ColorCodeService colorCodeService;

@GetMapping
public List<ColorCodeResponseDTO> getAllColors() {
return colorCodeService.getAllColors();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package chzzk.grassdiary.domain.color.dto;

import chzzk.grassdiary.domain.color.entity.ColorCode;

public record ColorCodeResponseDTO(
Long id,
String colorName,
String rgb,
int price
) {
public static ColorCodeResponseDTO from(ColorCode colorCode) {
return new ColorCodeResponseDTO(
colorCode.getId(),
colorCode.getColorName(),
colorCode.getRgb(),
colorCode.getPrice()
);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package chzzk.grassdiary.domain.color;
package chzzk.grassdiary.domain.color.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package chzzk.grassdiary.domain.color;
package chzzk.grassdiary.domain.color.entity;

import chzzk.grassdiary.domain.color.entity.ColorCode;
import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package chzzk.grassdiary.domain.color.service;

import chzzk.grassdiary.domain.color.dto.ColorCodeResponseDTO;
import chzzk.grassdiary.domain.color.entity.ColorCode;
import chzzk.grassdiary.domain.color.entity.ColorCodeDAO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ColorCodeService {

private final ColorCodeDAO colorCodeDAO;

@Transactional(readOnly = true)
public List<ColorCodeResponseDTO> getAllColors() {
List<ColorCode> colorCodes = colorCodeDAO.findAll();
return colorCodes.stream()
.map(ColorCodeResponseDTO::from)
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package chzzk.grassdiary.domain.member.controller;

import chzzk.grassdiary.domain.member.dto.EquipColorResponseDTO;
import chzzk.grassdiary.domain.member.dto.MemberPurchasedColorsResponseDTO;
import chzzk.grassdiary.domain.member.service.MemberService;
import chzzk.grassdiary.domain.member.service.MyPageService;
import chzzk.grassdiary.domain.member.dto.MemberInfoDTO;
import chzzk.grassdiary.domain.member.dto.TotalRewardDTO;
import chzzk.grassdiary.domain.reward.service.RewardService;
import chzzk.grassdiary.global.auth.common.AuthenticatedMember;
import chzzk.grassdiary.global.auth.service.dto.AuthMemberPayload;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
Expand All @@ -14,6 +19,7 @@
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

Expand All @@ -24,6 +30,7 @@
public class MemberController {
private final MyPageService myPageService;
private final RewardService rewardService;
private final MemberService memberService;

@GetMapping("profile/{memberId}")
@Operation(
Expand All @@ -34,7 +41,7 @@ public class MemberController {
public ResponseEntity<?> getProfileInfo(@PathVariable Long memberId) {
return ResponseEntity.ok(myPageService.findProfileById(memberId));
}

@GetMapping("totalReward/{memberId}")
@Operation(
summary = "멤버의 누적 리워드 정보",
Expand All @@ -44,4 +51,16 @@ public ResponseEntity<?> getProfileInfo(@PathVariable Long memberId) {
public ResponseEntity<?> getTotalReward(@PathVariable Long memberId) {
return ResponseEntity.ok(rewardService.findTotalRewardById(memberId));
}

@GetMapping("/{memberId}/colors")
public MemberPurchasedColorsResponseDTO getMemberColors(@PathVariable Long memberId) {
return memberService.getPurchasedColors(memberId);
}

@PostMapping("/colors/{colorCodeId}/equip")
public EquipColorResponseDTO equipColor(
@PathVariable(name = "colorCodeId") Long colorCodeId,
@AuthenticatedMember AuthMemberPayload payload) {
return memberService.equipColor(payload.id(), colorCodeId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package chzzk.grassdiary.domain.member.dto;

import chzzk.grassdiary.domain.member.entity.Member;
import chzzk.grassdiary.domain.color.entity.ColorCode;

public record EquipColorResponseDTO(
Long memberId,
Long colorCodeId,
String colorName,
String rgb
) {
public static EquipColorResponseDTO from(Member member) {
ColorCode currentColorCode = member.getCurrentColorCode();
return new EquipColorResponseDTO(
member.getId(),
currentColorCode.getId(),
currentColorCode.getColorName(),
currentColorCode.getRgb()
);
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
package chzzk.grassdiary.domain.member.dto;


import chzzk.grassdiary.domain.color.entity.ColorCode;
import chzzk.grassdiary.domain.member.entity.MemberPurchasedColor;

public record MemberPurchasedColorResponseDTO(
Long id,
Long memberId,
Long colorCodeId,
String colorName,
String rgb
String rgb,
int price
) {
public MemberPurchasedColorResponseDTO(MemberPurchasedColor memberPurchasedColor) {
this(
memberPurchasedColor.getId(),
memberPurchasedColor.getMember().getId(),
memberPurchasedColor.getColorCode().getId(),
memberPurchasedColor.getColorCode().getColorName(),
memberPurchasedColor.getColorCode().getRgb()
public static MemberPurchasedColorResponseDTO from(MemberPurchasedColor memberPurchasedColor) {
ColorCode colorCode = memberPurchasedColor.getColorCode();
return new MemberPurchasedColorResponseDTO(
colorCode.getId(),
colorCode.getColorName(),
colorCode.getRgb(),
colorCode.getPrice()
);
}

public static MemberPurchasedColorResponseDTO from(ColorCode colorCode) {
return new MemberPurchasedColorResponseDTO(
colorCode.getId(),
colorCode.getColorName(),
colorCode.getRgb(),
colorCode.getPrice()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package chzzk.grassdiary.domain.member.dto;


import java.util.List;

public record MemberPurchasedColorsResponseDTO(
List<MemberPurchasedColorResponseDTO> colors
) {
public static MemberPurchasedColorsResponseDTO from(List<MemberPurchasedColorResponseDTO> colors) {
return new MemberPurchasedColorsResponseDTO(colors);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package chzzk.grassdiary.domain.member.entity;

import chzzk.grassdiary.domain.base.BaseTimeEntity;
import chzzk.grassdiary.domain.color.ColorCode;
import chzzk.grassdiary.domain.color.entity.ColorCode;
import chzzk.grassdiary.domain.diary.entity.Diary;
import chzzk.grassdiary.global.common.error.exception.SystemException;
import chzzk.grassdiary.global.common.response.ClientErrorCode;
Expand Down Expand Up @@ -102,4 +102,11 @@ public void deductRewardPoints(int points) {
}
this.rewardPoint -= points;
}

public void equipColor(ColorCode newColor) {
if (this.currentColorCode.getId().equals(newColor.getId())) {
throw new SystemException(ClientErrorCode.COLOR_ALREADY_EQUIPPED_ERR);
}
this.currentColorCode = newColor;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
package chzzk.grassdiary.domain.member.service;

import chzzk.grassdiary.domain.member.dto.EquipColorResponseDTO;
import chzzk.grassdiary.domain.member.dto.MemberPurchasedColorResponseDTO;
import chzzk.grassdiary.domain.member.dto.MemberPurchasedColorsResponseDTO;
import chzzk.grassdiary.domain.member.entity.MemberPurchasedColorDAO;
import chzzk.grassdiary.global.auth.service.dto.GoogleUserInfo;
import chzzk.grassdiary.domain.color.ColorCode;
import chzzk.grassdiary.domain.color.ColorCodeDAO;
import chzzk.grassdiary.domain.color.entity.ColorCode;
import chzzk.grassdiary.domain.color.entity.ColorCodeDAO;
import chzzk.grassdiary.domain.member.entity.Member;
import chzzk.grassdiary.domain.member.entity.MemberDAO;
import chzzk.grassdiary.global.common.error.exception.SystemException;
import chzzk.grassdiary.global.common.response.ClientErrorCode;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand All @@ -20,6 +28,7 @@ public class MemberService {

private final MemberDAO memberDAO;
private final ColorCodeDAO colorCodeDAO;
private final MemberPurchasedColorDAO memberPurchasedColorDAO;

public Member createMemberIfNotExist(GoogleUserInfo googleUserInfo) {
Optional<Member> foundMember = memberDAO.findByEmail(googleUserInfo.email());
Expand Down Expand Up @@ -47,4 +56,67 @@ private ColorCode getDefaultColorCode() {
.build()
));
}

public MemberPurchasedColorsResponseDTO getPurchasedColors(Long memberId) {
if (!memberDAO.existsById(memberId)) {
throw new SystemException(ClientErrorCode.MEMBER_NOT_FOUND_ERR);
}

List<MemberPurchasedColorResponseDTO> colors = new ArrayList<>(
memberPurchasedColorDAO.findAllByMemberId(memberId).stream()
.map(MemberPurchasedColorResponseDTO::from)
.toList()
);

colors.add(getDefaultColorDTO());

return MemberPurchasedColorsResponseDTO.from(colors);
}

private MemberPurchasedColorResponseDTO getDefaultColorDTO() {
ColorCode defaultColorCode = colorCodeDAO.findByColorName(DEFAULT_COLOR_NAME)
.orElseThrow(() -> new SystemException(ClientErrorCode.COLOR_CODE_NOT_FOUND_ERR));

return MemberPurchasedColorResponseDTO.from(defaultColorCode);
}

public EquipColorResponseDTO equipColor(Long logInMemberId, Long colorCodeId) {
Member member = getMemberById(logInMemberId);

validateMemberOwnsColor(colorCodeId, logInMemberId);

validateColorAlreadyEquipped(member, colorCodeId);

changeMemberColor(member, colorCodeId);

return EquipColorResponseDTO.from(member);
}

private Member getMemberById(Long id) {
return memberDAO.findById(id)
.orElseThrow(() -> new SystemException(ClientErrorCode.MEMBER_NOT_FOUND_ERR));
}

private void validateMemberOwnsColor(Long memberId, Long colorCodeId) {
boolean ownsColor = memberPurchasedColorDAO.existsByColorCodeIdAndMemberId(memberId, colorCodeId);
if (!ownsColor) {
throw new SystemException(ClientErrorCode.MEMBER_DOES_NOT_OWN_COLOR_ERR);
}
}

private void validateColorAlreadyEquipped(Member member, Long colorId) {
if (member.getCurrentColorCode().getId().equals(colorId)) {
throw new SystemException(ClientErrorCode.COLOR_ALREADY_EQUIPPED_ERR);
}
}

private void changeMemberColor(Member member, Long colorCodeId) {
ColorCode newColor = colorCodeDAO.findById(colorCodeId)
.orElseThrow(() -> new SystemException(ClientErrorCode.COLOR_CODE_NOT_FOUND_ERR));

member.equipColor(newColor);

memberDAO.save(member);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ public enum ClientErrorCode implements ErrorCodeModel {
AUTH_SESSION_EXPIRED(440, "AUTH_SESSION_EXPIRED", "세션이 만료되었습니다. 다시 로그인 해주세요."),

MEMBER_NOT_FOUND_ERR(404, "MEMBER_NOT_FOUND_ERR", "요청하신 사용자를 찾을 수 없습니다."),
MEMBER_DOES_NOT_OWN_COLOR_ERR(409, "MEMBER_DOES_NOT_OWN_COLOR_ERR", "해당 색상을 소유하고 있지 않습니다."),
PAST_DIARY_MODIFICATION_NOT_ALLOWED(409, "PAST_DIARY_MODIFICATION_NOT_ALLOWED", "과거의 일기는 수정할 수 없습니다."),
DIARY_NOT_FOUND_ERR(404, "DIARY_NOT_FOUND_ERR", "요청하신 다이어리를 찾을 수 없습니다."),
DIARY_LIKE_NOT_FOUND(404, "DIARY_LIKE_NOT_FOUND", "해당 다이어리에 좋아요를 누르지 않았습니다."),
DIARY_LIKE_ALREADY_EXISTS(409, "DIARY_LIKE_ALREADY_EXISTS", "다이어리에 좋아요를 이미 눌렀습니다."),
DIARY_ALREADY_EXISTS_FOR_TODAY(409, "DIARY_ALREADY_EXISTS_FOR_TODAY", "일기는 하루에 하나만 작성 가능합니다."),
COMMENT_NOT_FOUND_ERR(404, "COMMENT_NOT_FOUND_ERR", "요청하신 댓글을 찾을 수 없습니다."),
COLOR_ALREADY_EQUIPPED_ERR(409, "COLOR_ALREADY_EQUIPPED_ERR", "현재 사용중인 색상입니다."),
INSUFFICIENT_REWARD_POINTS_ERR(409, "INSUFFICIENT_REWARD_POINTS_ERR", "포인트가 충분하지 않습니다."),
INVALID_IMAGE_FORMAT(400, "INVALID_IMAGE_FORMAT", "허용되지 않는 파일 형식입니다."),
IMAGE_FILE_EMPTY(400, "IMAGE_FILE_EMPTY", "이미지 파일이 비어 있습니다."),
Expand Down

0 comments on commit 2e401ff

Please sign in to comment.