Phase 2c-1: ac 모듈 per-service 분해 (1서비스=1파일+카피북) + build.sh 이중스타일

- app/src/ac/svc/: 30 서비스 .pgc + 31 카피북 .h (각 typedef struct + prototype)
- ac_svr.pgc = 얇은 디스패처(advertise 테이블만)
- build.sh: src/<mod>/svc/*.pgc → lib<mod>svc.a 링크, inline/split 자동판별
- ac dbio 25 + batch 17 + run 17 스크립트
- 고유도: svc 30/30, dbio 25/25 (정규화 md5, 클론 0)
- 검증: 12서버 runok, 333 서비스, 매입체인 XA 커밋, prepared_xacts=0

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
forge-bot 2026-07-19 11:30:03 +00:00
parent bec83c721e
commit c3b99a8b75
139 changed files with 3363 additions and 653 deletions

24
app/src/ac/svc/ACQUIRE.h Normal file
View file

@ -0,0 +1,24 @@
/*
* ACQUIRE.h - ac ACQUIRE (copybook / record header).
* Request fields: T_MERCHANT, T_AMOUNT, T_BIZDATE
* Response fields: T_PURCHASE_ID, T_FEE, T_NET, T_STATUS
*/
#ifndef ACQUIRE_H
#define ACQUIRE_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
char merchant_id[64];
long amount;
long fee;
long net;
char status[8];
char channel[16];
char biz_date[16];
} ac_acquire_rec_t;
void ACQUIRE(TPSVCINFO *p);
#endif /* ACQUIRE_H */

View file

@ -0,0 +1,45 @@
/*
* ACQUIRE.pgc - ac 모듈 서비스 ACQUIRE (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQUIRE.h"
void ACQUIRE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
long amount, bps = 25, fee, net, pid, rlen = 0;
gets_(b, T_MERCHANT, merch, sizeof(merch));
if (merch[0] == 0) { userlog("ACQUIRE: missing T_MERCHANT"); FAIL(b); }
amount = getl(b, T_AMOUNT);
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
if (acdb_merchant_mdr(merch, &bps) < 0) bps = 25; /* keep 25bps default */
fee = acq_fee(amount, bps);
net = amount - fee;
pid = acdb_next_purchase_id();
if (pid < 0) FAIL(b);
if (acdb_insert_purchase(pid, merch, amount, fee, net, "A", "POS", bizdate) < 0) FAIL(b);
if (acdb_insert_approval(pid, 1) < 0) FAIL(b);
setl(b, T_PURCHASE_ID, pid);
setl(b, T_FEE, fee);
setl(b, T_NET, net);
Bchg(b, T_STATUS, 0, "A", 0L);
userlog("ACQUIRE pid=%ld merch=%s amount=%ld fee=%ld net=%ld -> RECONCILE",
pid, merch, amount, fee, net);
/* continue the SAME global tx into rc_svr (distinct branch) */
if (tpcall("RECONCILE", (char *)b, 0L, (char **)&b, &rlen, 0L) < 0) {
userlog("ACQUIRE: tpcall(RECONCILE) FAIL: %s", tpstrerror(tperrno));
FAIL(b);
}
/* our branch resumes: settle-complete the purchase we own */
if (acdb_update_status(pid, "S") < 0) FAIL(b);
Bchg(b, T_STATUS, 0, "S", 0L);
OK(b);
}

View file

@ -0,0 +1,21 @@
/*
* ACQ_AMTFIX.h - ac ACQ_AMTFIX (copybook / record header).
* Request fields: T_PURCHASE_ID, T_AMOUNT, T_MERCHANT
* Response fields: T_FEE, T_NET
*/
#ifndef ACQ_AMTFIX_H
#define ACQ_AMTFIX_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
char merchant_id[64];
long amount;
long fee;
long net;
} ac_amtfix_rec_t;
void ACQ_AMTFIX(TPSVCINFO *p);
#endif /* ACQ_AMTFIX_H */

View file

@ -0,0 +1,31 @@
/*
* ACQ_AMTFIX.pgc - ac 모듈 서비스 ACQ_AMTFIX (one service = one file).
* 금액 확정 정정: 직전 금액 조회 후 하우스 25bps 로 절대 재계산, 증감(delta) 회신.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_AMTFIX.h"
void ACQ_AMTFIX(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long amount, fee, net;
EXEC SQL BEGIN DECLARE SECTION;
long h_pid, h_old = 0, h_amount, h_fee, h_net;
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
amount = getl(b, T_AMOUNT);
/* absolute fix: read prior amount, recompute fee at flat house 25bps (no MDR lookup) */
EXEC SQL SELECT amount INTO :h_old FROM purchase WHERE purchase_id = :h_pid;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
fee = acq_fee(amount, 25);
net = amount - fee;
h_amount = amount; h_fee = fee; h_net = net;
EXEC SQL UPDATE purchase SET amount = :h_amount, fee = :h_fee, net = :h_net, updated_at = now()
WHERE purchase_id = :h_pid;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
setl(b, T_DELTA, amount - h_old);
setl(b, T_FEE, fee);
setl(b, T_NET, net);
OK(b);
}

View file

@ -0,0 +1,19 @@
/*
* ACQ_APPRLINK.h - ac ACQ_APPRLINK (copybook / record header).
* Request fields: T_PURCHASE_ID
* Response fields: (none)
*/
#ifndef ACQ_APPRLINK_H
#define ACQ_APPRLINK_H
#include "ac_svc.h"
typedef struct {
long approval_id;
long purchase_id;
int approved;
} ac_apprlink_rec_t;
void ACQ_APPRLINK(TPSVCINFO *p);
#endif /* ACQ_APPRLINK_H */

View file

@ -0,0 +1,14 @@
/*
* ACQ_APPRLINK.pgc - ac 모듈 서비스 ACQ_APPRLINK (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_APPRLINK.h"
void ACQ_APPRLINK(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long pid = getl(b, T_PURCHASE_ID);
if (acdb_insert_approval(pid, 1) < 0) FAIL(b);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_APPRMAP.h - ac ACQ_APPRMAP (copybook / record header).
* Request fields: T_PURCHASE_ID
* Response fields: T_COUNT
*/
#ifndef ACQ_APPRMAP_H
#define ACQ_APPRMAP_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
long count;
} ac_apprmap_rec_t;
void ACQ_APPRMAP(TPSVCINFO *p);
#endif /* ACQ_APPRMAP_H */

View file

@ -0,0 +1,19 @@
/*
* ACQ_APPRMAP.pgc - ac 모듈 서비스 ACQ_APPRMAP (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_APPRMAP.h"
void ACQ_APPRMAP(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_pid, h_cnt;
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
EXEC SQL SELECT count(*) INTO :h_cnt FROM approval WHERE purchase_id = :h_pid;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_COUNT, h_cnt);
OK(b);
}

View file

@ -0,0 +1,22 @@
/*
* ACQ_CANCEL.h - ac ACQ_CANCEL (copybook / record header).
* Request fields: T_PURCHASE_ID, T_AMOUNT, T_BIZDATE, T_REASON
* Response fields: T_CANCEL_ID, T_STATUS
*/
#ifndef ACQ_CANCEL_H
#define ACQ_CANCEL_H
#include "ac_svc.h"
typedef struct {
long cancel_id;
long purchase_id;
char cancel_type[8];
long amount;
char reason[128];
char biz_date[16];
} ac_cancel_rec_t;
void ACQ_CANCEL(TPSVCINFO *p);
#endif /* ACQ_CANCEL_H */

View file

@ -0,0 +1,33 @@
/*
* ACQ_CANCEL.pgc - ac 모듈 서비스 ACQ_CANCEL (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_CANCEL.h"
void ACQ_CANCEL(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16], reason[128];
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_pid, h_amt;
char h_bizdate[16], h_reason[128];
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
h_amt = getl(b, T_AMOUNT);
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
gets_(b, T_REASON, reason, sizeof(reason)); if (reason[0] == 0) strcpy(reason, "CUSTOMER");
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
strncpy(h_reason, reason, sizeof(h_reason)-1); h_reason[sizeof(h_reason)-1] = 0;
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, 'FULL', :h_amt, :h_reason, :h_bizdate);
if (sqlca.sqlcode < 0) FAIL(b);
if (acdb_update_status(h_pid, "C") < 0) FAIL(b);
setl(b, T_CANCEL_ID, h_id);
Bchg(b, T_STATUS, 0, "C", 0L);
OK(b);
}

View file

@ -0,0 +1,21 @@
/*
* ACQ_CORRECT.h - ac ACQ_CORRECT (copybook / record header).
* Request fields: T_PURCHASE_ID, T_AMOUNT, T_MERCHANT
* Response fields: T_FEE, T_NET
*/
#ifndef ACQ_CORRECT_H
#define ACQ_CORRECT_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
char merchant_id[64];
long amount;
long fee;
long net;
} ac_correct_rec_t;
void ACQ_CORRECT(TPSVCINFO *p);
#endif /* ACQ_CORRECT_H */

View file

@ -0,0 +1,20 @@
/*
* ACQ_CORRECT.pgc - ac 모듈 서비스 ACQ_CORRECT (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_CORRECT.h"
void ACQ_CORRECT(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64];
long pid, amount, bps = 25, fee, net;
pid = getl(b, T_PURCHASE_ID); amount = getl(b, T_AMOUNT);
gets_(b, T_MERCHANT, merch, sizeof(merch));
if (merch[0] && acdb_merchant_mdr(merch, &bps) < 0) bps = 25;
fee = acq_fee(amount, bps); net = amount - fee;
if (acdb_update_amount(pid, amount, fee, net) < 0) FAIL(b);
setl(b, T_FEE, fee); setl(b, T_NET, net);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_DATECHG.h - ac ACQ_DATECHG (copybook / record header).
* Request fields: T_PURCHASE_ID, T_BIZDATE
* Response fields: (none)
*/
#ifndef ACQ_DATECHG_H
#define ACQ_DATECHG_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
char biz_date[16];
} ac_datechg_rec_t;
void ACQ_DATECHG(TPSVCINFO *p);
#endif /* ACQ_DATECHG_H */

View file

@ -0,0 +1,22 @@
/*
* ACQ_DATECHG.pgc - ac 모듈 서비스 ACQ_DATECHG (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_DATECHG.h"
void ACQ_DATECHG(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_pid;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL UPDATE purchase SET biz_date = :h_bizdate, updated_at = now() WHERE purchase_id = :h_pid;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
OK(b);
}

23
app/src/ac/svc/ACQ_DDC.h Normal file
View file

@ -0,0 +1,23 @@
/*
* ACQ_DDC.h - ac ACQ_DDC (copybook / record header).
* Request fields: T_PURCHASE_ID, T_FX_AMT, T_CCY, T_BIZDATE
* Response fields: T_AMOUNT
*/
#ifndef ACQ_DDC_H
#define ACQ_DDC_H
#include "ac_svc.h"
typedef struct {
long fx_id;
long purchase_id;
char ccy[8];
long fx_amount;
long krw_amount;
long rate_bps;
char biz_date[16];
} ac_ddc_rec_t;
void ACQ_DDC(TPSVCINFO *p);
#endif /* ACQ_DDC_H */

View file

@ -0,0 +1,33 @@
/*
* ACQ_DDC.pgc - ac 모듈 서비스 ACQ_DDC (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_DDC.h"
void ACQ_DDC(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16], ccy[8];
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_pid, h_fx, h_krw, h_rate;
char h_ccy[8], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
h_fx = getl(b, T_FX_AMT);
gets_(b, T_CCY, ccy, sizeof(ccy)); if (ccy[0] == 0) strcpy(ccy, "USD");
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
h_rate = 1350; /* 13.50 KRW per unit (bps of 100) */
h_krw = h_fx * h_rate / 100;
strncpy(h_ccy, ccy, sizeof(h_ccy)-1); h_ccy[sizeof(h_ccy)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT nextval('ac_fx_seq') INTO :h_id;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL INSERT INTO ac_fx (fx_id, purchase_id, ccy, fx_amount, krw_amount, rate_bps, biz_date)
VALUES (:h_id, :h_pid, :h_ccy, :h_fx, :h_krw, :h_rate, :h_bizdate);
if (sqlca.sqlcode < 0) { userlog("ACQ_DDC INSERT FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); FAIL(b); }
setl(b, T_AMOUNT, h_krw);
OK(b);
}

View file

@ -0,0 +1,20 @@
/*
* ACQ_DUPCHK.h - ac ACQ_DUPCHK (copybook / record header).
* Request fields: T_MERCHANT, T_AMOUNT, T_BIZDATE
* Response fields: T_COUNT
*/
#ifndef ACQ_DUPCHK_H
#define ACQ_DUPCHK_H
#include "ac_svc.h"
typedef struct {
char merchant_id[64];
long amount;
char biz_date[16];
long count;
} ac_dupchk_rec_t;
void ACQ_DUPCHK(TPSVCINFO *p);
#endif /* ACQ_DUPCHK_H */

View file

@ -0,0 +1,26 @@
/*
* ACQ_DUPCHK.pgc - ac 모듈 서비스 ACQ_DUPCHK (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_DUPCHK.h"
void ACQ_DUPCHK(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_cnt, h_amt;
char h_merch[64], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
h_amt = getl(b, T_AMOUNT);
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT count(*) INTO :h_cnt FROM purchase
WHERE merchant_id = :h_merch AND amount = :h_amt AND biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_COUNT, h_cnt);
OK(b);
}

22
app/src/ac/svc/ACQ_EDC.h Normal file
View file

@ -0,0 +1,22 @@
/*
* ACQ_EDC.h - ac ACQ_EDC (copybook / record header).
* Request fields: T_MERCHANT, T_AMOUNT, T_BIZDATE
* Response fields: T_PURCHASE_ID, T_FEE, T_NET
*/
#ifndef ACQ_EDC_H
#define ACQ_EDC_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
char merchant_id[64];
long amount;
long fee;
long net;
char biz_date[16];
} ac_edc_rec_t;
void ACQ_EDC(TPSVCINFO *p);
#endif /* ACQ_EDC_H */

View file

@ -0,0 +1,25 @@
/*
* ACQ_EDC.pgc - ac 모듈 서비스 ACQ_EDC (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_EDC.h"
void ACQ_EDC(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
long amount, bps = 25, fee, net, pid;
gets_(b, T_MERCHANT, merch, sizeof(merch));
amount = getl(b, T_AMOUNT);
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
if (acdb_merchant_mdr(merch, &bps) < 0) bps = 25;
fee = acq_fee(amount, bps); net = amount - fee;
pid = acdb_next_purchase_id();
if (pid < 0) FAIL(b);
if (acdb_insert_purchase(pid, merch, amount, fee, net, "A", "EDC", bizdate) < 0) FAIL(b);
if (acdb_insert_approval(pid, 1) < 0) FAIL(b);
setl(b, T_PURCHASE_ID, pid); setl(b, T_FEE, fee); setl(b, T_NET, net);
OK(b);
}

21
app/src/ac/svc/ACQ_EDI.h Normal file
View file

@ -0,0 +1,21 @@
/*
* ACQ_EDI.h - ac ACQ_EDI (copybook / record header).
* Request fields: T_MERCHANT, T_DOCNO, T_AMOUNT, T_BIZDATE
* Response fields: (none)
*/
#ifndef ACQ_EDI_H
#define ACQ_EDI_H
#include "ac_svc.h"
typedef struct {
long edi_id;
char merchant_id[64];
char doc_no[32];
long amount;
char biz_date[16];
} ac_edi_rec_t;
void ACQ_EDI(TPSVCINFO *p);
#endif /* ACQ_EDI_H */

View file

@ -0,0 +1,31 @@
/*
* ACQ_EDI.pgc - ac 모듈 서비스 ACQ_EDI (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_EDI.h"
void ACQ_EDI(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], docno[32], bizdate[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_amount;
char h_merch[64], h_doc[32], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_DOCNO, docno, sizeof(docno)); if (docno[0] == 0) strcpy(docno, "EDI-AUTO");
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
h_amount = getl(b, T_AMOUNT);
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
strncpy(h_doc, docno, sizeof(h_doc)-1); h_doc[sizeof(h_doc)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT nextval('ac_edi_seq') INTO :h_id;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL INSERT INTO ac_edi (edi_id, merchant_id, doc_no, amount, biz_date)
VALUES (:h_id, :h_merch, :h_doc, :h_amount, :h_bizdate);
if (sqlca.sqlcode < 0) { userlog("ACQ_EDI INSERT FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); FAIL(b); }
OK(b);
}

View file

@ -0,0 +1,21 @@
/*
* ACQ_FEEADJ.h - ac ACQ_FEEADJ (copybook / record header).
* Request fields: T_PURCHASE_ID, T_DELTA, T_BIZDATE, T_REASON
* Response fields: T_ADJ
*/
#ifndef ACQ_FEEADJ_H
#define ACQ_FEEADJ_H
#include "ac_svc.h"
typedef struct {
long adj_id;
long purchase_id;
long delta;
char reason[128];
char biz_date[16];
} ac_feeadj_rec_t;
void ACQ_FEEADJ(TPSVCINFO *p);
#endif /* ACQ_FEEADJ_H */

View file

@ -0,0 +1,30 @@
/*
* ACQ_FEEADJ.pgc - ac 모듈 서비스 ACQ_FEEADJ (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_FEEADJ.h"
void ACQ_FEEADJ(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16], reason[128];
long pid, delta, adj;
EXEC SQL BEGIN DECLARE SECTION;
long e_pid, e_delta;
EXEC SQL END DECLARE SECTION;
pid = getl(b, T_PURCHASE_ID);
delta = getl(b, T_DELTA);
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
gets_(b, T_REASON, reason, sizeof(reason)); if (reason[0] == 0) strcpy(reason, "ADJ");
adj = acdb_insert_fee_adj(pid, delta, reason, bizdate);
if (adj < 0) FAIL(b);
e_pid = pid; e_delta = delta;
EXEC SQL UPDATE purchase SET fee = fee + :e_delta, net = net - :e_delta, updated_at = now()
WHERE purchase_id = :e_pid;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
setl(b, T_ADJ, adj);
OK(b);
}

View file

@ -0,0 +1,24 @@
/*
* ACQ_FOREIGN.h - ac ACQ_FOREIGN (copybook / record header).
* Request fields: T_MERCHANT, T_AMOUNT, T_BIZDATE, T_CCY
* Response fields: T_PURCHASE_ID, T_FEE
*/
#ifndef ACQ_FOREIGN_H
#define ACQ_FOREIGN_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
char merchant_id[64];
long amount;
long fee;
long net;
char ccy[8];
long fx_id;
char biz_date[16];
} ac_foreign_rec_t;
void ACQ_FOREIGN(TPSVCINFO *p);
#endif /* ACQ_FOREIGN_H */

View file

@ -0,0 +1,38 @@
/*
* ACQ_FOREIGN.pgc - ac 모듈 서비스 ACQ_FOREIGN (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_FOREIGN.h"
void ACQ_FOREIGN(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16], ccy[8];
long amount, bps = 30, fee, net, pid;
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_pid, h_fx, h_krw, h_rate;
char h_ccy[8], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_MERCHANT, merch, sizeof(merch));
amount = getl(b, T_AMOUNT);
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
gets_(b, T_CCY, ccy, sizeof(ccy)); if (ccy[0] == 0) strcpy(ccy, "USD");
if (acdb_merchant_mdr(merch, &bps) < 0) bps = 30;
fee = acq_fee(amount, bps); net = amount - fee;
pid = acdb_next_purchase_id();
if (pid < 0) FAIL(b);
if (acdb_insert_purchase(pid, merch, amount, fee, net, "A", "FOREIGN", bizdate) < 0) FAIL(b);
h_pid = pid; h_fx = amount; h_rate = 1350; h_krw = amount;
strncpy(h_ccy, ccy, sizeof(h_ccy)-1); h_ccy[sizeof(h_ccy)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT nextval('ac_fx_seq') INTO :h_id;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL INSERT INTO ac_fx (fx_id, purchase_id, ccy, fx_amount, krw_amount, rate_bps, biz_date)
VALUES (:h_id, :h_pid, :h_ccy, :h_fx, :h_krw, :h_rate, :h_bizdate);
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_PURCHASE_ID, pid); setl(b, T_FEE, fee);
OK(b);
}

18
app/src/ac/svc/ACQ_HOLD.h Normal file
View file

@ -0,0 +1,18 @@
/*
* ACQ_HOLD.h - ac ACQ_HOLD (copybook / record header).
* Request fields: T_PURCHASE_ID
* Response fields: T_STATUS
*/
#ifndef ACQ_HOLD_H
#define ACQ_HOLD_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
char status[8];
} ac_hold_rec_t;
void ACQ_HOLD(TPSVCINFO *p);
#endif /* ACQ_HOLD_H */

View file

@ -0,0 +1,24 @@
/*
* ACQ_HOLD.pgc - ac 모듈 서비스 ACQ_HOLD (one service = one file).
* 매입 보류: 접수/대사(A,M) 상태만 보류로 전이, 반영 건수를 T_RC 로.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_HOLD.h"
void ACQ_HOLD(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);
/* only an approved(A)/matched(M) purchase may be put on hold */
EXEC SQL UPDATE purchase SET status = 'H', updated_at = now()
WHERE purchase_id = :h_pid AND status IN ('A', 'M');
if (sqlca.sqlcode < 0) { userlog("ACQ_HOLD FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); FAIL(b); }
h_aff = sqlca.sqlerrd[2];
if (h_aff > 0) Bchg(b, T_STATUS, 0, "H", 0L);
setl(b, T_RC, h_aff > 0 ? 0 : 1);
OK(b);
}

View file

@ -0,0 +1,22 @@
/*
* ACQ_INSTALL.h - ac ACQ_INSTALL (copybook / record header).
* Request fields: T_PURCHASE_ID, T_INSTALL_N, T_AMOUNT, T_BIZDATE
* Response fields: T_COUNT
*/
#ifndef ACQ_INSTALL_H
#define ACQ_INSTALL_H
#include "ac_svc.h"
typedef struct {
long install_id;
long purchase_id;
long seq_no;
long months;
long month_amount;
char biz_date[16];
} ac_install_rec_t;
void ACQ_INSTALL(TPSVCINFO *p);
#endif /* ACQ_INSTALL_H */

View file

@ -0,0 +1,34 @@
/*
* ACQ_INSTALL.pgc - ac 모듈 서비스 ACQ_INSTALL (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_INSTALL.h"
void ACQ_INSTALL(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16];
long months, amount, i;
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_pid, h_seq, h_months, h_mamt;
char h_bizdate[16];
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
months = getl(b, T_INSTALL_N); if (months < 1) months = 3;
amount = getl(b, T_AMOUNT);
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
h_months = months; h_mamt = amount / months;
for (i = 1; i <= months; i++) {
h_seq = i;
EXEC SQL SELECT nextval('ac_install_seq') INTO :h_id;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL INSERT INTO ac_install (install_id, purchase_id, seq_no, months, month_amount, biz_date)
VALUES (:h_id, :h_pid, :h_seq, :h_months, :h_mamt, :h_bizdate);
if (sqlca.sqlcode < 0) FAIL(b);
}
setl(b, T_COUNT, months);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_ISSUERCLS.h - ac ACQ_ISSUERCLS (copybook / record header).
* Request fields: T_PURCHASE_ID, T_ISSUER
* Response fields: (none)
*/
#ifndef ACQ_ISSUERCLS_H
#define ACQ_ISSUERCLS_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
char issuer[32];
} ac_issuercls_rec_t;
void ACQ_ISSUERCLS(TPSVCINFO *p);
#endif /* ACQ_ISSUERCLS_H */

View file

@ -0,0 +1,22 @@
/*
* ACQ_ISSUERCLS.pgc - ac 모듈 서비스 ACQ_ISSUERCLS (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_ISSUERCLS.h"
void ACQ_ISSUERCLS(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char issuer[32];
EXEC SQL BEGIN DECLARE SECTION;
long h_pid;
char h_issuer[32];
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
gets_(b, T_ISSUER, issuer, sizeof(issuer)); if (issuer[0] == 0) strcpy(issuer, "BC");
strncpy(h_issuer, issuer, sizeof(h_issuer)-1); h_issuer[sizeof(h_issuer)-1] = 0;
EXEC SQL UPDATE purchase SET issuer = :h_issuer, updated_at = now() WHERE purchase_id = :h_pid;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
OK(b);
}

View file

@ -0,0 +1,21 @@
/*
* ACQ_LIMITCHK.h - ac ACQ_LIMITCHK (copybook / record header).
* Request fields: T_MERCHANT, T_BIZDATE
* Response fields: T_GROSS, T_RC
*/
#ifndef ACQ_LIMITCHK_H
#define ACQ_LIMITCHK_H
#include "ac_svc.h"
typedef struct {
char merchant_id[64];
char biz_date[16];
long gross;
long daily_limit;
long rc;
} ac_limitchk_rec_t;
void ACQ_LIMITCHK(TPSVCINFO *p);
#endif /* ACQ_LIMITCHK_H */

View file

@ -0,0 +1,28 @@
/*
* ACQ_LIMITCHK.pgc - ac 모듈 서비스 ACQ_LIMITCHK (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_LIMITCHK.h"
void ACQ_LIMITCHK(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_sum, h_lim;
char h_merch[64], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT coalesce(sum(amount),0) INTO :h_sum FROM purchase
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL SELECT daily_limit INTO :h_lim FROM merchant WHERE merchant_id = :h_merch;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
setl(b, T_GROSS, h_sum);
setl(b, T_RC, h_sum > h_lim ? 1 : 0);
OK(b);
}

View file

@ -0,0 +1,22 @@
/*
* ACQ_MERCHSUM.h - ac ACQ_MERCHSUM (copybook / record header).
* Request fields: T_MERCHANT, T_BIZDATE
* Response fields: T_COUNT, T_GROSS
*/
#ifndef ACQ_MERCHSUM_H
#define ACQ_MERCHSUM_H
#include "ac_svc.h"
typedef struct {
char merchant_id[64];
char biz_date[16];
long count;
long gross;
long fee;
long net;
} ac_merchsum_rec_t;
void ACQ_MERCHSUM(TPSVCINFO *p);
#endif /* ACQ_MERCHSUM_H */

View file

@ -0,0 +1,27 @@
/*
* ACQ_MERCHSUM.pgc - ac 모듈 서비스 ACQ_MERCHSUM (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_MERCHSUM.h"
void ACQ_MERCHSUM(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_cnt, h_gross, h_fee, h_net;
char h_merch[64], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT count(*), coalesce(sum(amount),0), coalesce(sum(fee),0), coalesce(sum(net),0)
INTO :h_cnt, :h_gross, :h_fee, :h_net FROM purchase
WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
if (sqlca.sqlcode < 0) FAIL(b);
if (acdb_upsert_merch_sum(merch, bizdate, h_gross, h_fee, h_net, h_cnt) < 0) FAIL(b);
setl(b, T_COUNT, h_cnt); setl(b, T_GROSS, h_gross);
OK(b);
}

View file

@ -0,0 +1,20 @@
/*
* ACQ_PARTIAL.h - ac ACQ_PARTIAL (copybook / record header).
* Request fields: T_PURCHASE_ID, T_AMOUNT, T_BIZDATE
* Response fields: T_CANCEL_ID
*/
#ifndef ACQ_PARTIAL_H
#define ACQ_PARTIAL_H
#include "ac_svc.h"
typedef struct {
long cancel_id;
long purchase_id;
long amount;
char biz_date[16];
} ac_partial_rec_t;
void ACQ_PARTIAL(TPSVCINFO *p);
#endif /* ACQ_PARTIAL_H */

View file

