Phase 2c: 전 11모듈 per-service 레거시 구조 분해·확장 (실동작 유지)

- 10개 모듈(au py rc st lg cl mm vl mg cm)을 ac 템플릿대로 분해:
  svc/ 30 서비스 .pgc + 카피북 .h, 얇은 <mod>_svr 디스패처
  dbio/ ~25 .pgc(+.h), batch/ ~17 .pgc, run/ ~17 .sh (모듈마다)
- 파일: svc 330 + dbio 276 + batch 187 + run 187, 총 소스 1602본
- 서비스별 고유 실로직(정규화 md5), build.sh 자동발견(inline/split 양립)
- 통합 검증: build DONE modules=11 servers=11 batches=187, 12서버 runok,
  333 서비스 AVAIL, 매입체인 XA 커밋(status=S), prepared_xacts=0

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
forge-bot 2026-07-19 11:58:44 +00:00
parent c3b99a8b75
commit fd8b418c6e
1404 changed files with 30322 additions and 5994 deletions

View file

@ -1,53 +1,56 @@
/*
* au_svr.pgc - au (승인/한도) MODULE SERVER.
* au_svr.pgc - au (승인/한도) MODULE SERVER (thin dispatcher).
*
* ONE binary that tpadvertise()s ALL ~30 online au services (the real Tuxedo
* "one module server, many services" pattern). Every service is a distinct
* 승인/한도 operation with genuine EXEC SQL (directly, or via the linked
* libaudbio.a dbio layer) and common math from libacqcommon.a.
* The legacy "one module server, many services" pattern: this binary owns NO
* business logic. Each of au's ~30 online services now lives in its own file
* (app/src/au/svc/<SVCNAME>.pgc) with its own copybook header
* (app/src/au/svc/<SVCNAME>.h); those objects are archived into libausvc.a and
* linked into this server. Here we only:
* - include every service copybook (for the extern prototypes),
* - tpopen() the ECPG XA RM,
* - tpadvertise() all services from a {name, fn} table,
* - tpclose() at shutdown.
*
* XA: the connection is opened once by tpopen() (ECPG XA switch); there is NO
* EXEC SQL CONNECT. Owner-writes discipline: services in this server never
* tpcall each other; each owns its tables on this process's XA branch.
* XA: the connection is opened once by tpopen() (ECPG XA switch libndrxxaecpg.so);
* there is NO EXEC SQL CONNECT. Each tpcall runs on this process's XA branch.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include <ubf.h>
#include <userlog.h>
#include <ndebug.h>
#include "acq.fd.h"
#include "au_dbio.h"
#include "acq_common.h"
/* ----- small UBF helpers ------------------------------------------------- */
static long getl(UBFH *b, BFLDID f) { long v = 0; Bget(b, f, 0, (char *)&v, 0L); return v; }
static void gets_(UBFH *b, BFLDID f, char *out, int cap)
{ BFLDLEN l = cap; out[0] = 0; Bget(b, f, 0, out, &l); }
static void setl(UBFH *b, BFLDID f, long v) { Bchg(b, f, 0, (char *)&v, 0L); }
/* every au service's copybook header (declares its record struct + prototype) */
#include "AUTH.h"
#include "AUTH_CANCEL.h"
#include "AUTH_PARTCXL.h"
#include "LIMIT_CHK.h"
#include "LIMIT_DEC.h"
#include "LIMIT_RST.h"
#include "LIMIT_INQ.h"
#include "STANDIN.h"
#include "FRAUD_DETECT.h"
#include "AUTH_RETRY.h"
#include "INSTALL_AUTH.h"
#include "AUTH_STATUS.h"
#include "AUTH_REVERSE.h"
#include "AUTH_APPROVE.h"
#include "AUTH_DECLINE.h"
#include "CARD_VALIDATE.h"
#include "VELOCITY_CHK.h"
#include "BLACKLIST_CHK.h"
#include "AUTH_HOLD.h"
#include "AUTH_RELEASE.h"
#include "AUTH_HISTORY.h"
#include "LIMIT_SET.h"
#include "LIMIT_TEMP.h"
#include "AUTH_SUMMARY.h"
#include "AUTH_ROUTE.h"
#include "DCC_QUOTE.h"
#include "AUTH_CAPTURE.h"
#include "PREAUTH.h"
#include "PREAUTH_COMPLETE.h"
#include "AUTH_VOID.h"
#define FAIL(b) do { tpreturn(TPFAIL, 0, (char *)(b), 0L, 0L); return; } while (0)
#define OK(b) do { tpreturn(TPSUCCESS, 0, (char *)(b), 0L, 0L); return; } while (0)
/* ----- service prototypes ------------------------------------------------ */
void AUTH(TPSVCINFO *p); void AUTH_CANCEL(TPSVCINFO *p);
void AUTH_PARTCXL(TPSVCINFO *p); void LIMIT_CHK(TPSVCINFO *p);
void LIMIT_DEC(TPSVCINFO *p); void LIMIT_RST(TPSVCINFO *p);
void LIMIT_INQ(TPSVCINFO *p); void STANDIN(TPSVCINFO *p);
void FRAUD_DETECT(TPSVCINFO *p); void AUTH_RETRY(TPSVCINFO *p);
void INSTALL_AUTH(TPSVCINFO *p); void AUTH_STATUS(TPSVCINFO *p);
void AUTH_REVERSE(TPSVCINFO *p); void AUTH_APPROVE(TPSVCINFO *p);
void AUTH_DECLINE(TPSVCINFO *p); void CARD_VALIDATE(TPSVCINFO *p);
void VELOCITY_CHK(TPSVCINFO *p); void BLACKLIST_CHK(TPSVCINFO *p);
void AUTH_HOLD(TPSVCINFO *p); void AUTH_RELEASE(TPSVCINFO *p);
void AUTH_HISTORY(TPSVCINFO *p); void LIMIT_SET(TPSVCINFO *p);
void LIMIT_TEMP(TPSVCINFO *p); void AUTH_SUMMARY(TPSVCINFO *p);
void AUTH_ROUTE(TPSVCINFO *p); void DCC_QUOTE(TPSVCINFO *p);
void AUTH_CAPTURE(TPSVCINFO *p); void PREAUTH(TPSVCINFO *p);
void PREAUTH_COMPLETE(TPSVCINFO *p); void AUTH_VOID(TPSVCINFO *p);
/* ----- advertise table (this is what "scales to 30" cleanly) ------------- */
/* ----- advertise table: {service name, function} (fn is extern from its file) */
static struct { const char *name; void (*fn)(TPSVCINFO *); } SVCS[] = {
{"AUTH", AUTH}, {"AUTH_CANCEL", AUTH_CANCEL},
{"AUTH_PARTCXL", AUTH_PARTCXL}, {"LIMIT_CHK", LIMIT_CHK},
@ -90,571 +93,4 @@ void tpsvrdone(void)
userlog("au_svr: tpsvrdone");
}
/* ========================================================================= */
/* 1. AUTH - 승인 접수: 한도 점검 후 authorization 원장 기록 + 한도 차감. */
/* ========================================================================= */
void AUTH(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24], merch[64], bizdate[16], appr[12];
long amount, auth_id, lim = 0, used = 0;
gets_(b, T_KEY1, card, sizeof(card));
if (card[0] == 0) { userlog("AUTH: T_KEY1(카드번호) 누락"); FAIL(b); }
gets_(b, T_MERCHANT, merch, sizeof(merch));
amount = getl(b, T_AMOUNT);
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
/* 한도 점검: 초과면 거절(D) 상태로 기록 */
if (audb_limit_get(card, &lim, &used) < 0) FAIL(b);
if (used + amount > lim) {
userlog("AUTH 한도초과 card=%s used=%ld amt=%ld lim=%ld -> 거절", card, used, amount, lim);
auth_id = audb_next_auth_id();
if (auth_id < 0) FAIL(b);
if (audb_insert_auth(auth_id, card, merch, amount, "000000", "AUTH", "D", bizdate) < 0) FAIL(b);
setl(b, T_ID1, auth_id);
setl(b, T_RC, 1);
Bchg(b, T_STATUS, 0, "D", 0L);
OK(b);
}
auth_id = audb_next_auth_id();
if (auth_id < 0) FAIL(b);
sprintf(appr, "%06ld", auth_id % 1000000);
if (audb_insert_auth(auth_id, card, merch, amount, appr, "AUTH", "A", bizdate) < 0) FAIL(b);
if (audb_limit_dec(card, amount) < 0) FAIL(b);
setl(b, T_ID1, auth_id);
setl(b, T_RC, 0);
Bchg(b, T_STR2, 0, appr, 0L);
Bchg(b, T_STATUS, 0, "A", 0L);
userlog("AUTH 승인 auth_id=%ld card=%s merch=%s amt=%ld appr=%s", auth_id, card, merch, amount, appr);
OK(b);
}
/* 2. AUTH_CANCEL - 승인 전체 취소 + 한도 원복. */
void AUTH_CANCEL(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24], bizdate[16], reason[128];
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_auth, h_amt;
char h_card[24], h_bizdate[16], h_reason[128];
EXEC SQL END DECLARE SECTION;
h_auth = getl(b, T_ID1);
h_amt = getl(b, T_AMOUNT);
gets_(b, T_KEY1, card, sizeof(card));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
gets_(b, T_REASON, reason, sizeof(reason)); if (reason[0] == 0) strcpy(reason, "CUSTOMER");
strncpy(h_card, card, sizeof(h_card)-1); h_card[sizeof(h_card)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
strncpy(h_reason, reason, sizeof(h_reason)-1); h_reason[sizeof(h_reason)-1] = 0;
EXEC SQL SELECT nextval('au_cancel_seq') INTO :h_id;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL INSERT INTO au_cancel (cancel_id, auth_id, cancel_type, amount, reason, biz_date)
VALUES (:h_id, :h_auth, 'FULL', :h_amt, :h_reason, :h_bizdate);
if (sqlca.sqlcode < 0) FAIL(b);
if (audb_update_auth_status(h_auth, "C") < 0) FAIL(b);
if (card[0] && audb_limit_dec(card, -h_amt) < 0) FAIL(b);
setl(b, T_CANCEL_ID, h_id);
Bchg(b, T_STATUS, 0, "C", 0L);
OK(b);
}
/* 3. AUTH_PARTCXL - 부분 취소: 승인 금액 감액 + 한도 부분 원복. */
void AUTH_PARTCXL(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24], bizdate[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_auth, h_amt, h_new;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
h_auth = getl(b, T_ID1);
h_amt = getl(b, T_AMOUNT); /* 취소 금액 */
gets_(b, T_KEY1, card, sizeof(card));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT amount INTO :h_new FROM au_authorization WHERE auth_id = :h_auth;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
h_new = h_new - h_amt;
EXEC SQL SELECT nextval('au_cancel_seq') INTO :h_id;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL INSERT INTO au_cancel (cancel_id, auth_id, cancel_type, amount, reason, biz_date)
VALUES (:h_id, :h_auth, 'PARTIAL', :h_amt, 'PARTIAL', :h_bizdate);
if (sqlca.sqlcode < 0) FAIL(b);
if (audb_update_auth_amount(h_auth, h_new) < 0) FAIL(b);
if (card[0] && audb_limit_dec(card, -h_amt) < 0) FAIL(b);
setl(b, T_CANCEL_ID, h_id);
setl(b, T_AMOUNT, h_new);
OK(b);
}
/* 4. LIMIT_CHK - 카드 한도 점검 (사용가능 여부만 리턴). */
void LIMIT_CHK(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24];
long amount, lim = 0, used = 0;
gets_(b, T_KEY1, card, sizeof(card));
amount = getl(b, T_AMOUNT);
if (audb_limit_get(card, &lim, &used) < 0) FAIL(b);
setl(b, T_AMT1, lim);
setl(b, T_AMT2, used);
setl(b, T_RC, (used + amount > lim) ? 1 : 0);
OK(b);
}
/* 5. LIMIT_DEC - 한도 차감(사용금액 증가). */
void LIMIT_DEC(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24];
long amount = getl(b, T_AMOUNT);
gets_(b, T_KEY1, card, sizeof(card));
if (audb_limit_dec(card, amount) < 0) FAIL(b);
OK(b);
}
/* 6. LIMIT_RST - 한도 사용금액 초기화(일마감 원복). */
void LIMIT_RST(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24];
gets_(b, T_KEY1, card, sizeof(card));
if (audb_limit_reset(card) < 0) FAIL(b);
OK(b);
}
/* 7. LIMIT_INQ - 한도 조회 (가용한도 계산). */
void LIMIT_INQ(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24];
long lim = 0, used = 0;
gets_(b, T_KEY1, card, sizeof(card));
if (audb_limit_get(card, &lim, &used) < 0) FAIL(b);
setl(b, T_AMT1, lim);
setl(b, T_AMT2, used);
setl(b, T_AMT3, lim - used); /* 가용한도 */
OK(b);
}
/* 8. STANDIN - 발급사 무응답 시 대리승인(STANDIN, 소액 한도 내). */
void STANDIN(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24], merch[64], bizdate[16];
long amount, auth_id, stand_lim = 50000;
gets_(b, T_KEY1, card, sizeof(card));
gets_(b, T_MERCHANT, merch, sizeof(merch));
amount = getl(b, T_AMOUNT);
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
if (amount > stand_lim) { setl(b, T_RC, 1); Bchg(b, T_STATUS, 0, "D", 0L); OK(b); }
auth_id = audb_next_auth_id();
if (auth_id < 0) FAIL(b);
if (audb_insert_auth(auth_id, card, merch, amount, "STDIN0", "STANDIN", "A", bizdate) < 0) FAIL(b);
setl(b, T_ID1, auth_id);
setl(b, T_RC, 0);
Bchg(b, T_STATUS, 0, "A", 0L);
OK(b);
}
/* 9. FRAUD_DETECT - 부정거래 스코어링 + 위험시 fraud_log 기록. */
void FRAUD_DETECT(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24], bizdate[16], reason[128];
long auth_id, amount, score = 0, fraud_id;
EXEC SQL BEGIN DECLARE SECTION;
long h_cnt;
char h_card[24];
EXEC SQL END DECLARE SECTION;
auth_id = getl(b, T_ID1);
amount = getl(b, T_AMOUNT);
gets_(b, T_KEY1, card, sizeof(card));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_card, card, sizeof(h_card)-1); h_card[sizeof(h_card)-1] = 0;
/* 룰: 고액 + 당일 승인건수 과다 = 스코어 상승 */
if (amount > 1000000) score += 50;
EXEC SQL SELECT count(*) INTO :h_cnt FROM au_authorization WHERE card_no = :h_card;
if (sqlca.sqlcode < 0) FAIL(b);
if (h_cnt > 5) score += 40;
score += (h_cnt * 2);
strcpy(reason, score >= 50 ? "HIGH_RISK" : "OK");
setl(b, T_ARG1, score);
if (score >= 50) {
fraud_id = audb_insert_fraud(auth_id, card, score, reason, bizdate);
if (fraud_id < 0) FAIL(b);
setl(b, T_ID2, fraud_id);
setl(b, T_RC, 1);
} else {
setl(b, T_RC, 0);
}
OK(b);
}
/* 10. AUTH_RETRY - 거절 승인 재시도 (상태 D->A 재승인). */
void AUTH_RETRY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24];
long auth_id = getl(b, T_ID1), amount = getl(b, T_AMOUNT), lim = 0, used = 0;
gets_(b, T_KEY1, card, sizeof(card));
if (audb_limit_get(card, &lim, &used) < 0) FAIL(b);
if (used + amount > lim) { setl(b, T_RC, 1); FAIL(b); }
if (audb_update_auth_status(auth_id, "A") < 0) FAIL(b);
if (audb_limit_dec(card, amount) < 0) FAIL(b);
setl(b, T_RC, 0);
Bchg(b, T_STATUS, 0, "A", 0L);
OK(b);
}
/* 11. INSTALL_AUTH - 할부 승인: 개월 수만큼 분할 승인 레코드. */
void INSTALL_AUTH(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24], merch[64], bizdate[16];
long months, amount, i, auth_id;
gets_(b, T_KEY1, card, sizeof(card));
gets_(b, T_MERCHANT, merch, sizeof(merch));
amount = getl(b, T_AMOUNT);
months = getl(b, T_INSTALL_N); if (months < 1) months = 3;
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
for (i = 1; i <= months; i++) {
auth_id = audb_next_auth_id();
if (auth_id < 0) FAIL(b);
if (audb_insert_auth(auth_id, card, merch, amount / months, "INST00", "INSTALL", "A", bizdate) < 0) FAIL(b);
}
if (audb_limit_dec(card, amount) < 0) FAIL(b);
setl(b, T_COUNT, months);
OK(b);
}
/* 12. AUTH_STATUS - 승인 상태 조회 (dbio). */
void AUTH_STATUS(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long auth_id = getl(b, T_ID1);
char st[4];
if (audb_get_auth_status(auth_id, st) < 0) FAIL(b);
Bchg(b, T_STATUS, 0, st, 0L);
OK(b);
}
/* 13. AUTH_REVERSE - 승인 역전(reversal) + 한도 원복. */
void AUTH_REVERSE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24];
long auth_id = getl(b, T_ID1), amount = getl(b, T_AMOUNT);
gets_(b, T_KEY1, card, sizeof(card));
if (audb_update_auth_status(auth_id, "R") < 0) FAIL(b);
if (card[0] && audb_limit_dec(card, -amount) < 0) FAIL(b);
Bchg(b, T_STATUS, 0, "R", 0L);
OK(b);
}
/* 14. AUTH_APPROVE - 승인 확정(pending->approved). */
void AUTH_APPROVE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long auth_id = getl(b, T_ID1);
if (audb_update_auth_status(auth_id, "A") < 0) FAIL(b);
Bchg(b, T_STATUS, 0, "A", 0L);
OK(b);
}
/* 15. AUTH_DECLINE - 승인 거절 처리. */
void AUTH_DECLINE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char reason[128];
EXEC SQL BEGIN DECLARE SECTION;
long h_auth;
char h_reason[128];
EXEC SQL END DECLARE SECTION;
h_auth = getl(b, T_ID1);
gets_(b, T_REASON, reason, sizeof(reason)); if (reason[0] == 0) strcpy(reason, "DECLINE");
strncpy(h_reason, reason, sizeof(h_reason)-1); h_reason[sizeof(h_reason)-1] = 0;
EXEC SQL UPDATE au_authorization SET status = 'D', decline_reason = :h_reason, updated_at = now()
WHERE auth_id = :h_auth;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
Bchg(b, T_STATUS, 0, "D", 0L);
OK(b);
}
/* 16. CARD_VALIDATE - 카드번호 Luhn 검증 (common lib). */
void CARD_VALIDATE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24];
gets_(b, T_KEY1, card, sizeof(card));
setl(b, T_RC, acq_luhn_ok(card) ? 0 : 1);
OK(b);
}
/* 17. VELOCITY_CHK - 속도(velocity) 점검: 당일 카드 승인건수/합계. */
void VELOCITY_CHK(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24], bizdate[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_cnt, h_sum;
char h_card[24], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_KEY1, card, sizeof(card));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_card, card, sizeof(h_card)-1); h_card[sizeof(h_card)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT count(*), coalesce(sum(amount),0) INTO :h_cnt, :h_sum
FROM au_authorization WHERE card_no = :h_card AND biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_COUNT, h_cnt);
setl(b, T_GROSS, h_sum);
setl(b, T_RC, (h_cnt > 10) ? 1 : 0);
OK(b);
}
/* 18. BLACKLIST_CHK - 블랙리스트 카드 조회. */
void BLACKLIST_CHK(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24];
EXEC SQL BEGIN DECLARE SECTION;
long h_cnt;
char h_card[24];
EXEC SQL END DECLARE SECTION;
gets_(b, T_KEY1, card, sizeof(card));
strncpy(h_card, card, sizeof(h_card)-1); h_card[sizeof(h_card)-1] = 0;
EXEC SQL SELECT count(*) INTO :h_cnt FROM au_blacklist WHERE card_no = :h_card;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_RC, (h_cnt > 0) ? 1 : 0);
OK(b);
}
/* 19. AUTH_HOLD - 승인 보류. */
void AUTH_HOLD(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long auth_id = getl(b, T_ID1);
if (audb_update_auth_status(auth_id, "H") < 0) FAIL(b);
Bchg(b, T_STATUS, 0, "H", 0L);
OK(b);
}
/* 20. AUTH_RELEASE - 보류 해제. */
void AUTH_RELEASE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long auth_id = getl(b, T_ID1);
if (audb_update_auth_status(auth_id, "A") < 0) FAIL(b);
Bchg(b, T_STATUS, 0, "A", 0L);
OK(b);
}
/* 21. AUTH_HISTORY - 카드 승인 이력 건수 조회. */
void AUTH_HISTORY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24];
EXEC SQL BEGIN DECLARE SECTION;
long h_cnt;
char h_card[24];
EXEC SQL END DECLARE SECTION;
gets_(b, T_KEY1, card, sizeof(card));
strncpy(h_card, card, sizeof(h_card)-1); h_card[sizeof(h_card)-1] = 0;
EXEC SQL SELECT count(*) INTO :h_cnt FROM au_authorization WHERE card_no = :h_card;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_COUNT, h_cnt);
OK(b);
}
/* 22. LIMIT_SET - 카드 한도 설정/등록 (dbio upsert). */
void LIMIT_SET(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24];
long lim = getl(b, T_AMT1);
gets_(b, T_KEY1, card, sizeof(card));
if (lim <= 0) lim = 1000000;
if (audb_limit_set(card, lim) < 0) FAIL(b);
OK(b);
}
/* 23. LIMIT_TEMP - 임시 한도 상향 (temp_limit 저장 + 당일 상향). */
void LIMIT_TEMP(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24];
EXEC SQL BEGIN DECLARE SECTION;
long h_temp;
char h_card[24];
EXEC SQL END DECLARE SECTION;
gets_(b, T_KEY1, card, sizeof(card));
h_temp = getl(b, T_AMT1); if (h_temp <= 0) h_temp = 2000000;
strncpy(h_card, card, sizeof(h_card)-1); h_card[sizeof(h_card)-1] = 0;
EXEC SQL UPDATE card_limit
SET temp_limit = :h_temp, daily_limit = daily_limit + :h_temp, updated_at = now()
WHERE card_no = :h_card;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
OK(b);
}
/* 24. AUTH_SUMMARY - 가맹점 당일 승인 집계 upsert (dbio). */
void AUTH_SUMMARY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_cnt, h_appr, h_dec, h_amt;
char h_merch[64], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT count(*),
count(*) FILTER (WHERE status = 'A'),
count(*) FILTER (WHERE status = 'D'),
coalesce(sum(amount),0)
INTO :h_cnt, :h_appr, :h_dec, :h_amt
FROM au_authorization WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
if (audb_upsert_auth_summary(merch, bizdate, h_cnt, h_appr, h_dec, h_amt) < 0) FAIL(b);
setl(b, T_COUNT, h_cnt);
setl(b, T_GROSS, h_amt);
OK(b);
}
/* 25. AUTH_ROUTE - 승인 라우팅(발급사 BIN 기준 라우팅 코드 산출). */
void AUTH_ROUTE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24], route[8];
long bin;
gets_(b, T_KEY1, card, sizeof(card));
bin = atol(card) / 1000000000L; /* 앞 6자리 근사 BIN */
if (card[0] == '4') strcpy(route, "VISA");
else if (card[0] == '5') strcpy(route, "MC");
else if (card[0] == '3') strcpy(route, "AMEX");
else strcpy(route, "LOCAL");
Bchg(b, T_STR1, 0, route, 0L);
setl(b, T_ARG1, bin);
OK(b);
}
/* 26. DCC_QUOTE - 해외승인 DCC 환산 견적(통화 -> 원화). */
void DCC_QUOTE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char ccy[8];
long fx, rate = 1350, krw;
fx = getl(b, T_FX_AMT);
gets_(b, T_CCY, ccy, sizeof(ccy)); if (ccy[0] == 0) strcpy(ccy, "USD");
krw = fx * rate / 100;
setl(b, T_AMOUNT, krw);
setl(b, T_ARG1, rate);
OK(b);
}
/* 27. AUTH_CAPTURE - 승인 매입확정(capture): 상태 A->M(매입대상). */
void AUTH_CAPTURE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_auth;
EXEC SQL END DECLARE SECTION;
h_auth = getl(b, T_ID1);
EXEC SQL UPDATE au_authorization SET status = 'M', captured_at = now(), updated_at = now()
WHERE auth_id = :h_auth AND status = 'A';
if (sqlca.sqlcode < 0) FAIL(b);
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); FAIL(b); }
setl(b, T_RC, 0);
Bchg(b, T_STATUS, 0, "M", 0L);
OK(b);
}
/* 28. PREAUTH - 예비승인(pre-authorization) 기록. */
void PREAUTH(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24], merch[64], bizdate[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_amt;
char h_card[24], h_merch[64], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_KEY1, card, sizeof(card));
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
h_amt = getl(b, T_AMOUNT);
strncpy(h_card, card, sizeof(h_card)-1); h_card[sizeof(h_card)-1] = 0;
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT nextval('au_preauth_seq') INTO :h_id;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL INSERT INTO au_preauth (preauth_id, card_no, merchant_id, amount, status, biz_date)
VALUES (:h_id, :h_card, :h_merch, :h_amt, 'P', :h_bizdate);
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_ID2, h_id);
OK(b);
}
/* 29. PREAUTH_COMPLETE - 예비승인 확정: preauth 소진 + 본승인 생성. */
void PREAUTH_COMPLETE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16];
long auth_id;
EXEC SQL BEGIN DECLARE SECTION;
long h_pre, h_amt;
char h_card[24], h_merch[64], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
h_pre = getl(b, T_ID2);
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT card_no, merchant_id, amount INTO :h_card, :h_merch, :h_amt
FROM au_preauth WHERE preauth_id = :h_pre;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
EXEC SQL UPDATE au_preauth SET status = 'C' WHERE preauth_id = :h_pre;
if (sqlca.sqlcode < 0) FAIL(b);
auth_id = audb_next_auth_id();
if (auth_id < 0) FAIL(b);
if (audb_insert_auth(auth_id, h_card, h_merch, h_amt, "PRECMP", "PREAUTH", "A", bizdate) < 0) FAIL(b);
setl(b, T_ID1, auth_id);
OK(b);
}
/* 30. AUTH_VOID - 당일 승인 무효화(void) + 한도 원복. */
void AUTH_VOID(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24], bizdate[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_auth, h_amt;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
h_auth = getl(b, T_ID1); h_amt = getl(b, T_AMOUNT);
gets_(b, T_KEY1, card, sizeof(card));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT nextval('au_cancel_seq') INTO :h_id;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL INSERT INTO au_cancel (cancel_id, auth_id, cancel_type, amount, reason, biz_date)
VALUES (:h_id, :h_auth, 'VOID', :h_amt, 'VOID', :h_bizdate);
if (sqlca.sqlcode < 0) FAIL(b);
if (audb_update_auth_status(h_auth, "V") < 0) FAIL(b);
if (card[0] && audb_limit_dec(card, -h_amt) < 0) FAIL(b);
setl(b, T_CANCEL_ID, h_id);
Bchg(b, T_STATUS, 0, "V", 0L);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,41 @@
/*
* au_blacklist_promote_batch.pgc - au 고위험 카드 블랙리스트 승격 (INSERT..SELECT, XA).
*
* Promotes cards with high fraud scores into au_blacklist via a single set-based
* INSERT..SELECT (ON CONFLICT skip), under ONE global XA transaction.
* Usage: au_blacklist_promote_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "au_dbio.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
long rows = 0;
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL INSERT INTO au_blacklist (card_no, reason, biz_date)
SELECT DISTINCT card_no, 'HIGH_FRAUD_SCORE', :h_bizdate
FROM au_fraud_log WHERE biz_date = :h_bizdate AND score >= 80
ON CONFLICT (card_no) DO NOTHING;
if (sqlca.sqlcode < 0) { fprintf(stderr, "au_blacklist_promote_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
rows = sqlca.sqlerrd[2];
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> au_blacklist_promote_batch COMMIT: bizdate=%s promoted=%ld\n", bizdate, rows);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,40 @@
/*
* au_cancel_daily_batch.pgc - au 일일 취소 집계 (다중 집계 배치, XA).
*
* Runs two sequential EXEC SQL aggregates (FULL then PARTIAL cancel sums) on the
* biz_date under ONE global XA transaction. Usage: au_cancel_daily_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "au_dbio.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_full, h_part;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT coalesce(sum(amount),0) INTO :h_full FROM au_cancel
WHERE biz_date = :h_bizdate AND cancel_type = 'FULL';
if (sqlca.sqlcode < 0) { fprintf(stderr, "FULL agg FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
EXEC SQL SELECT coalesce(sum(amount),0) INTO :h_part FROM au_cancel
WHERE biz_date = :h_bizdate AND cancel_type = 'PARTIAL';
if (sqlca.sqlcode < 0) { fprintf(stderr, "PARTIAL agg FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> au_cancel_daily_batch COMMIT: bizdate=%s full=%ld partial=%ld\n", bizdate, h_full, h_part);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,52 @@
/*
* au_capture_sweep_batch.pgc - au 승인 매입확정 스윕 (커서 + 인라인 UPDATE, XA).
*
* Cursor-scans approved(A) authorizations for a biz_date and flips each to
* captured(M) with an inline EXEC SQL UPDATE inside the loop, all under ONE
* global XA transaction. Usage: au_capture_sweep_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "au_dbio.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
long rows = 0;
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_auth;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL DECLARE csc CURSOR FOR
SELECT auth_id FROM au_authorization
WHERE biz_date = :h_bizdate AND status = 'A' ORDER BY auth_id;
EXEC SQL OPEN csc;
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
for (;;) {
EXEC SQL FETCH csc INTO :h_auth;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { fprintf(stderr, "FETCH FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE csc; tpabort(0); return 1; }
EXEC SQL UPDATE au_authorization SET status = 'M', captured_at = now(), updated_at = now()
WHERE auth_id = :h_auth;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE csc; tpabort(0); return 1; }
rows++;
}
EXEC SQL CLOSE csc;
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> au_capture_sweep_batch COMMIT: bizdate=%s captured(A->M)=%ld\n", bizdate, rows);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,38 @@
/*
* au_daily_auth_batch.pgc - au 일일 승인 총계 (단건 집계 배치, XA).
*
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
* transaction, an EXEC SQL aggregate runs on the biz_date, then tpcommit drives
* XA 2PC. Usage: au_daily_auth_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "au_dbio.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_cnt, h_appr, h_gross;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT count(*), count(*) FILTER (WHERE status = 'A'), coalesce(sum(amount),0)
INTO :h_cnt, :h_appr, :h_gross FROM au_authorization WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) { fprintf(stderr, "au_daily_auth_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> au_daily_auth_batch COMMIT: bizdate=%s auths=%ld approved=%ld gross=%ld\n", bizdate, h_cnt, h_appr, h_gross);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,37 @@
/*
* au_dcc_settle_batch.pgc - au 대리승인(STANDIN) 정산 집계 (2열 집계, XA).
*
* Single EXEC SQL two-column aggregate over STANDIN-type authorizations for a
* biz_date under ONE global XA transaction. Usage: au_dcc_settle_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "au_dbio.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_cnt, h_sum;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT count(*), coalesce(sum(amount),0) INTO :h_cnt, :h_sum
FROM au_authorization WHERE biz_date = :h_bizdate AND auth_type = 'STANDIN';
if (sqlca.sqlcode < 0) { fprintf(stderr, "au_dcc_settle_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> au_dcc_settle_batch COMMIT: bizdate=%s standin_txns=%ld standin_sum=%ld\n", bizdate, h_cnt, h_sum);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,50 @@
/*
* au_decline_bucket_batch.pgc - au 거절사유 버킷 집계 (커서 누적, 무기록, XA).
*
* Cursor-scans the day's declines grouped by reason and accumulates counts in C
* (read-only work, no DB write) under ONE global XA transaction, printing the
* total and distinct-reason bucket count. Usage: au_decline_bucket_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "au_dbio.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
long buckets = 0, total = 0;
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16], h_reason[128];
long h_cnt;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL DECLARE dbc CURSOR FOR
SELECT decline_reason, count(*) FROM au_authorization
WHERE biz_date = :h_bizdate AND status = 'D' GROUP BY decline_reason;
EXEC SQL OPEN dbc;
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
for (;;) {
EXEC SQL FETCH dbc INTO :h_reason, :h_cnt;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { fprintf(stderr, "FETCH FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE dbc; tpabort(0); return 1; }
total = total + h_cnt;
buckets++;
}
EXEC SQL CLOSE dbc;
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> au_decline_bucket_batch COMMIT: bizdate=%s reasons=%ld total_declines=%ld\n", bizdate, buckets, total);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,52 @@
/*
* au_eod_reflect_batch.pgc - au 일마감 승인 반영 (커서 + 다중 dbio 호출, XA).
*
* Cursor-scans captured(M) authorizations for a biz_date and, per row, calls TWO
* dbio helpers (settle the status, then re-stamp the amount) under ONE global XA
* transaction. Usage: au_eod_reflect_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "au_dbio.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
long rows = 0, total = 0;
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_auth, h_amt;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL DECLARE erc CURSOR FOR
SELECT auth_id, amount FROM au_authorization
WHERE biz_date = :h_bizdate AND status = 'M' ORDER BY auth_id;
EXEC SQL OPEN erc;
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
for (;;) {
EXEC SQL FETCH erc INTO :h_auth, :h_amt;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { fprintf(stderr, "FETCH FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE erc; tpabort(0); return 1; }
if (audb_update_auth_status(h_auth, "S") < 0) { EXEC SQL CLOSE erc; tpabort(0); return 1; }
if (audb_update_auth_amount(h_auth, h_amt) < 0) { EXEC SQL CLOSE erc; tpabort(0); return 1; }
total = total + h_amt;
rows++;
}
EXEC SQL CLOSE erc;
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> au_eod_reflect_batch COMMIT: bizdate=%s reflected(M->S)=%ld amount=%ld\n", bizdate, rows, total);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,35 @@
/*
* au_fraud_summary_batch.pgc - au 부정거래 요약 (dbio 헬퍼 호출 배치, XA).
*
* Instead of inline SQL, this batch drives the libaudbio.a query helpers
* (audb_fraud_avg_score + audb_auth_count_by_date) under ONE global XA
* transaction and prints a summary. Usage: au_fraud_summary_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "au_dbio.h"
#include "au_fraud_agg_dbio.h"
#include "au_auth_agg_dbio.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
long avg_score, auth_cnt;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
avg_score = audb_fraud_avg_score(bizdate);
if (avg_score < 0) { fprintf(stderr, "avg_score FAIL\n"); tpabort(0); return 1; }
auth_cnt = audb_auth_count_by_date(bizdate);
if (auth_cnt < 0) { fprintf(stderr, "auth_cnt FAIL\n"); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> au_fraud_summary_batch COMMIT: bizdate=%s auths=%ld avg_fraud_score=%ld\n", bizdate, auth_cnt, avg_score);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,43 @@
/*
* au_limit_reset_batch.pgc - au 일마감 한도 사용액 초기화 (커서 + dbio, XA).
*
* Cursor-scans every card_limit row and calls audb_limit_reset() on each under
* ONE global XA transaction, zeroing daily used_amount. Usage: au_limit_reset_batch
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "au_dbio.h"
int main(int argc, char **argv)
{
long rows = 0;
EXEC SQL BEGIN DECLARE SECTION;
char h_card[24];
EXEC SQL END DECLARE SECTION;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL DECLARE lrc CURSOR FOR SELECT card_no FROM card_limit WHERE used_amount > 0;
EXEC SQL OPEN lrc;
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
for (;;) {
EXEC SQL FETCH lrc INTO :h_card;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { fprintf(stderr, "FETCH FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE lrc; tpabort(0); return 1; }
if (audb_limit_reset(h_card) < 0) { EXEC SQL CLOSE lrc; tpabort(0); return 1; }
rows++;
}
EXEC SQL CLOSE lrc;
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> au_limit_reset_batch COMMIT: cards_reset=%ld\n", rows);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,41 @@
/*
* au_limit_topup_batch.pgc - au 임시한도 정리 + 기본한도 상향 (다중 UPDATE, XA).
*
* Runs two sequential set UPDATEs (clear temp_limit, then top up daily_limit for
* low-limit cards) under ONE global XA transaction. Usage: au_limit_topup_batch [DELTA]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "au_dbio.h"
int main(int argc, char **argv)
{
long delta = (argc > 1) ? atol(argv[1]) : 500000;
long cleared = 0, topped = 0;
EXEC SQL BEGIN DECLARE SECTION;
long h_delta;
EXEC SQL END DECLARE SECTION;
h_delta = delta;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL UPDATE card_limit SET temp_limit = 0, updated_at = now() WHERE temp_limit > 0;
if (sqlca.sqlcode < 0) { fprintf(stderr, "clear FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
cleared = sqlca.sqlerrd[2];
EXEC SQL UPDATE card_limit SET daily_limit = daily_limit + :h_delta, updated_at = now()
WHERE daily_limit < 1000000;
if (sqlca.sqlcode < 0) { fprintf(stderr, "topup FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
topped = sqlca.sqlerrd[2];
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> au_limit_topup_batch COMMIT: temp_cleared=%ld topped_up=%ld delta=%ld\n", cleared, topped, delta);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,39 @@
/*
* au_preauth_expire_batch.pgc - au 미확정 예비승인 만료 (단건 UPDATE, XA).
*
* Expires stale pre-authorizations (status 'P') for a biz_date to 'X' in a single
* set UPDATE, reporting the affected-row count via sqlca.sqlerrd[2], under ONE
* global XA transaction. Usage: au_preauth_expire_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "au_dbio.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
long expired = 0;
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL UPDATE au_preauth SET status = 'X'
WHERE biz_date = :h_bizdate AND status = 'P';
if (sqlca.sqlcode < 0) { fprintf(stderr, "au_preauth_expire_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
expired = sqlca.sqlerrd[2];
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> au_preauth_expire_batch COMMIT: bizdate=%s expired(P->X)=%ld\n", bizdate, expired);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,44 @@
/*
* au_reversal_audit_batch.pgc - au 역전건 감사 (집계 후 UPDATE, XA).
*
* First aggregates the day's reversed(R) authorization amount, then stamps those
* rows as audited via a set UPDATE - both under ONE global XA transaction.
* Usage: au_reversal_audit_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "au_dbio.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
long stamped = 0;
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_sum;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT coalesce(sum(amount),0) INTO :h_sum FROM au_authorization
WHERE biz_date = :h_bizdate AND status = 'R';
if (sqlca.sqlcode < 0) { fprintf(stderr, "SUM FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
EXEC SQL UPDATE au_authorization SET updated_at = now()
WHERE biz_date = :h_bizdate AND status = 'R';
if (sqlca.sqlcode < 0) { fprintf(stderr, "UPDATE FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
stamped = sqlca.sqlerrd[2];
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> au_reversal_audit_batch COMMIT: bizdate=%s reversed_sum=%ld stamped=%ld\n", bizdate, h_sum, stamped);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,48 @@
/*
* au_summary_build_batch.pgc - au 가맹점 승인 일집계 생성 (INSERT..SELECT, XA).
*
* Rolls the day's au_authorization rows up per merchant and INSERTs them into
* au_summary in a single set-based statement (ON CONFLICT merge), all under ONE
* global XA transaction. Usage: au_summary_build_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "au_dbio.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
long rows = 0;
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL INSERT INTO au_summary
(merchant_id, biz_date, auth_count, approve_count, decline_count, auth_amount)
SELECT merchant_id, :h_bizdate, count(*),
count(*) FILTER (WHERE status = 'A'),
count(*) FILTER (WHERE status = 'D'),
coalesce(sum(amount),0)
FROM au_authorization WHERE biz_date = :h_bizdate GROUP BY merchant_id
ON CONFLICT (merchant_id, biz_date) DO UPDATE
SET auth_count = EXCLUDED.auth_count, approve_count = EXCLUDED.approve_count,
decline_count = EXCLUDED.decline_count, auth_amount = EXCLUDED.auth_amount,
updated_at = now();
if (sqlca.sqlcode < 0) { fprintf(stderr, "au_summary_build_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
rows = sqlca.sqlerrd[2];
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> au_summary_build_batch COMMIT: bizdate=%s merchants=%ld\n", bizdate, rows);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,40 @@
/*
* au_summary_rate_batch.pgc - au 승인율 리포트 (dbio 호출 + 인라인 집계 혼합, XA).
*
* Combines a libaudbio.a helper (audb_summary_approval_rate) with an inline
* EXEC SQL aggregate under ONE global XA transaction. Usage: au_summary_rate_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "au_dbio.h"
#include "au_summary_rate_dbio.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
long rate;
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_merchants;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
rate = audb_summary_approval_rate(bizdate);
if (rate < 0) { fprintf(stderr, "rate FAIL\n"); tpabort(0); return 1; }
EXEC SQL SELECT count(*) INTO :h_merchants FROM au_summary WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) { fprintf(stderr, "count FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> au_summary_rate_batch COMMIT: bizdate=%s merchants=%ld approval_rate=%ld%%\n", bizdate, h_merchants, rate);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,44 @@
/*
* au_void_sweep_batch.pgc - au 역전건 무효화 스윕 (UPDATE 후 집계, XA).
*
* First flips reversed(R) authorizations for a biz_date to void(V) with a set
* UPDATE, then aggregates the remaining voided count - both under ONE global XA
* transaction. Usage: au_void_sweep_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "au_dbio.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
long voided = 0;
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_total;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL UPDATE au_authorization SET status = 'V', updated_at = now()
WHERE biz_date = :h_bizdate AND status = 'R';
if (sqlca.sqlcode < 0) { fprintf(stderr, "UPDATE FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
voided = sqlca.sqlerrd[2];
EXEC SQL SELECT count(*) INTO :h_total FROM au_authorization
WHERE biz_date = :h_bizdate AND status = 'V';
if (sqlca.sqlcode < 0) { fprintf(stderr, "COUNT FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> au_void_sweep_batch COMMIT: bizdate=%s newly_voided=%ld total_void=%ld\n", bizdate, voided, h_total);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,14 @@
/*
* au_auth_agg_dbio.h - au DB copybook (au_auth_agg_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_AUTH_AGG_DBIO_H
#define AU_AUTH_AGG_DBIO_H
typedef struct { char biz_date[16]; long gross; long cnt; } au_auth_agg_rec_t;
long audb_auth_gross_by_date(const char *bizdate);
long audb_auth_count_by_date(const char *bizdate);
#endif /* AU_AUTH_AGG_DBIO_H */

View file

@ -0,0 +1,35 @@
/*
* au_auth_agg_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_auth_agg_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: aggregate sum/count (일자별 집계).
*/
#include <string.h>
#include <userlog.h>
#include "au_auth_agg_dbio.h"
/* 당일 승인 총액. */
long audb_auth_gross_by_date(const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_v = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT coalesce(sum(amount),0) INTO :h_v FROM au_authorization
WHERE biz_date = :h_bizdate AND status = 'A';
if (sqlca.sqlcode < 0) { userlog("audb_auth_gross_by_date FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
return h_v;
}
/* 당일 승인 건수. */
long audb_auth_count_by_date(const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_v = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT count(*) INTO :h_v FROM au_authorization WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) { userlog("audb_auth_count_by_date FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
return h_v;
}

View file

@ -0,0 +1,13 @@
/*
* au_auth_bucket_dbio.h - au DB copybook (au_auth_bucket_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_AUTH_BUCKET_DBIO_H
#define AU_AUTH_BUCKET_DBIO_H
typedef struct { char biz_date[16]; long small; long medium; long large; } au_auth_bucket_rec_t;
long audb_auth_large_bucket(const char *bizdate);
#endif /* AU_AUTH_BUCKET_DBIO_H */

View file

@ -0,0 +1,25 @@
/*
* au_auth_bucket_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_auth_bucket_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: CASE-based bucketing aggregate (금액대별 버킷팅, 고액 버킷 건수).
*/
#include <string.h>
#include <userlog.h>
#include "au_auth_bucket_dbio.h"
/* 당일 승인을 금액대(소/중/대)로 CASE 버킷팅하여 고액(>=1,000,000) 버킷 건수 반환. */
long audb_auth_large_bucket(const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_v = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT coalesce(sum(
CASE WHEN amount >= 1000000 THEN 1
WHEN amount >= 100000 THEN 0
ELSE 0 END), 0) INTO :h_v
FROM au_authorization WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) return -1;
return h_v;
}

View file

@ -0,0 +1,13 @@
/*
* au_auth_overavg_dbio.h - au DB copybook (au_auth_overavg_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_AUTH_OVERAVG_DBIO_H
#define AU_AUTH_OVERAVG_DBIO_H
typedef struct { char biz_date[16]; long over_avg_cnt; } au_auth_overavg_rec_t;
long audb_auth_over_avg_count(const char *bizdate);
#endif /* AU_AUTH_OVERAVG_DBIO_H */

View file

@ -0,0 +1,23 @@
/*
* au_auth_overavg_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_auth_overavg_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: scalar-subquery comparison WHERE amount > (SELECT avg ...) (평균초과 승인 건수).
*/
#include <string.h>
#include <userlog.h>
#include "au_auth_overavg_dbio.h"
/* 당일 평균 승인금액을 초과하는 승인 건수 (스칼라 서브쿼리 비교). */
long audb_auth_over_avg_count(const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_v = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT count(*) INTO :h_v FROM au_authorization
WHERE biz_date = :h_bizdate
AND amount > (SELECT coalesce(avg(amount),0) FROM au_authorization WHERE biz_date = :h_bizdate);
if (sqlca.sqlcode < 0) return -1;
return h_v;
}

View file

@ -0,0 +1,14 @@
/*
* au_auth_query_dbio.h - au DB copybook (au_auth_query_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_AUTH_QUERY_DBIO_H
#define AU_AUTH_QUERY_DBIO_H
typedef struct { long auth_id; long amount; char status[8]; } au_auth_q_rec_t;
long audb_auth_amount(long auth_id);
long audb_auth_card_count(const char *card);
#endif /* AU_AUTH_QUERY_DBIO_H */

View file

@ -0,0 +1,33 @@
/*
* au_auth_query_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_auth_query_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: plain scalar SELECT (단건 스칼라 조회).
*/
#include <string.h>
#include <userlog.h>
#include "au_auth_query_dbio.h"
/* 단일 승인의 금액. */
long audb_auth_amount(long auth_id)
{
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_v = 0;
EXEC SQL END DECLARE SECTION;
h_id = auth_id;
EXEC SQL SELECT coalesce(amount,0) INTO :h_v FROM au_authorization WHERE auth_id = :h_id;
if (sqlca.sqlcode < 0) { userlog("audb_auth_amount FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
return h_v;
}
/* 카드의 전체 승인 건수. */
long audb_auth_card_count(const char *card)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_card[24];
long h_v = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_card, card, sizeof(h_card)-1); h_card[sizeof(h_card)-1] = 0;
EXEC SQL SELECT count(*) INTO :h_v FROM au_authorization WHERE card_no = :h_card;
if (sqlca.sqlcode < 0) { userlog("audb_auth_card_count FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
return h_v;
}

View file

@ -0,0 +1,13 @@
/*
* au_auth_status_dbio.h - au DB copybook (au_auth_status_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_AUTH_STATUS_DBIO_H
#define AU_AUTH_STATUS_DBIO_H
typedef struct { char biz_date[16]; char status[8]; long cnt; } au_auth_status_rec_t;
long audb_status_declined_count(const char *bizdate);
#endif /* AU_AUTH_STATUS_DBIO_H */

View file

@ -0,0 +1,30 @@
/*
* au_auth_status_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_auth_status_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: cursor loop (DECLARE/OPEN/FETCH/CLOSE) over status groups.
*/
#include <string.h>
#include <userlog.h>
#include "au_auth_status_dbio.h"
/* 상태별 건수를 커서로 순회하여 거절(D) 건수만 추출. */
long audb_status_declined_count(const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16], h_st[8];
long h_cnt, declined = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL DECLARE ausc CURSOR FOR
SELECT status, count(*) FROM au_authorization WHERE biz_date = :h_bizdate GROUP BY status;
EXEC SQL OPEN ausc;
if (sqlca.sqlcode < 0) return -1;
for (;;) {
EXEC SQL FETCH ausc INTO :h_st, :h_cnt;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE ausc; return -1; }
if (h_st[0] == 'D') declined = h_cnt;
}
EXEC SQL CLOSE ausc;
return declined;
}

View file

@ -0,0 +1,13 @@
/*
* au_auth_type_dbio.h - au DB copybook (au_auth_type_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_AUTH_TYPE_DBIO_H
#define AU_AUTH_TYPE_DBIO_H
typedef struct { char biz_date[16]; long variety; } au_auth_type_rec_t;
long audb_auth_type_variety(const char *bizdate);
#endif /* AU_AUTH_TYPE_DBIO_H */

View file

@ -0,0 +1,21 @@
/*
* au_auth_type_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_auth_type_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: count(DISTINCT ...) (당일 사용된 승인유형 가짓수).
*/
#include <string.h>
#include <userlog.h>
#include "au_auth_type_dbio.h"
/* 당일 사용된 승인유형(AUTH/STANDIN/INSTALL/PREAUTH ...) 가짓수. */
long audb_auth_type_variety(const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_v = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT count(DISTINCT auth_type) INTO :h_v FROM au_authorization WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) return -1;
return h_v;
}

View file

@ -0,0 +1,13 @@
/*
* au_blacklist_query_dbio.h - au DB copybook (au_blacklist_query_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_BLACKLIST_QUERY_DBIO_H
#define AU_BLACKLIST_QUERY_DBIO_H
typedef struct { char card_no[24]; long listed; } au_blacklist_q_rec_t;
long audb_blacklist_exists(const char *card);
#endif /* AU_BLACKLIST_QUERY_DBIO_H */

View file

@ -0,0 +1,22 @@
/*
* au_blacklist_query_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_blacklist_query_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: EXISTS predicate SELECT (블랙리스트 존재여부 0/1).
*/
#include <string.h>
#include <userlog.h>
#include "au_blacklist_query_dbio.h"
/* 카드가 블랙리스트에 존재하면 1, 없으면 0. */
long audb_blacklist_exists(const char *card)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_card[24];
int h_v = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_card, card, sizeof(h_card)-1); h_card[sizeof(h_card)-1] = 0;
EXEC SQL SELECT CASE WHEN EXISTS (SELECT 1 FROM au_blacklist WHERE card_no = :h_card)
THEN 1 ELSE 0 END INTO :h_v;
if (sqlca.sqlcode < 0) { userlog("audb_blacklist_exists FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
return (long)h_v;
}

View file

@ -0,0 +1,13 @@
/*
* au_cancel_agg_dbio.h - au DB copybook (au_cancel_agg_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_CANCEL_AGG_DBIO_H
#define AU_CANCEL_AGG_DBIO_H
typedef struct { char biz_date[16]; long full_amt; long partial_amt; } au_cancel_agg_rec_t;
long audb_cancel_partial_sum(const char *bizdate);
#endif /* AU_CANCEL_AGG_DBIO_H */

View file

@ -0,0 +1,25 @@
/*
* au_cancel_agg_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_cancel_agg_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: FILTER (WHERE ...) aggregate (취소유형별 분리 집계).
*/
#include <string.h>
#include <userlog.h>
#include "au_cancel_agg_dbio.h"
/* FULL/PARTIAL 취소를 한 번에 분리 집계하고 PARTIAL 합 반환. */
long audb_cancel_partial_sum(const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_full = 0, h_part = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT
coalesce(sum(amount) FILTER (WHERE cancel_type = 'FULL'), 0),
coalesce(sum(amount) FILTER (WHERE cancel_type = 'PARTIAL'), 0)
INTO :h_full, :h_part FROM au_cancel WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) return -1;
if (h_full < 0) return -1;
return h_part;
}

View file

@ -0,0 +1,13 @@
/*
* au_cancel_query_dbio.h - au DB copybook (au_cancel_query_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_CANCEL_QUERY_DBIO_H
#define AU_CANCEL_QUERY_DBIO_H
typedef struct { long auth_id; long cancel_amount; char cancel_type[8]; } au_cancel_q_rec_t;
long audb_cancel_amount_by_auth(long auth_id);
#endif /* AU_CANCEL_QUERY_DBIO_H */

View file

@ -0,0 +1,20 @@
/*
* au_cancel_query_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_cancel_query_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: aggregate sum keyed by FK (한 승인의 누적 취소액).
*/
#include <string.h>
#include <userlog.h>
#include "au_cancel_query_dbio.h"
/* 한 승인건에 대한 누적 취소 금액. */
long audb_cancel_amount_by_auth(long auth_id)
{
EXEC SQL BEGIN DECLARE SECTION;
long h_auth, h_v = 0;
EXEC SQL END DECLARE SECTION;
h_auth = auth_id;
EXEC SQL SELECT coalesce(sum(amount),0) INTO :h_v FROM au_cancel WHERE auth_id = :h_auth;
if (sqlca.sqlcode < 0) { userlog("audb_cancel_amount_by_auth FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
return h_v;
}

View file

@ -0,0 +1,13 @@
/*
* au_capture_query_dbio.h - au DB copybook (au_capture_query_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_CAPTURE_QUERY_DBIO_H
#define AU_CAPTURE_QUERY_DBIO_H
typedef struct { char biz_date[16]; long max_amt; long min_amt; } au_capture_q_rec_t;
long audb_capture_amount_range(const char *bizdate);
#endif /* AU_CAPTURE_QUERY_DBIO_H */

View file

@ -0,0 +1,23 @@
/*
* au_capture_query_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_capture_query_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: min AND max in one SELECT, computed range (매입확정 금액 범위).
*/
#include <string.h>
#include <userlog.h>
#include "au_capture_query_dbio.h"
/* 매입확정(M) 승인의 최대-최소 금액 폭. */
long audb_capture_amount_range(const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_max = 0, h_min = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT coalesce(max(amount),0), coalesce(min(amount),0)
INTO :h_max, :h_min FROM au_authorization
WHERE biz_date = :h_bizdate AND status = 'M';
if (sqlca.sqlcode < 0) return -1;
return h_max - h_min;
}

View file

@ -0,0 +1,13 @@
/*
* au_card_velocity_dbio.h - au DB copybook (au_card_velocity_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_CARD_VELOCITY_DBIO_H
#define AU_CARD_VELOCITY_DBIO_H
typedef struct { char biz_date[16]; long blacklisted_auths; } au_card_velocity_rec_t;
long audb_blacklisted_auth_count(const char *bizdate);
#endif /* AU_CARD_VELOCITY_DBIO_H */

View file

@ -0,0 +1,23 @@
/*
* au_card_velocity_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_card_velocity_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: subquery WHERE col IN (SELECT ...) (블랙리스트 카드의 당일 승인 건수).
*/
#include <string.h>
#include <userlog.h>
#include "au_card_velocity_dbio.h"
/* 블랙리스트에 등재된 카드가 당일 발생시킨 승인 건수. */
long audb_blacklisted_auth_count(const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_v = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT count(*) INTO :h_v FROM au_authorization
WHERE biz_date = :h_bizdate
AND card_no IN (SELECT card_no FROM au_blacklist);
if (sqlca.sqlcode < 0) return -1;
return h_v;
}

View file

@ -0,0 +1,13 @@
/*
* au_decline_reason_dbio.h - au DB copybook (au_decline_reason_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_DECLINE_REASON_DBIO_H
#define AU_DECLINE_REASON_DBIO_H
typedef struct { char biz_date[16]; char reason[128]; long cnt; } au_decline_reason_rec_t;
long audb_decline_total_by_reason(const char *bizdate);
#endif /* AU_DECLINE_REASON_DBIO_H */

View file

@ -0,0 +1,32 @@
/*
* au_decline_reason_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_decline_reason_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: cursor over GROUP BY decline_reason, accumulating counts (거절사유 누적).
*/
#include <string.h>
#include <userlog.h>
#include "au_decline_reason_dbio.h"
/* 거절(D) 건을 사유별로 커서 순회하며 총 거절 건수를 누적. */
long audb_decline_total_by_reason(const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16], h_reason[128];
long h_cnt, total = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL DECLARE drc CURSOR FOR
SELECT decline_reason, count(*) FROM au_authorization
WHERE biz_date = :h_bizdate AND status = 'D'
GROUP BY decline_reason;
EXEC SQL OPEN drc;
if (sqlca.sqlcode < 0) return -1;
for (;;) {
EXEC SQL FETCH drc INTO :h_reason, :h_cnt;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE drc; return -1; }
total = total + h_cnt;
}
EXEC SQL CLOSE drc;
return total;
}

View file

@ -0,0 +1,13 @@
/*
* au_fraud_agg_dbio.h - au DB copybook (au_fraud_agg_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_FRAUD_AGG_DBIO_H
#define AU_FRAUD_AGG_DBIO_H
typedef struct { char biz_date[16]; long score_sum; long fraud_cnt; } au_fraud_agg_rec_t;
long audb_fraud_avg_score(const char *bizdate);
#endif /* AU_FRAUD_AGG_DBIO_H */

View file

@ -0,0 +1,23 @@
/*
* au_fraud_agg_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_fraud_agg_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: computed avg = sum/count (건당 평균 스코어).
*/
#include <string.h>
#include <userlog.h>
#include "au_fraud_agg_dbio.h"
/* 당일 건당 평균 부정거래 스코어 = sum(score)/count(*). */
long audb_fraud_avg_score(const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_sum = 0, h_cnt = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT coalesce(sum(score),0), count(*)
INTO :h_sum, :h_cnt FROM au_fraud_log WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) return -1;
if (h_cnt <= 0) return 0;
return h_sum / h_cnt;
}

