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

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

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

View file

@ -96,6 +96,65 @@
#include "ACQ_APPRGAP.h"
#include "ACQ_FXCONVERT.h"
#include "ACQ_CHANDETAIL.h"
#include "ACQ_BRANDSUM.h"
#include "ACQ_BRANDQRY.h"
#include "ACQ_CTRYQRY.h"
#include "ACQ_CCYQRY.h"
#include "ACQ_CCYRANK.h"
#include "ACQ_CHANRANK.h"
#include "ACQ_BRANDRANK.h"
#include "ACQ_CTRYRANK.h"
#include "ACQ_ERRCLASS.h"
#include "ACQ_ERRQRY.h"
#include "ACQ_ERRRETRY.h"
#include "ACQ_ERRSTAT.h"
#include "ACQ_REBUYAPPR.h"
#include "ACQ_REBUYREJ.h"
#include "ACQ_REBUYHIST.h"
#include "ACQ_CB_RND2.h"
#include "ACQ_CB_ARB.h"
#include "ACQ_CB_FINAL.h"
#include "ACQ_CB_REVERSE.h"
#include "ACQ_CORRRSN.h"
#include "ACQ_CORRSTAT.h"
#include "ACQ_CORRAPPR.h"
#include "ACQ_INSTQRY.h"
#include "ACQ_INSTPREPAY.h"
#include "ACQ_INSTPLAN.h"
#include "ACQ_INSTCXL.h"
#include "ACQ_ESCROW.h"
#include "ACQ_ESCROWREL.h"
#include "ACQ_GUARANTEE.h"
#include "ACQ_GUARQRY.h"
#include "ACQ_TAXMODIFY.h"
#include "ACQ_TAXREVERSE.h"
#include "ACQ_TAXQRY.h"
#include "ACQ_ALERTAMT.h"
#include "ACQ_ALERTVEL.h"
#include "ACQ_ALERTDUP.h"
#include "ACQ_ALERTQRY.h"
#include "ACQ_EDIRSNDCH.h"
#include "ACQ_EDIQRY.h"
#include "ACQ_EDISTAT.h"
#include "ACQ_HOURSTAT.h"
#include "ACQ_DOWSTAT.h"
#include "ACQ_QTRSTAT.h"
#include "ACQ_GRADESTAT.h"
#include "ACQ_HALFSTAT.h"
#include "ACQ_BULKCHK.h"
#include "ACQ_BULKRPT.h"
#include "ACQ_EVENTBUY.h"
#include "ACQ_PROMOQRY.h"
#include "ACQ_PROMOSTAT.h"
#include "ACQ_LIMITEXC.h"
#include "ACQ_LIMITOVR.h"
#include "ACQ_SETTLEPRE.h"
#include "ACQ_SETTLEEXP.h"
#include "ACQ_EXCHANGE.h"
#include "ACQ_RETURNQRY.h"
#include "ACQ_RETURNSTAT.h"
/* ----- advertise table: {service name, function} (fn is extern from its file) */
static struct { const char *name; void (*fn)(TPSVCINFO *); } SVCS[] = {
{"ACQUIRE", ACQUIRE}, {"ACQ_DDC", ACQ_DDC},
@ -136,6 +195,64 @@ static struct { const char *name; void (*fn)(TPSVCINFO *); } SVCS[] = {
{"ACQ_VELOCITY", ACQ_VELOCITY}, {"ACQ_TOPMERCH", ACQ_TOPMERCH},
{"ACQ_NETCALC", ACQ_NETCALC}, {"ACQ_APPRGAP", ACQ_APPRGAP},
{"ACQ_FXCONVERT", ACQ_FXCONVERT},
{"ACQ_CHANDETAIL", ACQ_CHANDETAIL},
{"ACQ_BRANDSUM", ACQ_BRANDSUM},
{"ACQ_BRANDQRY", ACQ_BRANDQRY},
{"ACQ_CTRYQRY", ACQ_CTRYQRY},
{"ACQ_CCYQRY", ACQ_CCYQRY},
{"ACQ_CCYRANK", ACQ_CCYRANK},
{"ACQ_CHANRANK", ACQ_CHANRANK},
{"ACQ_BRANDRANK", ACQ_BRANDRANK},
{"ACQ_CTRYRANK", ACQ_CTRYRANK},
{"ACQ_ERRCLASS", ACQ_ERRCLASS},
{"ACQ_ERRQRY", ACQ_ERRQRY},
{"ACQ_ERRRETRY", ACQ_ERRRETRY},
{"ACQ_ERRSTAT", ACQ_ERRSTAT},
{"ACQ_REBUYAPPR", ACQ_REBUYAPPR},
{"ACQ_REBUYREJ", ACQ_REBUYREJ},
{"ACQ_REBUYHIST", ACQ_REBUYHIST},
{"ACQ_CB_RND2", ACQ_CB_RND2},
{"ACQ_CB_ARB", ACQ_CB_ARB},
{"ACQ_CB_FINAL", ACQ_CB_FINAL},
{"ACQ_CB_REVERSE", ACQ_CB_REVERSE},
{"ACQ_CORRRSN", ACQ_CORRRSN},
{"ACQ_CORRSTAT", ACQ_CORRSTAT},
{"ACQ_CORRAPPR", ACQ_CORRAPPR},
{"ACQ_INSTQRY", ACQ_INSTQRY},
{"ACQ_INSTPREPAY", ACQ_INSTPREPAY},
{"ACQ_INSTPLAN", ACQ_INSTPLAN},
{"ACQ_INSTCXL", ACQ_INSTCXL},
{"ACQ_ESCROW", ACQ_ESCROW},
{"ACQ_ESCROWREL", ACQ_ESCROWREL},
{"ACQ_GUARANTEE", ACQ_GUARANTEE},
{"ACQ_GUARQRY", ACQ_GUARQRY},
{"ACQ_TAXMODIFY", ACQ_TAXMODIFY},
{"ACQ_TAXREVERSE", ACQ_TAXREVERSE},
{"ACQ_TAXQRY", ACQ_TAXQRY},
{"ACQ_ALERTAMT", ACQ_ALERTAMT},
{"ACQ_ALERTVEL", ACQ_ALERTVEL},
{"ACQ_ALERTDUP", ACQ_ALERTDUP},
{"ACQ_ALERTQRY", ACQ_ALERTQRY},
{"ACQ_EDIRSNDCH", ACQ_EDIRSNDCH},
{"ACQ_EDIQRY", ACQ_EDIQRY},
{"ACQ_EDISTAT", ACQ_EDISTAT},
{"ACQ_HOURSTAT", ACQ_HOURSTAT},
{"ACQ_DOWSTAT", ACQ_DOWSTAT},
{"ACQ_QTRSTAT", ACQ_QTRSTAT},
{"ACQ_GRADESTAT", ACQ_GRADESTAT},
{"ACQ_HALFSTAT", ACQ_HALFSTAT},
{"ACQ_BULKCHK", ACQ_BULKCHK},
{"ACQ_BULKRPT", ACQ_BULKRPT},
{"ACQ_EVENTBUY", ACQ_EVENTBUY},
{"ACQ_PROMOQRY", ACQ_PROMOQRY},
{"ACQ_PROMOSTAT", ACQ_PROMOSTAT},
{"ACQ_LIMITEXC", ACQ_LIMITEXC},
{"ACQ_LIMITOVR", ACQ_LIMITOVR},
{"ACQ_SETTLEPRE", ACQ_SETTLEPRE},
{"ACQ_SETTLEEXP", ACQ_SETTLEEXP},
{"ACQ_EXCHANGE", ACQ_EXCHANGE},
{"ACQ_RETURNQRY", ACQ_RETURNQRY},
{"ACQ_RETURNSTAT", ACQ_RETURNSTAT},
{NULL, NULL}
};

View file

@ -0,0 +1,19 @@
/*
* ac_brand_batch.h - ac ac_brand_batch (batch copybook / record header).
* ac () ( , XA).
*/
#ifndef AC_BRAND_BATCH_H
#define AC_BRAND_BATCH_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "ac_dbio.h"
typedef struct {
long brands;
long gross;
} ac_brand_batch_rec_t;
#endif /* AC_BRAND_BATCH_H */

View file

@ -0,0 +1,35 @@
/*
* ac_brand_batch.pgc - ac 발급사(브랜드)별 매입 집계 (단건 집계 배치, XA).
* 영업일 매입을 발급사 기준으로 브랜드 종수와 총 매출을 집계한다.
*
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
* transaction, aggregate(s) run on the biz_date, then tpcommit drives XA 2PC.
* Usage: ac_brand_batch [YYYY-MM-DD]
*/
EXEC SQL INCLUDE ac_brand_batch;
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_brands, h_gross;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT count(distinct issuer), coalesce(sum(amount),0)
INTO :h_brands, :h_gross FROM purchase WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) { fprintf(stderr, "ac_brand_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> ac_brand_batch COMMIT: bizdate=%s brands=%ld gross=%ld\n", bizdate, h_brands, h_gross);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,20 @@
/*
* ac_ccyband_batch.h - ac ac_ccyband_batch (batch copybook / record header).
* ac ( , XA).
*/
#ifndef AC_CCYBAND_BATCH_H
#define AC_CCYBAND_BATCH_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "ac_dbio.h"
typedef struct {
long ccys;
long fx_amount;
long krw_amount;
} ac_ccyband_batch_rec_t;
#endif /* AC_CCYBAND_BATCH_H */

View file

@ -0,0 +1,35 @@
/*
* ac_ccyband_batch.pgc - ac 통화별 해외매입 집계 (단건 집계 배치, XA).
* 해외매입 원장에서 통화 종수와 원통화/원화 합계를 집계한다.
*
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
* transaction, aggregate(s) run on the biz_date, then tpcommit drives XA 2PC.
* Usage: ac_ccyband_batch [YYYY-MM-DD]
*/
EXEC SQL INCLUDE ac_ccyband_batch;
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_ccys, h_fx, h_krw;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT count(distinct ccy), coalesce(sum(fx_amount),0), coalesce(sum(krw_amount),0)
INTO :h_ccys, :h_fx, :h_krw FROM ac_fx WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) { fprintf(stderr, "ac_ccyband_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> ac_ccyband_batch COMMIT: bizdate=%s ccys=%ld fx=%ld krw=%ld\n", bizdate, h_ccys, h_fx, h_krw);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,20 @@
/*
* ac_country_batch.h - ac ac_country_batch (batch copybook / record header).
* ac () ( , XA).
*/
#ifndef AC_COUNTRY_BATCH_H
#define AC_COUNTRY_BATCH_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "ac_dbio.h"
typedef struct {
long us;
long jp;
long etc;
} ac_country_batch_rec_t;
#endif /* AC_COUNTRY_BATCH_H */

View file

@ -0,0 +1,37 @@
/*
* ac_country_batch.pgc - ac 국가(통화권역)별 해외매입 집계 (단건 집계 배치, XA).
* 해외매입 원화금액을 미주/일본/기타 권역 대표통화 기준으로 분해 집계한다.
*
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
* transaction, aggregate(s) run on the biz_date, then tpcommit drives XA 2PC.
* Usage: ac_country_batch [YYYY-MM-DD]
*/
EXEC SQL INCLUDE ac_country_batch;
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_us, h_jp, h_etc;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT coalesce(sum(krw_amount) FILTER (WHERE ccy IN ('USD','CAD')),0),
coalesce(sum(krw_amount) FILTER (WHERE ccy = 'JPY'),0),
coalesce(sum(krw_amount) FILTER (WHERE ccy NOT IN ('USD','CAD','JPY')),0)
INTO :h_us, :h_jp, :h_etc FROM ac_fx WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) { fprintf(stderr, "ac_country_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> ac_country_batch COMMIT: bizdate=%s us=%ld jp=%ld etc=%ld\n", bizdate, h_us, h_jp, h_etc);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,20 @@
/*
* ac_dow_batch.h - ac ac_dow_batch (batch copybook / record header).
* ac ( , XA).
*/
#ifndef AC_DOW_BATCH_H
#define AC_DOW_BATCH_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "ac_dbio.h"
typedef struct {
long weekday;
long weekend;
long gross;
} ac_dow_batch_rec_t;
#endif /* AC_DOW_BATCH_H */

View file

@ -0,0 +1,36 @@
/*
* ac_dow_batch.pgc - ac 요일별 매입 집계 (단건 집계 배치, XA).
* 영업일의 요일(dow)을 판정해 평일/주말 매입 건수와 매출을 분해 집계한다.
*
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
* transaction, aggregate(s) run on the biz_date, then tpcommit drives XA 2PC.
* Usage: ac_dow_batch [YYYY-MM-DD]
*/
EXEC SQL INCLUDE ac_dow_batch;
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_wd, h_we, h_gross;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT count(*) FILTER (WHERE extract(dow from biz_date) BETWEEN 1 AND 5),
count(*) FILTER (WHERE extract(dow from biz_date) IN (0, 6)), coalesce(sum(amount),0)
INTO :h_wd, :h_we, :h_gross FROM purchase WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) { fprintf(stderr, "ac_dow_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> ac_dow_batch COMMIT: bizdate=%s weekday=%ld weekend=%ld gross=%ld\n", bizdate, h_wd, h_we, h_gross);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,20 @@
/*
* ac_errtype_batch.h - ac ac_errtype_batch (batch copybook / record header).
* ac ( , XA).
*/
#ifndef AC_ERRTYPE_BATCH_H
#define AC_ERRTYPE_BATCH_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "ac_dbio.h"
typedef struct {
long dup;
long limit;
long fx;
} ac_errtype_batch_rec_t;
#endif /* AC_ERRTYPE_BATCH_H */

View file

@ -0,0 +1,37 @@
/*
* ac_errtype_batch.pgc - ac 오류유형별 미매입 집계 (단건 집계 배치, XA).
* 미매입 원장의 사유 접두어별로 중복/한도/환율 오류 건수를 분해 집계한다.
*
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
* transaction, aggregate(s) run on the biz_date, then tpcommit drives XA 2PC.
* Usage: ac_errtype_batch [YYYY-MM-DD]
*/
EXEC SQL INCLUDE ac_errtype_batch;
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_dup, h_lim, h_fx;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT count(*) FILTER (WHERE reason LIKE 'DUP%'),
count(*) FILTER (WHERE reason LIKE 'LIMIT%'),
count(*) FILTER (WHERE reason LIKE 'FX%')
INTO :h_dup, :h_lim, :h_fx FROM ac_unmatch WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) { fprintf(stderr, "ac_errtype_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> ac_errtype_batch COMMIT: bizdate=%s dup=%ld limit=%ld fx=%ld\n", bizdate, h_dup, h_lim, h_fx);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,20 @@
/*
* ac_escrow_batch.h - ac ac_escrow_batch (batch copybook / record header).
* ac ( , XA).
*/
#ifndef AC_ESCROW_BATCH_H
#define AC_ESCROW_BATCH_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "ac_dbio.h"
typedef struct {
long escrow;
long release;
long balance;
} ac_escrow_batch_rec_t;
#endif /* AC_ESCROW_BATCH_H */

View file

@ -0,0 +1,37 @@
/*
* ac_escrow_batch.pgc - ac 에스크로 잔액 집계 (단건 집계 배치, XA).
* 원장에서 예치(ESCROW)와 해제(ESCROW_REL) 합계를 구해 순 예치 잔액을 낸다.
*
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
* transaction, aggregate(s) run on the biz_date, then tpcommit drives XA 2PC.
* Usage: ac_escrow_batch [YYYY-MM-DD]
*/
EXEC SQL INCLUDE ac_escrow_batch;
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_esc, h_rel, h_bal;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT coalesce(sum(amount) FILTER (WHERE entry_type = 'ESCROW'),0),
coalesce(sum(amount) FILTER (WHERE entry_type = 'ESCROW_REL'),0)
INTO :h_esc, :h_rel FROM ledger WHERE biz_date = :h_bizdate;
h_bal = h_esc - h_rel;
if (sqlca.sqlcode < 0) { fprintf(stderr, "ac_escrow_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> ac_escrow_batch COMMIT: bizdate=%s escrow=%ld release=%ld balance=%ld\n", bizdate, h_esc, h_rel, h_bal);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,20 @@
/*
* ac_exchange_batch.h - ac ac_exchange_batch (batch copybook / record header).
* ac / ( , XA).
*/
#ifndef AC_EXCHANGE_BATCH_H
#define AC_EXCHANGE_BATCH_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "ac_dbio.h"
typedef struct {
long returns;
long exchanges;
long amount;
} ac_exchange_batch_rec_t;
#endif /* AC_EXCHANGE_BATCH_H */

View file

@ -0,0 +1,37 @@
/*
* ac_exchange_batch.pgc - ac 반품/교환 집계 (단건 집계 배치, XA).
* 취소 원장에서 반품(RETURN)/교환(EXCHANGE) 건수와 금액을 분해 집계한다.
*
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
* transaction, aggregate(s) run on the biz_date, then tpcommit drives XA 2PC.
* Usage: ac_exchange_batch [YYYY-MM-DD]
*/
EXEC SQL INCLUDE ac_exchange_batch;
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_ret, h_exc, h_amt;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT count(*) FILTER (WHERE cancel_type = 'RETURN'),
count(*) FILTER (WHERE cancel_type = 'EXCHANGE'),
coalesce(sum(amount) FILTER (WHERE cancel_type IN ('RETURN','EXCHANGE')),0)
INTO :h_ret, :h_exc, :h_amt FROM ac_cancel WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) { fprintf(stderr, "ac_exchange_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> ac_exchange_batch COMMIT: bizdate=%s return=%ld exchange=%ld amount=%ld\n", bizdate, h_ret, h_exc, h_amt);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,20 @@
/*
* ac_grade_batch.h - ac ac_grade_batch (batch copybook / record header).
* ac ( , XA).
*/
#ifndef AC_GRADE_BATCH_H
#define AC_GRADE_BATCH_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "ac_dbio.h"
typedef struct {
long premium;
long std;
long basic;
} ac_grade_batch_rec_t;
#endif /* AC_GRADE_BATCH_H */

View file

@ -0,0 +1,38 @@
/*
* ac_grade_batch.pgc - ac 가맹점등급별 매입 집계 (단건 집계 배치, XA).
* 가맹점 MDR(bps)을 프리미엄(<=20)/일반/기본 등급으로 나눠 매출을 집계한다.
*
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
* transaction, aggregate(s) run on the biz_date, then tpcommit drives XA 2PC.
* Usage: ac_grade_batch [YYYY-MM-DD]
*/
EXEC SQL INCLUDE ac_grade_batch;
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_prem, h_std, h_basic;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT coalesce(sum(p.amount) FILTER (WHERE m.mdr_bps <= 20),0),
coalesce(sum(p.amount) FILTER (WHERE m.mdr_bps BETWEEN 21 AND 28),0),
coalesce(sum(p.amount) FILTER (WHERE m.mdr_bps > 28),0)
INTO :h_prem, :h_std, :h_basic FROM purchase p
JOIN merchant m ON m.merchant_id = p.merchant_id WHERE p.biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) { fprintf(stderr, "ac_grade_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> ac_grade_batch COMMIT: bizdate=%s premium=%ld std=%ld basic=%ld\n", bizdate, h_prem, h_std, h_basic);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,19 @@
/*
* ac_hourly_batch.h - ac ac_hourly_batch (batch copybook / record header).
* ac ( , XA).
*/
#ifndef AC_HOURLY_BATCH_H
#define AC_HOURLY_BATCH_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "ac_dbio.h"
typedef struct {
long day;
long night;
} ac_hourly_batch_rec_t;
#endif /* AC_HOURLY_BATCH_H */

View file

@ -0,0 +1,36 @@
/*
* ac_hourly_batch.pgc - ac 시간대별 매입 집계 (단건 집계 배치, XA).
* 접수시각을 주간(6~17시)/야간으로 나눠 시간대별 매입 건수를 집계한다.
*
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
* transaction, aggregate(s) run on the biz_date, then tpcommit drives XA 2PC.
* Usage: ac_hourly_batch [YYYY-MM-DD]
*/
EXEC SQL INCLUDE ac_hourly_batch;
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_day, h_night;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT count(*) FILTER (WHERE extract(hour from created_at) BETWEEN 6 AND 17),
count(*) FILTER (WHERE extract(hour from created_at) NOT BETWEEN 6 AND 17)
INTO :h_day, :h_night FROM purchase WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) { fprintf(stderr, "ac_hourly_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> ac_hourly_batch COMMIT: bizdate=%s day=%ld night=%ld\n", bizdate, h_day, h_night);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,21 @@
/*
* ac_quarter_batch.h - ac ac_quarter_batch (batch copybook / record header).
* ac ( , XA).
*/
#ifndef AC_QUARTER_BATCH_H
#define AC_QUARTER_BATCH_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "ac_dbio.h"
typedef struct {
long q1;
long q2;
long q3;
long q4;
} ac_quarter_batch_rec_t;
#endif /* AC_QUARTER_BATCH_H */

View file

@ -0,0 +1,40 @@
/*
* ac_quarter_batch.pgc - ac 분기별 매입 집계 (단건 집계 배치, XA).
* 영업일이 속한 연도의 분기별 매출 합계를 한 번의 집계로 산출한다.
*
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
* transaction, aggregate(s) run on the biz_date, then tpcommit drives XA 2PC.
* Usage: ac_quarter_batch [YYYY-MM-DD]
*/
EXEC SQL INCLUDE ac_quarter_batch;
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_q1, h_q2, h_q3, h_q4;
int h_yr;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
h_yr = atoi(bizdate);
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT coalesce(sum(amount) FILTER (WHERE extract(quarter from biz_date) = 1),0),
coalesce(sum(amount) FILTER (WHERE extract(quarter from biz_date) = 2),0),
coalesce(sum(amount) FILTER (WHERE extract(quarter from biz_date) = 3),0),
coalesce(sum(amount) FILTER (WHERE extract(quarter from biz_date) = 4),0)
INTO :h_q1, :h_q2, :h_q3, :h_q4 FROM purchase WHERE extract(year from biz_date) = :h_yr;
if (sqlca.sqlcode < 0) { fprintf(stderr, "ac_quarter_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> ac_quarter_batch COMMIT: year=%d q1=%ld q2=%ld q3=%ld q4=%ld\n", h_yr, h_q1, h_q2, h_q3, h_q4);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,20 @@
/*
* ac_rebuy_batch.h - ac ac_rebuy_batch (batch copybook / record header).
* ac / ( , XA).
*/
#ifndef AC_REBUY_BATCH_H
#define AC_REBUY_BATCH_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "ac_dbio.h"
typedef struct {
long cb;
long cb2;
long refund;
} ac_rebuy_batch_rec_t;
#endif /* AC_REBUY_BATCH_H */

View file

@ -0,0 +1,37 @@
/*
* ac_rebuy_batch.pgc - ac 재매입/취소 유형 집계 (단건 집계 배치, XA).
* 취소 원장에서 지불거절(CB/CB2)과 환불(REFUND) 건수를 분해 집계한다.
*
* ATMI client: tpinit/tpopen open the ECPG XA RM, tpbegin starts ONE global
* transaction, aggregate(s) run on the biz_date, then tpcommit drives XA 2PC.
* Usage: ac_rebuy_batch [YYYY-MM-DD]
*/
EXEC SQL INCLUDE ac_rebuy_batch;
int main(int argc, char **argv)
{
const char *bizdate = (argc > 1) ? argv[1] : "2026-07-19";
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_cb, h_cb2, h_rf;
EXEC SQL END DECLARE SECTION;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpopen() < 0) { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }
EXEC SQL SELECT count(*) FILTER (WHERE cancel_type = 'CB'),
count(*) FILTER (WHERE cancel_type = 'CB2'),
count(*) FILTER (WHERE cancel_type = 'REFUND')
INTO :h_cb, :h_cb2, :h_rf FROM ac_cancel WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) { fprintf(stderr, "ac_rebuy_batch FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }
if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
printf(">>> ac_rebuy_batch COMMIT: bizdate=%s cb=%ld cb2=%ld refund=%ld\n", bizdate, h_cb, h_cb2, h_rf);
tpclose(); tpterm();
return 0;
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_ALERTAMT.h - ac ACQ_ALERTAMT (copybook / record header).
* : (T_AMOUNT)
*/
#ifndef ACQ_ALERTAMT_H
#define ACQ_ALERTAMT_H
#include "ac_svc.h"
typedef struct {
long threshold;
long over_count;
long max_amount;
} acq_alertamt_rec_t;
void ACQ_ALERTAMT(TPSVCINFO *p);
#endif /* ACQ_ALERTAMT_H */

View file

@ -0,0 +1,30 @@
/*
* ACQ_ALERTAMT.pgc - ac 모듈 서비스 ACQ_ALERTAMT (one service = one file).
* 매입 금액초과 알림: 가맹점의 영업일 매입 중 임계금액(T_AMOUNT)을 초과한
* 고액 건수와 최고 매입액을 조회해 경보 여부를 판정한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_ALERTAMT.h"
void ACQ_ALERTAMT(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_lim, h_over = 0, h_max = 0;
char h_merch[64], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
h_lim = getl(b, T_AMOUNT); if (h_lim <= 0) h_lim = 1000000;
gets_(b, T_MERCHANT, h_merch, sizeof(h_merch));
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL SELECT count(*) FILTER (WHERE amount > :h_lim), coalesce(max(amount),0)
INTO :h_over, :h_max FROM purchase
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_COUNT, h_over);
setl(b, T_AMT1, h_max);
setl(b, T_RC, h_over > 0 ? 1 : 0);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_ALERTDUP.h - ac ACQ_ALERTDUP (copybook / record header).
* : 2
*/
#ifndef ACQ_ALERTDUP_H
#define ACQ_ALERTDUP_H
#include "ac_svc.h"
typedef struct {
char merchant[64];
long dup_groups;
long rc;
} acq_alertdup_rec_t;
void ACQ_ALERTDUP(TPSVCINFO *p);
#endif /* ACQ_ALERTDUP_H */

View file

@ -0,0 +1,28 @@
/*
* ACQ_ALERTDUP.pgc - ac 모듈 서비스 ACQ_ALERTDUP (one service = one file).
* 매입 중복 알림: 가맹점의 영업일 매입 중 동일 금액이 2건 이상 반복된
* 금액 그룹 수를 세어 중복 의심 여부를 알린다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_ALERTDUP.h"
void ACQ_ALERTDUP(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_grp = 0;
char h_merch[64], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_MERCHANT, h_merch, sizeof(h_merch));
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL SELECT count(*) INTO :h_grp FROM (
SELECT amount FROM purchase WHERE merchant_id = :h_merch
AND biz_date = :h_bizdate GROUP BY amount HAVING count(*) > 1) d;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_COUNT, h_grp);
setl(b, T_RC, h_grp > 0 ? 1 : 0);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_ALERTQRY.h - ac ACQ_ALERTQRY (copybook / record header).
* : (//)
*/
#ifndef ACQ_ALERTQRY_H
#define ACQ_ALERTQRY_H
#include "ac_svc.h"
typedef struct {
long velocity;
long limit;
long dup;
} acq_alertqry_rec_t;
void ACQ_ALERTQRY(TPSVCINFO *p);
#endif /* ACQ_ALERTQRY_H */

View file

@ -0,0 +1,30 @@
/*
* ACQ_ALERTQRY.pgc - ac 모듈 서비스 ACQ_ALERTQRY (one service = one file).
* 매입 알림 유형별 조회: 미매입 원장을 알림 유형(속도/한도/중복) 접두어로
* 한 번에 분해 집계해 유형별 미해소 알림 건수를 응답한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_ALERTQRY.h"
void ACQ_ALERTQRY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_vel = 0, h_lim = 0, h_dup = 0;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL SELECT count(*) FILTER (WHERE reason LIKE 'VEL%'),
count(*) FILTER (WHERE reason LIKE 'LIMIT%'),
count(*) FILTER (WHERE reason LIKE 'DUP%')
INTO :h_vel, :h_lim, :h_dup FROM ac_unmatch WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_ARG1, h_vel);
setl(b, T_ARG2, h_lim);
setl(b, T_ARG3, h_dup);
setl(b, T_COUNT, h_vel + h_lim + h_dup);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_ALERTVEL.h - ac ACQ_ALERTVEL (copybook / record header).
* : 5
*/
#ifndef ACQ_ALERTVEL_H
#define ACQ_ALERTVEL_H
#include "ac_svc.h"
typedef struct {
char channel[16];
long win5m;
long win30m;
} acq_alertvel_rec_t;
void ACQ_ALERTVEL(TPSVCINFO *p);
#endif /* ACQ_ALERTVEL_H */

View file

@ -0,0 +1,30 @@
/*
* ACQ_ALERTVEL.pgc - ac 모듈 서비스 ACQ_ALERTVEL (one service = one file).
* 매입 속도 알림: 채널의 최근 5분간 유입 건수를 재어 분당 허용치를 넘으면
* 경보한다. 참고로 직전 30분 건수도 함께 조회한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_ALERTVEL.h"
void ACQ_ALERTVEL(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long allow;
EXEC SQL BEGIN DECLARE SECTION;
long h_5m = 0, h_30m = 0;
char h_chan[16];
EXEC SQL END DECLARE SECTION;
allow = getl(b, T_ARG1); if (allow <= 0) allow = 50;
gets_(b, T_CHANNEL, h_chan, sizeof(h_chan));
EXEC SQL SELECT count(*) FILTER (WHERE created_at >= now() - interval '5 minutes'),
count(*) FILTER (WHERE created_at >= now() - interval '30 minutes')
INTO :h_5m, :h_30m FROM purchase WHERE channel = :h_chan;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_ARG2, h_5m);
setl(b, T_ARG3, h_30m);
setl(b, T_RC, h_5m > allow ? 1 : 0);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_BRANDQRY.h - ac ACQ_BRANDQRY (copybook / record header).
* : (T_ISSUER) ,
*/
#ifndef ACQ_BRANDQRY_H
#define ACQ_BRANDQRY_H
#include "ac_svc.h"
typedef struct {
char issuer[32];
long count;
long gross;
} acq_brandqry_rec_t;
void ACQ_BRANDQRY(TPSVCINFO *p);
#endif /* ACQ_BRANDQRY_H */

View file

@ -0,0 +1,30 @@
/*
* ACQ_BRANDQRY.pgc - ac 모듈 서비스 ACQ_BRANDQRY (one service = one file).
* 매입 브랜드별 조회: 지정 발급사(T_ISSUER)의 영업일 매입 건수와 총액,
* 평균 수수료를 단건으로 조회해 응답 버퍼에 채운다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_BRANDQRY.h"
void ACQ_BRANDQRY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_n = 0, h_sum = 0, h_fee = 0;
char h_iss[32], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_ISSUER, h_iss, sizeof(h_iss));
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL SELECT count(*), coalesce(sum(amount),0), coalesce(sum(fee),0)
INTO :h_n, :h_sum, :h_fee FROM purchase
WHERE issuer = :h_iss AND biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_COUNT, h_n);
setl(b, T_GROSS, h_sum);
setl(b, T_FEE, h_fee);
setl(b, T_RC, h_n > 0 ? 0 : 1);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_BRANDRANK.h - ac ACQ_BRANDRANK (copybook / record header).
* :
*/
#ifndef ACQ_BRANDRANK_H
#define ACQ_BRANDRANK_H
#include "ac_svc.h"
typedef struct {
char issuer[32];
long grand;
long half_at;
} acq_brandrank_rec_t;
void ACQ_BRANDRANK(TPSVCINFO *p);
#endif /* ACQ_BRANDRANK_H */

View file

@ -0,0 +1,42 @@
/*
* ACQ_BRANDRANK.pgc - ac 모듈 서비스 ACQ_BRANDRANK (one service = one file).
* 매입 브랜드별 순위: 발급사 매출 상위 순으로 커서 조회하며 누적 점유율을
* 계산해 상위 브랜드가 전체의 절반을 넘는 지점(집중도)을 함께 낸다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_BRANDRANK.h"
void ACQ_BRANDRANK(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long rank = 0, run = 0, half_at = 0;
EXEC SQL BEGIN DECLARE SECTION;
long h_sum, h_grand = 0;
char h_iss[32], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL SELECT coalesce(sum(amount),0) INTO :h_grand FROM purchase WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL DECLARE brr_cur CURSOR FOR
SELECT issuer, sum(amount) FROM purchase WHERE biz_date = :h_bizdate
GROUP BY issuer ORDER BY sum(amount) DESC;
EXEC SQL OPEN brr_cur;
if (sqlca.sqlcode < 0) FAIL(b);
for (;;) {
EXEC SQL FETCH brr_cur INTO :h_iss, :h_sum;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE brr_cur; FAIL(b); }
rank++; run += h_sum;
if (half_at == 0 && h_grand > 0 && run * 2 >= h_grand) half_at = rank;
if (rank <= 6) Badd(b, T_ISSUER, h_iss, 0L);
}
EXEC SQL CLOSE brr_cur;
setl(b, T_GROSS, h_grand);
setl(b, T_ARG1, rank);
setl(b, T_ARG2, half_at);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_BRANDSUM.h - ac ACQ_BRANDSUM (copybook / record header).
* : ( )
*/
#ifndef ACQ_BRANDSUM_H
#define ACQ_BRANDSUM_H
#include "ac_svc.h"
typedef struct {
char issuer[32];
long amount;
long kinds;
} acq_brandsum_rec_t;
void ACQ_BRANDSUM(TPSVCINFO *p);
#endif /* ACQ_BRANDSUM_H */

View file

@ -0,0 +1,37 @@
/*
* ACQ_BRANDSUM.pgc - ac 모듈 서비스 ACQ_BRANDSUM (one service = one file).
* 매입 브랜드별 집계: 발급사(카드 브랜드) 기준으로 매출 합계를 그룹 집계해
* 브랜드명·매출액 쌍을 occurrence 로 내리고 최다 브랜드 건수를 함께 계산한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_BRANDSUM.h"
void ACQ_BRANDSUM(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long grand = 0, kinds = 0;
EXEC SQL BEGIN DECLARE SECTION;
long h_sum, h_n;
char h_iss[32], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL DECLARE brs_cur CURSOR FOR
SELECT issuer, sum(amount), count(*) FROM purchase
WHERE biz_date = :h_bizdate GROUP BY issuer ORDER BY sum(amount) DESC;
EXEC SQL OPEN brs_cur;
if (sqlca.sqlcode < 0) FAIL(b);
for (;;) {
EXEC SQL FETCH brs_cur INTO :h_iss, :h_sum, :h_n;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE brs_cur; FAIL(b); }
if (kinds < 8) { Badd(b, T_ISSUER, h_iss, 0L); Badd(b, T_AMT1, (char *)&h_sum, 0L); }
grand += h_sum; kinds++;
}
EXEC SQL CLOSE brs_cur;
setl(b, T_GROSS, grand);
setl(b, T_ARG1, kinds);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_BULKCHK.h - ac ACQ_BULKCHK (copybook / record header).
* : (A)
*/
#ifndef ACQ_BULKCHK_H
#define ACQ_BULKCHK_H
#include "ac_svc.h"
typedef struct {
long ok_count;
long bad_count;
long rc;
} acq_bulkchk_rec_t;
void ACQ_BULKCHK(TPSVCINFO *p);
#endif /* ACQ_BULKCHK_H */

View file

@ -0,0 +1,38 @@
/*
* ACQ_BULKCHK.pgc - ac 모듈 서비스 ACQ_BULKCHK (one service = one file).
* 대량매입 배치검증: 영업일 접수(A) 매입을 커서로 순회하며 금액 양수 및
* 수수료 정합(net=amount-fee)을 점검해 정상/오류 건수를 분리 집계한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_BULKCHK.h"
void ACQ_BULKCHK(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long ok = 0, bad = 0;
EXEC SQL BEGIN DECLARE SECTION;
long h_pid, h_amt, h_fee, h_net;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL DECLARE blk_cur CURSOR FOR
SELECT purchase_id, amount, fee, net FROM purchase
WHERE biz_date = :h_bizdate AND status = 'A';
EXEC SQL OPEN blk_cur;
if (sqlca.sqlcode < 0) FAIL(b);
for (;;) {
EXEC SQL FETCH blk_cur INTO :h_pid, :h_amt, :h_fee, :h_net;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE blk_cur; FAIL(b); }
if (h_amt > 0 && h_net == h_amt - h_fee) ok++;
else { bad++; if (bad <= 8) Badd(b, T_PURCHASE_ID, (char *)&h_pid, 0L); }
}
EXEC SQL CLOSE blk_cur;
setl(b, T_ARG1, ok);
setl(b, T_ARG2, bad);
setl(b, T_RC, bad > 0 ? 1 : 0);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_BULKRPT.h - ac ACQ_BULKRPT (copybook / record header).
* : (///)
*/
#ifndef ACQ_BULKRPT_H
#define ACQ_BULKRPT_H
#include "ac_svc.h"
typedef struct {
long a;
long m;
long settled;
} acq_bulkrpt_rec_t;
void ACQ_BULKRPT(TPSVCINFO *p);
#endif /* ACQ_BULKRPT_H */

View file

@ -0,0 +1,32 @@
/*
* ACQ_BULKRPT.pgc - ac 모듈 서비스 ACQ_BULKRPT (one service = one file).
* 대량매입 리포트: 영업일 매입을 상태(접수/대사/정산/취소)별로 한 번에 분해
* 집계해 상태별 건수와 총 매출·순정산 금액을 요약 리포트로 낸다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_BULKRPT.h"
void ACQ_BULKRPT(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_a = 0, h_m = 0, h_s = 0, h_c = 0, h_g = 0, h_net = 0;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL SELECT count(*) FILTER (WHERE status = 'A'), count(*) FILTER (WHERE status = 'M'),
count(*) FILTER (WHERE status = 'S'), count(*) FILTER (WHERE status = 'C'),
coalesce(sum(amount),0), coalesce(sum(net) FILTER (WHERE status = 'S'),0)
INTO :h_a, :h_m, :h_s, :h_c, :h_g, :h_net FROM purchase WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_ARG1, h_a);
setl(b, T_ARG2, h_m);
setl(b, T_ARG3, h_s);
setl(b, T_ARG4, h_c);
setl(b, T_GROSS, h_g);
setl(b, T_NET, h_net);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_CB_ARB.h - ac ACQ_CB_ARB (copybook / record header).
* : 2 . CB
*/
#ifndef ACQ_CB_ARB_H
#define ACQ_CB_ARB_H
#include "ac_svc.h"
typedef struct {
long cancel_id;
long purchase_id;
long rc;
} acq_cb_arb_rec_t;
void ACQ_CB_ARB(TPSVCINFO *p);
#endif /* ACQ_CB_ARB_H */

View file

@ -0,0 +1,36 @@
/*
* ACQ_CB_ARB.pgc - ac 모듈 서비스 ACQ_CB_ARB (one service = one file).
* 지불거절 중재: 라운드2까지 미해결 건을 카드사 중재로 넘긴다. 해당 CB
* 행 사유를 ARB 로 갱신하고 원매입을 보류(H)로 유지한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_CB_ARB.h"
void ACQ_CB_ARB(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char note[80];
EXEC SQL BEGIN DECLARE SECTION;
long h_cid, h_pid = 0;
char h_reason[100];
EXEC SQL END DECLARE SECTION;
h_cid = getl(b, T_CANCEL_ID);
gets_(b, T_REASON, note, sizeof(note));
snprintf(h_reason, sizeof(h_reason), "ARB:%s", note[0] ? note : "PENDING");
EXEC SQL SELECT purchase_id INTO :h_pid FROM ac_cancel
WHERE cancel_id = :h_cid AND cancel_type IN ('CB', 'CB2');
if (sqlca.sqlcode == 100) { setl(b, T_RC, 4); FAIL(b); }
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL UPDATE ac_cancel SET reason = :h_reason WHERE cancel_id = :h_cid;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL UPDATE purchase SET status = 'H', updated_at = now()
WHERE purchase_id = :h_pid AND status <> 'C';
if (sqlca.sqlcode < 0) { userlog("ACQ_CB_ARB FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); FAIL(b); }
setl(b, T_PURCHASE_ID, h_pid);
setl(b, T_RC, 0);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_CB_FINAL.h - ac ACQ_CB_FINAL (copybook / record header).
* : (C)
*/
#ifndef ACQ_CB_FINAL_H
#define ACQ_CB_FINAL_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
long affected;
long rc;
} acq_cb_final_rec_t;
void ACQ_CB_FINAL(TPSVCINFO *p);
#endif /* ACQ_CB_FINAL_H */

View file

@ -0,0 +1,26 @@
/*
* ACQ_CB_FINAL.pgc - ac 모듈 서비스 ACQ_CB_FINAL (one service = one file).
* 지불거절 최종확정: 중재 결과로 매입사 패소가 확정되면 원매입을 취소(C)로
* 확정 전이하고, 확정 여부(반영 건수)를 결과코드로 응답한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_CB_FINAL.h"
void ACQ_CB_FINAL(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_pid, h_aff;
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
EXEC SQL UPDATE purchase SET status = 'C', updated_at = now()
WHERE purchase_id = :h_pid AND status = 'H';
if (sqlca.sqlcode < 0) { userlog("ACQ_CB_FINAL FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); FAIL(b); }
h_aff = sqlca.sqlerrd[2];
if (h_aff > 0) Bchg(b, T_STATUS, 0, "C", 0L);
setl(b, T_COUNT, h_aff);
setl(b, T_RC, h_aff > 0 ? 0 : 1);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_CB_REVERSE.h - ac ACQ_CB_REVERSE (copybook / record header).
* : CB . CB/CB2
*/
#ifndef ACQ_CB_REVERSE_H
#define ACQ_CB_REVERSE_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
long cancel_id;
long restored;
} acq_cb_reverse_rec_t;
void ACQ_CB_REVERSE(TPSVCINFO *p);
#endif /* ACQ_CB_REVERSE_H */

View file

@ -0,0 +1,33 @@
/*
* ACQ_CB_REVERSE.pgc - ac 모듈 서비스 ACQ_CB_REVERSE (one service = one file).
* 지불거절 역전: 방어 승소로 CB 를 무효화한다. 최근 CB/CB2 행을 조회해
* 취소 사유를 REVERSED 로 바꾸고 보류 원매입을 대사완료(M)로 복원한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_CB_REVERSE.h"
void ACQ_CB_REVERSE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long restored;
EXEC SQL BEGIN DECLARE SECTION;
long h_pid, h_cid = 0, h_aff;
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
EXEC SQL SELECT max(cancel_id) INTO :h_cid FROM ac_cancel
WHERE purchase_id = :h_pid AND cancel_type IN ('CB', 'CB2');
if (sqlca.sqlcode < 0 || h_cid == 0) { setl(b, T_RC, 4); FAIL(b); }
EXEC SQL UPDATE ac_cancel SET reason = 'REVERSED' WHERE cancel_id = :h_cid;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL UPDATE purchase SET status = 'M', updated_at = now()
WHERE purchase_id = :h_pid AND status = 'H';
if (sqlca.sqlcode < 0) { userlog("ACQ_CB_REVERSE FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); FAIL(b); }
h_aff = sqlca.sqlerrd[2];
restored = h_aff;
setl(b, T_CANCEL_ID, h_cid);
setl(b, T_RC, restored > 0 ? 0 : 1);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_CB_RND2.h - ac ACQ_CB_RND2 (copybook / record header).
* 2(2): 1 .
*/
#ifndef ACQ_CB_RND2_H
#define ACQ_CB_RND2_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
long cancel_id;
long prev_cb;
} acq_cb_rnd2_rec_t;
void ACQ_CB_RND2(TPSVCINFO *p);
#endif /* ACQ_CB_RND2_H */

View file

@ -0,0 +1,38 @@
/*
* ACQ_CB_RND2.pgc - ac 모듈 서비스 ACQ_CB_RND2 (one service = one file).
* 지불거절 2차(라운드2): 1차 방어 이후 재청구를 접수한다. 원매입에 이미
* 1차 CB 이력이 있어야 하며, ac_cancel 에 CB2 유형 행을 추가한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_CB_RND2.h"
void ACQ_CB_RND2(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char why[80];
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_pid, h_amt, h_prev = 0;
char h_reason[100], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
h_amt = getl(b, T_AMOUNT);
gets_(b, T_REASON, why, sizeof(why));
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL SELECT count(*) INTO :h_prev FROM ac_cancel
WHERE purchase_id = :h_pid AND cancel_type = 'CB';
if (sqlca.sqlcode < 0) FAIL(b);
if (h_prev == 0) { setl(b, T_RC, 4); FAIL(b); }
snprintf(h_reason, sizeof(h_reason), "CB2:%s", why[0] ? why : "REPRESENT");
EXEC SQL SELECT nextval('ac_cancel_seq') INTO :h_id;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL INSERT INTO ac_cancel (cancel_id, purchase_id, cancel_type, amount, reason, biz_date)
VALUES (:h_id, :h_pid, 'CB2', :h_amt, :h_reason, :h_bizdate);
if (sqlca.sqlcode < 0) { userlog("ACQ_CB_RND2 FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); FAIL(b); }
setl(b, T_CANCEL_ID, h_id);
setl(b, T_RC, 0);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_CCYQRY.h - ac ACQ_CCYQRY (copybook / record header).
* : (T_CCY)
*/
#ifndef ACQ_CCYQRY_H
#define ACQ_CCYQRY_H
#include "ac_svc.h"
typedef struct {
char ccy[8];
long fx_amount;
long krw_amount;
} acq_ccyqry_rec_t;
void ACQ_CCYQRY(TPSVCINFO *p);
#endif /* ACQ_CCYQRY_H */

View file

@ -0,0 +1,29 @@
/*
* ACQ_CCYQRY.pgc - ac 모듈 서비스 ACQ_CCYQRY (one service = one file).
* 매입 통화별 조회: 지정 통화(T_CCY)의 원통화 합계와 원화 환산 합계를
* 해외매입 원장에서 조회해 환산차(원화-원통화)를 계산한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_CCYQRY.h"
void ACQ_CCYQRY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long diff;
EXEC SQL BEGIN DECLARE SECTION;
long h_fx = 0, h_krw = 0;
char h_ccy[8];
EXEC SQL END DECLARE SECTION;
gets_(b, T_CCY, h_ccy, sizeof(h_ccy));
EXEC SQL SELECT coalesce(sum(fx_amount),0), coalesce(sum(krw_amount),0)
INTO :h_fx, :h_krw FROM ac_fx WHERE ccy = :h_ccy;
if (sqlca.sqlcode < 0) FAIL(b);
diff = h_krw - h_fx;
setl(b, T_FX_AMT, h_fx);
setl(b, T_GROSS, h_krw);
setl(b, T_DELTA, diff);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_CCYRANK.h - ac ACQ_CCYRANK (copybook / record header).
* :
*/
#ifndef ACQ_CCYRANK_H
#define ACQ_CCYRANK_H
#include "ac_svc.h"
typedef struct {
char top_ccy[8];
long ranks;
long krw;
} acq_ccyrank_rec_t;
void ACQ_CCYRANK(TPSVCINFO *p);
#endif /* ACQ_CCYRANK_H */

View file

@ -0,0 +1,40 @@
/*
* ACQ_CCYRANK.pgc - ac 모듈 서비스 ACQ_CCYRANK (one service = one file).
* 매입 통화별 순위: 해외매입 통화 그룹을 원화 합계 내림차순으로 커서 조회해
* 상위 통화코드·원화액 쌍을 occurrence 로 내리고 1위 통화를 표시한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_CCYRANK.h"
void ACQ_CCYRANK(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long rank = 0;
char top[8];
EXEC SQL BEGIN DECLARE SECTION;
long h_krw;
char h_ccy[8], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
top[0] = 0;
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL DECLARE ccr_cur CURSOR FOR
SELECT ccy, sum(krw_amount) FROM ac_fx WHERE biz_date = :h_bizdate
GROUP BY ccy ORDER BY sum(krw_amount) DESC;
EXEC SQL OPEN ccr_cur;
if (sqlca.sqlcode < 0) FAIL(b);
for (;;) {
EXEC SQL FETCH ccr_cur INTO :h_ccy, :h_krw;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE ccr_cur; FAIL(b); }
if (rank == 0) { strncpy(top, h_ccy, sizeof(top)-1); top[sizeof(top)-1] = 0; }
if (rank < 5) { Badd(b, T_CCY, h_ccy, 0L); Badd(b, T_AMT1, (char *)&h_krw, 0L); }
rank++;
}
EXEC SQL CLOSE ccr_cur;
if (top[0]) Bchg(b, T_STR1, 0, top, 0L);
setl(b, T_ARG1, rank);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_CHANDETAIL.h - ac ACQ_CHANDETAIL (copybook / record header).
* : //
*/
#ifndef ACQ_CHANDETAIL_H
#define ACQ_CHANDETAIL_H
#include "ac_svc.h"
typedef struct {
char channel[16];
long avg_amount;
long kinds;
} acq_chandetail_rec_t;
void ACQ_CHANDETAIL(TPSVCINFO *p);
#endif /* ACQ_CHANDETAIL_H */

View file

@ -0,0 +1,39 @@
/*
* ACQ_CHANDETAIL.pgc - ac 모듈 서비스 ACQ_CHANDETAIL (one service = one file).
* 매입 채널별 상세 조회: 영업일 채널 그룹의 건수/총액/평균을 커서로 훑어
* 채널명·평균단가 쌍을 occurrence 로 내리고 전체 평균을 함께 반환한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_CHANDETAIL.h"
void ACQ_CHANDETAIL(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long tot = 0, cnt = 0, kinds = 0;
EXEC SQL BEGIN DECLARE SECTION;
long h_n, h_sum, h_avg;
char h_chan[16], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL DECLARE chd_cur CURSOR FOR
SELECT channel, count(*), sum(amount), avg(amount)::bigint FROM purchase
WHERE biz_date = :h_bizdate AND status <> 'C' GROUP BY channel ORDER BY channel;
EXEC SQL OPEN chd_cur;
if (sqlca.sqlcode < 0) FAIL(b);
for (;;) {
EXEC SQL FETCH chd_cur INTO :h_chan, :h_n, :h_sum, :h_avg;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE chd_cur; FAIL(b); }
if (kinds < 8) { Badd(b, T_STR1, h_chan, 0L); Badd(b, T_AMT1, (char *)&h_avg, 0L); }
tot += h_sum; cnt += h_n; kinds++;
}
EXEC SQL CLOSE chd_cur;
setl(b, T_GROSS, tot);
setl(b, T_COUNT, cnt);
setl(b, T_ARG1, kinds);
setl(b, T_AMT2, cnt > 0 ? tot / cnt : 0);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_CHANRANK.h - ac ACQ_CHANRANK (copybook / record header).
* :
*/
#ifndef ACQ_CHANRANK_H
#define ACQ_CHANRANK_H
#include "ac_svc.h"
typedef struct {
char busiest[16];
long count;
long ranks;
} acq_chanrank_rec_t;
void ACQ_CHANRANK(TPSVCINFO *p);
#endif /* ACQ_CHANRANK_H */

View file

@ -0,0 +1,41 @@
/*
* ACQ_CHANRANK.pgc - ac 모듈 서비스 ACQ_CHANRANK (one service = one file).
* 매입 채널별 순위: 영업일 채널을 건수 내림차순으로 정렬해 커서 조회하고
* 채널명·건수 쌍을 occurrence 로 내려 최다 유입 채널을 판별한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_CHANRANK.h"
void ACQ_CHANRANK(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long rank = 0, busiest = 0;
char topchan[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_n;
char h_chan[16], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
topchan[0] = 0;
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL DECLARE chr_cur CURSOR FOR
SELECT channel, count(*) FROM purchase WHERE biz_date = :h_bizdate
GROUP BY channel ORDER BY count(*) DESC, channel;
EXEC SQL OPEN chr_cur;
if (sqlca.sqlcode < 0) FAIL(b);
for (;;) {
EXEC SQL FETCH chr_cur INTO :h_chan, :h_n;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE chr_cur; FAIL(b); }
if (rank == 0) { strncpy(topchan, h_chan, sizeof(topchan)-1); topchan[sizeof(topchan)-1] = 0; busiest = h_n; }
if (rank < 6) { Badd(b, T_CHANNEL, h_chan, 0L); Badd(b, T_ARG3, (char *)&h_n, 0L); }
rank++;
}
EXEC SQL CLOSE chr_cur;
if (topchan[0]) Bchg(b, T_STR2, 0, topchan, 0L);
setl(b, T_COUNT, busiest);
setl(b, T_ARG1, rank);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_CORRAPPR.h - ac ACQ_CORRAPPR (copybook / record header).
* : (ac_fee_adj) OK
*/
#ifndef ACQ_CORRAPPR_H
#define ACQ_CORRAPPR_H
#include "ac_svc.h"
typedef struct {
long adj_id;
long affected;
long rc;
} acq_corrappr_rec_t;
void ACQ_CORRAPPR(TPSVCINFO *p);
#endif /* ACQ_CORRAPPR_H */

View file

@ -0,0 +1,30 @@
/*
* ACQ_CORRAPPR.pgc - ac 모듈 서비스 ACQ_CORRAPPR (one service = one file).
* 매입 정정 승인: 접수된 조정(ac_fee_adj) 행의 사유 앞에 OK 승인 표식을
* 덧대어 확정한다. 이미 승인된 건은 중복 승인하지 않는다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_CORRAPPR.h"
void ACQ_CORRAPPR(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_aff;
char h_reason[128];
EXEC SQL END DECLARE SECTION;
h_id = getl(b, T_ADJ);
EXEC SQL SELECT reason INTO :h_reason FROM ac_fee_adj WHERE adj_id = :h_id;
if (sqlca.sqlcode == 100) { setl(b, T_RC, 5); FAIL(b); }
if (sqlca.sqlcode < 0) FAIL(b);
if (strncmp(h_reason, "OK:", 3) == 0) { setl(b, T_RC, 2); FAIL(b); }
EXEC SQL UPDATE ac_fee_adj SET reason = 'OK:' || reason WHERE adj_id = :h_id;
if (sqlca.sqlcode < 0) { userlog("ACQ_CORRAPPR FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); FAIL(b); }
h_aff = sqlca.sqlerrd[2];
setl(b, T_ADJ, h_id);
setl(b, T_RC, h_aff > 0 ? 0 : 1);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_CORRRSN.h - ac ACQ_CORRRSN (copybook / record header).
* : (ac_fee_adj)
*/
#ifndef ACQ_CORRRSN_H
#define ACQ_CORRRSN_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
long adj_id;
long delta;
} acq_corrrsn_rec_t;
void ACQ_CORRRSN(TPSVCINFO *p);
#endif /* ACQ_CORRRSN_H */

View file

@ -0,0 +1,34 @@
/*
* ACQ_CORRRSN.pgc - ac 모듈 서비스 ACQ_CORRRSN (one service = one file).
* 매입 정정 사유별 처리: 수수료 조정 원장(ac_fee_adj)에 사유 코드가 붙은
* 증감 행을 남긴다. 증감액(T_DELTA)과 사유(T_REASON)를 그대로 기록한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_CORRRSN.h"
void ACQ_CORRRSN(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char why[80];
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_pid, h_delta;
char h_reason[100], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
h_delta = getl(b, T_DELTA);
gets_(b, T_REASON, why, sizeof(why));
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
if (h_delta == 0) { setl(b, T_RC, 3); FAIL(b); }
snprintf(h_reason, sizeof(h_reason), "CORR:%s", why[0] ? why : "MISC");
EXEC SQL SELECT nextval('ac_feeadj_seq') INTO :h_id;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL INSERT INTO ac_fee_adj (adj_id, purchase_id, delta, reason, biz_date)
VALUES (:h_id, :h_pid, :h_delta, :h_reason, :h_bizdate);
if (sqlca.sqlcode < 0) { userlog("ACQ_CORRRSN FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); FAIL(b); }
setl(b, T_ADJ, h_id);
setl(b, T_RC, 0);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_CORRSTAT.h - ac ACQ_CORRSTAT (copybook / record header).
* : ·
*/
#ifndef ACQ_CORRSTAT_H
#define ACQ_CORRSTAT_H
#include "ac_svc.h"
typedef struct {
char reason[64];
long net;
long kinds;
} acq_corrstat_rec_t;
void ACQ_CORRSTAT(TPSVCINFO *p);
#endif /* ACQ_CORRSTAT_H */

View file

@ -0,0 +1,37 @@
/*
* ACQ_CORRSTAT.pgc - ac 모듈 서비스 ACQ_CORRSTAT (one service = one file).
* 매입 정정 사유별 통계: 조정 원장을 사유 접두어별로 그룹 집계해 사유코드·
* 증감합계 쌍을 occurrence 로 내리고 순증감 총액을 계산한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_CORRSTAT.h"
void ACQ_CORRSTAT(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long net = 0, kinds = 0;
EXEC SQL BEGIN DECLARE SECTION;
long h_sum;
char h_reason[64], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL DECLARE crs_cur CURSOR FOR
SELECT split_part(reason, ':', 1), sum(delta) FROM ac_fee_adj
WHERE biz_date = :h_bizdate GROUP BY split_part(reason, ':', 1) ORDER BY 1;
EXEC SQL OPEN crs_cur;
if (sqlca.sqlcode < 0) FAIL(b);
for (;;) {
EXEC SQL FETCH crs_cur INTO :h_reason, :h_sum;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE crs_cur; FAIL(b); }
if (kinds < 8) { Badd(b, T_REASON, h_reason, 0L); Badd(b, T_DELTA, (char *)&h_sum, 0L); }
net += h_sum; kinds++;
}
EXEC SQL CLOSE crs_cur;
setl(b, T_GROSS, net);
setl(b, T_ARG1, kinds);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_CTRYQRY.h - ac ACQ_CTRYQRY (copybook / record header).
* : (T_CCY) (ac_fx)
*/
#ifndef ACQ_CTRYQRY_H
#define ACQ_CTRYQRY_H
#include "ac_svc.h"
typedef struct {
char ccy[8];
long krw;
long rate_bps;
} acq_ctryqry_rec_t;
void ACQ_CTRYQRY(TPSVCINFO *p);
#endif /* ACQ_CTRYQRY_H */

View file

@ -0,0 +1,29 @@
/*
* ACQ_CTRYQRY.pgc - ac 모듈 서비스 ACQ_CTRYQRY (one service = one file).
* 매입 국가별 조회: 통화권역 대표 통화(T_CCY)로 해외매입(ac_fx)을 필터해
* 권역 원화 합계와 건수를 조회하고 평균 환율(bps)을 함께 낸다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_CTRYQRY.h"
void ACQ_CTRYQRY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_n = 0, h_krw = 0, h_rate = 0;
char h_ccy[8], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_CCY, h_ccy, sizeof(h_ccy));
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL SELECT count(*), coalesce(sum(krw_amount),0), coalesce(avg(rate_bps),0)::bigint
INTO :h_n, :h_krw, :h_rate FROM ac_fx
WHERE ccy = :h_ccy AND biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_COUNT, h_n);
setl(b, T_GROSS, h_krw);
setl(b, T_ARG1, h_rate);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_CTRYRANK.h - ac ACQ_CTRYRANK (copybook / record header).
* : (///) C
*/
#ifndef ACQ_CTRYRANK_H
#define ACQ_CTRYRANK_H
#include "ac_svc.h"
typedef struct {
long buckets[4];
long best;
long rc;
} acq_ctryrank_rec_t;
void ACQ_CTRYRANK(TPSVCINFO *p);
#endif /* ACQ_CTRYRANK_H */

View file

@ -0,0 +1,49 @@
/*
* ACQ_CTRYRANK.pgc - ac 모듈 서비스 ACQ_CTRYRANK (one service = one file).
* 매입 국가별 순위: 통화코드를 권역(미주/일본/유럽/기타)으로 분류하는 C
* 분류기로 원화 합계를 권역 버킷에 모아 최대 권역 인덱스를 판정한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_CTRYRANK.h"
/* 통화 → 권역 인덱스 (0=미주 1=일본 2=유럽 3=기타) */
static int ac_region(const char *c)
{
if (strcmp(c, "USD") == 0 || strcmp(c, "CAD") == 0) return 0;
if (strcmp(c, "JPY") == 0) return 1;
if (strcmp(c, "EUR") == 0 || strcmp(c, "GBP") == 0) return 2;
return 3;
}
void ACQ_CTRYRANK(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long bucket[4] = {0, 0, 0, 0};
int i, best = 0;
EXEC SQL BEGIN DECLARE SECTION;
long h_krw;
char h_ccy[8], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL DECLARE ctr_rk CURSOR FOR
SELECT ccy, sum(krw_amount) FROM ac_fx WHERE biz_date = :h_bizdate GROUP BY ccy;
EXEC SQL OPEN ctr_rk;
if (sqlca.sqlcode < 0) FAIL(b);
for (;;) {
EXEC SQL FETCH ctr_rk INTO :h_ccy, :h_krw;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE ctr_rk; FAIL(b); }
bucket[ac_region(h_ccy)] += h_krw;
}
EXEC SQL CLOSE ctr_rk;
for (i = 1; i < 4; i++) if (bucket[i] > bucket[best]) best = i;
setl(b, T_ARG1, bucket[0]);
setl(b, T_ARG2, bucket[1]);
setl(b, T_ARG3, bucket[2]);
setl(b, T_ARG4, bucket[3]);
setl(b, T_RC, best);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_DOWSTAT.h - ac ACQ_DOWSTAT (copybook / record header).
* : (T_STR1~T_STR2) (0~6)
*/
#ifndef ACQ_DOWSTAT_H
#define ACQ_DOWSTAT_H
#include "ac_svc.h"
typedef struct {
long total;
long weekend;
long rc;
} acq_dowstat_rec_t;
void ACQ_DOWSTAT(TPSVCINFO *p);
#endif /* ACQ_DOWSTAT_H */

View file

@ -0,0 +1,41 @@
/*
* ACQ_DOWSTAT.pgc - ac 모듈 서비스 ACQ_DOWSTAT (one service = one file).
* 매입 요일별 통계: 지정 기간(T_STR1~T_STR2)의 매입을 요일(0~6)별로 그룹
* 집계해 요일번호·건수 쌍을 occurrence 로 내리고 주말 비중을 계산한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_DOWSTAT.h"
void ACQ_DOWSTAT(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long total = 0, weekend = 0;
EXEC SQL BEGIN DECLARE SECTION;
long h_dow, h_n;
char h_from[16], h_to[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_STR1, h_from, sizeof(h_from));
gets_(b, T_STR2, h_to, sizeof(h_to));
EXEC SQL DECLARE dow_cur CURSOR FOR
SELECT extract(dow from biz_date)::int, count(*) FROM purchase
WHERE biz_date BETWEEN :h_from AND :h_to GROUP BY 1 ORDER BY 1;
EXEC SQL OPEN dow_cur;
if (sqlca.sqlcode < 0) FAIL(b);
for (;;) {
EXEC SQL FETCH dow_cur INTO :h_dow, :h_n;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE dow_cur; FAIL(b); }
Badd(b, T_ARG5, (char *)&h_dow, 0L);
Badd(b, T_ARG6, (char *)&h_n, 0L);
total += h_n;
if (h_dow == 0 || h_dow == 6) weekend += h_n;
}
EXEC SQL CLOSE dow_cur;
setl(b, T_COUNT, total);
setl(b, T_ARG1, weekend);
setl(b, T_RC, total > 0 ? 0 : 1);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_EDIQRY.h - ac ACQ_EDIQRY (copybook / record header).
* EDI : (T_MERCHANT) EDI
*/
#ifndef ACQ_EDIQRY_H
#define ACQ_EDIQRY_H
#include "ac_svc.h"
typedef struct {
char merchant[64];
long count;
long sum;
} acq_ediqry_rec_t;
void ACQ_EDIQRY(TPSVCINFO *p);
#endif /* ACQ_EDIQRY_H */

View file

@ -0,0 +1,28 @@
/*
* ACQ_EDIQRY.pgc - ac 모듈 서비스 ACQ_EDIQRY (one service = one file).
* EDI 조회: 지정 가맹점(T_MERCHANT)의 영업일 EDI 접수 문서 건수와 금액
* 합계를 조회해 응답한다. 접수분이 없으면 결과코드 1.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_EDIQRY.h"
void ACQ_EDIQRY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_n = 0, h_sum = 0;
char h_merch[64], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_MERCHANT, h_merch, sizeof(h_merch));
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL SELECT count(*), coalesce(sum(amount),0) INTO :h_n, :h_sum
FROM ac_edi WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_COUNT, h_n);
setl(b, T_GROSS, h_sum);
setl(b, T_RC, h_n > 0 ? 0 : 1);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_EDIRSNDCH.h - ac ACQ_EDIRSNDCH (copybook / record header).
* EDI : EDI
*/
#ifndef ACQ_EDIRSNDCH_H
#define ACQ_EDIRSNDCH_H
#include "ac_svc.h"
typedef struct {
char doc_no[32];
long count;
long total;
} acq_edirsndch_rec_t;
void ACQ_EDIRSNDCH(TPSVCINFO *p);
#endif /* ACQ_EDIRSNDCH_H */

View file

@ -0,0 +1,37 @@
/*
* ACQ_EDIRSNDCH.pgc - ac 모듈 서비스 ACQ_EDIRSNDCH (one service = one file).
* EDI 재전송 채널별: 영업일 미수신 EDI 문서를 가맹점별로 커서 조회해
* 문서번호·금액 쌍을 occurrence 로 내리고 재전송 대상 건수를 집계한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_EDIRSNDCH.h"
void ACQ_EDIRSNDCH(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long n = 0, tot = 0;
EXEC SQL BEGIN DECLARE SECTION;
long h_amt;
char h_doc[32], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL DECLARE edr_cur CURSOR FOR
SELECT doc_no, amount FROM ac_edi WHERE biz_date = :h_bizdate ORDER BY doc_no;
EXEC SQL OPEN edr_cur;
if (sqlca.sqlcode < 0) FAIL(b);
for (;;) {
EXEC SQL FETCH edr_cur INTO :h_doc, :h_amt;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE edr_cur; FAIL(b); }
if (n < 8) { Badd(b, T_DOCNO, h_doc, 0L); Badd(b, T_AMT1, (char *)&h_amt, 0L); }
n++; tot += h_amt;
}
EXEC SQL CLOSE edr_cur;
setl(b, T_COUNT, n);
setl(b, T_GROSS, tot);
setl(b, T_RC, n > 0 ? 0 : 1);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_EDISTAT.h - ac ACQ_EDISTAT (copybook / record header).
* EDI : EDI (//)
*/
#ifndef ACQ_EDISTAT_H
#define ACQ_EDISTAT_H
#include "ac_svc.h"
typedef struct {
long lo;
long mid;
long hi;
} acq_edistat_rec_t;
void ACQ_EDISTAT(TPSVCINFO *p);
#endif /* ACQ_EDISTAT_H */

View file

@ -0,0 +1,30 @@
/*
* ACQ_EDISTAT.pgc - ac 모듈 서비스 ACQ_EDISTAT (one service = one file).
* EDI 통계: 영업일 EDI 문서를 금액대(소액/중액/고액)로 나눠 대역별 건수를
* 한 번의 집계에서 산출하고 전체 문서 금액 합계를 함께 낸다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_EDISTAT.h"
void ACQ_EDISTAT(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_lo = 0, h_mid = 0, h_hi = 0, h_sum = 0;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL SELECT count(*) FILTER (WHERE amount < 100000),
count(*) FILTER (WHERE amount >= 100000 AND amount < 1000000),
count(*) FILTER (WHERE amount >= 1000000), coalesce(sum(amount),0)
INTO :h_lo, :h_mid, :h_hi, :h_sum FROM ac_edi WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_ARG1, h_lo);
setl(b, T_ARG2, h_mid);
setl(b, T_ARG3, h_hi);
setl(b, T_GROSS, h_sum);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_ERRCLASS.h - ac ACQ_ERRCLASS (copybook / record header).
* : (ac_unmatch)
*/
#ifndef ACQ_ERRCLASS_H
#define ACQ_ERRCLASS_H
#include "ac_svc.h"
typedef struct {
long classes[4];
long count;
long rc;
} acq_errclass_rec_t;
void ACQ_ERRCLASS(TPSVCINFO *p);
#endif /* ACQ_ERRCLASS_H */

View file

@ -0,0 +1,46 @@
/*
* ACQ_ERRCLASS.pgc - ac 모듈 서비스 ACQ_ERRCLASS (one service = one file).
* 매입 오류유형별 분류: 미매입 원장(ac_unmatch)의 사유 접두어를 읽어
* 중복/한도/환율/기타 4개 오류군으로 분류하고 군별 건수를 집계한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_ERRCLASS.h"
/* 사유 접두어 → 오류군 (0=중복 1=한도 2=환율 3=기타) */
static int ac_errkind(const char *r)
{
if (strncmp(r, "DUP", 3) == 0) return 0;
if (strncmp(r, "LIMIT", 5) == 0) return 1;
if (strncmp(r, "FX", 2) == 0) return 2;
return 3;
}
void ACQ_ERRCLASS(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long cls[4] = {0, 0, 0, 0};
EXEC SQL BEGIN DECLARE SECTION;
char h_reason[64], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL DECLARE erc_cur CURSOR FOR
SELECT reason FROM ac_unmatch WHERE biz_date = :h_bizdate;
EXEC SQL OPEN erc_cur;
if (sqlca.sqlcode < 0) FAIL(b);
for (;;) {
EXEC SQL FETCH erc_cur INTO :h_reason;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE erc_cur; FAIL(b); }
cls[ac_errkind(h_reason)]++;
}
EXEC SQL CLOSE erc_cur;
setl(b, T_ARG1, cls[0]);
setl(b, T_ARG2, cls[1]);
setl(b, T_ARG3, cls[2]);
setl(b, T_ARG4, cls[3]);
setl(b, T_COUNT, cls[0] + cls[1] + cls[2] + cls[3]);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_ERRQRY.h - ac ACQ_ERRQRY (copybook / record header).
* : (T_REASON)
*/
#ifndef ACQ_ERRQRY_H
#define ACQ_ERRQRY_H
#include "ac_svc.h"
typedef struct {
char pattern[64];
long count;
long rc;
} acq_errqry_rec_t;
void ACQ_ERRQRY(TPSVCINFO *p);
#endif /* ACQ_ERRQRY_H */

View file

@ -0,0 +1,28 @@
/*
* ACQ_ERRQRY.pgc - ac 모듈 서비스 ACQ_ERRQRY (one service = one file).
* 매입 오류유형별 조회: 사유 접두어(T_REASON)로 시작하는 미매입 건을
* 패턴 조회해 해당 오류유형의 건수를 응답한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_ERRQRY.h"
void ACQ_ERRQRY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char pat[64];
EXEC SQL BEGIN DECLARE SECTION;
long h_n = 0;
char h_like[70];
EXEC SQL END DECLARE SECTION;
gets_(b, T_REASON, pat, sizeof(pat));
if (pat[0] == 0) strcpy(pat, "DUP");
snprintf(h_like, sizeof(h_like), "%s%%", pat);
EXEC SQL SELECT count(*) INTO :h_n FROM ac_unmatch WHERE reason LIKE :h_like;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_COUNT, h_n);
setl(b, T_RC, h_n > 0 ? 0 : 1);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_ERRRETRY.h - ac ACQ_ERRRETRY (copybook / record header).
* : (H) (A)
*/
#ifndef ACQ_ERRRETRY_H
#define ACQ_ERRRETRY_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
long affected;
long rc;
} acq_errretry_rec_t;
void ACQ_ERRRETRY(TPSVCINFO *p);
#endif /* ACQ_ERRRETRY_H */

View file

@ -0,0 +1,25 @@
/*
* ACQ_ERRRETRY.pgc - ac 모듈 서비스 ACQ_ERRRETRY (one service = one file).
* 매입 오류 재처리: 보류(H) 상태로 묶여 있던 오류 매입을 접수(A)로 되돌려
* 재처리 큐에 태우고 반영 건수를 결과코드로 응답한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_ERRRETRY.h"
void ACQ_ERRRETRY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_pid, h_aff;
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
EXEC SQL UPDATE purchase SET status = 'A', updated_at = now()
WHERE purchase_id = :h_pid AND status = 'H';
if (sqlca.sqlcode < 0) { userlog("ACQ_ERRRETRY FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); FAIL(b); }
h_aff = sqlca.sqlerrd[2];
if (h_aff > 0) Bchg(b, T_STATUS, 0, "A", 0L);
setl(b, T_RC, h_aff > 0 ? 0 : 1);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_ERRSTAT.h - ac ACQ_ERRSTAT (copybook / record header).
* :
*/
#ifndef ACQ_ERRSTAT_H
#define ACQ_ERRSTAT_H
#include "ac_svc.h"
typedef struct {
long dup;
long limit;
long fx;
} acq_errstat_rec_t;
void ACQ_ERRSTAT(TPSVCINFO *p);
#endif /* ACQ_ERRSTAT_H */

View file

@ -0,0 +1,30 @@
/*
* ACQ_ERRSTAT.pgc - ac 모듈 서비스 ACQ_ERRSTAT (one service = one file).
* 매입 오류유형별 통계: 미매입 원장을 사유 접두어 기준으로 한 번의 집계에서
* 중복/한도/환율 오류 건수를 FILTER 로 분해해 동시에 응답한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_ERRSTAT.h"
void ACQ_ERRSTAT(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_dup = 0, h_lim = 0, h_fx = 0, h_all = 0;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL SELECT count(*) FILTER (WHERE reason LIKE 'DUP%'),
count(*) FILTER (WHERE reason LIKE 'LIMIT%'),
count(*) FILTER (WHERE reason LIKE 'FX%'), count(*)
INTO :h_dup, :h_lim, :h_fx, :h_all FROM ac_unmatch WHERE biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_ARG1, h_dup);
setl(b, T_ARG2, h_lim);
setl(b, T_ARG3, h_fx);
setl(b, T_COUNT, h_all);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_ESCROW.h - ac ACQ_ESCROW (copybook / record header).
* :
*/
#ifndef ACQ_ESCROW_H
#define ACQ_ESCROW_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
long ledger_id;
long amount;
} acq_escrow_rec_t;
void ACQ_ESCROW(TPSVCINFO *p);
#endif /* ACQ_ESCROW_H */

View file

@ -0,0 +1,31 @@
/*
* ACQ_ESCROW.pgc - ac 모듈 서비스 ACQ_ESCROW (one service = one file).
* 매입 에스크로 예치: 분쟁 소지 매입 금액을 정산 전 유보하기 위해 원장에
* ESCROW 항목으로 예치액을 적립한다. 금액이 0 이하면 거절.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_ESCROW.h"
void ACQ_ESCROW(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_pid, h_amt, h_lid;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
h_amt = getl(b, T_AMOUNT);
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
if (h_amt <= 0) { setl(b, T_RC, 3); FAIL(b); }
EXEC SQL SELECT nextval('ledger_seq') INTO :h_lid;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL INSERT INTO ledger (ledger_id, purchase_id, entry_type, amount, biz_date)
VALUES (:h_lid, :h_pid, 'ESCROW', :h_amt, :h_bizdate);
if (sqlca.sqlcode < 0) { userlog("ACQ_ESCROW FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); FAIL(b); }
setl(b, T_SETTLE_ID, h_lid);
setl(b, T_RC, 0);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_ESCROWREL.h - ac ACQ_ESCROWREL (copybook / record header).
* : (ESCROW) (ESCROW_REL)
*/
#ifndef ACQ_ESCROWREL_H
#define ACQ_ESCROWREL_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
long balance;
long rc;
} acq_escrowrel_rec_t;
void ACQ_ESCROWREL(TPSVCINFO *p);
#endif /* ACQ_ESCROWREL_H */

View file

@ -0,0 +1,36 @@
/*
* ACQ_ESCROWREL.pgc - ac 모듈 서비스 ACQ_ESCROWREL (one service = one file).
* 매입 에스크로 해제: 예치(ESCROW)와 해제(ESCROW_REL) 원장 잔액을 계산해
* 잔여 예치금을 해제 항목으로 전액 반제하고 잔액을 0 으로 만든다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_ESCROWREL.h"
void ACQ_ESCROWREL(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_pid, h_esc = 0, h_rel = 0, h_lid, h_bal;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL SELECT coalesce(sum(amount) FILTER (WHERE entry_type = 'ESCROW'),0),
coalesce(sum(amount) FILTER (WHERE entry_type = 'ESCROW_REL'),0)
INTO :h_esc, :h_rel FROM ledger WHERE purchase_id = :h_pid;
if (sqlca.sqlcode < 0) FAIL(b);
h_bal = h_esc - h_rel;
if (h_bal <= 0) { setl(b, T_GROSS, 0); setl(b, T_RC, 1); OK(b); }
EXEC SQL SELECT nextval('ledger_seq') INTO :h_lid;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL INSERT INTO ledger (ledger_id, purchase_id, entry_type, amount, biz_date)
VALUES (:h_lid, :h_pid, 'ESCROW_REL', :h_bal, :h_bizdate);
if (sqlca.sqlcode < 0) { userlog("ACQ_ESCROWREL FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); FAIL(b); }
setl(b, T_GROSS, h_bal);
setl(b, T_RC, 0);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_EVENTBUY.h - ac ACQ_EVENTBUY (copybook / record header).
* : EVENT .
*/
#ifndef ACQ_EVENTBUY_H
#define ACQ_EVENTBUY_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
long fee;
long net;
} acq_eventbuy_rec_t;
void ACQ_EVENTBUY(TPSVCINFO *p);
#endif /* ACQ_EVENTBUY_H */

View file

@ -0,0 +1,41 @@
/*
* ACQ_EVENTBUY.pgc - ac 모듈 서비스 ACQ_EVENTBUY (one service = one file).
* 이벤트 매입: 프로모션 행사 매입을 EVENT 채널로 접수한다. 활성 가맹점만
* 허용하며 이벤트 할인율(T_ARG1, bps)만큼 수수료를 감면해 net 을 올린다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_EVENTBUY.h"
void ACQ_EVENTBUY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long fee, disc;
EXEC SQL BEGIN DECLARE SECTION;
long h_pid, h_amt, h_bps = 0, h_disc, h_fee, h_net;
char h_merch[64], h_mst[16], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
h_amt = getl(b, T_AMOUNT);
disc = getl(b, T_ARG1); if (disc < 0) disc = 0;
gets_(b, T_MERCHANT, h_merch, sizeof(h_merch));
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
if (h_amt <= 0) { setl(b, T_RC, 3); FAIL(b); }
EXEC SQL SELECT status, mdr_bps INTO :h_mst, :h_bps FROM merchant WHERE merchant_id = :h_merch;
if (sqlca.sqlcode == 100) { setl(b, T_RC, 5); FAIL(b); }
if (sqlca.sqlcode < 0) FAIL(b);
if (strcmp(h_mst, "ACTIVE") != 0) { setl(b, T_RC, 6); FAIL(b); }
h_disc = (h_bps > disc) ? h_bps - disc : 0;
fee = h_amt * h_disc / 10000; h_fee = fee; h_net = h_amt - fee;
EXEC SQL SELECT nextval('purchase_seq') INTO :h_pid;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL INSERT INTO purchase (purchase_id, merchant_id, amount, fee, net, status, biz_date, channel, category)
VALUES (:h_pid, :h_merch, :h_amt, :h_fee, :h_net, 'A', :h_bizdate, 'EVENT', 'PROMO');
if (sqlca.sqlcode < 0) { userlog("ACQ_EVENTBUY FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); FAIL(b); }
setl(b, T_PURCHASE_ID, h_pid);
setl(b, T_FEE, h_fee);
setl(b, T_RC, 0);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_EXCHANGE.h - ac ACQ_EXCHANGE (copybook / record header).
* : .
*/
#ifndef ACQ_EXCHANGE_H
#define ACQ_EXCHANGE_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
long cancel_id;
long amount;
} acq_exchange_rec_t;
void ACQ_EXCHANGE(TPSVCINFO *p);
#endif /* ACQ_EXCHANGE_H */

View file

@ -0,0 +1,38 @@
/*
* ACQ_EXCHANGE.pgc - ac 모듈 서비스 ACQ_EXCHANGE (one service = one file).
* 매입 교환 처리: 반품 후 동일가 재구매를 한 번에 처리한다. 원매입에 대해
* EXCHANGE 취소 행을 남기고 원매입 상태를 대사완료(M)로 유지한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_EXCHANGE.h"
void ACQ_EXCHANGE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char why[80];
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_pid, h_amt, h_orig = 0;
char h_reason[100], h_st[4], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
h_amt = getl(b, T_AMOUNT);
gets_(b, T_REASON, why, sizeof(why));
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL SELECT status, amount INTO :h_st, :h_orig FROM purchase WHERE purchase_id = :h_pid;
if (sqlca.sqlcode == 100) { setl(b, T_RC, 5); FAIL(b); }
if (sqlca.sqlcode < 0) FAIL(b);
if (h_amt <= 0 || h_amt > h_orig) { setl(b, T_RC, 3); FAIL(b); }
snprintf(h_reason, sizeof(h_reason), "EXCHANGE:%s", why[0] ? why : "SWAP");
EXEC SQL SELECT nextval('ac_cancel_seq') INTO :h_id;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL INSERT INTO ac_cancel (cancel_id, purchase_id, cancel_type, amount, reason, biz_date)
VALUES (:h_id, :h_pid, 'EXCHANGE', :h_amt, :h_reason, :h_bizdate);
if (sqlca.sqlcode < 0) { userlog("ACQ_EXCHANGE FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); FAIL(b); }
setl(b, T_CANCEL_ID, h_id);
setl(b, T_RC, 0);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_GRADESTAT.h - ac ACQ_GRADESTAT (copybook / record header).
* : MDR(bps) //
*/
#ifndef ACQ_GRADESTAT_H
#define ACQ_GRADESTAT_H
#include "ac_svc.h"
typedef struct {
long grades[3];
long gross;
long rc;
} acq_gradestat_rec_t;
void ACQ_GRADESTAT(TPSVCINFO *p);
#endif /* ACQ_GRADESTAT_H */

View file

@ -0,0 +1,47 @@
/*
* ACQ_GRADESTAT.pgc - ac 모듈 서비스 ACQ_GRADESTAT (one service = one file).
* 매입 가맹점등급별 통계: 가맹점 MDR(bps)을 프리미엄/일반/기본 등급으로 나눠
* 등급별 매출 합계를 버킷 집계한다. 등급 경계는 C 분류기로 판정한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_GRADESTAT.h"
/* MDR(bps) → 등급 (0=프리미엄 1=일반 2=기본) */
static int ac_grade(long bps)
{
if (bps <= 20) return 0;
if (bps <= 28) return 1;
return 2;
}
void ACQ_GRADESTAT(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long g[3] = {0, 0, 0};
EXEC SQL BEGIN DECLARE SECTION;
long h_bps, h_sum;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
EXEC SQL DECLARE grd_cur CURSOR FOR
SELECT m.mdr_bps, coalesce(sum(p.amount),0) FROM merchant m
JOIN purchase p ON p.merchant_id = m.merchant_id AND p.biz_date = :h_bizdate
GROUP BY m.merchant_id, m.mdr_bps;
EXEC SQL OPEN grd_cur;
if (sqlca.sqlcode < 0) FAIL(b);
for (;;) {
EXEC SQL FETCH grd_cur INTO :h_bps, :h_sum;
if (sqlca.sqlcode == 100) break;
if (sqlca.sqlcode < 0) { EXEC SQL CLOSE grd_cur; FAIL(b); }
g[ac_grade(h_bps)] += h_sum;
}
EXEC SQL CLOSE grd_cur;
setl(b, T_ARG1, g[0]);
setl(b, T_ARG2, g[1]);
setl(b, T_ARG3, g[2]);
setl(b, T_GROSS, g[0] + g[1] + g[2]);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_GUARANTEE.h - ac ACQ_GUARANTEE (copybook / record header).
* : GUARANTEE
*/
#ifndef ACQ_GUARANTEE_H
#define ACQ_GUARANTEE_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
long guarantee;
long ledger_id;
} acq_guarantee_rec_t;
void ACQ_GUARANTEE(TPSVCINFO *p);
#endif /* ACQ_GUARANTEE_H */

View file

@ -0,0 +1,34 @@
/*
* ACQ_GUARANTEE.pgc - ac 모듈 서비스 ACQ_GUARANTEE (one service = one file).
* 매입 보증 등록: 대형 매입에 대한 이행보증금을 원장에 GUARANTEE 항목으로
* 적립한다. 보증률(T_ARG1, bps)로 보증금을 산출하며 기본 10%.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_GUARANTEE.h"
void ACQ_GUARANTEE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_pid, h_amt, h_bps, h_lid, h_guar;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
h_amt = getl(b, T_AMOUNT);
h_bps = getl(b, T_ARG1); if (h_bps <= 0) h_bps = 1000;
gets_(b, T_BIZDATE, h_bizdate, sizeof(h_bizdate));
h_guar = h_amt * h_bps / 10000;
if (h_guar <= 0) { setl(b, T_RC, 3); FAIL(b); }
EXEC SQL SELECT nextval('ledger_seq') INTO :h_lid;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL INSERT INTO ledger (ledger_id, purchase_id, entry_type, amount, biz_date)
VALUES (:h_lid, :h_pid, 'GUARANTEE', :h_guar, :h_bizdate);
if (sqlca.sqlcode < 0) { userlog("ACQ_GUARANTEE FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); FAIL(b); }
setl(b, T_AMT1, h_guar);
setl(b, T_SETTLE_ID, h_lid);
setl(b, T_RC, 0);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_GUARQRY.h - ac ACQ_GUARQRY (copybook / record header).
* : (GUARANTEE)
*/
#ifndef ACQ_GUARQRY_H
#define ACQ_GUARQRY_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
long guarantee;
long count;
} acq_guarqry_rec_t;
void ACQ_GUARQRY(TPSVCINFO *p);
#endif /* ACQ_GUARQRY_H */

View file

@ -0,0 +1,26 @@
/*
* ACQ_GUARQRY.pgc - ac 모듈 서비스 ACQ_GUARQRY (one service = one file).
* 매입 보증 조회: 한 매입에 적립된 보증금(GUARANTEE) 총액과 건수를 원장에서
* 조회해 응답한다. 보증 이력이 없으면 결과코드 1.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_GUARQRY.h"
void ACQ_GUARQRY(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_pid, h_sum = 0, h_n = 0;
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
EXEC SQL SELECT coalesce(sum(amount),0), count(*) INTO :h_sum, :h_n
FROM ledger WHERE purchase_id = :h_pid AND entry_type = 'GUARANTEE';
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_AMT1, h_sum);
setl(b, T_COUNT, h_n);
setl(b, T_RC, h_n > 0 ? 0 : 1);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_HALFSTAT.h - ac ACQ_HALFSTAT (copybook / record header).
* : (T_ARG1) (1~6)/(7~12)
*/
#ifndef ACQ_HALFSTAT_H
#define ACQ_HALFSTAT_H
#include "ac_svc.h"
typedef struct {
long h1;
long h2;
long share;
} acq_halfstat_rec_t;
void ACQ_HALFSTAT(TPSVCINFO *p);
#endif /* ACQ_HALFSTAT_H */

View file

@ -0,0 +1,32 @@
/*
* ACQ_HALFSTAT.pgc - ac 모듈 서비스 ACQ_HALFSTAT (one service = one file).
* 매입 반기별 통계: 지정 연도(T_ARG1) 매입을 상반기(1~6월)/하반기(7~12월)로
* 나눠 반기별 매출과 건수를 산출하고 상반기 비중을 계산한다.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_HALFSTAT.h"
void ACQ_HALFSTAT(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long share = 0, total;
EXEC SQL BEGIN DECLARE SECTION;
long h_h1 = 0, h_h2 = 0, h_n = 0;
int h_yr;
EXEC SQL END DECLARE SECTION;
h_yr = (int)getl(b, T_ARG1); if (h_yr < 2000) h_yr = 2026;
EXEC SQL SELECT coalesce(sum(amount) FILTER (WHERE extract(month from biz_date) <= 6),0),
coalesce(sum(amount) FILTER (WHERE extract(month from biz_date) > 6),0), count(*)
INTO :h_h1, :h_h2, :h_n FROM purchase WHERE extract(year from biz_date) = :h_yr;
if (sqlca.sqlcode < 0) FAIL(b);
total = h_h1 + h_h2;
if (total > 0) share = h_h1 * 100 / total;
setl(b, T_ARG2, h_h1);
setl(b, T_ARG3, h_h2);
setl(b, T_COUNT, h_n);
setl(b, T_RC, share);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_HOURSTAT.h - ac ACQ_HOURSTAT (copybook / record header).
* : ///
*/
#ifndef ACQ_HOURSTAT_H
#define ACQ_HOURSTAT_H
#include "ac_svc.h"
typedef struct {
long bands[4];
long peak;
long rc;
} acq_hourstat_rec_t;
void ACQ_HOURSTAT(TPSVCINFO *p);
#endif /* ACQ_HOURSTAT_H */

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