-- V85: 외부 연동(펌뱅킹/SMS·카카오) 호출 감사 이력 -- -- 목적: BankTransferAdapter / MessageAdapter 모든 호출을 자동 영속화. -- 운영 감사·장애 추적·외부 SDK 통합 검증에 사용. AOP(@Around)가 INSERT. -- PII 는 요약 필드에 어댑터에서 이미 마스킹된 값만 들어간다 (계좌·전화 뒤 4자리만). CREATE TABLE IF NOT EXISTS external_call_log ( log_id BIGSERIAL PRIMARY KEY, call_type VARCHAR(20) NOT NULL, -- BANK / MESSAGE adapter_class VARCHAR(200) NOT NULL, -- 실제 호출된 구현체 (Mock/Kftc/Toast) method_name VARCHAR(50) NOT NULL, -- requestTransfer / queryStatus / send target_ref_type VARCHAR(30), -- WITHDRAW / APPROVAL 등 (가능 시) target_ref_id BIGINT, -- withdrawRequestId / refId 등 request_summary TEXT, -- 요청 요약 (마스킹된 JSON 한 줄) response_summary TEXT, -- 응답 요약 result_code VARCHAR(20), -- 외부 응답 코드 (정상 시) result_message TEXT, success BOOLEAN NOT NULL DEFAULT TRUE, duration_ms INTEGER, -- 호출 소요 시간 (ms) error_class VARCHAR(200), -- 예외 발생 시 클래스명 error_message TEXT, -- 예외 메시지 called_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_by BIGINT -- 시도자 (가능 시) ); COMMENT ON TABLE external_call_log IS '외부 연동 호출 감사 이력 (AOP 자동 영속화)'; COMMENT ON COLUMN external_call_log.call_type IS 'BANK / MESSAGE'; COMMENT ON COLUMN external_call_log.adapter_class IS '실제 호출된 어댑터 클래스 (Mock/Kftc/Toast)'; COMMENT ON COLUMN external_call_log.method_name IS 'requestTransfer / queryStatus / send'; COMMENT ON COLUMN external_call_log.success IS 'true=정상응답, false=예외/실패'; CREATE INDEX IF NOT EXISTS idx_ecl_called_at_desc ON external_call_log(called_at DESC); CREATE INDEX IF NOT EXISTS idx_ecl_type_called_at ON external_call_log(call_type, called_at DESC); CREATE INDEX IF NOT EXISTS idx_ecl_target ON external_call_log(target_ref_type, target_ref_id) WHERE target_ref_type IS NOT NULL; CREATE INDEX IF NOT EXISTS idx_ecl_failures ON external_call_log(called_at DESC) WHERE success = FALSE; -- ============================================================ -- 메뉴 등록 (시스템 그룹 하위) -- ============================================================ INSERT INTO menu (menu_code, menu_name, menu_type, menu_path, component_path, menu_icon, menu_level, sort_order, is_visible, is_active, parent_menu_id, description) SELECT 'SYSTEM_EXTERNAL_CALL', '외부연동 호출이력', 'PAGE', '/system/external-call-log', 'system/ExternalCallLogList', 'api', 2, 20, 'Y', 'Y', (SELECT menu_id FROM menu WHERE menu_code = 'GRP_SYSTEM'), '펌뱅킹/SMS·카카오 어댑터 호출 감사 이력 (AOP 자동 영속화)' WHERE EXISTS (SELECT 1 FROM menu WHERE menu_code = 'GRP_SYSTEM') ON CONFLICT (menu_code) DO NOTHING; -- ============================================================ -- 권한 정의 (READ 만 — 감사 로그는 수동 등록 없음) -- ============================================================ INSERT INTO menu_permission (menu_id, perm_code, perm_name, sort_order) SELECT menu_id, 'READ', '조회', 1 FROM menu WHERE menu_code = 'SYSTEM_EXTERNAL_CALL' ON CONFLICT (menu_id, perm_code) DO NOTHING; -- ============================================================ -- 역할 부여 (SUPER_ADMIN / ADMIN) -- ============================================================ INSERT INTO role_menu_permission (role_id, menu_id, perm_code, is_granted) SELECT r.role_id, m.menu_id, p.perm_code, 'Y' FROM role r CROSS JOIN menu m JOIN menu_permission p ON p.menu_id = m.menu_id WHERE r.role_code IN ('SUPER_ADMIN', 'ADMIN') AND m.menu_code = 'SYSTEM_EXTERNAL_CALL' AND p.perm_code = 'READ' ON CONFLICT (role_id, menu_id, perm_code) DO NOTHING;