규모확장 Wave A: 전 11모듈 svc 30→75·batch 22→35 + 전 모듈 운영데이터 시드
- svc 330→825 (모듈당 +45 고유 실업무: chargeback·재매입·심사워크플로·전문유형별· 대사세분·정산시뮬·지급재처리·복식결산·마감워크플로·마스터심사·검증룰·전문라우팅 등) - batch 242→385 (모듈당 +13), 카피북 헤더·디스패처 advertise 전 75 반영 - db/schema.d/95-module-seed.sql: 전 모듈 테이블 운영데이터(au 8.4k·st 15.9k·mg 16.9k· lg 14.6k·rc 7.7k·py 2.9k·vl 8.5k·cm 10.4k 등, 총 ~171k행) — base 거래와 정합 - 화면 매니페스트 825 재생성, 큐 메모리 튜닝(NDRX_MSGMAX 50→30) - 검증: build DONE modules=11 batches=385, 12서버 runok, xadmin psc 828 AVAIL, 매입체인 XA 커밋(status=S), 새서비스 시드데이터 스모크(ACQ_MERCHSUM/RC_STATS 실값), 전 코퍼스 .pgc 클론 0, 헤드리스 스크린샷 확인 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
19acf4ed96
commit
ea90bef264
1292 changed files with 53968 additions and 20 deletions
63
app/src/mm/batch/mm_acct_reverify_batch.pgc
Normal file
63
app/src/mm/batch/mm_acct_reverify_batch.pgc
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* mm_acct_reverify_batch.pgc - 정산계좌 정기 재검증 배치 (전수 검증 이력 적재 + XA).
|
||||
*
|
||||
* 활성 가맹점의 정산계좌를 커서로 전수 재검증하여 결과(OK/EMPTY/FORMAT)를
|
||||
* 가맹점별 ACCT_VRF 검증 이력으로 남긴다 (온라인 MM_ACCT_VERIFY 와 동일 판정 기준).
|
||||
* 전 구간 ONE global XA transaction.
|
||||
* host 변수는 전용 카피북 mm_acct_reverify_cpy.h 를 EXEC SQL INCLUDE.
|
||||
* Usage: mm_acct_reverify_batch
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "mm_dbio.h"
|
||||
|
||||
static const char *acct_verdict(const char *acct)
|
||||
{
|
||||
size_t i, len = strlen(acct);
|
||||
if (len == 0) return "EMPTY";
|
||||
if (len < 10 || len > 16) return "FORMAT";
|
||||
for (i = 0; i < len; i++)
|
||||
if (acct[i] < '0' || acct[i] > '9') return "FORMAT";
|
||||
return "OK";
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
long total = 0, failed = 0;
|
||||
const char *result;
|
||||
(void)argc; (void)argv;
|
||||
|
||||
EXEC SQL INCLUDE mm_acct_reverify_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(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL DECLARE arv CURSOR FOR
|
||||
SELECT merchant_id, settle_acct FROM mm_merchant_ext
|
||||
WHERE status = 'ACTIVE'
|
||||
ORDER BY merchant_id;
|
||||
EXEC SQL OPEN arv;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
|
||||
for (;;) {
|
||||
EXEC SQL FETCH arv INTO :b_merch, :b_acct;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "FETCH FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE arv; tpabort(0); return 1; }
|
||||
result = acct_verdict(b_acct);
|
||||
if (mmdb_insert_merch_hist(b_merch, "ACCT_VRF", "", result, "정기 배치 재검증") < 0) {
|
||||
EXEC SQL CLOSE arv; tpabort(0); return 1;
|
||||
}
|
||||
total++;
|
||||
if (strcmp(result, "OK") != 0) failed++;
|
||||
}
|
||||
EXEC SQL CLOSE arv;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> mm_acct_reverify_batch COMMIT: 재검증=%ld건 불량=%ld건\n", total, failed);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
5
app/src/mm/batch/mm_acct_reverify_cpy.h
Normal file
5
app/src/mm/batch/mm_acct_reverify_cpy.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
/* mm_acct_reverify_cpy.h - mm_acct_reverify_batch 전용 카피북 (host 변수 선언). */
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char b_merch[64];
|
||||
char b_acct[40];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
55
app/src/mm/batch/mm_apply_expire_batch.pgc
Normal file
55
app/src/mm/batch/mm_apply_expire_batch.pgc
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* mm_apply_expire_batch.pgc - 장기 미처리 가입신청 자동반려 배치 (심사 워크플로 + XA).
|
||||
*
|
||||
* APPLIED/REVIEW 상태로 기한을 넘긴 신청 건을 커서로 훑어 REJECTED 로 전환하고
|
||||
* 자동반려 사유를 이력(REJECT)으로 남긴다. 전 구간 ONE global XA transaction.
|
||||
* host 변수는 전용 카피북 mm_apply_expire_cpy.h 를 EXEC SQL INCLUDE.
|
||||
* Usage: mm_apply_expire_batch [DAYS=30]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "mm_dbio.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
long expired = 0;
|
||||
|
||||
EXEC SQL INCLUDE mm_apply_expire_cpy;
|
||||
|
||||
b_days = (argc > 1) ? atol(argv[1]) : 30;
|
||||
if (b_days < 1) b_days = 30;
|
||||
|
||||
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 aex CURSOR FOR
|
||||
SELECT merchant_id, status FROM mm_merchant_ext
|
||||
WHERE status IN ('APPLIED', 'REVIEW')
|
||||
AND updated_at < now() - :b_days * interval '1 day'
|
||||
ORDER BY merchant_id;
|
||||
EXEC SQL OPEN aex;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
|
||||
for (;;) {
|
||||
EXEC SQL FETCH aex INTO :b_merch, :b_stat;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "FETCH FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE aex; tpabort(0); return 1; }
|
||||
EXEC SQL UPDATE mm_merchant_ext SET status = 'REJECTED', updated_at = now()
|
||||
WHERE merchant_id = :b_merch;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "UPDATE FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE aex; tpabort(0); return 1; }
|
||||
if (mmdb_insert_merch_hist(b_merch, "REJECT", b_stat, "REJECTED", "심사기한 초과 자동반려") < 0) {
|
||||
EXEC SQL CLOSE aex; tpabort(0); return 1;
|
||||
}
|
||||
expired++;
|
||||
}
|
||||
EXEC SQL CLOSE aex;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> mm_apply_expire_batch COMMIT: 기한=%ld일 자동반려=%ld건\n", b_days, expired);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
6
app/src/mm/batch/mm_apply_expire_cpy.h
Normal file
6
app/src/mm/batch/mm_apply_expire_cpy.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
/* mm_apply_expire_cpy.h - mm_apply_expire_batch 전용 카피북 (host 변수 선언). */
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long b_days;
|
||||
char b_merch[64];
|
||||
char b_stat[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
65
app/src/mm/batch/mm_audit_compact_batch.pgc
Normal file
65
app/src/mm/batch/mm_audit_compact_batch.pgc
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* mm_audit_compact_batch.pgc - 감사 이력 압축 배치 (요약행 생성 후 원본 삭제 + XA).
|
||||
*
|
||||
* 보존일수를 넘긴 가맹점별 이력이 임계 건수를 초과하면 건수를 담은 AUDIT_SUM
|
||||
* 요약행 1건을 남기고 해당 구간의 원본 이력을 삭제해 mm_merch_hist 를 압축한다.
|
||||
* (AUDIT_SUM 자신은 삭제 대상에서 제외.) 전 구간 ONE global XA transaction.
|
||||
* host 변수는 전용 카피북 mm_audit_compact_cpy.h 를 EXEC SQL INCLUDE.
|
||||
* Usage: mm_audit_compact_batch [DAYS=365] [KEEP_THRESHOLD=10]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "mm_dbio.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
long merchants = 0, removed = 0;
|
||||
char summary[96];
|
||||
|
||||
EXEC SQL INCLUDE mm_audit_compact_cpy;
|
||||
|
||||
b_days = (argc > 1) ? atol(argv[1]) : 365;
|
||||
b_keep = (argc > 2) ? atol(argv[2]) : 10;
|
||||
if (b_days < 30) b_days = 365;
|
||||
if (b_keep < 1) b_keep = 10;
|
||||
|
||||
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 acp CURSOR FOR
|
||||
SELECT merchant_id, count(*) FROM mm_merch_hist
|
||||
WHERE created_at < now() - :b_days * interval '1 day'
|
||||
AND action <> 'AUDIT_SUM'
|
||||
GROUP BY merchant_id
|
||||
HAVING count(*) > :b_keep
|
||||
ORDER BY merchant_id;
|
||||
EXEC SQL OPEN acp;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
|
||||
for (;;) {
|
||||
EXEC SQL FETCH acp INTO :b_merch, :b_cnt;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "FETCH FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE acp; tpabort(0); return 1; }
|
||||
snprintf(summary, sizeof(summary), "보존기한 경과 이력 %ld건 압축 요약", b_cnt);
|
||||
if (mmdb_insert_merch_hist(b_merch, "AUDIT_SUM", "", "", summary) < 0) {
|
||||
EXEC SQL CLOSE acp; tpabort(0); return 1;
|
||||
}
|
||||
EXEC SQL DELETE FROM mm_merch_hist
|
||||
WHERE merchant_id = :b_merch
|
||||
AND created_at < now() - :b_days * interval '1 day'
|
||||
AND action <> 'AUDIT_SUM';
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "DELETE FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE acp; tpabort(0); return 1; }
|
||||
removed += sqlca.sqlerrd[2];
|
||||
merchants++;
|
||||
}
|
||||
EXEC SQL CLOSE acp;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> mm_audit_compact_batch COMMIT: 압축 가맹점=%ld 삭제 이력=%ld건\n", merchants, removed);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
7
app/src/mm/batch/mm_audit_compact_cpy.h
Normal file
7
app/src/mm/batch/mm_audit_compact_cpy.h
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
/* mm_audit_compact_cpy.h - mm_audit_compact_batch 전용 카피북 (host 변수 선언). */
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long b_days;
|
||||
long b_keep;
|
||||
char b_merch[64];
|
||||
long b_cnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
68
app/src/mm/batch/mm_bizno_audit_batch.pgc
Normal file
68
app/src/mm/batch/mm_bizno_audit_batch.pgc
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* mm_bizno_audit_batch.pgc - 사업자등록번호 전수 점검 배치 (형식+검증공식 + XA).
|
||||
*
|
||||
* 활성 가맹점의 사업자번호를 커서로 전수 검사한다: 10자리 숫자 형식과
|
||||
* 국세청 검증공식(가중치 1,3,7,1,3,7,1,3,5) checksum. 위반 건은 BIZNO_ERR
|
||||
* 이력으로 적재한다. 전 구간 ONE global XA transaction.
|
||||
* host 변수는 전용 카피북 mm_bizno_audit_cpy.h 를 EXEC SQL INCLUDE.
|
||||
* Usage: mm_bizno_audit_batch
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "mm_dbio.h"
|
||||
|
||||
/* 0=정상, 1=형식 오류, 2=검증숫자 불일치 */
|
||||
static int bizno_verdict(const char *no)
|
||||
{
|
||||
static const int w[9] = { 1, 3, 7, 1, 3, 7, 1, 3, 5 };
|
||||
int i, sum = 0;
|
||||
if (strlen(no) != 10) return 1;
|
||||
for (i = 0; i < 10; i++) if (no[i] < '0' || no[i] > '9') return 1;
|
||||
for (i = 0; i < 9; i++) sum += (no[i] - '0') * w[i];
|
||||
sum += ((no[8] - '0') * 5) / 10;
|
||||
return ((10 - sum % 10) % 10) == (no[9] - '0') ? 0 : 2;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
long checked = 0, bad = 0;
|
||||
int verdict;
|
||||
(void)argc; (void)argv;
|
||||
|
||||
EXEC SQL INCLUDE mm_bizno_audit_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(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL DECLARE bza CURSOR FOR
|
||||
SELECT merchant_id, biz_reg_no FROM mm_merchant_ext
|
||||
WHERE status = 'ACTIVE' AND biz_reg_no <> ''
|
||||
ORDER BY merchant_id;
|
||||
EXEC SQL OPEN bza;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
|
||||
for (;;) {
|
||||
EXEC SQL FETCH bza INTO :b_merch, :b_bizno;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "FETCH FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE bza; tpabort(0); return 1; }
|
||||
checked++;
|
||||
verdict = bizno_verdict(b_bizno);
|
||||
if (verdict != 0) {
|
||||
if (mmdb_insert_merch_hist(b_merch, "BIZNO_ERR", "", b_bizno,
|
||||
verdict == 1 ? "사업자번호 형식 오류" : "사업자번호 검증숫자 불일치") < 0) {
|
||||
EXEC SQL CLOSE bza; tpabort(0); return 1;
|
||||
}
|
||||
bad++;
|
||||
}
|
||||
}
|
||||
EXEC SQL CLOSE bza;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> mm_bizno_audit_batch COMMIT: 점검=%ld건 위반=%ld건\n", checked, bad);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
5
app/src/mm/batch/mm_bizno_audit_cpy.h
Normal file
5
app/src/mm/batch/mm_bizno_audit_cpy.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
/* mm_bizno_audit_cpy.h - mm_bizno_audit_batch 전용 카피북 (host 변수 선언). */
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char b_merch[64];
|
||||
char b_bizno[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
47
app/src/mm/batch/mm_close_sweep_batch.pgc
Normal file
47
app/src/mm/batch/mm_close_sweep_batch.pgc
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* mm_close_sweep_batch.pgc - 폐업 가맹점 부속 마스터 정리 배치 (IN-subquery 일괄 + XA).
|
||||
*
|
||||
* DELETED 가맹점에 딸린 부속 데이터를 일괄 정리한다:
|
||||
* 미폐기 단말 SCRAPPED 전환, 수수료율 행 삭제, 한도 행 삭제.
|
||||
* 커서 없이 서브쿼리 3방으로 처리. 전 구간 ONE global XA transaction.
|
||||
* host 변수는 전용 카피북 mm_close_sweep_cpy.h 를 EXEC SQL INCLUDE.
|
||||
* Usage: mm_close_sweep_batch
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
(void)argc; (void)argv;
|
||||
|
||||
EXEC SQL INCLUDE mm_close_sweep_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(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL UPDATE mm_terminal SET status = 'SCRAPPED'
|
||||
WHERE status <> 'SCRAPPED'
|
||||
AND merchant_id IN (SELECT merchant_id FROM mm_merchant_ext WHERE status = 'DELETED');
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "TERM FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
b_terms = sqlca.sqlerrd[2];
|
||||
|
||||
EXEC SQL DELETE FROM mm_fee_rate
|
||||
WHERE merchant_id IN (SELECT merchant_id FROM mm_merchant_ext WHERE status = 'DELETED');
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "FEE FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
b_fees = sqlca.sqlerrd[2];
|
||||
|
||||
EXEC SQL DELETE FROM mm_limit
|
||||
WHERE merchant_id IN (SELECT merchant_id FROM mm_merchant_ext WHERE status = 'DELETED');
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "LIMIT FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
b_limits = sqlca.sqlerrd[2];
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> mm_close_sweep_batch COMMIT: 단말 폐기=%ld 요율 삭제=%ld 한도 삭제=%ld\n",
|
||||
b_terms, b_fees, b_limits);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
6
app/src/mm/batch/mm_close_sweep_cpy.h
Normal file
6
app/src/mm/batch/mm_close_sweep_cpy.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
/* mm_close_sweep_cpy.h - mm_close_sweep_batch 전용 카피북 (host 변수 선언). */
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long b_terms;
|
||||
long b_fees;
|
||||
long b_limits;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
46
app/src/mm/batch/mm_codemap_gc_batch.pgc
Normal file
46
app/src/mm/batch/mm_codemap_gc_batch.pgc
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* mm_codemap_gc_batch.pgc - 비활성 코드 매핑 정리(GC) 배치 (집합 DELETE 2단 + XA).
|
||||
*
|
||||
* (1) MAP_* 네임스페이스의 INACTIVE 매핑 행을 즉시 삭제하고,
|
||||
* (2) MERCH_REL 관계의 INACTIVE 행은 보존일수 경과분만 삭제한다.
|
||||
* 커서 없이 집합 DELETE 두 번으로 처리, 삭제 건수는 sqlca.sqlerrd 로 집계.
|
||||
* 전 구간 ONE global XA transaction.
|
||||
* host 변수는 전용 카피북 mm_codemap_gc_cpy.h 를 EXEC SQL INCLUDE.
|
||||
* Usage: mm_codemap_gc_batch [REL_KEEP_DAYS=90]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
long map_gone, rel_gone;
|
||||
|
||||
EXEC SQL INCLUDE mm_codemap_gc_cpy;
|
||||
|
||||
b_days = (argc > 1) ? atol(argv[1]) : 90;
|
||||
if (b_days < 1) b_days = 90;
|
||||
|
||||
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 DELETE FROM mm_code
|
||||
WHERE substr(code_group, 1, 4) = 'MAP_' AND status = 'INACTIVE';
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "DELETE(MAP) FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
map_gone = sqlca.sqlerrd[2];
|
||||
|
||||
EXEC SQL DELETE FROM mm_code
|
||||
WHERE code_group = 'MERCH_REL' AND status = 'INACTIVE'
|
||||
AND created_at < now() - :b_days * interval '1 day';
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "DELETE(REL) FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
rel_gone = sqlca.sqlerrd[2];
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> mm_codemap_gc_batch COMMIT: 매핑 삭제=%ld건 관계 삭제=%ld건 (보존 %ld일)\n",
|
||||
map_gone, rel_gone, b_days);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
4
app/src/mm/batch/mm_codemap_gc_cpy.h
Normal file
4
app/src/mm/batch/mm_codemap_gc_cpy.h
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
/* mm_codemap_gc_cpy.h - mm_codemap_gc_batch 전용 카피북 (host 변수 선언). */
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long b_days;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
63
app/src/mm/batch/mm_consist_report_batch.pgc
Normal file
63
app/src/mm/batch/mm_consist_report_batch.pgc
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* mm_consist_report_batch.pgc - 마스터 정합성 종합 리포트 배치 (read-only 점검 5종 + XA).
|
||||
*
|
||||
* 마스터 전반의 불일치를 한 트랜잭션 스냅샷에서 집계해 리포트로 출력한다:
|
||||
* 고아 단말 / 요율 없는 활성 가맹점 / 한도 없는 활성 가맹점 / 중복 사업자번호 /
|
||||
* 심사 적체(APPLIED+REVIEW). 불일치가 하나라도 있으면 exit 2 (모니터링 연동용).
|
||||
* host 변수는 전용 카피북 mm_consist_report_cpy.h 를 EXEC SQL INCLUDE.
|
||||
* Usage: mm_consist_report_batch
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
long faults;
|
||||
(void)argc; (void)argv;
|
||||
|
||||
EXEC SQL INCLUDE mm_consist_report_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(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :r_orphan_term FROM mm_terminal t
|
||||
WHERE NOT EXISTS (SELECT 1 FROM mm_merchant_ext m WHERE m.merchant_id = t.merchant_id);
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "CHK1 FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :r_no_fee FROM mm_merchant_ext m
|
||||
WHERE m.status = 'ACTIVE'
|
||||
AND NOT EXISTS (SELECT 1 FROM mm_fee_rate f WHERE f.merchant_id = m.merchant_id);
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "CHK2 FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :r_no_limit FROM mm_merchant_ext m
|
||||
WHERE m.status = 'ACTIVE'
|
||||
AND NOT EXISTS (SELECT 1 FROM mm_limit l WHERE l.merchant_id = m.merchant_id);
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "CHK3 FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :r_dup_bizno FROM (
|
||||
SELECT biz_reg_no FROM mm_merchant_ext
|
||||
WHERE biz_reg_no <> '' AND status <> 'DELETED'
|
||||
GROUP BY biz_reg_no HAVING count(*) > 1) d;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "CHK4 FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :r_backlog FROM mm_merchant_ext
|
||||
WHERE status IN ('APPLIED', 'REVIEW');
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "CHK5 FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
|
||||
faults = r_orphan_term + r_no_fee + r_no_limit + r_dup_bizno;
|
||||
printf("=== mm 마스터 정합성 리포트 ===\n");
|
||||
printf("고아 단말 : %ld\n", r_orphan_term);
|
||||
printf("요율 없는 활성 가맹점: %ld\n", r_no_fee);
|
||||
printf("한도 없는 활성 가맹점: %ld\n", r_no_limit);
|
||||
printf("중복 사업자번호 : %ld\n", r_dup_bizno);
|
||||
printf("심사 적체(참고) : %ld\n", r_backlog);
|
||||
printf(">>> mm_consist_report_batch DONE: 불일치=%ld\n", faults);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return faults > 0 ? 2 : 0;
|
||||
}
|
||||
8
app/src/mm/batch/mm_consist_report_cpy.h
Normal file
8
app/src/mm/batch/mm_consist_report_cpy.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
/* mm_consist_report_cpy.h - mm_consist_report_batch 전용 카피북 (host 변수 선언). */
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long r_orphan_term;
|
||||
long r_no_fee;
|
||||
long r_no_limit;
|
||||
long r_dup_bizno;
|
||||
long r_backlog;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
62
app/src/mm/batch/mm_contract_renew_batch.pgc
Normal file
62
app/src/mm/batch/mm_contract_renew_batch.pgc
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* mm_contract_renew_batch.pgc - 만기 도래 가맹 계약 자동갱신 배치 (GROUP BY 커서 + XA).
|
||||
*
|
||||
* 가맹점별 최종 계약 만기(after_val 최대값)가 오늘 이하인 건을 커서로 훑어
|
||||
* 만기일 기준 개월수 연장한 새 CONTRACT 이력을 적재한다 (해지 이력이 뒤따르는
|
||||
* 가맹점은 갱신 대상에서 제외). 전 구간 ONE global XA transaction.
|
||||
* host 변수는 전용 카피북 mm_contract_renew_cpy.h 를 EXEC SQL INCLUDE.
|
||||
* Usage: mm_contract_renew_batch [MONTHS=12]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "mm_dbio.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
long renewed = 0;
|
||||
|
||||
EXEC SQL INCLUDE mm_contract_renew_cpy;
|
||||
|
||||
b_mon = (argc > 1) ? atol(argv[1]) : 12;
|
||||
if (b_mon < 1 || b_mon > 120) b_mon = 12;
|
||||
|
||||
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 crn CURSOR FOR
|
||||
SELECT h.merchant_id, max(h.after_val)
|
||||
FROM mm_merch_hist h
|
||||
JOIN mm_merchant_ext m ON m.merchant_id = h.merchant_id AND m.status = 'ACTIVE'
|
||||
WHERE h.action = 'CONTRACT'
|
||||
AND NOT EXISTS (SELECT 1 FROM mm_merch_hist e
|
||||
WHERE e.merchant_id = h.merchant_id AND e.action = 'CONT_END'
|
||||
AND e.hist_id > h.hist_id)
|
||||
GROUP BY h.merchant_id
|
||||
HAVING max(h.after_val) <= to_char(current_date, 'YYYYMMDD')
|
||||
ORDER BY h.merchant_id;
|
||||
EXEC SQL OPEN crn;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
|
||||
for (;;) {
|
||||
EXEC SQL FETCH crn INTO :b_merch, :b_old;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "FETCH FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE crn; tpabort(0); return 1; }
|
||||
EXEC SQL SELECT to_char(to_date(:b_old, 'YYYYMMDD') + :b_mon * interval '1 month', 'YYYYMMDD')
|
||||
INTO :b_new;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "CALC FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE crn; tpabort(0); return 1; }
|
||||
if (mmdb_insert_merch_hist(b_merch, "CONTRACT", b_old, b_new, "만기 도래 배치 자동갱신") < 0) {
|
||||
EXEC SQL CLOSE crn; tpabort(0); return 1;
|
||||
}
|
||||
renewed++;
|
||||
}
|
||||
EXEC SQL CLOSE crn;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> mm_contract_renew_batch COMMIT: 연장=%ld개월 갱신=%ld건\n", b_mon, renewed);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
7
app/src/mm/batch/mm_contract_renew_cpy.h
Normal file
7
app/src/mm/batch/mm_contract_renew_cpy.h
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
/* mm_contract_renew_cpy.h - mm_contract_renew_batch 전용 카피북 (host 변수 선언). */
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long b_mon;
|
||||
char b_merch[64];
|
||||
char b_old[16];
|
||||
char b_new[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
76
app/src/mm/batch/mm_grade_demote_batch.pgc
Normal file
76
app/src/mm/batch/mm_grade_demote_batch.pgc
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* mm_grade_demote_batch.pgc - 매출 미달 가맹점 등급 강등 배치 (LEFT JOIN 집계 커서 + XA).
|
||||
*
|
||||
* 최근 N일 매출 합계가 현재 등급의 유지 기준(S>=5억, A>=1억, B>=1천만)에 미달하는
|
||||
* 활성 가맹점을 한 단계씩 강등(S->A->B->C)하고 GRADE_DEM 이력을 남긴다.
|
||||
* 승격은 하지 않는다 (승격은 mm_grade_recalc_batch 소관). ONE global XA transaction.
|
||||
* host 변수는 전용 카피북 mm_grade_demote_cpy.h 를 EXEC SQL INCLUDE.
|
||||
* Usage: mm_grade_demote_batch [DAYS=90]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "mm_dbio.h"
|
||||
|
||||
/* 등급 유지 최소 매출 (원). 미달 시 한 단계 강등 */
|
||||
static long keep_floor(const char *grade)
|
||||
{
|
||||
if (grade[0] == 'S') return 500000000L;
|
||||
if (grade[0] == 'A') return 100000000L;
|
||||
if (grade[0] == 'B') return 10000000L;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *one_down(const char *grade)
|
||||
{
|
||||
if (grade[0] == 'S') return "A";
|
||||
if (grade[0] == 'A') return "B";
|
||||
return "C";
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
long demoted = 0;
|
||||
|
||||
EXEC SQL INCLUDE mm_grade_demote_cpy;
|
||||
|
||||
b_days = (argc > 1) ? atol(argv[1]) : 90;
|
||||
if (b_days < 1) b_days = 90;
|
||||
|
||||
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 gdm CURSOR FOR
|
||||
SELECT me.merchant_id, me.grade, coalesce(sum(ms.gross_amount), 0)
|
||||
FROM mm_merchant_ext me
|
||||
LEFT JOIN merchant_summary ms
|
||||
ON ms.merchant_id = me.merchant_id
|
||||
AND ms.biz_date >= current_date - :b_days
|
||||
WHERE me.status = 'ACTIVE' AND me.grade IN ('S', 'A', 'B')
|
||||
GROUP BY me.merchant_id, me.grade
|
||||
ORDER BY me.merchant_id;
|
||||
EXEC SQL OPEN gdm;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
|
||||
for (;;) {
|
||||
EXEC SQL FETCH gdm INTO :b_merch, :b_grade, :b_gross;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "FETCH FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE gdm; tpabort(0); return 1; }
|
||||
if (b_gross >= keep_floor(b_grade)) continue;
|
||||
strncpy(b_next, one_down(b_grade), sizeof(b_next)-1); b_next[sizeof(b_next)-1] = 0;
|
||||
if (mmdb_update_merchant_grade(b_merch, b_next) < 0) { EXEC SQL CLOSE gdm; tpabort(0); return 1; }
|
||||
if (mmdb_insert_merch_hist(b_merch, "GRADE_DEM", b_grade, b_next, "매출 미달 배치 강등") < 0) {
|
||||
EXEC SQL CLOSE gdm; tpabort(0); return 1;
|
||||
}
|
||||
demoted++;
|
||||
}
|
||||
EXEC SQL CLOSE gdm;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> mm_grade_demote_batch COMMIT: 기간=%ld일 강등=%ld건\n", b_days, demoted);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
8
app/src/mm/batch/mm_grade_demote_cpy.h
Normal file
8
app/src/mm/batch/mm_grade_demote_cpy.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
/* mm_grade_demote_cpy.h - mm_grade_demote_batch 전용 카피북 (host 변수 선언). */
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long b_days;
|
||||
char b_merch[64];
|
||||
char b_grade[8];
|
||||
long b_gross;
|
||||
char b_next[8];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
56
app/src/mm/batch/mm_mcc_reclass_batch.pgc
Normal file
56
app/src/mm/batch/mm_mcc_reclass_batch.pgc
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* mm_mcc_reclass_batch.pgc - MCC 위험도 재분류 배치 (업종별 폐업률 기반 + XA).
|
||||
*
|
||||
* MCC 별 소속 가맹점의 폐업(DELETED) 비율로 위험도를 재산정한다:
|
||||
* 신위험도 = 1 + (폐업수 * 4 / 전체수), 1~5 범위. 기존 값과 다를 때만 UPDATE.
|
||||
* 전 구간 ONE global XA transaction.
|
||||
* host 변수는 전용 카피북 mm_mcc_reclass_cpy.h 를 EXEC SQL INCLUDE.
|
||||
* Usage: mm_mcc_reclass_batch
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
long scanned = 0, changed = 0;
|
||||
(void)argc; (void)argv;
|
||||
|
||||
EXEC SQL INCLUDE mm_mcc_reclass_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(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL DECLARE mrc CURSOR FOR
|
||||
SELECT c.mcc, c.risk_level, count(me.merchant_id),
|
||||
coalesce(sum(CASE WHEN me.status = 'DELETED' THEN 1 ELSE 0 END), 0)
|
||||
FROM mm_mcc c
|
||||
JOIN mm_merchant_ext me ON me.mcc = c.mcc
|
||||
GROUP BY c.mcc, c.risk_level
|
||||
ORDER BY c.mcc;
|
||||
EXEC SQL OPEN mrc;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
|
||||
for (;;) {
|
||||
EXEC SQL FETCH mrc INTO :b_mcc, :b_risk, :b_total, :b_closed;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "FETCH FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE mrc; tpabort(0); return 1; }
|
||||
scanned++;
|
||||
if (b_total <= 0) continue;
|
||||
b_newrisk = 1 + (b_closed * 4) / b_total;
|
||||
if (b_newrisk > 5) b_newrisk = 5;
|
||||
if (b_newrisk == b_risk) continue;
|
||||
EXEC SQL UPDATE mm_mcc SET risk_level = :b_newrisk WHERE mcc = :b_mcc;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "UPDATE FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE mrc; tpabort(0); return 1; }
|
||||
changed++;
|
||||
}
|
||||
EXEC SQL CLOSE mrc;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> mm_mcc_reclass_batch COMMIT: 점검 MCC=%ld 위험도 변경=%ld건\n", scanned, changed);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
8
app/src/mm/batch/mm_mcc_reclass_cpy.h
Normal file
8
app/src/mm/batch/mm_mcc_reclass_cpy.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
/* mm_mcc_reclass_cpy.h - mm_mcc_reclass_batch 전용 카피북 (host 변수 선언). */
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char b_mcc[8];
|
||||
long b_total;
|
||||
long b_closed;
|
||||
long b_risk;
|
||||
long b_newrisk;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
58
app/src/mm/batch/mm_partner_sync_batch.pgc
Normal file
58
app/src/mm/batch/mm_partner_sync_batch.pgc
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* mm_partner_sync_batch.pgc - 제휴사 마스터-발급사 동기화 배치 (upsert 커서 + XA).
|
||||
*
|
||||
* 활성 발급사(mm_issuer)를 커서로 훑어 제휴사 코드(PARTNER 코드그룹)로 upsert 하고,
|
||||
* 발급사 마스터에서 사라졌거나 비활성인 제휴사 코드는 INACTIVE 로 내린다.
|
||||
* 전 구간 ONE global XA transaction.
|
||||
* host 변수는 전용 카피북 mm_partner_sync_cpy.h 를 EXEC SQL INCLUDE.
|
||||
* Usage: mm_partner_sync_batch
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
long synced = 0, retired;
|
||||
(void)argc; (void)argv;
|
||||
|
||||
EXEC SQL INCLUDE mm_partner_sync_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(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL DECLARE psy CURSOR FOR
|
||||
SELECT issuer_cd, issuer_name FROM mm_issuer
|
||||
WHERE status = 'ACTIVE' ORDER BY issuer_cd;
|
||||
EXEC SQL OPEN psy;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
|
||||
for (;;) {
|
||||
EXEC SQL FETCH psy INTO :b_cd, :b_nm;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "FETCH FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE psy; tpabort(0); return 1; }
|
||||
EXEC SQL INSERT INTO mm_code (code_group, code, code_name, status)
|
||||
VALUES ('PARTNER', :b_cd, :b_nm, 'ACTIVE')
|
||||
ON CONFLICT (code_group, code)
|
||||
DO UPDATE SET code_name = EXCLUDED.code_name, status = 'ACTIVE';
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "UPSERT FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE psy; tpabort(0); return 1; }
|
||||
synced++;
|
||||
}
|
||||
EXEC SQL CLOSE psy;
|
||||
|
||||
/* 발급사 마스터에 없는(또는 비활성) 제휴사 코드는 은퇴 처리 */
|
||||
EXEC SQL UPDATE mm_code SET status = 'INACTIVE'
|
||||
WHERE code_group = 'PARTNER' AND status = 'ACTIVE'
|
||||
AND NOT EXISTS (SELECT 1 FROM mm_issuer i
|
||||
WHERE i.issuer_cd = mm_code.code AND i.status = 'ACTIVE');
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "RETIRE FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
retired = sqlca.sqlerrd[2];
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> mm_partner_sync_batch COMMIT: 동기화=%ld건 은퇴=%ld건\n", synced, retired);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
5
app/src/mm/batch/mm_partner_sync_cpy.h
Normal file
5
app/src/mm/batch/mm_partner_sync_cpy.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
/* mm_partner_sync_cpy.h - mm_partner_sync_batch 전용 카피북 (host 변수 선언). */
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char b_cd[16];
|
||||
char b_nm[64];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
55
app/src/mm/batch/mm_rel_orphan_batch.pgc
Normal file
55
app/src/mm/batch/mm_rel_orphan_batch.pgc
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* mm_rel_orphan_batch.pgc - 대표-하위 가맹점 관계 정합성 정리 배치 (NOT EXISTS 커서 + XA).
|
||||
*
|
||||
* 대표가맹점(code_name)이 더 이상 활성이 아닌 MERCH_REL 관계 행을 커서로 찾아
|
||||
* INACTIVE 로 내리고 하위가맹점 이력(REL_UNLINK)을 남긴다.
|
||||
* 전 구간 ONE global XA transaction.
|
||||
* host 변수는 전용 카피북 mm_rel_orphan_cpy.h 를 EXEC SQL INCLUDE.
|
||||
* Usage: mm_rel_orphan_batch
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "mm_dbio.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
long cleaned = 0;
|
||||
(void)argc; (void)argv;
|
||||
|
||||
EXEC SQL INCLUDE mm_rel_orphan_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(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
|
||||
|
||||
EXEC SQL DECLARE rox CURSOR FOR
|
||||
SELECT c.code, c.code_name FROM mm_code c
|
||||
WHERE c.code_group = 'MERCH_REL' AND c.status = 'ACTIVE'
|
||||
AND NOT EXISTS (SELECT 1 FROM mm_merchant_ext m
|
||||
WHERE m.merchant_id = c.code_name AND m.status = 'ACTIVE')
|
||||
ORDER BY c.code;
|
||||
EXEC SQL OPEN rox;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
|
||||
for (;;) {
|
||||
EXEC SQL FETCH rox INTO :b_child, :b_parent;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "FETCH FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE rox; tpabort(0); return 1; }
|
||||
EXEC SQL UPDATE mm_code SET status = 'INACTIVE'
|
||||
WHERE code_group = 'MERCH_REL' AND code = :b_child;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "UPDATE FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE rox; tpabort(0); return 1; }
|
||||
if (mmdb_insert_merch_hist(b_child, "REL_UNLINK", b_parent, "", "대표가맹점 비활성 배치 해제") < 0) {
|
||||
EXEC SQL CLOSE rox; tpabort(0); return 1;
|
||||
}
|
||||
cleaned++;
|
||||
}
|
||||
EXEC SQL CLOSE rox;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> mm_rel_orphan_batch COMMIT: 관계 해제=%ld건\n", cleaned);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
5
app/src/mm/batch/mm_rel_orphan_cpy.h
Normal file
5
app/src/mm/batch/mm_rel_orphan_cpy.h
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
/* mm_rel_orphan_cpy.h - mm_rel_orphan_batch 전용 카피북 (host 변수 선언). */
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char b_child[64];
|
||||
char b_parent[64];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
54
app/src/mm/batch/mm_term_scrap_batch.pgc
Normal file
54
app/src/mm/batch/mm_term_scrap_batch.pgc
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* mm_term_scrap_batch.pgc - 장기 정지 단말 일괄 폐기 배치 (커서 + UPDATE + 이력 + XA).
|
||||
*
|
||||
* SUSPENDED 상태로 보존일수 이상 경과한 단말을 커서로 훑어 SCRAPPED 로 전환하고,
|
||||
* 소속 가맹점 이력(TERM_SCRAP)을 남긴다. 전 구간 ONE global XA transaction.
|
||||
* host 변수는 전용 카피북 mm_term_scrap_cpy.h 를 EXEC SQL INCLUDE.
|
||||
* Usage: mm_term_scrap_batch [DAYS=180]
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <atmi.h>
|
||||
#include "mm_dbio.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
long scrapped = 0;
|
||||
|
||||
EXEC SQL INCLUDE mm_term_scrap_cpy;
|
||||
|
||||
b_days = (argc > 1) ? atol(argv[1]) : 180;
|
||||
if (b_days < 1) b_days = 180;
|
||||
|
||||
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 tsc CURSOR FOR
|
||||
SELECT terminal_id, merchant_id FROM mm_terminal
|
||||
WHERE status = 'SUSPENDED'
|
||||
AND created_at < now() - :b_days * interval '1 day'
|
||||
ORDER BY terminal_id;
|
||||
EXEC SQL OPEN tsc;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
|
||||
|
||||
for (;;) {
|
||||
EXEC SQL FETCH tsc INTO :b_term, :b_merch;
|
||||
if (sqlca.sqlcode == 100) break;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "FETCH FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE tsc; tpabort(0); return 1; }
|
||||
EXEC SQL UPDATE mm_terminal SET status = 'SCRAPPED' WHERE terminal_id = :b_term;
|
||||
if (sqlca.sqlcode < 0) { fprintf(stderr, "UPDATE FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); EXEC SQL CLOSE tsc; tpabort(0); return 1; }
|
||||
if (mmdb_insert_merch_hist(b_merch, "TERM_SCRAP", "SUSPENDED", "SCRAPPED", "장기 정지 단말 배치 폐기") < 0) {
|
||||
EXEC SQL CLOSE tsc; tpabort(0); return 1;
|
||||
}
|
||||
scrapped++;
|
||||
}
|
||||
EXEC SQL CLOSE tsc;
|
||||
|
||||
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
|
||||
printf(">>> mm_term_scrap_batch COMMIT: 기준=%ld일 폐기=%ld대\n", b_days, scrapped);
|
||||
|
||||
tpclose(); tpterm();
|
||||
return 0;
|
||||
}
|
||||
6
app/src/mm/batch/mm_term_scrap_cpy.h
Normal file
6
app/src/mm/batch/mm_term_scrap_cpy.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
/* mm_term_scrap_cpy.h - mm_term_scrap_batch 전용 카피북 (host 변수 선언). */
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long b_days;
|
||||
char b_term[64];
|
||||
char b_merch[64];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
* mm_svr.pgc - mm (마스터/master) MODULE SERVER (thin dispatcher).
|
||||
*
|
||||
* The legacy "one module server, many services" pattern: this binary owns NO
|
||||
* business logic. Each of mm's ~30 online services now lives in its own file
|
||||
* business logic. Each of mm's ~75 online services now lives in its own file
|
||||
* (app/src/mm/svc/<SVCNAME>.pgc) with its own copybook header
|
||||
* (app/src/mm/svc/<SVCNAME>.h); those objects are archived into libmmsvc.a and
|
||||
* linked into this server. Here we only include every service copybook, tpopen()
|
||||
|
|
@ -46,6 +46,51 @@
|
|||
#include "MM_CODE_CACHE.h"
|
||||
#include "MM_STATUS.h"
|
||||
#include "MM_CONFIRM.h"
|
||||
#include "MM_TERM_MOVE.h"
|
||||
#include "MM_TERM_SCRAP.h"
|
||||
#include "MM_TERM_SUSPEND.h"
|
||||
#include "MM_TERM_CNT.h"
|
||||
#include "MM_APPLY_REG.h"
|
||||
#include "MM_APPLY_REVIEW.h"
|
||||
#include "MM_APPLY_APPROVE.h"
|
||||
#include "MM_APPLY_REJECT.h"
|
||||
#include "MM_APPLY_STATUS.h"
|
||||
#include "MM_CONTRACT_NEW.h"
|
||||
#include "MM_CONTRACT_RENEW.h"
|
||||
#include "MM_CONTRACT_END.h"
|
||||
#include "MM_CONTRACT_INQ.h"
|
||||
#include "MM_PARTNER_REG.h"
|
||||
#include "MM_PARTNER_INQ.h"
|
||||
#include "MM_PARTNER_STATUS.h"
|
||||
#include "MM_REL_LINK.h"
|
||||
#include "MM_REL_UNLINK.h"
|
||||
#include "MM_REL_LIST.h"
|
||||
#include "MM_MCC_UPD.h"
|
||||
#include "MM_MCC_INQ.h"
|
||||
#include "MM_MCC_RISKLIST.h"
|
||||
#include "MM_RATE_REQ.h"
|
||||
#include "MM_RATE_APPROVE.h"
|
||||
#include "MM_RATE_REJECT.h"
|
||||
#include "MM_MERCH_PAUSE.h"
|
||||
#include "MM_MERCH_RESUME.h"
|
||||
#include "MM_MERCH_CLOSE.h"
|
||||
#include "MM_ACCT_VERIFY.h"
|
||||
#include "MM_ACCT_VRF_HIST.h"
|
||||
#include "MM_ACCT_VRF_STAT.h"
|
||||
#include "MM_GRADE_PREVIEW.h"
|
||||
#include "MM_GRADE_ADJUST.h"
|
||||
#include "MM_GRADE_DIST.h"
|
||||
#include "MM_AUDIT_TRAIL.h"
|
||||
#include "MM_AUDIT_RECENT.h"
|
||||
#include "MM_AUDIT_PURGE.h"
|
||||
#include "MM_CHK_TERM.h"
|
||||
#include "MM_CHK_FEERATE.h"
|
||||
#include "MM_CHK_LIMIT.h"
|
||||
#include "MM_CODEMAP_SET.h"
|
||||
#include "MM_CODEMAP_GET.h"
|
||||
#include "MM_CODEMAP_DEL.h"
|
||||
#include "MM_BIZNO_CHECK.h"
|
||||
#include "MM_BIZNO_UPD.h"
|
||||
|
||||
/* ----- advertise table: {service name, function} (fn is extern from its file) */
|
||||
static struct { const char *name; void (*fn)(TPSVCINFO *); } SVCS[] = {
|
||||
|
|
@ -79,6 +124,51 @@ static struct { const char *name; void (*fn)(TPSVCINFO *); } SVCS[] = {
|
|||
{"MM_CODE_CACHE", MM_CODE_CACHE},
|
||||
{"MM_STATUS", MM_STATUS},
|
||||
{"MM_CONFIRM", MM_CONFIRM},
|
||||
{"MM_TERM_MOVE", MM_TERM_MOVE},
|
||||
{"MM_TERM_SCRAP", MM_TERM_SCRAP},
|
||||
{"MM_TERM_SUSPEND", MM_TERM_SUSPEND},
|
||||
{"MM_TERM_CNT", MM_TERM_CNT},
|
||||
{"MM_APPLY_REG", MM_APPLY_REG},
|
||||
{"MM_APPLY_REVIEW", MM_APPLY_REVIEW},
|
||||
{"MM_APPLY_APPROVE", MM_APPLY_APPROVE},
|
||||
{"MM_APPLY_REJECT", MM_APPLY_REJECT},
|
||||
{"MM_APPLY_STATUS", MM_APPLY_STATUS},
|
||||
{"MM_CONTRACT_NEW", MM_CONTRACT_NEW},
|
||||
{"MM_CONTRACT_RENEW", MM_CONTRACT_RENEW},
|
||||
{"MM_CONTRACT_END", MM_CONTRACT_END},
|
||||
{"MM_CONTRACT_INQ", MM_CONTRACT_INQ},
|
||||
{"MM_PARTNER_REG", MM_PARTNER_REG},
|
||||
{"MM_PARTNER_INQ", MM_PARTNER_INQ},
|
||||
{"MM_PARTNER_STATUS", MM_PARTNER_STATUS},
|
||||
{"MM_REL_LINK", MM_REL_LINK},
|
||||
{"MM_REL_UNLINK", MM_REL_UNLINK},
|
||||
{"MM_REL_LIST", MM_REL_LIST},
|
||||
{"MM_MCC_UPD", MM_MCC_UPD},
|
||||
{"MM_MCC_INQ", MM_MCC_INQ},
|
||||
{"MM_MCC_RISKLIST", MM_MCC_RISKLIST},
|
||||
{"MM_RATE_REQ", MM_RATE_REQ},
|
||||
{"MM_RATE_APPROVE", MM_RATE_APPROVE},
|
||||
{"MM_RATE_REJECT", MM_RATE_REJECT},
|
||||
{"MM_MERCH_PAUSE", MM_MERCH_PAUSE},
|
||||
{"MM_MERCH_RESUME", MM_MERCH_RESUME},
|
||||
{"MM_MERCH_CLOSE", MM_MERCH_CLOSE},
|
||||
{"MM_ACCT_VERIFY", MM_ACCT_VERIFY},
|
||||
{"MM_ACCT_VRF_HIST", MM_ACCT_VRF_HIST},
|
||||
{"MM_ACCT_VRF_STAT", MM_ACCT_VRF_STAT},
|
||||
{"MM_GRADE_PREVIEW", MM_GRADE_PREVIEW},
|
||||
{"MM_GRADE_ADJUST", MM_GRADE_ADJUST},
|
||||
{"MM_GRADE_DIST", MM_GRADE_DIST},
|
||||
{"MM_AUDIT_TRAIL", MM_AUDIT_TRAIL},
|
||||
{"MM_AUDIT_RECENT", MM_AUDIT_RECENT},
|
||||
{"MM_AUDIT_PURGE", MM_AUDIT_PURGE},
|
||||
{"MM_CHK_TERM", MM_CHK_TERM},
|
||||
{"MM_CHK_FEERATE", MM_CHK_FEERATE},
|
||||
{"MM_CHK_LIMIT", MM_CHK_LIMIT},
|
||||
{"MM_CODEMAP_SET", MM_CODEMAP_SET},
|
||||
{"MM_CODEMAP_GET", MM_CODEMAP_GET},
|
||||
{"MM_CODEMAP_DEL", MM_CODEMAP_DEL},
|
||||
{"MM_BIZNO_CHECK", MM_BIZNO_CHECK},
|
||||
{"MM_BIZNO_UPD", MM_BIZNO_UPD},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
|||
12
app/src/mm/svc/MM_ACCT_VERIFY.h
Normal file
12
app/src/mm/svc/MM_ACCT_VERIFY.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_ACCT_VERIFY.h - mm 서비스 MM_ACCT_VERIFY 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_STR1(검증 결과), T_RC
|
||||
*/
|
||||
#ifndef MM_ACCT_VERIFY_H
|
||||
#define MM_ACCT_VERIFY_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_ACCT_VERIFY(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_ACCT_VERIFY_H */
|
||||
42
app/src/mm/svc/MM_ACCT_VERIFY.pgc
Normal file
42
app/src/mm/svc/MM_ACCT_VERIFY.pgc
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* MM_ACCT_VERIFY.pgc - mm 모듈 서비스 MM_ACCT_VERIFY (one service = one file).
|
||||
* 기능: 정산계좌 검증 실행 (형식 검사 + ACCT_VRF 검증 이력 적재).
|
||||
* 입력: T_MERCHANT. 출력: T_STR1=결과(OK/EMPTY/FORMAT), T_RC=0정상 1미존재 2계좌미등록 3형식오류.
|
||||
* 검증 결과는 성공/실패 모두 이력으로 남긴다 (감사 추적용).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_ACCT_VERIFY.h"
|
||||
|
||||
void MM_ACCT_VERIFY(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64];
|
||||
const char *result;
|
||||
long rc = 0;
|
||||
size_t i, len;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_acct[40];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT settle_acct INTO :h_acct FROM mm_merchant_ext
|
||||
WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
len = strlen(h_acct);
|
||||
if (len == 0) { result = "EMPTY"; rc = 2; }
|
||||
else {
|
||||
result = "OK";
|
||||
if (len < 10 || len > 16) { result = "FORMAT"; rc = 3; }
|
||||
else for (i = 0; i < len; i++)
|
||||
if (h_acct[i] < '0' || h_acct[i] > '9') { result = "FORMAT"; rc = 3; break; }
|
||||
}
|
||||
|
||||
if (mmdb_insert_merch_hist(h_merch, "ACCT_VRF", "", result, "정산계좌 검증 수행") < 0) FAIL(b);
|
||||
Bchg(b, T_STR1, 0, (char *)result, 0L);
|
||||
setl(b, T_RC, rc);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_ACCT_VRF_HIST.h
Normal file
12
app/src/mm/svc/MM_ACCT_VRF_HIST.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_ACCT_VRF_HIST.h - mm 서비스 MM_ACCT_VRF_HIST 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_COUNT, T_STR1(최근 결과), T_STR2(최근 검증일), T_RC
|
||||
*/
|
||||
#ifndef MM_ACCT_VRF_HIST_H
|
||||
#define MM_ACCT_VRF_HIST_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_ACCT_VRF_HIST(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_ACCT_VRF_HIST_H */
|
||||
39
app/src/mm/svc/MM_ACCT_VRF_HIST.pgc
Normal file
39
app/src/mm/svc/MM_ACCT_VRF_HIST.pgc
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* MM_ACCT_VRF_HIST.pgc - mm 모듈 서비스 MM_ACCT_VRF_HIST (one service = one file).
|
||||
* 기능: 정산계좌 검증 이력 조회 (누적 횟수 + 최근 결과/일시).
|
||||
* 입력: T_MERCHANT. 출력: T_COUNT, T_STR1=최근 결과, T_STR2=최근 검증일(YYYYMMDD).
|
||||
* RC: 1=검증 이력 없음.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_ACCT_VRF_HIST.h"
|
||||
|
||||
void MM_ACCT_VRF_HIST(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_last[16], h_when[16];
|
||||
long h_cnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_cnt FROM mm_merch_hist
|
||||
WHERE merchant_id = :h_merch AND action = 'ACCT_VRF';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt == 0) { setl(b, T_RC, 1); OK(b); }
|
||||
|
||||
EXEC SQL SELECT after_val, to_char(created_at, 'YYYYMMDD')
|
||||
INTO :h_last, :h_when
|
||||
FROM mm_merch_hist
|
||||
WHERE merchant_id = :h_merch AND action = 'ACCT_VRF'
|
||||
ORDER BY hist_id DESC LIMIT 1;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
Bchg(b, T_STR1, 0, h_last, 0L);
|
||||
Bchg(b, T_STR2, 0, h_when, 0L);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_ACCT_VRF_STAT.h
Normal file
12
app/src/mm/svc/MM_ACCT_VRF_STAT.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_ACCT_VRF_STAT.h - mm 서비스 MM_ACCT_VRF_STAT 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_COUNT(총 검증), T_ARG1(검증 가맹점 수), T_ARG2(실패 건), T_RC
|
||||
*/
|
||||
#ifndef MM_ACCT_VRF_STAT_H
|
||||
#define MM_ACCT_VRF_STAT_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_ACCT_VRF_STAT(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_ACCT_VRF_STAT_H */
|
||||
28
app/src/mm/svc/MM_ACCT_VRF_STAT.pgc
Normal file
28
app/src/mm/svc/MM_ACCT_VRF_STAT.pgc
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* MM_ACCT_VRF_STAT.pgc - mm 모듈 서비스 MM_ACCT_VRF_STAT (one service = one file).
|
||||
* 기능: 정산계좌 검증 전사 통계 (총 검증 수, 검증 대상 가맹점 수, 실패 건수).
|
||||
* 출력: T_COUNT, T_ARG1, T_ARG2. 실패 = 결과가 OK가 아닌 검증.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_ACCT_VRF_STAT.h"
|
||||
|
||||
void MM_ACCT_VRF_STAT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_tot, h_merch, h_bad;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
EXEC SQL SELECT count(*),
|
||||
count(DISTINCT merchant_id),
|
||||
coalesce(sum(CASE WHEN after_val <> 'OK' THEN 1 ELSE 0 END), 0)
|
||||
INTO :h_tot, :h_merch, :h_bad
|
||||
FROM mm_merch_hist WHERE action = 'ACCT_VRF';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_COUNT, h_tot);
|
||||
setl(b, T_ARG1, h_merch);
|
||||
setl(b, T_ARG2, h_bad);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_APPLY_APPROVE.h
Normal file
12
app/src/mm/svc/MM_APPLY_APPROVE.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_APPLY_APPROVE.h - mm 서비스 MM_APPLY_APPROVE 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_ARG1(기본 수수료율 bps), T_RC
|
||||
*/
|
||||
#ifndef MM_APPLY_APPROVE_H
|
||||
#define MM_APPLY_APPROVE_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_APPLY_APPROVE(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_APPLY_APPROVE_H */
|
||||
43
app/src/mm/svc/MM_APPLY_APPROVE.pgc
Normal file
43
app/src/mm/svc/MM_APPLY_APPROVE.pgc
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* MM_APPLY_APPROVE.pgc - mm 모듈 서비스 MM_APPLY_APPROVE (one service = one file).
|
||||
* 기능: 가입 심사 승인 (REVIEW -> ACTIVE, 기본 수수료율/한도 자동 개설).
|
||||
* 입력: T_MERCHANT, T_ARG1=기본 수수료율 bps(없으면 25).
|
||||
* RC: 1=가맹점 없음, 2=REVIEW 상태가 아님.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_APPLY_APPROVE.h"
|
||||
|
||||
void MM_APPLY_APPROVE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_stat[16];
|
||||
long h_bps;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
h_bps = getl(b, T_ARG1);
|
||||
if (h_bps <= 0 || h_bps > 500) h_bps = 25;
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT status INTO :h_stat FROM mm_merchant_ext WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (strcmp(h_stat, "REVIEW") != 0) { setl(b, T_RC, 2); OK(b); }
|
||||
|
||||
EXEC SQL UPDATE mm_merchant_ext SET status = 'ACTIVE', updated_at = now()
|
||||
WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
/* 승인과 동시에 기본 수수료율/한도 레코드 개설 (이미 있으면 유지) */
|
||||
EXEC SQL INSERT INTO mm_fee_rate (merchant_id, card_type, rate_bps)
|
||||
VALUES (:h_merch, 'CREDIT', :h_bps)
|
||||
ON CONFLICT (merchant_id, card_type) DO NOTHING;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL INSERT INTO mm_limit (merchant_id) VALUES (:h_merch)
|
||||
ON CONFLICT (merchant_id) DO NOTHING;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (mmdb_insert_merch_hist(h_merch, "APPROVE", "REVIEW", "ACTIVE", "심사 승인, 기본 요율/한도 개설") < 0) FAIL(b);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_APPLY_REG.h
Normal file
12
app/src/mm/svc/MM_APPLY_REG.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_APPLY_REG.h - mm 서비스 MM_APPLY_REG 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_STR1(상호), T_STR2(사업자번호), T_STR3(MCC), T_RC
|
||||
*/
|
||||
#ifndef MM_APPLY_REG_H
|
||||
#define MM_APPLY_REG_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_APPLY_REG(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_APPLY_REG_H */
|
||||
45
app/src/mm/svc/MM_APPLY_REG.pgc
Normal file
45
app/src/mm/svc/MM_APPLY_REG.pgc
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* MM_APPLY_REG.pgc - mm 모듈 서비스 MM_APPLY_REG (one service = one file).
|
||||
* 기능: 가맹점 가입 신청 접수 (심사 워크플로 시작, 상태 APPLIED).
|
||||
* 입력: T_MERCHANT, T_STR1=상호, T_STR2=사업자번호(10자리), T_STR3=MCC.
|
||||
* RC: 1=이미 존재하는 가맹점, 2=사업자번호 형식 오류, 3=필수값 누락.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_APPLY_REG.h"
|
||||
|
||||
void MM_APPLY_REG(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64], name[64], bizno[16], mcc[8];
|
||||
int i;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_name[64], h_bizno[16], h_mcc[8];
|
||||
long h_dup;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
gets_(b, T_STR1, name, sizeof(name));
|
||||
gets_(b, T_STR2, bizno, sizeof(bizno));
|
||||
gets_(b, T_STR3, mcc, sizeof(mcc));
|
||||
if (mcc[0] == 0) strcpy(mcc, "0000");
|
||||
if (merch[0] == 0 || name[0] == 0) { setl(b, T_RC, 3); OK(b); }
|
||||
if (strlen(bizno) != 10) { setl(b, T_RC, 2); OK(b); }
|
||||
for (i = 0; i < 10; i++)
|
||||
if (bizno[i] < '0' || bizno[i] > '9') { setl(b, T_RC, 2); OK(b); }
|
||||
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
strncpy(h_name, name, sizeof(h_name)-1); h_name[sizeof(h_name)-1] = 0;
|
||||
strncpy(h_bizno, bizno, sizeof(h_bizno)-1); h_bizno[sizeof(h_bizno)-1] = 0;
|
||||
strncpy(h_mcc, mcc, sizeof(h_mcc)-1); h_mcc[sizeof(h_mcc)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_dup FROM mm_merchant_ext WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_dup > 0) { setl(b, T_RC, 1); OK(b); }
|
||||
|
||||
EXEC SQL INSERT INTO mm_merchant_ext (merchant_id, name, biz_reg_no, mcc, status)
|
||||
VALUES (:h_merch, :h_name, :h_bizno, :h_mcc, 'APPLIED');
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (mmdb_insert_merch_hist(h_merch, "APPLY", "", "APPLIED", "가입 신청 접수") < 0) FAIL(b);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_APPLY_REJECT.h
Normal file
12
app/src/mm/svc/MM_APPLY_REJECT.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_APPLY_REJECT.h - mm 서비스 MM_APPLY_REJECT 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_REASON, T_RC
|
||||
*/
|
||||
#ifndef MM_APPLY_REJECT_H
|
||||
#define MM_APPLY_REJECT_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_APPLY_REJECT(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_APPLY_REJECT_H */
|
||||
36
app/src/mm/svc/MM_APPLY_REJECT.pgc
Normal file
36
app/src/mm/svc/MM_APPLY_REJECT.pgc
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* MM_APPLY_REJECT.pgc - mm 모듈 서비스 MM_APPLY_REJECT (one service = one file).
|
||||
* 기능: 가입 심사 반려 (APPLIED/REVIEW -> REJECTED, 반려 사유 필수).
|
||||
* 입력: T_MERCHANT, T_REASON=반려 사유(필수).
|
||||
* RC: 1=가맹점 없음, 2=심사중 상태가 아님, 3=반려 사유 누락.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_APPLY_REJECT.h"
|
||||
|
||||
void MM_APPLY_REJECT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64], reason[128];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_stat[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
gets_(b, T_REASON, reason, sizeof(reason));
|
||||
if (reason[0] == 0) { setl(b, T_RC, 3); OK(b); }
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT status INTO :h_stat FROM mm_merchant_ext WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (strcmp(h_stat, "APPLIED") != 0 && strcmp(h_stat, "REVIEW") != 0) {
|
||||
setl(b, T_RC, 2); OK(b);
|
||||
}
|
||||
|
||||
EXEC SQL UPDATE mm_merchant_ext SET status = 'REJECTED', updated_at = now()
|
||||
WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (mmdb_insert_merch_hist(h_merch, "REJECT", h_stat, "REJECTED", reason) < 0) FAIL(b);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_APPLY_REVIEW.h
Normal file
12
app/src/mm/svc/MM_APPLY_REVIEW.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_APPLY_REVIEW.h - mm 서비스 MM_APPLY_REVIEW 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_ARG1(MCC 등록 여부), T_RC
|
||||
*/
|
||||
#ifndef MM_APPLY_REVIEW_H
|
||||
#define MM_APPLY_REVIEW_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_APPLY_REVIEW(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_APPLY_REVIEW_H */
|
||||
40
app/src/mm/svc/MM_APPLY_REVIEW.pgc
Normal file
40
app/src/mm/svc/MM_APPLY_REVIEW.pgc
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* MM_APPLY_REVIEW.pgc - mm 모듈 서비스 MM_APPLY_REVIEW (one service = one file).
|
||||
* 기능: 가입 신청 심사 개시 (APPLIED -> REVIEW, MCC 유효성 사전점검).
|
||||
* 입력: T_MERCHANT. 출력: T_ARG1=신청 MCC의 마스터 등록 여부(1/0).
|
||||
* RC: 1=가맹점 없음, 2=APPLIED 상태가 아님.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_APPLY_REVIEW.h"
|
||||
|
||||
void MM_APPLY_REVIEW(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64], memo[128];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_stat[16], h_mcc[8];
|
||||
long h_mccok;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT status, mcc INTO :h_stat, :h_mcc
|
||||
FROM mm_merchant_ext WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (strcmp(h_stat, "APPLIED") != 0) { setl(b, T_RC, 2); OK(b); }
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_mccok FROM mm_mcc WHERE mcc = :h_mcc;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
EXEC SQL UPDATE mm_merchant_ext SET status = 'REVIEW', updated_at = now()
|
||||
WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
snprintf(memo, sizeof(memo), "심사 개시 (MCC %s %s)", h_mcc,
|
||||
h_mccok > 0 ? "등록됨" : "미등록");
|
||||
if (mmdb_insert_merch_hist(h_merch, "REVIEW", "APPLIED", "REVIEW", memo) < 0) FAIL(b);
|
||||
setl(b, T_ARG1, h_mccok > 0 ? 1 : 0);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_APPLY_STATUS.h
Normal file
12
app/src/mm/svc/MM_APPLY_STATUS.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_APPLY_STATUS.h - mm 서비스 MM_APPLY_STATUS 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_STATUS, T_ARG1(심사 단계), T_COUNT, T_RC
|
||||
*/
|
||||
#ifndef MM_APPLY_STATUS_H
|
||||
#define MM_APPLY_STATUS_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_APPLY_STATUS(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_APPLY_STATUS_H */
|
||||
42
app/src/mm/svc/MM_APPLY_STATUS.pgc
Normal file
42
app/src/mm/svc/MM_APPLY_STATUS.pgc
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* MM_APPLY_STATUS.pgc - mm 모듈 서비스 MM_APPLY_STATUS (one service = one file).
|
||||
* 기능: 가입 심사 진행 상태 조회 (단계 코드 + 워크플로 이력 건수).
|
||||
* 입력: T_MERCHANT. 출력: T_STATUS=현재 상태, T_ARG1=단계(1접수 2심사 3승인 9반려), T_COUNT=워크플로 이력 수.
|
||||
* RC: 1=가맹점 없음.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_APPLY_STATUS.h"
|
||||
|
||||
void MM_APPLY_STATUS(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64];
|
||||
long stage = 0;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_stat[16];
|
||||
long h_cnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT status INTO :h_stat FROM mm_merchant_ext WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
if (strcmp(h_stat, "APPLIED") == 0) stage = 1;
|
||||
else if (strcmp(h_stat, "REVIEW") == 0) stage = 2;
|
||||
else if (strcmp(h_stat, "ACTIVE") == 0) stage = 3;
|
||||
else if (strcmp(h_stat, "REJECTED") == 0) stage = 9;
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_cnt FROM mm_merch_hist
|
||||
WHERE merchant_id = :h_merch
|
||||
AND action IN ('APPLY', 'REVIEW', 'APPROVE', 'REJECT');
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
Bchg(b, T_STATUS, 0, h_stat, 0L);
|
||||
setl(b, T_ARG1, stage);
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_AUDIT_PURGE.h
Normal file
12
app/src/mm/svc/MM_AUDIT_PURGE.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_AUDIT_PURGE.h - mm 서비스 MM_AUDIT_PURGE 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_ARG1(보존일수), T_COUNT(삭제 건수), T_RC
|
||||
*/
|
||||
#ifndef MM_AUDIT_PURGE_H
|
||||
#define MM_AUDIT_PURGE_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_AUDIT_PURGE(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_AUDIT_PURGE_H */
|
||||
36
app/src/mm/svc/MM_AUDIT_PURGE.pgc
Normal file
36
app/src/mm/svc/MM_AUDIT_PURGE.pgc
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* MM_AUDIT_PURGE.pgc - mm 모듈 서비스 MM_AUDIT_PURGE (one service = one file).
|
||||
* 기능: 감사 이력 보존기한 경과분 삭제 (삭제 내역 자체도 감사 기록으로 남김).
|
||||
* 입력: T_ARG1=보존일수(기본 365, 최소 30). 출력: T_COUNT=삭제 건수.
|
||||
* RC: 3=보존일수 30일 미만 불가.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_AUDIT_PURGE.h"
|
||||
|
||||
void MM_AUDIT_PURGE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char memo[96];
|
||||
long purged;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_days;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_days = getl(b, T_ARG1);
|
||||
if (h_days == 0) h_days = 365;
|
||||
if (h_days < 30) { setl(b, T_RC, 3); OK(b); }
|
||||
|
||||
EXEC SQL DELETE FROM mm_merch_hist
|
||||
WHERE created_at < now() - :h_days * interval '1 day'
|
||||
AND action <> 'AUDIT_PRG';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
purged = sqlca.sqlerrd[2];
|
||||
|
||||
if (purged > 0) {
|
||||
snprintf(memo, sizeof(memo), "보존기한 %ld일 경과 이력 %ld건 삭제", h_days, purged);
|
||||
if (mmdb_insert_merch_hist("*", "AUDIT_PRG", "", "", memo) < 0) FAIL(b);
|
||||
}
|
||||
setl(b, T_COUNT, purged);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_AUDIT_RECENT.h
Normal file
12
app/src/mm/svc/MM_AUDIT_RECENT.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_AUDIT_RECENT.h - mm 서비스 MM_AUDIT_RECENT 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_STR1(액션), T_STR2(변경 후 값), T_MSG(메모), T_BIZDATE(변경일), T_RC
|
||||
*/
|
||||
#ifndef MM_AUDIT_RECENT_H
|
||||
#define MM_AUDIT_RECENT_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_AUDIT_RECENT(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_AUDIT_RECENT_H */
|
||||
35
app/src/mm/svc/MM_AUDIT_RECENT.pgc
Normal file
35
app/src/mm/svc/MM_AUDIT_RECENT.pgc
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* MM_AUDIT_RECENT.pgc - mm 모듈 서비스 MM_AUDIT_RECENT (one service = one file).
|
||||
* 기능: 가맹점 최근 변경 감사 조회 (최신 이력 1건: 액션/변경값/메모/일자).
|
||||
* 입력: T_MERCHANT. 출력: T_STR1, T_STR2, T_MSG, T_BIZDATE.
|
||||
* RC: 1=변경 이력 없음.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_AUDIT_RECENT.h"
|
||||
|
||||
void MM_AUDIT_RECENT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_act[32], h_after[128], h_memo[128], h_when[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT action, after_val, memo, to_char(created_at, 'YYYYMMDD')
|
||||
INTO :h_act, :h_after, :h_memo, :h_when
|
||||
FROM mm_merch_hist
|
||||
WHERE merchant_id = :h_merch
|
||||
ORDER BY hist_id DESC LIMIT 1;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
Bchg(b, T_STR1, 0, h_act, 0L);
|
||||
Bchg(b, T_STR2, 0, h_after, 0L);
|
||||
Bchg(b, T_MSG, 0, h_memo, 0L);
|
||||
Bchg(b, T_BIZDATE, 0, h_when, 0L);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_AUDIT_TRAIL.h
Normal file
12
app/src/mm/svc/MM_AUDIT_TRAIL.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_AUDIT_TRAIL.h - mm 서비스 MM_AUDIT_TRAIL 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_STR1(action 필터), T_COUNT, T_ARG1(액션 종류 수), T_RC
|
||||
*/
|
||||
#ifndef MM_AUDIT_TRAIL_H
|
||||
#define MM_AUDIT_TRAIL_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_AUDIT_TRAIL(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_AUDIT_TRAIL_H */
|
||||
35
app/src/mm/svc/MM_AUDIT_TRAIL.pgc
Normal file
35
app/src/mm/svc/MM_AUDIT_TRAIL.pgc
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* MM_AUDIT_TRAIL.pgc - mm 모듈 서비스 MM_AUDIT_TRAIL (one service = one file).
|
||||
* 기능: 가맹점 마스터 변경 감사 추적 (액션 필터별 이력 건수 + 발생 액션 종류 수).
|
||||
* 입력: T_MERCHANT, T_STR1=액션 필터(빈값이면 전체).
|
||||
* 출력: T_COUNT=이력 건수, T_ARG1=서로 다른 액션 종류 수.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_AUDIT_TRAIL.h"
|
||||
|
||||
void MM_AUDIT_TRAIL(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64], act[32];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_act[32];
|
||||
long h_cnt, h_kinds;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
gets_(b, T_STR1, act, sizeof(act));
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
strncpy(h_act, act, sizeof(h_act)-1); h_act[sizeof(h_act)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT count(*), count(DISTINCT action)
|
||||
INTO :h_cnt, :h_kinds
|
||||
FROM mm_merch_hist
|
||||
WHERE merchant_id = :h_merch
|
||||
AND (:h_act = '' OR action = :h_act);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_ARG1, h_kinds);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_BIZNO_CHECK.h
Normal file
12
app/src/mm/svc/MM_BIZNO_CHECK.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_BIZNO_CHECK.h - mm 서비스 MM_BIZNO_CHECK 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_STR2(사업자번호), T_COUNT(중복 사용 가맹점 수), T_RC
|
||||
*/
|
||||
#ifndef MM_BIZNO_CHECK_H
|
||||
#define MM_BIZNO_CHECK_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_BIZNO_CHECK(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_BIZNO_CHECK_H */
|
||||
44
app/src/mm/svc/MM_BIZNO_CHECK.pgc
Normal file
44
app/src/mm/svc/MM_BIZNO_CHECK.pgc
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* MM_BIZNO_CHECK.pgc - mm 모듈 서비스 MM_BIZNO_CHECK (one service = one file).
|
||||
* 기능: 사업자등록번호 검증 (10자리 형식 + 국세청 검증공식 checksum + 마스터 중복 사용 확인).
|
||||
* checksum: 가중치 1,3,7,1,3,7,1,3,5 곱 합 + floor(9번째*5/10), (10-합%10)%10 == 검증숫자.
|
||||
* 입력: T_STR2=사업자번호. 출력: T_COUNT=해당 번호를 쓰는 기존 가맹점 수.
|
||||
* RC: 0=유효, 2=형식 오류, 3=검증숫자 불일치.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_BIZNO_CHECK.h"
|
||||
|
||||
static int bizno_checksum_ok(const char *no)
|
||||
{
|
||||
static const int w[9] = { 1, 3, 7, 1, 3, 7, 1, 3, 5 };
|
||||
int i, sum = 0;
|
||||
for (i = 0; i < 9; i++) sum += (no[i] - '0') * w[i];
|
||||
sum += ((no[8] - '0') * 5) / 10;
|
||||
return ((10 - sum % 10) % 10) == (no[9] - '0');
|
||||
}
|
||||
|
||||
void MM_BIZNO_CHECK(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char bizno[16];
|
||||
int i;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_bizno[16];
|
||||
long h_used;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_STR2, bizno, sizeof(bizno));
|
||||
if (strlen(bizno) != 10) { setl(b, T_RC, 2); OK(b); }
|
||||
for (i = 0; i < 10; i++)
|
||||
if (bizno[i] < '0' || bizno[i] > '9') { setl(b, T_RC, 2); OK(b); }
|
||||
if (!bizno_checksum_ok(bizno)) { setl(b, T_RC, 3); OK(b); }
|
||||
|
||||
strncpy(h_bizno, bizno, sizeof(h_bizno)-1); h_bizno[sizeof(h_bizno)-1] = 0;
|
||||
EXEC SQL SELECT count(*) INTO :h_used FROM mm_merchant_ext
|
||||
WHERE biz_reg_no = :h_bizno AND status <> 'DELETED';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_COUNT, h_used);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_BIZNO_UPD.h
Normal file
12
app/src/mm/svc/MM_BIZNO_UPD.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_BIZNO_UPD.h - mm 서비스 MM_BIZNO_UPD 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_STR2(신규 사업자번호), T_STR1(기존 번호), T_RC
|
||||
*/
|
||||
#ifndef MM_BIZNO_UPD_H
|
||||
#define MM_BIZNO_UPD_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_BIZNO_UPD(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_BIZNO_UPD_H */
|
||||
46
app/src/mm/svc/MM_BIZNO_UPD.pgc
Normal file
46
app/src/mm/svc/MM_BIZNO_UPD.pgc
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* MM_BIZNO_UPD.pgc - mm 모듈 서비스 MM_BIZNO_UPD (one service = one file).
|
||||
* 기능: 사업자등록번호 변경 (형식 검사 + 타 가맹점 중복 차단 + 변경 이력).
|
||||
* 입력: T_MERCHANT, T_STR2=신규 번호. 출력: T_STR1=기존 번호.
|
||||
* RC: 1=가맹점 없음, 2=형식 오류, 4=타 가맹점이 이미 사용, 5=기존 번호와 동일.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_BIZNO_UPD.h"
|
||||
|
||||
void MM_BIZNO_UPD(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64], bizno[16];
|
||||
int i;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_new[16], h_old[16];
|
||||
long h_other;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
gets_(b, T_STR2, bizno, sizeof(bizno));
|
||||
if (strlen(bizno) != 10) { setl(b, T_RC, 2); OK(b); }
|
||||
for (i = 0; i < 10; i++)
|
||||
if (bizno[i] < '0' || bizno[i] > '9') { setl(b, T_RC, 2); OK(b); }
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
strncpy(h_new, bizno, sizeof(h_new)-1); h_new[sizeof(h_new)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT biz_reg_no INTO :h_old FROM mm_merchant_ext
|
||||
WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (strcmp(h_old, h_new) == 0) { setl(b, T_RC, 5); OK(b); }
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_other FROM mm_merchant_ext
|
||||
WHERE biz_reg_no = :h_new AND merchant_id <> :h_merch AND status <> 'DELETED';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_other > 0) { setl(b, T_RC, 4); OK(b); }
|
||||
|
||||
EXEC SQL UPDATE mm_merchant_ext SET biz_reg_no = :h_new, updated_at = now()
|
||||
WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (mmdb_insert_merch_hist(h_merch, "BIZNO", h_old, h_new, "사업자번호 변경") < 0) FAIL(b);
|
||||
Bchg(b, T_STR1, 0, h_old, 0L);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_CHK_FEERATE.h
Normal file
12
app/src/mm/svc/MM_CHK_FEERATE.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_CHK_FEERATE.h - mm 서비스 MM_CHK_FEERATE 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_COUNT(요율 미설정), T_ARG1(범위 이탈 요율), T_ARG2(고아 요율), T_RC
|
||||
*/
|
||||
#ifndef MM_CHK_FEERATE_H
|
||||
#define MM_CHK_FEERATE_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_CHK_FEERATE(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_CHK_FEERATE_H */
|
||||
37
app/src/mm/svc/MM_CHK_FEERATE.pgc
Normal file
37
app/src/mm/svc/MM_CHK_FEERATE.pgc
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* MM_CHK_FEERATE.pgc - mm 모듈 서비스 MM_CHK_FEERATE (one service = one file).
|
||||
* 기능: 수수료율 마스터 정합성 점검 (활성 가맹점 요율 누락 / bps 범위 이탈 / 고아 요율).
|
||||
* 출력: T_COUNT=요율 없는 활성 가맹점, T_ARG1=bps 0 이하 또는 500 초과, T_ARG2=가맹점 없는 요율.
|
||||
* T_RC=0 정상 / 9 불일치 존재.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_CHK_FEERATE.h"
|
||||
|
||||
void MM_CHK_FEERATE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_missing, h_range, h_orphan;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_missing FROM mm_merchant_ext m
|
||||
WHERE m.status = 'ACTIVE'
|
||||
AND NOT EXISTS (SELECT 1 FROM mm_fee_rate f
|
||||
WHERE f.merchant_id = m.merchant_id);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_range FROM mm_fee_rate
|
||||
WHERE rate_bps <= 0 OR rate_bps > 500;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_orphan FROM mm_fee_rate f
|
||||
WHERE NOT EXISTS (SELECT 1 FROM mm_merchant_ext m
|
||||
WHERE m.merchant_id = f.merchant_id);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_COUNT, h_missing);
|
||||
setl(b, T_ARG1, h_range);
|
||||
setl(b, T_ARG2, h_orphan);
|
||||
setl(b, T_RC, (h_missing + h_range + h_orphan) > 0 ? 9 : 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_CHK_LIMIT.h
Normal file
12
app/src/mm/svc/MM_CHK_LIMIT.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_CHK_LIMIT.h - mm 서비스 MM_CHK_LIMIT 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_COUNT(한도 미설정), T_ARG1(한도 역전), T_RC
|
||||
*/
|
||||
#ifndef MM_CHK_LIMIT_H
|
||||
#define MM_CHK_LIMIT_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_CHK_LIMIT(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_CHK_LIMIT_H */
|
||||
31
app/src/mm/svc/MM_CHK_LIMIT.pgc
Normal file
31
app/src/mm/svc/MM_CHK_LIMIT.pgc
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* MM_CHK_LIMIT.pgc - mm 모듈 서비스 MM_CHK_LIMIT (one service = one file).
|
||||
* 기능: 한도 마스터 정합성 점검 (활성 가맹점 한도 누락 + 한도 체계 역전 검출).
|
||||
* 역전 = 건당한도 > 일한도 또는 일한도 > 월한도.
|
||||
* 출력: T_COUNT=한도 없는 활성 가맹점, T_ARG1=역전 한도 행. T_RC=0 정상 / 9 불일치 존재.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_CHK_LIMIT.h"
|
||||
|
||||
void MM_CHK_LIMIT(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_missing, h_invert;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_missing FROM mm_merchant_ext m
|
||||
WHERE m.status = 'ACTIVE'
|
||||
AND NOT EXISTS (SELECT 1 FROM mm_limit l
|
||||
WHERE l.merchant_id = m.merchant_id);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_invert FROM mm_limit
|
||||
WHERE per_txn_limit > daily_limit OR daily_limit > monthly_limit;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_COUNT, h_missing);
|
||||
setl(b, T_ARG1, h_invert);
|
||||
setl(b, T_RC, (h_missing + h_invert) > 0 ? 9 : 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_CHK_TERM.h
Normal file
12
app/src/mm/svc/MM_CHK_TERM.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_CHK_TERM.h - mm 서비스 MM_CHK_TERM 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_COUNT(고아 단말), T_ARG1(폐업 가맹점 가동 단말), T_RC
|
||||
*/
|
||||
#ifndef MM_CHK_TERM_H
|
||||
#define MM_CHK_TERM_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_CHK_TERM(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_CHK_TERM_H */
|
||||
30
app/src/mm/svc/MM_CHK_TERM.pgc
Normal file
30
app/src/mm/svc/MM_CHK_TERM.pgc
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* MM_CHK_TERM.pgc - mm 모듈 서비스 MM_CHK_TERM (one service = one file).
|
||||
* 기능: 단말 마스터 정합성 점검 (소속 가맹점 없는 고아 단말 + 폐업 가맹점의 가동 단말).
|
||||
* 출력: T_COUNT=고아 단말 수, T_ARG1=폐업 가맹점 소속 미폐기 단말 수, T_RC=0 정상 / 9 불일치 존재.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_CHK_TERM.h"
|
||||
|
||||
void MM_CHK_TERM(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_orphan, h_zombie;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_orphan FROM mm_terminal t
|
||||
WHERE NOT EXISTS (SELECT 1 FROM mm_merchant_ext m
|
||||
WHERE m.merchant_id = t.merchant_id);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_zombie FROM mm_terminal t
|
||||
JOIN mm_merchant_ext m ON m.merchant_id = t.merchant_id
|
||||
WHERE m.status = 'DELETED' AND t.status <> 'SCRAPPED';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_COUNT, h_orphan);
|
||||
setl(b, T_ARG1, h_zombie);
|
||||
setl(b, T_RC, (h_orphan + h_zombie) > 0 ? 9 : 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_CODEMAP_DEL.h
Normal file
12
app/src/mm/svc/MM_CODEMAP_DEL.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_CODEMAP_DEL.h - mm 서비스 MM_CODEMAP_DEL 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_KEY1(네임스페이스), T_STR1(원본 코드; 빈값=네임스페이스 전체), T_COUNT, T_RC
|
||||
*/
|
||||
#ifndef MM_CODEMAP_DEL_H
|
||||
#define MM_CODEMAP_DEL_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_CODEMAP_DEL(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_CODEMAP_DEL_H */
|
||||
37
app/src/mm/svc/MM_CODEMAP_DEL.pgc
Normal file
37
app/src/mm/svc/MM_CODEMAP_DEL.pgc
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* MM_CODEMAP_DEL.pgc - mm 모듈 서비스 MM_CODEMAP_DEL (one service = one file).
|
||||
* 기능: 코드 매핑 삭제 (단건 또는 네임스페이스 전체 일괄 삭제).
|
||||
* 입력: T_KEY1=네임스페이스, T_STR1=원본 코드(빈값이면 네임스페이스 전체 삭제).
|
||||
* 출력: T_COUNT=삭제 건수. RC: 1=대상 없음, 3=네임스페이스 누락.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_CODEMAP_DEL.h"
|
||||
|
||||
void MM_CODEMAP_DEL(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char ns[16], src[32];
|
||||
long ndel;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_grp[24], h_src[32];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_KEY1, ns, sizeof(ns));
|
||||
gets_(b, T_STR1, src, sizeof(src));
|
||||
if (ns[0] == 0) { setl(b, T_RC, 3); OK(b); }
|
||||
snprintf(h_grp, sizeof(h_grp), "MAP_%s", ns);
|
||||
strncpy(h_src, src, sizeof(h_src)-1); h_src[sizeof(h_src)-1] = 0;
|
||||
|
||||
if (h_src[0] == 0) {
|
||||
EXEC SQL DELETE FROM mm_code WHERE code_group = :h_grp;
|
||||
} else {
|
||||
EXEC SQL DELETE FROM mm_code WHERE code_group = :h_grp AND code = :h_src;
|
||||
}
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
ndel = sqlca.sqlerrd[2];
|
||||
if (ndel == 0) { setl(b, T_RC, 1); OK(b); }
|
||||
|
||||
setl(b, T_COUNT, ndel);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_CODEMAP_GET.h
Normal file
12
app/src/mm/svc/MM_CODEMAP_GET.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_CODEMAP_GET.h - mm 서비스 MM_CODEMAP_GET 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_KEY1(네임스페이스), T_STR1(원본 코드), T_STR2(변환 결과), T_RC
|
||||
*/
|
||||
#ifndef MM_CODEMAP_GET_H
|
||||
#define MM_CODEMAP_GET_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_CODEMAP_GET(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_CODEMAP_GET_H */
|
||||
36
app/src/mm/svc/MM_CODEMAP_GET.pgc
Normal file
36
app/src/mm/svc/MM_CODEMAP_GET.pgc
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* MM_CODEMAP_GET.pgc - mm 모듈 서비스 MM_CODEMAP_GET (one service = one file).
|
||||
* 기능: 코드 매핑 변환 조회 (네임스페이스의 원본 코드를 대상 코드로 변환).
|
||||
* 입력: T_KEY1=네임스페이스, T_STR1=원본 코드. 출력: T_STR2=변환된 대상 코드.
|
||||
* RC: 1=활성 매핑 없음 (이때 T_STR2에는 원본 코드를 그대로 반환 - passthrough).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_CODEMAP_GET.h"
|
||||
|
||||
void MM_CODEMAP_GET(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char ns[16], src[32];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_grp[24], h_src[32], h_dst[32];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_KEY1, ns, sizeof(ns));
|
||||
gets_(b, T_STR1, src, sizeof(src));
|
||||
snprintf(h_grp, sizeof(h_grp), "MAP_%s", ns);
|
||||
strncpy(h_src, src, sizeof(h_src)-1); h_src[sizeof(h_src)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT code_name INTO :h_dst FROM mm_code
|
||||
WHERE code_group = :h_grp AND code = :h_src AND status = 'ACTIVE';
|
||||
if (sqlca.sqlcode == 100) {
|
||||
/* 매핑이 없으면 원본 코드 그대로 통과 */
|
||||
Bchg(b, T_STR2, 0, h_src, 0L);
|
||||
setl(b, T_RC, 1);
|
||||
OK(b);
|
||||
}
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
Bchg(b, T_STR2, 0, h_dst, 0L);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_CODEMAP_SET.h
Normal file
12
app/src/mm/svc/MM_CODEMAP_SET.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_CODEMAP_SET.h - mm 서비스 MM_CODEMAP_SET 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_KEY1(매핑 네임스페이스), T_STR1(원본 코드), T_STR2(대상 코드), T_RC
|
||||
*/
|
||||
#ifndef MM_CODEMAP_SET_H
|
||||
#define MM_CODEMAP_SET_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_CODEMAP_SET(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_CODEMAP_SET_H */
|
||||
33
app/src/mm/svc/MM_CODEMAP_SET.pgc
Normal file
33
app/src/mm/svc/MM_CODEMAP_SET.pgc
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* MM_CODEMAP_SET.pgc - mm 모듈 서비스 MM_CODEMAP_SET (one service = one file).
|
||||
* 기능: 코드 매핑 등록/갱신 (외부코드->내부코드 변환표, MAP_<네임스페이스> 코드그룹 upsert).
|
||||
* 입력: T_KEY1=네임스페이스(예: VAN1), T_STR1=원본 코드, T_STR2=대상 코드.
|
||||
* RC: 3=필수값 누락. 재등록 시 대상 코드 교체 + 상태 ACTIVE 복원.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_CODEMAP_SET.h"
|
||||
|
||||
void MM_CODEMAP_SET(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char ns[16], src[32], dst[32];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_grp[24], h_src[32], h_dst[32];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_KEY1, ns, sizeof(ns));
|
||||
gets_(b, T_STR1, src, sizeof(src));
|
||||
gets_(b, T_STR2, dst, sizeof(dst));
|
||||
if (ns[0] == 0 || src[0] == 0 || dst[0] == 0) { setl(b, T_RC, 3); OK(b); }
|
||||
snprintf(h_grp, sizeof(h_grp), "MAP_%s", ns);
|
||||
strncpy(h_src, src, sizeof(h_src)-1); h_src[sizeof(h_src)-1] = 0;
|
||||
strncpy(h_dst, dst, sizeof(h_dst)-1); h_dst[sizeof(h_dst)-1] = 0;
|
||||
|
||||
EXEC SQL INSERT INTO mm_code (code_group, code, code_name, status)
|
||||
VALUES (:h_grp, :h_src, :h_dst, 'ACTIVE')
|
||||
ON CONFLICT (code_group, code)
|
||||
DO UPDATE SET code_name = EXCLUDED.code_name, status = 'ACTIVE';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_CONTRACT_END.h
Normal file
12
app/src/mm/svc/MM_CONTRACT_END.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_CONTRACT_END.h - mm 서비스 MM_CONTRACT_END 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_REASON, T_RC
|
||||
*/
|
||||
#ifndef MM_CONTRACT_END_H
|
||||
#define MM_CONTRACT_END_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_CONTRACT_END(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_CONTRACT_END_H */
|
||||
43
app/src/mm/svc/MM_CONTRACT_END.pgc
Normal file
43
app/src/mm/svc/MM_CONTRACT_END.pgc
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* MM_CONTRACT_END.pgc - mm 모듈 서비스 MM_CONTRACT_END (one service = one file).
|
||||
* 기능: 가맹 계약 해지 (CONT_END 이력 + 가맹점 상태 HOLD 전환).
|
||||
* 입력: T_MERCHANT, T_REASON=해지 사유(필수).
|
||||
* RC: 1=체결된 계약 없음, 2=이미 해지됨, 3=해지 사유 누락.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_CONTRACT_END.h"
|
||||
|
||||
void MM_CONTRACT_END(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64], reason[128];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_end[16];
|
||||
long h_ended;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
gets_(b, T_REASON, reason, sizeof(reason));
|
||||
if (reason[0] == 0) { setl(b, T_RC, 3); OK(b); }
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT after_val INTO :h_end FROM mm_merch_hist
|
||||
WHERE merchant_id = :h_merch AND action = 'CONTRACT'
|
||||
ORDER BY hist_id DESC LIMIT 1;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_ended FROM mm_merch_hist
|
||||
WHERE merchant_id = :h_merch AND action = 'CONT_END'
|
||||
AND hist_id > (SELECT max(hist_id) FROM mm_merch_hist
|
||||
WHERE merchant_id = :h_merch AND action = 'CONTRACT');
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_ended > 0) { setl(b, T_RC, 2); OK(b); }
|
||||
|
||||
EXEC SQL UPDATE mm_merchant_ext SET status = 'HOLD', updated_at = now()
|
||||
WHERE merchant_id = :h_merch AND status = 'ACTIVE';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (mmdb_insert_merch_hist(h_merch, "CONT_END", h_end, "", reason) < 0) FAIL(b);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_CONTRACT_INQ.h
Normal file
12
app/src/mm/svc/MM_CONTRACT_INQ.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_CONTRACT_INQ.h - mm 서비스 MM_CONTRACT_INQ 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_COUNT(체결 횟수), T_STR1(최종 만기), T_ARG1(유효 여부), T_RC
|
||||
*/
|
||||
#ifndef MM_CONTRACT_INQ_H
|
||||
#define MM_CONTRACT_INQ_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_CONTRACT_INQ(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_CONTRACT_INQ_H */
|
||||
37
app/src/mm/svc/MM_CONTRACT_INQ.pgc
Normal file
37
app/src/mm/svc/MM_CONTRACT_INQ.pgc
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* MM_CONTRACT_INQ.pgc - mm 모듈 서비스 MM_CONTRACT_INQ (one service = one file).
|
||||
* 기능: 가맹 계약 현황 조회 (체결/갱신 횟수, 최종 만기일, 유효 여부).
|
||||
* 입력: T_MERCHANT. 출력: T_COUNT=체결·갱신 누계, T_STR1=최종 만기, T_ARG1=1이면 만기 미도래.
|
||||
* RC: 1=계약 이력 없음.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_CONTRACT_INQ.h"
|
||||
|
||||
void MM_CONTRACT_INQ(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_end[16], h_today[16];
|
||||
long h_cnt;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT count(*), coalesce(max(after_val), '')
|
||||
INTO :h_cnt, :h_end
|
||||
FROM mm_merch_hist
|
||||
WHERE merchant_id = :h_merch AND action = 'CONTRACT';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_cnt == 0) { setl(b, T_RC, 1); OK(b); }
|
||||
|
||||
EXEC SQL SELECT to_char(current_date, 'YYYYMMDD') INTO :h_today;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
Bchg(b, T_STR1, 0, h_end, 0L);
|
||||
setl(b, T_ARG1, strcmp(h_end, h_today) > 0 ? 1 : 0);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_CONTRACT_NEW.h
Normal file
12
app/src/mm/svc/MM_CONTRACT_NEW.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_CONTRACT_NEW.h - mm 서비스 MM_CONTRACT_NEW 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_ARG1(계약기간 개월), T_STR1(만기일), T_RC
|
||||
*/
|
||||
#ifndef MM_CONTRACT_NEW_H
|
||||
#define MM_CONTRACT_NEW_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_CONTRACT_NEW(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_CONTRACT_NEW_H */
|
||||
44
app/src/mm/svc/MM_CONTRACT_NEW.pgc
Normal file
44
app/src/mm/svc/MM_CONTRACT_NEW.pgc
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* MM_CONTRACT_NEW.pgc - mm 모듈 서비스 MM_CONTRACT_NEW (one service = one file).
|
||||
* 기능: 가맹 계약 체결 (기간 개월수로 만기일 산출, CONTRACT 이력 기록).
|
||||
* 입력: T_MERCHANT, T_ARG1=계약기간 개월(1~120, 기본 12). 출력: T_STR1=만기일(YYYYMMDD).
|
||||
* RC: 1=활성 가맹점 아님, 3=기간 범위 오류, 4=미만기 계약 이미 존재.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_CONTRACT_NEW.h"
|
||||
|
||||
void MM_CONTRACT_NEW(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_end[16];
|
||||
long h_mon, h_alive, h_open;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
h_mon = getl(b, T_ARG1);
|
||||
if (h_mon == 0) h_mon = 12;
|
||||
if (h_mon < 1 || h_mon > 120) { setl(b, T_RC, 3); OK(b); }
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_alive FROM mm_merchant_ext
|
||||
WHERE merchant_id = :h_merch AND status = 'ACTIVE';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_alive == 0) { setl(b, T_RC, 1); OK(b); }
|
||||
|
||||
/* 만기 미도래 계약이 남아 있으면 신규 체결 불가 */
|
||||
EXEC SQL SELECT count(*) INTO :h_open FROM mm_merch_hist
|
||||
WHERE merchant_id = :h_merch AND action = 'CONTRACT'
|
||||
AND after_val > to_char(current_date, 'YYYYMMDD');
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_open > 0) { setl(b, T_RC, 4); OK(b); }
|
||||
|
||||
EXEC SQL SELECT to_char(current_date + :h_mon * interval '1 month', 'YYYYMMDD')
|
||||
INTO :h_end;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (mmdb_insert_merch_hist(h_merch, "CONTRACT", "", h_end, "가맹 계약 체결") < 0) FAIL(b);
|
||||
Bchg(b, T_STR1, 0, h_end, 0L);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_CONTRACT_RENEW.h
Normal file
12
app/src/mm/svc/MM_CONTRACT_RENEW.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_CONTRACT_RENEW.h - mm 서비스 MM_CONTRACT_RENEW 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_ARG1(연장 개월), T_STR1(기존 만기), T_STR2(신규 만기), T_RC
|
||||
*/
|
||||
#ifndef MM_CONTRACT_RENEW_H
|
||||
#define MM_CONTRACT_RENEW_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_CONTRACT_RENEW(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_CONTRACT_RENEW_H */
|
||||
47
app/src/mm/svc/MM_CONTRACT_RENEW.pgc
Normal file
47
app/src/mm/svc/MM_CONTRACT_RENEW.pgc
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* MM_CONTRACT_RENEW.pgc - mm 모듈 서비스 MM_CONTRACT_RENEW (one service = one file).
|
||||
* 기능: 가맹 계약 갱신 (직전 만기일 기준 개월수 연장).
|
||||
* 입력: T_MERCHANT, T_ARG1=연장 개월(기본 12). 출력: T_STR1=기존 만기, T_STR2=신규 만기.
|
||||
* RC: 1=체결된 계약 없음, 2=해지된 계약(갱신 불가), 3=기간 범위 오류.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_CONTRACT_RENEW.h"
|
||||
|
||||
void MM_CONTRACT_RENEW(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_old[16], h_new[16];
|
||||
long h_mon, h_ended;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
h_mon = getl(b, T_ARG1);
|
||||
if (h_mon == 0) h_mon = 12;
|
||||
if (h_mon < 1 || h_mon > 120) { setl(b, T_RC, 3); OK(b); }
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT after_val INTO :h_old FROM mm_merch_hist
|
||||
WHERE merchant_id = :h_merch AND action = 'CONTRACT'
|
||||
ORDER BY hist_id DESC LIMIT 1;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
/* 만기 이후 해지 이력이 있으면 갱신 불가 */
|
||||
EXEC SQL SELECT count(*) INTO :h_ended FROM mm_merch_hist
|
||||
WHERE merchant_id = :h_merch AND action = 'CONT_END'
|
||||
AND hist_id > (SELECT max(hist_id) FROM mm_merch_hist
|
||||
WHERE merchant_id = :h_merch AND action = 'CONTRACT');
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_ended > 0) { setl(b, T_RC, 2); OK(b); }
|
||||
|
||||
EXEC SQL SELECT to_char(to_date(:h_old, 'YYYYMMDD') + :h_mon * interval '1 month', 'YYYYMMDD')
|
||||
INTO :h_new;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (mmdb_insert_merch_hist(h_merch, "CONTRACT", h_old, h_new, "계약 갱신 연장") < 0) FAIL(b);
|
||||
Bchg(b, T_STR1, 0, h_old, 0L);
|
||||
Bchg(b, T_STR2, 0, h_new, 0L);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_GRADE_ADJUST.h
Normal file
12
app/src/mm/svc/MM_GRADE_ADJUST.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_GRADE_ADJUST.h - mm 서비스 MM_GRADE_ADJUST 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_STR2(조정 등급), T_REASON(필수), T_STR1(이전 등급), T_RC
|
||||
*/
|
||||
#ifndef MM_GRADE_ADJUST_H
|
||||
#define MM_GRADE_ADJUST_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_GRADE_ADJUST(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_GRADE_ADJUST_H */
|
||||
38
app/src/mm/svc/MM_GRADE_ADJUST.pgc
Normal file
38
app/src/mm/svc/MM_GRADE_ADJUST.pgc
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* MM_GRADE_ADJUST.pgc - mm 모듈 서비스 MM_GRADE_ADJUST (one service = one file).
|
||||
* 기능: 가맹점 등급 수동 보정 (산정 결과 예외 조정, 조정 사유 필수 감사 기록).
|
||||
* 입력: T_MERCHANT, T_STR2=조정 등급(S/A/B/C), T_REASON=조정 사유(필수).
|
||||
* 출력: T_STR1=이전 등급. RC: 1=가맹점 없음, 2=동일 등급, 3=등급값 오류, 4=사유 누락.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_GRADE_ADJUST.h"
|
||||
|
||||
void MM_GRADE_ADJUST(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64], grade[8], reason[128];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_old[8], h_new[8];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
gets_(b, T_STR2, grade, sizeof(grade));
|
||||
gets_(b, T_REASON, reason, sizeof(reason));
|
||||
if (strlen(grade) != 1 || strchr("SABC", grade[0]) == NULL) { setl(b, T_RC, 3); OK(b); }
|
||||
if (reason[0] == 0) { setl(b, T_RC, 4); OK(b); }
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
strncpy(h_new, grade, sizeof(h_new)-1); h_new[sizeof(h_new)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT grade INTO :h_old FROM mm_merchant_ext WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (strcmp(h_old, h_new) == 0) { setl(b, T_RC, 2); OK(b); }
|
||||
|
||||
EXEC SQL UPDATE mm_merchant_ext SET grade = :h_new, updated_at = now()
|
||||
WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (mmdb_insert_merch_hist(h_merch, "GRADE_ADJ", h_old, h_new, reason) < 0) FAIL(b);
|
||||
Bchg(b, T_STR1, 0, h_old, 0L);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_GRADE_DIST.h
Normal file
12
app/src/mm/svc/MM_GRADE_DIST.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_GRADE_DIST.h - mm 서비스 MM_GRADE_DIST 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_BIZDATE(기준일), T_ARG1~T_ARG4(S/A/B/C 분포), T_COUNT(합계), T_RC
|
||||
*/
|
||||
#ifndef MM_GRADE_DIST_H
|
||||
#define MM_GRADE_DIST_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_GRADE_DIST(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_GRADE_DIST_H */
|
||||
42
app/src/mm/svc/MM_GRADE_DIST.pgc
Normal file
42
app/src/mm/svc/MM_GRADE_DIST.pgc
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* MM_GRADE_DIST.pgc - mm 모듈 서비스 MM_GRADE_DIST (one service = one file).
|
||||
* 기능: 가맹점 등급 분포 조회 (최근 등급 통계일 기준 S/A/B/C 세분 현황).
|
||||
* 출력: T_BIZDATE=통계 기준일, T_ARG1=S, T_ARG2=A, T_ARG3=B, T_ARG4=C, T_COUNT=합계.
|
||||
* RC: 1=통계 미생성 (mm_stat_batch 선행 필요).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_GRADE_DIST.h"
|
||||
|
||||
void MM_GRADE_DIST(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_date[16];
|
||||
long h_s, h_a, h_b, h_c, h_rows;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_rows FROM mm_grade_stat;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_rows == 0) { setl(b, T_RC, 1); OK(b); }
|
||||
|
||||
EXEC SQL SELECT to_char(max(stat_date), 'YYYYMMDD') INTO :h_date FROM mm_grade_stat;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
EXEC SQL SELECT coalesce(sum(CASE WHEN grade = 'S' THEN merch_cnt ELSE 0 END), 0),
|
||||
coalesce(sum(CASE WHEN grade = 'A' THEN merch_cnt ELSE 0 END), 0),
|
||||
coalesce(sum(CASE WHEN grade = 'B' THEN merch_cnt ELSE 0 END), 0),
|
||||
coalesce(sum(CASE WHEN grade = 'C' THEN merch_cnt ELSE 0 END), 0)
|
||||
INTO :h_s, :h_a, :h_b, :h_c
|
||||
FROM mm_grade_stat
|
||||
WHERE stat_date = (SELECT max(stat_date) FROM mm_grade_stat);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
Bchg(b, T_BIZDATE, 0, h_date, 0L);
|
||||
setl(b, T_ARG1, h_s);
|
||||
setl(b, T_ARG2, h_a);
|
||||
setl(b, T_ARG3, h_b);
|
||||
setl(b, T_ARG4, h_c);
|
||||
setl(b, T_COUNT, h_s + h_a + h_b + h_c);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_GRADE_PREVIEW.h
Normal file
12
app/src/mm/svc/MM_GRADE_PREVIEW.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_GRADE_PREVIEW.h - mm 서비스 MM_GRADE_PREVIEW 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_STR1(현재 등급), T_STR2(산정 등급), T_GROSS, T_ARG1(변경 필요), T_RC
|
||||
*/
|
||||
#ifndef MM_GRADE_PREVIEW_H
|
||||
#define MM_GRADE_PREVIEW_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_GRADE_PREVIEW(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_GRADE_PREVIEW_H */
|
||||
43
app/src/mm/svc/MM_GRADE_PREVIEW.pgc
Normal file
43
app/src/mm/svc/MM_GRADE_PREVIEW.pgc
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* MM_GRADE_PREVIEW.pgc - mm 모듈 서비스 MM_GRADE_PREVIEW (one service = one file).
|
||||
* 기능: 가맹점 등급 산정 시뮬레이션 (누적 매출로 등급 산출, 마스터는 불변).
|
||||
* 임계: S>=10억, A>=3억, B>=5천만, 그 외 C (배치 재산정과 동일 기준).
|
||||
* 입력: T_MERCHANT. 출력: T_STR1=현재, T_STR2=산정, T_GROSS=누적 매출, T_ARG1=1이면 등급 변경 대상.
|
||||
* RC: 1=가맹점 없음.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_GRADE_PREVIEW.h"
|
||||
|
||||
void MM_GRADE_PREVIEW(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64];
|
||||
const char *calc;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_cur[8];
|
||||
long h_gross;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT grade INTO :h_cur FROM mm_merchant_ext WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
EXEC SQL SELECT coalesce(sum(gross_amount), 0) INTO :h_gross
|
||||
FROM merchant_summary WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
if (h_gross >= 1000000000L) calc = "S";
|
||||
else if (h_gross >= 300000000L) calc = "A";
|
||||
else if (h_gross >= 50000000L) calc = "B";
|
||||
else calc = "C";
|
||||
|
||||
Bchg(b, T_STR1, 0, h_cur, 0L);
|
||||
Bchg(b, T_STR2, 0, (char *)calc, 0L);
|
||||
setl(b, T_GROSS, h_gross);
|
||||
setl(b, T_ARG1, strcmp(h_cur, calc) != 0 ? 1 : 0);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_MCC_INQ.h
Normal file
12
app/src/mm/svc/MM_MCC_INQ.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_MCC_INQ.h - mm 서비스 MM_MCC_INQ 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_CATEGORY(MCC), T_STR1(명칭), T_ARG1(위험도), T_COUNT(소속 가맹점 수), T_RC
|
||||
*/
|
||||
#ifndef MM_MCC_INQ_H
|
||||
#define MM_MCC_INQ_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_MCC_INQ(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_MCC_INQ_H */
|
||||
36
app/src/mm/svc/MM_MCC_INQ.pgc
Normal file
36
app/src/mm/svc/MM_MCC_INQ.pgc
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* MM_MCC_INQ.pgc - mm 모듈 서비스 MM_MCC_INQ (one service = one file).
|
||||
* 기능: MCC 업종 조회 (명칭/위험도 + 해당 업종 활성 가맹점 수).
|
||||
* 입력: T_CATEGORY=MCC. 출력: T_STR1, T_ARG1, T_COUNT.
|
||||
* RC: 1=미등록 MCC.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_MCC_INQ.h"
|
||||
|
||||
void MM_MCC_INQ(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char mcc[8];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_mcc[8], h_name[64];
|
||||
long h_risk, h_merch;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_CATEGORY, mcc, sizeof(mcc));
|
||||
strncpy(h_mcc, mcc, sizeof(h_mcc)-1); h_mcc[sizeof(h_mcc)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT mcc_name, risk_level INTO :h_name, :h_risk
|
||||
FROM mm_mcc WHERE mcc = :h_mcc;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_merch FROM mm_merchant_ext
|
||||
WHERE mcc = :h_mcc AND status = 'ACTIVE';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
Bchg(b, T_STR1, 0, h_name, 0L);
|
||||
setl(b, T_ARG1, h_risk);
|
||||
setl(b, T_COUNT, h_merch);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_MCC_RISKLIST.h
Normal file
12
app/src/mm/svc/MM_MCC_RISKLIST.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_MCC_RISKLIST.h - mm 서비스 MM_MCC_RISKLIST 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_ARG1(최소 위험도), T_COUNT(MCC 수), T_ARG2(최고 위험도), T_ARG3(소속 가맹점 수), T_RC
|
||||
*/
|
||||
#ifndef MM_MCC_RISKLIST_H
|
||||
#define MM_MCC_RISKLIST_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_MCC_RISKLIST(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_MCC_RISKLIST_H */
|
||||
36
app/src/mm/svc/MM_MCC_RISKLIST.pgc
Normal file
36
app/src/mm/svc/MM_MCC_RISKLIST.pgc
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* MM_MCC_RISKLIST.pgc - mm 모듈 서비스 MM_MCC_RISKLIST (one service = one file).
|
||||
* 기능: 고위험 MCC 현황 (기준 위험도 이상 MCC 수, 최고 위험도, 소속 활성 가맹점 수).
|
||||
* 입력: T_ARG1=최소 위험도(기본 3). 출력: T_COUNT, T_ARG2, T_ARG3.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_MCC_RISKLIST.h"
|
||||
|
||||
void MM_MCC_RISKLIST(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
long h_min, h_cnt, h_max, h_merch;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
h_min = getl(b, T_ARG1);
|
||||
if (h_min <= 0) h_min = 3;
|
||||
|
||||
EXEC SQL SELECT count(*), coalesce(max(risk_level), 0)
|
||||
INTO :h_cnt, :h_max
|
||||
FROM mm_mcc WHERE risk_level >= :h_min;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_merch
|
||||
FROM mm_merchant_ext me
|
||||
WHERE me.status = 'ACTIVE'
|
||||
AND EXISTS (SELECT 1 FROM mm_mcc c
|
||||
WHERE c.mcc = me.mcc AND c.risk_level >= :h_min);
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
setl(b, T_COUNT, h_cnt);
|
||||
setl(b, T_ARG2, h_max);
|
||||
setl(b, T_ARG3, h_merch);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_MCC_UPD.h
Normal file
12
app/src/mm/svc/MM_MCC_UPD.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_MCC_UPD.h - mm 서비스 MM_MCC_UPD 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_CATEGORY(MCC), T_STR1(명칭), T_ARG1(위험도), T_RC
|
||||
*/
|
||||
#ifndef MM_MCC_UPD_H
|
||||
#define MM_MCC_UPD_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_MCC_UPD(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_MCC_UPD_H */
|
||||
37
app/src/mm/svc/MM_MCC_UPD.pgc
Normal file
37
app/src/mm/svc/MM_MCC_UPD.pgc
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* MM_MCC_UPD.pgc - mm 모듈 서비스 MM_MCC_UPD (one service = one file).
|
||||
* 기능: MCC 업종 마스터 변경 (명칭 선택 변경 + 위험도 1~5 재설정).
|
||||
* 입력: T_CATEGORY=MCC, T_STR1=명칭(빈값이면 유지), T_ARG1=위험도(1~5).
|
||||
* RC: 1=미등록 MCC, 3=위험도 범위 오류.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_MCC_UPD.h"
|
||||
|
||||
void MM_MCC_UPD(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char mcc[8], name[64];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_mcc[8], h_name[64];
|
||||
long h_risk, h_found;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_CATEGORY, mcc, sizeof(mcc));
|
||||
gets_(b, T_STR1, name, sizeof(name));
|
||||
h_risk = getl(b, T_ARG1);
|
||||
if (h_risk < 1 || h_risk > 5) { setl(b, T_RC, 3); OK(b); }
|
||||
strncpy(h_mcc, mcc, sizeof(h_mcc)-1); h_mcc[sizeof(h_mcc)-1] = 0;
|
||||
strncpy(h_name, name, sizeof(h_name)-1); h_name[sizeof(h_name)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT count(*) INTO :h_found FROM mm_mcc WHERE mcc = :h_mcc;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (h_found == 0) { setl(b, T_RC, 1); OK(b); }
|
||||
|
||||
EXEC SQL UPDATE mm_mcc
|
||||
SET mcc_name = CASE WHEN :h_name = '' THEN mcc_name ELSE :h_name END,
|
||||
risk_level = :h_risk
|
||||
WHERE mcc = :h_mcc;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_MERCH_CLOSE.h
Normal file
12
app/src/mm/svc/MM_MERCH_CLOSE.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_MERCH_CLOSE.h - mm 서비스 MM_MERCH_CLOSE 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_REASON, T_COUNT(폐기 단말 수), T_RC
|
||||
*/
|
||||
#ifndef MM_MERCH_CLOSE_H
|
||||
#define MM_MERCH_CLOSE_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_MERCH_CLOSE(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_MERCH_CLOSE_H */
|
||||
46
app/src/mm/svc/MM_MERCH_CLOSE.pgc
Normal file
46
app/src/mm/svc/MM_MERCH_CLOSE.pgc
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* MM_MERCH_CLOSE.pgc - mm 모듈 서비스 MM_MERCH_CLOSE (one service = one file).
|
||||
* 기능: 가맹점 폐업 처리 (DELETED 전환 + 전체 단말 폐기 + 하위 관계 해제).
|
||||
* 입력: T_MERCHANT, T_REASON=폐업 사유(없으면 '폐업 신고'). 출력: T_COUNT=폐기된 단말 수.
|
||||
* RC: 1=가맹점 없음, 2=이미 폐업됨.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_MERCH_CLOSE.h"
|
||||
|
||||
void MM_MERCH_CLOSE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64], reason[128], memo[160];
|
||||
long nterm;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_stat[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
gets_(b, T_REASON, reason, sizeof(reason));
|
||||
if (reason[0] == 0) strcpy(reason, "폐업 신고");
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT status INTO :h_stat FROM mm_merchant_ext WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (strcmp(h_stat, "DELETED") == 0) { setl(b, T_RC, 2); OK(b); }
|
||||
|
||||
EXEC SQL UPDATE mm_merchant_ext SET status = 'DELETED', updated_at = now()
|
||||
WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL UPDATE mm_terminal SET status = 'SCRAPPED'
|
||||
WHERE merchant_id = :h_merch AND status <> 'SCRAPPED';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
nterm = sqlca.sqlerrd[2];
|
||||
/* 대표-하위 관계도 함께 해제 (이 가맹점이 하위이거나 대표인 경우 모두) */
|
||||
EXEC SQL UPDATE mm_code SET status = 'INACTIVE'
|
||||
WHERE code_group = 'MERCH_REL'
|
||||
AND (code = :h_merch OR code_name = :h_merch) AND status = 'ACTIVE';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
snprintf(memo, sizeof(memo), "%s (단말 %ld대 폐기)", reason, nterm);
|
||||
if (mmdb_insert_merch_hist(h_merch, "CLOSE", h_stat, "DELETED", memo) < 0) FAIL(b);
|
||||
setl(b, T_COUNT, nterm);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_MERCH_PAUSE.h
Normal file
12
app/src/mm/svc/MM_MERCH_PAUSE.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_MERCH_PAUSE.h - mm 서비스 MM_MERCH_PAUSE 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_REASON, T_COUNT(정지된 단말 수), T_RC
|
||||
*/
|
||||
#ifndef MM_MERCH_PAUSE_H
|
||||
#define MM_MERCH_PAUSE_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_MERCH_PAUSE(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_MERCH_PAUSE_H */
|
||||
40
app/src/mm/svc/MM_MERCH_PAUSE.pgc
Normal file
40
app/src/mm/svc/MM_MERCH_PAUSE.pgc
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* MM_MERCH_PAUSE.pgc - mm 모듈 서비스 MM_MERCH_PAUSE (one service = one file).
|
||||
* 기능: 가맹점 휴업 처리 (ACTIVE -> HOLD, 가동 단말 일괄 SUSPENDED).
|
||||
* 입력: T_MERCHANT, T_REASON=휴업 사유(없으면 '자진 휴업'). 출력: T_COUNT=정지된 단말 수.
|
||||
* RC: 1=가맹점 없음, 2=활성 상태가 아님.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_MERCH_PAUSE.h"
|
||||
|
||||
void MM_MERCH_PAUSE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64], reason[128];
|
||||
long nterm;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_stat[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
gets_(b, T_REASON, reason, sizeof(reason));
|
||||
if (reason[0] == 0) strcpy(reason, "자진 휴업");
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT status INTO :h_stat FROM mm_merchant_ext WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (strcmp(h_stat, "ACTIVE") != 0) { setl(b, T_RC, 2); OK(b); }
|
||||
|
||||
EXEC SQL UPDATE mm_merchant_ext SET status = 'HOLD', updated_at = now()
|
||||
WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL UPDATE mm_terminal SET status = 'SUSPENDED'
|
||||
WHERE merchant_id = :h_merch AND status = 'ACTIVE';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
nterm = sqlca.sqlerrd[2];
|
||||
if (mmdb_insert_merch_hist(h_merch, "PAUSE", "ACTIVE", "HOLD", reason) < 0) FAIL(b);
|
||||
setl(b, T_COUNT, nterm);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_MERCH_RESUME.h
Normal file
12
app/src/mm/svc/MM_MERCH_RESUME.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_MERCH_RESUME.h - mm 서비스 MM_MERCH_RESUME 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_COUNT(재가동 단말 수), T_RC
|
||||
*/
|
||||
#ifndef MM_MERCH_RESUME_H
|
||||
#define MM_MERCH_RESUME_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_MERCH_RESUME(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_MERCH_RESUME_H */
|
||||
38
app/src/mm/svc/MM_MERCH_RESUME.pgc
Normal file
38
app/src/mm/svc/MM_MERCH_RESUME.pgc
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* MM_MERCH_RESUME.pgc - mm 모듈 서비스 MM_MERCH_RESUME (one service = one file).
|
||||
* 기능: 가맹점 영업 재개 (HOLD -> ACTIVE, 정지 단말 재가동).
|
||||
* 입력: T_MERCHANT. 출력: T_COUNT=재가동된 단말 수.
|
||||
* RC: 1=가맹점 없음, 2=휴업 상태가 아님.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_MERCH_RESUME.h"
|
||||
|
||||
void MM_MERCH_RESUME(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64];
|
||||
long nterm;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_stat[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT status INTO :h_stat FROM mm_merchant_ext WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (strcmp(h_stat, "HOLD") != 0) { setl(b, T_RC, 2); OK(b); }
|
||||
|
||||
EXEC SQL UPDATE mm_merchant_ext SET status = 'ACTIVE', updated_at = now()
|
||||
WHERE merchant_id = :h_merch;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
EXEC SQL UPDATE mm_terminal SET status = 'ACTIVE'
|
||||
WHERE merchant_id = :h_merch AND status = 'SUSPENDED';
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
nterm = sqlca.sqlerrd[2];
|
||||
if (mmdb_insert_merch_hist(h_merch, "RESUME", "HOLD", "ACTIVE", "영업 재개") < 0) FAIL(b);
|
||||
setl(b, T_COUNT, nterm);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_PARTNER_INQ.h
Normal file
12
app/src/mm/svc/MM_PARTNER_INQ.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_PARTNER_INQ.h - mm 서비스 MM_PARTNER_INQ 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_KEY1, T_STR1(제휴사명), T_STATUS, T_ARG1(표시순서), T_RC
|
||||
*/
|
||||
#ifndef MM_PARTNER_INQ_H
|
||||
#define MM_PARTNER_INQ_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_PARTNER_INQ(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_PARTNER_INQ_H */
|
||||
32
app/src/mm/svc/MM_PARTNER_INQ.pgc
Normal file
32
app/src/mm/svc/MM_PARTNER_INQ.pgc
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* MM_PARTNER_INQ.pgc - mm 모듈 서비스 MM_PARTNER_INQ (one service = one file).
|
||||
* 기능: 제휴사 마스터 단건 조회 (명칭/상태/표시순서).
|
||||
* 입력: T_KEY1=제휴사 코드. 출력: T_STR1, T_STATUS, T_ARG1.
|
||||
* RC: 1=미등록 제휴사.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_PARTNER_INQ.h"
|
||||
|
||||
void MM_PARTNER_INQ(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char code[16];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_code[16], h_name[64], h_stat[16];
|
||||
long h_sort;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_KEY1, code, sizeof(code));
|
||||
strncpy(h_code, code, sizeof(h_code)-1); h_code[sizeof(h_code)-1] = 0;
|
||||
|
||||
EXEC SQL SELECT code_name, status, sort_order INTO :h_name, :h_stat, :h_sort
|
||||
FROM mm_code WHERE code_group = 'PARTNER' AND code = :h_code;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
Bchg(b, T_STR1, 0, h_name, 0L);
|
||||
Bchg(b, T_STATUS, 0, h_stat, 0L);
|
||||
setl(b, T_ARG1, h_sort);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_PARTNER_REG.h
Normal file
12
app/src/mm/svc/MM_PARTNER_REG.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_PARTNER_REG.h - mm 서비스 MM_PARTNER_REG 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_KEY1(제휴사 코드), T_STR1(제휴사명), T_ARG1(표시순서), T_RC
|
||||
*/
|
||||
#ifndef MM_PARTNER_REG_H
|
||||
#define MM_PARTNER_REG_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_PARTNER_REG(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_PARTNER_REG_H */
|
||||
33
app/src/mm/svc/MM_PARTNER_REG.pgc
Normal file
33
app/src/mm/svc/MM_PARTNER_REG.pgc
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* MM_PARTNER_REG.pgc - mm 모듈 서비스 MM_PARTNER_REG (one service = one file).
|
||||
* 기능: 제휴사 마스터 등록/갱신 (공통코드 PARTNER 그룹 upsert).
|
||||
* 입력: T_KEY1=제휴사 코드, T_STR1=제휴사명, T_ARG1=표시순서.
|
||||
* RC: 3=필수값 누락. 재등록 시 명칭/순서 갱신 (기존 상태 유지).
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_PARTNER_REG.h"
|
||||
|
||||
void MM_PARTNER_REG(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char code[16], name[64];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_code[16], h_name[64];
|
||||
long h_sort;
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_KEY1, code, sizeof(code));
|
||||
gets_(b, T_STR1, name, sizeof(name));
|
||||
h_sort = getl(b, T_ARG1);
|
||||
if (code[0] == 0 || name[0] == 0) { setl(b, T_RC, 3); OK(b); }
|
||||
strncpy(h_code, code, sizeof(h_code)-1); h_code[sizeof(h_code)-1] = 0;
|
||||
strncpy(h_name, name, sizeof(h_name)-1); h_name[sizeof(h_name)-1] = 0;
|
||||
|
||||
EXEC SQL INSERT INTO mm_code (code_group, code, code_name, sort_order)
|
||||
VALUES ('PARTNER', :h_code, :h_name, :h_sort)
|
||||
ON CONFLICT (code_group, code)
|
||||
DO UPDATE SET code_name = EXCLUDED.code_name, sort_order = EXCLUDED.sort_order;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_PARTNER_STATUS.h
Normal file
12
app/src/mm/svc/MM_PARTNER_STATUS.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_PARTNER_STATUS.h - mm 서비스 MM_PARTNER_STATUS 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_KEY1, T_STATUS(ACTIVE/INACTIVE), T_RC
|
||||
*/
|
||||
#ifndef MM_PARTNER_STATUS_H
|
||||
#define MM_PARTNER_STATUS_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_PARTNER_STATUS(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_PARTNER_STATUS_H */
|
||||
32
app/src/mm/svc/MM_PARTNER_STATUS.pgc
Normal file
32
app/src/mm/svc/MM_PARTNER_STATUS.pgc
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* MM_PARTNER_STATUS.pgc - mm 모듈 서비스 MM_PARTNER_STATUS (one service = one file).
|
||||
* 기능: 제휴사 사용 상태 변경 (ACTIVE/INACTIVE 만 허용).
|
||||
* 입력: T_KEY1=제휴사 코드, T_STATUS=변경할 상태.
|
||||
* RC: 1=미등록 제휴사, 3=허용되지 않는 상태값.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_PARTNER_STATUS.h"
|
||||
|
||||
void MM_PARTNER_STATUS(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char code[16], stat[16];
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_code[16], h_stat[16];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_KEY1, code, sizeof(code));
|
||||
gets_(b, T_STATUS, stat, sizeof(stat));
|
||||
if (strcmp(stat, "ACTIVE") != 0 && strcmp(stat, "INACTIVE") != 0) {
|
||||
setl(b, T_RC, 3); OK(b);
|
||||
}
|
||||
strncpy(h_code, code, sizeof(h_code)-1); h_code[sizeof(h_code)-1] = 0;
|
||||
strncpy(h_stat, stat, sizeof(h_stat)-1); h_stat[sizeof(h_stat)-1] = 0;
|
||||
|
||||
EXEC SQL UPDATE mm_code SET status = :h_stat
|
||||
WHERE code_group = 'PARTNER' AND code = :h_code;
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
if (sqlca.sqlerrd[2] == 0) { setl(b, T_RC, 1); OK(b); }
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_RATE_APPROVE.h
Normal file
12
app/src/mm/svc/MM_RATE_APPROVE.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_RATE_APPROVE.h - mm 서비스 MM_RATE_APPROVE 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_AMT1(적용 bps), T_STR2(카드종류), T_RC
|
||||
*/
|
||||
#ifndef MM_RATE_APPROVE_H
|
||||
#define MM_RATE_APPROVE_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_RATE_APPROVE(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_RATE_APPROVE_H */
|
||||
47
app/src/mm/svc/MM_RATE_APPROVE.pgc
Normal file
47
app/src/mm/svc/MM_RATE_APPROVE.pgc
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* MM_RATE_APPROVE.pgc - mm 모듈 서비스 MM_RATE_APPROVE (one service = one file).
|
||||
* 기능: 수수료율 변경 승인 (대기 요청을 실제 요율 마스터에 반영, RATE_APV 이력).
|
||||
* 입력: T_MERCHANT. 출력: T_STR2=카드종류, T_AMT1=적용 bps.
|
||||
* RC: 1=대기중 요청 없음, 5=요청 데이터 형식 오류.
|
||||
* caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
|
||||
*/
|
||||
#include "MM_RATE_APPROVE.h"
|
||||
|
||||
void MM_RATE_APPROVE(TPSVCINFO *p)
|
||||
{
|
||||
UBFH *b = (UBFH *)p->data;
|
||||
char merch[64], card[16];
|
||||
char *colon;
|
||||
long bps;
|
||||
EXEC SQL BEGIN DECLARE SECTION;
|
||||
char h_merch[64], h_req[32];
|
||||
EXEC SQL END DECLARE SECTION;
|
||||
|
||||
gets_(b, T_MERCHANT, merch, sizeof(merch));
|
||||
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
|
||||
|
||||
/* 최신 미처리 RATE_REQ 를 찾는다 (형식 "CARD:bps") */
|
||||
EXEC SQL SELECT r.after_val INTO :h_req FROM mm_merch_hist r
|
||||
WHERE r.merchant_id = :h_merch AND r.action = 'RATE_REQ'
|
||||
AND NOT EXISTS (SELECT 1 FROM mm_merch_hist d
|
||||
WHERE d.merchant_id = r.merchant_id
|
||||
AND d.action IN ('RATE_APV', 'RATE_REJ')
|
||||
AND d.hist_id > r.hist_id)
|
||||
ORDER BY r.hist_id DESC LIMIT 1;
|
||||
if (sqlca.sqlcode == 100) { setl(b, T_RC, 1); OK(b); }
|
||||
if (sqlca.sqlcode < 0) FAIL(b);
|
||||
|
||||
colon = strchr(h_req, ':');
|
||||
if (colon == NULL) { setl(b, T_RC, 5); OK(b); }
|
||||
*colon = 0;
|
||||
strncpy(card, h_req, sizeof(card)-1); card[sizeof(card)-1] = 0;
|
||||
bps = atol(colon + 1);
|
||||
if (bps < 1 || bps > 500) { setl(b, T_RC, 5); OK(b); }
|
||||
|
||||
if (mmdb_set_fee_rate(h_merch, card, bps) < 0) FAIL(b);
|
||||
if (mmdb_insert_merch_hist(h_merch, "RATE_APV", "", colon + 1, "요율 변경 승인 반영") < 0) FAIL(b);
|
||||
Bchg(b, T_STR2, 0, card, 0L);
|
||||
setl(b, T_AMT1, bps);
|
||||
setl(b, T_RC, 0);
|
||||
OK(b);
|
||||
}
|
||||
12
app/src/mm/svc/MM_RATE_REJECT.h
Normal file
12
app/src/mm/svc/MM_RATE_REJECT.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* MM_RATE_REJECT.h - mm 서비스 MM_RATE_REJECT 카피북 (copybook / record header).
|
||||
* 사용 UBF 필드: T_MERCHANT, T_REASON, T_STR1(반려된 요청), T_RC
|
||||
*/
|
||||
#ifndef MM_RATE_REJECT_H
|
||||
#define MM_RATE_REJECT_H
|
||||
|
||||
#include "mm_svc.h"
|
||||
|
||||
void MM_RATE_REJECT(TPSVCINFO *p);
|
||||
|
||||
#endif /* MM_RATE_REJECT_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