고도화: 전 모듈 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
60
app/src/ac/batch/ac_amountband_batch.pgc
Normal file
60
app/src/ac/batch/ac_amountband_batch.pgc
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* ac_amountband_batch.pgc - ac 매입 금액대 분포 배치 (CASE 버킷 + XA).
|
||||
*
|
||||
* ATMI client: one global transaction; a single CASE-bucketed aggregate splits
|
||||
* the day's purchases into three amount bands. The C helper mirrors the band
|
||||
* thresholds for reporting. tpcommit drives XA 2PC.
|
||||
* Usage: ac_amountband_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "ac_amountband_batch.h"
|
||||
|
||||
/* 금액을 3구간으로 분류. */
|
||||
int acb_band_classify(long amount)
|
||||
{
|
||||
if (amount < 50000L) return 0;
|
||||
if (amount < 500000L) return 1;
|
||||
return 2;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ac_band_ctx_t ctx;
|
||||
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
|
||||
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_lo = 0, h_mid = 0, h_hi = 0;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
strncpy(ctx.biz_date, bizdate, sizeof(ctx.biz_date)-1);
|
||||
|
||||
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL SELECT
|
||||
count(*) FILTER (WHERE amount < 50000),
|
||||
count(*) FILTER (WHERE amount >= 50000 AND amount < 500000),
|
||||
count(*) FILTER (WHERE amount >= 500000)
|
||||
INTO :h_lo, :h_mid, :h_hi
|
||||
FROM purchase WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "ac_amountband_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
|
||||
ctx.band_lo = h_lo;
|
||||
ctx.band_mid = h_mid;
|
||||
ctx.band_hi = h_hi;
|
||||
(void)acb_band_classify(ctx.band_hi);
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> ac_amountband_batch COMMIT: bizdate=%s lo=%ld mid=%ld hi=%ld\n",
|
||||
ctx.biz_date, ctx.band_lo, ctx.band_mid, ctx.band_hi);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
58
app/src/ac/batch/ac_concentration_batch.pgc
Normal file
58
app/src/ac/batch/ac_concentration_batch.pgc
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* ac_concentration_batch.pgc - ac 상위매입 집중도 배치 (window + XA).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction, a windowed subquery ranks purchases and a scalar sums the top-3
|
||||
* against the daily total; tpcommit drives XA 2PC.
|
||||
* Usage: ac_concentration_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "ac_concentration_batch.h"
|
||||
|
||||
/* 집중도(bps) = top_sum / total * 10000. total<=0 이면 0. */
|
||||
long acb_conc_ratio_bps(long top_sum, long total)
|
||||
{
|
||||
if (total <= 0) return 0;
|
||||
return (top_sum * 10000L) / total;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ac_conc_ctx_t ctx;
|
||||
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
|
||||
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_top = 0, h_total = 0;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
strncpy(ctx.biz_date, bizdate, sizeof(ctx.biz_date)-1);
|
||||
|
||||
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL SELECT coalesce(sum(amount),0) INTO :h_top FROM (
|
||||
SELECT amount, row_number() OVER (ORDER BY amount DESC) AS rn
|
||||
FROM purchase WHERE biz_date = :h_bizdate) t WHERE t.rn <= 3;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "ac_concentration_batch TOP FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
|
||||
EXEC SQL SELECT coalesce(sum(amount),0) INTO :h_total FROM purchase WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "ac_concentration_batch TOT FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
|
||||
ctx.top_sum = h_top;
|
||||
ctx.total = h_total;
|
||||
ctx.ratio_bps = acb_conc_ratio_bps(ctx.top_sum, ctx.total);
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> ac_concentration_batch COMMIT: bizdate=%s top3=%ld total=%ld ratio_bps=%ld\n",
|
||||
ctx.biz_date, ctx.top_sum, ctx.total, ctx.ratio_bps);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
53
app/src/ac/batch/ac_fxweight_batch.pgc
Normal file
53
app/src/ac/batch/ac_fxweight_batch.pgc
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* ac_fxweight_batch.pgc - ac 해외매입 가중 평균 환율 배치 (XA).
|
||||
*
|
||||
* ATMI client: one global transaction; sums rate_bps weighted by krw_amount and
|
||||
* the weight itself, then a C helper computes the weighted average bps.
|
||||
* tpcommit drives XA 2PC. Usage: ac_fxweight_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "ac_fxweight_batch.h"
|
||||
|
||||
/* 가중합/가중치 나눗셈 (0 보호). */
|
||||
long acb_fxw_divide(long num, long den)
|
||||
{
|
||||
if (den <= 0) return 0;
|
||||
return num / den;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ac_fxw_ctx_t ctx;
|
||||
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
|
||||
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_num = 0, h_den = 0;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
strncpy(ctx.biz_date, bizdate, sizeof(ctx.biz_date)-1);
|
||||
|
||||
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL SELECT coalesce(sum(rate_bps * krw_amount),0), coalesce(sum(krw_amount),0)
|
||||
INTO :h_num, :h_den FROM ac_fx WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "ac_fxweight_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
|
||||
ctx.num = h_num;
|
||||
ctx.den = h_den;
|
||||
ctx.avg_bps = acb_fxw_divide(ctx.num, ctx.den);
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> ac_fxweight_batch COMMIT: bizdate=%s weight=%ld avg_bps=%ld\n",
|
||||
ctx.biz_date, ctx.den, ctx.avg_bps);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
63
app/src/ac/batch/ac_summaryrebuild_batch.pgc
Normal file
63
app/src/ac/batch/ac_summaryrebuild_batch.pgc
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* ac_summaryrebuild_batch.pgc - ac 가맹점 일집계 재구축 배치 (INSERT..SELECT + upsert + XA).
|
||||
*
|
||||
* ATMI client: one global transaction; an INSERT..SELECT..GROUP BY re-aggregates
|
||||
* purchase into merchant_summary via ON CONFLICT DO UPDATE, then reads back the
|
||||
* rebuilt gross. tpcommit drives XA 2PC. Usage: ac_summaryrebuild_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "ac_summaryrebuild_batch.h"
|
||||
|
||||
/* 반영 행수가 음수가 아니면 그대로 반환. */
|
||||
long acb_rebuild_ok(long affected)
|
||||
{
|
||||
return (affected < 0) ? 0 : affected;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ac_rebuild_ctx_t ctx;
|
||||
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
|
||||
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_gross = 0;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
strncpy(ctx.biz_date, bizdate, sizeof(ctx.biz_date)-1);
|
||||
|
||||
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 merchant_summary
|
||||
(merchant_id, biz_date, txn_count, gross_amount, fee_amount, net_amount)
|
||||
SELECT merchant_id, biz_date, count(*), coalesce(sum(amount),0),
|
||||
coalesce(sum(fee),0), coalesce(sum(net),0)
|
||||
FROM purchase WHERE biz_date = :h_bizdate
|
||||
GROUP BY merchant_id, biz_date
|
||||
ON CONFLICT (merchant_id, biz_date) DO UPDATE
|
||||
SET txn_count = EXCLUDED.txn_count,
|
||||
gross_amount = EXCLUDED.gross_amount,
|
||||
fee_amount = EXCLUDED.fee_amount,
|
||||
net_amount = EXCLUDED.net_amount,
|
||||
updated_at = now();
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "ac_summaryrebuild_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
ctx.rows_affected = acb_rebuild_ok(sqlca.sqlerrd[2]);
|
||||
|
||||
EXEC SQL SELECT coalesce(sum(gross_amount),0) INTO :h_gross FROM merchant_summary WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "ac_summaryrebuild_batch READ FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
ctx.total_gross = h_gross;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> ac_summaryrebuild_batch COMMIT: bizdate=%s rows=%ld gross=%ld\n",
|
||||
ctx.biz_date, ctx.rows_affected, ctx.total_gross);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
49
app/src/ac/batch/ac_unmatchpurge_batch.pgc
Normal file
49
app/src/ac/batch/ac_unmatchpurge_batch.pgc
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* ac_unmatchpurge_batch.pgc - ac 미매입 로그 정리 배치 (구간 DELETE + XA).
|
||||
*
|
||||
* ATMI client: one global transaction; a range DELETE removes ac_unmatch rows
|
||||
* older than the cutoff. The deleted count comes from sqlca.sqlerrd[2].
|
||||
* tpcommit drives XA 2PC. Usage: ac_unmatchpurge_batch [cutoff-YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "ac_unmatchpurge_batch.h"
|
||||
|
||||
/* 배치 인자를 cutoff 문자열로 복사 (그대로 사용). */
|
||||
void acb_purge_cutoff(const char *bizdate, char *out, int outsz)
|
||||
{
|
||||
strncpy(out, bizdate, outsz - 1);
|
||||
out[outsz - 1] = 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ac_purge_ctx_t ctx;
|
||||
const char *cutoff = (argc > 1) ? argv[1] : "2026-07-01";
|
||||
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_cut[16];
|
||||
long h_deleted = 0;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
acb_purge_cutoff(cutoff, ctx.cutoff, (int)sizeof(ctx.cutoff));
|
||||
strncpy(h_cut, ctx.cutoff, sizeof(h_cut)-1); h_cut[sizeof(h_cut)-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 ac_unmatch WHERE biz_date < :h_cut;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "ac_unmatchpurge_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
h_deleted = sqlca.sqlerrd[2];
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
ctx.deleted = h_deleted;
|
||||
printf(">>> ac_unmatchpurge_batch COMMIT: cutoff=%s deleted=%ld\n", ctx.cutoff, ctx.deleted);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
17
app/src/ac/dbio/ac_amountband_batch.h
Normal file
17
app/src/ac/dbio/ac_amountband_batch.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* ac_amountband_batch.h - copybook for ac_amountband_batch (XA client).
|
||||
* CASE 금액대 분포 구조체 + 분류 헬퍼. Kept in dbio/ for -I resolution.
|
||||
*/
|
||||
#ifndef AC_AMOUNTBAND_BATCH_H
|
||||
#define AC_AMOUNTBAND_BATCH_H
|
||||
|
||||
typedef struct {
|
||||
char biz_date[16];
|
||||
long band_lo; /* < 5만 */
|
||||
long band_mid; /* 5만~50만 */
|
||||
long band_hi; /* >= 50만 */
|
||||
} ac_band_ctx_t;
|
||||
|
||||
int acb_band_classify(long amount); /* 0=lo, 1=mid, 2=hi */
|
||||
|
||||
#endif /* AC_AMOUNTBAND_BATCH_H */
|
||||
14
app/src/ac/dbio/ac_cancel_casebucket_dbio.h
Normal file
14
app/src/ac/dbio/ac_cancel_casebucket_dbio.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* ac_cancel_casebucket_dbio.h - ac 모듈 DB 접근 계층 copybook (ac_cancel_casebucket_dbio, part of libacdbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
* Shape: CASE 금액 구간 버킷 분류.
|
||||
*/
|
||||
#ifndef AC_CANCEL_CASEBUCKET_DBIO_H
|
||||
#define AC_CANCEL_CASEBUCKET_DBIO_H
|
||||
|
||||
typedef struct { long small; long mid; long large; } ac_cancel_bucket_rec_t;
|
||||
|
||||
int acdb_cancel_buckets(const char *bizdate, ac_cancel_bucket_rec_t *out);
|
||||
|
||||
#endif /* AC_CANCEL_CASEBUCKET_DBIO_H */
|
||||
32
app/src/ac/dbio/ac_cancel_casebucket_dbio.pgc
Normal file
32
app/src/ac/dbio/ac_cancel_casebucket_dbio.pgc
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* ac_cancel_casebucket_dbio.pgc - ac 모듈 DB 접근 함수 세트 (ac_cancel_casebucket_dbio), archived into libacdbio.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 "ac_cancel_casebucket_dbio.h"
|
||||
|
||||
/* 취소 금액을 소액(<1만)/중액(<10만)/고액 3구간으로 CASE 버킷팅하여 out 에 채움. */
|
||||
int acdb_cancel_buckets(const char *bizdate, ac_cancel_bucket_rec_t *out)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_sm = 0, h_md = 0, h_lg = 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(*) FILTER (WHERE amount < 10000),
|
||||
count(*) FILTER (WHERE amount >= 10000 AND amount < 100000),
|
||||
count(*) FILTER (WHERE amount >= 100000)
|
||||
INTO :h_sm, :h_md, :h_lg
|
||||
FROM ac_cancel WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) {
|
||||
userlog("acdb_cancel_buckets FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
|
||||
return -1;
|
||||
}
|
||||
out->small = h_sm;
|
||||
out->mid = h_md;
|
||||
out->large = h_lg;
|
||||
return 0;
|
||||
}
|
||||
18
app/src/ac/dbio/ac_concentration_batch.h
Normal file
18
app/src/ac/dbio/ac_concentration_batch.h
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* ac_concentration_batch.h - copybook for ac_concentration_batch (XA client).
|
||||
* Struct + helper prototype #include'd by the batch; kept in dbio/ so both ecpg
|
||||
* (-I dbio) and gcc (CFLAGS -I dbio) resolve it. The helper is defined in the batch TU.
|
||||
*/
|
||||
#ifndef AC_CONCENTRATION_BATCH_H
|
||||
#define AC_CONCENTRATION_BATCH_H
|
||||
|
||||
typedef struct {
|
||||
char biz_date[16];
|
||||
long top_sum; /* 상위 N 매입 금액 합 */
|
||||
long total; /* 당일 총 매입 금액 */
|
||||
long ratio_bps; /* 집중도 = top_sum/total (bps) */
|
||||
} ac_conc_ctx_t;
|
||||
|
||||
long acb_conc_ratio_bps(long top_sum, long total);
|
||||
|
||||
#endif /* AC_CONCENTRATION_BATCH_H */
|
||||
14
app/src/ac/dbio/ac_edi_intoledger_dbio.h
Normal file
14
app/src/ac/dbio/ac_edi_intoledger_dbio.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* ac_edi_intoledger_dbio.h - ac 모듈 DB 접근 계층 copybook (ac_edi_intoledger_dbio, part of libacdbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
* Shape: INSERT INTO ledger SELECT ... FROM ac_edi.
|
||||
*/
|
||||
#ifndef AC_EDI_INTOLEDGER_DBIO_H
|
||||
#define AC_EDI_INTOLEDGER_DBIO_H
|
||||
|
||||
typedef struct { long inserted; long total_amount; } ac_edi_post_rec_t;
|
||||
|
||||
long acdb_edi_post_to_ledger(const char *bizdate);
|
||||
|
||||
#endif /* AC_EDI_INTOLEDGER_DBIO_H */
|
||||
27
app/src/ac/dbio/ac_edi_intoledger_dbio.pgc
Normal file
27
app/src/ac/dbio/ac_edi_intoledger_dbio.pgc
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* ac_edi_intoledger_dbio.pgc - ac 모듈 DB 접근 함수 세트 (ac_edi_intoledger_dbio), archived into libacdbio.a.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
* Shape: INSERT INTO ledger SELECT (set-based 전기), 삽입 건수 반환.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "ac_edi_intoledger_dbio.h"
|
||||
|
||||
/* 당일 EDI 문서를 RECON 원장 엔트리로 set-based 전기하고 삽입 건수를 반환. */
|
||||
long acdb_edi_post_to_ledger(const char *bizdate)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long inserted = 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 ledger (ledger_id, purchase_id, entry_type, amount, biz_date)
|
||||
SELECT nextval('ledger_seq'), 0, 'RECON', e.amount, e.biz_date
|
||||
FROM ac_edi e WHERE e.biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) {
|
||||
userlog("acdb_edi_post_to_ledger FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
|
||||
return -1;
|
||||
}
|
||||
inserted = sqlca.sqlerrd[2];
|
||||
return inserted;
|
||||
}
|
||||
14
app/src/ac/dbio/ac_feeadj_repeat_dbio.h
Normal file
14
app/src/ac/dbio/ac_feeadj_repeat_dbio.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* ac_feeadj_repeat_dbio.h - ac 모듈 DB 접근 계층 copybook (ac_feeadj_repeat_dbio, part of libacdbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
* Shape: GROUP BY purchase_id HAVING count(*) > 1 (복수 수수료조정).
|
||||
*/
|
||||
#ifndef AC_FEEADJ_REPEAT_DBIO_H
|
||||
#define AC_FEEADJ_REPEAT_DBIO_H
|
||||
|
||||
typedef struct { long purchase_id; long adj_count; long delta_sum; } ac_feeadj_repeat_rec_t;
|
||||
|
||||
long acdb_feeadj_repeat_purchases(const char *bizdate, long *delta_out);
|
||||
|
||||
#endif /* AC_FEEADJ_REPEAT_DBIO_H */
|
||||
34
app/src/ac/dbio/ac_feeadj_repeat_dbio.pgc
Normal file
34
app/src/ac/dbio/ac_feeadj_repeat_dbio.pgc
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* ac_feeadj_repeat_dbio.pgc - ac 모듈 DB 접근 함수 세트 (ac_feeadj_repeat_dbio), archived into libacdbio.a.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
* Shape: GROUP BY purchase_id HAVING count(*) > 1 커서로 반복조정 매입 수 + delta 합.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "ac_feeadj_repeat_dbio.h"
|
||||
|
||||
/* 수수료조정이 2회 이상 발생한 매입 수를 세고, delta 총합을 delta_out 에 반환. */
|
||||
long acdb_feeadj_repeat_purchases(const char *bizdate, long *delta_out)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_pid, h_cnt, h_delta, purchases = 0, delta_total = 0;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
EXEC SQL DECLARE frc CURSOR FOR
|
||||
SELECT purchase_id, count(*), coalesce(sum(delta),0) FROM ac_fee_adj
|
||||
WHERE biz_date = :h_bizdate
|
||||
GROUP BY purchase_id HAVING count(*) > 1;
|
||||
EXEC SQL OPEN frc;
|
||||
if (sqlca.sqlcode < 0) return -1;
|
||||
for (;;) {
|
||||
EXEC SQL FETCH frc INTO :h_pid, :h_cnt, :h_delta;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE frc; return -1; }
|
||||
purchases++;
|
||||
delta_total += h_delta;
|
||||
}
|
||||
EXEC SQL CLOSE frc;
|
||||
*delta_out = delta_total;
|
||||
return purchases;
|
||||
}
|
||||
14
app/src/ac/dbio/ac_fx_weightavg_dbio.h
Normal file
14
app/src/ac/dbio/ac_fx_weightavg_dbio.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* ac_fx_weightavg_dbio.h - ac 모듈 DB 접근 계층 copybook (ac_fx_weightavg_dbio, part of libacdbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
* Shape: KRW 가중 평균 환율(bps).
|
||||
*/
|
||||
#ifndef AC_FX_WEIGHTAVG_DBIO_H
|
||||
#define AC_FX_WEIGHTAVG_DBIO_H
|
||||
|
||||
typedef struct { long weighted_num; long weight; long avg_bps; } ac_fx_weight_rec_t;
|
||||
|
||||
long acdb_fx_weighted_rate(const char *bizdate);
|
||||
|
||||
#endif /* AC_FX_WEIGHTAVG_DBIO_H */
|
||||
25
app/src/ac/dbio/ac_fx_weightavg_dbio.pgc
Normal file
25
app/src/ac/dbio/ac_fx_weightavg_dbio.pgc
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* ac_fx_weightavg_dbio.pgc - ac 모듈 DB 접근 함수 세트 (ac_fx_weightavg_dbio), archived into libacdbio.a.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
* Shape: KRW 금액 가중 평균 환율 = sum(rate_bps*krw_amount)/sum(krw_amount).
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "ac_fx_weightavg_dbio.h"
|
||||
|
||||
/* 원화 환산액을 가중치로 하는 평균 환율(bps). 가중치 0 이면 0 반환. */
|
||||
long acdb_fx_weighted_rate(const char *bizdate)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_num = 0, h_den = 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(rate_bps * krw_amount), 0),
|
||||
coalesce(sum(krw_amount), 0)
|
||||
INTO :h_num, :h_den FROM ac_fx WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) return -1;
|
||||
if (h_den <= 0) return 0;
|
||||
return h_num / h_den;
|
||||
}
|
||||
17
app/src/ac/dbio/ac_fxweight_batch.h
Normal file
17
app/src/ac/dbio/ac_fxweight_batch.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* ac_fxweight_batch.h - copybook for ac_fxweight_batch (XA client).
|
||||
* KRW 가중 평균 환율 누산 구조체 + 헬퍼. Kept in dbio/ for -I resolution.
|
||||
*/
|
||||
#ifndef AC_FXWEIGHT_BATCH_H
|
||||
#define AC_FXWEIGHT_BATCH_H
|
||||
|
||||
typedef struct {
|
||||
char biz_date[16];
|
||||
long num; /* sum(rate_bps*krw) */
|
||||
long den; /* sum(krw) */
|
||||
long avg_bps; /* 가중 평균 */
|
||||
} ac_fxw_ctx_t;
|
||||
|
||||
long acb_fxw_divide(long num, long den);
|
||||
|
||||
#endif /* AC_FXWEIGHT_BATCH_H */
|
||||
14
app/src/ac/dbio/ac_install_corr_dbio.h
Normal file
14
app/src/ac/dbio/ac_install_corr_dbio.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* ac_install_corr_dbio.h - ac 모듈 DB 접근 계층 copybook (ac_install_corr_dbio, part of libacdbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
* Shape: 상관 서브쿼리 - 자기 매입 평균 초과 할부회차.
|
||||
*/
|
||||
#ifndef AC_INSTALL_CORR_DBIO_H
|
||||
#define AC_INSTALL_CORR_DBIO_H
|
||||
|
||||
typedef struct { long install_id; long month_amount; } ac_install_corr_rec_t;
|
||||
|
||||
long acdb_install_above_own_avg(const char *bizdate);
|
||||
|
||||
#endif /* AC_INSTALL_CORR_DBIO_H */
|
||||
24
app/src/ac/dbio/ac_install_corr_dbio.pgc
Normal file
24
app/src/ac/dbio/ac_install_corr_dbio.pgc
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* ac_install_corr_dbio.pgc - ac 모듈 DB 접근 함수 세트 (ac_install_corr_dbio), archived into libacdbio.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 "ac_install_corr_dbio.h"
|
||||
|
||||
/* 같은 purchase_id 의 평균 month_amount 를 초과하는 할부 회차 건수. */
|
||||
long acdb_install_above_own_avg(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 ac_install i
|
||||
WHERE i.biz_date = :h_bizdate
|
||||
AND i.month_amount > (SELECT avg(j.month_amount) FROM ac_install j
|
||||
WHERE j.purchase_id = i.purchase_id);
|
||||
if (sqlca.sqlcode < 0) return -1;
|
||||
return h_v;
|
||||
}
|
||||
14
app/src/ac/dbio/ac_merchant_bigday_dbio.h
Normal file
14
app/src/ac/dbio/ac_merchant_bigday_dbio.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* ac_merchant_bigday_dbio.h - ac 모듈 DB 접근 계층 copybook (ac_merchant_bigday_dbio, part of libacdbio.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(amount) >= 임계.
|
||||
*/
|
||||
#ifndef AC_MERCHANT_BIGDAY_DBIO_H
|
||||
#define AC_MERCHANT_BIGDAY_DBIO_H
|
||||
|
||||
typedef struct { char merchant_id[64]; long gross; } ac_bigday_rec_t;
|
||||
|
||||
long acdb_bigday_merchant_count(const char *bizdate, long threshold);
|
||||
|
||||
#endif /* AC_MERCHANT_BIGDAY_DBIO_H */
|
||||
34
app/src/ac/dbio/ac_merchant_bigday_dbio.pgc
Normal file
34
app/src/ac/dbio/ac_merchant_bigday_dbio.pgc
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* ac_merchant_bigday_dbio.pgc - ac 모듈 DB 접근 함수 세트 (ac_merchant_bigday_dbio), archived into libacdbio.a.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
* Shape: GROUP BY ... HAVING sum(amount) >= 임계, 커서로 가맹점 계수 + 최대 group 합.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "ac_merchant_bigday_dbio.h"
|
||||
|
||||
/* 당일 매입합이 threshold 이상인 가맹점 수를 세고, 최대 group 합은 peak 로 보고. */
|
||||
long acdb_bigday_merchant_count(const char *bizdate, long threshold)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16], h_merch[64];
|
||||
long h_gross, h_thr = threshold, cnt = 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 bdc CURSOR FOR
|
||||
SELECT merchant_id, sum(amount) FROM purchase
|
||||
WHERE biz_date = :h_bizdate
|
||||
GROUP BY merchant_id HAVING sum(amount) >= :h_thr;
|
||||
EXEC SQL OPEN bdc;
|
||||
if (sqlca.sqlcode < 0) return -1;
|
||||
for (;;) {
|
||||
EXEC SQL FETCH bdc INTO :h_merch, :h_gross;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE bdc; return -1; }
|
||||
cnt++;
|
||||
if (h_gross > peak) peak = h_gross;
|
||||
}
|
||||
EXEC SQL CLOSE bdc;
|
||||
if (peak < 0) return -1;
|
||||
return cnt;
|
||||
}
|
||||
15
app/src/ac/dbio/ac_purchase_incancel_dbio.h
Normal file
15
app/src/ac/dbio/ac_purchase_incancel_dbio.h
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* ac_purchase_incancel_dbio.h - ac 모듈 DB 접근 계층 copybook (ac_purchase_incancel_dbio, part of libacdbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
* Shape: WHERE purchase_id IN (SELECT ... FROM ac_cancel).
|
||||
*/
|
||||
#ifndef AC_PURCHASE_INCANCEL_DBIO_H
|
||||
#define AC_PURCHASE_INCANCEL_DBIO_H
|
||||
|
||||
typedef struct { long cancelled_cnt; long cancelled_amount; } ac_incancel_rec_t;
|
||||
|
||||
long acdb_cancelled_purchase_count(const char *bizdate);
|
||||
long acdb_cancelled_purchase_amount(const char *bizdate);
|
||||
|
||||
#endif /* AC_PURCHASE_INCANCEL_DBIO_H */
|
||||
38
app/src/ac/dbio/ac_purchase_incancel_dbio.pgc
Normal file
38
app/src/ac/dbio/ac_purchase_incancel_dbio.pgc
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* ac_purchase_incancel_dbio.pgc - ac 모듈 DB 접근 함수 세트 (ac_purchase_incancel_dbio), archived into libacdbio.a.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
* Shape: IN 서브셀렉트 - 취소 이력이 있는 매입 집계.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "ac_purchase_incancel_dbio.h"
|
||||
|
||||
/* 취소 테이블에 존재하는 purchase_id 를 가진 매입 건수. */
|
||||
long acdb_cancelled_purchase_count(const char *bizdate)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_v = 0;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
EXEC SQL SELECT count(*) INTO :h_v FROM purchase
|
||||
WHERE biz_date = :h_bizdate
|
||||
AND purchase_id IN (SELECT purchase_id FROM ac_cancel);
|
||||
if (sqlca.sqlcode < 0) return -1;
|
||||
return h_v;
|
||||
}
|
||||
|
||||
/* 취소 이력이 있는 매입들의 원매입 금액 합계. */
|
||||
long acdb_cancelled_purchase_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 purchase
|
||||
WHERE biz_date = :h_bizdate
|
||||
AND purchase_id IN (SELECT purchase_id FROM ac_cancel);
|
||||
if (sqlca.sqlcode < 0) return -1;
|
||||
return h_v;
|
||||
}
|
||||
14
app/src/ac/dbio/ac_purchase_rankpid_dbio.h
Normal file
14
app/src/ac/dbio/ac_purchase_rankpid_dbio.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* ac_purchase_rankpid_dbio.h - ac 모듈 DB 접근 계층 copybook (ac_purchase_rankpid_dbio, part of libacdbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
* Shape: window rank() 로 특정 매입의 순위 산정.
|
||||
*/
|
||||
#ifndef AC_PURCHASE_RANKPID_DBIO_H
|
||||
#define AC_PURCHASE_RANKPID_DBIO_H
|
||||
|
||||
typedef struct { long rk; long purchase_id; long amount; } ac_rankpid_rec_t;
|
||||
|
||||
long acdb_purchase_rank_of(const char *bizdate, long pid);
|
||||
|
||||
#endif /* AC_PURCHASE_RANKPID_DBIO_H */
|
||||
31
app/src/ac/dbio/ac_purchase_rankpid_dbio.pgc
Normal file
31
app/src/ac/dbio/ac_purchase_rankpid_dbio.pgc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* ac_purchase_rankpid_dbio.pgc - ac 모듈 DB 접근 함수 세트 (ac_purchase_rankpid_dbio), archived into libacdbio.a.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
* Shape: rank() OVER (ORDER BY amount DESC) 커서 스캔 후 대상 pid 의 순위 반환.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "ac_purchase_rankpid_dbio.h"
|
||||
|
||||
/* 금액 순위표에서 지정 매입(pid)의 rank 를 찾아 반환. 미발견 시 0. */
|
||||
long acdb_purchase_rank_of(const char *bizdate, long pid)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_rk, h_pid, h_amt, target = pid, found = 0;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
EXEC SQL DECLARE rkc CURSOR FOR
|
||||
SELECT rank() OVER (ORDER BY amount DESC) AS rk, purchase_id, amount
|
||||
FROM purchase WHERE biz_date = :h_bizdate;
|
||||
EXEC SQL OPEN rkc;
|
||||
if (sqlca.sqlcode < 0) return -1;
|
||||
for (;;) {
|
||||
EXEC SQL FETCH rkc INTO :h_rk, :h_pid, :h_amt;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE rkc; return -1; }
|
||||
if (h_pid == target) { found = h_rk; break; }
|
||||
}
|
||||
EXEC SQL CLOSE rkc;
|
||||
return found;
|
||||
}
|
||||
14
app/src/ac/dbio/ac_purchase_topn_dbio.h
Normal file
14
app/src/ac/dbio/ac_purchase_topn_dbio.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* ac_purchase_topn_dbio.h - ac 모듈 DB 접근 계층 copybook (ac_purchase_topn_dbio, part of libacdbio.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() 상위 N 매입 누적.
|
||||
*/
|
||||
#ifndef AC_PURCHASE_TOPN_DBIO_H
|
||||
#define AC_PURCHASE_TOPN_DBIO_H
|
||||
|
||||
typedef struct { long rn; long purchase_id; long amount; } ac_topn_rec_t;
|
||||
|
||||
long acdb_topn_amount_sum(const char *bizdate, long topn);
|
||||
|
||||
#endif /* AC_PURCHASE_TOPN_DBIO_H */
|
||||
31
app/src/ac/dbio/ac_purchase_topn_dbio.pgc
Normal file
31
app/src/ac/dbio/ac_purchase_topn_dbio.pgc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* ac_purchase_topn_dbio.pgc - ac 모듈 DB 접근 함수 세트 (ac_purchase_topn_dbio), archived into libacdbio.a.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
* Shape: window row_number() OVER (ORDER BY amount DESC) 상위 N 매입 금액 누적.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "ac_purchase_topn_dbio.h"
|
||||
|
||||
/* 금액 내림차순 상위 topn 매입의 amount 합계를 커서 누적으로 반환. */
|
||||
long acdb_topn_amount_sum(const char *bizdate, long topn)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_rn, h_amt, acc = 0;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
EXEC SQL DECLARE tnc CURSOR FOR
|
||||
SELECT row_number() OVER (ORDER BY amount DESC) AS rn, amount
|
||||
FROM purchase WHERE biz_date = :h_bizdate;
|
||||
EXEC SQL OPEN tnc;
|
||||
if (sqlca.sqlcode < 0) return -1;
|
||||
for (;;) {
|
||||
EXEC SQL FETCH tnc INTO :h_rn, :h_amt;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE tnc; return -1; }
|
||||
if (h_rn <= topn) acc += h_amt;
|
||||
}
|
||||
EXEC SQL CLOSE tnc;
|
||||
return acc;
|
||||
}
|
||||
15
app/src/ac/dbio/ac_settle_join_dbio.h
Normal file
15
app/src/ac/dbio/ac_settle_join_dbio.h
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* ac_settle_join_dbio.h - ac 모듈 DB 접근 계층 copybook (ac_settle_join_dbio, part of libacdbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
* Shape: purchase JOIN settlement 집계.
|
||||
*/
|
||||
#ifndef AC_SETTLE_JOIN_DBIO_H
|
||||
#define AC_SETTLE_JOIN_DBIO_H
|
||||
|
||||
typedef struct { char merchant_id[64]; long settled_net; long matched; } ac_settle_join_rec_t;
|
||||
|
||||
long acdb_settled_net_by_merchant(const char *merch, const char *bizdate);
|
||||
long acdb_settled_match_count(const char *bizdate);
|
||||
|
||||
#endif /* AC_SETTLE_JOIN_DBIO_H */
|
||||
39
app/src/ac/dbio/ac_settle_join_dbio.pgc
Normal file
39
app/src/ac/dbio/ac_settle_join_dbio.pgc
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* ac_settle_join_dbio.pgc - ac 모듈 DB 접근 함수 세트 (ac_settle_join_dbio), archived into libacdbio.a.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
* Shape: purchase p JOIN settlement s ON p.purchase_id=s.purchase_id 집계.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "ac_settle_join_dbio.h"
|
||||
|
||||
/* 특정 가맹점의 정산 완료된 매입 net 합계 (조인 기준 매입측 net). */
|
||||
long acdb_settled_net_by_merchant(const char *merch, const char *bizdate)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_bizdate[16];
|
||||
long h_v = 0;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
EXEC SQL SELECT coalesce(sum(p.net),0) INTO :h_v
|
||||
FROM purchase p JOIN settlement s ON p.purchase_id = s.purchase_id
|
||||
WHERE p.merchant_id = :h_merch AND s.biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) return -1;
|
||||
return h_v;
|
||||
}
|
||||
|
||||
/* 당일 정산행과 매입행이 조인 매칭된 건수. */
|
||||
long acdb_settled_match_count(const char *bizdate)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_v = 0;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
EXEC SQL SELECT count(*) INTO :h_v
|
||||
FROM settlement s JOIN purchase p ON s.purchase_id = p.purchase_id
|
||||
WHERE s.biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) return -1;
|
||||
return h_v;
|
||||
}
|
||||
14
app/src/ac/dbio/ac_settle_notexists_dbio.h
Normal file
14
app/src/ac/dbio/ac_settle_notexists_dbio.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* ac_settle_notexists_dbio.h - ac 모듈 DB 접근 계층 copybook (ac_settle_notexists_dbio, part of libacdbio.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 AC_SETTLE_NOTEXISTS_DBIO_H
|
||||
#define AC_SETTLE_NOTEXISTS_DBIO_H
|
||||
|
||||
typedef struct { long purchase_id; long net; } ac_settle_gap_rec_t;
|
||||
|
||||
long acdb_unsettled_count(const char *bizdate);
|
||||
|
||||
#endif /* AC_SETTLE_NOTEXISTS_DBIO_H */
|
||||
23
app/src/ac/dbio/ac_settle_notexists_dbio.pgc
Normal file
23
app/src/ac/dbio/ac_settle_notexists_dbio.pgc
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* ac_settle_notexists_dbio.pgc - ac 모듈 DB 접근 함수 세트 (ac_settle_notexists_dbio), archived into libacdbio.a.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
* Shape: NOT EXISTS 상관 서브쿼리 - 대사완료(M) 이나 정산행이 없는 매입.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "ac_settle_notexists_dbio.h"
|
||||
|
||||
/* 상태가 대사완료(M) 이지만 settlement 에 대응행이 없는 매입 건수. */
|
||||
long acdb_unsettled_count(const char *bizdate)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_v = 0;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
EXEC SQL SELECT count(*) INTO :h_v FROM purchase p
|
||||
WHERE p.biz_date = :h_bizdate AND p.status = 'M'
|
||||
AND NOT EXISTS (SELECT 1 FROM settlement s WHERE s.purchase_id = p.purchase_id);
|
||||
if (sqlca.sqlcode < 0) return -1;
|
||||
return h_v;
|
||||
}
|
||||
14
app/src/ac/dbio/ac_summary_rebuild_dbio.h
Normal file
14
app/src/ac/dbio/ac_summary_rebuild_dbio.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* ac_summary_rebuild_dbio.h - ac 모듈 DB 접근 계층 copybook (ac_summary_rebuild_dbio, part of libacdbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
* Shape: INSERT INTO ... SELECT ... GROUP BY ... ON CONFLICT DO UPDATE (재집계 upsert).
|
||||
*/
|
||||
#ifndef AC_SUMMARY_REBUILD_DBIO_H
|
||||
#define AC_SUMMARY_REBUILD_DBIO_H
|
||||
|
||||
typedef struct { char biz_date[16]; long merchants; } ac_summary_rebuild_rec_t;
|
||||
|
||||
long acdb_summary_rebuild_from_purchase(const char *bizdate);
|
||||
|
||||
#endif /* AC_SUMMARY_REBUILD_DBIO_H */
|
||||
36
app/src/ac/dbio/ac_summary_rebuild_dbio.pgc
Normal file
36
app/src/ac/dbio/ac_summary_rebuild_dbio.pgc
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* ac_summary_rebuild_dbio.pgc - ac 모듈 DB 접근 함수 세트 (ac_summary_rebuild_dbio), archived into libacdbio.a.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
* Shape: INSERT INTO merchant_summary SELECT ... GROUP BY ... ON CONFLICT DO UPDATE (재집계 upsert).
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "ac_summary_rebuild_dbio.h"
|
||||
|
||||
/* 당일 purchase 를 가맹점별로 재집계하여 merchant_summary 에 upsert. 반영 행수 반환. */
|
||||
long acdb_summary_rebuild_from_purchase(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 merchant_summary
|
||||
(merchant_id, biz_date, txn_count, gross_amount, fee_amount, net_amount)
|
||||
SELECT merchant_id, biz_date, count(*), coalesce(sum(amount),0),
|
||||
coalesce(sum(fee),0), coalesce(sum(net),0)
|
||||
FROM purchase WHERE biz_date = :h_bizdate
|
||||
GROUP BY merchant_id, biz_date
|
||||
ON CONFLICT (merchant_id, biz_date) DO UPDATE
|
||||
SET txn_count = EXCLUDED.txn_count,
|
||||
gross_amount = EXCLUDED.gross_amount,
|
||||
fee_amount = EXCLUDED.fee_amount,
|
||||
net_amount = EXCLUDED.net_amount,
|
||||
updated_at = now();
|
||||
if (sqlca.sqlcode < 0) {
|
||||
userlog("acdb_summary_rebuild_from_purchase FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
|
||||
return -1;
|
||||
}
|
||||
affected = sqlca.sqlerrd[2];
|
||||
return affected;
|
||||
}
|
||||
16
app/src/ac/dbio/ac_summaryrebuild_batch.h
Normal file
16
app/src/ac/dbio/ac_summaryrebuild_batch.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* ac_summaryrebuild_batch.h - copybook for ac_summaryrebuild_batch (XA client).
|
||||
* merchant_summary 재집계 구조체 + 헬퍼. Kept in dbio/ for -I resolution.
|
||||
*/
|
||||
#ifndef AC_SUMMARYREBUILD_BATCH_H
|
||||
#define AC_SUMMARYREBUILD_BATCH_H
|
||||
|
||||
typedef struct {
|
||||
char biz_date[16];
|
||||
long rows_affected;
|
||||
long total_gross;
|
||||
} ac_rebuild_ctx_t;
|
||||
|
||||
long acb_rebuild_ok(long affected);
|
||||
|
||||
#endif /* AC_SUMMARYREBUILD_BATCH_H */
|
||||
15
app/src/ac/dbio/ac_taxinv_spread_dbio.h
Normal file
15
app/src/ac/dbio/ac_taxinv_spread_dbio.h
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* ac_taxinv_spread_dbio.h - ac 모듈 DB 접근 계층 copybook (ac_taxinv_spread_dbio, part of libacdbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
* Shape: max(vat)-min(vat) 스프레드.
|
||||
*/
|
||||
#ifndef AC_TAXINV_SPREAD_DBIO_H
|
||||
#define AC_TAXINV_SPREAD_DBIO_H
|
||||
|
||||
typedef struct { long vat_max; long vat_min; long spread; } ac_taxinv_spread_rec_t;
|
||||
|
||||
long acdb_taxinv_vat_spread(const char *bizdate);
|
||||
long acdb_taxinv_count(const char *bizdate);
|
||||
|
||||
#endif /* AC_TAXINV_SPREAD_DBIO_H */
|
||||
35
app/src/ac/dbio/ac_taxinv_spread_dbio.pgc
Normal file
35
app/src/ac/dbio/ac_taxinv_spread_dbio.pgc
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* ac_taxinv_spread_dbio.pgc - ac 모듈 DB 접근 함수 세트 (ac_taxinv_spread_dbio), archived into libacdbio.a.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
* Shape: 세금계산서 VAT 최대-최소 스프레드 및 건수.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "ac_taxinv_spread_dbio.h"
|
||||
|
||||
/* 당일 세금계산서 VAT 의 max-min 스프레드. 데이터 없으면 0. */
|
||||
long acdb_taxinv_vat_spread(const char *bizdate)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_max = 0, h_min = 0;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
EXEC SQL SELECT coalesce(max(vat),0), coalesce(min(vat),0)
|
||||
INTO :h_max, :h_min FROM ac_tax_invoice WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) return -1;
|
||||
return h_max - h_min;
|
||||
}
|
||||
|
||||
/* 당일 발행된 세금계산서 건수. */
|
||||
long acdb_taxinv_count(const char *bizdate)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_v = 0;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
EXEC SQL SELECT count(*) INTO :h_v FROM ac_tax_invoice WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) return -1;
|
||||
return h_v;
|
||||
}
|
||||
14
app/src/ac/dbio/ac_unmatch_purge_dbio.h
Normal file
14
app/src/ac/dbio/ac_unmatch_purge_dbio.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* ac_unmatch_purge_dbio.h - ac 모듈 DB 접근 계층 copybook (ac_unmatch_purge_dbio, part of libacdbio.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 < 기준 (구간 삭제).
|
||||
*/
|
||||
#ifndef AC_UNMATCH_PURGE_DBIO_H
|
||||
#define AC_UNMATCH_PURGE_DBIO_H
|
||||
|
||||
typedef struct { char cutoff[16]; long deleted; } ac_unmatch_purge_rec_t;
|
||||
|
||||
long acdb_unmatch_purge_before(const char *cutoff);
|
||||
|
||||
#endif /* AC_UNMATCH_PURGE_DBIO_H */
|
||||
25
app/src/ac/dbio/ac_unmatch_purge_dbio.pgc
Normal file
25
app/src/ac/dbio/ac_unmatch_purge_dbio.pgc
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* ac_unmatch_purge_dbio.pgc - ac 모듈 DB 접근 함수 세트 (ac_unmatch_purge_dbio), archived into libacdbio.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 "ac_unmatch_purge_dbio.h"
|
||||
|
||||
/* cutoff(YYYY-MM-DD) 이전의 ac_unmatch 로그를 삭제하고 삭제 건수를 반환. */
|
||||
long acdb_unmatch_purge_before(const char *cutoff)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_cut[16];
|
||||
long 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 ac_unmatch WHERE biz_date < :h_cut;
|
||||
if (sqlca.sqlcode < 0) {
|
||||
userlog("acdb_unmatch_purge_before FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
|
||||
return -1;
|
||||
}
|
||||
deleted = sqlca.sqlerrd[2];
|
||||
return deleted;
|
||||
}
|
||||
15
app/src/ac/dbio/ac_unmatchpurge_batch.h
Normal file
15
app/src/ac/dbio/ac_unmatchpurge_batch.h
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* ac_unmatchpurge_batch.h - copybook for ac_unmatchpurge_batch (XA client).
|
||||
* 미매입 로그 구간 삭제 구조체 + 기준일 계산 헬퍼. Kept in dbio/ for -I resolution.
|
||||
*/
|
||||
#ifndef AC_UNMATCHPURGE_BATCH_H
|
||||
#define AC_UNMATCHPURGE_BATCH_H
|
||||
|
||||
typedef struct {
|
||||
char cutoff[16];
|
||||
long deleted;
|
||||
} ac_purge_ctx_t;
|
||||
|
||||
void acb_purge_cutoff(const char *bizdate, char *out, int outsz);
|
||||
|
||||
#endif /* AC_UNMATCHPURGE_BATCH_H */
|
||||
14
app/src/ac/dbio/ac_wht_distinct_dbio.h
Normal file
14
app/src/ac/dbio/ac_wht_distinct_dbio.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* ac_wht_distinct_dbio.h - ac 모듈 DB 접근 계층 copybook (ac_wht_distinct_dbio, part of libacdbio.a).
|
||||
* ECPG functions; run on the caller's XA branch (no EXEC SQL CONNECT).
|
||||
* Return convention: >=0 ok, -1 = SQL error.
|
||||
* Shape: count(DISTINCT purchase_id) + sum(tax_amount).
|
||||
*/
|
||||
#ifndef AC_WHT_DISTINCT_DBIO_H
|
||||
#define AC_WHT_DISTINCT_DBIO_H
|
||||
|
||||
typedef struct { long distinct_purchases; long total_tax; } ac_wht_distinct_rec_t;
|
||||
|
||||
int acdb_wht_distinct_summary(const char *bizdate, ac_wht_distinct_rec_t *out);
|
||||
|
||||
#endif /* AC_WHT_DISTINCT_DBIO_H */
|
||||
27
app/src/ac/dbio/ac_wht_distinct_dbio.pgc
Normal file
27
app/src/ac/dbio/ac_wht_distinct_dbio.pgc
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* ac_wht_distinct_dbio.pgc - ac 모듈 DB 접근 함수 세트 (ac_wht_distinct_dbio), archived into libacdbio.a.
|
||||
* ECPG (EXEC SQL) functions; run on the caller's XA branch. No EXEC SQL CONNECT.
|
||||
* Shape: count(DISTINCT purchase_id) 와 sum(tax_amount) 를 한 번에 산출하여 구조체로 반환.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <userlog.h>
|
||||
#include "ac_wht_distinct_dbio.h"
|
||||
|
||||
/* 원천징수가 걸린 서로 다른 매입 수와 총 원천세액을 out 에 채운다. */
|
||||
int acdb_wht_distinct_summary(const char *bizdate, ac_wht_distinct_rec_t *out)
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_dp = 0, h_tax = 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 purchase_id), coalesce(sum(tax_amount),0)
|
||||
INTO :h_dp, :h_tax FROM ac_wht WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) {
|
||||
userlog("acdb_wht_distinct_summary FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
|
||||
return -1;
|
||||
}
|
||||
out->distinct_purchases = h_dp;
|
||||
out->total_tax = h_tax;
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue