고도화: 전 모듈 dbio 25→40 · batch 17→22 세분화 (+432본, 전부 고유)

- 11개 모듈 각 dbio +15(→40), batch +5(→22) 새 고유 ECPG 프로그램 + 카피북 헤더
  (window/HAVING/JOIN/FILTER/NOT EXISTS/upsert/correlated/INSERT..SELECT 등 구조 다양)
- 전 코퍼스 .pgc 1004/1004 정규화-고유 (dup 그룹 0)
- 통합 검증: 12서버 runok, 333 서비스, 242 배치 바이너리, 매입체인 XA 커밋, 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 14:37:10 +00:00
parent 05ad8a3064
commit fc16ea64c8
422 changed files with 8717 additions and 0 deletions

View file

@ -0,0 +1,17 @@
/*
* au_approverate_batch.h - copybook for au_approverate_batch (XA client).
* + . Kept in dbio/ for -I resolution.
*/
#ifndef AU_APPROVERATE_BATCH_H
#define AU_APPROVERATE_BATCH_H
typedef struct {
char biz_date[16];
long approved;
long total;
long rate_bps; /* approved/total (bps) */
} au_rate_ctx_t;
long aub_rate_bps(long approved, long total);
#endif /* AU_APPROVERATE_BATCH_H */

View file

@ -0,0 +1,14 @@
/*
* au_auth_distinctcard_dbio.h - au DB copybook (au_auth_distinctcard_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.
* Shape: count(DISTINCT card_no) + count(DISTINCT merchant_id).
*/
#ifndef AU_AUTH_DISTINCTCARD_DBIO_H
#define AU_AUTH_DISTINCTCARD_DBIO_H
typedef struct { long distinct_cards; long distinct_merchants; } au_distinct_rec_t;
int audb_auth_distinct_counts(const char *bizdate, au_distinct_rec_t *out);
#endif /* AU_AUTH_DISTINCTCARD_DBIO_H */

View file

@ -0,0 +1,28 @@
/*
* au_auth_distinctcard_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_auth_distinctcard_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_distinctcard_dbio.h"
/* 당일 승인(A) 건에서 사용된 서로 다른 카드/가맹점 수를 out 에 채운다. */
int audb_auth_distinct_counts(const char *bizdate, au_distinct_rec_t *out)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_cards = 0, h_merch = 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 card_no), count(DISTINCT merchant_id)
INTO :h_cards, :h_merch FROM au_authorization
WHERE biz_date = :h_bizdate AND status = 'A';
if (sqlca.sqlcode < 0) {
userlog("audb_auth_distinct_counts FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
return -1;
}
out->distinct_cards = h_cards;
out->distinct_merchants = h_merch;
return 0;
}

View file

@ -0,0 +1,14 @@
/*
* au_auth_incancel_dbio.h - au DB copybook (au_auth_incancel_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.
* Shape: WHERE auth_id IN (SELECT auth_id FROM au_cancel WHERE ...).
*/
#ifndef AU_AUTH_INCANCEL_DBIO_H
#define AU_AUTH_INCANCEL_DBIO_H
typedef struct { long auth_id; long amount; } au_incancel_rec_t;
long audb_fullcancelled_auth_amount(const char *bizdate);
#endif /* AU_AUTH_INCANCEL_DBIO_H */

View file

@ -0,0 +1,23 @@
/*
* au_auth_incancel_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_auth_incancel_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: IN 서브셀렉트(내부 WHERE 조건 포함) - 전액취소된 승인 금액 합.
*/
#include <string.h>
#include <userlog.h>
#include "au_auth_incancel_dbio.h"
/* 전액취소(FULL) 이력이 있는 승인들의 원승인 금액 합계. */
long audb_fullcancelled_auth_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(amount),0) INTO :h_v FROM au_authorization
WHERE biz_date = :h_bizdate
AND auth_id IN (SELECT auth_id FROM au_cancel WHERE cancel_type = 'FULL');
if (sqlca.sqlcode < 0) return -1;
return h_v;
}

View file

@ -0,0 +1,14 @@
/*
* au_auth_rankcard_dbio.h - au DB copybook (au_auth_rankcard_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.
* Shape: window rank() N위 .
*/
#ifndef AU_AUTH_RANKCARD_DBIO_H
#define AU_AUTH_RANKCARD_DBIO_H
typedef struct { long rk; long auth_id; long amount; } au_rankcard_rec_t;
long audb_auth_amount_at_rank(const char *bizdate, long target_rank);
#endif /* AU_AUTH_RANKCARD_DBIO_H */

View file

@ -0,0 +1,31 @@
/*
* au_auth_rankcard_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_auth_rankcard_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: rank() OVER (ORDER BY amount DESC) 커서에서 목표 순위의 금액 반환.
*/
#include <string.h>
#include <userlog.h>
#include "au_auth_rankcard_dbio.h"
/* 금액 순위표에서 target_rank 위에 해당하는 승인 금액을 반환. 없으면 0. */
long audb_auth_amount_at_rank(const char *bizdate, long target_rank)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_rk, h_aid, h_amt, tr = target_rank, hit = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL DECLARE arc CURSOR FOR
SELECT rank() OVER (ORDER BY amount DESC) AS rk, auth_id, amount
FROM au_authorization WHERE biz_date = :h_bizdate AND status = 'A';
EXEC SQL OPEN arc;
if (sqlca.sqlcode < 0) return -1;
for (;;) {
EXEC SQL FETCH arc INTO :h_rk, :h_aid, :h_amt;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE arc; return -1; }
if (h_rk == tr) { hit = h_amt; break; }
}
EXEC SQL CLOSE arc;
return hit;
}

View file

@ -0,0 +1,14 @@
/*
* au_auth_topcard_dbio.h - au DB copybook (au_auth_topcard_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.
* Shape: window row_number() PARTITION BY card_no ( ).
*/
#ifndef AU_AUTH_TOPCARD_DBIO_H
#define AU_AUTH_TOPCARD_DBIO_H
typedef struct { long rn; char card_no[24]; long amount; } au_topcard_rec_t;
long audb_topcard_distinct(const char *bizdate, long *peak_out);
#endif /* AU_AUTH_TOPCARD_DBIO_H */

View file

@ -0,0 +1,35 @@
/*
* au_auth_topcard_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_auth_topcard_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: row_number() OVER (PARTITION BY card_no ORDER BY amount DESC) 커서 스캔.
*/
#include <string.h>
#include <userlog.h>
#include "au_auth_topcard_dbio.h"
/* 카드별 최고 승인행(rn=1)만 세어 서로 다른 카드 수를 반환하고 최고 금액은 peak_out. */
long audb_topcard_distinct(const char *bizdate, long *peak_out)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16], h_card[24];
long h_rn, h_amt, cards = 0, peak = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL DECLARE tcc CURSOR FOR
SELECT row_number() OVER (PARTITION BY card_no ORDER BY amount DESC) AS rn, card_no, amount
FROM au_authorization WHERE biz_date = :h_bizdate;
EXEC SQL OPEN tcc;
if (sqlca.sqlcode < 0) return -1;
for (;;) {
EXEC SQL FETCH tcc INTO :h_rn, :h_card, :h_amt;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE tcc; return -1; }
if (h_rn == 1) {
cards++;
if (h_amt > peak) peak = h_amt;
}
}
EXEC SQL CLOSE tcc;
*peak_out = peak;
return cards;
}

View file

@ -0,0 +1,14 @@
/*
* au_cancel_corr_dbio.h - au DB copybook (au_cancel_corr_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.
* Shape: - .
*/
#ifndef AU_CANCEL_CORR_DBIO_H
#define AU_CANCEL_CORR_DBIO_H
typedef struct { long cancel_id; long amount; } au_cancel_corr_rec_t;
long audb_cancel_over_peer_max(const char *bizdate);
#endif /* AU_CANCEL_CORR_DBIO_H */

View file

@ -0,0 +1,23 @@
/*
* au_cancel_corr_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_cancel_corr_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: 상관(correlated) 서브쿼리 + 부가조건 - 동일 승인 부분취소 평균 초과 건수.
*/
#include <string.h>
#include <userlog.h>
#include "au_cancel_corr_dbio.h"
/* 부분취소(PARTIAL) 중, 같은 auth_id 의 평균 취소액을 초과하는 건수. */
long audb_cancel_over_peer_max(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_cancel c
WHERE c.biz_date = :h_bizdate AND c.cancel_type = 'PARTIAL'
AND c.amount > (SELECT avg(d.amount) FROM au_cancel d WHERE d.auth_id = c.auth_id);
if (sqlca.sqlcode < 0) return -1;
return h_v;
}

View file

@ -0,0 +1,14 @@
/*
* au_capture_join_dbio.h - au DB copybook (au_capture_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.
* Shape: au_authorization JOIN au_cancel .
*/
#ifndef AU_CAPTURE_JOIN_DBIO_H
#define AU_CAPTURE_JOIN_DBIO_H
typedef struct { long auth_id; long cancel_amount; } au_capture_join_rec_t;
long audb_cancelled_capture_amount(const char *bizdate);
#endif /* AU_CAPTURE_JOIN_DBIO_H */

View file

@ -0,0 +1,23 @@
/*
* au_capture_join_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_capture_join_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: au_authorization a JOIN au_cancel c ON a.auth_id=c.auth_id 집계 (매입확정 취소액).
*/
#include <string.h>
#include <userlog.h>
#include "au_capture_join_dbio.h"
/* 매입확정(M)/정산반영(S) 승인에 대한 취소 금액 합계 (조인 기준 취소측 amount). */
long audb_cancelled_capture_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(c.amount),0) INTO :h_v
FROM au_authorization a JOIN au_cancel c ON a.auth_id = c.auth_id
WHERE c.biz_date = :h_bizdate AND a.status IN ('M', 'S');
if (sqlca.sqlcode < 0) return -1;
return h_v;
}

View file

@ -0,0 +1,14 @@
/*
* au_fraud_casescore_dbio.h - au DB copybook (au_fraud_casescore_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.
* Shape: CASE WHEN score sum ( ).
*/
#ifndef AU_FRAUD_CASESCORE_DBIO_H
#define AU_FRAUD_CASESCORE_DBIO_H
typedef struct { long weighted; long high; } au_casescore_rec_t;
long audb_fraud_high_weight(const char *bizdate);
#endif /* AU_FRAUD_CASESCORE_DBIO_H */

View file

@ -0,0 +1,25 @@
/*
* au_fraud_casescore_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_fraud_casescore_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: CASE WHEN 으로 점수 구간별 가중치를 합산하여 위험 점수 총합 반환.
*/
#include <string.h>
#include <userlog.h>
#include "au_fraud_casescore_dbio.h"
/* score 구간에 3/2/1 가중치를 부여한 CASE 합계(위험 가중 점수)를 반환. */
long audb_fraud_high_weight(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 score >= 80 THEN 3
WHEN score >= 50 THEN 2
ELSE 1 END), 0)
INTO :h_v FROM au_fraud_log WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) return -1;
return h_v;
}

View file

@ -0,0 +1,14 @@
/*
* au_fraud_intolog_dbio.h - au DB copybook (au_fraud_intolog_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.
* Shape: INSERT INTO au_fraud_log SELECT ... FROM au_authorization.
*/
#ifndef AU_FRAUD_INTOLOG_DBIO_H
#define AU_FRAUD_INTOLOG_DBIO_H
typedef struct { long flagged; long threshold; } au_autoflag_rec_t;
long audb_autoflag_high_amount(const char *bizdate, long threshold);
#endif /* AU_FRAUD_INTOLOG_DBIO_H */

View file

@ -0,0 +1,28 @@
/*
* au_fraud_intolog_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_fraud_intolog_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: INSERT INTO au_fraud_log SELECT (고액 승인 자동 플래그), 삽입 건수 반환.
*/
#include <string.h>
#include <userlog.h>
#include "au_fraud_intolog_dbio.h"
/* threshold 초과 고액 승인을 부정거래 로그에 자동 등록(set-based)하고 건수 반환. */
long audb_autoflag_high_amount(const char *bizdate, long threshold)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_thr = threshold, flagged = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL INSERT INTO au_fraud_log (fraud_id, auth_id, card_no, score, reason, biz_date)
SELECT nextval('au_fraud_seq'), a.auth_id, a.card_no, 90, 'AUTOFLAG_HIGH', a.biz_date
FROM au_authorization a
WHERE a.biz_date = :h_bizdate AND a.amount > :h_thr;
if (sqlca.sqlcode < 0) {
userlog("audb_autoflag_high_amount FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
return -1;
}
flagged = sqlca.sqlerrd[2];
return flagged;
}

View file

@ -0,0 +1,14 @@
/*
* au_fraud_purge_dbio.h - au DB copybook (au_fraud_purge_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.
* Shape: DELETE ... WHERE biz_date < AND score < ( ).
*/
#ifndef AU_FRAUD_PURGE_DBIO_H
#define AU_FRAUD_PURGE_DBIO_H
typedef struct { char cutoff[16]; long min_score; long deleted; } au_fraud_purge_rec_t;
long audb_fraud_purge_lowscore(const char *cutoff, long min_score);
#endif /* AU_FRAUD_PURGE_DBIO_H */

View file

@ -0,0 +1,25 @@
/*
* au_fraud_purge_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_fraud_purge_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: DELETE 복합조건 구간 삭제 - 기준일 이전 저점수 부정로그 정리.
*/
#include <string.h>
#include <userlog.h>
#include "au_fraud_purge_dbio.h"
/* cutoff 이전이면서 점수가 min_score 미만인 부정로그를 삭제하고 삭제 건수를 반환. */
long audb_fraud_purge_lowscore(const char *cutoff, long min_score)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_cut[16];
long h_min = min_score, deleted = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_cut, cutoff, sizeof(h_cut)-1); h_cut[sizeof(h_cut)-1] = 0;
EXEC SQL DELETE FROM au_fraud_log WHERE biz_date < :h_cut AND score < :h_min;
if (sqlca.sqlcode < 0) {
userlog("audb_fraud_purge_lowscore FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
return -1;
}
deleted = sqlca.sqlerrd[2];
return deleted;
}

View file

@ -0,0 +1,16 @@
/*
* au_fraudpurge_batch.h - copybook for au_fraudpurge_batch (XA client).
* + . Kept in dbio/ for -I resolution.
*/
#ifndef AU_FRAUDPURGE_BATCH_H
#define AU_FRAUDPURGE_BATCH_H
typedef struct {
char cutoff[16];
long min_score;
long deleted;
} au_fpurge_ctx_t;
long aub_fpurge_floor(long score);
#endif /* AU_FRAUDPURGE_BATCH_H */

View file

@ -0,0 +1,14 @@
/*
* au_limit_spread_dbio.h - au DB copybook (au_limit_spread_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.
* Shape: max/min/avg 3 .
*/
#ifndef AU_LIMIT_SPREAD_DBIO_H
#define AU_LIMIT_SPREAD_DBIO_H
typedef struct { long lim_max; long lim_min; long used_avg; } au_limit_spread_rec_t;
long audb_limit_spread(long *used_avg_out);
#endif /* AU_LIMIT_SPREAD_DBIO_H */

View file

@ -0,0 +1,22 @@
/*
* au_limit_spread_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_limit_spread_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: 한 번의 SELECT 로 max/min/avg 3중 집계 - 한도 스프레드 + 평균 사용액.
*/
#include <string.h>
#include <userlog.h>
#include "au_limit_spread_dbio.h"
/* 활성 카드 한도의 max-min 스프레드를 반환하고 평균 사용액을 used_avg_out 에 채운다. */
long audb_limit_spread(long *used_avg_out)
{
EXEC SQL BEGIN DECLARE SECTION;
long h_max = 0, h_min = 0, h_avg = 0;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT coalesce(max(daily_limit),0), coalesce(min(daily_limit),0),
coalesce(avg(used_amount),0)::bigint
INTO :h_max, :h_min, :h_avg FROM card_limit WHERE status = 'ACTIVE';
if (sqlca.sqlcode < 0) return -1;
*used_avg_out = h_avg;
return h_max - h_min;
}

View file

@ -0,0 +1,14 @@
/*
* au_merchant_active_dbio.h - au DB copybook (au_merchant_active_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.
* Shape: GROUP BY merchant_id HAVING count(*) >= .
*/
#ifndef AU_MERCHANT_ACTIVE_DBIO_H
#define AU_MERCHANT_ACTIVE_DBIO_H
typedef struct { char merchant_id[64]; long auths; } au_active_rec_t;
long audb_active_merchant_count(const char *bizdate, long min_auths);
#endif /* AU_MERCHANT_ACTIVE_DBIO_H */

View file

@ -0,0 +1,32 @@
/*
* au_merchant_active_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_merchant_active_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: GROUP BY merchant_id HAVING count(*) >= 최소건수, 커서로 활성 가맹점 계수.
*/
#include <string.h>
#include <userlog.h>
#include "au_merchant_active_dbio.h"
/* 당일 승인 건수가 min_auths 이상인 가맹점 수. */
long audb_active_merchant_count(const char *bizdate, long min_auths)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16], h_merch[64];
long h_cnt, h_min = min_auths, active = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL DECLARE amc CURSOR FOR
SELECT merchant_id, count(*) FROM au_authorization
WHERE biz_date = :h_bizdate
GROUP BY merchant_id HAVING count(*) >= :h_min;
EXEC SQL OPEN amc;
if (sqlca.sqlcode < 0) return -1;
for (;;) {
EXEC SQL FETCH amc INTO :h_merch, :h_cnt;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE amc; return -1; }
active++;
}
EXEC SQL CLOSE amc;
return active;
}

View file

@ -0,0 +1,14 @@
/*
* au_preauth_notexists_dbio.h - au DB copybook (au_preauth_notexists_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.
* Shape: NOT EXISTS .
*/
#ifndef AU_PREAUTH_NOTEXISTS_DBIO_H
#define AU_PREAUTH_NOTEXISTS_DBIO_H
typedef struct { long preauth_id; long amount; } au_preauth_gap_rec_t;
long audb_preauth_unconfirmed(const char *bizdate);
#endif /* AU_PREAUTH_NOTEXISTS_DBIO_H */

View file

@ -0,0 +1,24 @@
/*
* au_preauth_notexists_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_preauth_notexists_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: NOT EXISTS 상관 서브쿼리(복합조건) - 대응 승인이 없는 미확정 예비승인.
*/
#include <string.h>
#include <userlog.h>
#include "au_preauth_notexists_dbio.h"
/* 상태 P(예비) 이면서 같은 카드/금액의 승인행이 없는 예비승인 건수. */
long audb_preauth_unconfirmed(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_preauth p
WHERE p.biz_date = :h_bizdate AND p.status = 'P'
AND NOT EXISTS (SELECT 1 FROM au_authorization a
WHERE a.card_no = p.card_no AND a.amount = p.amount);
if (sqlca.sqlcode < 0) return -1;
return h_v;
}

View file

@ -0,0 +1,17 @@
/*
* au_scorebucket_batch.h - copybook for au_scorebucket_batch (XA client).
* CASE + . Kept in dbio/ for -I resolution.
*/
#ifndef AU_SCOREBUCKET_BATCH_H
#define AU_SCOREBUCKET_BATCH_H
typedef struct {
char biz_date[16];
long low; /* < 50 */
long mid; /* 50~79 */
long high; /* >= 80 */
} au_score_ctx_t;
const char *aub_score_label(long score);
#endif /* AU_SCOREBUCKET_BATCH_H */

View file

@ -0,0 +1,14 @@
/*
* au_summary_rebuild_dbio.h - au DB copybook (au_summary_rebuild_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.
* Shape: INSERT INTO au_summary SELECT ... FILTER ... GROUP BY ... ON CONFLICT DO UPDATE.
*/
#ifndef AU_SUMMARY_REBUILD_DBIO_H
#define AU_SUMMARY_REBUILD_DBIO_H
typedef struct { char biz_date[16]; long merchants; } au_summary_rebuild_rec_t;
long audb_summary_rebuild_from_auth(const char *bizdate);
#endif /* AU_SUMMARY_REBUILD_DBIO_H */

View file

@ -0,0 +1,38 @@
/*
* au_summary_rebuild_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_summary_rebuild_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: INSERT INTO au_summary SELECT count(*) FILTER (...) GROUP BY ... ON CONFLICT DO UPDATE.
*/
#include <string.h>
#include <userlog.h>
#include "au_summary_rebuild_dbio.h"
/* 당일 au_authorization 을 가맹점별 승인/거절/금액으로 재집계하여 au_summary 에 upsert. */
long audb_summary_rebuild_from_auth(const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long affected = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL INSERT INTO au_summary
(merchant_id, biz_date, auth_count, approve_count, decline_count, auth_amount)
SELECT merchant_id, biz_date, 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, biz_date
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) {
userlog("audb_summary_rebuild_from_auth FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
return -1;
}
affected = sqlca.sqlerrd[2];
return affected;
}

View file

