규모확장 Wave A: 전 11모듈 svc 30→75·batch 22→35 + 전 모듈 운영데이터 시드
- svc 330→825 (모듈당 +45 고유 실업무: chargeback·재매입·심사워크플로·전문유형별· 대사세분·정산시뮬·지급재처리·복식결산·마감워크플로·마스터심사·검증룰·전문라우팅 등) - batch 242→385 (모듈당 +13), 카피북 헤더·디스패처 advertise 전 75 반영 - db/schema.d/95-module-seed.sql: 전 모듈 테이블 운영데이터(au 8.4k·st 15.9k·mg 16.9k· lg 14.6k·rc 7.7k·py 2.9k·vl 8.5k·cm 10.4k 등, 총 ~171k행) — base 거래와 정합 - 화면 매니페스트 825 재생성, 큐 메모리 튜닝(NDRX_MSGMAX 50→30) - 검증: build DONE modules=11 batches=385, 12서버 runok, xadmin psc 828 AVAIL, 매입체인 XA 커밋(status=S), 새서비스 시드데이터 스모크(ACQ_MERCHSUM/RC_STATS 실값), 전 코퍼스 .pgc 클론 0, 헤드리스 스크린샷 확인 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
19acf4ed96
commit
ea90bef264
1292 changed files with 53968 additions and 20 deletions
43
app/src/vl/batch/vl_agedopen_batch.pgc
Normal file
43
app/src/vl/batch/vl_agedopen_batch.pgc
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* vl_agedopen_batch.pgc - 장기미결 의심거래 에스컬레이션 배치 (XA 단일 글로벌 트랜잭션 배치).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; N일 초과 OPEN 의심거래의 severity를 CRIT로 승격한 뒤
|
||||
* tpcommit drives XA 2PC.
|
||||
* Usage: vl_agedopen_batch [YYYY-MM-DD] [경과일수]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_agedopen_batch.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_days;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_agedopen_rec_t rec;
|
||||
(void)bizdate;
|
||||
|
||||
h_days = (argc > 2) ? atol(argv[2]) : VL_AGEDOPEN_DEF_DAYS;
|
||||
if (h_days <= 0) h_days = VL_AGEDOPEN_DEF_DAYS;
|
||||
|
||||
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 = 'CRIT'
|
||||
WHERE status = 'OPEN' AND severity <> 'CRIT'
|
||||
AND created_at < now() - (:h_days || ' days')::interval;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_agedopen_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
rec.escalated = (long)sqlca.sqlerrd[2];
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
rec.days = h_days;
|
||||
printf(">>> vl_agedopen_batch COMMIT: 기준=%ld일 CRIT승격=%ld\n", rec.days, rec.escalated);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
46
app/src/vl/batch/vl_apprsum_batch.pgc
Normal file
46
app/src/vl/batch/vl_apprsum_batch.pgc
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* vl_apprsum_batch.pgc - 일자별 매입-승인 금액 대사 배치 (XA 단일 글로벌 트랜잭션 배치).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; 취소 제외 매입 총액과 가결 승인이 붙은 매입 총액을 대조한 뒤
|
||||
* tpcommit drives XA 2PC.
|
||||
* Usage: vl_apprsum_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_apprsum_batch.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *bizdate = (argc > 1) ? argv[1] : VL_APPRSUM_DEF_DATE;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_all, h_appr;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_apprsum_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(amount),0) INTO :h_all FROM purchase
|
||||
WHERE biz_date = :h_bizdate AND status <> 'C';
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_apprsum_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
EXEC SQL SELECT coalesce(sum(p.amount),0) INTO :h_appr FROM purchase p
|
||||
WHERE p.biz_date = :h_bizdate AND p.status <> 'C'
|
||||
AND EXISTS (SELECT 1 FROM approval a
|
||||
WHERE a.purchase_id = p.purchase_id AND a.approved);
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_apprsum_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; }
|
||||
rec.total_amt = h_all; rec.appr_amt = h_appr; rec.gap_amt = h_all - h_appr;
|
||||
printf(">>> vl_apprsum_batch COMMIT: bizdate=%s 매입총액=%ld 승인보유=%ld 미승인=%ld\n",
|
||||
bizdate, rec.total_amt, rec.appr_amt, rec.gap_amt);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
46
app/src/vl/batch/vl_daterev_batch.pgc
Normal file
46
app/src/vl/batch/vl_daterev_batch.pgc
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* vl_daterev_batch.pgc - 일자 역전 검출 배치 (XA 단일 글로벌 트랜잭션 배치).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; 매입일보다 과거로 기표된 정산/원장 건수를 각각 집계한 뒤
|
||||
* tpcommit drives XA 2PC.
|
||||
* Usage: vl_daterev_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_daterev_batch.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *bizdate = (argc > 1) ? argv[1] : VL_DATEREV_DEF_DATE;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_srev, h_lrev;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_daterev_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_srev
|
||||
FROM settlement s JOIN purchase p ON p.purchase_id = s.purchase_id
|
||||
WHERE s.biz_date = :h_bizdate AND s.biz_date < p.biz_date;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_daterev_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
EXEC SQL SELECT count(*) INTO :h_lrev
|
||||
FROM ledger l JOIN purchase p ON p.purchase_id = l.purchase_id
|
||||
WHERE l.biz_date = :h_bizdate AND l.biz_date < p.biz_date;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_daterev_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; }
|
||||
rec.settle_rev = h_srev; rec.ledger_rev = h_lrev;
|
||||
printf(">>> vl_daterev_batch COMMIT: bizdate=%s 정산역전=%ld 원장역전=%ld\n",
|
||||
bizdate, rec.settle_rev, rec.ledger_rev);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
56
app/src/vl/batch/vl_duppay_batch.pgc
Normal file
56
app/src/vl/batch/vl_duppay_batch.pgc
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* vl_duppay_batch.pgc - 중복지급 스캔 배치 (XA 단일 글로벌 트랜잭션 배치).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; 커서로 지급(XFER) 원장이 2건 이상인 매입을 훑어 의심거래로
|
||||
* 적재한 뒤 tpcommit drives XA 2PC.
|
||||
* Usage: vl_duppay_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_dbio.h"
|
||||
#include "vl_duppay_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_duppay_rec_t rec; rec.dup_groups = 0; rec.suspects = 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 vdpc CURSOR FOR
|
||||
SELECT purchase_id, count(*) FROM ledger
|
||||
WHERE biz_date = :h_bizdate AND entry_type = 'XFER'
|
||||
GROUP BY purchase_id HAVING count(*) > 1;
|
||||
EXEC SQL OPEN vdpc;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_duppay_batch OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
for (;;) {
|
||||
EXEC SQL FETCH vdpc INTO :h_pid, :h_cnt;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_duppay_batch FETCH FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
rec.dup_groups++;
|
||||
if (vldb_insert_suspect(h_pid, VL_DUPPAY_RULE, VL_DUPPAY_SEV,
|
||||
"지급 원장 중복 기표", h_bizdate) < 0) {
|
||||
fprintf(stderr, "vl_duppay_batch 의심거래 적재 FAIL\n"); tpabort(0); return 1;
|
||||
}
|
||||
rec.suspects++;
|
||||
}
|
||||
EXEC SQL CLOSE vdpc;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> vl_duppay_batch COMMIT: bizdate=%s 중복지급그룹=%ld 의심거래적재=%ld\n",
|
||||
bizdate, rec.dup_groups, rec.suspects);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
47
app/src/vl/batch/vl_feerecalc_batch.pgc
Normal file
47
app/src/vl/batch/vl_feerecalc_batch.pgc
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* vl_feerecalc_batch.pgc - 수수료 재계산 편차 검증 배치 (XA 단일 글로벌 트랜잭션 배치).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; 가맹점 요율로 수수료를 재계산해 허용오차를 넘는 매입 건수와
|
||||
* 편차 총액을 집계한 뒤 tpcommit drives XA 2PC.
|
||||
* Usage: vl_feerecalc_batch [YYYY-MM-DD] [허용오차원]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_feerecalc_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_tol, h_viol, h_devsum;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_feerecalc_rec_t rec;
|
||||
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
h_tol = (argc > 2) ? atol(argv[2]) : VL_FEERECALC_DEF_TOL;
|
||||
if (h_tol < 0) h_tol = VL_FEERECALC_DEF_TOL;
|
||||
|
||||
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(sum(abs(p.fee - p.amount * m.mdr_bps / 10000)),0)
|
||||
INTO :h_viol, :h_devsum
|
||||
FROM purchase p JOIN merchant m ON m.merchant_id = p.merchant_id
|
||||
WHERE p.biz_date = :h_bizdate
|
||||
AND abs(p.fee - p.amount * m.mdr_bps / 10000) > :h_tol;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_feerecalc_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; }
|
||||
rec.tol_won = h_tol; rec.viol = h_viol; rec.dev_sum = h_devsum;
|
||||
printf(">>> vl_feerecalc_batch COMMIT: bizdate=%s 허용=%ld원 편차초과=%ld 편차합=%ld\n",
|
||||
bizdate, rec.tol_won, rec.viol, rec.dev_sum);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
57
app/src/vl/batch/vl_negbal_batch.pgc
Normal file
57
app/src/vl/batch/vl_negbal_batch.pgc
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* vl_negbal_batch.pgc - 마이너스 잔액 가맹점 검출 배치 (XA 단일 글로벌 트랜잭션 배치).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; 커서로 일별 집계 순액이 음수인 가맹점을 훑어 의심거래로 적재하고
|
||||
* 최악치를 보고한 뒤 tpcommit drives XA 2PC.
|
||||
* Usage: vl_negbal_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_dbio.h"
|
||||
#include "vl_negbal_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_net;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
char detail[96];
|
||||
vl_negbal_rec_t rec; rec.merchants = 0; rec.worst_amt = 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 vnbc CURSOR FOR
|
||||
SELECT merchant_id, net_amount FROM merchant_summary
|
||||
WHERE biz_date = :h_bizdate AND net_amount < 0
|
||||
ORDER BY net_amount;
|
||||
EXEC SQL OPEN vnbc;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_negbal_batch OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
for (;;) {
|
||||
EXEC SQL FETCH vnbc INTO :h_merch, :h_net;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_negbal_batch FETCH FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
if (rec.merchants == 0) rec.worst_amt = h_net; /* 정렬상 첫 행이 최악치 */
|
||||
snprintf(detail, sizeof(detail), "가맹점 %s 순액 %ld", h_merch, h_net);
|
||||
if (vldb_insert_suspect(0, VL_NEGBAL_RULE, "CRIT", detail, h_bizdate) < 0) {
|
||||
fprintf(stderr, "vl_negbal_batch 의심거래 적재 FAIL\n"); tpabort(0); return 1;
|
||||
}
|
||||
rec.merchants++;
|
||||
}
|
||||
EXEC SQL CLOSE vnbc;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> vl_negbal_batch COMMIT: bizdate=%s 음수잔액가맹점=%ld 최악=%ld\n",
|
||||
bizdate, rec.merchants, rec.worst_amt);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
47
app/src/vl/batch/vl_ratedev_batch.pgc
Normal file
47
app/src/vl/batch/vl_ratedev_batch.pgc
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* vl_ratedev_batch.pgc - 실적용 요율 편차 스캔 배치 (XA 단일 글로벌 트랜잭션 배치).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; 매입별 실적용 요율(fee*10000/amount)과 가맹점 요율의 편차가
|
||||
* 허용치를 넘는 건수/최대편차를 집계한 뒤 tpcommit drives XA 2PC.
|
||||
* Usage: vl_ratedev_batch [YYYY-MM-DD] [허용편차bps]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_ratedev_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_tol, h_viol, h_maxdev;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_ratedev_rec_t rec;
|
||||
|
||||
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
|
||||
h_tol = (argc > 2) ? atol(argv[2]) : VL_RATEDEV_DEF_TOL;
|
||||
if (h_tol <= 0) h_tol = VL_RATEDEV_DEF_TOL;
|
||||
|
||||
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(max(abs(p.fee * 10000 / p.amount - m.mdr_bps)),0)
|
||||
INTO :h_viol, :h_maxdev
|
||||
FROM purchase p JOIN merchant m ON m.merchant_id = p.merchant_id
|
||||
WHERE p.biz_date = :h_bizdate AND p.amount > 0
|
||||
AND abs(p.fee * 10000 / p.amount - m.mdr_bps) > :h_tol;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_ratedev_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; }
|
||||
rec.tol_bps = h_tol; rec.viol = h_viol; rec.max_dev = h_maxdev;
|
||||
printf(">>> vl_ratedev_batch COMMIT: bizdate=%s 허용=%ldbps 위반=%ld 최대편차=%ldbps\n",
|
||||
bizdate, rec.tol_bps, rec.viol, rec.max_dev);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
55
app/src/vl/batch/vl_ruleaudit_batch.pgc
Normal file
55
app/src/vl/batch/vl_ruleaudit_batch.pgc
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* vl_ruleaudit_batch.pgc - 검증 규칙 감사 배치 (XA 단일 글로벌 트랜잭션 배치).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; 커서로 임계값이 설정되지 않은 ACTIVE 고위험(ERROR/CRIT) 규칙을
|
||||
* 훑어 규칙별로 검증로그에 남긴 뒤 tpcommit drives XA 2PC.
|
||||
* Usage: vl_ruleaudit_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_dbio.h"
|
||||
#include "vl_ruleaudit_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_rule[64];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
char detail[96];
|
||||
vl_ruleaudit_rec_t rec; rec.bad_rules = 0; rec.logged = 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 vrac CURSOR FOR
|
||||
SELECT rule_code FROM vl_rule
|
||||
WHERE status = 'ACTIVE' AND severity IN ('ERROR','CRIT')
|
||||
AND threshold <= 0
|
||||
ORDER BY rule_code;
|
||||
EXEC SQL OPEN vrac;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_ruleaudit_batch OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
for (;;) {
|
||||
EXEC SQL FETCH vrac INTO :h_rule;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_ruleaudit_batch FETCH FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
rec.bad_rules++;
|
||||
snprintf(detail, sizeof(detail), "%s 임계값 미설정 고위험 규칙", h_rule);
|
||||
if (vldb_insert_check_log(VL_RULEAUDIT_CHECK, 0, 1, detail, bizdate) < 0) {
|
||||
fprintf(stderr, "vl_ruleaudit_batch 검증로그 적재 FAIL\n"); tpabort(0); return 1;
|
||||
}
|
||||
rec.logged++;
|
||||
}
|
||||
EXEC SQL CLOSE vrac;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> vl_ruleaudit_batch COMMIT: bizdate=%s 감사적발규칙=%ld 로그=%ld\n",
|
||||
bizdate, rec.bad_rules, rec.logged);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
51
app/src/vl/batch/vl_sumrecon_batch.pgc
Normal file
51
app/src/vl/batch/vl_sumrecon_batch.pgc
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* vl_sumrecon_batch.pgc - 가맹점 일별 통계-원천 대사 배치 (XA 단일 글로벌 트랜잭션 배치).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; merchant_summary의 건수/총액을 purchase 원천 재집계와 대조해
|
||||
* 불일치 행 수를 산출한 뒤 tpcommit drives XA 2PC.
|
||||
* Usage: vl_sumrecon_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_sumrecon_batch.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *bizdate = (argc > 1) ? argv[1] : VL_SUMRECON_DEF_DATE;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_rows, h_mis;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_sumrecon_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_rows FROM merchant_summary
|
||||
WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_sumrecon_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
EXEC SQL SELECT count(*) INTO :h_mis FROM merchant_summary ms
|
||||
WHERE ms.biz_date = :h_bizdate
|
||||
AND (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')
|
||||
OR ms.gross_amount <> coalesce((SELECT sum(p.amount) FROM purchase p
|
||||
WHERE p.merchant_id = ms.merchant_id
|
||||
AND p.biz_date = ms.biz_date
|
||||
AND p.status <> 'C'), 0));
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_sumrecon_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; }
|
||||
rec.summary_rows = h_rows; rec.mismatched = h_mis;
|
||||
printf(">>> vl_sumrecon_batch COMMIT: bizdate=%s 통계행=%ld 대사불일치=%ld\n",
|
||||
bizdate, rec.summary_rows, rec.mismatched);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
42
app/src/vl/batch/vl_thrtrim_batch.pgc
Normal file
42
app/src/vl/batch/vl_thrtrim_batch.pgc
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* vl_thrtrim_batch.pgc - 검증 규칙 임계값 정리 배치 (XA 단일 글로벌 트랜잭션 배치).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; 잘못 저장된 음수 임계값을 0으로 클램프하고 전체 규칙 수를
|
||||
* 함께 보고한 뒤 tpcommit drives XA 2PC.
|
||||
* Usage: vl_thrtrim_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_thrtrim_batch.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_total;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_thrtrim_rec_t rec;
|
||||
(void)bizdate;
|
||||
|
||||
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_rule SET threshold = 0, updated_at = now()
|
||||
WHERE threshold < 0;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_thrtrim_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
rec.clamped = (long)sqlca.sqlerrd[2];
|
||||
EXEC SQL SELECT count(*) INTO :h_total FROM vl_rule;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_thrtrim_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; }
|
||||
rec.total_rules = h_total;
|
||||
printf(">>> vl_thrtrim_batch COMMIT: 음수임계값정리=%ld 전체규칙=%ld\n",
|
||||
rec.clamped, rec.total_rules);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
55
app/src/vl/batch/vl_tristage_batch.pgc
Normal file
55
app/src/vl/batch/vl_tristage_batch.pgc
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* vl_tristage_batch.pgc - 매입-정산-지급 3단 정합 대사 배치 (XA 단일 글로벌 트랜잭션 배치).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; 정산완료 매입 순액/정산 순액/지급(XFER) 원장 합계와 건별 3단
|
||||
* 불일치 건수를 집계한 뒤 tpcommit drives XA 2PC.
|
||||
* Usage: vl_tristage_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_tristage_batch.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *bizdate = (argc > 1) ? argv[1] : VL_TRISTAGE_DEF_DATE;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_pnet, h_snet, h_xamt, h_bad;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_tristage_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, "vl_tristage_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); 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_tristage_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
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) { fprintf(stderr, "vl_tristage_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
EXEC SQL SELECT count(*) INTO :h_bad FROM purchase p
|
||||
WHERE p.biz_date = :h_bizdate AND p.status = 'S'
|
||||
AND (p.net <> coalesce((SELECT sum(s.net) FROM settlement s
|
||||
WHERE s.purchase_id = p.purchase_id), 0)
|
||||
OR p.net <> coalesce((SELECT sum(l.amount) FROM ledger l
|
||||
WHERE l.purchase_id = p.purchase_id
|
||||
AND l.entry_type = 'XFER'), 0));
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_tristage_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; }
|
||||
rec.p_net = h_pnet; rec.s_net = h_snet; rec.x_amt = h_xamt; rec.broken = h_bad;
|
||||
printf(">>> vl_tristage_batch COMMIT: bizdate=%s 매입=%ld 정산=%ld 지급=%ld 3단불일치=%ld\n",
|
||||
bizdate, rec.p_net, rec.s_net, rec.x_amt, rec.broken);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
45
app/src/vl/batch/vl_unacq_batch.pgc
Normal file
45
app/src/vl/batch/vl_unacq_batch.pgc
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* vl_unacq_batch.pgc - 미매입 승인 검출 배치 (XA 단일 글로벌 트랜잭션 배치).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; 매입 원장이 없는 고아 승인을 집계하고 결과를 검증로그에 남긴 뒤
|
||||
* tpcommit drives XA 2PC.
|
||||
* Usage: vl_unacq_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_dbio.h"
|
||||
#include "vl_unacq_batch.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_cnt, h_first;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_unacq_rec_t rec;
|
||||
|
||||
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(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) { fprintf(stderr, "vl_unacq_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
if (vldb_insert_check_log(VL_UNACQ_CHECK, h_first, (h_cnt > 0) ? 1 : 0,
|
||||
"미매입 승인 정기 스캔", bizdate) < 0) {
|
||||
fprintf(stderr, "vl_unacq_batch 검증로그 적재 FAIL\n"); tpabort(0); return 1;
|
||||
}
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
rec.orphans = h_cnt; rec.first_id = h_first;
|
||||
printf(">>> vl_unacq_batch COMMIT: bizdate=%s 고아승인=%ld 최초ID=%ld\n",
|
||||
bizdate, rec.orphans, rec.first_id);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
45
app/src/vl/batch/vl_wfstat_batch.pgc
Normal file
45
app/src/vl/batch/vl_wfstat_batch.pgc
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* vl_wfstat_batch.pgc - 의심거래 워크플로 상태 통계 배치 (XA 단일 글로벌 트랜잭션 배치).
|
||||
*
|
||||
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
|
||||
* transaction; 일자별 의심거래를 확인/조치/종결 워크플로 상태별로 집계한 뒤
|
||||
* tpcommit drives XA 2PC.
|
||||
* Usage: vl_wfstat_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "vl_wfstat_batch.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *bizdate = (argc > 1) ? argv[1] : VL_WFSTAT_DEF_DATE;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_open, h_conf, h_closed;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
vl_wfstat_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(CASE WHEN status = 'OPEN' THEN 1 ELSE 0 END),0),
|
||||
coalesce(sum(CASE WHEN status = 'CONFIRMED' THEN 1 ELSE 0 END),0),
|
||||
coalesce(sum(CASE WHEN status = 'CLOSED' THEN 1 ELSE 0 END),0)
|
||||
INTO :h_open, :h_conf, :h_closed
|
||||
FROM vl_suspect WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "vl_wfstat_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; }
|
||||
rec.open_c = h_open; rec.conf_c = h_conf; rec.closed_c = h_closed;
|
||||
printf(">>> vl_wfstat_batch COMMIT: bizdate=%s 미결=%ld 확인=%ld 종결=%ld\n",
|
||||
bizdate, rec.open_c, rec.conf_c, rec.closed_c);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
12
app/src/vl/dbio/vl_agedopen_batch.h
Normal file
12
app/src/vl/dbio/vl_agedopen_batch.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* vl_agedopen_batch.h - vl vl_agedopen_batch 배치 전용 카피북 (copybook). 장기미결 의심거래 에스컬레이션 배치
|
||||
* 기본 경과일 상수 + 승격 결과 레코드. Included by vl_agedopen_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_AGEDOPEN_BATCH_H
|
||||
#define VL_AGEDOPEN_BATCH_H
|
||||
|
||||
#define VL_AGEDOPEN_DEF_DAYS 7L
|
||||
|
||||
typedef struct { long days; long escalated; } vl_agedopen_rec_t;
|
||||
|
||||
#endif /* VL_AGEDOPEN_BATCH_H */
|
||||
12
app/src/vl/dbio/vl_apprsum_batch.h
Normal file
12
app/src/vl/dbio/vl_apprsum_batch.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* vl_apprsum_batch.h - vl vl_apprsum_batch 배치 전용 카피북 (copybook). 일자별 매입-승인 금액 대사 배치
|
||||
* 대사 결과 레코드 + 기본 영업일 상수. Included by vl_apprsum_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_APPRSUM_BATCH_H
|
||||
#define VL_APPRSUM_BATCH_H
|
||||
|
||||
#define VL_APPRSUM_DEF_DATE "2026-07-19"
|
||||
|
||||
typedef struct { long total_amt; long appr_amt; long gap_amt; } vl_apprsum_rec_t;
|
||||
|
||||
#endif /* VL_APPRSUM_BATCH_H */
|
||||
12
app/src/vl/dbio/vl_daterev_batch.h
Normal file
12
app/src/vl/dbio/vl_daterev_batch.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* vl_daterev_batch.h - vl vl_daterev_batch 배치 전용 카피북 (copybook). 일자 역전 검출 배치
|
||||
* 역전 유형별 집계 레코드 + 기본 영업일 상수. Included by vl_daterev_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_DATEREV_BATCH_H
|
||||
#define VL_DATEREV_BATCH_H
|
||||
|
||||
#define VL_DATEREV_DEF_DATE "2026-07-19"
|
||||
|
||||
typedef struct { long settle_rev; long ledger_rev; } vl_daterev_rec_t;
|
||||
|
||||
#endif /* VL_DATEREV_BATCH_H */
|
||||
13
app/src/vl/dbio/vl_duppay_batch.h
Normal file
13
app/src/vl/dbio/vl_duppay_batch.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* vl_duppay_batch.h - vl vl_duppay_batch 배치 전용 카피북 (copybook). 중복지급 스캔/의심거래 적재 배치
|
||||
* 적재 규칙 코드/심각도 상수 + 스캔 결과 레코드. Included by vl_duppay_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_DUPPAY_BATCH_H
|
||||
#define VL_DUPPAY_BATCH_H
|
||||
|
||||
#define VL_DUPPAY_RULE "DUP_PAY"
|
||||
#define VL_DUPPAY_SEV "ERROR"
|
||||
|
||||
typedef struct { long dup_groups; long suspects; } vl_duppay_rec_t;
|
||||
|
||||
#endif /* VL_DUPPAY_BATCH_H */
|
||||
12
app/src/vl/dbio/vl_feerecalc_batch.h
Normal file
12
app/src/vl/dbio/vl_feerecalc_batch.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* vl_feerecalc_batch.h - vl vl_feerecalc_batch 배치 전용 카피북 (copybook). 수수료 재계산 편차 배치
|
||||
* 기본 허용오차(원) 상수 + 재계산 결과 레코드. Included by vl_feerecalc_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_FEERECALC_BATCH_H
|
||||
#define VL_FEERECALC_BATCH_H
|
||||
|
||||
#define VL_FEERECALC_DEF_TOL 10L
|
||||
|
||||
typedef struct { long tol_won; long viol; long dev_sum; } vl_feerecalc_rec_t;
|
||||
|
||||
#endif /* VL_FEERECALC_BATCH_H */
|
||||
12
app/src/vl/dbio/vl_negbal_batch.h
Normal file
12
app/src/vl/dbio/vl_negbal_batch.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* vl_negbal_batch.h - vl vl_negbal_batch 배치 전용 카피북 (copybook). 마이너스 잔액 가맹점 검출 배치
|
||||
* 적재 규칙 코드 상수 + 검출 결과 레코드. Included by vl_negbal_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_NEGBAL_BATCH_H
|
||||
#define VL_NEGBAL_BATCH_H
|
||||
|
||||
#define VL_NEGBAL_RULE "NEG_BAL"
|
||||
|
||||
typedef struct { long merchants; long worst_amt; } vl_negbal_rec_t;
|
||||
|
||||
#endif /* VL_NEGBAL_BATCH_H */
|
||||
12
app/src/vl/dbio/vl_ratedev_batch.h
Normal file
12
app/src/vl/dbio/vl_ratedev_batch.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* vl_ratedev_batch.h - vl vl_ratedev_batch 배치 전용 카피북 (copybook). 요율 편차 스캔 배치
|
||||
* 기본 허용편차(bps) 상수 + 스캔 결과 레코드. Included by vl_ratedev_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_RATEDEV_BATCH_H
|
||||
#define VL_RATEDEV_BATCH_H
|
||||
|
||||
#define VL_RATEDEV_DEF_TOL 5L
|
||||
|
||||
typedef struct { long tol_bps; long viol; long max_dev; } vl_ratedev_rec_t;
|
||||
|
||||
#endif /* VL_RATEDEV_BATCH_H */
|
||||
12
app/src/vl/dbio/vl_ruleaudit_batch.h
Normal file
12
app/src/vl/dbio/vl_ruleaudit_batch.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* vl_ruleaudit_batch.h - vl vl_ruleaudit_batch 배치 전용 카피북 (copybook). 검증 규칙 감사 배치
|
||||
* 검증로그 check_type 상수 + 감사 결과 레코드. Included by vl_ruleaudit_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_RULEAUDIT_BATCH_H
|
||||
#define VL_RULEAUDIT_BATCH_H
|
||||
|
||||
#define VL_RULEAUDIT_CHECK "VL_RULEAUDIT"
|
||||
|
||||
typedef struct { long bad_rules; long logged; } vl_ruleaudit_rec_t;
|
||||
|
||||
#endif /* VL_RULEAUDIT_BATCH_H */
|
||||
12
app/src/vl/dbio/vl_sumrecon_batch.h
Normal file
12
app/src/vl/dbio/vl_sumrecon_batch.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* vl_sumrecon_batch.h - vl vl_sumrecon_batch 배치 전용 카피북 (copybook). 통계-원천 대사 배치
|
||||
* 대사 결과 레코드 + 기본 영업일 상수. Included by vl_sumrecon_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_SUMRECON_BATCH_H
|
||||
#define VL_SUMRECON_BATCH_H
|
||||
|
||||
#define VL_SUMRECON_DEF_DATE "2026-07-19"
|
||||
|
||||
typedef struct { long summary_rows; long mismatched; } vl_sumrecon_rec_t;
|
||||
|
||||
#endif /* VL_SUMRECON_BATCH_H */
|
||||
10
app/src/vl/dbio/vl_thrtrim_batch.h
Normal file
10
app/src/vl/dbio/vl_thrtrim_batch.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* vl_thrtrim_batch.h - vl vl_thrtrim_batch 배치 전용 카피북 (copybook). 임계값 정리(음수 클램프) 배치
|
||||
* 정리 결과 레코드. Included by vl_thrtrim_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_THRTRIM_BATCH_H
|
||||
#define VL_THRTRIM_BATCH_H
|
||||
|
||||
typedef struct { long clamped; long total_rules; } vl_thrtrim_rec_t;
|
||||
|
||||
#endif /* VL_THRTRIM_BATCH_H */
|
||||
12
app/src/vl/dbio/vl_tristage_batch.h
Normal file
12
app/src/vl/dbio/vl_tristage_batch.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* vl_tristage_batch.h - vl vl_tristage_batch 배치 전용 카피북 (copybook). 매입-정산-지급 3단 대사 배치
|
||||
* 3단 합계/불일치 레코드 + 기본 영업일 상수. Included by vl_tristage_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_TRISTAGE_BATCH_H
|
||||
#define VL_TRISTAGE_BATCH_H
|
||||
|
||||
#define VL_TRISTAGE_DEF_DATE "2026-07-19"
|
||||
|
||||
typedef struct { long p_net; long s_net; long x_amt; long broken; } vl_tristage_rec_t;
|
||||
|
||||
#endif /* VL_TRISTAGE_BATCH_H */
|
||||
12
app/src/vl/dbio/vl_unacq_batch.h
Normal file
12
app/src/vl/dbio/vl_unacq_batch.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* vl_unacq_batch.h - vl vl_unacq_batch 배치 전용 카피북 (copybook). 미매입 승인 검출 배치
|
||||
* 검증로그 check_type 상수 + 검출 결과 레코드. Included by vl_unacq_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_UNACQ_BATCH_H
|
||||
#define VL_UNACQ_BATCH_H
|
||||
|
||||
#define VL_UNACQ_CHECK "VL_UNACQ_BATCH"
|
||||
|
||||
typedef struct { long orphans; long first_id; } vl_unacq_rec_t;
|
||||
|
||||
#endif /* VL_UNACQ_BATCH_H */
|
||||
12
app/src/vl/dbio/vl_wfstat_batch.h
Normal file
12
app/src/vl/dbio/vl_wfstat_batch.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* vl_wfstat_batch.h - vl vl_wfstat_batch 배치 전용 카피북 (copybook). 의심거래 워크플로 상태 통계 배치
|
||||
* 상태별 건수 레코드 + 기본 영업일 상수. Included by vl_wfstat_batch.pgc.
|
||||
*/
|
||||
#ifndef VL_WFSTAT_BATCH_H
|
||||
#define VL_WFSTAT_BATCH_H
|
||||
|
||||
#define VL_WFSTAT_DEF_DATE "2026-07-19"
|
||||
|
||||
typedef struct { long open_c; long conf_c; long closed_c; } vl_wfstat_rec_t;
|
||||
|
||||
#endif /* VL_WFSTAT_BATCH_H */
|
||||
12
app/src/vl/svc/VL_AGEDCONF.h
Normal file
12
app/src/vl/svc/VL_AGEDCONF.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_AGEDCONF.h - vl 서비스 VL_AGEDCONF 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_ARG1, T_ARG2, T_COUNT, T_ARG3, T_RC
|
||||
*/
|
||||
#ifndef VL_AGEDCONF_H
|
||||
#define VL_AGEDCONF_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_AGEDCONF(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_AGEDCONF_H */
|
||||
35
app/src/vl/svc/VL_AGEDCONF.pgc
Normal file
35
app/src/vl/svc/VL_AGEDCONF.pgc
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* VL_AGEDCONF.pgc - vl 모듈 서비스 VL_AGEDCONF (one service = one file).
|
||||
* 기능: 장기 미종결 확인건 검출 (CONFIRMED N일 초과, RC 1=존재; T_ARG2=1이면 severity CRIT 승격).
|
||||
* 경과일 기준은 T_ARG1(기본 14일).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_AGEDCONF.h"
|
||||
|
||||
void VL_AGEDCONF(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0, esc, bumped = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_days, h_cnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_days = getl(b, T_ARG1);
|
||||
if (h_days <= 0) h_days = 14;
|
||||
esc = getl(b, T_ARG2);
|
||||
EXEC SQL SELECT count(*) INTO :h_cnt FROM vl_suspect
|
||||
WHERE status = 'CONFIRMED'
|
||||
AND created_at < now() - (:h_days || ' days')::interval;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 장기 미종결 확인건 존재 */
|
||||
if (rc == 1 && esc == 1) {
|
||||
EXEC SQL UPDATE vl_suspect SET severity = 'CRIT'
|
||||
WHERE status = 'CONFIRMED' AND severity <> 'CRIT'
|
||||
AND created_at < now() - (:h_days || ' days')::interval;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
bumped = (long)sqlca.sqlerrd[2]; /* CRIT 승격 건수 */
|
||||
}
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_ARG3, bumped);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_AGEDOPEN.h
Normal file
12
app/src/vl/svc/VL_AGEDOPEN.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_AGEDOPEN.h - vl 서비스 VL_AGEDOPEN 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_ARG1, T_COUNT, T_ID1, T_RC
|
||||
*/
|
||||
#ifndef VL_AGEDOPEN_H
|
||||
#define VL_AGEDOPEN_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_AGEDOPEN(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_AGEDOPEN_H */
|
||||
28
app/src/vl/svc/VL_AGEDOPEN.pgc
Normal file
28
app/src/vl/svc/VL_AGEDOPEN.pgc
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* VL_AGEDOPEN.pgc - vl 모듈 서비스 VL_AGEDOPEN (one service = one file).
|
||||
* 기능: 장기미결 의심거래 검출 (OPEN 상태로 N일 초과 경과, RC 1=존재).
|
||||
* 경과일 기준은 T_ARG1(기본 7일).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_AGEDOPEN.h"
|
||||
|
||||
void VL_AGEDOPEN(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 created_at < now() - (:h_days || ' days')::interval;
|
||||
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_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_APPRAGG.h
Normal file
12
app/src/vl/svc/VL_APPRAGG.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_APPRAGG.h - vl 서비스 VL_APPRAGG 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE, T_GROSS, T_AMT1, T_DELTA, T_RC
|
||||
*/
|
||||
#ifndef VL_APPRAGG_H
|
||||
#define VL_APPRAGG_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_APPRAGG(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_APPRAGG_H */
|
||||
33
app/src/vl/svc/VL_APPRAGG.pgc
Normal file
33
app/src/vl/svc/VL_APPRAGG.pgc
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* VL_APPRAGG.pgc - vl 모듈 서비스 VL_APPRAGG (one service = one file).
|
||||
* 기능: 일자별 매입-승인 금액 대사 (승인보유 매입금액 vs 전체 매입금액, RC 1=미승인 금액 존재).
|
||||
* 취소(C) 제외 매입 총액과 가결 승인이 붙은 매입 총액의 차이를 계산한다.
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_APPRAGG.h"
|
||||
|
||||
void VL_APPRAGG(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_all, h_appr;
|
||||
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_all FROM purchase
|
||||
WHERE biz_date = :h_bizdate AND status <> 'C';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL SELECT coalesce(sum(p.amount),0) INTO :h_appr FROM purchase p
|
||||
WHERE p.biz_date = :h_bizdate AND p.status <> 'C'
|
||||
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_all != h_appr) rc = 1; /* 미승인 매입금액 존재 */
|
||||
setl(b, T_GROSS, h_all);
|
||||
setl(b, T_AMT1, h_appr);
|
||||
setl(b, T_DELTA, h_all - h_appr);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_APPRAMT.h
Normal file
12
app/src/vl/svc/VL_APPRAMT.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_APPRAMT.h - vl 서비스 VL_APPRAMT 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_PURCHASE_ID, T_AMOUNT, T_COUNT, T_ARG1, T_RC
|
||||
*/
|
||||
#ifndef VL_APPRAMT_H
|
||||
#define VL_APPRAMT_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_APPRAMT(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_APPRAMT_H */
|
||||
30
app/src/vl/svc/VL_APPRAMT.pgc
Normal file
30
app/src/vl/svc/VL_APPRAMT.pgc
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* VL_APPRAMT.pgc - vl 모듈 서비스 VL_APPRAMT (one service = one file).
|
||||
* 기능: 건별 매입-승인 금액/존재 정합 검증 (RC 1=승인없음, 2=거절승인만 존재, 3=매입없음).
|
||||
* 매입 1건에 대해 승인 레코드 존재와 승인가결 건수를 대조한다.
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_APPRAMT.h"
|
||||
|
||||
void VL_APPRAMT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_amt, h_tot, h_ok;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_pid = getl(b, T_PURCHASE_ID);
|
||||
EXEC SQL SELECT amount INTO :h_amt FROM purchase WHERE purchase_id = :h_pid;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 3); OK(b); } /* 3=매입 없음 */
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL SELECT count(*), coalesce(sum(CASE WHEN approved THEN 1 ELSE 0 END),0)
|
||||
INTO :h_tot, :h_ok FROM approval WHERE purchase_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_tot == 0) rc = 1; /* 승인 레코드 자체가 없음 */
|
||||
else if (h_ok == 0) rc = 2; /* 거절 승인만 존재 */
|
||||
setl(b, T_AMOUNT, h_amt);
|
||||
setl(b, T_COUNT, h_tot);
|
||||
setl(b, T_ARG1, h_ok);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_CANCELMIS.h
Normal file
12
app/src/vl/svc/VL_CANCELMIS.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_CANCELMIS.h - vl 서비스 VL_CANCELMIS 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_PURCHASE_ID, T_AMOUNT, T_AMT1, T_COUNT, T_STATUS, T_RC
|
||||
*/
|
||||
#ifndef VL_CANCELMIS_H
|
||||
#define VL_CANCELMIS_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_CANCELMIS(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_CANCELMIS_H */
|
||||
33
app/src/vl/svc/VL_CANCELMIS.pgc
Normal file
33
app/src/vl/svc/VL_CANCELMIS.pgc
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* VL_CANCELMIS.pgc - vl 모듈 서비스 VL_CANCELMIS (one service = one file).
|
||||
* 기능: 취소 정합 검증 (RC 비트합 1=취소합>매입금액, 2=취소 존재하나 매입상태 미반영, 3=매입없음).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_CANCELMIS.h"
|
||||
|
||||
void VL_CANCELMIS(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_amt, h_csum, h_ccnt;
|
||||
char h_st[8];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_pid = getl(b, T_PURCHASE_ID);
|
||||
EXEC SQL SELECT amount, status INTO :h_amt, :h_st FROM purchase
|
||||
WHERE purchase_id = :h_pid;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 3); OK(b); } /* 3=매입 없음 */
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL SELECT coalesce(sum(amount),0), count(*) INTO :h_csum, :h_ccnt
|
||||
FROM ac_cancel WHERE purchase_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_csum > h_amt) rc |= 1; /* 과다 취소 */
|
||||
if (h_ccnt > 0 && strcmp(h_st, "C") != 0 && strcmp(h_st, "V") != 0)
|
||||
rc |= 2; /* 취소 반영 안 된 매입상태 */
|
||||
setl(b, T_AMOUNT, h_amt);
|
||||
setl(b, T_AMT1, h_csum);
|
||||
setl(b, T_COUNT, h_ccnt);
|
||||
Bchg(b, T_STATUS, 0, h_st, 0L);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_DATEREV.h
Normal file
12
app/src/vl/svc/VL_DATEREV.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_DATEREV.h - vl 서비스 VL_DATEREV 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_PURCHASE_ID, T_COUNT, T_RC
|
||||
*/
|
||||
#ifndef VL_DATEREV_H
|
||||
#define VL_DATEREV_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_DATEREV(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_DATEREV_H */
|
||||
27
app/src/vl/svc/VL_DATEREV.pgc
Normal file
27
app/src/vl/svc/VL_DATEREV.pgc
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* VL_DATEREV.pgc - vl 모듈 서비스 VL_DATEREV (one service = one file).
|
||||
* 기능: 건별 정산 일자 역전 검출 (settlement.biz_date < purchase.biz_date → RC 1, 3=매입없음).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_DATEREV.h"
|
||||
|
||||
void VL_DATEREV(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_exists, h_rev;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_pid = getl(b, T_PURCHASE_ID);
|
||||
EXEC SQL SELECT count(*) INTO :h_exists FROM purchase WHERE purchase_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_exists == 0) { setl(b, T_RC, 3); OK(b); } /* 3=매입 없음 */
|
||||
EXEC SQL SELECT count(*) INTO :h_rev
|
||||
FROM settlement s JOIN purchase p ON p.purchase_id = s.purchase_id
|
||||
WHERE p.purchase_id = :h_pid AND s.biz_date < p.biz_date;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_rev > 0) rc = 1; /* 정산일이 매입일보다 과거 */
|
||||
setl(b, T_COUNT, h_rev);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_DAYLIMIT.h
Normal file
12
app/src/vl/svc/VL_DAYLIMIT.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_DAYLIMIT.h - vl 서비스 VL_DAYLIMIT 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_BIZDATE, T_AMT1, T_GROSS, T_DELTA, T_RC
|
||||
*/
|
||||
#ifndef VL_DAYLIMIT_H
|
||||
#define VL_DAYLIMIT_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_DAYLIMIT(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_DAYLIMIT_H */
|
||||
33
app/src/vl/svc/VL_DAYLIMIT.pgc
Normal file
33
app/src/vl/svc/VL_DAYLIMIT.pgc
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* VL_DAYLIMIT.pgc - vl 모듈 서비스 VL_DAYLIMIT (one service = one file).
|
||||
* 기능: 가맹점 일한도 위반 검증 (일자 매입합 > daily_limit → RC 1, 3=가맹점 없음).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_DAYLIMIT.h"
|
||||
|
||||
void VL_DAYLIMIT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_bizdate[16];
|
||||
long h_lim, h_used;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_MERCHANT, h_merch, sizeof(h_merch));
|
||||
if (h_merch[0] == 0) { userlog("VL_DAYLIMIT: 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 daily_limit INTO :h_lim FROM merchant
|
||||
WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 3); OK(b); } /* 3=가맹점 없음 */
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL SELECT coalesce(sum(amount),0) INTO :h_used FROM purchase
|
||||
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate AND status <> 'C';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_used > h_lim) rc = 1; /* 일한도 초과 */
|
||||
setl(b, T_AMT1, h_lim);
|
||||
setl(b, T_GROSS, h_used);
|
||||
setl(b, T_DELTA, h_lim - h_used);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_DUPPAY.h
Normal file
12
app/src/vl/svc/VL_DUPPAY.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_DUPPAY.h - vl 서비스 VL_DUPPAY 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_PURCHASE_ID, T_BIZDATE, T_COUNT, T_GROSS, T_RC
|
||||
*/
|
||||
#ifndef VL_DUPPAY_H
|
||||
#define VL_DUPPAY_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_DUPPAY(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_DUPPAY_H */
|
||||
31
app/src/vl/svc/VL_DUPPAY.pgc
Normal file
31
app/src/vl/svc/VL_DUPPAY.pgc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* VL_DUPPAY.pgc - vl 모듈 서비스 VL_DUPPAY (one service = one file).
|
||||
* 기능: 건별 중복지급 검출 (ledger XFER 엔트리 2건 이상 → RC 1, 검증로그 기록).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_DUPPAY.h"
|
||||
|
||||
void VL_DUPPAY(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
char bizdate[16];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_cnt, h_amt;
|
||||
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(*), coalesce(sum(amount),0) INTO :h_cnt, :h_amt
|
||||
FROM ledger WHERE purchase_id = :h_pid AND entry_type = 'XFER';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 1) {
|
||||
rc = 1; /* 동일 매입 다중 지급 */
|
||||
if (vldb_insert_check_log("VL_DUPPAY", h_pid, rc, "중복지급 검출", bizdate) < 0)
|
||||
FAIL(b);
|
||||
}
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_GROSS, h_amt);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_DUPPAYDAY.h
Normal file
12
app/src/vl/svc/VL_DUPPAYDAY.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_DUPPAYDAY.h - vl 서비스 VL_DUPPAYDAY 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE, T_COUNT, T_ARG2, T_RC
|
||||
*/
|
||||
#ifndef VL_DUPPAYDAY_H
|
||||
#define VL_DUPPAYDAY_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_DUPPAYDAY(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_DUPPAYDAY_H */
|
||||
28
app/src/vl/svc/VL_DUPPAYDAY.pgc
Normal file
28
app/src/vl/svc/VL_DUPPAYDAY.pgc
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* VL_DUPPAYDAY.pgc - vl 모듈 서비스 VL_DUPPAYDAY (one service = one file).
|
||||
* 기능: 일자별 중복지급 그룹 집계 (XFER 2건 이상 매입 그룹수/초과건수, RC 1=중복지급 존재).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_DUPPAYDAY.h"
|
||||
|
||||
void VL_DUPPAYDAY(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_grp, h_extra;
|
||||
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(sum(c - 1),0) INTO :h_grp, :h_extra
|
||||
FROM (SELECT count(*) AS c FROM ledger
|
||||
WHERE biz_date = :h_bizdate AND entry_type = 'XFER'
|
||||
GROUP BY purchase_id HAVING count(*) > 1) t;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_grp > 0) rc = 1; /* 중복지급 매입 존재 */
|
||||
setl(b, T_COUNT, h_grp);
|
||||
setl(b, T_ARG2, h_extra); /* 초과 지급 건수 */
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_DUPSETTLE.h
Normal file
12
app/src/vl/svc/VL_DUPSETTLE.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_DUPSETTLE.h - vl 서비스 VL_DUPSETTLE 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_PURCHASE_ID, T_COUNT, T_NET, T_ID1, T_ID2, T_RC
|
||||
*/
|
||||
#ifndef VL_DUPSETTLE_H
|
||||
#define VL_DUPSETTLE_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_DUPSETTLE(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_DUPSETTLE_H */
|
||||
28
app/src/vl/svc/VL_DUPSETTLE.pgc
Normal file
28
app/src/vl/svc/VL_DUPSETTLE.pgc
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* VL_DUPSETTLE.pgc - vl 모듈 서비스 VL_DUPSETTLE (one service = one file).
|
||||
* 기능: 건별 중복 정산 검출 (동일 매입에 정산 2건 이상 → RC 1, 최초/최종 정산 ID 반환).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_DUPSETTLE.h"
|
||||
|
||||
void VL_DUPSETTLE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_cnt, h_net, h_min, h_max;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_pid = getl(b, T_PURCHASE_ID);
|
||||
EXEC SQL SELECT count(*), coalesce(sum(net),0),
|
||||
coalesce(min(settlement_id),0), coalesce(max(settlement_id),0)
|
||||
INTO :h_cnt, :h_net, :h_min, :h_max
|
||||
FROM settlement WHERE purchase_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 1) rc = 1; /* 중복 정산 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_NET, h_net);
|
||||
setl(b, T_ID1, h_min);
|
||||
setl(b, T_ID2, h_max);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_FEEADJNET.h
Normal file
12
app/src/vl/svc/VL_FEEADJNET.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_FEEADJNET.h - vl 서비스 VL_FEEADJNET 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_PURCHASE_ID, T_FEE, T_DELTA, T_COUNT, T_RC
|
||||
*/
|
||||
#ifndef VL_FEEADJNET_H
|
||||
#define VL_FEEADJNET_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_FEEADJNET(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_FEEADJNET_H */
|
||||
31
app/src/vl/svc/VL_FEEADJNET.pgc
Normal file
31
app/src/vl/svc/VL_FEEADJNET.pgc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* VL_FEEADJNET.pgc - vl 모듈 서비스 VL_FEEADJNET (one service = one file).
|
||||
* 기능: 수수료 조정 반영 검증 (fee+sum(ac_fee_adj.delta) 유효범위 점검, RC 1=음수 수수료 2=금액 초과 3=매입없음).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_FEEADJNET.h"
|
||||
|
||||
void VL_FEEADJNET(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0, eff;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_amt, h_fee, h_adj, h_acnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_pid = getl(b, T_PURCHASE_ID);
|
||||
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, 3); OK(b); } /* 3=매입 없음 */
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL SELECT coalesce(sum(delta),0), count(*) INTO :h_adj, :h_acnt
|
||||
FROM ac_fee_adj WHERE purchase_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
eff = h_fee + h_adj;
|
||||
if (eff < 0) rc = 1; /* 조정 후 수수료 음수 */
|
||||
else if (eff > h_amt) rc = 2; /* 조정 후 수수료가 매입금액 초과 */
|
||||
setl(b, T_FEE, eff);
|
||||
setl(b, T_DELTA, h_adj);
|
||||
setl(b, T_COUNT, h_acnt);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_FEERECALC.h
Normal file
12
app/src/vl/svc/VL_FEERECALC.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_FEERECALC.h - vl 서비스 VL_FEERECALC 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_PURCHASE_ID, T_ARG1, T_FEE, T_AMT1, T_DELTA, T_RC
|
||||
*/
|
||||
#ifndef VL_FEERECALC_H
|
||||
#define VL_FEERECALC_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_FEERECALC(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_FEERECALC_H */
|
||||
33
app/src/vl/svc/VL_FEERECALC.pgc
Normal file
33
app/src/vl/svc/VL_FEERECALC.pgc
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* VL_FEERECALC.pgc - vl 모듈 서비스 VL_FEERECALC (one service = one file).
|
||||
* 기능: 수수료 재계산 검증 (가맹점 요율 mdr_bps로 기대수수료 재산출, |fee-기대|>허용오차 → RC 1, 3=매입/가맹점 없음).
|
||||
* 허용오차는 T_ARG1(기본 10원).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_FEERECALC.h"
|
||||
|
||||
void VL_FEERECALC(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0, tol, expfee, d;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_amt, h_fee, h_bps;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_pid = getl(b, T_PURCHASE_ID);
|
||||
tol = getl(b, T_ARG1);
|
||||
if (tol <= 0) tol = 10;
|
||||
EXEC SQL SELECT p.amount, p.fee, m.mdr_bps INTO :h_amt, :h_fee, :h_bps
|
||||
FROM purchase p JOIN merchant m ON m.merchant_id = p.merchant_id
|
||||
WHERE p.purchase_id = :h_pid;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 3); OK(b); } /* 3=매입/가맹점 없음 */
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
expfee = h_amt * h_bps / 10000;
|
||||
d = h_fee - expfee;
|
||||
if (d < 0) d = -d;
|
||||
if (d > tol) rc = 1; /* 재계산 편차 초과 */
|
||||
setl(b, T_FEE, h_fee);
|
||||
setl(b, T_AMT1, expfee);
|
||||
setl(b, T_DELTA, h_fee - expfee);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_FXCHK.h
Normal file
12
app/src/vl/svc/VL_FXCHK.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_FXCHK.h - vl 서비스 VL_FXCHK 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_PURCHASE_ID, T_ARG1, T_FX_AMT, T_AMT1, T_DELTA, T_RC
|
||||
*/
|
||||
#ifndef VL_FXCHK_H
|
||||
#define VL_FXCHK_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_FXCHK(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_FXCHK_H */
|
||||
33
app/src/vl/svc/VL_FXCHK.pgc
Normal file
33
app/src/vl/svc/VL_FXCHK.pgc
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* VL_FXCHK.pgc - vl 모듈 서비스 VL_FXCHK (one service = one file).
|
||||
* 기능: 해외 매입 환산 정합 검증 (krw vs fx*rate_bps/10000, 오차>T_ARG1 → RC 1, 2=해외 내역 없음).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_FXCHK.h"
|
||||
|
||||
void VL_FXCHK(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0, tol, expkrw, d;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_cnt, h_fx, h_krw, h_rate;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_pid = getl(b, T_PURCHASE_ID);
|
||||
tol = getl(b, T_ARG1);
|
||||
if (tol <= 0) tol = 100; /* 환산 반올림 허용오차 */
|
||||
EXEC SQL SELECT count(*), coalesce(sum(fx_amount),0),
|
||||
coalesce(sum(krw_amount),0), coalesce(max(rate_bps),0)
|
||||
INTO :h_cnt, :h_fx, :h_krw, :h_rate
|
||||
FROM ac_fx WHERE purchase_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt == 0) { setl(b, T_RC, 2); OK(b); } /* 해외 매입 아님 */
|
||||
expkrw = h_fx * h_rate / 10000;
|
||||
d = h_krw - expkrw;
|
||||
if (d < 0) d = -d;
|
||||
if (d > tol) rc = 1; /* 환산 금액 불일치 */
|
||||
setl(b, T_FX_AMT, h_fx);
|
||||
setl(b, T_AMT1, expkrw);
|
||||
setl(b, T_DELTA, h_krw - expkrw);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_INSTCHK.h
Normal file
12
app/src/vl/svc/VL_INSTCHK.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_INSTCHK.h - vl 서비스 VL_INSTCHK 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_PURCHASE_ID, T_ARG1, T_AMT1, T_INSTALL_N, T_COUNT, T_DELTA, T_RC
|
||||
*/
|
||||
#ifndef VL_INSTCHK_H
|
||||
#define VL_INSTCHK_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_INSTCHK(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_INSTCHK_H */
|
||||
37
app/src/vl/svc/VL_INSTCHK.pgc
Normal file
37
app/src/vl/svc/VL_INSTCHK.pgc
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* VL_INSTCHK.pgc - vl 모듈 서비스 VL_INSTCHK (one service = one file).
|
||||
* 기능: 할부 정합 검증 (sum(월부금) vs 매입금액, 오차>T_ARG1 → RC 1, 2=할부 없음 3=매입없음).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_INSTCHK.h"
|
||||
|
||||
void VL_INSTCHK(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0, tol, d;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_amt, h_isum, h_icnt, h_months;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_pid = getl(b, T_PURCHASE_ID);
|
||||
tol = getl(b, T_ARG1);
|
||||
if (tol < 0) tol = 0; /* 기본: 원단위 완전일치 */
|
||||
EXEC SQL SELECT amount INTO :h_amt FROM purchase WHERE purchase_id = :h_pid;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 3); OK(b); } /* 3=매입 없음 */
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL SELECT coalesce(sum(month_amount),0), count(*), coalesce(max(months),0)
|
||||
INTO :h_isum, :h_icnt, :h_months
|
||||
FROM ac_install WHERE purchase_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_icnt == 0) rc = 2; /* 할부 내역 없음 */
|
||||
else {
|
||||
d = h_isum - h_amt;
|
||||
if (d < 0) d = -d;
|
||||
if (d > tol) rc = 1; /* 할부합-매입금액 오차 초과 */
|
||||
}
|
||||
setl(b, T_AMT1, h_isum);
|
||||
setl(b, T_INSTALL_N, h_months);
|
||||
setl(b, T_COUNT, h_icnt);
|
||||
setl(b, T_DELTA, h_isum - h_amt);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_LEDGBAL.h
Normal file
12
app/src/vl/svc/VL_LEDGBAL.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_LEDGBAL.h - vl 서비스 VL_LEDGBAL 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE, T_AMT1, T_AMT2, T_COUNT, T_DELTA, T_RC
|
||||
*/
|
||||
#ifndef VL_LEDGBAL_H
|
||||
#define VL_LEDGBAL_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_LEDGBAL(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_LEDGBAL_H */
|
||||
33
app/src/vl/svc/VL_LEDGBAL.pgc
Normal file
33
app/src/vl/svc/VL_LEDGBAL.pgc
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* VL_LEDGBAL.pgc - vl 모듈 서비스 VL_LEDGBAL (one service = one file).
|
||||
* 기능: 일자별 원장 대차 정합 검증 (차변 RECON 합 vs 대변 SETTLE+XFER 합, RC 1=대차 불일치).
|
||||
* 한 SELECT의 CASE 집계로 차/대변을 동시에 산출한다.
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_LEDGBAL.h"
|
||||
|
||||
void VL_LEDGBAL(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_dr, h_cr, 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
|
||||
coalesce(sum(CASE WHEN entry_type = 'RECON' THEN amount ELSE 0 END),0),
|
||||
coalesce(sum(CASE WHEN entry_type IN ('SETTLE','XFER') THEN amount ELSE 0 END),0),
|
||||
count(*)
|
||||
INTO :h_dr, :h_cr, :h_cnt
|
||||
FROM ledger WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_dr != h_cr) rc = 1; /* 대차 불일치 */
|
||||
setl(b, T_AMT1, h_dr);
|
||||
setl(b, T_AMT2, h_cr);
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_DELTA, h_dr - h_cr);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_LEDGDATE.h
Normal file
12
app/src/vl/svc/VL_LEDGDATE.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_LEDGDATE.h - vl 서비스 VL_LEDGDATE 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_PURCHASE_ID, T_COUNT, T_ID1, T_RC
|
||||
*/
|
||||
#ifndef VL_LEDGDATE_H
|
||||
#define VL_LEDGDATE_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_LEDGDATE(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_LEDGDATE_H */
|
||||
25
app/src/vl/svc/VL_LEDGDATE.pgc
Normal file
25
app/src/vl/svc/VL_LEDGDATE.pgc
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* VL_LEDGDATE.pgc - vl 모듈 서비스 VL_LEDGDATE (one service = one file).
|
||||
* 기능: 건별 원장 일자 역전 검출 (ledger.biz_date < purchase.biz_date 엔트리 수, RC 1=역전 존재).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_LEDGDATE.h"
|
||||
|
||||
void VL_LEDGDATE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_rev, h_first;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_pid = getl(b, T_PURCHASE_ID);
|
||||
EXEC SQL SELECT count(*), coalesce(min(l.ledger_id),0) INTO :h_rev, :h_first
|
||||
FROM ledger l JOIN purchase p ON p.purchase_id = l.purchase_id
|
||||
WHERE p.purchase_id = :h_pid AND l.biz_date < p.biz_date;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_rev > 0) rc = 1; /* 원장 기표일 역전 */
|
||||
setl(b, T_COUNT, h_rev);
|
||||
setl(b, T_ID1, h_first);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_LEDGENTRY.h
Normal file
12
app/src/vl/svc/VL_LEDGENTRY.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_LEDGENTRY.h - vl 서비스 VL_LEDGENTRY 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_PURCHASE_ID, T_AMOUNT, T_AMT1, T_COUNT, T_RC
|
||||
*/
|
||||
#ifndef VL_LEDGENTRY_H
|
||||
#define VL_LEDGENTRY_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_LEDGENTRY(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_LEDGENTRY_H */
|
||||
29
app/src/vl/svc/VL_LEDGENTRY.pgc
Normal file
29
app/src/vl/svc/VL_LEDGENTRY.pgc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* VL_LEDGENTRY.pgc - vl 모듈 서비스 VL_LEDGENTRY (one service = one file).
|
||||
* 기능: 건별 원장 대사 엔트리 검증 (purchase.amount vs ledger RECON 합, RC 1=금액불일치 2=원장없음 3=매입없음).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_LEDGENTRY.h"
|
||||
|
||||
void VL_LEDGENTRY(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_amt, h_lcnt, h_lamt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_pid = getl(b, T_PURCHASE_ID);
|
||||
EXEC SQL SELECT amount INTO :h_amt FROM purchase WHERE purchase_id = :h_pid;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 3); OK(b); } /* 3=매입 없음 */
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL SELECT count(*), coalesce(sum(amount),0) INTO :h_lcnt, :h_lamt
|
||||
FROM ledger WHERE purchase_id = :h_pid AND entry_type = 'RECON';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_lcnt == 0) rc = 2; /* RECON 원장 미기표 */
|
||||
else if (h_lamt != h_amt) rc = 1; /* 기표 금액 불일치 */
|
||||
setl(b, T_AMOUNT, h_amt);
|
||||
setl(b, T_AMT1, h_lamt);
|
||||
setl(b, T_COUNT, h_lcnt);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_LIMITNEAR.h
Normal file
12
app/src/vl/svc/VL_LIMITNEAR.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_LIMITNEAR.h - vl 서비스 VL_LIMITNEAR 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_BIZDATE, T_ARG1, T_AMT1, T_GROSS, T_ARG2, T_RC
|
||||
*/
|
||||
#ifndef VL_LIMITNEAR_H
|
||||
#define VL_LIMITNEAR_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_LIMITNEAR(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_LIMITNEAR_H */
|
||||
40
app/src/vl/svc/VL_LIMITNEAR.pgc
Normal file
40
app/src/vl/svc/VL_LIMITNEAR.pgc
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* VL_LIMITNEAR.pgc - vl 모듈 서비스 VL_LIMITNEAR (one service = one file).
|
||||
* 기능: 가맹점 일한도 임박 검출 (사용률>=T_ARG1% → RC 1, 초과 → RC 2, 3=가맹점 없음).
|
||||
* 임박 기준 사용률은 T_ARG1(기본 90%).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_LIMITNEAR.h"
|
||||
|
||||
void VL_LIMITNEAR(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0, thr, pct = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_bizdate[16];
|
||||
long h_lim, h_used;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
thr = getl(b, T_ARG1);
|
||||
if (thr <= 0 || thr > 100) thr = 90;
|
||||
gets_(b, T_MERCHANT, h_merch, sizeof(h_merch));
|
||||
if (h_merch[0] == 0) { userlog("VL_LIMITNEAR: 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 m.daily_limit, coalesce(sum(p.amount),0)
|
||||
INTO :h_lim, :h_used
|
||||
FROM merchant m LEFT JOIN purchase p
|
||||
ON p.merchant_id = m.merchant_id
|
||||
AND p.biz_date = :h_bizdate AND p.status <> 'C'
|
||||
WHERE m.merchant_id = :h_merch
|
||||
GROUP BY m.daily_limit;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 3); OK(b); } /* 3=가맹점 없음 */
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_lim > 0) pct = h_used * 100 / h_lim;
|
||||
if (h_used > h_lim) rc = 2; /* 이미 한도 초과 */
|
||||
else if (pct >= thr) rc = 1; /* 한도 임박 */
|
||||
setl(b, T_AMT1, h_lim);
|
||||
setl(b, T_GROSS, h_used);
|
||||
setl(b, T_ARG2, pct);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_MDRRATE.h
Normal file
12
app/src/vl/svc/VL_MDRRATE.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_MDRRATE.h - vl 서비스 VL_MDRRATE 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_COUNT, T_ARG1, T_STR1, T_RC
|
||||
*/
|
||||
#ifndef VL_MDRRATE_H
|
||||
#define VL_MDRRATE_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_MDRRATE(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_MDRRATE_H */
|
||||
29
app/src/vl/svc/VL_MDRRATE.pgc
Normal file
29
app/src/vl/svc/VL_MDRRATE.pgc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* VL_MDRRATE.pgc - vl 모듈 서비스 VL_MDRRATE (one service = one file).
|
||||
* 기능: 가맹점 요율 위반 검출 (mdr_bps<0 또는 규칙 MDR_MAX 초과, RC 1=위반 존재).
|
||||
* 상한은 vl_rule MDR_MAX(없으면 1000bps).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_MDRRATE.h"
|
||||
|
||||
void VL_MDRRATE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
char sev[8];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_max, h_cnt;
|
||||
char h_first[64];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_max = 0;
|
||||
if (vldb_get_rule("MDR_MAX", &h_max, sev) < 0 || h_max <= 0) h_max = 1000;
|
||||
EXEC SQL SELECT count(*), coalesce(min(merchant_id),'') INTO :h_cnt, :h_first
|
||||
FROM merchant WHERE mdr_bps < 0 OR mdr_bps > :h_max;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 요율 위반 가맹점 존재 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_ARG1, h_max);
|
||||
Bchg(b, T_STR1, 0, h_first, 0L);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_NEGBAL.h
Normal file
12
app/src/vl/svc/VL_NEGBAL.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_NEGBAL.h - vl 서비스 VL_NEGBAL 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE, T_COUNT, T_AMT1, T_STR1, T_RC
|
||||
*/
|
||||
#ifndef VL_NEGBAL_H
|
||||
#define VL_NEGBAL_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_NEGBAL(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_NEGBAL_H */
|
||||
29
app/src/vl/svc/VL_NEGBAL.pgc
Normal file
29
app/src/vl/svc/VL_NEGBAL.pgc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* VL_NEGBAL.pgc - vl 모듈 서비스 VL_NEGBAL (one service = one file).
|
||||
* 기능: 마이너스 잔액 가맹점 검출 (merchant_summary.net_amount<0, RC 1=존재; 최악치 반환).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_NEGBAL.h"
|
||||
|
||||
void VL_NEGBAL(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16], h_worst_m[64];
|
||||
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_amount),0), coalesce(min(merchant_id),'')
|
||||
INTO :h_cnt, :h_worst, :h_worst_m
|
||||
FROM merchant_summary
|
||||
WHERE biz_date = :h_bizdate AND net_amount < 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);
|
||||
Bchg(b, T_STR1, 0, h_worst_m, 0L);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_NEGNET.h
Normal file
12
app/src/vl/svc/VL_NEGNET.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_NEGNET.h - vl 서비스 VL_NEGNET 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE, T_COUNT, T_ARG1, T_ARG2, T_RC
|
||||
*/
|
||||
#ifndef VL_NEGNET_H
|
||||
#define VL_NEGNET_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_NEGNET(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_NEGNET_H */
|
||||
31
app/src/vl/svc/VL_NEGNET.pgc
Normal file
31
app/src/vl/svc/VL_NEGNET.pgc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* VL_NEGNET.pgc - vl 모듈 서비스 VL_NEGNET (one service = one file).
|
||||
* 기능: 일자별 음수 순액/역전 수수료 매입 검출 (net<0, fee<0, fee>amount, RC 1=존재).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_NEGNET.h"
|
||||
|
||||
void VL_NEGNET(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_cnt, h_neg, h_over;
|
||||
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(sum(CASE WHEN net < 0 THEN 1 ELSE 0 END),0),
|
||||
coalesce(sum(CASE WHEN fee > amount THEN 1 ELSE 0 END),0)
|
||||
INTO :h_cnt, :h_neg, :h_over
|
||||
FROM purchase
|
||||
WHERE biz_date = :h_bizdate AND (net < 0 OR fee < 0 OR fee > amount);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 음수/역전 건 존재 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_ARG1, h_neg); /* 음수 순액 건수 */
|
||||
setl(b, T_ARG2, h_over); /* 수수료>금액 건수 */
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RATEDEV.h
Normal file
12
app/src/vl/svc/VL_RATEDEV.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RATEDEV.h - vl 서비스 VL_RATEDEV 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_PURCHASE_ID, T_ARG1, T_ARG2, T_ARG3, T_DELTA, T_RC
|
||||
*/
|
||||
#ifndef VL_RATEDEV_H
|
||||
#define VL_RATEDEV_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RATEDEV(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RATEDEV_H */
|
||||
33
app/src/vl/svc/VL_RATEDEV.pgc
Normal file
33
app/src/vl/svc/VL_RATEDEV.pgc
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* VL_RATEDEV.pgc - vl 모듈 서비스 VL_RATEDEV (one service = one file).
|
||||
* 기능: 건별 실적용 요율 편차 검출 (fee*10000/amount vs mdr_bps, 편차>T_ARG1 → RC 1, 2=금액 0 이하, 3=매입없음).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RATEDEV.h"
|
||||
|
||||
void VL_RATEDEV(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0, tol, actual, dev;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_amt, h_fee, h_bps;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_pid = getl(b, T_PURCHASE_ID);
|
||||
tol = getl(b, T_ARG1);
|
||||
if (tol <= 0) tol = 5; /* 기본 허용편차 5bps */
|
||||
EXEC SQL SELECT p.amount, p.fee, m.mdr_bps INTO :h_amt, :h_fee, :h_bps
|
||||
FROM purchase p JOIN merchant m ON m.merchant_id = p.merchant_id
|
||||
WHERE p.purchase_id = :h_pid;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 3); OK(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_amt <= 0) { setl(b, T_RC, 2); OK(b); } /* 요율 산출 불가 */
|
||||
actual = h_fee * 10000 / h_amt;
|
||||
dev = actual - h_bps;
|
||||
if (dev < 0) dev = -dev;
|
||||
if (dev > tol) rc = 1; /* 요율 편차 초과 */
|
||||
setl(b, T_ARG2, actual);
|
||||
setl(b, T_ARG3, h_bps);
|
||||
setl(b, T_DELTA, dev);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RILEDGER.h
Normal file
12
app/src/vl/svc/VL_RILEDGER.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RILEDGER.h - vl 서비스 VL_RILEDGER 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE, T_ARG1, T_ARG2, T_ARG3, T_COUNT, T_RC
|
||||
*/
|
||||
#ifndef VL_RILEDGER_H
|
||||
#define VL_RILEDGER_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RILEDGER(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RILEDGER_H */
|
||||
37
app/src/vl/svc/VL_RILEDGER.pgc
Normal file
37
app/src/vl/svc/VL_RILEDGER.pgc
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* VL_RILEDGER.pgc - vl 모듈 서비스 VL_RILEDGER (one service = one file).
|
||||
* 기능: 참조무결성 세분 검증 - 원장→매입 고아 엔트리 (RC 비트합 1=RECON 2=SETTLE 4=XFER 고아).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RILEDGER.h"
|
||||
|
||||
void VL_RILEDGER(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 l.entry_type = 'RECON' THEN 1 ELSE 0 END),0),
|
||||
coalesce(sum(CASE WHEN l.entry_type = 'SETTLE' THEN 1 ELSE 0 END),0),
|
||||
coalesce(sum(CASE WHEN l.entry_type = 'XFER' THEN 1 ELSE 0 END),0)
|
||||
INTO :h_recon, :h_settle, :h_xfer
|
||||
FROM ledger l
|
||||
WHERE l.biz_date = :h_bizdate
|
||||
AND NOT EXISTS (SELECT 1 FROM purchase p
|
||||
WHERE p.purchase_id = l.purchase_id);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_recon > 0) rc |= 1; /* RECON 고아 */
|
||||
if (h_settle > 0) rc |= 2; /* SETTLE 고아 */
|
||||
if (h_xfer > 0) rc |= 4; /* XFER 고아 */
|
||||
setl(b, T_ARG1, h_recon);
|
||||
setl(b, T_ARG2, h_settle);
|
||||
setl(b, T_ARG3, h_xfer);
|
||||
setl(b, T_COUNT, h_recon + h_settle + h_xfer);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RIMERCH.h
Normal file
12
app/src/vl/svc/VL_RIMERCH.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RIMERCH.h - vl 서비스 VL_RIMERCH 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE, T_COUNT, T_ID1, T_RC
|
||||
*/
|
||||
#ifndef VL_RIMERCH_H
|
||||
#define VL_RIMERCH_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RIMERCH(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RIMERCH_H */
|
||||
29
app/src/vl/svc/VL_RIMERCH.pgc
Normal file
29
app/src/vl/svc/VL_RIMERCH.pgc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* VL_RIMERCH.pgc - vl 모듈 서비스 VL_RIMERCH (one service = one file).
|
||||
* 기능: 참조무결성 세분 검증 - 매입→가맹점 (일자별 고아 매입 수, RC 1=고아 존재).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RIMERCH.h"
|
||||
|
||||
void VL_RIMERCH(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 NOT EXISTS (SELECT 1 FROM merchant m
|
||||
WHERE m.merchant_id = p.merchant_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_RIPURCH.h
Normal file
12
app/src/vl/svc/VL_RIPURCH.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RIPURCH.h - vl 서비스 VL_RIPURCH 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE, T_COUNT, T_ID1, T_NET, T_RC
|
||||
*/
|
||||
#ifndef VL_RIPURCH_H
|
||||
#define VL_RIPURCH_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RIPURCH(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RIPURCH_H */
|
||||
31
app/src/vl/svc/VL_RIPURCH.pgc
Normal file
31
app/src/vl/svc/VL_RIPURCH.pgc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* VL_RIPURCH.pgc - vl 모듈 서비스 VL_RIPURCH (one service = one file).
|
||||
* 기능: 참조무결성 세분 검증 - 정산→매입 (일자별 고아 정산 수/금액, RC 1=고아 존재).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RIPURCH.h"
|
||||
|
||||
void VL_RIPURCH(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_cnt, h_first, h_net;
|
||||
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(s.settlement_id),0), coalesce(sum(s.net),0)
|
||||
INTO :h_cnt, :h_first, :h_net
|
||||
FROM settlement s
|
||||
WHERE s.biz_date = :h_bizdate
|
||||
AND NOT EXISTS (SELECT 1 FROM purchase p
|
||||
WHERE p.purchase_id = s.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_NET, h_net); /* 고아 정산 금액 합 */
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RISETTLE.h
Normal file
12
app/src/vl/svc/VL_RISETTLE.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RISETTLE.h - vl 서비스 VL_RISETTLE 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE, T_COUNT, T_PURCHASE_ID, T_RC
|
||||
*/
|
||||
#ifndef VL_RISETTLE_H
|
||||
#define VL_RISETTLE_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RISETTLE(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RISETTLE_H */
|
||||
27
app/src/vl/svc/VL_RISETTLE.pgc
Normal file
27
app/src/vl/svc/VL_RISETTLE.pgc
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* VL_RISETTLE.pgc - vl 모듈 서비스 VL_RISETTLE (one service = one file).
|
||||
* 기능: 참조무결성 세분 검증 - 정산 가맹점 불일치 (settlement.merchant_id <> purchase.merchant_id, RC 1=불일치 존재).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RISETTLE.h"
|
||||
|
||||
void VL_RISETTLE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_cnt, h_first_p;
|
||||
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(s.purchase_id),0) INTO :h_cnt, :h_first_p
|
||||
FROM settlement s JOIN purchase p ON p.purchase_id = s.purchase_id
|
||||
WHERE s.biz_date = :h_bizdate AND s.merchant_id <> p.merchant_id;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 정산-매입 가맹점 불일치 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_PURCHASE_ID, h_first_p);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RULEHIST.h
Normal file
12
app/src/vl/svc/VL_RULEHIST.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RULEHIST.h - vl 서비스 VL_RULEHIST 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_STR3, T_COUNT, T_ID1, T_RC
|
||||
*/
|
||||
#ifndef VL_RULEHIST_H
|
||||
#define VL_RULEHIST_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RULEHIST(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RULEHIST_H */
|
||||
29
app/src/vl/svc/VL_RULEHIST.pgc
Normal file
29
app/src/vl/svc/VL_RULEHIST.pgc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* VL_RULEHIST.pgc - vl 모듈 서비스 VL_RULEHIST (one service = one file).
|
||||
* 기능: 검증 규칙 변경이력 조회 (vl_check_log의 VL_RULEMOD 이력 건수/최종 로그 ID, RC 1=이력 없음).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RULEHIST.h"
|
||||
|
||||
void VL_RULEHIST(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
char rule[32];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_pat[40];
|
||||
long h_cnt, h_last;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_STR3, rule, sizeof(rule));
|
||||
if (rule[0] == 0) { userlog("VL_RULEHIST: T_STR3(rule_code) 누락"); FAIL(b); }
|
||||
snprintf(h_pat, sizeof(h_pat), "%s %%", rule);
|
||||
EXEC SQL SELECT count(*), coalesce(max(log_id),0) INTO :h_cnt, :h_last
|
||||
FROM vl_check_log
|
||||
WHERE check_type = 'VL_RULEMOD' AND detail LIKE :h_pat;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt == 0) rc = 1; /* 변경 이력 없음 */
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_ID1, h_last);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RULEMOD.h
Normal file
12
app/src/vl/svc/VL_RULEMOD.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RULEMOD.h - vl 서비스 VL_RULEMOD 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_STR3, T_ARG1, T_STR4, T_BIZDATE, T_ARG2, T_RC
|
||||
*/
|
||||
#ifndef VL_RULEMOD_H
|
||||
#define VL_RULEMOD_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RULEMOD(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RULEMOD_H */
|
||||
39
app/src/vl/svc/VL_RULEMOD.pgc
Normal file
39
app/src/vl/svc/VL_RULEMOD.pgc
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* VL_RULEMOD.pgc - vl 모듈 서비스 VL_RULEMOD (one service = one file).
|
||||
* 기능: 검증 규칙 변경 + 변경이력 기록 (임계값/심각도 UPDATE 후 vl_check_log에 이력 적재, RC 3=규칙 없음).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RULEMOD.h"
|
||||
|
||||
void VL_RULEMOD(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char bizdate[16], hist[128];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_rule[32], h_sev[8];
|
||||
long h_old, h_new;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_STR3, h_rule, sizeof(h_rule));
|
||||
if (h_rule[0] == 0) { userlog("VL_RULEMOD: T_STR3(rule_code) 누락"); FAIL(b); }
|
||||
h_new = getl(b, T_ARG1);
|
||||
gets_(b, T_STR4, h_sev, sizeof(h_sev));
|
||||
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
|
||||
if (bizdate[0] == 0) strcpy(bizdate, "2026-07-19");
|
||||
EXEC SQL SELECT threshold INTO :h_old 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 (h_sev[0] == 0) {
|
||||
EXEC SQL UPDATE vl_rule SET threshold = :h_new, updated_at = now()
|
||||
WHERE rule_code = :h_rule;
|
||||
} else {
|
||||
EXEC SQL UPDATE vl_rule SET threshold = :h_new, severity = :h_sev,
|
||||
updated_at = now()
|
||||
WHERE rule_code = :h_rule;
|
||||
}
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
snprintf(hist, sizeof(hist), "%s THR %ld -> %ld", h_rule, h_old, h_new);
|
||||
if (vldb_insert_check_log("VL_RULEMOD", 0, 0, hist, bizdate) < 0) FAIL(b);
|
||||
setl(b, T_ARG2, h_old); /* 변경 전 임계값 */
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RULEOFF.h
Normal file
12
app/src/vl/svc/VL_RULEOFF.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RULEOFF.h - vl 서비스 VL_RULEOFF 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_STR3, T_STR5, T_RC
|
||||
*/
|
||||
#ifndef VL_RULEOFF_H
|
||||
#define VL_RULEOFF_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RULEOFF(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RULEOFF_H */
|
||||
28
app/src/vl/svc/VL_RULEOFF.pgc
Normal file
28
app/src/vl/svc/VL_RULEOFF.pgc
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* VL_RULEOFF.pgc - vl 모듈 서비스 VL_RULEOFF (one service = one file).
|
||||
* 기능: 검증 규칙 활성/비활성 전환 (T_STR5 = ACTIVE|INACTIVE, RC 1=규칙 없음 2=상태값 오류).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RULEOFF.h"
|
||||
|
||||
void VL_RULEOFF(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
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_RULEOFF: T_STR3(rule_code) 누락"); FAIL(b); }
|
||||
gets_(b, T_STR5, h_st, sizeof(h_st));
|
||||
if (strcmp(h_st, "ACTIVE") != 0 && strcmp(h_st, "INACTIVE") != 0) {
|
||||
setl(b, T_RC, 2); /* 허용되지 않는 상태값 */
|
||||
OK(b);
|
||||
}
|
||||
EXEC SQL UPDATE vl_rule SET status = :h_st, 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_RULEREG.h
Normal file
12
app/src/vl/svc/VL_RULEREG.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RULEREG.h - vl 서비스 VL_RULEREG 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_STR3, T_STR1, T_STR4, T_ARG1, T_RC
|
||||
*/
|
||||
#ifndef VL_RULEREG_H
|
||||
#define VL_RULEREG_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RULEREG(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RULEREG_H */
|
||||
34
app/src/vl/svc/VL_RULEREG.pgc
Normal file
34
app/src/vl/svc/VL_RULEREG.pgc
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* VL_RULEREG.pgc - vl 모듈 서비스 VL_RULEREG (one service = one file).
|
||||
* 기능: 검증 규칙 신규 등록 (이미 존재하면 RC 1로 거부, 신규만 INSERT).
|
||||
* 갱신 겸용 upsert는 VL_RULE이 담당하고, 본 서비스는 순수 신규 등록만 허용한다.
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RULEREG.h"
|
||||
|
||||
void VL_RULEREG(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_rule[32], h_name[64], h_sev[8];
|
||||
long h_thr, h_cnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_STR3, h_rule, sizeof(h_rule));
|
||||
if (h_rule[0] == 0) { userlog("VL_RULEREG: T_STR3(rule_code) 누락"); FAIL(b); }
|
||||
gets_(b, T_STR1, h_name, sizeof(h_name));
|
||||
if (h_name[0] == 0) strcpy(h_name, "신규 검증 규칙");
|
||||
gets_(b, T_STR4, h_sev, sizeof(h_sev));
|
||||
if (h_sev[0] == 0) strcpy(h_sev, "INFO");
|
||||
h_thr = getl(b, T_ARG1);
|
||||
EXEC SQL SELECT count(*) INTO :h_cnt FROM vl_rule WHERE rule_code = :h_rule;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt > 0) rc = 1; /* 이미 등록된 규칙 */
|
||||
else {
|
||||
EXEC SQL INSERT INTO vl_rule (rule_code, rule_name, threshold, severity)
|
||||
VALUES (:h_rule, :h_name, :h_thr, :h_sev);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
}
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_RULESTAT.h
Normal file
12
app/src/vl/svc/VL_RULESTAT.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_RULESTAT.h - vl 서비스 VL_RULESTAT 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_COUNT, T_ARG1, T_ARG2, T_RC
|
||||
*/
|
||||
#ifndef VL_RULESTAT_H
|
||||
#define VL_RULESTAT_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_RULESTAT(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_RULESTAT_H */
|
||||
27
app/src/vl/svc/VL_RULESTAT.pgc
Normal file
27
app/src/vl/svc/VL_RULESTAT.pgc
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* VL_RULESTAT.pgc - vl 모듈 서비스 VL_RULESTAT (one service = one file).
|
||||
* 기능: 검증 규칙 현황 집계 (전체/ACTIVE/CRIT 건수, RC 1=활성 규칙 전무).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_RULESTAT.h"
|
||||
|
||||
void VL_RULESTAT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_tot, h_act, h_crit;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
EXEC SQL SELECT count(*),
|
||||
coalesce(sum(CASE WHEN status = 'ACTIVE' THEN 1 ELSE 0 END),0),
|
||||
coalesce(sum(CASE WHEN severity = 'CRIT' THEN 1 ELSE 0 END),0)
|
||||
INTO :h_tot, :h_act, :h_crit
|
||||
FROM vl_rule;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_act == 0) rc = 1; /* 활성 규칙 없음: 검증 공백 */
|
||||
setl(b, T_COUNT, h_tot);
|
||||
setl(b, T_ARG1, h_act);
|
||||
setl(b, T_ARG2, h_crit);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_SUMFEE.h
Normal file
12
app/src/vl/svc/VL_SUMFEE.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_SUMFEE.h - vl 서비스 VL_SUMFEE 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_BIZDATE, T_FEE, T_AMT1, T_NET, T_AMT2, T_DELTA, T_RC
|
||||
*/
|
||||
#ifndef VL_SUMFEE_H
|
||||
#define VL_SUMFEE_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_SUMFEE(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_SUMFEE_H */
|
||||
38
app/src/vl/svc/VL_SUMFEE.pgc
Normal file
38
app/src/vl/svc/VL_SUMFEE.pgc
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* VL_SUMFEE.pgc - vl 모듈 서비스 VL_SUMFEE (one service = one file).
|
||||
* 기능: 통계-원천 수수료/순액 대사 (merchant_summary fee/net vs purchase 재집계, RC 비트합 1=수수료 2=순액, 8=통계 없음).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_SUMFEE.h"
|
||||
|
||||
void VL_SUMFEE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_bizdate[16];
|
||||
long h_sfee, h_snet, h_pfee, h_pnet;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_MERCHANT, h_merch, sizeof(h_merch));
|
||||
if (h_merch[0] == 0) { userlog("VL_SUMFEE: 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 fee_amount, net_amount INTO :h_sfee, :h_snet
|
||||
FROM merchant_summary
|
||||
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 8); OK(b); } /* 8=통계 없음 */
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL SELECT coalesce(sum(fee),0), coalesce(sum(net),0) INTO :h_pfee, :h_pnet
|
||||
FROM purchase
|
||||
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate AND status <> 'C';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_sfee != h_pfee) rc |= 1; /* 수수료 대사 불일치 */
|
||||
if (h_snet != h_pnet) rc |= 2; /* 순액 대사 불일치 */
|
||||
setl(b, T_FEE, h_pfee);
|
||||
setl(b, T_AMT1, h_sfee);
|
||||
setl(b, T_NET, h_pnet);
|
||||
setl(b, T_AMT2, h_snet);
|
||||
setl(b, T_DELTA, (h_sfee - h_pfee) + (h_snet - h_pnet));
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_SUMRECON.h
Normal file
12
app/src/vl/svc/VL_SUMRECON.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_SUMRECON.h - vl 서비스 VL_SUMRECON 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_BIZDATE, T_COUNT, T_ARG1, T_GROSS, T_AMT1, T_RC
|
||||
*/
|
||||
#ifndef VL_SUMRECON_H
|
||||
#define VL_SUMRECON_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_SUMRECON(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_SUMRECON_H */
|
||||
37
app/src/vl/svc/VL_SUMRECON.pgc
Normal file
37
app/src/vl/svc/VL_SUMRECON.pgc
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* VL_SUMRECON.pgc - vl 모듈 서비스 VL_SUMRECON (one service = one file).
|
||||
* 기능: 통계-원천 대사 검증 (merchant_summary 건수/총액 vs purchase 재집계, RC 비트합 1=건수 2=총액, 8=통계 없음).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_SUMRECON.h"
|
||||
|
||||
void VL_SUMRECON(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_bizdate[16];
|
||||
long h_scnt, h_sgross, h_pcnt, h_pgross;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
gets_(b, T_MERCHANT, h_merch, sizeof(h_merch));
|
||||
if (h_merch[0] == 0) { userlog("VL_SUMRECON: 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 txn_count, gross_amount INTO :h_scnt, :h_sgross
|
||||
FROM merchant_summary
|
||||
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 8); OK(b); } /* 8=통계 없음 */
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL SELECT count(*), coalesce(sum(amount),0) INTO :h_pcnt, :h_pgross
|
||||
FROM purchase
|
||||
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate AND status <> 'C';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_scnt != h_pcnt) rc |= 1; /* 건수 대사 불일치 */
|
||||
if (h_sgross != h_pgross) rc |= 2; /* 총액 대사 불일치 */
|
||||
setl(b, T_COUNT, h_pcnt);
|
||||
setl(b, T_ARG1, h_scnt);
|
||||
setl(b, T_GROSS, h_pgross);
|
||||
setl(b, T_AMT1, h_sgross);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_SUSPACK.h
Normal file
12
app/src/vl/svc/VL_SUSPACK.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_SUSPACK.h - vl 서비스 VL_SUSPACK 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_ID1, T_STR1, T_ARG1, T_RC
|
||||
*/
|
||||
#ifndef VL_SUSPACK_H
|
||||
#define VL_SUSPACK_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_SUSPACK(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_SUSPACK_H */
|
||||
29
app/src/vl/svc/VL_SUSPACK.pgc
Normal file
29
app/src/vl/svc/VL_SUSPACK.pgc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* VL_SUSPACK.pgc - vl 모듈 서비스 VL_SUSPACK (one service = one file).
|
||||
* 기능: 의심거래 워크플로 1단계 확인 (OPEN→CONFIRMED, 확인자 기록, RC 1=OPEN 상태 아님/없음).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_SUSPACK.h"
|
||||
|
||||
void VL_SUSPACK(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0, rows;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_sid;
|
||||
char h_who[32];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_sid = getl(b, T_ID1);
|
||||
gets_(b, T_STR1, h_who, sizeof(h_who));
|
||||
if (h_who[0] == 0) strcpy(h_who, "MISC");
|
||||
EXEC SQL UPDATE vl_suspect
|
||||
SET status = 'CONFIRMED',
|
||||
detail = detail || ' [확인:' || :h_who || ']'
|
||||
WHERE suspect_id = :h_sid AND status = 'OPEN';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
rows = (long)sqlca.sqlerrd[2];
|
||||
if (rows == 0) rc = 1; /* OPEN 아님 또는 미존재 */
|
||||
setl(b, T_ARG1, rows);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_SUSPACT.h
Normal file
12
app/src/vl/svc/VL_SUSPACT.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_SUSPACT.h - vl 서비스 VL_SUSPACT 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_ID1, T_REASON, T_BIZDATE, T_PURCHASE_ID, T_RC
|
||||
*/
|
||||
#ifndef VL_SUSPACT_H
|
||||
#define VL_SUSPACT_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_SUSPACT(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_SUSPACT_H */
|
||||
34
app/src/vl/svc/VL_SUSPACT.pgc
Normal file
34
app/src/vl/svc/VL_SUSPACT.pgc
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* VL_SUSPACT.pgc - vl 모듈 서비스 VL_SUSPACT (one service = one file).
|
||||
* 기능: 의심거래 워크플로 2단계 조치 등록 (조치내용 detail 부기 + 검증로그 적재, RC 2=이미 종결 3=없음 4=조치내용 누락).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_SUSPACT.h"
|
||||
|
||||
void VL_SUSPACT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char bizdate[16];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_sid, h_pid;
|
||||
char h_st[16], h_act[128];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_sid = getl(b, T_ID1);
|
||||
gets_(b, T_REASON, h_act, sizeof(h_act));
|
||||
if (h_act[0] == 0) { setl(b, T_RC, 4); OK(b); } /* 조치내용 필수 */
|
||||
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
|
||||
if (bizdate[0] == 0) strcpy(bizdate, "2026-07-19");
|
||||
EXEC SQL SELECT purchase_id, status INTO :h_pid, :h_st
|
||||
FROM vl_suspect WHERE suspect_id = :h_sid;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 3); OK(b); } /* 3=의심거래 없음 */
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (strcmp(h_st, "CLOSED") == 0) { setl(b, T_RC, 2); OK(b); } /* 종결건 조치 불가 */
|
||||
EXEC SQL UPDATE vl_suspect
|
||||
SET detail = detail || ' [조치:' || :h_act || ']'
|
||||
WHERE suspect_id = :h_sid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (vldb_insert_check_log("VL_SUSPACT", h_pid, 0, h_act, bizdate) < 0) FAIL(b);
|
||||
setl(b, T_PURCHASE_ID, h_pid);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_SUSPFINAL.h
Normal file
12
app/src/vl/svc/VL_SUSPFINAL.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_SUSPFINAL.h - vl 서비스 VL_SUSPFINAL 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_ID1, T_ARG1, T_RC
|
||||
*/
|
||||
#ifndef VL_SUSPFINAL_H
|
||||
#define VL_SUSPFINAL_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_SUSPFINAL(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_SUSPFINAL_H */
|
||||
27
app/src/vl/svc/VL_SUSPFINAL.pgc
Normal file
27
app/src/vl/svc/VL_SUSPFINAL.pgc
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* VL_SUSPFINAL.pgc - vl 모듈 서비스 VL_SUSPFINAL (one service = one file).
|
||||
* 기능: 의심거래 워크플로 3단계 종결 (CONFIRMED→CLOSED만 허용, RC 1=이미 종결 2=확인 전 종결 불가 3=없음).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_SUSPFINAL.h"
|
||||
|
||||
void VL_SUSPFINAL(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_sid;
|
||||
char h_st[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_sid = getl(b, T_ID1);
|
||||
EXEC SQL SELECT status INTO :h_st FROM vl_suspect WHERE suspect_id = :h_sid;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 3); OK(b); } /* 3=의심거래 없음 */
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (strcmp(h_st, "CLOSED") == 0) { setl(b, T_RC, 1); OK(b); } /* 이미 종결 */
|
||||
if (strcmp(h_st, "OPEN") == 0) { setl(b, T_RC, 2); OK(b); } /* 확인 단계 미경유 */
|
||||
EXEC SQL UPDATE vl_suspect SET status = 'CLOSED'
|
||||
WHERE suspect_id = :h_sid AND status = 'CONFIRMED';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
setl(b, T_ARG1, (long)sqlca.sqlerrd[2]);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/vl/svc/VL_SUSPREOPEN.h
Normal file
12
app/src/vl/svc/VL_SUSPREOPEN.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* VL_SUSPREOPEN.h - vl 서비스 VL_SUSPREOPEN 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_ID1, T_REASON, T_RC
|
||||
*/
|
||||
#ifndef VL_SUSPREOPEN_H
|
||||
#define VL_SUSPREOPEN_H
|
||||
|
||||
#include "vl_svc.h"
|
||||
|
||||
void VL_SUSPREOPEN(TPSVCINFO *p);
|
||||
|
||||
#endif /* VL_SUSPREOPEN_H */
|
||||
27
app/src/vl/svc/VL_SUSPREOPEN.pgc
Normal file
27
app/src/vl/svc/VL_SUSPREOPEN.pgc
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* VL_SUSPREOPEN.pgc - vl 모듈 서비스 VL_SUSPREOPEN (one service = one file).
|
||||
* 기능: 종결 의심거래 재오픈 (CLOSED→OPEN, 재오픈 사유 필수, RC 1=종결건 아님/없음 2=사유 누락).
|
||||
* vl_svr가 tpsvrinit에서 이 서비스를 tpadvertise 한다.
|
||||
*/
|
||||
#include "VL_SUSPREOPEN.h"
|
||||
|
||||
void VL_SUSPREOPEN(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long rc = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_sid;
|
||||
char h_rsn[128];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
h_sid = getl(b, T_ID1);
|
||||
gets_(b, T_REASON, h_rsn, sizeof(h_rsn));
|
||||
if (h_rsn[0] == 0) { setl(b, T_RC, 2); OK(b); } /* 재오픈 사유 필수 */
|
||||
EXEC SQL UPDATE vl_suspect
|
||||
SET status = 'OPEN',
|
||||
detail = detail || ' [재오픈:' || :h_rsn || ']'
|
||||
WHERE suspect_id = :h_sid AND status = 'CLOSED';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if ((long)sqlca.sqlerrd[2] == 0) rc = 1; /* CLOSED 상태 아님 */
|
||||
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