Wave H: Oracle 계보(As-Is) 심기 + 시스템 조망 재편(운영 콘솔)
■ 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>
This commit is contained in:
parent
2ac4c3c920
commit
e1729d6edc
14 changed files with 2054 additions and 7 deletions
224
legacy-oracle/proc/RECONCILE.pc
Normal file
224
legacy-oracle/proc/RECONCILE.pc
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
/*==========================================================================*/
|
||||
/* RECONCILE.pc - 대사(對査) 온라인 서비스 (As-Is 원본, Oracle Pro*C) */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* 대상 : BC 매입시스템 / Tuxedo ATMI 서비스 RECONCILE */
|
||||
/* DBMS : Oracle 19c 전처리 : Pro*C/C++ (proc) */
|
||||
/* 기능 : 당일 매입 vs 원장 대사 — 커서순회 매칭분류 + 예외적재 + 정산연계. */
|
||||
/* ※ 이 파일은 **As-Is 역사 원본**이다. 현행 오픈스택 이식본은 */
|
||||
/* app/src/rc/svc/RECONCILE.pgc (ECPG/PostgreSQL). 컴파일 제외. */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* 변경이력 */
|
||||
/* 2001.07.16 SEO K.T 최초작성 (일 매입-원장 대사) */
|
||||
/* 2005.12.02 HAN Y.J 허용오차(tolerance) 매칭 도입, DECODE 등급 */
|
||||
/* 2009.04.27 LEE S.W 조직/코드 트리 CONNECT BY 집계 추가 */
|
||||
/* 2015.10.13 JANG M.K 예외원장(rc_exception) 분리, 감사로그 표준화 */
|
||||
/* 2019.09.01 CHOI H.W Oracle 11g -> 19c, 커서/시퀀스 정비 */
|
||||
/*==========================================================================*/
|
||||
#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 "rcfld.h"
|
||||
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
VARCHAR h_bizdate[9]; /* YYYYMMDD */
|
||||
VARCHAR h_merch[64];
|
||||
VARCHAR h_status[16];
|
||||
VARCHAR h_pstat[2];
|
||||
VARCHAR h_orgcode[16]; /* 조직/코드 트리 루트 */
|
||||
VARCHAR h_orgname[64];
|
||||
long h_pid;
|
||||
long h_amt;
|
||||
long h_fee;
|
||||
long h_net;
|
||||
long h_act;
|
||||
long h_exp;
|
||||
long h_gross;
|
||||
long h_cnt;
|
||||
long h_mcnt;
|
||||
long h_ecnt;
|
||||
long h_mdr_bps;
|
||||
long h_limit;
|
||||
long h_led;
|
||||
long h_lvl; /* 코드트리 계층레벨 */
|
||||
long h_orgsum;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* RECONCILE - Tuxedo 서비스 엔트리 */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void RECONCILE(TPSVCINFO *rqst)
|
||||
{
|
||||
FBFR32 *fb = (FBFR32 *)rqst->data;
|
||||
char bizdate[9], merch[64];
|
||||
long tol = 0, rc_code = 0, adiff = 0;
|
||||
long scan_rows = 0, matched = 0, unmatched = 0, unmatched_amt = 0;
|
||||
|
||||
userlog("RECONCILE 진입: 당일 매입-원장 대사");
|
||||
EXEC SQL WHENEVER SQLERROR GOTO sql_error;
|
||||
|
||||
/* ---- 1) 입력 검증 ------------------------------------------------ */
|
||||
Fget(fb, RC_BIZDATE, 0, bizdate, (FLDLEN32 *)NULL);
|
||||
if (strlen(bizdate) < 8) {
|
||||
EXEC SQL SELECT TO_CHAR(SYSDATE,'YYYYMMDD') INTO :h_bizdate FROM DUAL;
|
||||
strcpy(bizdate, (char *)h_bizdate.arr);
|
||||
}
|
||||
strcpy((char *)h_bizdate.arr, bizdate); h_bizdate.len = strlen(bizdate);
|
||||
h_pid = Fvall(fb, RC_PURCHASE_ID, 0);
|
||||
h_net = Fvall(fb, RC_NET, 0);
|
||||
|
||||
/* ---- 2) 마스터/정책 조회 (미커밋 매입은 전문값, 외부조인 (+)) ---- */
|
||||
EXEC SQL
|
||||
SELECT NVL(p.amount,0), NVL(p.fee,0), NVL(p.net,:h_net),
|
||||
NVL(p.status,'A'), NVL(m.merchant_id, ' '),
|
||||
NVL(m.mdr_bps, 25), NVL(m.daily_limit, 100000000)
|
||||
INTO :h_amt, :h_fee, :h_net, :h_pstat, :h_merch, :h_mdr_bps, :h_limit
|
||||
FROM purchase p, merchant m
|
||||
WHERE p.purchase_id = :h_pid
|
||||
AND m.merchant_id (+) = p.merchant_id;
|
||||
if (sqlca.sqlcode == 1403) {
|
||||
h_amt = Fvall(fb, RC_AMOUNT, 0);
|
||||
h_fee = Fvall(fb, RC_FEE, 0);
|
||||
h_net = Fvall(fb, RC_NET, 0);
|
||||
Fget(fb, RC_MERCHANT, 0, merch, (FLDLEN32 *)NULL);
|
||||
strcpy((char *)h_merch.arr, merch); h_merch.len = strlen(merch);
|
||||
h_mdr_bps = 25; h_limit = 100000000;
|
||||
userlog("RECONCILE: 체인 신규매입(미커밋) pid=%ld — 전문값 대사", h_pid);
|
||||
}
|
||||
|
||||
/* ---- 3) 당일 매입/대사로그/예외 집계 (NVL 널가드) --------------- */
|
||||
EXEC SQL
|
||||
SELECT COUNT(*), NVL(SUM(amount),0)
|
||||
INTO :h_cnt, :h_gross
|
||||
FROM purchase
|
||||
WHERE biz_date = TO_DATE(:h_bizdate,'YYYYMMDD');
|
||||
EXEC SQL
|
||||
SELECT COUNT(*) INTO :h_mcnt
|
||||
FROM rc_match_log
|
||||
WHERE biz_date = TO_DATE(:h_bizdate,'YYYYMMDD')
|
||||
AND status = 'MATCHED';
|
||||
EXEC SQL
|
||||
SELECT COUNT(*) INTO :h_ecnt
|
||||
FROM rc_exception
|
||||
WHERE biz_date = TO_DATE(:h_bizdate,'YYYYMMDD')
|
||||
AND resolved = 'N';
|
||||
|
||||
/* ---- 4) 거래집합 커서순회 + 허용오차 매칭분류 ------------------- */
|
||||
EXEC SQL DECLARE cur_reconcile CURSOR FOR
|
||||
SELECT p.purchase_id, NVL(p.net,0)
|
||||
FROM purchase p
|
||||
WHERE p.biz_date = TO_DATE(:h_bizdate,'YYYYMMDD')
|
||||
ORDER BY p.purchase_id;
|
||||
EXEC SQL OPEN cur_reconcile;
|
||||
for (;;) {
|
||||
EXEC SQL WHENEVER NOTFOUND DO break;
|
||||
EXEC SQL FETCH cur_reconcile INTO :h_pid, :h_exp;
|
||||
EXEC SQL
|
||||
SELECT NVL(SUM(amount),0) INTO :h_act
|
||||
FROM ledger
|
||||
WHERE purchase_id = :h_pid
|
||||
AND entry_type IN ('RECON','SETTLE');
|
||||
adiff = h_exp - h_act;
|
||||
if (adiff < 0) adiff = -adiff;
|
||||
scan_rows++;
|
||||
if (adiff <= (tol > 0 ? tol : 0)) matched++;
|
||||
else { unmatched++; unmatched_amt += adiff; }
|
||||
}
|
||||
EXEC SQL WHENEVER NOTFOUND CONTINUE;
|
||||
EXEC SQL CLOSE cur_reconcile;
|
||||
userlog("RECONCILE 대사스캔: scan=%ld match=%ld unmatch=%ld",
|
||||
scan_rows, matched, unmatched);
|
||||
|
||||
/* ---- 5) 조직/코드 트리 집계 (계층질의 CONNECT BY PRIOR) --------- */
|
||||
/* 가맹점이 속한 정산조직 코드트리를 루트→하위로 전개하여 소속 조직의 */
|
||||
/* 당일 정산 순액 합계를 취득한다(대사 대상 조직 범위 확정용). */
|
||||
EXEC SQL
|
||||
SELECT NVL(org_code,'ROOT'), NVL(org_name,'-')
|
||||
INTO :h_orgcode, :h_orgname
|
||||
FROM rc_org_map
|
||||
WHERE merchant_id = :h_merch
|
||||
AND ROWNUM = 1;
|
||||
if (sqlca.sqlcode == 1403) { strcpy((char *)h_orgcode.arr, "ROOT");
|
||||
h_orgcode.len = 4; }
|
||||
EXEC SQL
|
||||
SELECT NVL(SUM(s.net),0), NVL(MAX(LEVEL),1)
|
||||
INTO :h_orgsum, :h_lvl
|
||||
FROM settlement s, rc_org o
|
||||
WHERE s.biz_date = TO_DATE(:h_bizdate,'YYYYMMDD')
|
||||
AND s.org_code = o.org_code
|
||||
AND o.org_code IN (
|
||||
SELECT org_code
|
||||
FROM rc_org
|
||||
START WITH org_code = :h_orgcode
|
||||
CONNECT BY PRIOR org_code = parent_code);
|
||||
userlog("RECONCILE 코드트리: org=%.8s depth=%ld 정산합=%ld",
|
||||
h_orgcode.arr, h_lvl, h_orgsum);
|
||||
|
||||
/* ---- 6) 업무규칙 분기 (매칭율 기반 상태판정, DECODE) ------------- */
|
||||
if (h_gross <= 0 && scan_rows == 0) {
|
||||
rc_code = 0; strcpy((char *)h_status.arr, "NODATA");
|
||||
} else if (unmatched == 0) {
|
||||
rc_code = 0; strcpy((char *)h_status.arr, "MATCHED");
|
||||
} else if (unmatched * 100 <= (scan_rows > 0 ? scan_rows : 1) * 5) {
|
||||
rc_code = 1; strcpy((char *)h_status.arr, "TOLERATED");
|
||||
} else {
|
||||
rc_code = 2; strcpy((char *)h_status.arr, "EXCEPTION");
|
||||
}
|
||||
h_status.len = strlen((char *)h_status.arr);
|
||||
/* 감사 심각도 라벨 (DECODE 코드분기) */
|
||||
EXEC SQL
|
||||
SELECT DECODE(:rc_code, 0,'I', 1,'W', 2,'E', 'X')
|
||||
INTO :h_pstat
|
||||
FROM DUAL;
|
||||
|
||||
/* ---- 7) 본처리: RECON 원장 적재 (.NEXTVAL 채번) ---------------- */
|
||||
EXEC SQL SELECT ledger_seq.NEXTVAL INTO :h_led FROM DUAL;
|
||||
EXEC SQL
|
||||
INSERT INTO ledger
|
||||
(ledger_id, purchase_id, entry_type, amount, biz_date, posted_at)
|
||||
VALUES (:h_led, :h_pid, 'RECON', :h_net,
|
||||
TO_DATE(:h_bizdate,'YYYYMMDD'), SYSDATE);
|
||||
|
||||
/* ---- 8) 불일치 예외 적재 + 감사로그 (PL/SQL 대사 패키지) -------- */
|
||||
if (rc_code >= 2) {
|
||||
EXEC SQL
|
||||
INSERT INTO rc_exception
|
||||
(exc_id, biz_date, merchant_id, unmatch_cnt, unmatch_amt,
|
||||
resolved, created_at)
|
||||
VALUES (rc_exception_seq.NEXTVAL, TO_DATE(:h_bizdate,'YYYYMMDD'),
|
||||
:h_merch, :unmatched, :unmatched_amt, 'N', SYSDATE);
|
||||
}
|
||||
EXEC SQL EXECUTE
|
||||
BEGIN
|
||||
pkg_settle.recon_audit(:h_bizdate, :h_merch, :scan_rows,
|
||||
:matched, :unmatched, :rc_code);
|
||||
END;
|
||||
END-EXEC;
|
||||
|
||||
EXEC SQL COMMIT WORK;
|
||||
|
||||
/* ---- 9) 응답부 ------------------------------------------------- */
|
||||
Fchg(fb, RC_STATUS, 0, (char *)h_status.arr, 0L);
|
||||
Fchg(fb, RC_MATCHED, 0, (char *)&matched, 0L);
|
||||
Fchg(fb, RC_UNMATCHED, 0, (char *)&unmatched, 0L);
|
||||
Fchg(fb, RC_RC, 0, (char *)&rc_code, 0L);
|
||||
userlog("RECONCILE 완료: biz=%.8s status=%.10s rc=%ld orgsum=%ld",
|
||||
h_bizdate.arr, h_status.arr, rc_code, h_orgsum);
|
||||
tpreturn(TPSUCCESS, 0, (char *)fb, 0L, 0L);
|
||||
return;
|
||||
|
||||
sql_error:
|
||||
userlog("RECONCILE SQL 오류: %.70s (sqlcode=%ld)",
|
||||
sqlca.sqlerrm.sqlerrmc, sqlca.sqlcode);
|
||||
EXEC SQL WHENEVER SQLERROR CONTINUE;
|
||||
EXEC SQL ROLLBACK WORK;
|
||||
Fchg(fb, RC_RC, 0, (char *)"E900", 0L);
|
||||
tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
|
||||
return;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue