Skip to content

Commit

Permalink
[MERGE/#77] 학교, 학과 검색 API 구현
Browse files Browse the repository at this point in the history
[FEAT] #77 - 학교, 학과 검색 API 구현
  • Loading branch information
ckkim817 authored Jul 15, 2024
2 parents a2d0c94 + ee63948 commit a28cd57
Show file tree
Hide file tree
Showing 24 changed files with 180 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ private Appointment(
this.personalTopic = personalTopic;
}

public static Appointment createAppointment(
public static Appointment create(
Member member,
Senior senior,
AppointmentStatus appointmentStatus,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class MemberController {
@PostMapping("/auth/login")
public ResponseEntity<LoginSuccessResponse> login(
@RequestParam final String authorizationCode,
@RequestBody @Valid final MemberLoginRequest loginRequest
@Valid @RequestBody final MemberLoginRequest loginRequest
) {
return ResponseEntity.ok(memberService.create(authorizationCode, loginRequest));
}
Expand All @@ -43,7 +43,7 @@ public ResponseEntity<Void> validNickname(

@PostMapping("/phone/verify")
public ResponseEntity<Void> sendCode(
@RequestBody final SendCodeRequest sendCodeRequest
@Valid @RequestBody final SendCodeRequest sendCodeRequest
) {
messageService.sendMessage(sendCodeRequest);

Expand All @@ -52,7 +52,7 @@ public ResponseEntity<Void> sendCode(

@PostMapping("/phone/verifycode")
public ResponseEntity<Void> verifyCode(
@RequestBody final VerifyCodeRequest verifyCodeRequest
@Valid @RequestBody final VerifyCodeRequest verifyCodeRequest
) {
messageService.verifyCode(verifyCodeRequest);
messageService.validPhoneNumberDuplication(verifyCodeRequest);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package org.sopt.seonyakServer.domain.member.dto;

import jakarta.validation.constraints.NotBlank;

public record SendCodeRequest(
@NotBlank(message = "전화번호는 공백일 수 없습니다.")
String phoneNumber
) {
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package org.sopt.seonyakServer.domain.member.dto;

import jakarta.validation.constraints.NotBlank;

public record VerifyCodeRequest(
@NotBlank(message = "전화번호는 공백일 수 없습니다.")
String phoneNumber,

@NotBlank(message = "인증번호는 공백일 수 없습니다.")
String verificationCode
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ private Member(
this.email = email;
}

public static Member createMember(
public static Member create(
final SocialType socialType,
final String socialId,
final String email
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.springframework.data.jpa.repository.JpaRepository;

public interface MemberRepository extends JpaRepository<Member, Long> {

Optional<Member> findBySocialTypeAndSocialId(SocialType socialType, String socialId);

Optional<Member> findMemberById(Long id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class MemberManagementService {

@Transactional
public Long createMember(final MemberInfoResponse memberInfoResponse) {
Member member = Member.createMember(
Member member = Member.create(
memberInfoResponse.socialType(),
memberInfoResponse.socialId(),
memberInfoResponse.email()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public void sendMessage(SendCodeRequest sendCodeRequest) {
message.setText("[선약] 인증번호는 [" + verificationCode + "] 입니다.");

this.defaultMessageService.sendOne(new SingleMessageSendingRequest(message));
codeService.saveCertificationCode(toNumber, verificationCode);
codeService.saveVerificationCode(toNumber, verificationCode);
}

// 인증번호를 위한 랜덤 숫자 생성
Expand All @@ -73,7 +73,7 @@ private String generateRandomNumber(int digitCount) {
public void verifyCode(VerifyCodeRequest verifyCodeRequest) {
if (verifyCodeRequest.verificationCode().equals(
codeService.findCodeByPhoneNumber(verifyCodeRequest.phoneNumber()))) {
codeService.deleteCertificationCode(verifyCodeRequest.phoneNumber());
codeService.deleteVerificationCode(verifyCodeRequest.phoneNumber());
} else {
throw new CustomException(ErrorType.INVALID_VERIFICATION_CODE_ERROR);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ private Senior(
this.level = level;
}

public static Senior createSenior(
public static Senior create(
Member member,
String businessCard,
String detailPosition,
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.sopt.seonyakServer.domain.university.controller;

import java.util.List;
import lombok.RequiredArgsConstructor;
import org.sopt.seonyakServer.domain.university.dto.SearchDeptResponse;
import org.sopt.seonyakServer.domain.university.dto.SearchUnivResponse;
import org.sopt.seonyakServer.domain.university.service.UnivService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/search")
public class UnivController {

private final UnivService univService;

@GetMapping("/univ")
public ResponseEntity<SearchUnivResponse> searchUniv(
@RequestParam final String univName
) {
return ResponseEntity.ok(univService.searchUniv(univName));
}

@GetMapping("/dept")
public ResponseEntity<List<SearchDeptResponse>> searchDept(
@RequestParam final String univName,
@RequestParam final String deptName
) {
return ResponseEntity.ok(univService.searchDept(univName, deptName));
}
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.sopt.seonyakServer.domain.university.dto;

public record SearchDeptResponse(
String deptName,
boolean isClosed
) {
public static SearchDeptResponse of(
final String deptName,
final boolean isClosed
) {
return new SearchDeptResponse(
deptName,
isClosed
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.sopt.seonyakServer.domain.university.dto;

import java.util.List;

public record SearchUnivResponse(
List<String> univSearchResult
) {
public static SearchUnivResponse of(final List<String> univSearchResult) {
return new SearchUnivResponse(univSearchResult);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ private Department(
this.isClosed = isClosed;
}

public static Department createDepartment(
public static Department create(
final University university,
final String deptName,
final boolean isClosed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ private University(
this.univName = univName;
}

public static University createUniversity(
public static University create(
final String univName
) {
return University.builder()
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.sopt.seonyakServer.domain.university.repository;

import java.util.List;
import org.sopt.seonyakServer.domain.university.model.Department;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface DeptRepository extends JpaRepository<Department, Long> {

@Query("SELECT d "
+ "FROM Department d "
+ "WHERE d.university.univName = :univName "
+ "AND d.deptName "
+ "LIKE %:deptName%")
List<Department> findByUnivIdAndDeptNameContaining(
@Param("univName") String univName,
@Param("deptName") String deptName
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.sopt.seonyakServer.domain.university.repository;

import java.util.List;
import org.sopt.seonyakServer.domain.university.model.University;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

public interface UnivRepository extends JpaRepository<University, Long> {

@Query("SELECT u.univName "
+ "FROM University u "
+ "WHERE u.univName "
+ "LIKE %:univNamePart%")
List<String> findByUnivNameContaining(@Param("univNamePart") String univNamePart);

boolean existsByUnivName(String UnivName);
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.sopt.seonyakServer.domain.university.service;

import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.sopt.seonyakServer.domain.university.dto.SearchDeptResponse;
import org.sopt.seonyakServer.domain.university.dto.SearchUnivResponse;
import org.sopt.seonyakServer.domain.university.model.Department;
import org.sopt.seonyakServer.domain.university.repository.DeptRepository;
import org.sopt.seonyakServer.domain.university.repository.UnivRepository;
import org.sopt.seonyakServer.global.exception.enums.ErrorType;
import org.sopt.seonyakServer.global.exception.model.CustomException;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class UnivService {

private final UnivRepository univRepository;
private final DeptRepository deptRepository;

public SearchUnivResponse searchUniv(final String univNamePart) {
if (univNamePart == null || univNamePart.trim().isEmpty()) {
return SearchUnivResponse.of(List.of());
}

return SearchUnivResponse.of(univRepository.findByUnivNameContaining(univNamePart));
}

public List<SearchDeptResponse> searchDept(
final String univName,
final String deptName
) {
if (!univRepository.existsByUnivName(univName)) {
throw new CustomException(ErrorType.INVALID_UNIV_NAME_ERROR);
}

List<Department> departments = deptRepository.findByUnivIdAndDeptNameContaining(univName, deptName);

return departments.stream()
.map(department -> SearchDeptResponse.of(
department.getDeptName(),
department.isClosed())
)
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,32 @@
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;

@RedisHash(value = "Code", timeToLive = 5 * 60L) // TTL 5분
@RedisHash(value = "VerificationCode", timeToLive = 5 * 60L) // TTL 5분
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Code {

@Id
private String phoneNumber;

private String certificationCode;
private String verificationCode;

@Builder(access = AccessLevel.PRIVATE)
private Code(
final String phoneNumber,
final String certificationCode
final String verificationCode
) {
this.phoneNumber = phoneNumber;
this.certificationCode = certificationCode;
this.verificationCode = verificationCode;
}

public static Code createCode(
final String phoneNumber,
final String certificationCode
final String verificationCode
) {
return Code.builder()
.phoneNumber(phoneNumber)
.certificationCode(certificationCode)
.verificationCode(verificationCode)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,29 @@ public class CodeService {
private final CodeRepository codeRepository;

@Transactional
public void saveCertificationCode(
public void saveVerificationCode(
final String phoneNumber,
final String certificationCode
final String verificationCode
) {
codeRepository.save(
Code.createCode(
phoneNumber,
certificationCode
verificationCode
)
);
}

@Transactional(readOnly = true)
public String findCodeByPhoneNumber(final String phoneNumber) {
Code code = codeRepository.findByPhoneNumber(phoneNumber).orElseThrow(
() -> new CustomException(ErrorType.NO_VERIFICATION_REQUEST_HISTORY)
);

return code.getCertificationCode();
return code.getVerificationCode();
}

@Transactional
public void deleteCertificationCode(final String phoneNumber) {
public void deleteVerificationCode(final String phoneNumber) {
Code code = codeRepository.findByPhoneNumber(phoneNumber).orElseThrow(
() -> new CustomException(ErrorType.NO_VERIFICATION_REQUEST_HISTORY)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public enum ErrorType {
INVALID_UNIV_NAME_ERROR(HttpStatus.BAD_REQUEST, "40015", "서버에 존재하지 않는 대학명입니다."),
MAP_TO_JSON_ERROR(HttpStatus.BAD_REQUEST, "40016", "Map을 JSON 문자열로 변환하는 중 오류가 발생했습니다."),
JSON_TO_MAP_ERROR(HttpStatus.BAD_REQUEST, "40017", "JSON 문자열을 Map으로 변환하는 중 오류가 발생했습니다."),
UNIV_CERT_REQUEST_ERROR(HttpStatus.BAD_REQUEST, "40018", "이미 인증이 완료 이메일입니다."),
UNIV_CERT_REQUEST_ERROR(HttpStatus.BAD_REQUEST, "40018", "이미 인증이 완료된 이메일입니다."),
SAME_MEMBER_APPOINTMENT_ERROR(HttpStatus.BAD_REQUEST, "40019", "자기 자신에게는 약속을 신청할 수 없습니다."),

// S3 관련 오류
Expand Down

0 comments on commit a28cd57

Please sign in to comment.