From 07a399e0bc90786a534898e509156b2188e87cfe Mon Sep 17 00:00:00 2001 From: JuyeonLee <104489022+Juye0nLee@users.noreply.github.com> Date: Tue, 26 Nov 2024 14:33:12 +0900 Subject: [PATCH 1/7] =?UTF-8?q?=E2=9C=A8=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=EC=8B=A0=EC=B2=AD,=20=EC=A1=B0=ED=9A=8C=20=EC=8B=9C=20?= =?UTF-8?q?=EB=8F=8C=EB=B4=84=20=EB=A9=94=EB=AA=A8=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=20(#46)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * πŸ› μ‹ μ²­ λͺ©λ‘ λ°˜ν™˜ μ‹œ μ‹ μ²­ κΈ°λ³Έν‚€ λ°˜ν™˜ (#35) (#36) * πŸ› μ‹ μ²­ api μ‘λ‹΅μœΌλ‘œ applyId λ°˜ν™˜ (#39) * πŸ› μ‹ μ²­ λͺ©λ‘ λ°˜ν™˜ μ‹œ μ‹ μ²­ κΈ°λ³Έν‚€ λ°˜ν™˜ (#35) * πŸ› μ‹ μ²­ api μ‘λ‹΅μœΌλ‘œ applyId λ°˜ν™˜ (#38) * πŸ› μ‹ μ²­ λͺ©λ‘ λ°˜ν™˜ μ‹œ μ‹ μ²­ κΈ°λ³Έν‚€ λ°˜ν™˜ (#35) (#36) * ✨ μ‹ μ²­ API applyId λ°˜ν™˜ * πŸ› μ‹ μ²­ μ„ΈλΆ€ 쑰회 둜직 μˆ˜μ • (#42) * πŸ› μ‹ μ²­ λͺ©λ‘ λ°˜ν™˜ μ‹œ μ‹ μ²­ κΈ°λ³Έν‚€ λ°˜ν™˜ (#35) * πŸ› μ‹ μ²­ api μ‘λ‹΅μœΌλ‘œ applyId λ°˜ν™˜ (#38) * πŸ› μ‹ μ²­ λͺ©λ‘ λ°˜ν™˜ μ‹œ μ‹ μ²­ κΈ°λ³Έν‚€ λ°˜ν™˜ (#35) (#36) * ✨ μ‹ μ²­ API applyId λ°˜ν™˜ * πŸ› μ‹ μ²­ 쑰회 둜직 μˆ˜μ • (#41) * πŸ› μ‹ μ²­ λͺ©λ‘ λ°˜ν™˜ μ‹œ μ‹ μ²­ κΈ°λ³Έν‚€ λ°˜ν™˜ (#35) (#36) * πŸ› μ‹ μ²­ api μ‘λ‹΅μœΌλ‘œ applyId λ°˜ν™˜ (#39) * πŸ› μ‹ μ²­ λͺ©λ‘ λ°˜ν™˜ μ‹œ μ‹ μ²­ κΈ°λ³Έν‚€ λ°˜ν™˜ (#35) * πŸ› μ‹ μ²­ api μ‘λ‹΅μœΌλ‘œ applyId λ°˜ν™˜ (#38) * πŸ› μ‹ μ²­ λͺ©λ‘ λ°˜ν™˜ μ‹œ μ‹ μ²­ κΈ°λ³Έν‚€ λ°˜ν™˜ (#35) (#36) * ✨ μ‹ μ²­ API applyId λ°˜ν™˜ * πŸ› μ‹ μ²­ μ„ΈλΆ€ 쑰회 였λ₯˜ μˆ˜μ • * πŸš€ Cd νŒŒμ΄ν”„λΌμΈ μˆ˜μ • * chore: CD νŒŒμ΄ν”„λΌμΈ μˆ˜μ • * 🎨 카카였페이 approval_url 배포 λ„λ©”μΈμœΌλ‘œ μˆ˜μ • (#44) * 🎨 카카였페이 approval_url 배포 λ„λ©”μΈμœΌλ‘œ μˆ˜μ • * πŸ› μ‹ μ²­ - μ„œλ₯˜ 연관관계 μˆ˜μ • * ✨ Status에 μƒνƒœ μΆ”κ°€ * ✨ λ©”λͺ¨ μΆ”κ°€ * ✨ GetStatus λ©”μ†Œλ“œ μˆ˜μ • --------- Co-authored-by: GiHwan2 --- .github/workflows/CICD.yml | 2 +- src/main/java/com/ivory/ivory/domain/Apply.java | 9 +++++++-- src/main/java/com/ivory/ivory/domain/Status.java | 2 +- src/main/java/com/ivory/ivory/dto/ApplyDetailDto.java | 3 +++ src/main/java/com/ivory/ivory/dto/ApplyDto.java | 3 +++ src/main/java/com/ivory/ivory/service/ApplyService.java | 8 +++++++- .../java/com/ivory/ivory/service/KakaoPayService.java | 2 +- 7 files changed, 23 insertions(+), 6 deletions(-) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 8c5ca40..b84ee07 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -49,7 +49,7 @@ jobs: runs-on: self-hosted steps: - # 1. backend μ„œλΉ„μŠ€ 쀑지 + # 1. 기쑴의 μ»¨ν…Œμ΄λ„ˆλ₯Ό μ€‘μ§€μ‹œν‚΅λ‹ˆλ‹€ - name: Stop backend service run: sudo docker stop Ivory-Backend diff --git a/src/main/java/com/ivory/ivory/domain/Apply.java b/src/main/java/com/ivory/ivory/domain/Apply.java index 8c5220f..50db262 100644 --- a/src/main/java/com/ivory/ivory/domain/Apply.java +++ b/src/main/java/com/ivory/ivory/domain/Apply.java @@ -39,6 +39,9 @@ public class Apply extends BaseEntity { @Column(name="status", nullable = false) private Status status; + @Column(name="memo") + private String memo; + @ManyToOne @JoinColumn(name="member_id") private Member member; @@ -47,11 +50,11 @@ public class Apply extends BaseEntity { @JoinColumn(name="child_id") private Child child; - @OneToOne + @ManyToOne @JoinColumn(name="medical_certificate_id") private MedicalCertificate medicalCertificate; - @OneToOne + @ManyToOne @JoinColumn(name="absence_certificate_id") private AbsenceCertificate absenceCertificate; @@ -61,6 +64,7 @@ public static Apply toEntity( Long subsidy, IncomeType incomeType, Status status, + String memo, Member member, Child child, MedicalCertificate medicalCertificate, @@ -73,6 +77,7 @@ public static Apply toEntity( .subsidy(subsidy) .incomeType(incomeType) .status(status) + .memo(memo) .member(member) .child(child) .medicalCertificate(medicalCertificate) diff --git a/src/main/java/com/ivory/ivory/domain/Status.java b/src/main/java/com/ivory/ivory/domain/Status.java index 4ac0259..1349dd7 100644 --- a/src/main/java/com/ivory/ivory/domain/Status.java +++ b/src/main/java/com/ivory/ivory/domain/Status.java @@ -1,5 +1,5 @@ package com.ivory.ivory.domain; public enum Status { - YET, IN_PROGRESS, COMPLETE + YET, MATCHED, IN_PROGRESS, COMPLETE } diff --git a/src/main/java/com/ivory/ivory/dto/ApplyDetailDto.java b/src/main/java/com/ivory/ivory/dto/ApplyDetailDto.java index fd3aa62..d1b861d 100644 --- a/src/main/java/com/ivory/ivory/dto/ApplyDetailDto.java +++ b/src/main/java/com/ivory/ivory/dto/ApplyDetailDto.java @@ -19,6 +19,7 @@ public class ApplyDetailDto { private String incomeType; private String careDate; private String careTime; + private String memo; private String totalAmount; private String subsidy; private String copay; @@ -34,6 +35,7 @@ public static ApplyDetailDto from( String incomeType, String careDate, String careTime, + String memo, String totalAmount, String subsidy, String copay, @@ -49,6 +51,7 @@ public static ApplyDetailDto from( .incomeType(incomeType) .careDate(careDate) .careTime(careTime) + .memo(memo) .totalAmount(totalAmount) .subsidy(subsidy) .copay(copay) diff --git a/src/main/java/com/ivory/ivory/dto/ApplyDto.java b/src/main/java/com/ivory/ivory/dto/ApplyDto.java index 6882441..e9e97eb 100644 --- a/src/main/java/com/ivory/ivory/dto/ApplyDto.java +++ b/src/main/java/com/ivory/ivory/dto/ApplyDto.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.annotation.JsonFormat; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -28,4 +29,6 @@ public class ApplyDto { @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime endDate; + + private String memo; } diff --git a/src/main/java/com/ivory/ivory/service/ApplyService.java b/src/main/java/com/ivory/ivory/service/ApplyService.java index 6e2e2ce..574db2e 100644 --- a/src/main/java/com/ivory/ivory/service/ApplyService.java +++ b/src/main/java/com/ivory/ivory/service/ApplyService.java @@ -90,7 +90,7 @@ public CustomApiResponse applyService(ApplyDto dto, Long currentMemberId) { Status status = getNowStatus(startDate,endDate); //μ—”ν‹°ν‹° 생성 - Apply apply = Apply.toEntity(dto,totalAmount,subsidy,incomeType,status,member.get(),child.get(),medicalCertificate.get(),absenceCertificate.get()); + Apply apply = Apply.toEntity(dto,totalAmount,subsidy,incomeType,status,dto.getMemo(),member.get(),child.get(),medicalCertificate.get(),absenceCertificate.get()); //DB에 μ €μž₯ Apply newApply = serviceRepository.save(apply); @@ -193,6 +193,9 @@ public CustomApiResponse getApplyDetail(Long applyId, Long currentMemberId) { //μ„œλΉ„μŠ€ μ΄μš©μ‹œκ°„ String careTime = getCareTime(startDate,endDate); + //λŒλ΄„ λ©”λͺ¨ + String memo = apply.get().getMemo(); + //κΈ°λ³Έ μš”κΈˆ Long totalAmount = apply.get().getTotalAmount(); @@ -238,6 +241,7 @@ public CustomApiResponse getApplyDetail(Long applyId, Long currentMemberId) { incomeType.getDescription(), careDate, careTime, + memo, amountFormat(totalAmount), amountFormat(subsidy), amountFormat(copay), @@ -283,6 +287,7 @@ else if (IncomeType.C.equals(incomeType) || IncomeType.D.equals(incomeType)) { } //ν˜„μž¬ μ„œλΉ„μŠ€ μƒνƒœ 계산 λ©”μ†Œλ“œ + //TODO : MATCHED 일 λ•Œ μΆ”κ°€ 해야함 public Status getNowStatus(LocalDateTime startDate, LocalDateTime endDate) { LocalDateTime now = LocalDateTime.now(); if (now.isBefore(startDate)) { @@ -310,6 +315,7 @@ public String getCareTime(LocalDateTime startDate, LocalDateTime endDate) { public String getStatus(Status Status) { switch (Status) { case YET: return "μ„œλΉ„μŠ€ μ‹ μ²­ μ™„λ£Œ"; + case MATCHED: return "돌보미 맀칭"; case IN_PROGRESS: return "λŒλ΄„ μ„œλΉ„μŠ€ 이용 쀑"; case COMPLETE: return "이용 μ™„λ£Œ"; default: return ""; diff --git a/src/main/java/com/ivory/ivory/service/KakaoPayService.java b/src/main/java/com/ivory/ivory/service/KakaoPayService.java index d009dfd..5048f48 100644 --- a/src/main/java/com/ivory/ivory/service/KakaoPayService.java +++ b/src/main/java/com/ivory/ivory/service/KakaoPayService.java @@ -60,7 +60,7 @@ public KakaoPayReadyDto kakaoPayReady(Long applyId) { parameters.put("total_amount",copay); parameters.put("vat_amount","200"); parameters.put("tax_free_amount","0"); - parameters.put("approval_url","http://localhost:3000/apply/payments/success"); //TODO: μΆ”ν›„ 배포된 λ„λ©”μΈμœΌλ‘œ μˆ˜μ •ν•΄μ•Όν•¨ + parameters.put("approval_url","https://danpoong-ivory.vercel.app/apply/payments/success"); // 도메인 parameters.put("fail_url","http://localhost:3000/apply/payments/fail"); parameters.put("cancel_url","http://localhost:3000/apply/payments/cancel"); From 7174b9b799befc7484869a1ad10fd5bf80cb0966 Mon Sep 17 00:00:00 2001 From: JuyeonLee <104489022+Juye0nLee@users.noreply.github.com> Date: Tue, 26 Nov 2024 19:59:24 +0900 Subject: [PATCH 2/7] =?UTF-8?q?=E2=9C=A8=20=EB=94=94=ED=8F=B4=ED=8A=B8=20?= =?UTF-8?q?=EB=8F=8C=EB=B3=B4=EB=AF=B8=20=EA=B3=84=EC=A0=95=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=20(#49)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ λŒλ΄„ λͺ©λ‘ 리슀트 쑰회 κ΅¬ν˜„ * ✨ λ””ν΄νŠΈ λŒλ΄„μ΄ 계정 생성 --- .../ivory/controller/CaregiverController.java | 24 ++++++++++ .../com/ivory/ivory/domain/Authority.java | 2 +- .../com/ivory/ivory/domain/Caregiver.java | 34 ++++++++++++++ .../java/com/ivory/ivory/dto/CareListDto.java | 22 +++++++++ .../java/com/ivory/ivory/dto/TokenDto.java | 5 +- .../com/ivory/ivory/init/DataInitializer.java | 36 +++++++++++++++ .../com/ivory/ivory/jwt/TokenProvider.java | 1 + .../ivory/repository/ApplyRepository.java | 1 - .../ivory/repository/CaregiverRepository.java | 15 ++++++ .../com/ivory/ivory/service/AuthService.java | 18 +++++--- .../ivory/ivory/service/CaregiverService.java | 46 +++++++++++++++++++ .../service/CustomUserDetailsService.java | 19 ++++++++ 12 files changed, 214 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/ivory/ivory/controller/CaregiverController.java create mode 100644 src/main/java/com/ivory/ivory/domain/Caregiver.java create mode 100644 src/main/java/com/ivory/ivory/dto/CareListDto.java create mode 100644 src/main/java/com/ivory/ivory/init/DataInitializer.java create mode 100644 src/main/java/com/ivory/ivory/repository/CaregiverRepository.java create mode 100644 src/main/java/com/ivory/ivory/service/CaregiverService.java diff --git a/src/main/java/com/ivory/ivory/controller/CaregiverController.java b/src/main/java/com/ivory/ivory/controller/CaregiverController.java new file mode 100644 index 0000000..0362def --- /dev/null +++ b/src/main/java/com/ivory/ivory/controller/CaregiverController.java @@ -0,0 +1,24 @@ +package com.ivory.ivory.controller; + +import com.ivory.ivory.service.CaregiverService; +import com.ivory.ivory.util.SecurityUtil; +import com.ivory.ivory.util.response.CustomApiResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/caregivers") +@RequiredArgsConstructor +public class CaregiverController { + + private final CaregiverService caregiverService; + private final SecurityUtil securityUtil; + + @GetMapping("/list") + public ResponseEntity getCareList () { + Long currentMemberId = securityUtil.getCurrentMemberId(); + CustomApiResponse response =caregiverService.getCareList(currentMemberId); + return ResponseEntity.ok(response); + } +} diff --git a/src/main/java/com/ivory/ivory/domain/Authority.java b/src/main/java/com/ivory/ivory/domain/Authority.java index 31e7116..49a3a93 100644 --- a/src/main/java/com/ivory/ivory/domain/Authority.java +++ b/src/main/java/com/ivory/ivory/domain/Authority.java @@ -1,5 +1,5 @@ package com.ivory.ivory.domain; public enum Authority { - ROLE_USER, ROLE_ADMIN + ROLE_USER, ROLE_CAREGIVER, ROLE_ADMIN } diff --git a/src/main/java/com/ivory/ivory/domain/Caregiver.java b/src/main/java/com/ivory/ivory/domain/Caregiver.java new file mode 100644 index 0000000..c8105eb --- /dev/null +++ b/src/main/java/com/ivory/ivory/domain/Caregiver.java @@ -0,0 +1,34 @@ +package com.ivory.ivory.domain; + +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Table(name="caregiver") +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Caregiver { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name="id") + private Long id; + + @Column(name="email") + private String email; + + @Column(name="password") + private String password; + + @Enumerated(EnumType.STRING) + private Authority authority; + + public static Caregiver toEntity(String email, String password) { + return Caregiver.builder() + .email(email) + .password(password) + .authority(Authority.ROLE_CAREGIVER) + .build(); + } +} diff --git a/src/main/java/com/ivory/ivory/dto/CareListDto.java b/src/main/java/com/ivory/ivory/dto/CareListDto.java new file mode 100644 index 0000000..12443fe --- /dev/null +++ b/src/main/java/com/ivory/ivory/dto/CareListDto.java @@ -0,0 +1,22 @@ +package com.ivory.ivory.dto; + +import lombok.*; + +@Getter +@Setter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class CareListDto { + private String applyDate; + private String careDate; + private String careTime; + + public static CareListDto toCareList(String applyDate, String careDate, String careTime ) { + return CareListDto.builder() + .applyDate(applyDate) + .careDate(careDate) + .careTime(careTime) + .build(); + } +} diff --git a/src/main/java/com/ivory/ivory/dto/TokenDto.java b/src/main/java/com/ivory/ivory/dto/TokenDto.java index 330dd50..8542141 100644 --- a/src/main/java/com/ivory/ivory/dto/TokenDto.java +++ b/src/main/java/com/ivory/ivory/dto/TokenDto.java @@ -1,5 +1,6 @@ package com.ivory.ivory.dto; +import com.ivory.ivory.domain.Authority; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -10,13 +11,15 @@ @NoArgsConstructor public class TokenDto { + private String authority; private String grantType; private String accessToken; private Long accessTokenExpiresIn; private String refreshToken; @Builder - public TokenDto(String grantType, String accessToken, Long accessTokenExpiresIn, String refreshToken) { + public TokenDto(String authority, String grantType, String accessToken, Long accessTokenExpiresIn, String refreshToken) { + this.authority = authority; this.grantType = grantType; this.accessToken = accessToken; this.accessTokenExpiresIn = accessTokenExpiresIn; diff --git a/src/main/java/com/ivory/ivory/init/DataInitializer.java b/src/main/java/com/ivory/ivory/init/DataInitializer.java new file mode 100644 index 0000000..88d354e --- /dev/null +++ b/src/main/java/com/ivory/ivory/init/DataInitializer.java @@ -0,0 +1,36 @@ +package com.ivory.ivory.init; + +import com.ivory.ivory.domain.Caregiver; +import com.ivory.ivory.repository.CaregiverRepository; +import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class DataInitializer { + + private final CaregiverRepository caregiverRepository; + private final PasswordEncoder passwordEncoder; + + @PostConstruct + public void init() { + createCaregiver(); + } + + public void createCaregiver() { + if (caregiverRepository.count() == 0) { + + //λΉ„λ°€λ²ˆν˜Έ μ•”ν˜Έν™” + String encodedPassword = passwordEncoder.encode("1234"); + + Caregiver caregiver = Caregiver.toEntity( + "admin@gmail.com", + encodedPassword + ); + + caregiverRepository.save(caregiver); + } + } +} diff --git a/src/main/java/com/ivory/ivory/jwt/TokenProvider.java b/src/main/java/com/ivory/ivory/jwt/TokenProvider.java index ae666bf..c48bdf7 100644 --- a/src/main/java/com/ivory/ivory/jwt/TokenProvider.java +++ b/src/main/java/com/ivory/ivory/jwt/TokenProvider.java @@ -64,6 +64,7 @@ public TokenDto generateTokenDto(Authentication authentication) { .compact(); return TokenDto.builder() + .authority(authorities) .grantType(BEARER_TYPE) .accessToken(accessToken) .accessTokenExpiresIn(accessTokenExpiresIn.getTime()) diff --git a/src/main/java/com/ivory/ivory/repository/ApplyRepository.java b/src/main/java/com/ivory/ivory/repository/ApplyRepository.java index c982479..74172c4 100644 --- a/src/main/java/com/ivory/ivory/repository/ApplyRepository.java +++ b/src/main/java/com/ivory/ivory/repository/ApplyRepository.java @@ -12,5 +12,4 @@ public interface ApplyRepository extends JpaRepository { List findAllByChild_Id(Long childId); Optional findById (Long applyId); Apply findFirstByChild_IdOrderByCreateAt(Long childID); - } diff --git a/src/main/java/com/ivory/ivory/repository/CaregiverRepository.java b/src/main/java/com/ivory/ivory/repository/CaregiverRepository.java new file mode 100644 index 0000000..525eeac --- /dev/null +++ b/src/main/java/com/ivory/ivory/repository/CaregiverRepository.java @@ -0,0 +1,15 @@ +package com.ivory.ivory.repository; + +import com.ivory.ivory.domain.Authority; +import com.ivory.ivory.domain.Caregiver; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface CaregiverRepository extends JpaRepository { + Optional findByEmail(String username); + Authority findAuthorityByEmail(String email); +} + diff --git a/src/main/java/com/ivory/ivory/service/AuthService.java b/src/main/java/com/ivory/ivory/service/AuthService.java index bece85c..7339f33 100644 --- a/src/main/java/com/ivory/ivory/service/AuthService.java +++ b/src/main/java/com/ivory/ivory/service/AuthService.java @@ -59,25 +59,31 @@ public TokenDto login(MemberRequestDto memberRequestDto) { // 1. Login ID/PW λ₯Ό 기반으둜 AuthenticationToken 생성 UsernamePasswordAuthenticationToken authenticationToken = memberRequestDto.toAuthentication(); - // 2. μ‹€μ œλ‘œ 검증 (μ‚¬μš©μž λΉ„λ°€λ²ˆν˜Έ 체크) 이 μ΄λ£¨μ–΄μ§€λŠ” λΆ€λΆ„ - // authenticate λ©”μ„œλ“œκ°€ 싀행이 될 λ•Œ CustomUserDetailsService μ—μ„œ λ§Œλ“€μ—ˆλ˜ loadUserByUsername λ©”μ„œλ“œκ°€ 싀행됨 + // 2. μ‹€μ œλ‘œ 검증 (μ‚¬μš©μž λΉ„λ°€λ²ˆν˜Έ 체크) + // authenticate λ©”μ„œλ“œκ°€ 싀행될 λ•Œ CustomUserDetailsService의 loadUserByUsername μ‹€ν–‰ Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken); - // 3. 인증 정보λ₯Ό 기반으둜 JWT 토큰 생성 + // 3. 인증된 μ‚¬μš©μž 정보 확인 + String username = authentication.getName(); // username (email) + + String auth = authentication.getAuthorities().toString(); + + // 4. JWT 토큰 생성 TokenDto tokenDto = tokenProvider.generateTokenDto(authentication); - // 4. RefreshToken μ €μž₯ + // 5. RefreshToken μ €μž₯ RefreshToken refreshToken = RefreshToken.builder() - .key(authentication.getName()) + .key(username) .value(tokenDto.getRefreshToken()) .build(); refreshTokenRepository.save(refreshToken); - // 5. 토큰 λ°œκΈ‰ + // 6. 토큰 λ°œκΈ‰ return tokenDto; } + @Transactional public TokenDto reissue(TokenRequestDto tokenRequestDto) { // 1. Refresh Token 검증 diff --git a/src/main/java/com/ivory/ivory/service/CaregiverService.java b/src/main/java/com/ivory/ivory/service/CaregiverService.java new file mode 100644 index 0000000..ecd1c1d --- /dev/null +++ b/src/main/java/com/ivory/ivory/service/CaregiverService.java @@ -0,0 +1,46 @@ +package com.ivory.ivory.service; + +import com.ivory.ivory.domain.Apply; +import com.ivory.ivory.domain.Authority; +import com.ivory.ivory.domain.Caregiver; +import com.ivory.ivory.dto.ApplyListDto; +import com.ivory.ivory.dto.CareListDto; +import com.ivory.ivory.repository.ApplyRepository; +import com.ivory.ivory.repository.CaregiverRepository; +import com.ivory.ivory.util.response.CustomApiResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.web.server.ResponseStatusException; + +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +@Service +@RequiredArgsConstructor +public class CaregiverService { + + private final ApplyRepository applyRepository; + private final ApplyService applyService; + private final CaregiverRepository caregiverRepository; + + public CustomApiResponse getCareList(Long currentMemberId) { + List applyList = applyRepository.findAll(); + List careListDto = new ArrayList<>(); + applyList.forEach(apply -> { + //μ„œλΉ„μŠ€ μ‹ μ²­ λ‚ μ§œ + String applyDate = applyService.getApplyDate(apply.getCreateAt()); + + //μ„œλΉ„μŠ€ 이용 λ‚ μ§œ + String careDate = apply.getStartDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); + + //μ„œλΉ„μŠ€ 이용 μ‹œκ°„ + String careTime = applyService.getCareTime(apply.getStartDate(),apply.getEndDate()); + + careListDto.add(CareListDto.toCareList(applyDate,careDate,careTime)); + }); + return CustomApiResponse.createSuccess(HttpStatus.OK.value(),"λŒλ΄„ ν™œλ™ λͺ©λ‘μ΄ μ‘°νšŒλ˜μ—ˆμŠ΅λ‹ˆλ‹€.",careListDto); + } +} diff --git a/src/main/java/com/ivory/ivory/service/CustomUserDetailsService.java b/src/main/java/com/ivory/ivory/service/CustomUserDetailsService.java index 78da97e..dce6777 100644 --- a/src/main/java/com/ivory/ivory/service/CustomUserDetailsService.java +++ b/src/main/java/com/ivory/ivory/service/CustomUserDetailsService.java @@ -1,6 +1,8 @@ package com.ivory.ivory.service; +import com.ivory.ivory.domain.Caregiver; import com.ivory.ivory.domain.Member; +import com.ivory.ivory.repository.CaregiverRepository; import com.ivory.ivory.repository.MemberRepository; import jakarta.transaction.Transactional; import java.util.Collections; @@ -18,15 +20,21 @@ public class CustomUserDetailsService implements UserDetailsService { private final MemberRepository memberRepository; + private final CaregiverRepository caregiverRepository; @Override @Transactional public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + // Member ν…Œμ΄λΈ”μ—μ„œ 이메일을 검색 return memberRepository.findByEmail(username) .map(this::createUserDetails) + // Member ν…Œμ΄λΈ”μ— μ—†μœΌλ©΄ Caregiver ν…Œμ΄λΈ”μ—μ„œ 이메일 검색 + .or(() -> caregiverRepository.findByEmail(username).map(this::createUserDetails)) + // λ‘˜ λ‹€ 없을 경우 μ˜ˆμ™Έ λ°œμƒ .orElseThrow(() -> new UsernameNotFoundException(username + " -> λ°μ΄ν„°λ² μ΄μŠ€μ—μ„œ 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.")); } + // DB 에 User 값이 μ‘΄μž¬ν•œλ‹€λ©΄ UserDetails 객체둜 λ§Œλ“€μ–΄μ„œ 리턴 private UserDetails createUserDetails(Member member) { GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(member.getAuthority().toString()); @@ -37,4 +45,15 @@ private UserDetails createUserDetails(Member member) { Collections.singleton(grantedAuthority) ); } + + private UserDetails createUserDetails(Caregiver caregiver) { + GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(caregiver.getAuthority().toString()); + + return new User( + String.valueOf(caregiver.getId()), + caregiver.getPassword(), + Collections.singleton(grantedAuthority) + ); + } + } \ No newline at end of file From ecba518cbb2de15cf88174f006c063dfd34f0a25 Mon Sep 17 00:00:00 2001 From: JuyeonLee <104489022+Juye0nLee@users.noreply.github.com> Date: Tue, 26 Nov 2024 20:05:26 +0900 Subject: [PATCH 3/7] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20init=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=8F=99=20(#50)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ λŒλ΄„ λͺ©λ‘ 리슀트 쑰회 κ΅¬ν˜„ * ✨ λ””ν΄νŠΈ λŒλ΄„μ΄ 계정 생성 * ♻️ Init νŒ¨ν‚€μ§€ 이동 --- .../ivory/util/init/DataInitializer.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/main/java/com/ivory/ivory/util/init/DataInitializer.java diff --git a/src/main/java/com/ivory/ivory/util/init/DataInitializer.java b/src/main/java/com/ivory/ivory/util/init/DataInitializer.java new file mode 100644 index 0000000..78a4acb --- /dev/null +++ b/src/main/java/com/ivory/ivory/util/init/DataInitializer.java @@ -0,0 +1,36 @@ +package com.ivory.ivory.util.init; + +import com.ivory.ivory.domain.Caregiver; +import com.ivory.ivory.repository.CaregiverRepository; +import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class DataInitializer { + + private final CaregiverRepository caregiverRepository; + private final PasswordEncoder passwordEncoder; + + @PostConstruct + public void init() { + createCaregiver(); + } + + public void createCaregiver() { + if (caregiverRepository.count() == 0) { + + //λΉ„λ°€λ²ˆν˜Έ μ•”ν˜Έν™” + String encodedPassword = passwordEncoder.encode("1234"); + + Caregiver caregiver = Caregiver.toEntity( + "admin@gmail.com", + encodedPassword + ); + + caregiverRepository.save(caregiver); + } + } +} From 6eb32e7c0b6dbf9405b1b9e853ad012ad2fde580 Mon Sep 17 00:00:00 2001 From: JuyeonLee <104489022+Juye0nLee@users.noreply.github.com> Date: Tue, 26 Nov 2024 20:06:31 +0900 Subject: [PATCH 4/7] =?UTF-8?q?Revert=20"=E2=99=BB=EF=B8=8F=20init=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=8F=99=20(#50)"=20(#5?= =?UTF-8?q?1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit ecba518cbb2de15cf88174f006c063dfd34f0a25. --- .../ivory/util/init/DataInitializer.java | 36 ------------------- 1 file changed, 36 deletions(-) delete mode 100644 src/main/java/com/ivory/ivory/util/init/DataInitializer.java diff --git a/src/main/java/com/ivory/ivory/util/init/DataInitializer.java b/src/main/java/com/ivory/ivory/util/init/DataInitializer.java deleted file mode 100644 index 78a4acb..0000000 --- a/src/main/java/com/ivory/ivory/util/init/DataInitializer.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.ivory.ivory.util.init; - -import com.ivory.ivory.domain.Caregiver; -import com.ivory.ivory.repository.CaregiverRepository; -import jakarta.annotation.PostConstruct; -import lombok.RequiredArgsConstructor; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Component; - -@Component -@RequiredArgsConstructor -public class DataInitializer { - - private final CaregiverRepository caregiverRepository; - private final PasswordEncoder passwordEncoder; - - @PostConstruct - public void init() { - createCaregiver(); - } - - public void createCaregiver() { - if (caregiverRepository.count() == 0) { - - //λΉ„λ°€λ²ˆν˜Έ μ•”ν˜Έν™” - String encodedPassword = passwordEncoder.encode("1234"); - - Caregiver caregiver = Caregiver.toEntity( - "admin@gmail.com", - encodedPassword - ); - - caregiverRepository.save(caregiver); - } - } -} From 445e409f577a2fd1bffa5442ab132b2607547b27 Mon Sep 17 00:00:00 2001 From: JuyeonLee <104489022+Juye0nLee@users.noreply.github.com> Date: Wed, 27 Nov 2024 01:45:33 +0900 Subject: [PATCH 5/7] =?UTF-8?q?=E2=9C=A8=20=EB=8F=8C=EB=B4=84=EC=9D=B4=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20API=20=EA=B5=AC=ED=98=84=20(#52)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✨ λŒλ΄„ λ‚΄μš© 상세 쑰회 api 개발 * ✨ λŒλ΄„ 수락 μ‹œ μƒνƒœλ³€κ²½ * ✨ μˆ˜λ½ν•œ λŒλ΄„ ν™œλ™ 1개 쑰회 * ✨ Apply - Caregiver 연관관계 맀핑 --- .../ivory/controller/CaregiverController.java | 23 ++++ .../java/com/ivory/ivory/domain/Apply.java | 9 +- .../com/ivory/ivory/domain/Caregiver.java | 8 +- .../com/ivory/ivory/dto/CareDetailDto.java | 49 +++++++ .../java/com/ivory/ivory/dto/CareDto.java | 28 ++++ .../java/com/ivory/ivory/dto/CareListDto.java | 4 +- .../ivory/repository/ApplyRepository.java | 3 + .../com/ivory/ivory/service/ApplyService.java | 19 +-- .../ivory/ivory/service/CaregiverService.java | 128 +++++++++++++++++- 9 files changed, 256 insertions(+), 15 deletions(-) create mode 100644 src/main/java/com/ivory/ivory/dto/CareDetailDto.java create mode 100644 src/main/java/com/ivory/ivory/dto/CareDto.java diff --git a/src/main/java/com/ivory/ivory/controller/CaregiverController.java b/src/main/java/com/ivory/ivory/controller/CaregiverController.java index 0362def..de7e60d 100644 --- a/src/main/java/com/ivory/ivory/controller/CaregiverController.java +++ b/src/main/java/com/ivory/ivory/controller/CaregiverController.java @@ -21,4 +21,27 @@ public ResponseEntity getCareList () { CustomApiResponse response =caregiverService.getCareList(currentMemberId); return ResponseEntity.ok(response); } + + @GetMapping("/{applyId}") + public ResponseEntity getCareDetail(@PathVariable Long applyId) { + Long currentMemberId = securityUtil.getCurrentMemberId(); + CustomApiResponse response = caregiverService.getCareDetail(currentMemberId,applyId); + return ResponseEntity.ok(response); + } + + @PostMapping("/{applyId}") + public ResponseEntity AcceptCare (@PathVariable Long applyId) { + Long currentMemberId = securityUtil.getCurrentMemberId(); + CustomApiResponse response = caregiverService.AcceptCare(currentMemberId,applyId); + return ResponseEntity.ok(response); + } + + @GetMapping() + public ResponseEntity getMatchedCare() { + Long currentMemberId = securityUtil.getCurrentMemberId(); + CustomApiResponse response = caregiverService.getMatchedCare(currentMemberId); + return ResponseEntity.ok(response); + } + + } diff --git a/src/main/java/com/ivory/ivory/domain/Apply.java b/src/main/java/com/ivory/ivory/domain/Apply.java index 50db262..6555917 100644 --- a/src/main/java/com/ivory/ivory/domain/Apply.java +++ b/src/main/java/com/ivory/ivory/domain/Apply.java @@ -11,6 +11,7 @@ @Builder @Table(name="apply") @Getter +@Setter @NoArgsConstructor @AllArgsConstructor public class Apply extends BaseEntity { @@ -58,6 +59,10 @@ public class Apply extends BaseEntity { @JoinColumn(name="absence_certificate_id") private AbsenceCertificate absenceCertificate; + @ManyToOne + @JoinColumn(name="caregiver_id") + private Caregiver caregiver; + public static Apply toEntity( ApplyDto service, Long totalAmount, @@ -68,7 +73,8 @@ public static Apply toEntity( Member member, Child child, MedicalCertificate medicalCertificate, - AbsenceCertificate absenceCertificate + AbsenceCertificate absenceCertificate, + Caregiver caregiver ) { return Apply.builder() .startDate(service.getStartDate()) @@ -82,6 +88,7 @@ public static Apply toEntity( .child(child) .medicalCertificate(medicalCertificate) .absenceCertificate(absenceCertificate) + .caregiver(caregiver) .build(); } } diff --git a/src/main/java/com/ivory/ivory/domain/Caregiver.java b/src/main/java/com/ivory/ivory/domain/Caregiver.java index c8105eb..129cd68 100644 --- a/src/main/java/com/ivory/ivory/domain/Caregiver.java +++ b/src/main/java/com/ivory/ivory/domain/Caregiver.java @@ -11,7 +11,13 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Caregiver { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "caregiver_seq") + @SequenceGenerator( + name = "caregiver_seq", // μ‹œν€€μŠ€ μ œλ„ˆλ ˆμ΄ν„° 이름 + sequenceName = "caregiver_sequence", // μ‹€μ œ λ°μ΄ν„°λ² μ΄μŠ€ μ‹œν€€μŠ€ 이름 + initialValue = 100, // μ‹œμž‘ κ°’ + allocationSize = 1 // 증가 κ°’ + ) @Column(name="id") private Long id; diff --git a/src/main/java/com/ivory/ivory/dto/CareDetailDto.java b/src/main/java/com/ivory/ivory/dto/CareDetailDto.java new file mode 100644 index 0000000..a31f18b --- /dev/null +++ b/src/main/java/com/ivory/ivory/dto/CareDetailDto.java @@ -0,0 +1,49 @@ +package com.ivory.ivory.dto; + +import lombok.*; + +import java.time.LocalDate; + +@Getter +@Setter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class CareDetailDto { + private String applyDate; + private String careDate; + private String careTime; + private String memo; + private String childName; + private String birthDate; + private Long age; + private String diagnosisName; + private String diagnosisContent; + private String image; + + public static CareDetailDto from ( + String applyDate, + String careDate, + String careTime, + String memo, + String childName, + String birthDate, + Long age, + String diagnosisName, + String diagnosisContent, + String image) { + return CareDetailDto.builder() + .applyDate(applyDate) + .careDate(careDate) + .careTime(careTime) + .memo(memo) + .childName(childName) + .birthDate(birthDate) + .age(age) + .diagnosisName(diagnosisName) + .diagnosisContent(diagnosisContent) + .image(image) + .build(); + } +} + diff --git a/src/main/java/com/ivory/ivory/dto/CareDto.java b/src/main/java/com/ivory/ivory/dto/CareDto.java new file mode 100644 index 0000000..9eca291 --- /dev/null +++ b/src/main/java/com/ivory/ivory/dto/CareDto.java @@ -0,0 +1,28 @@ +package com.ivory.ivory.dto; + +import lombok.*; + +@Getter +@Setter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class CareDto { + private Long id; + private String careDate; + private String careTime; + private String childName; + private Long age; + private String image; + + public static CareDto of(Long id, String careDate, String careTime, String childName, Long age, String image) { + return CareDto.builder() + .id(id) + .careDate(careDate) + .careTime(careTime) + .childName(childName) + .age(age) + .image(image) + .build(); + } +} diff --git a/src/main/java/com/ivory/ivory/dto/CareListDto.java b/src/main/java/com/ivory/ivory/dto/CareListDto.java index 12443fe..69d7634 100644 --- a/src/main/java/com/ivory/ivory/dto/CareListDto.java +++ b/src/main/java/com/ivory/ivory/dto/CareListDto.java @@ -8,12 +8,14 @@ @AllArgsConstructor @NoArgsConstructor public class CareListDto { + private Long applyId; private String applyDate; private String careDate; private String careTime; - public static CareListDto toCareList(String applyDate, String careDate, String careTime ) { + public static CareListDto toCareList(Long applyId, String applyDate, String careDate, String careTime ) { return CareListDto.builder() + .applyId(applyId) .applyDate(applyDate) .careDate(careDate) .careTime(careTime) diff --git a/src/main/java/com/ivory/ivory/repository/ApplyRepository.java b/src/main/java/com/ivory/ivory/repository/ApplyRepository.java index 74172c4..54f8338 100644 --- a/src/main/java/com/ivory/ivory/repository/ApplyRepository.java +++ b/src/main/java/com/ivory/ivory/repository/ApplyRepository.java @@ -1,6 +1,7 @@ package com.ivory.ivory.repository; import com.ivory.ivory.domain.Apply; +import com.ivory.ivory.domain.Status; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -12,4 +13,6 @@ public interface ApplyRepository extends JpaRepository { List findAllByChild_Id(Long childId); Optional findById (Long applyId); Apply findFirstByChild_IdOrderByCreateAt(Long childID); + Optional findFirstByStatusOrderByCreateAtDesc(Status status); + } diff --git a/src/main/java/com/ivory/ivory/service/ApplyService.java b/src/main/java/com/ivory/ivory/service/ApplyService.java index 574db2e..79375df 100644 --- a/src/main/java/com/ivory/ivory/service/ApplyService.java +++ b/src/main/java/com/ivory/ivory/service/ApplyService.java @@ -87,10 +87,12 @@ public CustomApiResponse applyService(ApplyDto dto, Long currentMemberId) { subsidy = getSubsidy(incomeType,age,totalAmount); //μ„œλΉ„μŠ€ μƒνƒœ 계산 - Status status = getNowStatus(startDate,endDate); + Status status = Status.YET; + + Caregiver caregiver = null; //μ—”ν‹°ν‹° 생성 - Apply apply = Apply.toEntity(dto,totalAmount,subsidy,incomeType,status,dto.getMemo(),member.get(),child.get(),medicalCertificate.get(),absenceCertificate.get()); + Apply apply = Apply.toEntity(dto,totalAmount,subsidy,incomeType,status,dto.getMemo(),member.get(),child.get(),medicalCertificate.get(),absenceCertificate.get(),caregiver); //DB에 μ €μž₯ Apply newApply = serviceRepository.save(apply); @@ -140,7 +142,7 @@ public CustomApiResponse getApplyList(Long childId, Long currentMemberId) { String careTime = getCareTime(apply.getStartDate(),apply.getEndDate()); //호좜 μ‹œμ μ˜ μ„œλΉ„μŠ€ μƒνƒœ 쑰회 - Status serviceStatus = getNowStatus(apply.getStartDate(),apply.getEndDate()); + Status serviceStatus = getNowStatus(apply.getStartDate(),apply.getEndDate(),apply.getStatus()); String status = getStatus(serviceStatus); applyListDto.add(ApplyListDto.from(id,name,applyDate,careDate,careTime,status)); @@ -206,7 +208,7 @@ public CustomApiResponse getApplyDetail(Long applyId, Long currentMemberId) { Long copay = totalAmount - subsidy; //호좜 μ‹œμ μ˜ μƒνƒœ - Status nowStatus = getNowStatus(startDate,endDate); + Status nowStatus = getNowStatus(startDate,endDate,apply.get().getStatus()); String status = getStatus(nowStatus); //μ§„λ‹¨μ„œ κ΄€λ ¨ 정보 @@ -287,12 +289,13 @@ else if (IncomeType.C.equals(incomeType) || IncomeType.D.equals(incomeType)) { } //ν˜„μž¬ μ„œλΉ„μŠ€ μƒνƒœ 계산 λ©”μ†Œλ“œ - //TODO : MATCHED 일 λ•Œ μΆ”κ°€ 해야함 - public Status getNowStatus(LocalDateTime startDate, LocalDateTime endDate) { + public Status getNowStatus(LocalDateTime startDate, LocalDateTime endDate,Status status) { LocalDateTime now = LocalDateTime.now(); - if (now.isBefore(startDate)) { + if (now.isBefore(startDate) && status.equals(Status.YET)) { return Status.YET; - } else if (!now.isAfter(endDate)) { + } else if (now.isBefore(endDate) && status.equals(Status.MATCHED)) { + return Status.MATCHED; + } else if (!now.isAfter(endDate) && status.equals(Status.MATCHED)) { return Status.IN_PROGRESS; } else { return Status.COMPLETE; diff --git a/src/main/java/com/ivory/ivory/service/CaregiverService.java b/src/main/java/com/ivory/ivory/service/CaregiverService.java index ecd1c1d..100ade0 100644 --- a/src/main/java/com/ivory/ivory/service/CaregiverService.java +++ b/src/main/java/com/ivory/ivory/service/CaregiverService.java @@ -1,18 +1,23 @@ package com.ivory.ivory.service; -import com.ivory.ivory.domain.Apply; -import com.ivory.ivory.domain.Authority; -import com.ivory.ivory.domain.Caregiver; +import com.ivory.ivory.domain.*; import com.ivory.ivory.dto.ApplyListDto; +import com.ivory.ivory.dto.CareDetailDto; +import com.ivory.ivory.dto.CareDto; import com.ivory.ivory.dto.CareListDto; import com.ivory.ivory.repository.ApplyRepository; import com.ivory.ivory.repository.CaregiverRepository; +import com.ivory.ivory.repository.ChildRepository; import com.ivory.ivory.util.response.CustomApiResponse; +import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; +import org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.web.server.ResponseStatusException; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; @@ -25,11 +30,18 @@ public class CaregiverService { private final ApplyRepository applyRepository; private final ApplyService applyService; private final CaregiverRepository caregiverRepository; + private final ChildRepository childRepository; + private final ChildService childService; public CustomApiResponse getCareList(Long currentMemberId) { + Optional caregiver = caregiverRepository.findById(currentMemberId); + if(caregiver.isEmpty()) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST,"돌보미만 μ‘°νšŒκ°€ κ°€λŠ₯ν•©λ‹ˆλ‹€."); + } List applyList = applyRepository.findAll(); List careListDto = new ArrayList<>(); applyList.forEach(apply -> { + Long applyId = apply.getId(); //μ„œλΉ„μŠ€ μ‹ μ²­ λ‚ μ§œ String applyDate = applyService.getApplyDate(apply.getCreateAt()); @@ -39,8 +51,116 @@ public CustomApiResponse getCareList(Long currentMemberId) { //μ„œλΉ„μŠ€ 이용 μ‹œκ°„ String careTime = applyService.getCareTime(apply.getStartDate(),apply.getEndDate()); - careListDto.add(CareListDto.toCareList(applyDate,careDate,careTime)); + careListDto.add(CareListDto.toCareList(applyId,applyDate,careDate,careTime)); }); return CustomApiResponse.createSuccess(HttpStatus.OK.value(),"λŒλ΄„ ν™œλ™ λͺ©λ‘μ΄ μ‘°νšŒλ˜μ—ˆμŠ΅λ‹ˆλ‹€.",careListDto); } + + public CustomApiResponse getCareDetail(Long currentMemberId, Long applyId) { + Optional caregiver = caregiverRepository.findById(currentMemberId); + if(caregiver.isEmpty()) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST,"돌보미만 μ‘°νšŒκ°€ κ°€λŠ₯ν•©λ‹ˆλ‹€."); + } + + Optional apply = applyRepository.findById(applyId); + if (apply.isEmpty()) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND,"μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” μ‹ μ²­ λ‚΄μ—­μž…λ‹ˆλ‹€."); + } + Optional child = childRepository.findById(apply.get().getChild().getId()); + //μ‹ μ²­ λ‚ μ§œ + String applyDate = applyService.getApplyDate(apply.get().getCreateAt()); + //이용 λ‚ μ§œ + String careDate = apply.get().getStartDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); + //이용 μ‹œκ°„ + String careTime = applyService.getCareTime(apply.get().getStartDate(),apply.get().getEndDate()); + //λŒλ΄„ λ©”λͺ¨ + String memo = apply.get().getMemo(); + //아이 이름 + String childName = child.get().getName(); + //아이 생년월일 + String birthDate = child.get().getBirth().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); + //λ‚˜μ΄ + Long age = childService.calculateAge(child.get().getBirth(), LocalDate.now()); + //아이 진단λͺ… + String diagnosisName = apply.get().getMedicalCertificate().getDisease().getName(); + //μ§„λ£Œ λ‚΄μš© + String diagnosisContent = apply.get().getMedicalCertificate().getDiagnosisContent(); + //아이 사진 + String image = child.get().getImage(); + + //응닡 생성 + CareDetailDto careDetailDto = CareDetailDto.from( + applyDate, + careDate, + careTime, + memo, + childName, + birthDate, + age, + diagnosisName, + diagnosisContent, + image + ); + return CustomApiResponse.createSuccess(HttpStatus.OK.value(),"λŒλ΄„ λ‚΄μš©μ΄ 상세 μ‘°νšŒλ˜μ—ˆμŠ΅λ‹ˆλ‹€.",careDetailDto); + } + + //λŒλ΄„ 수락 + //TODO : μ†ŒμΌ“ν†΅μ‹  + @Transactional + public CustomApiResponse AcceptCare(Long currentMemberId, Long applyId) { + Optional caregiver = caregiverRepository.findById(currentMemberId); + //μ‹ μ²­ λ‚΄μ—­ 쑰회 + Optional applyOptional = applyRepository.findById(applyId); + if (applyOptional.isEmpty()) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” μ‹ μ²­ λ‚΄μ—­μž…λ‹ˆλ‹€."); + } + + Apply apply = applyOptional.get(); + + //μƒνƒœ λ³€κ²½ + if (apply.getStatus() == Status.YET) { + apply.setStatus(Status.MATCHED); //μƒνƒœλ³€κ²½ + apply.setCaregiver(caregiver.get()); //λŒλ΄„μ΄ 연관관계 λ§ΊκΈ° + } else { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "이미 맀칭된 λŒλ΄„μž…λ‹ˆλ‹€."); + } + + applyRepository.save(apply); + + return CustomApiResponse.createSuccess(HttpStatus.OK.value(), "λŒλ΄„μ΄ 맀칭 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.", null); + } + + + public CustomApiResponse getMatchedCare(Long currentMemberId) { + Optional caregiver = caregiverRepository.findById(currentMemberId); + if(caregiver.isEmpty()) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST,"돌보미만 μ‘°νšŒκ°€ κ°€λŠ₯ν•©λ‹ˆλ‹€."); + } + Optional apply = applyRepository.findFirstByStatusOrderByCreateAtDesc(Status.MATCHED); + if(apply.isEmpty()) { + return CustomApiResponse.createSuccess(HttpStatus.OK.value(), "아직 맀칭된 λŒλ΄„ ν™œλ™μ΄ μ—†μŠ΅λ‹ˆλ‹€.", null); + } + Optional child = childRepository.findById(apply.get().getChild().getId()); + + //κΈ°λ³Έν‚€ + Long applyId = apply.get().getId(); + + //λŒλ΄„ λ‚ μ§œ + String careDate = apply.get().getStartDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); + + //λŒλ΄„ μ‹œκ°„ + String careTime = applyService.getCareTime(apply.get().getStartDate(),apply.get().getEndDate()); + + //아이 이름 + String childName = child.get().getName(); + + //아이 λ‚˜μ΄ + Long age = childService.calculateAge(child.get().getBirth(), LocalDate.now()); + + //아이 사진 + String image = child.get().getImage(); + + CareDto careDto = CareDto.of(applyId,careDate,careTime,childName,age,image); + return CustomApiResponse.createSuccess(HttpStatus.OK.value(), "맀칭된 λŒλ΄„ ν™œλ™μ΄ 쑰회 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.",careDto); + } } From 2419b09d7c5daab000e42ee59329f11b41166078 Mon Sep 17 00:00:00 2001 From: GiHwan2 Date: Thu, 28 Nov 2024 00:26:28 +0900 Subject: [PATCH 6/7] =?UTF-8?q?feat:=20=EB=8F=8C=EB=B3=B4=EB=AF=B8=20?= =?UTF-8?q?=EB=A7=A4=EC=B9=AD=20=EC=95=8C=EB=A6=BC=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 ++ .../ivory/ivory/config/DevSecurityConfig.java | 2 +- .../ivory/ivory/config/WebSocketConfig.java | 38 +++++++++++++++++++ .../ivory/ivory/service/CaregiverService.java | 30 ++++++++++----- src/main/resources/application-dev.yml | 6 ++- src/main/resources/application.yml | 7 +--- 6 files changed, 69 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/ivory/ivory/config/WebSocketConfig.java diff --git a/build.gradle b/build.gradle index c721ef9..1ff647a 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,9 @@ dependencies { implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' + //Web Socket + implementation 'org.springframework.boot:spring-boot-starter-websocket' + //jwt implementation 'io.jsonwebtoken:jjwt-api:0.11.5' implementation 'io.jsonwebtoken:jjwt-impl:0.11.5' diff --git a/src/main/java/com/ivory/ivory/config/DevSecurityConfig.java b/src/main/java/com/ivory/ivory/config/DevSecurityConfig.java index 5d7cff4..584fb0c 100644 --- a/src/main/java/com/ivory/ivory/config/DevSecurityConfig.java +++ b/src/main/java/com/ivory/ivory/config/DevSecurityConfig.java @@ -61,7 +61,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { ).permitAll() // 인증 없이 ν—ˆμš©ν•  μΆ”κ°€ 경둜 - .requestMatchers("/api/v1/auth/**","/api/v1/apply/payments/**").permitAll() //카카였페이 401μ—λŸ¬ λ•Œλ¬Έμ—,,,일단은,, + .requestMatchers("/api/v1/auth/**","/api/v1/apply/payments/**","/ws/**").permitAll() // λ‚˜λ¨Έμ§€ μš”μ²­μ€ 인증 ν•„μš” .anyRequest().authenticated() diff --git a/src/main/java/com/ivory/ivory/config/WebSocketConfig.java b/src/main/java/com/ivory/ivory/config/WebSocketConfig.java new file mode 100644 index 0000000..7cd1ee3 --- /dev/null +++ b/src/main/java/com/ivory/ivory/config/WebSocketConfig.java @@ -0,0 +1,38 @@ +package com.ivory.ivory.config; + + +import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.simp.config.MessageBrokerRegistry; +import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; +import org.springframework.web.socket.config.annotation.StompEndpointRegistry; +import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; + +@Configuration +@EnableWebSocketMessageBroker +public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { + + @Override + public void configureMessageBroker(MessageBrokerRegistry registry) { + // ν΄λΌμ΄μ–ΈνŠΈκ°€ ꡬ독할 μ—”λ“œν¬μΈνŠΈ + registry.enableSimpleBroker("/topic"); + // ν΄λΌμ΄μ–ΈνŠΈκ°€ λ©”μ‹œμ§€λ₯Ό 보낼 μ—”λ“œν¬μΈνŠΈ + registry.setApplicationDestinationPrefixes("/app"); + } + + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { + // WebSocket μ—°κ²° μ—”λ“œν¬μΈνŠΈ + registry.addEndpoint("/ws") + .setAllowedOriginPatterns( + "*" + ); + registry.addEndpoint("/ws") + .setAllowedOriginPatterns( + "https://ivorygroup.click", + "https://danpoong-ivory.vercel.app", + "http://localhost:3000" + ) + .withSockJS(); // SockJS 지원 + } + +} \ No newline at end of file diff --git a/src/main/java/com/ivory/ivory/service/CaregiverService.java b/src/main/java/com/ivory/ivory/service/CaregiverService.java index 100ade0..a7f955b 100644 --- a/src/main/java/com/ivory/ivory/service/CaregiverService.java +++ b/src/main/java/com/ivory/ivory/service/CaregiverService.java @@ -1,7 +1,6 @@ package com.ivory.ivory.service; import com.ivory.ivory.domain.*; -import com.ivory.ivory.dto.ApplyListDto; import com.ivory.ivory.dto.CareDetailDto; import com.ivory.ivory.dto.CareDto; import com.ivory.ivory.dto.CareListDto; @@ -11,13 +10,12 @@ import com.ivory.ivory.util.response.CustomApiResponse; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; -import org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties; import org.springframework.http.HttpStatus; +import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.stereotype.Service; import org.springframework.web.server.ResponseStatusException; import java.time.LocalDate; -import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; @@ -32,6 +30,7 @@ public class CaregiverService { private final CaregiverRepository caregiverRepository; private final ChildRepository childRepository; private final ChildService childService; + private final SimpMessagingTemplate messagingTemplate; public CustomApiResponse getCareList(Long currentMemberId) { Optional caregiver = caregiverRepository.findById(currentMemberId); @@ -105,11 +104,16 @@ public CustomApiResponse getCareDetail(Long currentMemberId, Long applyId) { } //λŒλ΄„ 수락 - //TODO : μ†ŒμΌ“ν†΅μ‹  @Transactional public CustomApiResponse AcceptCare(Long currentMemberId, Long applyId) { Optional caregiver = caregiverRepository.findById(currentMemberId); - //μ‹ μ²­ λ‚΄μ—­ 쑰회 + + String caregiverName = "κΉ€λŒλ΄„"; + + if (caregiver.isEmpty()) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” λŒλ³΄λ―Έμž…λ‹ˆλ‹€."); + } + Optional applyOptional = applyRepository.findById(applyId); if (applyOptional.isEmpty()) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, "μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” μ‹ μ²­ λ‚΄μ—­μž…λ‹ˆλ‹€."); @@ -117,17 +121,25 @@ public CustomApiResponse AcceptCare(Long currentMemberId, Long applyId) { Apply apply = applyOptional.get(); - //μƒνƒœ λ³€κ²½ + // μƒνƒœ λ³€κ²½ if (apply.getStatus() == Status.YET) { - apply.setStatus(Status.MATCHED); //μƒνƒœλ³€κ²½ - apply.setCaregiver(caregiver.get()); //λŒλ΄„μ΄ 연관관계 λ§ΊκΈ° + apply.setStatus(Status.MATCHED); + apply.setCaregiver(caregiver.get()); } else { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "이미 맀칭된 λŒλ΄„μž…λ‹ˆλ‹€."); } applyRepository.save(apply); - return CustomApiResponse.createSuccess(HttpStatus.OK.value(), "λŒλ΄„μ΄ 맀칭 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.", null); + // μ‚¬μš©μžμ—κ²Œ μ•Œλ¦Ό 전솑 + String notificationMessage = String.format("돌보미 %sλ‹˜μ΄ 신청을 μˆ˜λ½ν–ˆμŠ΅λ‹ˆλ‹€.", caregiverName); + + messagingTemplate.convertAndSend( + "/topic/notifications/users/" + apply.getMember().getId().toString(), // λͺ¨λ“  κ΅¬λ…μžκ°€ 받을 수 μžˆλŠ” λΈŒλ‘œλ“œμΊμŠ€νŠΈ 경둜 + notificationMessage + ); + + return CustomApiResponse.createSuccess(HttpStatus.OK.value(), "λŒλ΄„μ΄ λ§€μΉ­λ˜μ—ˆμŠ΅λ‹ˆλ‹€.", null); } diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 228b603..5ca63c9 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -13,5 +13,9 @@ logging: hibernate: SQL: debug type: trace + springframework: + web: + socket: DEBUG + security: DEBUG com: - ivory.ivory: debug \ No newline at end of file + ivory.ivory: debug diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 9505a56..0280f1f 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -29,14 +29,9 @@ ocr: api: secret-key: ${OCR_API_SECRET} url: ${OCR_API_URL} - template-ids: ${OCR_TEMPLATE_IDS} kakaopay: secretKey: ${KAKAOPAY_SECRET_KEY} cid: ${CID} jwt: - secret: ${JWT_SECRET} - -swagger: - server: - url: http://localhost:8080 \ No newline at end of file + secret: ${JWT_SECRET} \ No newline at end of file From 7a797e4083c2cd16622aaeba0045cb88b9baf062 Mon Sep 17 00:00:00 2001 From: GiHwan2 Date: Thu, 28 Nov 2024 00:47:53 +0900 Subject: [PATCH 7/7] =?UTF-8?q?feat:=20=EB=8B=A4=EC=96=91=ED=95=9C=20?= =?UTF-8?q?=EC=9C=A0=ED=98=95=20=EC=A7=84=EB=8B=A8=EC=84=9C=20=EC=97=85?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.dev.yml | 2 + docker-compose.prod.yml | 2 + .../ivory/domain/MedicalCertificate.java | 10 +-- .../com/ivory/ivory/dto/CareDetailDto.java | 3 - .../dto/MedicalCertificateResponseDto.java | 7 +- .../ivory/ivory/ocr/CertificateOcrParser.java | 2 +- .../ocr/MedicalCertificateOcrParser.java | 55 ++++++++++++++ .../ocr/MedicalCertificateOcrService.java | 76 +++++++++++++++++++ .../java/com/ivory/ivory/ocr/OcrService.java | 18 +---- .../service/AbsenceCertificateService.java | 11 ++- .../ivory/ivory/service/CaregiverService.java | 6 -- .../service/MedicalCertificateService.java | 31 ++++---- src/main/resources/application.yml | 8 +- 13 files changed, 173 insertions(+), 58 deletions(-) create mode 100644 src/main/java/com/ivory/ivory/ocr/MedicalCertificateOcrParser.java create mode 100644 src/main/java/com/ivory/ivory/ocr/MedicalCertificateOcrService.java diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index bbb5a7b..d0e45b3 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -15,6 +15,8 @@ services: OCR_API_SECRET: ${OCR_API_SECRET} OCR_API_URL: ${OCR_API_URL} OCR_TEMPLATE_IDS: ${OCR_TEMPLATE_IDS} + MEDICAL_CERTIFICATE_OCR_API_SECRET_KEY: ${MEDICAL_CERTIFICATE_OCR_API_SECRET_KEY} + MEDICAL_CERTIFICATE_OCR_API_URL: ${MEDICAL_CERTIFICATE_OCR_API_URL} KAKAOPAY_SECRET_KEY: ${KAKAOPAY_SECRET_KEY} CID: ${CID} diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index c040dca..a1468e3 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -16,6 +16,8 @@ services: OCR_TEMPLATE_IDS: ${OCR_TEMPLATE_IDS} KAKAOPAY_SECRET_KEY: ${KAKAOPAY_SECRET_KEY} CID: ${CID} + MEDICAL_CERTIFICATE_OCR_API_SECRET_KEY: ${MEDICAL_CERTIFICATE_OCR_API_SECRET_KEY} + MEDICAL_CERTIFICATE_OCR_API_URL: ${MEDICAL_CERTIFICATE_OCR_API_URL} SPRING_PROFILES_ACTIVE: prod depends_on: diff --git a/src/main/java/com/ivory/ivory/domain/MedicalCertificate.java b/src/main/java/com/ivory/ivory/domain/MedicalCertificate.java index b8c605c..2e7031e 100644 --- a/src/main/java/com/ivory/ivory/domain/MedicalCertificate.java +++ b/src/main/java/com/ivory/ivory/domain/MedicalCertificate.java @@ -42,24 +42,16 @@ public class MedicalCertificate extends BaseEntity { @Column(name = "disease", nullable = true) private Disease disease; - @Column(name = "diagnosis_content", nullable = true) - private String diagnosisContent; - - @Column(name = "doctor_name", nullable = true) - private String doctorName; - @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="child_id", nullable = false) private Child child; @Builder - public MedicalCertificate(String name, String address, LocalDate diagnosisDate, Disease disease, String diagnosisContent, String doctorName, Child child) { + public MedicalCertificate(String name, String address, LocalDate diagnosisDate, Disease disease, Child child) { this.name = name; this.address = address; this.diagnosisDate = diagnosisDate; this.disease = disease; - this.diagnosisContent = diagnosisContent; - this.doctorName = doctorName; this.child = child; } } diff --git a/src/main/java/com/ivory/ivory/dto/CareDetailDto.java b/src/main/java/com/ivory/ivory/dto/CareDetailDto.java index a31f18b..0f22f8d 100644 --- a/src/main/java/com/ivory/ivory/dto/CareDetailDto.java +++ b/src/main/java/com/ivory/ivory/dto/CareDetailDto.java @@ -18,7 +18,6 @@ public class CareDetailDto { private String birthDate; private Long age; private String diagnosisName; - private String diagnosisContent; private String image; public static CareDetailDto from ( @@ -30,7 +29,6 @@ public static CareDetailDto from ( String birthDate, Long age, String diagnosisName, - String diagnosisContent, String image) { return CareDetailDto.builder() .applyDate(applyDate) @@ -41,7 +39,6 @@ public static CareDetailDto from ( .birthDate(birthDate) .age(age) .diagnosisName(diagnosisName) - .diagnosisContent(diagnosisContent) .image(image) .build(); } diff --git a/src/main/java/com/ivory/ivory/dto/MedicalCertificateResponseDto.java b/src/main/java/com/ivory/ivory/dto/MedicalCertificateResponseDto.java index 71fa341..4b8bafb 100644 --- a/src/main/java/com/ivory/ivory/dto/MedicalCertificateResponseDto.java +++ b/src/main/java/com/ivory/ivory/dto/MedicalCertificateResponseDto.java @@ -14,19 +14,14 @@ public class MedicalCertificateResponseDto { private String address; private LocalDate diagnosisDate; private String diagnosisName; - private String diagnosisContent; - private String doctorName; @Builder public MedicalCertificateResponseDto(Long id, String name, String address, LocalDate diagnosisDate, - String diagnosisName, - String diagnosisContent, String doctorName) { + String diagnosisName) { this.id = id; this.name = name; this.address = address; this.diagnosisDate = diagnosisDate; this.diagnosisName = diagnosisName; - this.diagnosisContent = diagnosisContent; - this.doctorName = doctorName; } } diff --git a/src/main/java/com/ivory/ivory/ocr/CertificateOcrParser.java b/src/main/java/com/ivory/ivory/ocr/CertificateOcrParser.java index 7fa4207..24627d8 100644 --- a/src/main/java/com/ivory/ivory/ocr/CertificateOcrParser.java +++ b/src/main/java/com/ivory/ivory/ocr/CertificateOcrParser.java @@ -7,7 +7,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; -@Component() +@Component("certificateOcrParser") @Slf4j public class CertificateOcrParser implements OcrParser { diff --git a/src/main/java/com/ivory/ivory/ocr/MedicalCertificateOcrParser.java b/src/main/java/com/ivory/ivory/ocr/MedicalCertificateOcrParser.java new file mode 100644 index 0000000..fca519e --- /dev/null +++ b/src/main/java/com/ivory/ivory/ocr/MedicalCertificateOcrParser.java @@ -0,0 +1,55 @@ +package com.ivory.ivory.ocr; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.HashMap; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +@Component("medicalCertificateOcrParser") +@Slf4j +public class MedicalCertificateOcrParser implements OcrParser { + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public Map parse(String response) { + Map result = new HashMap<>(); + try { + JsonNode root = objectMapper.readTree(response); + + // 첫 번째 이미지 데이터 μΆ”μΆœ + JsonNode image = root.path("result").path("images").get(0); + if (image == null || image.isEmpty() || !image.has("result")) { + throw new IllegalArgumentException("OCR μ‘λ‹΅μ—μ„œ 이미지 데이터가 μ—†μŠ΅λ‹ˆλ‹€.", null); + } + + // "cl" λ°°μ—΄μ—μ„œ 각 ν•„λ“œ μΆ”μΆœ + JsonNode fields = image.path("result").path("cl"); + if (fields == null || !fields.isArray()) { + throw new IllegalArgumentException("OCR μ‘λ‹΅μ—μ„œ ν•„λ“œ 데이터가 μ—†μŠ΅λ‹ˆλ‹€.", null); + } + + for (JsonNode field : fields) { + String name = field.path("category").asText(null); + String value = field.path("value").asText(null); + + if (name == null || value == null) { + log.warn("ν•„λ“œ 데이터가 λˆ„λ½λ˜μ—ˆμŠ΅λ‹ˆλ‹€: {}", field); + continue; + } + + result.put(name, value); + } + + if (result.isEmpty()) { + throw new IllegalArgumentException("OCR 결과에 ν•„μˆ˜ ν•„λ“œκ°€ μ—†μŠ΅λ‹ˆλ‹€.", null); + } + } catch (Exception e) { + log.error("OCR 응닡 νŒŒμ‹± μ‹€νŒ¨: 응닡 λ‚΄μš© = {}", response, e); + throw new RuntimeException("OCR 응닡 νŒŒμ‹± μ‹€νŒ¨", e); + } + return result; + } +} \ No newline at end of file diff --git a/src/main/java/com/ivory/ivory/ocr/MedicalCertificateOcrService.java b/src/main/java/com/ivory/ivory/ocr/MedicalCertificateOcrService.java new file mode 100644 index 0000000..f506083 --- /dev/null +++ b/src/main/java/com/ivory/ivory/ocr/MedicalCertificateOcrService.java @@ -0,0 +1,76 @@ +package com.ivory.ivory.ocr; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Base64; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +@Service +@RequiredArgsConstructor +@Slf4j +public class MedicalCertificateOcrService { + public String processOcr(MultipartFile file, String apiUrl, String secretKey) throws IOException { + // 1. JSON λ©”μ‹œμ§€ 생성 + String jsonMessage = createJsonMessage(file); + + // 2. HTTP μ—°κ²° μ„€μ • + HttpURLConnection connection = (HttpURLConnection) new URL(apiUrl).openConnection(); + connection.setRequestMethod("POST"); + connection.setDoOutput(true); + connection.setDoInput(true); + connection.setUseCaches(false); + connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); + connection.setRequestProperty("x-incizorlens-api-key", secretKey); + connection.setReadTimeout(30000); + + // 3. JSON 데이터 전솑 + try (var outputStream = connection.getOutputStream()) { + outputStream.write(jsonMessage.getBytes("UTF-8")); + outputStream.flush(); + } + + // 4. 응닡 처리 + int responseCode = connection.getResponseCode(); + System.out.println("responseCode = " + responseCode); + System.out.println("responseMessage = " + connection.getResponseMessage()); + if (responseCode != HttpURLConnection.HTTP_OK) { + throw new IOException("OCR μš”μ²­ μ‹€νŒ¨: μƒνƒœ μ½”λ“œ = " + responseCode + connection.getResponseMessage()); + } + + // 5. 응닡 데이터 읽기 + return new String(connection.getInputStream().readAllBytes(), "UTF-8"); + } + + private String createJsonMessage(MultipartFile file) throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + + // JSON λ©”μ‹œμ§€ 생성 + ObjectNode root = objectMapper.createObjectNode(); + root.put("version", "V2"); + root.put("requestId", UUID.randomUUID().toString()); + root.put("timestamp", System.currentTimeMillis()); + + // 이미지 정보 μΆ”κ°€ + ArrayNode images = objectMapper.createArrayNode(); + ObjectNode image = objectMapper.createObjectNode(); + image.put("format", "jpg"); + image.put("name", file.getName()); + + // 파일 데이터 Base64 인코딩 + String base64File = Base64.getEncoder().encodeToString(file.getBytes()); + image.put("data", base64File); // Base64 데이터λ₯Ό JSON에 μΆ”κ°€ + images.add(image); + + root.set("images", images); + + return objectMapper.writeValueAsString(root); + } +} \ No newline at end of file diff --git a/src/main/java/com/ivory/ivory/ocr/OcrService.java b/src/main/java/com/ivory/ivory/ocr/OcrService.java index 6421bec..87b59b3 100644 --- a/src/main/java/com/ivory/ivory/ocr/OcrService.java +++ b/src/main/java/com/ivory/ivory/ocr/OcrService.java @@ -18,14 +18,8 @@ @RequiredArgsConstructor @Slf4j public class OcrService { - @Value("${ocr.api.url}") - private String apiUrl; - @Value("${ocr.api.secret-key}") - private String secretKey; -// @Value("#{'${ocr.template-ids}'.split(',')}") -// private List templateIds; - - public String processOcr(MultipartFile file) throws IOException { + + public String processOcr(MultipartFile file, String apiUrl, String secretKey) throws IOException { // 1. JSON λ©”μ‹œμ§€ 생성 String jsonMessage = createJsonMessage(); @@ -47,6 +41,8 @@ public String processOcr(MultipartFile file) throws IOException { // 4. 응닡 처리 int responseCode = connection.getResponseCode(); + System.out.println("responseCode = " + responseCode); + System.out.println("responseMessage = " + connection.getResponseMessage()); if (responseCode != HttpURLConnection.HTTP_OK) { throw new IOException("OCR μš”μ²­ μ‹€νŒ¨: μƒνƒœ μ½”λ“œ = " + responseCode + connection.getResponseMessage()); } @@ -67,14 +63,8 @@ private String createJsonMessage() throws IOException { // 이미지 정보 μΆ”κ°€ ArrayNode images = objectMapper.createArrayNode(); ObjectNode image = objectMapper.createObjectNode(); -// ArrayNode templateIdsNode = objectMapper.createArrayNode(); image.put("format", "jpg"); image.put("name", "uploaded_image"); -// image.put("templateIds", objectMapper.createArrayNode()); -// System.out.println(templateIds); -// for (String templateId : templateIds) { -// templateIdsNode.add(templateId); -// } images.add(image); root.set("images", images); diff --git a/src/main/java/com/ivory/ivory/service/AbsenceCertificateService.java b/src/main/java/com/ivory/ivory/service/AbsenceCertificateService.java index c956e3f..43d1110 100644 --- a/src/main/java/com/ivory/ivory/service/AbsenceCertificateService.java +++ b/src/main/java/com/ivory/ivory/service/AbsenceCertificateService.java @@ -23,6 +23,8 @@ import java.util.Map; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -38,9 +40,14 @@ public class AbsenceCertificateService { private final AbsenceCertificateRepository absenceCertificateRepository; private final ChildRepository childRepository; private final OcrService ocrService; + @Qualifier("certificateOcrParser") private final OcrParser certificateOcrParser; - //TODO: 미등원 ν™•μΈμ„œ 검증 둜직 μΆ”κ°€ + @Value("${ocr.api.url}") + private String apiUrl; + @Value("${ocr.api.secret-key}") + private String secretKey; + @Transactional public AbsenceCertificateResponseDto addAbsenceCertificate( AbsenceCertificateRequestDto absenceCertificateRequestDto, Long childId, Long memberId) { @@ -51,7 +58,7 @@ public AbsenceCertificateResponseDto addAbsenceCertificate( throw new IllegalArgumentException("본인의 μžλ…€μ— λŒ€ν•œ 미등원 ν™•μΈμ„œλ§Œ 등둝할 수 μžˆμŠ΅λ‹ˆλ‹€."); } - String jsonResponse = ocrService.processOcr(absenceCertificateRequestDto.getFile()); + String jsonResponse = ocrService.processOcr(absenceCertificateRequestDto.getFile(), apiUrl, secretKey); Map parseData = certificateOcrParser.parse(jsonResponse); String name = parseData.get("이름"); // μ—†μœΌλ©΄ null diff --git a/src/main/java/com/ivory/ivory/service/CaregiverService.java b/src/main/java/com/ivory/ivory/service/CaregiverService.java index 100ade0..c6c36eb 100644 --- a/src/main/java/com/ivory/ivory/service/CaregiverService.java +++ b/src/main/java/com/ivory/ivory/service/CaregiverService.java @@ -1,7 +1,6 @@ package com.ivory.ivory.service; import com.ivory.ivory.domain.*; -import com.ivory.ivory.dto.ApplyListDto; import com.ivory.ivory.dto.CareDetailDto; import com.ivory.ivory.dto.CareDto; import com.ivory.ivory.dto.CareListDto; @@ -11,13 +10,11 @@ import com.ivory.ivory.util.response.CustomApiResponse; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; -import org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.web.server.ResponseStatusException; import java.time.LocalDate; -import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; @@ -83,8 +80,6 @@ public CustomApiResponse getCareDetail(Long currentMemberId, Long applyId) { Long age = childService.calculateAge(child.get().getBirth(), LocalDate.now()); //아이 진단λͺ… String diagnosisName = apply.get().getMedicalCertificate().getDisease().getName(); - //μ§„λ£Œ λ‚΄μš© - String diagnosisContent = apply.get().getMedicalCertificate().getDiagnosisContent(); //아이 사진 String image = child.get().getImage(); @@ -98,7 +93,6 @@ public CustomApiResponse getCareDetail(Long currentMemberId, Long applyId) { birthDate, age, diagnosisName, - diagnosisContent, image ); return CustomApiResponse.createSuccess(HttpStatus.OK.value(),"λŒλ΄„ λ‚΄μš©μ΄ 상세 μ‘°νšŒλ˜μ—ˆμŠ΅λ‹ˆλ‹€.",careDetailDto); diff --git a/src/main/java/com/ivory/ivory/service/MedicalCertificateService.java b/src/main/java/com/ivory/ivory/service/MedicalCertificateService.java index 4ca3536..ac8b2b9 100644 --- a/src/main/java/com/ivory/ivory/service/MedicalCertificateService.java +++ b/src/main/java/com/ivory/ivory/service/MedicalCertificateService.java @@ -11,6 +11,7 @@ import com.ivory.ivory.dto.MedicalCertificateResponseDto; import com.ivory.ivory.dto.MedicalCertificatesDto; import com.ivory.ivory.dto.PageInfo; +import com.ivory.ivory.ocr.MedicalCertificateOcrService; import com.ivory.ivory.ocr.OcrParser; import com.ivory.ivory.ocr.OcrService; import com.ivory.ivory.repository.AbsenceCertificateRepository; @@ -24,6 +25,8 @@ import java.util.Map; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -38,10 +41,15 @@ public class MedicalCertificateService { private final MedicalCertificateRepository medicalCertificateRepository; private final ChildRepository childRepository; - private final OcrService ocrService; - private final OcrParser certificateOcrParser; + private final MedicalCertificateOcrService ocrService; + + @Qualifier("medicalCertificateOcrParser") + private final OcrParser medicalCertificateOcrParser; + @Value("${ocr.medical-certificate.api.url}") + private String apiUrl; + @Value("${ocr.medical-certificate.api.secret-key}") + private String secretKey; - //TODO: μ§„λ‹¨μ„œ 검증 둜직 μΆ”κ°€ @Transactional public MedicalCertificateResponseDto addMedicalCertificate(MedicalCertificateRequestDto medicalCertificateRequestDto, Long childId, Long memberId) { try { @@ -51,23 +59,20 @@ public MedicalCertificateResponseDto addMedicalCertificate(MedicalCertificateReq throw new IllegalArgumentException("본인의 μžλ…€μ— λŒ€ν•œ μ§„λ‹¨μ„œλ§Œ 등둝할 수 μžˆμŠ΅λ‹ˆλ‹€."); } - String jsonResponse = ocrService.processOcr(medicalCertificateRequestDto.getFile()); - Map parseData = certificateOcrParser.parse(jsonResponse); + String jsonResponse = ocrService.processOcr(medicalCertificateRequestDto.getFile(), apiUrl, secretKey); + System.out.println(jsonResponse); + Map parseData = medicalCertificateOcrParser.parse(jsonResponse); - String name = parseData.get("이름"); + String name = parseData.get("ν™˜μžμ„±λͺ…"); String address = parseData.get("μ£Όμ†Œ"); - String diagnosisDate = parseData.get("진단일"); + String diagnosisDate = parseData.get("진단연월일"); String diagnosisName = parseData.get("진단λͺ…"); - String diagnosisContent = parseData.get("의견"); - String doctorName = parseData.get("μ˜μ‚¬λͺ…"); MedicalCertificate medicalCertificate = MedicalCertificate.builder() .name(name) .address(address) .diagnosisDate(diagnosisDate != null ? DateUtil.parseToLocalDate(diagnosisDate) : null) .disease(Disease.findByDiagnosisName(diagnosisName)) - .diagnosisContent(diagnosisContent) - .doctorName(doctorName) .child(child) .build(); @@ -79,8 +84,6 @@ public MedicalCertificateResponseDto addMedicalCertificate(MedicalCertificateReq .address(medicalCertificate.getAddress()) .diagnosisDate(medicalCertificate.getDiagnosisDate()) .diagnosisName(medicalCertificate.getDisease().getName()) - .diagnosisContent(medicalCertificate.getDiagnosisContent()) - .doctorName(medicalCertificate.getDoctorName()) .build(); } catch (IllegalArgumentException e) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage()); @@ -148,8 +151,6 @@ public MedicalCertificateResponseDto getMedicalCertificateDetail(Long medicalCer .address(medicalCertificate.getAddress()) .diagnosisDate(medicalCertificate.getDiagnosisDate()) .diagnosisName(medicalCertificate.getDisease().getName()) - .diagnosisContent(medicalCertificate.getDiagnosisContent()) - .doctorName(medicalCertificate.getDoctorName()) .build(); } catch (IllegalArgumentException e) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, e.getMessage()); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 9505a56..8202a66 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,8 +1,8 @@ spring: servlet: multipart: - max-file-size: 10MB - max-request-size: 10MB + max-file-size: 8MB + max-request-size: 8MB profiles: active: local application: @@ -30,6 +30,10 @@ ocr: secret-key: ${OCR_API_SECRET} url: ${OCR_API_URL} template-ids: ${OCR_TEMPLATE_IDS} + medical-certificate: + api: + secret-key: ${MEDICAL_CERTIFICATE_OCR_API_SECRET_KEY} + url: ${MEDICAL_CERTIFICATE_OCR_API_URL} kakaopay: secretKey: ${KAKAOPAY_SECRET_KEY} cid: ${CID}