From 7ceabea9383a6a327b422d494c04751b04634a06 Mon Sep 17 00:00:00 2001 From: kimjunhee Date: Mon, 7 Jul 2025 20:50:56 +0900 Subject: [PATCH 01/12] =?UTF-8?q?=EC=9A=94=EC=96=91=20=EB=B3=B4=ED=98=B8?= =?UTF-8?q?=EC=82=AC=20=EB=B0=98=ED=99=98=EA=B0=92=EC=97=90=20helperSeq=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/HelperSignUpResponseDto.java | 19 +++++++++++++++++++ .../galaxy/signUp/SignUpController.java | 2 -- .../galaxy/signUp/service/SignUpService.java | 4 ++-- .../signUp/service/SignUpServiceImpl.java | 8 ++++++-- 4 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/balybus/galaxy/login/classic/dto/response/HelperSignUpResponseDto.java diff --git a/src/main/java/com/balybus/galaxy/login/classic/dto/response/HelperSignUpResponseDto.java b/src/main/java/com/balybus/galaxy/login/classic/dto/response/HelperSignUpResponseDto.java new file mode 100644 index 00000000..e445d3ea --- /dev/null +++ b/src/main/java/com/balybus/galaxy/login/classic/dto/response/HelperSignUpResponseDto.java @@ -0,0 +1,19 @@ +package com.balybus.galaxy.login.classic.dto.response; + +import com.balybus.galaxy.login.classic.dto.request.HelperCertDTO; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class HelperSignUpResponseDto { + + private Long helperSeq; + List invalidCertList; +} diff --git a/src/main/java/com/balybus/galaxy/signUp/SignUpController.java b/src/main/java/com/balybus/galaxy/signUp/SignUpController.java index 5ceeee81..19598079 100644 --- a/src/main/java/com/balybus/galaxy/signUp/SignUpController.java +++ b/src/main/java/com/balybus/galaxy/signUp/SignUpController.java @@ -81,8 +81,6 @@ public ResponseEntity checkAuthenticationCode(@RequestBody MailRequestDto.Che }) @PostMapping("/helper") public ResponseEntity signUpHelper(@RequestBody SignUpDTO signUpDTO) { -// if(SignUpDTO.hasNullDataBeforeSignUp(signUpDTO)) -// throw new BadRequestException(SIGNUP_INFO_NULL); if(signUpDTO.hasNullDataBeforeSignUp()) throw new BadRequestException(SIGNUP_INFO_NULL); diff --git a/src/main/java/com/balybus/galaxy/signUp/service/SignUpService.java b/src/main/java/com/balybus/galaxy/signUp/service/SignUpService.java index c5e5a93b..42866bf4 100644 --- a/src/main/java/com/balybus/galaxy/signUp/service/SignUpService.java +++ b/src/main/java/com/balybus/galaxy/signUp/service/SignUpService.java @@ -6,15 +6,15 @@ import com.balybus.galaxy.global.domain.tblCenterManager.dto.CenterManagerResponseDto; import com.balybus.galaxy.global.utils.mail.dto.MailRequestDto; import com.balybus.galaxy.global.utils.mail.dto.MailResponseDto; -import com.balybus.galaxy.login.classic.dto.request.HelperCertDTO; import com.balybus.galaxy.login.classic.dto.request.SignUpDTO; +import com.balybus.galaxy.login.classic.dto.response.HelperSignUpResponseDto; import java.util.List; public interface SignUpService { MailResponseDto.AuthenticationMail authenticationMail(MailRequestDto.AuthenticationMail dto); MailResponseDto.CheckAuthenticationCode checkAuthenticationCode(MailRequestDto.CheckAuthenticationCode dto); - List signUpHelper(SignUpDTO signUpRequest); + HelperSignUpResponseDto signUpHelper(SignUpDTO signUpRequest); CenterResponseDto.GetCenterList getCenterList(CenterRequestDto.GetCenterList centerDto); CenterResponseDto.RegisterCenter registerCenter(CenterRequestDto.RegisterCenter centerDto); CenterManagerResponseDto.SignUpManager signUpManager(CenterManagerRequestDto.SignUpManager centerDto); diff --git a/src/main/java/com/balybus/galaxy/signUp/service/SignUpServiceImpl.java b/src/main/java/com/balybus/galaxy/signUp/service/SignUpServiceImpl.java index d9c567c7..3ba52781 100644 --- a/src/main/java/com/balybus/galaxy/signUp/service/SignUpServiceImpl.java +++ b/src/main/java/com/balybus/galaxy/signUp/service/SignUpServiceImpl.java @@ -26,6 +26,7 @@ import com.balybus.galaxy.login.classic.domain.type.RoleType; import com.balybus.galaxy.login.classic.dto.request.HelperCertDTO; import com.balybus.galaxy.login.classic.dto.request.SignUpDTO; +import com.balybus.galaxy.login.classic.dto.response.HelperSignUpResponseDto; import com.balybus.galaxy.member.domain.TblUser; import com.balybus.galaxy.member.domain.type.LoginType; import com.balybus.galaxy.member.repository.MemberRepository; @@ -192,7 +193,7 @@ private TblUser signUpLogin(String email, String pw, RoleType roleType, LoginTyp * @return TblHelperResponse */ @Override - public List signUpHelper(SignUpDTO signUpRequest) { + public HelperSignUpResponseDto signUpHelper(SignUpDTO signUpRequest) { // 1.이메일 유효셩 검사 및 아이디 비밀번호 등록 TblUser savedMember = signUpLogin(signUpRequest.getEmail(), signUpRequest.getPassword(), signUpRequest.getRoleType(), LoginType.DOLBOM_LOGIN); @@ -267,7 +268,10 @@ public List signUpHelper(SignUpDTO signUpRequest) { } } - return invalidCertList; + return HelperSignUpResponseDto.builder() + .helperSeq(helper.getId()) + .invalidCertList(invalidCertList) + .build(); } // public TblHelperCert makeCertTbl(String name, From f30cdbcc2d9e2207bf8abaa265e7eb41c761cddc Mon Sep 17 00:00:00 2001 From: jg Date: Fri, 11 Jul 2025 12:56:58 +0900 Subject: [PATCH 02/12] =?UTF-8?q?[MOD]=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=8B=9C=20=EB=B0=98=ED=99=98=EA=B0=92=EC=9C=BC=EB=A1=9C=20hel?= =?UTF-8?q?perSeq/cmSeq=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../classic/controller/LoginController.java | 4 +++ .../service/login/LoginServiceImpl.java | 28 +++++++++++++++++-- .../member/dto/response/MemberResponse.java | 6 ++++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/balybus/galaxy/login/classic/controller/LoginController.java b/src/main/java/com/balybus/galaxy/login/classic/controller/LoginController.java index 5c8c51bb..4f38828f 100644 --- a/src/main/java/com/balybus/galaxy/login/classic/controller/LoginController.java +++ b/src/main/java/com/balybus/galaxy/login/classic/controller/LoginController.java @@ -69,6 +69,10 @@ public ResponseEntity refreshToken() { @ApiResponse(responseCode = "200", description = "로그인 성공", content = @Content(schema = @Schema(implementation = MemberResponse.SignInDto.class))), @ApiResponse(responseCode = "4002", description = "아이디/비밀번호 불일치", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse(responseCode = "3000", description = "요양보호사 정보를 찾을 수 없습니다.", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse(responseCode = "7000", description = "관리자 정보를 찾을 수 없습니다.", content = @Content(schema = @Schema(implementation = ErrorResponse.class))) }) public ResponseEntity signIn(@RequestBody MemberRequest.SignInDto dto, HttpServletRequest request, HttpServletResponse response) { diff --git a/src/main/java/com/balybus/galaxy/login/classic/service/login/LoginServiceImpl.java b/src/main/java/com/balybus/galaxy/login/classic/service/login/LoginServiceImpl.java index a5e72ef7..24c2fb35 100644 --- a/src/main/java/com/balybus/galaxy/login/classic/service/login/LoginServiceImpl.java +++ b/src/main/java/com/balybus/galaxy/login/classic/service/login/LoginServiceImpl.java @@ -1,15 +1,20 @@ package com.balybus.galaxy.login.classic.service.login; +import com.balybus.galaxy.careAssistant.domain.TblHelper; +import com.balybus.galaxy.careAssistant.repository.HelperRepository; import com.balybus.galaxy.global.domain.tblAuthenticationMail.TblAuthenticationMailMsgEnum; import com.balybus.galaxy.global.config.jwt.CookieUtils; import com.balybus.galaxy.global.config.jwt.redis.TokenRedis; import com.balybus.galaxy.global.config.jwt.redis.TokenRedisRepository; +import com.balybus.galaxy.global.domain.tblCenterManager.TblCenterManager; +import com.balybus.galaxy.global.domain.tblCenterManager.TblCenterManagerRepository; import com.balybus.galaxy.global.exception.BadRequestException; import com.balybus.galaxy.global.exception.ExceptionCode; import com.balybus.galaxy.global.utils.mail.ContentType; import com.balybus.galaxy.global.utils.mail.SendMailRequest; import com.balybus.galaxy.global.utils.mail.SendMailUtils; import com.balybus.galaxy.global.utils.mail.dto.contents.ContentDto; +import com.balybus.galaxy.login.classic.domain.type.RoleType; import com.balybus.galaxy.login.classic.dto.request.RefreshTokenDTO; import com.balybus.galaxy.login.classic.infrastructure.jwt.TokenProvider; import com.balybus.galaxy.member.domain.TblUser; @@ -44,6 +49,9 @@ public class LoginServiceImpl implements LoginService { private final MemberRepository memberRepository; private final TokenRedisRepository tokenRedisRepository; + private final HelperRepository helperRepository; + private final TblCenterManagerRepository centerManagerRepository; + public String renewAccessToken(RefreshTokenDTO refreshTokenDTO) { return tokenProvider.renewAccessToken(refreshTokenDTO.getRefreshToken()); } @@ -68,20 +76,34 @@ public MemberResponse.SignInDto signIn(MemberRequest.SignInDto signInDto, HttpSe TblUser login = userOpt.get(); // 2. 비밀번호 일치하는지 확인 if (bCryptPasswordEncoder.matches(signInDto.getUserPw(), login.getPassword())) { - // 3. 1에서 찾은 데이터를 통해 JWT 생성 및 반환 + // 3. 요양보호사/센터관리자 구분자 찾기 + Long authSeq = null; + if(login.getUserAuth().equals(RoleType.MEMBER)){ + Optional helperOpt = helperRepository.findByUserId(login.getId()); + if(helperOpt.isEmpty()) throw new BadRequestException(ExceptionCode.NOT_FOUND_HELPER); + authSeq = helperOpt.get().getId(); + } else if(login.getUserAuth().equals(RoleType.MANAGER)){ + Optional cmOpt = centerManagerRepository.findByMember_Id(login.getId()); + if(cmOpt.isEmpty()) throw new BadRequestException(ExceptionCode.NOT_FOUND_MANAGER); + authSeq = cmOpt.get().getId(); + } + + // 4. 1에서 찾은 데이터를 통해 JWT 생성 및 반환 String accessToken = tokenProvider.generateAccessToken(login.getEmail()); String refreshToken = tokenProvider.refreshToken(login.getEmail()); login.updateRefreshToken(refreshToken); - // 4. redis 에 토큰 저장 + // 5. redis 에 토큰 저장 tokenRedisRepository.save(new TokenRedis(login.getEmail(), accessToken, refreshToken)); cookieUtils.saveCookie(request, response, accessToken); - // 5. 조회 결과 전달 + // 6. 조회 결과 전달 return MemberResponse.SignInDto.builder() .chatSenderId(login.getId()) .email(login.getEmail()) .userAuth(login.getUserAuth()) + .helperSeq(login.getUserAuth().equals(RoleType.MEMBER) ? authSeq : null) + .cmSeq(login.getUserAuth().equals(RoleType.MANAGER) ? authSeq : null) .build(); } else { log.error("로그인 실패 : 아이디, 비밀번호 불일치, 사용자 ID {}", signInDto.getUserId()); diff --git a/src/main/java/com/balybus/galaxy/member/dto/response/MemberResponse.java b/src/main/java/com/balybus/galaxy/member/dto/response/MemberResponse.java index 513d87fe..3a52dc15 100644 --- a/src/main/java/com/balybus/galaxy/member/dto/response/MemberResponse.java +++ b/src/main/java/com/balybus/galaxy/member/dto/response/MemberResponse.java @@ -1,6 +1,7 @@ package com.balybus.galaxy.member.dto.response; import com.balybus.galaxy.login.classic.domain.type.RoleType; +import com.fasterxml.jackson.annotation.JsonInclude; import lombok.Builder; import lombok.Getter; @@ -11,6 +12,11 @@ public static class SignInDto{ private Long chatSenderId; private String email; private RoleType userAuth; + + @JsonInclude(JsonInclude.Include.NON_NULL) + private Long helperSeq; //요양보호사 구분자 + @JsonInclude(JsonInclude.Include.NON_NULL) + private Long cmSeq; //센터관리자 구분자 } @Builder @Getter From f2833041f7d5dc758bd49f16e9101018aa0a46e4 Mon Sep 17 00:00:00 2001 From: LeeJeongGyo <56748935+LeeJeonggyo@users.noreply.github.com> Date: Fri, 11 Jul 2025 13:05:36 +0900 Subject: [PATCH 03/12] Update gradle.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit push/pull 시 서버 반영 작업 --- .github/workflows/gradle.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 8db66f5b..a068696b 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -2,11 +2,9 @@ name: CI/CD with Gradle on: push: - branches: main + branches: [ "main", "dev" ] pull_request: - branches: - - main - - dev + branches: [ "main", "dev" ] env: S3_BUCKET_NAME: galaxy-dev-bucket From f6b722adfb08704682dd67a9c37c9389bb4bff38 Mon Sep 17 00:00:00 2001 From: kimjunhee Date: Fri, 18 Jul 2025 14:52:48 +0900 Subject: [PATCH 04/12] =?UTF-8?q?=EA=B0=9C=EC=9D=B8=20=EC=9A=94=EC=96=91?= =?UTF-8?q?=EB=B3=B4=ED=98=B8=EC=82=AC=20=EA=B5=AC=EB=B6=84=EC=9E=90?= =?UTF-8?q?=EB=A1=9C=20=EC=9A=94=EC=96=91=EB=B3=B4=ED=98=B8=EC=82=AC=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/HelperController.java | 19 ++++++++++- .../dto/request/HelperDetailDTO.java | 12 +++++++ .../dto/response/HelperDetailResponse.java | 27 +++++++++++++++ .../careAssistant/service/HelperService.java | 2 +- .../service/HelperServiceImpl.java | 33 +++++++++++++++++++ .../member/dto/request/MemberRequest.java | 1 - 6 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/balybus/galaxy/careAssistant/dto/request/HelperDetailDTO.java create mode 100644 src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperDetailResponse.java diff --git a/src/main/java/com/balybus/galaxy/careAssistant/controller/HelperController.java b/src/main/java/com/balybus/galaxy/careAssistant/controller/HelperController.java index 1bd11735..c1011394 100644 --- a/src/main/java/com/balybus/galaxy/careAssistant/controller/HelperController.java +++ b/src/main/java/com/balybus/galaxy/careAssistant/controller/HelperController.java @@ -184,7 +184,7 @@ public ResponseEntity searchHelper(@RequestBody HelperSear * @param helperCertDTO 요양 보호사 자격증 정보 * @return */ - @Operation(summary = "요양 보호사 자격증 검증", description = "요양 보호사 관련 자격증 유효성을 Q-Net에서 검증하기ㅏ") + @Operation(summary = "요양 보호사 자격증 검증", description = "요양 보호사 관련 자격증 유효성을 Q-Net에서 검증하기") @ApiResponses({ @ApiResponse(responseCode = "200", description = "요양 보호사 관련 자격증이 인증되었습니다.", content = @Content(schema = @Schema(implementation = HelperSearchResponse.class))), @@ -198,4 +198,21 @@ public ResponseEntity> certiVerify( Map result = helperService.saveCertificateByQNet(helperCertDTO, userDetails); return ResponseEntity.ok(result); } + + ////////////// + + @Operation(summary = "요양 보호사 정보 모두보기", description = "개인 요양보호사 구분자로 요양보호사 상세 조회") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "요양 보호사 정보를 성공적으로 불러왔습니다.", + content = @Content(schema = @Schema(implementation = HelperResponse.class)) + ), + @ApiResponse(responseCode = "3000", description = "요양 보호사 정보를 찾을 수 없습니다.") + }) + @PostMapping("/detail/helper-info") + public ResponseEntity detailHelperInfo( + @RequestBody HelperDetailDTO helperDetailDTO + ) { + HelperResponse helperResponse = helperService.getHelperDetail(helperDetailDTO); + return ResponseEntity.ok(helperResponse); + } } diff --git a/src/main/java/com/balybus/galaxy/careAssistant/dto/request/HelperDetailDTO.java b/src/main/java/com/balybus/galaxy/careAssistant/dto/request/HelperDetailDTO.java new file mode 100644 index 00000000..a996fdeb --- /dev/null +++ b/src/main/java/com/balybus/galaxy/careAssistant/dto/request/HelperDetailDTO.java @@ -0,0 +1,12 @@ +package com.balybus.galaxy.careAssistant.dto.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class HelperDetailDTO { + private Long helperSeq; +} diff --git a/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperDetailResponse.java b/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperDetailResponse.java new file mode 100644 index 00000000..87876be0 --- /dev/null +++ b/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperDetailResponse.java @@ -0,0 +1,27 @@ +package com.balybus.galaxy.careAssistant.dto.response; + +import com.balybus.galaxy.login.classic.dto.request.HelperCertDTO; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Builder +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class HelperDetailResponse { + private Long id; + private String userEmail; + + private String name; + private String phone; + private String addressDetail; + private List certificates; + private boolean carOwnYn; + private boolean eduYn; + private Integer wage; + private Integer wageState; +} diff --git a/src/main/java/com/balybus/galaxy/careAssistant/service/HelperService.java b/src/main/java/com/balybus/galaxy/careAssistant/service/HelperService.java index 6bb26cb5..53174419 100644 --- a/src/main/java/com/balybus/galaxy/careAssistant/service/HelperService.java +++ b/src/main/java/com/balybus/galaxy/careAssistant/service/HelperService.java @@ -18,5 +18,5 @@ public interface HelperService { HelperSearchResponse helperSearch(HelperSearchDTO helperSearchDTO); Map saveCertificateByQNet(List helperCertDTO, UserDetails userDetails); String checkCertificate(String name, String birth, String certNo, String issueDate, String insideNo); - + HelperResponse getHelperDetail(HelperDetailDTO helperDetailDTO); } diff --git a/src/main/java/com/balybus/galaxy/careAssistant/service/HelperServiceImpl.java b/src/main/java/com/balybus/galaxy/careAssistant/service/HelperServiceImpl.java index 821fdc2d..3aace107 100644 --- a/src/main/java/com/balybus/galaxy/careAssistant/service/HelperServiceImpl.java +++ b/src/main/java/com/balybus/galaxy/careAssistant/service/HelperServiceImpl.java @@ -491,5 +491,38 @@ public String checkCertificate(String name, String birth, String certNo, String return result; } + @Override + public HelperResponse getHelperDetail(HelperDetailDTO helperDetailDTO) { + TblHelper helper = helperRepository.findById(helperDetailDTO.getHelperSeq()) + .orElseThrow(() -> new BadRequestException(NOT_FOUND_HELPER)); + TblUser user = memberRepository.findById(helper.getUser().getId()) + .orElseThrow(() -> new BadRequestException(NOT_FOUND_HELPER)); + + List certificates = helperCertRepository.findAllById(Collections.singleton(helper.getId())); + List certDTOList = new ArrayList<>(); + + for(TblHelperCert tblHelperCert : certificates) { + certDTOList.add(HelperCertDTO.builder() + .certName(tblHelperCert.getCertName()) + .certNum(tblHelperCert.getCertNum()) + .certDateIssue(tblHelperCert.getCertDateIssue()) + .certSerialNum(tblHelperCert.getCertSerialNum()) + .build()); + } + + return HelperResponse.builder() + .id(helper.getId()) + .userEmail(user.getEmail()) + .name(helper.getName()) + .phone(helper.getPhone()) + .addressDetail(helper.getAddressDetail()) + .certificates(certDTOList) + .carOwnYn(helper.isCarOwnYn()) + .eduYn(helper.isEduYn()) + .wage(helper.getWage()) + .wageState(helper.getWageState()) + .build(); + } + } \ No newline at end of file diff --git a/src/main/java/com/balybus/galaxy/member/dto/request/MemberRequest.java b/src/main/java/com/balybus/galaxy/member/dto/request/MemberRequest.java index 13fd2b94..ebd4e526 100644 --- a/src/main/java/com/balybus/galaxy/member/dto/request/MemberRequest.java +++ b/src/main/java/com/balybus/galaxy/member/dto/request/MemberRequest.java @@ -1,6 +1,5 @@ package com.balybus.galaxy.member.dto.request; -import com.balybus.galaxy.login.oauth.domain.type.CaseType; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; From 61694a02d11b768247d57ccdb41d8aaba2a99caa Mon Sep 17 00:00:00 2001 From: kimjunhee Date: Sat, 19 Jul 2025 19:29:51 +0900 Subject: [PATCH 05/12] =?UTF-8?q?=EA=B0=9C=EC=9D=B8=20=EC=9A=94=EC=96=91?= =?UTF-8?q?=EB=B3=B4=ED=98=B8=EC=82=AC=20=EA=B5=AC=EB=B6=84=EC=9E=90?= =?UTF-8?q?=EB=A1=9C=20=EC=9A=94=EC=96=91=EB=B3=B4=ED=98=B8=EC=82=AC=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20=EC=9A=94=EC=96=91=20?= =?UTF-8?q?=EB=B3=B4=ED=98=B8=EC=82=AC=20=EA=B5=AC=EB=B6=84=EC=9E=90?= =?UTF-8?q?=EB=A1=9C=20=EB=A7=A4=EC=B9=AD=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tblMatching/TblMatchingRepository.java | 37 ++++- .../service/login/LoginServiceImpl.java | 2 +- .../loginAuth/LoginAuthCheckService.java | 2 + .../loginAuth/LoginAuthCheckServiceImpl.java | 25 ++- .../MatchingStatusController.java | 58 ++++++- .../dto/MatchingStatusResponseDto.java | 50 +++++- .../service/MatchingStatusService.java | 8 + .../service/MatchingStatusServiceImpl.java | 154 ++++++++++++++++++ 8 files changed, 329 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/balybus/galaxy/global/domain/tblMatching/TblMatchingRepository.java b/src/main/java/com/balybus/galaxy/global/domain/tblMatching/TblMatchingRepository.java index 90bf35ae..db168722 100644 --- a/src/main/java/com/balybus/galaxy/global/domain/tblMatching/TblMatchingRepository.java +++ b/src/main/java/com/balybus/galaxy/global/domain/tblMatching/TblMatchingRepository.java @@ -43,12 +43,47 @@ List findMatchingByManagerIdAndMatchStates( @Param("matchStates") List matchStates ); + // 요양보호사 기준 매칭 조회 메서드들 + @Query(""" + SELECT m FROM TblMatching m + JOIN FETCH m.helper h + JOIN FETCH m.patientLog pl + JOIN FETCH pl.patient p + JOIN FETCH pl.tblAddressFirst af + JOIN FETCH pl.tblAddressSecond as + JOIN FETCH pl.tblAddressThird at + WHERE m.helper.id = :helperId + AND m.matchState IN :matchStates + AND m.useYn = true + ORDER BY m.createDatetime DESC""") + List findMatchingByHelperIdAndMatchStates( + @Param("helperId") Long helperId, + @Param("matchStates") List matchStates + ); + + @Query(""" + SELECT m FROM TblMatching m + JOIN FETCH m.helper h + JOIN FETCH m.patientLog pl + JOIN FETCH pl.patient p + JOIN FETCH pl.tblAddressFirst af + JOIN FETCH pl.tblAddressSecond as + JOIN FETCH pl.tblAddressThird at + WHERE m.helper.id = :helperId + AND m.matchState = :matchState + AND m.useYn = true + ORDER BY m.createDatetime DESC""") + List findMatchingByHelperIdAndMatchState( + @Param("helperId") Long helperId, + @Param("matchState") MatchState matchState + ); + @Query(value = """ select count(case when (a.reject_count = 0 and a.match_fin_count = 0 and a.permit_tune_count = 0 and a.match_request_count = 0 and a.init_count > 0) then 1 end) as new_match_count -- 신규 매칭 건수 : 해당 계정으로 관리하고 있는 완료되지 않은 매칭(공고) 건수 - init 만으로 구성된공고 개수 ,count(a.pl_seq) as total -- 전체 매칭 건수 : 해당 계정으로 관리하고 있는 매칭(공고) 건수 ,count(case when (a.match_fin_count = 0 and a.permit_tune_count > 0) then 1 end) as in_progress_count -- 상태별 매칭 건수 - 진행중 : PERMIT_TUNE(2, "수락함(조율중)") 상태의 공고 개수 - 매칭 완료가 아닌 공고 중 수락함(조율 중) 상태의 건수가 하나라도 존재하는 경우, 진행중으로 여긴다. - ,count(case when a.match_fin_count > 0 then 1 end) as match_fin_count -- 상태별 매칭 건수 - 완료 : MATCH_FIN(3, "매칭 완료") 상태의 공고 개수 - 매칭보호사 리스트 중 한 명이라도 완료가 되면, 해당 건은 매칭이 완료된 것으로 여긴다. + ,count(case when a.match_fin_count > 0 then 1 end) as match_fin_count -- 상태별 매칭 건수 - 완료 : MATCH_FIN(3, "매칭 완료") 상태의 공고 개수 - 매칭보호사 리스트 중 ,sum(a.permit_tune_count + a.match_fin_count) as permit_count -- 매칭 비율 - 수락률 : 매칭 리스트 전체에 대한 조율 매칭 완료 개수(수락)의 비율 - 수락/(수락+거절) ,sum(a.reject_count) as reject_count -- 매칭 비율 - 거절률 : 매칭 리스트 전체에 대한 거절 개수(거절)의 비율 - 거절/(수락+거절) from( diff --git a/src/main/java/com/balybus/galaxy/login/classic/service/login/LoginServiceImpl.java b/src/main/java/com/balybus/galaxy/login/classic/service/login/LoginServiceImpl.java index 24c2fb35..48e2ef10 100644 --- a/src/main/java/com/balybus/galaxy/login/classic/service/login/LoginServiceImpl.java +++ b/src/main/java/com/balybus/galaxy/login/classic/service/login/LoginServiceImpl.java @@ -94,7 +94,7 @@ public MemberResponse.SignInDto signIn(MemberRequest.SignInDto signInDto, HttpSe login.updateRefreshToken(refreshToken); // 5. redis 에 토큰 저장 - tokenRedisRepository.save(new TokenRedis(login.getEmail(), accessToken, refreshToken)); +// tokenRedisRepository.save(new TokenRedis(login.getEmail(), accessToken, refreshToken)); cookieUtils.saveCookie(request, response, accessToken); // 6. 조회 결과 전달 diff --git a/src/main/java/com/balybus/galaxy/login/classic/service/loginAuth/LoginAuthCheckService.java b/src/main/java/com/balybus/galaxy/login/classic/service/loginAuth/LoginAuthCheckService.java index f931578a..c998fa6e 100644 --- a/src/main/java/com/balybus/galaxy/login/classic/service/loginAuth/LoginAuthCheckService.java +++ b/src/main/java/com/balybus/galaxy/login/classic/service/loginAuth/LoginAuthCheckService.java @@ -2,8 +2,10 @@ import com.balybus.galaxy.global.domain.tblCenterManager.TblCenterManager; import com.balybus.galaxy.global.domain.tblPatient.TblPatient; +import com.balybus.galaxy.careAssistant.domain.TblHelper; public interface LoginAuthCheckService { TblCenterManager checkManager(String userEmail); // 관리자 권한 확인 TblPatient checkPatientManagerAuth(Long patientSeq, Long managerSeq); // 관리자 사용자의 어르신 정보 접근 권한 확인 + TblHelper checkHelper(String userEmail); // 요양보호사 권한 확인 } diff --git a/src/main/java/com/balybus/galaxy/login/classic/service/loginAuth/LoginAuthCheckServiceImpl.java b/src/main/java/com/balybus/galaxy/login/classic/service/loginAuth/LoginAuthCheckServiceImpl.java index c39dc459..95729665 100644 --- a/src/main/java/com/balybus/galaxy/login/classic/service/loginAuth/LoginAuthCheckServiceImpl.java +++ b/src/main/java/com/balybus/galaxy/login/classic/service/loginAuth/LoginAuthCheckServiceImpl.java @@ -9,6 +9,8 @@ import com.balybus.galaxy.member.repository.MemberRepository; import com.balybus.galaxy.global.domain.tblPatient.TblPatient; import com.balybus.galaxy.global.domain.tblPatient.TblPatientRepository; +import com.balybus.galaxy.careAssistant.domain.TblHelper; +import com.balybus.galaxy.careAssistant.repository.HelperRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -16,10 +18,12 @@ @Service @RequiredArgsConstructor -public class LoginAuthCheckServiceImpl implements LoginAuthCheckService{ +public class LoginAuthCheckServiceImpl implements LoginAuthCheckService { private final MemberRepository memberRepository; private final TblCenterManagerRepository centerManagerRepository; private final TblPatientRepository patientRepository; + private final HelperRepository helperRepository; + @Override public TblCenterManager checkManager(String userEmail) { //1. 로그인 테이블 조회 @@ -50,4 +54,23 @@ public TblPatient checkPatientManagerAuth(Long patientSeq, Long managerSeq){ return patient; } + + /** + * 요양보호사 권한 확인 + * @param userEmail String: 사용자 이메일 + * @return TblHelper + */ + @Override + public TblHelper checkHelper(String userEmail) { + //1. 로그인 테이블 조회 + Optional userOpt = memberRepository.findByEmail(userEmail); // 토큰 이메일로 정보 조회 + if(userOpt.isEmpty()) throw new BadRequestException(ExceptionCode.DO_NOT_LOGIN); + TblUser userEntity = userOpt.get(); + + //2. 요양보호사 테이블 조회 + Optional helperOpt = helperRepository.findByUserId(userEntity.getId()); + if(!userEntity.getUserAuth().equals(RoleType.MEMBER) + || helperOpt.isEmpty()) throw new BadRequestException(ExceptionCode.NOT_FOUND_HELPER); + return helperOpt.get(); + } } diff --git a/src/main/java/com/balybus/galaxy/patient/matchingStatus/MatchingStatusController.java b/src/main/java/com/balybus/galaxy/patient/matchingStatus/MatchingStatusController.java index d029313e..9b0e7869 100644 --- a/src/main/java/com/balybus/galaxy/patient/matchingStatus/MatchingStatusController.java +++ b/src/main/java/com/balybus/galaxy/patient/matchingStatus/MatchingStatusController.java @@ -19,9 +19,10 @@ @RestController @Slf4j @RequiredArgsConstructor -@RequestMapping("/api/patient-match-status") +@RequestMapping("tient-match-status") public class MatchingStatusController { private final MatchingStatusServiceImpl matchingStatusService; + @Operation(summary = "어르신 매칭 대기 중 리스트 반환 API", description = "매칭 대기 중인 어르신 정보를 반환합니다.") @ApiResponses({ @ApiResponse(responseCode = "200", description = "반환 성공", @@ -64,7 +65,6 @@ public ResponseEntity getMatchedPatientList(@AuthenticationPrincipal UserDeta return ResponseEntity.ok().body(matchingStatusService.matchedFinPatientInfoList(userDetails.getUsername())); } - @Operation(summary = "어르신 공고 매칭 상태 변경 API", description = "매칭 완료 / 거절 상태인 어르신 정보를 반환합니다.") @ApiResponses({ @ApiResponse(responseCode = "200", description = "반환 성공", @@ -79,4 +79,58 @@ public ResponseEntity updatePatientMatchStatus(@AuthenticationPrincipal UserD @RequestBody MatchingStatusRequestDto.UpdatePatientMatchStatus dto) { return ResponseEntity.ok().body(matchingStatusService.updatePatientMatchStatus(userDetails.getUsername(), dto)); } + + // 요양보호사 기준 매칭 목록 조회 API + @Operation(summary = "요양보호사 매칭 요청 목록 조회 API", description = "요양보호사 기준으로 매칭 요청/조율 상태인 공고 목록을 반환합니다.") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "반환 성공", + content = @Content(schema = @Schema(implementation = MatchingStatusResponseDto.HelperMatchingList.class))), + @ApiResponse(responseCode = "4008", description = "사용자정의에러코드:로그인이 정보 없음(쿠키 없음)", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse(responseCode = "3007", description = "사용자정의에러코드:로그인한 사용자의 권한이 요양보호사가 아닙니다.", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))) + }) + @GetMapping("/helper-matching-request-list") + public ResponseEntity getHelperMatchingRequestList(@AuthenticationPrincipal UserDetails userDetails) { + return ResponseEntity.ok().body(matchingStatusService.helperMatchingRequestList(userDetails.getUsername())); + } + + @Operation(summary = "요양보호사 매칭 완료 목록 조회 API", description = "요양보호사 기준으로 매칭 완료 상태인 공고 목록을 반환합니다.") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "반환 성공", + content = @Content(schema = @Schema(implementation = MatchingStatusResponseDto.HelperMatchingList.class))), + @ApiResponse(responseCode = "4008", description = "사용자정의에러코드:로그인이 정보 없음(쿠키 없음)", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse(responseCode = "3007", description = "사용자정의에러코드:로그인한 사용자의 권한이 요양보호사가 아닙니다.", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))) + }) + @GetMapping("/helper-matching-completed-list") + public ResponseEntity getHelperMatchingCompletedList(@AuthenticationPrincipal UserDetails userDetails) { + return ResponseEntity.ok().body(matchingStatusService.helperMatchingCompletedList(userDetails.getUsername())); + } + + // 요양보호사 구분자 기반 매칭 목록 조회 API + @Operation(summary = "요양보호사 구분자로 매칭 요청 목록 조회 API", description = "요양보호사 구분자를 이용해 매칭 요청/조율 상태인 공고 목록을 반환합니다.") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "반환 성공", + content = @Content(schema = @Schema(implementation = MatchingStatusResponseDto.HelperMatchingList.class))), + @ApiResponse(responseCode = "400", description = "잘못된 요청", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))) + }) + @GetMapping("/helper/{helperId}/matching-request-list") + public ResponseEntity getHelperMatchingRequestListByHelperId(@PathVariable Long helperId) { + return ResponseEntity.ok().body(matchingStatusService.helperMatchingRequestListByHelperId(helperId)); + } + + @Operation(summary = "요양보호사 구분자로 매칭 완료 목록 조회 API", description = "요양보호사 구분자를 이용해 매칭 완료 상태인 공고 목록을 반환합니다.") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "반환 성공", + content = @Content(schema = @Schema(implementation = MatchingStatusResponseDto.HelperMatchingList.class))), + @ApiResponse(responseCode = "400", description = "잘못된 요청", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))) + }) + @GetMapping("/helper/{helperId}/matching-completed-list") + public ResponseEntity getHelperMatchingCompletedListByHelperId(@PathVariable Long helperId) { + return ResponseEntity.ok().body(matchingStatusService.helperMatchingCompletedListByHelperId(helperId)); + } } diff --git a/src/main/java/com/balybus/galaxy/patient/matchingStatus/dto/MatchingStatusResponseDto.java b/src/main/java/com/balybus/galaxy/patient/matchingStatus/dto/MatchingStatusResponseDto.java index d06d2b2a..780550eb 100644 --- a/src/main/java/com/balybus/galaxy/patient/matchingStatus/dto/MatchingStatusResponseDto.java +++ b/src/main/java/com/balybus/galaxy/patient/matchingStatus/dto/MatchingStatusResponseDto.java @@ -17,6 +17,13 @@ public static class MatchingStatusPatientInfoList { private List list; } + // 요양보호사 기준 매칭 목록 조회 DTO + @Getter + @Builder + public static class HelperMatchingList { + private List list; + } + @Getter @NoArgsConstructor @JsonInclude(JsonInclude.Include.NON_NULL) @@ -42,6 +49,47 @@ public MatchedFinPatientInfo(MatchingPatientInfo s } } + /** + * 요양보호사 기준 매칭 정보 DTO + */ + @Getter + @NoArgsConstructor + public static class HelperMatchingInfo { + private Long patientSeq; // 어르신 구분자 + private Long patientLogSeq; // 어르신 공고 구분자 + private String name; // 어르신 이름 + private String birthDate; // 어르신 생년월일 + private String gender; // 어르신 성별 + private String workType; // 희망 근무 종류 + private String careLevel; // 장기 요양 등급 + private String addressFirst; // 시.도 + private String addressSecond; // 시.군.구 + private String addressThird; // 읍.면.동 + private int age; // 어르신 만 나이 + private String matchState; // 매칭 상태 + private String matchStateMsg; // 매칭 상태 메시지 + + public HelperMatchingInfo(Long patientSeq, Long patientLogSeq, + String name, String birthDate, + String gender, String workType, String careLevel, + String addressFirst, String addressSecond, String addressThird, + String matchState, String matchStateMsg){ + this.patientSeq = patientSeq; + this.patientLogSeq = patientLogSeq; + this.name = name; + this.birthDate = birthDate; + this.gender = gender; + this.workType = workType; + this.careLevel = careLevel; + this.addressFirst = addressFirst; + this.addressSecond = addressSecond; + this.addressThird = addressThird; + this.matchState = matchState; + this.matchStateMsg = matchStateMsg; + this.age = calAge(birthDate, "yyyyMMdd"); //만나이 계산 + } + } + /** * 어르신 공고 간소화 DTO */ @@ -112,8 +160,6 @@ private static int calAge(String birthDate, String pattern) { return period.getYears(); } - - @Getter @Builder public static class UpdatePatientMatchStatus{ diff --git a/src/main/java/com/balybus/galaxy/patient/matchingStatus/service/MatchingStatusService.java b/src/main/java/com/balybus/galaxy/patient/matchingStatus/service/MatchingStatusService.java index a5f8345e..17fd5c00 100644 --- a/src/main/java/com/balybus/galaxy/patient/matchingStatus/service/MatchingStatusService.java +++ b/src/main/java/com/balybus/galaxy/patient/matchingStatus/service/MatchingStatusService.java @@ -8,4 +8,12 @@ public interface MatchingStatusService { MatchingStatusResponseDto.MatchingStatusPatientInfoList matchingPatientInfoList(String userEmail); // 어르신 매칭중 리스트 반화 MatchingStatusResponseDto.MatchingStatusPatientInfoList matchedFinPatientInfoList(String userEmail); // 어르신 매칭 완료 리스트 반화 MatchingStatusResponseDto.UpdatePatientMatchStatus updatePatientMatchStatus(String userEmail, MatchingStatusRequestDto.UpdatePatientMatchStatus dto); // 어르신 공고 매칭 상태 변경 + + // 요양보호사 기준 매칭 목록 조회 (JWT 토큰 기반) + MatchingStatusResponseDto.HelperMatchingList helperMatchingRequestList(String userEmail); // 요양보호사 매칭 요청 목록 조회 (요청/조율) + MatchingStatusResponseDto.HelperMatchingList helperMatchingCompletedList(String userEmail); // 요양보호사 매칭 완료 목록 조회 (매칭 완료) + + // 요양보호사 구분자 기반 매칭 목록 조회 + MatchingStatusResponseDto.HelperMatchingList helperMatchingRequestListByHelperId(Long helperId); // 요양보호사 구분자로 매칭 요청 목록 조회 (요청/조율) + MatchingStatusResponseDto.HelperMatchingList helperMatchingCompletedListByHelperId(Long helperId); // 요양보호사 구분자로 매칭 완료 목록 조회 (매칭 완료) } diff --git a/src/main/java/com/balybus/galaxy/patient/matchingStatus/service/MatchingStatusServiceImpl.java b/src/main/java/com/balybus/galaxy/patient/matchingStatus/service/MatchingStatusServiceImpl.java index 045c96d1..d5381def 100644 --- a/src/main/java/com/balybus/galaxy/patient/matchingStatus/service/MatchingStatusServiceImpl.java +++ b/src/main/java/com/balybus/galaxy/patient/matchingStatus/service/MatchingStatusServiceImpl.java @@ -13,12 +13,14 @@ import com.balybus.galaxy.global.domain.tblPatientLog.TblPatientLog; import com.balybus.galaxy.patient.matchingStatus.dto.MatchingStatusRequestDto; import com.balybus.galaxy.patient.matchingStatus.dto.MatchingStatusResponseDto; +import com.balybus.galaxy.careAssistant.domain.TblHelper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; +import java.util.stream.Collectors; import static com.balybus.galaxy.global.domain.tblMatching.MatchState.*; import static com.balybus.galaxy.global.domain.tblMatching.SelectMatchStatus.*; @@ -152,4 +154,156 @@ public MatchingStatusResponseDto.UpdatePatientMatchStatus updatePatientMatchStat .build(); } } + + /** + * 요양보호사 매칭 요청 목록 조회 (요청/조율) + * @param userEmail 요양보호사 이메일 + * @return MatchingStatusResponseDto.HelperMatchingList + */ + @Override + public MatchingStatusResponseDto.HelperMatchingList helperMatchingRequestList(String userEmail) { + //1. 요양보호사 로그인 유효성 확인 + TblHelper helper = loginAuthCheckService.checkHelper(userEmail); + + //2. 해당 요양보호사의 매칭 요청/조율 상태 조회 (MATCH_REQUEST, PERMIT_TUNE) + List matchStates = Arrays.asList(MATCH_REQUEST, PERMIT_TUNE); + List matchings = tblMatchingRepository.findMatchingByHelperIdAndMatchStates(helper.getId(), matchStates); + + //3. 매칭 정보를 DTO로 변환 + List result = matchings.stream() + .map(matching -> { + TblPatientLog patientLog = matching.getPatientLog(); + return new MatchingStatusResponseDto.HelperMatchingInfo( + patientLog.getPatient().getId(), + patientLog.getId(), + patientLog.getName(), + patientLog.getBirthDate(), + String.valueOf(patientLog.getGender()), + String.valueOf(patientLog.getWorkType()), + String.valueOf(patientLog.getCareLevel()), + patientLog.getTblAddressFirst().getName(), + patientLog.getTblAddressSecond().getName(), + patientLog.getTblAddressThird().getName(), + matching.getMatchState().name(), + matching.getMatchState().getMsg() + ); + }) + .collect(Collectors.toList()); + + return MatchingStatusResponseDto.HelperMatchingList.builder() + .list(result) + .build(); + } + + /** + * 요양보호사 매칭 완료 목록 조회 (매칭 완료) + * @param userEmail 요양보호사 이메일 + * @return MatchingStatusResponseDto.HelperMatchingList + */ + @Override + public MatchingStatusResponseDto.HelperMatchingList helperMatchingCompletedList(String userEmail) { + //1. 요양보호사 로그인 유효성 확인 + TblHelper helper = loginAuthCheckService.checkHelper(userEmail); + + //2. 해당 요양보호사의 매칭 완료 상태 조회 (MATCH_FIN) + List matchings = tblMatchingRepository.findMatchingByHelperIdAndMatchState(helper.getId(), MATCH_FIN); + + //3. 매칭 정보를 DTO로 변환 + List result = matchings.stream() + .map(matching -> { + TblPatientLog patientLog = matching.getPatientLog(); + return new MatchingStatusResponseDto.HelperMatchingInfo( + patientLog.getPatient().getId(), + patientLog.getId(), + patientLog.getName(), + patientLog.getBirthDate(), + String.valueOf(patientLog.getGender()), + String.valueOf(patientLog.getWorkType()), + String.valueOf(patientLog.getCareLevel()), + patientLog.getTblAddressFirst().getName(), + patientLog.getTblAddressSecond().getName(), + patientLog.getTblAddressThird().getName(), + matching.getMatchState().name(), + matching.getMatchState().getMsg() + ); + }) + .collect(Collectors.toList()); + + return MatchingStatusResponseDto.HelperMatchingList.builder() + .list(result) + .build(); + } + + /** + * 요양보호사 구분자로 매칭 요청 목록 조회 (요청/조율) + * @param helperId 요양보호사 구분자 + * @return MatchingStatusResponseDto.HelperMatchingList + */ + @Override + public MatchingStatusResponseDto.HelperMatchingList helperMatchingRequestListByHelperId(Long helperId) { + //1. 해당 요양보호사의 매칭 요청/조율 상태 조회 (MATCH_REQUEST, PERMIT_TUNE) + List matchStates = Arrays.asList(MATCH_REQUEST, PERMIT_TUNE); + List matchings = tblMatchingRepository.findMatchingByHelperIdAndMatchStates(helperId, matchStates); + + //2. 매칭 정보를 DTO로 변환 + List result = matchings.stream() + .map(matching -> { + TblPatientLog patientLog = matching.getPatientLog(); + return new MatchingStatusResponseDto.HelperMatchingInfo( + patientLog.getPatient().getId(), + patientLog.getId(), + patientLog.getName(), + patientLog.getBirthDate(), + String.valueOf(patientLog.getGender()), + String.valueOf(patientLog.getWorkType()), + String.valueOf(patientLog.getCareLevel()), + patientLog.getTblAddressFirst().getName(), + patientLog.getTblAddressSecond().getName(), + patientLog.getTblAddressThird().getName(), + matching.getMatchState().name(), + matching.getMatchState().getMsg() + ); + }) + .collect(Collectors.toList()); + + return MatchingStatusResponseDto.HelperMatchingList.builder() + .list(result) + .build(); + } + + /** + * 요양보호사 구분자로 매칭 완료 목록 조회 (매칭 완료) + * @param helperId 요양보호사 구분자 + * @return MatchingStatusResponseDto.HelperMatchingList + */ + @Override + public MatchingStatusResponseDto.HelperMatchingList helperMatchingCompletedListByHelperId(Long helperId) { + //1. 해당 요양보호사의 매칭 완료 상태 조회 (MATCH_FIN) + List matchings = tblMatchingRepository.findMatchingByHelperIdAndMatchState(helperId, MATCH_FIN); + + //2. 매칭 정보를 DTO로 변환 + List result = matchings.stream() + .map(matching -> { + TblPatientLog patientLog = matching.getPatientLog(); + return new MatchingStatusResponseDto.HelperMatchingInfo( + patientLog.getPatient().getId(), + patientLog.getId(), + patientLog.getName(), + patientLog.getBirthDate(), + String.valueOf(patientLog.getGender()), + String.valueOf(patientLog.getWorkType()), + String.valueOf(patientLog.getCareLevel()), + patientLog.getTblAddressFirst().getName(), + patientLog.getTblAddressSecond().getName(), + patientLog.getTblAddressThird().getName(), + matching.getMatchState().name(), + matching.getMatchState().getMsg() + ); + }) + .collect(Collectors.toList()); + + return MatchingStatusResponseDto.HelperMatchingList.builder() + .list(result) + .build(); + } } From 56c278602b122189a750b9cb20d02a779222d858 Mon Sep 17 00:00:00 2001 From: jg Date: Sat, 26 Jul 2025 18:07:13 +0900 Subject: [PATCH 06/12] =?UTF-8?q?[FEATURE]=20=EB=A9=94=EC=84=B8=EC=A7=80?= =?UTF-8?q?=20=EC=A0=84=EC=86=A1=20=EC=84=B1=EA=B3=B5=20=EC=97=AC=EB=B6=80?= =?UTF-8?q?=20=EC=A0=84=EB=8B=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../galaxy/chat/controller/ChatSocketController.java | 3 ++- src/main/resources/templates/chat/chatTestA.html | 9 +++++++++ src/main/resources/templates/chat/chatTestB.html | 9 +++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/balybus/galaxy/chat/controller/ChatSocketController.java b/src/main/java/com/balybus/galaxy/chat/controller/ChatSocketController.java index 2382d3df..250e6650 100644 --- a/src/main/java/com/balybus/galaxy/chat/controller/ChatSocketController.java +++ b/src/main/java/com/balybus/galaxy/chat/controller/ChatSocketController.java @@ -34,7 +34,8 @@ public void sendPrivateMessage(ChatMsgRequestDto.SendPrivateMessage message, @He String sender = simpUser.getName(); try { ChatMsgResponseDto.SendPrivateMessage responseDto = chatService.saveMessage(message, sender); //채팅 데이터 DB 저장 - messagingTemplate.convertAndSendToUser(responseDto.getReceiverMail(), "/queue/private", responseDto); + messagingTemplate.convertAndSendToUser(responseDto.getReceiverMail(), "/queue/private", responseDto); //받는사람에게 채팅 전송 + messagingTemplate.convertAndSendToUser(sender, "/queue/success", "SUCCESS"); //보낸사람에게 채팅 전송 성공여부 전송 } catch (Exception e) { // 예외가 발생한 경우 메시지를 보낸 사람에게 에러 메시지를 보냄 messagingTemplate.convertAndSendToUser(sender, "/queue/error", "Error occurred: " + e.getMessage()); diff --git a/src/main/resources/templates/chat/chatTestA.html b/src/main/resources/templates/chat/chatTestA.html index 75207ecc..3cabcbfc 100644 --- a/src/main/resources/templates/chat/chatTestA.html +++ b/src/main/resources/templates/chat/chatTestA.html @@ -46,6 +46,15 @@

WebSocket Test

messageContainer.innerHTML += `

받은 개인 메시지: ${message.content}

`; }); + // 전송 성공 콜백 + stompClient.subscribe('/user/queue/success', function(message) { + console.log("전송 성공 콜백:", message.body); + + // 메시지를 div에 추가 + const messageContainer = document.getElementById("messageContainer"); + messageContainer.innerHTML += `

