고도화: 전 모듈 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
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