Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,12 @@ dependencies {
implementation("org.modelmapper:modelmapper:3.1.1")

// (1) hospital-interface 모듈
implementation "com.doubleo.grpc:hospital-interface:0.2.7"
implementation "com.doubleo.grpc:patient-interface:0.2.7"
implementation "com.doubleo.grpc:member-interface:0.2.7"
implementation "com.doubleo.grpc:log-interface:0.2.7"
implementation "com.doubleo.grpc:hospital-interface:0.3.3"
implementation "com.doubleo.grpc:patient-interface:0.3.3"
implementation "com.doubleo.grpc:member-interface:0.3.3"
implementation "com.doubleo.grpc:log-interface:0.3.3"
implementation "com.doubleo.grpc:acapy-interface:0.3.3"
implementation "com.doubleo.grpc:pass-interface:0.3.3"

// (2) gRPC 런타임
implementation "io.grpc:grpc-netty:1.63.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ public enum IssuanceStatus {
PENDING,
REJECTED,
EXPIRED,
PROCESSING
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ public class PassServiceImpl implements PassService {
"%s, %s님에 대한 보호자 출입이 신청되었습니다.";
public static final String GUARDIAN_PASS_APPLY_TO_PATIENT_TITLE = "보호자 출입 신청";
public static final String GUARDIAN_PASS_APPLY_TO_PATIENT_CONTENT = "%s, %s님이 보호자 출입을 신청하였습니다.";
public static final String GUARDIAN_APPROVED_NOTIFICATION_TITLE = "보호자 신청 승인";
public static final String GUARDIAN_APPROVED_NOTIFICATION_CONTENT = "%s님의 보호자 신청이 승인되었습니다.";
public static final String GUARDIAN_REJECTED_NOTIFICATION_TITLE = "보호자 신청 거절";
public static final String GUARDIAN_REJECTED_NOTIFICATION_CONTENT = "%s님의 보호자 신청이 거절되었습니다.";

Expand All @@ -62,6 +60,7 @@ public class PassServiceImpl implements PassService {
private final PatientClient patientClient;
private final GuardianClient guardianClient;
private final LogClient logClient;
private final AcapyClient acapyClient;
private final FcmService fcmService;

@Override
Expand Down Expand Up @@ -123,15 +122,29 @@ public PassCreateResponse createPatientPass(
patientClient.getPatientByNameAndRegNo(
tenantId, member.getMemberName(), member.getMemberRegNo());

return createPass(
memberId,
hospitalId,
patient.getPatientId(),
tenantId,
startAt,
startAt.plusDays(1),
VisitCategory.PATIENT,
IssuanceStatus.ISSUED);
PassCreateResponse response =
createPass(
memberId,
hospitalId,
patient.getPatientId(),
tenantId,
startAt,
startAt.plusDays(1),
VisitCategory.PATIENT,
IssuanceStatus.PROCESSING);

try {
boolean success = acapyClient.issueVc(tenantId, response.passId(), memberId);
if (!success) {
log.error("VC 발급 상태 false");
throw new CommonException(PassErrorCode.VC_ISSUE_FAILED);
}
} catch (Exception e) {
log.error("VC 발급 중 예외 발생: {}", e.getMessage());
throw new CommonException(PassErrorCode.VC_ISSUE_FAILED);
}

return response;
}

@Override
Expand All @@ -154,15 +167,27 @@ public PassCreateResponse createGuardianPass(
for (GuardianResponse guardian : guardians) {
if (guardian.getGuardianName().equals(memberName)
&& guardian.getGuardianContact().equals(memberContact)) {
return createPass(
memberId,
hospitalId,
patientId,
tenantId,
startAt,
startAt.plusDays(1),
VisitCategory.GUARDIAN,
IssuanceStatus.ISSUED);
PassCreateResponse response =
createPass(
memberId,
hospitalId,
patientId,
tenantId,
startAt,
startAt.plusDays(1),
VisitCategory.GUARDIAN,
IssuanceStatus.PROCESSING);
try {
boolean success = acapyClient.issueVc(tenantId, response.passId(), memberId);
if (!success) {
log.error("VC 발급 상태 false");
throw new CommonException(PassErrorCode.VC_ISSUE_FAILED);
}
} catch (Exception e) {
log.error("VC 발급 중 예외 발생: {}", e.getMessage());
throw new CommonException(PassErrorCode.VC_ISSUE_FAILED);
}
return response;
}
}
return createPass(
Expand All @@ -176,11 +201,6 @@ public PassCreateResponse createGuardianPass(
IssuanceStatus.PENDING);
}

@Override
public void deletePass(Long passId) {
passRepository.deleteById(passId);
}

@Override
public Page<PendingPassResponse> getPendingPassList(String tenantId, Pageable pageable) {
Page<Pass> passes =
Expand All @@ -204,6 +224,11 @@ public Page<PendingPassResponse> getPendingPassList(String tenantId, Pageable pa
});
}

@Override
public void deletePass(Long passId) {
passRepository.deleteById(passId);
}

@Override
public PassCreateResponse createGuardianAndUpdatePassStatus(
Long passId, IssuanceStatus issuanceStatus) {
Expand All @@ -221,72 +246,34 @@ public PassCreateResponse createGuardianAndUpdatePassStatus(
log.warn("환자 멤버가 존재하지 않아 알림을 생략합니다.");
}

try {
// TODO: 실제 connection id 가져올 부분
String didConnectionId = "c76e52c9-a3f9-4a59-b299-be22a0ab36b7";
pass.updateDidConnectionId(didConnectionId);
} catch (Exception e) {
log.warn("DID Connection ID를 가져오는 데 실패했습니다: {}", e.getMessage());
}
if (issuanceStatus == IssuanceStatus.ISSUED) {

try {
boolean success =
acapyClient.issueVc(pass.getTenantId(), passId, pass.getMemberId());
if (!success) {
log.error("VC 발급 상태 false");
throw new CommonException(PassErrorCode.VC_ISSUE_FAILED);
}
} catch (Exception e) {
log.error("VC 발급 중 예외 발생: {}", e.getMessage());
throw new CommonException(PassErrorCode.VC_ISSUE_FAILED);
}

pass.updateStatus(issuanceStatus);
pass = passRepository.save(pass);
pass.updateStatus(IssuanceStatus.PROCESSING);
pass = passRepository.save(pass);

if (issuanceStatus == IssuanceStatus.ISSUED) {
guardianClient.createGuardian(
pass.getTenantId(),
pass.getPatientId(),
member.getMemberName(),
member.getMemberContact());
List<String> areaCodes =
passAreaRepository.findAllByPass(pass).stream()
.map(PassArea::getAreaCode)
.toList();
try {
logClient.createIssuedLog(
pass.getTenantId(),
pass.getMemberId(),
member.getMemberName(),
member.getMemberContact(),
pass.getId(),
pass.getStartAt(),
pass.getExpiredAt(),
pass.getVisitCategory(),
areaCodes);
} catch (Exception e) {
log.error("로그 전송 실패: {}", e.getMessage());
}
fcmService.sendNotification(
new FcmSendRequest(
member.getFcmToken(),
GUARDIAN_APPROVED_NOTIFICATION_TITLE,
String.format(
GUARDIAN_APPROVED_NOTIFICATION_CONTENT,
member.getMemberName())));
memberNotificationRepository.save(
MemberNotification.createMemberNotification(
member.getMemberId(),
GUARDIAN_APPROVED_NOTIFICATION_TITLE,
String.format(
GUARDIAN_APPROVED_NOTIFICATION_CONTENT,
member.getMemberName())));
if (patientMember != null) {
fcmService.sendNotification(
new FcmSendRequest(
patientMember.getFcmToken(),
GUARDIAN_APPROVED_NOTIFICATION_TITLE,
String.format(
GUARDIAN_APPROVED_NOTIFICATION_CONTENT,
member.getMemberName())));
memberNotificationRepository.save(
MemberNotification.createMemberNotification(
patientMember.getMemberId(),
GUARDIAN_APPROVED_NOTIFICATION_TITLE,
String.format(
GUARDIAN_APPROVED_NOTIFICATION_CONTENT,
member.getMemberName())));
}

} else if (issuanceStatus == IssuanceStatus.REJECTED) {

pass.updateStatus(IssuanceStatus.REJECTED);
pass = passRepository.save(pass);

fcmService.sendNotification(
new FcmSendRequest(
member.getFcmToken(),
Expand Down Expand Up @@ -337,19 +324,10 @@ private PassCreateResponse createPass(

PatientResponse patient = patientClient.getPatientById(patientId);

String didConnectionId = null;

List<AreaResponse> areas =
patient.getAreasList().stream().map(areaClient::getAreaById).toList();
List<String> areaCodes = areas.stream().map(AreaResponse::getAreaCode).toList();

try {
// TODO: 실제 connection id 가져올 부분
didConnectionId = "c76e52c9-a3f9-4a59-b299-be22a0ab36b7";
} catch (Exception e) {
log.warn("DID Connection ID를 가져오는 데 실패했습니다: {}", e.getMessage());
}

Pass pass =
Pass.createPass(
tenantId,
Expand All @@ -360,7 +338,7 @@ private PassCreateResponse createPass(
patientId,
visitCategory,
status,
didConnectionId);
null);
passRepository.save(pass);

List<PassArea> passAreas =
Expand Down Expand Up @@ -406,22 +384,6 @@ private PassCreateResponse createPass(
patient.getName())));
}

if (status == IssuanceStatus.ISSUED) {
try {
logClient.createIssuedLog(
tenantId,
memberId,
member.getMemberName(),
member.getMemberContact(),
pass.getId(),
startAt,
expiredAt,
visitCategory,
areaCodes);
} catch (Exception e) {
log.error("로그 전송 실패: {}", e.getMessage());
}
}
return new PassCreateResponse(pass.getId());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
public enum PassErrorCode implements BaseErrorCode {
PATIENT_ID_REQUIRED_FOR_GUARDIAN(HttpStatus.BAD_REQUEST, "patient id가 필요합니다."),
PASS_NOT_FOUND(HttpStatus.NOT_FOUND, "pass를 찾을 수 없습니다."),
VISIT_CATEGORY_REQUIRED_FOR_PASS(HttpStatus.BAD_REQUEST, "visit category가 올바르지 않습니다.");
VISIT_CATEGORY_REQUIRED_FOR_PASS(HttpStatus.BAD_REQUEST, "visit category가 올바르지 않습니다."),
VC_ISSUE_FAILED(HttpStatus.INTERNAL_SERVER_ERROR, "VC 발급에 실패했습니다."),
CONNECTION_ID_NOT_ASSIGNED(HttpStatus.CONFLICT, "connectionId가 아직 할당되지 않았습니다.");

private final HttpStatus httpStatus;
private final String message;
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/com/doubleo/passservice/grpc/client/AcapyClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.doubleo.passservice.grpc.client;

import com.doubleo.didagent.grpc.server.AcapyServiceGrpc;
import com.doubleo.didagent.grpc.server.VcIssueRequest;
import com.doubleo.didagent.grpc.server.VcIssueResponse;
import com.doubleo.hospitalservice.domain.area.grpc.server.*;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class AcapyClient {

@GrpcClient("acapy-service")
private AcapyServiceGrpc.AcapyServiceBlockingStub blockingStub;

public boolean issueVc(String tenantId, Long passId, Long memberId) {
VcIssueRequest request =
VcIssueRequest.newBuilder()
.setTenantId(tenantId)
.setPassId(passId)
.setMemberId(memberId)
.build();

VcIssueResponse response = blockingStub.issueVc(request);
return response.getIsInvitationCreated();
}
}
Loading