규모확장 Wave B: 전 11모듈 svc 75→133·batch 35→46 (BAIS 온라인 1:1)
- svc 825→1,463 (모듈당 133), batch 385→506 (모듈당 46) — 전부 새 고유 실업무 로직 + 카피북 헤더, 디스패처 133 advertise, 한글 기능설명(매니페스트 추출) - BAIS As-Is 대비: 온라인 1,463 vs 1,466(99.8%), 배치 506 vs 503(초과) - 화면 매니페스트 1,463 재생성 - 검증: build DONE modules=11 batches=506, 12서버 runok, xadmin psc 1,466 AVAIL, 매입체인 XA 커밋, 신규서비스 실데이터 스모크, 전 코퍼스 .pgc 클론 0 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ea90bef264
commit
c62d91b7a7
1526 changed files with 59213 additions and 12 deletions
49
app/src/vl/batch/vl_axis_recon_batch.pgc
Normal file
49
app/src/vl/batch/vl_axis_recon_batch.pgc
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* vl_axis_recon_batch.pgc - 정합성 축 매입-정산 대사 배치 (XA).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; the 검증 SELECT/집계 runs on that branch, then tpcommit drives XA 2PC.
|
||||
* Usage: vl_axis_recon_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_dbio.h"
|
||||
#include "vl_axis_recon_batch.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *bizdate = (argc > 1) ? argv[1] : VL_AXIS_DEF_DATE;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_pnet, h_snet;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_axis_rec_t rec;
|
||||
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
|
||||
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL SELECT coalesce(sum(net),0) INTO :h_pnet FROM purchase
|
||||
WHERE biz_date = :h_bizdate AND status = 'S';
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "SEL1 FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
EXEC SQL SELECT coalesce(sum(net),0) INTO :h_snet FROM settlement
|
||||
WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_axis_recon_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
rec.pnet = h_pnet; rec.snet = h_snet;
|
||||
if (h_pnet != h_snet) {
|
||||
if (vldb_insert_suspect(0, VL_AXIS_RULE, "ERROR", "매입-정산 축 총액 불일치", h_bizdate) < 0) {
|
||||
fprintf(stderr, "insert_suspect FAIL\n"); tpabort(0); return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> vl_axis_recon_batch COMMIT: bizdate=%s 매입순액=%ld 정산순액=%ld delta=%ld\n",
|
||||
bizdate, rec.pnet, rec.snet, rec.pnet - rec.snet);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
48
app/src/vl/batch/vl_cancelrate_batch.pgc
Normal file
48
app/src/vl/batch/vl_cancelrate_batch.pgc
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* vl_cancelrate_batch.pgc - 취소율 이상 스캔 배치 (XA).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; the 검증 SELECT/집계 runs on that branch, then tpcommit drives XA 2PC.
|
||||
* Usage: vl_cancelrate_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_dbio.h"
|
||||
#include "vl_cancelrate_batch.h"
|
||||
|
||||
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_pcnt, h_ccnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_cancelrate_rec_t rec;
|
||||
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
|
||||
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_pcnt FROM purchase WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "SEL1 FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
EXEC SQL SELECT count(*) INTO :h_ccnt FROM ac_cancel WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_cancelrate_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
rec.pcnt = h_pcnt; rec.ccnt = h_ccnt;
|
||||
rec.pct = (h_pcnt > 0) ? (h_ccnt * 100 / h_pcnt) : 0;
|
||||
if (rec.pct >= VL_CXLRATE_THR) {
|
||||
if (vldb_insert_suspect(0, VL_CXLRATE_RULE, "WARN", "취소율 과다", h_bizdate) < 0) {
|
||||
tpabort(0); return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> vl_cancelrate_batch COMMIT: bizdate=%s 매입=%ld 취소=%ld 취소율=%ld%%\n",
|
||||
bizdate, rec.pcnt, rec.ccnt, rec.pct);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
45
app/src/vl/batch/vl_datefut_batch.pgc
Normal file
45
app/src/vl/batch/vl_datefut_batch.pgc
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* vl_datefut_batch.pgc - 미래일자 매입 스캔 배치 (XA).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; the 검증 SELECT/집계 runs on that branch, then tpcommit drives XA 2PC.
|
||||
* Usage: vl_datefut_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_dbio.h"
|
||||
#include "vl_datefut_batch.h"
|
||||
|
||||
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, h_first;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_datefut_rec_t rec;
|
||||
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
|
||||
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL SELECT count(*), coalesce(min(purchase_id),0) INTO :h_cnt, :h_first
|
||||
FROM purchase WHERE biz_date > current_date;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_datefut_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
rec.cnt = h_cnt; rec.first_id = h_first;
|
||||
if (h_cnt > 0) {
|
||||
if (vldb_insert_suspect(h_first, VL_DATEFUT_RULE, "ERROR", "미래일자 매입", h_bizdate) < 0) {
|
||||
tpabort(0); return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> vl_datefut_batch COMMIT: bizdate=%s 미래일자매입=%ld\n", bizdate, rec.cnt);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
52
app/src/vl/batch/vl_dupappr_batch.pgc
Normal file
52
app/src/vl/batch/vl_dupappr_batch.pgc
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* vl_dupappr_batch.pgc - 중복 승인 스캔 배치 (XA).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; the 검증 SELECT/집계 runs on that branch, then tpcommit drives XA 2PC.
|
||||
* Usage: vl_dupappr_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_dbio.h"
|
||||
#include "vl_dupappr_batch.h"
|
||||
|
||||
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_pid, h_cnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_dupappr_rec_t rec; rec.groups = 0;
|
||||
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
|
||||
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL DECLARE dac CURSOR FOR
|
||||
SELECT purchase_id, count(*) FROM approval
|
||||
WHERE approved = true GROUP BY purchase_id HAVING count(*) > 1;
|
||||
EXEC SQL OPEN dac;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
for (;;) {
|
||||
EXEC SQL FETCH dac INTO :h_pid, :h_cnt;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE dac; tpabort(0); return 1; }
|
||||
if (vldb_insert_suspect(h_pid, VL_DUPAPPR_RULE, "WARN", "중복 승인 의심", h_bizdate) < 0) {
|
||||
EXEC SQL CLOSE dac; tpabort(0); return 1;
|
||||
}
|
||||
rec.groups++;
|
||||
}
|
||||
EXEC SQL CLOSE dac;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_dupappr_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(">>> vl_dupappr_batch COMMIT: bizdate=%s 중복승인그룹=%ld\n", bizdate, rec.groups);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
45
app/src/vl/batch/vl_negfee_batch.pgc
Normal file
45
app/src/vl/batch/vl_negfee_batch.pgc
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* vl_negfee_batch.pgc - 음수 수수료 매입 스캔 배치 (XA).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; the 검증 SELECT/집계 runs on that branch, then tpcommit drives XA 2PC.
|
||||
* Usage: vl_negfee_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_dbio.h"
|
||||
#include "vl_negfee_batch.h"
|
||||
|
||||
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, h_first;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_negfee_rec_t rec;
|
||||
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
|
||||
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL SELECT count(*), coalesce(min(purchase_id),0) INTO :h_cnt, :h_first
|
||||
FROM purchase WHERE biz_date = :h_bizdate AND fee < 0;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_negfee_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
rec.cnt = h_cnt; rec.first_id = h_first;
|
||||
if (h_cnt > 0) {
|
||||
if (vldb_insert_suspect(h_first, VL_NEGFEE_RULE, "ERROR", "음수 수수료 매입", h_bizdate) < 0) {
|
||||
tpabort(0); return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> vl_negfee_batch COMMIT: bizdate=%s 음수수수료=%ld 최소매입ID=%ld\n", bizdate, rec.cnt, rec.first_id);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
54
app/src/vl/batch/vl_outlier_batch.pgc
Normal file
54
app/src/vl/batch/vl_outlier_batch.pgc
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* vl_outlier_batch.pgc - 금액 이상치 매입 스캔 배치 (XA).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; the 검증 SELECT/집계 runs on that branch, then tpcommit drives XA 2PC.
|
||||
* Usage: vl_outlier_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_dbio.h"
|
||||
#include "vl_outlier_batch.h"
|
||||
|
||||
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_pid, h_amt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_outlier_rec_t rec; rec.outliers = 0;
|
||||
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
|
||||
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL DECLARE dou CURSOR FOR
|
||||
SELECT purchase_id, amount FROM purchase
|
||||
WHERE biz_date = :h_bizdate
|
||||
AND amount > 4 * (SELECT coalesce(avg(amount),0) FROM purchase
|
||||
WHERE biz_date = :h_bizdate);
|
||||
EXEC SQL OPEN dou;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
for (;;) {
|
||||
EXEC SQL FETCH dou INTO :h_pid, :h_amt;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE dou; tpabort(0); return 1; }
|
||||
if (vldb_insert_suspect(h_pid, VL_OUTLIER_RULE, "WARN", "금액 이상치 매입", h_bizdate) < 0) {
|
||||
EXEC SQL CLOSE dou; tpabort(0); return 1;
|
||||
}
|
||||
rec.outliers++;
|
||||
}
|
||||
EXEC SQL CLOSE dou;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_outlier_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(">>> vl_outlier_batch COMMIT: bizdate=%s 이상치=%ld\n", bizdate, rec.outliers);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
54
app/src/vl/batch/vl_overlimit_batch.pgc
Normal file
54
app/src/vl/batch/vl_overlimit_batch.pgc
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* vl_overlimit_batch.pgc - 가맹점 한도위반 스캔 배치 (XA).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; the 검증 SELECT/집계 runs on that branch, then tpcommit drives XA 2PC.
|
||||
* Usage: vl_overlimit_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_dbio.h"
|
||||
#include "vl_overlimit_batch.h"
|
||||
|
||||
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_merch[64];
|
||||
long h_sum;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_overlimit_rec_t rec; rec.merchants = 0;
|
||||
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
|
||||
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL DECLARE dol CURSOR FOR
|
||||
SELECT p.merchant_id, sum(p.amount) FROM purchase p
|
||||
JOIN merchant m ON m.merchant_id = p.merchant_id
|
||||
WHERE p.biz_date = :h_bizdate
|
||||
GROUP BY p.merchant_id HAVING sum(p.amount) > max(m.daily_limit);
|
||||
EXEC SQL OPEN dol;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
for (;;) {
|
||||
EXEC SQL FETCH dol INTO :h_merch, :h_sum;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE dol; tpabort(0); return 1; }
|
||||
if (vldb_insert_suspect(0, VL_OVRLIM_RULE, "WARN", "가맹점 일한도 초과", h_bizdate) < 0) {
|
||||
EXEC SQL CLOSE dol; tpabort(0); return 1;
|
||||
}
|
||||
rec.merchants++;
|
||||
}
|
||||
EXEC SQL CLOSE dol;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_overlimit_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(">>> vl_overlimit_batch COMMIT: bizdate=%s 한도초과가맹점=%ld\n", bizdate, rec.merchants);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
53
app/src/vl/batch/vl_purnoappr_batch.pgc
Normal file
53
app/src/vl/batch/vl_purnoappr_batch.pgc
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* vl_purnoappr_batch.pgc - 무승인 매입 스캔 배치 (XA).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; the 검증 SELECT/집계 runs on that branch, then tpcommit drives XA 2PC.
|
||||
* Usage: vl_purnoappr_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_dbio.h"
|
||||
#include "vl_purnoappr_batch.h"
|
||||
|
||||
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_pid;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_purnoappr_rec_t rec; rec.unapproved = 0;
|
||||
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
|
||||
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL DECLARE dna CURSOR FOR
|
||||
SELECT p.purchase_id FROM purchase p
|
||||
WHERE p.biz_date = :h_bizdate AND p.status <> 'C'
|
||||
AND NOT EXISTS (SELECT 1 FROM approval a WHERE a.purchase_id = p.purchase_id);
|
||||
EXEC SQL OPEN dna;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
for (;;) {
|
||||
EXEC SQL FETCH dna INTO :h_pid;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE dna; tpabort(0); return 1; }
|
||||
if (vldb_insert_suspect(h_pid, VL_NOAPPR_RULE, "WARN", "무승인 매입", h_bizdate) < 0) {
|
||||
EXEC SQL CLOSE dna; tpabort(0); return 1;
|
||||
}
|
||||
rec.unapproved++;
|
||||
}
|
||||
EXEC SQL CLOSE dna;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_purnoappr_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(">>> vl_purnoappr_batch COMMIT: bizdate=%s 무승인매입=%ld\n", bizdate, rec.unapproved);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
45
app/src/vl/batch/vl_riappr_batch.pgc
Normal file
45
app/src/vl/batch/vl_riappr_batch.pgc
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* vl_riappr_batch.pgc - 승인 참조무결성 스캔 배치 (XA).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; the 검증 SELECT/집계 runs on that branch, then tpcommit drives XA 2PC.
|
||||
* Usage: vl_riappr_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_dbio.h"
|
||||
#include "vl_riappr_batch.h"
|
||||
|
||||
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_orphan;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_riappr_rec_t rec;
|
||||
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
|
||||
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_orphan FROM approval a
|
||||
WHERE NOT EXISTS (SELECT 1 FROM purchase p WHERE p.purchase_id = a.purchase_id);
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_riappr_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
rec.orphans = h_orphan;
|
||||
if (h_orphan > 0) {
|
||||
if (vldb_insert_suspect(0, VL_RIAPPR_RULE, "CRIT", "승인 참조무결성 위반", h_bizdate) < 0) {
|
||||
tpabort(0); return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> vl_riappr_batch COMMIT: bizdate=%s 고아승인=%ld\n", bizdate, rec.orphans);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
57
app/src/vl/batch/vl_sumtxn_batch.pgc
Normal file
57
app/src/vl/batch/vl_sumtxn_batch.pgc
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* vl_sumtxn_batch.pgc - 집계-원천 건수 대사 배치 (XA).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; the 검증 SELECT/집계 runs on that branch, then tpcommit drives XA 2PC.
|
||||
* Usage: vl_sumtxn_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_dbio.h"
|
||||
#include "vl_sumtxn_batch.h"
|
||||
|
||||
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_merch[64];
|
||||
long h_scnt, h_pcnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_sumtxn_rec_t rec; rec.mismatches = 0;
|
||||
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
|
||||
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL DECLARE dsm CURSOR FOR
|
||||
SELECT ms.merchant_id, ms.txn_count,
|
||||
(SELECT count(*) FROM purchase p
|
||||
WHERE p.merchant_id = ms.merchant_id AND p.biz_date = ms.biz_date
|
||||
AND p.status <> 'C')
|
||||
FROM merchant_summary ms WHERE ms.biz_date = :h_bizdate;
|
||||
EXEC SQL OPEN dsm;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
for (;;) {
|
||||
EXEC SQL FETCH dsm INTO :h_merch, :h_scnt, :h_pcnt;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE dsm; tpabort(0); return 1; }
|
||||
if (h_scnt != h_pcnt) {
|
||||
if (vldb_insert_suspect(0, VL_SUMCNT_RULE, "WARN", "집계-원천 건수 불일치", h_bizdate) < 0) {
|
||||
EXEC SQL CLOSE dsm; tpabort(0); return 1;
|
||||
}
|
||||
rec.mismatches++;
|
||||
}
|
||||
}
|
||||
EXEC SQL CLOSE dsm;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_sumtxn_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(">>> vl_sumtxn_batch COMMIT: bizdate=%s 건수불일치=%ld\n", bizdate, rec.mismatches);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
41
app/src/vl/batch/vl_suspesc_batch.pgc
Normal file
41
app/src/vl/batch/vl_suspesc_batch.pgc
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* vl_suspesc_batch.pgc - 장기 미결 의심거래 자동 상향 배치 (XA).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; the 검증 SELECT/집계 runs on that branch, then tpcommit drives XA 2PC.
|
||||
* Usage: vl_suspesc_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_dbio.h"
|
||||
#include "vl_suspesc_batch.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
long age = (argc > 2) ? atol(argv[2]) : VL_SUSPESC_AGE;
|
||||
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19"; (void)bizdate;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_age, h_rows;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_suspesc_rec_t rec;
|
||||
h_age = (age > 0) ? age : VL_SUSPESC_AGE;
|
||||
|
||||
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 UPDATE vl_suspect SET severity = 'ERROR'
|
||||
WHERE status = 'OPEN' AND severity = 'WARN'
|
||||
AND biz_date < current_date - CAST(:h_age AS int);
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_suspesc_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
h_rows = (long)sqlca.sqlerrd[2];
|
||||
rec.escalated = h_rows;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> vl_suspesc_batch COMMIT: 경과일>%ld 자동상향=%ld건\n", h_age, rec.escalated);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
12
app/src/vl/dbio/vl_axis_recon_batch.h
Normal file
12
app/src/vl/dbio/vl_axis_recon_batch.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* vl_axis_recon_batch.h - vl vl_axis_recon_batch 배치 전용 카피북 (copybook). 정합성 축 매입-정산 대사 배치
|
||||
* 축 대사 결과 레코드 + 적재 규칙 코드 상수. Included by vl_axis_recon_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_AXIS_RECON_BATCH_H
|
||||
#define VL_AXIS_RECON_BATCH_H
|
||||
#define VL_AXIS_RULE "AXIS_MIS"
|
||||
#define VL_AXIS_DEF_DATE "2026-07-19"
|
||||
|
||||
typedef struct { long pnet; long snet; } vl_axis_rec_t;
|
||||
|
||||
#endif /* VL_AXIS_RECON_BATCH_H */
|
||||
12
app/src/vl/dbio/vl_cancelrate_batch.h
Normal file
12
app/src/vl/dbio/vl_cancelrate_batch.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* vl_cancelrate_batch.h - vl vl_cancelrate_batch 배치 전용 카피북 (copybook). 취소율 이상 스캔 배치
|
||||
* 취소율 산출 레코드 + 임계율/적재 규칙 코드 상수. Included by vl_cancelrate_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_CANCELRATE_BATCH_H
|
||||
#define VL_CANCELRATE_BATCH_H
|
||||
#define VL_CXLRATE_RULE "CXLRATE"
|
||||
#define VL_CXLRATE_THR 10
|
||||
|
||||
typedef struct { long pcnt; long ccnt; long pct; } vl_cancelrate_rec_t;
|
||||
|
||||
#endif /* VL_CANCELRATE_BATCH_H */
|
||||
11
app/src/vl/dbio/vl_datefut_batch.h
Normal file
11
app/src/vl/dbio/vl_datefut_batch.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* vl_datefut_batch.h - vl vl_datefut_batch 배치 전용 카피북 (copybook). 미래일자 매입 스캔 배치
|
||||
* 미래일자 매입 검출 레코드 + 적재 규칙 코드 상수. Included by vl_datefut_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_DATEFUT_BATCH_H
|
||||
#define VL_DATEFUT_BATCH_H
|
||||
#define VL_DATEFUT_RULE "DATEFUT"
|
||||
|
||||
typedef struct { long cnt; long first_id; } vl_datefut_rec_t;
|
||||
|
||||
#endif /* VL_DATEFUT_BATCH_H */
|
||||
11
app/src/vl/dbio/vl_dupappr_batch.h
Normal file
11
app/src/vl/dbio/vl_dupappr_batch.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* vl_dupappr_batch.h - vl vl_dupappr_batch 배치 전용 카피북 (copybook). 중복 승인 스캔 배치
|
||||
* 중복 승인 그룹 카운트 레코드 + 적재 규칙 코드 상수. Included by vl_dupappr_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_DUPAPPR_BATCH_H
|
||||
#define VL_DUPAPPR_BATCH_H
|
||||
#define VL_DUPAPPR_RULE "DUPAPPR"
|
||||
|
||||
typedef struct { long groups; } vl_dupappr_rec_t;
|
||||
|
||||
#endif /* VL_DUPAPPR_BATCH_H */
|
||||
11
app/src/vl/dbio/vl_negfee_batch.h
Normal file
11
app/src/vl/dbio/vl_negfee_batch.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* vl_negfee_batch.h - vl vl_negfee_batch 배치 전용 카피북 (copybook). 음수 수수료 매입 스캔 배치
|
||||
* 음수 수수료 검출 레코드 + 적재 규칙 코드 상수. Included by vl_negfee_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_NEGFEE_BATCH_H
|
||||
#define VL_NEGFEE_BATCH_H
|
||||
#define VL_NEGFEE_RULE "NEGFEE"
|
||||
|
||||
typedef struct { long cnt; long first_id; } vl_negfee_rec_t;
|
||||
|
||||
#endif /* VL_NEGFEE_BATCH_H */
|
||||
11
app/src/vl/dbio/vl_outlier_batch.h
Normal file
11
app/src/vl/dbio/vl_outlier_batch.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* vl_outlier_batch.h - vl vl_outlier_batch 배치 전용 카피북 (copybook). 금액 이상치 매입 스캔 배치
|
||||
* 이상치 매입 카운트 레코드 + 적재 규칙 코드 상수. Included by vl_outlier_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_OUTLIER_BATCH_H
|
||||
#define VL_OUTLIER_BATCH_H
|
||||
#define VL_OUTLIER_RULE "OUTLIER"
|
||||
|
||||
typedef struct { long outliers; } vl_outlier_rec_t;
|
||||
|
||||
#endif /* VL_OUTLIER_BATCH_H */
|
||||
11
app/src/vl/dbio/vl_overlimit_batch.h
Normal file
11
app/src/vl/dbio/vl_overlimit_batch.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* vl_overlimit_batch.h - vl vl_overlimit_batch 배치 전용 카피북 (copybook). 가맹점 한도위반 스캔 배치
|
||||
* 한도 초과 가맹점 카운트 레코드 + 적재 규칙 코드 상수. Included by vl_overlimit_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_OVERLIMIT_BATCH_H
|
||||
#define VL_OVERLIMIT_BATCH_H
|
||||
#define VL_OVRLIM_RULE "OVRLIM"
|
||||
|
||||
typedef struct { long merchants; } vl_overlimit_rec_t;
|
||||
|
||||
#endif /* VL_OVERLIMIT_BATCH_H */
|
||||
11
app/src/vl/dbio/vl_purnoappr_batch.h
Normal file
11
app/src/vl/dbio/vl_purnoappr_batch.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* vl_purnoappr_batch.h - vl vl_purnoappr_batch 배치 전용 카피북 (copybook). 무승인 매입 스캔 배치
|
||||
* 무승인 매입 카운트 레코드 + 적재 규칙 코드 상수. Included by vl_purnoappr_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_PURNOAPPR_BATCH_H
|
||||
#define VL_PURNOAPPR_BATCH_H
|
||||
#define VL_NOAPPR_RULE "NOAPPR"
|
||||
|
||||
typedef struct { long unapproved; } vl_purnoappr_rec_t;
|
||||
|
||||
#endif /* VL_PURNOAPPR_BATCH_H */
|
||||
11
app/src/vl/dbio/vl_riappr_batch.h
Normal file
11
app/src/vl/dbio/vl_riappr_batch.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* vl_riappr_batch.h - vl vl_riappr_batch 배치 전용 카피북 (copybook). 승인 참조무결성 스캔 배치
|
||||
* 고아 승인 카운트 레코드 + 적재 규칙 코드 상수. Included by vl_riappr_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_RIAPPR_BATCH_H
|
||||
#define VL_RIAPPR_BATCH_H
|
||||
#define VL_RIAPPR_RULE "RIAPPR"
|
||||
|
||||
typedef struct { long orphans; } vl_riappr_rec_t;
|
||||
|
||||
#endif /* VL_RIAPPR_BATCH_H */
|
||||
11
app/src/vl/dbio/vl_sumtxn_batch.h
Normal file
11
app/src/vl/dbio/vl_sumtxn_batch.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* vl_sumtxn_batch.h - vl vl_sumtxn_batch 배치 전용 카피북 (copybook). 집계-원천 건수 대사 배치
|
||||
* 건수 대사 불일치 카운트 레코드 + 적재 규칙 코드 상수. Included by vl_sumtxn_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_SUMTXN_BATCH_H
|
||||
#define VL_SUMTXN_BATCH_H
|
||||
#define VL_SUMCNT_RULE "SUMCNT"
|
||||
|
||||
typedef struct { long mismatches; } vl_sumtxn_rec_t;
|
||||
|
||||
#endif /* VL_SUMTXN_BATCH_H */
|
||||
11
app/src/vl/dbio/vl_suspesc_batch.h
Normal file
11
app/src/vl/dbio/vl_suspesc_batch.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* vl_suspesc_batch.h - vl vl_suspesc_batch 배치 전용 카피북 (copybook). 장기 미결 의심거래 자동 상향 배치
|
||||
* 자동 상향 건수 레코드 + 경과일 임계 상수. Included by vl_suspesc_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_SUSPESC_BATCH_H
|
||||
#define VL_SUSPESC_BATCH_H
|
||||
#define VL_SUSPESC_AGE 3
|
||||
|
||||
typedef struct { long escalated; } vl_suspesc_rec_t;
|
||||
|
||||
#endif /* VL_SUSPESC_BATCH_H */
|
||||
12
app/src/vl/svc/VL_APPRLATE.h
Normal file
12
app/src/vl/svc/VL_APPRLATE.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_APPRLATE.h - vl 서비스 VL_APPRLATE 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_PURCHASE_ID,T_ARG1,T_ARG2,T_RC
|
||||
*/
|
||||
#ifndef VL_APPRLATE_H
|
||||
#define VL_APPRLATE_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_APPRLATE(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_APPRLATE_H */
|
||||
27
app/src/vl/svc/VL_APPRLATE.pgc
Normal file
27
app/src/vl/svc/VL_APPRLATE.pgc
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* VL_APPRLATE.pgc - vl 모듈 서비스 VL_APPRLATE (one service = one file).
|
||||
* 기능: 지연 승인 검출 건별 (승인시각-매입생성 경과초>T_ARG1 기본86400, RC 1=지연).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_APPRLATE.h"
|
||||
|
||||
void VL_APPRLATE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0, limit;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_secs;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_pid = getl(b, T_PURCHASE_ID);
|
||||
limit = getl(b, T_ARG1);
|
||||
if (limit <= 0) limit = 86400;
|
||||
EXEC SQL SELECT coalesce(max(CAST(EXTRACT(EPOCH FROM (a.approved_at - p.created_at)) AS bigint)),0)
|
||||
INTO :h_secs
|
||||
FROM approval a JOIN purchase p ON p.purchase_id = a.purchase_id
|
||||
WHERE a.purchase_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_secs > limit) rc = 1; /* 승인 지연 초과 */
|
||||
setl(b, T_ARG2, h_secs);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_APPRNOPUR.h
Normal file
12
app/src/vl/svc/VL_APPRNOPUR.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_APPRNOPUR.h - vl 서비스 VL_APPRNOPUR 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_COUNT,T_ID1,T_RC
|
||||
*/
|
||||
#ifndef VL_APPRNOPUR_H
|
||||
#define VL_APPRNOPUR_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_APPRNOPUR(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_APPRNOPUR_H */
|
||||
25
app/src/vl/svc/VL_APPRNOPUR.pgc
Normal file
25
app/src/vl/svc/VL_APPRNOPUR.pgc
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* VL_APPRNOPUR.pgc - vl 모듈 서비스 VL_APPRNOPUR (one service = one file).
|
||||
* 기능: 미매입 승인 검출 (매입 원거래 없는 고아 승인 전수, RC 1=존재; 최소 승인ID 반환).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_APPRNOPUR.h"
|
||||
|
||||
void VL_APPRNOPUR(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_cnt, h_first;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
EXEC SQL SELECT count(*), coalesce(min(a.approval_id),0) INTO :h_cnt, :h_first
|
||||
FROM approval a
|
||||
WHERE NOT EXISTS (SELECT 1 FROM purchase p
|
||||
WHERE p.purchase_id = a.purchase_id);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 매입 없는 승인 존재 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_ID1, h_first);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_AXLEDGDC.h
Normal file
12
app/src/vl/svc/VL_AXLEDGDC.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_AXLEDGDC.h - vl 서비스 VL_AXLEDGDC 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE,T_AMT1,T_AMT2,T_AMT3,T_RC
|
||||
*/
|
||||
#ifndef VL_AXLEDGDC_H
|
||||
#define VL_AXLEDGDC_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_AXLEDGDC(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_AXLEDGDC_H */
|
||||
32
app/src/vl/svc/VL_AXLEDGDC.pgc
Normal file
32
app/src/vl/svc/VL_AXLEDGDC.pgc
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* VL_AXLEDGDC.pgc - vl 모듈 서비스 VL_AXLEDGDC (one service = one file).
|
||||
* 기능: 정합성 축 검증 원장 대차 (RECON 차변 vs SETTLE 대변, RC 비트 1=대차불일치 2=지급대응 없음).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_AXLEDGDC.h"
|
||||
|
||||
void VL_AXLEDGDC(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_recon, h_settle, h_xfer;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
EXEC SQL SELECT
|
||||
coalesce(sum(CASE WHEN entry_type = 'RECON' THEN amount ELSE 0 END),0),
|
||||
coalesce(sum(CASE WHEN entry_type = 'SETTLE' THEN amount ELSE 0 END),0),
|
||||
coalesce(sum(CASE WHEN entry_type = 'XFER' THEN amount ELSE 0 END),0)
|
||||
INTO :h_recon, :h_settle, :h_xfer
|
||||
FROM ledger WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_recon != h_settle) rc |= 1; /* 차변-대변 불일치 */
|
||||
if (h_xfer > 0 && h_settle == 0) rc |= 2; /* 지급 있으나 정산분개 없음 */
|
||||
setl(b, T_AMT1, h_recon);
|
||||
setl(b, T_AMT2, h_settle);
|
||||
setl(b, T_AMT3, h_xfer);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_AXPURAPPR.h
Normal file
12
app/src/vl/svc/VL_AXPURAPPR.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_AXPURAPPR.h - vl 서비스 VL_AXPURAPPR 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE,T_AMT1,T_AMT2,T_DELTA,T_RC
|
||||
*/
|
||||
#ifndef VL_AXPURAPPR_H
|
||||
#define VL_AXPURAPPR_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_AXPURAPPR(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_AXPURAPPR_H */
|
||||
32
app/src/vl/svc/VL_AXPURAPPR.pgc
Normal file
32
app/src/vl/svc/VL_AXPURAPPR.pgc
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* VL_AXPURAPPR.pgc - vl 모듈 서비스 VL_AXPURAPPR (one service = one file).
|
||||
* 기능: 정합성 축 검증 매입-승인 (일자별 총매입금액 vs 승인가결 매입금액 합, RC 1=불일치).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_AXPURAPPR.h"
|
||||
|
||||
void VL_AXPURAPPR(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_pall, h_papp;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
EXEC SQL SELECT coalesce(sum(amount),0) INTO :h_pall FROM purchase
|
||||
WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL SELECT coalesce(sum(p.amount),0) INTO :h_papp FROM purchase p
|
||||
WHERE p.biz_date = :h_bizdate
|
||||
AND EXISTS (SELECT 1 FROM approval a
|
||||
WHERE a.purchase_id = p.purchase_id AND a.approved);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_pall != h_papp) rc = 1; /* 매입-승인 축 불일치 */
|
||||
setl(b, T_AMT1, h_pall);
|
||||
setl(b, T_AMT2, h_papp);
|
||||
setl(b, T_DELTA, h_pall - h_papp);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_AXPURSETT.h
Normal file
12
app/src/vl/svc/VL_AXPURSETT.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_AXPURSETT.h - vl 서비스 VL_AXPURSETT 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE,T_AMT1,T_AMT2,T_COUNT,T_DELTA,T_RC
|
||||
*/
|
||||
#ifndef VL_AXPURSETT_H
|
||||
#define VL_AXPURSETT_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_AXPURSETT(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_AXPURSETT_H */
|
||||
31
app/src/vl/svc/VL_AXPURSETT.pgc
Normal file
31
app/src/vl/svc/VL_AXPURSETT.pgc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* VL_AXPURSETT.pgc - vl 모듈 서비스 VL_AXPURSETT (one service = one file).
|
||||
* 기능: 정합성 축 검증 매입-정산 (정산대상 매입 순액 vs settlement 순액 합, RC 1=불일치).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_AXPURSETT.h"
|
||||
|
||||
void VL_AXPURSETT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_pnet, h_snet, h_scnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
EXEC SQL SELECT coalesce(sum(net),0) INTO :h_pnet FROM purchase
|
||||
WHERE biz_date = :h_bizdate AND status IN ('S','M');
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL SELECT count(*), coalesce(sum(net),0) INTO :h_scnt, :h_snet
|
||||
FROM settlement WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_pnet != h_snet) rc = 1; /* 매입-정산 축 불일치 */
|
||||
setl(b, T_AMT1, h_pnet);
|
||||
setl(b, T_AMT2, h_snet);
|
||||
setl(b, T_COUNT, h_scnt);
|
||||
setl(b, T_DELTA, h_pnet - h_snet);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_AXSETTPAY.h
Normal file
12
app/src/vl/svc/VL_AXSETTPAY.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_AXSETTPAY.h - vl 서비스 VL_AXSETTPAY 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE,T_AMT1,T_AMT2,T_DELTA,T_RC
|
||||
*/
|
||||
#ifndef VL_AXSETTPAY_H
|
||||
#define VL_AXSETTPAY_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_AXSETTPAY(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_AXSETTPAY_H */
|
||||
30
app/src/vl/svc/VL_AXSETTPAY.pgc
Normal file
30
app/src/vl/svc/VL_AXSETTPAY.pgc
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* VL_AXSETTPAY.pgc - vl 모듈 서비스 VL_AXSETTPAY (one service = one file).
|
||||
* 기능: 정합성 축 검증 정산-지급 (settlement 순액 합 vs 원장 지급 XFER 합, RC 1=불일치).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_AXSETTPAY.h"
|
||||
|
||||
void VL_AXSETTPAY(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_snet, h_xamt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
EXEC SQL SELECT coalesce(sum(net),0) INTO :h_snet FROM settlement
|
||||
WHERE biz_date = :h_bizdate AND status = 'SETTLED';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL SELECT coalesce(sum(amount),0) INTO :h_xamt FROM ledger
|
||||
WHERE biz_date = :h_bizdate AND entry_type = 'XFER';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_snet != h_xamt) rc = 1; /* 정산-지급 축 불일치 */
|
||||
setl(b, T_AMT1, h_snet);
|
||||
setl(b, T_AMT2, h_xamt);
|
||||
setl(b, T_DELTA, h_snet - h_xamt);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_CANCELRATE.h
Normal file
12
app/src/vl/svc/VL_CANCELRATE.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_CANCELRATE.h - vl 서비스 VL_CANCELRATE 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE,T_ARG1,T_ARG2,T_ARG3,T_COUNT,T_RC
|
||||
*/
|
||||
#ifndef VL_CANCELRATE_H
|
||||
#define VL_CANCELRATE_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_CANCELRATE(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_CANCELRATE_H */
|
||||
31
app/src/vl/svc/VL_CANCELRATE.pgc
Normal file
31
app/src/vl/svc/VL_CANCELRATE.pgc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* VL_CANCELRATE.pgc - vl 모듈 서비스 VL_CANCELRATE (one service = one file).
|
||||
* 기능: 취소율 검증 (취소 건수/매입 건수 비율>=T_ARG1% 기본10, RC 1=취소율 과다).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_CANCELRATE.h"
|
||||
|
||||
void VL_CANCELRATE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0, pct, thr;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_pcnt, h_ccnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
thr = getl(b, T_ARG1);
|
||||
if (thr <= 0) thr = 10;
|
||||
EXEC SQL SELECT count(*) INTO :h_pcnt FROM purchase WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL SELECT count(*) INTO :h_ccnt FROM ac_cancel WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
pct = (h_pcnt > 0) ? (h_ccnt * 100 / h_pcnt) : 0;
|
||||
if (pct >= thr) rc = 1; /* 취소율 과다 */
|
||||
setl(b, T_COUNT, h_pcnt);
|
||||
setl(b, T_ARG2, h_ccnt);
|
||||
setl(b, T_ARG3, pct);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_CATSKEW.h
Normal file
12
app/src/vl/svc/VL_CATSKEW.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_CATSKEW.h - vl 서비스 VL_CATSKEW 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE,T_ARG1,T_ARG2,T_ARG3,T_COUNT,T_RC
|
||||
*/
|
||||
#ifndef VL_CATSKEW_H
|
||||
#define VL_CATSKEW_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_CATSKEW(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_CATSKEW_H */
|
||||
33
app/src/vl/svc/VL_CATSKEW.pgc
Normal file
33
app/src/vl/svc/VL_CATSKEW.pgc
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* VL_CATSKEW.pgc - vl 모듈 서비스 VL_CATSKEW (one service = one file).
|
||||
* 기능: 업종 편중 탐지 (최다 업종 비중>=T_ARG1% 기본80, RC 1=편중).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_CATSKEW.h"
|
||||
|
||||
void VL_CATSKEW(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0, pct, thr;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_tot, h_top;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
thr = getl(b, T_ARG1);
|
||||
if (thr <= 0) thr = 80;
|
||||
EXEC SQL SELECT count(*) INTO :h_tot FROM purchase WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL SELECT coalesce(max(c),0) INTO :h_top FROM (
|
||||
SELECT count(*) AS c FROM purchase
|
||||
WHERE biz_date = :h_bizdate GROUP BY category) t;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
pct = (h_tot > 0) ? (h_top * 100 / h_tot) : 0;
|
||||
if (pct >= thr) rc = 1; /* 단일 업종 편중 */
|
||||
setl(b, T_COUNT, h_tot);
|
||||
setl(b, T_ARG2, h_top);
|
||||
setl(b, T_ARG3, pct);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_CHANSPLIT.h
Normal file
12
app/src/vl/svc/VL_CHANSPLIT.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_CHANSPLIT.h - vl 서비스 VL_CHANSPLIT 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE,T_ARG1,T_ARG2,T_ARG3,T_COUNT,T_RC
|
||||
*/
|
||||
#ifndef VL_CHANSPLIT_H
|
||||
#define VL_CHANSPLIT_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_CHANSPLIT(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_CHANSPLIT_H */
|
||||
32
app/src/vl/svc/VL_CHANSPLIT.pgc
Normal file
32
app/src/vl/svc/VL_CHANSPLIT.pgc
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* VL_CHANSPLIT.pgc - vl 모듈 서비스 VL_CHANSPLIT (one service = one file).
|
||||
* 기능: 채널 분포 검증 (FOREIGN 채널 비중>=T_ARG1% 기본30, RC 1=편중).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_CHANSPLIT.h"
|
||||
|
||||
void VL_CHANSPLIT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0, pct, thr;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_tot, h_frn;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
thr = getl(b, T_ARG1);
|
||||
if (thr <= 0) thr = 30;
|
||||
EXEC SQL SELECT count(*),
|
||||
coalesce(sum(CASE WHEN channel = 'FOREIGN' THEN 1 ELSE 0 END),0)
|
||||
INTO :h_tot, :h_frn
|
||||
FROM purchase WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
pct = (h_tot > 0) ? (h_frn * 100 / h_tot) : 0;
|
||||
if (pct >= thr) rc = 1; /* 해외 채널 편중 */
|
||||
setl(b, T_COUNT, h_tot);
|
||||
setl(b, T_ARG2, h_frn);
|
||||
setl(b, T_ARG3, pct);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_DATEFUT.h
Normal file
12
app/src/vl/svc/VL_DATEFUT.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_DATEFUT.h - vl 서비스 VL_DATEFUT 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_COUNT,T_ID1,T_RC
|
||||
*/
|
||||
#ifndef VL_DATEFUT_H
|
||||
#define VL_DATEFUT_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_DATEFUT(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_DATEFUT_H */
|
||||
23
app/src/vl/svc/VL_DATEFUT.pgc
Normal file
23
app/src/vl/svc/VL_DATEFUT.pgc
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* VL_DATEFUT.pgc - vl 모듈 서비스 VL_DATEFUT (one service = one file).
|
||||
* 기능: 미래일자 매입 검출 (영업일이 오늘 이후인 매입 수, RC 1=존재).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_DATEFUT.h"
|
||||
|
||||
void VL_DATEFUT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_cnt, h_first;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
EXEC SQL SELECT count(*), coalesce(min(purchase_id),0) INTO :h_cnt, :h_first
|
||||
FROM purchase WHERE biz_date > current_date;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 미래일자 매입 존재 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_ID1, h_first);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_DATEGAP.h
Normal file
12
app/src/vl/svc/VL_DATEGAP.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_DATEGAP.h - vl 서비스 VL_DATEGAP 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_COUNT,T_SETTLE_ID,T_RC
|
||||
*/
|
||||
#ifndef VL_DATEGAP_H
|
||||
#define VL_DATEGAP_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_DATEGAP(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_DATEGAP_H */
|
||||
24
app/src/vl/svc/VL_DATEGAP.pgc
Normal file
24
app/src/vl/svc/VL_DATEGAP.pgc
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* VL_DATEGAP.pgc - vl 모듈 서비스 VL_DATEGAP (one service = one file).
|
||||
* 기능: 매입-정산 일자 역전 검출 (정산일<매입일 건수, RC 1=존재; 최소 정산ID 반환).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_DATEGAP.h"
|
||||
|
||||
void VL_DATEGAP(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_cnt, h_first;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
EXEC SQL SELECT count(*), coalesce(min(s.settlement_id),0) INTO :h_cnt, :h_first
|
||||
FROM settlement s JOIN purchase p ON p.purchase_id = s.purchase_id
|
||||
WHERE s.biz_date < p.biz_date;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 정산일이 매입일보다 앞섬 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_SETTLE_ID, h_first);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_DUPAPPR.h
Normal file
12
app/src/vl/svc/VL_DUPAPPR.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_DUPAPPR.h - vl 서비스 VL_DUPAPPR 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_PURCHASE_ID,T_BIZDATE,T_COUNT,T_RC
|
||||
*/
|
||||
#ifndef VL_DUPAPPR_H
|
||||
#define VL_DUPAPPR_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_DUPAPPR(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_DUPAPPR_H */
|
||||
30
app/src/vl/svc/VL_DUPAPPR.pgc
Normal file
30
app/src/vl/svc/VL_DUPAPPR.pgc
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* VL_DUPAPPR.pgc - vl 모듈 서비스 VL_DUPAPPR (one service = one file).
|
||||
* 기능: 중복 승인 검출 건별 (동일 매입 승인가결 2건 이상, RC 1=중복; 검증로그 기록).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_DUPAPPR.h"
|
||||
|
||||
void VL_DUPAPPR(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
char bizdate[16];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_cnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_pid = getl(b, T_PURCHASE_ID);
|
||||
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
|
||||
if (bizdate[0] == 0) strcpy(bizdate, "2026-07-19");
|
||||
EXEC SQL SELECT count(*) INTO :h_cnt FROM approval
|
||||
WHERE purchase_id = :h_pid AND approved = true;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 1) {
|
||||
rc = 1; /* 중복 승인 */
|
||||
if (vldb_insert_check_log("VL_DUPAPPR", h_pid, rc, "중복 승인 검출", bizdate) < 0)
|
||||
FAIL(b);
|
||||
}
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_DUPLEDGR.h
Normal file
12
app/src/vl/svc/VL_DUPLEDGR.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_DUPLEDGR.h - vl 서비스 VL_DUPLEDGR 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_PURCHASE_ID,T_COUNT,T_RC
|
||||
*/
|
||||
#ifndef VL_DUPLEDGR_H
|
||||
#define VL_DUPLEDGR_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_DUPLEDGR(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_DUPLEDGR_H */
|
||||
24
app/src/vl/svc/VL_DUPLEDGR.pgc
Normal file
24
app/src/vl/svc/VL_DUPLEDGR.pgc
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* VL_DUPLEDGR.pgc - vl 모듈 서비스 VL_DUPLEDGR (one service = one file).
|
||||
* 기능: 중복 원장 엔트리 검출 (동일 매입+엔트리유형 최대 그룹 건수>1, RC 1=중복).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_DUPLEDGR.h"
|
||||
|
||||
void VL_DUPLEDGR(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_maxdup;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_pid = getl(b, T_PURCHASE_ID);
|
||||
EXEC SQL SELECT coalesce(max(c),0) INTO :h_maxdup FROM (
|
||||
SELECT count(*) AS c FROM ledger
|
||||
WHERE purchase_id = :h_pid GROUP BY entry_type) t;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_maxdup > 1) rc = 1; /* 동일 유형 원장 중복 */
|
||||
setl(b, T_COUNT, h_maxdup);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_DUPPURCH.h
Normal file
12
app/src/vl/svc/VL_DUPPURCH.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_DUPPURCH.h - vl 서비스 VL_DUPPURCH 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_PURCHASE_ID,T_COUNT,T_RC
|
||||
*/
|
||||
#ifndef VL_DUPPURCH_H
|
||||
#define VL_DUPPURCH_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_DUPPURCH(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_DUPPURCH_H */
|
||||
28
app/src/vl/svc/VL_DUPPURCH.pgc
Normal file
28
app/src/vl/svc/VL_DUPPURCH.pgc
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* VL_DUPPURCH.pgc - vl 모듈 서비스 VL_DUPPURCH (one service = one file).
|
||||
* 기능: 중복 매입 검출 건별 (동일 가맹점+금액+영업일의 타 매입 존재, RC 1=중복).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_DUPPURCH.h"
|
||||
|
||||
void VL_DUPPURCH(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_dups;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_pid = getl(b, T_PURCHASE_ID);
|
||||
EXEC SQL SELECT count(*) INTO :h_dups FROM purchase p
|
||||
WHERE p.purchase_id <> :h_pid
|
||||
AND EXISTS (SELECT 1 FROM purchase q
|
||||
WHERE q.purchase_id = :h_pid
|
||||
AND q.merchant_id = p.merchant_id
|
||||
AND q.amount = p.amount
|
||||
AND q.biz_date = p.biz_date);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_dups > 0) rc = 1; /* 동일 조건 중복 매입 */
|
||||
setl(b, T_COUNT, h_dups);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_DUPSETTMR.h
Normal file
12
app/src/vl/svc/VL_DUPSETTMR.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_DUPSETTMR.h - vl 서비스 VL_DUPSETTMR 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT,T_BIZDATE,T_COUNT,T_RC
|
||||
*/
|
||||
#ifndef VL_DUPSETTMR_H
|
||||
#define VL_DUPSETTMR_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_DUPSETTMR(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_DUPSETTMR_H */
|
||||
27
app/src/vl/svc/VL_DUPSETTMR.pgc
Normal file
27
app/src/vl/svc/VL_DUPSETTMR.pgc
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* VL_DUPSETTMR.pgc - vl 모듈 서비스 VL_DUPSETTMR (one service = one file).
|
||||
* 기능: 가맹점 중복 정산 검출 (동일 가맹점+영업일 settlement 2건 이상, RC 1=중복).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_DUPSETTMR.h"
|
||||
|
||||
void VL_DUPSETTMR(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_bizdate[16];
|
||||
long h_cnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_MERCHANT, h_merch, sizeof(h_merch));
|
||||
if (h_merch[0] == 0) { userlog("VL_DUPSETTMR: T_MERCHANT 누락"); FAIL(b); }
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
EXEC SQL SELECT count(*) INTO :h_cnt FROM settlement
|
||||
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 1) rc = 1; /* 가맹점 일별 중복 정산 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_FEEHIGH.h
Normal file
12
app/src/vl/svc/VL_FEEHIGH.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_FEEHIGH.h - vl 서비스 VL_FEEHIGH 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_PURCHASE_ID,T_FEE,T_ARG1,T_ARG2,T_RC
|
||||
*/
|
||||
#ifndef VL_FEEHIGH_H
|
||||
#define VL_FEEHIGH_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_FEEHIGH(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_FEEHIGH_H */
|
||||
27
app/src/vl/svc/VL_FEEHIGH.pgc
Normal file
27
app/src/vl/svc/VL_FEEHIGH.pgc
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* VL_FEEHIGH.pgc - vl 모듈 서비스 VL_FEEHIGH (one service = one file).
|
||||
* 기능: 수수료 과다 검출 건별 (fee 실효요율 bps>T_ARG1 기본500, RC 1=과다 8=매입없음).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_FEEHIGH.h"
|
||||
|
||||
void VL_FEEHIGH(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0, bps;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_amt, h_fee;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_pid = getl(b, T_PURCHASE_ID);
|
||||
bps = getl(b, T_ARG1);
|
||||
if (bps <= 0) bps = 500;
|
||||
EXEC SQL SELECT amount, fee INTO :h_amt, :h_fee FROM purchase
|
||||
WHERE purchase_id = :h_pid;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 8); OK(b); } /* 8=매입 없음 */
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_amt > 0 && h_fee * 10000 > h_amt * bps) rc = 1; /* 실효요율 초과 */
|
||||
setl(b, T_FEE, h_fee);
|
||||
setl(b, T_ARG2, bps);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_ISSUERMIX.h
Normal file
12
app/src/vl/svc/VL_ISSUERMIX.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_ISSUERMIX.h - vl 서비스 VL_ISSUERMIX 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE,T_ARG1,T_ARG2,T_ARG3,T_STR1,T_RC
|
||||
*/
|
||||
#ifndef VL_ISSUERMIX_H
|
||||
#define VL_ISSUERMIX_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_ISSUERMIX(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_ISSUERMIX_H */
|
||||
34
app/src/vl/svc/VL_ISSUERMIX.pgc
Normal file
34
app/src/vl/svc/VL_ISSUERMIX.pgc
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* VL_ISSUERMIX.pgc - vl 모듈 서비스 VL_ISSUERMIX (one service = one file).
|
||||
* 기능: 발급사 분포 이상 (최다 발급사 비중>=T_ARG1% 기본80, RC 1=편중 8=무거래).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_ISSUERMIX.h"
|
||||
|
||||
void VL_ISSUERMIX(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0, pct, thr;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16], h_iss[64];
|
||||
long h_tot, h_top;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
thr = getl(b, T_ARG1);
|
||||
if (thr <= 0) thr = 80;
|
||||
EXEC SQL SELECT issuer, count(*) INTO :h_iss, :h_top FROM purchase
|
||||
WHERE biz_date = :h_bizdate
|
||||
GROUP BY issuer ORDER BY count(*) DESC LIMIT 1;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 8); OK(b); } /* 8=무거래 */
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL SELECT count(*) INTO :h_tot FROM purchase WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
pct = (h_tot > 0) ? (h_top * 100 / h_tot) : 0;
|
||||
if (pct >= thr) rc = 1; /* 단일 발급사 편중 */
|
||||
setl(b, T_ARG2, h_top);
|
||||
setl(b, T_ARG3, pct);
|
||||
Bchg(b, T_STR1, 0, h_iss, 0L);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_LIMITPCT.h
Normal file
12
app/src/vl/svc/VL_LIMITPCT.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_LIMITPCT.h - vl 서비스 VL_LIMITPCT 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT,T_BIZDATE,T_ARG1,T_ARG2,T_AMT1,T_RC
|
||||
*/
|
||||
#ifndef VL_LIMITPCT_H
|
||||
#define VL_LIMITPCT_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_LIMITPCT(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_LIMITPCT_H */
|
||||
34
app/src/vl/svc/VL_LIMITPCT.pgc
Normal file
34
app/src/vl/svc/VL_LIMITPCT.pgc
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* VL_LIMITPCT.pgc - vl 모듈 서비스 VL_LIMITPCT (one service = one file).
|
||||
* 기능: 한도 사용률 검증 (가맹점 일 매입합/한도 %가 T_ARG1 기본90 이상, RC 1=근접 8=가맹점없음).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_LIMITPCT.h"
|
||||
|
||||
void VL_LIMITPCT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0, pct, thr;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_bizdate[16];
|
||||
long h_sum, h_lim;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_MERCHANT, h_merch, sizeof(h_merch));
|
||||
if (h_merch[0] == 0) { userlog("VL_LIMITPCT: T_MERCHANT 누락"); FAIL(b); }
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
thr = getl(b, T_ARG1);
|
||||
if (thr <= 0) thr = 90;
|
||||
EXEC SQL SELECT daily_limit INTO :h_lim FROM merchant WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 8); OK(b); } /* 8=가맹점 없음 */
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL SELECT coalesce(sum(amount),0) INTO :h_sum FROM purchase
|
||||
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
pct = (h_lim > 0) ? (h_sum * 100 / h_lim) : 0;
|
||||
if (pct >= thr) rc = 1; /* 한도 근접/초과 */
|
||||
setl(b, T_ARG2, pct);
|
||||
setl(b, T_AMT1, h_sum);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_LONGOPEN.h
Normal file
12
app/src/vl/svc/VL_LONGOPEN.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_LONGOPEN.h - vl 서비스 VL_LONGOPEN 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_ARG1,T_ARG2,T_COUNT,T_ID1,T_RC
|
||||
*/
|
||||
#ifndef VL_LONGOPEN_H
|
||||
#define VL_LONGOPEN_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_LONGOPEN(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_LONGOPEN_H */
|
||||
28
app/src/vl/svc/VL_LONGOPEN.pgc
Normal file
28
app/src/vl/svc/VL_LONGOPEN.pgc
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* VL_LONGOPEN.pgc - vl 모듈 서비스 VL_LONGOPEN (one service = one file).
|
||||
* 기능: 장기 미결 의심거래 검출 (OPEN 상태로 N일 초과 경과, 기준 T_ARG1 기본7, RC 1=존재).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_LONGOPEN.h"
|
||||
|
||||
void VL_LONGOPEN(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_days, h_cnt, h_oldest;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_days = getl(b, T_ARG1);
|
||||
if (h_days <= 0) h_days = 7;
|
||||
EXEC SQL SELECT count(*), coalesce(min(suspect_id),0) INTO :h_cnt, :h_oldest
|
||||
FROM vl_suspect
|
||||
WHERE status = 'OPEN'
|
||||
AND biz_date < current_date - CAST(:h_days AS int);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 장기 미결 의심 존재 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_ID1, h_oldest);
|
||||
setl(b, T_ARG2, h_days);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_NEGFEE.h
Normal file
12
app/src/vl/svc/VL_NEGFEE.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_NEGFEE.h - vl 서비스 VL_NEGFEE 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE,T_COUNT,T_ID1,T_RC
|
||||
*/
|
||||
#ifndef VL_NEGFEE_H
|
||||
#define VL_NEGFEE_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_NEGFEE(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_NEGFEE_H */
|
||||
26
app/src/vl/svc/VL_NEGFEE.pgc
Normal file
26
app/src/vl/svc/VL_NEGFEE.pgc
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* VL_NEGFEE.pgc - vl 모듈 서비스 VL_NEGFEE (one service = one file).
|
||||
* 기능: 음수 수수료 매입 검출 (일자별 fee<0 매입 수, RC 1=존재; 최소 매입ID 반환).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_NEGFEE.h"
|
||||
|
||||
void VL_NEGFEE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_cnt, h_first;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
EXEC SQL SELECT count(*), coalesce(min(purchase_id),0) INTO :h_cnt, :h_first
|
||||
FROM purchase WHERE biz_date = :h_bizdate AND fee < 0;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 음수 수수료 매입 존재 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_ID1, h_first);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_NIGHTTXN.h
Normal file
12
app/src/vl/svc/VL_NIGHTTXN.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_NIGHTTXN.h - vl 서비스 VL_NIGHTTXN 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE,T_ARG1,T_ARG2,T_ARG3,T_COUNT,T_RC
|
||||
*/
|
||||
#ifndef VL_NIGHTTXN_H
|
||||
#define VL_NIGHTTXN_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_NIGHTTXN(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_NIGHTTXN_H */
|
||||
32
app/src/vl/svc/VL_NIGHTTXN.pgc
Normal file
32
app/src/vl/svc/VL_NIGHTTXN.pgc
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* VL_NIGHTTXN.pgc - vl 모듈 서비스 VL_NIGHTTXN (one service = one file).
|
||||
* 기능: 심야 거래 패턴 탐지 (0-6시 거래 비중>=T_ARG1% 기본20, RC 1=편중).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_NIGHTTXN.h"
|
||||
|
||||
void VL_NIGHTTXN(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0, pct, thr;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_tot, h_night;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
thr = getl(b, T_ARG1);
|
||||
if (thr <= 0) thr = 20;
|
||||
EXEC SQL SELECT count(*),
|
||||
coalesce(sum(CASE WHEN EXTRACT(HOUR FROM created_at) < 6 THEN 1 ELSE 0 END),0)
|
||||
INTO :h_tot, :h_night
|
||||
FROM purchase WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
pct = (h_tot > 0) ? (h_night * 100 / h_tot) : 0;
|
||||
if (pct >= thr) rc = 1; /* 심야 거래 편중 */
|
||||
setl(b, T_COUNT, h_tot);
|
||||
setl(b, T_ARG2, h_night);
|
||||
setl(b, T_ARG3, pct);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_OUTLIER.h
Normal file
12
app/src/vl/svc/VL_OUTLIER.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_OUTLIER.h - vl 서비스 VL_OUTLIER 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE,T_ARG1,T_COUNT,T_RC
|
||||
*/
|
||||
#ifndef VL_OUTLIER_H
|
||||
#define VL_OUTLIER_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_OUTLIER(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_OUTLIER_H */
|
||||
29
app/src/vl/svc/VL_OUTLIER.pgc
Normal file
29
app/src/vl/svc/VL_OUTLIER.pgc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* VL_OUTLIER.pgc - vl 모듈 서비스 VL_OUTLIER (one service = one file).
|
||||
* 기능: 이상치 매입 탐지 (금액>당일 평균*배수 T_ARG1 기본4 건수, RC 1=존재).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_OUTLIER.h"
|
||||
|
||||
void VL_OUTLIER(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_mult, h_cnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
h_mult = getl(b, T_ARG1);
|
||||
if (h_mult <= 0) h_mult = 4;
|
||||
EXEC SQL SELECT count(*) INTO :h_cnt FROM purchase
|
||||
WHERE biz_date = :h_bizdate
|
||||
AND amount > :h_mult * (SELECT coalesce(avg(amount),0)
|
||||
FROM purchase WHERE biz_date = :h_bizdate);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 이상치 매입 존재 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_OVERLIMIT.h
Normal file
12
app/src/vl/svc/VL_OVERLIMIT.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_OVERLIMIT.h - vl 서비스 VL_OVERLIMIT 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE,T_COUNT,T_RC
|
||||
*/
|
||||
#ifndef VL_OVERLIMIT_H
|
||||
#define VL_OVERLIMIT_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_OVERLIMIT(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_OVERLIMIT_H */
|
||||
29
app/src/vl/svc/VL_OVERLIMIT.pgc
Normal file
29
app/src/vl/svc/VL_OVERLIMIT.pgc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* VL_OVERLIMIT.pgc - vl 모듈 서비스 VL_OVERLIMIT (one service = one file).
|
||||
* 기능: 가맹점 한도위반 검출 (일 매입합>일한도 가맹점 수, RC 1=존재).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_OVERLIMIT.h"
|
||||
|
||||
void VL_OVERLIMIT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_cnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
EXEC SQL SELECT count(*) INTO :h_cnt FROM (
|
||||
SELECT p.merchant_id
|
||||
FROM purchase p JOIN merchant m ON m.merchant_id = p.merchant_id
|
||||
WHERE p.biz_date = :h_bizdate
|
||||
GROUP BY p.merchant_id
|
||||
HAVING sum(p.amount) > max(m.daily_limit)) t;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 일한도 초과 가맹점 존재 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_PURNOAPPR.h
Normal file
12
app/src/vl/svc/VL_PURNOAPPR.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_PURNOAPPR.h - vl 서비스 VL_PURNOAPPR 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE,T_COUNT,T_ID1,T_RC
|
||||
*/
|
||||
#ifndef VL_PURNOAPPR_H
|
||||
#define VL_PURNOAPPR_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_PURNOAPPR(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_PURNOAPPR_H */
|
||||
29
app/src/vl/svc/VL_PURNOAPPR.pgc
Normal file
29
app/src/vl/svc/VL_PURNOAPPR.pgc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* VL_PURNOAPPR.pgc - vl 모듈 서비스 VL_PURNOAPPR (one service = one file).
|
||||
* 기능: 무승인 매입 검출 (일자별 승인 전무 매입 수, 취소분 제외, RC 1=존재).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_PURNOAPPR.h"
|
||||
|
||||
void VL_PURNOAPPR(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_cnt, h_first;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
EXEC SQL SELECT count(*), coalesce(min(p.purchase_id),0) INTO :h_cnt, :h_first
|
||||
FROM purchase p
|
||||
WHERE p.biz_date = :h_bizdate AND p.status <> 'C'
|
||||
AND NOT EXISTS (SELECT 1 FROM approval a
|
||||
WHERE a.purchase_id = p.purchase_id);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 승인 없는 매입 존재 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_ID1, h_first);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RIAPPR.h
Normal file
12
app/src/vl/svc/VL_RIAPPR.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RIAPPR.h - vl 서비스 VL_RIAPPR 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_COUNT,T_RC
|
||||
*/
|
||||
#ifndef VL_RIAPPR_H
|
||||
#define VL_RIAPPR_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RIAPPR(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RIAPPR_H */
|
||||
23
app/src/vl/svc/VL_RIAPPR.pgc
Normal file
23
app/src/vl/svc/VL_RIAPPR.pgc
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* VL_RIAPPR.pgc - vl 모듈 서비스 VL_RIAPPR (one service = one file).
|
||||
* 기능: 참조무결성 승인 (취소/무효 매입에 승인가결 존재 건수, RC 1=위반).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RIAPPR.h"
|
||||
|
||||
void VL_RIAPPR(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_cnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
EXEC SQL SELECT count(*) INTO :h_cnt FROM approval a
|
||||
JOIN purchase p ON p.purchase_id = a.purchase_id
|
||||
WHERE a.approved AND p.status IN ('C','V');
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 취소/무효 매입 승인 존재 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RICANCEL.h
Normal file
12
app/src/vl/svc/VL_RICANCEL.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RICANCEL.h - vl 서비스 VL_RICANCEL 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE,T_COUNT,T_CANCEL_ID,T_RC
|
||||
*/
|
||||
#ifndef VL_RICANCEL_H
|
||||
#define VL_RICANCEL_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RICANCEL(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RICANCEL_H */
|
||||
29
app/src/vl/svc/VL_RICANCEL.pgc
Normal file
29
app/src/vl/svc/VL_RICANCEL.pgc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* VL_RICANCEL.pgc - vl 모듈 서비스 VL_RICANCEL (one service = one file).
|
||||
* 기능: 참조무결성 취소 (일자별 매입 원거래 없는 취소 수, RC 1=위반; 최소 취소ID 반환).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RICANCEL.h"
|
||||
|
||||
void VL_RICANCEL(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_cnt, h_first;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
EXEC SQL SELECT count(*), coalesce(min(c.cancel_id),0) INTO :h_cnt, :h_first
|
||||
FROM ac_cancel c
|
||||
WHERE c.biz_date = :h_bizdate
|
||||
AND NOT EXISTS (SELECT 1 FROM purchase p
|
||||
WHERE p.purchase_id = c.purchase_id);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 매입 없는 취소 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_CANCEL_ID, h_first);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RIFX.h
Normal file
12
app/src/vl/svc/VL_RIFX.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RIFX.h - vl 서비스 VL_RIFX 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_COUNT,T_AMT1,T_RC
|
||||
*/
|
||||
#ifndef VL_RIFX_H
|
||||
#define VL_RIFX_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RIFX(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RIFX_H */
|
||||
25
app/src/vl/svc/VL_RIFX.pgc
Normal file
25
app/src/vl/svc/VL_RIFX.pgc
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* VL_RIFX.pgc - vl 모듈 서비스 VL_RIFX (one service = one file).
|
||||
* 기능: 참조무결성 해외 (매입 원거래 없는 해외 내역 수+환산합, RC 1=위반).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RIFX.h"
|
||||
|
||||
void VL_RIFX(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_cnt, h_amt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
EXEC SQL SELECT count(*), coalesce(sum(f.krw_amount),0) INTO :h_cnt, :h_amt
|
||||
FROM ac_fx f
|
||||
WHERE NOT EXISTS (SELECT 1 FROM purchase p
|
||||
WHERE p.purchase_id = f.purchase_id);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 매입 없는 해외 내역 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_AMT1, h_amt);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RIINSTALL.h
Normal file
12
app/src/vl/svc/VL_RIINSTALL.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RIINSTALL.h - vl 서비스 VL_RIINSTALL 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_COUNT,T_RC
|
||||
*/
|
||||
#ifndef VL_RIINSTALL_H
|
||||
#define VL_RIINSTALL_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RIINSTALL(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RIINSTALL_H */
|
||||
22
app/src/vl/svc/VL_RIINSTALL.pgc
Normal file
22
app/src/vl/svc/VL_RIINSTALL.pgc
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* VL_RIINSTALL.pgc - vl 모듈 서비스 VL_RIINSTALL (one service = one file).
|
||||
* 기능: 참조무결성 할부 (매입 원거래 없는 할부 내역 수, NOT IN, RC 1=위반).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RIINSTALL.h"
|
||||
|
||||
void VL_RIINSTALL(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_cnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
EXEC SQL SELECT count(*) INTO :h_cnt FROM ac_install i
|
||||
WHERE i.purchase_id NOT IN (SELECT purchase_id FROM purchase);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 매입 없는 할부 내역 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RIPAY.h
Normal file
12
app/src/vl/svc/VL_RIPAY.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RIPAY.h - vl 서비스 VL_RIPAY 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_COUNT,T_ID1,T_RC
|
||||
*/
|
||||
#ifndef VL_RIPAY_H
|
||||
#define VL_RIPAY_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RIPAY(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RIPAY_H */
|
||||
26
app/src/vl/svc/VL_RIPAY.pgc
Normal file
26
app/src/vl/svc/VL_RIPAY.pgc
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* VL_RIPAY.pgc - vl 모듈 서비스 VL_RIPAY (one service = one file).
|
||||
* 기능: 참조무결성 지급 (지급 XFER 원장의 매입 원거래 부재 건수, RC 1=위반).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RIPAY.h"
|
||||
|
||||
void VL_RIPAY(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_cnt, h_first;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
EXEC SQL SELECT count(*), coalesce(min(l.ledger_id),0) INTO :h_cnt, :h_first
|
||||
FROM ledger l
|
||||
WHERE l.entry_type = 'XFER'
|
||||
AND NOT EXISTS (SELECT 1 FROM purchase p
|
||||
WHERE p.purchase_id = l.purchase_id);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 매입 없는 지급 원장 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_ID1, h_first);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RITAXINV.h
Normal file
12
app/src/vl/svc/VL_RITAXINV.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RITAXINV.h - vl 서비스 VL_RITAXINV 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_COUNT,T_RC
|
||||
*/
|
||||
#ifndef VL_RITAXINV_H
|
||||
#define VL_RITAXINV_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RITAXINV(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RITAXINV_H */
|
||||
23
app/src/vl/svc/VL_RITAXINV.pgc
Normal file
23
app/src/vl/svc/VL_RITAXINV.pgc
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* VL_RITAXINV.pgc - vl 모듈 서비스 VL_RITAXINV (one service = one file).
|
||||
* 기능: 참조무결성 세금계산서 (매입 원거래 없는 세금계산서 수, LEFT JOIN, RC 1=위반).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RITAXINV.h"
|
||||
|
||||
void VL_RITAXINV(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_cnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
EXEC SQL SELECT count(*) INTO :h_cnt FROM ac_tax_invoice t
|
||||
LEFT JOIN purchase p ON p.purchase_id = t.purchase_id
|
||||
WHERE p.purchase_id IS NULL;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 매입 없는 세금계산서 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_ROUNDAMT.h
Normal file
12
app/src/vl/svc/VL_ROUNDAMT.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_ROUNDAMT.h - vl 서비스 VL_ROUNDAMT 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE,T_ARG1,T_ARG2,T_ARG3,T_COUNT,T_RC
|
||||
*/
|
||||
#ifndef VL_ROUNDAMT_H
|
||||
#define VL_ROUNDAMT_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_ROUNDAMT(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_ROUNDAMT_H */
|
||||
32
app/src/vl/svc/VL_ROUNDAMT.pgc
Normal file
32
app/src/vl/svc/VL_ROUNDAMT.pgc
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* VL_ROUNDAMT.pgc - vl 모듈 서비스 VL_ROUNDAMT (one service = one file).
|
||||
* 기능: 라운드금액 패턴 탐지 (10만원 배수 매입 비중>=T_ARG1% 기본50, RC 1=편중).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_ROUNDAMT.h"
|
||||
|
||||
void VL_ROUNDAMT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0, pct, thr;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_tot, h_round;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
thr = getl(b, T_ARG1);
|
||||
if (thr <= 0) thr = 50;
|
||||
EXEC SQL SELECT count(*),
|
||||
coalesce(sum(CASE WHEN amount % 100000 = 0 THEN 1 ELSE 0 END),0)
|
||||
INTO :h_tot, :h_round
|
||||
FROM purchase WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
pct = (h_tot > 0) ? (h_round * 100 / h_tot) : 0;
|
||||
if (pct >= thr) rc = 1; /* 라운드금액 편중 */
|
||||
setl(b, T_COUNT, h_tot);
|
||||
setl(b, T_ARG2, h_round);
|
||||
setl(b, T_ARG3, pct);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RULECOUNT.h
Normal file
12
app/src/vl/svc/VL_RULECOUNT.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RULECOUNT.h - vl 서비스 VL_RULECOUNT 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_ARG1,T_ARG2,T_ARG3,T_ARG4,T_RC
|
||||
*/
|
||||
#ifndef VL_RULECOUNT_H
|
||||
#define VL_RULECOUNT_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RULECOUNT(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RULECOUNT_H */
|
||||
30
app/src/vl/svc/VL_RULECOUNT.pgc
Normal file
30
app/src/vl/svc/VL_RULECOUNT.pgc
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* VL_RULECOUNT.pgc - vl 모듈 서비스 VL_RULECOUNT (one service = one file).
|
||||
* 기능: 검증규칙 심각도 분포 (INFO/WARN/ERROR/CRIT 건수, RC 1=CRIT 규칙 존재).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RULECOUNT.h"
|
||||
|
||||
void VL_RULECOUNT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_info, h_warn, h_err, h_crit;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
EXEC SQL SELECT
|
||||
coalesce(sum(CASE WHEN severity = 'INFO' THEN 1 ELSE 0 END),0),
|
||||
coalesce(sum(CASE WHEN severity = 'WARN' THEN 1 ELSE 0 END),0),
|
||||
coalesce(sum(CASE WHEN severity = 'ERROR' THEN 1 ELSE 0 END),0),
|
||||
coalesce(sum(CASE WHEN severity = 'CRIT' THEN 1 ELSE 0 END),0)
|
||||
INTO :h_info, :h_warn, :h_err, :h_crit
|
||||
FROM vl_rule;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_crit > 0) rc = 1; /* CRIT 규칙 존재 알림 */
|
||||
setl(b, T_ARG1, h_info);
|
||||
setl(b, T_ARG2, h_warn);
|
||||
setl(b, T_ARG3, h_err);
|
||||
setl(b, T_ARG4, h_crit);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RULEFIND.h
Normal file
12
app/src/vl/svc/VL_RULEFIND.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RULEFIND.h - vl 서비스 VL_RULEFIND 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_STR3,T_ARG1,T_STR4,T_RC
|
||||
*/
|
||||
#ifndef VL_RULEFIND_H
|
||||
#define VL_RULEFIND_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RULEFIND(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RULEFIND_H */
|
||||
24
app/src/vl/svc/VL_RULEFIND.pgc
Normal file
24
app/src/vl/svc/VL_RULEFIND.pgc
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* VL_RULEFIND.pgc - vl 모듈 서비스 VL_RULEFIND (one service = one file).
|
||||
* 기능: 검증규칙 단건 조회 (dbio vldb_get_rule 로 임계값/심각도 반환, RC 1=미존재).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RULEFIND.h"
|
||||
|
||||
void VL_RULEFIND(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char rule[32], sev[8];
|
||||
long thr = 0;
|
||||
gets_(b, T_STR3, rule, sizeof(rule));
|
||||
if (rule[0] == 0) { userlog("VL_RULEFIND: T_STR3(rule_code) 누락"); FAIL(b); }
|
||||
sev[0] = 0;
|
||||
if (vldb_get_rule(rule, &thr, sev) < 0) {
|
||||
setl(b, T_RC, 1); /* 규칙 미존재 */
|
||||
OK(b);
|
||||
}
|
||||
setl(b, T_ARG1, thr);
|
||||
Bchg(b, T_STR4, 0, sev, 0L);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RULEON.h
Normal file
12
app/src/vl/svc/VL_RULEON.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RULEON.h - vl 서비스 VL_RULEON 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_STR3,T_RC
|
||||
*/
|
||||
#ifndef VL_RULEON_H
|
||||
#define VL_RULEON_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RULEON(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RULEON_H */
|
||||
25
app/src/vl/svc/VL_RULEON.pgc
Normal file
25
app/src/vl/svc/VL_RULEON.pgc
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* VL_RULEON.pgc - vl 모듈 서비스 VL_RULEON (one service = one file).
|
||||
* 기능: 검증규칙 활성화 (status ACTIVE 전환, RC 1=이미 활성 2=상태변경 실패 3=규칙없음).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RULEON.h"
|
||||
|
||||
void VL_RULEON(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_rule[32], h_st[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_STR3, h_rule, sizeof(h_rule));
|
||||
if (h_rule[0] == 0) { userlog("VL_RULEON: T_STR3(rule_code) 누락"); FAIL(b); }
|
||||
EXEC SQL SELECT status INTO :h_st FROM vl_rule WHERE rule_code = :h_rule;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 3); OK(b); } /* 3=규칙 없음 */
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (strcmp(h_st, "ACTIVE") == 0) { setl(b, T_RC, 1); OK(b); } /* 이미 활성 */
|
||||
EXEC SQL UPDATE vl_rule SET status = 'ACTIVE', updated_at = now()
|
||||
WHERE rule_code = :h_rule;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
setl(b, T_RC, ((long)sqlca.sqlerrd[2] == 0) ? 2 : 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RULERENAME.h
Normal file
12
app/src/vl/svc/VL_RULERENAME.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RULERENAME.h - vl 서비스 VL_RULERENAME 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_STR3,T_STR1,T_RC
|
||||
*/
|
||||
#ifndef VL_RULERENAME_H
|
||||
#define VL_RULERENAME_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RULERENAME(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RULERENAME_H */
|
||||
25
app/src/vl/svc/VL_RULERENAME.pgc
Normal file
25
app/src/vl/svc/VL_RULERENAME.pgc
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* VL_RULERENAME.pgc - vl 모듈 서비스 VL_RULERENAME (one service = one file).
|
||||
* 기능: 검증규칙 명칭 변경 (rule_name UPDATE, 빈 값이면 기본명, RC 1=대상 규칙 없음).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RULERENAME.h"
|
||||
|
||||
void VL_RULERENAME(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_rule[32], h_name[64];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_STR3, h_rule, sizeof(h_rule));
|
||||
if (h_rule[0] == 0) { userlog("VL_RULERENAME: T_STR3(rule_code) 누락"); FAIL(b); }
|
||||
gets_(b, T_STR1, h_name, sizeof(h_name));
|
||||
if (h_name[0] == 0) strcpy(h_name, "무명 검증 규칙");
|
||||
EXEC SQL UPDATE vl_rule SET rule_name = :h_name, updated_at = now()
|
||||
WHERE rule_code = :h_rule;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if ((long)sqlca.sqlerrd[2] == 0) rc = 1; /* 대상 규칙 없음 */
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RULESEV.h
Normal file
12
app/src/vl/svc/VL_RULESEV.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RULESEV.h - vl 서비스 VL_RULESEV 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_STR3,T_STR4,T_RC
|
||||
*/
|
||||
#ifndef VL_RULESEV_H
|
||||
#define VL_RULESEV_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RULESEV(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RULESEV_H */
|
||||
29
app/src/vl/svc/VL_RULESEV.pgc
Normal file
29
app/src/vl/svc/VL_RULESEV.pgc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* VL_RULESEV.pgc - vl 모듈 서비스 VL_RULESEV (one service = one file).
|
||||
* 기능: 검증규칙 심각도 변경 (INFO/WARN/ERROR/CRIT 유효성 검사 후 UPDATE, RC 1=규칙없음 2=심각도오류).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RULESEV.h"
|
||||
|
||||
void VL_RULESEV(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_rule[32], h_sev[8];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_STR3, h_rule, sizeof(h_rule));
|
||||
if (h_rule[0] == 0) { userlog("VL_RULESEV: T_STR3(rule_code) 누락"); FAIL(b); }
|
||||
gets_(b, T_STR4, h_sev, sizeof(h_sev));
|
||||
if (strcmp(h_sev, "INFO") != 0 && strcmp(h_sev, "WARN") != 0 &&
|
||||
strcmp(h_sev, "ERROR") != 0 && strcmp(h_sev, "CRIT") != 0) {
|
||||
setl(b, T_RC, 2); /* 허용되지 않는 심각도 */
|
||||
OK(b);
|
||||
}
|
||||
EXEC SQL UPDATE vl_rule SET severity = :h_sev, updated_at = now()
|
||||
WHERE rule_code = :h_rule;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if ((long)sqlca.sqlerrd[2] == 0) rc = 1; /* 대상 규칙 없음 */
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RULEVER.h
Normal file
12
app/src/vl/svc/VL_RULEVER.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RULEVER.h - vl 서비스 VL_RULEVER 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_STR3,T_ARG1,T_ARG2,T_RC
|
||||
*/
|
||||
#ifndef VL_RULEVER_H
|
||||
#define VL_RULEVER_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RULEVER(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RULEVER_H */
|
||||
31
app/src/vl/svc/VL_RULEVER.pgc
Normal file
31
app/src/vl/svc/VL_RULEVER.pgc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* VL_RULEVER.pgc - vl 모듈 서비스 VL_RULEVER (one service = one file).
|
||||
* 기능: 검증규칙 최신성 검사 (T_ARG1 기본30일 이내 갱신 여부, RC 1=노후 2=규칙없음).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RULEVER.h"
|
||||
|
||||
void VL_RULEVER(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_rule[32];
|
||||
long h_days, h_recent, h_exist;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_STR3, h_rule, sizeof(h_rule));
|
||||
if (h_rule[0] == 0) { userlog("VL_RULEVER: T_STR3(rule_code) 누락"); FAIL(b); }
|
||||
h_days = getl(b, T_ARG1);
|
||||
if (h_days <= 0) h_days = 30;
|
||||
EXEC SQL SELECT count(*) INTO :h_exist FROM vl_rule WHERE rule_code = :h_rule;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_exist == 0) { setl(b, T_RC, 2); OK(b); } /* 2=규칙 없음 */
|
||||
EXEC SQL SELECT count(*) INTO :h_recent FROM vl_rule
|
||||
WHERE rule_code = :h_rule
|
||||
AND updated_at >= now() - CAST(:h_days AS int) * INTERVAL '1 day';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_recent == 0) rc = 1; /* 장기 미갱신 규칙 */
|
||||
setl(b, T_ARG2, h_days);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_SETTLREV.h
Normal file
12
app/src/vl/svc/VL_SETTLREV.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_SETTLREV.h - vl 서비스 VL_SETTLREV 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE,T_COUNT,T_AMT1,T_RC
|
||||
*/
|
||||
#ifndef VL_SETTLREV_H
|
||||
#define VL_SETTLREV_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_SETTLREV(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_SETTLREV_H */
|
||||
26
app/src/vl/svc/VL_SETTLREV.pgc
Normal file
26
app/src/vl/svc/VL_SETTLREV.pgc
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* VL_SETTLREV.pgc - vl 모듈 서비스 VL_SETTLREV (one service = one file).
|
||||
* 기능: 정산 역전 검출 (일자별 순액 음수 settlement 건수, RC 1=존재; 최악치 반환).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_SETTLREV.h"
|
||||
|
||||
void VL_SETTLREV(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_cnt, h_worst;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
EXEC SQL SELECT count(*), coalesce(min(net),0) INTO :h_cnt, :h_worst
|
||||
FROM settlement WHERE biz_date = :h_bizdate AND net < 0;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 순액 역전 정산 존재 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_AMT1, h_worst);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_SPIKEAMT.h
Normal file
12
app/src/vl/svc/VL_SPIKEAMT.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_SPIKEAMT.h - vl 서비스 VL_SPIKEAMT 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE,T_ARG1,T_AMT1,T_AMT2,T_COUNT,T_RC
|
||||
*/
|
||||
#ifndef VL_SPIKEAMT_H
|
||||
#define VL_SPIKEAMT_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_SPIKEAMT(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_SPIKEAMT_H */
|
||||
31
app/src/vl/svc/VL_SPIKEAMT.pgc
Normal file
31
app/src/vl/svc/VL_SPIKEAMT.pgc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* VL_SPIKEAMT.pgc - vl 모듈 서비스 VL_SPIKEAMT (one service = one file).
|
||||
* 기능: 금액 급증 탐지 (당일 최대 매입>평균*배수 T_ARG1 기본5, RC 1=급증).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); vl_svr가 tpsvrinit에서 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_SPIKEAMT.h"
|
||||
|
||||
void VL_SPIKEAMT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0, mult;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_max, h_avg, h_cnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
|
||||
mult = getl(b, T_ARG1);
|
||||
if (mult <= 0) mult = 5;
|
||||
EXEC SQL SELECT coalesce(max(amount),0),
|
||||
coalesce(CAST(avg(amount) AS bigint),0), count(*)
|
||||
INTO :h_max, :h_avg, :h_cnt
|
||||
FROM purchase WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0 && h_max > h_avg * mult) rc = 1; /* 금액 급증 */
|
||||
setl(b, T_AMT1, h_max);
|
||||
setl(b, T_AMT2, h_avg);
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue