/*==========================================================================*/ /* 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 #include #include #include #include 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; }