■ 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>
177 lines
6.9 KiB
PkgConfig
177 lines
6.9 KiB
PkgConfig
/*==========================================================================*/
|
|
/* ACQUIRE.pc - 매입 접수 온라인 서비스 (As-Is 원본, Oracle Pro*C) */
|
|
/*--------------------------------------------------------------------------*/
|
|
/* 대상 : BC 매입시스템 / Tuxedo ATMI 서비스 ACQUIRE */
|
|
/* DBMS : Oracle 19c 전처리 : Pro*C/C++ (proc) */
|
|
/* ※ 이 파일은 **As-Is 역사 원본**이다. 현행 오픈스택 이식본은 */
|
|
/* app/src/ac/svc/ACQUIRE.pgc (ECPG/PostgreSQL). 대조는 */
|
|
/* docs/ORACLE_PROVENANCE.md 참조. 컴파일 대상 아님(빌드 제외). */
|
|
/*--------------------------------------------------------------------------*/
|
|
/* 변경이력 */
|
|
/* 1998.11.02 KIM K.H 최초작성 (신용승인 연계 매입) */
|
|
/* 2004.06.18 PARK J.S 체크카드 매입구분 추가, DECODE 요율분기 */
|
|
/* 2011.03.30 LEE S.W 원천징수(3.3%) 반영, 세금계산서 연계 */
|
|
/* 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);
|
|
|
|
/* 전역 FML 필드 ID (FLD.h 에서 생성) */
|
|
#include "acqfld.h"
|
|
|
|
EXEC SQL BEGIN DECLARE SECTION;
|
|
VARCHAR h_merch[16];
|
|
VARCHAR h_name[64];
|
|
VARCHAR h_status[2];
|
|
VARCHAR h_bizdate[9]; /* YYYYMMDD */
|
|
VARCHAR h_cardtype[2]; /* C=신용 K=체크 */
|
|
long h_amount;
|
|
long h_limit;
|
|
long h_daysum;
|
|
long h_daycnt;
|
|
long h_mdr_bps;
|
|
long h_fee;
|
|
long h_net;
|
|
long h_wht; /* 원천징수액 */
|
|
long h_pid;
|
|
long h_grade;
|
|
EXEC SQL END DECLARE SECTION;
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* ACQUIRE - Tuxedo 서비스 엔트리 */
|
|
/*--------------------------------------------------------------------------*/
|
|
void ACQUIRE(TPSVCINFO *rqst)
|
|
{
|
|
FBFR32 *fb = (FBFR32 *)rqst->data;
|
|
char merch[16], bizdate[9];
|
|
long amount;
|
|
|
|
userlog("ACQUIRE 진입: 매입 접수 요청");
|
|
|
|
/* Pro*C 오류는 즉시 라벨분기 (전형적 레거시 패턴) */
|
|
EXEC SQL WHENEVER SQLERROR GOTO sql_error;
|
|
|
|
/* ---- 1) 요청 FML 파싱 -------------------------------------------- */
|
|
Fget(fb, ACQ_MERCHANT, 0, merch, (FLDLEN32 *)NULL);
|
|
Fget(fb, ACQ_BIZDATE, 0, bizdate, (FLDLEN32 *)NULL);
|
|
amount = Fvall(fb, ACQ_AMOUNT, 0);
|
|
|
|
strcpy((char *)h_merch.arr, merch); h_merch.len = strlen(merch);
|
|
strcpy((char *)h_bizdate.arr, bizdate); h_bizdate.len = strlen(bizdate);
|
|
h_amount = amount;
|
|
|
|
if (h_amount <= 0) {
|
|
Fchg(fb, ACQ_RC, 0, (char *)"E101", 0L);
|
|
tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
|
|
return;
|
|
}
|
|
|
|
/* 영업일 미지정시 시스템일자 (Oracle SYSDATE) */
|
|
if (h_bizdate.len == 0) {
|
|
EXEC SQL SELECT TO_CHAR(SYSDATE,'YYYYMMDD') INTO :h_bizdate FROM DUAL;
|
|
}
|
|
|
|
/* ---- 2) 가맹점 마스터 조회 (NVL 로 널가드) ----------------------- */
|
|
EXEC SQL
|
|
SELECT m.name,
|
|
NVL(m.status,'N'),
|
|
NVL(m.daily_limit, 0),
|
|
NVL(m.mdr_bps, 25),
|
|
DECODE(m.risk_grade, 'A',1, 'B',2, 'C',3, 9)
|
|
INTO :h_name, :h_status, :h_limit, :h_mdr_bps, :h_grade
|
|
FROM merchant m
|
|
WHERE m.merchant_id = :h_merch;
|
|
|
|
if (strncmp((char *)h_status.arr, "A", 1) != 0) {
|
|
userlog("ACQUIRE: 비활성 가맹점 %s status=%.1s", merch, h_status.arr);
|
|
Fchg(fb, ACQ_RC, 0, (char *)"E203", 0L);
|
|
tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
|
|
return;
|
|
}
|
|
|
|
/* ---- 3) 당일 누적 매입 조회 (한도 점검용) ------------------------ */
|
|
EXEC SQL
|
|
SELECT COUNT(*), NVL(SUM(amount), 0)
|
|
INTO :h_daycnt, :h_daysum
|
|
FROM purchase
|
|
WHERE merchant_id = :h_merch
|
|
AND biz_date = TO_DATE(:h_bizdate,'YYYYMMDD')
|
|
AND status <> 'C';
|
|
|
|
if (h_daysum + h_amount > h_limit) {
|
|
userlog("ACQUIRE: 일한도 초과 merch=%s sum=%ld+%ld > %ld",
|
|
merch, h_daysum, h_amount, h_limit);
|
|
Fchg(fb, ACQ_RC, 0, (char *)"E210", 0L);
|
|
tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
|
|
return;
|
|
}
|
|
|
|
/* ---- 4) 수수료/원천/정산액 산출 (DECODE 카드구분 요율) ----------- */
|
|
/* 카드종류는 승인원장 조인으로 (외부조인 (+) — 무승인 매입 허용) */
|
|
EXEC SQL
|
|
SELECT NVL(a.card_type, 'C')
|
|
INTO :h_cardtype
|
|
FROM au_authorization a
|
|
WHERE a.auth_id (+) = :h_pid;
|
|
|
|
h_fee = h_amount * h_mdr_bps / 10000;
|
|
/* 병의원/약국(원천징수 대상 업종)만 3.3% 원천 (DECODE 업종분기) */
|
|
EXEC SQL
|
|
SELECT DECODE(mcc.risk_level, 1, ROUND(:h_amount * 33 / 1000), 0)
|
|
INTO :h_wht
|
|
FROM mm_merch_mcc mm, mm_mcc mcc
|
|
WHERE mm.merchant_id = :h_merch
|
|
AND mcc.mcc = mm.mcc
|
|
AND ROWNUM = 1;
|
|
|
|
h_net = h_amount - h_fee - h_wht;
|
|
|
|
/* ---- 5) 매입원장 채번 및 적재 (시퀀스 .NEXTVAL) ------------------ */
|
|
EXEC SQL SELECT purchase_seq.NEXTVAL INTO :h_pid FROM DUAL;
|
|
|
|
EXEC SQL
|
|
INSERT INTO purchase
|
|
(purchase_id, merchant_id, amount, fee, net, wht,
|
|
status, biz_date, created_at)
|
|
VALUES (:h_pid, :h_merch, :h_amount, :h_fee, :h_net, :h_wht,
|
|
'A', TO_DATE(:h_bizdate,'YYYYMMDD'), SYSDATE);
|
|
|
|
EXEC SQL
|
|
INSERT INTO approval (approval_id, purchase_id, approved, approved_at)
|
|
VALUES (approval_seq.NEXTVAL, :h_pid, 'Y', SYSDATE);
|
|
|
|
/* ---- 6) 정산 PL/SQL 패키지 호출 (묶음 정산 연계) ----------------- */
|
|
EXEC SQL EXECUTE
|
|
BEGIN
|
|
pkg_settle.acquire_post(:h_pid, :h_merch, :h_amount, :h_fee, :h_net);
|
|
END;
|
|
END-EXEC;
|
|
|
|
/* ---- 7) 커밋 및 응답 -------------------------------------------- */
|
|
EXEC SQL COMMIT WORK;
|
|
|
|
Fchg(fb, ACQ_PURCHASE_ID, 0, (char *)&h_pid, 0L);
|
|
Fchg(fb, ACQ_FEE, 0, (char *)&h_fee, 0L);
|
|
Fchg(fb, ACQ_NET, 0, (char *)&h_net, 0L);
|
|
Fchg(fb, ACQ_STATUS, 0, (char *)"S", 0L);
|
|
|
|
userlog("ACQUIRE 완료: pid=%ld fee=%ld wht=%ld net=%ld", h_pid, h_fee, h_wht, h_net);
|
|
tpreturn(TPSUCCESS, 0, (char *)fb, 0L, 0L);
|
|
return;
|
|
|
|
sql_error:
|
|
userlog("ACQUIRE SQL 오류: %.70s (sqlcode=%ld)",
|
|
sqlca.sqlerrm.sqlerrmc, sqlca.sqlcode);
|
|
EXEC SQL WHENEVER SQLERROR CONTINUE;
|
|
EXEC SQL ROLLBACK WORK;
|
|
Fchg(fb, ACQ_RC, 0, (char *)"E900", 0L);
|
|
tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
|
|
return;
|
|
}
|