규모확장 Wave B: 전 11모듈 svc 75→133·batch 35→46 (BAIS 온라인 1:1)
- svc 825→1,463 (모듈당 133), batch 385→506 (모듈당 46) — 전부 새 고유 실업무 로직 + 카피북 헤더, 디스패처 133 advertise, 한글 기능설명(매니페스트 추출) - BAIS As-Is 대비: 온라인 1,463 vs 1,466(99.8%), 배치 506 vs 503(초과) - 화면 매니페스트 1,463 재생성 - 검증: build DONE modules=11 batches=506, 12서버 runok, xadmin psc 1,466 AVAIL, 매입체인 XA 커밋, 신규서비스 실데이터 스모크, 전 코퍼스 .pgc 클론 0 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ea90bef264
commit
c62d91b7a7
1526 changed files with 59213 additions and 12 deletions
45
app/src/py/batch/py_apprpend_batch.pgc
Normal file
45
app/src/py/batch/py_apprpend_batch.pgc
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* py_apprpend_batch.pgc - py 승인대기 리포트 배치 (커서 GROUP BY, XA).
|
||||
*
|
||||
* 아직 승인 전인 요청(R) 지급건을 가맹점별로 묶어 대기 건수/요청금액 합을
|
||||
* 건수 내림차순 커서로 훑어 stdout 리포트로 출력한다 (승인 워크로드 파악).
|
||||
* Usage: py_apprpend_batch
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
long groups = 0, waiting = 0;
|
||||
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64];
|
||||
long h_cnt, h_amt;
|
||||
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 pap CURSOR FOR
|
||||
SELECT merchant_id, count(*), coalesce(sum(amount),0)
|
||||
FROM py_payout WHERE status = 'R'
|
||||
GROUP BY merchant_id ORDER BY 2 DESC, 1;
|
||||
EXEC SQL OPEN pap;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
for (;;) {
|
||||
EXEC SQL FETCH pap INTO :h_merch, :h_cnt, :h_amt;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE pap; tpabort(0); return 1; }
|
||||
groups++; waiting += h_cnt;
|
||||
printf(" %s: 대기 %ld건 요청 %ld원\n", h_merch, h_cnt, h_amt);
|
||||
}
|
||||
EXEC SQL CLOSE pap;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> py_apprpend_batch COMMIT: merchants=%ld waiting=%ld\n", groups, waiting);
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
47
app/src/py/batch/py_bankverify_batch.pgc
Normal file
47
app/src/py/batch/py_bankverify_batch.pgc
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* py_bankverify_batch.pgc - py 지급파일 전건 대사 배치 (커서 검증, XA).
|
||||
*
|
||||
* 생성(G) 상태 파일을 커서로 훑어 파일 헤더의 건수/금액과 실제 편성 지급건의
|
||||
* 건수/net 합을 비교해 불일치 파일을 리포트한다. 갱신 없이 검증만 수행한다.
|
||||
* host 변수는 전용 카피북 py_bankverify_cpy.h 를 EXEC SQL INCLUDE.
|
||||
* Usage: py_bankverify_batch
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
long files = 0, mism = 0;
|
||||
|
||||
EXEC SQL INCLUDE py_bankverify_cpy;
|
||||
|
||||
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(120, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL DECLARE pbv CURSOR FOR
|
||||
SELECT file_id, record_count, total_amount FROM py_file WHERE status = 'G' ORDER BY file_id;
|
||||
EXEC SQL OPEN pbv;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
for (;;) {
|
||||
EXEC SQL FETCH pbv INTO :c_fid, :c_hcnt, :c_hsum;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE pbv; tpabort(0); return 1; }
|
||||
EXEC SQL SELECT count(*), coalesce(sum(net),0) INTO :c_acnt, :c_asum
|
||||
FROM py_payout WHERE file_id = :c_fid;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE pbv; tpabort(0); return 1; }
|
||||
files++;
|
||||
if (c_hcnt != c_acnt || c_hsum != c_asum) {
|
||||
mism++;
|
||||
printf(" 파일 %ld 불일치: hdr(%ld/%ld) act(%ld/%ld)\n", c_fid, c_hcnt, c_hsum, c_acnt, c_asum);
|
||||
}
|
||||
}
|
||||
EXEC SQL CLOSE pbv;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> py_bankverify_batch COMMIT: files=%ld mismatch=%ld\n", files, mism);
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
4
app/src/py/batch/py_bankverify_cpy.h
Normal file
4
app/src/py/batch/py_bankverify_cpy.h
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
/* py_bankverify_cpy.h - py_bankverify_batch 전용 카피북 (host 변수 선언). */
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long c_fid, c_hcnt, c_hsum, c_acnt, c_asum;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
44
app/src/py/batch/py_carryover_batch.pgc
Normal file
44
app/src/py/batch/py_carryover_batch.pgc
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* py_carryover_batch.pgc - py 미지급 이월 배치 (SELECT 카운트 + UPDATE, XA).
|
||||
*
|
||||
* 지정 기준일 이전의 미지급 요청(R) 건 수를 먼저 집계한 뒤, 그 건들의
|
||||
* biz_date 를 차기 영업일로 일괄 이월한다. ONE XA transaction.
|
||||
* Usage: py_carryover_batch [CUTOFF-YYYY-MM-DD] [NEXT-YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *cut = (argc > 1) ? argv[1] : "2026-07-19";
|
||||
const char *next = (argc > 2) ? argv[2] : "2026-07-20";
|
||||
long moved;
|
||||
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_cut[16], h_next[16];
|
||||
long h_cnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
strncpy(h_cut, cut, sizeof(h_cut)-1); h_cut[sizeof(h_cut)-1] = 0;
|
||||
strncpy(h_next, next, sizeof(h_next)-1); h_next[sizeof(h_next)-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_cnt
|
||||
FROM py_payout WHERE status = 'R' AND biz_date < :h_cut;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "CNT FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
|
||||
EXEC SQL UPDATE py_payout SET biz_date = :h_next, updated_at = now()
|
||||
WHERE status = 'R' AND biz_date < :h_cut;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "UPD FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
moved = sqlca.sqlerrd[2];
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> py_carryover_batch COMMIT: cutoff=%s next=%s candidates=%ld moved=%ld\n", cut, next, h_cnt, moved);
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
39
app/src/py/batch/py_dormscan_batch.pgc
Normal file
39
app/src/py/batch/py_dormscan_batch.pgc
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* py_dormscan_batch.pgc - py 휴면 계좌 스캔 배치 (NOT EXISTS UPDATE, XA).
|
||||
*
|
||||
* 지정 기준일 이후 지급 이력이 전혀 없는 활성(ACTIVE) 계좌를 NOT EXISTS
|
||||
* 서브쿼리로 골라 휴면(DORMANT)으로 일괄 전환한다. ONE XA transaction.
|
||||
* Usage: py_dormscan_batch [SINCE-YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *since = (argc > 1) ? argv[1] : "2026-04-01";
|
||||
long dormant;
|
||||
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_since[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
strncpy(h_since, since, sizeof(h_since)-1); h_since[sizeof(h_since)-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(90, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL UPDATE py_account SET status = 'DORMANT', updated_at = now()
|
||||
WHERE status = 'ACTIVE'
|
||||
AND NOT EXISTS (SELECT 1 FROM py_payout p
|
||||
WHERE p.account_no = py_account.account_no AND p.biz_date >= :h_since);
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "UPD FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
dormant = sqlca.sqlerrd[2];
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> py_dormscan_batch COMMIT: since=%s dormant=%ld\n", since, dormant);
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
41
app/src/py/batch/py_feecap_batch.pgc
Normal file
41
app/src/py/batch/py_feecap_batch.pgc
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* py_feecap_batch.pgc - py 수수료 상한 일괄 적용 배치 (INSERT..SELECT + UPDATE, XA).
|
||||
*
|
||||
* 미지급(R/A) 건 중 수수료가 상한(인자)을 넘는 건을 대상으로, 초과분을
|
||||
* py_adjust 에 양수 조정으로 적재한 뒤 fee 를 상한까지 낮추고 net 을 보정한다.
|
||||
* host 변수는 전용 카피북 py_feecap_cpy.h 를 EXEC SQL INCLUDE.
|
||||
* Usage: py_feecap_batch [YYYY-MM-DD] [CAP]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
|
||||
|
||||
EXEC SQL INCLUDE py_feecap_cpy;
|
||||
|
||||
strncpy(c_bizdate, bizdate, sizeof(c_bizdate)-1); c_bizdate[sizeof(c_bizdate)-1] = 0;
|
||||
c_cap = (argc > 2) ? atol(argv[2]) : 5000;
|
||||
|
||||
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(90, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL INSERT INTO py_adjust (adj_id, payout_id, delta, reason, biz_date)
|
||||
SELECT nextval('py_adjust_seq'), payout_id, fee - :c_cap, '수수료상한배치', :c_bizdate
|
||||
FROM py_payout WHERE status IN ('R','A') AND fee > :c_cap;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "ADJ FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
|
||||
EXEC SQL UPDATE py_payout SET net = net + (fee - :c_cap), fee = :c_cap, updated_at = now()
|
||||
WHERE status IN ('R','A') AND fee > :c_cap;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "UPD FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
c_capped = sqlca.sqlerrd[2];
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> py_feecap_batch COMMIT: bizdate=%s cap=%ld capped=%ld\n", bizdate, c_cap, c_capped);
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
5
app/src/py/batch/py_feecap_cpy.h
Normal file
5
app/src/py/batch/py_feecap_cpy.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
/* py_feecap_cpy.h - py_feecap_batch 전용 카피북 (host 변수 선언). */
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char c_bizdate[16];
|
||||
long c_cap, c_capped;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
45
app/src/py/batch/py_garnish_batch.pgc
Normal file
45
app/src/py/batch/py_garnish_batch.pgc
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* py_garnish_batch.pgc - py 압류/가압류 계좌 지급보류 배치 (커서 + UPDATE, XA).
|
||||
*
|
||||
* 압류(SEIZED)/가압류(GARNISH) 상태 계좌를 커서로 훑어 각 계좌의 미지급(R/A)
|
||||
* 건을 '압류보류'로 보류(H) 전이한다. 계좌별 보류 건수를 리포트한다.
|
||||
* host 변수는 전용 카피북 py_garnish_cpy.h 를 EXEC SQL INCLUDE.
|
||||
* Usage: py_garnish_batch
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
long accts = 0, held = 0;
|
||||
|
||||
EXEC SQL INCLUDE py_garnish_cpy;
|
||||
|
||||
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(120, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL DECLARE pgr CURSOR FOR
|
||||
SELECT account_no FROM py_account WHERE status IN ('SEIZED','GARNISH') ORDER BY account_no;
|
||||
EXEC SQL OPEN pgr;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
for (;;) {
|
||||
EXEC SQL FETCH pgr INTO :c_acct;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE pgr; tpabort(0); return 1; }
|
||||
EXEC SQL UPDATE py_payout SET status = 'H', reject_reason = '압류보류', updated_at = now()
|
||||
WHERE account_no = :c_acct AND status IN ('R','A');
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE pgr; tpabort(0); return 1; }
|
||||
c_held = sqlca.sqlerrd[2];
|
||||
accts++; held += c_held;
|
||||
if (c_held > 0) printf(" 계좌 %s: %ld건 압류보류\n", c_acct, c_held);
|
||||
}
|
||||
EXEC SQL CLOSE pgr;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> py_garnish_batch COMMIT: accounts=%ld held=%ld\n", accts, held);
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
5
app/src/py/batch/py_garnish_cpy.h
Normal file
5
app/src/py/batch/py_garnish_cpy.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
/* py_garnish_cpy.h - py_garnish_batch 전용 카피북 (host 변수 선언). */
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char c_acct[32];
|
||||
long c_held;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
47
app/src/py/batch/py_notifypush_batch.pgc
Normal file
47
app/src/py/batch/py_notifypush_batch.pgc
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* py_notifypush_batch.pgc - py 지급완료 푸시 통지 시뮬 배치 (조인 커서, XA).
|
||||
*
|
||||
* 당일 지급완료(P) 건을 py_account 조인 커서로 훑어 예금주/은행/금액으로
|
||||
* 푸시 통지 발송을 stdout 으로 시뮬레이션한다 (실발송 없음). 은행별 집계 없이
|
||||
* 건별 발송. host 변수는 전용 카피북 py_notifypush_cpy.h 를 EXEC SQL INCLUDE.
|
||||
* Usage: py_notifypush_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
|
||||
long pushed = 0, total = 0;
|
||||
|
||||
EXEC SQL INCLUDE py_notifypush_cpy;
|
||||
|
||||
strncpy(c_bizdate, bizdate, sizeof(c_bizdate)-1); c_bizdate[sizeof(c_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 pnp CURSOR FOR
|
||||
SELECT p.payout_id, p.net, a.holder, a.bank_code
|
||||
FROM py_payout p JOIN py_account a ON p.account_no = a.account_no
|
||||
WHERE p.biz_date = :c_bizdate AND p.status = 'P'
|
||||
ORDER BY a.bank_code, p.payout_id;
|
||||
EXEC SQL OPEN pnp;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
for (;;) {
|
||||
EXEC SQL FETCH pnp INTO :c_pid, :c_net, :c_holder, :c_bank;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE pnp; tpabort(0); return 1; }
|
||||
printf(" [PUSH시뮬] %s(%s) %ld원 지급알림 (payout=%ld)\n", c_holder, c_bank, c_net, c_pid);
|
||||
pushed++; total += c_net;
|
||||
}
|
||||
EXEC SQL CLOSE pnp;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> py_notifypush_batch COMMIT: bizdate=%s pushed=%ld total=%ld\n", bizdate, pushed, total);
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
7
app/src/py/batch/py_notifypush_cpy.h
Normal file
7
app/src/py/batch/py_notifypush_cpy.h
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
/* py_notifypush_cpy.h - py_notifypush_batch 전용 카피북 (host 변수 선언). */
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char c_bizdate[16];
|
||||
char c_holder[64];
|
||||
char c_bank[8];
|
||||
long c_pid, c_net;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
41
app/src/py/batch/py_pendaging_batch.pgc
Normal file
41
app/src/py/batch/py_pendaging_batch.pgc
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* py_pendaging_batch.pgc - py 미지급 경과일 집계 배치 (CASE 단일 집계, XA).
|
||||
*
|
||||
* 미지급(R/A/H) 건을 기준일 대비 경과일수로 당일/3일내/장기(초과) 3구간으로
|
||||
* CASE 분류해 구간별 건수를 한 번의 집계 쿼리로 산출해 리포트한다.
|
||||
* Usage: py_pendaging_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.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_fresh, h_mid, h_old;
|
||||
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(CASE WHEN :h_bizdate::date - biz_date <= 0 THEN 1 ELSE 0 END),0),
|
||||
coalesce(sum(CASE WHEN :h_bizdate::date - biz_date BETWEEN 1 AND 3 THEN 1 ELSE 0 END),0),
|
||||
coalesce(sum(CASE WHEN :h_bizdate::date - biz_date > 3 THEN 1 ELSE 0 END),0)
|
||||
INTO :h_fresh, :h_mid, :h_old
|
||||
FROM py_payout WHERE status IN ('R','A','H');
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "AGG FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> py_pendaging_batch COMMIT: base=%s 당일=%ld 3일내=%ld 장기=%ld\n",
|
||||
bizdate, h_fresh, h_mid, h_old);
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
38
app/src/py/batch/py_requeue_batch.pgc
Normal file
38
app/src/py/batch/py_requeue_batch.pgc
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* py_requeue_batch.pgc - py 실패 재처리 일괄 적재 배치 (단일 UPDATE, XA).
|
||||
*
|
||||
* 당일 반려(J) 건 중 재시도 여력(retry_count<3)이 있는 건을 요청(R)으로
|
||||
* 되돌리며 retry_count 를 +1 해 재처리 큐에 일괄 적재한다. ONE XA txn.
|
||||
* Usage: py_requeue_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
|
||||
long requeued;
|
||||
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
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 UPDATE py_payout
|
||||
SET status = 'R', retry_count = retry_count + 1, reject_reason = '', updated_at = now()
|
||||
WHERE biz_date = :h_bizdate AND status = 'J' AND retry_count < 3;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "UPD FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
requeued = sqlca.sqlerrd[2];
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> py_requeue_batch COMMIT: bizdate=%s requeued=%ld\n", bizdate, requeued);
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
50
app/src/py/batch/py_statmonth_batch.pgc
Normal file
50
app/src/py/batch/py_statmonth_batch.pgc
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* py_statmonth_batch.pgc - py 월별 지급 집계 리포트 배치 (커서 GROUP BY, XA).
|
||||
*
|
||||
* 지정 기간의 지급건을 'YYYY-MM' 월 단위로 묶어 월별 건수/net 합을 커서로
|
||||
* 훑어 stdout 리포트로 출력한다 (갱신 없음, 읽기 전용 리포트).
|
||||
* Usage: py_statmonth_batch [FROM-YYYY-MM-DD] [TO-YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *from = (argc > 1) ? argv[1] : "2026-01-01";
|
||||
const char *to = (argc > 2) ? argv[2] : "2026-12-31";
|
||||
long months = 0, grand = 0;
|
||||
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_from[16], h_to[16], h_mon[16];
|
||||
long h_cnt, h_amt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
strncpy(h_from, from, sizeof(h_from)-1); h_from[sizeof(h_from)-1] = 0;
|
||||
strncpy(h_to, to, sizeof(h_to)-1); h_to[sizeof(h_to)-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(90, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL DECLARE psm CURSOR FOR
|
||||
SELECT to_char(biz_date, 'YYYY-MM'), count(*), coalesce(sum(net),0)
|
||||
FROM py_payout WHERE biz_date BETWEEN :h_from AND :h_to
|
||||
GROUP BY 1 ORDER BY 1;
|
||||
EXEC SQL OPEN psm;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
for (;;) {
|
||||
EXEC SQL FETCH psm INTO :h_mon, :h_cnt, :h_amt;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE psm; tpabort(0); return 1; }
|
||||
months++; grand += h_amt;
|
||||
printf(" %s: %ld건 %ld원\n", h_mon, h_cnt, h_amt);
|
||||
}
|
||||
EXEC SQL CLOSE psm;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> py_statmonth_batch COMMIT: months=%ld grand=%ld\n", months, grand);
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
50
app/src/py/batch/py_xferconf_batch.pgc
Normal file
50
app/src/py/batch/py_xferconf_batch.pgc
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* py_xferconf_batch.pgc - py 이체 기표 일괄 확정 배치 (커서 + INSERT, XA).
|
||||
*
|
||||
* 당일 지급완료(P) 이면서 XFER 기표가 아직 없는 건을 NOT EXISTS 커서로 뽑아
|
||||
* py_ledger 에 net 만큼 XFER 기표를 일괄 생성한다. ONE XA txn.
|
||||
* host 변수는 전용 카피북 py_xferconf_cpy.h 를 EXEC SQL INCLUDE.
|
||||
* Usage: py_xferconf_batch [YYYY-MM-DD]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
|
||||
long posted = 0;
|
||||
|
||||
EXEC SQL INCLUDE py_xferconf_cpy;
|
||||
|
||||
strncpy(c_bizdate, bizdate, sizeof(c_bizdate)-1); c_bizdate[sizeof(c_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(120, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL DECLARE pxc CURSOR FOR
|
||||
SELECT payout_id, net FROM py_payout p
|
||||
WHERE p.biz_date = :c_bizdate AND p.status = 'P'
|
||||
AND NOT EXISTS (SELECT 1 FROM py_ledger l
|
||||
WHERE l.payout_id = p.payout_id AND l.entry_type = 'XFER')
|
||||
ORDER BY payout_id;
|
||||
EXEC SQL OPEN pxc;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
for (;;) {
|
||||
EXEC SQL FETCH pxc INTO :c_pid, :c_net;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE pxc; tpabort(0); return 1; }
|
||||
EXEC SQL INSERT INTO py_ledger (ledger_id, payout_id, entry_type, amount, biz_date)
|
||||
VALUES (nextval('py_ledger_seq'), :c_pid, 'XFER', :c_net, :c_bizdate);
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE pxc; tpabort(0); return 1; }
|
||||
posted++;
|
||||
}
|
||||
EXEC SQL CLOSE pxc;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> py_xferconf_batch COMMIT: bizdate=%s posted=%ld\n", bizdate, posted);
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
5
app/src/py/batch/py_xferconf_cpy.h
Normal file
5
app/src/py/batch/py_xferconf_cpy.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
/* py_xferconf_cpy.h - py_xferconf_batch 전용 카피북 (host 변수 선언). */
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char c_bizdate[16];
|
||||
long c_pid, c_net;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
* py_svr.pgc - py (지급) MODULE SERVER (thin dispatcher).
|
||||
*
|
||||
* The legacy "one module server, many services" pattern: this binary owns NO
|
||||
* business logic. Each of py's 75 online services now lives in its own file
|
||||
* business logic. Each of py's 133 online services now lives in its own file
|
||||
* (app/src/py/svc/<SVCNAME>.pgc) with its own copybook header
|
||||
* (app/src/py/svc/<SVCNAME>.h); those objects are archived into libpysvc.a and
|
||||
* linked into this server. Here we only:
|
||||
|
|
@ -94,6 +94,64 @@
|
|||
#include "PAY_LEDGERSUM.h"
|
||||
#include "PAY_ACCTLIST.h"
|
||||
#include "PAY_NETRECALC.h"
|
||||
#include "PAY_XFERFILE.h"
|
||||
#include "PAY_FILECONF.h"
|
||||
#include "PAY_FILECANCEL.h"
|
||||
#include "PAY_BANKVERIFY.h"
|
||||
#include "PAY_XFERTYPE.h"
|
||||
#include "PAY_NOTIFYPUSH.h"
|
||||
#include "PAY_NOTIFYKAKAO.h"
|
||||
#include "PAY_NOTIFYALL.h"
|
||||
#include "PAY_NOTIFYFAIL.h"
|
||||
#include "PAY_NOTIFYRESEND.h"
|
||||
#include "PAY_ACCTVERIFY.h"
|
||||
#include "PAY_ACCTFREEZE.h"
|
||||
#include "PAY_ACCTREOPEN.h"
|
||||
#include "PAY_REPAYACCT.h"
|
||||
#include "PAY_HOLDBYRSN.h"
|
||||
#include "PAY_HOLDCLEAR.h"
|
||||
#include "PAY_HOLDEXT.h"
|
||||
#include "PAY_HOLDNOTE.h"
|
||||
#include "PAY_SEIZELIST.h"
|
||||
#include "PAY_SEIZEAMT.h"
|
||||
#include "PAY_OFFSETAPPLY.h"
|
||||
#include "PAY_GARNISH.h"
|
||||
#include "PAY_ADVGRANT.h"
|
||||
#include "PAY_URGENTQ.h"
|
||||
#include "PAY_RESVLIST.h"
|
||||
#include "PAY_RESVMODIFY.h"
|
||||
#include "PAY_SPLITEVEN.h"
|
||||
#include "PAY_CARRYOVER.h"
|
||||
#include "PAY_COMBINE.h"
|
||||
#include "PAY_ROLLFWD.h"
|
||||
#include "PAY_FEEFIXED.h"
|
||||
#include "PAY_FEECAP.h"
|
||||
#include "PAY_FEEREFUND.h"
|
||||
#include "PAY_FEESUM.h"
|
||||
#include "PAY_FAILRSN.h"
|
||||
#include "PAY_REQUEUE.h"
|
||||
#include "PAY_FAILCLEAR.h"
|
||||
#include "PAY_RETRYONE.h"
|
||||
#include "PAY_XFERDIFF.h"
|
||||
#include "PAY_XFERUNMATCH.h"
|
||||
#include "PAY_VOIDONE.h"
|
||||
#include "PAY_RECLAIM.h"
|
||||
#include "PAY_CHARGEBACK.h"
|
||||
#include "PAY_LIMITSET.h"
|
||||
#include "PAY_LIMITLIST.h"
|
||||
#include "PAY_LIMITWARN.h"
|
||||
#include "PAY_APPRHIST.h"
|
||||
#include "PAY_APPRCANCEL.h"
|
||||
#include "PAY_CLOSEDSTOP.h"
|
||||
#include "PAY_DORMLIST.h"
|
||||
#include "PAY_REACTIVATE.h"
|
||||
#include "PAY_STATSTATUS.h"
|
||||
#include "PAY_STATAMT.h"
|
||||
#include "PAY_STATFEE.h"
|
||||
#include "PAY_STATMONTH.h"
|
||||
#include "PAY_PENDLIST.h"
|
||||
#include "PAY_APPRPEND.h"
|
||||
#include "PAY_XFERCONF.h"
|
||||
|
||||
/* ----- advertise table: {service name, function} (fn is extern from its file) */
|
||||
static struct { const char *name; void (*fn)(TPSVCINFO *); } SVCS[] = {
|
||||
|
|
@ -135,6 +193,64 @@ static struct { const char *name; void (*fn)(TPSVCINFO *); } SVCS[] = {
|
|||
{"PAY_STATRANGE", PAY_STATRANGE}, {"PAY_SCHEDCANCEL", PAY_SCHEDCANCEL},
|
||||
{"PAY_LEDGERSUM", PAY_LEDGERSUM}, {"PAY_ACCTLIST", PAY_ACCTLIST},
|
||||
{"PAY_NETRECALC", PAY_NETRECALC},
|
||||
{"PAY_XFERFILE", PAY_XFERFILE},
|
||||
{"PAY_FILECONF", PAY_FILECONF},
|
||||
{"PAY_FILECANCEL", PAY_FILECANCEL},
|
||||
{"PAY_BANKVERIFY", PAY_BANKVERIFY},
|
||||
{"PAY_XFERTYPE", PAY_XFERTYPE},
|
||||
{"PAY_NOTIFYPUSH", PAY_NOTIFYPUSH},
|
||||
{"PAY_NOTIFYKAKAO", PAY_NOTIFYKAKAO},
|
||||
{"PAY_NOTIFYALL", PAY_NOTIFYALL},
|
||||
{"PAY_NOTIFYFAIL", PAY_NOTIFYFAIL},
|
||||
{"PAY_NOTIFYRESEND", PAY_NOTIFYRESEND},
|
||||
{"PAY_ACCTVERIFY", PAY_ACCTVERIFY},
|
||||
{"PAY_ACCTFREEZE", PAY_ACCTFREEZE},
|
||||
{"PAY_ACCTREOPEN", PAY_ACCTREOPEN},
|
||||
{"PAY_REPAYACCT", PAY_REPAYACCT},
|
||||
{"PAY_HOLDBYRSN", PAY_HOLDBYRSN},
|
||||
{"PAY_HOLDCLEAR", PAY_HOLDCLEAR},
|
||||
{"PAY_HOLDEXT", PAY_HOLDEXT},
|
||||
{"PAY_HOLDNOTE", PAY_HOLDNOTE},
|
||||
{"PAY_SEIZELIST", PAY_SEIZELIST},
|
||||
{"PAY_SEIZEAMT", PAY_SEIZEAMT},
|
||||
{"PAY_OFFSETAPPLY", PAY_OFFSETAPPLY},
|
||||
{"PAY_GARNISH", PAY_GARNISH},
|
||||
{"PAY_ADVGRANT", PAY_ADVGRANT},
|
||||
{"PAY_URGENTQ", PAY_URGENTQ},
|
||||
{"PAY_RESVLIST", PAY_RESVLIST},
|
||||
{"PAY_RESVMODIFY", PAY_RESVMODIFY},
|
||||
{"PAY_SPLITEVEN", PAY_SPLITEVEN},
|
||||
{"PAY_CARRYOVER", PAY_CARRYOVER},
|
||||
{"PAY_COMBINE", PAY_COMBINE},
|
||||
{"PAY_ROLLFWD", PAY_ROLLFWD},
|
||||
{"PAY_FEEFIXED", PAY_FEEFIXED},
|
||||
{"PAY_FEECAP", PAY_FEECAP},
|
||||
{"PAY_FEEREFUND", PAY_FEEREFUND},
|
||||
{"PAY_FEESUM", PAY_FEESUM},
|
||||
{"PAY_FAILRSN", PAY_FAILRSN},
|
||||
{"PAY_REQUEUE", PAY_REQUEUE},
|
||||
{"PAY_FAILCLEAR", PAY_FAILCLEAR},
|
||||
{"PAY_RETRYONE", PAY_RETRYONE},
|
||||
{"PAY_XFERDIFF", PAY_XFERDIFF},
|
||||
{"PAY_XFERUNMATCH", PAY_XFERUNMATCH},
|
||||
{"PAY_VOIDONE", PAY_VOIDONE},
|
||||
{"PAY_RECLAIM", PAY_RECLAIM},
|
||||
{"PAY_CHARGEBACK", PAY_CHARGEBACK},
|
||||
{"PAY_LIMITSET", PAY_LIMITSET},
|
||||
{"PAY_LIMITLIST", PAY_LIMITLIST},
|
||||
{"PAY_LIMITWARN", PAY_LIMITWARN},
|
||||
{"PAY_APPRHIST", PAY_APPRHIST},
|
||||
{"PAY_APPRCANCEL", PAY_APPRCANCEL},
|
||||
{"PAY_CLOSEDSTOP", PAY_CLOSEDSTOP},
|
||||
{"PAY_DORMLIST", PAY_DORMLIST},
|
||||
{"PAY_REACTIVATE", PAY_REACTIVATE},
|
||||
{"PAY_STATSTATUS", PAY_STATSTATUS},
|
||||
{"PAY_STATAMT", PAY_STATAMT},
|
||||
{"PAY_STATFEE", PAY_STATFEE},
|
||||
{"PAY_STATMONTH", PAY_STATMONTH},
|
||||
{"PAY_PENDLIST", PAY_PENDLIST},
|
||||
{"PAY_APPRPEND", PAY_APPRPEND},
|
||||
{"PAY_XFERCONF", PAY_XFERCONF},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
|||
20
app/src/py/svc/PAY_ACCTFREEZE.h
Normal file
20
app/src/py/svc/PAY_ACCTFREEZE.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_ACCTFREEZE.h - py 서비스 PAY_ACCTFREEZE 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_ACCTFREEZE.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_ACCTFREEZE_H
|
||||
#define PAY_ACCTFREEZE_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_acctfreeze_rec_t;
|
||||
|
||||
void PAY_ACCTFREEZE(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_ACCTFREEZE_H */
|
||||
34
app/src/py/svc/PAY_ACCTFREEZE.pgc
Normal file
34
app/src/py/svc/PAY_ACCTFREEZE.pgc
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* PAY_ACCTFREEZE.pgc - py 모듈 서비스 PAY_ACCTFREEZE (one service = one file).
|
||||
* 지급계좌 동결: 활성(ACTIVE) 계좌만 FROZEN 으로 전환한다. 먼저 해당 계좌의
|
||||
* 미지급(R/A) 건수를 조회해 함께 회신하고, 동결 대상이 아니면 거절한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_ACCTFREEZE.h"
|
||||
|
||||
void PAY_ACCTFREEZE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_acct[32];
|
||||
long h_pend;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_KEY1, h_acct, sizeof(h_acct));
|
||||
EXEC SQL SELECT count(*) INTO :h_pend
|
||||
FROM py_payout WHERE account_no = :h_acct AND status IN ('R','A');
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL UPDATE py_account SET status = 'FROZEN', updated_at = now()
|
||||
WHERE account_no = :h_acct AND status = 'ACTIVE';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (sqlca.sqlerrd[2] == 0) {
|
||||
setl(b, T_RC, 1);
|
||||
Bchg(b, T_MSG, 0, "동결 대상 아님(활성계좌 아님)", 0L);
|
||||
FAIL(b);
|
||||
}
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_COUNT, h_pend);
|
||||
Bchg(b, T_STATUS, 0, "FROZEN", 0L);
|
||||
userlog("PAY_ACCTFREEZE acct=%s pending=%ld", h_acct, h_pend);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_ACCTREOPEN.h
Normal file
20
app/src/py/svc/PAY_ACCTREOPEN.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_ACCTREOPEN.h - py 서비스 PAY_ACCTREOPEN 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_ACCTREOPEN.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_ACCTREOPEN_H
|
||||
#define PAY_ACCTREOPEN_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_acctreopen_rec_t;
|
||||
|
||||
void PAY_ACCTREOPEN(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_ACCTREOPEN_H */
|
||||
36
app/src/py/svc/PAY_ACCTREOPEN.pgc
Normal file
36
app/src/py/svc/PAY_ACCTREOPEN.pgc
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* PAY_ACCTREOPEN.pgc - py 모듈 서비스 PAY_ACCTREOPEN (one service = one file).
|
||||
* 동결 해제: 동결(FROZEN) 계좌를 ACTIVE 로 복구하고, 동결 사유로 보류(H)됐던
|
||||
* 그 계좌의 지급건을 승인(A)으로 되돌린다. 동결 계좌가 아니면 거절한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_ACCTREOPEN.h"
|
||||
|
||||
void PAY_ACCTREOPEN(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_acct[32];
|
||||
long h_rel;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_KEY1, h_acct, sizeof(h_acct));
|
||||
EXEC SQL UPDATE py_account SET status = 'ACTIVE', updated_at = now()
|
||||
WHERE account_no = :h_acct AND status = 'FROZEN';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (sqlca.sqlerrd[2] == 0) {
|
||||
setl(b, T_RC, 1);
|
||||
Bchg(b, T_MSG, 0, "동결 계좌 아님", 0L);
|
||||
FAIL(b);
|
||||
}
|
||||
EXEC SQL UPDATE py_payout SET status = 'A', reject_reason = '', updated_at = now()
|
||||
WHERE account_no = :h_acct AND status = 'H' AND reject_reason LIKE '동결%';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
h_rel = sqlca.sqlerrd[2];
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_COUNT, h_rel);
|
||||
Bchg(b, T_STATUS, 0, "ACTIVE", 0L);
|
||||
userlog("PAY_ACCTREOPEN acct=%s released=%ld", h_acct, h_rel);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_ACCTVERIFY.h
Normal file
20
app/src/py/svc/PAY_ACCTVERIFY.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_ACCTVERIFY.h - py 서비스 PAY_ACCTVERIFY 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_ACCTVERIFY.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_ACCTVERIFY_H
|
||||
#define PAY_ACCTVERIFY_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_acctverify_rec_t;
|
||||
|
||||
void PAY_ACCTVERIFY(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_ACCTVERIFY_H */
|
||||
34
app/src/py/svc/PAY_ACCTVERIFY.pgc
Normal file
34
app/src/py/svc/PAY_ACCTVERIFY.pgc
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* PAY_ACCTVERIFY.pgc - py 모듈 서비스 PAY_ACCTVERIFY (one service = one file).
|
||||
* 지급계좌 검증: 계좌의 상태/예금주/잔액을 조회하고, 요청에 예금주가 주어지면
|
||||
* 일치 여부까지 확인한다. 미등록/불일치는 사유코드로 구분해 회신한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_ACCTVERIFY.h"
|
||||
|
||||
void PAY_ACCTVERIFY(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char inh[64];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_acct[32], h_st[16], h_holder[64];
|
||||
long h_bal;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_KEY1, h_acct, sizeof(h_acct));
|
||||
gets_(b, T_STR1, inh, sizeof(inh));
|
||||
EXEC SQL SELECT status, holder, balance INTO :h_st, :h_holder, :h_bal
|
||||
FROM py_account WHERE account_no = :h_acct;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 2); Bchg(b, T_MSG, 0, "미등록 계좌", 0L); FAIL(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (inh[0] != 0 && strcmp(inh, h_holder) != 0) {
|
||||
setl(b, T_RC, 1);
|
||||
Bchg(b, T_MSG, 0, "예금주 불일치", 0L);
|
||||
FAIL(b);
|
||||
}
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_AMT1, h_bal);
|
||||
Bchg(b, T_STATUS, 0, h_st, 0L);
|
||||
Bchg(b, T_STR2, 0, h_holder, 0L);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_ADVGRANT.h
Normal file
20
app/src/py/svc/PAY_ADVGRANT.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_ADVGRANT.h - py 서비스 PAY_ADVGRANT 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_ADVGRANT.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_ADVGRANT_H
|
||||
#define PAY_ADVGRANT_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_advgrant_rec_t;
|
||||
|
||||
void PAY_ADVGRANT(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_ADVGRANT_H */
|
||||
32
app/src/py/svc/PAY_ADVGRANT.pgc
Normal file
32
app/src/py/svc/PAY_ADVGRANT.pgc
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* PAY_ADVGRANT.pgc - py 모듈 서비스 PAY_ADVGRANT (one service = one file).
|
||||
* 선지급 승인: 선지급(ADVANCE) 채널의 요청(R) 건만 승인(A)으로 전이한다.
|
||||
* 채널/상태를 함께 가드하며, 대상이 아니면 사유코드로 구분해 회신한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_ADVGRANT.h"
|
||||
|
||||
void PAY_ADVGRANT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_amt;
|
||||
char h_st[4], h_chan[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_pid = getl(b, T_ID1);
|
||||
EXEC SQL SELECT status, channel, amount INTO :h_st, :h_chan, :h_amt
|
||||
FROM py_payout WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
|
||||
if (strcmp(h_chan, "ADVANCE") != 0) { setl(b, T_RC, 2); Bchg(b, T_MSG, 0, "선지급 건 아님", 0L); FAIL(b); }
|
||||
if (h_st[0] != 'R') { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "요청 상태만 승인 가능", 0L); FAIL(b); }
|
||||
|
||||
EXEC SQL UPDATE py_payout SET status = 'A', updated_at = now() WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_AMOUNT, h_amt);
|
||||
Bchg(b, T_STATUS, 0, "A", 0L);
|
||||
userlog("PAY_ADVGRANT payout=%ld amt=%ld", h_pid, h_amt);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_APPRCANCEL.h
Normal file
20
app/src/py/svc/PAY_APPRCANCEL.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_APPRCANCEL.h - py 서비스 PAY_APPRCANCEL 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_APPRCANCEL.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_APPRCANCEL_H
|
||||
#define PAY_APPRCANCEL_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_apprcancel_rec_t;
|
||||
|
||||
void PAY_APPRCANCEL(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_APPRCANCEL_H */
|
||||
28
app/src/py/svc/PAY_APPRCANCEL.pgc
Normal file
28
app/src/py/svc/PAY_APPRCANCEL.pgc
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* PAY_APPRCANCEL.pgc - py 모듈 서비스 PAY_APPRCANCEL (one service = one file).
|
||||
* 지급 승인 취소: 아직 파일에 편성되지 않은 승인(A) 건을 요청(R)으로 되돌린다.
|
||||
* 파일편성(F)/지급완료(P) 이후에는 승인 취소가 불가하다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_APPRCANCEL.h"
|
||||
|
||||
void PAY_APPRCANCEL(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long reverted;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_pid = getl(b, T_ID1);
|
||||
EXEC SQL UPDATE py_payout SET status = 'R', updated_at = now()
|
||||
WHERE payout_id = :h_pid AND status = 'A';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
reverted = sqlca.sqlerrd[2];
|
||||
if (reverted == 0) { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "승인 상태 건만 취소 가능", 0L); FAIL(b); }
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
Bchg(b, T_STATUS, 0, "R", 0L);
|
||||
userlog("PAY_APPRCANCEL payout=%ld -> R", h_pid);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_APPRHIST.h
Normal file
20
app/src/py/svc/PAY_APPRHIST.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_APPRHIST.h - py 서비스 PAY_APPRHIST 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_APPRHIST.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_APPRHIST_H
|
||||
#define PAY_APPRHIST_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_apprhist_rec_t;
|
||||
|
||||
void PAY_APPRHIST(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_APPRHIST_H */
|
||||
41
app/src/py/svc/PAY_APPRHIST.pgc
Normal file
41
app/src/py/svc/PAY_APPRHIST.pgc
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* PAY_APPRHIST.pgc - py 모듈 서비스 PAY_APPRHIST (one service = one file).
|
||||
* 지급 승인/원장 이력: 지정 지급건의 py_ledger 기표를 시간순 커서로 훑어
|
||||
* 기표유형/금액/일자를 occurrence 로 회신한다 (승인·이체·환입 흐름 추적).
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_APPRHIST.h"
|
||||
|
||||
void PAY_APPRHIST(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
int i = 0;
|
||||
long rows = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_amt;
|
||||
char h_type[16], h_date[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_pid = getl(b, T_ID1);
|
||||
EXEC SQL DECLARE cur_apprhist CURSOR FOR
|
||||
SELECT entry_type, amount, CAST(biz_date AS text)
|
||||
FROM py_ledger WHERE payout_id = :h_pid ORDER BY ledger_id;
|
||||
EXEC SQL OPEN cur_apprhist;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
for (;;) {
|
||||
EXEC SQL FETCH cur_apprhist INTO :h_type, :h_amt, :h_date;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE cur_apprhist; FAIL(b); }
|
||||
rows++;
|
||||
if (i < 12) {
|
||||
Bchg(b, T_STR3, i, h_type, 0L);
|
||||
Bchg(b, T_AMT1, i, (char *)&h_amt, 0L);
|
||||
Bchg(b, T_STR4, i, h_date, 0L);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
EXEC SQL CLOSE cur_apprhist;
|
||||
setl(b, T_COUNT, rows);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_APPRPEND.h
Normal file
20
app/src/py/svc/PAY_APPRPEND.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_APPRPEND.h - py 서비스 PAY_APPRPEND 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_APPRPEND.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_APPRPEND_H
|
||||
#define PAY_APPRPEND_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_apprpend_rec_t;
|
||||
|
||||
void PAY_APPRPEND(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_APPRPEND_H */
|
||||
43
app/src/py/svc/PAY_APPRPEND.pgc
Normal file
43
app/src/py/svc/PAY_APPRPEND.pgc
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* PAY_APPRPEND.pgc - py 모듈 서비스 PAY_APPRPEND (one service = one file).
|
||||
* 승인 대기 집계: 아직 승인 전인 요청(R) 지급건을 가맹점별로 묶어 대기 건수/
|
||||
* 요청금액 합을 건수 내림차순 occurrence 로 회신한다 (승인 워크로드 파악).
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_APPRPEND.h"
|
||||
|
||||
void PAY_APPRPEND(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
int i = 0;
|
||||
long grp = 0, waiting = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64];
|
||||
long h_cnt, h_amt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
EXEC SQL DECLARE cur_apprpend CURSOR FOR
|
||||
SELECT merchant_id, count(*), coalesce(sum(amount),0)
|
||||
FROM py_payout WHERE status = 'R'
|
||||
GROUP BY merchant_id ORDER BY 2 DESC, 1;
|
||||
EXEC SQL OPEN cur_apprpend;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
for (;;) {
|
||||
EXEC SQL FETCH cur_apprpend INTO :h_merch, :h_cnt, :h_amt;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE cur_apprpend; FAIL(b); }
|
||||
grp++;
|
||||
waiting += h_cnt;
|
||||
if (i < 10) {
|
||||
Bchg(b, T_STR2, i, h_merch, 0L);
|
||||
Bchg(b, T_ARG3, i, (char *)&h_cnt, 0L);
|
||||
Bchg(b, T_AMT1, i, (char *)&h_amt, 0L);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
EXEC SQL CLOSE cur_apprpend;
|
||||
setl(b, T_COUNT, grp);
|
||||
setl(b, T_ARG2, waiting);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_BANKVERIFY.h
Normal file
20
app/src/py/svc/PAY_BANKVERIFY.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_BANKVERIFY.h - py 서비스 PAY_BANKVERIFY 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_BANKVERIFY.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_BANKVERIFY_H
|
||||
#define PAY_BANKVERIFY_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_bankverify_rec_t;
|
||||
|
||||
void PAY_BANKVERIFY(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_BANKVERIFY_H */
|
||||
37
app/src/py/svc/PAY_BANKVERIFY.pgc
Normal file
37
app/src/py/svc/PAY_BANKVERIFY.pgc
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* PAY_BANKVERIFY.pgc - py 모듈 서비스 PAY_BANKVERIFY (one service = one file).
|
||||
* 지급파일 검증: 파일 헤더(record_count/total_amount)와 실제 편성 지급건의
|
||||
* 건수/net 합을 대사해 일치 여부와 금액 차액(T_DELTA)을 회신한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_BANKVERIFY.h"
|
||||
|
||||
void PAY_BANKVERIFY(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_fid, h_hcnt, h_hsum, h_acnt, h_asum;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_fid = getl(b, T_ID2);
|
||||
EXEC SQL SELECT record_count, total_amount INTO :h_hcnt, :h_hsum
|
||||
FROM py_file WHERE file_id = :h_fid;
|
||||
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
|
||||
EXEC SQL SELECT count(*), coalesce(sum(net),0) INTO :h_acnt, :h_asum
|
||||
FROM py_payout WHERE file_id = :h_fid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_AMT1, h_hsum);
|
||||
setl(b, T_AMT2, h_asum);
|
||||
setl(b, T_COUNT, h_acnt);
|
||||
setl(b, T_DELTA, h_hsum - h_asum);
|
||||
if (h_hcnt == h_acnt && h_hsum == h_asum) {
|
||||
setl(b, T_RC, 0);
|
||||
Bchg(b, T_MSG, 0, "파일 대사 일치", 0L);
|
||||
} else {
|
||||
setl(b, T_RC, 1);
|
||||
Bchg(b, T_MSG, 0, "파일 대사 불일치", 0L);
|
||||
userlog("PAY_BANKVERIFY 불일치 file=%ld hcnt=%ld acnt=%ld", h_fid, h_hcnt, h_acnt);
|
||||
}
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_CARRYOVER.h
Normal file
20
app/src/py/svc/PAY_CARRYOVER.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_CARRYOVER.h - py 서비스 PAY_CARRYOVER 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_CARRYOVER.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_CARRYOVER_H
|
||||
#define PAY_CARRYOVER_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_carryover_rec_t;
|
||||
|
||||
void PAY_CARRYOVER(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_CARRYOVER_H */
|
||||
40
app/src/py/svc/PAY_CARRYOVER.pgc
Normal file
40
app/src/py/svc/PAY_CARRYOVER.pgc
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* PAY_CARRYOVER.pgc - py 모듈 서비스 PAY_CARRYOVER (one service = one file).
|
||||
* 지급 이월(단건): 미지급(R/A) 건의 지급기준일(biz_date)을 지정 차기일자로
|
||||
* 이월하고, 이월 사유를 py_adjust 에 0원 조정으로 증적으로 남긴다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_CARRYOVER.h"
|
||||
|
||||
void PAY_CARRYOVER(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char nextdate[16], reason[96];
|
||||
long adj;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid;
|
||||
char h_st[4], h_next[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_pid = getl(b, T_ID1);
|
||||
gets_(b, T_KEY2, nextdate, sizeof(nextdate));
|
||||
gets_(b, T_REASON, reason, sizeof(reason));
|
||||
if (nextdate[0] == 0) { setl(b, T_RC, 2); Bchg(b, T_MSG, 0, "이월일자 미지정", 0L); FAIL(b); }
|
||||
if (reason[0] == 0) strcpy(reason, "지급이월");
|
||||
strncpy(h_next, nextdate, sizeof(h_next)-1); h_next[sizeof(h_next)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT status INTO :h_st FROM py_payout WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
|
||||
if (h_st[0] != 'R' && h_st[0] != 'A') { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "미지급 건만 이월 가능", 0L); FAIL(b); }
|
||||
|
||||
EXEC SQL UPDATE py_payout SET biz_date = :h_next, updated_at = now() WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
adj = pydb_insert_adjust(h_pid, 0, reason, nextdate);
|
||||
if (adj < 0) FAIL(b);
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_ADJ, adj);
|
||||
Bchg(b, T_STR1, 0, nextdate, 0L);
|
||||
userlog("PAY_CARRYOVER id=%ld to=%s", h_pid, nextdate);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_CHARGEBACK.h
Normal file
20
app/src/py/svc/PAY_CHARGEBACK.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_CHARGEBACK.h - py 서비스 PAY_CHARGEBACK 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_CHARGEBACK.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_CHARGEBACK_H
|
||||
#define PAY_CHARGEBACK_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_chargeback_rec_t;
|
||||
|
||||
void PAY_CHARGEBACK(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_CHARGEBACK_H */
|
||||
36
app/src/py/svc/PAY_CHARGEBACK.pgc
Normal file
36
app/src/py/svc/PAY_CHARGEBACK.pgc
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* PAY_CHARGEBACK.pgc - py 모듈 서비스 PAY_CHARGEBACK (one service = one file).
|
||||
* 지급 되물림: 분쟁 등으로 지급완료(P) 건을 되물릴 때, 원건은 보존한 채
|
||||
* 음수 금액의 상계 지급건(CHGBK 채널)을 신규 생성해 상쇄 처리한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_CHARGEBACK.h"
|
||||
|
||||
void PAY_CHARGEBACK(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char bizdate[16];
|
||||
long newid, neg;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_net;
|
||||
char h_merch[64], h_acct[32], h_st[4];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_pid = getl(b, T_ID1);
|
||||
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
|
||||
EXEC SQL SELECT merchant_id, account_no, net, status
|
||||
INTO :h_merch, :h_acct, :h_net, :h_st FROM py_payout WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
|
||||
if (h_st[0] != 'P') { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "지급완료 건만 되물림 가능", 0L); FAIL(b); }
|
||||
|
||||
neg = -h_net;
|
||||
newid = pydb_next_payout_id();
|
||||
if (newid < 0) FAIL(b);
|
||||
if (pydb_insert_payout(newid, h_merch, h_acct, neg, 0, neg, "R", "CHGBK", bizdate) < 0) FAIL(b);
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_ID2, newid);
|
||||
setl(b, T_NET, neg);
|
||||
userlog("PAY_CHARGEBACK src=%ld offset=%ld net=%ld", h_pid, newid, neg);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_CLOSEDSTOP.h
Normal file
20
app/src/py/svc/PAY_CLOSEDSTOP.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_CLOSEDSTOP.h - py 서비스 PAY_CLOSEDSTOP 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_CLOSEDSTOP.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_CLOSEDSTOP_H
|
||||
#define PAY_CLOSEDSTOP_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_closedstop_rec_t;
|
||||
|
||||
void PAY_CLOSEDSTOP(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_CLOSEDSTOP_H */
|
||||
32
app/src/py/svc/PAY_CLOSEDSTOP.pgc
Normal file
32
app/src/py/svc/PAY_CLOSEDSTOP.pgc
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* PAY_CLOSEDSTOP.pgc - py 모듈 서비스 PAY_CLOSEDSTOP (one service = one file).
|
||||
* 폐업 가맹점 지급정지: 가맹점 상태가 CLOSED 인 가맹점의 미지급(R/A) 건을
|
||||
* 모두 보류(H)+'폐업정지' 사유로 전이한다. 지급망 유출을 사전 차단한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_CLOSEDSTOP.h"
|
||||
|
||||
void PAY_CLOSEDSTOP(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long stopped;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64];
|
||||
char h_mst[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, h_merch, sizeof(h_merch));
|
||||
EXEC SQL SELECT status INTO :h_mst FROM merchant WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
|
||||
if (strcmp(h_mst, "CLOSED") != 0) { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "폐업 가맹점 아님", 0L); FAIL(b); }
|
||||
|
||||
EXEC SQL UPDATE py_payout SET status = 'H', reject_reason = '폐업정지', updated_at = now()
|
||||
WHERE merchant_id = :h_merch AND status IN ('R','A');
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
stopped = sqlca.sqlerrd[2];
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_COUNT, stopped);
|
||||
userlog("PAY_CLOSEDSTOP merch=%s stopped=%ld", h_merch, stopped);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_COMBINE.h
Normal file
20
app/src/py/svc/PAY_COMBINE.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_COMBINE.h - py 서비스 PAY_COMBINE 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_COMBINE.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_COMBINE_H
|
||||
#define PAY_COMBINE_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_combine_rec_t;
|
||||
|
||||
void PAY_COMBINE(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_COMBINE_H */
|
||||
42
app/src/py/svc/PAY_COMBINE.pgc
Normal file
42
app/src/py/svc/PAY_COMBINE.pgc
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* PAY_COMBINE.pgc - py 모듈 서비스 PAY_COMBINE (one service = one file).
|
||||
* 지급 합산: 같은 계좌의 당일 요청(R) 건들을 하나로 합산 지급한다. 합계
|
||||
* 금액으로 신규 합산건(BULK)을 만들고 원건들은 취소(C) 처리한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_COMBINE.h"
|
||||
|
||||
void PAY_COMBINE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char bizdate[16];
|
||||
long newid;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_acct[32], h_bizdate[16], h_merch[64];
|
||||
long h_cnt, h_sum;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_KEY1, h_acct, sizeof(h_acct));
|
||||
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(amount),0), coalesce(max(merchant_id),'')
|
||||
INTO :h_cnt, :h_sum, :h_merch
|
||||
FROM py_payout WHERE account_no = :h_acct AND biz_date = :h_bizdate AND status = 'R';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt < 2) { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "합산 대상(2건 이상) 없음", 0L); FAIL(b); }
|
||||
|
||||
EXEC SQL UPDATE py_payout SET status = 'C', updated_at = now()
|
||||
WHERE account_no = :h_acct AND biz_date = :h_bizdate AND status = 'R';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
newid = pydb_next_payout_id();
|
||||
if (newid < 0) FAIL(b);
|
||||
if (pydb_insert_payout(newid, h_merch, h_acct, h_sum, 0, h_sum, "R", "BULK", bizdate) < 0) FAIL(b);
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_ID2, newid);
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_GROSS, h_sum);
|
||||
userlog("PAY_COMBINE acct=%s merged=%ld sum=%ld new=%ld", h_acct, h_cnt, h_sum, newid);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_DORMLIST.h
Normal file
20
app/src/py/svc/PAY_DORMLIST.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_DORMLIST.h - py 서비스 PAY_DORMLIST 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_DORMLIST.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_DORMLIST_H
|
||||
#define PAY_DORMLIST_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_dormlist_rec_t;
|
||||
|
||||
void PAY_DORMLIST(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_DORMLIST_H */
|
||||
44
app/src/py/svc/PAY_DORMLIST.pgc
Normal file
44
app/src/py/svc/PAY_DORMLIST.pgc
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* PAY_DORMLIST.pgc - py 모듈 서비스 PAY_DORMLIST (one service = one file).
|
||||
* 휴면 계좌 목록: 지정 기준일 이후 지급 이력이 전혀 없는 활성(ACTIVE) 계좌를
|
||||
* NOT EXISTS 커서로 뽑아 계좌/예금주/잔액을 occurrence 로 회신한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_DORMLIST.h"
|
||||
|
||||
void PAY_DORMLIST(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
int i = 0;
|
||||
long n = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_since[16], h_acct[32], h_holder[64];
|
||||
long h_bal;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_BIZDATE, h_since, sizeof(h_since));
|
||||
EXEC SQL DECLARE cur_dormlist CURSOR FOR
|
||||
SELECT a.account_no, a.holder, a.balance FROM py_account a
|
||||
WHERE a.status = 'ACTIVE'
|
||||
AND NOT EXISTS (SELECT 1 FROM py_payout p
|
||||
WHERE p.account_no = a.account_no AND p.biz_date >= :h_since)
|
||||
ORDER BY a.account_no;
|
||||
EXEC SQL OPEN cur_dormlist;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
for (;;) {
|
||||
EXEC SQL FETCH cur_dormlist INTO :h_acct, :h_holder, :h_bal;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE cur_dormlist; FAIL(b); }
|
||||
n++;
|
||||
if (i < 10) {
|
||||
Bchg(b, T_STR5, i, h_acct, 0L);
|
||||
Bchg(b, T_STR6, i, h_holder, 0L);
|
||||
Bchg(b, T_AMT1, i, (char *)&h_bal, 0L);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
EXEC SQL CLOSE cur_dormlist;
|
||||
setl(b, T_COUNT, n);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_FAILCLEAR.h
Normal file
20
app/src/py/svc/PAY_FAILCLEAR.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_FAILCLEAR.h - py 서비스 PAY_FAILCLEAR 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_FAILCLEAR.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_FAILCLEAR_H
|
||||
#define PAY_FAILCLEAR_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_failclear_rec_t;
|
||||
|
||||
void PAY_FAILCLEAR(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_FAILCLEAR_H */
|
||||
34
app/src/py/svc/PAY_FAILCLEAR.pgc
Normal file
34
app/src/py/svc/PAY_FAILCLEAR.pgc
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* PAY_FAILCLEAR.pgc - py 모듈 서비스 PAY_FAILCLEAR (one service = one file).
|
||||
* 실패 종결: 재처리 불가한 반려(J) 단건을 취소(C)로 종결하고 종결 사유를
|
||||
* reject_reason 에 남긴다. 반려 상태가 아니면 거절한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_FAILCLEAR.h"
|
||||
|
||||
void PAY_FAILCLEAR(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long payout_id = getl(b, T_ID1);
|
||||
char st[4], reason[128];
|
||||
|
||||
gets_(b, T_REASON, reason, sizeof(reason));
|
||||
if (reason[0] == 0) strcpy(reason, "재처리불가종결");
|
||||
if (pydb_get_status(payout_id, st) < 0) FAIL(b);
|
||||
if (st[0] != 'J') { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "반려 건만 종결 가능", 0L); FAIL(b); }
|
||||
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid = payout_id;
|
||||
char h_rsn[128];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
strncpy(h_rsn, reason, sizeof(h_rsn)-1); h_rsn[sizeof(h_rsn)-1] = 0;
|
||||
EXEC SQL UPDATE py_payout SET status = 'C', reject_reason = :h_rsn, updated_at = now()
|
||||
WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
}
|
||||
setl(b, T_RC, 0);
|
||||
Bchg(b, T_STATUS, 0, "C", 0L);
|
||||
Bchg(b, T_REASON, 0, reason, 0L);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_FAILRSN.h
Normal file
20
app/src/py/svc/PAY_FAILRSN.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_FAILRSN.h - py 서비스 PAY_FAILRSN 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_FAILRSN.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_FAILRSN_H
|
||||
#define PAY_FAILRSN_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_failrsn_rec_t;
|
||||
|
||||
void PAY_FAILRSN(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_FAILRSN_H */
|
||||
42
app/src/py/svc/PAY_FAILRSN.pgc
Normal file
42
app/src/py/svc/PAY_FAILRSN.pgc
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* PAY_FAILRSN.pgc - py 모듈 서비스 PAY_FAILRSN (one service = one file).
|
||||
* 실패 재시도횟수별 분포: 당일 반려(J) 건을 retry_count 별 커서로 건수/net
|
||||
* 집계해 재시도 횟수 오름차순 occurrence 로 회신한다 (재처리 난이도 파악).
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_FAILRSN.h"
|
||||
|
||||
void PAY_FAILRSN(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
int i = 0;
|
||||
long buckets = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_rc, h_cnt, h_amt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
EXEC SQL DECLARE cur_failrsn CURSOR FOR
|
||||
SELECT retry_count, count(*), coalesce(sum(net),0)
|
||||
FROM py_payout WHERE status = 'J' AND biz_date = :h_bizdate
|
||||
GROUP BY retry_count ORDER BY retry_count;
|
||||
EXEC SQL OPEN cur_failrsn;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
for (;;) {
|
||||
EXEC SQL FETCH cur_failrsn INTO :h_rc, :h_cnt, :h_amt;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE cur_failrsn; FAIL(b); }
|
||||
buckets++;
|
||||
if (i < 8) {
|
||||
Bchg(b, T_ARG6, i, (char *)&h_rc, 0L);
|
||||
Bchg(b, T_ARG7, i, (char *)&h_cnt, 0L);
|
||||
Bchg(b, T_AMT2, i, (char *)&h_amt, 0L);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
EXEC SQL CLOSE cur_failrsn;
|
||||
setl(b, T_COUNT, buckets);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_FEECAP.h
Normal file
20
app/src/py/svc/PAY_FEECAP.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_FEECAP.h - py 서비스 PAY_FEECAP 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_FEECAP.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_FEECAP_H
|
||||
#define PAY_FEECAP_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_feecap_rec_t;
|
||||
|
||||
void PAY_FEECAP(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_FEECAP_H */
|
||||
45
app/src/py/svc/PAY_FEECAP.pgc
Normal file
45
app/src/py/svc/PAY_FEECAP.pgc
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* PAY_FEECAP.pgc - py 모듈 서비스 PAY_FEECAP (one service = one file).
|
||||
* 수수료 상한 적용: 미지급 건 수수료가 상한(T_AMOUNT)을 넘으면 상한까지
|
||||
* 낮추고 초과분만큼 net 을 늘린다. 초과분은 py_adjust 에 양수로 남긴다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_FEECAP.h"
|
||||
|
||||
void PAY_FEECAP(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char reason[96], bizdate[16];
|
||||
long cap, cut, adj;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_fee, h_net, h_newfee, h_newnet;
|
||||
char h_st[4];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_pid = getl(b, T_ID1);
|
||||
cap = getl(b, T_AMOUNT);
|
||||
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
|
||||
gets_(b, T_REASON, reason, sizeof(reason));
|
||||
if (reason[0] == 0) strcpy(reason, "수수료상한");
|
||||
|
||||
EXEC SQL SELECT fee, net, status INTO :h_fee, :h_net, :h_st FROM py_payout WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
|
||||
if (h_st[0] != 'R' && h_st[0] != 'A') { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "미지급 건만 적용 가능", 0L); FAIL(b); }
|
||||
if (h_fee <= cap) { setl(b, T_RC, 2); Bchg(b, T_MSG, 0, "수수료가 상한 이내", 0L); FAIL(b); }
|
||||
|
||||
cut = h_fee - cap;
|
||||
h_newfee = cap;
|
||||
h_newnet = h_net + cut;
|
||||
adj = pydb_insert_adjust(h_pid, cut, reason, bizdate);
|
||||
if (adj < 0) FAIL(b);
|
||||
EXEC SQL UPDATE py_payout SET fee = :h_newfee, net = :h_newnet, updated_at = now()
|
||||
WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_ADJ, adj);
|
||||
setl(b, T_FEE, h_newfee);
|
||||
setl(b, T_NET, h_newnet);
|
||||
userlog("PAY_FEECAP id=%ld cap=%ld cut=%ld", h_pid, cap, cut);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_FEEFIXED.h
Normal file
20
app/src/py/svc/PAY_FEEFIXED.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_FEEFIXED.h - py 서비스 PAY_FEEFIXED 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_FEEFIXED.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_FEEFIXED_H
|
||||
#define PAY_FEEFIXED_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_feefixed_rec_t;
|
||||
|
||||
void PAY_FEEFIXED(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_FEEFIXED_H */
|
||||
36
app/src/py/svc/PAY_FEEFIXED.pgc
Normal file
36
app/src/py/svc/PAY_FEEFIXED.pgc
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* PAY_FEEFIXED.pgc - py 모듈 서비스 PAY_FEEFIXED (one service = one file).
|
||||
* 정액 수수료 적용: 미지급(R/A) 건에 요청 정액 수수료(T_AMOUNT)를 부과하고
|
||||
* net 을 amount-fee 로 재계산한다. 수수료가 원금을 넘으면 거절한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_FEEFIXED.h"
|
||||
|
||||
void PAY_FEEFIXED(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long fixed;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_amt, h_fee, h_net;
|
||||
char h_st[4];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_pid = getl(b, T_ID1);
|
||||
fixed = getl(b, T_AMOUNT);
|
||||
EXEC SQL SELECT amount, status INTO :h_amt, :h_st FROM py_payout WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
|
||||
if (h_st[0] != 'R' && h_st[0] != 'A') { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "미지급 건만 적용 가능", 0L); FAIL(b); }
|
||||
if (fixed > h_amt) { setl(b, T_RC, 2); Bchg(b, T_MSG, 0, "수수료가 원금 초과", 0L); FAIL(b); }
|
||||
|
||||
h_fee = fixed;
|
||||
h_net = h_amt - fixed;
|
||||
EXEC SQL UPDATE py_payout SET fee = :h_fee, net = :h_net, updated_at = now()
|
||||
WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_FEE, h_fee);
|
||||
setl(b, T_NET, h_net);
|
||||
userlog("PAY_FEEFIXED id=%ld fee=%ld net=%ld", h_pid, h_fee, h_net);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_FEEREFUND.h
Normal file
20
app/src/py/svc/PAY_FEEREFUND.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_FEEREFUND.h - py 서비스 PAY_FEEREFUND 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_FEEREFUND.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_FEEREFUND_H
|
||||
#define PAY_FEEREFUND_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_feerefund_rec_t;
|
||||
|
||||
void PAY_FEEREFUND(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_FEEREFUND_H */
|
||||
34
app/src/py/svc/PAY_FEEREFUND.pgc
Normal file
34
app/src/py/svc/PAY_FEEREFUND.pgc
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* PAY_FEEREFUND.pgc - py 모듈 서비스 PAY_FEEREFUND (one service = one file).
|
||||
* 수수료 환급: 지급완료(P) 건의 수수료를 지급계좌에 되돌려 입금하고,
|
||||
* py_ledger 에 양수 FEEREFUND 기표를 남긴다. 수수료가 없으면 거절한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_FEEREFUND.h"
|
||||
|
||||
void PAY_FEEREFUND(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_fee;
|
||||
char h_acct[32], h_st[4], h_bizdate[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_pid = getl(b, T_ID1);
|
||||
EXEC SQL SELECT account_no, fee, status, CAST(biz_date AS text)
|
||||
INTO :h_acct, :h_fee, :h_st, :h_bizdate FROM py_payout WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
|
||||
if (h_st[0] != 'P') { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "지급완료 건만 환급 가능", 0L); FAIL(b); }
|
||||
if (h_fee <= 0) { setl(b, T_RC, 2); Bchg(b, T_MSG, 0, "환급할 수수료 없음", 0L); FAIL(b); }
|
||||
|
||||
if (pydb_account_add(h_acct, h_fee) < 0) FAIL(b);
|
||||
EXEC SQL INSERT INTO py_ledger (ledger_id, payout_id, entry_type, amount, biz_date)
|
||||
VALUES (nextval('py_ledger_seq'), :h_pid, 'FEEREFUND', :h_fee, :h_bizdate);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_FEE, h_fee);
|
||||
Bchg(b, T_STR1, 0, h_acct, 0L);
|
||||
userlog("PAY_FEEREFUND id=%ld fee=%ld acct=%s", h_pid, h_fee, h_acct);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_FEESUM.h
Normal file
20
app/src/py/svc/PAY_FEESUM.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_FEESUM.h - py 서비스 PAY_FEESUM 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_FEESUM.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_FEESUM_H
|
||||
#define PAY_FEESUM_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_feesum_rec_t;
|
||||
|
||||
void PAY_FEESUM(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_FEESUM_H */
|
||||
32
app/src/py/svc/PAY_FEESUM.pgc
Normal file
32
app/src/py/svc/PAY_FEESUM.pgc
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* PAY_FEESUM.pgc - py 모듈 서비스 PAY_FEESUM (one service = one file).
|
||||
* 수수료 집계: 당일 지급건의 수수료 합/건수와, py_adjust 에 쌓인 조정 합을
|
||||
* 각각 조회해 순수수료(수수료-조정)를 산출해 회신한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_FEESUM.h"
|
||||
|
||||
void PAY_FEESUM(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_cnt, h_fee, h_adj;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
EXEC SQL SELECT count(*), coalesce(sum(fee),0) INTO :h_cnt, :h_fee
|
||||
FROM py_payout WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL SELECT coalesce(sum(delta),0) INTO :h_adj
|
||||
FROM py_adjust WHERE biz_date = :h_bizdate;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_FEE, h_fee);
|
||||
setl(b, T_ADJ, h_adj);
|
||||
setl(b, T_NET, h_fee - h_adj);
|
||||
userlog("PAY_FEESUM date=%s fee=%ld adj=%ld", h_bizdate, h_fee, h_adj);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_FILECANCEL.h
Normal file
20
app/src/py/svc/PAY_FILECANCEL.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_FILECANCEL.h - py 서비스 PAY_FILECANCEL 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_FILECANCEL.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_FILECANCEL_H
|
||||
#define PAY_FILECANCEL_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_filecancel_rec_t;
|
||||
|
||||
void PAY_FILECANCEL(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_FILECANCEL_H */
|
||||
34
app/src/py/svc/PAY_FILECANCEL.pgc
Normal file
34
app/src/py/svc/PAY_FILECANCEL.pgc
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* PAY_FILECANCEL.pgc - py 모듈 서비스 PAY_FILECANCEL (one service = one file).
|
||||
* 지급파일 취소: 확정(C) 전 파일만 취소 가능. 편성(F) 건을 승인(A)+file_id=0
|
||||
* 으로 되돌린 뒤 파일 헤더를 삭제한다. 확정/부재 파일은 사유코드로 거절.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_FILECANCEL.h"
|
||||
|
||||
void PAY_FILECANCEL(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_fid, h_back;
|
||||
char h_st[4];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_fid = getl(b, T_ID2);
|
||||
EXEC SQL SELECT status INTO :h_st FROM py_file WHERE file_id = :h_fid;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 2); Bchg(b, T_MSG, 0, "파일 없음", 0L); FAIL(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_st[0] == 'C') { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "확정 파일은 취소 불가", 0L); FAIL(b); }
|
||||
|
||||
EXEC SQL UPDATE py_payout SET status = 'A', file_id = 0, updated_at = now()
|
||||
WHERE file_id = :h_fid AND status = 'F';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
h_back = sqlca.sqlerrd[2];
|
||||
EXEC SQL DELETE FROM py_file WHERE file_id = :h_fid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_COUNT, h_back);
|
||||
userlog("PAY_FILECANCEL file=%ld reverted=%ld", h_fid, h_back);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_FILECONF.h
Normal file
20
app/src/py/svc/PAY_FILECONF.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_FILECONF.h - py 서비스 PAY_FILECONF 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_FILECONF.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_FILECONF_H
|
||||
#define PAY_FILECONF_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_fileconf_rec_t;
|
||||
|
||||
void PAY_FILECONF(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_FILECONF_H */
|
||||
34
app/src/py/svc/PAY_FILECONF.pgc
Normal file
34
app/src/py/svc/PAY_FILECONF.pgc
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* PAY_FILECONF.pgc - py 모듈 서비스 PAY_FILECONF (one service = one file).
|
||||
* 지급파일 확정: 생성(G) 파일만 확정(C)+confirmed_at 로 전이하고, 그 파일에
|
||||
* 편성(F)된 지급건을 지급완료(P)로 확정한다. 이미 확정 파일은 거절.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_FILECONF.h"
|
||||
|
||||
void PAY_FILECONF(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_fid, h_paid;
|
||||
char h_st[4];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_fid = getl(b, T_ID2);
|
||||
EXEC SQL SELECT status INTO :h_st FROM py_file WHERE file_id = :h_fid;
|
||||
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
|
||||
if (h_st[0] == 'C') { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "이미 확정된 파일", 0L); FAIL(b); }
|
||||
|
||||
EXEC SQL UPDATE py_file SET status = 'C', confirmed_at = now() WHERE file_id = :h_fid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL UPDATE py_payout SET status = 'P', updated_at = now()
|
||||
WHERE file_id = :h_fid AND status = 'F';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
h_paid = sqlca.sqlerrd[2];
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_COUNT, h_paid);
|
||||
Bchg(b, T_STATUS, 0, "C", 0L);
|
||||
userlog("PAY_FILECONF file=%ld paid=%ld", h_fid, h_paid);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_GARNISH.h
Normal file
20
app/src/py/svc/PAY_GARNISH.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_GARNISH.h - py 서비스 PAY_GARNISH 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_GARNISH.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_GARNISH_H
|
||||
#define PAY_GARNISH_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_garnish_rec_t;
|
||||
|
||||
void PAY_GARNISH(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_GARNISH_H */
|
||||
38
app/src/py/svc/PAY_GARNISH.pgc
Normal file
38
app/src/py/svc/PAY_GARNISH.pgc
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* PAY_GARNISH.pgc - py 모듈 서비스 PAY_GARNISH (one service = one file).
|
||||
* 가압류 등록: 활성 계좌를 GARNISH 로 표시하고, 그 계좌 미지급(R/A) 잔액을
|
||||
* 집계해 가압류 채권으로 py_ledger 에 음수 GARNISH 기표를 남긴다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_GARNISH.h"
|
||||
|
||||
void PAY_GARNISH(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_acct[32], h_bizdate[16];
|
||||
long h_cnt, h_sum, h_neg;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_KEY1, h_acct, sizeof(h_acct));
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
|
||||
EXEC SQL UPDATE py_account SET status = 'GARNISH', updated_at = now()
|
||||
WHERE account_no = :h_acct AND status = 'ACTIVE';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (sqlca.sqlerrd[2] == 0) { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "활성 계좌 아님", 0L); FAIL(b); }
|
||||
|
||||
EXEC SQL SELECT count(*), coalesce(sum(net),0) INTO :h_cnt, :h_sum
|
||||
FROM py_payout WHERE account_no = :h_acct AND status IN ('R','A');
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
h_neg = -h_sum;
|
||||
EXEC SQL INSERT INTO py_ledger (ledger_id, payout_id, entry_type, amount, biz_date)
|
||||
VALUES (nextval('py_ledger_seq'), 0, 'GARNISH', :h_neg, :h_bizdate);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_GROSS, h_sum);
|
||||
userlog("PAY_GARNISH acct=%s frozen=%ld amt=%ld", h_acct, h_cnt, h_sum);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_HOLDBYRSN.h
Normal file
20
app/src/py/svc/PAY_HOLDBYRSN.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_HOLDBYRSN.h - py 서비스 PAY_HOLDBYRSN 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_HOLDBYRSN.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_HOLDBYRSN_H
|
||||
#define PAY_HOLDBYRSN_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_holdbyrsn_rec_t;
|
||||
|
||||
void PAY_HOLDBYRSN(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_HOLDBYRSN_H */
|
||||
42
app/src/py/svc/PAY_HOLDBYRSN.pgc
Normal file
42
app/src/py/svc/PAY_HOLDBYRSN.pgc
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* PAY_HOLDBYRSN.pgc - py 모듈 서비스 PAY_HOLDBYRSN (one service = one file).
|
||||
* 보류 사유별 집계: 당일 보류(H) 건을 reject_reason 별 커서로 건수/net 합
|
||||
* 집계해 건수 내림차순 occurrence 로 회신한다 (보류 원인 분포 파악).
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_HOLDBYRSN.h"
|
||||
|
||||
void PAY_HOLDBYRSN(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
int i = 0;
|
||||
long rows = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16], h_rsn[128];
|
||||
long h_cnt, h_amt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
EXEC SQL DECLARE cur_holdbyrsn CURSOR FOR
|
||||
SELECT coalesce(nullif(reject_reason,''),'미지정'), count(*), coalesce(sum(net),0)
|
||||
FROM py_payout WHERE status = 'H' AND biz_date = :h_bizdate
|
||||
GROUP BY 1 ORDER BY 2 DESC, 1;
|
||||
EXEC SQL OPEN cur_holdbyrsn;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
for (;;) {
|
||||
EXEC SQL FETCH cur_holdbyrsn INTO :h_rsn, :h_cnt, :h_amt;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE cur_holdbyrsn; FAIL(b); }
|
||||
rows++;
|
||||
if (i < 10) {
|
||||
Bchg(b, T_STR4, i, h_rsn, 0L);
|
||||
Bchg(b, T_ARG5, i, (char *)&h_cnt, 0L);
|
||||
Bchg(b, T_AMT4, i, (char *)&h_amt, 0L);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
EXEC SQL CLOSE cur_holdbyrsn;
|
||||
setl(b, T_COUNT, rows);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_HOLDCLEAR.h
Normal file
20
app/src/py/svc/PAY_HOLDCLEAR.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_HOLDCLEAR.h - py 서비스 PAY_HOLDCLEAR 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_HOLDCLEAR.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_HOLDCLEAR_H
|
||||
#define PAY_HOLDCLEAR_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_holdclear_rec_t;
|
||||
|
||||
void PAY_HOLDCLEAR(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_HOLDCLEAR_H */
|
||||
33
app/src/py/svc/PAY_HOLDCLEAR.pgc
Normal file
33
app/src/py/svc/PAY_HOLDCLEAR.pgc
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* PAY_HOLDCLEAR.pgc - py 모듈 서비스 PAY_HOLDCLEAR (one service = one file).
|
||||
* 보류 일괄 해제: 지정 계좌의 보류(H) 지급건을 모두 승인(A)으로 되돌리고
|
||||
* 반려사유를 비운다. 해제 대상이 없으면 사유코드 1 로 안내한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_HOLDCLEAR.h"
|
||||
|
||||
void PAY_HOLDCLEAR(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long cleared;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_acct[32];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_KEY1, h_acct, sizeof(h_acct));
|
||||
EXEC SQL UPDATE py_payout SET status = 'A', reject_reason = '', updated_at = now()
|
||||
WHERE account_no = :h_acct AND status = 'H';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
cleared = sqlca.sqlerrd[2];
|
||||
|
||||
setl(b, T_COUNT, cleared);
|
||||
if (cleared == 0) {
|
||||
setl(b, T_RC, 1);
|
||||
Bchg(b, T_MSG, 0, "해제할 보류 건 없음", 0L);
|
||||
} else {
|
||||
setl(b, T_RC, 0);
|
||||
Bchg(b, T_MSG, 0, "보류 일괄 해제 완료", 0L);
|
||||
userlog("PAY_HOLDCLEAR acct=%s cleared=%ld", h_acct, cleared);
|
||||
}
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_HOLDEXT.h
Normal file
20
app/src/py/svc/PAY_HOLDEXT.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_HOLDEXT.h - py 서비스 PAY_HOLDEXT 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_HOLDEXT.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_HOLDEXT_H
|
||||
#define PAY_HOLDEXT_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_holdext_rec_t;
|
||||
|
||||
void PAY_HOLDEXT(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_HOLDEXT_H */
|
||||
32
app/src/py/svc/PAY_HOLDEXT.pgc
Normal file
32
app/src/py/svc/PAY_HOLDEXT.pgc
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* PAY_HOLDEXT.pgc - py 모듈 서비스 PAY_HOLDEXT (one service = one file).
|
||||
* 보류 연장: 보류(H) 건의 반려사유 뒤에 '(연장)' 표식을 덧붙여 갱신한다.
|
||||
* 보류 상태가 아니면 거절한다. 재보류 없이 사유 텍스트만 확장한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_HOLDEXT.h"
|
||||
|
||||
void PAY_HOLDEXT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid;
|
||||
char h_st[4], h_rsn[128], newrsn[160];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_pid = getl(b, T_ID1);
|
||||
EXEC SQL SELECT status, reject_reason INTO :h_st, :h_rsn
|
||||
FROM py_payout WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
|
||||
if (h_st[0] != 'H') { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "보류 건만 연장 가능", 0L); FAIL(b); }
|
||||
|
||||
snprintf(newrsn, sizeof(newrsn), "%s(연장)", h_rsn[0] ? h_rsn : "보류");
|
||||
EXEC SQL UPDATE py_payout SET reject_reason = :newrsn, updated_at = now()
|
||||
WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
Bchg(b, T_REASON, 0, newrsn, 0L);
|
||||
userlog("PAY_HOLDEXT payout=%ld reason=%s", h_pid, newrsn);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_HOLDNOTE.h
Normal file
20
app/src/py/svc/PAY_HOLDNOTE.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_HOLDNOTE.h - py 서비스 PAY_HOLDNOTE 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_HOLDNOTE.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_HOLDNOTE_H
|
||||
#define PAY_HOLDNOTE_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_holdnote_rec_t;
|
||||
|
||||
void PAY_HOLDNOTE(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_HOLDNOTE_H */
|
||||
33
app/src/py/svc/PAY_HOLDNOTE.pgc
Normal file
33
app/src/py/svc/PAY_HOLDNOTE.pgc
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* PAY_HOLDNOTE.pgc - py 모듈 서비스 PAY_HOLDNOTE (one service = one file).
|
||||
* 보류 사유 갱신: 보류(H) 단건의 반려사유를 요청 사유로 교체한다. dbio 로
|
||||
* 현재 상태를 확인해 보류 건만 허용하고, 사유 미입력 시 거절한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_HOLDNOTE.h"
|
||||
|
||||
void PAY_HOLDNOTE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long payout_id = getl(b, T_ID1);
|
||||
char st[4], reason[128];
|
||||
|
||||
gets_(b, T_REASON, reason, sizeof(reason));
|
||||
if (reason[0] == 0) { setl(b, T_RC, 2); Bchg(b, T_MSG, 0, "사유 미입력", 0L); FAIL(b); }
|
||||
if (pydb_get_status(payout_id, st) < 0) FAIL(b);
|
||||
if (st[0] != 'H') { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "보류 건만 갱신 가능", 0L); FAIL(b); }
|
||||
|
||||
{
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid = payout_id;
|
||||
char h_rsn[128];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
strncpy(h_rsn, reason, sizeof(h_rsn)-1); h_rsn[sizeof(h_rsn)-1] = 0;
|
||||
EXEC SQL UPDATE py_payout SET reject_reason = :h_rsn, updated_at = now()
|
||||
WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
}
|
||||
setl(b, T_RC, 0);
|
||||
Bchg(b, T_REASON, 0, reason, 0L);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_LIMITLIST.h
Normal file
20
app/src/py/svc/PAY_LIMITLIST.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_LIMITLIST.h - py 서비스 PAY_LIMITLIST 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_LIMITLIST.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_LIMITLIST_H
|
||||
#define PAY_LIMITLIST_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_limitlist_rec_t;
|
||||
|
||||
void PAY_LIMITLIST(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_LIMITLIST_H */
|
||||
44
app/src/py/svc/PAY_LIMITLIST.pgc
Normal file
44
app/src/py/svc/PAY_LIMITLIST.pgc
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* PAY_LIMITLIST.pgc - py 모듈 서비스 PAY_LIMITLIST (one service = one file).
|
||||
* 지급 한도 사용현황 목록: 가맹점별 일한도와 당일 확정성(A/F/P) 사용액을
|
||||
* 조인 커서로 훑어 가맹점/한도/사용액을 occurrence 로 회신한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_LIMITLIST.h"
|
||||
|
||||
void PAY_LIMITLIST(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
int i = 0;
|
||||
long n = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16], h_merch[64];
|
||||
long h_lim, h_used;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
EXEC SQL DECLARE cur_limitlist CURSOR FOR
|
||||
SELECT m.merchant_id, m.daily_limit,
|
||||
coalesce((SELECT sum(net) FROM py_payout p
|
||||
WHERE p.merchant_id = m.merchant_id AND p.biz_date = :h_bizdate
|
||||
AND p.status IN ('A','F','P')), 0)
|
||||
FROM merchant m ORDER BY m.merchant_id;
|
||||
EXEC SQL OPEN cur_limitlist;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
for (;;) {
|
||||
EXEC SQL FETCH cur_limitlist INTO :h_merch, :h_lim, :h_used;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE cur_limitlist; FAIL(b); }
|
||||
n++;
|
||||
if (i < 10) {
|
||||
Bchg(b, T_STR2, i, h_merch, 0L);
|
||||
Bchg(b, T_AMT1, i, (char *)&h_lim, 0L);
|
||||
Bchg(b, T_AMT2, i, (char *)&h_used, 0L);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
EXEC SQL CLOSE cur_limitlist;
|
||||
setl(b, T_COUNT, n);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_LIMITSET.h
Normal file
20
app/src/py/svc/PAY_LIMITSET.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_LIMITSET.h - py 서비스 PAY_LIMITSET 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_LIMITSET.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_LIMITSET_H
|
||||
#define PAY_LIMITSET_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_limitset_rec_t;
|
||||
|
||||
void PAY_LIMITSET(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_LIMITSET_H */
|
||||
31
app/src/py/svc/PAY_LIMITSET.pgc
Normal file
31
app/src/py/svc/PAY_LIMITSET.pgc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* PAY_LIMITSET.pgc - py 모듈 서비스 PAY_LIMITSET (one service = one file).
|
||||
* 지급 일한도 설정: 가맹점의 일 지급한도(merchant.daily_limit)를 새 값으로
|
||||
* 갱신한다. 존재하지 않는 가맹점이거나 음수 한도면 거절한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_LIMITSET.h"
|
||||
|
||||
void PAY_LIMITSET(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long newlim;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64];
|
||||
long h_lim;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, h_merch, sizeof(h_merch));
|
||||
newlim = getl(b, T_AMOUNT);
|
||||
if (newlim < 0) { setl(b, T_RC, 2); Bchg(b, T_MSG, 0, "한도는 0 이상이어야 함", 0L); FAIL(b); }
|
||||
h_lim = newlim;
|
||||
|
||||
EXEC SQL UPDATE merchant SET daily_limit = :h_lim WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (sqlca.sqlerrd[2] == 0) { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "가맹점 없음", 0L); FAIL(b); }
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_AMT1, h_lim);
|
||||
userlog("PAY_LIMITSET merch=%s limit=%ld", h_merch, h_lim);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_LIMITWARN.h
Normal file
20
app/src/py/svc/PAY_LIMITWARN.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_LIMITWARN.h - py 서비스 PAY_LIMITWARN 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_LIMITWARN.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_LIMITWARN_H
|
||||
#define PAY_LIMITWARN_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_limitwarn_rec_t;
|
||||
|
||||
void PAY_LIMITWARN(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_LIMITWARN_H */
|
||||
49
app/src/py/svc/PAY_LIMITWARN.pgc
Normal file
49
app/src/py/svc/PAY_LIMITWARN.pgc
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* PAY_LIMITWARN.pgc - py 모듈 서비스 PAY_LIMITWARN (one service = one file).
|
||||
* 지급 한도 근접 경보: 당일 사용액이 일한도의 지정 비율(T_ARG1 %, 기본 80)
|
||||
* 이상인 가맹점을 커서로 뽑아 경보 목록을 occurrence 로 회신한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_LIMITWARN.h"
|
||||
|
||||
void PAY_LIMITWARN(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
int i = 0;
|
||||
long warns = 0, ratio;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16], h_merch[64];
|
||||
long h_ratio, h_lim, h_used;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
ratio = getl(b, T_ARG1);
|
||||
h_ratio = (ratio > 0) ? ratio : 80;
|
||||
|
||||
EXEC SQL DECLARE cur_limitwarn CURSOR FOR
|
||||
SELECT m.merchant_id, m.daily_limit, u.used
|
||||
FROM merchant m JOIN (
|
||||
SELECT merchant_id, sum(net) AS used FROM py_payout
|
||||
WHERE biz_date = :h_bizdate AND status IN ('A','F','P')
|
||||
GROUP BY merchant_id) u ON u.merchant_id = m.merchant_id
|
||||
WHERE u.used * 100 >= m.daily_limit * :h_ratio
|
||||
ORDER BY u.used DESC;
|
||||
EXEC SQL OPEN cur_limitwarn;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
for (;;) {
|
||||
EXEC SQL FETCH cur_limitwarn INTO :h_merch, :h_lim, :h_used;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE cur_limitwarn; FAIL(b); }
|
||||
warns++;
|
||||
if (i < 10) {
|
||||
Bchg(b, T_STR2, i, h_merch, 0L);
|
||||
Bchg(b, T_AMT1, i, (char *)&h_used, 0L);
|
||||
Bchg(b, T_AMT2, i, (char *)&h_lim, 0L);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
EXEC SQL CLOSE cur_limitwarn;
|
||||
setl(b, T_COUNT, warns);
|
||||
setl(b, T_RC, warns > 0 ? 1 : 0);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_NOTIFYALL.h
Normal file
20
app/src/py/svc/PAY_NOTIFYALL.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_NOTIFYALL.h - py 서비스 PAY_NOTIFYALL 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_NOTIFYALL.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_NOTIFYALL_H
|
||||
#define PAY_NOTIFYALL_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_notifyall_rec_t;
|
||||
|
||||
void PAY_NOTIFYALL(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_NOTIFYALL_H */
|
||||
34
app/src/py/svc/PAY_NOTIFYALL.pgc
Normal file
34
app/src/py/svc/PAY_NOTIFYALL.pgc
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* PAY_NOTIFYALL.pgc - py 모듈 서비스 PAY_NOTIFYALL (one service = one file).
|
||||
* 전 채널 일괄 통지(시뮬): 지급완료(P) 단건을 SMS/EMAIL/PUSH 세 채널로 각각
|
||||
* 발송 시뮬레이션하고 발송 채널 수를 회신한다 (C 배열 순회).
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_NOTIFYALL.h"
|
||||
|
||||
void PAY_NOTIFYALL(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
const char *chans[3] = { "SMS", "EMAIL", "PUSH" };
|
||||
int k, sent = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_net;
|
||||
char h_merch[64], h_st[4];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_pid = getl(b, T_ID1);
|
||||
EXEC SQL SELECT merchant_id, net, status INTO :h_merch, :h_net, :h_st
|
||||
FROM py_payout WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
|
||||
if (h_st[0] != 'P') { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "지급완료 건만 통지", 0L); FAIL(b); }
|
||||
|
||||
for (k = 0; k < 3; k++) {
|
||||
userlog("PAY_NOTIFYALL ch=%s payout=%ld to=%s", chans[k], h_pid, h_merch);
|
||||
sent++;
|
||||
}
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_COUNT, sent);
|
||||
setl(b, T_NET, h_net);
|
||||
Bchg(b, T_MSG, 0, "전 채널 통지 완료", 0L);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_NOTIFYFAIL.h
Normal file
20
app/src/py/svc/PAY_NOTIFYFAIL.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_NOTIFYFAIL.h - py 서비스 PAY_NOTIFYFAIL 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_NOTIFYFAIL.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_NOTIFYFAIL_H
|
||||
#define PAY_NOTIFYFAIL_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_notifyfail_rec_t;
|
||||
|
||||
void PAY_NOTIFYFAIL(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_NOTIFYFAIL_H */
|
||||
31
app/src/py/svc/PAY_NOTIFYFAIL.pgc
Normal file
31
app/src/py/svc/PAY_NOTIFYFAIL.pgc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* PAY_NOTIFYFAIL.pgc - py 모듈 서비스 PAY_NOTIFYFAIL (one service = one file).
|
||||
* 지급실패 통지(시뮬): 반려(J) 건의 가맹점/반려사유를 읽어 실패 안내 본문을
|
||||
* 조립해 발송 시뮬레이션한다. 반려 건이 아니면 거절한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_NOTIFYFAIL.h"
|
||||
|
||||
void PAY_NOTIFYFAIL(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char msg[224];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid;
|
||||
char h_merch[64], h_st[4], h_rsn[128];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_pid = getl(b, T_ID1);
|
||||
EXEC SQL SELECT merchant_id, status, reject_reason INTO :h_merch, :h_st, :h_rsn
|
||||
FROM py_payout WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
|
||||
if (h_st[0] != 'J') { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "반려 건만 실패통지 대상", 0L); FAIL(b); }
|
||||
if (h_rsn[0] == 0) strcpy(h_rsn, "사유미상");
|
||||
|
||||
snprintf(msg, sizeof(msg), "[Forge] %s 지급실패: %s", h_merch, h_rsn);
|
||||
userlog("PAY_NOTIFYFAIL payout=%ld reason=%s", h_pid, h_rsn);
|
||||
setl(b, T_RC, 0);
|
||||
Bchg(b, T_REASON, 0, h_rsn, 0L);
|
||||
Bchg(b, T_MSG, 0, msg, 0L);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_NOTIFYKAKAO.h
Normal file
20
app/src/py/svc/PAY_NOTIFYKAKAO.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_NOTIFYKAKAO.h - py 서비스 PAY_NOTIFYKAKAO 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_NOTIFYKAKAO.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_NOTIFYKAKAO_H
|
||||
#define PAY_NOTIFYKAKAO_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_notifykakao_rec_t;
|
||||
|
||||
void PAY_NOTIFYKAKAO(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_NOTIFYKAKAO_H */
|
||||
29
app/src/py/svc/PAY_NOTIFYKAKAO.pgc
Normal file
29
app/src/py/svc/PAY_NOTIFYKAKAO.pgc
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* PAY_NOTIFYKAKAO.pgc - py 모듈 서비스 PAY_NOTIFYKAKAO (one service = one file).
|
||||
* 알림톡 일괄 통지(시뮬): 당일 지급완료(P) 건수/금액을 한 번에 집계해 알림톡
|
||||
* 대량발송을 시뮬레이션한다. 대상이 없으면 안내 후 정상 종료한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_NOTIFYKAKAO.h"
|
||||
|
||||
void PAY_NOTIFYKAKAO(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
long h_cnt, h_sum;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
EXEC SQL SELECT count(*), coalesce(sum(net),0) INTO :h_cnt, :h_sum
|
||||
FROM py_payout WHERE biz_date = :h_bizdate AND status = 'P';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt == 0) { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "통지 대상 없음", 0L); OK(b); }
|
||||
|
||||
userlog("PAY_NOTIFYKAKAO 일괄발송시뮬 bizdate=%s targets=%ld amt=%ld", h_bizdate, h_cnt, h_sum);
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_GROSS, h_sum);
|
||||
Bchg(b, T_MSG, 0, "알림톡 발송 완료", 0L);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_NOTIFYPUSH.h
Normal file
20
app/src/py/svc/PAY_NOTIFYPUSH.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_NOTIFYPUSH.h - py 서비스 PAY_NOTIFYPUSH 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_NOTIFYPUSH.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_NOTIFYPUSH_H
|
||||
#define PAY_NOTIFYPUSH_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_notifypush_rec_t;
|
||||
|
||||
void PAY_NOTIFYPUSH(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_NOTIFYPUSH_H */
|
||||
33
app/src/py/svc/PAY_NOTIFYPUSH.pgc
Normal file
33
app/src/py/svc/PAY_NOTIFYPUSH.pgc
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* PAY_NOTIFYPUSH.pgc - py 모듈 서비스 PAY_NOTIFYPUSH (one service = one file).
|
||||
* 지급완료 푸시 통지(시뮬): 지급완료(P)건을 py_account 조인으로 예금주/은행을
|
||||
* 읽어 푸시 본문을 조립하고 발송은 userlog 로 시뮬레이션한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_NOTIFYPUSH.h"
|
||||
|
||||
void PAY_NOTIFYPUSH(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char msg[192];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_net;
|
||||
char h_holder[64], h_st[4], h_bank[8];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_pid = getl(b, T_ID1);
|
||||
EXEC SQL SELECT p.net, p.status, a.holder, a.bank_code
|
||||
INTO :h_net, :h_st, :h_holder, :h_bank
|
||||
FROM py_payout p JOIN py_account a ON p.account_no = a.account_no
|
||||
WHERE p.payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
|
||||
if (h_st[0] != 'P') { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "지급완료 건만 푸시 가능", 0L); FAIL(b); }
|
||||
|
||||
snprintf(msg, sizeof(msg), "[Forge] %s(%s) %ld원 지급 알림", h_holder, h_bank, h_net);
|
||||
userlog("PAY_NOTIFYPUSH 발송시뮬 payout=%ld holder=%s", h_pid, h_holder);
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_NET, h_net);
|
||||
Bchg(b, T_STR2, 0, h_bank, 0L);
|
||||
Bchg(b, T_MSG, 0, msg, 0L);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_NOTIFYRESEND.h
Normal file
20
app/src/py/svc/PAY_NOTIFYRESEND.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_NOTIFYRESEND.h - py 서비스 PAY_NOTIFYRESEND 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_NOTIFYRESEND.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_NOTIFYRESEND_H
|
||||
#define PAY_NOTIFYRESEND_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_notifyresend_rec_t;
|
||||
|
||||
void PAY_NOTIFYRESEND(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_NOTIFYRESEND_H */
|
||||
32
app/src/py/svc/PAY_NOTIFYRESEND.pgc
Normal file
32
app/src/py/svc/PAY_NOTIFYRESEND.pgc
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* PAY_NOTIFYRESEND.pgc - py 모듈 서비스 PAY_NOTIFYRESEND (one service = one file).
|
||||
* 통지 재발송: 지급완료(P) 건의 retry_count 를 재발송 횟수로 삼아 3회까지만
|
||||
* 허용하며, 재발송 시 카운터를 +1 하고 현재 시도 회차를 회신한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_NOTIFYRESEND.h"
|
||||
|
||||
void PAY_NOTIFYRESEND(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_rc;
|
||||
char h_st[4];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_pid = getl(b, T_ID1);
|
||||
EXEC SQL SELECT status, retry_count INTO :h_st, :h_rc
|
||||
FROM py_payout WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
|
||||
if (h_st[0] != 'P') { setl(b, T_RC, 2); Bchg(b, T_MSG, 0, "지급완료 건만 재발송", 0L); FAIL(b); }
|
||||
if (h_rc >= 3) { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "재발송 한도 초과", 0L); FAIL(b); }
|
||||
|
||||
EXEC SQL UPDATE py_payout SET retry_count = retry_count + 1, updated_at = now()
|
||||
WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
userlog("PAY_NOTIFYRESEND payout=%ld attempt=%ld", h_pid, h_rc + 1);
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_COUNT, h_rc + 1);
|
||||
Bchg(b, T_MSG, 0, "통지 재발송 완료", 0L);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_OFFSETAPPLY.h
Normal file
20
app/src/py/svc/PAY_OFFSETAPPLY.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_OFFSETAPPLY.h - py 서비스 PAY_OFFSETAPPLY 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_OFFSETAPPLY.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_OFFSETAPPLY_H
|
||||
#define PAY_OFFSETAPPLY_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_offsetapply_rec_t;
|
||||
|
||||
void PAY_OFFSETAPPLY(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_OFFSETAPPLY_H */
|
||||
41
app/src/py/svc/PAY_OFFSETAPPLY.pgc
Normal file
41
app/src/py/svc/PAY_OFFSETAPPLY.pgc
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* PAY_OFFSETAPPLY.pgc - py 모듈 서비스 PAY_OFFSETAPPLY (one service = one file).
|
||||
* 상계 적용: 미지급(R/A) 건의 net 에서 상계액을 차감(net 미만으로 캡)하고,
|
||||
* 차감분을 py_adjust 에 음수 조정으로 남긴다. 지급 전 채권 상계 반영.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_OFFSETAPPLY.h"
|
||||
|
||||
void PAY_OFFSETAPPLY(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char reason[96], bizdate[16];
|
||||
long off, adj;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_net, h_cut;
|
||||
char h_st[4];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_pid = getl(b, T_ID1);
|
||||
off = getl(b, T_AMOUNT);
|
||||
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
|
||||
gets_(b, T_REASON, reason, sizeof(reason));
|
||||
if (reason[0] == 0) strcpy(reason, "상계");
|
||||
|
||||
EXEC SQL SELECT net, status INTO :h_net, :h_st FROM py_payout WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
|
||||
if (h_st[0] != 'R' && h_st[0] != 'A') { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "미지급 건만 상계 가능", 0L); FAIL(b); }
|
||||
h_cut = (off > h_net) ? h_net : off;
|
||||
if (h_cut <= 0) { setl(b, T_RC, 2); Bchg(b, T_MSG, 0, "상계액 무효", 0L); FAIL(b); }
|
||||
|
||||
adj = pydb_insert_adjust(h_pid, -h_cut, reason, bizdate);
|
||||
if (adj < 0) FAIL(b);
|
||||
EXEC SQL UPDATE py_payout SET net = net - :h_cut, updated_at = now() WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_ADJ, adj);
|
||||
setl(b, T_NET, h_net - h_cut);
|
||||
userlog("PAY_OFFSETAPPLY id=%ld off=%ld", h_pid, h_cut);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_PENDLIST.h
Normal file
20
app/src/py/svc/PAY_PENDLIST.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_PENDLIST.h - py 서비스 PAY_PENDLIST 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_PENDLIST.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_PENDLIST_H
|
||||
#define PAY_PENDLIST_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_pendlist_rec_t;
|
||||
|
||||
void PAY_PENDLIST(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_PENDLIST_H */
|
||||
43
app/src/py/svc/PAY_PENDLIST.pgc
Normal file
43
app/src/py/svc/PAY_PENDLIST.pgc
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* PAY_PENDLIST.pgc - py 모듈 서비스 PAY_PENDLIST (one service = one file).
|
||||
* 미지급 목록: 당일 미완결(요청R/승인A/보류H) 지급건을 커서로 훑어 지급ID/
|
||||
* 가맹점/net/상태를 occurrence 로 회신한다 (집계 없는 상세 리스트).
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_PENDLIST.h"
|
||||
|
||||
void PAY_PENDLIST(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
int i = 0;
|
||||
long n = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16], h_merch[64], h_st[4];
|
||||
long h_pid, h_net;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
EXEC SQL DECLARE cur_pendlist CURSOR FOR
|
||||
SELECT payout_id, merchant_id, net, status FROM py_payout
|
||||
WHERE biz_date = :h_bizdate AND status IN ('R','A','H')
|
||||
ORDER BY payout_id;
|
||||
EXEC SQL OPEN cur_pendlist;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
for (;;) {
|
||||
EXEC SQL FETCH cur_pendlist INTO :h_pid, :h_merch, :h_net, :h_st;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE cur_pendlist; FAIL(b); }
|
||||
n++;
|
||||
if (i < 12) {
|
||||
Bchg(b, T_ARG1, i, (char *)&h_pid, 0L);
|
||||
Bchg(b, T_STR2, i, h_merch, 0L);
|
||||
Bchg(b, T_AMT1, i, (char *)&h_net, 0L);
|
||||
Bchg(b, T_STR3, i, h_st, 0L);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
EXEC SQL CLOSE cur_pendlist;
|
||||
setl(b, T_COUNT, n);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_REACTIVATE.h
Normal file
20
app/src/py/svc/PAY_REACTIVATE.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_REACTIVATE.h - py 서비스 PAY_REACTIVATE 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_REACTIVATE.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_REACTIVATE_H
|
||||
#define PAY_REACTIVATE_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_reactivate_rec_t;
|
||||
|
||||
void PAY_REACTIVATE(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_REACTIVATE_H */
|
||||
26
app/src/py/svc/PAY_REACTIVATE.pgc
Normal file
26
app/src/py/svc/PAY_REACTIVATE.pgc
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* PAY_REACTIVATE.pgc - py 모듈 서비스 PAY_REACTIVATE (one service = one file).
|
||||
* 휴면 계좌 재활성: 휴면(DORMANT) 처리된 지급계좌를 다시 활성(ACTIVE)으로
|
||||
* 되돌린다. 휴면 상태가 아니면 재활성 대상이 아니므로 거절한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_REACTIVATE.h"
|
||||
|
||||
void PAY_REACTIVATE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_acct[32];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_KEY1, h_acct, sizeof(h_acct));
|
||||
EXEC SQL UPDATE py_account SET status = 'ACTIVE', updated_at = now()
|
||||
WHERE account_no = :h_acct AND status = 'DORMANT';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (sqlca.sqlerrd[2] == 0) { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "휴면 계좌 아님", 0L); FAIL(b); }
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
Bchg(b, T_STATUS, 0, "ACTIVE", 0L);
|
||||
userlog("PAY_REACTIVATE acct=%s -> ACTIVE", h_acct);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_RECLAIM.h
Normal file
20
app/src/py/svc/PAY_RECLAIM.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_RECLAIM.h - py 서비스 PAY_RECLAIM 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_RECLAIM.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_RECLAIM_H
|
||||
#define PAY_RECLAIM_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_reclaim_rec_t;
|
||||
|
||||
void PAY_RECLAIM(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_RECLAIM_H */
|
||||
38
app/src/py/svc/PAY_RECLAIM.pgc
Normal file
38
app/src/py/svc/PAY_RECLAIM.pgc
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* PAY_RECLAIM.pgc - py 모듈 서비스 PAY_RECLAIM (one service = one file).
|
||||
* 과지급 환수: 지급완료(P) 건에서 요청 환수액(T_AMOUNT, net 한도)만큼을
|
||||
* 지급계좌에서 차감(음수 account_add)하고 py_ledger 에 음수 RECLAIM 기표.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_RECLAIM.h"
|
||||
|
||||
void PAY_RECLAIM(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long want, recl;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_net, h_neg;
|
||||
char h_acct[32], h_st[4], h_bizdate[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_pid = getl(b, T_ID1);
|
||||
want = getl(b, T_AMOUNT);
|
||||
EXEC SQL SELECT account_no, net, status, CAST(biz_date AS text)
|
||||
INTO :h_acct, :h_net, :h_st, :h_bizdate FROM py_payout WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
|
||||
if (h_st[0] != 'P') { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "지급완료 건만 환수 가능", 0L); FAIL(b); }
|
||||
|
||||
recl = (want > 0 && want < h_net) ? want : h_net;
|
||||
if (recl <= 0) { setl(b, T_RC, 2); Bchg(b, T_MSG, 0, "환수액 무효", 0L); FAIL(b); }
|
||||
if (pydb_account_add(h_acct, -recl) < 0) FAIL(b);
|
||||
h_neg = -recl;
|
||||
EXEC SQL INSERT INTO py_ledger (ledger_id, payout_id, entry_type, amount, biz_date)
|
||||
VALUES (nextval('py_ledger_seq'), :h_pid, 'RECLAIM', :h_neg, :h_bizdate);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_AMT1, recl);
|
||||
Bchg(b, T_STR1, 0, h_acct, 0L);
|
||||
userlog("PAY_RECLAIM id=%ld reclaimed=%ld acct=%s", h_pid, recl, h_acct);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_REPAYACCT.h
Normal file
20
app/src/py/svc/PAY_REPAYACCT.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_REPAYACCT.h - py 서비스 PAY_REPAYACCT 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_REPAYACCT.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_REPAYACCT_H
|
||||
#define PAY_REPAYACCT_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_repayacct_rec_t;
|
||||
|
||||
void PAY_REPAYACCT(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_REPAYACCT_H */
|
||||
39
app/src/py/svc/PAY_REPAYACCT.pgc
Normal file
39
app/src/py/svc/PAY_REPAYACCT.pgc
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* PAY_REPAYACCT.pgc - py 모듈 서비스 PAY_REPAYACCT (one service = one file).
|
||||
* 계좌변경 재지급: 반려(J)된 지급건의 금액/수수료를 승계해 새 계좌(T_KEY2)로
|
||||
* 신규 요청(R) 지급건을 복제 생성한다 (원건은 그대로 두어 이력 보존).
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_REPAYACCT.h"
|
||||
|
||||
void PAY_REPAYACCT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char newacct[32], bizdate[16];
|
||||
long newid;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_pid, h_amt, h_fee, h_net;
|
||||
char h_merch[64], h_st[4];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_pid = getl(b, T_ID1);
|
||||
gets_(b, T_KEY2, newacct, sizeof(newacct));
|
||||
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
|
||||
if (newacct[0] == 0) { setl(b, T_RC, 3); Bchg(b, T_MSG, 0, "새 계좌 미지정", 0L); FAIL(b); }
|
||||
|
||||
EXEC SQL SELECT merchant_id, amount, fee, net, status
|
||||
INTO :h_merch, :h_amt, :h_fee, :h_net, :h_st
|
||||
FROM py_payout WHERE payout_id = :h_pid;
|
||||
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
|
||||
if (h_st[0] != 'J') { setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "반려 건만 재지급 대상", 0L); FAIL(b); }
|
||||
|
||||
newid = pydb_next_payout_id();
|
||||
if (newid < 0) FAIL(b);
|
||||
if (pydb_insert_payout(newid, h_merch, newacct, h_amt, h_fee, h_net, "R", "STD", bizdate) < 0) FAIL(b);
|
||||
|
||||
setl(b, T_RC, 0);
|
||||
setl(b, T_ID2, newid);
|
||||
setl(b, T_NET, h_net);
|
||||
userlog("PAY_REPAYACCT old=%ld new=%ld acct=%s", h_pid, newid, newacct);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_REQUEUE.h
Normal file
20
app/src/py/svc/PAY_REQUEUE.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_REQUEUE.h - py 서비스 PAY_REQUEUE 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_REQUEUE.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_REQUEUE_H
|
||||
#define PAY_REQUEUE_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_requeue_rec_t;
|
||||
|
||||
void PAY_REQUEUE(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_REQUEUE_H */
|
||||
28
app/src/py/svc/PAY_REQUEUE.pgc
Normal file
28
app/src/py/svc/PAY_REQUEUE.pgc
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* PAY_REQUEUE.pgc - py 모듈 서비스 PAY_REQUEUE (one service = one file).
|
||||
* 실패 일괄 재처리 적재: 당일 반려(J) 건 중 재시도 여력(retry_count<3)이
|
||||
* 있는 건들을 요청(R)으로 되돌리고 retry_count 를 +1 해 재처리 큐에 올린다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_REQUEUE.h"
|
||||
|
||||
void PAY_REQUEUE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
long requeued;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizdate[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
|
||||
EXEC SQL UPDATE py_payout
|
||||
SET status = 'R', retry_count = retry_count + 1, reject_reason = '', updated_at = now()
|
||||
WHERE biz_date = :h_bizdate AND status = 'J' AND retry_count < 3;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
requeued = sqlca.sqlerrd[2];
|
||||
|
||||
setl(b, T_RC, requeued > 0 ? 0 : 1);
|
||||
setl(b, T_COUNT, requeued);
|
||||
userlog("PAY_REQUEUE date=%s requeued=%ld", h_bizdate, requeued);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_RESVLIST.h
Normal file
20
app/src/py/svc/PAY_RESVLIST.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_RESVLIST.h - py 서비스 PAY_RESVLIST 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_RESVLIST.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_RESVLIST_H
|
||||
#define PAY_RESVLIST_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_resvlist_rec_t;
|
||||
|
||||
void PAY_RESVLIST(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_RESVLIST_H */
|
||||
43
app/src/py/svc/PAY_RESVLIST.pgc
Normal file
43
app/src/py/svc/PAY_RESVLIST.pgc
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* PAY_RESVLIST.pgc - py 모듈 서비스 PAY_RESVLIST (one service = one file).
|
||||
* 예약 지급 목록: 지정 실행일(T_BIZDATE)에 걸린 예약(S) 을 py_schedule 과
|
||||
* py_payout 조인 커서로 훑어 예약ID/지급ID/금액을 occurrence 로 회신한다.
|
||||
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
|
||||
*/
|
||||
#include "PAY_RESVLIST.h"
|
||||
|
||||
void PAY_RESVLIST(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
int i = 0;
|
||||
long n = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_rundate[16];
|
||||
long h_sid, h_pid, h_amt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_BIZDATE, h_rundate, sizeof(h_rundate));
|
||||
EXEC SQL DECLARE cur_resvlist CURSOR FOR
|
||||
SELECT s.schedule_id, s.payout_id, coalesce(p.net,0)
|
||||
FROM py_schedule s LEFT JOIN py_payout p ON s.payout_id = p.payout_id
|
||||
WHERE s.run_date = :h_rundate AND s.status = 'S'
|
||||
ORDER BY s.schedule_id;
|
||||
EXEC SQL OPEN cur_resvlist;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
for (;;) {
|
||||
EXEC SQL FETCH cur_resvlist INTO :h_sid, :h_pid, :h_amt;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE cur_resvlist; FAIL(b); }
|
||||
n++;
|
||||
if (i < 12) {
|
||||
Bchg(b, T_ARG1, i, (char *)&h_sid, 0L);
|
||||
Bchg(b, T_ARG2, i, (char *)&h_pid, 0L);
|
||||
Bchg(b, T_AMT1, i, (char *)&h_amt, 0L);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
EXEC SQL CLOSE cur_resvlist;
|
||||
setl(b, T_COUNT, n);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
20
app/src/py/svc/PAY_RESVMODIFY.h
Normal file
20
app/src/py/svc/PAY_RESVMODIFY.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* PAY_RESVMODIFY.h - py 서비스 PAY_RESVMODIFY 카피북 (copybook / record header).
|
||||
* Shared base(py_svc.h) + 이 서비스의 레코드 구조체 + 함수 프로토타입.
|
||||
* Request/Response 필드는 PAY_RESVMODIFY.pgc 본문의 get/set 호출을 참조.
|
||||
*/
|
||||
#ifndef PAY_RESVMODIFY_H
|
||||
#define PAY_RESVMODIFY_H
|
||||
|
||||
#include "py_svc.h"
|
||||
|
||||
typedef struct {
|
||||
long payout_id;
|
||||
long amount;
|
||||
long net;
|
||||
char status[8];
|
||||
} pay_resvmodify_rec_t;
|
||||
|
||||
void PAY_RESVMODIFY(TPSVCINFO *p);
|
||||
|
||||
#endif /* PAY_RESVMODIFY_H */
|
||||
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