규모확장 Wave B: 전 11모듈 svc 75→133·batch 35→46 (BAIS 온라인 1:1)

- svc 825→1,463 (모듈당 133), batch 385→506 (모듈당 46) — 전부 새 고유 실업무 로직
  + 카피북 헤더, 디스패처 133 advertise, 한글 기능설명(매니페스트 추출)
- BAIS As-Is 대비: 온라인 1,463 vs 1,466(99.8%), 배치 506 vs 503(초과)
- 화면 매니페스트 1,463 재생성
- 검증: build DONE modules=11 batches=506, 12서버 runok, xadmin psc 1,466 AVAIL,
  매입체인 XA 커밋, 신규서비스 실데이터 스모크, 전 코퍼스 .pgc 클론 0

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
hyeongwoo-choi 2026-07-20 22:55:47 +00:00
parent ea90bef264
commit c62d91b7a7
1526 changed files with 59213 additions and 12 deletions

View file

@ -0,0 +1,56 @@
/*
* st_baddebt_batch.pgc - 대손 상각 배치 (XA 배치).
* 기준일 이전 지급일의 장기 보류(HELD) 미수 지급을 커서로 합산해 대손 규모를 산출한
* 뒤, 해당 지급을 일괄 취소(CANCELLED)하고 대손 상각 음(-) 조정을 1건 기록한다.
* 사용법: st_baddebt_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "st_dbio.h"
#include "st_baddebt_batch.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
st_baddebt_rec_t rec;
memset(&rec, 0, sizeof(rec));
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_net;
EXEC SQL END DECLARE SECTION;
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 baddebt_bc CURSOR FOR
SELECT net_amount FROM st_payment
WHERE status = 'HELD' AND pay_date <= :h_bizdate;
EXEC SQL OPEN baddebt_bc;
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
for (;;) {
EXEC SQL FETCH baddebt_bc INTO :h_net;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE baddebt_bc; tpabort(0); return 1; }
rec.held_cnt++; rec.writeoff += h_net;
}
EXEC SQL CLOSE baddebt_bc;
if (rec.held_cnt > 0) {
EXEC SQL UPDATE st_payment SET status = 'CANCELLED'
WHERE status = 'HELD' AND pay_date <= :h_bizdate;
if (sqlca.sqlcode < 0) { fprintf(stderr, "UPD FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
rec.adj_id = stdb_insert_adjust(0, 0, -rec.writeoff, "BADDEBT", bizdate);
if (rec.adj_id < 0) { tpabort(0); return 1; }
}
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> %s COMMIT: bizdate=%s held_cnt=%ld writeoff=%ld adj=%ld\n",
ST_BADDEBT_TAG, bizdate, rec.held_cnt, rec.writeoff, rec.adj_id);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,62 @@
/*
* st_biweekly_batch.pgc - 격주 정산 지급 예정 배치 (XA 배치).
* 당일 정산을 가맹점별 net 으로 집계하고, 영업일 기준 10일 뒤(약 2주) 지급일을 미리
* 계산해 지급 원장(st_payment)에 지급 예정(SCHEDULED)으로 등록한다.
* 사용법: st_biweekly_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "st_dbio.h"
#include "acq_common.h"
#include "st_biweekly_batch.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
st_biweekly_rec_t rec;
char cur[16], nxt[16], paydate[16];
int i;
memset(&rec, 0, sizeof(rec));
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16], h_mid[64];
long h_net;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
strncpy(cur, bizdate, sizeof(cur)-1); cur[sizeof(cur)-1] = 0;
for (i = 0; i < 10; i++) { /* 지급일 = 영업일 +10 */
if (acq_next_bizday(cur, nxt) < 0) { fprintf(stderr, "DATE FAIL\n"); return 1; }
strncpy(cur, nxt, sizeof(cur)-1); cur[sizeof(cur)-1] = 0;
}
strncpy(paydate, cur, sizeof(paydate)-1); paydate[sizeof(paydate)-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 biweekly_bc CURSOR FOR
SELECT merchant_id, coalesce(sum(net),0) FROM settlement
WHERE biz_date = :h_bizdate GROUP BY merchant_id ORDER BY merchant_id;
EXEC SQL OPEN biweekly_bc;
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
for (;;) {
long pay;
EXEC SQL FETCH biweekly_bc INTO :h_mid, :h_net;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE biweekly_bc; tpabort(0); return 1; }
if (h_net <= 0) continue;
pay = stdb_insert_payment(h_mid, h_net, paydate, "SCHEDULED", bizdate);
if (pay < 0) { EXEC SQL CLOSE biweekly_bc; tpabort(0); return 1; }
rec.merchants++; rec.sched_total += h_net; rec.pay_last = pay;
printf(" SCHED %-8s net=%ld paydate=%s\n", h_mid, h_net, paydate);
}
EXEC SQL CLOSE biweekly_bc;
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> %s COMMIT: bizdate=%s paydate=%s merchants=%ld sched_total=%ld\n",
ST_BIWEEKLY_TAG, bizdate, paydate, rec.merchants, rec.sched_total);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,47 @@
/*
* st_chargeback_batch.pgc - 차지백 회수 정산 배치 (XA 배치).
* 당일 정산 조정 중 차지백(reason=CHARGEBACK) 건을 집계해 회수 규모를 산출하고,
* 당일 지급 예정(SCHEDULED)을 일괄 보류(HELD)로 전환해 회수 대상을 잠근다.
* 사용법: st_chargeback_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "st_dbio.h"
#include "st_chargeback_batch.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
st_chargeback_rec_t rec;
memset(&rec, 0, sizeof(rec));
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_cnt, h_sum;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT count(*), coalesce(sum(delta),0) INTO :h_cnt, :h_sum
FROM st_adjust WHERE biz_date = :h_bizdate AND reason = 'CHARGEBACK';
if (sqlca.sqlcode < 0) { fprintf(stderr, "SUM FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
rec.cb_cnt = h_cnt; rec.cb_total = h_sum;
if (h_cnt > 0) {
EXEC SQL UPDATE st_payment SET status = 'HELD'
WHERE biz_date = :h_bizdate AND status = 'SCHEDULED';
if (sqlca.sqlcode < 0) { fprintf(stderr, "UPD FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
rec.held_upd = sqlca.sqlerrd[2];
}
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> %s COMMIT: bizdate=%s cb_cnt=%ld cb_total=%ld held_upd=%ld\n",
ST_CHARGEBACK_TAG, bizdate, rec.cb_cnt, rec.cb_total, rec.held_upd);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,47 @@
/*
* st_gradestat_batch.pgc - 가맹점 등급별 통계 배치 (XA 배치).
* 가맹점을 요율(mdr_bps) 등급으로 묶어 등급별 가맹점 수를 커서로 집계하고 최다 등급
* 요율을 산출해 등급 분포를 출력한다 (집계 전용).
* 사용법: st_gradestat_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "st_dbio.h"
#include "st_gradestat_batch.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
st_gradestat_rec_t rec;
long topcnt = 0;
memset(&rec, 0, sizeof(rec));
EXEC SQL BEGIN DECLARE SECTION;
long h_bps, h_cnt;
EXEC SQL END DECLARE SECTION;
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 gradestat_bc CURSOR FOR
SELECT mdr_bps, count(*) FROM merchant GROUP BY mdr_bps ORDER BY mdr_bps;
EXEC SQL OPEN gradestat_bc;
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
for (;;) {
EXEC SQL FETCH gradestat_bc INTO :h_bps, :h_cnt;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE gradestat_bc; tpabort(0); return 1; }
rec.grades++; rec.merchants += h_cnt;
if (h_cnt > topcnt) { topcnt = h_cnt; rec.top_bps = h_bps; }
printf(" GRADE bps=%ld count=%ld\n", h_bps, h_cnt);
}
EXEC SQL CLOSE gradestat_bc;
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> %s COMMIT: bizdate=%s grades=%ld merchants=%ld top_bps=%ld\n",
ST_GRADESTAT_TAG, bizdate, rec.grades, rec.merchants, rec.top_bps);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,53 @@
/*
* st_grpalloc_batch.pgc - 그룹 통합정산 배분 배치 (XA 배치).
* 가맹점 ID 앞 2자리를 그룹 키로 묶어 당일 net 을 그룹별로 집계하고, 각 그룹의 대표
* 지급처로 통합 지급 예정(st_payment)을 등록한다.
* 사용법: st_grpalloc_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "st_dbio.h"
#include "st_grpalloc_batch.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
st_grpalloc_rec_t rec;
memset(&rec, 0, sizeof(rec));
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16], h_grp[8];
long h_net;
EXEC SQL END DECLARE SECTION;
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 grpalloc_bc CURSOR FOR
SELECT left(merchant_id, 2), coalesce(sum(net_amount),0) FROM st_merch_settle
WHERE biz_date = :h_bizdate GROUP BY left(merchant_id, 2) ORDER BY 1;
EXEC SQL OPEN grpalloc_bc;
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
for (;;) {
long pay;
EXEC SQL FETCH grpalloc_bc INTO :h_grp, :h_net;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE grpalloc_bc; tpabort(0); return 1; }
if (h_net <= 0) continue;
pay = stdb_insert_payment(h_grp, h_net, bizdate, "SCHEDULED", bizdate);
if (pay < 0) { EXEC SQL CLOSE grpalloc_bc; tpabort(0); return 1; }
rec.groups++; rec.alloc_total += h_net; rec.pay_last = pay;
printf(" GRP %-4s net=%ld (pay=%ld)\n", h_grp, h_net, pay);
}
EXEC SQL CLOSE grpalloc_bc;
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> %s COMMIT: bizdate=%s groups=%ld alloc_total=%ld\n",
ST_GRPALLOC_TAG, bizdate, rec.groups, rec.alloc_total);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,53 @@
/*
* st_instant_batch.pgc - 즉시정산 지급 배치 (XA 배치).
* 당일 정산(settlement)을 가맹점별 net 으로 집계해 지급 원장(st_payment)에 즉시
* 지급 완료(PAID) 건으로 등록한다 (SCHEDULED 단계 생략).
* 사용법: st_instant_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "st_dbio.h"
#include "st_instant_batch.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
st_instant_rec_t rec;
memset(&rec, 0, sizeof(rec));
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16], h_mid[64];
long h_net;
EXEC SQL END DECLARE SECTION;
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 instant_bc CURSOR FOR
SELECT merchant_id, coalesce(sum(net),0) FROM settlement
WHERE biz_date = :h_bizdate GROUP BY merchant_id ORDER BY merchant_id;
EXEC SQL OPEN instant_bc;
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
for (;;) {
long pay;
EXEC SQL FETCH instant_bc INTO :h_mid, :h_net;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE instant_bc; tpabort(0); return 1; }
if (h_net <= 0) continue;
pay = stdb_insert_payment(h_mid, h_net, bizdate, "PAID", bizdate);
if (pay < 0) { EXEC SQL CLOSE instant_bc; tpabort(0); return 1; }
rec.paid_cnt++; rec.paid_total += h_net; rec.pay_last = pay;
printf(" PAID %-8s net=%ld (pay=%ld)\n", h_mid, h_net, pay);
}
EXEC SQL CLOSE instant_bc;
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> %s COMMIT: bizdate=%s paid_cnt=%ld paid_total=%ld\n",
ST_INSTANT_TAG, bizdate, rec.paid_cnt, rec.paid_total);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,54 @@
/*
* st_rebate_batch.pgc - 리베이트 정산 배치 (XA 배치).
* 당일 가맹점 집계(st_merch_settle)를 커서로 순회하며 부과 수수료의 5%를 리베이트로
* 산정해 정산 조정(st_adjust)에 양(+) 금액으로 적립한다.
* 사용법: st_rebate_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "st_dbio.h"
#include "st_rebate_batch.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
st_rebate_rec_t rec;
memset(&rec, 0, sizeof(rec));
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16], h_mid[64];
long h_fee;
EXEC SQL END DECLARE SECTION;
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 rebate_bc CURSOR FOR
SELECT merchant_id, fee_amount FROM st_merch_settle
WHERE biz_date = :h_bizdate AND fee_amount > 0 ORDER BY merchant_id;
EXEC SQL OPEN rebate_bc;
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
for (;;) {
long rebate, adj;
EXEC SQL FETCH rebate_bc INTO :h_mid, :h_fee;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE rebate_bc; tpabort(0); return 1; }
rebate = h_fee * 500 / 10000; /* 수수료 5% 리베이트 */
if (rebate <= 0) continue;
adj = stdb_insert_adjust(0, 0, rebate, "REBATE", bizdate);
if (adj < 0) { EXEC SQL CLOSE rebate_bc; tpabort(0); return 1; }
rec.merchants++; rec.rebate_total += rebate; rec.adj_last = adj;
printf(" REBATE %-8s fee=%ld -> %ld (adj=%ld)\n", h_mid, h_fee, rebate, adj);
}
EXEC SQL CLOSE rebate_bc;
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> %s COMMIT: bizdate=%s merchants=%ld rebate_total=%ld\n",
ST_REBATE_TAG, bizdate, rec.merchants, rec.rebate_total);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,45 @@
/*
* st_recvage_batch.pgc - 미수금 연령 분석 배치 (XA 배치).
* 보류(HELD) 지급을 기준일 대비 지급일 경과에 따라 연령 구간(정상/연체)으로 나누어
* 건수와 금액을 집계, 미수금 노후화 규모를 출력한다 (집계 전용).
* 사용법: st_recvage_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "st_dbio.h"
#include "st_recvage_batch.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
st_recvage_rec_t rec;
memset(&rec, 0, sizeof(rec));
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_cnt, h_sum, h_overdue;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT count(*), coalesce(sum(net_amount),0) INTO :h_cnt, :h_sum
FROM st_payment WHERE status = 'HELD';
if (sqlca.sqlcode < 0) { fprintf(stderr, "SUM FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
rec.held_cnt = h_cnt; rec.recv_total = h_sum;
EXEC SQL SELECT count(*) INTO :h_overdue FROM st_payment
WHERE status = 'HELD' AND pay_date < :h_bizdate;
if (sqlca.sqlcode < 0) { fprintf(stderr, "OVERDUE FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
rec.oldest = h_overdue;
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> %s COMMIT: bizdate=%s held_cnt=%ld recv_total=%ld overdue_cnt=%ld\n",
ST_RECVAGE_TAG, bizdate, rec.held_cnt, rec.recv_total, rec.oldest);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,62 @@
/*
* st_slabfee_batch.pgc - 슬라브(누진 구간) 요율 배치 (XA 배치).
* 당일 매입 총액을 기준으로 MDR 요율표의 구간을 커서로 순회하며, 금액이 각 구간에
* 걸치는 부분에만 해당 요율을 적용하는 누진(슬라브) 방식으로 예상 수수료를 합산한다.
* 사용법: st_slabfee_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "st_dbio.h"
#include "st_slabfee_batch.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
st_slabfee_rec_t rec;
long prev_min = -1, prev_bps = 0;
memset(&rec, 0, sizeof(rec));
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_gross, h_min, h_bps;
EXEC SQL END DECLARE SECTION;
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_gross FROM purchase WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) { fprintf(stderr, "GROSS FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
rec.day_gross = h_gross;
EXEC SQL DECLARE slabfee_bc CURSOR FOR
SELECT band_min, rate_bps FROM st_fee_rate WHERE fee_type = 'MDR' ORDER BY band_min;
EXEC SQL OPEN slabfee_bc;
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
for (;;) {
EXEC SQL FETCH slabfee_bc INTO :h_min, :h_bps;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE slabfee_bc; tpabort(0); return 1; }
if (prev_min >= 0 && h_gross > prev_min) {
long top = (h_gross < h_min) ? h_gross : h_min;
long seg = (top - prev_min) * prev_bps / 10000;
rec.slab_fee += seg; rec.segs++;
printf(" SLAB [%ld,%ld) bps=%ld -> %ld\n", prev_min, h_min, prev_bps, seg);
}
prev_min = h_min; prev_bps = h_bps;
}
EXEC SQL CLOSE slabfee_bc;
if (prev_min >= 0 && h_gross > prev_min) {
long seg = (h_gross - prev_min) * prev_bps / 10000;
rec.slab_fee += seg; rec.segs++;
}
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> %s COMMIT: bizdate=%s gross=%ld segs=%ld slab_fee=%ld\n",
ST_SLABFEE_TAG, bizdate, rec.day_gross, rec.segs, rec.slab_fee);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,55 @@
/*
* st_vatdetail_batch.pgc - 부가세 명세 생성 배치 (XA 배치).
* 당일 가맹점별 수수료 상세(MDR/VAN/RELAY) 합계를 커서로 집계해 공급가액으로 보고
* 부가세(10%)를 산정, 정산 상세(st_settle_dtl)에 VAT 라인으로 기록한다.
* 사용법: st_vatdetail_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "st_dbio.h"
#include "acq_common.h"
#include "st_vatdetail_batch.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
st_vatdetail_rec_t rec;
memset(&rec, 0, sizeof(rec));
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16], h_mid[64];
long h_supply;
EXEC SQL END DECLARE SECTION;
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 vatdetail_bc CURSOR FOR
SELECT merchant_id, coalesce(sum(amount),0) FROM st_settle_dtl
WHERE biz_date = :h_bizdate AND fee_type IN ('MDR', 'VAN', 'RELAY')
GROUP BY merchant_id ORDER BY merchant_id;
EXEC SQL OPEN vatdetail_bc;
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
for (;;) {
long vat, dtl;
EXEC SQL FETCH vatdetail_bc INTO :h_mid, :h_supply;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE vatdetail_bc; tpabort(0); return 1; }
vat = acq_vat(h_supply);
dtl = stdb_insert_fee_dtl(0, 0, h_mid, "VAT", vat, bizdate);
if (dtl < 0) { EXEC SQL CLOSE vatdetail_bc; tpabort(0); return 1; }
rec.merchants++; rec.supply_total += h_supply; rec.vat_total += vat;
printf(" VAT %-8s supply=%ld vat=%ld\n", h_mid, h_supply, vat);
}
EXEC SQL CLOSE vatdetail_bc;
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> %s COMMIT: bizdate=%s merchants=%ld supply=%ld vat=%ld\n",
ST_VATDETAIL_TAG, bizdate, rec.merchants, rec.supply_total, rec.vat_total);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,53 @@
/*
* st_whtdetail_batch.pgc - 원천세 명세 집계 배치 (XA 배치).
* 당일 가맹점별 정률(PCT) 수수료 합계를 커서로 집계해 원천징수세(3.3%)를 산정하고
* 명세로 출력한다 (집계/출력 전용, 원장 미기록).
* 사용법: st_whtdetail_batch [YYYY-MM-DD]
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "st_dbio.h"
#include "acq_common.h"
#include "st_whtdetail_batch.h"
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
st_whtdetail_rec_t rec;
memset(&rec, 0, sizeof(rec));
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16], h_mid[64];
long h_fee;
EXEC SQL END DECLARE SECTION;
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 whtdetail_bc CURSOR FOR
SELECT merchant_id, coalesce(sum(amount),0) FROM st_settle_dtl
WHERE biz_date = :h_bizdate AND fee_type = 'PCT'
GROUP BY merchant_id ORDER BY merchant_id;
EXEC SQL OPEN whtdetail_bc;
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
for (;;) {
long wht;
EXEC SQL FETCH whtdetail_bc INTO :h_mid, :h_fee;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE whtdetail_bc; tpabort(0); return 1; }
wht = acq_wht_amt(h_fee, 330); /* 3.3% 원천 */
rec.merchants++; rec.fee_total += h_fee; rec.wht_total += wht;
printf(" WHT %-8s fee=%ld wht=%ld\n", h_mid, h_fee, wht);
}
EXEC SQL CLOSE whtdetail_bc;
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> %s COMMIT: bizdate=%s merchants=%ld fee=%ld wht=%ld\n",
ST_WHTDETAIL_TAG, bizdate, rec.merchants, rec.fee_total, rec.wht_total);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,6 @@
/* st_baddebt_batch.h - st 대손 상각 배치 copybook. */
#ifndef ST_BADDEBT_BATCH_H
#define ST_BADDEBT_BATCH_H
#define ST_BADDEBT_TAG "st_baddebt_batch"
typedef struct { long held_cnt; long writeoff; long adj_id; } st_baddebt_rec_t;
#endif

