고도화: 전 모듈 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:
parent
05ad8a3064
commit
fc16ea64c8
422 changed files with 8717 additions and 0 deletions
46
app/src/py/batch/py_cancelpurge_batch.pgc
Normal file
46
app/src/py/batch/py_cancelpurge_batch.pgc
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* py_cancelpurge_batch.pgc - py 취소 지급 정리 (기간 DELETE 배치, XA).
|
||||
*
|
||||
* Deletes cancelled(C) payouts across a [from,to] date range in ONE XA
|
||||
* transaction and reports how many rows were purged.
|
||||
* Usage: py_cancelpurge_batch FROM_DATE TO_DATE
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "py_cancelpurge_batch.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *from_date = (argc > 1) ? argv[1] : "2026-01-01";
|
||||
const char *to_date = (argc > 2) ? argv[2] : "2026-06-30";
|
||||
py_cancelpurge_rec_t rec;
|
||||
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_from[16], h_to[16];
|
||||
long h_purged;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
strncpy(h_from, from_date, sizeof(h_from)-1); h_from[sizeof(h_from)-1] = 0;
|
||||
strncpy(h_to, to_date, sizeof(h_to)-1); h_to[sizeof(h_to)-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 DELETE FROM py_payout
|
||||
WHERE status = 'C' AND biz_date >= :h_from AND biz_date <= :h_to;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "py_cancelpurge_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
h_purged = sqlca.sqlerrd[2];
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
|
||||
strncpy(rec.from_date, from_date, sizeof(rec.from_date)-1); rec.from_date[sizeof(rec.from_date)-1] = 0;
|
||||
strncpy(rec.to_date, to_date, sizeof(rec.to_date)-1); rec.to_date[sizeof(rec.to_date)-1] = 0;
|
||||
rec.purged = h_purged;
|
||||
printf(">>> py_cancelpurge_batch COMMIT: range=%s..%s purged=%ld\n", rec.from_date, rec.to_date, rec.purged);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
52
app/src/py/batch/py_chanwalk_batch.pgc
Normal file
52
app/src/py/batch/py_chanwalk_batch.pgc
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* py_chanwalk_batch.pgc - py 채널별 집계 순회 (커서 배치, XA).
|
||||
*
|
||||
* Walks a channel-grouped cursor over the day's payouts, accumulating channel
|
||||
* count and grand total, inside ONE XA transaction.
|
||||
* Usage: py_chanwalk_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "py_chanwalk_batch.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
|
||||
py_chanwalk_rec_t rec;
|
||||
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16], h_ch[16];
|
||||
long h_cnt, h_amt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
rec.channels = 0; rec.grand_total = 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 cwcur CURSOR FOR
|
||||
SELECT channel, count(*), coalesce(sum(amount),0)
|
||||
FROM py_payout WHERE biz_date = :h_bizdate GROUP BY channel ORDER BY channel;
|
||||
EXEC SQL OPEN cwcur;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "py_chanwalk_batch OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
for (;;) {
|
||||
EXEC SQL FETCH cwcur INTO :h_ch, :h_cnt, :h_amt;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE cwcur; fprintf(stderr, "py_chanwalk_batch FETCH FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
rec.channels++; rec.grand_total += h_amt;
|
||||
}
|
||||
EXEC SQL CLOSE cwcur;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
|
||||
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date)-1); rec.biz_date[sizeof(rec.biz_date)-1] = 0;
|
||||
printf(">>> py_chanwalk_batch COMMIT: date=%s channels=%ld grand_total=%ld\n",
|
||||
rec.biz_date, rec.channels, rec.grand_total);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
44
app/src/py/batch/py_ledgerpost_batch.pgc
Normal file
44
app/src/py/batch/py_ledgerpost_batch.pgc
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* py_ledgerpost_batch.pgc - py 지급완료 원장 전기 (INSERT..SELECT 배치, XA).
|
||||
*
|
||||
* Posts every paid(P) payout of the day into py_ledger as an OUT entry with a
|
||||
* single INSERT..SELECT, in ONE XA transaction.
|
||||
* Usage: py_ledgerpost_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "py_ledgerpost_batch.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
|
||||
py_ledgerpost_rec_t rec;
|
||||
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_posted;
|
||||
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 py_ledger (ledger_id, payout_id, entry_type, amount, biz_date)
|
||||
SELECT nextval('py_ledger_seq'), payout_id, 'OUT', net, biz_date
|
||||
FROM py_payout WHERE biz_date = :h_bizdate AND status = 'P';
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "py_ledgerpost_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
h_posted = sqlca.sqlerrd[2];
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
|
||||
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date)-1); rec.biz_date[sizeof(rec.biz_date)-1] = 0;
|
||||
rec.posted = h_posted;
|
||||
printf(">>> py_ledgerpost_batch COMMIT: date=%s posted=%ld\n", rec.biz_date, rec.posted);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
49
app/src/py/batch/py_recon_batch.pgc
Normal file
49
app/src/py/batch/py_recon_batch.pgc
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* py_recon_batch.pgc - py 지급집계 대사 (집계 vs 실집계 2-쿼리 대조 배치, XA).
|
||||
*
|
||||
* Compares the stored py_summary amount against the live py_payout sum for one
|
||||
* merchant/day and reports the gap, all inside ONE XA transaction.
|
||||
* Usage: py_recon_batch MERCHANT [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "py_recon_batch.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *merch = (argc > 1) ? argv[1] : "M0001";
|
||||
const char *bizdate = (argc > 2) ? argv[2] : "2026-07-19";
|
||||
py_recon_rec_t rec;
|
||||
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_bizdate[16];
|
||||
long h_rec, h_live;
|
||||
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;
|
||||
|
||||
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(payout_amount,0) INTO :h_rec FROM py_summary
|
||||
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "py_recon_batch sum FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
if (sqlca.sqlcode == 100) h_rec = 0;
|
||||
EXEC SQL SELECT coalesce(sum(amount),0) INTO :h_live FROM py_payout
|
||||
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "py_recon_batch live 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; }
|
||||
|
||||
strncpy(rec.merchant_id, merch, sizeof(rec.merchant_id)-1); rec.merchant_id[sizeof(rec.merchant_id)-1] = 0;
|
||||
rec.recorded_amt = h_rec; rec.live_amt = h_live; rec.gap = h_live - h_rec;
|
||||
printf(">>> py_recon_batch COMMIT: merch=%s date=%s recorded=%ld live=%ld gap=%ld\n",
|
||||
rec.merchant_id, bizdate, rec.recorded_amt, rec.live_amt, rec.gap);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
43
app/src/py/batch/py_winrank_batch.pgc
Normal file
43
app/src/py/batch/py_winrank_batch.pgc
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* py_winrank_batch.pgc - py 누계 최고점 (윈도우 함수 배치, XA).
|
||||
*
|
||||
* Computes the peak per-merchant running total of net payouts for the day using
|
||||
* a SUM() OVER window, inside ONE XA transaction.
|
||||
* Usage: py_winrank_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "py_winrank_batch.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
|
||||
py_winrank_rec_t rec;
|
||||
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_peak;
|
||||
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(max(run_tot),0) INTO :h_peak FROM (
|
||||
SELECT sum(net) OVER (PARTITION BY merchant_id ORDER BY payout_id) AS run_tot
|
||||
FROM py_payout WHERE biz_date = :h_bizdate) w;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "py_winrank_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; }
|
||||
|
||||
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date)-1); rec.biz_date[sizeof(rec.biz_date)-1] = 0;
|
||||
rec.peak_running = h_peak;
|
||||
printf(">>> py_winrank_batch COMMIT: date=%s peak_running=%ld\n", rec.biz_date, rec.peak_running);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
11
app/src/py/dbio/py_account_having_dbio.h
Normal file
11
app/src/py/dbio/py_account_having_dbio.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* py_account_having_dbio.h - py 모듈 DB 접근 계층 copybook (py_account_having_dbio, part of libpydbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
*/
|
||||
#ifndef PY_ACCOUNT_HAVING_DBIO_H
|
||||
#define PY_ACCOUNT_HAVING_DBIO_H
|
||||
|
||||
long pydb_account_low_balance_merchants(long floor_bal);
|
||||
|
||||
#endif /* PY_ACCOUNT_HAVING_DBIO_H */
|
||||
21
app/src/py/dbio/py_account_having_dbio.pgc
Normal file
21
app/src/py/dbio/py_account_having_dbio.pgc
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* py_account_having_dbio.pgc - py 모듈 DB 접근 함수 세트 (py_account_having_dbio), archived into libpydbio.a.
|
||||
* 가맹점 계좌 합산잔액이 기준 미만인 가맹점 수를 GROUP BY HAVING 으로 센다.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "py_account_having_dbio.h"
|
||||
|
||||
/* GROUP BY HAVING: 합산잔액 < floor 인 가맹점 수. */
|
||||
long pydb_account_low_balance_merchants(long floor_bal)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_floor = floor_bal, h_cnt = 0;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
EXEC SQL SELECT count(*) INTO :h_cnt FROM (
|
||||
SELECT merchant_id FROM py_account
|
||||
GROUP BY merchant_id HAVING coalesce(sum(balance),0) < :h_floor) t;
|
||||
if (sqlca.sqlcode < 0) { userlog("pydb_account_low_balance_merchants FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
|
||||
return h_cnt;
|
||||
}
|
||||
14
app/src/py/dbio/py_cancelpurge_batch.h
Normal file
14
app/src/py/dbio/py_cancelpurge_batch.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* py_cancelpurge_batch.h - py 취소건 정리 배치 전용 copybook.
|
||||
* 삭제 범위/건수 레이아웃.
|
||||
*/
|
||||
#ifndef PY_CANCELPURGE_BATCH_H
|
||||
#define PY_CANCELPURGE_BATCH_H
|
||||
|
||||
typedef struct {
|
||||
char from_date[16];
|
||||
char to_date[16];
|
||||
long purged;
|
||||
} py_cancelpurge_rec_t;
|
||||
|
||||
#endif /* PY_CANCELPURGE_BATCH_H */
|
||||
11
app/src/py/dbio/py_channel_walk_dbio.h
Normal file
11
app/src/py/dbio/py_channel_walk_dbio.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* py_channel_walk_dbio.h - py 모듈 DB 접근 계층 copybook (py_channel_walk_dbio, part of libpydbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
*/
|
||||
#ifndef PY_CHANNEL_WALK_DBIO_H
|
||||
#define PY_CHANNEL_WALK_DBIO_H
|
||||
|
||||
long pydb_channel_active(const char *bizdate, long min_txn);
|
||||
|
||||
#endif /* PY_CHANNEL_WALK_DBIO_H */
|
||||
32
app/src/py/dbio/py_channel_walk_dbio.pgc
Normal file
32
app/src/py/dbio/py_channel_walk_dbio.pgc
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* py_channel_walk_dbio.pgc - py 모듈 DB 접근 함수 세트 (py_channel_walk_dbio), archived into libpydbio.a.
|
||||
* 채널별 집계를 커서로 순회하며 활성 채널(기준 건수 이상)을 센다.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "py_channel_walk_dbio.h"
|
||||
|
||||
/* 커서 순회: 채널별 (건수, 금액) 을 훑어 min_txn 이상인 채널 수 반환. */
|
||||
long pydb_channel_active(const char *bizdate, long min_txn)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16], h_ch[16];
|
||||
long h_min = min_txn, h_cnt, h_amt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
long active = 0;
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
EXEC SQL DECLARE pych CURSOR FOR
|
||||
SELECT channel, count(*), coalesce(sum(amount),0)
|
||||
FROM py_payout WHERE biz_date = :h_bizdate GROUP BY channel ORDER BY channel;
|
||||
EXEC SQL OPEN pych;
|
||||
if (sqlca.sqlcode < 0) return -1;
|
||||
for (;;) {
|
||||
EXEC SQL FETCH pych INTO :h_ch, :h_cnt, :h_amt;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE pych; return -1; }
|
||||
if (h_cnt >= h_min) active++;
|
||||
}
|
||||
EXEC SQL CLOSE pych;
|
||||
return active;
|
||||
}
|
||||
14
app/src/py/dbio/py_chanwalk_batch.h
Normal file
14
app/src/py/dbio/py_chanwalk_batch.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* py_chanwalk_batch.h - py 채널 순회 집계 배치 전용 copybook.
|
||||
* 채널별 (건수,금액) 누적 레이아웃.
|
||||
*/
|
||||
#ifndef PY_CHANWALK_BATCH_H
|
||||
#define PY_CHANWALK_BATCH_H
|
||||
|
||||
typedef struct {
|
||||
char biz_date[16];
|
||||
long channels;
|
||||
long grand_total;
|
||||
} py_chanwalk_rec_t;
|
||||
|
||||
#endif /* PY_CHANWALK_BATCH_H */
|
||||
11
app/src/py/dbio/py_file_span_dbio.h
Normal file
11
app/src/py/dbio/py_file_span_dbio.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* py_file_span_dbio.h - py 모듈 DB 접근 계층 copybook (py_file_span_dbio, part of libpydbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
*/
|
||||
#ifndef PY_FILE_SPAN_DBIO_H
|
||||
#define PY_FILE_SPAN_DBIO_H
|
||||
|
||||
int pydb_file_record_span(const char *bizdate, long *min_out, long *max_out);
|
||||
|
||||
#endif /* PY_FILE_SPAN_DBIO_H */
|
||||
23
app/src/py/dbio/py_file_span_dbio.pgc
Normal file
23
app/src/py/dbio/py_file_span_dbio.pgc
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* py_file_span_dbio.pgc - py 모듈 DB 접근 함수 세트 (py_file_span_dbio), archived into libpydbio.a.
|
||||
* 당일 지급파일의 최소/최대 레코드건수를 한 번에 조회한다.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "py_file_span_dbio.h"
|
||||
|
||||
/* min/max: 당일 파일 레코드건수 범위를 out 파라미터로 반환. */
|
||||
int pydb_file_record_span(const char *bizdate, long *min_out, long *max_out)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_min = 0, h_max = 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(min(record_count),0), coalesce(max(record_count),0)
|
||||
INTO :h_min, :h_max FROM py_file WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) { userlog("pydb_file_record_span FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
|
||||
*min_out = h_min; *max_out = h_max;
|
||||
return 0;
|
||||
}
|
||||
11
app/src/py/dbio/py_ledger_mix_dbio.h
Normal file
11
app/src/py/dbio/py_ledger_mix_dbio.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* py_ledger_mix_dbio.h - py 모듈 DB 접근 계층 copybook (py_ledger_mix_dbio, part of libpydbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
*/
|
||||
#ifndef PY_LEDGER_MIX_DBIO_H
|
||||
#define PY_LEDGER_MIX_DBIO_H
|
||||
|
||||
int pydb_ledger_type_mix(const char *bizdate, long *kinds_out, long *out_amt_out);
|
||||
|
||||
#endif /* PY_LEDGER_MIX_DBIO_H */
|
||||
24
app/src/py/dbio/py_ledger_mix_dbio.pgc
Normal file
24
app/src/py/dbio/py_ledger_mix_dbio.pgc
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* py_ledger_mix_dbio.pgc - py 모듈 DB 접근 함수 세트 (py_ledger_mix_dbio), archived into libpydbio.a.
|
||||
* 지급원장 상세의 엔트리 종류 수와 OUT 금액을 count DISTINCT + FILTER 로 함께 구한다.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "py_ledger_mix_dbio.h"
|
||||
|
||||
/* count DISTINCT + FILTER: 엔트리 종류 수와 OUT 합계 동시 산출. */
|
||||
int pydb_ledger_type_mix(const char *bizdate, long *kinds_out, long *out_amt_out)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_kinds = 0, h_out = 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 entry_type),
|
||||
coalesce(sum(amount) FILTER (WHERE entry_type = 'OUT'), 0)
|
||||
INTO :h_kinds, :h_out FROM py_ledger WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) { userlog("pydb_ledger_type_mix FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
|
||||
*kinds_out = h_kinds; *out_amt_out = h_out;
|
||||
return 0;
|
||||
}
|
||||
11
app/src/py/dbio/py_ledger_post_dbio.h
Normal file
11
app/src/py/dbio/py_ledger_post_dbio.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* py_ledger_post_dbio.h - py 모듈 DB 접근 계층 copybook (py_ledger_post_dbio, part of libpydbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
*/
|
||||
#ifndef PY_LEDGER_POST_DBIO_H
|
||||
#define PY_LEDGER_POST_DBIO_H
|
||||
|
||||
long pydb_ledger_post_paid(const char *bizdate);
|
||||
|
||||
#endif /* PY_LEDGER_POST_DBIO_H */
|
||||
22
app/src/py/dbio/py_ledger_post_dbio.pgc
Normal file
22
app/src/py/dbio/py_ledger_post_dbio.pgc
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* py_ledger_post_dbio.pgc - py 모듈 DB 접근 함수 세트 (py_ledger_post_dbio), archived into libpydbio.a.
|
||||
* 지급완료(P) 건을 지급원장 상세로 INSERT..SELECT 전기한다.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "py_ledger_post_dbio.h"
|
||||
|
||||
/* INSERT..SELECT: 지급완료 건을 OUT 엔트리로 원장상세에 적재, 적재 건수 반환. */
|
||||
long pydb_ledger_post_paid(const char *bizdate)
|
||||
{
|
||||
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;
|
||||
EXEC SQL INSERT INTO py_ledger (ledger_id, payout_id, entry_type, amount, biz_date)
|
||||
SELECT nextval('py_ledger_seq'), payout_id, 'OUT', net, biz_date
|
||||
FROM py_payout WHERE biz_date = :h_bizdate AND status = 'P';
|
||||
if (sqlca.sqlcode < 0) { userlog("pydb_ledger_post_paid FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
|
||||
return sqlca.sqlerrd[2];
|
||||
}
|
||||
13
app/src/py/dbio/py_ledgerpost_batch.h
Normal file
13
app/src/py/dbio/py_ledgerpost_batch.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* py_ledgerpost_batch.h - py 지급완료 원장전기 배치 전용 copybook.
|
||||
* INSERT..SELECT 전기 건수 레이아웃.
|
||||
*/
|
||||
#ifndef PY_LEDGERPOST_BATCH_H
|
||||
#define PY_LEDGERPOST_BATCH_H
|
||||
|
||||
typedef struct {
|
||||
char biz_date[16];
|
||||
long posted;
|
||||
} py_ledgerpost_rec_t;
|
||||
|
||||
#endif /* PY_LEDGERPOST_BATCH_H */
|
||||
11
app/src/py/dbio/py_payout_corr_dbio.h
Normal file
11
app/src/py/dbio/py_payout_corr_dbio.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* py_payout_corr_dbio.h - py 모듈 DB 접근 계층 copybook (py_payout_corr_dbio, part of libpydbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
*/
|
||||
#ifndef PY_PAYOUT_CORR_DBIO_H
|
||||
#define PY_PAYOUT_CORR_DBIO_H
|
||||
|
||||
long pydb_payout_above_own_avg(const char *bizdate);
|
||||
|
||||
#endif /* PY_PAYOUT_CORR_DBIO_H */
|
||||
24
app/src/py/dbio/py_payout_corr_dbio.pgc
Normal file
24
app/src/py/dbio/py_payout_corr_dbio.pgc
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* py_payout_corr_dbio.pgc - py 모듈 DB 접근 함수 세트 (py_payout_corr_dbio), archived into libpydbio.a.
|
||||
* 같은 가맹점 평균 금액을 상회하는 지급건 수를 상관 서브쿼리로 센다.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "py_payout_corr_dbio.h"
|
||||
|
||||
/* 상관 서브쿼리: 자기 가맹점 평균금액 초과 지급건 수. */
|
||||
long pydb_payout_above_own_avg(const char *bizdate)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long 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 count(*) INTO :h_cnt FROM py_payout p1
|
||||
WHERE p1.biz_date = :h_bizdate
|
||||
AND p1.amount > (SELECT avg(p2.amount) FROM py_payout p2
|
||||
WHERE p2.merchant_id = p1.merchant_id);
|
||||
if (sqlca.sqlcode < 0) { userlog("pydb_payout_above_own_avg FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
|
||||
return h_cnt;
|
||||
}
|
||||
11
app/src/py/dbio/py_payout_delrange_dbio.h
Normal file
11
app/src/py/dbio/py_payout_delrange_dbio.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* py_payout_delrange_dbio.h - py 모듈 DB 접근 계층 copybook (py_payout_delrange_dbio, part of libpydbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
*/
|
||||
#ifndef PY_PAYOUT_DELRANGE_DBIO_H
|
||||
#define PY_PAYOUT_DELRANGE_DBIO_H
|
||||
|
||||
long pydb_payout_purge_cancelled(const char *from_date, const char *to_date);
|
||||
|
||||
#endif /* PY_PAYOUT_DELRANGE_DBIO_H */
|
||||
22
app/src/py/dbio/py_payout_delrange_dbio.pgc
Normal file
22
app/src/py/dbio/py_payout_delrange_dbio.pgc
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* py_payout_delrange_dbio.pgc - py 모듈 DB 접근 함수 세트 (py_payout_delrange_dbio), archived into libpydbio.a.
|
||||
* 기간 범위의 취소(C) 지급건을 정리 삭제한다.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "py_payout_delrange_dbio.h"
|
||||
|
||||
/* DELETE 범위: [from,to] 기간의 취소 지급건 삭제, 삭제 건수 반환. */
|
||||
long pydb_payout_purge_cancelled(const char *from_date, const char *to_date)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_from[16], h_to[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
strncpy(h_from, from_date, sizeof(h_from)-1); h_from[sizeof(h_from)-1] = 0;
|
||||
strncpy(h_to, to_date, sizeof(h_to)-1); h_to[sizeof(h_to)-1] = 0;
|
||||
EXEC SQL DELETE FROM py_payout
|
||||
WHERE status = 'C' AND biz_date >= :h_from AND biz_date <= :h_to;
|
||||
if (sqlca.sqlcode < 0) { userlog("pydb_payout_purge_cancelled FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
|
||||
return sqlca.sqlerrd[2];
|
||||
}
|
||||
11
app/src/py/dbio/py_payout_notexists_dbio.h
Normal file
11
app/src/py/dbio/py_payout_notexists_dbio.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* py_payout_notexists_dbio.h - py 모듈 DB 접근 계층 copybook (py_payout_notexists_dbio, part of libpydbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
*/
|
||||
#ifndef PY_PAYOUT_NOTEXISTS_DBIO_H
|
||||
#define PY_PAYOUT_NOTEXISTS_DBIO_H
|
||||
|
||||
long pydb_payout_unscheduled(const char *bizdate);
|
||||
|
||||
#endif /* PY_PAYOUT_NOTEXISTS_DBIO_H */
|
||||
23
app/src/py/dbio/py_payout_notexists_dbio.pgc
Normal file
23
app/src/py/dbio/py_payout_notexists_dbio.pgc
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* py_payout_notexists_dbio.pgc - py 모듈 DB 접근 함수 세트 (py_payout_notexists_dbio), archived into libpydbio.a.
|
||||
* 예약 테이블에 대응 행이 없는 지급건(미예약)을 NOT EXISTS 로 센다.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "py_payout_notexists_dbio.h"
|
||||
|
||||
/* NOT EXISTS: 예약행이 없는 당일 지급건 수. */
|
||||
long pydb_payout_unscheduled(const char *bizdate)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long 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 count(*) INTO :h_cnt FROM py_payout pp
|
||||
WHERE pp.biz_date = :h_bizdate
|
||||
AND NOT EXISTS (SELECT 1 FROM py_schedule ps WHERE ps.payout_id = pp.payout_id);
|
||||
if (sqlca.sqlcode < 0) { userlog("pydb_payout_unscheduled FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
|
||||
return h_cnt;
|
||||
}
|
||||
11
app/src/py/dbio/py_payout_rejrate_dbio.h
Normal file
11
app/src/py/dbio/py_payout_rejrate_dbio.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* py_payout_rejrate_dbio.h - py 모듈 DB 접근 계층 copybook (py_payout_rejrate_dbio, part of libpydbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
*/
|
||||
#ifndef PY_PAYOUT_REJRATE_DBIO_H
|
||||
#define PY_PAYOUT_REJRATE_DBIO_H
|
||||
|
||||
long pydb_payout_reject_rate(const char *bizdate);
|
||||
|
||||
#endif /* PY_PAYOUT_REJRATE_DBIO_H */
|
||||
24
app/src/py/dbio/py_payout_rejrate_dbio.pgc
Normal file
24
app/src/py/dbio/py_payout_rejrate_dbio.pgc
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* py_payout_rejrate_dbio.pgc - py 모듈 DB 접근 함수 세트 (py_payout_rejrate_dbio), archived into libpydbio.a.
|
||||
* 반려(J) 지급건 비율(퍼센트)을 CASE 분기 나눗셈으로 산출한다.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "py_payout_rejrate_dbio.h"
|
||||
|
||||
/* 비율(CASE): 반려 건수 비중(%) = count(J)*100 / count(*). */
|
||||
long pydb_payout_reject_rate(const char *bizdate)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_rate = 0;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
EXEC SQL SELECT CASE WHEN count(*) > 0
|
||||
THEN count(*) FILTER (WHERE status = 'J') * 100 / count(*)
|
||||
ELSE 0 END
|
||||
INTO :h_rate FROM py_payout WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) { userlog("pydb_payout_reject_rate FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
|
||||
return h_rate;
|
||||
}
|
||||
11
app/src/py/dbio/py_payout_retryhist_dbio.h
Normal file
11
app/src/py/dbio/py_payout_retryhist_dbio.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* py_payout_retryhist_dbio.h - py 모듈 DB 접근 계층 copybook (py_payout_retryhist_dbio, part of libpydbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
*/
|
||||
#ifndef PY_PAYOUT_RETRYHIST_DBIO_H
|
||||
#define PY_PAYOUT_RETRYHIST_DBIO_H
|
||||
|
||||
long pydb_payout_retry_buckets(const char *bizdate, long min_share);
|
||||
|
||||
#endif /* PY_PAYOUT_RETRYHIST_DBIO_H */
|
||||
23
app/src/py/dbio/py_payout_retryhist_dbio.pgc
Normal file
23
app/src/py/dbio/py_payout_retryhist_dbio.pgc
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* py_payout_retryhist_dbio.pgc - py 모듈 DB 접근 함수 세트 (py_payout_retryhist_dbio), archived into libpydbio.a.
|
||||
* 재시도 횟수별 분포에서 일정 건수 이상 나타난 버킷 수를 구한다.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "py_payout_retryhist_dbio.h"
|
||||
|
||||
/* GROUP BY retry_count HAVING: 건수 >= min_share 인 재시도 버킷 수. */
|
||||
long pydb_payout_retry_buckets(const char *bizdate, long min_share)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_min = min_share, 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 count(*) INTO :h_cnt FROM (
|
||||
SELECT retry_count FROM py_payout WHERE biz_date = :h_bizdate
|
||||
GROUP BY retry_count HAVING count(*) >= :h_min) b;
|
||||
if (sqlca.sqlcode < 0) { userlog("pydb_payout_retry_buckets FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
|
||||
return h_cnt;
|
||||
}
|
||||
11
app/src/py/dbio/py_payout_weighted_dbio.h
Normal file
11
app/src/py/dbio/py_payout_weighted_dbio.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* py_payout_weighted_dbio.h - py 모듈 DB 접근 계층 copybook (py_payout_weighted_dbio, part of libpydbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
*/
|
||||
#ifndef PY_PAYOUT_WEIGHTED_DBIO_H
|
||||
#define PY_PAYOUT_WEIGHTED_DBIO_H
|
||||
|
||||
long pydb_payout_weighted_bps(const char *bizdate);
|
||||
|
||||
#endif /* PY_PAYOUT_WEIGHTED_DBIO_H */
|
||||
23
app/src/py/dbio/py_payout_weighted_dbio.pgc
Normal file
23
app/src/py/dbio/py_payout_weighted_dbio.pgc
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* py_payout_weighted_dbio.pgc - py 모듈 DB 접근 함수 세트 (py_payout_weighted_dbio), archived into libpydbio.a.
|
||||
* 금액 가중 수수료율(bps) = sum(fee)*10000 / sum(amount).
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "py_payout_weighted_dbio.h"
|
||||
|
||||
/* 가중평균 수수료율(bps): 총수수료를 총금액으로 나눈 값. */
|
||||
long pydb_payout_weighted_bps(const char *bizdate)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_bps = 0;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
EXEC SQL SELECT CASE WHEN coalesce(sum(amount),0) > 0
|
||||
THEN sum(fee) * 10000 / sum(amount) ELSE 0 END
|
||||
INTO :h_bps FROM py_payout WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) { userlog("pydb_payout_weighted_bps FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
|
||||
return h_bps;
|
||||
}
|
||||
11
app/src/py/dbio/py_payout_window_dbio.h
Normal file
11
app/src/py/dbio/py_payout_window_dbio.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* py_payout_window_dbio.h - py 모듈 DB 접근 계층 copybook (py_payout_window_dbio, part of libpydbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
*/
|
||||
#ifndef PY_PAYOUT_WINDOW_DBIO_H
|
||||
#define PY_PAYOUT_WINDOW_DBIO_H
|
||||
|
||||
long pydb_payout_peak_running(const char *bizdate);
|
||||
|
||||
#endif /* PY_PAYOUT_WINDOW_DBIO_H */
|
||||
23
app/src/py/dbio/py_payout_window_dbio.pgc
Normal file
23
app/src/py/dbio/py_payout_window_dbio.pgc
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* py_payout_window_dbio.pgc - py 모듈 DB 접근 함수 세트 (py_payout_window_dbio), archived into libpydbio.a.
|
||||
* 가맹점별 지급 순액을 윈도우 누계로 계산해 최대 누계선을 구한다.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "py_payout_window_dbio.h"
|
||||
|
||||
/* 윈도우 함수: 가맹점별 payout_id 순 누계(net) 중 최대값. */
|
||||
long pydb_payout_peak_running(const char *bizdate)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_peak = 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(run_tot),0) INTO :h_peak FROM (
|
||||
SELECT sum(net) OVER (PARTITION BY merchant_id ORDER BY payout_id) AS run_tot
|
||||
FROM py_payout WHERE biz_date = :h_bizdate) w;
|
||||
if (sqlca.sqlcode < 0) { userlog("pydb_payout_peak_running FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
|
||||
return h_peak;
|
||||
}
|
||||
15
app/src/py/dbio/py_recon_batch.h
Normal file
15
app/src/py/dbio/py_recon_batch.h
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* py_recon_batch.h - py 대사 배치 전용 copybook (레코드 레이아웃).
|
||||
* 집계 테이블 vs 원장 실집계 대사 결과를 담는 구조체.
|
||||
*/
|
||||
#ifndef PY_RECON_BATCH_H
|
||||
#define PY_RECON_BATCH_H
|
||||
|
||||
typedef struct {
|
||||
char merchant_id[64];
|
||||
long recorded_amt;
|
||||
long live_amt;
|
||||
long gap;
|
||||
} py_recon_rec_t;
|
||||
|
||||
#endif /* PY_RECON_BATCH_H */
|
||||
11
app/src/py/dbio/py_schedule_due_dbio.h
Normal file
11
app/src/py/dbio/py_schedule_due_dbio.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* py_schedule_due_dbio.h - py 모듈 DB 접근 계층 copybook (py_schedule_due_dbio, part of libpydbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
*/
|
||||
#ifndef PY_SCHEDULE_DUE_DBIO_H
|
||||
#define PY_SCHEDULE_DUE_DBIO_H
|
||||
|
||||
long pydb_schedule_due_net(const char *rundate);
|
||||
|
||||
#endif /* PY_SCHEDULE_DUE_DBIO_H */
|
||||
23
app/src/py/dbio/py_schedule_due_dbio.pgc
Normal file
23
app/src/py/dbio/py_schedule_due_dbio.pgc
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* py_schedule_due_dbio.pgc - py 모듈 DB 접근 함수 세트 (py_schedule_due_dbio), archived into libpydbio.a.
|
||||
* 실행일에 예약(S)되고 승인(A)된 지급건의 순액을 예약-지급 조인으로 합산한다.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "py_schedule_due_dbio.h"
|
||||
|
||||
/* JOIN: 예약(S) x 승인(A) 지급건의 실행 대상 순액 합. */
|
||||
long pydb_schedule_due_net(const char *rundate)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_rundate[16];
|
||||
long h_v = 0;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
strncpy(h_rundate, rundate, sizeof(h_rundate)-1); h_rundate[sizeof(h_rundate)-1] = 0;
|
||||
EXEC SQL SELECT coalesce(sum(pp.net),0) INTO :h_v
|
||||
FROM py_schedule ps JOIN py_payout pp ON ps.payout_id = pp.payout_id
|
||||
WHERE ps.run_date = :h_rundate AND ps.status = 'S' AND pp.status = 'A';
|
||||
if (sqlca.sqlcode < 0) { userlog("pydb_schedule_due_net FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
|
||||
return h_v;
|
||||
}
|
||||
11
app/src/py/dbio/py_summary_accum_dbio.h
Normal file
11
app/src/py/dbio/py_summary_accum_dbio.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* py_summary_accum_dbio.h - py 모듈 DB 접근 계층 copybook (py_summary_accum_dbio, part of libpydbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
*/
|
||||
#ifndef PY_SUMMARY_ACCUM_DBIO_H
|
||||
#define PY_SUMMARY_ACCUM_DBIO_H
|
||||
|
||||
int pydb_summary_accumulate(const char *merch, const char *bizdate, long cnt, long amount);
|
||||
|
||||
#endif /* PY_SUMMARY_ACCUM_DBIO_H */
|
||||
27
app/src/py/dbio/py_summary_accum_dbio.pgc
Normal file
27
app/src/py/dbio/py_summary_accum_dbio.pgc
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* py_summary_accum_dbio.pgc - py 모듈 DB 접근 함수 세트 (py_summary_accum_dbio), archived into libpydbio.a.
|
||||
* 가맹점 일별 집계에 건수/금액을 누적 가산하는 upsert.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "py_summary_accum_dbio.h"
|
||||
|
||||
/* ON CONFLICT 누적 upsert: 기존 집계에 delta 를 더한다. */
|
||||
int pydb_summary_accumulate(const char *merch, const char *bizdate, long cnt, long amount)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_bizdate[16];
|
||||
long h_cnt = cnt, h_amt = amount;
|
||||
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 INSERT INTO py_summary (merchant_id, biz_date, payout_count, payout_amount)
|
||||
VALUES (:h_merch, :h_bizdate, :h_cnt, :h_amt)
|
||||
ON CONFLICT (merchant_id, biz_date) DO UPDATE
|
||||
SET payout_count = py_summary.payout_count + EXCLUDED.payout_count,
|
||||
payout_amount = py_summary.payout_amount + EXCLUDED.payout_amount,
|
||||
updated_at = now();
|
||||
if (sqlca.sqlcode < 0) { userlog("pydb_summary_accumulate FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
|
||||
return 0;
|
||||
}
|
||||
12
app/src/py/dbio/py_summary_gap_dbio.h
Normal file
12
app/src/py/dbio/py_summary_gap_dbio.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* py_summary_gap_dbio.h - py 모듈 DB 접근 계층 copybook (py_summary_gap_dbio, part of libpydbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
*/
|
||||
#ifndef PY_SUMMARY_GAP_DBIO_H
|
||||
#define PY_SUMMARY_GAP_DBIO_H
|
||||
|
||||
int pydb_summary_gap(const char *merch, const char *bizdate,
|
||||
long *recorded, long *live, long *gap);
|
||||
|
||||
#endif /* PY_SUMMARY_GAP_DBIO_H */
|
||||
29
app/src/py/dbio/py_summary_gap_dbio.pgc
Normal file
29
app/src/py/dbio/py_summary_gap_dbio.pgc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* py_summary_gap_dbio.pgc - py 모듈 DB 접근 함수 세트 (py_summary_gap_dbio), archived into libpydbio.a.
|
||||
* 집계 테이블에 적재된 금액과 원장 실집계 금액의 차이를 대조한다.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "py_summary_gap_dbio.h"
|
||||
|
||||
/* 집계 vs 실집계 대조: 적재금액, 실집계금액, 차액을 반환. */
|
||||
int pydb_summary_gap(const char *merch, const char *bizdate,
|
||||
long *recorded, long *live, long *gap)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_bizdate[16];
|
||||
long h_rec = 0, h_live = 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(payout_amount,0) INTO :h_rec FROM py_summary
|
||||
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0 && sqlca.sqlcode != 100) return -1;
|
||||
if (sqlca.sqlcode == 100) h_rec = 0;
|
||||
EXEC SQL SELECT coalesce(sum(amount),0) INTO :h_live FROM py_payout
|
||||
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) { userlog("pydb_summary_gap FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); return -1; }
|
||||
*recorded = h_rec; *live = h_live; *gap = h_live - h_rec;
|
||||
return 0;
|
||||
}
|
||||
13
app/src/py/dbio/py_winrank_batch.h
Normal file
13
app/src/py/dbio/py_winrank_batch.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* py_winrank_batch.h - py 윈도우 누계 배치 전용 copybook.
|
||||
* 가맹점별 누계선 최고점 산출 결과 레이아웃.
|
||||
*/
|
||||
#ifndef PY_WINRANK_BATCH_H
|
||||
#define PY_WINRANK_BATCH_H
|
||||
|
||||
typedef struct {
|
||||
char biz_date[16];
|
||||
long peak_running;
|
||||
} py_winrank_rec_t;
|
||||
|
||||
#endif /* PY_WINRANK_BATCH_H */
|
||||
Loading…
Add table
Add a link
Reference in a new issue