@ -0,0 +1,14 @@
/*
* au_summary_riskmerch_dbio.h - au DB copybook (au_summary_riskmerch_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.
* Shape: GROUP BY merchant_id HAVING sum(decline) > sum(approve).
*/
#ifndef AU_SUMMARY_RISKMERCH_DBIO_H
#define AU_SUMMARY_RISKMERCH_DBIO_H
typedef struct { char merchant_id[64]; long declines; long approves; } au_riskmerch_rec_t;
long audb_decline_heavy_merchants(const char *bizdate);
#endif /* AU_SUMMARY_RISKMERCH_DBIO_H */

View file

@ -0,0 +1,32 @@
/*
* au_summary_riskmerch_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_summary_riskmerch_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: GROUP BY merchant_id HAVING sum(decline_count) > sum(approve_count) 커서 계수.
*/
#include <string.h>
#include <userlog.h>
#include "au_summary_riskmerch_dbio.h"
/* 거절 건수가 승인 건수보다 많은(위험) 가맹점 수를 GROUP BY/HAVING 커서로 계수. */
long audb_decline_heavy_merchants(const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16], h_merch[64];
long h_dec, h_app, risky = 0;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL DECLARE rmc CURSOR FOR
SELECT merchant_id, sum(decline_count), sum(approve_count) FROM au_summary
WHERE biz_date = :h_bizdate
GROUP BY merchant_id HAVING sum(decline_count) > sum(approve_count);
EXEC SQL OPEN rmc;
if (sqlca.sqlcode < 0) return -1;
for (;;) {
EXEC SQL FETCH rmc INTO :h_merch, :h_dec, :h_app;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE rmc; return -1; }
risky++;
}
EXEC SQL CLOSE rmc;
return risky;
}

View file

@ -0,0 +1,14 @@
/*
* au_summary_weightavg_dbio.h - au DB copybook (au_summary_weightavg_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.
* Shape: .
*/
#ifndef AU_SUMMARY_WEIGHTAVG_DBIO_H
#define AU_SUMMARY_WEIGHTAVG_DBIO_H
typedef struct { char merchant_id[64]; long auth_count; long auth_amount; } au_weight_rec_t;
long audb_summary_weighted_ticket(const char *bizdate);
#endif /* AU_SUMMARY_WEIGHTAVG_DBIO_H */

View file

@ -0,0 +1,33 @@
/*
* au_summary_weightavg_dbio.pgc - au 모듈 DB 접근 함수 세트 (au_summary_weightavg_dbio), archived into libaudbio.a.
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
* Shape: 커서로 가맹점별 행을 순회하며 건수 가중 평균 티켓을 C 측에서 누산/산출.
*/
#include <string.h>
#include <userlog.h>
#include "au_summary_weightavg_dbio.h"
/* 건수(auth_count)를 가중치로 하는 평균 승인 티켓을 커서 누산으로 계산. */
long audb_summary_weighted_ticket(const char *bizdate)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16], h_merch[64];
long h_cnt, h_amt;
EXEC SQL END DECLARE SECTION;
long num = 0, den = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL DECLARE swc CURSOR FOR
SELECT merchant_id, auth_count, auth_amount FROM au_summary WHERE biz_date = :h_bizdate;
EXEC SQL OPEN swc;
if (sqlca.sqlcode < 0) return -1;
for (;;) {
EXEC SQL FETCH swc INTO :h_merch, :h_cnt, :h_amt;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE swc; return -1; }
num += h_amt;
den += h_cnt;
}
EXEC SQL CLOSE swc;
if (den <= 0) return 0;
return num / den;
}

View file

@ -0,0 +1,16 @@
/*
* au_summaryrebuild_batch.h - copybook for au_summaryrebuild_batch (XA client).
* au_summary + . Kept in dbio/ for -I resolution.
*/
#ifndef AU_SUMMARYREBUILD_BATCH_H
#define AU_SUMMARYREBUILD_BATCH_H
typedef struct {
char biz_date[16];
long rows_affected;
long total_approved;
} au_rebuild_ctx_t;
long aub_rebuild_clip(long affected);
#endif /* AU_SUMMARYREBUILD_BATCH_H */

View file

@ -0,0 +1,16 @@
/*
* au_topcard_batch.h - copybook for au_topcard_batch (XA client).
* + . Kept in dbio/ for -I resolution.
*/
#ifndef AU_TOPCARD_BATCH_H
#define AU_TOPCARD_BATCH_H
typedef struct {
char biz_date[16];
char top_card[24];
long top_spend;
} au_topcard_ctx_t;
int aub_topcard_valid(long spend);
#endif /* AU_TOPCARD_BATCH_H */