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
247
legacy-oracle/proc/PAY_FILEGEN.pc
Normal file
247
legacy-oracle/proc/PAY_FILEGEN.pc
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
/*==========================================================================*/
|
||||
/* PAY_FILEGEN.pc - 지급파일 생성 배치 (As-Is 원본, Oracle Pro*C) */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* 대상 : BC 매입시스템 / 지급(펌뱅킹) 파일 생성 배치 PAYFGEN */
|
||||
/* DBMS : Oracle 19c 전처리 : Pro*C/C++ (proc) */
|
||||
/* 실행 : payfgen <YYYYMMDD> (인자 생략시 SYSDATE) */
|
||||
/* 기능 : 당일 승인(A) 지급건을 커서로 스윕하여 py_file 헤더 채번 + */
|
||||
/* 평문 지급레코드를 UTL_FILE 로 디스크 파일에 기록(펌뱅킹 규격). */
|
||||
/* ※ 이 파일은 **As-Is 역사 원본**이다. 현행 오픈스택 이식본은 */
|
||||
/* app/src/py/svc/PAY_FILEGEN.pgc (ECPG/PostgreSQL, Tuxedo 서비스화; */
|
||||
/* 디스크 I/O 는 별도 xfer 로 분리됨). 컴파일 대상 아님(빌드 제외). */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* 변경이력 */
|
||||
/* 2000.07.03 KIM K.H 최초작성 (전은행 공통 지급파일 EBCDIC->ASCII) */
|
||||
/* 2006.12.20 PARK J.S 정책 파라미터(cm_param) 기반 최대건수 분할 */
|
||||
/* 2013.04.09 LEE S.W UTL_FILE 로 헤더/명세/트레일러 3레코드 규격화 */
|
||||
/* 2019.09.01 CHOI H.W Oracle 11g -> 19c, CHAR->VARCHAR2 정비 */
|
||||
/*==========================================================================*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
EXEC SQL INCLUDE sqlca;
|
||||
EXEC SQL INCLUDE oraca;
|
||||
EXEC ORACLE OPTION (ORACA=YES);
|
||||
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
VARCHAR h_user[32];
|
||||
VARCHAR h_pass[32];
|
||||
VARCHAR h_dbstr[32];
|
||||
VARCHAR h_bizdate[9]; /* YYYYMMDD */
|
||||
VARCHAR h_fname[64];
|
||||
VARCHAR h_dir[32];
|
||||
VARCHAR h_bankcd[4];
|
||||
VARCHAR h_acctno[20];
|
||||
VARCHAR h_merch[16];
|
||||
VARCHAR h_line[256];
|
||||
VARCHAR h_pval[16];
|
||||
long h_fileid;
|
||||
long h_payid;
|
||||
long h_amount;
|
||||
long h_fee;
|
||||
long h_net;
|
||||
long h_reccnt;
|
||||
long h_totamt;
|
||||
long h_thr;
|
||||
long h_seq;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
/* 당일 승인(A) 지급 대상 커서 — 계좌 마스터 외부조인으로 은행/계좌 획득 */
|
||||
EXEC SQL DECLARE cur_pay CURSOR FOR
|
||||
SELECT p.payout_id,
|
||||
p.merchant_id,
|
||||
NVL(a.bank_code, '000'),
|
||||
NVL(a.account_no, 'X'),
|
||||
NVL(p.amount, 0),
|
||||
NVL(p.fee, 0),
|
||||
NVL(p.net, 0)
|
||||
FROM py_payout p, py_account a
|
||||
WHERE a.merchant_id (+) = p.merchant_id
|
||||
AND p.biz_date = TO_DATE(:h_bizdate,'YYYYMMDD')
|
||||
AND p.status = 'A'
|
||||
ORDER BY p.merchant_id, p.payout_id;
|
||||
|
||||
static void sql_error(const char *stage);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int done = 0;
|
||||
|
||||
strcpy((char *)h_user.arr, "pybatch"); h_user.len = strlen((char *)h_user.arr);
|
||||
strcpy((char *)h_pass.arr, "pybatch"); h_pass.len = strlen((char *)h_pass.arr);
|
||||
strcpy((char *)h_dbstr.arr, "ACQPRD"); h_dbstr.len = strlen((char *)h_dbstr.arr);
|
||||
|
||||
EXEC SQL WHENEVER SQLERROR GOTO connect_err;
|
||||
EXEC SQL CONNECT :h_user IDENTIFIED BY :h_pass USING :h_dbstr;
|
||||
EXEC SQL WHENEVER SQLERROR GOTO sqlfail;
|
||||
|
||||
/* ---- 1) 영업일 결정 -------------------------------------------- */
|
||||
if (argc >= 2) {
|
||||
strncpy((char *)h_bizdate.arr, argv[1], 8);
|
||||
h_bizdate.arr[8] = '\0';
|
||||
h_bizdate.len = strlen((char *)h_bizdate.arr);
|
||||
} else {
|
||||
EXEC SQL SELECT TO_CHAR(SYSDATE,'YYYYMMDD') INTO :h_bizdate FROM DUAL;
|
||||
}
|
||||
printf("[PAY_FILEGEN] 지급파일 생성 개시 bizdate=%.8s\n", h_bizdate.arr);
|
||||
|
||||
/* ---- 2) 편성 대상 사전집계 (건수/총액) ------------------------- */
|
||||
EXEC SQL
|
||||
SELECT COUNT(*), NVL(SUM(net), 0)
|
||||
INTO :h_reccnt, :h_totamt
|
||||
FROM py_payout
|
||||
WHERE biz_date = TO_DATE(:h_bizdate,'YYYYMMDD')
|
||||
AND status = 'A';
|
||||
if (h_reccnt == 0) {
|
||||
printf("[PAY_FILEGEN] 편성 대상 승인건 없음 - 파일생성 생략\n");
|
||||
EXEC SQL ROLLBACK WORK RELEASE;
|
||||
return 0;
|
||||
}
|
||||
if (h_totamt <= 0) {
|
||||
fprintf(stderr, "[PAY_FILEGEN] 편성 총액 비정상 amt=%ld\n", h_totamt);
|
||||
EXEC SQL ROLLBACK WORK RELEASE;
|
||||
return 4;
|
||||
}
|
||||
|
||||
/* ---- 3) 정책 파라미터 조회 (최대 레코드수) — NVL 널가드 --------- */
|
||||
EXEC SQL
|
||||
SELECT NVL(MAX(param_val), '100000')
|
||||
INTO :h_pval
|
||||
FROM cm_param
|
||||
WHERE param_key = 'pay_filegen_max_rec';
|
||||
h_thr = atol((char *)h_pval.arr);
|
||||
if (h_thr <= 0) h_thr = 100000;
|
||||
if (h_reccnt > h_thr) {
|
||||
fprintf(stderr, "[PAY_FILEGEN] 최대 레코드수 초과 %ld > %ld - 분할 필요\n",
|
||||
h_reccnt, h_thr);
|
||||
EXEC SQL ROLLBACK WORK RELEASE;
|
||||
return 5;
|
||||
}
|
||||
|
||||
/* ---- 4) 파일 채번 및 헤더행 적재 (시퀀스 .NEXTVAL) ------------- */
|
||||
EXEC SQL SELECT py_file_seq.NEXTVAL INTO :h_fileid FROM DUAL;
|
||||
sprintf((char *)h_fname.arr, "PAYOUT_%.8s_%ld.dat",
|
||||
h_bizdate.arr, h_fileid);
|
||||
h_fname.len = strlen((char *)h_fname.arr);
|
||||
strcpy((char *)h_dir.arr, "PAYOUT_OUT"); /* DIRECTORY 객체명 */
|
||||
h_dir.len = strlen((char *)h_dir.arr);
|
||||
|
||||
EXEC SQL
|
||||
INSERT INTO py_file
|
||||
(file_id, biz_date, file_name, record_count, total_amount, status, created_at)
|
||||
VALUES (:h_fileid, TO_DATE(:h_bizdate,'YYYYMMDD'), :h_fname,
|
||||
:h_reccnt, :h_totamt, 'G', SYSDATE);
|
||||
|
||||
/* UTL_FILE 로 파일 오픈 후 헤더레코드('H') 기록 (PL/SQL 익명블록) */
|
||||
EXEC SQL EXECUTE
|
||||
BEGIN
|
||||
pkg_payfile.open_file(:h_dir, :h_fname);
|
||||
pkg_payfile.put_header(:h_bizdate, :h_reccnt, :h_totamt);
|
||||
END;
|
||||
END-EXEC;
|
||||
|
||||
/* ---- 5) 본처리: 지급건 커서 루프 + 명세레코드('D') 기록 -------- */
|
||||
h_seq = 0;
|
||||
EXEC SQL OPEN cur_pay;
|
||||
for (;;) {
|
||||
EXEC SQL WHENEVER NOTFOUND DO done = 1;
|
||||
EXEC SQL FETCH cur_pay
|
||||
INTO :h_payid, :h_merch, :h_bankcd, :h_acctno,
|
||||
:h_amount, :h_fee, :h_net;
|
||||
if (done) break;
|
||||
|
||||
h_seq += 1;
|
||||
|
||||
/* 무계좌(외부조인 미스) 건은 파일에서 제외하고 보류 전이 */
|
||||
if (strncmp((char *)h_bankcd.arr, "000", 3) == 0) {
|
||||
printf("[PAY_FILEGEN] 계좌미등록 payout=%ld merch=%.*s - 보류전이\n",
|
||||
h_payid, h_merch.len, h_merch.arr);
|
||||
EXEC SQL
|
||||
UPDATE py_payout
|
||||
SET status = 'H', updated_at = SYSDATE
|
||||
WHERE payout_id = :h_payid;
|
||||
h_seq -= 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 펌뱅킹 명세레코드 조립 (고정폭: 구분1 은행3 계좌20 금액13) */
|
||||
sprintf((char *)h_line.arr, "D%3.3s%-20.20s%013ld",
|
||||
h_bankcd.arr, h_acctno.arr, h_net);
|
||||
h_line.len = strlen((char *)h_line.arr);
|
||||
|
||||
EXEC SQL EXECUTE
|
||||
BEGIN
|
||||
pkg_payfile.put_line(:h_line);
|
||||
END;
|
||||
END-EXEC;
|
||||
|
||||
/* 지급건을 이 파일로 편성 ('A'->'F') */
|
||||
EXEC SQL
|
||||
UPDATE py_payout
|
||||
SET file_id = :h_fileid,
|
||||
status = DECODE(status, 'A', 'F', status),
|
||||
updated_at = SYSDATE
|
||||
WHERE payout_id = :h_payid;
|
||||
|
||||
if (h_seq % 1000 == 0) {
|
||||
printf("[PAY_FILEGEN] 진행 %ld건 편성 - 중간커밋\n", h_seq);
|
||||
EXEC SQL COMMIT WORK;
|
||||
}
|
||||
}
|
||||
EXEC SQL CLOSE cur_pay;
|
||||
|
||||
/* ---- 6) 트레일러('T') 기록 및 파일 클로즈 --------------------- */
|
||||
EXEC SQL EXECUTE
|
||||
BEGIN
|
||||
pkg_payfile.put_trailer(:h_seq, :h_totamt);
|
||||
pkg_payfile.close_file;
|
||||
END;
|
||||
END-EXEC;
|
||||
|
||||
/* ---- 7) 파일헤더 확정 (실제 기록건수 반영, 'G'->'C') ----------- */
|
||||
EXEC SQL
|
||||
UPDATE py_file
|
||||
SET record_count = :h_seq,
|
||||
status = 'C',
|
||||
closed_at = SYSDATE
|
||||
WHERE file_id = :h_fileid;
|
||||
|
||||
EXEC SQL
|
||||
INSERT INTO cm_log (log_id, svc_name, log_level, msg, biz_date)
|
||||
VALUES (cm_log_seq.NEXTVAL, 'PAY_FILEGEN', 'I',
|
||||
'PAY_FILEGEN file='||:h_fileid||' name='||:h_fname
|
||||
||' rec='||:h_seq||' amt='||:h_totamt,
|
||||
TO_DATE(:h_bizdate,'YYYYMMDD'));
|
||||
|
||||
/* ---- 8) 최종 커밋 --------------------------------------------- */
|
||||
EXEC SQL COMMIT WORK;
|
||||
|
||||
printf("[PAY_FILEGEN] 완료 file=%ld name=%.*s rec=%ld amt=%ld\n",
|
||||
h_fileid, h_fname.len, h_fname.arr, h_seq, h_totamt);
|
||||
EXEC SQL COMMIT WORK RELEASE;
|
||||
return 0;
|
||||
|
||||
connect_err:
|
||||
fprintf(stderr, "[PAY_FILEGEN] DB 접속 실패: %.70s\n", sqlca.sqlerrm.sqlerrmc);
|
||||
return 8;
|
||||
|
||||
sqlfail:
|
||||
sql_error("지급파일 생성");
|
||||
/* UTL_FILE 핸들 정리 (best-effort) */
|
||||
EXEC SQL WHENEVER SQLERROR CONTINUE;
|
||||
EXEC SQL EXECUTE BEGIN pkg_payfile.close_file; END; END-EXEC;
|
||||
EXEC SQL ROLLBACK WORK RELEASE;
|
||||
return 12;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* sql_error - 오류 로깅 (sqlca/oraca) */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static void sql_error(const char *stage)
|
||||
{
|
||||
fprintf(stderr, "[PAY_FILEGEN] SQL 오류 (%s): %.70s\n",
|
||||
stage, sqlca.sqlerrm.sqlerrmc);
|
||||
fprintf(stderr, " sqlcode=%ld rows=%ld\n",
|
||||
sqlca.sqlcode, sqlca.sqlerrd[2]);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue