diff --git a/app/src/cm/batch/cm_archive_batch.pgc b/app/src/cm/batch/cm_archive_batch.pgc index 2c18418..4caf131 100644 --- a/app/src/cm/batch/cm_archive_batch.pgc +++ b/app/src/cm/batch/cm_archive_batch.pgc @@ -1,8 +1,9 @@ /* - * cm_archive_batch.pgc - cm 모듈 상태 일괄 전이 업데이트 배치 (XA). + * cm_archive_batch.pgc - cm 정보(I) 로그 보관(A) 전이 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 상태 일괄 전이 업데이트; then tpcommit drives XA 2PC. + * transaction; 해당 영업일 정보 로그 중 log_id 오름차순 앞 5000건을 보관(A) + * 상태로 전이(UPDATE ... WHERE log_id IN (서브셀렉트 ORDER BY LIMIT)); tpcommit. * Usage: cm_archive_batch [YYYY-MM-DD] */ #include @@ -25,13 +26,15 @@ int main(int argc, char **argv) if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; } if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; } - EXEC SQL UPDATE cm_log SET log_level = 'A', updated_at = now() - WHERE biz_date = :h_bizdate AND log_level = 'I'; + EXEC SQL UPDATE cm_log SET log_level = 'A' + WHERE log_id IN (SELECT log_id FROM cm_log + WHERE biz_date = :h_bizdate AND log_level = 'I' + ORDER BY log_id LIMIT 5000); if (sqlca.sqlcode < 0) { fprintf(stderr, "cm_archive_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } h_upd = sqlca.sqlerrd[2]; if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> cm_archive_batch COMMIT: bizdate=%s updated=%ld\n", bizdate, h_upd); + printf(">>> cm_archive_batch COMMIT: bizdate=%s archived=%ld\n", bizdate, h_upd); tpclose(); tpterm(); return 0; diff --git a/app/src/cm/batch/cm_dbgpurge_batch.pgc b/app/src/cm/batch/cm_dbgpurge_batch.pgc index c1cf15d..7d34c31 100644 --- a/app/src/cm/batch/cm_dbgpurge_batch.pgc +++ b/app/src/cm/batch/cm_dbgpurge_batch.pgc @@ -1,8 +1,9 @@ /* - * cm_dbgpurge_batch.pgc - cm 모듈 상태 조건 삭제 배치 (XA). + * cm_dbgpurge_batch.pgc - cm 디버그/추적 로그 정리 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 상태 조건 삭제; then tpcommit drives XA 2PC. + * transaction; 기준 영업일 이전(<)의 디버그(D)/추적(T) 로그를 한 번의 + * DELETE (OR 조건 그룹) 로 정리; then tpcommit drives XA 2PC. * Usage: cm_dbgpurge_batch [YYYY-MM-DD] */ #include @@ -25,7 +26,8 @@ int main(int argc, char **argv) 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 cm_log WHERE biz_date = :h_bizdate AND log_level = 'D'; + EXEC SQL DELETE FROM cm_log + WHERE biz_date < :h_bizdate AND (log_level = 'D' OR log_level = 'T'); if (sqlca.sqlcode < 0) { fprintf(stderr, "cm_dbgpurge_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } h_del = sqlca.sqlerrd[2]; diff --git a/app/src/cm/batch/cm_distinct_batch.pgc b/app/src/cm/batch/cm_distinct_batch.pgc index 3d0c604..319ac32 100644 --- a/app/src/cm/batch/cm_distinct_batch.pgc +++ b/app/src/cm/batch/cm_distinct_batch.pgc @@ -1,8 +1,9 @@ /* - * cm_distinct_batch.pgc - cm 모듈 고유값(distinct) 집계 배치 (XA). + * cm_distinct_batch.pgc - cm 반복 서비스(로그 2건 이상) 수 집계 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 고유값(distinct) 집계; then tpcommit drives XA 2PC. + * transaction; 해당 영업일에 로그가 2건 이상인 서비스 수를 FROM 서브쿼리 + * (GROUP BY ... HAVING count(*)>1) 를 다시 count 하여 산출; then tpcommit. * Usage: cm_distinct_batch [YYYY-MM-DD] */ #include @@ -25,11 +26,13 @@ int main(int argc, char **argv) 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(DISTINCT svc_name) INTO :h_d FROM cm_log WHERE biz_date = :h_bizdate; + EXEC SQL SELECT count(*) INTO :h_d FROM + (SELECT svc_name FROM cm_log WHERE biz_date = :h_bizdate + GROUP BY svc_name HAVING count(*) > 1) t; if (sqlca.sqlcode < 0) { fprintf(stderr, "cm_distinct_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> cm_distinct_batch COMMIT: bizdate=%s distinct=%ld\n", bizdate, h_d); + printf(">>> cm_distinct_batch COMMIT: bizdate=%s repeated_svc=%ld\n", bizdate, h_d); tpclose(); tpterm(); return 0; diff --git a/app/src/cm/batch/cm_errbps_batch.pgc b/app/src/cm/batch/cm_errbps_batch.pgc index f1b0b02..d577fad 100644 --- a/app/src/cm/batch/cm_errbps_batch.pgc +++ b/app/src/cm/batch/cm_errbps_batch.pgc @@ -1,8 +1,9 @@ /* - * cm_errbps_batch.pgc - cm 모듈 두 SELECT 비율(bps) 산출 배치 (XA). + * cm_errbps_batch.pgc - cm 오류 로그 비율(bps) 산출 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 두 SELECT 비율(bps) 산출; then tpcommit drives XA 2PC. + * transaction; 단일 SELECT 에서 count(*) FILTER (WHERE ...) 로 오류(E) 건과 + * 전체 건을 동시에 집계한 뒤 C 에서 bps 를 계산; then tpcommit drives XA 2PC. * Usage: cm_errbps_batch [YYYY-MM-DD] */ #include @@ -16,7 +17,7 @@ int main(int argc, char **argv) const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; EXEC SQL BEGIN DECLARE SECTION; char h_bizdate[16]; - long h_a = 0, h_b = 0, h_bps = 0; + long h_err = 0, h_tot = 0, h_bps = 0; EXEC SQL END DECLARE SECTION; strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0; @@ -25,15 +26,13 @@ int main(int argc, char **argv) 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(*) INTO :h_a FROM cm_log - WHERE biz_date = :h_bizdate AND log_level = 'E'; - if (sqlca.sqlcode < 0) { tpabort(0); return 1; } - EXEC SQL SELECT count(*) INTO :h_b FROM cm_log WHERE biz_date = :h_bizdate; - if (sqlca.sqlcode < 0) { tpabort(0); return 1; } - h_bps = (h_b > 0) ? h_a * 10000 / h_b : 0; + EXEC SQL SELECT count(*) FILTER (WHERE log_level = 'E'), count(*) + INTO :h_err, :h_tot FROM cm_log WHERE biz_date = :h_bizdate; + if (sqlca.sqlcode < 0) { fprintf(stderr, "cm_errbps_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } + h_bps = (h_tot > 0) ? h_err * 10000 / h_tot : 0; if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> cm_errbps_batch COMMIT: bizdate=%s hit=%ld total=%ld bps=%ld\n", bizdate, h_a, h_b, h_bps); + printf(">>> cm_errbps_batch COMMIT: bizdate=%s err=%ld total=%ld bps=%ld\n", bizdate, h_err, h_tot, h_bps); tpclose(); tpterm(); return 0; diff --git a/app/src/cm/batch/cm_fxjoin_batch.pgc b/app/src/cm/batch/cm_fxjoin_batch.pgc index baaa0d4..0f01967 100644 --- a/app/src/cm/batch/cm_fxjoin_batch.pgc +++ b/app/src/cm/batch/cm_fxjoin_batch.pgc @@ -1,8 +1,9 @@ /* - * cm_fxjoin_batch.pgc - cm 모듈 조인 집계 배치 (XA). + * cm_fxjoin_batch.pgc - cm 환율 x 통화코드 조인 집계 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 조인 집계; then tpcommit drives XA 2PC. + * transaction; cm_fx_rate 를 cm_code(CCY 그룹)와 조인하여 등록 통화의 환율 + * 합계와 고유 통화 수(count DISTINCT)를 한 행으로 집계; then tpcommit. * Usage: cm_fxjoin_batch [YYYY-MM-DD] */ #include @@ -16,7 +17,7 @@ int main(int argc, char **argv) const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; EXEC SQL BEGIN DECLARE SECTION; char h_bizdate[16]; - long h_v = 0; + long h_sum = 0, h_ccy = 0; EXEC SQL END DECLARE SECTION; strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0; @@ -25,13 +26,14 @@ int main(int argc, char **argv) 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(a.rate_bps),0) INTO :h_v - FROM cm_fx_rate a JOIN cm_holiday b ON a.base_date = b.holi_date - WHERE a.base_date = :h_bizdate; + EXEC SQL SELECT coalesce(sum(r.rate_bps),0), count(DISTINCT r.ccy) + INTO :h_sum, :h_ccy + FROM cm_fx_rate r JOIN cm_code c ON r.ccy = c.code + WHERE r.base_date = :h_bizdate AND c.code_grp = 'CCY'; if (sqlca.sqlcode < 0) { fprintf(stderr, "cm_fxjoin_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> cm_fxjoin_batch COMMIT: bizdate=%s joined_sum=%ld\n", bizdate, h_v); + printf(">>> cm_fxjoin_batch COMMIT: bizdate=%s rate_sum=%ld ccy=%ld\n", bizdate, h_sum, h_ccy); tpclose(); tpterm(); return 0; diff --git a/app/src/cm/batch/cm_fxspread_batch.pgc b/app/src/cm/batch/cm_fxspread_batch.pgc index 4399ff9..6c48b79 100644 --- a/app/src/cm/batch/cm_fxspread_batch.pgc +++ b/app/src/cm/batch/cm_fxspread_batch.pgc @@ -1,8 +1,9 @@ /* - * cm_fxspread_batch.pgc - cm 모듈 최대-최소 스프레드 집계 배치 (XA). + * cm_fxspread_batch.pgc - cm 환율 최대/최소/평균 분포 집계 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 최대-최소 스프레드 집계; then tpcommit drives XA 2PC. + * transaction; 기준일 환율의 max/min/avg(3개 집계, avg 는 CAST ... AS BIGINT) + * 를 한 행으로 뽑아 C 에서 스프레드(max-min)를 계산; then tpcommit. * Usage: cm_fxspread_batch [YYYY-MM-DD] */ #include @@ -16,7 +17,7 @@ int main(int argc, char **argv) const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; EXEC SQL BEGIN DECLARE SECTION; char h_bizdate[16]; - long h_max = 0, h_min = 0, h_spread = 0; + long h_max = 0, h_min = 0, h_avg = 0, h_spread = 0; EXEC SQL END DECLARE SECTION; strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0; @@ -25,13 +26,14 @@ int main(int argc, char **argv) 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(rate_bps),0), coalesce(min(rate_bps),0) - INTO :h_max, :h_min FROM cm_fx_rate WHERE base_date = :h_bizdate; + EXEC SQL SELECT coalesce(max(rate_bps),0), coalesce(min(rate_bps),0), + CAST(coalesce(avg(rate_bps),0) AS BIGINT) + INTO :h_max, :h_min, :h_avg FROM cm_fx_rate WHERE base_date = :h_bizdate; if (sqlca.sqlcode < 0) { fprintf(stderr, "cm_fxspread_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } h_spread = h_max - h_min; if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> cm_fxspread_batch COMMIT: bizdate=%s max=%ld min=%ld spread=%ld\n", bizdate, h_max, h_min, h_spread); + printf(">>> cm_fxspread_batch COMMIT: bizdate=%s max=%ld min=%ld avg=%ld spread=%ld\n", bizdate, h_max, h_min, h_avg, h_spread); tpclose(); tpterm(); return 0; diff --git a/app/src/cm/batch/cm_fxsum_batch.pgc b/app/src/cm/batch/cm_fxsum_batch.pgc index 3126b36..06dde68 100644 --- a/app/src/cm/batch/cm_fxsum_batch.pgc +++ b/app/src/cm/batch/cm_fxsum_batch.pgc @@ -1,8 +1,9 @@ /* - * cm_fxsum_batch.pgc - cm 모듈 스칼라 합계 집계 배치 (XA). + * cm_fxsum_batch.pgc - cm 외화(비원화) 환율 합계/건수 집계 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 스칼라 합계 집계; then tpcommit drives XA 2PC. + * transaction; 기준일 환율 중 원화(KRW)를 제외(<>)한 통화의 rate_bps 합계와 + * 건수를 한 행으로 집계; then tpcommit drives XA 2PC. * Usage: cm_fxsum_batch [YYYY-MM-DD] */ #include @@ -16,7 +17,7 @@ int main(int argc, char **argv) const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; EXEC SQL BEGIN DECLARE SECTION; char h_bizdate[16]; - long h_v = 0; + long h_sum = 0, h_cnt = 0; EXEC SQL END DECLARE SECTION; strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0; @@ -25,11 +26,12 @@ int main(int argc, char **argv) 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),0) INTO :h_v FROM cm_fx_rate WHERE base_date = :h_bizdate; + EXEC SQL SELECT coalesce(sum(rate_bps),0), count(*) INTO :h_sum, :h_cnt + FROM cm_fx_rate WHERE base_date = :h_bizdate AND ccy <> 'KRW'; if (sqlca.sqlcode < 0) { fprintf(stderr, "cm_fxsum_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> cm_fxsum_batch COMMIT: bizdate=%s total=%ld\n", bizdate, h_v); + printf(">>> cm_fxsum_batch COMMIT: bizdate=%s fx_sum=%ld ccy_cnt=%ld\n", bizdate, h_sum, h_cnt); tpclose(); tpterm(); return 0; diff --git a/app/src/cm/batch/cm_levelstat_batch.pgc b/app/src/cm/batch/cm_levelstat_batch.pgc index a22fb76..b75cab7 100644 --- a/app/src/cm/batch/cm_levelstat_batch.pgc +++ b/app/src/cm/batch/cm_levelstat_batch.pgc @@ -1,8 +1,9 @@ /* - * cm_levelstat_batch.pgc - cm 모듈 3분류 CASE 집계 배치 (XA). + * cm_levelstat_batch.pgc - cm 로그 레벨 4분류 CASE 집계 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 3분류 CASE 집계; then tpcommit drives XA 2PC. + * transaction; 정보(I)/경고(W)/오류(E)/기타(NOT IN) 4개 CASE 합계를 한 행으로 + * 집계; then tpcommit drives XA 2PC. * Usage: cm_levelstat_batch [YYYY-MM-DD] */ #include @@ -16,7 +17,7 @@ int main(int argc, char **argv) const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; EXEC SQL BEGIN DECLARE SECTION; char h_bizdate[16]; - long h_a = 0, h_b = 0, h_c = 0; + long h_i = 0, h_w = 0, h_e = 0, h_o = 0; EXEC SQL END DECLARE SECTION; strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0; @@ -28,12 +29,13 @@ int main(int argc, char **argv) EXEC SQL SELECT coalesce(sum(CASE WHEN log_level = 'I' THEN 1 ELSE 0 END),0), coalesce(sum(CASE WHEN log_level = 'W' THEN 1 ELSE 0 END),0), - coalesce(sum(CASE WHEN log_level = 'E' THEN 1 ELSE 0 END),0) - INTO :h_a, :h_b, :h_c FROM cm_log WHERE biz_date = :h_bizdate; + coalesce(sum(CASE WHEN log_level = 'E' THEN 1 ELSE 0 END),0), + coalesce(sum(CASE WHEN log_level NOT IN ('I','W','E') THEN 1 ELSE 0 END),0) + INTO :h_i, :h_w, :h_e, :h_o FROM cm_log WHERE biz_date = :h_bizdate; if (sqlca.sqlcode < 0) { fprintf(stderr, "cm_levelstat_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> cm_levelstat_batch COMMIT: bizdate=%s a=%ld b=%ld c=%ld\n", bizdate, h_a, h_b, h_c); + printf(">>> cm_levelstat_batch COMMIT: bizdate=%s i=%ld w=%ld e=%ld other=%ld\n", bizdate, h_i, h_w, h_e, h_o); tpclose(); tpterm(); return 0; diff --git a/app/src/cm/batch/cm_logcnt_batch.pgc b/app/src/cm/batch/cm_logcnt_batch.pgc index 554467a..1e2c71f 100644 --- a/app/src/cm/batch/cm_logcnt_batch.pgc +++ b/app/src/cm/batch/cm_logcnt_batch.pgc @@ -1,8 +1,9 @@ /* - * cm_logcnt_batch.pgc - cm 모듈 건수+금액 단건 집계 배치 (XA). + * cm_logcnt_batch.pgc - cm 로그 건수/합계/최대 log_id 집계 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 건수+금액 단건 집계; then tpcommit drives XA 2PC. + * transaction; 기준일 로그의 건수 + log_id 합계 + 최대 log_id(3개 집계)를 한 + * 행으로 산출; then tpcommit drives XA 2PC. * Usage: cm_logcnt_batch [YYYY-MM-DD] */ #include @@ -16,7 +17,7 @@ int main(int argc, char **argv) const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; EXEC SQL BEGIN DECLARE SECTION; char h_bizdate[16]; - long h_cnt = 0, h_sum = 0; + long h_cnt = 0, h_sum = 0, h_max = 0; EXEC SQL END DECLARE SECTION; strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0; @@ -25,12 +26,12 @@ int main(int argc, char **argv) if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; } if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; } - EXEC SQL SELECT count(*), coalesce(sum(log_id),0) INTO :h_cnt, :h_sum - FROM cm_log WHERE biz_date = :h_bizdate; + EXEC SQL SELECT count(*), coalesce(sum(log_id),0), coalesce(max(log_id),0) + INTO :h_cnt, :h_sum, :h_max FROM cm_log WHERE biz_date = :h_bizdate; if (sqlca.sqlcode < 0) { fprintf(stderr, "cm_logcnt_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> cm_logcnt_batch COMMIT: bizdate=%s rows=%ld sum=%ld\n", bizdate, h_cnt, h_sum); + printf(">>> cm_logcnt_batch COMMIT: bizdate=%s rows=%ld sum=%ld max_id=%ld\n", bizdate, h_cnt, h_sum, h_max); tpclose(); tpterm(); return 0; diff --git a/app/src/cm/batch/cm_logprune_batch.pgc b/app/src/cm/batch/cm_logprune_batch.pgc index 8309bf5..c9d7e9c 100644 --- a/app/src/cm/batch/cm_logprune_batch.pgc +++ b/app/src/cm/batch/cm_logprune_batch.pgc @@ -1,8 +1,9 @@ /* - * cm_logprune_batch.pgc - cm 모듈 서브셀렉트 IN 조건 삭제 배치 (XA). + * cm_logprune_batch.pgc - cm 비휴일 디버그 로그 정리 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 서브셀렉트 IN 조건 삭제; then tpcommit drives XA 2PC. + * transaction; 기준일 이하(<=)의 디버그(D) 로그 중 휴일(cm_holiday)이 아닌 + * (NOT EXISTS 상관 서브쿼리) 날짜의 로그를 삭제; then tpcommit. * Usage: cm_logprune_batch [YYYY-MM-DD] */ #include @@ -26,7 +27,8 @@ int main(int argc, char **argv) if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; } EXEC SQL DELETE FROM cm_log - WHERE log_id IN (SELECT log_id FROM cm_log WHERE biz_date = :h_bizdate AND log_level = 'D'); + WHERE log_level = 'D' AND biz_date <= :h_bizdate + AND NOT EXISTS (SELECT 1 FROM cm_holiday h WHERE h.holi_date = cm_log.biz_date); if (sqlca.sqlcode < 0) { fprintf(stderr, "cm_logprune_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } h_del = sqlca.sqlerrd[2]; diff --git a/app/src/cm/batch/cm_logroll_batch.pgc b/app/src/cm/batch/cm_logroll_batch.pgc index e16e68b..c130573 100644 --- a/app/src/cm/batch/cm_logroll_batch.pgc +++ b/app/src/cm/batch/cm_logroll_batch.pgc @@ -1,8 +1,9 @@ /* - * cm_logroll_batch.pgc - cm 모듈 INSERT ... SELECT 그룹 롤업 적재 배치 (XA). + * cm_logroll_batch.pgc - cm 서비스별 로그 롤업 요약행 적재 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; INSERT ... SELECT 그룹 롤업 적재; then tpcommit drives XA 2PC. + * transaction; 기준일 로그를 서비스별로 GROUP BY ... HAVING count(*)>0 집계하여 + * 서비스당 요약(S) 로그 한 건씩을 INSERT ... SELECT 로 재적재; then tpcommit. * Usage: cm_logroll_batch [YYYY-MM-DD] */ #include @@ -25,9 +26,10 @@ int main(int argc, char **argv) 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 cm_log_rollup (svc_name, biz_date, cnt, amt) - SELECT svc_name, biz_date, count(*), coalesce(sum(log_id),0) - FROM cm_log WHERE biz_date = :h_bizdate GROUP BY svc_name, biz_date; + EXEC SQL INSERT INTO cm_log (log_id, svc_name, log_level, msg, biz_date) + SELECT nextval('cm_log_seq'), svc_name, 'S', 'ROLLUP', :h_bizdate + FROM cm_log WHERE biz_date = :h_bizdate + GROUP BY svc_name HAVING count(*) > 0; if (sqlca.sqlcode < 0) { fprintf(stderr, "cm_logroll_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } h_rows = sqlca.sqlerrd[2]; diff --git a/app/src/cm/batch/cm_marker_batch.pgc b/app/src/cm/batch/cm_marker_batch.pgc index c1ae88e..e48ba2d 100644 --- a/app/src/cm/batch/cm_marker_batch.pgc +++ b/app/src/cm/batch/cm_marker_batch.pgc @@ -1,8 +1,9 @@ /* - * cm_marker_batch.pgc - cm 모듈 시퀀스 채번 + 마커 행 INSERT 배치 (XA). + * cm_marker_batch.pgc - cm 일마감 마커 로그 적재 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 시퀀스 채번 + 마커 행 INSERT; then tpcommit drives XA 2PC. + * transaction; 기준일 로그의 건수와 최대 log_id 를 집계한 뒤, cm_log 에 마감 + * 마커(I) 한 건을 nextval 채번으로 직접 INSERT(VALUES); then tpcommit. * Usage: cm_marker_batch [YYYY-MM-DD] */ #include @@ -16,7 +17,7 @@ int main(int argc, char **argv) const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; EXEC SQL BEGIN DECLARE SECTION; char h_bizdate[16]; - long h_id = 0, h_cnt = 0; + long h_cnt = 0, h_max = 0; EXEC SQL END DECLARE SECTION; strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0; @@ -25,15 +26,15 @@ int main(int argc, char **argv) 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(*) INTO :h_cnt FROM cm_log WHERE biz_date = :h_bizdate; + EXEC SQL SELECT count(*), coalesce(max(log_id),0) INTO :h_cnt, :h_max + FROM cm_log WHERE biz_date = :h_bizdate; if (sqlca.sqlcode < 0) { tpabort(0); return 1; } - EXEC SQL SELECT nextval('cm_log_seq') INTO :h_id; - if (sqlca.sqlcode < 0) { tpabort(0); return 1; } - EXEC SQL INSERT INTO cm_eod_mark (mark_id, biz_date, cnt) VALUES (:h_id, :h_bizdate, :h_cnt); + EXEC SQL INSERT INTO cm_log (log_id, svc_name, log_level, msg, biz_date) + VALUES (nextval('cm_log_seq'), 'EOD', 'I', 'DAY MARK', :h_bizdate); if (sqlca.sqlcode < 0) { fprintf(stderr, "cm_marker_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> cm_marker_batch COMMIT: bizdate=%s mark_id=%ld cnt=%ld\n", bizdate, h_id, h_cnt); + printf(">>> cm_marker_batch COMMIT: bizdate=%s cnt=%ld max_id=%ld\n", bizdate, h_cnt, h_max); tpclose(); tpterm(); return 0; diff --git a/app/src/cm/batch/cm_reconf_batch.pgc b/app/src/cm/batch/cm_reconf_batch.pgc index c2a5f73..bbebfaa 100644 --- a/app/src/cm/batch/cm_reconf_batch.pgc +++ b/app/src/cm/batch/cm_reconf_batch.pgc @@ -1,8 +1,9 @@ /* - * cm_reconf_batch.pgc - cm 모듈 건수 확인 후 조건부 업데이트 배치 (XA). + * cm_reconf_batch.pgc - cm 경고(W) 로그 조건부 재분류 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 건수 확인 후 조건부 업데이트; then tpcommit drives XA 2PC. + * transaction; 경고(W) 로그 건수를 먼저 확인하고, 존재할 때만 msg 내용에 따라 + * CASE 로 보관(A)/유지(W)를 결정하는 UPDATE 를 수행; then tpcommit. * Usage: cm_reconf_batch [YYYY-MM-DD] */ #include @@ -29,14 +30,15 @@ int main(int argc, char **argv) WHERE biz_date = :h_bizdate AND log_level = 'W'; if (sqlca.sqlcode < 0) { tpabort(0); return 1; } if (h_cnt > 0) { - EXEC SQL UPDATE cm_log SET log_level = 'A', updated_at = now() + EXEC SQL UPDATE cm_log + SET log_level = CASE WHEN msg LIKE '%OK%' THEN 'A' ELSE 'W' END WHERE biz_date = :h_bizdate AND log_level = 'W'; if (sqlca.sqlcode < 0) { fprintf(stderr, "cm_reconf_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } h_upd = sqlca.sqlerrd[2]; } if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> cm_reconf_batch COMMIT: bizdate=%s pending=%ld updated=%ld\n", bizdate, h_cnt, h_upd); + printf(">>> cm_reconf_batch COMMIT: bizdate=%s warn=%ld reclassified=%ld\n", bizdate, h_cnt, h_upd); tpclose(); tpterm(); return 0; diff --git a/app/src/cm/batch/cm_svcacc_batch.pgc b/app/src/cm/batch/cm_svcacc_batch.pgc index 54cc520..3b75927 100644 --- a/app/src/cm/batch/cm_svcacc_batch.pgc +++ b/app/src/cm/batch/cm_svcacc_batch.pgc @@ -1,8 +1,9 @@ /* - * cm_svcacc_batch.pgc - cm 모듈 커서 누적 합계 (행별 DML 없음) 배치 (XA). + * cm_svcacc_batch.pgc - cm 서비스별 로그 커서 누적/최대 산출 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 커서 누적 합계 (행별 DML 없음); then tpcommit drives XA 2PC. + * transaction; 서비스별(건수,log_id 합)을 커서로 순회하며 총건수/총합을 누적 + * 하고, C 에서 최대 그룹합(peak)을 if 로 갱신(행별 DML 없음); then tpcommit. * Usage: cm_svcacc_batch [YYYY-MM-DD] */ #include @@ -16,8 +17,9 @@ int main(int argc, char **argv) const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; EXEC SQL BEGIN DECLARE SECTION; char h_bizdate[16], h_key[32]; - long h_amt = 0, total = 0, rows = 0; + long h_cnt = 0, h_amt = 0; EXEC SQL END DECLARE SECTION; + long tot_cnt = 0, tot_amt = 0, peak = 0, groups = 0; strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0; @@ -25,21 +27,22 @@ int main(int argc, char **argv) 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 bc CURSOR FOR - SELECT svc_name, coalesce(sum(log_id),0) FROM cm_log + EXEC SQL DECLARE ac CURSOR FOR + SELECT svc_name, count(*), coalesce(sum(log_id),0) FROM cm_log WHERE biz_date = :h_bizdate GROUP BY svc_name; - EXEC SQL OPEN bc; + EXEC SQL OPEN ac; if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } for (;;) { - EXEC SQL FETCH bc INTO :h_key, :h_amt; + EXEC SQL FETCH ac INTO :h_key, :h_cnt, :h_amt; if (sqlca.sqlcode == 100) break; - if (sqlca.sqlcode < 0) { EXEC SQL CLOSE bc; tpabort(0); return 1; } - total += h_amt; rows++; + if (sqlca.sqlcode < 0) { EXEC SQL CLOSE ac; tpabort(0); return 1; } + tot_cnt += h_cnt; tot_amt += h_amt; groups++; + if (h_amt > peak) peak = h_amt; } - EXEC SQL CLOSE bc; + EXEC SQL CLOSE ac; if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> cm_svcacc_batch COMMIT: bizdate=%s groups=%ld total=%ld\n", bizdate, rows, total); + printf(">>> cm_svcacc_batch COMMIT: bizdate=%s groups=%ld rows=%ld sum=%ld peak=%ld\n", bizdate, groups, tot_cnt, tot_amt, peak); tpclose(); tpterm(); return 0; diff --git a/app/src/cm/batch/cm_svcsnap_batch.pgc b/app/src/cm/batch/cm_svcsnap_batch.pgc index e799de5..1da7a5f 100644 --- a/app/src/cm/batch/cm_svcsnap_batch.pgc +++ b/app/src/cm/batch/cm_svcsnap_batch.pgc @@ -1,8 +1,9 @@ /* - * cm_svcsnap_batch.pgc - cm 모듈 커서 순회 후 대상 테이블 행별 INSERT 배치 (XA). + * cm_svcsnap_batch.pgc - cm 서비스별 스냅샷 마커 조건부 적재 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 커서 순회 후 대상 테이블 행별 INSERT; then tpcommit drives XA 2PC. + * transaction; 서비스별 log_id 합을 커서로 순회하며 합이 0보다 큰 서비스에만 + * (if 가드) cm_log 스냅샷(S) 마커를 행별 INSERT; then tpcommit. * Usage: cm_svcsnap_batch [YYYY-MM-DD] */ #include @@ -16,8 +17,9 @@ int main(int argc, char **argv) const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; EXEC SQL BEGIN DECLARE SECTION; char h_bizdate[16], h_key[32]; - long h_amt = 0, rows = 0; + long h_amt = 0; EXEC SQL END DECLARE SECTION; + long inserted = 0, skipped = 0; strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0; @@ -25,24 +27,28 @@ int main(int argc, char **argv) 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 bc CURSOR FOR + EXEC SQL DECLARE sc CURSOR FOR SELECT svc_name, coalesce(sum(log_id),0) FROM cm_log WHERE biz_date = :h_bizdate GROUP BY svc_name; - EXEC SQL OPEN bc; + EXEC SQL OPEN sc; if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } for (;;) { - EXEC SQL FETCH bc INTO :h_key, :h_amt; + EXEC SQL FETCH sc INTO :h_key, :h_amt; if (sqlca.sqlcode == 100) break; - if (sqlca.sqlcode < 0) { EXEC SQL CLOSE bc; tpabort(0); return 1; } - EXEC SQL INSERT INTO cm_svc_snap (svc_name, biz_date, amt) - VALUES (:h_key, :h_bizdate, :h_amt); - if (sqlca.sqlcode < 0) { EXEC SQL CLOSE bc; tpabort(0); return 1; } - rows++; + if (sqlca.sqlcode < 0) { EXEC SQL CLOSE sc; tpabort(0); return 1; } + if (h_amt > 0) { + EXEC SQL INSERT INTO cm_log (log_id, svc_name, log_level, msg, biz_date) + VALUES (nextval('cm_log_seq'), :h_key, 'S', 'SNAP', :h_bizdate); + if (sqlca.sqlcode < 0) { EXEC SQL CLOSE sc; tpabort(0); return 1; } + inserted++; + } else { + skipped++; + } } - EXEC SQL CLOSE bc; + EXEC SQL CLOSE sc; if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> cm_svcsnap_batch COMMIT: bizdate=%s inserted=%ld\n", bizdate, rows); + printf(">>> cm_svcsnap_batch COMMIT: bizdate=%s inserted=%ld skipped=%ld\n", bizdate, inserted, skipped); tpclose(); tpterm(); return 0; diff --git a/app/src/mg/batch/mg_amount_batch.pgc b/app/src/mg/batch/mg_amount_batch.pgc index 7a6af40..8f914f1 100644 --- a/app/src/mg/batch/mg_amount_batch.pgc +++ b/app/src/mg/batch/mg_amount_batch.pgc @@ -1,8 +1,9 @@ /* - * mg_amount_batch.pgc - mg 모듈 건수+금액 단건 집계 배치 (XA). + * mg_amount_batch.pgc - mg 전문 금액 합계/평균 집계 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 건수+금액 단건 집계; then tpcommit drives XA 2PC. + * transaction; 기준일 전문의 금액 합계와 평균(CAST avg ... AS BIGINT)을 한 + * 행으로 집계; then tpcommit drives XA 2PC. * Usage: mg_amount_batch [YYYY-MM-DD] */ #include @@ -16,7 +17,7 @@ int main(int argc, char **argv) const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; EXEC SQL BEGIN DECLARE SECTION; char h_bizdate[16]; - long h_cnt = 0, h_sum = 0; + long h_sum = 0, h_avg = 0; EXEC SQL END DECLARE SECTION; strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0; @@ -25,12 +26,12 @@ int main(int argc, char **argv) if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; } if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; } - EXEC SQL SELECT count(*), coalesce(sum(amount),0) INTO :h_cnt, :h_sum - FROM mg_msg_log WHERE biz_date = :h_bizdate; + EXEC SQL SELECT coalesce(sum(amount),0), CAST(coalesce(avg(amount),0) AS BIGINT) + INTO :h_sum, :h_avg FROM mg_msg_log WHERE biz_date = :h_bizdate; if (sqlca.sqlcode < 0) { fprintf(stderr, "mg_amount_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> mg_amount_batch COMMIT: bizdate=%s rows=%ld sum=%ld\n", bizdate, h_cnt, h_sum); + printf(">>> mg_amount_batch COMMIT: bizdate=%s sum=%ld avg=%ld\n", bizdate, h_sum, h_avg); tpclose(); tpterm(); return 0; diff --git a/app/src/mg/batch/mg_chanacc_batch.pgc b/app/src/mg/batch/mg_chanacc_batch.pgc index ad355da..052cd91 100644 --- a/app/src/mg/batch/mg_chanacc_batch.pgc +++ b/app/src/mg/batch/mg_chanacc_batch.pgc @@ -1,8 +1,9 @@ /* - * mg_chanacc_batch.pgc - mg 모듈 커서 누적 합계 (행별 DML 없음) 배치 (XA). + * mg_chanacc_batch.pgc - mg 채널별 전문 커서 누적 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 커서 누적 합계 (행별 DML 없음); then tpcommit drives XA 2PC. + * transaction; 채널별(건수, 금액합)을 커서로 순회하며 총건수/총금액을 누적만 + * 한다(행별 DML/조건분기 없음); then tpcommit drives XA 2PC. * Usage: mg_chanacc_batch [YYYY-MM-DD] */ #include @@ -16,8 +17,9 @@ int main(int argc, char **argv) const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; EXEC SQL BEGIN DECLARE SECTION; char h_bizdate[16], h_key[32]; - long h_amt = 0, total = 0, rows = 0; + long h_cnt = 0, h_amt = 0; EXEC SQL END DECLARE SECTION; + long tot_cnt = 0, tot_amt = 0, groups = 0; strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0; @@ -25,21 +27,21 @@ int main(int argc, char **argv) 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 bc CURSOR FOR - SELECT channel, coalesce(sum(amount),0) FROM mg_msg_log + EXEC SQL DECLARE cc CURSOR FOR + SELECT channel, count(*), coalesce(sum(amount),0) FROM mg_msg_log WHERE biz_date = :h_bizdate GROUP BY channel; - EXEC SQL OPEN bc; + EXEC SQL OPEN cc; if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } for (;;) { - EXEC SQL FETCH bc INTO :h_key, :h_amt; + EXEC SQL FETCH cc INTO :h_key, :h_cnt, :h_amt; if (sqlca.sqlcode == 100) break; - if (sqlca.sqlcode < 0) { EXEC SQL CLOSE bc; tpabort(0); return 1; } - total += h_amt; rows++; + if (sqlca.sqlcode < 0) { EXEC SQL CLOSE cc; tpabort(0); return 1; } + tot_cnt += h_cnt; tot_amt += h_amt; groups++; } - EXEC SQL CLOSE bc; + EXEC SQL CLOSE cc; if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> mg_chanacc_batch COMMIT: bizdate=%s groups=%ld total=%ld\n", bizdate, rows, total); + printf(">>> mg_chanacc_batch COMMIT: bizdate=%s channels=%ld rows=%ld amount=%ld\n", bizdate, groups, tot_cnt, tot_amt); tpclose(); tpterm(); return 0; diff --git a/app/src/mg/batch/mg_chansnap_batch.pgc b/app/src/mg/batch/mg_chansnap_batch.pgc index 558f36f..2e648cd 100644 --- a/app/src/mg/batch/mg_chansnap_batch.pgc +++ b/app/src/mg/batch/mg_chansnap_batch.pgc @@ -1,8 +1,9 @@ /* - * mg_chansnap_batch.pgc - mg 모듈 커서 순회 후 대상 테이블 행별 INSERT 배치 (XA). + * mg_chansnap_batch.pgc - mg 채널 last_stan 커서 갱신 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 커서 순회 후 대상 테이블 행별 INSERT; then tpcommit drives XA 2PC. + * transaction; 채널별 최대 STAN 을 커서로 순회하며 mg_channel.last_stan 을 + * 채널마다 행별 UPDATE 로 반영(스냅샷); then tpcommit drives XA 2PC. * Usage: mg_chansnap_batch [YYYY-MM-DD] */ #include @@ -16,8 +17,9 @@ int main(int argc, char **argv) const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; EXEC SQL BEGIN DECLARE SECTION; char h_bizdate[16], h_key[32]; - long h_amt = 0, rows = 0; + long h_stan = 0; EXEC SQL END DECLARE SECTION; + long updated = 0; strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0; @@ -25,24 +27,23 @@ int main(int argc, char **argv) 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 bc CURSOR FOR - SELECT channel, coalesce(sum(amount),0) FROM mg_msg_log + EXEC SQL DECLARE nc CURSOR FOR + SELECT channel, coalesce(max(stan),0) FROM mg_msg_log WHERE biz_date = :h_bizdate GROUP BY channel; - EXEC SQL OPEN bc; + EXEC SQL OPEN nc; if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } for (;;) { - EXEC SQL FETCH bc INTO :h_key, :h_amt; + EXEC SQL FETCH nc INTO :h_key, :h_stan; if (sqlca.sqlcode == 100) break; - if (sqlca.sqlcode < 0) { EXEC SQL CLOSE bc; tpabort(0); return 1; } - EXEC SQL INSERT INTO mg_chan_snap (channel, biz_date, amt) - VALUES (:h_key, :h_bizdate, :h_amt); - if (sqlca.sqlcode < 0) { EXEC SQL CLOSE bc; tpabort(0); return 1; } - rows++; + if (sqlca.sqlcode < 0) { EXEC SQL CLOSE nc; tpabort(0); return 1; } + EXEC SQL UPDATE mg_channel SET last_stan = :h_stan WHERE channel = :h_key; + if (sqlca.sqlcode < 0) { EXEC SQL CLOSE nc; tpabort(0); return 1; } + updated += sqlca.sqlerrd[2]; } - EXEC SQL CLOSE bc; + EXEC SQL CLOSE nc; if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> mg_chansnap_batch COMMIT: bizdate=%s inserted=%ld\n", bizdate, rows); + printf(">>> mg_chansnap_batch COMMIT: bizdate=%s updated=%ld\n", bizdate, updated); tpclose(); tpterm(); return 0; diff --git a/app/src/mg/batch/mg_confirm_batch.pgc b/app/src/mg/batch/mg_confirm_batch.pgc index 9412d5b..a8c1231 100644 --- a/app/src/mg/batch/mg_confirm_batch.pgc +++ b/app/src/mg/batch/mg_confirm_batch.pgc @@ -1,8 +1,9 @@ /* - * mg_confirm_batch.pgc - mg 모듈 건수 확인 후 조건부 업데이트 배치 (XA). + * mg_confirm_batch.pgc - mg 송신완료 큐 확인 전이 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 건수 확인 후 조건부 업데이트; then tpcommit drives XA 2PC. + * transaction; 송신(S) 큐 존재 여부를 EXISTS(CASE) 로 판정하고, 존재할 때만 + * 해당 큐를 확인완료(D) 로 UPDATE; then tpcommit drives XA 2PC. * Usage: mg_confirm_batch [YYYY-MM-DD] */ #include @@ -16,7 +17,7 @@ int main(int argc, char **argv) const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; EXEC SQL BEGIN DECLARE SECTION; char h_bizdate[16]; - long h_cnt = 0, h_upd = 0; + long h_flag = 0, h_upd = 0; EXEC SQL END DECLARE SECTION; strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0; @@ -25,18 +26,19 @@ int main(int argc, char **argv) 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(*) INTO :h_cnt FROM mg_queue - WHERE biz_date = :h_bizdate AND status = 'S'; + EXEC SQL SELECT CASE WHEN EXISTS + (SELECT 1 FROM mg_queue WHERE biz_date = :h_bizdate AND status = 'S') + THEN 1 ELSE 0 END INTO :h_flag; if (sqlca.sqlcode < 0) { tpabort(0); return 1; } - if (h_cnt > 0) { - EXEC SQL UPDATE mg_queue SET status = 'C', updated_at = now() + if (h_flag > 0) { + EXEC SQL UPDATE mg_queue SET status = 'D', updated_at = now() WHERE biz_date = :h_bizdate AND status = 'S'; if (sqlca.sqlcode < 0) { fprintf(stderr, "mg_confirm_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } h_upd = sqlca.sqlerrd[2]; } if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> mg_confirm_batch COMMIT: bizdate=%s pending=%ld updated=%ld\n", bizdate, h_cnt, h_upd); + printf(">>> mg_confirm_batch COMMIT: bizdate=%s has_sent=%ld confirmed=%ld\n", bizdate, h_flag, h_upd); tpclose(); tpterm(); return 0; diff --git a/app/src/mg/batch/mg_dirstat_batch.pgc b/app/src/mg/batch/mg_dirstat_batch.pgc index b1733d9..8aa0402 100644 --- a/app/src/mg/batch/mg_dirstat_batch.pgc +++ b/app/src/mg/batch/mg_dirstat_batch.pgc @@ -1,8 +1,9 @@ /* - * mg_dirstat_batch.pgc - mg 모듈 3분류 CASE 집계 배치 (XA). + * mg_dirstat_batch.pgc - mg 수신/송신 금액 CASE 집계 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 3분류 CASE 집계; then tpcommit drives XA 2PC. + * transaction; 방향(IN/OUT)별 금액 합을 2개 CASE-sum 으로 집계하고, C 에서 + * 순포지션(net=in-out)을 계산; then tpcommit drives XA 2PC. * Usage: mg_dirstat_batch [YYYY-MM-DD] */ #include @@ -16,7 +17,7 @@ int main(int argc, char **argv) const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; EXEC SQL BEGIN DECLARE SECTION; char h_bizdate[16]; - long h_a = 0, h_b = 0, h_c = 0; + long h_in = 0, h_out = 0, h_net = 0; EXEC SQL END DECLARE SECTION; strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0; @@ -26,14 +27,14 @@ int main(int argc, char **argv) if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; } EXEC SQL SELECT - coalesce(sum(CASE WHEN direction = 'IN' THEN 1 ELSE 0 END),0), - coalesce(sum(CASE WHEN direction = 'OUT' THEN 1 ELSE 0 END),0), - coalesce(sum(CASE WHEN direction = 'IN' THEN 1 ELSE 0 END),0) - INTO :h_a, :h_b, :h_c FROM mg_msg_log WHERE biz_date = :h_bizdate; + coalesce(sum(CASE WHEN direction = 'IN' THEN amount ELSE 0 END),0), + coalesce(sum(CASE WHEN direction = 'OUT' THEN amount ELSE 0 END),0) + INTO :h_in, :h_out FROM mg_msg_log WHERE biz_date = :h_bizdate; if (sqlca.sqlcode < 0) { fprintf(stderr, "mg_dirstat_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } + h_net = h_in - h_out; if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> mg_dirstat_batch COMMIT: bizdate=%s a=%ld b=%ld c=%ld\n", bizdate, h_a, h_b, h_c); + printf(">>> mg_dirstat_batch COMMIT: bizdate=%s in=%ld out=%ld net=%ld\n", bizdate, h_in, h_out, h_net); tpclose(); tpterm(); return 0; diff --git a/app/src/mg/batch/mg_distinct_batch.pgc b/app/src/mg/batch/mg_distinct_batch.pgc index 8ed07e6..9a9a8aa 100644 --- a/app/src/mg/batch/mg_distinct_batch.pgc +++ b/app/src/mg/batch/mg_distinct_batch.pgc @@ -1,8 +1,9 @@ /* - * mg_distinct_batch.pgc - mg 모듈 고유값(distinct) 집계 배치 (XA). + * mg_distinct_batch.pgc - mg 고유 채널/전문유형 수 집계 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 고유값(distinct) 집계; then tpcommit drives XA 2PC. + * transaction; 기준일 전문의 고유 채널 수와 고유 전문유형(mti) 수를 2개의 + * count(DISTINCT ...) 로 동시에 집계; then tpcommit drives XA 2PC. * Usage: mg_distinct_batch [YYYY-MM-DD] */ #include @@ -16,7 +17,7 @@ int main(int argc, char **argv) const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; EXEC SQL BEGIN DECLARE SECTION; char h_bizdate[16]; - long h_d = 0; + long h_chan = 0, h_mti = 0; EXEC SQL END DECLARE SECTION; strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0; @@ -25,11 +26,12 @@ int main(int argc, char **argv) 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(DISTINCT channel) INTO :h_d FROM mg_msg_log WHERE biz_date = :h_bizdate; + EXEC SQL SELECT count(DISTINCT channel), count(DISTINCT mti) + INTO :h_chan, :h_mti FROM mg_msg_log WHERE biz_date = :h_bizdate; if (sqlca.sqlcode < 0) { fprintf(stderr, "mg_distinct_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> mg_distinct_batch COMMIT: bizdate=%s distinct=%ld\n", bizdate, h_d); + printf(">>> mg_distinct_batch COMMIT: bizdate=%s channels=%ld mtis=%ld\n", bizdate, h_chan, h_mti); tpclose(); tpterm(); return 0; diff --git a/app/src/mg/batch/mg_errbps_batch.pgc b/app/src/mg/batch/mg_errbps_batch.pgc index a22062b..bb0f511 100644 --- a/app/src/mg/batch/mg_errbps_batch.pgc +++ b/app/src/mg/batch/mg_errbps_batch.pgc @@ -1,8 +1,9 @@ /* - * mg_errbps_batch.pgc - mg 모듈 두 SELECT 비율(bps) 산출 배치 (XA). + * mg_errbps_batch.pgc - mg 실패 응답코드 비율(bps) 산출 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 두 SELECT 비율(bps) 산출; then tpcommit drives XA 2PC. + * transaction; 단일 SELECT 에서 CASE-sum(rc<>'00') 으로 실패 건과 전체 건을 + * 동시에 집계하고 C 에서 bps 를 계산; then tpcommit drives XA 2PC. * Usage: mg_errbps_batch [YYYY-MM-DD] */ #include @@ -16,7 +17,7 @@ int main(int argc, char **argv) const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; EXEC SQL BEGIN DECLARE SECTION; char h_bizdate[16]; - long h_a = 0, h_b = 0, h_bps = 0; + long h_fail = 0, h_tot = 0, h_bps = 0; EXEC SQL END DECLARE SECTION; strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0; @@ -25,15 +26,14 @@ int main(int argc, char **argv) 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(*) INTO :h_a FROM mg_msg_log - WHERE biz_date = :h_bizdate AND status = 'N'; - if (sqlca.sqlcode < 0) { tpabort(0); return 1; } - EXEC SQL SELECT count(*) INTO :h_b FROM mg_msg_log WHERE biz_date = :h_bizdate; - if (sqlca.sqlcode < 0) { tpabort(0); return 1; } - h_bps = (h_b > 0) ? h_a * 10000 / h_b : 0; + EXEC SQL SELECT + coalesce(sum(CASE WHEN rc <> '00' THEN 1 ELSE 0 END),0), count(*) + INTO :h_fail, :h_tot FROM mg_msg_log WHERE biz_date = :h_bizdate; + if (sqlca.sqlcode < 0) { fprintf(stderr, "mg_errbps_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } + h_bps = (h_tot > 0) ? h_fail * 10000 / h_tot : 0; if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> mg_errbps_batch COMMIT: bizdate=%s hit=%ld total=%ld bps=%ld\n", bizdate, h_a, h_b, h_bps); + printf(">>> mg_errbps_batch COMMIT: bizdate=%s fail=%ld total=%ld bps=%ld\n", bizdate, h_fail, h_tot, h_bps); tpclose(); tpterm(); return 0; diff --git a/app/src/mg/batch/mg_join_batch.pgc b/app/src/mg/batch/mg_join_batch.pgc index a1bae46..a0e71e5 100644 --- a/app/src/mg/batch/mg_join_batch.pgc +++ b/app/src/mg/batch/mg_join_batch.pgc @@ -1,8 +1,9 @@ /* - * mg_join_batch.pgc - mg 모듈 조인 집계 배치 (XA). + * mg_join_batch.pgc - mg 큐 x 채널 조인 재시도 합계 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 조인 집계; then tpcommit drives XA 2PC. + * transaction; mg_queue 를 mg_channel 과 조인하여 UP 채널에 걸린 큐의 재시도 + * 횟수 합계를 단일 집계로 산출; then tpcommit drives XA 2PC. * Usage: mg_join_batch [YYYY-MM-DD] */ #include @@ -16,7 +17,7 @@ int main(int argc, char **argv) const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; EXEC SQL BEGIN DECLARE SECTION; char h_bizdate[16]; - long h_v = 0; + long h_retry = 0; EXEC SQL END DECLARE SECTION; strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0; @@ -25,13 +26,13 @@ int main(int argc, char **argv) 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(a.amount),0) INTO :h_v - FROM mg_msg_log a JOIN mg_route b ON a.channel = b.channel - WHERE a.biz_date = :h_bizdate; + EXEC SQL SELECT coalesce(sum(q.retry_cnt),0) INTO :h_retry + FROM mg_queue q JOIN mg_channel c ON q.channel = c.channel + WHERE q.biz_date = :h_bizdate AND c.status = 'UP'; if (sqlca.sqlcode < 0) { fprintf(stderr, "mg_join_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> mg_join_batch COMMIT: bizdate=%s joined_sum=%ld\n", bizdate, h_v); + printf(">>> mg_join_batch COMMIT: bizdate=%s retry_sum=%ld\n", bizdate, h_retry); tpclose(); tpterm(); return 0; diff --git a/app/src/mg/batch/mg_marker_batch.pgc b/app/src/mg/batch/mg_marker_batch.pgc index 2a479db..c60bde4 100644 --- a/app/src/mg/batch/mg_marker_batch.pgc +++ b/app/src/mg/batch/mg_marker_batch.pgc @@ -1,8 +1,9 @@ /* - * mg_marker_batch.pgc - mg 모듈 시퀀스 채번 + 마커 행 INSERT 배치 (XA). + * mg_marker_batch.pgc - mg 일마감 마커 큐 적재 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 시퀀스 채번 + 마커 행 INSERT; then tpcommit drives XA 2PC. + * transaction; 기준일 전문의 금액합/건수를 집계한 뒤, mg_queue 에 마감 마커 + * 한 건을 nextval 채번으로 직접 INSERT(VALUES, 7컬럼); then tpcommit. * Usage: mg_marker_batch [YYYY-MM-DD] */ #include @@ -16,7 +17,7 @@ int main(int argc, char **argv) const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; EXEC SQL BEGIN DECLARE SECTION; char h_bizdate[16]; - long h_id = 0, h_cnt = 0; + long h_sum = 0, h_cnt = 0; EXEC SQL END DECLARE SECTION; strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0; @@ -25,15 +26,15 @@ int main(int argc, char **argv) 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(*) INTO :h_cnt FROM mg_msg_log WHERE biz_date = :h_bizdate; + EXEC SQL SELECT coalesce(sum(amount),0), count(*) INTO :h_sum, :h_cnt + FROM mg_msg_log WHERE biz_date = :h_bizdate; if (sqlca.sqlcode < 0) { tpabort(0); return 1; } - EXEC SQL SELECT nextval('mg_msg_seq') INTO :h_id; - if (sqlca.sqlcode < 0) { tpabort(0); return 1; } - EXEC SQL INSERT INTO mg_eod_mark (mark_id, biz_date, cnt) VALUES (:h_id, :h_bizdate, :h_cnt); + EXEC SQL INSERT INTO mg_queue (queue_id, stan, channel, mti, payload, status, biz_date) + VALUES (nextval('mg_queue_seq'), 0, 'EOD', '0800', 'DAY MARK', 'Q', :h_bizdate); if (sqlca.sqlcode < 0) { fprintf(stderr, "mg_marker_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> mg_marker_batch COMMIT: bizdate=%s mark_id=%ld cnt=%ld\n", bizdate, h_id, h_cnt); + printf(">>> mg_marker_batch COMMIT: bizdate=%s sum=%ld cnt=%ld\n", bizdate, h_sum, h_cnt); tpclose(); tpterm(); return 0; diff --git a/app/src/mg/batch/mg_promote_batch.pgc b/app/src/mg/batch/mg_promote_batch.pgc index 76730ce..645ff28 100644 --- a/app/src/mg/batch/mg_promote_batch.pgc +++ b/app/src/mg/batch/mg_promote_batch.pgc @@ -1,8 +1,9 @@ /* - * mg_promote_batch.pgc - mg 모듈 상태 일괄 전이 업데이트 배치 (XA). + * mg_promote_batch.pgc - mg 실패 큐 재시도 승격 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 상태 일괄 전이 업데이트; then tpcommit drives XA 2PC. + * transaction; 실패(F) 큐를 대기(Q)로 되돌리면서 retry_cnt 를 산술 증가 + * (SET retry_cnt = retry_cnt + 1) 시키는 UPDATE; then tpcommit drives XA 2PC. * Usage: mg_promote_batch [YYYY-MM-DD] */ #include @@ -25,13 +26,13 @@ int main(int argc, char **argv) if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; } if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; } - EXEC SQL UPDATE mg_queue SET status = 'Q', updated_at = now() + EXEC SQL UPDATE mg_queue SET retry_cnt = retry_cnt + 1, status = 'Q' WHERE biz_date = :h_bizdate AND status = 'F'; if (sqlca.sqlcode < 0) { fprintf(stderr, "mg_promote_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } h_upd = sqlca.sqlerrd[2]; if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> mg_promote_batch COMMIT: bizdate=%s updated=%ld\n", bizdate, h_upd); + printf(">>> mg_promote_batch COMMIT: bizdate=%s promoted=%ld\n", bizdate, h_upd); tpclose(); tpterm(); return 0; diff --git a/app/src/mg/batch/mg_prunequeue_batch.pgc b/app/src/mg/batch/mg_prunequeue_batch.pgc index 7fc7b1f..39514d2 100644 --- a/app/src/mg/batch/mg_prunequeue_batch.pgc +++ b/app/src/mg/batch/mg_prunequeue_batch.pgc @@ -1,8 +1,9 @@ /* - * mg_prunequeue_batch.pgc - mg 모듈 서브셀렉트 IN 조건 삭제 배치 (XA). + * mg_prunequeue_batch.pgc - mg 비활성 채널 큐 정리 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 서브셀렉트 IN 조건 삭제; then tpcommit drives XA 2PC. + * transaction; 기준일 큐 중 현재 UP 상태 채널 목록에 없는(NOT IN 서브셀렉트) + * 채널의 큐를 삭제; then tpcommit drives XA 2PC. * Usage: mg_prunequeue_batch [YYYY-MM-DD] */ #include @@ -26,7 +27,8 @@ int main(int argc, char **argv) if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; } EXEC SQL DELETE FROM mg_queue - WHERE stan IN (SELECT stan FROM mg_msg_log WHERE biz_date = :h_bizdate AND status = 'N'); + WHERE biz_date = :h_bizdate + AND channel NOT IN (SELECT channel FROM mg_channel WHERE status = 'UP'); if (sqlca.sqlcode < 0) { fprintf(stderr, "mg_prunequeue_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } h_del = sqlca.sqlerrd[2]; diff --git a/app/src/mg/batch/mg_purge_batch.pgc b/app/src/mg/batch/mg_purge_batch.pgc index c0a13c9..4055ed1 100644 --- a/app/src/mg/batch/mg_purge_batch.pgc +++ b/app/src/mg/batch/mg_purge_batch.pgc @@ -1,8 +1,9 @@ /* - * mg_purge_batch.pgc - mg 모듈 상태 조건 삭제 배치 (XA). + * mg_purge_batch.pgc - mg 종결 상태 큐 일괄 정리 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 상태 조건 삭제; then tpcommit drives XA 2PC. + * transaction; 기준일 큐 중 종결 상태(송신 S / 완료 D / 확인 C)를 IN 값목록 + * 으로 한 번에 삭제; then tpcommit drives XA 2PC. * Usage: mg_purge_batch [YYYY-MM-DD] */ #include @@ -25,7 +26,8 @@ int main(int argc, char **argv) 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 mg_queue WHERE biz_date = :h_bizdate AND status = 'S'; + EXEC SQL DELETE FROM mg_queue + WHERE biz_date = :h_bizdate AND status IN ('S', 'D', 'C'); if (sqlca.sqlcode < 0) { fprintf(stderr, "mg_purge_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } h_del = sqlca.sqlerrd[2]; diff --git a/app/src/mg/batch/mg_rollup_batch.pgc b/app/src/mg/batch/mg_rollup_batch.pgc index 7b591ea..5c5c297 100644 --- a/app/src/mg/batch/mg_rollup_batch.pgc +++ b/app/src/mg/batch/mg_rollup_batch.pgc @@ -1,8 +1,9 @@ /* - * mg_rollup_batch.pgc - mg 모듈 INSERT ... SELECT 그룹 롤업 적재 배치 (XA). + * mg_rollup_batch.pgc - mg 채널별 통계 조인 롤업 적재 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; INSERT ... SELECT 그룹 롤업 적재; then tpcommit drives XA 2PC. + * transaction; mg_msg_log 를 mg_channel 과 조인하여 채널별 금액합을 GROUP BY + * 로 집계한 뒤 mg_stat 에 INSERT ... SELECT 로 적재; then tpcommit. * Usage: mg_rollup_batch [YYYY-MM-DD] */ #include @@ -25,9 +26,11 @@ int main(int argc, char **argv) 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 mg_chan_rollup (channel, biz_date, cnt, amt) - SELECT channel, biz_date, count(*), coalesce(sum(amount),0) - FROM mg_msg_log WHERE biz_date = :h_bizdate GROUP BY channel, biz_date; + EXEC SQL INSERT INTO mg_stat (channel, biz_date, in_cnt, out_cnt, err_cnt, amount_sum) + SELECT m.channel, m.biz_date, 0, 0, 0, coalesce(sum(m.amount),0) + FROM mg_msg_log m JOIN mg_channel c ON m.channel = c.channel + WHERE m.biz_date = :h_bizdate + GROUP BY m.channel, m.biz_date; if (sqlca.sqlcode < 0) { fprintf(stderr, "mg_rollup_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } h_rows = sqlca.sqlerrd[2]; diff --git a/app/src/mg/batch/mg_scalar_batch.pgc b/app/src/mg/batch/mg_scalar_batch.pgc index 4f591a0..1bf9d12 100644 --- a/app/src/mg/batch/mg_scalar_batch.pgc +++ b/app/src/mg/batch/mg_scalar_batch.pgc @@ -1,8 +1,9 @@ /* - * mg_scalar_batch.pgc - mg 모듈 스칼라 합계 집계 배치 (XA). + * mg_scalar_batch.pgc - mg 송신완료 출금 전문 금액 합계 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 스칼라 합계 집계; then tpcommit drives XA 2PC. + * transaction; 기준일 전문 중 방향=OUT 이고 상태=S(송신완료)인 전문의 금액 + * 합계를 단일 스칼라 집계(WHERE 3조건)로 산출; then tpcommit drives XA 2PC. * Usage: mg_scalar_batch [YYYY-MM-DD] */ #include @@ -25,11 +26,12 @@ int main(int argc, char **argv) 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_v FROM mg_msg_log WHERE biz_date = :h_bizdate; + EXEC SQL SELECT coalesce(sum(amount),0) INTO :h_v FROM mg_msg_log + WHERE biz_date = :h_bizdate AND direction = 'OUT' AND status = 'S'; if (sqlca.sqlcode < 0) { fprintf(stderr, "mg_scalar_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; } - printf(">>> mg_scalar_batch COMMIT: bizdate=%s total=%ld\n", bizdate, h_v); + printf(">>> mg_scalar_batch COMMIT: bizdate=%s out_sent_sum=%ld\n", bizdate, h_v); tpclose(); tpterm(); return 0; diff --git a/app/src/mg/batch/mg_spread_batch.pgc b/app/src/mg/batch/mg_spread_batch.pgc index ff027ea..ded032f 100644 --- a/app/src/mg/batch/mg_spread_batch.pgc +++ b/app/src/mg/batch/mg_spread_batch.pgc @@ -1,8 +1,9 @@ /* - * mg_spread_batch.pgc - mg 모듈 최대-최소 스프레드 집계 배치 (XA). + * mg_spread_batch.pgc - mg 양수 금액 전문 최대-최소 스프레드 배치 (XA). * * ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global - * transaction; 최대-최소 스프레드 집계; then tpcommit drives XA 2PC. + * transaction; 기준일 전문 중 금액>0 인 건에 한해 max/min(2개 집계)을 뽑아 + * C 에서 스프레드(max-min)를 계산; then tpcommit drives XA 2PC. * Usage: mg_spread_batch [YYYY-MM-DD] */ #include @@ -26,7 +27,8 @@ int main(int argc, char **argv) if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; } EXEC SQL SELECT coalesce(max(amount),0), coalesce(min(amount),0) - INTO :h_max, :h_min FROM mg_msg_log WHERE biz_date = :h_bizdate; + INTO :h_max, :h_min FROM mg_msg_log + WHERE biz_date = :h_bizdate AND amount > 0; if (sqlca.sqlcode < 0) { fprintf(stderr, "mg_spread_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; } h_spread = h_max - h_min; diff --git a/app/src/mm/dbio/mm_status_dbio.pgc b/app/src/mm/dbio/mm_status_dbio.pgc index abcd801..b54d233 100644 --- a/app/src/mm/dbio/mm_status_dbio.pgc +++ b/app/src/mm/dbio/mm_status_dbio.pgc @@ -12,7 +12,10 @@ int mmdb_merch_status(const char *merch, char *status_out) char h_merch[64], h_status[16]; EXEC SQL END DECLARE SECTION; strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0; - EXEC SQL SELECT status INTO :h_status FROM mm_merchant_ext WHERE merchant_id = :h_merch; + /* 확장 마스터 등급/상태를 함께 보고 유효 상태를 CASE 로 도출한다. */ + EXEC SQL SELECT CASE WHEN status = 'ACTIVE' AND grade IN ('S','A','B','C') + THEN status ELSE 'HOLD' END + INTO :h_status FROM mm_merchant_ext WHERE merchant_id = :h_merch; if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) { userlog("mmdb_merch_status FAIL [%d]", sqlca.sqlcode); return -1; } strncpy(status_out, h_status, 15); status_out[15] = 0; return 0; diff --git a/app/src/vl/dbio/vl_merch_query_dbio.pgc b/app/src/vl/dbio/vl_merch_query_dbio.pgc index 6a9b536..b28f36d 100644 --- a/app/src/vl/dbio/vl_merch_query_dbio.pgc +++ b/app/src/vl/dbio/vl_merch_query_dbio.pgc @@ -12,8 +12,10 @@ int vldb_merch_status(const char *merch, char *status_out) char h_merch[64], h_status[16]; EXEC SQL END DECLARE SECTION; strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0; - EXEC SQL SELECT status INTO :h_status FROM merchant WHERE merchant_id = :h_merch; - if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) { userlog("vldb_merch_status FAIL [%d]", sqlca.sqlcode); return -1; } + /* base merchant 원장에서 상태를 집계 조회(없으면 NONE)하여 항상 한 행을 얻는다. */ + EXEC SQL SELECT coalesce(max(status), 'NONE') INTO :h_status + FROM merchant WHERE merchant_id = :h_merch; + if (sqlca.sqlcode < 0) { userlog("vldb_merch_status FAIL [%d]", sqlca.sqlcode); return -1; } strncpy(status_out, h_status, 15); status_out[15] = 0; return 0; }