@ -0,0 +1,26 @@
/*
* ACQ_PARTIAL.pgc - ac 모듈 서비스 ACQ_PARTIAL (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_PARTIAL.h"
void ACQ_PARTIAL(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_pid, h_amt;
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, bizdate, sizeof(bizdate));
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
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, 'PARTIAL', :h_amt, 'PARTIAL', :h_bizdate);
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_CANCEL_ID, h_id);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_RECLASS.h - ac ACQ_RECLASS (copybook / record header).
* Request fields: T_PURCHASE_ID, T_CATEGORY
* Response fields: (none)
*/
#ifndef ACQ_RECLASS_H
#define ACQ_RECLASS_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
char category[32];
} ac_reclass_rec_t;
void ACQ_RECLASS(TPSVCINFO *p);
#endif /* ACQ_RECLASS_H */

View file

@ -0,0 +1,30 @@
/*
* ACQ_RECLASS.pgc - ac 모듈 서비스 ACQ_RECLASS (one service = one file).
* 업종/분류 재지정: category 갱신 후 같은 가맹점에서 동일 분류 건수를 집계 회신.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_RECLASS.h"
void ACQ_RECLASS(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char cat[32];
EXEC SQL BEGIN DECLARE SECTION;
long h_pid, h_cnt = 0;
char h_cat[32];
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
gets_(b, T_CATEGORY, cat, sizeof(cat)); if (cat[0] == 0) strcpy(cat, "GEN");
strncpy(h_cat, cat, sizeof(h_cat)-1); h_cat[sizeof(h_cat)-1] = 0;
EXEC SQL UPDATE purchase SET category = :h_cat, updated_at = now() WHERE purchase_id = :h_pid;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
/* how many of this merchant's purchases now carry the new 분류 */
EXEC SQL SELECT count(*) INTO :h_cnt FROM purchase
WHERE merchant_id = (SELECT merchant_id FROM purchase WHERE purchase_id = :h_pid)
AND category = :h_cat;
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_COUNT, h_cnt);
OK(b);
}

View file

@ -0,0 +1,21 @@
/*
* ACQ_REFUND.h - ac ACQ_REFUND (copybook / record header).
* Request fields: T_PURCHASE_ID, T_AMOUNT, T_BIZDATE, T_REASON
* Response fields: T_CANCEL_ID
*/
#ifndef ACQ_REFUND_H
#define ACQ_REFUND_H
#include "ac_svc.h"
typedef struct {
long cancel_id;
long purchase_id;
long amount;
char reason[128];
char biz_date[16];
} ac_refund_rec_t;
void ACQ_REFUND(TPSVCINFO *p);
#endif /* ACQ_REFUND_H */

View file

@ -0,0 +1,28 @@
/*
* ACQ_REFUND.pgc - ac 모듈 서비스 ACQ_REFUND (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_REFUND.h"
void ACQ_REFUND(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16], reason[128];
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_pid, h_amt;
char h_bizdate[16], h_reason[128];
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID); h_amt = getl(b, T_AMOUNT);
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
gets_(b, T_REASON, reason, sizeof(reason)); if (reason[0] == 0) strcpy(reason, "REFUND");
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
strncpy(h_reason, reason, sizeof(h_reason)-1); h_reason[sizeof(h_reason)-1] = 0;
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, 'REFUND', :h_amt, :h_reason, :h_bizdate);
if (sqlca.sqlcode < 0) FAIL(b);
setl(b, T_CANCEL_ID, h_id);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_RELEASE.h - ac ACQ_RELEASE (copybook / record header).
* Request fields: T_PURCHASE_ID
* Response fields: T_STATUS
*/
#ifndef ACQ_RELEASE_H
#define ACQ_RELEASE_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
char status[8];
} ac_release_rec_t;
void ACQ_RELEASE(TPSVCINFO *p);
#endif /* ACQ_RELEASE_H */

View file

@ -0,0 +1,27 @@
/*
* ACQ_RELEASE.pgc - ac 모듈 서비스 ACQ_RELEASE (one service = one file).
* 보류 해제: 직전 상태를 조회한 뒤 H->A 전이, 이전 상태를 함께 회신.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_RELEASE.h"
void ACQ_RELEASE(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
EXEC SQL BEGIN DECLARE SECTION;
long h_pid, h_aff;
char h_prev[8];
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
EXEC SQL SELECT status INTO :h_prev FROM purchase WHERE purchase_id = :h_pid;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
/* release only from HOLD; report whether the transition actually fired */
EXEC SQL UPDATE purchase SET status = 'A', updated_at = now()
WHERE purchase_id = :h_pid AND status = 'H';
if (sqlca.sqlcode < 0) FAIL(b);
h_aff = sqlca.sqlerrd[2];
Bchg(b, T_STATUS, 0, h_aff > 0 ? "A" : h_prev, 0L);
setl(b, T_RC, h_aff > 0 ? 0 : 1);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_REPROC.h - ac ACQ_REPROC (copybook / record header).
* Request fields: T_PURCHASE_ID
* Response fields: T_STATUS
*/
#ifndef ACQ_REPROC_H
#define ACQ_REPROC_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
char status[8];
} ac_reproc_rec_t;
void ACQ_REPROC(TPSVCINFO *p);
#endif /* ACQ_REPROC_H */

View file

@ -0,0 +1,15 @@
/*
* ACQ_REPROC.pgc - ac 모듈 서비스 ACQ_REPROC (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_REPROC.h"
void ACQ_REPROC(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long pid = getl(b, T_PURCHASE_ID);
if (acdb_update_status(pid, "A") < 0) FAIL(b);
Bchg(b, T_STATUS, 0, "A", 0L);
OK(b);
}

View file

@ -0,0 +1,19 @@
/*
* ACQ_SETTLELINK.h - ac ACQ_SETTLELINK (copybook / record header).
* Request fields: T_PURCHASE_ID, T_NET, T_BIZDATE
* Response fields: (none)
*/
#ifndef ACQ_SETTLELINK_H
#define ACQ_SETTLELINK_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
long net;
char biz_date[16];
} ac_settlelink_rec_t;
void ACQ_SETTLELINK(TPSVCINFO *p);
#endif /* ACQ_SETTLELINK_H */

View file

@ -0,0 +1,36 @@
/*
* ACQ_SETTLELINK.pgc - ac 모듈 서비스 ACQ_SETTLELINK (one service = one file).
* 정산 연계: 가맹점 미지정 시 매입에서 조회, settlement 링크 행(status='LINKED') 생성.
* Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
*/
#include "ACQ_SETTLELINK.h"
void ACQ_SETTLELINK(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_pid, h_net;
char h_merch[64], h_bizdate[16];
EXEC SQL END DECLARE SECTION;
h_pid = getl(b, T_PURCHASE_ID);
h_net = getl(b, T_NET);
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
if (merch[0] == 0) {
EXEC SQL SELECT merchant_id INTO :h_merch FROM purchase WHERE purchase_id = :h_pid;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
} else {
strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
}
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL SELECT nextval('settlement_seq') INTO :h_id;
if (sqlca.sqlcode < 0) FAIL(b);
EXEC SQL INSERT INTO settlement (settlement_id, purchase_id, merchant_id, net, biz_date, status)
VALUES (:h_id, :h_pid, :h_merch, :h_net, :h_bizdate, 'LINKED');
if (sqlca.sqlcode < 0) { userlog("ACQ_SETTLELINK FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); FAIL(b); }
setl(b, T_SETTLE_ID, h_id);
OK(b);
}

View file

@ -0,0 +1,18 @@
/*
* ACQ_STATUS.h - ac ACQ_STATUS (copybook / record header).
* Request fields: T_PURCHASE_ID
* Response fields: T_STATUS
*/
#ifndef ACQ_STATUS_H
#define ACQ_STATUS_H
#include "ac_svc.h"
typedef struct {
long purchase_id;
char status[8];
} ac_status_rec_t;
void ACQ_STATUS(TPSVCINFO *p);
#endif /* ACQ_STATUS_H */

View file

@ -0,0 +1,16 @@
/*
* ACQ_STATUS.pgc - ac 모듈 서비스 ACQ_STATUS (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_STATUS.h"
void ACQ_STATUS(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
long pid = getl(b, T_PURCHASE_ID);
char st[4];
if (acdb_get_status(pid, st) < 0) FAIL(b);
Bchg(b, T_STATUS, 0, st, 0L);
OK(b);
}

View file

@ -0,0 +1,22 @@
/*
* ACQ_TAXINV.h - ac ACQ_TAXINV (copybook / record header).
* Request fields: T_PURCHASE_ID, T_AMOUNT, T_MERCHANT, T_BIZDATE
* Response fields: T_TAX
*/
#ifndef ACQ_TAXINV_H
#define ACQ_TAXINV_H
#include "ac_svc.h"
typedef struct {
long inv_id;
long purchase_id;
char merchant_id[64];
long supply;
long vat;
char biz_date[16];
} ac_taxinv_rec_t;
void ACQ_TAXINV(TPSVCINFO *p);
#endif /* ACQ_TAXINV_H */

View file

@ -0,0 +1,22 @@
/*
* ACQ_TAXINV.pgc - ac 모듈 서비스 ACQ_TAXINV (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_TAXINV.h"
void ACQ_TAXINV(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char merch[64], bizdate[16];
long pid, supply, vat, inv;
pid = getl(b, T_PURCHASE_ID);
supply = getl(b, T_AMOUNT);
gets_(b, T_MERCHANT, merch, sizeof(merch));
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
vat = acq_vat(supply);
inv = acdb_insert_tax_invoice(pid, merch, supply, vat, bizdate);
if (inv < 0) FAIL(b);
setl(b, T_TAX, vat);
OK(b);
}

View file

@ -0,0 +1,21 @@
/*
* ACQ_UNMATCH.h - ac ACQ_UNMATCH (copybook / record header).
* Request fields: T_BIZDATE
* Response fields: T_COUNT
*/
#ifndef ACQ_UNMATCH_H
#define ACQ_UNMATCH_H
#include "ac_svc.h"
typedef struct {
long unmatch_id;
long purchase_id;
char reason[16];
char biz_date[16];
long count;
} ac_unmatch_rec_t;
void ACQ_UNMATCH(TPSVCINFO *p);
#endif /* ACQ_UNMATCH_H */

View file

@ -0,0 +1,29 @@
/*
* ACQ_UNMATCH.pgc - ac 모듈 서비스 ACQ_UNMATCH (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_UNMATCH.h"
void ACQ_UNMATCH(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16];
EXEC SQL BEGIN DECLARE SECTION;
char h_bizdate[16];
long h_cnt;
EXEC SQL END DECLARE SECTION;
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
EXEC SQL INSERT INTO ac_unmatch (unmatch_id, purchase_id, reason, biz_date)
SELECT nextval('ac_unmatch_seq'), p.purchase_id, 'NO_LEDGER', p.biz_date
FROM purchase p
WHERE p.biz_date = :h_bizdate
AND NOT EXISTS (SELECT 1 FROM ledger l WHERE l.purchase_id = p.purchase_id)
AND NOT EXISTS (SELECT 1 FROM ac_unmatch u WHERE u.purchase_id = p.purchase_id);
if (sqlca.sqlcode < 0) { userlog("ACQ_UNMATCH FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); FAIL(b); }
h_cnt = sqlca.sqlerrd[2];
setl(b, T_COUNT, h_cnt);
OK(b);
}

21
app/src/ac/svc/ACQ_VOID.h Normal file
View file

@ -0,0 +1,21 @@
/*
* ACQ_VOID.h - ac ACQ_VOID (copybook / record header).
* Request fields: T_PURCHASE_ID, T_AMOUNT, T_BIZDATE
* Response fields: T_CANCEL_ID, T_STATUS
*/
#ifndef ACQ_VOID_H
#define ACQ_VOID_H
#include "ac_svc.h"
typedef struct {
long cancel_id;
long purchase_id;
long amount;
char status[8];
char biz_date[16];
} ac_void_rec_t;
void ACQ_VOID(TPSVCINFO *p);
#endif /* ACQ_VOID_H */

View file

@ -0,0 +1,28 @@
/*
* ACQ_VOID.pgc - ac 모듈 서비스 ACQ_VOID (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_VOID.h"
void ACQ_VOID(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16];
EXEC SQL BEGIN DECLARE SECTION;
long h_id, h_pid, h_amt;
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, bizdate, sizeof(bizdate));
strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
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, 'VOID', :h_amt, 'VOID', :h_bizdate);
if (sqlca.sqlcode < 0) FAIL(b);
if (acdb_update_status(h_pid, "V") < 0) FAIL(b);
setl(b, T_CANCEL_ID, h_id);
Bchg(b, T_STATUS, 0, "V", 0L);
OK(b);
}

21
app/src/ac/svc/ACQ_WHT.h Normal file
View file

@ -0,0 +1,21 @@
/*
* ACQ_WHT.h - ac ACQ_WHT (copybook / record header).
* Request fields: T_PURCHASE_ID, T_BIZDATE
* Response fields: T_TAX
*/
#ifndef ACQ_WHT_H
#define ACQ_WHT_H
#include "ac_svc.h"
typedef struct {
long wht_id;
long purchase_id;
long fee;
long tax_amount;
char biz_date[16];
} ac_wht_rec_t;
void ACQ_WHT(TPSVCINFO *p);
#endif /* ACQ_WHT_H */

View file

@ -0,0 +1,26 @@
/*
* ACQ_WHT.pgc - ac 모듈 서비스 ACQ_WHT (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_WHT.h"
void ACQ_WHT(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16];
long pid, tax, wht_id;
EXEC SQL BEGIN DECLARE SECTION;
long e_pid, e_fee;
EXEC SQL END DECLARE SECTION;
pid = getl(b, T_PURCHASE_ID);
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
e_pid = pid;
EXEC SQL SELECT fee INTO :e_fee FROM purchase WHERE purchase_id = :e_pid;
if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) FAIL(b);
tax = acq_wht_amt(e_fee, 2200); /* 22% */
wht_id = acdb_insert_wht(pid, tax, bizdate);
if (wht_id < 0) FAIL(b);
setl(b, T_TAX, tax);
OK(b);
}

View file

@ -0,0 +1,21 @@
/*
* ACQ_XFERLINK.h - ac ACQ_XFERLINK (copybook / record header).
* Request fields: T_PURCHASE_ID, T_AMOUNT, T_BIZDATE
* Response fields: (none)
*/
#ifndef ACQ_XFERLINK_H
#define ACQ_XFERLINK_H
#include "ac_svc.h"
typedef struct {
long ledger_id;
long purchase_id;
char entry_type[16];
long amount;
char biz_date[16];
} ac_xferlink_rec_t;
void ACQ_XFERLINK(TPSVCINFO *p);
#endif /* ACQ_XFERLINK_H */

View file

@ -0,0 +1,16 @@
/*
* ACQ_XFERLINK.pgc - ac 모듈 서비스 ACQ_XFERLINK (one service = one file).
* Moved verbatim from the former inline ac_svr.pgc; runs on the caller's XA
* branch (no EXEC SQL CONNECT). Advertised by ac_svr at tpsvrinit.
*/
#include "ACQ_XFERLINK.h"
void ACQ_XFERLINK(TPSVCINFO *p)
{
UBFH *b = (UBFH *)p->data;
char bizdate[16];
long pid = getl(b, T_PURCHASE_ID), amt = getl(b, T_AMOUNT);
gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
if (acdb_insert_ledger(pid, "XFER", amt, bizdate) < 0) FAIL(b);
OK(b);
}

33
app/src/ac/svc/ac_svc.h Normal file
View file

@ -0,0 +1,33 @@
/*
* ac_svc.h - ac () (shared copybook for all ac svc/*.pgc).
*
* Every per-service file (svc/<SVCNAME>.pgc) includes its own copybook header
* (svc/<SVCNAME>.h), which in turn includes THIS shared base. It pulls in the
* ATMI/UBF runtime, the acq.fd field ids, the ac dbio layer (libacdbio.a) and the
* common math (libacqcommon.a), and provides the tiny UBF helpers + tpreturn
* macros every service uses. No business logic and no service function lives here.
*/
#ifndef AC_SVC_H
#define AC_SVC_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include <ubf.h>
#include <userlog.h>
#include <ndebug.h>
#include "acq.fd.h"
#include "ac_dbio.h"
#include "acq_common.h"
/* ----- small UBF helpers (one copy per service TU) ----------------------- */
static long getl(UBFH *b, BFLDID f) { long v = 0; Bget(b, f, 0, (char *)&v, 0L); return v; }
static void gets_(UBFH *b, BFLDID f, char *out, int cap)
{ BFLDLEN l = cap; out[0] = 0; Bget(b, f, 0, out, &l); }
static void setl(UBFH *b, BFLDID f, long v) { Bchg(b, f, 0, (char *)&v, 0L); }
#define FAIL(b) do { tpreturn(TPFAIL, 0, (char *)(b), 0L, 0L); return; } while (0)
#define OK(b) do { tpreturn(TPSUCCESS, 0, (char *)(b), 0L, 0L); return; } while (0)
#endif /* AC_SVC_H */