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

[FEAT/#90] 인증 동네 삭제 API 구현 #91

Merged
merged 3 commits into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
Expand Up @@ -52,6 +52,10 @@ public enum ErrorType {
INVALID_IMAGE_TYPE_ERROR(HttpStatus.BAD_REQUEST, 40045, "유효하지 않은 imageType입니다."),
INVALID_NICKNAME_ERROR(HttpStatus.BAD_REQUEST, 40051, "닉네임이 조건을 만족하지 않습니다."),
INVALID_BIRTH_DATE_ERROR(HttpStatus.BAD_REQUEST, 40053, "유효하지 않은 생년월일입니다."),
INVALID_VERIFIED_AREA_ERROR(HttpStatus.BAD_REQUEST, 40054, "유효하지 않은 인증 동네입니다."),

/* 404 Not Found */
NOT_FOUND_VERIFIED_AREA_ERROR(HttpStatus.NOT_FOUND, 40404, "존재하지 않는 인증 동네입니다."),

/* 409 Conflict */
DUPLICATED_NICKNAME_ERROR(HttpStatus.CONFLICT, 40901, "이미 사용 중인 닉네임입니다."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@
import jakarta.validation.Valid;
import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Positive;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand Down Expand Up @@ -70,7 +73,6 @@ public ResponseEntity<LoginResponse> login(
public ResponseEntity<VerifiedAreaResponse> postVerifiedArea(
@Valid @RequestBody final VerifiedAreaRequest request
) {

return ResponseEntity.ok(
memberService.createVerifiedArea(request.latitude(), request.longitude())
);
Expand All @@ -79,12 +81,21 @@ public ResponseEntity<VerifiedAreaResponse> postVerifiedArea(
@GetMapping(path = "/members/verified-areas", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<VerifiedAreaListResponse> getVerifiedAreaList(
) {

return ResponseEntity.ok(
memberService.fetchVerifiedAreaList()
);
}

@DeleteMapping(path = "/members/verified-areas/{verifiedAreaId}")
public ResponseEntity<Void> deleteVerifiedArea(
@Positive(message = "verifiedAreaId는 양수여야 합니다.")
@PathVariable(name = "verifiedAreaId") final Long verifiedAreaId
) {
memberService.deleteVerifiedArea(verifiedAreaId);

return ResponseEntity.ok().build();
}

@GetMapping(path = "/area", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<AreaResponse> getArea(
@DecimalMin(value = "33.1", message = "위도는 최소 33.1°N 이상이어야 합니다.(대한민국 기준)")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public class MemberService {
private static final char[] CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.".toCharArray();
private static final int MAX_NICKNAME_LENGTH = 16;
private static final String NICKNAME_PATTERN = "^[a-zA-Z0-9_.가-힣]+$";
private static final int MIN_VERIFIED_AREA_SIZE = 1;
private static final int MAX_VERIFIED_AREA_SIZE = 5;

private final GuidedSpotRepository guidedSpotRepository;
Expand Down Expand Up @@ -163,10 +164,7 @@ public VerifiedAreaResponse createVerifiedArea(
) {
MemberEntity memberEntity = memberRepository.findByIdOrElseThrow(principalHandler.getUserIdFromPrincipal());

List<VerifiedAreaEntity> verifiedAreaEntityList = verifiedAreaRepository.findAllByMemberId(
memberEntity.getId());

if (verifiedAreaEntityList.size() >= MAX_VERIFIED_AREA_SIZE) {
if (verifiedAreaRepository.countByMemberId(memberEntity.getId()) >= MAX_VERIFIED_AREA_SIZE) {
throw new BusinessException(ErrorType.INVALID_AREA_SIZE_ERROR);
}

Expand All @@ -193,7 +191,22 @@ public VerifiedAreaListResponse fetchVerifiedAreaList() {
.toList();

return new VerifiedAreaListResponse(verifiedAreaList);
}

@Transactional
public void deleteVerifiedArea(final Long verifiedAreaId) {
MemberEntity memberEntity = memberRepository.findByIdOrElseThrow(principalHandler.getUserIdFromPrincipal());
VerifiedAreaEntity verifiedAreaEntity = verifiedAreaRepository.findByIdOrElseThrow(verifiedAreaId);

if (!verifiedAreaEntity.getMemberId().equals(memberEntity.getId())) {
throw new BusinessException(ErrorType.INVALID_VERIFIED_AREA_ERROR);
}

if (verifiedAreaRepository.countByMemberId(memberEntity.getId()) <= MIN_VERIFIED_AREA_SIZE) {
throw new BusinessException(ErrorType.INVALID_AREA_SIZE_ERROR);
}

verifiedAreaRepository.deleteById(verifiedAreaId);
}

private VerifiedAreaEntity updateVerifiedAreaEntity(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ public interface MemberRepository extends JpaRepository<MemberEntity, Long> {
boolean existsByNickname(String nickname);

default MemberEntity findByIdOrElseThrow(Long id) {
return findById(id)
.orElseThrow(() -> new BusinessException(ErrorType.NOT_FOUND_MEMBER_ERROR));
return findById(id).orElseThrow(
() -> new BusinessException(ErrorType.NOT_FOUND_MEMBER_ERROR)
);
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
package com.acon.server.member.infra.repository;

import com.acon.server.global.exception.BusinessException;
import com.acon.server.global.exception.ErrorType;
import com.acon.server.member.infra.entity.VerifiedAreaEntity;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;

public interface VerifiedAreaRepository extends JpaRepository<VerifiedAreaEntity, Long> {

long countByMemberId(Long memberId);

boolean existsByMemberId(Long memberId);

boolean existsByMemberIdAndName(Long memberId, String name);

Optional<VerifiedAreaEntity> findById(Long id);
Copy link
Collaborator

@gahyuun gahyuun Feb 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q2: 해당 메서드를 꼭 명시해 줘야 하나요!? findById는 직접 작성하지 않아도 JpaRepository에 존재하는 거 아니었나요!?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

어머 마자요 orElseThrow 메서드 만드는 데만 집중하느라 까묵은 마이 미스테이크 .. 수정해놓겠습니다


Optional<VerifiedAreaEntity> findByMemberIdAndName(Long memberId, String name);

List<VerifiedAreaEntity> findAllByMemberId(Long memberId);
default VerifiedAreaEntity findByIdOrElseThrow(Long id) {
return findById(id).orElseThrow(
() -> new BusinessException(ErrorType.NOT_FOUND_VERIFIED_AREA_ERROR)
);
}

boolean existsByMemberId(Long memberId);
}
List<VerifiedAreaEntity> findAllByMemberId(Long memberId);
}