변경/해지 신청 개선 및 사전검사 추가
eapim-portal CI (from elink-portal-common) / build (push) Has been cancelled

- 변경/해지 상태 표시 및 취소 기능 추가
- 해지 신청 사전검사 및 경고 메시지 처리 구현
- 관리자 승인 이전 허용되는 취소 정책 지원
This commit is contained in:
Rinjae
2026-08-11 14:15:33 +09:00
parent fa6dd17384
commit 9856d4ea78
@@ -23,6 +23,9 @@ public class ProcessingState implements ApprovalState {
case DENY:
handleDeny(approval, options);
break;
case CANCEL:
handleCancel(approval, options);
break;
default:
logger.warn("Invalid event {} for ProcessingState in approval {}", event, approval.getId());
throw new UnsupportedOperationException("Invalid event for Processing state");
@@ -91,6 +94,38 @@ public class ProcessingState implements ApprovalState {
}
}
/**
* 신청자 취소. 심사중(PROCESSING)이라도 <b>아직 아무도 승인하지 않은</b> 경우에 한해 허용한다.
*
* <p>관리자가 결재 상세를 열어보기만 해도 REQUESTED → PROCESSING 으로 바뀌므로(admin
* {@code PortalApprovalManService.selectDetail}), 이 상태의 상당수는 실제로 결재가 진행된 것이
* 아니라 열람만 된 건이다. 그런 건이 취소 불가로 남으면 해당 인증키의 후속 신청(변경/해지)이
* 무기한 막힌다. 승인 이력이 하나라도 있으면 기존 정책대로 거절한다.</p>
*/
private void handleCancel(Approval approval, Map<String, Object> options) {
boolean anyApproved = approval.getApprovers().stream()
.anyMatch(approver -> ApproverStatus.APPROVED.equals(approver.getApproverStatus()));
if (anyApproved) {
logger.warn("Cancel rejected for approval {} - already approved by at least one approver", approval.getId());
throw new UnsupportedOperationException("Cannot cancel approval already approved by an approver");
}
String approverId = (String) options.getOrDefault(ApprovalConstants.APPROVER, "");
if (!isAuthorizedApprover(approval, approverId, options)) {
logger.warn("Unauthorized cancel attempt for approval {} by {}", approval.getId(), approverId);
throw new UnauthorizedApprovalException("Unauthorized approver");
}
approval.getApprovers().forEach(approver -> {
approver.setApproverStatus(ApproverStatus.CANCELED);
approver.setApprovedDate(LocalDateTime.now());
});
approval.setApprovalDate(LocalDateTime.now());
getApprovalListener(options).rollback(approval);
approval.setApprovalStatus(new CanceledState());
logger.info("Approval {} cancelled in Processing state by {}", approval.getId(), approverId);
}
@Override
public String toString() {
return ApprovalStatus.PROCESSING.toString();