전송 성공 콜백: ${message.body}

`; + }); + stompClient.subscribe('/user/queue/error', function(message) { console.log("에러 발생 메시지:", message.body); diff --git a/src/main/resources/templates/chat/chatTestB.html b/src/main/resources/templates/chat/chatTestB.html index ccf57f14..7e4d8efe 100644 --- a/src/main/resources/templates/chat/chatTestB.html +++ b/src/main/resources/templates/chat/chatTestB.html @@ -46,6 +46,15 @@

WebSocket Test

messageContainer.innerHTML += `

받은 개인 메시지: ${message.content}

`; }); + // 전송 성공 콜백 + stompClient.subscribe('/user/queue/success', function(message) { + console.log("전송 성공 콜백:", message.body); + + // 메시지를 div에 추가 + const messageContainer = document.getElementById("messageContainer"); + messageContainer.innerHTML += `

전송 성공 콜백: ${message.body}

`; + }); + stompClient.subscribe('/user/queue/error', function(message) { console.log("에러 발생 메시지:", message.body); From 2d06d104535bdde62531655bea4b2a2908ad271a Mon Sep 17 00:00:00 2001 From: jg Date: Sat, 26 Jul 2025 21:26:41 +0900 Subject: [PATCH 07/12] =?UTF-8?q?[FEATURE]=20=EC=9A=94=EC=96=91=EB=B3=B4?= =?UTF-8?q?=ED=98=B8=EC=82=AC=20-=20=EC=96=B4=EB=A5=B4=EC=8B=A0=20?= =?UTF-8?q?=EA=B3=B5=EA=B3=A0=20=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../patient/recruit/RecruitController.java | 21 ++++++- .../recruit/dto/RecruitResponseDto.java | 57 +++++++++++++++++++ .../recruit/service/RecruitService.java | 2 +- .../recruit/service/RecruitServiceImpl.java | 44 ++++++++++---- 4 files changed, 111 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/balybus/galaxy/patient/recruit/RecruitController.java b/src/main/java/com/balybus/galaxy/patient/recruit/RecruitController.java index 58eb7ae9..38216c19 100644 --- a/src/main/java/com/balybus/galaxy/patient/recruit/RecruitController.java +++ b/src/main/java/com/balybus/galaxy/patient/recruit/RecruitController.java @@ -88,7 +88,26 @@ public ResponseEntity getRecruitPersonalList(@AuthenticationPrincipal UserDet }) public ResponseEntity getOneRecruitPatientInfo(@AuthenticationPrincipal UserDetails userDetails, @PathVariable("patientLogSeq") Long patientLogSeq) { - return ResponseEntity.ok().body(noticeService.getOneRecruitPatientInfo(userDetails.getUsername(), patientLogSeq)); + return ResponseEntity.ok().body(noticeService.getOneRecruitPatientInfo(userDetails.getUsername(), patientLogSeq, true)); + } + + @GetMapping("/{patientLogSeq}/detail-helper") + @Operation(summary = "요양보호사 - 어르신 공고 상세 조회 API", description = "어르신 공고를 조회합니다.") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "수정 성공", + content = @Content(schema = @Schema(implementation = RecruitResponseDto.GetOneRecruitPatientInfo.class))), + @ApiResponse(responseCode = "4008", description = "사용자정의에러코드:로그인이 정보 없음(쿠키 없음)", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse(responseCode = "8001", description = "사용자정의에러코드:NOT_FOUND_PATIENT_RECRUIT", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse(responseCode = "8000", description = "사용자정의에러코드:해당 어르신 정보를 찾을 수 없습니다.", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse(responseCode = "7001", description = "사용자정의에러코드:조회 권한 없음", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))) + }) + public ResponseEntity getOneRecruitPatientInfoToHelper(@AuthenticationPrincipal UserDetails userDetails, + @PathVariable("patientLogSeq") Long patientLogSeq) { + return ResponseEntity.ok().body(noticeService.getOneRecruitPatientInfo(userDetails.getUsername(), patientLogSeq, false)); } diff --git a/src/main/java/com/balybus/galaxy/patient/recruit/dto/RecruitResponseDto.java b/src/main/java/com/balybus/galaxy/patient/recruit/dto/RecruitResponseDto.java index ea7401b3..e9a637e6 100644 --- a/src/main/java/com/balybus/galaxy/patient/recruit/dto/RecruitResponseDto.java +++ b/src/main/java/com/balybus/galaxy/patient/recruit/dto/RecruitResponseDto.java @@ -102,6 +102,63 @@ public void setCareBaseDtoNull(){ } + @Data + @EqualsAndHashCode(callSuper = true) + public static class GetOneRecruitPatientInfoToHelper extends PatientBaseDto { + private Boolean linkingYn; //어르신 기본정보로 업데이트 할 것인지 여부 + private Boolean wageNegotiation; //급여 협의 여부 + private int wageState; // 1:시급, 2:일급, 3:주급 구분 + private int wage; // 급여 + private String requestContents; // 기타 요청 사항 + + private CareChoiceListDto careChoice; + public GetOneRecruitPatientInfoToHelper(TblPatientLog patient, List patientTimeList){ + this.wageNegotiation = patient.getWageNegotiation(); + this.wageState = patient.getWageState(); + this.wage = patient.getWage(); + this.requestContents = patient.getRequestContents(); + this.welfare = patient.getWelfare(); // 복리후생 + + this.afSeq = patient.getTblAddressFirst().getId(); // 광역시.도 구분자 + this.asSeq = patient.getTblAddressSecond().getId(); // 시.군.구 구분자 + this.atSeq = patient.getTblAddressThird().getId(); // 읍.면.동 구분자 + this.careLevel = patient.getCareLevel(); // 장기요양등급 + this.inmateState = patient.getInmateState(); // 동거인 여부 + this.workType = patient.getWorkType(); // 근무종류 + this.gender = patient.getGender(); // 남성:1 여성:2 + this.dementiaSymptom = patient.getDementiaSymptom(); // 치매증상 + this.serviceMeal = patient.getServiceMeal(); // 식사보조 + this.serviceToilet = patient.getServiceToilet(); // 배변보조 + this.serviceMobility = patient.getServiceMobility(); // 이동보조 + this.serviceDaily = patient.getServiceDaily(); // 일상생활 + this.name = patient.getName(); // 어르신 이름 + this.birthDate = patient.getBirthDate(); // 생년월일 + this.weight = patient.getWeight(); // 몸무게 + this.diseases = patient.getDiseases(); // 보유 질병/질환 + this.timeNegotiation = patient.getTimeNegotiation(); // 돌봄 요일 시간 협의 여부 + + List timeList = new ArrayList<>(); + for(TblPatientTimeLog patientTime: patientTimeList){ + timeList.add(new SavePatientTimeInfo(patientTime)); + } + this.timeList = timeList; // 돌봄요일 리스트 : 선택한 요일에 대한 데이터만 리스트에 넣어서 전달. + } + + public void setCareBaseDtoNull(){ + this.careLevel = null; // 장기요양등급 + this.inmateState = null; // 동거인여부 + this.workType = null; // 근무종류 + this.gender = null; // 남성:1 여성:2 + this.dementiaSymptom = null; // 치매증상 + this.serviceMeal = null; // 식사보조 + this.serviceToilet = null; // 배변보조 + this.serviceMobility = null; // 이동보조 + this.serviceDaily = null; // 일상생활 + this.welfare = null; // 복리후생 + } + + } + @Getter @Builder public static class UpdateRecruitPatientInfo{ diff --git a/src/main/java/com/balybus/galaxy/patient/recruit/service/RecruitService.java b/src/main/java/com/balybus/galaxy/patient/recruit/service/RecruitService.java index 0eefff6b..26969411 100644 --- a/src/main/java/com/balybus/galaxy/patient/recruit/service/RecruitService.java +++ b/src/main/java/com/balybus/galaxy/patient/recruit/service/RecruitService.java @@ -8,6 +8,6 @@ public interface RecruitService { RecruitResponseDto.RecruitHelper recruitHelper(UserDetails userDetails, RecruitRequestDto.RecruitHelper dto); // 어르신 공고 등록 RecruitResponseDto.GetRecruitList getRecruitList(String userEmail, RecruitRequestDto.GetRecruitList dto); // 어르신 공고 리스트 조회 RecruitResponseDto.GetRecruitList getRecruitPersonalList(String userEmail, RecruitRequestDto.GetRecruitPersonalList dto); // 어르신 개인 공고 리스트 조회 - RecruitResponseDto.GetOneRecruitPatientInfo getOneRecruitPatientInfo(String userEmail, Long patientLogSeq); // 어르신 정보 상세 조회 + RecruitResponseDto.GetOneRecruitPatientInfo getOneRecruitPatientInfo(String userEmail, Long patientLogSeq, boolean managerYn); // 어르신 정보 상세 조회 RecruitResponseDto.UpdateRecruitPatientInfo updateRecruitPatientInfo(String userEmail, RecruitRequestDto.UpdateRecruitPatientInfo dto); // 어르신 정보 상세 조회 } diff --git a/src/main/java/com/balybus/galaxy/patient/recruit/service/RecruitServiceImpl.java b/src/main/java/com/balybus/galaxy/patient/recruit/service/RecruitServiceImpl.java index 39d3db89..384bea05 100644 --- a/src/main/java/com/balybus/galaxy/patient/recruit/service/RecruitServiceImpl.java +++ b/src/main/java/com/balybus/galaxy/patient/recruit/service/RecruitServiceImpl.java @@ -1,5 +1,6 @@ package com.balybus.galaxy.patient.recruit.service; +import com.balybus.galaxy.careAssistant.domain.TblHelper; import com.balybus.galaxy.global.domain.tblAddressFirst.TblAddressFirst; import com.balybus.galaxy.global.domain.tblAddressSecond.TblAddressSecond; import com.balybus.galaxy.global.domain.tblAddressThird.TblAddressThird; @@ -8,6 +9,8 @@ import com.balybus.galaxy.global.domain.tblCare.service.TblCareServiceImpl; import com.balybus.galaxy.global.domain.tblCenterManager.TblCenterManager; import com.balybus.galaxy.global.domain.tblMatching.MatchingServiceImpl; +import com.balybus.galaxy.global.domain.tblMatching.TblMatching; +import com.balybus.galaxy.global.domain.tblMatching.TblMatchingRepository; import com.balybus.galaxy.global.exception.BadRequestException; import com.balybus.galaxy.global.exception.ExceptionCode; import com.balybus.galaxy.global.utils.address.service.serviceImpl.TblAddressFirstServiceImpl; @@ -51,6 +54,7 @@ public class RecruitServiceImpl implements RecruitService { private final TblPatientLogRepository patientLogRepository; private final TblPatientTimeLogRepository patientTimeLogRepository; private final TblCareRepository careRepository; + private final TblMatchingRepository matchingRepository; private final LoginAuthCheckServiceImpl loginAuthCheckService; private final MatchingServiceImpl matchingService; @@ -257,17 +261,24 @@ public RecruitResponseDto.GetRecruitList getRecruitPersonalList(String userEmail * @return PatientResponseDto.GetOnePatientInfo */ @Override - public RecruitResponseDto.GetOneRecruitPatientInfo getOneRecruitPatientInfo(String userEmail, Long patientLogSeq) { - //1. 관리자 정보 조회 - TblCenterManager centerManager = loginAuthCheckService.checkManager(userEmail); - - //어르신 로그 정보 조회 - Optional patientLogOpt = patientLogRepository.findById(patientLogSeq); - if(patientLogOpt.isEmpty()) throw new BadRequestException(ExceptionCode.NOT_FOUND_PATIENT_RECRUIT); - TblPatientLog patientLog = patientLogOpt.get(); - - //2. 어르신 정보 조회 (어르신 구분자 & 관리자 구분자) - TblPatient patient = loginAuthCheckService.checkPatientManagerAuth(patientLog.getPatient().getId(), centerManager.getId()); + public RecruitResponseDto.GetOneRecruitPatientInfo getOneRecruitPatientInfo(String userEmail, Long patientLogSeq, boolean managerYn) { + //1. 어르신 로그 정보 조회 + TblPatientLog patientLog = getPatientLog(patientLogSeq); + + //2. 로그인 정보 조회 + if(managerYn) { + //2-1-1. 관리자 정보 조회 + TblCenterManager centerManager = loginAuthCheckService.checkManager(userEmail); + //2-1-2. 어르신 정보 조회 가능 여부 확인(어르신 구분자 & 관리자 구분자) + TblPatient patient = loginAuthCheckService.checkPatientManagerAuth(patientLog.getPatient().getId(), centerManager.getId()); + } else { + //2-2-1. 요양보호사 정보 조회 + TblHelper helper = loginAuthCheckService.checkHelper(userEmail); + + //2-2-2. 어르신 정보 조회 가능 여부 확인(매칭 확인 - 요양보호사) + Optional matchingOpt = matchingRepository.findByPatientLog_idAndHelper_id(patientLogSeq, helper.getId()); + if(matchingOpt.isEmpty()) throw new BadRequestException(ExceptionCode.NOT_FOUND_PATIENT_RECRUIT); + } //3. 어르신 돌봄 시간 요일 조회 List patientTimeLogList = patientTimeLogRepository.findByPatientLog_Id(patientLog.getId()); @@ -279,6 +290,17 @@ public RecruitResponseDto.GetOneRecruitPatientInfo getOneRecruitPatientInfo(Stri return resultDto; } + /** + * 어르신 로그 정보 조회 + * @param patientLogSeq 어르신로그(공고) 구분자 + * @return TblPatientLog 엔티티 + */ + private TblPatientLog getPatientLog(Long patientLogSeq){ + Optional patientLogOpt = patientLogRepository.findById(patientLogSeq); + if(patientLogOpt.isEmpty()) throw new BadRequestException(ExceptionCode.NOT_FOUND_PATIENT_RECRUIT); + return patientLogOpt.get(); + } + /** * 어르신 공고 등록 From 38261409c0aafaff3aa950dd7839c4b2f63c0a88 Mon Sep 17 00:00:00 2001 From: jg Date: Sat, 26 Jul 2025 21:27:22 +0900 Subject: [PATCH 08/12] =?UTF-8?q?[FEATURE]=20=EC=9A=94=EC=96=91=EB=B3=B4?= =?UTF-8?q?=ED=98=B8=EC=82=AC=20-=20=EC=96=B4=EB=A5=B4=EC=8B=A0=20?= =?UTF-8?q?=EA=B3=B5=EA=B3=A0=20=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../recruit/dto/RecruitResponseDto.java | 57 ------------------- 1 file changed, 57 deletions(-) diff --git a/src/main/java/com/balybus/galaxy/patient/recruit/dto/RecruitResponseDto.java b/src/main/java/com/balybus/galaxy/patient/recruit/dto/RecruitResponseDto.java index e9a637e6..ea7401b3 100644 --- a/src/main/java/com/balybus/galaxy/patient/recruit/dto/RecruitResponseDto.java +++ b/src/main/java/com/balybus/galaxy/patient/recruit/dto/RecruitResponseDto.java @@ -102,63 +102,6 @@ public void setCareBaseDtoNull(){ } - @Data - @EqualsAndHashCode(callSuper = true) - public static class GetOneRecruitPatientInfoToHelper extends PatientBaseDto { - private Boolean linkingYn; //어르신 기본정보로 업데이트 할 것인지 여부 - private Boolean wageNegotiation; //급여 협의 여부 - private int wageState; // 1:시급, 2:일급, 3:주급 구분 - private int wage; // 급여 - private String requestContents; // 기타 요청 사항 - - private CareChoiceListDto careChoice; - public GetOneRecruitPatientInfoToHelper(TblPatientLog patient, List patientTimeList){ - this.wageNegotiation = patient.getWageNegotiation(); - this.wageState = patient.getWageState(); - this.wage = patient.getWage(); - this.requestContents = patient.getRequestContents(); - this.welfare = patient.getWelfare(); // 복리후생 - - this.afSeq = patient.getTblAddressFirst().getId(); // 광역시.도 구분자 - this.asSeq = patient.getTblAddressSecond().getId(); // 시.군.구 구분자 - this.atSeq = patient.getTblAddressThird().getId(); // 읍.면.동 구분자 - this.careLevel = patient.getCareLevel(); // 장기요양등급 - this.inmateState = patient.getInmateState(); // 동거인 여부 - this.workType = patient.getWorkType(); // 근무종류 - this.gender = patient.getGender(); // 남성:1 여성:2 - this.dementiaSymptom = patient.getDementiaSymptom(); // 치매증상 - this.serviceMeal = patient.getServiceMeal(); // 식사보조 - this.serviceToilet = patient.getServiceToilet(); // 배변보조 - this.serviceMobility = patient.getServiceMobility(); // 이동보조 - this.serviceDaily = patient.getServiceDaily(); // 일상생활 - this.name = patient.getName(); // 어르신 이름 - this.birthDate = patient.getBirthDate(); // 생년월일 - this.weight = patient.getWeight(); // 몸무게 - this.diseases = patient.getDiseases(); // 보유 질병/질환 - this.timeNegotiation = patient.getTimeNegotiation(); // 돌봄 요일 시간 협의 여부 - - List timeList = new ArrayList<>(); - for(TblPatientTimeLog patientTime: patientTimeList){ - timeList.add(new SavePatientTimeInfo(patientTime)); - } - this.timeList = timeList; // 돌봄요일 리스트 : 선택한 요일에 대한 데이터만 리스트에 넣어서 전달. - } - - public void setCareBaseDtoNull(){ - this.careLevel = null; // 장기요양등급 - this.inmateState = null; // 동거인여부 - this.workType = null; // 근무종류 - this.gender = null; // 남성:1 여성:2 - this.dementiaSymptom = null; // 치매증상 - this.serviceMeal = null; // 식사보조 - this.serviceToilet = null; // 배변보조 - this.serviceMobility = null; // 이동보조 - this.serviceDaily = null; // 일상생활 - this.welfare = null; // 복리후생 - } - - } - @Getter @Builder public static class UpdateRecruitPatientInfo{ From ffb8cb7bc80e4251a045d945775ce2bec59ecca4 Mon Sep 17 00:00:00 2001 From: mike Date: Sun, 27 Jul 2025 17:02:58 +0900 Subject: [PATCH 09/12] =?UTF-8?q?[Feat]:=20=EC=9A=94=EC=96=91=20=EB=B3=B4?= =?UTF-8?q?=ED=98=B8=EC=82=AC=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/HelperController.java | 13 +- .../dto/request/HelperProfileDTO.java | 5 +- .../dto/response/HelperResponse.java | 2 + .../repository/HelperCertRepository.java | 3 + .../careAssistant/service/HelperService.java | 2 +- .../service/HelperServiceImpl.java | 183 ++++++++++++++++-- .../global/exception/ExceptionCode.java | 9 + 7 files changed, 191 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/balybus/galaxy/careAssistant/controller/HelperController.java b/src/main/java/com/balybus/galaxy/careAssistant/controller/HelperController.java index c1011394..6048dbe2 100644 --- a/src/main/java/com/balybus/galaxy/careAssistant/controller/HelperController.java +++ b/src/main/java/com/balybus/galaxy/careAssistant/controller/HelperController.java @@ -76,14 +76,17 @@ public ResponseEntity updateWage( @Operation(summary = "요양 보호사 프로필 업데이트", description = "현재 로그인한 요양 보호사 프로필 업데이트") @ApiResponses({ @ApiResponse(responseCode = "200", description = "프로필이 정상적으로 업데이트 되었습니다.", - content = @Content(schema = @Schema(implementation = String.class))), + content = @Content(schema = @Schema(implementation = Map.class))), @ApiResponse(responseCode = "3000", description = "요양 보호사 테이블을 찾을 수 없습니다."), - @ApiResponse(responseCode = "3010", description = "로그인한 회원을 찾을 수 없습니다.") + @ApiResponse(responseCode = "3010", description = "로그인한 회원을 찾을 수 없습니다."), + @ApiResponse(responseCode = "3012", description = "자격증 이름이 유효하지 않습니다."), + @ApiResponse(responseCode = "3013", description = "자격증 번호가 유효하지 않습니다."), + @ApiResponse(responseCode = "3014", description = "자격증 번호 형식이 올바르지 않습니다.") }) @PutMapping("/update-profile") - public ResponseEntity updateProfile(@RequestBody HelperProfileDTO helperProfileDTO, @AuthenticationPrincipal UserDetails userDetails) { - helperService.updateProfile(userDetails, helperProfileDTO); - return ResponseEntity.ok("프로필이 정상적으로 업데이트 되었습니다."); + public ResponseEntity> updateProfile(@RequestBody HelperProfileDTO helperProfileDTO, @AuthenticationPrincipal UserDetails userDetails) { + Map result = helperService.updateProfile(userDetails, helperProfileDTO); + return ResponseEntity.ok(result); } diff --git a/src/main/java/com/balybus/galaxy/careAssistant/dto/request/HelperProfileDTO.java b/src/main/java/com/balybus/galaxy/careAssistant/dto/request/HelperProfileDTO.java index efa757d6..0c8b297d 100644 --- a/src/main/java/com/balybus/galaxy/careAssistant/dto/request/HelperProfileDTO.java +++ b/src/main/java/com/balybus/galaxy/careAssistant/dto/request/HelperProfileDTO.java @@ -1,7 +1,6 @@ package com.balybus.galaxy.careAssistant.dto.request; import com.balybus.galaxy.login.classic.dto.request.HelperCertDTO; -import jakarta.validation.constraints.NotEmpty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -15,8 +14,6 @@ public class HelperProfileDTO { private String introduce; private Boolean careExperience; - @NotEmpty(message = "자격증은 최소 1개 이상 필수입니다.") + // @NotEmpty 제거 - 자격증이 없어도 부분 업데이트 가능하도록 private List certificates; - - } diff --git a/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperResponse.java b/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperResponse.java index 7ad59b73..fb949cea 100644 --- a/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperResponse.java +++ b/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperResponse.java @@ -23,4 +23,6 @@ public class HelperResponse { private boolean eduYn; private Integer wage; private Integer wageState; + private String introduce; + private Boolean careExperience; } diff --git a/src/main/java/com/balybus/galaxy/careAssistant/repository/HelperCertRepository.java b/src/main/java/com/balybus/galaxy/careAssistant/repository/HelperCertRepository.java index bc2ad492..10bece12 100644 --- a/src/main/java/com/balybus/galaxy/careAssistant/repository/HelperCertRepository.java +++ b/src/main/java/com/balybus/galaxy/careAssistant/repository/HelperCertRepository.java @@ -1,6 +1,7 @@ package com.balybus.galaxy.careAssistant.repository; import com.balybus.galaxy.careAssistant.domain.TblHelperCert; +import com.balybus.galaxy.careAssistant.domain.TblHelper; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -9,4 +10,6 @@ @Repository public interface HelperCertRepository extends JpaRepository { List findAllById(Long helperId); + List findByTblHelperId(Long helperId); + List findByTblHelper(TblHelper tblHelper); } diff --git a/src/main/java/com/balybus/galaxy/careAssistant/service/HelperService.java b/src/main/java/com/balybus/galaxy/careAssistant/service/HelperService.java index 53174419..8c7e0fa5 100644 --- a/src/main/java/com/balybus/galaxy/careAssistant/service/HelperService.java +++ b/src/main/java/com/balybus/galaxy/careAssistant/service/HelperService.java @@ -10,7 +10,7 @@ public interface HelperService { HelperResponse getAllHelperInfo(UserDetails userDetails); - void updateProfile(UserDetails userDetails, HelperProfileDTO helperProfileDTO); + Map updateProfile(UserDetails userDetails, HelperProfileDTO helperProfileDTO); WageUpdateResponse updateWage(UserDetails userDetails, WageUpdateDTO wageUpdateDTO); HelperWorkLocationReponse workLocationSignUp(HelperWorkLocationDTO helperWorkLocationDTO, UserDetails userDetails); HelperWorkTimeResponse workTimeSignUp(HelperWorkTimeRequestDTO helperWorkTimeRequestDTO, UserDetails userDetails); diff --git a/src/main/java/com/balybus/galaxy/careAssistant/service/HelperServiceImpl.java b/src/main/java/com/balybus/galaxy/careAssistant/service/HelperServiceImpl.java index 3aace107..517a8eeb 100644 --- a/src/main/java/com/balybus/galaxy/careAssistant/service/HelperServiceImpl.java +++ b/src/main/java/com/balybus/galaxy/careAssistant/service/HelperServiceImpl.java @@ -3,6 +3,7 @@ import com.balybus.galaxy.global.domain.tblAddressFirst.TblAddressFirst; import com.balybus.galaxy.global.domain.tblAddressSecond.TblAddressSecond; import com.balybus.galaxy.global.domain.tblAddressThird.TblAddressThird; +import com.balybus.galaxy.global.exception.ExceptionCode; import com.balybus.galaxy.global.utils.address.repository.TblAddressFirstRepository; import com.balybus.galaxy.global.utils.address.repository.TblAddressSecondRepository; import com.balybus.galaxy.global.utils.address.repository.TblAddressThirdRepository; @@ -71,7 +72,7 @@ public HelperResponse getAllHelperInfo(UserDetails userDetails) { TblHelper tblHelper = helperRepository.findByUserId(tblUser.getId()) .orElseThrow(() -> new BadRequestException(NOT_FOUND_HELPER)); - List certificates = helperCertRepository.findAllById(Collections.singleton(tblHelper.getId())); + List certificates = helperCertRepository.findByTblHelperId(tblHelper.getId()); List certDTOList = new ArrayList<>(); for(TblHelperCert tblHelperCert : certificates) { @@ -94,11 +95,14 @@ public HelperResponse getAllHelperInfo(UserDetails userDetails) { .eduYn(tblHelper.isEduYn()) .wage(tblHelper.getWage()) .wageState(tblHelper.getWageState()) + .introduce(tblHelper.getIntroduce()) + .careExperience(tblHelper.getIs_experienced()) .build(); } @Override - public void updateProfile(UserDetails userDetails, HelperProfileDTO helperProfileDTO) { + @Transactional + public Map updateProfile(UserDetails userDetails, HelperProfileDTO helperProfileDTO) { String username = userDetails.getUsername(); TblUser tblUser = memberRepository.findByEmail(username) @@ -107,24 +111,83 @@ public void updateProfile(UserDetails userDetails, HelperProfileDTO helperProfil TblHelper tblHelper = helperRepository.findByUserId(tblUser.getId()) .orElseThrow(() -> new BadRequestException(NOT_FOUND_HELPER)); - tblHelper.setIntroduce(helperProfileDTO.getIntroduce()); - tblHelper.setIs_experienced(helperProfileDTO.getCareExperience()); + Map result = new HashMap<>(); + Map certificateResults = new HashMap<>(); + + // null이 아닌 필드만 업데이트 (부분 업데이트 지원) + boolean profileUpdated = false; + if (helperProfileDTO.getIntroduce() != null) { + tblHelper.setIntroduce(helperProfileDTO.getIntroduce()); + profileUpdated = true; + } + if (helperProfileDTO.getCareExperience() != null) { + tblHelper.setIs_experienced(helperProfileDTO.getCareExperience()); + profileUpdated = true; + } + + // 자격증 정보가 있는 경우에만 업데이트 + if (helperProfileDTO.getCertificates() != null && !helperProfileDTO.getCertificates().isEmpty()) { + List certificates = helperCertRepository.findByTblHelperId(tblHelper.getId()); + + for (HelperCertDTO helperCertDTO : helperProfileDTO.getCertificates()) { + // 자격증 형식 검증 + validateCertificateFormat(helperCertDTO); + + // Q-net 인증 시도 + String qnetResult = checkCertificate( + tblHelper.getName(), + tblHelper.getBirthday(), + helperCertDTO.getCertNum(), + String.valueOf(helperCertDTO.getCertDateIssue()), + String.valueOf(helperCertDTO.getCertSerialNum()) + ); - List certificates = helperCertRepository.findAllById(tblHelper.getId()); + certificateResults.put(helperCertDTO.getCertName(), qnetResult); + + // 기존 자격증 찾아서 업데이트 + TblHelperCert existingCert = certificates.stream() + .filter(cert -> helperCertDTO.getCertName().equals(cert.getCertName())) + .findFirst() + .orElse(null); + + if (existingCert != null) { + // 기존 자격증 업데이트 + existingCert.setCertNum(helperCertDTO.getCertNum()); + existingCert.setCertDateIssue(helperCertDTO.getCertDateIssue()); + existingCert.setCertSerialNum(helperCertDTO.getCertSerialNum()); + } else { + // 새로운 자격증 추가 + TblHelperCert newCert = TblHelperCert.builder() + .tblHelper(tblHelper) + .certName(helperCertDTO.getCertName()) + .certNum(helperCertDTO.getCertNum()) + .certDateIssue(helperCertDTO.getCertDateIssue()) + .certSerialNum(helperCertDTO.getCertSerialNum()) + .build(); + certificates.add(newCert); + } - for(HelperCertDTO helperCertDTO : helperProfileDTO.getCertificates()) { - for(TblHelperCert certificate : certificates) { - if(helperCertDTO.getCertName().equals(certificate.getCertName())) { - certificate.setCertNum(helperCertDTO.getCertNum()); - certificate.setCertDateIssue(helperCertDTO.getCertDateIssue()); - certificate.setCertSerialNum(helperCertDTO.getCertSerialNum()); - break; + // Q-net 인증 실패 시 로그 기록 (fallback으로 DB에는 저장) + if (!"VALID".equals(qnetResult)) { + log.warn("Q-net 자격증 인증 실패 - 자격증명: {}, 번호: {}, 결과: {}", + helperCertDTO.getCertName(), helperCertDTO.getCertNum(), qnetResult); } } + + helperCertRepository.saveAll(certificates); } - helperCertRepository.saveAll(certificates); helperRepository.save(tblHelper); + + // 결과 구성 + result.put("message", "프로필이 정상적으로 업데이트 되었습니다."); + result.put("profileUpdated", profileUpdated); + result.put("certificatesUpdated", !certificateResults.isEmpty()); + if (!certificateResults.isEmpty()) { + result.put("certificateVerificationResults", certificateResults); + } + + return result; } @Override @@ -410,6 +473,7 @@ else if(totalYears < 1) { } @Override + @Transactional public Map saveCertificateByQNet(List helperCertDTO, UserDetails userDetails) { TblUser tblUser = memberRepository.findByEmail(userDetails.getUsername()) .orElseThrow(() -> new BadRequestException(MEMBER_NOT_FOUND)); @@ -417,16 +481,58 @@ public Map saveCertificateByQNet(List helperCertD TblHelper tblHelper = helperRepository.findByUserId(tblUser.getId()) .orElseThrow(() -> new BadRequestException(NOT_FOUND_HELPER)); + List certificates = helperCertRepository.findByTblHelperId(tblHelper.getId()); Map answers = new HashMap<>(); + for(HelperCertDTO helperCert : helperCertDTO) { - answers.put(helperCert.getCertName(), checkCertificate( + // 자격증 형식 검증 + validateCertificateFormat(helperCert); + + // Q-net 인증 시도 + String qnetResult = checkCertificate( tblHelper.getName(), tblHelper.getBirthday(), helperCert.getCertNum(), String.valueOf(helperCert.getCertDateIssue()), String.valueOf(helperCert.getCertSerialNum()) - )); + ); + + answers.put(helperCert.getCertName(), qnetResult); + + // Q-net 인증 결과와 상관없이 DB에 저장 (fallback 로직) + // 기존 자격증 찾기 + TblHelperCert existingCert = certificates.stream() + .filter(cert -> helperCert.getCertName().equals(cert.getCertName())) + .findFirst() + .orElse(null); + + if (existingCert != null) { + // 기존 자격증 업데이트 + existingCert.setCertNum(helperCert.getCertNum()); + existingCert.setCertDateIssue(helperCert.getCertDateIssue()); + existingCert.setCertSerialNum(helperCert.getCertSerialNum()); + } else { + // 새로운 자격증 추가 + TblHelperCert newCert = TblHelperCert.builder() + .tblHelper(tblHelper) + .certName(helperCert.getCertName()) + .certNum(helperCert.getCertNum()) + .certDateIssue(helperCert.getCertDateIssue()) + .certSerialNum(helperCert.getCertSerialNum()) + .build(); + certificates.add(newCert); + } + + // Q-net 인증 실패 시 로그 기록 + if (!"VALID".equals(qnetResult)) { + log.warn("Q-net 자격증 인증 실패하였으나 DB에 저장 - 자격증명: {}, 번호: {}, 결과: {}", + helperCert.getCertName(), helperCert.getCertNum(), qnetResult); + } } + + // 자격증 정보 DB에 저장 (Q-net 결과와 무관하게) + helperCertRepository.saveAll(certificates); + return answers; } @@ -491,6 +597,49 @@ public String checkCertificate(String name, String birth, String certNo, String return result; } + /** + * 자격증 형식 검증 메서드 + * @param helperCertDTO 검증할 자격증 정보 + */ + private void validateCertificateFormat(HelperCertDTO helperCertDTO) { + // 자격증 이름 검증 + if (helperCertDTO.getCertName() == null || helperCertDTO.getCertName().trim().isEmpty()) { + throw new BadRequestException(ExceptionCode.INVALID_CERTIFICATE_NAME); + } + + // 자격증 번호 검증 (요양보호사 자격증 형식: 숫자-숫자-숫자 형태) + if (helperCertDTO.getCertNum() == null || helperCertDTO.getCertNum().trim().isEmpty()) { + throw new BadRequestException(ExceptionCode.INVALID_CERTIFICATE_NUMBER); + } + + // 요양보호사 자격증 번호 형식 검증 (예: 123456-1234-567890) + String certNumPattern = "^\\d{6}-\\d{4}-\\d{6}$"; + if (!helperCertDTO.getCertNum().matches(certNumPattern)) { + throw new BadRequestException(ExceptionCode.INVALID_CERTIFICATE_FORMAT); + } + + // 발급일 검증 + if (helperCertDTO.getCertDateIssue() == null) { + throw new BadRequestException(ExceptionCode.INVALID_CERTIFICATE_ISSUE_DATE); + } + + // 발급일 형식 검증 (YYYYMMDD) + String issueDateStr = String.valueOf(helperCertDTO.getCertDateIssue()); + if (issueDateStr.length() != 8 || !issueDateStr.matches("^\\d{8}$")) { + throw new BadRequestException(ExceptionCode.INVALID_CERTIFICATE_ISSUE_DATE_FORMAT); + } + + // 내지번호 검증 + if (helperCertDTO.getCertSerialNum() == null) { + throw new BadRequestException(ExceptionCode.INVALID_CERTIFICATE_SERIAL_NUMBER); + } + + // 내지번호는 1자리 이상의 숫자 + if (helperCertDTO.getCertSerialNum() <= 0) { + throw new BadRequestException(ExceptionCode.INVALID_CERTIFICATE_SERIAL_NUMBER_FORMAT); + } + } + @Override public HelperResponse getHelperDetail(HelperDetailDTO helperDetailDTO) { TblHelper helper = helperRepository.findById(helperDetailDTO.getHelperSeq()) @@ -498,7 +647,7 @@ public HelperResponse getHelperDetail(HelperDetailDTO helperDetailDTO) { TblUser user = memberRepository.findById(helper.getUser().getId()) .orElseThrow(() -> new BadRequestException(NOT_FOUND_HELPER)); - List certificates = helperCertRepository.findAllById(Collections.singleton(helper.getId())); + List certificates = helperCertRepository.findByTblHelperId(helper.getId()); List certDTOList = new ArrayList<>(); for(TblHelperCert tblHelperCert : certificates) { @@ -521,6 +670,8 @@ public HelperResponse getHelperDetail(HelperDetailDTO helperDetailDTO) { .eduYn(helper.isEduYn()) .wage(helper.getWage()) .wageState(helper.getWageState()) + .introduce(helper.getIntroduce()) + .careExperience(helper.getIs_experienced()) .build(); } diff --git a/src/main/java/com/balybus/galaxy/global/exception/ExceptionCode.java b/src/main/java/com/balybus/galaxy/global/exception/ExceptionCode.java index 831e28ce..e062fbfb 100644 --- a/src/main/java/com/balybus/galaxy/global/exception/ExceptionCode.java +++ b/src/main/java/com/balybus/galaxy/global/exception/ExceptionCode.java @@ -33,6 +33,15 @@ public enum ExceptionCode { AGE_CAL_EXCEPTION(3011, "요양 보호사 나이 계산 중 알 수 없는 에러가 발생 했습니다."), + INVALID_CERTIFICATE_NAME(3012, "자격증 이름이 유효하지 않습니다."), + INVALID_CERTIFICATE_NUMBER(3013, "자격증 번호가 유효하지 않습니다."), + INVALID_CERTIFICATE_FORMAT(3014, "자격증 번호 형식이 올바르지 않습니다. (형식: 123456-1234-567890)"), + INVALID_CERTIFICATE_ISSUE_DATE(3015, "자격증 발급일이 유효하지 않습니다."), + INVALID_CERTIFICATE_ISSUE_DATE_FORMAT(3016, "자격증 발급일 형식이 올바르지 않습니다. (형식: YYYYMMDD)"), + INVALID_CERTIFICATE_SERIAL_NUMBER(3017, "자격증 내지번호가 유효하지 않습니다."), + INVALID_CERTIFICATE_SERIAL_NUMBER_FORMAT(3018, "자격증 내지번호 형식이 올바르지 않습니다. (1 이상의 숫자)"), + QNET_CERTIFICATE_VERIFICATION_FAILED(3019, "Q-net 자격증 인증에 실패했습니다."), + // 4xxx 로그인 LOGIN_ID_EXIST(4000, "로그인 아이디가 이미 존재합니다."), SIGNUP_INFO_NULL(4001, "회원 가입 정보를 확인해주세요."), From ecad64625ad26bd6130f6d578ad9b59a5c2097c3 Mon Sep 17 00:00:00 2001 From: mike Date: Wed, 30 Jul 2025 02:04:00 +0900 Subject: [PATCH 10/12] =?UTF-8?q?[Feat]:=20=EA=B5=AC=EB=B6=84=EC=9E=90?= =?UTF-8?q?=EB=A1=9C=20=EC=9A=94=EC=96=91=20=EB=B3=B4=ED=98=B8=EC=82=AC=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20=EC=9D=91=EB=8B=B5=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/TblHelperWorkTime.java | 3 +- .../dto/response/HelperResponse.java | 33 ++++-- .../dto/response/HelperWorkLocationDto.java | 16 +++ .../dto/response/HelperWorkTimeDto.java | 21 ++++ .../careAssistant/dto/response/ImageDto.java | 16 +++ .../HelperWorkLocationRepository.java | 3 + .../service/HelperServiceImpl.java | 111 ++++++++++++++---- .../tblAddressSecond/TblAddressSecond.java | 2 + 8 files changed, 170 insertions(+), 35 deletions(-) create mode 100644 src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperWorkLocationDto.java create mode 100644 src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperWorkTimeDto.java create mode 100644 src/main/java/com/balybus/galaxy/careAssistant/dto/response/ImageDto.java diff --git a/src/main/java/com/balybus/galaxy/careAssistant/domain/TblHelperWorkTime.java b/src/main/java/com/balybus/galaxy/careAssistant/domain/TblHelperWorkTime.java index 39a89bfe..ac960628 100644 --- a/src/main/java/com/balybus/galaxy/careAssistant/domain/TblHelperWorkTime.java +++ b/src/main/java/com/balybus/galaxy/careAssistant/domain/TblHelperWorkTime.java @@ -49,7 +49,6 @@ public class TblHelperWorkTime extends BaseEntity { private Boolean negotiation; @Column(name = "hwt_work_term") - @Convert(converter = StringListConverter.class) @Comment("근무 가능 기간") - private List workTerm = new ArrayList<>(); + private String workTerm; } diff --git a/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperResponse.java b/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperResponse.java index fb949cea..1cf75695 100644 --- a/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperResponse.java +++ b/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperResponse.java @@ -1,6 +1,12 @@ package com.balybus.galaxy.careAssistant.dto.response; +import com.balybus.galaxy.careAssistant.domain.TblHelperWorkLocation; +import com.balybus.galaxy.careAssistant.domain.TblHelperWorkTime; +import com.balybus.galaxy.global.domain.tblAddressFirst.TblAddressFirst; +import com.balybus.galaxy.global.domain.tblAddressSecond.TblAddressSecond; +import com.balybus.galaxy.global.domain.tblAddressThird.TblAddressThird; import com.balybus.galaxy.login.classic.dto.request.HelperCertDTO; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -18,11 +24,24 @@ public class HelperResponse { private String name; private String phone; private String addressDetail; - private List certificates; - private boolean carOwnYn; - private boolean eduYn; - private Integer wage; - private Integer wageState; - private String introduce; - private Boolean careExperience; + private ImageDto img; // 프로필 사진 + private List helperWorkLocation; // 선호 지역 + private List helperWorkTime; // 근무 가능일정 + + private int careLevel; // 장기 요양 등급 + private int inmateState; // 동거인 여부 + private int workType; // 근무 종류 + private int careGender; // 성별 + private int serviceMeal; // 식사 보조 + private int serviceMobility; // 이동 보조 + private int serviceDaily; // 일상 생활 + + private List certificates; // 자격증 번호 + private boolean carOwnYn; // 요양보호사 차량 소유 여부 + private boolean eduYn; // 치매 교육 이수 여부 + private Integer wage; // 급여 + private Integer wageState; // 시급, 일급, 주급 구분 + private String introduce; // 자기소개 + private Boolean careExperience; // 간병 경력 + private Boolean wageNegotiation; // 급여 협의 가능 여부 } diff --git a/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperWorkLocationDto.java b/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperWorkLocationDto.java new file mode 100644 index 00000000..442e9eac --- /dev/null +++ b/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperWorkLocationDto.java @@ -0,0 +1,16 @@ +package com.balybus.galaxy.careAssistant.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class HelperWorkLocationDto { + private Long afSeq; // 시.도 구분자 + private Long asSeq; // 시.군.구 구분자 + private Long atSeq; // 읍.면.동 구분자 +} \ No newline at end of file diff --git a/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperWorkTimeDto.java b/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperWorkTimeDto.java new file mode 100644 index 00000000..7f45b529 --- /dev/null +++ b/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperWorkTimeDto.java @@ -0,0 +1,21 @@ +package com.balybus.galaxy.careAssistant.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class HelperWorkTimeDto { + private Long id; + private Integer date; // 근무 가능 요일 + private String startTime; // 시작시간 + private String endTime; // 종료시간 + private Boolean negotiation; // 근무 협의 여부 + private String workTerm; // 근무 가능 기간 +} \ No newline at end of file diff --git a/src/main/java/com/balybus/galaxy/careAssistant/dto/response/ImageDto.java b/src/main/java/com/balybus/galaxy/careAssistant/dto/response/ImageDto.java new file mode 100644 index 00000000..9c7c28eb --- /dev/null +++ b/src/main/java/com/balybus/galaxy/careAssistant/dto/response/ImageDto.java @@ -0,0 +1,16 @@ +package com.balybus.galaxy.careAssistant.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ImageDto { + private Long id; + private String imgUuid; + private String imgOriginName; +} \ No newline at end of file diff --git a/src/main/java/com/balybus/galaxy/careAssistant/repository/HelperWorkLocationRepository.java b/src/main/java/com/balybus/galaxy/careAssistant/repository/HelperWorkLocationRepository.java index 77d965c5..66551df2 100644 --- a/src/main/java/com/balybus/galaxy/careAssistant/repository/HelperWorkLocationRepository.java +++ b/src/main/java/com/balybus/galaxy/careAssistant/repository/HelperWorkLocationRepository.java @@ -4,6 +4,9 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface HelperWorkLocationRepository extends JpaRepository { + List findByHelper_Id(Long helperId); } diff --git a/src/main/java/com/balybus/galaxy/careAssistant/service/HelperServiceImpl.java b/src/main/java/com/balybus/galaxy/careAssistant/service/HelperServiceImpl.java index 517a8eeb..eab55fd7 100644 --- a/src/main/java/com/balybus/galaxy/careAssistant/service/HelperServiceImpl.java +++ b/src/main/java/com/balybus/galaxy/careAssistant/service/HelperServiceImpl.java @@ -12,6 +12,8 @@ import com.balybus.galaxy.careAssistant.dto.request.*; import com.balybus.galaxy.careAssistant.dto.response.*; import com.balybus.galaxy.careAssistant.repository.*; +import com.balybus.galaxy.careAssistant.dto.response.HelperWorkLocationDto; +import com.balybus.galaxy.careAssistant.dto.response.ImageDto; import com.balybus.galaxy.login.classic.dto.request.HelperCertDTO; import com.balybus.galaxy.member.domain.TblUser; import com.balybus.galaxy.member.repository.MemberRepository; @@ -84,12 +86,49 @@ public HelperResponse getAllHelperInfo(UserDetails userDetails) { .build()); } + // 선호 지역 + List workLocations = helperWorkLocationRepository.findByHelper_Id(tblHelper.getId()); + List helperWorkLocationDtos = workLocations.stream() + .map(wl -> HelperWorkLocationDto.builder() + .afSeq(wl.getTblAddressFirst().getId()) + .asSeq(wl.getTblAddressSecond().getId()) + .atSeq(wl.getTblAddressThird().getId()) + .build()) + .toList(); + + // 근무 가능 일정 + List workTimes = helperWorkTimeRepository.findByHelper(tblHelper); + List helperWorkTimeDtos = workTimes.stream() + .map(wt -> HelperWorkTimeDto.builder() + .id(wt.getId()) + .date(wt.getDate()) + .startTime(wt.getStartTime()) + .endTime(wt.getEndTime()) + .negotiation(wt.getNegotiation()) + .workTerm(wt.getWorkTerm()) + .build()) + .toList(); + return HelperResponse.builder() .id(tblHelper.getId()) .userEmail(tblUser.getEmail()) .name(tblHelper.getName()) .phone(tblHelper.getPhone()) .addressDetail(tblHelper.getAddressDetail()) + .img(tblHelper.getImg() != null ? ImageDto.builder() + .id(tblHelper.getImg().getId()) + .imgUuid(tblHelper.getImg().getImgUuid()) + .imgOriginName(tblHelper.getImg().getImgOriginName()) + .build() : null) + .helperWorkLocation(helperWorkLocationDtos) + .helperWorkTime(helperWorkTimeDtos) + .careLevel(tblHelper.getCareLevel()) + .inmateState(tblHelper.getInmateState()) + .workType(tblHelper.getWorkType()) + .careGender(tblHelper.getCareGender()) + .serviceMeal(tblHelper.getServiceMeal()) + .serviceMobility(tblHelper.getServiceMobility()) + .serviceDaily(tblHelper.getServiceDaily()) .certificates(certDTOList) .carOwnYn(tblHelper.isCarOwnYn()) .eduYn(tblHelper.isEduYn()) @@ -97,6 +136,7 @@ public HelperResponse getAllHelperInfo(UserDetails userDetails) { .wageState(tblHelper.getWageState()) .introduce(tblHelper.getIntroduce()) .careExperience(tblHelper.getIs_experienced()) + .wageNegotiation(tblHelper.getWageNegotiation()) .build(); } @@ -272,7 +312,7 @@ public HelperWorkTimeResponse workTimeSignUp(HelperWorkTimeRequestDTO helperWork .startTime(dto.getStartTime()) .endTime(dto.getEndTime()) .negotiation(helperWorkTimeRequestDTO.getNegotiation()) - .workTerm(helperWorkTimeRequestDTO.getWorkTerm()) + .workTerm(helperWorkTimeRequestDTO.getWorkTerm().toString()) .build()) .collect(Collectors.toList()); @@ -421,31 +461,14 @@ else if(totalYears < 1) { List workTimes = helperWorkTimeRepository.findByHelper(helper); if (!workTimes.isEmpty() && !helperSearchDTO.getTerms().isEmpty()) { - long size = workTimes.size(); - long maxWorkTermValue = 0; - for(int i=0; i workLocations = helperWorkLocationRepository.findByHelper_Id(helper.getId()); + List helperWorkLocationDtos = workLocations.stream() + .map(wl -> HelperWorkLocationDto.builder() + .afSeq(wl.getTblAddressFirst().getId()) + .asSeq(wl.getTblAddressSecond().getId()) + .atSeq(wl.getTblAddressThird().getId()) + .build()) + .toList(); + + // 근무 가능 일정 + List workTimes = helperWorkTimeRepository.findByHelper(helper); + List helperWorkTimeDtos = workTimes.stream() + .map(wt -> HelperWorkTimeDto.builder() + .id(wt.getId()) + .date(wt.getDate()) + .startTime(wt.getStartTime()) + .endTime(wt.getEndTime()) + .negotiation(wt.getNegotiation()) + .workTerm(wt.getWorkTerm()) + .build()) + .toList(); + return HelperResponse.builder() .id(helper.getId()) .userEmail(user.getEmail()) .name(helper.getName()) .phone(helper.getPhone()) .addressDetail(helper.getAddressDetail()) + .img(helper.getImg() != null ? ImageDto.builder() + .id(helper.getImg().getId()) + .imgUuid(helper.getImg().getImgUuid()) + .imgOriginName(helper.getImg().getImgOriginName()) + .build() : null) + .helperWorkLocation(helperWorkLocationDtos) + .helperWorkTime(helperWorkTimeDtos) + .careLevel(helper.getCareLevel()) + .inmateState(helper.getInmateState()) + .workType(helper.getWorkType()) + .careGender(helper.getCareGender()) + .serviceMeal(helper.getServiceMeal()) + .serviceMobility(helper.getServiceMobility()) + .serviceDaily(helper.getServiceDaily()) .certificates(certDTOList) .carOwnYn(helper.isCarOwnYn()) .eduYn(helper.isEduYn()) @@ -672,8 +732,7 @@ public HelperResponse getHelperDetail(HelperDetailDTO helperDetailDTO) { .wageState(helper.getWageState()) .introduce(helper.getIntroduce()) .careExperience(helper.getIs_experienced()) + .wageNegotiation(helper.getWageNegotiation()) .build(); } - - } \ No newline at end of file diff --git a/src/main/java/com/balybus/galaxy/global/domain/tblAddressSecond/TblAddressSecond.java b/src/main/java/com/balybus/galaxy/global/domain/tblAddressSecond/TblAddressSecond.java index 2f2b8a88..7d641792 100644 --- a/src/main/java/com/balybus/galaxy/global/domain/tblAddressSecond/TblAddressSecond.java +++ b/src/main/java/com/balybus/galaxy/global/domain/tblAddressSecond/TblAddressSecond.java @@ -1,6 +1,7 @@ package com.balybus.galaxy.global.domain.tblAddressSecond; import com.balybus.galaxy.global.domain.tblAddressFirst.TblAddressFirst; +import com.fasterxml.jackson.annotation.JsonBackReference; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; @@ -23,6 +24,7 @@ public class TblAddressSecond { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "af_seq", nullable = false) @Comment("시.도 구분자") + @JsonBackReference private TblAddressFirst addressFirst; @Column(name = "as_name", nullable = false, length = 50) From 6e63ab0186ff5a29b9ec3280582a4b604340004c Mon Sep 17 00:00:00 2001 From: mike Date: Sat, 23 Aug 2025 07:28:05 +0900 Subject: [PATCH 11/12] =?UTF-8?q?[Feat]:=20=EC=9A=94=EC=95=BC=20=EB=B3=B4?= =?UTF-8?q?=ED=98=B8=EC=82=AC=20=ED=94=84=EB=A1=9C=ED=95=84=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=E3=85=A3=E3=85=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/HelperController.java | 28 +- .../dto/request/HelperCompleteProfileDTO.java | 54 ++ .../HelperCompleteProfileResponse.java | 43 ++ .../careAssistant/service/HelperService.java | 1 + .../service/HelperServiceImpl.java | 490 ++++++++++++++---- .../config/jwt/JwtAuthenticationFilter.java | 5 + 6 files changed, 516 insertions(+), 105 deletions(-) create mode 100644 src/main/java/com/balybus/galaxy/careAssistant/dto/request/HelperCompleteProfileDTO.java create mode 100644 src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperCompleteProfileResponse.java diff --git a/src/main/java/com/balybus/galaxy/careAssistant/controller/HelperController.java b/src/main/java/com/balybus/galaxy/careAssistant/controller/HelperController.java index 6048dbe2..d921d695 100644 --- a/src/main/java/com/balybus/galaxy/careAssistant/controller/HelperController.java +++ b/src/main/java/com/balybus/galaxy/careAssistant/controller/HelperController.java @@ -89,6 +89,32 @@ public ResponseEntity> updateProfile(@RequestBody HelperProf return ResponseEntity.ok(result); } + /** + * 요양 보호사 통합 프로필 업데이트 + * @param helperCompleteProfileDTO + * @param userDetails + * @return + */ + @Operation(summary = "요양 보호사 통합 프로필 업데이트", description = "현재 로그인한 요양 보호사의 모든 정보를 한 번에 업데이트") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "프로필이 성공적으로 업데이트되었습니다.", + content = @Content(schema = @Schema(implementation = HelperCompleteProfileResponse.class))), + @ApiResponse(responseCode = "3000", description = "요양 보호사 테이블을 찾을 수 없습니다."), + @ApiResponse(responseCode = "3010", description = "로그인한 회원을 찾을 수 없습니다."), + @ApiResponse(responseCode = "3008", description = "잘못된 주소 목록"), + @ApiResponse(responseCode = "3009", description = "중복된 근무 가능 시간이 존재합니다."), + @ApiResponse(responseCode = "3012", description = "자격증 이름이 유효하지 않습니다."), + @ApiResponse(responseCode = "3013", description = "자격증 번호가 유효하지 않습니다."), + @ApiResponse(responseCode = "3014", description = "자격증 번호 형식이 올바르지 않습니다.") + }) + @PutMapping("/helper/complete-profile") + public ResponseEntity updateCompleteProfile( + @RequestBody HelperCompleteProfileDTO helperCompleteProfileDTO, + @AuthenticationPrincipal UserDetails userDetails) { + HelperCompleteProfileResponse response = helperService.updateCompleteProfile(userDetails, helperCompleteProfileDTO); + return ResponseEntity.ok(response); + } + /////////////////////////////////////// @@ -204,7 +230,7 @@ public ResponseEntity> certiVerify( ////////////// - @Operation(summary = "요양 보호사 정보 모두보기", description = "개인 요양보호사 구분자로 요양보호사 상세 조회") + @Operation(summary = "요양 보호사 정보 조회", description = "개인 요양보호사 구분자로 요양보호사 상세 조회") @ApiResponses({ @ApiResponse(responseCode = "200", description = "요양 보호사 정보를 성공적으로 불러왔습니다.", content = @Content(schema = @Schema(implementation = HelperResponse.class)) diff --git a/src/main/java/com/balybus/galaxy/careAssistant/dto/request/HelperCompleteProfileDTO.java b/src/main/java/com/balybus/galaxy/careAssistant/dto/request/HelperCompleteProfileDTO.java new file mode 100644 index 00000000..33de29df --- /dev/null +++ b/src/main/java/com/balybus/galaxy/careAssistant/dto/request/HelperCompleteProfileDTO.java @@ -0,0 +1,54 @@ +package com.balybus.galaxy.careAssistant.dto.request; + +import com.balybus.galaxy.login.classic.dto.request.HelperCertDTO; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class HelperCompleteProfileDTO { + // 프로필 정보 + private String introduce; + private Boolean careExperience; + + // 자격증 정보 + private List certificates; + private Boolean verifyQnet; // Q-net 검증 여부 (기본값: false) + + // 급여 정보 + private Integer wage; + private Integer wageState; + private Boolean wageNegotiation; + + // 근무 희망 지역 + private List addressFirstIds; + private List addressSecondIds; + private List addressThirdIds; + + // 근무 가능 시간 + private List workTimes; + private Boolean negotiation; // 시간 협의 가능 여부 + private Integer workTerm; // 근무 기간 + + // 경력 정보 + private HelperExperienceDTO experience; + + // 돌봄 서비스 정보 + private Integer careLevel; + private Integer inmateState; + private Integer workType; + private Integer careGender; + private Integer serviceMeal; + private Integer serviceMobility; + private Integer serviceDaily; + + // 기타 정보 + private Boolean carOwnYn; + private Boolean eduYn; +} \ No newline at end of file diff --git a/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperCompleteProfileResponse.java b/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperCompleteProfileResponse.java new file mode 100644 index 00000000..1ba2a1fb --- /dev/null +++ b/src/main/java/com/balybus/galaxy/careAssistant/dto/response/HelperCompleteProfileResponse.java @@ -0,0 +1,43 @@ +package com.balybus.galaxy.careAssistant.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.Map; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class HelperCompleteProfileResponse { + private boolean success; + private String message; + + // 각 섹션별 처리 결과 + private SectionResult profileResult; + private SectionResult certificateResult; + private SectionResult wageResult; + private SectionResult locationResult; + private SectionResult workTimeResult; + private SectionResult experienceResult; + private SectionResult careServiceResult; + + // 자격증 검증 결과 (Q-net 검증한 경우) + private Map certificateVerificationResults; + + // 전체 업데이트된 프로필 정보 + private HelperResponse updatedProfile; + + @Getter + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class SectionResult { + private boolean updated; + private boolean success; + private String message; + private String error; + } +} \ No newline at end of file diff --git a/src/main/java/com/balybus/galaxy/careAssistant/service/HelperService.java b/src/main/java/com/balybus/galaxy/careAssistant/service/HelperService.java index 8c7e0fa5..31961809 100644 --- a/src/main/java/com/balybus/galaxy/careAssistant/service/HelperService.java +++ b/src/main/java/com/balybus/galaxy/careAssistant/service/HelperService.java @@ -19,4 +19,5 @@ public interface HelperService { Map saveCertificateByQNet(List helperCertDTO, UserDetails userDetails); String checkCertificate(String name, String birth, String certNo, String issueDate, String insideNo); HelperResponse getHelperDetail(HelperDetailDTO helperDetailDTO); + HelperCompleteProfileResponse updateCompleteProfile(UserDetails userDetails, HelperCompleteProfileDTO dto); } diff --git a/src/main/java/com/balybus/galaxy/careAssistant/service/HelperServiceImpl.java b/src/main/java/com/balybus/galaxy/careAssistant/service/HelperServiceImpl.java index eab55fd7..ef54f440 100644 --- a/src/main/java/com/balybus/galaxy/careAssistant/service/HelperServiceImpl.java +++ b/src/main/java/com/balybus/galaxy/careAssistant/service/HelperServiceImpl.java @@ -11,6 +11,7 @@ import com.balybus.galaxy.careAssistant.domain.*; import com.balybus.galaxy.careAssistant.dto.request.*; import com.balybus.galaxy.careAssistant.dto.response.*; +import com.balybus.galaxy.careAssistant.dto.response.HelperCompleteProfileResponse.SectionResult; import com.balybus.galaxy.careAssistant.repository.*; import com.balybus.galaxy.careAssistant.dto.response.HelperWorkLocationDto; import com.balybus.galaxy.careAssistant.dto.response.ImageDto; @@ -141,7 +142,6 @@ public HelperResponse getAllHelperInfo(UserDetails userDetails) { } @Override - @Transactional public Map updateProfile(UserDetails userDetails, HelperProfileDTO helperProfileDTO) { String username = userDetails.getUsername(); @@ -165,56 +165,9 @@ public Map updateProfile(UserDetails userDetails, HelperProfileD profileUpdated = true; } - // 자격증 정보가 있는 경우에만 업데이트 + // 자격증 정보가 있는 경우에만 업데이트 (Q-net 검증 없이) if (helperProfileDTO.getCertificates() != null && !helperProfileDTO.getCertificates().isEmpty()) { - List certificates = helperCertRepository.findByTblHelperId(tblHelper.getId()); - - for (HelperCertDTO helperCertDTO : helperProfileDTO.getCertificates()) { - // 자격증 형식 검증 - validateCertificateFormat(helperCertDTO); - - // Q-net 인증 시도 - String qnetResult = checkCertificate( - tblHelper.getName(), - tblHelper.getBirthday(), - helperCertDTO.getCertNum(), - String.valueOf(helperCertDTO.getCertDateIssue()), - String.valueOf(helperCertDTO.getCertSerialNum()) - ); - - certificateResults.put(helperCertDTO.getCertName(), qnetResult); - - // 기존 자격증 찾아서 업데이트 - TblHelperCert existingCert = certificates.stream() - .filter(cert -> helperCertDTO.getCertName().equals(cert.getCertName())) - .findFirst() - .orElse(null); - - if (existingCert != null) { - // 기존 자격증 업데이트 - existingCert.setCertNum(helperCertDTO.getCertNum()); - existingCert.setCertDateIssue(helperCertDTO.getCertDateIssue()); - existingCert.setCertSerialNum(helperCertDTO.getCertSerialNum()); - } else { - // 새로운 자격증 추가 - TblHelperCert newCert = TblHelperCert.builder() - .tblHelper(tblHelper) - .certName(helperCertDTO.getCertName()) - .certNum(helperCertDTO.getCertNum()) - .certDateIssue(helperCertDTO.getCertDateIssue()) - .certSerialNum(helperCertDTO.getCertSerialNum()) - .build(); - certificates.add(newCert); - } - - // Q-net 인증 실패 시 로그 기록 (fallback으로 DB에는 저장) - if (!"VALID".equals(qnetResult)) { - log.warn("Q-net 자격증 인증 실패 - 자격증명: {}, 번호: {}, 결과: {}", - helperCertDTO.getCertName(), helperCertDTO.getCertNum(), qnetResult); - } - } - - helperCertRepository.saveAll(certificates); + certificateResults = processCertificates(helperProfileDTO.getCertificates(), tblHelper, false); } helperRepository.save(tblHelper); @@ -496,7 +449,6 @@ else if(totalYears < 1) { } @Override - @Transactional public Map saveCertificateByQNet(List helperCertDTO, UserDetails userDetails) { TblUser tblUser = memberRepository.findByEmail(userDetails.getUsername()) .orElseThrow(() -> new BadRequestException(MEMBER_NOT_FOUND)); @@ -504,59 +456,8 @@ public Map saveCertificateByQNet(List helperCertD TblHelper tblHelper = helperRepository.findByUserId(tblUser.getId()) .orElseThrow(() -> new BadRequestException(NOT_FOUND_HELPER)); - List certificates = helperCertRepository.findByTblHelperId(tblHelper.getId()); - Map answers = new HashMap<>(); - - for(HelperCertDTO helperCert : helperCertDTO) { - // 자격증 형식 검증 - validateCertificateFormat(helperCert); - - // Q-net 인증 시도 - String qnetResult = checkCertificate( - tblHelper.getName(), - tblHelper.getBirthday(), - helperCert.getCertNum(), - String.valueOf(helperCert.getCertDateIssue()), - String.valueOf(helperCert.getCertSerialNum()) - ); - - answers.put(helperCert.getCertName(), qnetResult); - - // Q-net 인증 결과와 상관없이 DB에 저장 (fallback 로직) - // 기존 자격증 찾기 - TblHelperCert existingCert = certificates.stream() - .filter(cert -> helperCert.getCertName().equals(cert.getCertName())) - .findFirst() - .orElse(null); - - if (existingCert != null) { - // 기존 자격증 업데이트 - existingCert.setCertNum(helperCert.getCertNum()); - existingCert.setCertDateIssue(helperCert.getCertDateIssue()); - existingCert.setCertSerialNum(helperCert.getCertSerialNum()); - } else { - // 새로운 자격증 추가 - TblHelperCert newCert = TblHelperCert.builder() - .tblHelper(tblHelper) - .certName(helperCert.getCertName()) - .certNum(helperCert.getCertNum()) - .certDateIssue(helperCert.getCertDateIssue()) - .certSerialNum(helperCert.getCertSerialNum()) - .build(); - certificates.add(newCert); - } - - // Q-net 인증 실패 시 로그 기록 - if (!"VALID".equals(qnetResult)) { - log.warn("Q-net 자격증 인증 실패하였으나 DB에 저장 - 자격증명: {}, 번호: {}, 결과: {}", - helperCert.getCertName(), helperCert.getCertNum(), qnetResult); - } - } - - // 자격증 정보 DB에 저장 (Q-net 결과와 무관하게) - helperCertRepository.saveAll(certificates); - - return answers; + // processCertificates 메서드를 사용하여 처리 (Q-net 검증 포함) + return processCertificates(helperCertDTO, tblHelper, true); } @@ -663,6 +564,387 @@ private void validateCertificateFormat(HelperCertDTO helperCertDTO) { } } + /** + * 통합 프로필 업데이트 메서드 + * @param userDetails 현재 로그인한 사용자 정보 + * @param dto 통합 프로필 업데이트 DTO + * @return 업데이트 결과 + */ + @Transactional + public HelperCompleteProfileResponse updateCompleteProfile(UserDetails userDetails, HelperCompleteProfileDTO dto) { + String username = userDetails.getUsername(); + + TblUser tblUser = memberRepository.findByEmail(username) + .orElseThrow(() -> new BadRequestException(MEMBER_NOT_FOUND)); + + TblHelper tblHelper = helperRepository.findByUserId(tblUser.getId()) + .orElseThrow(() -> new BadRequestException(NOT_FOUND_HELPER)); + + HelperCompleteProfileResponse.HelperCompleteProfileResponseBuilder responseBuilder = + HelperCompleteProfileResponse.builder() + .success(true) + .message("프로필이 성공적으로 업데이트되었습니다."); + + // 1. 기본 프로필 정보 업데이트 + SectionResult profileResult = updateBasicProfile(tblHelper, dto); + responseBuilder.profileResult(profileResult); + + // 2. 자격증 정보 업데이트 + if (dto.getCertificates() != null && !dto.getCertificates().isEmpty()) { + boolean verifyQnet = dto.getVerifyQnet() != null ? dto.getVerifyQnet() : false; + Map certResults = processCertificates(dto.getCertificates(), tblHelper, verifyQnet); + + SectionResult certResult = SectionResult.builder() + .updated(true) + .success(true) + .message("자격증 정보가 업데이트되었습니다.") + .build(); + + responseBuilder.certificateResult(certResult) + .certificateVerificationResults(certResults); + } + + // 3. 급여 정보 업데이트 + if (dto.getWage() != null || dto.getWageState() != null || dto.getWageNegotiation() != null) { + SectionResult wageResult = updateWageInfo(tblHelper, dto); + responseBuilder.wageResult(wageResult); + } + + // 4. 근무 희망 지역 업데이트 + if (dto.getAddressFirstIds() != null && dto.getAddressSecondIds() != null && dto.getAddressThirdIds() != null) { + SectionResult locationResult = updateWorkLocation(tblHelper, dto); + responseBuilder.locationResult(locationResult); + } + + // 5. 근무 가능 시간 업데이트 + if (dto.getWorkTimes() != null && !dto.getWorkTimes().isEmpty()) { + SectionResult workTimeResult = updateWorkTime(tblHelper, dto); + responseBuilder.workTimeResult(workTimeResult); + } + + // 6. 경력 정보 업데이트 + if (dto.getExperience() != null) { + SectionResult experienceResult = updateExperience(tblHelper, dto.getExperience()); + responseBuilder.experienceResult(experienceResult); + } + + // 7. 돌봄 서비스 정보 업데이트 + SectionResult careServiceResult = updateCareService(tblHelper, dto); + responseBuilder.careServiceResult(careServiceResult); + + // Helper 엔티티 저장 + helperRepository.save(tblHelper); + + // 업데이트된 전체 프로필 정보 조회 + HelperResponse updatedProfile = getAllHelperInfo(userDetails); + responseBuilder.updatedProfile(updatedProfile); + + return responseBuilder.build(); + } + + private SectionResult updateBasicProfile(TblHelper tblHelper, HelperCompleteProfileDTO dto) { + boolean updated = false; + + if (dto.getIntroduce() != null) { + tblHelper.setIntroduce(dto.getIntroduce()); + updated = true; + } + + if (dto.getCareExperience() != null) { + tblHelper.setIs_experienced(dto.getCareExperience()); + updated = true; + } + + if (dto.getCarOwnYn() != null) { + tblHelper.setCarOwnYn(dto.getCarOwnYn()); + updated = true; + } + + if (dto.getEduYn() != null) { + tblHelper.setEduYn(dto.getEduYn()); + updated = true; + } + + return SectionResult.builder() + .updated(updated) + .success(true) + .message(updated ? "기본 프로필이 업데이트되었습니다." : "업데이트할 프로필 정보가 없습니다.") + .build(); + } + + private SectionResult updateWageInfo(TblHelper tblHelper, HelperCompleteProfileDTO dto) { + boolean updated = false; + + if (dto.getWage() != null) { + tblHelper.setWage(dto.getWage()); + updated = true; + } + + if (dto.getWageState() != null) { + tblHelper.setWageState(dto.getWageState()); + updated = true; + } + + if (dto.getWageNegotiation() != null) { + tblHelper.setWageNegotiation(dto.getWageNegotiation()); + updated = true; + } + + return SectionResult.builder() + .updated(updated) + .success(true) + .message(updated ? "급여 정보가 업데이트되었습니다." : "업데이트할 급여 정보가 없습니다.") + .build(); + } + + private SectionResult updateWorkLocation(TblHelper tblHelper, HelperCompleteProfileDTO dto) { + try { + // 기존 근무 희망 지역 삭제 + List existingLocations = helperWorkLocationRepository.findByHelper_Id(tblHelper.getId()); + helperWorkLocationRepository.deleteAll(existingLocations); + + // 새로운 근무 희망 지역 추가 + List addressFirstList = tblAddressFirstRepository.findAllById(dto.getAddressFirstIds()); + List addressSecondList = tblAddressSecondRepository.findAllById(dto.getAddressSecondIds()); + List addressThirdList = tblAddressThirdRepository.findAllById(dto.getAddressThirdIds()); + + if (addressFirstList.isEmpty() || addressSecondList.isEmpty() || addressThirdList.isEmpty()) { + return SectionResult.builder() + .updated(false) + .success(false) + .error("유효하지 않은 주소 정보입니다.") + .build(); + } + + List workLocations = new ArrayList<>(); + for (int i = 0; i < Math.min(addressFirstList.size(), Math.min(addressSecondList.size(), addressThirdList.size())); i++) { + TblHelperWorkLocation location = TblHelperWorkLocation.builder() + .helper(tblHelper) + .tblAddressFirst(addressFirstList.get(i)) + .tblAddressSecond(addressSecondList.get(i)) + .tblAddressThird(addressThirdList.get(i)) + .build(); + workLocations.add(location); + } + + helperWorkLocationRepository.saveAll(workLocations); + + return SectionResult.builder() + .updated(true) + .success(true) + .message("근무 희망 지역이 업데이트되었습니다.") + .build(); + } catch (Exception e) { + return SectionResult.builder() + .updated(false) + .success(false) + .error("근무 희망 지역 업데이트 중 오류가 발생했습니다: " + e.getMessage()) + .build(); + } + } + + private SectionResult updateWorkTime(TblHelper tblHelper, HelperCompleteProfileDTO dto) { + try { + List newWorkTimes = dto.getWorkTimes().stream() + .filter(wt -> !helperWorkTimeRepository.existsByHelperAndDateAndStartTimeAndEndTime( + tblHelper, wt.getDay(), wt.getStartTime(), wt.getEndTime())) + .map(wt -> TblHelperWorkTime.builder() + .helper(tblHelper) + .date(wt.getDay()) + .startTime(wt.getStartTime()) + .endTime(wt.getEndTime()) + .negotiation(dto.getNegotiation()) + .workTerm(dto.getWorkTerm() != null ? dto.getWorkTerm().toString() : null) + .build()) + .collect(Collectors.toList()); + + if (!newWorkTimes.isEmpty()) { + helperWorkTimeRepository.saveAll(newWorkTimes); + return SectionResult.builder() + .updated(true) + .success(true) + .message("근무 가능 시간이 업데이트되었습니다.") + .build(); + } + + return SectionResult.builder() + .updated(false) + .success(true) + .message("추가할 새로운 근무 시간이 없습니다.") + .build(); + } catch (Exception e) { + return SectionResult.builder() + .updated(false) + .success(false) + .error("근무 가능 시간 업데이트 중 오류가 발생했습니다: " + e.getMessage()) + .build(); + } + } + + private SectionResult updateExperience(TblHelper tblHelper, HelperExperienceDTO experienceDTO) { + try { + if (HelperExperienceDTO.hasNullHelperExperienceRequestDTO(experienceDTO)) { + return SectionResult.builder() + .updated(false) + .success(false) + .error("경력 정보가 불완전합니다.") + .build(); + } + + int countExperience = helperExperienceRepository.countByHelperAndFieldAndHeStartDateAndHeEndDate( + tblHelper, + experienceDTO.getField(), + experienceDTO.getHeStartDate(), + experienceDTO.getHeEndDate() + ); + + if (countExperience > 0) { + return SectionResult.builder() + .updated(false) + .success(false) + .error("이미 등록된 경력입니다.") + .build(); + } + + TblHelperExperience experience = TblHelperExperience.builder() + .helper(tblHelper) + .field(experienceDTO.getField()) + .heStartDate(experienceDTO.getHeStartDate()) + .heEndDate(experienceDTO.getHeEndDate()) + .build(); + + helperExperienceRepository.save(experience); + tblHelper.setIs_experienced(true); + + return SectionResult.builder() + .updated(true) + .success(true) + .message("경력 정보가 업데이트되었습니다.") + .build(); + } catch (Exception e) { + return SectionResult.builder() + .updated(false) + .success(false) + .error("경력 정보 업데이트 중 오류가 발생했습니다: " + e.getMessage()) + .build(); + } + } + + private SectionResult updateCareService(TblHelper tblHelper, HelperCompleteProfileDTO dto) { + boolean updated = false; + + if (dto.getCareLevel() != null) { + tblHelper.setCareLevel(dto.getCareLevel()); + updated = true; + } + + if (dto.getInmateState() != null) { + tblHelper.setInmateState(dto.getInmateState()); + updated = true; + } + + if (dto.getWorkType() != null) { + tblHelper.setWorkType(dto.getWorkType()); + updated = true; + } + + if (dto.getCareGender() != null) { + tblHelper.setCareGender(dto.getCareGender()); + updated = true; + } + + if (dto.getServiceMeal() != null) { + tblHelper.setServiceMeal(dto.getServiceMeal()); + updated = true; + } + + if (dto.getServiceMobility() != null) { + tblHelper.setServiceMobility(dto.getServiceMobility()); + updated = true; + } + + if (dto.getServiceDaily() != null) { + tblHelper.setServiceDaily(dto.getServiceDaily()); + updated = true; + } + + return SectionResult.builder() + .updated(updated) + .success(true) + .message(updated ? "돌봄 서비스 정보가 업데이트되었습니다." : "업데이트할 돌봄 서비스 정보가 없습니다.") + .build(); + } + + /** + * 자격증 처리를 위한 private 메서드 + * @param certificates 처리할 자격증 리스트 + * @param tblHelper 요양보호사 엔티티 + * @param verifyQnet Q-net 검증 여부 + * @return 처리 결과 Map + */ + private Map processCertificates(List certificates, TblHelper tblHelper, boolean verifyQnet) { + List existingCerts = helperCertRepository.findByTblHelperId(tblHelper.getId()); + Map results = new HashMap<>(); + + for (HelperCertDTO certDTO : certificates) { + try { + // 자격증 형식 검증 + validateCertificateFormat(certDTO); + + String verificationResult = "NOT_VERIFIED"; + + // Q-net 검증이 요청된 경우에만 수행 + if (verifyQnet) { + verificationResult = checkCertificate( + tblHelper.getName(), + tblHelper.getBirthday(), + certDTO.getCertNum(), + String.valueOf(certDTO.getCertDateIssue()), + String.valueOf(certDTO.getCertSerialNum()) + ); + } + + results.put(certDTO.getCertName(), verificationResult); + + // 기존 자격증 찾기 + TblHelperCert existingCert = existingCerts.stream() + .filter(cert -> certDTO.getCertName().equals(cert.getCertName())) + .findFirst() + .orElse(null); + + if (existingCert != null) { + // 기존 자격증 업데이트 + existingCert.setCertNum(certDTO.getCertNum()); + existingCert.setCertDateIssue(certDTO.getCertDateIssue()); + existingCert.setCertSerialNum(certDTO.getCertSerialNum()); + } else { + // 새로운 자격증 추가 + TblHelperCert newCert = TblHelperCert.builder() + .tblHelper(tblHelper) + .certName(certDTO.getCertName()) + .certNum(certDTO.getCertNum()) + .certDateIssue(certDTO.getCertDateIssue()) + .certSerialNum(certDTO.getCertSerialNum()) + .build(); + existingCerts.add(newCert); + } + + if (verifyQnet && !"VALID".equals(verificationResult)) { + log.warn("Q-net 자격증 인증 실패 - 자격증명: {}, 번호: {}, 결과: {}", + certDTO.getCertName(), certDTO.getCertNum(), verificationResult); + } + } catch (BadRequestException e) { + results.put(certDTO.getCertName(), "VALIDATION_FAILED: " + e.getMessage()); + log.error("자격증 검증 실패 - 자격증명: {}, 오류: {}", certDTO.getCertName(), e.getMessage()); + } + } + + // 자격증 정보 DB에 저장 + helperCertRepository.saveAll(existingCerts); + + return results; + } + @Override public HelperResponse getHelperDetail(HelperDetailDTO helperDetailDTO) { TblHelper helper = helperRepository.findById(helperDetailDTO.getHelperSeq()) diff --git a/src/main/java/com/balybus/galaxy/global/config/jwt/JwtAuthenticationFilter.java b/src/main/java/com/balybus/galaxy/global/config/jwt/JwtAuthenticationFilter.java index 5610bfe2..8bd5eb16 100644 --- a/src/main/java/com/balybus/galaxy/global/config/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/com/balybus/galaxy/global/config/jwt/JwtAuthenticationFilter.java @@ -48,6 +48,11 @@ private boolean checkUri(String requestUri) { return false; } + // 1. 엑세스, 리프레시 토큰 발급 + // 2. 로그인 회원가입 로직 + // 3. 권한 ROLE -> enum + // 4. + // 쿠키 사용 @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { From fb94911a290c5d31dcd0ab13c8e8ecb06c8dabe6 Mon Sep 17 00:00:00 2001 From: mike Date: Sun, 31 Aug 2025 18:18:33 +0900 Subject: [PATCH 12/12] =?UTF-8?q?[Feat]:=20application.yml=20->=20include?= =?UTF-8?q?=EC=97=90=EC=84=9C=20oauth=20=EC=A4=91=EB=B3=B5=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 234ff52b..6bb6d740 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,7 +1,7 @@ spring: profiles: active: dev - include: db, oauth, jwt, mail, aws, oauth + include: db, oauth, jwt, mail, aws springdoc: swagger-ui: