■ Oracle 계보 — "원본은 Oracle 19c + Pro*C 였다" 현행 코드(ECPG/PostgreSQL)가 Oracle 시스템의 1차 이관본임을 콘크리트하게 보존. - legacy-oracle/proc/*.pc (7본): ACQUIRE/AUTH_APPROVE/ST_MDR/SETTLE/RECONCILE/ CL_DAILY/PAY_FILEGEN. 순수 Oracle Pro*C 방언 — sqlca/oraca, VARCHAR, WHENEVER SQLERROR GOTO, NVL/DECODE/SYSDATE/DUAL/ROWNUM/(+)/CONNECT BY/ .NEXTVAL/TO_DATE, PL/SQL 패키지 호출, COMMIT WORK. 컴파일 대상 아님(As-Is 원본). - legacy-oracle/plsql/*.sql (2본): PKG_SETTLE(정산), PKG_LEDGER(복식부기 기표). VARCHAR2/%TYPE/%ROWTYPE/CURSOR/EXCEPTION/RAISE_APPLICATION_ERROR. - docs/ORACLE_PROVENANCE.md: As-Is(Oracle)→현행(ECPG)→To-Be(Spring Boot) 3단 계보 + Oracle→PostgreSQL 방언 이관 매핑 15종 + "왜 DB는 PostgreSQL인가". - gen_metrics.py: legacy-oracle 실측(원본 9파일 1,827LOC, 방언 12종 히트) → 마이그레이션 난이도 화면에 "④ Oracle 계보" 패널 추가. ■ 시스템 조망 재편 — 실제 매입시스템 운영 콘솔 "마이그레이션 난이도"(Forge 관점 메타)를 시스템 조망에서 분리하고, 시스템 자체의 상태·아키텍처를 보여주는 운영 화면 신설. - 신규 "시스템 현황"(#sys): 헬스 KPI(서버11/서비스1466/미결2PC/당일매입/채널UP/ 큐적체/오류) + 아키텍처 토폴로지(채널·카드망→전문GW→승인·매입→정산·지급→ 원장·마감·대사·검증→마스터·공통 계층도) + 채널상태 + 큐적체 + 처리량·오류율 + 정산사이클(마감·순액정산·클리어링·프레젠트먼트). 전부 실측 조회. - nav 재편: [시스템 조망]=시스템현황·아키텍처토폴로지·정산경제, [전환 분석(Forge)]=마이그레이션난이도. - 토폴로지 모듈박스 렌더 버그(return ASI) 수정. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
234 lines
9 KiB
PkgConfig
234 lines
9 KiB
PkgConfig
/*==========================================================================*/
|
|
/* AUTH_APPROVE.pc - 승인확정 온라인 서비스 (As-Is 원본, Oracle Pro*C) */
|
|
/*--------------------------------------------------------------------------*/
|
|
/* 대상 : BC 매입시스템 / Tuxedo ATMI 서비스 AUTH_APPROVE */
|
|
/* DBMS : Oracle 19c 전처리 : Pro*C/C++ (proc) */
|
|
/* 기능 : 승인 확정(pending->approved) — 원장 상태전이 + 카드 한도차감 */
|
|
/* ※ 이 파일은 **As-Is 역사 원본**이다. 현행 오픈스택 이식본은 */
|
|
/* app/src/au/svc/AUTH_APPROVE.pgc (ECPG/PostgreSQL). 컴파일 제외. */
|
|
/*--------------------------------------------------------------------------*/
|
|
/* 변경이력 */
|
|
/* 1999.05.12 KIM K.H 최초작성 (승인원장 확정전이) */
|
|
/* 2003.10.07 YOON D.H 블랙리스트/velocity 룰 추가, DECODE 등급분기 */
|
|
/* 2010.08.24 LEE S.W 당일 상태분포 재집계, au_summary 연계 */
|
|
/* 2016.02.19 JANG M.K 이상거래 점수(au_fraud_log) 반영 */
|
|
/* 2019.09.01 CHOI H.W Oracle 11g -> 19c, CHAR->VARCHAR2 정비 */
|
|
/*==========================================================================*/
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <atmi.h>
|
|
#include <fml32.h>
|
|
#include <userlog.h>
|
|
|
|
EXEC SQL INCLUDE sqlca;
|
|
EXEC SQL INCLUDE oraca;
|
|
EXEC ORACLE OPTION (ORACA=YES);
|
|
|
|
#include "aufld.h"
|
|
|
|
EXEC SQL BEGIN DECLARE SECTION;
|
|
VARCHAR h_card[24];
|
|
VARCHAR h_merch[64];
|
|
VARCHAR h_bizdate[9]; /* YYYYMMDD */
|
|
VARCHAR h_status[2];
|
|
VARCHAR h_cstat[16];
|
|
long h_auth;
|
|
long h_amount;
|
|
long h_delta;
|
|
long h_cnt;
|
|
long h_sum;
|
|
long h_appr;
|
|
long h_black;
|
|
long h_vel;
|
|
long h_risk;
|
|
long h_grade;
|
|
long h_mdr_bps;
|
|
long h_fee;
|
|
long h_vat;
|
|
long h_dlim;
|
|
long h_avail;
|
|
long h_led;
|
|
EXEC SQL END DECLARE SECTION;
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* AUTH_APPROVE - Tuxedo 서비스 엔트리 */
|
|
/*--------------------------------------------------------------------------*/
|
|
void AUTH_APPROVE(TPSVCINFO *rqst)
|
|
{
|
|
FBFR32 *fb = (FBFR32 *)rqst->data;
|
|
char card[24], merch[64];
|
|
long rc = 0;
|
|
TPINIT *tpi = (TPINIT *)NULL;
|
|
|
|
userlog("AUTH_APPROVE 진입: 승인 확정(pending->approved)");
|
|
EXEC SQL WHENEVER SQLERROR GOTO sql_error;
|
|
|
|
/* ---- 1) 요청 FML 파싱 -------------------------------------------- */
|
|
h_auth = Fvall(fb, AU_AUTH_ID, 0);
|
|
if (h_auth <= 0) {
|
|
userlog("AUTH_APPROVE: 식별자 범위오류 auth_id=%ld", h_auth);
|
|
Fchg(fb, AU_RC, 0, (char *)"E801", 0L);
|
|
tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
|
|
return;
|
|
}
|
|
h_delta = Fvall(fb, AU_DELTA, 0);
|
|
if (h_delta < 0) h_delta = -h_delta;
|
|
|
|
/* ---- 2) 대상 승인건 조회 (현재상태/금액/카드/영업일) -------------- */
|
|
/* 무마스터 승인 허용: 카드마스터는 외부조인 (+) 으로 등급만 취득 */
|
|
EXEC SQL
|
|
SELECT a.status,
|
|
NVL(a.amount, 0),
|
|
NVL(a.card_no, ' '),
|
|
TO_CHAR(NVL(a.biz_date, SYSDATE),'YYYYMMDD'),
|
|
DECODE(NVL(c.risk_grade,'B'), 'A',1, 'B',2, 'C',3, 9)
|
|
INTO :h_status, :h_amount, :h_card, :h_bizdate, :h_grade
|
|
FROM au_authorization a, card_master c
|
|
WHERE a.auth_id = :h_auth
|
|
AND c.card_no (+) = a.card_no;
|
|
|
|
if (sqlca.sqlcode == 1403) {
|
|
userlog("AUTH_APPROVE: 대상 승인건 없음 auth_id=%ld", h_auth);
|
|
Fchg(fb, AU_RC, 0, (char *)"E831", 0L);
|
|
tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
|
|
return;
|
|
}
|
|
strcpy(card, (char *)h_card.arr);
|
|
|
|
/* ---- 3) 전이 가능여부 분기 (허용 상태에서만 A 로 전이) ------------ */
|
|
if (strncmp((char *)h_status.arr, "A", 1) != 0 &&
|
|
strncmp((char *)h_status.arr, "P", 1) != 0) {
|
|
userlog("AUTH_APPROVE: 상태전이 불가 cur=%.1s auth_id=%ld",
|
|
h_status.arr, h_auth);
|
|
Fchg(fb, AU_RC, 0, (char *)"E833", 0L);
|
|
tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
|
|
return;
|
|
}
|
|
|
|
/* ---- 4) 본처리: 원장 상태전이 (+금액조정 델타) ------------------- */
|
|
EXEC SQL
|
|
UPDATE au_authorization
|
|
SET status = 'A', updated_at = SYSDATE
|
|
WHERE auth_id = :h_auth
|
|
AND status IN ('A','P');
|
|
if (sqlca.sqlerrd[2] == 0) {
|
|
userlog("AUTH_APPROVE: 반영건수 0 (경합/이미전이) auth_id=%ld", h_auth);
|
|
Fchg(fb, AU_RC, 0, (char *)"E835", 0L);
|
|
EXEC SQL ROLLBACK WORK;
|
|
tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
|
|
return;
|
|
}
|
|
if (h_delta > 0) {
|
|
EXEC SQL
|
|
UPDATE au_authorization
|
|
SET amount = amount + :h_delta, updated_at = SYSDATE
|
|
WHERE auth_id = :h_auth;
|
|
h_amount += h_delta;
|
|
}
|
|
|
|
/* ---- 5) 카드 당일 상태분포 재집계 (한도판정 기초) --------------- */
|
|
EXEC SQL
|
|
SELECT COUNT(*), NVL(SUM(amount),0),
|
|
NVL(SUM(DECODE(status,'A',1,0)),0)
|
|
INTO :h_cnt, :h_sum, :h_appr
|
|
FROM au_authorization
|
|
WHERE card_no = :h_card
|
|
AND biz_date = TO_DATE(:h_bizdate,'YYYYMMDD');
|
|
|
|
/* ---- 6) 업무규칙: 블랙리스트/카드상태/velocity/부정점수 --------- */
|
|
EXEC SQL
|
|
SELECT COUNT(*) INTO :h_black
|
|
FROM au_blacklist
|
|
WHERE card_no = :h_card;
|
|
if (h_black > 0) { rc = 91; userlog("AUTH_APPROVE: 블랙리스트 적중 card=%s", card); }
|
|
|
|
EXEC SQL
|
|
SELECT NVL(MAX(status),'NONE'), NVL(MAX(avail_limit),0)
|
|
INTO :h_cstat, :h_avail
|
|
FROM card_limit
|
|
WHERE card_no = :h_card;
|
|
if (strncmp((char *)h_cstat.arr, "ACTIVE", 6) != 0 &&
|
|
strncmp((char *)h_cstat.arr, "NONE", 4) != 0) {
|
|
if (rc == 0) rc = 92;
|
|
userlog("AUTH_APPROVE: 카드상태 비정상 card=%s status=%.8s", card, h_cstat.arr);
|
|
}
|
|
|
|
EXEC SQL
|
|
SELECT COUNT(*) INTO :h_vel
|
|
FROM au_authorization
|
|
WHERE card_no = :h_card
|
|
AND created_at > SYSDATE - 1/24;
|
|
if (h_vel >= 10) { if (rc == 0) rc = 93;
|
|
userlog("AUTH_APPROVE: velocity 경보 card=%s 1시간 %ld건", card, h_vel); }
|
|
|
|
EXEC SQL
|
|
SELECT NVL(MAX(score),0) INTO :h_risk
|
|
FROM au_fraud_log
|
|
WHERE card_no = :h_card
|
|
AND ROWNUM <= 100;
|
|
if (h_risk >= 90) userlog("AUTH_APPROVE: 고위험 카드 card=%s 최고점=%ld", card, h_risk);
|
|
|
|
/* ---- 7) 상태전이 이력 적재 (감사원장, 시퀀스 .NEXTVAL 채번) ----- */
|
|
EXEC SQL SELECT au_audit_seq.NEXTVAL INTO :h_led FROM DUAL;
|
|
EXEC SQL
|
|
INSERT INTO au_audit
|
|
(audit_id, auth_id, card_no, from_status, to_status,
|
|
amount, audit_rc, created_at)
|
|
VALUES (:h_led, :h_auth, :h_card, :h_status, 'A',
|
|
:h_amount, :rc, SYSDATE);
|
|
|
|
/* ---- 8) 가맹점 당일 승인 집계 (au_summary upsert, PL/SQL) ------ */
|
|
Fget(fb, AU_MERCHANT, 0, merch, (FLDLEN32 *)NULL);
|
|
strcpy((char *)h_merch.arr, merch); h_merch.len = strlen(merch);
|
|
if (h_merch.len > 0) {
|
|
EXEC SQL
|
|
SELECT COUNT(*),
|
|
NVL(SUM(DECODE(status,'A',1,0)),0),
|
|
NVL(SUM(amount),0)
|
|
INTO :h_cnt, :h_appr, :h_sum
|
|
FROM au_authorization
|
|
WHERE merchant_id = :h_merch
|
|
AND biz_date = TO_DATE(:h_bizdate,'YYYYMMDD');
|
|
EXEC SQL EXECUTE
|
|
BEGIN
|
|
pkg_settle.upsert_auth_summary(:h_merch, :h_bizdate,
|
|
:h_cnt, :h_appr, :h_sum);
|
|
END;
|
|
END-EXEC;
|
|
}
|
|
|
|
/* ---- 9) 정산 참고치: MDR 수수료/부가세 (DECODE 요율) ------------ */
|
|
EXEC SQL
|
|
SELECT NVL(m.mdr_bps, 25) INTO :h_mdr_bps
|
|
FROM merchant m
|
|
WHERE m.merchant_id = :h_merch;
|
|
h_fee = ROUND(h_amount * h_mdr_bps / 10000);
|
|
h_vat = ROUND(h_fee / 10);
|
|
|
|
/* ---- 10) 업무체인: 승인확정 한도차감 (LIMIT_DEC PL/SQL 패키지) -- */
|
|
EXEC SQL EXECUTE
|
|
BEGIN
|
|
pkg_settle.limit_dec(:h_card, :h_amount, :h_avail);
|
|
END;
|
|
END-EXEC;
|
|
|
|
EXEC SQL COMMIT WORK;
|
|
|
|
Fchg(fb, AU_STATUS, 0, (char *)"A", 0L);
|
|
Fchg(fb, AU_FEE, 0, (char *)&h_fee, 0L);
|
|
Fchg(fb, AU_AVAIL, 0, (char *)&h_avail, 0L);
|
|
Fchg(fb, AU_RC, 0, (char *)&rc, 0L);
|
|
userlog("AUTH_APPROVE 완료: auth_id=%ld amt=%ld fee=%ld rc=%ld",
|
|
h_auth, h_amount, h_fee, rc);
|
|
tpreturn(TPSUCCESS, 0, (char *)fb, 0L, 0L);
|
|
return;
|
|
|
|
sql_error:
|
|
userlog("AUTH_APPROVE SQL 오류: %.70s (sqlcode=%ld)",
|
|
sqlca.sqlerrm.sqlerrmc, sqlca.sqlcode);
|
|
EXEC SQL WHENEVER SQLERROR CONTINUE;
|
|
EXEC SQL ROLLBACK WORK;
|
|
Fchg(fb, AU_RC, 0, (char *)"E900", 0L);
|
|
tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
|
|
return;
|
|
}
|