/*==========================================================================*/ /* SETTLE.pc - 정산확정 온라인 서비스 (As-Is 원본, Oracle Pro*C) */ /*--------------------------------------------------------------------------*/ /* 대상 : BC 매입시스템 / Tuxedo ATMI 서비스 SETTLE */ /* DBMS : Oracle 19c 전처리 : Pro*C/C++ (proc) */ /* 기능 : 매입건 정산 확정 — 정산원장(settlement) 채번·적재 + 원장 기표. */ /* ※ 이 파일은 **As-Is 역사 원본**이다. 현행 오픈스택 이식본은 */ /* app/src/st/svc/SETTLE.pgc (ECPG/PostgreSQL). 컴파일 제외. */ /*--------------------------------------------------------------------------*/ /* 변경이력 */ /* 2000.03.21 PARK J.S 최초작성 (정산확정 원장적재) */ /* 2006.09.14 HAN Y.J 가맹점 지급주기(D+n) DECODE 반영 */ /* 2012.05.08 LEE S.W 정산 중복확정 방지, ROWNUM 최근건 조회 */ /* 2019.09.01 CHOI H.W Oracle 11g -> 19c, 시퀀스/커밋 표준화 */ /*==========================================================================*/ #include #include #include #include #include EXEC SQL INCLUDE sqlca; EXEC SQL INCLUDE oraca; EXEC ORACLE OPTION (ORACA=YES); #include "stfld.h" EXEC SQL BEGIN DECLARE SECTION; VARCHAR h_merch[64]; VARCHAR h_bizdate[9]; /* YYYYMMDD */ VARCHAR h_pdate[9]; VARCHAR h_pstat[2]; VARCHAR h_paycyc[4]; /* 지급주기 코드 */ long h_pid; long h_sid; long h_amount; long h_fee; long h_net; long h_dcnt; long h_dup; long h_addday; EXEC SQL END DECLARE SECTION; /*--------------------------------------------------------------------------*/ /* SETTLE - Tuxedo 서비스 엔트리 */ /*--------------------------------------------------------------------------*/ void SETTLE(TPSVCINFO *rqst) { FBFR32 *fb = (FBFR32 *)rqst->data; char merch[64], bizdate[9]; userlog("SETTLE 진입: 정산 확정"); EXEC SQL WHENEVER SQLERROR GOTO sql_error; /* ---- 1) 요청 FML 파싱 -------------------------------------------- */ h_pid = Fvall(fb, ST_PURCHASE_ID, 0); h_net = Fvall(fb, ST_NET, 0); Fget(fb, ST_MERCHANT, 0, merch, (FLDLEN32 *)NULL); Fget(fb, ST_BIZDATE, 0, bizdate, (FLDLEN32 *)NULL); strcpy((char *)h_merch.arr, merch); h_merch.len = strlen(merch); strcpy((char *)h_bizdate.arr, bizdate); h_bizdate.len = strlen(bizdate); if (h_bizdate.len == 0) { EXEC SQL SELECT TO_CHAR(SYSDATE,'YYYYMMDD') INTO :h_bizdate FROM DUAL; } if (h_pid <= 0) { userlog("SETTLE: 매입 ID 필수 pid=%ld", h_pid); Fchg(fb, ST_RC, 0, (char *)"E802", 0L); tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L); return; } /* ---- 2) 매입 상태/금액 확인 + 정산액 보정 (NVL/DECODE) ----------- */ EXEC SQL SELECT NVL(p.amount,0), NVL(p.fee,0), NVL(p.net,:h_net), NVL(p.status,'A') INTO :h_amount, :h_fee, :h_net, :h_pstat FROM purchase p WHERE p.purchase_id = :h_pid; if (sqlca.sqlcode == 1403) { h_amount = Fvall(fb, ST_AMOUNT, 0); userlog("SETTLE: 미커밋 매입 pid=%ld — 전문 net=%ld 사용", h_pid, h_net); } /* ---- 3) 중복확정 방지: 동일 매입 확정 정산 존재여부 (ROWNUM) ---- */ EXEC SQL SELECT NVL(MAX(settlement_id),0) INTO :h_dup FROM settlement WHERE purchase_id = :h_pid AND status = 'SETTLED' AND ROWNUM = 1; if (h_dup > 0) { userlog("SETTLE: 이미 확정된 정산 pid=%ld sid=%ld — 스킵", h_pid, h_dup); Fchg(fb, ST_SETTLE_ID, 0, (char *)&h_dup, 0L); Fchg(fb, ST_STATUS, 0, (char *)"D", 0L); EXEC SQL COMMIT WORK; tpreturn(TPSUCCESS, 0, (char *)fb, 0L, 0L); return; } /* ---- 4) 가맹점 지급주기 조회 → 지급예정일 산정 (DECODE D+n) ----- */ EXEC SQL SELECT NVL(paycycle,'D1'), DECODE(NVL(paycycle,'D1'), 'D0',0, 'D1',1, 'D2',2, 'W1',7, 1) INTO :h_paycyc, :h_addday FROM merchant WHERE merchant_id = :h_merch; EXEC SQL SELECT TO_CHAR(TO_DATE(:h_bizdate,'YYYYMMDD') + :h_addday,'YYYYMMDD') INTO :h_pdate FROM DUAL; /* ---- 5) 본처리: 정산원장 채번(.NEXTVAL) 및 적재 ----------------- */ EXEC SQL SELECT settlement_seq.NEXTVAL INTO :h_sid FROM DUAL; EXEC SQL INSERT INTO settlement (settlement_id, purchase_id, merchant_id, net, biz_date, pay_date, status, created_at) VALUES (:h_sid, :h_pid, :h_merch, :h_net, TO_DATE(:h_bizdate,'YYYYMMDD'), TO_DATE(:h_pdate,'YYYYMMDD'), 'SETTLED', SYSDATE); /* ---- 6) 정산원장 기표 (ledger SETTLE 엔트리) ------------------- */ EXEC SQL INSERT INTO ledger (ledger_id, purchase_id, entry_type, amount, biz_date, posted_at) VALUES (ledger_seq.NEXTVAL, :h_pid, 'SETTLE', :h_net, TO_DATE(:h_bizdate,'YYYYMMDD'), SYSDATE); /* ---- 7) 매입 상태 정산완료 전이 ------------------------------- */ EXEC SQL UPDATE purchase SET status = 'S', settled_at = SYSDATE WHERE purchase_id = :h_pid AND status <> 'C'; /* ---- 8) 정산확정-수수료산출 연계 (PL/SQL 정산 패키지) ---------- */ EXEC SQL EXECUTE BEGIN pkg_settle.settle_confirm(:h_sid, :h_pid, :h_merch, :h_net); END; END-EXEC; EXEC SQL COMMIT WORK; Fchg(fb, ST_SETTLE_ID, 0, (char *)&h_sid, 0L); Fchg(fb, ST_NET, 0, (char *)&h_net, 0L); Fchg(fb, ST_STATUS, 0, (char *)"S", 0L); userlog("SETTLE 완료: pid=%ld sid=%ld net=%ld paydate=%.8s", h_pid, h_sid, h_net, h_pdate.arr); tpreturn(TPSUCCESS, 0, (char *)fb, 0L, 0L); return; sql_error: userlog("SETTLE SQL 오류: %.70s (sqlcode=%ld)", sqlca.sqlerrm.sqlerrmc, sqlca.sqlcode); EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL ROLLBACK WORK; Fchg(fb, ST_RC, 0, (char *)"E900", 0L); tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L); return; }