View file

@ -0,0 +1,13 @@
/*
* au_fraud_join_dbio.h - au DB copybook (au_fraud_join_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_FRAUD_JOIN_DBIO_H
#define AU_FRAUD_JOIN_DBIO_H
typedef struct { char biz_date[16]; long high_risk_amount; } au_fraud_join_rec_t;
long audb_fraud_high_risk_amount(const char *bizdate);
#endif /* AU_FRAUD_JOIN_DBIO_H */

View file

@ -0,0 +1,24 @@
/*
* au_fraud_join_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_fraud_join_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: 2-table JOIN with predicate (고위험 부정거래 연계 승인금액).
*/
#include <string.h>
#include <userlog.h>
#include "au_fraud_join_dbio.h"
/* fraud_log(score>=50) 와 연결된 승인원장 금액 합계를 조인으로 산출. */
long audb_fraud_high_risk_amount(const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_v = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT coalesce(sum(a.amount),0) INTO :h_v
FROM au_fraud_log f
JOIN au_authorization a ON f.auth_id = a.auth_id
WHERE f.biz_date = :h_bizdate AND f.score >= 50;
if (sqlca.sqlcode < 0) { userlog("audb_fraud_high_risk_amount FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
return h_v;
}

View file

@ -0,0 +1,14 @@
/*
* au_fraud_query_dbio.h - au DB copybook (au_fraud_query_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_FRAUD_QUERY_DBIO_H
#define AU_FRAUD_QUERY_DBIO_H
typedef struct { char card_no[24]; long max_score; long min_score; } au_fraud_q_rec_t;
long audb_fraud_max_score(const char *card);
long audb_fraud_min_score(const char *card);
#endif /* AU_FRAUD_QUERY_DBIO_H */

View file

@ -0,0 +1,34 @@
/*
* au_fraud_query_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_fraud_query_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: min/max aggregate (카드별 부정거래 스코어 극값).
*/
#include <string.h>
#include <userlog.h>
#include "au_fraud_query_dbio.h"
/* 카드의 최대 부정거래 스코어. */
long audb_fraud_max_score(const char *card)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_card[24];
long h_v = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_card, card, sizeof(h_card)-1); h_card[sizeof(h_card)-1] = 0;
EXEC SQL SELECT coalesce(max(score),0) INTO :h_v FROM au_fraud_log WHERE card_no = :h_card;
if (sqlca.sqlcode < 0) return -1;
return h_v;
}
/* 카드의 최소 부정거래 스코어. */
long audb_fraud_min_score(const char *card)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_card[24];
long h_v = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_card, card, sizeof(h_card)-1); h_card[sizeof(h_card)-1] = 0;
EXEC SQL SELECT coalesce(min(score),0) INTO :h_v FROM au_fraud_log WHERE card_no = :h_card;
if (sqlca.sqlcode < 0) return -1;
return h_v;
}

View file

@ -0,0 +1,14 @@
/*
* au_limit_agg_dbio.h - au DB copybook (au_limit_agg_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_LIMIT_AGG_DBIO_H
#define AU_LIMIT_AGG_DBIO_H
typedef struct { long total_used; long over_cards; } au_limit_agg_rec_t;
long audb_limit_total_used(void);
long audb_limit_over_cards(void);
#endif /* AU_LIMIT_AGG_DBIO_H */

View file

@ -0,0 +1,30 @@
/*
* au_limit_agg_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_limit_agg_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: table-wide aggregate + comparison-predicate count (인자 없음).
*/
#include <string.h>
#include <userlog.h>
#include "au_limit_agg_dbio.h"
/* 전체 카드의 사용금액 총합. */
long audb_limit_total_used(void)
{
EXEC SQL BEGIN DECLARE SECTION;
long h_v = 0;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT coalesce(sum(used_amount),0) INTO :h_v FROM card_limit;
if (sqlca.sqlcode < 0) return -1;
return h_v;
}
/* 한도를 초과 사용한(used_amount > daily_limit) 카드 수. */
long audb_limit_over_cards(void)
{
EXEC SQL BEGIN DECLARE SECTION;
long h_v = 0;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT count(*) INTO :h_v FROM card_limit WHERE used_amount > daily_limit;
if (sqlca.sqlcode < 0) return -1;
return h_v;
}

View file

@ -0,0 +1,14 @@
/*
* au_limit_query_dbio.h - au DB copybook (au_limit_query_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_LIMIT_QUERY_DBIO_H
#define AU_LIMIT_QUERY_DBIO_H
typedef struct { char card_no[24]; long available; long utilization; } au_limit_q_rec_t;
long audb_limit_available(const char *card);
long audb_limit_utilization(const char *card);
#endif /* AU_LIMIT_QUERY_DBIO_H */

View file

@ -0,0 +1,37 @@
/*
* au_limit_query_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_limit_query_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: computed column SELECT + guarded division.
*/
#include <string.h>
#include <userlog.h>
#include "au_limit_query_dbio.h"
/* 가용한도 = daily_limit - used_amount (DB 계산). */
long audb_limit_available(const char *card)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_card[24];
long h_v = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_card, card, sizeof(h_card)-1); h_card[sizeof(h_card)-1] = 0;
EXEC SQL SELECT coalesce(daily_limit - used_amount, 0) INTO :h_v
FROM card_limit WHERE card_no = :h_card;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) return -1;
return h_v;
}
/* 한도 소진율(%) = used_amount*100/daily_limit (0 나눗셈 방지). */
long audb_limit_utilization(const char *card)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_card[24];
long h_lim = 0, h_used = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_card, card, sizeof(h_card)-1); h_card[sizeof(h_card)-1] = 0;
EXEC SQL SELECT coalesce(daily_limit,0), coalesce(used_amount,0)
INTO :h_lim, :h_used FROM card_limit WHERE card_no = :h_card;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) return -1;
if (h_lim <= 0) return 0;
return h_used * 100 / h_lim;
}

View file

@ -0,0 +1,13 @@
/*
* au_limit_upsert_dbio.h - au DB copybook (au_limit_upsert_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: 0 ok, -1 = SQL error.
*/
#ifndef AU_LIMIT_UPSERT_DBIO_H
#define AU_LIMIT_UPSERT_DBIO_H
typedef struct { char card_no[24]; long temp_limit; } au_limit_upsert_rec_t;
int audb_limit_temp_clear(const char *card);
#endif /* AU_LIMIT_UPSERT_DBIO_H */

View file

@ -0,0 +1,26 @@
/*
* au_limit_upsert_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_limit_upsert_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: ON CONFLICT upsert (임시한도 초기화 행 upsert).
*/
#include <string.h>
#include <userlog.h>
#include "au_limit_upsert_dbio.h"
/* 카드 한도행을 보장하고 임시한도(temp_limit)를 0 으로 초기화(upsert). */
int audb_limit_temp_clear(const char *card)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_card[24];
EXEC SQL END DECLARE SECTION;
strncpy(h_card, card, sizeof(h_card)-1); h_card[sizeof(h_card)-1] = 0;
EXEC SQL INSERT INTO card_limit (card_no, daily_limit, used_amount, temp_limit)
VALUES (:h_card, 0, 0, 0)
ON CONFLICT (card_no) DO UPDATE
SET temp_limit = 0, updated_at = now();
if (sqlca.sqlcode < 0) {
userlog("audb_limit_temp_clear FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
return -1;
}
return 0;
}

View file

@ -0,0 +1,13 @@
/*
* au_merchant_join_dbio.h - au DB copybook (au_merchant_join_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_MERCHANT_JOIN_DBIO_H
#define AU_MERCHANT_JOIN_DBIO_H
typedef struct { char merchant_id[64]; char biz_date[16]; long joined_gross; } au_merchant_join_rec_t;
long audb_merchant_reconciled_gross(const char *bizdate);
#endif /* AU_MERCHANT_JOIN_DBIO_H */

View file

@ -0,0 +1,24 @@
/*
* au_merchant_join_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_merchant_join_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: 2-table JOIN aggregate (승인원장 x 승인집계 조인 총액).
*/
#include <string.h>
#include <userlog.h>
#include "au_merchant_join_dbio.h"
/* au_summary 에 집계행이 존재하는 가맹점의 당일 승인 총액을 조인으로 집계. */
long audb_merchant_reconciled_gross(const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_v = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT coalesce(sum(a.amount),0) INTO :h_v
FROM au_authorization a
JOIN au_summary s ON a.merchant_id = s.merchant_id AND a.biz_date = s.biz_date
WHERE a.biz_date = :h_bizdate AND a.status = 'A';
if (sqlca.sqlcode < 0) { userlog("audb_merchant_reconciled_gross FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
return h_v;
}

View file

@ -0,0 +1,13 @@
/*
* au_preauth_agg_dbio.h - au DB copybook (au_preauth_agg_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_PREAUTH_AGG_DBIO_H
#define AU_PREAUTH_AGG_DBIO_H
typedef struct { char biz_date[16]; char merchant_id[64]; long open_cnt; } au_preauth_agg_rec_t;
long audb_preauth_open_merchants(const char *bizdate);
#endif /* AU_PREAUTH_AGG_DBIO_H */

View file

@ -0,0 +1,32 @@
/*
* au_preauth_agg_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_preauth_agg_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: GROUP BY ... HAVING via cursor (미확정 예비승인 보유 가맹점 수).
*/
#include <string.h>
#include <userlog.h>
#include "au_preauth_agg_dbio.h"
/* 미확정(P) 예비승인을 1건 이상 보유한 가맹점 수를 GROUP BY/HAVING 커서로 계수. */
long audb_preauth_open_merchants(const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16], h_merch[64];
long h_cnt, merchants = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL DECLARE pamc CURSOR FOR
SELECT merchant_id, count(*) FROM au_preauth
WHERE biz_date = :h_bizdate AND status = 'P'
GROUP BY merchant_id HAVING count(*) >= 1;
EXEC SQL OPEN pamc;
if (sqlca.sqlcode < 0) return -1;
for (;;) {
EXEC SQL FETCH pamc INTO :h_merch, :h_cnt;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE pamc; return -1; }
merchants++;
}
EXEC SQL CLOSE pamc;
return merchants;
}

View file

@ -0,0 +1,13 @@
/*
* au_preauth_query_dbio.h - au DB copybook (au_preauth_query_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_PREAUTH_QUERY_DBIO_H
#define AU_PREAUTH_QUERY_DBIO_H
typedef struct { long preauth_id; long amount; char status[8]; } au_preauth_q_rec_t;
int audb_preauth_detail(long preauth_id, long *amount_out, char *status_out /* >= 2 */);
#endif /* AU_PREAUTH_QUERY_DBIO_H */

View file

@ -0,0 +1,27 @@
/*
* au_preauth_query_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_preauth_query_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: multi-column SELECT INTO out-params (예비승인 상세).
*/
#include <string.h>
#include <userlog.h>
#include "au_preauth_query_dbio.h"
/* 예비승인의 금액/상태를 한 번에 조회하여 out 파라미터로 반환. */
int audb_preauth_detail(long preauth_id, long *amount_out, char *status_out)
{
EXEC SQL BEGIN DECLARE SECTION;
long h_pre = preauth_id, h_amt = 0;
char h_status[8];
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT coalesce(amount,0), status INTO :h_amt, :h_status
FROM au_preauth WHERE preauth_id = :h_pre;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) {
userlog("audb_preauth_detail FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
return -1;
}
*amount_out = h_amt;
status_out[0] = h_status[0];
status_out[1] = 0;
return 0;
}

View file

@ -0,0 +1,13 @@
/*
* au_summary_query_dbio.h - au DB copybook (au_summary_query_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_SUMMARY_QUERY_DBIO_H
#define AU_SUMMARY_QUERY_DBIO_H
typedef struct { char merchant_id[64]; char biz_date[16]; long approve_count; } au_summary_q_rec_t;
long audb_summary_approve_count(const char *merch, const char *bizdate);
#endif /* AU_SUMMARY_QUERY_DBIO_H */

View file

@ -0,0 +1,23 @@
/*
* au_summary_query_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_summary_query_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: two-key scalar SELECT (가맹점/일자 승인집계 단건).
*/
#include <string.h>
#include <userlog.h>
#include "au_summary_query_dbio.h"
/* 가맹점 당일 승인건수(au_summary.approve_count). */
long audb_summary_approve_count(const char *merch, const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_merch[64], h_bizdate[16];
long h_v = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT coalesce(approve_count,0) INTO :h_v FROM au_summary
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) { userlog("audb_summary_approve_count FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
return h_v;
}

View file

@ -0,0 +1,13 @@
/*
* au_summary_rate_dbio.h - au DB copybook (au_summary_rate_dbio, part of libaudbio.a).
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
* Return convention: >=0 ok, -1 = SQL error.
*/
#ifndef AU_SUMMARY_RATE_DBIO_H
#define AU_SUMMARY_RATE_DBIO_H
typedef struct { char biz_date[16]; long approve; long total; } au_summary_rate_rec_t;
long audb_summary_approval_rate(const char *bizdate);
#endif /* AU_SUMMARY_RATE_DBIO_H */

View file

@ -0,0 +1,23 @@
/*
* au_summary_rate_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_summary_rate_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: computed rate = approve*100/auth over an aggregated table (승인율).
*/
#include <string.h>
#include <userlog.h>
#include "au_summary_rate_dbio.h"
/* 당일 전체 승인율(%) = sum(approve_count)*100/sum(auth_count). */
long audb_summary_approval_rate(const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_appr = 0, h_total = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT coalesce(sum(approve_count),0), coalesce(sum(auth_count),0)
INTO :h_appr, :h_total FROM au_summary WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) return -1;
if (h_total <= 0) return 0;
return h_appr * 100 / h_total;
}

16
app/src/au/run/run_blacklist.sh Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
##
## run_blacklist.sh - 고위험 카드 블랙리스트 승격(INSERT..SELECT) 배치 실행.
## 운영 스크립트: Enduro/X + ECPG/XA 런타임 환경을 설정하고 배치/서비스를 실행.
## Usage: run_blacklist.sh [BIZDATE] [MERCH] [AMOUNT] [PID]
##
set -e
. /app/conf/setapp.sh
BIZDATE="${1:-2026-07-19}"
MERCH="${2:-M0001}"
AMOUNT="${3:-1000000}"
PID="${4:-1}"
echo "[run_blacklist.sh] BIZDATE=$BIZDATE"
exec /app/bin/au_blacklist_promote_batch "$BIZDATE"

16
app/src/au/run/run_cancel.sh Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
##
## run_cancel.sh - 일일 취소 집계(FULL/PARTIAL) 배치 실행.
## 운영 스크립트: Enduro/X + ECPG/XA 런타임 환경을 설정하고 배치/서비스를 실행.
## Usage: run_cancel.sh [BIZDATE] [MERCH] [AMOUNT] [PID]
##
set -e
. /app/conf/setapp.sh
BIZDATE="${1:-2026-07-19}"
MERCH="${2:-M0001}"
AMOUNT="${3:-1000000}"
PID="${4:-1}"
echo "[run_cancel.sh] BIZDATE=$BIZDATE"
exec /app/bin/au_cancel_daily_batch "$BIZDATE"

16
app/src/au/run/run_capture.sh Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
##
## run_capture.sh - 승인 매입확정 스윕(A->M) 배치 실행.
## 운영 스크립트: Enduro/X + ECPG/XA 런타임 환경을 설정하고 배치/서비스를 실행.
## Usage: run_capture.sh [BIZDATE] [MERCH] [AMOUNT] [PID]
##
set -e
. /app/conf/setapp.sh
BIZDATE="${1:-2026-07-19}"
MERCH="${2:-M0001}"
AMOUNT="${3:-1000000}"
PID="${4:-1}"
echo "[run_capture.sh] BIZDATE=$BIZDATE"
exec /app/bin/au_capture_sweep_batch "$BIZDATE"

16
app/src/au/run/run_daily.sh Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
##
## run_daily.sh - 일일 승인 총계 배치 실행.
## 운영 스크립트: Enduro/X + ECPG/XA 런타임 환경을 설정하고 배치/서비스를 실행.
## Usage: run_daily.sh [BIZDATE] [MERCH] [AMOUNT] [PID]
##
set -e
. /app/conf/setapp.sh
BIZDATE="${1:-2026-07-19}"
MERCH="${2:-M0001}"
AMOUNT="${3:-1000000}"
PID="${4:-1}"
echo "[run_daily.sh] BIZDATE=$BIZDATE MERCH=$MERCH AMOUNT=$AMOUNT"
exec /app/bin/au_daily_auth_batch "$BIZDATE"

16
app/src/au/run/run_dcc.sh Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
##
## run_dcc.sh - 대리승인(STANDIN) 정산 집계 배치 실행.
## 운영 스크립트: Enduro/X + ECPG/XA 런타임 환경을 설정하고 배치/서비스를 실행.
## Usage: run_dcc.sh [BIZDATE] [MERCH] [AMOUNT] [PID]
##
set -e
. /app/conf/setapp.sh
BIZDATE="${1:-2026-07-19}"
MERCH="${2:-M0001}"
AMOUNT="${3:-1000000}"
PID="${4:-1}"
echo "[run_dcc.sh] BIZDATE=$BIZDATE"
exec /app/bin/au_dcc_settle_batch "$BIZDATE"

16
app/src/au/run/run_decline.sh Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
##
## run_decline.sh - 거절사유 버킷 집계(커서 누적) 배치 실행.
## 운영 스크립트: Enduro/X + ECPG/XA 런타임 환경을 설정하고 배치/서비스를 실행.
## Usage: run_decline.sh [BIZDATE] [MERCH] [AMOUNT] [PID]
##
set -e
. /app/conf/setapp.sh
BIZDATE="${1:-2026-07-19}"
MERCH="${2:-M0001}"
AMOUNT="${3:-1000000}"
PID="${4:-1}"
echo "[run_decline.sh] BIZDATE=$BIZDATE"
exec /app/bin/au_decline_bucket_batch "$BIZDATE"

21
app/src/au/run/run_eod.sh Executable file
View file

@ -0,0 +1,21 @@
#!/bin/bash
##
## run_eod.sh - 일마감(EOD): 승인/한도 집계·반영 배치 일괄 실행.
## 운영 스크립트: Enduro/X + ECPG/XA 런타임 환경을 설정하고 배치/서비스를 실행.
## Usage: run_eod.sh [BIZDATE] [MERCH] [AMOUNT] [PID]
##
set -e
. /app/conf/setapp.sh
BIZDATE="${1:-2026-07-19}"
MERCH="${2:-M0001}"
AMOUNT="${3:-1000000}"
PID="${4:-1}"
echo "[run_eod.sh] BIZDATE=$BIZDATE MERCH=$MERCH AMOUNT=$AMOUNT"
for b in au_daily_auth_batch au_summary_build_batch au_capture_sweep_batch \
au_eod_reflect_batch au_settle_reflect_batch au_fraud_scan_batch \
au_cancel_daily_batch au_decline_bucket_batch au_limit_reset_batch; do
echo "--- $b $BIZDATE ---"
"/app/bin/$b" "$BIZDATE" || exit 1
done