View file

@ -0,0 +1,6 @@
/* st_biweekly_batch.h - st 격주 정산 지급 예정 배치 copybook. */
#ifndef ST_BIWEEKLY_BATCH_H
#define ST_BIWEEKLY_BATCH_H
#define ST_BIWEEKLY_TAG "st_biweekly_batch"
typedef struct { long merchants; long sched_total; long pay_last; } st_biweekly_rec_t;
#endif

View file

@ -0,0 +1,6 @@
/* st_chargeback_batch.h - st 차지백 회수 정산 배치 copybook. */
#ifndef ST_CHARGEBACK_BATCH_H
#define ST_CHARGEBACK_BATCH_H
#define ST_CHARGEBACK_TAG "st_chargeback_batch"
typedef struct { long cb_cnt; long cb_total; long held_upd; } st_chargeback_rec_t;
#endif

View file

@ -0,0 +1,6 @@
/* st_gradestat_batch.h - st 가맹점 등급별 통계 배치 copybook. */
#ifndef ST_GRADESTAT_BATCH_H
#define ST_GRADESTAT_BATCH_H
#define ST_GRADESTAT_TAG "st_gradestat_batch"
typedef struct { long grades; long merchants; long top_bps; } st_gradestat_rec_t;
#endif

View file

@ -0,0 +1,6 @@
/* st_grpalloc_batch.h - st 그룹 통합정산 배분 배치 copybook. */
#ifndef ST_GRPALLOC_BATCH_H
#define ST_GRPALLOC_BATCH_H
#define ST_GRPALLOC_TAG "st_grpalloc_batch"
typedef struct { long groups; long alloc_total; long pay_last; } st_grpalloc_rec_t;
#endif

View file

@ -0,0 +1,6 @@
/* st_instant_batch.h - st 즉시정산 지급 배치 copybook. */
#ifndef ST_INSTANT_BATCH_H
#define ST_INSTANT_BATCH_H
#define ST_INSTANT_TAG "st_instant_batch"
typedef struct { long paid_cnt; long paid_total; long pay_last; } st_instant_rec_t;
#endif

View file

@ -0,0 +1,6 @@
/* st_rebate_batch.h - st 리베이트 정산 배치 copybook. */
#ifndef ST_REBATE_BATCH_H
#define ST_REBATE_BATCH_H
#define ST_REBATE_TAG "st_rebate_batch"
typedef struct { long merchants; long rebate_total; long adj_last; } st_rebate_rec_t;
#endif

View file

@ -0,0 +1,6 @@
/* st_recvage_batch.h - st 미수금 연령 분석 배치 copybook. */
#ifndef ST_RECVAGE_BATCH_H
#define ST_RECVAGE_BATCH_H
#define ST_RECVAGE_TAG "st_recvage_batch"
typedef struct { long held_cnt; long recv_total; long oldest; } st_recvage_rec_t;
#endif

View file

@ -0,0 +1,6 @@
/* st_slabfee_batch.h - st 슬라브(누진 구간) 요율 배치 copybook. */
#ifndef ST_SLABFEE_BATCH_H
#define ST_SLABFEE_BATCH_H
#define ST_SLABFEE_TAG "st_slabfee_batch"
typedef struct { long day_gross; long segs; long slab_fee; } st_slabfee_rec_t;
#endif

View file

@ -0,0 +1,6 @@
/* st_vatdetail_batch.h - st 부가세 명세 생성 배치 copybook. */
#ifndef ST_VATDETAIL_BATCH_H
#define ST_VATDETAIL_BATCH_H
#define ST_VATDETAIL_TAG "st_vatdetail_batch"
typedef struct { long merchants; long supply_total; long vat_total; } st_vatdetail_rec_t;
#endif

View file

@ -0,0 +1,6 @@
/* st_whtdetail_batch.h - st 원천세 명세 집계 배치 copybook. */
#ifndef ST_WHTDETAIL_BATCH_H
#define ST_WHTDETAIL_BATCH_H
#define ST_WHTDETAIL_TAG "st_whtdetail_batch"
typedef struct { long merchants; long fee_total; long wht_total; } st_whtdetail_rec_t;
#endif

View file

@ -2,14 +2,14 @@
* st_svr.pgc - st (정산/수수료) MODULE SERVER (thin dispatcher).
*
* The legacy "one module server, many services" pattern: this binary owns NO
* business logic. Each of st's 75 online services now lives in its own file
* business logic. Each of st's 133 online services now lives in its own file
* (app/src/st/svc/<SVCNAME>.pgc) with its own copybook header
* (app/src/st/svc/<SVCNAME>.h); those objects are archived into libstsvc.a and
* linked into this server. Here we only include every service copybook, tpopen()
* the ECPG XA RM, tpadvertise() all services from a {name, fn} table, and
* tpclose() at shutdown.
*
* st_svr: ONE binary that tpadvertise()s ALL 75 online st(정산/수수료) services.
* st_svr: ONE binary that tpadvertise()s ALL 133 online st(정산/수수료) services.
* SETTLE keeps the proven behavior: its own XA branch writes the settlement +
* settle ledger rows. Terminal service of the 매입 chain.
*/
@ -93,6 +93,64 @@
#include "ST_PAYRETRY.h"
#include "ST_LIMITCHK.h"
#include "ST_LEDGERSNAP.h"
#include "ST_FLATFEE.h"
#include "ST_PCTFEE.h"
#include "ST_SLABFEE.h"
#include "ST_BANDSIM.h"
#include "ST_RATECARD.h"
#include "ST_RATECMP.h"
#include "ST_TIERFEE.h"
#include "ST_FLATVSPCT.h"
#include "ST_RATEMAX.h"
#include "ST_RATEFLOOR.h"
#include "ST_PROMOAPPLY.h"
#include "ST_EVENTFEE.h"
#include "ST_PARTNERSET.h"
#include "ST_COUPONADJ.h"
#include "ST_CASHBACK.h"
#include "ST_MKTGSHARE.h"
#include "ST_CYCLED3.h"
#include "ST_INSTANTPAY.h"
#include "ST_BIWEEKLY.h"
#include "ST_CYCLEQTR.h"
#include "ST_CYCLESET.h"
#include "ST_NEXTPAYDT.h"
#include "ST_PARTPAY.h"
#include "ST_REPARTIAL.h"
#include "ST_VOIDRECALC.h"
#include "ST_REFUNDCALC.h"
#include "ST_CHARGEBACK.h"
#include "ST_ADJREVERSE.h"
#include "ST_REBATE.h"
#include "ST_VOLREBATE.h"
#include "ST_LOYALTY.h"
#include "ST_GROWTHINC.h"
#include "ST_REFERRAL.h"
#include "ST_DEPOSITSET.h"
#include "ST_RECVAGE.h"
#include "ST_BADDEBT.h"
#include "ST_DEBTNET.h"
#include "ST_COLLATERAL.h"
#include "ST_RECVSTAT.h"
#include "ST_VATDETAIL.h"
#include "ST_WHTDETAIL.h"
#include "ST_TAXSUMMARY.h"
#include "ST_SUPPLYCALC.h"
#include "ST_VATADJUST.h"
#include "ST_PRECONFIRM.h"
#include "ST_LOCKBATCH.h"
#include "ST_UNLOCK.h"
#include "ST_APPROVEALL.h"
#include "ST_WORKFLOW.h"
#include "ST_GRPROLLUP.h"
#include "ST_GRPALLOC.h"
#include "ST_CHAINSET.h"
#include "ST_DISPUTERSV.h"
#include "ST_APPEALSTAT.h"
#include "ST_VANDETAIL.h"
#include "ST_RELAYSPLIT.h"
#include "ST_GRADESTAT.h"
#include "ST_MONTHSTAT.h"
/* ----- advertise table: {service name, function} ---------------------- */
static struct { const char *name; void (*fn)(TPSVCINFO *); } SVCS[] = {
@ -134,6 +192,35 @@ static struct { const char *name; void (*fn)(TPSVCINFO *); } SVCS[] = {
{"ST_EDIRECON", ST_EDIRECON}, {"ST_UNPAIDSUM", ST_UNPAIDSUM},
{"ST_PAYRETRY", ST_PAYRETRY}, {"ST_LIMITCHK", ST_LIMITCHK},
{"ST_LEDGERSNAP", ST_LEDGERSNAP},
{"ST_FLATFEE", ST_FLATFEE}, {"ST_PCTFEE", ST_PCTFEE},
{"ST_SLABFEE", ST_SLABFEE}, {"ST_BANDSIM", ST_BANDSIM},
{"ST_RATECARD", ST_RATECARD}, {"ST_RATECMP", ST_RATECMP},
{"ST_TIERFEE", ST_TIERFEE}, {"ST_FLATVSPCT", ST_FLATVSPCT},
{"ST_RATEMAX", ST_RATEMAX}, {"ST_RATEFLOOR", ST_RATEFLOOR},
{"ST_PROMOAPPLY", ST_PROMOAPPLY}, {"ST_EVENTFEE", ST_EVENTFEE},
{"ST_PARTNERSET", ST_PARTNERSET}, {"ST_COUPONADJ", ST_COUPONADJ},
{"ST_CASHBACK", ST_CASHBACK}, {"ST_MKTGSHARE", ST_MKTGSHARE},
{"ST_CYCLED3", ST_CYCLED3}, {"ST_INSTANTPAY", ST_INSTANTPAY},
{"ST_BIWEEKLY", ST_BIWEEKLY}, {"ST_CYCLEQTR", ST_CYCLEQTR},
{"ST_CYCLESET", ST_CYCLESET}, {"ST_NEXTPAYDT", ST_NEXTPAYDT},
{"ST_PARTPAY", ST_PARTPAY}, {"ST_REPARTIAL", ST_REPARTIAL},
{"ST_VOIDRECALC", ST_VOIDRECALC}, {"ST_REFUNDCALC", ST_REFUNDCALC},
{"ST_CHARGEBACK", ST_CHARGEBACK}, {"ST_ADJREVERSE", ST_ADJREVERSE},
{"ST_REBATE", ST_REBATE}, {"ST_VOLREBATE", ST_VOLREBATE},
{"ST_LOYALTY", ST_LOYALTY}, {"ST_GROWTHINC", ST_GROWTHINC},
{"ST_REFERRAL", ST_REFERRAL}, {"ST_DEPOSITSET", ST_DEPOSITSET},
{"ST_RECVAGE", ST_RECVAGE}, {"ST_BADDEBT", ST_BADDEBT},
{"ST_DEBTNET", ST_DEBTNET}, {"ST_COLLATERAL", ST_COLLATERAL},
{"ST_RECVSTAT", ST_RECVSTAT}, {"ST_VATDETAIL", ST_VATDETAIL},
{"ST_WHTDETAIL", ST_WHTDETAIL}, {"ST_TAXSUMMARY", ST_TAXSUMMARY},
{"ST_SUPPLYCALC", ST_SUPPLYCALC}, {"ST_VATADJUST", ST_VATADJUST},
{"ST_PRECONFIRM", ST_PRECONFIRM}, {"ST_LOCKBATCH", ST_LOCKBATCH},
{"ST_UNLOCK", ST_UNLOCK}, {"ST_APPROVEALL", ST_APPROVEALL},
{"ST_WORKFLOW", ST_WORKFLOW}, {"ST_GRPROLLUP", ST_GRPROLLUP},
{"ST_GRPALLOC", ST_GRPALLOC}, {"ST_CHAINSET", ST_CHAINSET},
{"ST_DISPUTERSV", ST_DISPUTERSV}, {"ST_APPEALSTAT", ST_APPEALSTAT},
{"ST_VANDETAIL", ST_VANDETAIL}, {"ST_RELAYSPLIT", ST_RELAYSPLIT},
{"ST_GRADESTAT", ST_GRADESTAT}, {"ST_MONTHSTAT", ST_MONTHSTAT},
{NULL, NULL}
};

View file

@ -0,0 +1,19 @@
/*
* ST_ADJREVERSE.h - st ST_ADJREVERSE (copybook / record header).
* ().
*/
#ifndef ST_ADJREVERSE_H
#define ST_ADJREVERSE_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_adjreverse_rec_t;
void ST_ADJREVERSE(TPSVCINFO *p);
#endif /* ST_ADJREVERSE_H */

View file

@ -0,0 +1,30 @@
/*
* ST_ADJREVERSE.pgc - st 모듈 서비스 ST_ADJREVERSE (one service = one file).
* 조정 취소(역분개): 기존 정산 조정(T_ADJ) 행을 조회해 동일 금액의 반대 부호 조정을
* 새로 기록함으로써 앞선 조정을 상쇄한다.
*/
#include "ST_ADJREVERSE.h"
/* 103. ST_ADJREVERSE - 기존 조정을 반대부호로 상쇄. */
void ST_ADJREVERSE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16];
long newadj;
EXEC SQL BEGIN DECLARE SECTION;
long h_adj, h_delta, h_sid, h_pid;
EXEC SQL END DECLARE SECTION;
h_adj = getl(b, T_ADJ);
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
EXEC SQL SELECT delta, settlement_id, purchase_id INTO :h_delta, :h_sid, :h_pid
FROM st_adjust WHERE adj_id = :h_adj;
if (sqlca.sqlcode < 0) FAIL(b);
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
newadj = stdb_insert_adjust(h_sid, h_pid, -h_delta, "REVERSE", bizdate);
if (newadj < 0) FAIL(b);
setl(b, T_ADJ, newadj);
setl(b, T_DELTA, -h_delta);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_APPEALSTAT.h - st ST_APPEALSTAT (copybook / record header).
* .
*/
#ifndef ST_APPEALSTAT_H
#define ST_APPEALSTAT_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_appealstat_rec_t;
void ST_APPEALSTAT(TPSVCINFO *p);
#endif /* ST_APPEALSTAT_H */

View file

@ -0,0 +1,28 @@
/*
* ST_APPEALSTAT.pgc - st 모듈 서비스 ST_APPEALSTAT (one service = one file).
* 이의신청 통계: 정산 조정 중 이의신청 관련(reason LIKE 'DISPUTE%') 건수와 청구
* 금액 합계를 집계해 이의신청 규모를 산출한다 (조회 전용).
*/
#include "ST_APPEALSTAT.h"
/* 129. ST_APPEALSTAT - 이의신청 조정 건수/금액 통계. */
void ST_APPEALSTAT(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_cnt, h_sum;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT count(*), coalesce(sum(delta),0) INTO :h_cnt, :h_sum
FROM st_adjust WHERE biz_date = :h_bizdate AND reason LIKE 'DISPUTE%';
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_COUNT, h_cnt);
setl(b, T_DELTA, h_sum);
setl(b, T_RC, (h_cnt > 0) ? 0 : 1);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_APPROVEALL.h - st ST_APPROVEALL (copybook / record header).
* .
*/
#ifndef ST_APPROVEALL_H
#define ST_APPROVEALL_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_approveall_rec_t;
void ST_APPROVEALL(TPSVCINFO *p);
#endif /* ST_APPROVEALL_H */

View file

@ -0,0 +1,28 @@
/*
* ST_APPROVEALL.pgc - st 모듈 서비스 ST_APPROVEALL (one service = one file).
* 정산 일괄 승인: 당일 지급 예정(SCHEDULED) 전 건을 한 번에 지급 완료(PAID)로
* 승인 처리한다. 승인된 지급 건수를 반환한다.
*/
#include "ST_APPROVEALL.h"
/* 123. ST_APPROVEALL - 당일 지급 예정 일괄 승인(->PAID). */
void ST_APPROVEALL(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16];
long approved;
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL UPDATE st_payment SET status = 'PAID'
WHERE biz_date = :h_bizdate AND status = 'SCHEDULED';
if (sqlca.sqlcode < 0) FAIL(b);
approved = sqlca.sqlerrd[2];
setl(b, T_COUNT, approved);
setl(b, T_RC, (approved > 0) ? 0 : 1);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_BADDEBT.h - st ST_BADDEBT (copybook / record header).
* .
*/
#ifndef ST_BADDEBT_H
#define ST_BADDEBT_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_baddebt_rec_t;
void ST_BADDEBT(TPSVCINFO *p);
#endif /* ST_BADDEBT_H */

View file

@ -0,0 +1,44 @@
/*
* ST_BADDEBT.pgc - st 모듈 서비스 ST_BADDEBT (one service = one file).
* 대손 상각: 특정 가맹점의 장기 보류(HELD) 지급 건을 커서로 순회해 총 미수액을
* 산출하고, 대손 상각 음(-) 조정 기록 + 해당 지급 취소(CANCELLED) 처리한다.
*/
#include "ST_BADDEBT.h"
/* 111. ST_BADDEBT - 장기 미수 대손 상각(상계+취소). */
void ST_BADDEBT(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
long total = 0, cnt = 0, adj;
EXEC SQL BEGIN DECLARE SECTION;
long h_net;
char h_merch[64], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL DECLARE baddebt_c CURSOR FOR
SELECT net_amount FROM st_payment
WHERE merchant_id = :h_merch AND status = 'HELD' AND pay_date <= :h_bizdate;
EXEC SQL OPEN baddebt_c;
if (sqlca.sqlcode < 0) FAIL(b);
for (;;) {
EXEC SQL FETCH baddebt_c INTO :h_net;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE baddebt_c; FAIL(b); }
total += h_net; cnt++;
}
EXEC SQL CLOSE baddebt_c;
if (cnt == 0) { setl(b, T_RC, 1); OK(b); }
adj = stdb_insert_adjust(0, 0, -total, "BADDEBT", bizdate);
if (adj < 0) FAIL(b);
if (stdb_update_payment_status(merch, "HELD", "CANCELLED", bizdate) < 0) FAIL(b);
setl(b, T_ADJ, adj);
setl(b, T_COUNT, cnt);
setl(b, T_DELTA, -total);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_BANDSIM.h - st ST_BANDSIM (copybook / record header).
* .
*/
#ifndef ST_BANDSIM_H
#define ST_BANDSIM_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_bandsim_rec_t;
void ST_BANDSIM(TPSVCINFO *p);
#endif /* ST_BANDSIM_H */

View file

@ -0,0 +1,41 @@
/*
* ST_BANDSIM.pgc - st 모듈 서비스 ST_BANDSIM (one service = one file).
* 구간별 요율 시뮬레이션: 입력 금액에 적용 가능한(band_min <= amount) 모든 구간 중
* 최고 요율 구간을 찾아 예상 수수료를 산출한다 (조회 전용, 최대치 시나리오).
*/
#include "ST_BANDSIM.h"
/* 79. ST_BANDSIM - 적용가능 구간 중 최고 요율 시뮬. */
void ST_BANDSIM(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char ftype[16];
long amount = getl(b, T_AMOUNT), maxbps = 0, hits = 0;
EXEC SQL BEGIN DECLARE SECTION;
long h_min, h_bps, h_amt;
char h_ftype[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_STR1, ftype, sizeof(ftype)); if (ftype[0] == 0) strcpy(ftype, "MDR");
strncpy(h_ftype, ftype, sizeof(h_ftype)-1); h_ftype[sizeof(h_ftype)-1] = 0;
h_amt = amount;
EXEC SQL DECLARE bandsim_c CURSOR FOR
SELECT band_min, rate_bps FROM st_fee_rate
WHERE fee_type = :h_ftype AND band_min <= :h_amt ORDER BY rate_bps DESC;
EXEC SQL OPEN bandsim_c;
if (sqlca.sqlcode < 0) FAIL(b);
for (;;) {
EXEC SQL FETCH bandsim_c INTO :h_min, :h_bps;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE bandsim_c; FAIL(b); }
if (hits == 0) maxbps = h_bps; /* rate_bps DESC: 첫 행이 최고 요율 */
hits++;
}
EXEC SQL CLOSE bandsim_c;
if (hits == 0) { setl(b, T_RC, -1); OK(b); }
setl(b, T_COUNT, hits);
setl(b, T_RC, maxbps);
setl(b, T_FEE, acq_fee(amount, maxbps));
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_BIWEEKLY.h - st ST_BIWEEKLY (copybook / record header).
* .
*/
#ifndef ST_BIWEEKLY_H
#define ST_BIWEEKLY_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_biweekly_rec_t;
void ST_BIWEEKLY(TPSVCINFO *p);
#endif /* ST_BIWEEKLY_H */

View file

@ -0,0 +1,39 @@
/*
* ST_BIWEEKLY.pgc - st 모듈 서비스 ST_BIWEEKLY (one service = one file).
* 격주 정산: 가맹점 당일 정산 net 합계를 집계하고 영업일 기준 10일 뒤(약 2주)
* 지급일로 지급 예정 등록한다.
*/
#include "ST_BIWEEKLY.h"
/* 94. ST_BIWEEKLY - 2주 주기 net 합계 지급 예정. */
void ST_BIWEEKLY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16], cur[16], nxt[16];
long pay;
int i;
EXEC SQL BEGIN DECLARE SECTION;
long h_sum;
char h_merch[64], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT coalesce(sum(net),0) INTO :h_sum FROM settlement
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
if (h_sum <= 0) { setl(b, T_RC, 1); OK(b); }
strncpy(cur, bizdate, sizeof(cur)-1); cur[sizeof(cur)-1] = 0;
for (i = 0; i < 10; i++) { /* 영업일 +10 (약 2주) */
if (acq_next_bizday(cur, nxt) < 0) FAIL(b);
strncpy(cur, nxt, sizeof(cur)-1); cur[sizeof(cur)-1] = 0;
}
pay = stdb_insert_payment(merch, h_sum, cur, "SCHEDULED", bizdate);
if (pay < 0) FAIL(b);
setl(b, T_ID1, pay);
setl(b, T_NET, h_sum);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_CASHBACK.h - st ST_CASHBACK (copybook / record header).
* .
*/
#ifndef ST_CASHBACK_H
#define ST_CASHBACK_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_cashback_rec_t;
void ST_CASHBACK(TPSVCINFO *p);
#endif /* ST_CASHBACK_H */

View file

@ -0,0 +1,26 @@
/*
* ST_CASHBACK.pgc - st 모듈 서비스 ST_CASHBACK (one service = one file).
* 캐시백 정산: 거래 금액에 캐시백율(T_ARG1 bps)을 적용한 캐시백을 가맹점 지급
* 예정(st_payment)으로 등록한다 (판촉성 지급).
*/
#include "ST_CASHBACK.h"
/* 90. ST_CASHBACK - 캐시백 지급 예정 등록. */
void ST_CASHBACK(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
long amount = getl(b, T_AMOUNT), bps = getl(b, T_ARG1), cash, pay;
gets_(b, T_MERCHANT, merch, sizeof(merch)); if (merch[0] == 0) strcpy(merch, "M0000");
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
if (bps <= 0) bps = 100; /* 기본 1% 캐시백 */
cash = acq_fee(amount, bps);
if (cash <= 0) { setl(b, T_RC, 1); OK(b); }
pay = stdb_insert_payment(merch, cash, bizdate, "SCHEDULED", bizdate);
if (pay < 0) FAIL(b);
setl(b, T_ID1, pay);
setl(b, T_AMOUNT, cash);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_CHAINSET.h - st ST_CHAINSET (copybook / record header).
* .
*/
#ifndef ST_CHAINSET_H
#define ST_CHAINSET_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_chainset_rec_t;
void ST_CHAINSET(TPSVCINFO *p);
#endif /* ST_CHAINSET_H */

View file

@ -0,0 +1,36 @@
/*
* ST_CHAINSET.pgc - st 모듈 서비스 ST_CHAINSET (one service = one file).
* 체인점 통합 정산: 업종/분류(T_CATEGORY)로 묶인 체인 매입의 정산 net 을 조인 집계해
* 대표 지급처(T_MERCHANT)로 통합 지급 예정 등록한다.
*/
#include "ST_CHAINSET.h"
/* 127. ST_CHAINSET - 업종 체인 통합 net 지급. */
void ST_CHAINSET(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], cat[32], bizdate[16];
long pay;
EXEC SQL BEGIN DECLARE SECTION;
long h_sum, h_cnt;
char h_cat[32], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_MERCHANT, merch, sizeof(merch)); if (merch[0] == 0) strcpy(merch, "CHAIN");
gets_(b, T_CATEGORY, cat, sizeof(cat)); if (cat[0] == 0) strcpy(cat, "GEN");
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_cat, cat, sizeof(h_cat)-1); h_cat[sizeof(h_cat)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT coalesce(sum(s.net),0), count(*) INTO :h_sum, :h_cnt
FROM settlement s JOIN purchase p ON p.purchase_id = s.purchase_id
WHERE p.category = :h_cat AND s.biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
if (h_sum <= 0) { setl(b, T_RC, 1); OK(b); }
pay = stdb_insert_payment(merch, h_sum, bizdate, "SCHEDULED", bizdate);
if (pay < 0) FAIL(b);
setl(b, T_ID1, pay);
setl(b, T_COUNT, h_cnt);
setl(b, T_NET, h_sum);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_CHARGEBACK.h - st ST_CHARGEBACK (copybook / record header).
* .
*/
#ifndef ST_CHARGEBACK_H
#define ST_CHARGEBACK_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_chargeback_rec_t;
void ST_CHARGEBACK(TPSVCINFO *p);
#endif /* ST_CHARGEBACK_H */

View file

@ -0,0 +1,28 @@
/*
* ST_CHARGEBACK.pgc - st 모듈 서비스 ST_CHARGEBACK (one service = one file).
* 차지백 정산 처리: 차지백 금액(T_AMOUNT)을 음(-)의 정산 조정으로 회수하고 해당
* 가맹점 지급을 보류(HELD) 상태로 전환한다.
*/
#include "ST_CHARGEBACK.h"
/* 102. ST_CHARGEBACK - 차지백 회수 조정 + 지급 보류. */
void ST_CHARGEBACK(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
long sid = getl(b, T_SETTLE_ID), pid = getl(b, T_PURCHASE_ID);
long amount = getl(b, T_AMOUNT), adj;
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
if (amount <= 0) { setl(b, T_RC, 1); OK(b); }
adj = stdb_insert_adjust(sid, pid, -amount, "CHARGEBACK", bizdate);
if (adj < 0) FAIL(b);
if (merch[0] != 0)
if (stdb_update_payment_status(merch, "SCHEDULED", "HELD", bizdate) < 0) FAIL(b);
setl(b, T_ADJ, adj);
setl(b, T_DELTA, -amount);
Bchg(b, T_STATUS, 0, "CB", 0L);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_COLLATERAL.h - st ST_COLLATERAL (copybook / record header).
* / .
*/
#ifndef ST_COLLATERAL_H
#define ST_COLLATERAL_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_collateral_rec_t;
void ST_COLLATERAL(TPSVCINFO *p);
#endif /* ST_COLLATERAL_H */

View file

@ -0,0 +1,28 @@
/*
* ST_COLLATERAL.pgc - st 모듈 서비스 ST_COLLATERAL (one service = one file).
* 담보/보증금 잔액: 정산 상세의 DEPOSIT 라인을 합산해 가맹점 누적 보증금(담보)
* 잔액과 예치 건수를 조회한다 (조회 전용).
*/
#include "ST_COLLATERAL.h"
/* 113. ST_COLLATERAL - 가맹점 누적 보증금 잔액 조회. */
void ST_COLLATERAL(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64];
EXEC SQL BEGIN DECLARE SECTION;
long h_bal, h_cnt;
char h_merch[64];
EXEC SQL END DECLARE SECTION;
gets_(b, T_MERCHANT, merch, sizeof(merch));
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
EXEC SQL SELECT coalesce(sum(amount),0), count(*) INTO :h_bal, :h_cnt
FROM st_settle_dtl WHERE merchant_id = :h_merch AND fee_type = 'DEPOSIT';
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_AMOUNT, h_bal);
setl(b, T_COUNT, h_cnt);
setl(b, T_RC, (h_bal > 0) ? 0 : 1);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_COUPONADJ.h - st ST_COUPONADJ (copybook / record header).
* .
*/
#ifndef ST_COUPONADJ_H
#define ST_COUPONADJ_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_couponadj_rec_t;
void ST_COUPONADJ(TPSVCINFO *p);
#endif /* ST_COUPONADJ_H */

View file

@ -0,0 +1,26 @@
/*
* ST_COUPONADJ.pgc - st 모듈 서비스 ST_COUPONADJ (one service = one file).
* 쿠폰 조정 정산: 발급 쿠폰 금액(T_ARG1)을 가맹점 부담분으로 양(+)의 정산 조정에
* 기록해 정산에 반영한다 (쿠폰 사용액 정산).
*/
#include "ST_COUPONADJ.h"
/* 89. ST_COUPONADJ - 쿠폰 사용액 정산 조정(가산). */
void ST_COUPONADJ(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16], reason[64], rbuf[96];
long sid = getl(b, T_SETTLE_ID), pid = getl(b, T_PURCHASE_ID);
long coupon = getl(b, T_ARG1), adj;
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
gets_(b, T_STR1, reason, sizeof(reason)); if (reason[0] == 0) strcpy(reason, "CPN");
if (coupon <= 0) { setl(b, T_RC, 1); OK(b); }
snprintf(rbuf, sizeof(rbuf), "COUPON:%s", reason);
adj = stdb_insert_adjust(sid, pid, coupon, rbuf, bizdate);
if (adj < 0) FAIL(b);
setl(b, T_ADJ, adj);
setl(b, T_DELTA, coupon);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_CYCLED3.h - st ST_CYCLED3 (copybook / record header).
* D+3 .
*/
#ifndef ST_CYCLED3_H
#define ST_CYCLED3_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_cycled3_rec_t;
void ST_CYCLED3(TPSVCINFO *p);
#endif /* ST_CYCLED3_H */

View file

@ -0,0 +1,29 @@
/*
* ST_CYCLED3.pgc - st 모듈 서비스 ST_CYCLED3 (one service = one file).
* D+3 정산 주기: 영업일(T_BIZDATE)로부터 영업일 기준 3일 뒤 지급일을 산출해
* (주말 스킵) 정산 net 을 해당 지급일로 지급 예정 등록한다.
*/
#include "ST_CYCLED3.h"
/* 92. ST_CYCLED3 - D+3 영업일 지급 예정 등록. */
void ST_CYCLED3(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16], cur[16], nxt[16];
long net = getl(b, T_NET), pay;
int i;
gets_(b, T_MERCHANT, merch, sizeof(merch)); if (merch[0] == 0) strcpy(merch, "M0000");
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(cur, bizdate, sizeof(cur)-1); cur[sizeof(cur)-1] = 0;
for (i = 0; i < 3; i++) { /* 영업일 +3 (주말 스킵) */
if (acq_next_bizday(cur, nxt) < 0) FAIL(b);
strncpy(cur, nxt, sizeof(cur)-1); cur[sizeof(cur)-1] = 0;
}
pay = stdb_insert_payment(merch, net, cur, "SCHEDULED", bizdate);
if (pay < 0) FAIL(b);
setl(b, T_ID1, pay);
Bchg(b, T_STR1, 0, cur, 0L);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_CYCLEQTR.h - st ST_CYCLEQTR (copybook / record header).
* .
*/
#ifndef ST_CYCLEQTR_H
#define ST_CYCLEQTR_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_cycleqtr_rec_t;
void ST_CYCLEQTR(TPSVCINFO *p);
#endif /* ST_CYCLEQTR_H */

View file

@ -0,0 +1,34 @@
/*
* ST_CYCLEQTR.pgc - st 모듈 서비스 ST_CYCLEQTR (one service = one file).
* 분기 정산 주기: 기준일(T_BIZDATE) 이하의 미지급 정산 net 을 누적 합계로 집계해
* 분기 통합 지급 예정으로 등록한다 (누적 정산).
*/
#include "ST_CYCLEQTR.h"
/* 95. ST_CYCLEQTR - 기준일까지 누적 net 분기 지급. */
void ST_CYCLEQTR(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
long pay;
EXEC SQL BEGIN DECLARE SECTION;
long h_sum, h_cnt;
char h_merch[64], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT count(*), coalesce(sum(net),0) INTO :h_cnt, :h_sum FROM settlement
WHERE merchant_id = :h_merch AND biz_date <= :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
if (h_sum <= 0) { setl(b, T_RC, 1); OK(b); }
pay = stdb_insert_payment(merch, h_sum, bizdate, "SCHEDULED", bizdate);
if (pay < 0) FAIL(b);
setl(b, T_ID1, pay);
setl(b, T_COUNT, h_cnt);
setl(b, T_NET, h_sum);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_CYCLESET.h - st ST_CYCLESET (copybook / record header).
* .
*/
#ifndef ST_CYCLESET_H
#define ST_CYCLESET_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_cycleset_rec_t;
void ST_CYCLESET(TPSVCINFO *p);
#endif /* ST_CYCLESET_H */

View file

@ -0,0 +1,32 @@
/*
* ST_CYCLESET.pgc - st 모듈 서비스 ST_CYCLESET (one service = one file).
* 정산 주기 설정 조회: 가맹점 한도(daily_limit)를 기준으로 적용 정산 주기 코드
* (대형=D1 / 중형=D2 / 소형=WEEK)를 파생해 반환한다 (조회 전용).
*/
#include "ST_CYCLESET.h"
/* 96. ST_CYCLESET - 가맹점 한도 기반 정산주기 코드 파생. */
void ST_CYCLESET(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], cyc[8];
EXEC SQL BEGIN DECLARE SECTION;
long h_limit;
char h_merch[64], h_status[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_MERCHANT, merch, sizeof(merch));
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
EXEC SQL SELECT daily_limit, status INTO :h_limit, :h_status FROM merchant
WHERE merchant_id = :h_merch;
if (sqlca.sqlcode < 0) FAIL(b);
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
if (h_limit >= 300000000) strcpy(cyc, "D1");
else if (h_limit >= 100000000) strcpy(cyc, "D2");
else strcpy(cyc, "WEEK");
setl(b, T_AMOUNT, h_limit);
Bchg(b, T_STATUS, 0, h_status, 0L);
Bchg(b, T_STR1, 0, cyc, 0L);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_DEBTNET.h - st ST_DEBTNET (copybook / record header).
* netting.
*/
#ifndef ST_DEBTNET_H
#define ST_DEBTNET_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_debtnet_rec_t;
void ST_DEBTNET(TPSVCINFO *p);
#endif /* ST_DEBTNET_H */

View file

@ -0,0 +1,34 @@
/*
* ST_DEBTNET.pgc - st 모듈 서비스 ST_DEBTNET (one service = one file).
* 채권 상계: 가맹점의 지급 예정(SCHEDULED) 채무와 보류(HELD) 미수 채권을 각각
* 집계해 상계 후 순 지급/회수 포지션을 계산한다 (조회 전용).
*/
#include "ST_DEBTNET.h"
/* 112. ST_DEBTNET - 지급 채무 대 미수 채권 상계. */
void ST_DEBTNET(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64];
long position;
EXEC SQL BEGIN DECLARE SECTION;
long h_payable, h_recv;
char h_merch[64];
EXEC SQL END DECLARE SECTION;
gets_(b, T_MERCHANT, merch, sizeof(merch));
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
EXEC SQL SELECT coalesce(sum(net_amount),0) INTO :h_payable FROM st_payment
WHERE merchant_id = :h_merch AND status = 'SCHEDULED';
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL SELECT coalesce(sum(net_amount),0) INTO :h_recv FROM st_payment
WHERE merchant_id = :h_merch AND status = 'HELD';
if (sqlca.sqlcode < 0) FAIL(b);
position = h_payable - h_recv;
setl(b, T_AMT1, h_payable);
setl(b, T_AMT2, h_recv);
setl(b, T_NET, position);
setl(b, T_RC, (position >= 0) ? 0 : 1); /* 1 = 순 회수 포지션 */
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_DEPOSITSET.h - st ST_DEPOSITSET (copybook / record header).
* /.
*/
#ifndef ST_DEPOSITSET_H
#define ST_DEPOSITSET_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_depositset_rec_t;
void ST_DEPOSITSET(TPSVCINFO *p);
#endif /* ST_DEPOSITSET_H */

View file

@ -0,0 +1,26 @@
/*
* ST_DEPOSITSET.pgc - st 모듈 서비스 ST_DEPOSITSET (one service = one file).
* 보증금 설정/차감: 가맹점 보증금 예치액(T_ARG1)을 정산 상세에 DEPOSIT 라인으로
* 적립 기록하고 정산 net 에서 차감한 잔여액을 반환한다.
*/
#include "ST_DEPOSITSET.h"
/* 109. ST_DEPOSITSET - 보증금 예치 기록 + net 차감. */
void ST_DEPOSITSET(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
long sid = getl(b, T_SETTLE_ID), pid = getl(b, T_PURCHASE_ID);
long net = getl(b, T_NET), deposit = getl(b, T_ARG1), dtl;
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
if (deposit <= 0) { setl(b, T_RC, 1); OK(b); }
if (deposit > net) deposit = net;
dtl = stdb_insert_fee_dtl(sid, pid, merch, "DEPOSIT", deposit, bizdate);
if (dtl < 0) FAIL(b);
setl(b, T_AMOUNT, deposit);
setl(b, T_NET, net - deposit);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_DISPUTERSV.h - st ST_DISPUTERSV (copybook / record header).
* .
*/
#ifndef ST_DISPUTERSV_H
#define ST_DISPUTERSV_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_disputersv_rec_t;
void ST_DISPUTERSV(TPSVCINFO *p);
#endif /* ST_DISPUTERSV_H */

View file

@ -0,0 +1,29 @@
/*
* ST_DISPUTERSV.pgc - st 모듈 서비스 ST_DISPUTERSV (one service = one file).
* 이의신청 결과 반영: 판정(T_STATUS: A=인용/R=기각)에 따라 인용 시 청구액을 양(+)의
* 조정으로 반영하고 지급을 재개(HELD->SCHEDULED), 기각 시 보류를 지급(HELD->PAID)한다.
*/
#include "ST_DISPUTERSV.h"
/* 128. ST_DISPUTERSV - 이의신청 인용/기각 후속 처리. */
void ST_DISPUTERSV(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16], decision[8];
long pid = getl(b, T_PURCHASE_ID), claimed = getl(b, T_DELTA), adj = 0;
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_STATUS, decision, sizeof(decision)); if (decision[0] == 0) strcpy(decision, "R");
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
if (decision[0] == 'A') { /* 인용: 청구액 반영 + 지급 재개 */
adj = stdb_insert_adjust(0, pid, claimed, "DISPUTE_OK", bizdate);
if (adj < 0) FAIL(b);
if (stdb_update_payment_status(merch, "HELD", "SCHEDULED", bizdate) < 0) FAIL(b);
} else { /* 기각: 보류 지급 확정 */
if (stdb_update_payment_status(merch, "HELD", "PAID", bizdate) < 0) FAIL(b);
}
setl(b, T_ADJ, adj);
Bchg(b, T_STATUS, 0, (decision[0] == 'A') ? "OK" : "NG", 0L);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_EVENTFEE.h - st ST_EVENTFEE (copybook / record header).
* .
*/
#ifndef ST_EVENTFEE_H
#define ST_EVENTFEE_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_eventfee_rec_t;
void ST_EVENTFEE(TPSVCINFO *p);
#endif /* ST_EVENTFEE_H */

View file

@ -0,0 +1,26 @@
/*
* ST_EVENTFEE.pgc - st 모듈 서비스 ST_EVENTFEE (one service = one file).
* 이벤트 수수료 감면: 이벤트 기간 거래에 대해 정상 요율의 절반을 적용한 감면
* 수수료를 산출하고 정산 상세에 EVENT 라인으로 기록한다.
*/
#include "ST_EVENTFEE.h"
/* 87. ST_EVENTFEE - 이벤트 반값 수수료 감면 기록. */
void ST_EVENTFEE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
long sid = getl(b, T_SETTLE_ID), pid = getl(b, T_PURCHASE_ID);
long amount = getl(b, T_AMOUNT), bps = getl(b, T_ARG1), fee, dtl;
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
if (bps <= 0) bps = 25;
fee = acq_fee(amount, bps) / 2; /* 이벤트 반값 */
dtl = stdb_insert_fee_dtl(sid, pid, merch, "EVENT", fee, bizdate);
if (dtl < 0) FAIL(b);
setl(b, T_FEE, fee);
setl(b, T_RC, bps / 2);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_FLATFEE.h - st ST_FLATFEE (copybook / record header).
* .
*/
#ifndef ST_FLATFEE_H
#define ST_FLATFEE_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_flat_rec_t;
void ST_FLATFEE(TPSVCINFO *p);
#endif /* ST_FLATFEE_H */

View file

@ -0,0 +1,25 @@
/*
* ST_FLATFEE.pgc - st 모듈 서비스 ST_FLATFEE (one service = one file).
* 정액 수수료 적용: 거래 건마다 고정 금액 수수료를 정산 상세(st_settle_dtl)에
* FLAT 라인으로 기록한다. 요율(bps)과 무관한 정액 과금.
*/
#include "ST_FLATFEE.h"
/* 76. ST_FLATFEE - 정액 수수료 적용 (고정액 정산 상세 기록). */
void ST_FLATFEE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
long sid = getl(b, T_SETTLE_ID), pid = getl(b, T_PURCHASE_ID);
long flat = getl(b, T_ARG1), dtl;
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
if (flat <= 0) flat = 500; /* 기본 정액 500원 */
dtl = stdb_insert_fee_dtl(sid, pid, merch, "FLAT", flat, bizdate);
if (dtl < 0) FAIL(b);
setl(b, T_FEE, flat);
setl(b, T_ID1, dtl);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_FLATVSPCT.h - st ST_FLATVSPCT (copybook / record header).
* .
*/
#ifndef ST_FLATVSPCT_H
#define ST_FLATVSPCT_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_flatvspct_rec_t;
void ST_FLATVSPCT(TPSVCINFO *p);
#endif /* ST_FLATVSPCT_H */

View file

@ -0,0 +1,26 @@
/*
* ST_FLATVSPCT.pgc - st 모듈 서비스 ST_FLATVSPCT (one service = one file).
* 정액 대 정률 비교: 정액(T_ARG1)과 정률(금액 x T_ARG2 bps)을 각각 계산해 더 저렴한
* 과금 방식을 판정하고 채택 수수료/방식코드를 반환한다 (조회 전용).
*/
#include "ST_FLATVSPCT.h"
/* 83. ST_FLATVSPCT - 정액/정률 중 저가 방식 선택. */
void ST_FLATVSPCT(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long amount = getl(b, T_AMOUNT), flat = getl(b, T_ARG1), bps = getl(b, T_ARG2);
long pct, chosen, mode;
if (flat <= 0) flat = 500;
if (bps <= 0) bps = 25;
pct = acq_fee(amount, bps);
if (flat <= pct) { chosen = flat; mode = 0; } /* 0 = 정액 채택 */
else { chosen = pct; mode = 1; } /* 1 = 정률 채택 */
setl(b, T_AMT1, flat);
setl(b, T_AMT2, pct);
setl(b, T_FEE, chosen);
setl(b, T_RC, mode);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_GRADESTAT.h - st ST_GRADESTAT (copybook / record header).
* .
*/
#ifndef ST_GRADESTAT_H
#define ST_GRADESTAT_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_gradestat_rec_t;
void ST_GRADESTAT(TPSVCINFO *p);
#endif /* ST_GRADESTAT_H */

View file

@ -0,0 +1,35 @@
/*
* ST_GRADESTAT.pgc - st 모듈 서비스 ST_GRADESTAT (one service = one file).
* 가맹점 등급별 통계: 가맹점 요율(mdr_bps) 그룹별 가맹점 수를 커서로 집계해 등급
* 분포와 최다 등급 요율을 산출한다 (조회 전용).
*/
#include "ST_GRADESTAT.h"
/* 132. ST_GRADESTAT - mdr_bps 등급별 가맹점 분포. */
void ST_GRADESTAT(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long grades = 0, total = 0, topcnt = 0, topbps = 0;
EXEC SQL BEGIN DECLARE SECTION;
long h_bps, h_cnt;
EXEC SQL END DECLARE SECTION;
EXEC SQL DECLARE gradestat_c CURSOR FOR
SELECT mdr_bps, count(*) FROM merchant GROUP BY mdr_bps ORDER BY mdr_bps;
EXEC SQL OPEN gradestat_c;
if (sqlca.sqlcode < 0) FAIL(b);
for (;;) {
EXEC SQL FETCH gradestat_c INTO :h_bps, :h_cnt;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE gradestat_c; FAIL(b); }
grades++; total += h_cnt;
if (h_cnt > topcnt) { topcnt = h_cnt; topbps = h_bps; }
}
EXEC SQL CLOSE gradestat_c;
setl(b, T_COUNT, grades);
setl(b, T_ARG1, total);
setl(b, T_ARG2, topcnt);
setl(b, T_RC, topbps);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_GROWTHINC.h - st ST_GROWTHINC (copybook / record header).
* ( ).
*/
#ifndef ST_GROWTHINC_H
#define ST_GROWTHINC_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_growthinc_rec_t;
void ST_GROWTHINC(TPSVCINFO *p);
#endif /* ST_GROWTHINC_H */

View file

@ -0,0 +1,44 @@
/*
* ST_GROWTHINC.pgc - st 모듈 서비스 ST_GROWTHINC (one service = one file).
* 성장 인센티브: 당일 매출과 비교일(T_STR1) 매출을 비교해 증가분(성장분)에 대해서만
* 인센티브 요율을 적용한 보상을 조정으로 기록한다.
*/
#include "ST_GROWTHINC.h"
/* 107. ST_GROWTHINC - 전기 대비 매출 성장분 인센티브. */
void ST_GROWTHINC(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16], prevdate[16];
long bps = getl(b, T_ARG1), growth, inc, adj;
EXEC SQL BEGIN DECLARE SECTION;
long h_now, h_prev;
char h_merch[64], h_now_d[16], h_prev_d[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
gets_(b, T_STR1, prevdate, sizeof(prevdate));
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
strncpy(h_now_d, bizdate, sizeof(h_now_d)-1); h_now_d[sizeof(h_now_d)-1] = 0;
strncpy(h_prev_d, prevdate, sizeof(h_prev_d)-1); h_prev_d[sizeof(h_prev_d)-1] = 0;
if (bps <= 0) bps = 30;
EXEC SQL SELECT coalesce(gross_amount,0) INTO :h_now FROM st_merch_settle
WHERE merchant_id = :h_merch AND biz_date = :h_now_d;
if (sqlca.sqlcode < 0) FAIL(b);
if (sqlca.sqlcode == 100) h_now = 0;
EXEC SQL SELECT coalesce(gross_amount,0) INTO :h_prev FROM st_merch_settle
WHERE merchant_id = :h_merch AND biz_date = :h_prev_d;
if (sqlca.sqlcode < 0) FAIL(b);
if (sqlca.sqlcode == 100) h_prev = 0;
growth = h_now - h_prev;
if (growth <= 0) { setl(b, T_RC, 1); setl(b, T_DELTA, 0); OK(b); }
inc = acq_fee(growth, bps);
adj = stdb_insert_adjust(0, 0, inc, "GROWTH", bizdate);
if (adj < 0) FAIL(b);
setl(b, T_ADJ, adj);
setl(b, T_AMT1, growth);
setl(b, T_DELTA, inc);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_GRPALLOC.h - st ST_GRPALLOC (copybook / record header).
* .
*/
#ifndef ST_GRPALLOC_H
#define ST_GRPALLOC_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_grpalloc_rec_t;
void ST_GRPALLOC(TPSVCINFO *p);
#endif /* ST_GRPALLOC_H */

View file

@ -0,0 +1,50 @@
/*
* ST_GRPALLOC.pgc - st 모듈 서비스 ST_GRPALLOC (one service = one file).
* 그룹 정산 배분: 그룹 통합 지급총액(T_AMOUNT)을 구성원의 net 비중에 따라 안분해
* 각 구성원에게 지급 예정(st_payment)으로 등록한다.
*/
#include "ST_GRPALLOC.h"
/* 126. ST_GRPALLOC - net 비중 안분 후 구성원별 지급 등록. */
void ST_GRPALLOC(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char prefix[16], like[24], bizdate[16];
long alloc = getl(b, T_AMOUNT), allocated = 0, members = 0;
EXEC SQL BEGIN DECLARE SECTION;
long h_base, h_mnet;
char h_like[24], h_bizdate[16], h_mid[64];
EXEC SQL END DECLARE SECTION;
gets_(b, T_KEY1, prefix, sizeof(prefix)); if (prefix[0] == 0) strcpy(prefix, "M0");
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
snprintf(like, sizeof(like), "%s%%", prefix);
strncpy(h_like, like, sizeof(h_like)-1); h_like[sizeof(h_like)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT coalesce(sum(net_amount),0) INTO :h_base FROM st_merch_settle
WHERE merchant_id LIKE :h_like AND biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
if (h_base <= 0) { setl(b, T_RC, 1); OK(b); }
EXEC SQL DECLARE grpalloc_c CURSOR FOR
SELECT merchant_id, net_amount FROM st_merch_settle
WHERE merchant_id LIKE :h_like AND biz_date = :h_bizdate ORDER BY merchant_id;
EXEC SQL OPEN grpalloc_c;
if (sqlca.sqlcode < 0) FAIL(b);
for (;;) {
char mid[64];
long share, pay;
EXEC SQL FETCH grpalloc_c INTO :h_mid, :h_mnet;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE grpalloc_c; FAIL(b); }
strncpy(mid, h_mid, sizeof(mid)-1); mid[sizeof(mid)-1] = 0;
share = alloc * h_mnet / h_base; /* net 비중 안분 */
pay = stdb_insert_payment(mid, share, bizdate, "SCHEDULED", bizdate);
if (pay < 0) { EXEC SQL CLOSE grpalloc_c; FAIL(b); }
allocated += share; members++;
}
EXEC SQL CLOSE grpalloc_c;
setl(b, T_COUNT, members);
setl(b, T_AMOUNT, allocated);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_GRPROLLUP.h - st ST_GRPROLLUP (copybook / record header).
* rollup.
*/
#ifndef ST_GRPROLLUP_H
#define ST_GRPROLLUP_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_grprollup_rec_t;
void ST_GRPROLLUP(TPSVCINFO *p);
#endif /* ST_GRPROLLUP_H */

View file

@ -0,0 +1,42 @@
/*
* ST_GRPROLLUP.pgc - st 모듈 서비스 ST_GRPROLLUP (one service = one file).
* 가맹점 그룹 집계 rollup: prefix(T_KEY1) 로 묶인 그룹 구성원의 당일 매출/수수료/net
* 을 커서로 순회 합산해 그룹 통합 집계를 반환한다 (조회 전용).
*/
#include "ST_GRPROLLUP.h"
/* 125. ST_GRPROLLUP - 그룹 구성원 매출/수수료/net rollup. */
void ST_GRPROLLUP(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char prefix[16], like[24], bizdate[16];
long members = 0, tg = 0, tf = 0, tn = 0;
EXEC SQL BEGIN DECLARE SECTION;
long h_g, h_f, h_n;
char h_like[24], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_KEY1, prefix, sizeof(prefix)); if (prefix[0] == 0) strcpy(prefix, "M0");
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
snprintf(like, sizeof(like), "%s%%", prefix);
strncpy(h_like, like, sizeof(h_like)-1); h_like[sizeof(h_like)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL DECLARE grproll_c CURSOR FOR
SELECT gross_amount, fee_amount, net_amount FROM st_merch_settle
WHERE merchant_id LIKE :h_like AND biz_date = :h_bizdate ORDER BY merchant_id;
EXEC SQL OPEN grproll_c;
if (sqlca.sqlcode < 0) FAIL(b);
for (;;) {
EXEC SQL FETCH grproll_c INTO :h_g, :h_f, :h_n;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE grproll_c; FAIL(b); }
members++; tg += h_g; tf += h_f; tn += h_n;
}
EXEC SQL CLOSE grproll_c;
setl(b, T_COUNT, members);
setl(b, T_GROSS, tg);
setl(b, T_FEE, tf);
setl(b, T_NET, tn);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_INSTANTPAY.h - st ST_INSTANTPAY (copybook / record header).
* .
*/
#ifndef ST_INSTANTPAY_H
#define ST_INSTANTPAY_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_instantpay_rec_t;
void ST_INSTANTPAY(TPSVCINFO *p);
#endif /* ST_INSTANTPAY_H */

View file

@ -0,0 +1,24 @@
/*
* ST_INSTANTPAY.pgc - st 모듈 서비스 ST_INSTANTPAY (one service = one file).
* 즉시 정산 지급: 정산 net 을 당일 지급으로 즉시 확정(status=PAID)해 지급
* 원장(st_payment)에 기록한다 (SCHEDULED 단계 없이 즉시 완료).
*/
#include "ST_INSTANTPAY.h"
/* 93. ST_INSTANTPAY - 즉시 지급(PAID) 등록. */
void ST_INSTANTPAY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
long net = getl(b, T_NET), pay;
gets_(b, T_MERCHANT, merch, sizeof(merch)); if (merch[0] == 0) strcpy(merch, "M0000");
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
if (net <= 0) { setl(b, T_RC, 1); OK(b); }
pay = stdb_insert_payment(merch, net, bizdate, "PAID", bizdate);
if (pay < 0) FAIL(b);
setl(b, T_ID1, pay);
Bchg(b, T_STATUS, 0, "PAID", 0L);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_LOCKBATCH.h - st ST_LOCKBATCH (copybook / record header).
* .
*/
#ifndef ST_LOCKBATCH_H
#define ST_LOCKBATCH_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_lockbatch_rec_t;
void ST_LOCKBATCH(TPSVCINFO *p);
#endif /* ST_LOCKBATCH_H */

View file

@ -0,0 +1,28 @@
/*
* ST_LOCKBATCH.pgc - st 모듈 서비스 ST_LOCKBATCH (one service = one file).
* 정산 배치 잠금: 당일 확정된 정산(status=SETTLED)을 일괄 LOCKED 로 전환해 이후
* 조정/재계산을 차단한다. 잠금된 건수를 반환한다.
*/
#include "ST_LOCKBATCH.h"
/* 121. ST_LOCKBATCH - 당일 정산 일괄 잠금(SETTLED->LOCKED). */
void ST_LOCKBATCH(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16];
long locked;
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL UPDATE settlement SET status = 'LOCKED'
WHERE biz_date = :h_bizdate AND status = 'SETTLED';
if (sqlca.sqlcode < 0) FAIL(b);
locked = sqlca.sqlerrd[2];
setl(b, T_COUNT, locked);
setl(b, T_RC, (locked > 0) ? 0 : 1);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_LOYALTY.h - st ST_LOYALTY (copybook / record header).
* .
*/
#ifndef ST_LOYALTY_H
#define ST_LOYALTY_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_loyalty_rec_t;
void ST_LOYALTY(TPSVCINFO *p);
#endif /* ST_LOYALTY_H */

View file

@ -0,0 +1,36 @@
/*
* ST_LOYALTY.pgc - st 모듈 서비스 ST_LOYALTY (one service = one file).
* 로열티 인센티브: 가맹점의 전체 기간 누적 매출(st_merch_settle 전 일자 합계)에
* 소액 요율을 적용한 장기 거래 로열티 보상을 조정으로 기록한다.
*/
#include "ST_LOYALTY.h"
/* 106. ST_LOYALTY - 누적 매출 기반 로열티 보상. */
void ST_LOYALTY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
long bps = getl(b, T_ARG1), bonus, adj;
EXEC SQL BEGIN DECLARE SECTION;
long h_total, h_days;
char h_merch[64];
EXEC SQL END DECLARE SECTION;
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
if (bps <= 0) bps = 5; /* 기본 0.05% 로열티 */
EXEC SQL SELECT coalesce(sum(gross_amount),0), count(*)
INTO :h_total, :h_days FROM st_merch_settle WHERE merchant_id = :h_merch;
if (sqlca.sqlcode < 0) FAIL(b);
if (h_total <= 0) { setl(b, T_RC, 1); OK(b); }
bonus = acq_fee(h_total, bps);
adj = stdb_insert_adjust(0, 0, bonus, "LOYALTY", bizdate);
if (adj < 0) FAIL(b);
setl(b, T_ADJ, adj);
setl(b, T_GROSS, h_total);
setl(b, T_COUNT, h_days);
setl(b, T_DELTA, bonus);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_MKTGSHARE.h - st ST_MKTGSHARE (copybook / record header).
* .
*/
#ifndef ST_MKTGSHARE_H
#define ST_MKTGSHARE_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_mktgshare_rec_t;
void ST_MKTGSHARE(TPSVCINFO *p);
#endif /* ST_MKTGSHARE_H */

View file

@ -0,0 +1,35 @@
/*
* ST_MKTGSHARE.pgc - st 모듈 서비스 ST_MKTGSHARE (one service = one file).
* 마케팅 분담금 정산: 가맹점 일별 집계(st_merch_settle)의 총매출에 분담율
* (T_ARG1 bps)을 적용한 마케팅 분담금을 정산 상세 MKTG 라인으로 기록한다.
*/
#include "ST_MKTGSHARE.h"
/* 91. ST_MKTGSHARE - 매출 기반 마케팅 분담금 부과. */
void ST_MKTGSHARE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
long bps = getl(b, T_ARG1), share, dtl;
EXEC SQL BEGIN DECLARE SECTION;
long h_gross;
char h_merch[64], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (bps <= 0) bps = 50; /* 기본 0.5% 분담 */
EXEC SQL SELECT coalesce(gross_amount,0) INTO :h_gross FROM st_merch_settle
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
if (sqlca.sqlcode == 100 || h_gross <= 0) { setl(b, T_RC, 1); OK(b); }
share = acq_fee(h_gross, bps);
dtl = stdb_insert_fee_dtl(0, 0, merch, "MKTG", share, bizdate);
if (dtl < 0) FAIL(b);
setl(b, T_GROSS, h_gross);
setl(b, T_FEE, share);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_MONTHSTAT.h - st ST_MONTHSTAT (copybook / record header).
* .
*/
#ifndef ST_MONTHSTAT_H
#define ST_MONTHSTAT_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_monthstat_rec_t;
void ST_MONTHSTAT(TPSVCINFO *p);
#endif /* ST_MONTHSTAT_H */

View file

@ -0,0 +1,29 @@
/*
* ST_MONTHSTAT.pgc - st 모듈 서비스 ST_MONTHSTAT (one service = one file).
* 월별 정산 통계: 대상 월(T_STR1, YYYY-MM)에 속하는 정산의 건수/net 합계/최대 net 을
* 월 단위로 집계해 반환한다 (조회 전용).
*/
#include "ST_MONTHSTAT.h"
/* 133. ST_MONTHSTAT - 월(YYYY-MM) 정산 집계. */
void ST_MONTHSTAT(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char month[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_cnt, h_sum, h_max;
char h_month[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_STR1, month, sizeof(month)); if (month[0] == 0) strcpy(month, "2026-07");
strncpy(h_month, month, sizeof(h_month)-1); h_month[sizeof(h_month)-1] = 0;
EXEC SQL SELECT count(*), coalesce(sum(net),0), coalesce(max(net),0)
INTO :h_cnt, :h_sum, :h_max FROM settlement
WHERE to_char(biz_date, 'YYYY-MM') = :h_month;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_COUNT, h_cnt);
setl(b, T_GROSS, h_sum);
setl(b, T_AMT1, h_max);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_NEXTPAYDT.h - st ST_NEXTPAYDT (copybook / record header).
* .
*/
#ifndef ST_NEXTPAYDT_H
#define ST_NEXTPAYDT_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_nextpaydt_rec_t;
void ST_NEXTPAYDT(TPSVCINFO *p);
#endif /* ST_NEXTPAYDT_H */

View file

@ -0,0 +1,21 @@
/*
* ST_NEXTPAYDT.pgc - st 모듈 서비스 ST_NEXTPAYDT (one service = one file).
* 다음 지급 영업일 계산: 입력 영업일의 다음 영업일(주말 스킵)을 공통 유틸
* (acq_next_bizday)로 계산해 지급 예정일 문자열로 반환한다 (조회 전용, 무DB).
*/
#include "ST_NEXTPAYDT.h"
/* 97. ST_NEXTPAYDT - 다음 영업일(지급일) 계산. */
void ST_NEXTPAYDT(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16], nxt[16];
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
if (bizdate[0] == 0) { setl(b, T_RC, 1); OK(b); }
if (acq_next_bizday(bizdate, nxt) < 0) { setl(b, T_RC, -1); FAIL(b); }
Bchg(b, T_STR1, 0, nxt, 0L);
setl(b, T_RC, 0);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_PARTNERSET.h - st ST_PARTNERSET (copybook / record header).
* .
*/
#ifndef ST_PARTNERSET_H
#define ST_PARTNERSET_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_partnerset_rec_t;
void ST_PARTNERSET(TPSVCINFO *p);
#endif /* ST_PARTNERSET_H */

View file

@ -0,0 +1,26 @@
/*
* ST_PARTNERSET.pgc - st 모듈 서비스 ST_PARTNERSET (one service = one file).
* 제휴사 정산 배분: 정산 net 금액에서 제휴 지분율(T_ARG1 bps)만큼을 제휴사
* (T_STR1) 몫으로 떼어 지급 예정(st_payment)으로 등록한다.
*/
#include "ST_PARTNERSET.h"
/* 88. ST_PARTNERSET - 제휴사 지분 지급 예정 등록. */
void ST_PARTNERSET(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char partner[64], bizdate[16];
long net = getl(b, T_NET), bps = getl(b, T_ARG1), share, pay;
gets_(b, T_STR1, partner, sizeof(partner)); if (partner[0] == 0) strcpy(partner, "PARTNER");
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
if (bps <= 0) bps = 2000; /* 기본 제휴 지분 20% */
share = acq_fee(net, bps);
if (share <= 0) { setl(b, T_RC, 1); OK(b); }
pay = stdb_insert_payment(partner, share, bizdate, "SCHEDULED", bizdate);
if (pay < 0) FAIL(b);
setl(b, T_ID1, pay);
setl(b, T_AMOUNT, share);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_PARTPAY.h - st ST_PARTPAY (copybook / record header).
* .
*/
#ifndef ST_PARTPAY_H
#define ST_PARTPAY_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_partpay_rec_t;
void ST_PARTPAY(TPSVCINFO *p);
#endif /* ST_PARTPAY_H */

View file

@ -0,0 +1,26 @@
/*
* ST_PARTPAY.pgc - st 모듈 서비스 ST_PARTPAY (one service = one file).
* 부분 지급 처리: 정산 net 중 일부(T_ARG1)만 당일 지급(PAID)으로 확정하고
* 잔여 지급액을 함께 반환한다 (분할 지급).
*/
#include "ST_PARTPAY.h"
/* 98. ST_PARTPAY - net 일부 부분 지급(PAID). */
void ST_PARTPAY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
long net = getl(b, T_NET), part = getl(b, T_ARG1), remain, pay;
gets_(b, T_MERCHANT, merch, sizeof(merch)); if (merch[0] == 0) strcpy(merch, "M0000");
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
if (part <= 0 || part > net) part = net;
remain = net - part;
pay = stdb_insert_payment(merch, part, bizdate, "PAID", bizdate);
if (pay < 0) FAIL(b);
setl(b, T_ID1, pay);
setl(b, T_AMOUNT, part);
setl(b, T_NET, remain);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_PCTFEE.h - st ST_PCTFEE (copybook / record header).
* .
*/
#ifndef ST_PCTFEE_H
#define ST_PCTFEE_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_pct_rec_t;
void ST_PCTFEE(TPSVCINFO *p);
#endif /* ST_PCTFEE_H */

View file

@ -0,0 +1,27 @@
/*
* ST_PCTFEE.pgc - st 모듈 서비스 ST_PCTFEE (one service = one file).
* 정률 수수료 계산: 거래 금액에 입력 요율(bps, T_ARG1)을 곱해(acq_fee) 수수료를
* 산출하고 정산 상세에 PCT 라인으로 기록한다.
*/
#include "ST_PCTFEE.h"
/* 77. ST_PCTFEE - 정률 수수료 계산 (금액 x bps). */
void ST_PCTFEE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
long sid = getl(b, T_SETTLE_ID), pid = getl(b, T_PURCHASE_ID);
long amount = getl(b, T_AMOUNT), bps = getl(b, T_ARG1), fee, dtl;
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
if (bps <= 0) bps = 25; /* 기본 요율 0.25% */
fee = acq_fee(amount, bps);
dtl = stdb_insert_fee_dtl(sid, pid, merch, "PCT", fee, bizdate);
if (dtl < 0) FAIL(b);
setl(b, T_FEE, fee);
setl(b, T_RC, bps);
setl(b, T_ID1, dtl);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_PRECONFIRM.h - st ST_PRECONFIRM (copybook / record header).
* .
*/
#ifndef ST_PRECONFIRM_H
#define ST_PRECONFIRM_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_preconfirm_rec_t;
void ST_PRECONFIRM(TPSVCINFO *p);
#endif /* ST_PRECONFIRM_H */

View file

@ -0,0 +1,31 @@
/*
* ST_PRECONFIRM.pgc - st 모듈 서비스 ST_PRECONFIRM (one service = one file).
* 정산 확정 전 검증: 당일 지급 중 보류(HELD) 건이 남아있는지 확인해 확정 가능
* 여부를 판정한다. 보류가 없으면 확정 가능(ready)으로 반환한다 (조회 전용).
*/
#include "ST_PRECONFIRM.h"
/* 120. ST_PRECONFIRM - 보류 잔여 여부로 확정 가능 판정. */
void ST_PRECONFIRM(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_held, h_sched;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT count(*) INTO :h_held FROM st_payment
WHERE biz_date = :h_bizdate AND status = 'HELD';
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL SELECT count(*) INTO :h_sched FROM st_payment
WHERE biz_date = :h_bizdate AND status = 'SCHEDULED';
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_AMT1, h_held);
setl(b, T_AMT2, h_sched);
setl(b, T_RC, (h_held == 0) ? 0 : 1); /* 0 = 확정 가능 */
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_PROMOAPPLY.h - st ST_PROMOAPPLY (copybook / record header).
* .
*/
#ifndef ST_PROMOAPPLY_H
#define ST_PROMOAPPLY_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_promoapply_rec_t;
void ST_PROMOAPPLY(TPSVCINFO *p);
#endif /* ST_PROMOAPPLY_H */

View file

@ -0,0 +1,27 @@
/*
* ST_PROMOAPPLY.pgc - st 모듈 서비스 ST_PROMOAPPLY (one service = one file).
* 프로모션 할인 적용: 산정된 수수료(T_FEE)에 프로모션 할인율(T_ARG1 bps)을 적용해
* 할인액을 계산하고 음(-)의 정산 조정으로 기록한다 (수수료 감액).
*/
#include "ST_PROMOAPPLY.h"
/* 86. ST_PROMOAPPLY - 수수료 프로모션 할인(음수 조정). */
void ST_PROMOAPPLY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16];
long sid = getl(b, T_SETTLE_ID), pid = getl(b, T_PURCHASE_ID);
long fee = getl(b, T_FEE), bps = getl(b, T_ARG1), disc, adj;
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
if (bps <= 0) bps = 1000; /* 기본 10% 할인 */
disc = acq_fee(fee, bps);
if (disc <= 0) { setl(b, T_RC, 1); OK(b); }
adj = stdb_insert_adjust(sid, pid, -disc, "PROMO", bizdate);
if (adj < 0) FAIL(b);
setl(b, T_ADJ, adj);
setl(b, T_DELTA, -disc);
setl(b, T_NET, fee - disc);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_RATECARD.h - st ST_RATECARD (copybook / record header).
* ( ).
*/
#ifndef ST_RATECARD_H
#define ST_RATECARD_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_ratecard_rec_t;
void ST_RATECARD(TPSVCINFO *p);
#endif /* ST_RATECARD_H */

View file

@ -0,0 +1,29 @@
/*
* ST_RATECARD.pgc - st 모듈 서비스 ST_RATECARD (one service = one file).
* 요율 카드 조회: 특정 수수료 유형의 등록 구간 개수와 최소/최대 요율을 집계해
* 요율표 요약(요율 카드)을 반환한다 (조회 전용).
*/
#include "ST_RATECARD.h"
/* 80. ST_RATECARD - 요율표 요약(구간수/최소/최대 bps). */
void ST_RATECARD(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char ftype[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_cnt, h_min, h_max;
char h_ftype[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_STR1, ftype, sizeof(ftype)); if (ftype[0] == 0) strcpy(ftype, "MDR");
strncpy(h_ftype, ftype, sizeof(h_ftype)-1); h_ftype[sizeof(h_ftype)-1] = 0;
EXEC SQL SELECT count(*), coalesce(min(rate_bps),0), coalesce(max(rate_bps),0)
INTO :h_cnt, :h_min, :h_max FROM st_fee_rate WHERE fee_type = :h_ftype;
if (sqlca.sqlcode < 0) FAIL(b);
if (h_cnt == 0) { setl(b, T_RC, 1); OK(b); }
setl(b, T_COUNT, h_cnt);
setl(b, T_AMT1, h_min);
setl(b, T_AMT2, h_max);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_RATECMP.h - st ST_RATECMP (copybook / record header).
* .
*/
#ifndef ST_RATECMP_H
#define ST_RATECMP_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_ratecmp_rec_t;
void ST_RATECMP(TPSVCINFO *p);
#endif /* ST_RATECMP_H */

View file

@ -0,0 +1,26 @@
/*
* ST_RATECMP.pgc - st 모듈 서비스 ST_RATECMP (one service = one file).
* 요율 유형 비교: 두 수수료 유형(T_STR1/T_STR2)의 입력 금액 적용 요율을
* dbio(stdb_lookup_rate)로 각각 조회해 요율 차이를 계산한다 (조회 전용).
*/
#include "ST_RATECMP.h"
/* 81. ST_RATECMP - 두 요율 유형 적용 bps 비교. */
void ST_RATECMP(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char ta[16], tb[16];
long amount = getl(b, T_AMOUNT), ra, rb;
gets_(b, T_STR1, ta, sizeof(ta)); if (ta[0] == 0) strcpy(ta, "MDR");
gets_(b, T_STR2, tb, sizeof(tb)); if (tb[0] == 0) strcpy(tb, "VAN");
ra = stdb_lookup_rate(ta, amount);
rb = stdb_lookup_rate(tb, amount);
if (ra < 0 || rb < 0) FAIL(b);
setl(b, T_ARG1, ra);
setl(b, T_ARG2, rb);
setl(b, T_DELTA, ra - rb);
setl(b, T_FEE, acq_fee(amount, ra) - acq_fee(amount, rb));
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_RATEFLOOR.h - st ST_RATEFLOOR (copybook / record header).
* .
*/
#ifndef ST_RATEFLOOR_H
#define ST_RATEFLOOR_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_ratefloor_rec_t;
void ST_RATEFLOOR(TPSVCINFO *p);
#endif /* ST_RATEFLOOR_H */

View file

@ -0,0 +1,29 @@
/*
* ST_RATEFLOOR.pgc - st 모듈 서비스 ST_RATEFLOOR (one service = one file).
* 요율 하한 적용: 정률 수수료(금액 x bps)가 하한액(T_ARG2)에 미달하면 하한으로
* 끌어올려 정산 상세에 FLRFEE 라인으로 기록한다.
*/
#include "ST_RATEFLOOR.h"
/* 85. ST_RATEFLOOR - 정률 수수료 하한 보정 후 기록. */
void ST_RATEFLOOR(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
long sid = getl(b, T_SETTLE_ID), pid = getl(b, T_PURCHASE_ID);
long amount = getl(b, T_AMOUNT), bps = getl(b, T_ARG1), floor = getl(b, T_ARG2);
long fee, lifted = 0, dtl;
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
if (bps <= 0) bps = 25;
if (floor <= 0) floor = 100;
fee = acq_fee(amount, bps);
if (fee < floor) { fee = floor; lifted = 1; }
dtl = stdb_insert_fee_dtl(sid, pid, merch, "FLRFEE", fee, bizdate);
if (dtl < 0) FAIL(b);
setl(b, T_FEE, fee);
setl(b, T_RC, lifted);
OK(b);
}
/* vim: set ts=4 sw=4 et smartindent: */

View file

@ -0,0 +1,19 @@
/*
* ST_RATEMAX.h - st ST_RATEMAX (copybook / record header).
* .
*/
#ifndef ST_RATEMAX_H
#define ST_RATEMAX_H
#include "st_svc.h"
typedef struct {
long in_amount;
long calc_fee;
long result_code;
long row_count;
} st_st_ratemax_rec_t;
void ST_RATEMAX(TPSVCINFO *p);
#endif /* ST_RATEMAX_H */

Some files were not shown because too many files have changed in this diff Show more