diff --git a/WebContent/jsp/onl/apim/approval/portalAppApprovalManPopup.jsp b/WebContent/jsp/onl/apim/approval/portalAppApprovalManPopup.jsp
index 3413aec..a691c5e 100644
--- a/WebContent/jsp/onl/apim/approval/portalAppApprovalManPopup.jsp
+++ b/WebContent/jsp/onl/apim/approval/portalAppApprovalManPopup.jsp
@@ -176,11 +176,52 @@
}
});
+ $("#btn_app_delete").click(function () {
+ if (!confirm("이 승인 요청을 삭제하시겠습니까?\n삭제 후에는 복구할 수 없습니다.")) {
+ return;
+ }
+ $.ajax({
+ type: "POST",
+ url: url,
+ data: {cmd: "DELETE", id: key},
+ success: function (args) {
+ alert("삭제되었습니다.");
+ if (window.dialogArguments && window.dialogArguments.self) {
+ window.dialogArguments.self.location.reload();
+ } else if (window.opener) {
+ window.opener.location.reload();
+ }
+ window.close();
+ },
+ error: function (e) {
+ alert(approvalErrorMessage(e));
+ }
+ });
+ });
+
$("#btn_close").click(function () {
window.close();
});
});
+ function approvalErrorMessage(e) {
+ try {
+ var json = JSON.parse(e.responseText);
+ return json.errorMsg || e.responseText;
+ } catch (ex) {
+ return e.responseText;
+ }
+ }
+
+ // 요청자(PTL_USER) row 가 삭제되면 상세 조회 자체가 불가능하다. 이 경우 삭제만 가능하도록 노출한다.
+ function showLoadFailure(message) {
+ $("#approvalSubject").text("상세 정보를 조회할 수 없는 승인 요청");
+ $("#approvalDetail").text(message);
+ $("#btn_modify, #btn_app_approve, #btn_app_reject, #btn_app_force_reject, #btn_app_redeploy").hide();
+ $("#gwActionSection, #gwActionResult").hide();
+ document.getElementById("btn_app_delete").style.display = "";
+ }
+
var currentRequestType = null; // 현재 신청 유형 (DELETE 승인 시 GW 처리방식 선택 노출용)
// 값이 있을 때만 행을 노출한다. (해지 신청처럼 해당 항목이 없는 유형에서 빈 행이 남지 않도록)
@@ -344,7 +385,9 @@
$("#apisTable tbody").html(apisHtml);
},
error: function (e) {
- alert(e.responseText);
+ var message = approvalErrorMessage(e);
+ alert(message);
+ showLoadFailure(message);
}
});
}
@@ -454,6 +497,9 @@
+
diff --git a/WebContent/jsp/onl/apim/approval/portalUserApprovalManPopup.jsp b/WebContent/jsp/onl/apim/approval/portalUserApprovalManPopup.jsp
index c8bca97..64f3217 100644
--- a/WebContent/jsp/onl/apim/approval/portalUserApprovalManPopup.jsp
+++ b/WebContent/jsp/onl/apim/approval/portalUserApprovalManPopup.jsp
@@ -181,7 +181,7 @@
});
$("#btn_user_delete").click(function() {
- if (!confirm("삭제된 사용자 또는 법인이 포함되어 승인·반려할 수 없는 요청입니다.\n이 승인 요청을 삭제하시겠습니까?")) {
+ if (!confirm("삭제된 요청자·사용자 또는 법인이 포함되어 승인·반려할 수 없는 요청입니다.\n이 승인 요청을 삭제하시겠습니까?\n삭제 후에는 복구할 수 없습니다.")) {
return;
}
$.ajax({
@@ -198,7 +198,7 @@
window.close();
},
error: function(e) {
- alert(e.responseText);
+ alert(approvalErrorMessage(e));
}
});
});
@@ -362,10 +362,31 @@
}
},
error: function(e) {
- alert(e.responseText);
+ var message = approvalErrorMessage(e);
+ alert(message);
+ showLoadFailure(message);
}
});
}
+
+ function approvalErrorMessage(e) {
+ try {
+ var json = JSON.parse(e.responseText);
+ return json.errorMsg || e.responseText;
+ } catch (ex) {
+ return e.responseText;
+ }
+ }
+
+ // 요청자(PTL_USER) row 가 삭제되면 상세 조회 자체가 불가능하다. 이 경우 삭제만 가능하도록 노출한다.
+ function showLoadFailure(message) {
+ $("#approvalSubject").text("상세 정보를 조회할 수 없는 승인 요청");
+ $("#approvalDetail").text(message);
+ $("#approvalDetailRow").show();
+ $("#btn_unmask").hide();
+ $("#btn_user_approve, #btn_user_reject, #btn_user_force_reject, #btn_user_redeploy").hide();
+ document.getElementById("btn_user_delete").style.display = "";
+ }
function updateDetailView(data) {
$("#approvalType").text(data.approvalType === 'USER' ? "법인사용자" : "API 사용");
$("#approvalStatus").text(data.approvalStatus.description);
diff --git a/src/main/java/com/eactive/eai/rms/onl/apim/approval/PortalApprovalManService.java b/src/main/java/com/eactive/eai/rms/onl/apim/approval/PortalApprovalManService.java
index 46173cb..6c3d5d4 100644
--- a/src/main/java/com/eactive/eai/rms/onl/apim/approval/PortalApprovalManService.java
+++ b/src/main/java/com/eactive/eai/rms/onl/apim/approval/PortalApprovalManService.java
@@ -468,8 +468,40 @@ public class PortalApprovalManService extends BaseService {
* 임의 삭제 방지를 위해 실제로 삭제된 사용자/법인이 포함된 USER 유형 요청만 허용한다.
*/
public void deleteApprovalRequest(String id) {
- Approval approval = approvalService.findById(id)
- .orElseThrow(() -> new BizException("승인 정보를 찾을 수 없습니다. ID: " + id));
+ Approval approval = null;
+ try {
+ approval = approvalService.findById(id).orElse(null);
+ } catch (Exception e) {
+ // 요청자/승인자 row 가 사라진 건은 엔티티 hydration 자체가 실패한다. 네이티브 조회로 우회한다.
+ logger.warn("Approval {} 엔티티 로딩 실패. 네이티브 조회로 대체합니다. 원인: {}", id, e.getMessage());
+ }
+
+ if (approval != null) {
+ assertDeletable(approval);
+ } else {
+ // Approval.requester 는 @JoinColumn(nullable=false) + @NotFound(IGNORE) 조합이라
+ // 요청자(PTL_USER) row 가 삭제되면 findById 가 빈 결과를 반환한다(조회·승인·반려 모두 불가).
+ assertDeletableByNativeQuery(id);
+ }
+
+ entityManager.createNativeQuery("DELETE FROM PTL_APPROVER WHERE APPROVAL_ID = :id")
+ .setParameter("id", id)
+ .executeUpdate();
+ int affected = entityManager.createNativeQuery("DELETE FROM PTL_APPROVAL WHERE ID = :id")
+ .setParameter("id", id)
+ .executeUpdate();
+ if (affected == 0) {
+ throw new BizException("승인 정보를 찾을 수 없습니다. ID: " + id);
+ }
+ logger.info("Approval {} deleted (deleted requester/target user/org present)", id);
+ }
+
+ /** 엔티티 로딩이 가능한 건: 요청자 삭제이거나, 대상 사용자·법인이 삭제된 법인사용자 요청만 삭제 허용 */
+ private void assertDeletable(Approval approval) {
+ boolean requesterDeleted = approval.getRequester() == null;
+ if (requesterDeleted) {
+ return;
+ }
if (!approval.getApprovalType().equals(ApprovalType.USER)) {
throw new BizException("법인사용자 승인 요청만 삭제할 수 있습니다.");
}
@@ -486,19 +518,38 @@ public class PortalApprovalManService extends BaseService {
|| "삭제된법인".equals(org.getOrgName());
}
if (!(userDeleted || orgDeleted)) {
- throw new BizException("삭제된 사용자 또는 법인이 포함된 요청만 삭제할 수 있습니다.");
+ throw new BizException("삭제된 요청자·사용자 또는 법인이 포함된 요청만 삭제할 수 있습니다.");
}
+ }
- entityManager.createNativeQuery("DELETE FROM PTL_APPROVER WHERE APPROVAL_ID = :id")
+ /** 엔티티 로딩이 불가능한 건: PTL_APPROVAL 원본 row 를 직접 읽어 요청자/대상 사용자 삭제 여부를 확인한다. */
+ @SuppressWarnings("unchecked")
+ private void assertDeletableByNativeQuery(String id) {
+ List