16
app/src/au/run/run_fraud.sh Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
##
## run_fraud.sh - 부정거래 스캔(GROUP BY HAVING 커서) 배치 실행.
## 운영 스크립트: Enduro/X + ECPG/XA 런타임 환경을 설정하고 배치/서비스를 실행.
## Usage: run_fraud.sh [BIZDATE] [MERCH] [AMOUNT] [PID]
##
set -e
. /app/conf/setapp.sh
BIZDATE="${1:-2026-07-19}"
MERCH="${2:-M0001}"
AMOUNT="${3:-1000000}"
PID="${4:-1}"
echo "[run_fraud.sh] BIZDATE=$BIZDATE"
exec /app/bin/au_fraud_scan_batch "$BIZDATE"

View file

@ -0,0 +1,16 @@
#!/bin/bash
##
## run_fraud_summary.sh - 부정거래 요약(dbio 헬퍼 호출) 배치 실행.
## 운영 스크립트: Enduro/X + ECPG/XA 런타임 환경을 설정하고 배치/서비스를 실행.
## Usage: run_fraud_summary.sh [BIZDATE] [MERCH] [AMOUNT] [PID]
##
set -e
. /app/conf/setapp.sh
BIZDATE="${1:-2026-07-19}"
MERCH="${2:-M0001}"
AMOUNT="${3:-1000000}"
PID="${4:-1}"
echo "[run_fraud_summary.sh] BIZDATE=$BIZDATE"
exec /app/bin/au_fraud_summary_batch "$BIZDATE"

View file

@ -0,0 +1,16 @@
#!/bin/bash
##
## run_limit_reset.sh - 일마감 카드 한도 사용액 초기화 배치 실행.
## 운영 스크립트: Enduro/X + ECPG/XA 런타임 환경을 설정하고 배치/서비스를 실행.
## Usage: run_limit_reset.sh [BIZDATE] [MERCH] [AMOUNT] [PID]
##
set -e
. /app/conf/setapp.sh
BIZDATE="${1:-2026-07-19}"
MERCH="${2:-M0001}"
AMOUNT="${3:-1000000}"
PID="${4:-1}"
echo "[run_limit_reset.sh] BIZDATE=$BIZDATE"
exec /app/bin/au_limit_reset_batch

16
app/src/au/run/run_preauth.sh Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
##
## run_preauth.sh - 미확정 예비승인 만료(P->X) 배치 실행.
## 운영 스크립트: Enduro/X + ECPG/XA 런타임 환경을 설정하고 배치/서비스를 실행.
## Usage: run_preauth.sh [BIZDATE] [MERCH] [AMOUNT] [PID]
##
set -e
. /app/conf/setapp.sh
BIZDATE="${1:-2026-07-19}"
MERCH="${2:-M0001}"
AMOUNT="${3:-1000000}"
PID="${4:-1}"
echo "[run_preauth.sh] BIZDATE=$BIZDATE"
exec /app/bin/au_preauth_expire_batch "$BIZDATE"

16
app/src/au/run/run_rate.sh Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
##
## run_rate.sh - 승인율 리포트(dbio 호출 + 인라인 집계) 배치 실행.
## 운영 스크립트: Enduro/X + ECPG/XA 런타임 환경을 설정하고 배치/서비스를 실행.
## Usage: run_rate.sh [BIZDATE] [MERCH] [AMOUNT] [PID]
##
set -e
. /app/conf/setapp.sh
BIZDATE="${1:-2026-07-19}"
MERCH="${2:-M0001}"
AMOUNT="${3:-1000000}"
PID="${4:-1}"
echo "[run_rate.sh] BIZDATE=$BIZDATE"
exec /app/bin/au_summary_rate_batch "$BIZDATE"

16
app/src/au/run/run_reversal.sh Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
##
## run_reversal.sh - 역전건 감사(집계 후 UPDATE) 배치 실행.
## 운영 스크립트: Enduro/X + ECPG/XA 런타임 환경을 설정하고 배치/서비스를 실행.
## Usage: run_reversal.sh [BIZDATE] [MERCH] [AMOUNT] [PID]
##
set -e
. /app/conf/setapp.sh
BIZDATE="${1:-2026-07-19}"
MERCH="${2:-M0001}"
AMOUNT="${3:-1000000}"
PID="${4:-1}"
echo "[run_reversal.sh] BIZDATE=$BIZDATE"
exec /app/bin/au_reversal_audit_batch "$BIZDATE"

16
app/src/au/run/run_settle.sh Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
##
## run_settle.sh - 승인 정산반영(커서 M->S) 배치 실행.
## 운영 스크립트: Enduro/X + ECPG/XA 런타임 환경을 설정하고 배치/서비스를 실행.
## Usage: run_settle.sh [BIZDATE] [MERCH] [AMOUNT] [PID]
##
set -e
. /app/conf/setapp.sh
BIZDATE="${1:-2026-07-19}"
MERCH="${2:-M0001}"
AMOUNT="${3:-1000000}"
PID="${4:-1}"
echo "[run_settle.sh] BIZDATE=$BIZDATE"
exec /app/bin/au_settle_reflect_batch "$BIZDATE"

16
app/src/au/run/run_summary.sh Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
##
## run_summary.sh - 가맹점 승인 일집계 생성(INSERT..SELECT) 배치 실행.
## 운영 스크립트: Enduro/X + ECPG/XA 런타임 환경을 설정하고 배치/서비스를 실행.
## Usage: run_summary.sh [BIZDATE] [MERCH] [AMOUNT] [PID]
##
set -e
. /app/conf/setapp.sh
BIZDATE="${1:-2026-07-19}"
MERCH="${2:-M0001}"
AMOUNT="${3:-1000000}"
PID="${4:-1}"
echo "[run_summary.sh] BIZDATE=$BIZDATE MERCH=$MERCH"
exec /app/bin/au_summary_build_batch "$BIZDATE"

16
app/src/au/run/run_topup.sh Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
##
## run_topup.sh - 임시한도 정리 + 기본한도 상향(다중 UPDATE) 배치 실행.
## 운영 스크립트: Enduro/X + ECPG/XA 런타임 환경을 설정하고 배치/서비스를 실행.
## Usage: run_topup.sh [DELTA] [MERCH] [AMOUNT] [PID]
##
set -e
. /app/conf/setapp.sh
DELTA="${1:-500000}"
MERCH="${2:-M0001}"
AMOUNT="${3:-1000000}"
PID="${4:-1}"
echo "[run_topup.sh] DELTA=$DELTA"
exec /app/bin/au_limit_topup_batch "$DELTA"

16
app/src/au/run/run_void.sh Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
##
## run_void.sh - 역전건 무효화 스윕(UPDATE 후 집계) 배치 실행.
## 운영 스크립트: Enduro/X + ECPG/XA 런타임 환경을 설정하고 배치/서비스를 실행.
## Usage: run_void.sh [BIZDATE] [MERCH] [AMOUNT] [PID]
##
set -e
. /app/conf/setapp.sh
BIZDATE="${1:-2026-07-19}"
MERCH="${2:-M0001}"
AMOUNT="${3:-1000000}"
PID="${4:-1}"
echo "[run_void.sh] BIZDATE=$BIZDATE"
exec /app/bin/au_void_sweep_batch "$BIZDATE"

24
app/src/au/svc/AUTH.h Normal file
View file

@ -0,0 +1,24 @@
/*
* AUTH.h - au AUTH (copybook / record header).
* Request fields: T_KEY1(), T_MERCHANT, T_AMOUNT, T_BIZDATE
* Response fields: T_ID1(auth_id), T_RC, T_STR2(), T_STATUS
*/
#ifndef AUTH_H
#define AUTH_H
#include "au_svc.h"
typedef struct {
long auth_id;
char card_no[24];
char merchant_id[64];
long amount;
char approval_code[12];
char auth_type[12];
char status[8];
char biz_date[16];
} au_auth_rec_t;
void AUTH(TPSVCINFO *p);
#endif /* AUTH_H */

45
app/src/au/svc/AUTH.pgc Normal file
View file

@ -0,0 +1,45 @@
/*
* AUTH.pgc - au 모듈 서비스 AUTH (one service = one file).
* 승인 접수: 한도 점검 후 authorization 원장 기록 + 한도 차감.
* Moved verbatim from the former inline au_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by au_svr at tpsvrinit.
*/
#include "AUTH.h"
void AUTH(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24], merch[64], bizdate[16], appr[12];
long amount, auth_id, lim = 0, used = 0;
gets_(b, T_KEY1, card, sizeof(card));
if (card[0] == 0) { userlog("AUTH: T_KEY1(카드번호) 누락"); FAIL(b); }
gets_(b, T_MERCHANT, merch, sizeof(merch));
amount = getl(b, T_AMOUNT);
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
/* 한도 점검: 초과면 거절(D) 상태로 기록 */
if (audb_limit_get(card, &lim, &used) < 0) FAIL(b);
if (used + amount > lim) {
userlog("AUTH 한도초과 card=%s used=%ld amt=%ld lim=%ld -> 거절", card, used, amount, lim);
auth_id = audb_next_auth_id();
if (auth_id < 0) FAIL(b);
if (audb_insert_auth(auth_id, card, merch, amount, "000000", "AUTH", "D", bizdate) < 0) FAIL(b);
setl(b, T_ID1, auth_id);
setl(b, T_RC, 1);
Bchg(b, T_STATUS, 0, "D", 0L);
OK(b);
}
auth_id = audb_next_auth_id();
if (auth_id < 0) FAIL(b);
sprintf(appr, "%06ld", auth_id % 1000000);
if (audb_insert_auth(auth_id, card, merch, amount, appr, "AUTH", "A", bizdate) < 0) FAIL(b);
if (audb_limit_dec(card, amount) < 0) FAIL(b);
setl(b, T_ID1, auth_id);
setl(b, T_RC, 0);
Bchg(b, T_STR2, 0, appr, 0L);
Bchg(b, T_STATUS, 0, "A", 0L);
userlog("AUTH 승인 auth_id=%ld card=%s merch=%s amt=%ld appr=%s", auth_id, card, merch, amount, appr);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* AUTH_APPROVE.h - au AUTH_APPROVE (copybook / record header).
* Request fields: T_ID1(auth_id)
* Response fields: T_STATUS
*/
#ifndef AUTH_APPROVE_H
#define AUTH_APPROVE_H
#include "au_svc.h"
typedef struct {
long auth_id;
char status[8];
} au_auth_approve_rec_t;
void AUTH_APPROVE(TPSVCINFO *p);
#endif /* AUTH_APPROVE_H */

View file

@ -0,0 +1,17 @@
/*
* AUTH_APPROVE.pgc - au 모듈 서비스 AUTH_APPROVE (one service = one file).
* 승인 확정(pending->approved): dbio 래퍼로 상태만 A 로 확정.
* Kept as the plain dbio-wrapper skeleton (cf. AUTH_HOLD = inline UPDATE ... IN,
* AUTH_RELEASE = SELECT-then-UPDATE) so the three status transitions stay
* structurally distinct. Runs on the caller's XA branch. Advertised by au_svr.
*/
#include "AUTH_APPROVE.h"
void AUTH_APPROVE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long auth_id = getl(b, T_ID1);
if (audb_update_auth_status(auth_id, "A") < 0) FAIL(b);
Bchg(b, T_STATUS, 0, "A", 0L);
OK(b);
}

View file

@ -0,0 +1,23 @@
/*
* AUTH_CANCEL.h - au AUTH_CANCEL (copybook / record header).
* Request fields: T_ID1(auth_id), T_AMOUNT, T_KEY1(), T_BIZDATE, T_REASON
* Response fields: T_CANCEL_ID, T_STATUS
*/
#ifndef AUTH_CANCEL_H
#define AUTH_CANCEL_H
#include "au_svc.h"
typedef struct {
long cancel_id;
long auth_id;
char cancel_type[8];
long amount;
char card_no[24];
char reason[128];
char biz_date[16];
} au_auth_cancel_rec_t;
void AUTH_CANCEL(TPSVCINFO *p);
#endif /* AUTH_CANCEL_H */

View file

@ -0,0 +1,37 @@
/*
* AUTH_CANCEL.pgc - au 모듈 서비스 AUTH_CANCEL (one service = one file).
* 승인 전체 취소 + 한도 원복.
* Moved verbatim from the former inline au_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by au_svr at tpsvrinit.
*/
#include "AUTH_CANCEL.h"
void AUTH_CANCEL(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24], bizdate[16], reason[128];
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_auth, h_amt;
char h_card[24], h_bizdate[16], h_reason[128];
EXEC SQL END DECLARE SECTION;
h_auth = getl(b, T_ID1);
h_amt = getl(b, T_AMOUNT);
gets_(b, T_KEY1, card, sizeof(card));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
gets_(b, T_REASON, reason, sizeof(reason)); if (reason[0] == 0) strcpy(reason, "CUSTOMER");
strncpy(h_card, card, sizeof(h_card)-1); h_card[sizeof(h_card)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
strncpy(h_reason, reason, sizeof(h_reason)-1); h_reason[sizeof(h_reason)-1] = 0;
EXEC SQL SELECT nextval('au_cancel_seq') INTO :h_id;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL INSERT INTO au_cancel (cancel_id, auth_id, cancel_type, amount, reason, biz_date)
VALUES (:h_id, :h_auth, 'FULL', :h_amt, :h_reason, :h_bizdate);
if (sqlca.sqlcode < 0) FAIL(b);
if (audb_update_auth_status(h_auth, "C") < 0) FAIL(b);
if (card[0] && audb_limit_dec(card, -h_amt) < 0) FAIL(b);
setl(b, T_CANCEL_ID, h_id);
Bchg(b, T_STATUS, 0, "C", 0L);
OK(b);
}

View file

@ -0,0 +1,19 @@
/*
* AUTH_CAPTURE.h - au AUTH_CAPTURE (copybook / record header).
* Request fields: T_ID1(auth_id)
* Response fields: T_RC(0=, 1=), T_STATUS
*/
#ifndef AUTH_CAPTURE_H
#define AUTH_CAPTURE_H
#include "au_svc.h"
typedef struct {
long auth_id;
long rc;
char status[8];
} au_auth_capture_rec_t;
void AUTH_CAPTURE(TPSVCINFO *p);
#endif /* AUTH_CAPTURE_H */

View file

@ -0,0 +1,23 @@
/*
* AUTH_CAPTURE.pgc - au 모듈 서비스 AUTH_CAPTURE (one service = one file).
* 승인 매입확정(capture): 상태 A->M(매입대상).
* Moved verbatim from the former inline au_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by au_svr at tpsvrinit.
*/
#include "AUTH_CAPTURE.h"
void AUTH_CAPTURE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_auth;
EXEC SQL END DECLARE SECTION;
h_auth = getl(b, T_ID1);
EXEC SQL UPDATE au_authorization SET status = 'M', captured_at = now(), updated_at = now()
WHERE auth_id = :h_auth AND status = 'A';
if (sqlca.sqlcode < 0) FAIL(b);
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); FAIL(b); }
setl(b, T_RC, 0);
Bchg(b, T_STATUS, 0, "M", 0L);
OK(b);
}

View file

@ -0,0 +1,19 @@
/*
* AUTH_DECLINE.h - au AUTH_DECLINE (copybook / record header).
* Request fields: T_ID1(auth_id), T_REASON
* Response fields: T_STATUS
*/
#ifndef AUTH_DECLINE_H
#define AUTH_DECLINE_H
#include "au_svc.h"
typedef struct {
long auth_id;
char reason[128];
char status[8];
} au_auth_decline_rec_t;
void AUTH_DECLINE(TPSVCINFO *p);
#endif /* AUTH_DECLINE_H */

View file

@ -0,0 +1,25 @@
/*
* AUTH_DECLINE.pgc - au 모듈 서비스 AUTH_DECLINE (one service = one file).
* 승인 거절 처리: 거절 사유와 함께 상태 D 로 갱신.
* Moved verbatim from the former inline au_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by au_svr at tpsvrinit.
*/
#include "AUTH_DECLINE.h"
void AUTH_DECLINE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char reason[128];
EXEC SQL BEGIN DECLARE SECTION;
long h_auth;
char h_reason[128];
EXEC SQL END DECLARE SECTION;
h_auth = getl(b, T_ID1);
gets_(b, T_REASON, reason, sizeof(reason)); if (reason[0] == 0) strcpy(reason, "DECLINE");
strncpy(h_reason, reason, sizeof(h_reason)-1); h_reason[sizeof(h_reason)-1] = 0;
EXEC SQL UPDATE au_authorization SET status = 'D', decline_reason = :h_reason, updated_at = now()
WHERE auth_id = :h_auth;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
Bchg(b, T_STATUS, 0, "D", 0L);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* AUTH_HISTORY.h - au AUTH_HISTORY (copybook / record header).
* Request fields: T_KEY1()
* Response fields: T_COUNT( )
*/
#ifndef AUTH_HISTORY_H
#define AUTH_HISTORY_H
#include "au_svc.h"
typedef struct {
char card_no[24];
long hist_count;
} au_auth_history_rec_t;
void AUTH_HISTORY(TPSVCINFO *p);
#endif /* AUTH_HISTORY_H */

View file

@ -0,0 +1,23 @@
/*
* AUTH_HISTORY.pgc - au 모듈 서비스 AUTH_HISTORY (one service = one file).
* 카드 승인 이력 건수 조회.
* Moved verbatim from the former inline au_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by au_svr at tpsvrinit.
*/
#include "AUTH_HISTORY.h"
void AUTH_HISTORY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24];
EXEC SQL BEGIN DECLARE SECTION;
long h_cnt;
char h_card[24];
EXEC SQL END DECLARE SECTION;
gets_(b, T_KEY1, card, sizeof(card));
strncpy(h_card, card, sizeof(h_card)-1); h_card[sizeof(h_card)-1] = 0;
EXEC SQL SELECT count(*) INTO :h_cnt FROM au_authorization WHERE card_no = :h_card;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_COUNT, h_cnt);
OK(b);
}

View file

@ -0,0 +1,19 @@
/*
* AUTH_HOLD.h - au AUTH_HOLD (copybook / record header).
* Request fields: T_ID1(auth_id)
* Response fields: T_STATUS, T_RC(0=, 1=)
*/
#ifndef AUTH_HOLD_H
#define AUTH_HOLD_H
#include "au_svc.h"
typedef struct {
long auth_id;
long affected;
char status[8];
} au_auth_hold_rec_t;
void AUTH_HOLD(TPSVCINFO *p);
#endif /* AUTH_HOLD_H */

View file

@ -0,0 +1,26 @@
/*
* AUTH_HOLD.pgc - au 모듈 서비스 AUTH_HOLD (one service = one file).
* 승인 보류: 승인/예비(A,P) 상태만 보류(H)로 전이, 반영 건수를 T_RC 로.
* Rewritten with an inline UPDATE ... WHERE status IN (...) guard + affected-count
* (via sqlca.sqlerrd[2]) so it is structurally DISTINCT from AUTH_APPROVE (dbio
* wrapper) and AUTH_RELEASE (SELECT-then-UPDATE). Runs on the caller's XA branch.
*/
#include "AUTH_HOLD.h"
void AUTH_HOLD(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_auth, h_aff;
EXEC SQL END DECLARE SECTION;
h_auth = getl(b, T_ID1);
/* only an approved(A)/pre-authorized(P) authorization may be put on hold */
EXEC SQL UPDATE au_authorization SET status = 'H', updated_at = now()
WHERE auth_id = :h_auth AND status IN ('A', 'P');
if (sqlca.sqlcode < 0) { userlog("AUTH_HOLD FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); FAIL(b); }
h_aff = sqlca.sqlerrd[2];
if (h_aff > 0) Bchg(b, T_STATUS, 0, "H", 0L);
setl(b, T_RC, h_aff > 0 ? 0 : 1);
OK(b);
}

View file

@ -0,0 +1,23 @@
/*
* AUTH_PARTCXL.h - au AUTH_PARTCXL (copybook / record header).
* Request fields: T_ID1(auth_id), T_AMOUNT(), T_KEY1(), T_BIZDATE
* Response fields: T_CANCEL_ID, T_AMOUNT()
*/
#ifndef AUTH_PARTCXL_H
#define AUTH_PARTCXL_H
#include "au_svc.h"
typedef struct {
long cancel_id;
long auth_id;
char cancel_type[8];
long cancel_amount;
long new_amount;
char card_no[24];
char biz_date[16];
} au_auth_partcxl_rec_t;
void AUTH_PARTCXL(TPSVCINFO *p);
#endif /* AUTH_PARTCXL_H */

View file

@ -0,0 +1,37 @@
/*
* AUTH_PARTCXL.pgc - au 모듈 서비스 AUTH_PARTCXL (one service = one file).
* 부분 취소: 승인 금액 감액 + 한도 부분 원복.
* Moved verbatim from the former inline au_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by au_svr at tpsvrinit.
*/
#include "AUTH_PARTCXL.h"
void AUTH_PARTCXL(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24], bizdate[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_auth, h_amt, h_new;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
h_auth = getl(b, T_ID1);
h_amt = getl(b, T_AMOUNT); /* 취소 금액 */
gets_(b, T_KEY1, card, sizeof(card));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT amount INTO :h_new FROM au_authorization WHERE auth_id = :h_auth;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
h_new = h_new - h_amt;
EXEC SQL SELECT nextval('au_cancel_seq') INTO :h_id;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL INSERT INTO au_cancel (cancel_id, auth_id, cancel_type, amount, reason, biz_date)
VALUES (:h_id, :h_auth, 'PARTIAL', :h_amt, 'PARTIAL', :h_bizdate);
if (sqlca.sqlcode < 0) FAIL(b);
if (audb_update_auth_amount(h_auth, h_new) < 0) FAIL(b);
if (card[0] && audb_limit_dec(card, -h_amt) < 0) FAIL(b);
setl(b, T_CANCEL_ID, h_id);
setl(b, T_AMOUNT, h_new);
OK(b);
}

View file

@ -0,0 +1,20 @@
/*
* AUTH_RELEASE.h - au AUTH_RELEASE (copybook / record header).
* Request fields: T_ID1(auth_id)
* Response fields: T_STATUS( / ), T_RC(0=, 1=)
*/
#ifndef AUTH_RELEASE_H
#define AUTH_RELEASE_H
#include "au_svc.h"
typedef struct {
long auth_id;
long affected;
char prev_status[8];
char status[8];
} au_auth_release_rec_t;
void AUTH_RELEASE(TPSVCINFO *p);
#endif /* AUTH_RELEASE_H */

View file

@ -0,0 +1,29 @@
/*
* AUTH_RELEASE.pgc - au 모듈 서비스 AUTH_RELEASE (one service = one file).
* 보류 해제: 직전 상태를 조회한 뒤 H->A 전이, 이전 상태를 함께 회신.
* Rewritten as SELECT-prev-status-then-UPDATE (WHERE status='H') so it is
* structurally DISTINCT from AUTH_HOLD (inline UPDATE ... IN) and AUTH_APPROVE
* (dbio wrapper). Runs on the caller's XA branch. Advertised by au_svr.
*/
#include "AUTH_RELEASE.h"
void AUTH_RELEASE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_auth, h_aff;
char h_prev[8];
EXEC SQL END DECLARE SECTION;
h_auth = getl(b, T_ID1);
EXEC SQL SELECT status INTO :h_prev FROM au_authorization WHERE auth_id = :h_auth;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
/* release only from HOLD; report whether the transition actually fired */
EXEC SQL UPDATE au_authorization SET status = 'A', updated_at = now()
WHERE auth_id = :h_auth AND status = 'H';
if (sqlca.sqlcode < 0) FAIL(b);
h_aff = sqlca.sqlerrd[2];
Bchg(b, T_STATUS, 0, h_aff > 0 ? "A" : h_prev, 0L);
setl(b, T_RC, h_aff > 0 ? 0 : 1);
OK(b);
}

View file

@ -0,0 +1,22 @@
/*
* AUTH_RETRY.h - au AUTH_RETRY (copybook / record header).
* Request fields: T_ID1(auth_id), T_AMOUNT, T_KEY1()
* Response fields: T_RC, T_STATUS
*/
#ifndef AUTH_RETRY_H
#define AUTH_RETRY_H
#include "au_svc.h"
typedef struct {
long auth_id;
char card_no[24];
long amount;
long daily_limit;
long used_amount;
char status[8];
} au_auth_retry_rec_t;
void AUTH_RETRY(TPSVCINFO *p);
#endif /* AUTH_RETRY_H */

View file

@ -0,0 +1,22 @@
/*
* AUTH_RETRY.pgc - au 모듈 서비스 AUTH_RETRY (one service = one file).
* 거절 승인 재시도 (상태 D->A 재승인).
* Moved verbatim from the former inline au_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by au_svr at tpsvrinit.
*/
#include "AUTH_RETRY.h"
void AUTH_RETRY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char card[24];
long auth_id = getl(b, T_ID1), amount = getl(b, T_AMOUNT), lim = 0, used = 0;
gets_(b, T_KEY1, card, sizeof(card));
if (audb_limit_get(card, &lim, &used) < 0) FAIL(b);
if (used + amount > lim) { setl(b, T_RC, 1); FAIL(b); }
if (audb_update_auth_status(auth_id, "A") < 0) FAIL(b);
if (audb_limit_dec(card, amount) < 0) FAIL(b);
setl(b, T_RC, 0);
Bchg(b, T_STATUS, 0, "A", 0L);
OK(b);
}

View file

@ -0,0 +1,20 @@
/*
* AUTH_REVERSE.h - au AUTH_REVERSE (copybook / record header).
* Request fields: T_ID1(auth_id), T_AMOUNT, T_KEY1()
* Response fields: T_STATUS
*/
#ifndef AUTH_REVERSE_H
#define AUTH_REVERSE_H
#include "au_svc.h"
typedef struct {
long auth_id;
char card_no[24];
long amount;
char status[8];
} au_auth_reverse_rec_t;
void AUTH_REVERSE(TPSVCINFO *p);
#endif /* AUTH_REVERSE_H */

Some files were not shown because too many files have changed in this diff Show more