다양화: 530개 online/batch 프로그램을 모듈별 고유 실업무 로직으로 재작성

- 템플릿 클론(정규화 후 0줄 상이) → 전 코퍼스 530/530 고유 바디
- 11개 모듈(mg/au/ac/rc/vl/st/py/lg/mm/cm/cl) 각 파일이 distinct한
  매입·대사·정산·수수료·지급·원장·마감·마스터·정합성·전문게이트웨이·공통 업무
- TxCore(ATMI 유사) + ECPG(EXEC SQL) 관용구, 프레임워크/헤더/DBIO API/파일ID·경로 유지
- 전체 docker make -j4 = EXIT 0, 958 오브젝트, 데모 바이너리 링크
- inventory.json loc 실측 갱신

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
forge-bot 2026-07-19 01:37:54 +00:00
parent b96cf702ee
commit c3a0259e95
1027 changed files with 68915 additions and 40962 deletions

View file

@ -8,15 +8,16 @@
#line 1 "app/online/ac_ol_0001.pgc"
/* @tier easy @module ac @transform acquire-online */
/*
* ac_ol_0001.pgc - (AC_OL_0001) [tier=easy]
* ac_ol_0001.pgc - (AC_OL_0001) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* (KEY) ac_ledger ///
* . .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,16 +90,53 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0001.pgc"
#line 16 "app/online/ac_ol_0001.pgc"
TX_SERVICE(AC_OL_0001, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* exec sql begin declare section */
#line 21 "app/online/ac_ol_0001.pgc"
char h_key [ 16 ] ;
#line 22 "app/online/ac_ol_0001.pgc"
char h_status [ 2 ] ;
#line 23 "app/online/ac_ol_0001.pgc"
char h_merch_id [ 16 ] ;
#line 24 "app/online/ac_ol_0001.pgc"
char h_card_no [ 20 ] ;
#line 25 "app/online/ac_ol_0001.pgc"
char h_biz_date [ 9 ] ;
#line 26 "app/online/ac_ol_0001.pgc"
long h_amount ;
#line 27 "app/online/ac_ol_0001.pgc"
long h_fee ;
/* exec sql end declare section */
#line 28 "app/online/ac_ol_0001.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0001] 매입 단건조회 서비스 진입");
char key[16];
char status_nm[16];
char amount_won[32];
char card_masked[20];
char settle_due[9];
size_t clen;
long peer_cnt;
tx_log(TX_LOG_INFO, "[AC_OL_0001] 매입 상태조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0001] KEY 누락");
@ -106,20 +144,92 @@ TX_SERVICE(AC_OL_0001, ctx)
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0001] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select status , amount , fee , merch_id , card_no , biz_date from ac_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_fee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_card_no),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 53 "app/online/ac_ol_0001.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0001] 대상 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_ledger");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (strcmp(h_status, AC_ST_RECV) == 0) {
strncpy(status_nm, "접수", sizeof(status_nm) - 1);
} else if (strcmp(h_status, AC_ST_DONE) == 0) {
strncpy(status_nm, "처리완료", sizeof(status_nm) - 1);
} else if (strcmp(h_status, AC_ST_FAIL) == 0) {
strncpy(status_nm, "불일치", sizeof(status_nm) - 1);
} else if (strcmp(h_status, AC_ST_SETTLED) == 0) {
strncpy(status_nm, "정산완료", sizeof(status_nm) - 1);
} else {
strncpy(status_nm, "알수없음", sizeof(status_nm) - 1);
}
status_nm[sizeof(status_nm) - 1] = '\0';
/* 카드번호 뒷자리 마스킹 (앞 6자리만 노출) */
clen = strlen(h_card_no);
strncpy(card_masked, h_card_no, sizeof(card_masked) - 1);
card_masked[sizeof(card_masked) - 1] = '\0';
if (clen > 6) {
size_t j;
for (j = 6; j < clen && j < sizeof(card_masked) - 1; j++)
card_masked[j] = '*';
}
/* 접수 상태면 정산예정일(다음 영업일)을 함께 안내 */
settle_due[0] = '\0';
if (strcmp(h_status, AC_ST_RECV) == 0) {
if (date_next_business(h_biz_date, settle_due) != 0)
settle_due[0] = '\0';
}
amount_format_won(h_amount, amount_won, sizeof(amount_won));
/* 참고정보: 동일 영업일/동일 상태 건수 (표준 DBIO 재사용) */
peer_cnt = ac_rec_count(h_biz_date, h_status);
if (peer_cnt < 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0001] 동일상태 건수조회 실패 rc=%ld", peer_cnt);
peer_cnt = 0;
}
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0001] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_sets(ctx->out, "MERCHID", h_merch_id);
tx_buf_sets(ctx->out, "CARDNO", card_masked);
tx_buf_setlong(ctx->out, "AMOUNT", h_amount);
tx_buf_sets(ctx->out, "AMOUNTWON", amount_won);
tx_buf_setlong(ctx->out, "FEE", h_fee);
tx_buf_sets(ctx->out, "STATUS", h_status);
tx_buf_sets(ctx->out, "STATUSNM", status_nm);
tx_buf_sets(ctx->out, "BIZDATE", h_biz_date);
tx_buf_setlong(ctx->out, "PEERCNT", peer_cnt);
if (settle_due[0] != '\0')
tx_buf_sets(ctx->out, "SETTLEDUE", settle_due);
tx_log(TX_LOG_INFO,
"[AC_OL_0001] 조회완료 key=%s status=%s(%s) amount=%ld 동일상태건수=%ld",
key, h_status, status_nm, h_amount, peer_cnt);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier easy @module ac @transform acquire-online */
/*
* ac_ol_0001.pgc - 매입 온라인 서비스 (AC_OL_0001) [tier=easy]
* ac_ol_0001.pgc - 매입 상태조회 서비스 (AC_OL_0001) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 처리키(KEY)로 ac_ledger 를 단건조회하여 상태/금액/수수료/가맹점번호
* 반환한다. 상태코드는 화면 표시용 한글 라벨로 매핑하여 함께 내려준다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,11 +17,25 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0001, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
char h_status[2];
char h_merch_id[16];
char h_card_no[20];
char h_biz_date[9];
long h_amount;
long h_fee;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0001] 매입 단건조회 서비스 진입");
char key[16];
char status_nm[16];
char amount_won[32];
char card_masked[20];
char settle_due[9];
size_t clen;
long peer_cnt;
tx_log(TX_LOG_INFO, "[AC_OL_0001] 매입 상태조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0001] KEY 누락");
@ -28,20 +43,80 @@ TX_SERVICE(AC_OL_0001, ctx)
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0001] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
EXEC SQL
SELECT status, amount, fee, merch_id, card_no, biz_date
INTO :h_status, :h_amount, :h_fee, :h_merch_id, :h_card_no, :h_biz_date
FROM ac_ledger
WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0001] 대상 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_ledger");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (strcmp(h_status, AC_ST_RECV) == 0) {
strncpy(status_nm, "접수", sizeof(status_nm) - 1);
} else if (strcmp(h_status, AC_ST_DONE) == 0) {
strncpy(status_nm, "처리완료", sizeof(status_nm) - 1);
} else if (strcmp(h_status, AC_ST_FAIL) == 0) {
strncpy(status_nm, "불일치", sizeof(status_nm) - 1);
} else if (strcmp(h_status, AC_ST_SETTLED) == 0) {
strncpy(status_nm, "정산완료", sizeof(status_nm) - 1);
} else {
strncpy(status_nm, "알수없음", sizeof(status_nm) - 1);
}
status_nm[sizeof(status_nm) - 1] = '\0';
/* 카드번호 뒷자리 마스킹 (앞 6자리만 노출) */
clen = strlen(h_card_no);
strncpy(card_masked, h_card_no, sizeof(card_masked) - 1);
card_masked[sizeof(card_masked) - 1] = '\0';
if (clen > 6) {
size_t j;
for (j = 6; j < clen && j < sizeof(card_masked) - 1; j++)
card_masked[j] = '*';
}
/* 접수 상태면 정산예정일(다음 영업일)을 함께 안내 */
settle_due[0] = '\0';
if (strcmp(h_status, AC_ST_RECV) == 0) {
if (date_next_business(h_biz_date, settle_due) != 0)
settle_due[0] = '\0';
}
amount_format_won(h_amount, amount_won, sizeof(amount_won));
/* 참고정보: 동일 영업일/동일 상태 건수 (표준 DBIO 재사용) */
peer_cnt = ac_rec_count(h_biz_date, h_status);
if (peer_cnt < 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0001] 동일상태 건수조회 실패 rc=%ld", peer_cnt);
peer_cnt = 0;
}
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0001] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_sets(ctx->out, "MERCHID", h_merch_id);
tx_buf_sets(ctx->out, "CARDNO", card_masked);
tx_buf_setlong(ctx->out, "AMOUNT", h_amount);
tx_buf_sets(ctx->out, "AMOUNTWON", amount_won);
tx_buf_setlong(ctx->out, "FEE", h_fee);
tx_buf_sets(ctx->out, "STATUS", h_status);
tx_buf_sets(ctx->out, "STATUSNM", status_nm);
tx_buf_sets(ctx->out, "BIZDATE", h_biz_date);
tx_buf_setlong(ctx->out, "PEERCNT", peer_cnt);
if (settle_due[0] != '\0')
tx_buf_sets(ctx->out, "SETTLEDUE", settle_due);
tx_log(TX_LOG_INFO,
"[AC_OL_0001] 조회완료 key=%s status=%s(%s) amount=%ld 동일상태건수=%ld",
key, h_status, status_nm, h_amount, peer_cnt);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -8,15 +8,17 @@
#line 1 "app/online/ac_ol_0002.pgc"
/* @tier medium @module ac @transform acquire-online */
/*
* ac_ol_0002.pgc - (AC_OL_0002) [tier=medium]
* ac_ol_0002.pgc - (AC_OL_0002) [tier=medium]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* (merchant.fee_rate) (limit_amt)
* / (status='R')
* ac_ledger . / .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,22 +91,53 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0002.pgc"
#line 17 "app/online/ac_ol_0002.pgc"
TX_SERVICE(AC_OL_0002, ctx)
{
/* exec sql begin declare section */
#line 22 "app/online/ac_ol_0002.pgc"
char h_key [ 16 ] ;
#line 23 "app/online/ac_ol_0002.pgc"
char h_merch_id [ 16 ] ;
#line 24 "app/online/ac_ol_0002.pgc"
long h_fee_rate ;
#line 25 "app/online/ac_ol_0002.pgc"
long h_limit_amt ;
#line 26 "app/online/ac_ol_0002.pgc"
char h_status [ 2 ] ;
#line 27 "app/online/ac_ol_0002.pgc"
long h_dup ;
/* exec sql end declare section */
#line 28 "app/online/ac_ol_0002.pgc"
ac_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
char key[16], merch[16], card[20], bizdate[16];
long amount = 0, fee, cnt;
int rc;
tx_log(TX_LOG_INFO, "[AC_OL_0002] 매입 등록 서비스 진입");
tx_log(TX_LOG_INFO, "[AC_OL_0002] 매입 접수 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "CARDNO", card, sizeof(card)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0002] 필수 필드 누락");
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
@ -113,26 +146,92 @@ TX_SERVICE(AC_OL_0002, ctx)
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0002] 금액 범위 오류 amount=%ld", amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0002] 영업일 오류 date=%s", bizdate);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
strncpy(h_merch_id, merch, sizeof(h_merch_id) - 1);
h_merch_id[sizeof(h_merch_id) - 1] = '\0';
strncpy(h_status, "A", sizeof(h_status));
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select fee_rate , limit_amt from merchant where merch_id = $1 and status = $2 ",
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_fee_rate),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_limit_amt),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 72 "app/online/ac_ol_0002.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0002] 미등록/비활성 가맹점 merch=%s", merch);
tx_buf_sets(ctx->out, "RESPCODE", RESP_NOMERCH);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT merchant.fee_rate");
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_limit_amt > 0 && amount > h_limit_amt) {
tx_log(TX_LOG_WARN, "[AC_OL_0002] 거래한도 초과 merch=%s amount=%ld limit=%ld",
merch, amount, h_limit_amt);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select count ( * ) from ac_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_dup),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 98 "app/online/ac_ol_0002.pgc"
if (sqlca.sqlcode != TX_SQL_OK && sqlca.sqlcode != TX_SQL_NOTFOUND) {
TX_DBIO_LOG_ERR("SELECT dup ac_ledger");
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_dup > 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0002] 중복 접수키 key=%s", key);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
fee = amount * h_fee_rate / 10000;
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.card_no, card, sizeof(rec.card_no) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
rec.fee = fee;
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0002] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, rc, ctx->out);
return;
}
@ -142,7 +241,8 @@ TX_SERVICE(AC_OL_0002, ctx)
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "FEE", fee);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0002] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0002] 접수완료 key=%s fee=%ld 당일건수=%ld", key, fee, cnt);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,16 @@
/* @tier medium @module ac @transform acquire-online */
/*
* ac_ol_0002.pgc - 매입 온라인 서비스 (AC_OL_0002) [tier=medium]
* ac_ol_0002.pgc - 매입 접수 서비스 (AC_OL_0002) [tier=medium]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 가맹점 수수료율(merchant.fee_rate)과 거래한도(limit_amt)를 조회하여
* 수수료를 산정하고 한도초과/중복키를 반려한 뒤 접수(status='R') 상태로
* ac_ledger 에 등록한다. 미등록/비활성 가맹점은 반려.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,17 +18,28 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0002, ctx)
{
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
char h_merch_id[16];
long h_fee_rate;
long h_limit_amt;
char h_status[2];
long h_dup;
EXEC SQL END DECLARE SECTION;
ac_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
char key[16], merch[16], card[20], bizdate[16];
long amount = 0, fee, cnt;
int rc;
tx_log(TX_LOG_INFO, "[AC_OL_0002] 매입 등록 서비스 진입");
tx_log(TX_LOG_INFO, "[AC_OL_0002] 매입 접수 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "CARDNO", card, sizeof(card)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0002] 필수 필드 누락");
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
@ -35,26 +48,83 @@ TX_SERVICE(AC_OL_0002, ctx)
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0002] 금액 범위 오류 amount=%ld", amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0002] 영업일 오류 date=%s", bizdate);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
strncpy(h_merch_id, merch, sizeof(h_merch_id) - 1);
h_merch_id[sizeof(h_merch_id) - 1] = '\0';
strncpy(h_status, "A", sizeof(h_status));
EXEC SQL
SELECT fee_rate, limit_amt INTO :h_fee_rate, :h_limit_amt
FROM merchant
WHERE merch_id = :h_merch_id
AND status = :h_status;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0002] 미등록/비활성 가맹점 merch=%s", merch);
tx_buf_sets(ctx->out, "RESPCODE", RESP_NOMERCH);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT merchant.fee_rate");
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_limit_amt > 0 && amount > h_limit_amt) {
tx_log(TX_LOG_WARN, "[AC_OL_0002] 거래한도 초과 merch=%s amount=%ld limit=%ld",
merch, amount, h_limit_amt);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
EXEC SQL
SELECT count(*) INTO :h_dup
FROM ac_ledger
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK && sqlca.sqlcode != TX_SQL_NOTFOUND) {
TX_DBIO_LOG_ERR("SELECT dup ac_ledger");
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_dup > 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0002] 중복 접수키 key=%s", key);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
fee = amount * h_fee_rate / 10000;
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.card_no, card, sizeof(rec.card_no) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
rec.fee = fee;
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0002] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, rc, ctx->out);
return;
}
@ -64,7 +134,8 @@ TX_SERVICE(AC_OL_0002, ctx)
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "FEE", fee);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0002] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0002] 접수완료 key=%s fee=%ld 당일건수=%ld", key, fee, cnt);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -8,15 +8,17 @@
#line 1 "app/online/ac_ol_0003.pgc"
/* @tier easy @module ac @transform acquire-online */
/*
* ac_ol_0003.pgc - (AC_OL_0003) [tier=easy]
* ac_ol_0003.pgc - DDC ( , AC_OL_0003) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* (DDC)
* (status='M') ac_ledger .
* .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,37 +91,181 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0003.pgc"
#line 17 "app/online/ac_ol_0003.pgc"
TX_SERVICE(AC_OL_0003, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* exec sql begin declare section */
#line 22 "app/online/ac_ol_0003.pgc"
char h_key [ 16 ] ;
#line 23 "app/online/ac_ol_0003.pgc"
char h_merch_id [ 16 ] ;
#line 24 "app/online/ac_ol_0003.pgc"
char h_card_no [ 20 ] ;
#line 25 "app/online/ac_ol_0003.pgc"
long h_amount ;
#line 26 "app/online/ac_ol_0003.pgc"
char h_biz_date [ 9 ] ;
#line 27 "app/online/ac_ol_0003.pgc"
char h_status [ 2 ] ;
#line 28 "app/online/ac_ol_0003.pgc"
long h_fee ;
#line 29 "app/online/ac_ol_0003.pgc"
char h_acq_type [ 4 ] ;
#line 30 "app/online/ac_ol_0003.pgc"
long h_merch_active ;
#line 31 "app/online/ac_ol_0003.pgc"
long h_dup ;
/* exec sql end declare section */
#line 32 "app/online/ac_ol_0003.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0003] 매입 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0003] KEY 누락");
char key[16], merch[16], card[20], bizdate[16];
long amount = 0;
tx_log(TX_LOG_INFO, "[AC_OL_0003] DDC 매입 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "CARDNO", card, sizeof(card)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0003] 필수 필드 누락");
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0003] 금액 범위 오류 amount=%ld", amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0003] 영업일 오류 date=%s", bizdate);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0003] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
strncpy(h_merch_id, merch, sizeof(h_merch_id) - 1);
h_merch_id[sizeof(h_merch_id) - 1] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select count ( * ) from merchant where merch_id = $1 and status = 'A'",
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_merch_active),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 72 "app/online/ac_ol_0003.pgc"
if (sqlca.sqlcode != TX_SQL_OK && sqlca.sqlcode != TX_SQL_NOTFOUND) {
TX_DBIO_LOG_ERR("SELECT merchant.status(DDC)");
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_merch_active <= 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0003] 미등록/비활성 가맹점 merch=%s", merch);
tx_buf_sets(ctx->out, "RESPCODE", RESP_NOMERCH);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select count ( * ) from ac_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_dup),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 90 "app/online/ac_ol_0003.pgc"
if (sqlca.sqlcode != TX_SQL_OK && sqlca.sqlcode != TX_SQL_NOTFOUND) {
TX_DBIO_LOG_ERR("SELECT dup ac_ledger(DDC)");
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_dup > 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0003] 중복 처리키 key=%s", key);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
strncpy(h_card_no, card, sizeof(h_card_no) - 1);
h_card_no[sizeof(h_card_no) - 1] = '\0';
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
h_biz_date[sizeof(h_biz_date) - 1] = '\0';
strncpy(h_status, AC_ST_DONE, sizeof(h_status));
strncpy(h_acq_type, "DDC", sizeof(h_acq_type) - 1);
h_acq_type[sizeof(h_acq_type) - 1] = '\0';
h_amount = amount;
h_fee = amount * 20 / 10000; /* 직불 수수료 0.20% */
if (tx_begin() != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0003] tx_begin 경고");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into ac_ledger ( key , merch_id , card_no , amount , biz_date , status , fee , acq_type ) values ( $1 , $2 , $3 , $4 , $5 , $6 , $7 , $8 )",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_card_no),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_fee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_acq_type),(long)4,(long)1,(4)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 123 "app/online/ac_ol_0003.pgc"
if (sqlca.sqlcode != TX_SQL_OK || sqlca.sqlerrd[2] != 1) {
TX_DBIO_LOG_ERR("INSERT ac_ledger(DDC)");
tx_abort();
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0003] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_sets(ctx->out, "STATUS", h_status);
tx_buf_setlong(ctx->out, "FEE", h_fee);
tx_log(TX_LOG_INFO, "[AC_OL_0003] DDC 즉시매입 완료 key=%s amount=%ld fee=%ld",
key, amount, h_fee);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,16 @@
/* @tier easy @module ac @transform acquire-online */
/*
* ac_ol_0003.pgc - 매입 온라인 서비스 (AC_OL_0003) [tier=easy]
* ac_ol_0003.pgc - DDC 매입 서비스 (직불카드 즉시매입, AC_OL_0003) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 직불카드(DDC)는 승인과 동시에 매입이 확정되므로 접수 단계 없이 바로
* 처리완료(status='M') 상태로 ac_ledger 에 적재한다. 가맹점 활성 여부와
* 접수키 중복을 사전 검증한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,32 +18,126 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0003, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
char h_merch_id[16];
char h_card_no[20];
long h_amount;
char h_biz_date[9];
char h_status[2];
long h_fee;
char h_acq_type[4];
long h_merch_active;
long h_dup;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0003] 매입 단건조회 서비스 진입");
char key[16], merch[16], card[20], bizdate[16];
long amount = 0;
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0003] KEY 누락");
tx_log(TX_LOG_INFO, "[AC_OL_0003] DDC 매입 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "CARDNO", card, sizeof(card)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0003] 필수 필드 누락");
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0003] 금액 범위 오류 amount=%ld", amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0003] 영업일 오류 date=%s", bizdate);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0003] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
strncpy(h_merch_id, merch, sizeof(h_merch_id) - 1);
h_merch_id[sizeof(h_merch_id) - 1] = '\0';
EXEC SQL
SELECT count(*) INTO :h_merch_active
FROM merchant
WHERE merch_id = :h_merch_id
AND status = 'A';
if (sqlca.sqlcode != TX_SQL_OK && sqlca.sqlcode != TX_SQL_NOTFOUND) {
TX_DBIO_LOG_ERR("SELECT merchant.status(DDC)");
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_merch_active <= 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0003] 미등록/비활성 가맹점 merch=%s", merch);
tx_buf_sets(ctx->out, "RESPCODE", RESP_NOMERCH);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
EXEC SQL
SELECT count(*) INTO :h_dup
FROM ac_ledger
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK && sqlca.sqlcode != TX_SQL_NOTFOUND) {
TX_DBIO_LOG_ERR("SELECT dup ac_ledger(DDC)");
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_dup > 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0003] 중복 처리키 key=%s", key);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
strncpy(h_card_no, card, sizeof(h_card_no) - 1);
h_card_no[sizeof(h_card_no) - 1] = '\0';
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
h_biz_date[sizeof(h_biz_date) - 1] = '\0';
strncpy(h_status, AC_ST_DONE, sizeof(h_status));
strncpy(h_acq_type, "DDC", sizeof(h_acq_type) - 1);
h_acq_type[sizeof(h_acq_type) - 1] = '\0';
h_amount = amount;
h_fee = amount * 20 / 10000; /* 직불 수수료 0.20% */
if (tx_begin() != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0003] tx_begin 경고");
EXEC SQL
INSERT INTO ac_ledger
(key, merch_id, card_no, amount, biz_date, status, fee, acq_type)
VALUES
(:h_key, :h_merch_id, :h_card_no, :h_amount, :h_biz_date,
:h_status, :h_fee, :h_acq_type);
if (sqlca.sqlcode != TX_SQL_OK || sqlca.sqlerrd[2] != 1) {
TX_DBIO_LOG_ERR("INSERT ac_ledger(DDC)");
tx_abort();
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0003] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_sets(ctx->out, "STATUS", h_status);
tx_buf_setlong(ctx->out, "FEE", h_fee);
tx_log(TX_LOG_INFO, "[AC_OL_0003] DDC 즉시매입 완료 key=%s amount=%ld fee=%ld",
key, amount, h_fee);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -8,15 +8,16 @@
#line 1 "app/online/ac_ol_0004.pgc"
/* @tier medium @module ac @transform acquire-online */
/*
* ac_ol_0004.pgc - (AC_OL_0004) [tier=medium]
* ac_ol_0004.pgc - EDC ( , AC_OL_0004) [tier=medium]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* (APPROVALNO) approval
* , approval_no ac_ledger acq_type='EDC' .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,60 +90,169 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0004.pgc"
#line 16 "app/online/ac_ol_0004.pgc"
TX_SERVICE(AC_OL_0004, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
/* exec sql begin declare section */
#line 21 "app/online/ac_ol_0004.pgc"
char h_appr_no [ 9 ] ;
#line 22 "app/online/ac_ol_0004.pgc"
long h_amount ;
#line 23 "app/online/ac_ol_0004.pgc"
char h_merch_id [ 16 ] ;
#line 24 "app/online/ac_ol_0004.pgc"
char h_card_no [ 20 ] ;
#line 25 "app/online/ac_ol_0004.pgc"
char h_appr_status [ 2 ] ;
#line 26 "app/online/ac_ol_0004.pgc"
char h_key [ 16 ] ;
#line 27 "app/online/ac_ol_0004.pgc"
char h_biz_date [ 9 ] ;
#line 28 "app/online/ac_ol_0004.pgc"
char h_status [ 2 ] ;
#line 29 "app/online/ac_ol_0004.pgc"
long h_fee ;
#line 30 "app/online/ac_ol_0004.pgc"
char h_acq_type [ 4 ] ;
/* exec sql end declare section */
#line 31 "app/online/ac_ol_0004.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0004] 매입 등록 서비스 진입");
char key[16], apprno[9], bizdate[16];
tx_log(TX_LOG_INFO, "[AC_OL_0004] EDC 매입 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "APPROVALNO", apprno, sizeof(apprno)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0004] 필수 필드 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0004] 금액 범위 오류 amount=%ld", amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0004] 영업일 오류 date=%s", bizdate);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_appr_no, apprno, sizeof(h_appr_no) - 1);
h_appr_no[sizeof(h_appr_no) - 1] = '\0';
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0004] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount , merch_id , card_no , appr_status from approval where approval_no = $1 ",
ECPGt_char,(h_appr_no),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_card_no),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_appr_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 59 "app/online/ac_ol_0004.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0004] 승인전표 없음 approvalno=%s", apprno);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT approval");
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
cnt = ac_rec_count(bizdate, AC_ST_RECV);
if (strcmp(h_appr_status, "A") != 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0004] 승인 미완료 approvalno=%s status=%s",
apprno, h_appr_status);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
if (!amount_is_valid(h_amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0004] 승인금액 범위 오류 amount=%ld", h_amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
h_biz_date[sizeof(h_biz_date) - 1] = '\0';
strncpy(h_status, AC_ST_DONE, sizeof(h_status));
strncpy(h_acq_type, "EDC", sizeof(h_acq_type) - 1);
h_acq_type[sizeof(h_acq_type) - 1] = '\0';
h_fee = h_amount * 15 / 10000; /* EDC 수수료 0.15% */
if (tx_begin() != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0004] tx_begin 경고");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into ac_ledger ( key , merch_id , card_no , amount , biz_date , status , fee , acq_type , approval_no ) values ( $1 , $2 , $3 , $4 , $5 , $6 , $7 , $8 , $9 )",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_card_no),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_fee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_acq_type),(long)4,(long)1,(4)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_appr_no),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 106 "app/online/ac_ol_0004.pgc"
if (sqlca.sqlcode != TX_SQL_OK || sqlca.sqlerrd[2] != 1) {
TX_DBIO_LOG_ERR("INSERT ac_ledger(EDC)");
tx_abort();
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0004] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_sets(ctx->out, "STATUS", h_status);
tx_buf_setlong(ctx->out, "FEE", h_fee);
tx_log(TX_LOG_INFO, "[AC_OL_0004] EDC 매입 완료 key=%s approvalno=%s fee=%ld",
key, apprno, h_fee);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier medium @module ac @transform acquire-online */
/*
* ac_ol_0004.pgc - 매입 온라인 서비스 (AC_OL_0004) [tier=medium]
* ac_ol_0004.pgc - EDC 매입 서비스 (전자매출전표 매입, AC_OL_0004) [tier=medium]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 승인번호(APPROVALNO)로 approval 원장을 조회하여 승인완료 건만 매입
* 처리하고, approval_no 를 연결키로 ac_ledger 에 acq_type='EDC' 로 적재한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,55 +17,110 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0004, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_appr_no[9];
long h_amount;
char h_merch_id[16];
char h_card_no[20];
char h_appr_status[2];
char h_key[16];
char h_biz_date[9];
char h_status[2];
long h_fee;
char h_acq_type[4];
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0004] 매입 등록 서비스 진입");
char key[16], apprno[9], bizdate[16];
tx_log(TX_LOG_INFO, "[AC_OL_0004] EDC 매입 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "APPROVALNO", apprno, sizeof(apprno)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0004] 필수 필드 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0004] 금액 범위 오류 amount=%ld", amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0004] 영업일 오류 date=%s", bizdate);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_appr_no, apprno, sizeof(h_appr_no) - 1);
h_appr_no[sizeof(h_appr_no) - 1] = '\0';
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0004] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
EXEC SQL
SELECT amount, merch_id, card_no, appr_status
INTO :h_amount, :h_merch_id, :h_card_no, :h_appr_status
FROM approval
WHERE approval_no = :h_appr_no;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0004] 승인전표 없음 approvalno=%s", apprno);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT approval");
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
cnt = ac_rec_count(bizdate, AC_ST_RECV);
if (strcmp(h_appr_status, "A") != 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0004] 승인 미완료 approvalno=%s status=%s",
apprno, h_appr_status);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
if (!amount_is_valid(h_amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0004] 승인금액 범위 오류 amount=%ld", h_amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
h_biz_date[sizeof(h_biz_date) - 1] = '\0';
strncpy(h_status, AC_ST_DONE, sizeof(h_status));
strncpy(h_acq_type, "EDC", sizeof(h_acq_type) - 1);
h_acq_type[sizeof(h_acq_type) - 1] = '\0';
h_fee = h_amount * 15 / 10000; /* EDC 수수료 0.15% */
if (tx_begin() != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0004] tx_begin 경고");
EXEC SQL
INSERT INTO ac_ledger
(key, merch_id, card_no, amount, biz_date, status, fee,
acq_type, approval_no)
VALUES
(:h_key, :h_merch_id, :h_card_no, :h_amount, :h_biz_date,
:h_status, :h_fee, :h_acq_type, :h_appr_no);
if (sqlca.sqlcode != TX_SQL_OK || sqlca.sqlerrd[2] != 1) {
TX_DBIO_LOG_ERR("INSERT ac_ledger(EDC)");
tx_abort();
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0004] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_sets(ctx->out, "STATUS", h_status);
tx_buf_setlong(ctx->out, "FEE", h_fee);
tx_log(TX_LOG_INFO, "[AC_OL_0004] EDC 매입 완료 key=%s approvalno=%s fee=%ld",
key, apprno, h_fee);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -8,15 +8,17 @@
#line 1 "app/online/ac_ol_0005.pgc"
/* @tier easy @module ac @transform acquire-online */
/*
* ac_ol_0005.pgc - (AC_OL_0005) [tier=easy]
* ac_ol_0005.pgc - (AC_OL_0005) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* (KEY) (S)/ (U)
* , (status='U') .
* , .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,37 +91,133 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0005.pgc"
#line 17 "app/online/ac_ol_0005.pgc"
TX_SERVICE(AC_OL_0005, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* exec sql begin declare section */
#line 22 "app/online/ac_ol_0005.pgc"
char h_key [ 16 ] ;
#line 23 "app/online/ac_ol_0005.pgc"
char h_status [ 2 ] ;
#line 24 "app/online/ac_ol_0005.pgc"
long h_amount ;
#line 25 "app/online/ac_ol_0005.pgc"
char h_biz_date [ 9 ] ;
#line 26 "app/online/ac_ol_0005.pgc"
char h_cancel_status [ 2 ] ;
/* exec sql end declare section */
#line 27 "app/online/ac_ol_0005.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0005] 매입 단건조회 서비스 진입");
char key[16];
char reason[32];
long cancel_cnt;
tx_log(TX_LOG_INFO, "[AC_OL_0005] 매입 취소 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0005] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (tx_buf_get(ctx->in, "REASON", reason, sizeof(reason)) != TX_OK ||
reason[0] == '\0') {
strncpy(reason, "미상", sizeof(reason) - 1);
reason[sizeof(reason) - 1] = '\0';
tx_log(TX_LOG_DEBUG, "[AC_OL_0005] 취소사유 미지정 key=%s 기본값 적용", key);
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0005] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select status , amount , biz_date from ac_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 54 "app/online/ac_ol_0005.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0005] 대상 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT status ac_ledger");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (strcmp(h_status, AC_ST_SETTLED) == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0005] 이미 정산완료 취소불가 key=%s", key);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_sets(ctx->out, "CANCELLED", "N");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
if (strcmp(h_status, AC_ST_FAIL) == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0005] 이미 취소된 건 key=%s", key);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_sets(ctx->out, "CANCELLED", "N");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
strncpy(h_cancel_status, AC_ST_FAIL, sizeof(h_cancel_status));
if (tx_begin() != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0005] tx_begin 경고");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update ac_ledger set status = $1 , upd_ts = now ( ) where key = $2 ",
ECPGt_char,(h_cancel_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 93 "app/online/ac_ol_0005.pgc"
if (sqlca.sqlcode != TX_SQL_OK || sqlca.sqlerrd[2] != 1) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger(취소)");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_commit();
/* 참고정보: 당일 취소건수 (표준 DBIO 재사용) */
cancel_cnt = ac_rec_count(h_biz_date, AC_ST_FAIL);
if (cancel_cnt < 0)
cancel_cnt = 0;
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0005] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_sets(ctx->out, "STATUS", h_cancel_status);
tx_buf_setlong(ctx->out, "AMOUNT", h_amount);
tx_buf_sets(ctx->out, "CANCELLED", "Y");
tx_buf_sets(ctx->out, "REASON", reason);
tx_buf_setlong(ctx->out, "DAYCANCELCNT", cancel_cnt);
tx_log(TX_LOG_INFO,
"[AC_OL_0005] 매입 취소완료 key=%s 이전상태=%s 사유=%s 당일취소건수=%ld",
key, h_status, reason, cancel_cnt);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,16 @@
/* @tier easy @module ac @transform acquire-online */
/*
* ac_ol_0005.pgc - 매입 온라인 서비스 (AC_OL_0005) [tier=easy]
* ac_ol_0005.pgc - 매입 취소 서비스 (AC_OL_0005) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 처리키(KEY)로 현재 상태를 조회하여 이미 정산완료(S)/이미 취소(U)된
* 건은 반려하고, 그 외는 취소(status='U')로 전이시킨다. 취소 사유코드는
* 로그로 남기고, 처리 후 당일 취소건수를 함께 안내한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,32 +18,103 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0005, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
char h_status[2];
long h_amount;
char h_biz_date[9];
char h_cancel_status[2];
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0005] 매입 단건조회 서비스 진입");
char key[16];
char reason[32];
long cancel_cnt;
tx_log(TX_LOG_INFO, "[AC_OL_0005] 매입 취소 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0005] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (tx_buf_get(ctx->in, "REASON", reason, sizeof(reason)) != TX_OK ||
reason[0] == '\0') {
strncpy(reason, "미상", sizeof(reason) - 1);
reason[sizeof(reason) - 1] = '\0';
tx_log(TX_LOG_DEBUG, "[AC_OL_0005] 취소사유 미지정 key=%s 기본값 적용", key);
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0005] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
EXEC SQL
SELECT status, amount, biz_date
INTO :h_status, :h_amount, :h_biz_date
FROM ac_ledger
WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0005] 대상 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT status ac_ledger");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (strcmp(h_status, AC_ST_SETTLED) == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0005] 이미 정산완료 취소불가 key=%s", key);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_sets(ctx->out, "CANCELLED", "N");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
if (strcmp(h_status, AC_ST_FAIL) == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0005] 이미 취소된 건 key=%s", key);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_sets(ctx->out, "CANCELLED", "N");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
strncpy(h_cancel_status, AC_ST_FAIL, sizeof(h_cancel_status));
if (tx_begin() != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0005] tx_begin 경고");
EXEC SQL
UPDATE ac_ledger
SET status = :h_cancel_status,
upd_ts = now()
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK || sqlca.sqlerrd[2] != 1) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger(취소)");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_commit();
/* 참고정보: 당일 취소건수 (표준 DBIO 재사용) */
cancel_cnt = ac_rec_count(h_biz_date, AC_ST_FAIL);
if (cancel_cnt < 0)
cancel_cnt = 0;
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0005] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_sets(ctx->out, "STATUS", h_cancel_status);
tx_buf_setlong(ctx->out, "AMOUNT", h_amount);
tx_buf_sets(ctx->out, "CANCELLED", "Y");
tx_buf_sets(ctx->out, "REASON", reason);
tx_buf_setlong(ctx->out, "DAYCANCELCNT", cancel_cnt);
tx_log(TX_LOG_INFO,
"[AC_OL_0005] 매입 취소완료 key=%s 이전상태=%s 사유=%s 당일취소건수=%ld",
key, h_status, reason, cancel_cnt);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -8,15 +8,17 @@
#line 1 "app/online/ac_ol_0006.pgc"
/* @tier hard @module ac @transform acquire-online */
/*
* ac_ol_0006.pgc - (AC_OL_0006) [tier=hard]
* ac_ol_0006.pgc - (AC_OL_0006) [tier=hard]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* /
* ac_ledger (UPDATE), (acq_type='CORR',
* orig_key ) . .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,88 +91,201 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0006.pgc"
#line 17 "app/online/ac_ol_0006.pgc"
TX_SERVICE(AC_OL_0006, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16], nextbiz[9];
long amount = 0, daysum = 0;
int rc;
TXBUF *sub_in;
TXBUF *sub_out;
/* exec sql begin declare section */
#line 22 "app/online/ac_ol_0006.pgc"
char h_key [ 16 ] ;
#line 23 "app/online/ac_ol_0006.pgc"
long h_old_amount ;
#line 24 "app/online/ac_ol_0006.pgc"
long h_old_fee ;
#line 25 "app/online/ac_ol_0006.pgc"
char h_merch_id [ 16 ] ;
#line 26 "app/online/ac_ol_0006.pgc"
char h_card_no [ 20 ] ;
#line 27 "app/online/ac_ol_0006.pgc"
char h_biz_date [ 9 ] ;
#line 28 "app/online/ac_ol_0006.pgc"
long h_new_amount ;
#line 29 "app/online/ac_ol_0006.pgc"
long h_new_fee ;
#line 30 "app/online/ac_ol_0006.pgc"
long h_fee_rate ;
#line 31 "app/online/ac_ol_0006.pgc"
char h_corr_key [ 16 ] ;
#line 32 "app/online/ac_ol_0006.pgc"
char h_status [ 2 ] ;
/* exec sql end declare section */
#line 33 "app/online/ac_ol_0006.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0006] 매입 트랜잭션 오케스트레이션 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0006] 필수 필드 누락");
char key[16];
long new_amount = 0;
size_t klen;
tx_log(TX_LOG_INFO, "[AC_OL_0006] 매입 정정 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0006] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
if (!amount_is_valid(amount) || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0006] 입력 검증 실패 amount=%ld date=%s",
amount, bizdate);
if (tx_buf_getlong(ctx->in, "NEWAMOUNT", &new_amount) != TX_OK ||
!amount_is_valid(new_amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0006] 정정금액 오류 amount=%ld", new_amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* 트랜잭션 시작 → 원장 반영 → 후속 서비스 연계 → 커밋 */
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
h_new_amount = new_amount;
if (tx_begin() != TX_OK) {
tx_return(ctx, TX_FAIL, ctx->out);
return;
tx_log(TX_LOG_WARN, "[AC_OL_0006] tx_begin 경고");
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100;
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount , fee , merch_id , card_no , biz_date from ac_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_old_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_old_fee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_card_no),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 65 "app/online/ac_ol_0006.pgc"
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0006] 원장반영 실패 rc=%d", rc);
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0006] 원거래 없음 key=%s", key);
tx_abort();
tx_return(ctx, rc, ctx->out);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_ledger(정정대상)");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 정산 영업일 = 거래일의 다음 영업일 */
if (date_next_business(bizdate, nextbiz) != 0) {
memcpy(nextbiz, bizdate, 8);
nextbiz[8] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select fee_rate from merchant where merch_id = $1 ",
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_fee_rate),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 83 "app/online/ac_ol_0006.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0006] 가맹점 없음 merch=%s", h_merch_id);
tx_abort();
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT merchant.fee_rate(정정)");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 후속 정산집계 서비스 연계 (레지스트리 문자열 디스패치) */
sub_in = tx_buf_alloc();
sub_out = tx_buf_alloc();
if (sub_in && sub_out) {
tx_buf_sets(sub_in, "MERCHID", merch);
tx_buf_sets(sub_in, "BIZDATE", nextbiz);
tx_buf_setlong(sub_in, "AMOUNT", amount);
rc = tx_call("AC_POST", sub_in, sub_out);
if (rc != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0006] 후속연계 경고 rc=%d", rc);
}
tx_buf_free(sub_in);
tx_buf_free(sub_out);
h_new_fee = h_new_amount * h_fee_rate / 10000;
/* 교차 검증: 당일 합계 재계산 */
if (ac_rec_sum(bizdate, &daysum) != TX_OK)
daysum = 0;
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update ac_ledger set amount = $1 , fee = $2 , upd_ts = now ( ) where key = $3 ",
ECPGt_long,&(h_new_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_new_fee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 105 "app/online/ac_ol_0006.pgc"
if (sqlca.sqlcode != TX_SQL_OK || sqlca.sqlerrd[2] != 1) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger(정정)");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 정정 이력키 = 원키 앞부분 13자 + "-C" (16바이트 한도 준수) */
klen = strlen(h_key);
if (klen > 13)
klen = 13;
memcpy(h_corr_key, h_key, klen);
h_corr_key[klen] = '\0';
strcat(h_corr_key, "-C");
strncpy(h_status, AC_ST_DONE, sizeof(h_status));
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into ac_ledger ( key , merch_id , card_no , amount , biz_date , status , fee , acq_type , orig_key ) values ( $1 , $2 , $3 , $4 , $5 , $6 , $7 , 'CORR' , $8 )",
ECPGt_char,(h_corr_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_card_no),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_new_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_new_fee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 129 "app/online/ac_ol_0006.pgc"
if (sqlca.sqlcode != TX_SQL_OK || sqlca.sqlerrd[2] != 1) {
TX_DBIO_LOG_ERR("INSERT ac_ledger(정정이력)");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYSUM", daysum);
tx_log(TX_LOG_INFO, "[AC_OL_0006] 완료 key=%s 당일합계=%ld", key, daysum);
tx_buf_setlong(ctx->out, "OLDAMOUNT", h_old_amount);
tx_buf_setlong(ctx->out, "NEWAMOUNT", h_new_amount);
tx_buf_setlong(ctx->out, "OLDFEE", h_old_fee);
tx_buf_setlong(ctx->out, "NEWFEE", h_new_fee);
tx_log(TX_LOG_INFO,
"[AC_OL_0006] 정정완료 key=%s 구금액=%ld 신금액=%ld 구수수료=%ld 신수수료=%ld",
key, h_old_amount, h_new_amount, h_old_fee, h_new_fee);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,16 @@
/* @tier hard @module ac @transform acquire-online */
/*
* ac_ol_0006.pgc - 매입 온라인 서비스 (AC_OL_0006) [tier=hard]
* ac_ol_0006.pgc - 매입 정정 서비스 (AC_OL_0006) [tier=hard]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 원거래 금액/수수료를 조회하고 가맹점 수수료율로 신규 수수료를 재산정한
* 뒤 ac_ledger 원장을 정정(UPDATE)하고, 정정 이력행(acq_type='CORR',
* orig_key 연결)을 별도로 적재한다. 전 과정을 하나의 트랜잭션으로 처리.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,83 +18,133 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0006, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16], nextbiz[9];
long amount = 0, daysum = 0;
int rc;
TXBUF *sub_in;
TXBUF *sub_out;
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
long h_old_amount;
long h_old_fee;
char h_merch_id[16];
char h_card_no[20];
char h_biz_date[9];
long h_new_amount;
long h_new_fee;
long h_fee_rate;
char h_corr_key[16];
char h_status[2];
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0006] 매입 트랜잭션 오케스트레이션 진입");
char key[16];
long new_amount = 0;
size_t klen;
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0006] 필수 필드 누락");
tx_log(TX_LOG_INFO, "[AC_OL_0006] 매입 정정 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0006] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
if (!amount_is_valid(amount) || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0006] 입력 검증 실패 amount=%ld date=%s",
amount, bizdate);
if (tx_buf_getlong(ctx->in, "NEWAMOUNT", &new_amount) != TX_OK ||
!amount_is_valid(new_amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0006] 정정금액 오류 amount=%ld", new_amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* 트랜잭션 시작 → 원장 반영 → 후속 서비스 연계 → 커밋 */
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
h_new_amount = new_amount;
if (tx_begin() != TX_OK) {
tx_return(ctx, TX_FAIL, ctx->out);
return;
tx_log(TX_LOG_WARN, "[AC_OL_0006] tx_begin 경고");
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100;
EXEC SQL
SELECT amount, fee, merch_id, card_no, biz_date
INTO :h_old_amount, :h_old_fee, :h_merch_id, :h_card_no, :h_biz_date
FROM ac_ledger
WHERE key = :h_key;
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0006] 원장반영 실패 rc=%d", rc);
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0006] 원거래 없음 key=%s", key);
tx_abort();
tx_return(ctx, rc, ctx->out);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_ledger(정정대상)");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 정산 영업일 = 거래일의 다음 영업일 */
if (date_next_business(bizdate, nextbiz) != 0) {
memcpy(nextbiz, bizdate, 8);
nextbiz[8] = '\0';
EXEC SQL
SELECT fee_rate INTO :h_fee_rate
FROM merchant
WHERE merch_id = :h_merch_id;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0006] 가맹점 없음 merch=%s", h_merch_id);
tx_abort();
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT merchant.fee_rate(정정)");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 후속 정산집계 서비스 연계 (레지스트리 문자열 디스패치) */
sub_in = tx_buf_alloc();
sub_out = tx_buf_alloc();
if (sub_in && sub_out) {
tx_buf_sets(sub_in, "MERCHID", merch);
tx_buf_sets(sub_in, "BIZDATE", nextbiz);
tx_buf_setlong(sub_in, "AMOUNT", amount);
rc = tx_call("AC_POST", sub_in, sub_out);
if (rc != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0006] 후속연계 경고 rc=%d", rc);
}
tx_buf_free(sub_in);
tx_buf_free(sub_out);
h_new_fee = h_new_amount * h_fee_rate / 10000;
/* 교차 검증: 당일 합계 재계산 */
if (ac_rec_sum(bizdate, &daysum) != TX_OK)
daysum = 0;
EXEC SQL
UPDATE ac_ledger
SET amount = :h_new_amount,
fee = :h_new_fee,
upd_ts = now()
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK || sqlca.sqlerrd[2] != 1) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger(정정)");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 정정 이력키 = 원키 앞부분 13자 + "-C" (16바이트 한도 준수) */
klen = strlen(h_key);
if (klen > 13)
klen = 13;
memcpy(h_corr_key, h_key, klen);
h_corr_key[klen] = '\0';
strcat(h_corr_key, "-C");
strncpy(h_status, AC_ST_DONE, sizeof(h_status));
EXEC SQL
INSERT INTO ac_ledger
(key, merch_id, card_no, amount, biz_date, status, fee,
acq_type, orig_key)
VALUES
(:h_corr_key, :h_merch_id, :h_card_no, :h_new_amount, :h_biz_date,
:h_status, :h_new_fee, 'CORR', :h_key);
if (sqlca.sqlcode != TX_SQL_OK || sqlca.sqlerrd[2] != 1) {
TX_DBIO_LOG_ERR("INSERT ac_ledger(정정이력)");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYSUM", daysum);
tx_log(TX_LOG_INFO, "[AC_OL_0006] 완료 key=%s 당일합계=%ld", key, daysum);
tx_buf_setlong(ctx->out, "OLDAMOUNT", h_old_amount);
tx_buf_setlong(ctx->out, "NEWAMOUNT", h_new_amount);
tx_buf_setlong(ctx->out, "OLDFEE", h_old_fee);
tx_buf_setlong(ctx->out, "NEWFEE", h_new_fee);
tx_log(TX_LOG_INFO,
"[AC_OL_0006] 정정완료 key=%s 구금액=%ld 신금액=%ld 구수수료=%ld 신수수료=%ld",
key, h_old_amount, h_new_amount, h_old_fee, h_new_fee);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -8,15 +8,17 @@
#line 1 "app/online/ac_ol_0007.pgc"
/* @tier easy @module ac @transform acquire-online */
/*
* ac_ol_0007.pgc - (AC_OL_0007) [tier=easy]
* ac_ol_0007.pgc - (AC_OL_0007) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* (CAPAMT) .
* , (acq_type='PART', orig_key )
* .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,37 +91,166 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0007.pgc"
#line 17 "app/online/ac_ol_0007.pgc"
TX_SERVICE(AC_OL_0007, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* exec sql begin declare section */
#line 22 "app/online/ac_ol_0007.pgc"
char h_key [ 16 ] ;
#line 23 "app/online/ac_ol_0007.pgc"
long h_orig_amount ;
#line 24 "app/online/ac_ol_0007.pgc"
char h_merch_id [ 16 ] ;
#line 25 "app/online/ac_ol_0007.pgc"
char h_card_no [ 20 ] ;
#line 26 "app/online/ac_ol_0007.pgc"
char h_biz_date [ 9 ] ;
#line 27 "app/online/ac_ol_0007.pgc"
long h_cap_amount ;
#line 28 "app/online/ac_ol_0007.pgc"
long h_remaining ;
#line 29 "app/online/ac_ol_0007.pgc"
char h_part_key [ 16 ] ;
#line 30 "app/online/ac_ol_0007.pgc"
char h_status [ 2 ] ;
/* exec sql end declare section */
#line 31 "app/online/ac_ol_0007.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0007] 매입 단건조회 서비스 진입");
char key[16];
long capamt = 0;
size_t klen;
tx_log(TX_LOG_INFO, "[AC_OL_0007] 부분매입 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0007] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0007] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
if (tx_buf_getlong(ctx->in, "CAPAMT", &capamt) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0007] CAPAMT 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount , merch_id , card_no , biz_date from ac_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_orig_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_card_no),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 57 "app/online/ac_ol_0007.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0007] 원거래 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_ledger(부분매입대상)");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (!amount_is_valid(capamt) || capamt > h_orig_amount) {
tx_log(TX_LOG_WARN, "[AC_OL_0007] 부분금액 오류 cap=%ld orig=%ld",
capamt, h_orig_amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
h_cap_amount = capamt;
h_remaining = h_orig_amount - capamt;
if (tx_begin() != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0007] tx_begin 경고");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update ac_ledger set amount = $1 , upd_ts = now ( ) where key = $2 ",
ECPGt_long,&(h_remaining),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 87 "app/online/ac_ol_0007.pgc"
if (sqlca.sqlcode != TX_SQL_OK || sqlca.sqlerrd[2] != 1) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger(부분매입)");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 부분매입 내역키 = 원키 앞부분 13자 + "-P" (16바이트 한도 준수) */
klen = strlen(h_key);
if (klen > 13)
klen = 13;
memcpy(h_part_key, h_key, klen);
h_part_key[klen] = '\0';
strcat(h_part_key, "-P");
strncpy(h_status, AC_ST_DONE, sizeof(h_status));
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into ac_ledger ( key , merch_id , card_no , amount , biz_date , status , fee , acq_type , orig_key ) values ( $1 , $2 , $3 , $4 , $5 , $6 , 0 , 'PART' , $7 )",
ECPGt_char,(h_part_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_card_no),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_cap_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 111 "app/online/ac_ol_0007.pgc"
if (sqlca.sqlcode != TX_SQL_OK || sqlca.sqlerrd[2] != 1) {
TX_DBIO_LOG_ERR("INSERT ac_ledger(부분매입내역)");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0007] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "CAPAMT", capamt);
tx_buf_setlong(ctx->out, "REMAINING", h_remaining);
tx_log(TX_LOG_INFO, "[AC_OL_0007] 부분매입 완료 key=%s cap=%ld 잔여=%ld",
key, capamt, h_remaining);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,16 @@
/* @tier easy @module ac @transform acquire-online */
/*
* ac_ol_0007.pgc - 매입 온라인 서비스 (AC_OL_0007) [tier=easy]
* ac_ol_0007.pgc - 부분매입 서비스 (AC_OL_0007) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 원거래 금액 중 일부(CAPAMT)만 매입 처리한다. 원장의 잔여금액을 차감
* 갱신하고, 부분매입 내역행(acq_type='PART', orig_key 연결)을 별도 적재
* 한 뒤 남은 잔여금액을 반환한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,32 +18,112 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0007, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
long h_orig_amount;
char h_merch_id[16];
char h_card_no[20];
char h_biz_date[9];
long h_cap_amount;
long h_remaining;
char h_part_key[16];
char h_status[2];
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0007] 매입 단건조회 서비스 진입");
char key[16];
long capamt = 0;
size_t klen;
tx_log(TX_LOG_INFO, "[AC_OL_0007] 부분매입 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0007] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0007] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
if (tx_buf_getlong(ctx->in, "CAPAMT", &capamt) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0007] CAPAMT 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
EXEC SQL
SELECT amount, merch_id, card_no, biz_date
INTO :h_orig_amount, :h_merch_id, :h_card_no, :h_biz_date
FROM ac_ledger
WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0007] 원거래 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_ledger(부분매입대상)");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (!amount_is_valid(capamt) || capamt > h_orig_amount) {
tx_log(TX_LOG_WARN, "[AC_OL_0007] 부분금액 오류 cap=%ld orig=%ld",
capamt, h_orig_amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
h_cap_amount = capamt;
h_remaining = h_orig_amount - capamt;
if (tx_begin() != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0007] tx_begin 경고");
EXEC SQL
UPDATE ac_ledger
SET amount = :h_remaining,
upd_ts = now()
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK || sqlca.sqlerrd[2] != 1) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger(부분매입)");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 부분매입 내역키 = 원키 앞부분 13자 + "-P" (16바이트 한도 준수) */
klen = strlen(h_key);
if (klen > 13)
klen = 13;
memcpy(h_part_key, h_key, klen);
h_part_key[klen] = '\0';
strcat(h_part_key, "-P");
strncpy(h_status, AC_ST_DONE, sizeof(h_status));
EXEC SQL
INSERT INTO ac_ledger
(key, merch_id, card_no, amount, biz_date, status, fee,
acq_type, orig_key)
VALUES
(:h_part_key, :h_merch_id, :h_card_no, :h_cap_amount, :h_biz_date,
:h_status, 0, 'PART', :h_key);
if (sqlca.sqlcode != TX_SQL_OK || sqlca.sqlerrd[2] != 1) {
TX_DBIO_LOG_ERR("INSERT ac_ledger(부분매입내역)");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0007] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "CAPAMT", capamt);
tx_buf_setlong(ctx->out, "REMAINING", h_remaining);
tx_log(TX_LOG_INFO, "[AC_OL_0007] 부분매입 완료 key=%s cap=%ld 잔여=%ld",
key, capamt, h_remaining);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -8,15 +8,17 @@
#line 1 "app/online/ac_ol_0008.pgc"
/* @tier hard @module ac @transform acquire-online */
/*
* ac_ol_0008.pgc - (AC_OL_0008) [tier=hard]
* ac_ol_0008.pgc - (AC_OL_0008) [tier=hard]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* (MONTHS, install_month>=2)
* ac_ledger (: KEY-01..KEY-NN, acq_type='INST') INSERT .
* 1 . .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,28 +91,71 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0008.pgc"
#line 17 "app/online/ac_ol_0008.pgc"
TX_SERVICE(AC_OL_0008, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16], nextbiz[9];
long amount = 0, daysum = 0;
int rc;
TXBUF *sub_in;
TXBUF *sub_out;
/* exec sql begin declare section */
#line 22 "app/online/ac_ol_0008.pgc"
char h_merch_id [ 16 ] ;
#line 23 "app/online/ac_ol_0008.pgc"
char h_card_no [ 20 ] ;
#line 24 "app/online/ac_ol_0008.pgc"
char h_biz_date [ 9 ] ;
#line 25 "app/online/ac_ol_0008.pgc"
char h_status [ 2 ] ;
#line 26 "app/online/ac_ol_0008.pgc"
char h_acq_type [ 4 ] ;
#line 27 "app/online/ac_ol_0008.pgc"
char h_row_key [ 16 ] ;
#line 28 "app/online/ac_ol_0008.pgc"
long h_row_amount ;
#line 29 "app/online/ac_ol_0008.pgc"
long h_row_fee ;
#line 30 "app/online/ac_ol_0008.pgc"
int h_install_month ;
/* exec sql end declare section */
#line 31 "app/online/ac_ol_0008.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0008] 매입 트랜잭션 오케스트레이션 진입");
char key[16], merch[16], card[20], bizdate[16];
char base_key[16];
long amount = 0, months_l = 0;
long monthly, remainder, row_amt, totalfee = 0;
int months, i, errcnt = 0;
size_t klen;
tx_log(TX_LOG_INFO, "[AC_OL_0008] 할부매입 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "CARDNO", card, sizeof(card)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0008] 필수 필드 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
tx_buf_getlong(ctx->in, "MONTHS", &months_l);
if (!amount_is_valid(amount) || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0008] 입력 검증 실패 amount=%ld date=%s",
@ -118,59 +163,91 @@ TX_SERVICE(AC_OL_0008, ctx)
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* 트랜잭션 시작 → 원장 반영 → 후속 서비스 연계 → 커밋 */
if (tx_begin() != TX_OK) {
tx_return(ctx, TX_FAIL, ctx->out);
if (months_l < 2) {
tx_log(TX_LOG_WARN, "[AC_OL_0008] 할부개월 오류 months=%ld", months_l);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
months = (int)months_l;
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100;
monthly = amount / months;
remainder = amount - (monthly * months);
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0008] 원장반영 실패 rc=%d", rc);
/* 원거래키 앞부분 12자 + "-NN" (16바이트 한도 준수) */
klen = strlen(key);
if (klen > 12)
klen = 12;
memcpy(base_key, key, klen);
base_key[klen] = '\0';
strncpy(h_merch_id, merch, sizeof(h_merch_id) - 1);
h_merch_id[sizeof(h_merch_id) - 1] = '\0';
strncpy(h_card_no, card, sizeof(h_card_no) - 1);
h_card_no[sizeof(h_card_no) - 1] = '\0';
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
h_biz_date[sizeof(h_biz_date) - 1] = '\0';
strncpy(h_status, AC_ST_RECV, sizeof(h_status));
strncpy(h_acq_type, "INST", sizeof(h_acq_type) - 1);
h_acq_type[sizeof(h_acq_type) - 1] = '\0';
if (tx_begin() != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0008] tx_begin 경고");
for (i = 1; i <= months; i++) {
row_amt = (i == 1) ? (monthly + remainder) : monthly;
snprintf(h_row_key, sizeof(h_row_key), "%s-%02d", base_key, i);
h_row_amount = row_amt;
h_row_fee = row_amt * 25 / 10000; /* 할부 수수료 0.25% */
h_install_month = i;
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into ac_ledger ( key , merch_id , card_no , amount , biz_date , status , fee , acq_type , install_month ) values ( $1 , $2 , $3 , $4 , $5 , $6 , $7 , $8 , $9 )",
ECPGt_char,(h_row_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_card_no),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_row_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_row_fee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_acq_type),(long)4,(long)1,(4)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_int,&(h_install_month),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 103 "app/online/ac_ol_0008.pgc"
if (sqlca.sqlcode != TX_SQL_OK || sqlca.sqlerrd[2] != 1) {
TX_DBIO_LOG_ERR("INSERT ac_ledger(할부회차)");
errcnt++;
break;
}
totalfee += h_row_fee;
}
if (errcnt > 0) {
tx_abort();
tx_return(ctx, rc, ctx->out);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 정산 영업일 = 거래일의 다음 영업일 */
if (date_next_business(bizdate, nextbiz) != 0) {
memcpy(nextbiz, bizdate, 8);
nextbiz[8] = '\0';
}
/* 후속 정산집계 서비스 연계 (레지스트리 문자열 디스패치) */
sub_in = tx_buf_alloc();
sub_out = tx_buf_alloc();
if (sub_in && sub_out) {
tx_buf_sets(sub_in, "MERCHID", merch);
tx_buf_sets(sub_in, "BIZDATE", nextbiz);
tx_buf_setlong(sub_in, "AMOUNT", amount);
rc = tx_call("AC_POST", sub_in, sub_out);
if (rc != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0008] 후속연계 경고 rc=%d", rc);
}
tx_buf_free(sub_in);
tx_buf_free(sub_out);
/* 교차 검증: 당일 합계 재계산 */
if (ac_rec_sum(bizdate, &daysum) != TX_OK)
daysum = 0;
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYSUM", daysum);
tx_log(TX_LOG_INFO, "[AC_OL_0008] 완료 key=%s 당일합계=%ld", key, daysum);
tx_buf_setlong(ctx->out, "MONTHCNT", months);
tx_buf_setlong(ctx->out, "FIRSTAMT", monthly + remainder);
tx_buf_setlong(ctx->out, "MONTHLYAMT", monthly);
tx_buf_setlong(ctx->out, "TOTALFEE", totalfee);
tx_log(TX_LOG_INFO,
"[AC_OL_0008] 할부매입 완료 key=%s 총액=%ld 개월=%d 1회차=%ld 월분=%ld",
key, amount, months, monthly + remainder, monthly);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,16 @@
/* @tier hard @module ac @transform acquire-online */
/*
* ac_ol_0008.pgc - 매입 온라인 서비스 (AC_OL_0008) [tier=hard]
* ac_ol_0008.pgc - 할부매입 서비스 (AC_OL_0008) [tier=hard]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 총 매입금액을 개월수(MONTHS, install_month>=2)로 분할하여 월별
* ac_ledger 행(키: KEY-01..KEY-NN, acq_type='INST')을 순차 INSERT 한다.
* 나머지 금액은 1회차에 몰아준다. 전 과정은 하나의 트랜잭션으로 처리.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,23 +18,37 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0008, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16], nextbiz[9];
long amount = 0, daysum = 0;
int rc;
TXBUF *sub_in;
TXBUF *sub_out;
EXEC SQL BEGIN DECLARE SECTION;
char h_merch_id[16];
char h_card_no[20];
char h_biz_date[9];
char h_status[2];
char h_acq_type[4];
char h_row_key[16];
long h_row_amount;
long h_row_fee;
int h_install_month;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0008] 매입 트랜잭션 오케스트레이션 진입");
char key[16], merch[16], card[20], bizdate[16];
char base_key[16];
long amount = 0, months_l = 0;
long monthly, remainder, row_amt, totalfee = 0;
int months, i, errcnt = 0;
size_t klen;
tx_log(TX_LOG_INFO, "[AC_OL_0008] 할부매입 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "CARDNO", card, sizeof(card)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0008] 필수 필드 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
tx_buf_getlong(ctx->in, "MONTHS", &months_l);
if (!amount_is_valid(amount) || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0008] 입력 검증 실패 amount=%ld date=%s",
@ -40,59 +56,77 @@ TX_SERVICE(AC_OL_0008, ctx)
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* 트랜잭션 시작 → 원장 반영 → 후속 서비스 연계 → 커밋 */
if (tx_begin() != TX_OK) {
tx_return(ctx, TX_FAIL, ctx->out);
if (months_l < 2) {
tx_log(TX_LOG_WARN, "[AC_OL_0008] 할부개월 오류 months=%ld", months_l);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
months = (int)months_l;
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100;
monthly = amount / months;
remainder = amount - (monthly * months);
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0008] 원장반영 실패 rc=%d", rc);
/* 원거래키 앞부분 12자 + "-NN" (16바이트 한도 준수) */
klen = strlen(key);
if (klen > 12)
klen = 12;
memcpy(base_key, key, klen);
base_key[klen] = '\0';
strncpy(h_merch_id, merch, sizeof(h_merch_id) - 1);
h_merch_id[sizeof(h_merch_id) - 1] = '\0';
strncpy(h_card_no, card, sizeof(h_card_no) - 1);
h_card_no[sizeof(h_card_no) - 1] = '\0';
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
h_biz_date[sizeof(h_biz_date) - 1] = '\0';
strncpy(h_status, AC_ST_RECV, sizeof(h_status));
strncpy(h_acq_type, "INST", sizeof(h_acq_type) - 1);
h_acq_type[sizeof(h_acq_type) - 1] = '\0';
if (tx_begin() != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0008] tx_begin 경고");
for (i = 1; i <= months; i++) {
row_amt = (i == 1) ? (monthly + remainder) : monthly;
snprintf(h_row_key, sizeof(h_row_key), "%s-%02d", base_key, i);
h_row_amount = row_amt;
h_row_fee = row_amt * 25 / 10000; /* 할부 수수료 0.25% */
h_install_month = i;
EXEC SQL
INSERT INTO ac_ledger
(key, merch_id, card_no, amount, biz_date, status, fee,
acq_type, install_month)
VALUES
(:h_row_key, :h_merch_id, :h_card_no, :h_row_amount, :h_biz_date,
:h_status, :h_row_fee, :h_acq_type, :h_install_month);
if (sqlca.sqlcode != TX_SQL_OK || sqlca.sqlerrd[2] != 1) {
TX_DBIO_LOG_ERR("INSERT ac_ledger(할부회차)");
errcnt++;
break;
}
totalfee += h_row_fee;
}
if (errcnt > 0) {
tx_abort();
tx_return(ctx, rc, ctx->out);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 정산 영업일 = 거래일의 다음 영업일 */
if (date_next_business(bizdate, nextbiz) != 0) {
memcpy(nextbiz, bizdate, 8);
nextbiz[8] = '\0';
}
/* 후속 정산집계 서비스 연계 (레지스트리 문자열 디스패치) */
sub_in = tx_buf_alloc();
sub_out = tx_buf_alloc();
if (sub_in && sub_out) {
tx_buf_sets(sub_in, "MERCHID", merch);
tx_buf_sets(sub_in, "BIZDATE", nextbiz);
tx_buf_setlong(sub_in, "AMOUNT", amount);
rc = tx_call("AC_POST", sub_in, sub_out);
if (rc != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0008] 후속연계 경고 rc=%d", rc);
}
tx_buf_free(sub_in);
tx_buf_free(sub_out);
/* 교차 검증: 당일 합계 재계산 */
if (ac_rec_sum(bizdate, &daysum) != TX_OK)
daysum = 0;
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYSUM", daysum);
tx_log(TX_LOG_INFO, "[AC_OL_0008] 완료 key=%s 당일합계=%ld", key, daysum);
tx_buf_setlong(ctx->out, "MONTHCNT", months);
tx_buf_setlong(ctx->out, "FIRSTAMT", monthly + remainder);
tx_buf_setlong(ctx->out, "MONTHLYAMT", monthly);
tx_buf_setlong(ctx->out, "TOTALFEE", totalfee);
tx_log(TX_LOG_INFO,
"[AC_OL_0008] 할부매입 완료 key=%s 총액=%ld 개월=%d 1회차=%ld 월분=%ld",
key, amount, months, monthly + remainder, monthly);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,15 @@
/*
* ac_ol_0009.pgc - (AC_OL_0009) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : ( 2 , *100)
* fx_rate . KEY ac_ledger
* (//) .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,37 +91,130 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0009.pgc"
#line 17 "app/online/ac_ol_0009.pgc"
TX_SERVICE(AC_OL_0009, ctx)
{
ac_rec_t rec;
/* exec sql begin declare section */
#line 22 "app/online/ac_ol_0009.pgc"
char h_cur [ 4 ] ;
#line 23 "app/online/ac_ol_0009.pgc"
char h_bizdate [ 9 ] ;
#line 24 "app/online/ac_ol_0009.pgc"
long h_fxamt ;
#line 25 "app/online/ac_ol_0009.pgc"
long h_rate ;
#line 26 "app/online/ac_ol_0009.pgc"
char h_key [ 16 ] ;
#line 27 "app/online/ac_ol_0009.pgc"
long h_krw ;
/* exec sql end declare section */
#line 28 "app/online/ac_ol_0009.pgc"
char curcode[4];
char bizdate[9];
char key[16];
int rc;
long fxamt = 0;
long krw;
int has_key;
tx_log(TX_LOG_INFO, "[AC_OL_0009] 매입 단건조회 서비스 진입");
tx_log(TX_LOG_INFO, "[AC_OL_0009] 해외매입 환산 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0009] KEY 누락");
if (tx_buf_get(ctx->in, "CURCODE", curcode, sizeof(curcode)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0009] 필수 필드 누락(CURCODE/BIZDATE)");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "FXAMT", &fxamt);
if (curcode[0] == '\0' || !date_is_valid(bizdate) || !amount_is_valid(fxamt)) {
tx_log(TX_LOG_WARN, "[AC_OL_0009] 입력 검증 실패 cur=%s date=%s fxamt=%ld",
curcode, bizdate, fxamt);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0009] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
strncpy(h_cur, curcode, sizeof(h_cur) - 1);
h_cur[sizeof(h_cur) - 1] = '\0';
strncpy(h_bizdate, bizdate, sizeof(h_bizdate) - 1);
h_bizdate[sizeof(h_bizdate) - 1] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select base_rate from fx_rate where cur_code = $1 and rate_date = $2 ",
ECPGt_char,(h_cur),(long)4,(long)1,(4)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_bizdate),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_rate),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 62 "app/online/ac_ol_0009.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0009] 고시환율 없음 cur=%s date=%s", curcode, bizdate);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0009 fx_rate select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
h_fxamt = fxamt;
krw = (h_fxamt * h_rate) / 10000; /* base_rate 는 10000 배 스케일 고시값 */
/* KEY 가 함께 오면 원장에 환산결과 반영 (조회성 호출이면 생략 가능) */
has_key = (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) == TX_OK && key[0] != '\0');
if (has_key) {
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
h_krw = krw;
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update ac_ledger set amount = $1 , fx_amount = $2 , cur_code = $3 , upd_ts = now ( ) where key = $4 ",
ECPGt_long,&(h_krw),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_fxamt),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_cur),(long)4,(long)1,(4)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 87 "app/online/ac_ol_0009.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0009 ac_ledger update");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0)
tx_log(TX_LOG_WARN, "[AC_OL_0009] 반영대상 원장 없음 key=%s", key);
else
tx_log(TX_LOG_INFO, "[AC_OL_0009] 원장반영 완료 key=%s krw=%ld", key, krw);
}
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0009] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "CURCODE", curcode);
tx_buf_setlong(ctx->out, "FXAMT", fxamt);
tx_buf_setlong(ctx->out, "RATE", h_rate);
tx_buf_setlong(ctx->out, "KRWAMT", krw);
tx_log(TX_LOG_INFO, "[AC_OL_0009] 환산완료 cur=%s fxamt=%ld rate=%ld krw=%ld",
curcode, fxamt, h_rate, krw);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,15 @@
/*
* ac_ol_0009.pgc - 매입 온라인 서비스 (AC_OL_0009) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 해외매입 환산: 외화금액(소수 2자리 포함 정수, 즉 외화금액*100)을
* fx_rate 고시환율로 원화 환산한다. KEY 가 함께 오면 ac_ledger 원장에
* 환산결과(원화금액/외화금액/통화코드)를 반영한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,32 +18,92 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0009, ctx)
{
ac_rec_t rec;
EXEC SQL BEGIN DECLARE SECTION;
char h_cur[4];
char h_bizdate[9];
long h_fxamt;
long h_rate;
char h_key[16];
long h_krw;
EXEC SQL END DECLARE SECTION;
char curcode[4];
char bizdate[9];
char key[16];
int rc;
long fxamt = 0;
long krw;
int has_key;
tx_log(TX_LOG_INFO, "[AC_OL_0009] 매입 단건조회 서비스 진입");
tx_log(TX_LOG_INFO, "[AC_OL_0009] 해외매입 환산 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0009] KEY 누락");
if (tx_buf_get(ctx->in, "CURCODE", curcode, sizeof(curcode)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0009] 필수 필드 누락(CURCODE/BIZDATE)");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "FXAMT", &fxamt);
if (curcode[0] == '\0' || !date_is_valid(bizdate) || !amount_is_valid(fxamt)) {
tx_log(TX_LOG_WARN, "[AC_OL_0009] 입력 검증 실패 cur=%s date=%s fxamt=%ld",
curcode, bizdate, fxamt);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0009] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
strncpy(h_cur, curcode, sizeof(h_cur) - 1);
h_cur[sizeof(h_cur) - 1] = '\0';
strncpy(h_bizdate, bizdate, sizeof(h_bizdate) - 1);
h_bizdate[sizeof(h_bizdate) - 1] = '\0';
EXEC SQL SELECT base_rate
INTO :h_rate
FROM fx_rate
WHERE cur_code = :h_cur AND rate_date = :h_bizdate;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0009] 고시환율 없음 cur=%s date=%s", curcode, bizdate);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0009 fx_rate select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
h_fxamt = fxamt;
krw = (h_fxamt * h_rate) / 10000; /* base_rate 는 10000 배 스케일 고시값 */
/* KEY 가 함께 오면 원장에 환산결과 반영 (조회성 호출이면 생략 가능) */
has_key = (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) == TX_OK && key[0] != '\0');
if (has_key) {
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
h_krw = krw;
EXEC SQL UPDATE ac_ledger
SET amount = :h_krw, fx_amount = :h_fxamt, cur_code = :h_cur, upd_ts = now()
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0009 ac_ledger update");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0)
tx_log(TX_LOG_WARN, "[AC_OL_0009] 반영대상 원장 없음 key=%s", key);
else
tx_log(TX_LOG_INFO, "[AC_OL_0009] 원장반영 완료 key=%s krw=%ld", key, krw);
}
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0009] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "CURCODE", curcode);
tx_buf_setlong(ctx->out, "FXAMT", fxamt);
tx_buf_setlong(ctx->out, "RATE", h_rate);
tx_buf_setlong(ctx->out, "KRWAMT", krw);
tx_log(TX_LOG_INFO, "[AC_OL_0009] 환산완료 cur=%s fxamt=%ld rate=%ld krw=%ld",
curcode, fxamt, h_rate, krw);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,14 @@
/*
* ac_ol_0010.pgc - (AC_OL_0010) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : ( )
* merchant.limit_amt . TX_FAIL .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,37 +90,120 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0010.pgc"
#line 16 "app/online/ac_ol_0010.pgc"
TX_SERVICE(AC_OL_0010, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* exec sql begin declare section */
#line 21 "app/online/ac_ol_0010.pgc"
char h_merch [ 16 ] ;
#line 22 "app/online/ac_ol_0010.pgc"
char h_today [ 9 ] ;
#line 23 "app/online/ac_ol_0010.pgc"
long h_limit ;
#line 24 "app/online/ac_ol_0010.pgc"
long h_used ;
/* exec sql end declare section */
#line 25 "app/online/ac_ol_0010.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0010] 매입 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0010] KEY 누락");
char merch[16];
char today[9];
long amount = 0;
long remain;
int over;
tx_log(TX_LOG_INFO, "[AC_OL_0010] 매입 한도체크 서비스 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0010] MERCHID 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
if (merch[0] == '\0' || !amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0010] 입력 검증 실패 merch=%s amount=%ld", merch, amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0010] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
strncpy(h_merch, merch, sizeof(h_merch) - 1);
h_merch[sizeof(h_merch) - 1] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select limit_amt from merchant where merch_id = $1 ",
ECPGt_char,(h_merch),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_limit),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 54 "app/online/ac_ol_0010.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0010] 가맹점 없음 merch=%s", merch);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_NOMERCH);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0010 merchant select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
date_today(today);
strncpy(h_today, today, sizeof(h_today) - 1);
h_today[sizeof(h_today) - 1] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select coalesce ( sum ( amount ) , 0 ) from ac_ledger where merch_id = $1 and biz_date = $2 and status <> 'U'",
ECPGt_char,(h_merch),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_today),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_used),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 78 "app/online/ac_ol_0010.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0010 ac_ledger sum select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
over = (h_used + amount > h_limit) ? 1 : 0;
remain = h_limit - h_used - amount;
if (remain < 0)
remain = 0;
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0010] 조회완료 key=%s amount=%ld", key, rec.amount);
if (over) {
tx_log(TX_LOG_WARN, "[AC_OL_0010] 한도초과 merch=%s used=%ld amount=%ld limit=%ld",
merch, h_used, amount, h_limit);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_buf_setlong(ctx->out, "OVER", 1);
tx_buf_setlong(ctx->out, "LIMIT", h_limit);
tx_buf_setlong(ctx->out, "USED", h_used);
tx_buf_setlong(ctx->out, "REMAIN", 0);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_setlong(ctx->out, "OVER", 0);
tx_buf_setlong(ctx->out, "LIMIT", h_limit);
tx_buf_setlong(ctx->out, "USED", h_used);
tx_buf_setlong(ctx->out, "REMAIN", remain);
tx_log(TX_LOG_INFO, "[AC_OL_0010] 한도체크 통과 merch=%s remain=%ld", merch, remain);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,14 @@
/*
* ac_ol_0010.pgc - 매입 온라인 서비스 (AC_OL_0010) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 매입 한도체크: 가맹점의 당일 누적매입액(미확정 제외)에 신규 매입금액을
* 더해 merchant.limit_amt 를 넘는지 검사한다. 초과 시 TX_FAIL 로 거절한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,32 +17,95 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0010, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_merch[16];
char h_today[9];
long h_limit;
long h_used;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0010] 매입 단건조회 서비스 진입");
char merch[16];
char today[9];
long amount = 0;
long remain;
int over;
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0010] KEY 누락");
tx_log(TX_LOG_INFO, "[AC_OL_0010] 매입 한도체크 서비스 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0010] MERCHID 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
if (merch[0] == '\0' || !amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0010] 입력 검증 실패 merch=%s amount=%ld", merch, amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0010] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
strncpy(h_merch, merch, sizeof(h_merch) - 1);
h_merch[sizeof(h_merch) - 1] = '\0';
EXEC SQL SELECT limit_amt
INTO :h_limit
FROM merchant
WHERE merch_id = :h_merch;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0010] 가맹점 없음 merch=%s", merch);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_NOMERCH);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0010 merchant select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
date_today(today);
strncpy(h_today, today, sizeof(h_today) - 1);
h_today[sizeof(h_today) - 1] = '\0';
EXEC SQL SELECT coalesce(sum(amount), 0)
INTO :h_used
FROM ac_ledger
WHERE merch_id = :h_merch
AND biz_date = :h_today
AND status <> 'U';
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0010 ac_ledger sum select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
over = (h_used + amount > h_limit) ? 1 : 0;
remain = h_limit - h_used - amount;
if (remain < 0)
remain = 0;
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0010] 조회완료 key=%s amount=%ld", key, rec.amount);
if (over) {
tx_log(TX_LOG_WARN, "[AC_OL_0010] 한도초과 merch=%s used=%ld amount=%ld limit=%ld",
merch, h_used, amount, h_limit);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_buf_setlong(ctx->out, "OVER", 1);
tx_buf_setlong(ctx->out, "LIMIT", h_limit);
tx_buf_setlong(ctx->out, "USED", h_used);
tx_buf_setlong(ctx->out, "REMAIN", 0);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_setlong(ctx->out, "OVER", 0);
tx_buf_setlong(ctx->out, "LIMIT", h_limit);
tx_buf_setlong(ctx->out, "USED", h_used);
tx_buf_setlong(ctx->out, "REMAIN", remain);
tx_log(TX_LOG_INFO, "[AC_OL_0010] 한도체크 통과 merch=%s remain=%ld", merch, remain);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,15 @@
/*
* ac_ol_0011.pgc - (AC_OL_0011) [tier=medium]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : ///
* .
* TX_FAIL .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,28 +91,59 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0011.pgc"
#line 17 "app/online/ac_ol_0011.pgc"
TX_SERVICE(AC_OL_0011, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
/* exec sql begin declare section */
#line 22 "app/online/ac_ol_0011.pgc"
char h_merch [ 16 ] ;
#line 23 "app/online/ac_ol_0011.pgc"
char h_card [ 20 ] ;
#line 24 "app/online/ac_ol_0011.pgc"
long h_amount ;
#line 25 "app/online/ac_ol_0011.pgc"
char h_bizdate [ 9 ] ;
#line 26 "app/online/ac_ol_0011.pgc"
int h_cnt ;
#line 27 "app/online/ac_ol_0011.pgc"
char h_exist_key [ 16 ] ;
/* exec sql end declare section */
#line 28 "app/online/ac_ol_0011.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0011] 매입 등록 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
char merch[16];
char card[20];
char bizdate[9];
long amount = 0;
long dup;
char exist_key[16];
int found_exist;
tx_log(TX_LOG_INFO, "[AC_OL_0011] 매입 중복검사 서비스 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "CARDNO", card, sizeof(card)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0011] 필수 필드 누락");
tx_log(TX_LOG_ERROR, "[AC_OL_0011] 필수 필드 누락(MERCHID/CARDNO/BIZDATE)");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0011] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
@ -122,27 +155,78 @@ TX_SERVICE(AC_OL_0011, ctx)
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_merch, merch, sizeof(h_merch) - 1);
h_merch[sizeof(h_merch) - 1] = '\0';
strncpy(h_card, card, sizeof(h_card) - 1);
h_card[sizeof(h_card) - 1] = '\0';
strncpy(h_bizdate, bizdate, sizeof(h_bizdate) - 1);
h_bizdate[sizeof(h_bizdate) - 1] = '\0';
h_amount = amount;
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0011] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select count ( * ) from ac_ledger where merch_id = $1 and card_no = $2 and amount = $3 and biz_date = $4 and status <> 'U'",
ECPGt_char,(h_merch),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_card),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_bizdate),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_int,&(h_cnt),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 75 "app/online/ac_ol_0011.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0011 dup count select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
dup = (long)h_cnt;
tx_buf_reset(ctx->out);
if (dup > 0) {
/* 중복건 중 하나의 기존 원장키를 참고용으로 조회한다 */
found_exist = 0;
exist_key[0] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select key from ac_ledger where merch_id = $1 and card_no = $2 and amount = $3 and biz_date = $4 and status <> 'U' limit 1",
ECPGt_char,(h_merch),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_card),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_bizdate),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_char,(h_exist_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 98 "app/online/ac_ol_0011.pgc"
if (sqlca.sqlcode == TX_SQL_OK) {
found_exist = 1;
strncpy(exist_key, h_exist_key, sizeof(exist_key) - 1);
exist_key[sizeof(exist_key) - 1] = '\0';
} else if (sqlca.sqlcode != TX_SQL_NOTFOUND) {
TX_DBIO_LOG_ERR("AC_OL_0011 exist key select");
}
tx_log(TX_LOG_WARN, "[AC_OL_0011] 중복매입 감지 merch=%s card=%s amount=%ld date=%s cnt=%ld",
merch, card, amount, bizdate, dup);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_buf_setlong(ctx->out, "DUP", 1);
tx_buf_setlong(ctx->out, "DUPCNT", dup);
if (found_exist)
tx_buf_sets(ctx->out, "EXISTKEY", exist_key);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
cnt = ac_rec_count(bizdate, AC_ST_RECV);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0011] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_setlong(ctx->out, "DUP", 0);
tx_buf_setlong(ctx->out, "DUPCNT", 0);
tx_log(TX_LOG_INFO, "[AC_OL_0011] 중복없음 merch=%s card=%s amount=%ld date=%s",
merch, card, amount, bizdate);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,15 @@
/*
* ac_ol_0011.pgc - 매입 온라인 서비스 (AC_OL_0011) [tier=medium]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 매입 중복검사: 동일 가맹점/카드/금액/영업일 조합이 이미 유효 상태로
* 존재하는지 검사한다. 중복이면 기존 원장키를 조회해 함께 반환하고
* TX_FAIL 로 경보한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,23 +18,34 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0011, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_merch[16];
char h_card[20];
long h_amount;
char h_bizdate[9];
int h_cnt;
char h_exist_key[16];
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0011] 매입 등록 서비스 진입");
char merch[16];
char card[20];
char bizdate[9];
long amount = 0;
long dup;
char exist_key[16];
int found_exist;
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_log(TX_LOG_INFO, "[AC_OL_0011] 매입 중복검사 서비스 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "CARDNO", card, sizeof(card)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0011] 필수 필드 누락");
tx_log(TX_LOG_ERROR, "[AC_OL_0011] 필수 필드 누락(MERCHID/CARDNO/BIZDATE)");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0011] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
@ -44,27 +57,69 @@ TX_SERVICE(AC_OL_0011, ctx)
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_merch, merch, sizeof(h_merch) - 1);
h_merch[sizeof(h_merch) - 1] = '\0';
strncpy(h_card, card, sizeof(h_card) - 1);
h_card[sizeof(h_card) - 1] = '\0';
strncpy(h_bizdate, bizdate, sizeof(h_bizdate) - 1);
h_bizdate[sizeof(h_bizdate) - 1] = '\0';
h_amount = amount;
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0011] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
EXEC SQL SELECT count(*)
INTO :h_cnt
FROM ac_ledger
WHERE merch_id = :h_merch
AND card_no = :h_card
AND amount = :h_amount
AND biz_date = :h_bizdate
AND status <> 'U';
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0011 dup count select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
dup = (long)h_cnt;
tx_buf_reset(ctx->out);
if (dup > 0) {
/* 중복건 중 하나의 기존 원장키를 참고용으로 조회한다 */
found_exist = 0;
exist_key[0] = '\0';
EXEC SQL SELECT key
INTO :h_exist_key
FROM ac_ledger
WHERE merch_id = :h_merch
AND card_no = :h_card
AND amount = :h_amount
AND biz_date = :h_bizdate
AND status <> 'U'
LIMIT 1;
if (sqlca.sqlcode == TX_SQL_OK) {
found_exist = 1;
strncpy(exist_key, h_exist_key, sizeof(exist_key) - 1);
exist_key[sizeof(exist_key) - 1] = '\0';
} else if (sqlca.sqlcode != TX_SQL_NOTFOUND) {
TX_DBIO_LOG_ERR("AC_OL_0011 exist key select");
}
tx_log(TX_LOG_WARN, "[AC_OL_0011] 중복매입 감지 merch=%s card=%s amount=%ld date=%s cnt=%ld",
merch, card, amount, bizdate, dup);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_buf_setlong(ctx->out, "DUP", 1);
tx_buf_setlong(ctx->out, "DUPCNT", dup);
if (found_exist)
tx_buf_sets(ctx->out, "EXISTKEY", exist_key);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
cnt = ac_rec_count(bizdate, AC_ST_RECV);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0011] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_setlong(ctx->out, "DUP", 0);
tx_buf_setlong(ctx->out, "DUPCNT", 0);
tx_log(TX_LOG_INFO, "[AC_OL_0011] 중복없음 merch=%s card=%s amount=%ld date=%s",
merch, card, amount, bizdate);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,15 @@
/*
* ac_ol_0012.pgc - (AC_OL_0012) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : KEY . NEWRATE(bp)
* , merchant.fee_rate
* ac_ledger.fee .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,37 +91,130 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0012.pgc"
#line 17 "app/online/ac_ol_0012.pgc"
TX_SERVICE(AC_OL_0012, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* exec sql begin declare section */
#line 22 "app/online/ac_ol_0012.pgc"
char h_key [ 16 ] ;
#line 23 "app/online/ac_ol_0012.pgc"
long h_amount ;
#line 24 "app/online/ac_ol_0012.pgc"
char h_merch [ 16 ] ;
#line 25 "app/online/ac_ol_0012.pgc"
long h_oldfee ;
#line 26 "app/online/ac_ol_0012.pgc"
long h_rate ;
#line 27 "app/online/ac_ol_0012.pgc"
long h_newfee ;
/* exec sql end declare section */
#line 28 "app/online/ac_ol_0012.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0012] 매입 단건조회 서비스 진입");
char key[16];
long newrate = 0;
int has_newrate;
tx_log(TX_LOG_INFO, "[AC_OL_0012] 매입 수수료 조정 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0012] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
has_newrate = (tx_buf_getlong(ctx->in, "NEWRATE", &newrate) == TX_OK && newrate > 0);
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0012] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount , merch_id , fee from ac_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_oldfee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 49 "app/online/ac_ol_0012.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0012] 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0012 ac_ledger select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (has_newrate) {
h_rate = newrate;
} else {
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select fee_rate from merchant where merch_id = $1 ",
ECPGt_char,(h_merch),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_rate),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 68 "app/online/ac_ol_0012.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0012] 가맹점 요율 없음 merch=%s", h_merch);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0012 merchant select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
}
h_newfee = (h_amount * h_rate) / 10000;
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update ac_ledger set fee = $1 , upd_ts = now ( ) where key = $2 ",
ECPGt_long,&(h_newfee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 86 "app/online/ac_ol_0012.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0012 ac_ledger update");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0012] 수수료 갱신대상 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0012] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "RATE", h_rate);
tx_buf_setlong(ctx->out, "OLDFEE", h_oldfee);
tx_buf_setlong(ctx->out, "NEWFEE", h_newfee);
tx_log(TX_LOG_INFO, "[AC_OL_0012] 수수료조정 완료 key=%s old=%ld new=%ld rate=%ld",
key, h_oldfee, h_newfee, h_rate);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,15 @@
/*
* ac_ol_0012.pgc - 매입 온라인 서비스 (AC_OL_0012) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 매입 수수료 조정: KEY 원장의 수수료를 재계산한다. NEWRATE(bp)가 오면
* 해당 요율을, 없으면 merchant.fee_rate 를 사용해 신규 수수료를 산출하고
* ac_ledger.fee 를 갱신한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,32 +18,91 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0012, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
long h_amount;
char h_merch[16];
long h_oldfee;
long h_rate;
long h_newfee;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0012] 매입 단건조회 서비스 진입");
char key[16];
long newrate = 0;
int has_newrate;
tx_log(TX_LOG_INFO, "[AC_OL_0012] 매입 수수료 조정 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0012] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
has_newrate = (tx_buf_getlong(ctx->in, "NEWRATE", &newrate) == TX_OK && newrate > 0);
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0012] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
EXEC SQL SELECT amount, merch_id, fee
INTO :h_amount, :h_merch, :h_oldfee
FROM ac_ledger
WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0012] 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0012 ac_ledger select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (has_newrate) {
h_rate = newrate;
} else {
EXEC SQL SELECT fee_rate
INTO :h_rate
FROM merchant
WHERE merch_id = :h_merch;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0012] 가맹점 요율 없음 merch=%s", h_merch);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0012 merchant select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
}
h_newfee = (h_amount * h_rate) / 10000;
EXEC SQL UPDATE ac_ledger
SET fee = :h_newfee, upd_ts = now()
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0012 ac_ledger update");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0012] 수수료 갱신대상 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0012] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "RATE", h_rate);
tx_buf_setlong(ctx->out, "OLDFEE", h_oldfee);
tx_buf_setlong(ctx->out, "NEWFEE", h_newfee);
tx_log(TX_LOG_INFO, "[AC_OL_0012] 수수료조정 완료 key=%s old=%ld new=%ld rate=%ld",
key, h_oldfee, h_newfee, h_rate);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,15 @@
/*
* ac_ol_0013.pgc - (AC_OL_0013) [tier=medium]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* ( ): (R)
* .
* (M) .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,60 +91,130 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0013.pgc"
#line 17 "app/online/ac_ol_0013.pgc"
TX_SERVICE(AC_OL_0013, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
/* exec sql begin declare section */
#line 22 "app/online/ac_ol_0013.pgc"
char h_key [ 16 ] ;
#line 23 "app/online/ac_ol_0013.pgc"
char h_bizdate [ 9 ] ;
#line 24 "app/online/ac_ol_0013.pgc"
char h_status [ 2 ] ;
#line 25 "app/online/ac_ol_0013.pgc"
char h_new_status [ 2 ] ;
#line 26 "app/online/ac_ol_0013.pgc"
char h_settle [ 9 ] ;
/* exec sql end declare section */
#line 27 "app/online/ac_ol_0013.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0013] 매입 등록 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0013] 필수 필드 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
char key[16];
char bizdate[9];
char status[2];
char settle[9];
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0013] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0013] 영업일 오류 date=%s", bizdate);
tx_log(TX_LOG_INFO, "[AC_OL_0013] 선매입(조기매입) 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0013] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0013] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select biz_date , status from ac_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_char,(h_bizdate),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 48 "app/online/ac_ol_0013.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0013] 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0013 ac_ledger select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
cnt = ac_rec_count(bizdate, AC_ST_RECV);
strncpy(bizdate, h_bizdate, sizeof(bizdate) - 1);
bizdate[sizeof(bizdate) - 1] = '\0';
strncpy(status, h_status, sizeof(status) - 1);
status[sizeof(status) - 1] = '\0';
if (strcmp(status, AC_ST_RECV) != 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0013] 조기매입 불가 상태 key=%s status=%s", key, status);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_buf_setlong(ctx->out, "ADVANCED", 0);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
/* 조기 정산목표일 = 거래일의 다음 영업일 */
if (date_next_business(bizdate, settle) != 0) {
strncpy(settle, bizdate, sizeof(settle) - 1);
settle[sizeof(settle) - 1] = '\0';
}
strncpy(h_new_status, AC_ST_DONE, sizeof(h_new_status) - 1);
h_new_status[sizeof(h_new_status) - 1] = '\0';
strncpy(h_settle, settle, sizeof(h_settle) - 1);
h_settle[sizeof(h_settle) - 1] = '\0';
/* 낙관적 갱신: 조회 시점과 동일한 상태(R)일 때만 전환한다 */
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update ac_ledger set status = $1 , settle_date = $2 , upd_ts = now ( ) where key = $3 and status = $4 ",
ECPGt_char,(h_new_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_settle),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 89 "app/online/ac_ol_0013.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0013 ac_ledger update");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0013] 동시성 충돌로 전환 실패 key=%s", key);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_buf_setlong(ctx->out, "ADVANCED", 0);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0013] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_setlong(ctx->out, "ADVANCED", 1);
tx_buf_sets(ctx->out, "SETTLEDATE", settle);
tx_log(TX_LOG_INFO, "[AC_OL_0013] 조기매입 완료 key=%s settle=%s", key, settle);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,15 @@
/*
* ac_ol_0013.pgc - 매입 온라인 서비스 (AC_OL_0013) [tier=medium]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 선매입(정산일 이전 조기매입): 접수 상태(R) 원장만 조기매입 대상으로
* 인정한다. 거래일 다음 영업일을 조기 정산목표일로 계산해 상태를
* 처리완료(M)로 전환하고 정산목표일을 원장에 반영한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,55 +18,95 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0013, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
char h_bizdate[9];
char h_status[2];
char h_new_status[2];
char h_settle[9];
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0013] 매입 등록 서비스 진입");
char key[16];
char bizdate[9];
char status[2];
char settle[9];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0013] 필수 필드 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
tx_log(TX_LOG_INFO, "[AC_OL_0013] 선매입(조기매입) 서비스 진입");
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0013] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0013] 영업일 오류 date=%s", bizdate);
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0013] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0013] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
EXEC SQL SELECT biz_date, status
INTO :h_bizdate, :h_status
FROM ac_ledger
WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0013] 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0013 ac_ledger select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
cnt = ac_rec_count(bizdate, AC_ST_RECV);
strncpy(bizdate, h_bizdate, sizeof(bizdate) - 1);
bizdate[sizeof(bizdate) - 1] = '\0';
strncpy(status, h_status, sizeof(status) - 1);
status[sizeof(status) - 1] = '\0';
if (strcmp(status, AC_ST_RECV) != 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0013] 조기매입 불가 상태 key=%s status=%s", key, status);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_buf_setlong(ctx->out, "ADVANCED", 0);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
/* 조기 정산목표일 = 거래일의 다음 영업일 */
if (date_next_business(bizdate, settle) != 0) {
strncpy(settle, bizdate, sizeof(settle) - 1);
settle[sizeof(settle) - 1] = '\0';
}
strncpy(h_new_status, AC_ST_DONE, sizeof(h_new_status) - 1);
h_new_status[sizeof(h_new_status) - 1] = '\0';
strncpy(h_settle, settle, sizeof(h_settle) - 1);
h_settle[sizeof(h_settle) - 1] = '\0';
/* 낙관적 갱신: 조회 시점과 동일한 상태(R)일 때만 전환한다 */
EXEC SQL UPDATE ac_ledger
SET status = :h_new_status, settle_date = :h_settle, upd_ts = now()
WHERE key = :h_key AND status = :h_status;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0013 ac_ledger update");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0013] 동시성 충돌로 전환 실패 key=%s", key);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_buf_setlong(ctx->out, "ADVANCED", 0);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0013] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_setlong(ctx->out, "ADVANCED", 1);
tx_buf_sets(ctx->out, "SETTLEDATE", settle);
tx_log(TX_LOG_INFO, "[AC_OL_0013] 조기매입 완료 key=%s settle=%s", key, settle);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,15 @@
/*
* ac_ol_0014.pgc - (AC_OL_0014) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : (M)
* // (-)
* .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,37 +91,99 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0014.pgc"
#line 17 "app/online/ac_ol_0014.pgc"
TX_SERVICE(AC_OL_0014, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* exec sql begin declare section */
#line 22 "app/online/ac_ol_0014.pgc"
char h_merch [ 16 ] ;
#line 23 "app/online/ac_ol_0014.pgc"
char h_bizdate [ 9 ] ;
#line 24 "app/online/ac_ol_0014.pgc"
char h_status [ 2 ] ;
#line 25 "app/online/ac_ol_0014.pgc"
int h_cnt ;
#line 26 "app/online/ac_ol_0014.pgc"
long h_totamt ;
#line 27 "app/online/ac_ol_0014.pgc"
long h_totfee ;
/* exec sql end declare section */
#line 28 "app/online/ac_ol_0014.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0014] 매입 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0014] KEY 누락");
char merch[16];
char bizdate[9];
long net;
tx_log(TX_LOG_INFO, "[AC_OL_0014] 가맹점별 매입집계 서비스 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0014] 필수 필드 누락(MERCHID/BIZDATE)");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0014] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
if (merch[0] == '\0' || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0014] 입력 검증 실패 merch=%s date=%s", merch, bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
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';
strncpy(h_status, AC_ST_DONE, sizeof(h_status) - 1);
h_status[sizeof(h_status) - 1] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select count ( * ) , coalesce ( sum ( amount ) , 0 ) , coalesce ( sum ( fee ) , 0 ) from ac_ledger where merch_id = $1 and biz_date = $2 and status = $3 ",
ECPGt_char,(h_merch),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_bizdate),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_int,&(h_cnt),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_totamt),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_totfee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 61 "app/online/ac_ol_0014.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0014 ac_ledger 집계 select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
net = h_totamt - h_totfee;
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0014] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "MERCHID", merch);
tx_buf_sets(ctx->out, "BIZDATE", bizdate);
tx_buf_setlong(ctx->out, "CNT", (long)h_cnt);
tx_buf_setlong(ctx->out, "TOTAMT", h_totamt);
tx_buf_setlong(ctx->out, "TOTFEE", h_totfee);
tx_buf_setlong(ctx->out, "NET", net);
tx_log(TX_LOG_INFO, "[AC_OL_0014] 집계완료 merch=%s date=%s cnt=%d totamt=%ld totfee=%ld net=%ld",
merch, bizdate, h_cnt, h_totamt, h_totfee, net);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,15 @@
/*
* ac_ol_0014.pgc - 매입 온라인 서비스 (AC_OL_0014) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 가맹점별 매입집계: 지정 가맹점의 지정 영업일 처리완료(M) 매입 건에
* 대해 건수/총매입금액/총수수료를 집계하고 순정산금액(총매입-총수수료)을
* 함께 산출한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,32 +18,65 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0014, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_merch[16];
char h_bizdate[9];
char h_status[2];
int h_cnt;
long h_totamt;
long h_totfee;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0014] 매입 단건조회 서비스 진입");
char merch[16];
char bizdate[9];
long net;
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0014] KEY 누락");
tx_log(TX_LOG_INFO, "[AC_OL_0014] 가맹점별 매입집계 서비스 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0014] 필수 필드 누락(MERCHID/BIZDATE)");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0014] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
if (merch[0] == '\0' || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0014] 입력 검증 실패 merch=%s date=%s", merch, bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
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';
strncpy(h_status, AC_ST_DONE, sizeof(h_status) - 1);
h_status[sizeof(h_status) - 1] = '\0';
EXEC SQL SELECT count(*), coalesce(sum(amount), 0), coalesce(sum(fee), 0)
INTO :h_cnt, :h_totamt, :h_totfee
FROM ac_ledger
WHERE merch_id = :h_merch
AND biz_date = :h_bizdate
AND status = :h_status;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0014 ac_ledger 집계 select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
net = h_totamt - h_totfee;
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0014] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "MERCHID", merch);
tx_buf_sets(ctx->out, "BIZDATE", bizdate);
tx_buf_setlong(ctx->out, "CNT", (long)h_cnt);
tx_buf_setlong(ctx->out, "TOTAMT", h_totamt);
tx_buf_setlong(ctx->out, "TOTFEE", h_totfee);
tx_buf_setlong(ctx->out, "NET", net);
tx_log(TX_LOG_INFO, "[AC_OL_0014] 집계완료 merch=%s date=%s cnt=%d totamt=%ld totfee=%ld net=%ld",
merch, bizdate, h_cnt, h_totamt, h_totfee, net);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,15 @@
/*
* ac_ol_0015.pgc - (AC_OL_0015) [tier=medium]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : KEY BIN( 2)
* ('94'KB, '95'SH, '96'HN, ETC).
* ac_ledger.corp_cd .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,60 +91,106 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0015.pgc"
#line 17 "app/online/ac_ol_0015.pgc"
TX_SERVICE(AC_OL_0015, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
/* exec sql begin declare section */
#line 22 "app/online/ac_ol_0015.pgc"
char h_key [ 16 ] ;
#line 23 "app/online/ac_ol_0015.pgc"
char h_card [ 20 ] ;
#line 24 "app/online/ac_ol_0015.pgc"
char h_corp [ 8 ] ;
/* exec sql end declare section */
#line 25 "app/online/ac_ol_0015.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0015] 매입 등록 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0015] 필수 필드 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
char key[16];
char card[20];
char bin[3];
char corp[8];
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0015] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0015] 영업일 오류 date=%s", bizdate);
tx_log(TX_LOG_INFO, "[AC_OL_0015] 카드사별 매입분류 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0015] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0015] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select card_no from ac_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_char,(h_card),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 46 "app/online/ac_ol_0015.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0015] 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0015 ac_ledger select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
cnt = ac_rec_count(bizdate, AC_ST_RECV);
strncpy(card, h_card, sizeof(card) - 1);
card[sizeof(card) - 1] = '\0';
bin[0] = card[0];
bin[1] = card[1];
bin[2] = '\0';
if (strcmp(bin, "94") == 0) {
strcpy(corp, "KB");
} else if (strcmp(bin, "95") == 0) {
strcpy(corp, "SH");
} else if (strcmp(bin, "96") == 0) {
strcpy(corp, "HN");
} else {
strcpy(corp, "ETC");
}
strncpy(h_corp, corp, sizeof(h_corp) - 1);
h_corp[sizeof(h_corp) - 1] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update ac_ledger set corp_cd = $1 , upd_ts = now ( ) where key = $2 ",
ECPGt_char,(h_corp),(long)8,(long)1,(8)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 81 "app/online/ac_ol_0015.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0015 ac_ledger update");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0015] 갱신대상 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0015] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_sets(ctx->out, "CORP", corp);
tx_log(TX_LOG_INFO, "[AC_OL_0015] 카드사분류 완료 key=%s bin=%s corp=%s", key, bin, corp);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,15 @@
/*
* ac_ol_0015.pgc - 매입 온라인 서비스 (AC_OL_0015) [tier=medium]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 카드사별 매입분류: KEY 원장의 카드번호 BIN(앞 2자리)으로 카드사 코드를
* 판별한다('94'→KB, '95'→SH, '96'→HN, 그 외 ETC). 판별한 코드를
* ac_ledger.corp_cd 에 반영한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,55 +18,83 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0015, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
char h_card[20];
char h_corp[8];
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0015] 매입 등록 서비스 진입");
char key[16];
char card[20];
char bin[3];
char corp[8];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0015] 필수 필드 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
tx_log(TX_LOG_INFO, "[AC_OL_0015] 카드사별 매입분류 서비스 진입");
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0015] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0015] 영업일 오류 date=%s", bizdate);
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0015] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0015] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
EXEC SQL SELECT card_no
INTO :h_card
FROM ac_ledger
WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0015] 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0015 ac_ledger select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
cnt = ac_rec_count(bizdate, AC_ST_RECV);
strncpy(card, h_card, sizeof(card) - 1);
card[sizeof(card) - 1] = '\0';
bin[0] = card[0];
bin[1] = card[1];
bin[2] = '\0';
if (strcmp(bin, "94") == 0) {
strcpy(corp, "KB");
} else if (strcmp(bin, "95") == 0) {
strcpy(corp, "SH");
} else if (strcmp(bin, "96") == 0) {
strcpy(corp, "HN");
} else {
strcpy(corp, "ETC");
}
strncpy(h_corp, corp, sizeof(h_corp) - 1);
h_corp[sizeof(h_corp) - 1] = '\0';
EXEC SQL UPDATE ac_ledger
SET corp_cd = :h_corp, upd_ts = now()
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0015 ac_ledger update");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0015] 갱신대상 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0015] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_sets(ctx->out, "CORP", corp);
tx_log(TX_LOG_INFO, "[AC_OL_0015] 카드사분류 완료 key=%s bin=%s corp=%s", key, bin, corp);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,15 @@
/*
* ac_ol_0016.pgc - (AC_OL_0016) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : KEY
* (merchant.withhold_rate, bp) (
* ) . ( ).
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,16 +91,37 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0016.pgc"
#line 17 "app/online/ac_ol_0016.pgc"
TX_SERVICE(AC_OL_0016, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* exec sql begin declare section */
#line 22 "app/online/ac_ol_0016.pgc"
char h_key [ 16 ] ;
#line 23 "app/online/ac_ol_0016.pgc"
long h_amount ;
#line 24 "app/online/ac_ol_0016.pgc"
char h_merch [ 16 ] ;
#line 25 "app/online/ac_ol_0016.pgc"
long h_wrate ;
/* exec sql end declare section */
#line 26 "app/online/ac_ol_0016.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0016] 매입 단건조회 서비스 진입");
char key[16];
long withhold;
long net;
tx_log(TX_LOG_INFO, "[AC_OL_0016] 매입 원천징수 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0016] KEY 누락");
@ -106,20 +129,62 @@ TX_SERVICE(AC_OL_0016, ctx)
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0016] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount , merch_id from ac_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 46 "app/online/ac_ol_0016.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0016] 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0016 ac_ledger select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select withhold_rate from merchant where merch_id = $1 ",
ECPGt_char,(h_merch),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_wrate),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 62 "app/online/ac_ol_0016.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0016] 가맹점 없음 merch=%s", h_merch);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_NOMERCH);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0016 merchant select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
withhold = (h_amount * h_wrate) / 10000;
net = h_amount - withhold;
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0016] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "AMOUNT", h_amount);
tx_buf_setlong(ctx->out, "WRATE", h_wrate);
tx_buf_setlong(ctx->out, "WITHHOLD", withhold);
tx_buf_setlong(ctx->out, "NETPAY", net);
tx_log(TX_LOG_INFO, "[AC_OL_0016] 원천징수 산출완료 key=%s amount=%ld withhold=%ld net=%ld",
key, h_amount, withhold, net);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,15 @@
/*
* ac_ol_0016.pgc - 매입 온라인 서비스 (AC_OL_0016) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 매입 원천징수: KEY 원장의 매입금액에 대해 가맹점별 원천징수율
* (merchant.withhold_rate, bp)을 적용해 원천징수액과 지급순액(세후
* 실지급액)을 계산해 반환한다. 원장은 변경하지 않는다(조회성 산출).
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,11 +18,18 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0016, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
long h_amount;
char h_merch[16];
long h_wrate;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0016] 매입 단건조회 서비스 진입");
char key[16];
long withhold;
long net;
tx_log(TX_LOG_INFO, "[AC_OL_0016] 매입 원천징수 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0016] KEY 누락");
@ -28,20 +37,54 @@ TX_SERVICE(AC_OL_0016, ctx)
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0016] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
EXEC SQL SELECT amount, merch_id
INTO :h_amount, :h_merch
FROM ac_ledger
WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0016] 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0016 ac_ledger select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
EXEC SQL SELECT withhold_rate
INTO :h_wrate
FROM merchant
WHERE merch_id = :h_merch;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0016] 가맹점 없음 merch=%s", h_merch);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_NOMERCH);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("AC_OL_0016 merchant select");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
withhold = (h_amount * h_wrate) / 10000;
net = h_amount - withhold;
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0016] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "AMOUNT", h_amount);
tx_buf_setlong(ctx->out, "WRATE", h_wrate);
tx_buf_setlong(ctx->out, "WITHHOLD", withhold);
tx_buf_setlong(ctx->out, "NETPAY", net);
tx_log(TX_LOG_INFO, "[AC_OL_0016] 원천징수 산출완료 key=%s amount=%ld withhold=%ld net=%ld",
key, h_amount, withhold, net);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,14 @@
/*
* ac_ol_0017.pgc - (AC_OL_0017) [tier=hard]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : (M)
* , .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,88 +90,205 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0017.pgc"
#line 16 "app/online/ac_ol_0017.pgc"
TX_SERVICE(AC_OL_0017, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16], nextbiz[9];
long amount = 0, daysum = 0;
int rc;
TXBUF *sub_in;
TXBUF *sub_out;
/* exec sql begin declare section */
#line 21 "app/online/ac_ol_0017.pgc"
char h_merch_id [ 16 ] ;
#line 22 "app/online/ac_ol_0017.pgc"
char h_biz_date [ 9 ] ;
#line 23 "app/online/ac_ol_0017.pgc"
char h_key [ 16 ] ;
#line 24 "app/online/ac_ol_0017.pgc"
char h_tax_no [ 17 ] ;
#line 25 "app/online/ac_ol_0017.pgc"
long h_supply ;
#line 26 "app/online/ac_ol_0017.pgc"
long h_vat ;
#line 27 "app/online/ac_ol_0017.pgc"
long h_supply_amt ;
/* exec sql end declare section */
#line 28 "app/online/ac_ol_0017.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0017] 매입 트랜잭션 오케스트레이션 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
char merch[16], bizdate[9], won[32];
long tagged = 0;
tx_log(TX_LOG_INFO, "[AC_OL_0017] 매입 세금계산서 연계 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0017] 필수 필드 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
if (!amount_is_valid(amount) || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0017] 입력 검증 실패 amount=%ld date=%s",
amount, bizdate);
tx_log(TX_LOG_ERROR, "[AC_OL_0017] 필수 필드(MERCHID/BIZDATE) 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* 트랜잭션 시작 → 원장 반영 → 후속 서비스 연계 → 커밋 */
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0017] 영업일 형식 오류 date=%s", bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
strncpy(h_merch_id, merch, sizeof(h_merch_id) - 1);
h_merch_id[sizeof(h_merch_id) - 1] = '\0';
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
h_biz_date[sizeof(h_biz_date) - 1] = '\0';
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0017] 트랜잭션 시작 실패");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100;
/* 처리완료(M) 매입 합계 집계 (부가세 포함 총액) */
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select coalesce ( sum ( amount ) , 0 ) from ac_ledger where merch_id = $1 and biz_date = $2 and status = 'M'",
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_supply),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 65 "app/online/ac_ol_0017.pgc"
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0017] 원장반영 실패 rc=%d", rc);
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT sum ac_ledger(tax)");
tx_abort();
tx_return(ctx, rc, ctx->out);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 정산 영업일 = 거래일의 다음 영업일 */
if (date_next_business(bizdate, nextbiz) != 0) {
memcpy(nextbiz, bizdate, 8);
nextbiz[8] = '\0';
if (h_supply <= 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0017] 집계대상 없음 merch=%s date=%s",
merch, bizdate);
tx_abort();
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
/* 후속 정산집계 서비스 연계 (레지스트리 문자열 디스패치) */
sub_in = tx_buf_alloc();
sub_out = tx_buf_alloc();
if (sub_in && sub_out) {
tx_buf_sets(sub_in, "MERCHID", merch);
tx_buf_sets(sub_in, "BIZDATE", nextbiz);
tx_buf_setlong(sub_in, "AMOUNT", amount);
rc = tx_call("AC_POST", sub_in, sub_out);
if (rc != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0017] 후속연계 경고 rc=%d", rc);
}
tx_buf_free(sub_in);
tx_buf_free(sub_out);
/* 부가세 10% 계산, 공급가액 = 매입합계 - 부가세 */
h_vat = h_supply / 10;
h_supply_amt = h_supply - h_vat;
/* 세금계산서번호 채번: TX + 영업일 + 가맹점번호(6자리) */
snprintf(h_tax_no, sizeof(h_tax_no), "TX%s%.6s", bizdate, merch);
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into tax_invoice ( tax_no , merch_id , biz_date , supply_amt , vat_amt , status ) values ( $1 , $2 , $3 , $4 , $5 , 'I' )",
ECPGt_char,(h_tax_no),(long)17,(long)1,(17)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_supply_amt),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_vat),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 92 "app/online/ac_ol_0017.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("INSERT tax_invoice");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 대상 매입 원장 커서 순회, 발행된 세금계산서번호 반영 */
ECPGset_var( 0, ( h_biz_date ), __LINE__);\
ECPGset_var( 1, ( h_merch_id ), __LINE__);\
/* declare cur_ac_ol_0017 cursor for select key from ac_ledger where merch_id = $1 and biz_date = $2 and status = 'M' */
#line 107 "app/online/ac_ol_0017.pgc"
#line 107 "app/online/ac_ol_0017.pgc"
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare cur_ac_ol_0017 cursor for select key from ac_ledger where merch_id = $1 and biz_date = $2 and status = 'M'",
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 109 "app/online/ac_ol_0017.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("OPEN cur_ac_ol_0017");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
for (;;) {
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch cur_ac_ol_0017", ECPGt_EOIT,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 118 "app/online/ac_ol_0017.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND)
break;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("FETCH cur_ac_ol_0017");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close cur_ac_ol_0017", ECPGt_EOIT, ECPGt_EORT);}
#line 123 "app/online/ac_ol_0017.pgc"
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update ac_ledger set tax_no = $1 where key = $2 ",
ECPGt_char,(h_tax_no),(long)17,(long)1,(17)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 131 "app/online/ac_ol_0017.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger tax_no");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close cur_ac_ol_0017", ECPGt_EOIT, ECPGt_EORT);}
#line 135 "app/online/ac_ol_0017.pgc"
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tagged += sqlca.sqlerrd[2];
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close cur_ac_ol_0017", ECPGt_EOIT, ECPGt_EORT);}
#line 143 "app/online/ac_ol_0017.pgc"
/* 교차 검증: 당일 합계 재계산 */
if (ac_rec_sum(bizdate, &daysum) != TX_OK)
daysum = 0;
tx_commit();
amount_format_won(h_supply_amt, won, sizeof(won));
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYSUM", daysum);
tx_log(TX_LOG_INFO, "[AC_OL_0017] 완료 key=%s 당일합계=%ld", key, daysum);
tx_buf_sets(ctx->out, "TAXNO", h_tax_no);
tx_buf_setlong(ctx->out, "SUPPLY", h_supply_amt);
tx_buf_setlong(ctx->out, "VAT", h_vat);
tx_buf_setlong(ctx->out, "TAGGED", tagged);
tx_log(TX_LOG_INFO,
"[AC_OL_0017] 완료 taxno=%s 공급가액=%s(%ld) 부가세=%ld 반영=%ld건",
h_tax_no, won, h_supply_amt, h_vat, tagged);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,14 @@
/*
* ac_ol_0017.pgc - 매입 온라인 서비스 (AC_OL_0017) [tier=hard]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 매입 세금계산서 연계: 지정 가맹점의 특정 영업일 처리완료(M) 매입 합계
* 집계하여 세금계산서를 발행하고, 대상 매입 원장에 세금계산서번호를 반영한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,83 +17,144 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0017, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16], nextbiz[9];
long amount = 0, daysum = 0;
int rc;
TXBUF *sub_in;
TXBUF *sub_out;
EXEC SQL BEGIN DECLARE SECTION;
char h_merch_id[16];
char h_biz_date[9];
char h_key[16];
char h_tax_no[17];
long h_supply;
long h_vat;
long h_supply_amt;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0017] 매입 트랜잭션 오케스트레이션 진입");
char merch[16], bizdate[9], won[32];
long tagged = 0;
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_log(TX_LOG_INFO, "[AC_OL_0017] 매입 세금계산서 연계 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0017] 필수 필드 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
if (!amount_is_valid(amount) || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0017] 입력 검증 실패 amount=%ld date=%s",
amount, bizdate);
tx_log(TX_LOG_ERROR, "[AC_OL_0017] 필수 필드(MERCHID/BIZDATE) 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* 트랜잭션 시작 → 원장 반영 → 후속 서비스 연계 → 커밋 */
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0017] 영업일 형식 오류 date=%s", bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
strncpy(h_merch_id, merch, sizeof(h_merch_id) - 1);
h_merch_id[sizeof(h_merch_id) - 1] = '\0';
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
h_biz_date[sizeof(h_biz_date) - 1] = '\0';
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0017] 트랜잭션 시작 실패");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100;
/* 처리완료(M) 매입 합계 집계 (부가세 포함 총액) */
EXEC SQL SELECT coalesce(sum(amount), 0)
INTO :h_supply
FROM ac_ledger
WHERE merch_id = :h_merch_id
AND biz_date = :h_biz_date
AND status = 'M';
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0017] 원장반영 실패 rc=%d", rc);
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT sum ac_ledger(tax)");
tx_abort();
tx_return(ctx, rc, ctx->out);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 정산 영업일 = 거래일의 다음 영업일 */
if (date_next_business(bizdate, nextbiz) != 0) {
memcpy(nextbiz, bizdate, 8);
nextbiz[8] = '\0';
if (h_supply <= 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0017] 집계대상 없음 merch=%s date=%s",
merch, bizdate);
tx_abort();
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
/* 후속 정산집계 서비스 연계 (레지스트리 문자열 디스패치) */
sub_in = tx_buf_alloc();
sub_out = tx_buf_alloc();
if (sub_in && sub_out) {
tx_buf_sets(sub_in, "MERCHID", merch);
tx_buf_sets(sub_in, "BIZDATE", nextbiz);
tx_buf_setlong(sub_in, "AMOUNT", amount);
rc = tx_call("AC_POST", sub_in, sub_out);
if (rc != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0017] 후속연계 경고 rc=%d", rc);
}
tx_buf_free(sub_in);
tx_buf_free(sub_out);
/* 부가세 10% 계산, 공급가액 = 매입합계 - 부가세 */
h_vat = h_supply / 10;
h_supply_amt = h_supply - h_vat;
/* 교차 검증: 당일 합계 재계산 */
if (ac_rec_sum(bizdate, &daysum) != TX_OK)
daysum = 0;
/* 세금계산서번호 채번: TX + 영업일 + 가맹점번호(6자리) */
snprintf(h_tax_no, sizeof(h_tax_no), "TX%s%.6s", bizdate, merch);
EXEC SQL INSERT INTO tax_invoice
(tax_no, merch_id, biz_date, supply_amt, vat_amt, status)
VALUES
(:h_tax_no, :h_merch_id, :h_biz_date, :h_supply_amt, :h_vat, 'I');
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("INSERT tax_invoice");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 대상 매입 원장 커서 순회, 발행된 세금계산서번호 반영 */
EXEC SQL DECLARE cur_ac_ol_0017 CURSOR FOR
SELECT key
FROM ac_ledger
WHERE merch_id = :h_merch_id
AND biz_date = :h_biz_date
AND status = 'M';
EXEC SQL OPEN cur_ac_ol_0017;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("OPEN cur_ac_ol_0017");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
for (;;) {
EXEC SQL FETCH cur_ac_ol_0017 INTO :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND)
break;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("FETCH cur_ac_ol_0017");
EXEC SQL CLOSE cur_ac_ol_0017;
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
EXEC SQL UPDATE ac_ledger
SET tax_no = :h_tax_no
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger tax_no");
EXEC SQL CLOSE cur_ac_ol_0017;
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tagged += sqlca.sqlerrd[2];
}
EXEC SQL CLOSE cur_ac_ol_0017;
tx_commit();
amount_format_won(h_supply_amt, won, sizeof(won));
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYSUM", daysum);
tx_log(TX_LOG_INFO, "[AC_OL_0017] 완료 key=%s 당일합계=%ld", key, daysum);
tx_buf_sets(ctx->out, "TAXNO", h_tax_no);
tx_buf_setlong(ctx->out, "SUPPLY", h_supply_amt);
tx_buf_setlong(ctx->out, "VAT", h_vat);
tx_buf_setlong(ctx->out, "TAGGED", tagged);
tx_log(TX_LOG_INFO,
"[AC_OL_0017] 완료 taxno=%s 공급가액=%s(%ld) 부가세=%ld 반영=%ld건",
h_tax_no, won, h_supply_amt, h_vat, tagged);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,14 @@
/*
* ac_ol_0018.pgc - (AC_OL_0018) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* - :
* / .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,37 +90,138 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0018.pgc"
#line 16 "app/online/ac_ol_0018.pgc"
TX_SERVICE(AC_OL_0018, ctx)
{
ac_rec_t rec;
char key[16];
/* exec sql begin declare section */
#line 21 "app/online/ac_ol_0018.pgc"
char h_key [ 16 ] ;
#line 22 "app/online/ac_ol_0018.pgc"
char h_approval_no [ 16 ] ;
#line 23 "app/online/ac_ol_0018.pgc"
long h_ledger_amt ;
#line 24 "app/online/ac_ol_0018.pgc"
long h_appr_amt ;
/* exec sql end declare section */
#line 25 "app/online/ac_ol_0018.pgc"
char key[16], apprno[16];
char won_ledger[32], won_appr[32];
long diff;
int match;
const char *newstatus;
int rc;
tx_log(TX_LOG_INFO, "[AC_OL_0018] 매입 단건조회 서비스 진입");
tx_log(TX_LOG_INFO, "[AC_OL_0018] 매입-승인 대사연계 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0018] KEY 누락");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "APPROVALNO", apprno, sizeof(apprno)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0018] 필수 필드(KEY/APPROVALNO) 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (key[0] == '\0' || apprno[0] == '\0') {
tx_log(TX_LOG_ERROR, "[AC_OL_0018] KEY/APPROVALNO 빈 값");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
strncpy(h_approval_no, apprno, sizeof(h_approval_no) - 1);
h_approval_no[sizeof(h_approval_no) - 1] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount from ac_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_ledger_amt),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 56 "app/online/ac_ol_0018.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0018] 매입 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_ledger amount");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount from approval where approval_no = $1 ",
ECPGt_char,(h_approval_no),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_appr_amt),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 72 "app/online/ac_ol_0018.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0018] 승인내역 없음 approvalno=%s", apprno);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT approval amount");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
diff = h_ledger_amt - h_appr_amt;
match = (diff == 0) ? 1 : 0;
newstatus = match ? AC_ST_DONE : AC_ST_FAIL;
amount_format_won(h_ledger_amt, won_ledger, sizeof(won_ledger));
amount_format_won(h_appr_amt, won_appr, sizeof(won_appr));
if (match) {
tx_log(TX_LOG_INFO,
"[AC_OL_0018] 대사일치 key=%s 원장=%s 승인=%s",
key, won_ledger, won_appr);
} else {
tx_log(TX_LOG_WARN,
"[AC_OL_0018] 대사불일치 key=%s 원장=%s 승인=%s diff=%ld",
key, won_ledger, won_appr, diff);
}
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0018] 트랜잭션 시작 실패");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
rc = ac_rec_update_status(key, newstatus);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0018] 조회 실패 key=%s rc=%d(%s)",
tx_log(TX_LOG_ERROR, "[AC_OL_0018] 상태전이 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_abort();
tx_return(ctx, rc, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0018] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "MATCH", (long)match);
tx_buf_setlong(ctx->out, "DIFF", diff);
tx_buf_sets(ctx->out, "STATUS", newstatus);
tx_log(TX_LOG_INFO, "[AC_OL_0018] 완료 key=%s match=%d diff=%ld status=%s",
key, match, diff, newstatus);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,14 @@
/*
* ac_ol_0018.pgc - 매입 온라인 서비스 (AC_OL_0018) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 매입-승인 대사연계: 매입 원장 금액과 카드사 승인 금액을 대사하여
* 일치 여부에 따라 매입 상태를 완료/불일치로 전이한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,32 +17,113 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0018, ctx)
{
ac_rec_t rec;
char key[16];
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
char h_approval_no[16];
long h_ledger_amt;
long h_appr_amt;
EXEC SQL END DECLARE SECTION;
char key[16], apprno[16];
char won_ledger[32], won_appr[32];
long diff;
int match;
const char *newstatus;
int rc;
tx_log(TX_LOG_INFO, "[AC_OL_0018] 매입 단건조회 서비스 진입");
tx_log(TX_LOG_INFO, "[AC_OL_0018] 매입-승인 대사연계 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0018] KEY 누락");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "APPROVALNO", apprno, sizeof(apprno)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0018] 필수 필드(KEY/APPROVALNO) 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (key[0] == '\0' || apprno[0] == '\0') {
tx_log(TX_LOG_ERROR, "[AC_OL_0018] KEY/APPROVALNO 빈 값");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
strncpy(h_approval_no, apprno, sizeof(h_approval_no) - 1);
h_approval_no[sizeof(h_approval_no) - 1] = '\0';
EXEC SQL SELECT amount
INTO :h_ledger_amt
FROM ac_ledger
WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0018] 매입 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_ledger amount");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
EXEC SQL SELECT amount
INTO :h_appr_amt
FROM approval
WHERE approval_no = :h_approval_no;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0018] 승인내역 없음 approvalno=%s", apprno);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT approval amount");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
diff = h_ledger_amt - h_appr_amt;
match = (diff == 0) ? 1 : 0;
newstatus = match ? AC_ST_DONE : AC_ST_FAIL;
amount_format_won(h_ledger_amt, won_ledger, sizeof(won_ledger));
amount_format_won(h_appr_amt, won_appr, sizeof(won_appr));
if (match) {
tx_log(TX_LOG_INFO,
"[AC_OL_0018] 대사일치 key=%s 원장=%s 승인=%s",
key, won_ledger, won_appr);
} else {
tx_log(TX_LOG_WARN,
"[AC_OL_0018] 대사불일치 key=%s 원장=%s 승인=%s diff=%ld",
key, won_ledger, won_appr, diff);
}
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0018] 트랜잭션 시작 실패");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
rc = ac_rec_update_status(key, newstatus);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0018] 조회 실패 key=%s rc=%d(%s)",
tx_log(TX_LOG_ERROR, "[AC_OL_0018] 상태전이 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_abort();
tx_return(ctx, rc, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0018] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "MATCH", (long)match);
tx_buf_setlong(ctx->out, "DIFF", diff);
tx_buf_sets(ctx->out, "STATUS", newstatus);
tx_log(TX_LOG_INFO, "[AC_OL_0018] 완료 key=%s match=%d diff=%ld status=%s",
key, match, diff, newstatus);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,13 @@
/*
* ac_ol_0019.pgc - (AC_OL_0019) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -94,11 +94,27 @@ struct sqlca_t *ECPGget_sqlca(void);
TX_SERVICE(AC_OL_0019, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* exec sql begin declare section */
#line 20 "app/online/ac_ol_0019.pgc"
char h_key [ 16 ] ;
#line 21 "app/online/ac_ol_0019.pgc"
char h_old_date [ 9 ] ;
#line 22 "app/online/ac_ol_0019.pgc"
char h_new_date [ 9 ] ;
/* exec sql end declare section */
#line 23 "app/online/ac_ol_0019.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0019] 매입 단건조회 서비스 진입");
char key[16], newdate_in[9], computed[9];
int has_newdate;
tx_log(TX_LOG_INFO, "[AC_OL_0019] 매입일자 변경 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0019] KEY 누락");
@ -106,20 +122,96 @@ TX_SERVICE(AC_OL_0019, ctx)
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0019] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
has_newdate = (tx_buf_get(ctx->in, "NEWDATE", newdate_in, sizeof(newdate_in)) == TX_OK);
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select biz_date from ac_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_char,(h_old_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 44 "app/online/ac_ol_0019.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0019] 매입 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_ledger biz_date");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (has_newdate && date_is_valid(newdate_in)) {
strncpy(computed, newdate_in, sizeof(computed) - 1);
computed[sizeof(computed) - 1] = '\0';
} else {
if (has_newdate)
tx_log(TX_LOG_WARN,
"[AC_OL_0019] NEWDATE 형식 오류(%s) - 다음영업일로 대체",
newdate_in);
if (date_next_business(h_old_date, computed) != 0) {
tx_log(TX_LOG_ERROR, "[AC_OL_0019] 다음영업일 산출 실패 date=%s",
h_old_date);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
}
strncpy(h_new_date, computed, sizeof(h_new_date) - 1);
h_new_date[sizeof(h_new_date) - 1] = '\0';
if (strcmp(h_old_date, h_new_date) == 0) {
tx_log(TX_LOG_INFO, "[AC_OL_0019] 변경 불필요 date=%s", h_old_date);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_sets(ctx->out, "OLDDATE", h_old_date);
tx_buf_sets(ctx->out, "NEWDATE", h_new_date);
tx_return(ctx, TX_OK, ctx->out);
return;
}
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0019] 트랜잭션 시작 실패");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update ac_ledger set biz_date = $1 where key = $2 ",
ECPGt_char,(h_new_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 95 "app/online/ac_ol_0019.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger biz_date");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0019] 변경대상 없음 key=%s", key);
tx_abort();
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0019] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_sets(ctx->out, "OLDDATE", h_old_date);
tx_buf_sets(ctx->out, "NEWDATE", h_new_date);
tx_log(TX_LOG_INFO, "[AC_OL_0019] 완료 key=%s %s -> %s",
key, h_old_date, h_new_date);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,13 @@
/*
* ac_ol_0019.pgc - 매입 온라인 서비스 (AC_OL_0019) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 매입일자 변경: 매입 원장의 영업일을 지정일 또는 다음 영업일로 변경한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,11 +16,16 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0019, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
char h_old_date[9];
char h_new_date[9];
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0019] 매입 단건조회 서비스 진입");
char key[16], newdate_in[9], computed[9];
int has_newdate;
tx_log(TX_LOG_INFO, "[AC_OL_0019] 매입일자 변경 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0019] KEY 누락");
@ -28,20 +33,89 @@ TX_SERVICE(AC_OL_0019, ctx)
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0019] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
has_newdate = (tx_buf_get(ctx->in, "NEWDATE", newdate_in, sizeof(newdate_in)) == TX_OK);
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
EXEC SQL SELECT biz_date
INTO :h_old_date
FROM ac_ledger
WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0019] 매입 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_ledger biz_date");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (has_newdate && date_is_valid(newdate_in)) {
strncpy(computed, newdate_in, sizeof(computed) - 1);
computed[sizeof(computed) - 1] = '\0';
} else {
if (has_newdate)
tx_log(TX_LOG_WARN,
"[AC_OL_0019] NEWDATE 형식 오류(%s) - 다음영업일로 대체",
newdate_in);
if (date_next_business(h_old_date, computed) != 0) {
tx_log(TX_LOG_ERROR, "[AC_OL_0019] 다음영업일 산출 실패 date=%s",
h_old_date);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
}
strncpy(h_new_date, computed, sizeof(h_new_date) - 1);
h_new_date[sizeof(h_new_date) - 1] = '\0';
if (strcmp(h_old_date, h_new_date) == 0) {
tx_log(TX_LOG_INFO, "[AC_OL_0019] 변경 불필요 date=%s", h_old_date);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_sets(ctx->out, "OLDDATE", h_old_date);
tx_buf_sets(ctx->out, "NEWDATE", h_new_date);
tx_return(ctx, TX_OK, ctx->out);
return;
}
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0019] 트랜잭션 시작 실패");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
EXEC SQL UPDATE ac_ledger
SET biz_date = :h_new_date
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger biz_date");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0019] 변경대상 없음 key=%s", key);
tx_abort();
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0019] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_sets(ctx->out, "OLDDATE", h_old_date);
tx_buf_sets(ctx->out, "NEWDATE", h_new_date);
tx_log(TX_LOG_INFO, "[AC_OL_0019] 완료 key=%s %s -> %s",
key, h_old_date, h_new_date);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,14 @@
/*
* ac_ol_0020.pgc - (AC_OL_0020) [tier=medium]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : (DELTA) ,
* .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,60 +90,159 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0020.pgc"
#line 16 "app/online/ac_ol_0020.pgc"
TX_SERVICE(AC_OL_0020, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
/* exec sql begin declare section */
#line 21 "app/online/ac_ol_0020.pgc"
char h_key [ 16 ] ;
#line 22 "app/online/ac_ol_0020.pgc"
char h_merch_id [ 16 ] ;
#line 23 "app/online/ac_ol_0020.pgc"
long h_amount ;
#line 24 "app/online/ac_ol_0020.pgc"
long h_fee ;
#line 25 "app/online/ac_ol_0020.pgc"
long h_new_amount ;
#line 26 "app/online/ac_ol_0020.pgc"
long h_new_fee ;
#line 27 "app/online/ac_ol_0020.pgc"
double h_fee_rate ;
/* exec sql end declare section */
#line 28 "app/online/ac_ol_0020.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0020] 매입 등록 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0020] 필수 필드 누락");
char key[16];
long delta = 0;
tx_log(TX_LOG_INFO, "[AC_OL_0020] 매입금액 보정 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0020] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0020] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0020] 영업일 오류 date=%s", bizdate);
if (tx_buf_getlong(ctx->in, "DELTA", &delta) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0020] DELTA 누락 key=%s", key);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0020] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount , fee , merch_id from ac_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_fee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 52 "app/online/ac_ol_0020.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0020] 매입 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_ledger amount/fee");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
cnt = ac_rec_count(bizdate, AC_ST_RECV);
h_new_amount = h_amount + delta;
if (!amount_is_valid(h_new_amount)) {
tx_log(TX_LOG_WARN,
"[AC_OL_0020] 보정후 금액 유효성 오류 key=%s delta=%ld amount=%ld",
key, delta, h_new_amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select fee_rate from merchant where merch_id = $1 ",
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_double,&(h_fee_rate),(long)1,(long)1,sizeof(double),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 77 "app/online/ac_ol_0020.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0020] 가맹점 정보 없음 merch=%s", h_merch_id);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT merchant fee_rate");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
h_new_fee = (long)(h_new_amount * h_fee_rate);
if (h_new_fee < 0)
h_new_fee = 0;
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0020] 트랜잭션 시작 실패");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update ac_ledger set amount = $1 , fee = $2 where key = $3 ",
ECPGt_long,&(h_new_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_new_fee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 102 "app/online/ac_ol_0020.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger amount/fee");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0020] 보정대상 없음 key=%s", key);
tx_abort();
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0020] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_setlong(ctx->out, "OLDAMOUNT", h_amount);
tx_buf_setlong(ctx->out, "NEWAMOUNT", h_new_amount);
tx_buf_setlong(ctx->out, "OLDFEE", h_fee);
tx_buf_setlong(ctx->out, "NEWFEE", h_new_fee);
tx_log(TX_LOG_INFO,
"[AC_OL_0020] 완료 key=%s amount %ld->%ld fee %ld->%ld",
key, h_amount, h_new_amount, h_fee, h_new_fee);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,14 @@
/*
* ac_ol_0020.pgc - 매입 온라인 서비스 (AC_OL_0020) [tier=medium]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 매입금액 보정: 지정 보정액(DELTA)만큼 매입금액을 가감하고, 가맹점
* 수수료율로 수수료를 재계산하여 반영한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,55 +17,115 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0020, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
char h_merch_id[16];
long h_amount;
long h_fee;
long h_new_amount;
long h_new_fee;
double h_fee_rate;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0020] 매입 등록 서비스 진입");
char key[16];
long delta = 0;
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0020] 필수 필드 누락");
tx_log(TX_LOG_INFO, "[AC_OL_0020] 매입금액 보정 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0020] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0020] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0020] 영업일 오류 date=%s", bizdate);
if (tx_buf_getlong(ctx->in, "DELTA", &delta) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0020] DELTA 누락 key=%s", key);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0020] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
EXEC SQL SELECT amount, fee, merch_id
INTO :h_amount, :h_fee, :h_merch_id
FROM ac_ledger
WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0020] 매입 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_ledger amount/fee");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
cnt = ac_rec_count(bizdate, AC_ST_RECV);
h_new_amount = h_amount + delta;
if (!amount_is_valid(h_new_amount)) {
tx_log(TX_LOG_WARN,
"[AC_OL_0020] 보정후 금액 유효성 오류 key=%s delta=%ld amount=%ld",
key, delta, h_new_amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
EXEC SQL SELECT fee_rate
INTO :h_fee_rate
FROM merchant
WHERE merch_id = :h_merch_id;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0020] 가맹점 정보 없음 merch=%s", h_merch_id);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT merchant fee_rate");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
h_new_fee = (long)(h_new_amount * h_fee_rate);
if (h_new_fee < 0)
h_new_fee = 0;
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0020] 트랜잭션 시작 실패");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
EXEC SQL UPDATE ac_ledger
SET amount = :h_new_amount, fee = :h_new_fee
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger amount/fee");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0020] 보정대상 없음 key=%s", key);
tx_abort();
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0020] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_setlong(ctx->out, "OLDAMOUNT", h_amount);
tx_buf_setlong(ctx->out, "NEWAMOUNT", h_new_amount);
tx_buf_setlong(ctx->out, "OLDFEE", h_fee);
tx_buf_setlong(ctx->out, "NEWFEE", h_new_fee);
tx_log(TX_LOG_INFO,
"[AC_OL_0020] 완료 key=%s amount %ld->%ld fee %ld->%ld",
key, h_amount, h_new_amount, h_fee, h_new_fee);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,14 @@
/*
* ac_ol_0021.pgc - (AC_OL_0021) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* :
* .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,37 +90,135 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0021.pgc"
#line 16 "app/online/ac_ol_0021.pgc"
TX_SERVICE(AC_OL_0021, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* exec sql begin declare section */
#line 21 "app/online/ac_ol_0021.pgc"
char h_key [ 16 ] ;
#line 22 "app/online/ac_ol_0021.pgc"
char h_approval_no [ 16 ] ;
#line 23 "app/online/ac_ol_0021.pgc"
int h_cnt ;
#line 24 "app/online/ac_ol_0021.pgc"
int h_ledger_cnt ;
/* exec sql end declare section */
#line 25 "app/online/ac_ol_0021.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0021] 매입 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0021] KEY 누락");
char key[16], apprno[16];
tx_log(TX_LOG_INFO, "[AC_OL_0021] 매입 승인번호 매핑 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "APPROVALNO", apprno, sizeof(apprno)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0021] 필수 필드(KEY/APPROVALNO) 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (key[0] == '\0' || apprno[0] == '\0') {
tx_log(TX_LOG_ERROR, "[AC_OL_0021] KEY/APPROVALNO 빈 값");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0021] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
strncpy(h_approval_no, apprno, sizeof(h_approval_no) - 1);
h_approval_no[sizeof(h_approval_no) - 1] = '\0';
/* 매입 원장 존재 확인 (선행 검증) */
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select count ( * ) from ac_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_int,&(h_ledger_cnt),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 52 "app/online/ac_ol_0021.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT count ac_ledger");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_ledger_cnt <= 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0021] 매입 원장 없음 key=%s", key);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_buf_setlong(ctx->out, "MAPPED", 0L);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
/* 카드사 승인내역 존재 확인 */
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select count ( * ) from approval where approval_no = $1 ",
ECPGt_char,(h_approval_no),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_int,&(h_cnt),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 72 "app/online/ac_ol_0021.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT count approval");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_cnt <= 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0021] 승인내역 없음 approvalno=%s", apprno);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_buf_setlong(ctx->out, "MAPPED", 0L);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0021] 트랜잭션 시작 실패");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update ac_ledger set approval_no = $1 where key = $2 ",
ECPGt_char,(h_approval_no),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 97 "app/online/ac_ol_0021.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger approval_no");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0021] 매핑대상 원장 없음 key=%s", key);
tx_abort();
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0021] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_sets(ctx->out, "APPROVALNO", apprno);
tx_buf_setlong(ctx->out, "MAPPED", 1L);
tx_log(TX_LOG_INFO, "[AC_OL_0021] 완료 key=%s approvalno=%s", key, apprno);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,14 @@
/*
* ac_ol_0021.pgc - 매입 온라인 서비스 (AC_OL_0021) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 매입 승인번호 매핑: 카드사 승인내역 존재를 확인한 뒤 매입 원장에
* 승인번호를 매핑한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,32 +17,106 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0021, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
char h_approval_no[16];
int h_cnt;
int h_ledger_cnt;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0021] 매입 단건조회 서비스 진입");
char key[16], apprno[16];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0021] KEY 누락");
tx_log(TX_LOG_INFO, "[AC_OL_0021] 매입 승인번호 매핑 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "APPROVALNO", apprno, sizeof(apprno)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0021] 필수 필드(KEY/APPROVALNO) 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (key[0] == '\0' || apprno[0] == '\0') {
tx_log(TX_LOG_ERROR, "[AC_OL_0021] KEY/APPROVALNO 빈 값");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0021] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
strncpy(h_approval_no, apprno, sizeof(h_approval_no) - 1);
h_approval_no[sizeof(h_approval_no) - 1] = '\0';
/* 매입 원장 존재 확인 (선행 검증) */
EXEC SQL SELECT count(*)
INTO :h_ledger_cnt
FROM ac_ledger
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT count ac_ledger");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_ledger_cnt <= 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0021] 매입 원장 없음 key=%s", key);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_buf_setlong(ctx->out, "MAPPED", 0L);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
/* 카드사 승인내역 존재 확인 */
EXEC SQL SELECT count(*)
INTO :h_cnt
FROM approval
WHERE approval_no = :h_approval_no;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT count approval");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_cnt <= 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0021] 승인내역 없음 approvalno=%s", apprno);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_buf_setlong(ctx->out, "MAPPED", 0L);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0021] 트랜잭션 시작 실패");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
EXEC SQL UPDATE ac_ledger
SET approval_no = :h_approval_no
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger approval_no");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0021] 매핑대상 원장 없음 key=%s", key);
tx_abort();
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0021] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_sets(ctx->out, "APPROVALNO", apprno);
tx_buf_setlong(ctx->out, "MAPPED", 1L);
tx_log(TX_LOG_INFO, "[AC_OL_0021] 완료 key=%s approvalno=%s", key, apprno);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,14 @@
/*
* ac_ol_0022.pgc - (AC_OL_0022) [tier=medium]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* :
* .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,60 +90,159 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0022.pgc"
#line 16 "app/online/ac_ol_0022.pgc"
TX_SERVICE(AC_OL_0022, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
/* exec sql begin declare section */
#line 21 "app/online/ac_ol_0022.pgc"
char h_key [ 16 ] ;
#line 22 "app/online/ac_ol_0022.pgc"
char h_merch_id [ 16 ] ;
#line 23 "app/online/ac_ol_0022.pgc"
char h_biz_date [ 9 ] ;
#line 24 "app/online/ac_ol_0022.pgc"
char h_status [ 2 ] ;
#line 25 "app/online/ac_ol_0022.pgc"
long h_amount ;
#line 26 "app/online/ac_ol_0022.pgc"
long h_fee ;
#line 27 "app/online/ac_ol_0022.pgc"
long h_settle_amt ;
#line 28 "app/online/ac_ol_0022.pgc"
char h_settle_no [ 17 ] ;
/* exec sql end declare section */
#line 29 "app/online/ac_ol_0022.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0022] 매입 등록 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0022] 필수 필드 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
char key[16], won[32];
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0022] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0022] 영업일 오류 date=%s", bizdate);
tx_log(TX_LOG_INFO, "[AC_OL_0022] 매입 정산연계 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0022] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0022] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount , fee , merch_id , biz_date , status from ac_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_fee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 47 "app/online/ac_ol_0022.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0022] 매입 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_ledger for settle");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
cnt = ac_rec_count(bizdate, AC_ST_RECV);
if (strncmp(h_status, AC_ST_DONE, 1) != 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0022] 정산연계 불가 상태 key=%s status=%s",
key, h_status);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
h_settle_amt = h_amount - h_fee;
if (h_settle_amt < 0)
h_settle_amt = 0;
/* 정산번호 채번: ST + 영업일 + 매입키(뒤 6자리) */
snprintf(h_settle_no, sizeof(h_settle_no), "ST%s%.6s", h_biz_date, key);
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0022] 트랜잭션 시작 실패");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into settle ( settle_no , merch_id , biz_date , settle_amt , status ) values ( $1 , $2 , $3 , $4 , 'S' )",
ECPGt_char,(h_settle_no),(long)17,(long)1,(17)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_settle_amt),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 83 "app/online/ac_ol_0022.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("INSERT settle");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update ac_ledger set status = 'S' , settle_no = $1 where key = $2 ",
ECPGt_char,(h_settle_no),(long)17,(long)1,(17)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 94 "app/online/ac_ol_0022.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger settle status");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0022] 정산반영 대상 없음 key=%s", key);
tx_abort();
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
tx_commit();
amount_format_won(h_settle_amt, won, sizeof(won));
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0022] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_sets(ctx->out, "SETTLENO", h_settle_no);
tx_buf_setlong(ctx->out, "SETTLEAMT", h_settle_amt);
tx_log(TX_LOG_INFO, "[AC_OL_0022] 완료 key=%s settleno=%s 정산액=%s(%ld)",
key, h_settle_no, won, h_settle_amt);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,14 @@
/*
* ac_ol_0022.pgc - 매입 온라인 서비스 (AC_OL_0022) [tier=medium]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 매입 정산연계: 처리완료 매입 건의 수수료를 차감한 정산금액을 산출하여
* 정산 테이블에 반영하고 매입 원장을 정산완료 상태로 전이한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,55 +17,106 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0022, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
char h_merch_id[16];
char h_biz_date[9];
char h_status[2];
long h_amount;
long h_fee;
long h_settle_amt;
char h_settle_no[17];
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0022] 매입 등록 서비스 진입");
char key[16], won[32];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0022] 필수 필드 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
tx_log(TX_LOG_INFO, "[AC_OL_0022] 매입 정산연계 진입");
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0022] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0022] 영업일 오류 date=%s", bizdate);
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0022] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0022] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
EXEC SQL SELECT amount, fee, merch_id, biz_date, status
INTO :h_amount, :h_fee, :h_merch_id, :h_biz_date, :h_status
FROM ac_ledger
WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0022] 매입 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_ledger for settle");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
cnt = ac_rec_count(bizdate, AC_ST_RECV);
if (strncmp(h_status, AC_ST_DONE, 1) != 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0022] 정산연계 불가 상태 key=%s status=%s",
key, h_status);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
h_settle_amt = h_amount - h_fee;
if (h_settle_amt < 0)
h_settle_amt = 0;
/* 정산번호 채번: ST + 영업일 + 매입키(뒤 6자리) */
snprintf(h_settle_no, sizeof(h_settle_no), "ST%s%.6s", h_biz_date, key);
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0022] 트랜잭션 시작 실패");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
EXEC SQL INSERT INTO settle
(settle_no, merch_id, biz_date, settle_amt, status)
VALUES
(:h_settle_no, :h_merch_id, :h_biz_date, :h_settle_amt, 'S');
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("INSERT settle");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
EXEC SQL UPDATE ac_ledger
SET status = 'S', settle_no = :h_settle_no
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger settle status");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0022] 정산반영 대상 없음 key=%s", key);
tx_abort();
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
tx_commit();
amount_format_won(h_settle_amt, won, sizeof(won));
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0022] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_sets(ctx->out, "SETTLENO", h_settle_no);
tx_buf_setlong(ctx->out, "SETTLEAMT", h_settle_amt);
tx_log(TX_LOG_INFO, "[AC_OL_0022] 완료 key=%s settleno=%s 정산액=%s(%ld)",
key, h_settle_no, won, h_settle_amt);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,14 @@
/*
* ac_ol_0023.pgc - (AC_OL_0023) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : ( )
* .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,37 +90,140 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0023.pgc"
#line 16 "app/online/ac_ol_0023.pgc"
TX_SERVICE(AC_OL_0023, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* exec sql begin declare section */
#line 21 "app/online/ac_ol_0023.pgc"
char h_merch_id [ 16 ] ;
#line 22 "app/online/ac_ol_0023.pgc"
char h_biz_date [ 9 ] ;
#line 23 "app/online/ac_ol_0023.pgc"
long h_net ;
#line 24 "app/online/ac_ol_0023.pgc"
char h_transfer_id [ 17 ] ;
#line 25 "app/online/ac_ol_0023.pgc"
int h_dup_cnt ;
/* exec sql end declare section */
#line 26 "app/online/ac_ol_0023.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0023] 매입 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0023] KEY 누락");
char merch[16], bizdate[9];
tx_log(TX_LOG_INFO, "[AC_OL_0023] 매입 이체연계 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0023] 필수 필드(MERCHID/BIZDATE) 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0023] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0023] 영업일 형식 오류 date=%s", bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
strncpy(h_merch_id, merch, sizeof(h_merch_id) - 1);
h_merch_id[sizeof(h_merch_id) - 1] = '\0';
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
h_biz_date[sizeof(h_biz_date) - 1] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select coalesce ( sum ( amount - fee ) , 0 ) from ac_ledger where merch_id = $1 and biz_date = $2 and status = 'S'",
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_net),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 55 "app/online/ac_ol_0023.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT sum net ac_ledger");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_net <= 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0023] 이체대상 없음 merch=%s date=%s",
merch, bizdate);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
/* 중복 이체지시 방지: 동일 가맹점/영업일 이체(T) 이력 확인 */
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select count ( * ) from settle where merch_id = $1 and biz_date = $2 and status = 'T'",
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_int,&(h_dup_cnt),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 76 "app/online/ac_ol_0023.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT count settle dup");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_dup_cnt > 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0023] 이체지시 중복 merch=%s date=%s",
merch, bizdate);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
/* 이체지시번호 채번: TR + 영업일 + 가맹점번호(6자리) */
snprintf(h_transfer_id, sizeof(h_transfer_id), "TR%s%.6s", bizdate, merch);
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0023] 트랜잭션 시작 실패");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into settle ( settle_no , merch_id , biz_date , settle_amt , status ) values ( $1 , $2 , $3 , $4 , 'T' )",
ECPGt_char,(h_transfer_id),(long)17,(long)1,(17)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_net),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 102 "app/online/ac_ol_0023.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("INSERT settle transfer");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0023] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "TRANSFERID", h_transfer_id);
tx_buf_setlong(ctx->out, "NETAMOUNT", h_net);
tx_log(TX_LOG_INFO, "[AC_OL_0023] 완료 transferid=%s 순매입액=%ld",
h_transfer_id, h_net);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,14 @@
/*
* ac_ol_0023.pgc - 매입 온라인 서비스 (AC_OL_0023) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 매입 이체연계: 정산완료 매입 건의 순매입액(수수료 차감 합계)을 집계하여
* 이체지시 레코드를 생성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,32 +17,105 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0023, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_merch_id[16];
char h_biz_date[9];
long h_net;
char h_transfer_id[17];
int h_dup_cnt;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0023] 매입 단건조회 서비스 진입");
char merch[16], bizdate[9];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0023] KEY 누락");
tx_log(TX_LOG_INFO, "[AC_OL_0023] 매입 이체연계 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0023] 필수 필드(MERCHID/BIZDATE) 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0023] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0023] 영업일 형식 오류 date=%s", bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
strncpy(h_merch_id, merch, sizeof(h_merch_id) - 1);
h_merch_id[sizeof(h_merch_id) - 1] = '\0';
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
h_biz_date[sizeof(h_biz_date) - 1] = '\0';
EXEC SQL SELECT coalesce(sum(amount - fee), 0)
INTO :h_net
FROM ac_ledger
WHERE merch_id = :h_merch_id
AND biz_date = :h_biz_date
AND status = 'S';
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT sum net ac_ledger");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_net <= 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0023] 이체대상 없음 merch=%s date=%s",
merch, bizdate);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
/* 중복 이체지시 방지: 동일 가맹점/영업일 이체(T) 이력 확인 */
EXEC SQL SELECT count(*)
INTO :h_dup_cnt
FROM settle
WHERE merch_id = :h_merch_id
AND biz_date = :h_biz_date
AND status = 'T';
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT count settle dup");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_dup_cnt > 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0023] 이체지시 중복 merch=%s date=%s",
merch, bizdate);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
/* 이체지시번호 채번: TR + 영업일 + 가맹점번호(6자리) */
snprintf(h_transfer_id, sizeof(h_transfer_id), "TR%s%.6s", bizdate, merch);
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0023] 트랜잭션 시작 실패");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
EXEC SQL INSERT INTO settle
(settle_no, merch_id, biz_date, settle_amt, status)
VALUES
(:h_transfer_id, :h_merch_id, :h_biz_date, :h_net, 'T');
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("INSERT settle transfer");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0023] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "TRANSFERID", h_transfer_id);
tx_buf_setlong(ctx->out, "NETAMOUNT", h_net);
tx_log(TX_LOG_INFO, "[AC_OL_0023] 완료 transferid=%s 순매입액=%ld",
h_transfer_id, h_net);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,14 @@
/*
* ac_ol_0024.pgc - (AC_OL_0024) [tier=medium]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : (acq_type) //
* .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,60 +90,132 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0024.pgc"
#line 16 "app/online/ac_ol_0024.pgc"
#define AC_TYPE_LARGE "LG"
#define AC_TYPE_MEDIUM "MD"
#define AC_TYPE_SMALL "SM"
TX_SERVICE(AC_OL_0024, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
/* exec sql begin declare section */
#line 25 "app/online/ac_ol_0024.pgc"
char h_key [ 16 ] ;
#line 26 "app/online/ac_ol_0024.pgc"
long h_amount ;
#line 27 "app/online/ac_ol_0024.pgc"
char h_old_type [ 4 ] ;
#line 28 "app/online/ac_ol_0024.pgc"
char h_acq_type [ 4 ] ;
/* exec sql end declare section */
#line 29 "app/online/ac_ol_0024.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0024] 매입 등록 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0024] 필수 필드 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
char key[16];
const char *class_name;
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0024] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0024] 영업일 오류 date=%s", bizdate);
tx_log(TX_LOG_INFO, "[AC_OL_0024] 매입 재분류 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0024] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0024] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount , coalesce ( acq_type , '' ) from ac_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_old_type),(long)4,(long)1,(4)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 48 "app/online/ac_ol_0024.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0024] 매입 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_ledger amount(reclass)");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
cnt = ac_rec_count(bizdate, AC_ST_RECV);
/* 업무규칙: 금액 구간별 매입유형 재분류 (대형/중형/소형) */
if (h_amount >= 1000000L) {
class_name = AC_TYPE_LARGE;
} else if (h_amount >= 100000L) {
class_name = AC_TYPE_MEDIUM;
} else {
class_name = AC_TYPE_SMALL;
}
strncpy(h_acq_type, class_name, sizeof(h_acq_type) - 1);
h_acq_type[sizeof(h_acq_type) - 1] = '\0';
if (strcmp(h_old_type, h_acq_type) == 0) {
tx_log(TX_LOG_INFO, "[AC_OL_0024] 재분류 변경 없음 key=%s type=%s",
key, h_acq_type);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "AMOUNT", h_amount);
tx_buf_sets(ctx->out, "OLDTYPE", h_old_type);
tx_buf_sets(ctx->out, "ACQTYPE", h_acq_type);
tx_return(ctx, TX_OK, ctx->out);
return;
}
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0024] 트랜잭션 시작 실패");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update ac_ledger set acq_type = $1 where key = $2 ",
ECPGt_char,(h_acq_type),(long)4,(long)1,(4)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 93 "app/online/ac_ol_0024.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger acq_type");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0024] 재분류대상 없음 key=%s", key);
tx_abort();
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0024] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_setlong(ctx->out, "AMOUNT", h_amount);
tx_buf_sets(ctx->out, "OLDTYPE", h_old_type);
tx_buf_sets(ctx->out, "ACQTYPE", h_acq_type);
tx_log(TX_LOG_INFO, "[AC_OL_0024] 완료 key=%s amount=%ld %s -> %s",
key, h_amount, h_old_type, h_acq_type);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,69 +2,119 @@
/*
* ac_ol_0024.pgc - 매입 온라인 서비스 (AC_OL_0024) [tier=medium]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 매입 재분류: 매입금액 구간에 따라 매입유형(acq_type)을 대형/중형/소형
* 가맹점 기준으로 재분류하여 매입 원장에 반영한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
EXEC SQL INCLUDE sqlca;
#define AC_TYPE_LARGE "LG"
#define AC_TYPE_MEDIUM "MD"
#define AC_TYPE_SMALL "SM"
TX_SERVICE(AC_OL_0024, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
long h_amount;
char h_old_type[4];
char h_acq_type[4];
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0024] 매입 등록 서비스 진입");
char key[16];
const char *class_name;
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0024] 필수 필드 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
tx_log(TX_LOG_INFO, "[AC_OL_0024] 매입 재분류 진입");
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0024] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0024] 영업일 오류 date=%s", bizdate);
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0024] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_key, key, sizeof(h_key) - 1);
h_key[sizeof(h_key) - 1] = '\0';
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0024] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
EXEC SQL SELECT amount, coalesce(acq_type, '')
INTO :h_amount, :h_old_type
FROM ac_ledger
WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0024] 매입 원장 없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_ledger amount(reclass)");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
cnt = ac_rec_count(bizdate, AC_ST_RECV);
/* 업무규칙: 금액 구간별 매입유형 재분류 (대형/중형/소형) */
if (h_amount >= 1000000L) {
class_name = AC_TYPE_LARGE;
} else if (h_amount >= 100000L) {
class_name = AC_TYPE_MEDIUM;
} else {
class_name = AC_TYPE_SMALL;
}
strncpy(h_acq_type, class_name, sizeof(h_acq_type) - 1);
h_acq_type[sizeof(h_acq_type) - 1] = '\0';
if (strcmp(h_old_type, h_acq_type) == 0) {
tx_log(TX_LOG_INFO, "[AC_OL_0024] 재분류 변경 없음 key=%s type=%s",
key, h_acq_type);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "AMOUNT", h_amount);
tx_buf_sets(ctx->out, "OLDTYPE", h_old_type);
tx_buf_sets(ctx->out, "ACQTYPE", h_acq_type);
tx_return(ctx, TX_OK, ctx->out);
return;
}
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0024] 트랜잭션 시작 실패");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
EXEC SQL UPDATE ac_ledger
SET acq_type = :h_acq_type
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger acq_type");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0024] 재분류대상 없음 key=%s", key);
tx_abort();
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0024] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_setlong(ctx->out, "AMOUNT", h_amount);
tx_buf_sets(ctx->out, "OLDTYPE", h_old_type);
tx_buf_sets(ctx->out, "ACQTYPE", h_acq_type);
tx_log(TX_LOG_INFO, "[AC_OL_0024] 완료 key=%s amount=%ld %s -> %s",
key, h_amount, h_old_type, h_acq_type);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,19 @@
/*
* ac_ol_0025.pgc - (AC_OL_0025) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : (BIZDATE) ()
* (ac_ledger.status='R') . ,
* / ( key)
* .
*
*
* ( ).
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,37 +95,131 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0025.pgc"
#line 21 "app/online/ac_ol_0025.pgc"
TX_SERVICE(AC_OL_0025, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* ---- ECPG 호스트 변수 선언부 ---- */
/* exec sql begin declare section */
#line 27 "app/online/ac_ol_0025.pgc"
char h_biz_date [ 9 ] ;
#line 28 "app/online/ac_ol_0025.pgc"
long h_cnt ;
#line 29 "app/online/ac_ol_0025.pgc"
long h_totamt ;
#line 30 "app/online/ac_ol_0025.pgc"
char h_oldest [ 16 ] ;
#line 31 "app/online/ac_ol_0025.pgc"
short h_oldest_ind ;
/* exec sql end declare section */
#line 32 "app/online/ac_ol_0025.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0025] 매입 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0025] KEY 누락");
char bizdate[9];
char totbuf[32];
tx_log(TX_LOG_INFO, "[AC_OL_0025] 미매입 추출 서비스 진입");
/* ---- 1. 입력 검증 ---- */
if (tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK ||
bizdate[0] == '\0') {
tx_log(TX_LOG_ERROR, "[AC_OL_0025] BIZDATE 누락");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0025] 영업일 형식 오류 date=%s", bizdate);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0025] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
return;
memset(h_biz_date, 0, sizeof(h_biz_date));
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
/* ---- 2. 조회기준일 업무 정합성 점검 (참고용 경고, 조회는 계속 진행) ---- */
{
char today[9];
date_today(today);
if (strcmp(bizdate, today) > 0) {
tx_log(TX_LOG_WARN,
"[AC_OL_0025] 조회기준일이 시스템 영업일보다 미래임 date=%s today=%s",
bizdate, today);
}
}
/* ---- 3. 미매입 접수건 집계 (건수 + 합계금액) ---- */
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select count ( * ) , coalesce ( SUM ( amount ) , 0 ) from ac_ledger where biz_date <= $1 and status = 'R'",
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_cnt),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_totamt),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 77 "app/online/ac_ol_0025.pgc"
if (sqlca.sqlcode != TX_SQL_OK && sqlca.sqlcode != TX_SQL_NOTFOUND) {
TX_DBIO_LOG_ERR("SELECT ac_ledger 미매입 집계");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlcode == TX_SQL_NOTFOUND || h_cnt < 0) {
h_cnt = 0;
h_totamt = 0;
}
/* ---- 4. 최장 대기 건(최소 key) 조회 ---- */
memset(h_oldest, 0, sizeof(h_oldest));
h_oldest_ind = -1;
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select MIN ( key ) from ac_ledger where biz_date <= $1 and status = 'R'",
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_char,(h_oldest),(long)16,(long)1,(16)*sizeof(char),
ECPGt_short,&(h_oldest_ind),(long)1,(long)1,sizeof(short), ECPGt_EORT);}
#line 100 "app/online/ac_ol_0025.pgc"
if (sqlca.sqlcode != TX_SQL_OK && sqlca.sqlcode != TX_SQL_NOTFOUND) {
TX_DBIO_LOG_ERR("SELECT ac_ledger 최장대기건");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_oldest_ind < 0 || h_cnt == 0)
h_oldest[0] = '\0';
amount_format_won(h_totamt, totbuf, sizeof(totbuf));
/* ---- 5. 응답 구성 ---- */
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0025] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "BIZDATE", bizdate);
tx_buf_setlong(ctx->out, "CNT", h_cnt);
tx_buf_setlong(ctx->out, "TOTAMT", h_totamt);
tx_buf_sets(ctx->out, "OLDEST", h_oldest);
tx_log(TX_LOG_INFO,
"[AC_OL_0025] 미매입 추출완료 date=%s 건수=%ld 합계=%s 최장대기=%s",
bizdate, h_cnt, totbuf, h_oldest[0] ? h_oldest : "-");
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,19 @@
/*
* ac_ol_0025.pgc - 매입 온라인 서비스 (AC_OL_0025) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 미매입 추출: 지정 영업일(BIZDATE) 이전(포함)까지 누적된 미매입 접수
* (ac_ledger.status='R') 건을 집계한다. 정산 배치 실행 전, 처리 대상
* 잔여 건수/합계금액과 최장 대기 건(최소 key)을 파악하기 위한 조회
* 전용 서비스이다.
*
* 조회기준일이 시스템 영업일보다 미래이면 업무상 비정상 조회로 보고
* 경고 로그만 남기고 조회는 계속 진행한다(운영 모니터링 목적).
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,32 +22,105 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0025, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* ---- ECPG 호스트 변수 선언부 ---- */
EXEC SQL BEGIN DECLARE SECTION;
char h_biz_date[9];
long h_cnt;
long h_totamt;
char h_oldest[16];
short h_oldest_ind;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0025] 매입 단건조회 서비스 진입");
char bizdate[9];
char totbuf[32];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0025] KEY 누락");
tx_log(TX_LOG_INFO, "[AC_OL_0025] 미매입 추출 서비스 진입");
/* ---- 1. 입력 검증 ---- */
if (tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK ||
bizdate[0] == '\0') {
tx_log(TX_LOG_ERROR, "[AC_OL_0025] BIZDATE 누락");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0025] 영업일 형식 오류 date=%s", bizdate);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0025] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
return;
memset(h_biz_date, 0, sizeof(h_biz_date));
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
/* ---- 2. 조회기준일 업무 정합성 점검 (참고용 경고, 조회는 계속 진행) ---- */
{
char today[9];
date_today(today);
if (strcmp(bizdate, today) > 0) {
tx_log(TX_LOG_WARN,
"[AC_OL_0025] 조회기준일이 시스템 영업일보다 미래임 date=%s today=%s",
bizdate, today);
}
}
/* ---- 3. 미매입 접수건 집계 (건수 + 합계금액) ---- */
EXEC SQL
SELECT COUNT(*), COALESCE(SUM(amount), 0)
INTO :h_cnt, :h_totamt
FROM ac_ledger
WHERE biz_date <= :h_biz_date
AND status = 'R';
if (sqlca.sqlcode != TX_SQL_OK && sqlca.sqlcode != TX_SQL_NOTFOUND) {
TX_DBIO_LOG_ERR("SELECT ac_ledger 미매입 집계");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlcode == TX_SQL_NOTFOUND || h_cnt < 0) {
h_cnt = 0;
h_totamt = 0;
}
/* ---- 4. 최장 대기 건(최소 key) 조회 ---- */
memset(h_oldest, 0, sizeof(h_oldest));
h_oldest_ind = -1;
EXEC SQL
SELECT MIN(key)
INTO :h_oldest:h_oldest_ind
FROM ac_ledger
WHERE biz_date <= :h_biz_date
AND status = 'R';
if (sqlca.sqlcode != TX_SQL_OK && sqlca.sqlcode != TX_SQL_NOTFOUND) {
TX_DBIO_LOG_ERR("SELECT ac_ledger 최장대기건");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_oldest_ind < 0 || h_cnt == 0)
h_oldest[0] = '\0';
amount_format_won(h_totamt, totbuf, sizeof(totbuf));
/* ---- 5. 응답 구성 ---- */
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0025] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "BIZDATE", bizdate);
tx_buf_setlong(ctx->out, "CNT", h_cnt);
tx_buf_setlong(ctx->out, "TOTAMT", h_totamt);
tx_buf_sets(ctx->out, "OLDEST", h_oldest);
tx_log(TX_LOG_INFO,
"[AC_OL_0025] 미매입 추출완료 date=%s 건수=%ld 합계=%s 최장대기=%s",
bizdate, h_cnt, totbuf, h_oldest[0] ? h_oldest : "-");
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,17 @@
/*
* ac_ol_0026.pgc - (AC_OL_0026) [tier=hard]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : (ac_ledger.status='U')
* . (status='M')
* ( ), (status='U')
* ( ). ,
* DB .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,88 +93,170 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0026.pgc"
#line 19 "app/online/ac_ol_0026.pgc"
TX_SERVICE(AC_OL_0026, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16], nextbiz[9];
long amount = 0, daysum = 0;
int rc;
TXBUF *sub_in;
TXBUF *sub_out;
/* ---- ECPG 호스트 변수 선언부 ---- */
/* exec sql begin declare section */
#line 25 "app/online/ac_ol_0026.pgc"
char h_biz_date [ 9 ] ;
#line 26 "app/online/ac_ol_0026.pgc"
char h_status_fail [ 2 ] ;
#line 27 "app/online/ac_ol_0026.pgc"
char h_status_done [ 2 ] ;
#line 28 "app/online/ac_ol_0026.pgc"
char h_key [ 16 ] ;
#line 29 "app/online/ac_ol_0026.pgc"
long h_amount ;
/* exec sql end declare section */
#line 30 "app/online/ac_ol_0026.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0026] 매입 트랜잭션 오케스트레이션 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0026] 필수 필드 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
char bizdate[9];
long reprocessed = 0;
long failed = 0;
long dberr = 0;
if (!amount_is_valid(amount) || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0026] 입력 검증 실패 amount=%ld date=%s",
amount, bizdate);
tx_log(TX_LOG_INFO, "[AC_OL_0026] 미매입 재처리 서비스 진입");
/* ---- 1. 입력 검증 ---- */
if (tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK ||
!date_is_valid(bizdate)) {
tx_log(TX_LOG_ERROR, "[AC_OL_0026] BIZDATE 누락/오류");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* 트랜잭션 시작 → 원장 반영 → 후속 서비스 연계 → 커밋 */
memset(h_biz_date, 0, sizeof(h_biz_date));
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
strncpy(h_status_fail, AC_ST_FAIL, sizeof(h_status_fail) - 1);
h_status_fail[sizeof(h_status_fail) - 1] = '\0';
strncpy(h_status_done, AC_ST_DONE, sizeof(h_status_done) - 1);
h_status_done[sizeof(h_status_done) - 1] = '\0';
/* ---- 2. 트랜잭션 시작 ---- */
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0026] 트랜잭션 시작 실패");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100;
/* ---- 3. 실패건 커서 오픈 ---- */
ECPGset_var( 0, ( h_status_fail ), __LINE__);\
ECPGset_var( 1, ( h_biz_date ), __LINE__);\
/* declare cur_ac_ol_0026 cursor for select key , amount from ac_ledger where biz_date = $1 and status = $2 order by key */
#line 71 "app/online/ac_ol_0026.pgc"
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0026] 원장반영 실패 rc=%d", rc);
#line 71 "app/online/ac_ol_0026.pgc"
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare cur_ac_ol_0026 cursor for select key , amount from ac_ledger where biz_date = $1 and status = $2 order by key",
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status_fail),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 73 "app/online/ac_ol_0026.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("cur_ac_ol_0026 open");
tx_abort();
tx_return(ctx, rc, ctx->out);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 정산 영업일 = 거래일의 다음 영업일 */
if (date_next_business(bizdate, nextbiz) != 0) {
memcpy(nextbiz, bizdate, 8);
nextbiz[8] = '\0';
/* ---- 4. 순회 재검증 ---- */
for (;;) {
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch cur_ac_ol_0026", ECPGt_EOIT,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 85 "app/online/ac_ol_0026.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND)
break;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("cur_ac_ol_0026 fetch");
dberr++;
break;
}
if (amount_is_valid(h_amount)) {
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update ac_ledger set status = $1 , upd_ts = now ( ) where key = $2 ",
ECPGt_char,(h_status_done),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 99 "app/online/ac_ol_0026.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("cur_ac_ol_0026 update done");
dberr++;
break;
}
reprocessed++;
tx_log(TX_LOG_DEBUG, "[AC_OL_0026] 재처리성공 key=%s amount=%ld",
h_key, h_amount);
} else {
/* 여전히 유효하지 않은 금액 -> 실패(U) 상태 유지 */
failed++;
tx_log(TX_LOG_DEBUG, "[AC_OL_0026] 재처리보류 key=%s amount=%ld",
h_key, h_amount);
}
}
/* 후속 정산집계 서비스 연계 (레지스트리 문자열 디스패치) */
sub_in = tx_buf_alloc();
sub_out = tx_buf_alloc();
if (sub_in && sub_out) {
tx_buf_sets(sub_in, "MERCHID", merch);
tx_buf_sets(sub_in, "BIZDATE", nextbiz);
tx_buf_setlong(sub_in, "AMOUNT", amount);
rc = tx_call("AC_POST", sub_in, sub_out);
if (rc != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0026] 후속연계 경고 rc=%d", rc);
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close cur_ac_ol_0026", ECPGt_EOIT, ECPGt_EORT);}
#line 117 "app/online/ac_ol_0026.pgc"
/* ---- 5. 커밋/롤백 ---- */
if (dberr > 0) {
tx_log(TX_LOG_ERROR, "[AC_OL_0026] DB 오류로 전체 롤백 dberr=%ld", dberr);
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_buf_free(sub_in);
tx_buf_free(sub_out);
/* 교차 검증: 당일 합계 재계산 */
if (ac_rec_sum(bizdate, &daysum) != TX_OK)
daysum = 0;
tx_commit();
if (tx_commit() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0026] 커밋 실패");
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
/* ---- 6. 응답 구성 ---- */
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYSUM", daysum);
tx_log(TX_LOG_INFO, "[AC_OL_0026] 완료 key=%s 당일합계=%ld", key, daysum);
tx_buf_sets(ctx->out, "BIZDATE", bizdate);
tx_buf_setlong(ctx->out, "REPROCESSED", reprocessed);
tx_buf_setlong(ctx->out, "FAILED", failed);
tx_log(TX_LOG_INFO,
"[AC_OL_0026] 재처리완료 date=%s 성공=%ld 보류=%ld",
bizdate, reprocessed, failed);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,17 @@
/*
* ac_ol_0026.pgc - 매입 온라인 서비스 (AC_OL_0026) [tier=hard]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 미매입 재처리: 지정 영업일의 실패건(ac_ledger.status='U')을 커서로
* 순회하며 금액 유효성을 재검증한다. 유효하면 완료(status='M')로
* 전이(재처리 성공)하고, 여전히 유효하지 않으면 실패(status='U') 상태를
* 유지(재처리 보류)한다. 전 건을 하나의 트랜잭션으로 묶어 처리하며,
* DB 오류 발생 시 전체 롤백한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,83 +20,130 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0026, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16], nextbiz[9];
long amount = 0, daysum = 0;
int rc;
TXBUF *sub_in;
TXBUF *sub_out;
/* ---- ECPG 호스트 변수 선언부 ---- */
EXEC SQL BEGIN DECLARE SECTION;
char h_biz_date[9];
char h_status_fail[2];
char h_status_done[2];
char h_key[16];
long h_amount;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0026] 매입 트랜잭션 오케스트레이션 진입");
char bizdate[9];
long reprocessed = 0;
long failed = 0;
long dberr = 0;
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0026] 필수 필드 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
tx_log(TX_LOG_INFO, "[AC_OL_0026] 미매입 재처리 서비스 진입");
if (!amount_is_valid(amount) || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0026] 입력 검증 실패 amount=%ld date=%s",
amount, bizdate);
/* ---- 1. 입력 검증 ---- */
if (tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK ||
!date_is_valid(bizdate)) {
tx_log(TX_LOG_ERROR, "[AC_OL_0026] BIZDATE 누락/오류");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* 트랜잭션 시작 → 원장 반영 → 후속 서비스 연계 → 커밋 */
memset(h_biz_date, 0, sizeof(h_biz_date));
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
strncpy(h_status_fail, AC_ST_FAIL, sizeof(h_status_fail) - 1);
h_status_fail[sizeof(h_status_fail) - 1] = '\0';
strncpy(h_status_done, AC_ST_DONE, sizeof(h_status_done) - 1);
h_status_done[sizeof(h_status_done) - 1] = '\0';
/* ---- 2. 트랜잭션 시작 ---- */
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0026] 트랜잭션 시작 실패");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100;
/* ---- 3. 실패건 커서 오픈 ---- */
EXEC SQL DECLARE cur_ac_ol_0026 CURSOR FOR
SELECT key, amount
FROM ac_ledger
WHERE biz_date = :h_biz_date
AND status = :h_status_fail
ORDER BY key;
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0026] 원장반영 실패 rc=%d", rc);
EXEC SQL OPEN cur_ac_ol_0026;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("cur_ac_ol_0026 open");
tx_abort();
tx_return(ctx, rc, ctx->out);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 정산 영업일 = 거래일의 다음 영업일 */
if (date_next_business(bizdate, nextbiz) != 0) {
memcpy(nextbiz, bizdate, 8);
nextbiz[8] = '\0';
/* ---- 4. 순회 재검증 ---- */
for (;;) {
EXEC SQL FETCH cur_ac_ol_0026 INTO :h_key, :h_amount;
if (sqlca.sqlcode == TX_SQL_NOTFOUND)
break;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("cur_ac_ol_0026 fetch");
dberr++;
break;
}
if (amount_is_valid(h_amount)) {
EXEC SQL
UPDATE ac_ledger
SET status = :h_status_done, upd_ts = now()
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("cur_ac_ol_0026 update done");
dberr++;
break;
}
reprocessed++;
tx_log(TX_LOG_DEBUG, "[AC_OL_0026] 재처리성공 key=%s amount=%ld",
h_key, h_amount);
} else {
/* 여전히 유효하지 않은 금액 -> 실패(U) 상태 유지 */
failed++;
tx_log(TX_LOG_DEBUG, "[AC_OL_0026] 재처리보류 key=%s amount=%ld",
h_key, h_amount);
}
}
/* 후속 정산집계 서비스 연계 (레지스트리 문자열 디스패치) */
sub_in = tx_buf_alloc();
sub_out = tx_buf_alloc();
if (sub_in && sub_out) {
tx_buf_sets(sub_in, "MERCHID", merch);
tx_buf_sets(sub_in, "BIZDATE", nextbiz);
tx_buf_setlong(sub_in, "AMOUNT", amount);
rc = tx_call("AC_POST", sub_in, sub_out);
if (rc != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0026] 후속연계 경고 rc=%d", rc);
EXEC SQL CLOSE cur_ac_ol_0026;
/* ---- 5. 커밋/롤백 ---- */
if (dberr > 0) {
tx_log(TX_LOG_ERROR, "[AC_OL_0026] DB 오류로 전체 롤백 dberr=%ld", dberr);
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_buf_free(sub_in);
tx_buf_free(sub_out);
/* 교차 검증: 당일 합계 재계산 */
if (ac_rec_sum(bizdate, &daysum) != TX_OK)
daysum = 0;
tx_commit();
if (tx_commit() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0026] 커밋 실패");
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
/* ---- 6. 응답 구성 ---- */
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYSUM", daysum);
tx_log(TX_LOG_INFO, "[AC_OL_0026] 완료 key=%s 당일합계=%ld", key, daysum);
tx_buf_sets(ctx->out, "BIZDATE", bizdate);
tx_buf_setlong(ctx->out, "REPROCESSED", reprocessed);
tx_buf_setlong(ctx->out, "FAILED", failed);
tx_log(TX_LOG_INFO,
"[AC_OL_0026] 재처리완료 date=%s 성공=%ld 보류=%ld",
bizdate, reprocessed, failed);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,20 @@
/*
* ac_ol_0027.pgc - (AC_OL_0027) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : (status='M') + (status='S')
* /// .
* /
* .
*
* , 0
* 0 0-division . (bp)
* .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,37 +96,134 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0027.pgc"
#line 22 "app/online/ac_ol_0027.pgc"
TX_SERVICE(AC_OL_0027, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* ---- ECPG 호스트 변수 선언부 ---- */
/* exec sql begin declare section */
#line 28 "app/online/ac_ol_0027.pgc"
char h_biz_date [ 9 ] ;
#line 29 "app/online/ac_ol_0027.pgc"
char h_status_done [ 2 ] ;
#line 30 "app/online/ac_ol_0027.pgc"
char h_status_settled [ 2 ] ;
#line 31 "app/online/ac_ol_0027.pgc"
long h_cnt ;
#line 32 "app/online/ac_ol_0027.pgc"
long h_tot ;
#line 33 "app/online/ac_ol_0027.pgc"
long h_totfee ;
/* exec sql end declare section */
#line 34 "app/online/ac_ol_0027.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0027] 매입 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0027] KEY 누락");
char bizdate[9];
char totbuf[32];
long avg = 0;
long avgfee = 0;
long feeratebp = 0;
tx_log(TX_LOG_INFO, "[AC_OL_0027] 매입 통계 서비스 진입");
/* ---- 1. 입력 검증 ---- */
if (tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK ||
!date_is_valid(bizdate)) {
tx_log(TX_LOG_ERROR, "[AC_OL_0027] BIZDATE 누락/오류");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0027] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
memset(h_biz_date, 0, sizeof(h_biz_date));
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
strncpy(h_status_done, AC_ST_DONE, sizeof(h_status_done) - 1);
h_status_done[sizeof(h_status_done) - 1] = '\0';
strncpy(h_status_settled, AC_ST_SETTLED, sizeof(h_status_settled) - 1);
h_status_settled[sizeof(h_status_settled) - 1] = '\0';
/* ---- 2. 완료 + 정산완료 건 집계 ---- */
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select count ( * ) , coalesce ( SUM ( amount ) , 0 ) , coalesce ( SUM ( fee ) , 0 ) from ac_ledger where biz_date = $1 and status in ( $2 , $3 )",
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status_done),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status_settled),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_cnt),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_tot),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_totfee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 67 "app/online/ac_ol_0027.pgc"
if (sqlca.sqlcode != TX_SQL_OK && sqlca.sqlcode != TX_SQL_NOTFOUND) {
TX_DBIO_LOG_ERR("SELECT ac_ledger 매입통계");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlcode == TX_SQL_NOTFOUND || h_cnt < 0) {
h_cnt = 0;
h_tot = 0;
h_totfee = 0;
}
tx_log(TX_LOG_DEBUG,
"[AC_OL_0027] 원시집계 date=%s 건수=%ld 합계=%ld 수수료=%ld",
bizdate, h_cnt, h_tot, h_totfee);
/* ---- 3. 건당 평균금액/평균수수료 산출 (0건 가드) ---- */
if (h_cnt > 0) {
avg = h_tot / h_cnt;
avgfee = h_totfee / h_cnt;
} else {
avg = 0;
avgfee = 0;
}
/*
* ---- 4. (bp, 1bp=0.01%) ( 0 ) ----
* feeratebp = * 10000 /
* (: feeratebp=150 -> 1.50%)
*/
if (h_tot > 0)
feeratebp = (h_totfee * 10000) / h_tot;
else
feeratebp = 0;
amount_format_won(h_tot, totbuf, sizeof(totbuf));
/* ---- 5. 응답 구성 ---- */
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0027] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "BIZDATE", bizdate);
tx_buf_setlong(ctx->out, "CNT", h_cnt);
tx_buf_setlong(ctx->out, "TOTAMT", h_tot);
tx_buf_setlong(ctx->out, "TOTFEE", h_totfee);
tx_buf_setlong(ctx->out, "AVGAMT", avg);
tx_buf_setlong(ctx->out, "AVGFEE", avgfee);
tx_buf_setlong(ctx->out, "FEERATEBP", feeratebp);
tx_log(TX_LOG_INFO,
"[AC_OL_0027] 매입통계완료 date=%s 건수=%ld 합계=%s 수수료=%ld 평균금액=%ld "
"평균수수료=%ld 수수료율(bp)=%ld",
bizdate, h_cnt, totbuf, h_totfee, avg, avgfee, feeratebp);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,20 @@
/*
* ac_ol_0027.pgc - 매입 온라인 서비스 (AC_OL_0027) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 매입 통계: 지정 영업일의 완료(status='M') + 정산완료(status='S') 건을
* 집계하여 건수/매입금액합계/수수료합계/건당 평균금액을 산출한다.
* 일별 매입 현황 대시보드/모니터링 화면에서 조회하는 통계 전용
* 서비스이다.
*
* 평균금액은 매입금액합계를 건수로 나눈 값이며, 대상 건이 0건이면
* 0으로 가드하여 0-division 을 방지한다. 실효 수수료율(bp)도 함께
* 산출하여 가맹점 수수료율 이상 징후를 조기에 확인할 수 있게 한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,32 +23,100 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0027, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* ---- ECPG 호스트 변수 선언부 ---- */
EXEC SQL BEGIN DECLARE SECTION;
char h_biz_date[9];
char h_status_done[2];
char h_status_settled[2];
long h_cnt;
long h_tot;
long h_totfee;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0027] 매입 단건조회 서비스 진입");
char bizdate[9];
char totbuf[32];
long avg = 0;
long avgfee = 0;
long feeratebp = 0;
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0027] KEY 누락");
tx_log(TX_LOG_INFO, "[AC_OL_0027] 매입 통계 서비스 진입");
/* ---- 1. 입력 검증 ---- */
if (tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK ||
!date_is_valid(bizdate)) {
tx_log(TX_LOG_ERROR, "[AC_OL_0027] BIZDATE 누락/오류");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0027] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
memset(h_biz_date, 0, sizeof(h_biz_date));
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
strncpy(h_status_done, AC_ST_DONE, sizeof(h_status_done) - 1);
h_status_done[sizeof(h_status_done) - 1] = '\0';
strncpy(h_status_settled, AC_ST_SETTLED, sizeof(h_status_settled) - 1);
h_status_settled[sizeof(h_status_settled) - 1] = '\0';
/* ---- 2. 완료 + 정산완료 건 집계 ---- */
EXEC SQL
SELECT COUNT(*), COALESCE(SUM(amount), 0), COALESCE(SUM(fee), 0)
INTO :h_cnt, :h_tot, :h_totfee
FROM ac_ledger
WHERE biz_date = :h_biz_date
AND status IN (:h_status_done, :h_status_settled);
if (sqlca.sqlcode != TX_SQL_OK && sqlca.sqlcode != TX_SQL_NOTFOUND) {
TX_DBIO_LOG_ERR("SELECT ac_ledger 매입통계");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlcode == TX_SQL_NOTFOUND || h_cnt < 0) {
h_cnt = 0;
h_tot = 0;
h_totfee = 0;
}
tx_log(TX_LOG_DEBUG,
"[AC_OL_0027] 원시집계 date=%s 건수=%ld 합계=%ld 수수료=%ld",
bizdate, h_cnt, h_tot, h_totfee);
/* ---- 3. 건당 평균금액/평균수수료 산출 (0건 가드) ---- */
if (h_cnt > 0) {
avg = h_tot / h_cnt;
avgfee = h_totfee / h_cnt;
} else {
avg = 0;
avgfee = 0;
}
/*
* ---- 4. 실효 수수료율(bp, 1bp=0.01%) 산출 (매입금액합계 0 가드) ----
* feeratebp = 수수료합계 * 10000 / 매입금액합계
* (예: feeratebp=150 -> 실효 수수료율 1.50%)
*/
if (h_tot > 0)
feeratebp = (h_totfee * 10000) / h_tot;
else
feeratebp = 0;
amount_format_won(h_tot, totbuf, sizeof(totbuf));
/* ---- 5. 응답 구성 ---- */
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0027] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "BIZDATE", bizdate);
tx_buf_setlong(ctx->out, "CNT", h_cnt);
tx_buf_setlong(ctx->out, "TOTAMT", h_tot);
tx_buf_setlong(ctx->out, "TOTFEE", h_totfee);
tx_buf_setlong(ctx->out, "AVGAMT", avg);
tx_buf_setlong(ctx->out, "AVGFEE", avgfee);
tx_buf_setlong(ctx->out, "FEERATEBP", feeratebp);
tx_log(TX_LOG_INFO,
"[AC_OL_0027] 매입통계완료 date=%s 건수=%ld 합계=%s 수수료=%ld 평균금액=%ld "
"평균수수료=%ld 수수료율(bp)=%ld",
bizdate, h_cnt, totbuf, h_totfee, avg, avgfee, feeratebp);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,17 @@
/*
* ac_ol_0028.pgc - (AC_OL_0028) [tier=hard]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : (status='M')
* , 10%
* (tax_invoice) 1 /.
* , DB
* .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,88 +93,183 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0028.pgc"
#line 19 "app/online/ac_ol_0028.pgc"
TX_SERVICE(AC_OL_0028, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16], nextbiz[9];
long amount = 0, daysum = 0;
int rc;
TXBUF *sub_in;
TXBUF *sub_out;
/* ---- ECPG 호스트 변수 선언부 ---- */
/* exec sql begin declare section */
#line 25 "app/online/ac_ol_0028.pgc"
char h_biz_date [ 9 ] ;
#line 26 "app/online/ac_ol_0028.pgc"
char h_status_done [ 2 ] ;
#line 27 "app/online/ac_ol_0028.pgc"
char h_merch_id [ 16 ] ;
#line 28 "app/online/ac_ol_0028.pgc"
long h_supply ;
#line 29 "app/online/ac_ol_0028.pgc"
char h_tax_no [ 32 ] ;
#line 30 "app/online/ac_ol_0028.pgc"
long h_vat ;
/* exec sql end declare section */
#line 31 "app/online/ac_ol_0028.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0028] 매입 트랜잭션 오케스트레이션 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0028] 필수 필드 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
char bizdate[9];
long merch_cnt = 0;
long tot_supply = 0;
long tot_vat = 0;
long dberr = 0;
if (!amount_is_valid(amount) || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0028] 입력 검증 실패 amount=%ld date=%s",
amount, bizdate);
tx_log(TX_LOG_INFO, "[AC_OL_0028] 매입 세금계산서 발행집계 서비스 진입");
/* ---- 1. 입력 검증 ---- */
if (tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK ||
!date_is_valid(bizdate)) {
tx_log(TX_LOG_ERROR, "[AC_OL_0028] BIZDATE 누락/오류");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* 트랜잭션 시작 → 원장 반영 → 후속 서비스 연계 → 커밋 */
memset(h_biz_date, 0, sizeof(h_biz_date));
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
strncpy(h_status_done, AC_ST_DONE, sizeof(h_status_done) - 1);
h_status_done[sizeof(h_status_done) - 1] = '\0';
/* ---- 2. 트랜잭션 시작 ---- */
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0028] 트랜잭션 시작 실패");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100;
/* ---- 3. 가맹점별 매입합계 그룹핑 커서 ---- */
ECPGset_var( 0, ( h_status_done ), __LINE__);\
ECPGset_var( 1, ( h_biz_date ), __LINE__);\
/* declare cur_ac_ol_0028 cursor for select merch_id , SUM ( amount ) from ac_ledger where biz_date = $1 and status = $2 group by merch_id order by merch_id */
#line 72 "app/online/ac_ol_0028.pgc"
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0028] 원장반영 실패 rc=%d", rc);
#line 72 "app/online/ac_ol_0028.pgc"
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare cur_ac_ol_0028 cursor for select merch_id , SUM ( amount ) from ac_ledger where biz_date = $1 and status = $2 group by merch_id order by merch_id",
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status_done),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 74 "app/online/ac_ol_0028.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("cur_ac_ol_0028 open");
tx_abort();
tx_return(ctx, rc, ctx->out);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 정산 영업일 = 거래일의 다음 영업일 */
if (date_next_business(bizdate, nextbiz) != 0) {
memcpy(nextbiz, bizdate, 8);
nextbiz[8] = '\0';
/* ---- 4. 가맹점 순회: 세금계산서 발행 ---- */
for (;;) {
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch cur_ac_ol_0028", ECPGt_EOIT,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_supply),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 86 "app/online/ac_ol_0028.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND)
break;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("cur_ac_ol_0028 fetch");
dberr++;
break;
}
/* 업무규칙: 매입 합계금액을 공급가액으로 보고 부가세 10% 산정 */
h_vat = h_supply / 10;
memset(h_tax_no, 0, sizeof(h_tax_no));
snprintf(h_tax_no, sizeof(h_tax_no), "%s%s", h_biz_date, h_merch_id);
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into tax_invoice ( tax_no , merch_id , biz_date , supply_amt , vat_amt ) values ( $1 , $2 , $3 , $4 , $5 )",
ECPGt_char,(h_tax_no),(long)32,(long)1,(32)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_supply),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_vat),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 104 "app/online/ac_ol_0028.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("cur_ac_ol_0028 insert tax_invoice");
dberr++;
break;
}
merch_cnt++;
tot_supply += h_supply;
tot_vat += h_vat;
tx_log(TX_LOG_DEBUG,
"[AC_OL_0028] 발행 merch=%s 공급가액=%ld 부가세=%ld",
h_merch_id, h_supply, h_vat);
}
/* 후속 정산집계 서비스 연계 (레지스트리 문자열 디스패치) */
sub_in = tx_buf_alloc();
sub_out = tx_buf_alloc();
if (sub_in && sub_out) {
tx_buf_sets(sub_in, "MERCHID", merch);
tx_buf_sets(sub_in, "BIZDATE", nextbiz);
tx_buf_setlong(sub_in, "AMOUNT", amount);
rc = tx_call("AC_POST", sub_in, sub_out);
if (rc != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0028] 후속연계 경고 rc=%d", rc);
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close cur_ac_ol_0028", ECPGt_EOIT, ECPGt_EORT);}
#line 120 "app/online/ac_ol_0028.pgc"
/* ---- 5. 커밋/롤백 ---- */
if (dberr > 0) {
tx_log(TX_LOG_ERROR, "[AC_OL_0028] DB 오류로 전체 롤백 dberr=%ld", dberr);
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_buf_free(sub_in);
tx_buf_free(sub_out);
/* 교차 검증: 당일 합계 재계산 */
if (ac_rec_sum(bizdate, &daysum) != TX_OK)
daysum = 0;
tx_commit();
if (tx_commit() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0028] 커밋 실패");
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
/* ---- 6. 응답 구성 ---- */
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYSUM", daysum);
tx_log(TX_LOG_INFO, "[AC_OL_0028] 완료 key=%s 당일합계=%ld", key, daysum);
tx_buf_sets(ctx->out, "BIZDATE", bizdate);
tx_buf_setlong(ctx->out, "MERCHCNT", merch_cnt);
tx_buf_setlong(ctx->out, "TOTSUPPLY", tot_supply);
tx_buf_setlong(ctx->out, "TOTVAT", tot_vat);
tx_log(TX_LOG_INFO,
"[AC_OL_0028] 발행집계완료 date=%s 가맹점수=%ld 공급가액합계=%ld 부가세합계=%ld",
bizdate, merch_cnt, tot_supply, tot_vat);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,17 @@
/*
* ac_ol_0028.pgc - 매입 온라인 서비스 (AC_OL_0028) [tier=hard]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 매입 세금계산서 발행집계: 지정 영업일의 완료(status='M') 매입 원장을
* 가맹점별로 그룹핑하여 매입 합계금액을 공급가액으로, 그 10%를 부가세로
* 산정한 세금계산서(tax_invoice)를 가맹점 단위로 1건씩 발행/적재한다.
* 전 가맹점을 하나의 트랜잭션으로 묶어 처리하며, DB 오류 발생 시 전체
* 롤백한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,83 +20,134 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0028, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16], nextbiz[9];
long amount = 0, daysum = 0;
int rc;
TXBUF *sub_in;
TXBUF *sub_out;
/* ---- ECPG 호스트 변수 선언부 ---- */
EXEC SQL BEGIN DECLARE SECTION;
char h_biz_date[9];
char h_status_done[2];
char h_merch_id[16];
long h_supply;
char h_tax_no[32];
long h_vat;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0028] 매입 트랜잭션 오케스트레이션 진입");
char bizdate[9];
long merch_cnt = 0;
long tot_supply = 0;
long tot_vat = 0;
long dberr = 0;
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0028] 필수 필드 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
tx_log(TX_LOG_INFO, "[AC_OL_0028] 매입 세금계산서 발행집계 서비스 진입");
if (!amount_is_valid(amount) || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0028] 입력 검증 실패 amount=%ld date=%s",
amount, bizdate);
/* ---- 1. 입력 검증 ---- */
if (tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK ||
!date_is_valid(bizdate)) {
tx_log(TX_LOG_ERROR, "[AC_OL_0028] BIZDATE 누락/오류");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* 트랜잭션 시작 → 원장 반영 → 후속 서비스 연계 → 커밋 */
memset(h_biz_date, 0, sizeof(h_biz_date));
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
strncpy(h_status_done, AC_ST_DONE, sizeof(h_status_done) - 1);
h_status_done[sizeof(h_status_done) - 1] = '\0';
/* ---- 2. 트랜잭션 시작 ---- */
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0028] 트랜잭션 시작 실패");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100;
/* ---- 3. 가맹점별 매입합계 그룹핑 커서 ---- */
EXEC SQL DECLARE cur_ac_ol_0028 CURSOR FOR
SELECT merch_id, SUM(amount)
FROM ac_ledger
WHERE biz_date = :h_biz_date
AND status = :h_status_done
GROUP BY merch_id
ORDER BY merch_id;
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0028] 원장반영 실패 rc=%d", rc);
EXEC SQL OPEN cur_ac_ol_0028;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("cur_ac_ol_0028 open");
tx_abort();
tx_return(ctx, rc, ctx->out);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 정산 영업일 = 거래일의 다음 영업일 */
if (date_next_business(bizdate, nextbiz) != 0) {
memcpy(nextbiz, bizdate, 8);
nextbiz[8] = '\0';
/* ---- 4. 가맹점 순회: 세금계산서 발행 ---- */
for (;;) {
EXEC SQL FETCH cur_ac_ol_0028 INTO :h_merch_id, :h_supply;
if (sqlca.sqlcode == TX_SQL_NOTFOUND)
break;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("cur_ac_ol_0028 fetch");
dberr++;
break;
}
/* 업무규칙: 매입 합계금액을 공급가액으로 보고 부가세 10% 산정 */
h_vat = h_supply / 10;
memset(h_tax_no, 0, sizeof(h_tax_no));
snprintf(h_tax_no, sizeof(h_tax_no), "%s%s", h_biz_date, h_merch_id);
EXEC SQL
INSERT INTO tax_invoice (tax_no, merch_id, biz_date, supply_amt, vat_amt)
VALUES (:h_tax_no, :h_merch_id, :h_biz_date, :h_supply, :h_vat);
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("cur_ac_ol_0028 insert tax_invoice");
dberr++;
break;
}
merch_cnt++;
tot_supply += h_supply;
tot_vat += h_vat;
tx_log(TX_LOG_DEBUG,
"[AC_OL_0028] 발행 merch=%s 공급가액=%ld 부가세=%ld",
h_merch_id, h_supply, h_vat);
}
/* 후속 정산집계 서비스 연계 (레지스트리 문자열 디스패치) */
sub_in = tx_buf_alloc();
sub_out = tx_buf_alloc();
if (sub_in && sub_out) {
tx_buf_sets(sub_in, "MERCHID", merch);
tx_buf_sets(sub_in, "BIZDATE", nextbiz);
tx_buf_setlong(sub_in, "AMOUNT", amount);
rc = tx_call("AC_POST", sub_in, sub_out);
if (rc != TX_OK)
tx_log(TX_LOG_WARN, "[AC_OL_0028] 후속연계 경고 rc=%d", rc);
EXEC SQL CLOSE cur_ac_ol_0028;
/* ---- 5. 커밋/롤백 ---- */
if (dberr > 0) {
tx_log(TX_LOG_ERROR, "[AC_OL_0028] DB 오류로 전체 롤백 dberr=%ld", dberr);
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_buf_free(sub_in);
tx_buf_free(sub_out);
/* 교차 검증: 당일 합계 재계산 */
if (ac_rec_sum(bizdate, &daysum) != TX_OK)
daysum = 0;
tx_commit();
if (tx_commit() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0028] 커밋 실패");
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
/* ---- 6. 응답 구성 ---- */
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYSUM", daysum);
tx_log(TX_LOG_INFO, "[AC_OL_0028] 완료 key=%s 당일합계=%ld", key, daysum);
tx_buf_sets(ctx->out, "BIZDATE", bizdate);
tx_buf_setlong(ctx->out, "MERCHCNT", merch_cnt);
tx_buf_setlong(ctx->out, "TOTSUPPLY", tot_supply);
tx_buf_setlong(ctx->out, "TOTVAT", tot_vat);
tx_log(TX_LOG_INFO,
"[AC_OL_0028] 발행집계완료 date=%s 가맹점수=%ld 공급가액합계=%ld 부가세합계=%ld",
bizdate, merch_cnt, tot_supply, tot_vat);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,18 @@
/*
* ac_ol_0029.pgc - (AC_OL_0029) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* (EDI): (CLAIMNO) (ac_claim)
* . EDI //
* // .
*
* EDI ,
* .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,37 +94,138 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0029.pgc"
#line 20 "app/online/ac_ol_0029.pgc"
TX_SERVICE(AC_OL_0029, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* ---- ECPG 호스트 변수 선언부 ---- */
/* exec sql begin declare section */
#line 26 "app/online/ac_ol_0029.pgc"
char h_claim_no [ 16 ] ;
#line 27 "app/online/ac_ol_0029.pgc"
char h_merch_id [ 16 ] ;
#line 28 "app/online/ac_ol_0029.pgc"
char h_biz_date [ 9 ] ;
#line 29 "app/online/ac_ol_0029.pgc"
long h_amount ;
#line 30 "app/online/ac_ol_0029.pgc"
long h_file_seq ;
#line 31 "app/online/ac_ol_0029.pgc"
char h_status [ 2 ] ;
/* exec sql end declare section */
#line 32 "app/online/ac_ol_0029.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0029] 매입 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0029] KEY 누락");
char claimno[16];
int len;
tx_log(TX_LOG_INFO, "[AC_OL_0029] 매입 청구조회(EDI) 서비스 진입");
/* ---- 1. 입력 검증 ---- */
if (tx_buf_get(ctx->in, "CLAIMNO", claimno, sizeof(claimno)) != TX_OK ||
claimno[0] == '\0') {
tx_log(TX_LOG_ERROR, "[AC_OL_0029] CLAIMNO 누락");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0029] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
/* ---- 2. 청구번호 정규화 (EDI 고정길이 전문의 트레일링 공백 제거) ---- */
len = (int)strlen(claimno);
while (len > 0 && claimno[len - 1] == ' ')
claimno[--len] = '\0';
if (len == 0) {
tx_log(TX_LOG_ERROR, "[AC_OL_0029] CLAIMNO 공백 전문");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(h_claim_no, 0, sizeof(h_claim_no));
strncpy(h_claim_no, claimno, sizeof(h_claim_no) - 1);
/* ---- 3. 청구내역 단건 조회 ---- */
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select merch_id , biz_date , amount , file_seq , status from ac_claim where claim_no = $1 ",
ECPGt_char,(h_claim_no),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_file_seq),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 70 "app/online/ac_ol_0029.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0029] 청구건 없음 claim_no=%s", claimno);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_claim");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* ---- 4. EDI 연계 정합성 참고 확인 (파일순번 미채번 시 경고만 남김) ---- */
if (h_file_seq <= 0) {
tx_log(TX_LOG_WARN,
"[AC_OL_0029] 파일순번 미채번 claim_no=%s file_seq=%ld",
claimno, h_file_seq);
}
/* ---- 5. 상태코드 설명 참고 로그 (응답필드는 원본 코드값 그대로 반환) ---- */
{
const char *statusdesc = "알수없음";
if (strcmp(h_status, "W") == 0)
statusdesc = "대기";
else if (strcmp(h_status, "S") == 0)
statusdesc = "전송완료";
else if (strcmp(h_status, "E") == 0)
statusdesc = "오류";
tx_log(TX_LOG_DEBUG, "[AC_OL_0029] 상태설명 claim_no=%s status=%s(%s)",
claimno, h_status, statusdesc);
}
/* ---- 6. 응답 구성 ---- */
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0029] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "CLAIMNO", claimno);
tx_buf_sets(ctx->out, "MERCHID", h_merch_id);
tx_buf_sets(ctx->out, "BIZDATE", h_biz_date);
tx_buf_setlong(ctx->out, "AMOUNT", h_amount);
tx_buf_setlong(ctx->out, "FILESEQ", h_file_seq);
tx_buf_sets(ctx->out, "STATUS", h_status);
tx_log(TX_LOG_INFO,
"[AC_OL_0029] 청구조회완료 claim_no=%s merch=%s amount=%ld status=%s",
claimno, h_merch_id, h_amount, h_status);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,18 @@
/*
* ac_ol_0029.pgc - 매입 온라인 서비스 (AC_OL_0029) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 매입 청구조회(EDI): 청구번호(CLAIMNO)로 매입 청구내역(ac_claim)을
* 단건 조회한다. EDI 연계 파일로 실제 적재된 청구건의 가맹점/영업일/
* 금액/파일순번/상태를 확인하기 위한 조회 전용 서비스이다.
*
* 청구번호는 EDI 파일 헤더에서 채번되어 전달되므로, 조회 전 앞뒤
* 공백을 제거하여 정규화한 뒤 원장 키로 사용한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,32 +21,103 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0029, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* ---- ECPG 호스트 변수 선언부 ---- */
EXEC SQL BEGIN DECLARE SECTION;
char h_claim_no[16];
char h_merch_id[16];
char h_biz_date[9];
long h_amount;
long h_file_seq;
char h_status[2];
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0029] 매입 단건조회 서비스 진입");
char claimno[16];
int len;
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0029] KEY 누락");
tx_log(TX_LOG_INFO, "[AC_OL_0029] 매입 청구조회(EDI) 서비스 진입");
/* ---- 1. 입력 검증 ---- */
if (tx_buf_get(ctx->in, "CLAIMNO", claimno, sizeof(claimno)) != TX_OK ||
claimno[0] == '\0') {
tx_log(TX_LOG_ERROR, "[AC_OL_0029] CLAIMNO 누락");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0029] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
/* ---- 2. 청구번호 정규화 (EDI 고정길이 전문의 트레일링 공백 제거) ---- */
len = (int)strlen(claimno);
while (len > 0 && claimno[len - 1] == ' ')
claimno[--len] = '\0';
if (len == 0) {
tx_log(TX_LOG_ERROR, "[AC_OL_0029] CLAIMNO 공백 전문");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(h_claim_no, 0, sizeof(h_claim_no));
strncpy(h_claim_no, claimno, sizeof(h_claim_no) - 1);
/* ---- 3. 청구내역 단건 조회 ---- */
EXEC SQL
SELECT merch_id, biz_date, amount, file_seq, status
INTO :h_merch_id, :h_biz_date, :h_amount, :h_file_seq, :h_status
FROM ac_claim
WHERE claim_no = :h_claim_no;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0029] 청구건 없음 claim_no=%s", claimno);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_claim");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* ---- 4. EDI 연계 정합성 참고 확인 (파일순번 미채번 시 경고만 남김) ---- */
if (h_file_seq <= 0) {
tx_log(TX_LOG_WARN,
"[AC_OL_0029] 파일순번 미채번 claim_no=%s file_seq=%ld",
claimno, h_file_seq);
}
/* ---- 5. 상태코드 설명 참고 로그 (응답필드는 원본 코드값 그대로 반환) ---- */
{
const char *statusdesc = "알수없음";
if (strcmp(h_status, "W") == 0)
statusdesc = "대기";
else if (strcmp(h_status, "S") == 0)
statusdesc = "전송완료";
else if (strcmp(h_status, "E") == 0)
statusdesc = "오류";
tx_log(TX_LOG_DEBUG, "[AC_OL_0029] 상태설명 claim_no=%s status=%s(%s)",
claimno, h_status, statusdesc);
}
/* ---- 6. 응답 구성 ---- */
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0029] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "CLAIMNO", claimno);
tx_buf_sets(ctx->out, "MERCHID", h_merch_id);
tx_buf_sets(ctx->out, "BIZDATE", h_biz_date);
tx_buf_setlong(ctx->out, "AMOUNT", h_amount);
tx_buf_setlong(ctx->out, "FILESEQ", h_file_seq);
tx_buf_sets(ctx->out, "STATUS", h_status);
tx_log(TX_LOG_INFO,
"[AC_OL_0029] 청구조회완료 claim_no=%s merch=%s amount=%ld status=%s",
claimno, h_merch_id, h_amount, h_status);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,15 @@
/*
* ac_ol_0030.pgc - (AC_OL_0030) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : ///
* ac_ledger ( key)
* (status='U') .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,37 +91,168 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0030.pgc"
#line 17 "app/online/ac_ol_0030.pgc"
TX_SERVICE(AC_OL_0030, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* ---- ECPG 호스트 변수 선언부 ---- */
/* exec sql begin declare section */
#line 23 "app/online/ac_ol_0030.pgc"
char h_merch_id [ 16 ] ;
#line 24 "app/online/ac_ol_0030.pgc"
char h_card_no [ 20 ] ;
#line 25 "app/online/ac_ol_0030.pgc"
long h_amount ;
#line 26 "app/online/ac_ol_0030.pgc"
char h_biz_date [ 9 ] ;
#line 27 "app/online/ac_ol_0030.pgc"
char h_status_fail [ 2 ] ;
#line 28 "app/online/ac_ol_0030.pgc"
long h_dupcnt ;
/* exec sql end declare section */
#line 29 "app/online/ac_ol_0030.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0030] 매입 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0030] KEY 누락");
char merch[16], cardno[20], bizdate[9];
long amount = 0;
long voided = 0;
tx_log(TX_LOG_INFO, "[AC_OL_0030] 매입 중복해제 서비스 진입");
/* ---- 1. 입력 검증 ---- */
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "CARDNO", cardno, sizeof(cardno)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0030] 필수 필드 누락");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
if (!amount_is_valid(amount) || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0030] 입력 검증 실패 amount=%ld date=%s",
amount, bizdate);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0030] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
memset(h_merch_id, 0, sizeof(h_merch_id));
strncpy(h_merch_id, merch, sizeof(h_merch_id) - 1);
memset(h_card_no, 0, sizeof(h_card_no));
strncpy(h_card_no, cardno, sizeof(h_card_no) - 1);
memset(h_biz_date, 0, sizeof(h_biz_date));
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
h_amount = amount;
strncpy(h_status_fail, AC_ST_FAIL, sizeof(h_status_fail) - 1);
h_status_fail[sizeof(h_status_fail) - 1] = '\0';
/* ---- 2. 중복 집합 크기 사전 확인 ---- */
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select count ( * ) from ac_ledger where merch_id = $1 and card_no = $2 and amount = $3 and biz_date = $4 ",
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_card_no),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_dupcnt),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 76 "app/online/ac_ol_0030.pgc"
if (sqlca.sqlcode != TX_SQL_OK && sqlca.sqlcode != TX_SQL_NOTFOUND) {
TX_DBIO_LOG_ERR("SELECT ac_ledger 중복집합 확인");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_dupcnt <= 1) {
tx_log(TX_LOG_INFO, "[AC_OL_0030] 중복건 없음 merch=%s card=%s", merch, cardno);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "MERCHID", merch);
tx_buf_setlong(ctx->out, "VOIDED", 0);
tx_return(ctx, TX_OK, ctx->out);
return;
}
/* ---- 3. 트랜잭션: 최초 건(최소 key) 제외 나머지 무효화 ---- */
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0030] 트랜잭션 시작 실패");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update ac_ledger set status = $1 , upd_ts = now ( ) where merch_id = $2 and card_no = $3 and amount = $4 and biz_date = $5 and key <> ( select MIN ( key ) from ac_ledger where merch_id = $6 and card_no = $7 and amount = $8 and biz_date = $9 )",
ECPGt_char,(h_status_fail),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_card_no),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch_id),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_card_no),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_biz_date),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 118 "app/online/ac_ol_0030.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger 중복무효");
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
voided = sqlca.sqlerrd[2];
if (tx_commit() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0030] 커밋 실패");
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
/* ---- 4. 응답 구성 ---- */
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0030] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "MERCHID", merch);
tx_buf_setlong(ctx->out, "VOIDED", voided);
tx_log(TX_LOG_INFO,
"[AC_OL_0030] 중복해제완료 merch=%s card=%s 무효건수=%ld",
merch, cardno, voided);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,15 @@
/*
* ac_ol_0030.pgc - 매입 온라인 서비스 (AC_OL_0030) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 매입 중복해제: 동일 가맹점/카드번호/금액/영업일 조합으로 중복 접수된
* ac_ledger 건 중 최초 건(최소 key)만 유효로 남기고 나머지는 중복
* 무효(status='U') 처리한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,32 +18,132 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0030, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* ---- ECPG 호스트 변수 선언부 ---- */
EXEC SQL BEGIN DECLARE SECTION;
char h_merch_id[16];
char h_card_no[20];
long h_amount;
char h_biz_date[9];
char h_status_fail[2];
long h_dupcnt;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0030] 매입 단건조회 서비스 진입");
char merch[16], cardno[20], bizdate[9];
long amount = 0;
long voided = 0;
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0030] KEY 누락");
tx_log(TX_LOG_INFO, "[AC_OL_0030] 매입 중복해제 서비스 진입");
/* ---- 1. 입력 검증 ---- */
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "CARDNO", cardno, sizeof(cardno)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0030] 필수 필드 누락");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
if (!amount_is_valid(amount) || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0030] 입력 검증 실패 amount=%ld date=%s",
amount, bizdate);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0030] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
memset(h_merch_id, 0, sizeof(h_merch_id));
strncpy(h_merch_id, merch, sizeof(h_merch_id) - 1);
memset(h_card_no, 0, sizeof(h_card_no));
strncpy(h_card_no, cardno, sizeof(h_card_no) - 1);
memset(h_biz_date, 0, sizeof(h_biz_date));
strncpy(h_biz_date, bizdate, sizeof(h_biz_date) - 1);
h_amount = amount;
strncpy(h_status_fail, AC_ST_FAIL, sizeof(h_status_fail) - 1);
h_status_fail[sizeof(h_status_fail) - 1] = '\0';
/* ---- 2. 중복 집합 크기 사전 확인 ---- */
EXEC SQL
SELECT COUNT(*)
INTO :h_dupcnt
FROM ac_ledger
WHERE merch_id = :h_merch_id
AND card_no = :h_card_no
AND amount = :h_amount
AND biz_date = :h_biz_date;
if (sqlca.sqlcode != TX_SQL_OK && sqlca.sqlcode != TX_SQL_NOTFOUND) {
TX_DBIO_LOG_ERR("SELECT ac_ledger 중복집합 확인");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (h_dupcnt <= 1) {
tx_log(TX_LOG_INFO, "[AC_OL_0030] 중복건 없음 merch=%s card=%s", merch, cardno);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "MERCHID", merch);
tx_buf_setlong(ctx->out, "VOIDED", 0);
tx_return(ctx, TX_OK, ctx->out);
return;
}
/* ---- 3. 트랜잭션: 최초 건(최소 key) 제외 나머지 무효화 ---- */
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0030] 트랜잭션 시작 실패");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
EXEC SQL
UPDATE ac_ledger
SET status = :h_status_fail, upd_ts = now()
WHERE merch_id = :h_merch_id
AND card_no = :h_card_no
AND amount = :h_amount
AND biz_date = :h_biz_date
AND key <> (
SELECT MIN(key)
FROM ac_ledger
WHERE merch_id = :h_merch_id
AND card_no = :h_card_no
AND amount = :h_amount
AND biz_date = :h_biz_date
);
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger 중복무효");
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
voided = sqlca.sqlerrd[2];
if (tx_commit() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0030] 커밋 실패");
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
/* ---- 4. 응답 구성 ---- */
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0030] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "MERCHID", merch);
tx_buf_setlong(ctx->out, "VOIDED", voided);
tx_log(TX_LOG_INFO,
"[AC_OL_0030] 중복해제완료 merch=%s card=%s 무효건수=%ld",
merch, cardno, voided);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,14 @@
/*
* ac_ol_0031.pgc - (AC_OL_0031) [tier=medium]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : (hold_yn) .
* (status='S') / .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,60 +90,136 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0031.pgc"
#line 16 "app/online/ac_ol_0031.pgc"
TX_SERVICE(AC_OL_0031, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
/* ---- ECPG 호스트 변수 선언부 ---- */
/* exec sql begin declare section */
#line 22 "app/online/ac_ol_0031.pgc"
char h_key [ 16 ] ;
#line 23 "app/online/ac_ol_0031.pgc"
char h_status [ 2 ] ;
#line 24 "app/online/ac_ol_0031.pgc"
char h_status_settled [ 2 ] ;
#line 25 "app/online/ac_ol_0031.pgc"
char h_hold [ 2 ] ;
/* exec sql end declare section */
#line 26 "app/online/ac_ol_0031.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0031] 매입 등록 서비스 진입");
char key[16], hold[2];
tx_log(TX_LOG_INFO, "[AC_OL_0031] 매입 보류처리 서비스 진입");
/* ---- 1. 입력 검증 ---- */
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_buf_get(ctx->in, "HOLD", hold, sizeof(hold)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0031] 필수 필드 누락");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0031] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0031] 영업일 오류 date=%s", bizdate);
if (hold[0] != 'Y' && hold[0] != 'N') {
tx_log(TX_LOG_WARN, "[AC_OL_0031] HOLD 값 오류 hold=%s", hold);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
memset(h_key, 0, sizeof(h_key));
strncpy(h_key, key, sizeof(h_key) - 1);
strncpy(h_status_settled, AC_ST_SETTLED, sizeof(h_status_settled) - 1);
h_status_settled[sizeof(h_status_settled) - 1] = '\0';
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0031] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
/* ---- 2. 현재 상태 조회 ---- */
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select status from ac_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 59 "app/online/ac_ol_0031.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0031] 대상건 없음 key=%s", key);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_ledger status");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
cnt = ac_rec_count(bizdate, AC_ST_RECV);
/* ---- 3. 업무규칙: 정산완료 건은 보류처리 불가 ---- */
if (strncmp(h_status, h_status_settled, 1) == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0031] 정산완료 보류불가 key=%s", key);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
memset(h_hold, 0, sizeof(h_hold));
strncpy(h_hold, hold, sizeof(h_hold) - 1);
/* ---- 4. 보류상태 갱신 ---- */
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0031] 트랜잭션 시작 실패");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update ac_ledger set hold_yn = $1 , upd_ts = now ( ) where key = $2 ",
ECPGt_char,(h_hold),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 100 "app/online/ac_ol_0031.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger hold_yn");
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (tx_commit() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0031] 커밋 실패");
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
/* ---- 5. 응답 구성 ---- */
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0031] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_sets(ctx->out, "HOLD", hold);
tx_log(TX_LOG_INFO, "[AC_OL_0031] 보류처리완료 key=%s hold=%s", key, hold);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,14 @@
/*
* ac_ol_0031.pgc - 매입 온라인 서비스 (AC_OL_0031) [tier=medium]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 매입 보류처리: 매입 원장 단건에 대해 보류 여부(hold_yn)를 설정한다.
* 이미 정산완료(status='S') 된 건은 보류 설정/해제를 허용하지 않는다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,55 +17,112 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0031, ctx)
{
ac_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
/* ---- ECPG 호스트 변수 선언부 ---- */
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
char h_status[2];
char h_status_settled[2];
char h_hold[2];
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0031] 매입 등록 서비스 진입");
char key[16], hold[2];
tx_log(TX_LOG_INFO, "[AC_OL_0031] 매입 보류처리 서비스 진입");
/* ---- 1. 입력 검증 ---- */
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_buf_get(ctx->in, "HOLD", hold, sizeof(hold)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0031] 필수 필드 누락");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AC_OL_0031] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AC_OL_0031] 영업일 오류 date=%s", bizdate);
if (hold[0] != 'Y' && hold[0] != 'N') {
tx_log(TX_LOG_WARN, "[AC_OL_0031] HOLD 값 오류 hold=%s", hold);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AC_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
memset(h_key, 0, sizeof(h_key));
strncpy(h_key, key, sizeof(h_key) - 1);
strncpy(h_status_settled, AC_ST_SETTLED, sizeof(h_status_settled) - 1);
h_status_settled[sizeof(h_status_settled) - 1] = '\0';
rc = ac_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0031] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
/* ---- 2. 현재 상태 조회 ---- */
EXEC SQL
SELECT status
INTO :h_status
FROM ac_ledger
WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0031] 대상건 없음 key=%s", key);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT ac_ledger status");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
cnt = ac_rec_count(bizdate, AC_ST_RECV);
/* ---- 3. 업무규칙: 정산완료 건은 보류처리 불가 ---- */
if (strncmp(h_status, h_status_settled, 1) == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0031] 정산완료 보류불가 key=%s", key);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
memset(h_hold, 0, sizeof(h_hold));
strncpy(h_hold, hold, sizeof(h_hold) - 1);
/* ---- 4. 보류상태 갱신 ---- */
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0031] 트랜잭션 시작 실패");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
EXEC SQL
UPDATE ac_ledger
SET hold_yn = :h_hold, upd_ts = now()
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger hold_yn");
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (tx_commit() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0031] 커밋 실패");
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
/* ---- 5. 응답 구성 ---- */
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AC_OL_0031] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_sets(ctx->out, "HOLD", hold);
tx_log(TX_LOG_INFO, "[AC_OL_0031] 보류처리완료 key=%s hold=%s", key, hold);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -10,13 +10,15 @@
/*
* ac_ol_0032.pgc - (AC_OL_0032) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF ac DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* : (NEWAPPROVALNO)
* . (approval.appr_status='A')
* ac_ledger.approval_no (status='M') .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -89,37 +91,143 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/ac_ol_0032.pgc"
#line 17 "app/online/ac_ol_0032.pgc"
TX_SERVICE(AC_OL_0032, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* ---- ECPG 호스트 변수 선언부 ---- */
/* exec sql begin declare section */
#line 23 "app/online/ac_ol_0032.pgc"
char h_key [ 16 ] ;
#line 24 "app/online/ac_ol_0032.pgc"
char h_new_appr [ 16 ] ;
#line 25 "app/online/ac_ol_0032.pgc"
char h_appr_status_ok [ 2 ] ;
#line 26 "app/online/ac_ol_0032.pgc"
long h_appr_amount ;
#line 27 "app/online/ac_ol_0032.pgc"
char h_status_done [ 2 ] ;
/* exec sql end declare section */
#line 28 "app/online/ac_ol_0032.pgc"
tx_log(TX_LOG_INFO, "[AC_OL_0032] 매입 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0032] KEY 누락");
char key[16], newappr[16];
long remapped = 0;
tx_log(TX_LOG_INFO, "[AC_OL_0032] 매입 재승인 매핑 서비스 진입");
/* ---- 1. 입력 검증 ---- */
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "NEWAPPROVALNO", newappr, sizeof(newappr)) != TX_OK ||
newappr[0] == '\0') {
tx_log(TX_LOG_ERROR, "[AC_OL_0032] 필수 필드 누락");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0032] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
memset(h_key, 0, sizeof(h_key));
strncpy(h_key, key, sizeof(h_key) - 1);
memset(h_new_appr, 0, sizeof(h_new_appr));
strncpy(h_new_appr, newappr, sizeof(h_new_appr) - 1);
strncpy(h_appr_status_ok, "A", sizeof(h_appr_status_ok));
strncpy(h_status_done, AC_ST_DONE, sizeof(h_status_done) - 1);
h_status_done[sizeof(h_status_done) - 1] = '\0';
/* ---- 2. 신규 승인번호 유효성 확인 (정상승인 건만 매핑 허용) ---- */
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount from approval where approval_no = $1 and appr_status = $2 ",
ECPGt_char,(h_new_appr),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_appr_status_ok),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_appr_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 60 "app/online/ac_ol_0032.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0032] 유효승인 아님 new_appr=%s", newappr);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT approval");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* ---- 3. 매입 원장에 재승인번호 매핑 ---- */
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0032] 트랜잭션 시작 실패");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update ac_ledger set approval_no = $1 , status = $2 , upd_ts = now ( ) where key = $3 ",
ECPGt_char,(h_new_appr),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status_done),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 89 "app/online/ac_ol_0032.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger approval_no");
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0032] 대상건 없음 key=%s", key);
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
remapped = 1;
if (tx_commit() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0032] 커밋 실패");
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
/* ---- 4. 응답 구성 ---- */
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0032] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_sets(ctx->out, "NEWAPPROVALNO", newappr);
tx_buf_setlong(ctx->out, "REMAPPED", remapped);
tx_buf_setlong(ctx->out, "AMOUNT", h_appr_amount);
tx_log(TX_LOG_INFO,
"[AC_OL_0032] 재승인매핑완료 key=%s new_appr=%s amount=%ld",
key, newappr, h_appr_amount);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -2,13 +2,15 @@
/*
* ac_ol_0032.pgc - 매입 온라인 서비스 (AC_OL_0032) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 ac 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* 매입 재승인 매핑: 기존 매입 원장 건에 새로운 승인번호(NEWAPPROVALNO)를
* 매핑한다. 신규 승인번호가 정상승인(approval.appr_status='A') 상태일
* 때만 ac_ledger.approval_no 를 갱신하고 완료(status='M') 로 전이한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "ac_core.h"
@ -16,32 +18,113 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AC_OL_0032, ctx)
{
ac_rec_t rec;
char key[16];
int rc;
/* ---- ECPG 호스트 변수 선언부 ---- */
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
char h_new_appr[16];
char h_appr_status_ok[2];
long h_appr_amount;
char h_status_done[2];
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AC_OL_0032] 매입 단건조회 서비스 진입");
char key[16], newappr[16];
long remapped = 0;
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0032] KEY 누락");
tx_log(TX_LOG_INFO, "[AC_OL_0032] 매입 재승인 매핑 서비스 진입");
/* ---- 1. 입력 검증 ---- */
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "NEWAPPROVALNO", newappr, sizeof(newappr)) != TX_OK ||
newappr[0] == '\0') {
tx_log(TX_LOG_ERROR, "[AC_OL_0032] 필수 필드 누락");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = ac_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AC_OL_0032] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
memset(h_key, 0, sizeof(h_key));
strncpy(h_key, key, sizeof(h_key) - 1);
memset(h_new_appr, 0, sizeof(h_new_appr));
strncpy(h_new_appr, newappr, sizeof(h_new_appr) - 1);
strncpy(h_appr_status_ok, "A", sizeof(h_appr_status_ok));
strncpy(h_status_done, AC_ST_DONE, sizeof(h_status_done) - 1);
h_status_done[sizeof(h_status_done) - 1] = '\0';
/* ---- 2. 신규 승인번호 유효성 확인 (정상승인 건만 매핑 허용) ---- */
EXEC SQL
SELECT amount
INTO :h_appr_amount
FROM approval
WHERE approval_no = :h_new_appr
AND appr_status = :h_appr_status_ok;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_log(TX_LOG_WARN, "[AC_OL_0032] 유효승인 아님 new_appr=%s", newappr);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("SELECT approval");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* ---- 3. 매입 원장에 재승인번호 매핑 ---- */
if (tx_begin() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0032] 트랜잭션 시작 실패");
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
EXEC SQL
UPDATE ac_ledger
SET approval_no = :h_new_appr, status = :h_status_done, upd_ts = now()
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("UPDATE ac_ledger approval_no");
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_log(TX_LOG_WARN, "[AC_OL_0032] 대상건 없음 key=%s", key);
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
remapped = 1;
if (tx_commit() != TX_OK) {
tx_log(TX_LOG_ERROR, "[AC_OL_0032] 커밋 실패");
tx_abort();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
/* ---- 4. 응답 구성 ---- */
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AC_OL_0032] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_sets(ctx->out, "NEWAPPROVALNO", newappr);
tx_buf_setlong(ctx->out, "REMAPPED", remapped);
tx_buf_setlong(ctx->out, "AMOUNT", h_appr_amount);
tx_log(TX_LOG_INFO,
"[AC_OL_0032] 재승인매핑완료 key=%s new_appr=%s amount=%ld",
key, newappr, h_appr_amount);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -8,15 +8,16 @@
#line 1 "app/online/au_ol_0002.pgc"
/* @tier medium @module au @transform authorization-online */
/*
* au_ol_0002.pgc - (AU_OL_0002) [tier=medium]
* au_ol_0002.pgc - (+INSERT) (AU_OL_0002) [tier=medium]
*
* TxCore TX_SERVICE . TXBUF au DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* TxCore TX_SERVICE . TXBUF SQL /
* DBIO / tx_call TXBUF .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -89,60 +90,98 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/au_ol_0002.pgc"
#line 16 "app/online/au_ol_0002.pgc"
TX_SERVICE(AU_OL_0002, ctx)
{
au_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
/* exec sql begin declare section */
#line 21 "app/online/au_ol_0002.pgc"
char h_key [ 16 ] , h_merch [ 16 ] , h_card [ 20 ] , h_bdate [ 9 ] , h_status [ 2 ] ;
#line 22 "app/online/au_ol_0002.pgc"
long h_amount , h_fee ;
#line 23 "app/online/au_ol_0002.pgc"
int h_dup ;
/* exec sql end declare section */
#line 24 "app/online/au_ol_0002.pgc"
tx_log(TX_LOG_INFO, "[AU_OL_0002] 승인한도 등록 서비스 진입");
char key[16], merch[16], card[20], bdate[16];
long amount = 0;
tx_log(TX_LOG_INFO, "[AU_OL_0002] 승인 접수등록 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0002] 필수 필드 누락");
tx_buf_get(ctx->in, "BIZDATE", bdate, sizeof(bdate)) != TX_OK) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (tx_buf_get(ctx->in, "CARDNO", card, sizeof(card)) != TX_OK)
strcpy(card, "0000");
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AU_OL_0002] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0002] 영업일 오류 date=%s", bizdate);
if (!amount_is_valid(amount) || !date_is_valid(bdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0002] 금액/영업일 오류");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AU_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_key, key, 15); h_key[15] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select count ( * ) from au_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_int,&(h_dup),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 46 "app/online/au_ol_0002.pgc"
rc = au_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0002] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
if (sqlca.sqlcode == TX_SQL_OK && h_dup > 0) {
tx_log(TX_LOG_WARN, "[AU_OL_0002] 중복 승인키 key=%s", key);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
cnt = au_rec_count(bizdate, AU_ST_RECV);
strncpy(h_merch, merch, 15); h_merch[15] = '\0';
strncpy(h_card, card, 19); h_card[19] = '\0';
strncpy(h_bdate, bdate, 8); h_bdate[8] = '\0';
strncpy(h_status, AU_ST_RECV, 1); h_status[1] = '\0';
h_amount = amount;
h_fee = amount / 100;
if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[AU_OL_0002] tx_begin 경고");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into au_ledger ( key , merch_id , card_no , amount , biz_date , status , fee ) values ( $1 , $2 , $3 , $4 , $5 , $6 , $7 )",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_card),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_bdate),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_fee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 62 "app/online/au_ol_0002.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0002 INSERT");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AU_OL_0002] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_setlong(ctx->out, "FEE", h_fee);
tx_log(TX_LOG_INFO, "[AU_OL_0002] 접수완료 key=%s fee=%ld", key, h_fee);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier medium @module au @transform authorization-online */
/*
* au_ol_0002.pgc - 승인한도 온라인 서비스 (AU_OL_0002) [tier=medium]
* au_ol_0002.pgc - 승인 접수등록(중복검사+INSERT) (AU_OL_0002) [tier=medium]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 au 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 임베디드 SQL / 표준
* DBIO / tx_call 로 처리한 뒤 응답 TXBUF 를 구성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -16,55 +17,61 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AU_OL_0002, ctx)
{
au_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16], h_merch[16], h_card[20], h_bdate[9], h_status[2];
long h_amount, h_fee;
int h_dup;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AU_OL_0002] 승인한도 등록 서비스 진입");
char key[16], merch[16], card[20], bdate[16];
long amount = 0;
tx_log(TX_LOG_INFO, "[AU_OL_0002] 승인 접수등록 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0002] 필수 필드 누락");
tx_buf_get(ctx->in, "BIZDATE", bdate, sizeof(bdate)) != TX_OK) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (tx_buf_get(ctx->in, "CARDNO", card, sizeof(card)) != TX_OK)
strcpy(card, "0000");
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AU_OL_0002] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0002] 영업일 오류 date=%s", bizdate);
if (!amount_is_valid(amount) || !date_is_valid(bdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0002] 금액/영업일 오류");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AU_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
rc = au_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0002] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
strncpy(h_key, key, 15); h_key[15] = '\0';
EXEC SQL SELECT count(*) INTO :h_dup FROM au_ledger WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_OK && h_dup > 0) {
tx_log(TX_LOG_WARN, "[AU_OL_0002] 중복 승인키 key=%s", key);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
cnt = au_rec_count(bizdate, AU_ST_RECV);
strncpy(h_merch, merch, 15); h_merch[15] = '\0';
strncpy(h_card, card, 19); h_card[19] = '\0';
strncpy(h_bdate, bdate, 8); h_bdate[8] = '\0';
strncpy(h_status, AU_ST_RECV, 1); h_status[1] = '\0';
h_amount = amount;
h_fee = amount / 100;
if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[AU_OL_0002] tx_begin 경고");
EXEC SQL INSERT INTO au_ledger (key, merch_id, card_no, amount, biz_date, status, fee)
VALUES (:h_key, :h_merch, :h_card, :h_amount, :h_bdate, :h_status, :h_fee);
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0002 INSERT");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AU_OL_0002] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_setlong(ctx->out, "FEE", h_fee);
tx_log(TX_LOG_INFO, "[AU_OL_0002] 접수완료 key=%s fee=%ld", key, h_fee);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -6,17 +6,18 @@
/* End of automatic include section */
#line 1 "app/online/au_ol_0003.pgc"
/* @tier easy @module au @transform authorization-online */
/* @tier medium @module au @transform authorization-online */
/*
* au_ol_0003.pgc - (AU_OL_0003) [tier=easy]
* au_ol_0003.pgc - ( ) (AU_OL_0003) [tier=medium]
*
* TxCore TX_SERVICE . TXBUF au DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* TxCore TX_SERVICE . TXBUF SQL /
* DBIO / tx_call TXBUF .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -89,37 +90,67 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/au_ol_0003.pgc"
#line 16 "app/online/au_ol_0003.pgc"
TX_SERVICE(AU_OL_0003, ctx)
{
au_rec_t rec;
char key[16];
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0003] 승인한도 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0003] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* exec sql begin declare section */
#line 27 "app/online/au_ol_0003.pgc"
char h_merch [ 16 ] , h_bdate [ 9 ] ;
#line 28 "app/online/au_ol_0003.pgc"
long h_used ;
/* exec sql end declare section */
#line 29 "app/online/au_ol_0003.pgc"
memset(&rec, 0, sizeof(rec));
rc = au_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AU_OL_0003] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
char merch[16], bdate[16];
long limit_amt = 50000000L, remain;
tx_log(TX_LOG_INFO, "[AU_OL_0003] 가맹점 한도조회 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (tx_buf_get(ctx->in, "BIZDATE", bdate, sizeof(bdate)) != TX_OK)
date_today(bdate);
strncpy(h_merch, merch, 15); h_merch[15] = '\0';
strncpy(h_bdate, bdate, 8); h_bdate[8] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select coalesce ( sum ( amount ) , 0 ) from au_ledger where merch_id = $1 and biz_date = $2 and status in ( 'R' , 'M' , 'S' )",
ECPGt_char,(h_merch),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_bdate),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_used),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 48 "app/online/au_ol_0003.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0003 한도조회");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
remain = limit_amt - h_used;
if (remain < 0) remain = 0;
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AU_OL_0003] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "MERCHID", merch);
tx_buf_setlong(ctx->out, "LIMIT", limit_amt);
tx_buf_setlong(ctx->out, "USED", h_used);
tx_buf_setlong(ctx->out, "REMAIN", remain);
tx_log(TX_LOG_INFO, "[AU_OL_0003] 한도 used=%ld remain=%ld", h_used, remain);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier easy @module au @transform authorization-online */
/* @tier medium @module au @transform authorization-online */
/*
* au_ol_0003.pgc - 승인한도 온라인 서비스 (AU_OL_0003) [tier=easy]
* au_ol_0003.pgc - 가맹점 한도 조회(잔여한도 산출) (AU_OL_0003) [tier=medium]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 au 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 임베디드 SQL / 표준
* DBIO / tx_call 로 처리한 뒤 응답 TXBUF 를 구성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -16,32 +17,49 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AU_OL_0003, ctx)
{
au_rec_t rec;
char key[16];
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0003] 승인한도 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0003] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
EXEC SQL BEGIN DECLARE SECTION;
char h_merch[16], h_bdate[9];
long h_used;
EXEC SQL END DECLARE SECTION;
memset(&rec, 0, sizeof(rec));
rc = au_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AU_OL_0003] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
char merch[16], bdate[16];
long limit_amt = 50000000L, remain;
tx_log(TX_LOG_INFO, "[AU_OL_0003] 가맹점 한도조회 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (tx_buf_get(ctx->in, "BIZDATE", bdate, sizeof(bdate)) != TX_OK)
date_today(bdate);
strncpy(h_merch, merch, 15); h_merch[15] = '\0';
strncpy(h_bdate, bdate, 8); h_bdate[8] = '\0';
EXEC SQL SELECT coalesce(sum(amount), 0) INTO :h_used
FROM au_ledger
WHERE merch_id = :h_merch AND biz_date = :h_bdate
AND status IN ('R', 'M', 'S');
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0003 한도조회");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
remain = limit_amt - h_used;
if (remain < 0) remain = 0;
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AU_OL_0003] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "MERCHID", merch);
tx_buf_setlong(ctx->out, "LIMIT", limit_amt);
tx_buf_setlong(ctx->out, "USED", h_used);
tx_buf_setlong(ctx->out, "REMAIN", remain);
tx_log(TX_LOG_INFO, "[AU_OL_0003] 한도 used=%ld remain=%ld", h_used, remain);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -8,15 +8,16 @@
#line 1 "app/online/au_ol_0004.pgc"
/* @tier medium @module au @transform authorization-online */
/*
* au_ol_0004.pgc - (AU_OL_0004) [tier=medium]
* au_ol_0004.pgc - (UPDATE ) (AU_OL_0004) [tier=medium]
*
* TxCore TX_SERVICE . TXBUF au DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* TxCore TX_SERVICE . TXBUF SQL /
* DBIO / tx_call TXBUF .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -89,60 +90,89 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/au_ol_0004.pgc"
#line 16 "app/online/au_ol_0004.pgc"
TX_SERVICE(AU_OL_0004, ctx)
{
au_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0004] 승인한도 등록 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0004] 필수 필드 누락");
char key[16];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0004] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* exec sql begin declare section */
#line 27 "app/online/au_ol_0004.pgc"
char h_key [ 16 ] , h_status [ 2 ] ;
#line 28 "app/online/au_ol_0004.pgc"
long h_amount , h_bal ;
/* exec sql end declare section */
#line 29 "app/online/au_ol_0004.pgc"
long amount = 0;
tx_log(TX_LOG_INFO, "[AU_OL_0004] 승인 한도차감 진입");
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AU_OL_0004] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0004] 영업일 오류 date=%s", bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AU_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_key, key, 15); h_key[15] = '\0';
h_amount = amount;
rc = au_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0004] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount , status from au_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_bal),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 44 "app/online/au_ol_0004.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (h_bal < h_amount) {
tx_log(TX_LOG_WARN, "[AU_OL_0004] 한도부족 bal=%ld req=%ld", h_bal, h_amount);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
cnt = au_rec_count(bizdate, AU_ST_RECV);
if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[AU_OL_0004] tx_begin 경고");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update au_ledger set amount = amount - $1 , upd_ts = now ( ) where key = $2 and status = 'R'",
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 60 "app/online/au_ol_0004.pgc"
if (sqlca.sqlcode != TX_SQL_OK || sqlca.sqlerrd[2] == 0) {
TX_DBIO_LOG_ERR("au_ol_0004 차감");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount from au_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_bal),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 67 "app/online/au_ol_0004.pgc"
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AU_OL_0004] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_setlong(ctx->out, "REMAIN", h_bal);
tx_log(TX_LOG_INFO, "[AU_OL_0004] 차감완료 잔액=%ld", h_bal);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier medium @module au @transform authorization-online */
/*
* au_ol_0004.pgc - 승인한도 온라인 서비스 (AU_OL_0004) [tier=medium]
* au_ol_0004.pgc - 승인 한도차감(UPDATE 잔액 감액) (AU_OL_0004) [tier=medium]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 au 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 임베디드 SQL / 표준
* DBIO / tx_call 로 처리한 뒤 응답 TXBUF 를 구성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -16,55 +17,59 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AU_OL_0004, ctx)
{
au_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0004] 승인한도 등록 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0004] 필수 필드 누락");
char key[16];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0004] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16], h_status[2];
long h_amount, h_bal;
EXEC SQL END DECLARE SECTION;
long amount = 0;
tx_log(TX_LOG_INFO, "[AU_OL_0004] 승인 한도차감 진입");
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AU_OL_0004] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0004] 영업일 오류 date=%s", bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AU_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_key, key, 15); h_key[15] = '\0';
h_amount = amount;
rc = au_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0004] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
EXEC SQL SELECT amount, status INTO :h_bal, :h_status
FROM au_ledger WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (h_bal < h_amount) {
tx_log(TX_LOG_WARN, "[AU_OL_0004] 한도부족 bal=%ld req=%ld", h_bal, h_amount);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
cnt = au_rec_count(bizdate, AU_ST_RECV);
if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[AU_OL_0004] tx_begin 경고");
EXEC SQL UPDATE au_ledger
SET amount = amount - :h_amount, upd_ts = now()
WHERE key = :h_key AND status = 'R';
if (sqlca.sqlcode != TX_SQL_OK || sqlca.sqlerrd[2] == 0) {
TX_DBIO_LOG_ERR("au_ol_0004 차감");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
EXEC SQL SELECT amount INTO :h_bal FROM au_ledger WHERE key = :h_key;
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AU_OL_0004] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_setlong(ctx->out, "REMAIN", h_bal);
tx_log(TX_LOG_INFO, "[AU_OL_0004] 차감완료 잔액=%ld", h_bal);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -6,17 +6,18 @@
/* End of automatic include section */
#line 1 "app/online/au_ol_0005.pgc"
/* @tier easy @module au @transform authorization-online */
/* @tier medium @module au @transform authorization-online */
/*
* au_ol_0005.pgc - (AU_OL_0005) [tier=easy]
* au_ol_0005.pgc - ( ) (AU_OL_0005) [tier=medium]
*
* TxCore TX_SERVICE . TXBUF au DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* TxCore TX_SERVICE . TXBUF SQL /
* DBIO / tx_call TXBUF .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -89,37 +90,73 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/au_ol_0005.pgc"
#line 16 "app/online/au_ol_0005.pgc"
TX_SERVICE(AU_OL_0005, ctx)
{
au_rec_t rec;
char key[16];
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0005] 승인한도 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0005] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* exec sql begin declare section */
#line 27 "app/online/au_ol_0005.pgc"
char h_key [ 16 ] ;
#line 28 "app/online/au_ol_0005.pgc"
long h_amount , h_bal ;
/* exec sql end declare section */
#line 29 "app/online/au_ol_0005.pgc"
memset(&rec, 0, sizeof(rec));
rc = au_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AU_OL_0005] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
long amount = 0;
tx_log(TX_LOG_INFO, "[AU_OL_0005] 승인 한도복원 진입");
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
if (amount <= 0) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
strncpy(h_key, key, 15); h_key[15] = '\0';
h_amount = amount;
if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[AU_OL_0005] tx_begin 경고");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update au_ledger set amount = amount + $1 , status = 'R' , upd_ts = now ( ) where key = $2 and status in ( 'U' , 'M' )",
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 45 "app/online/au_ol_0005.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0005 복원");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_abort();
tx_log(TX_LOG_WARN, "[AU_OL_0005] 복원 대상없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount from au_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_bal),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 58 "app/online/au_ol_0005.pgc"
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AU_OL_0005] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "REMAIN", h_bal);
tx_log(TX_LOG_INFO, "[AU_OL_0005] 복원완료 key=%s 잔액=%ld", key, h_bal);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier easy @module au @transform authorization-online */
/* @tier medium @module au @transform authorization-online */
/*
* au_ol_0005.pgc - 승인한도 온라인 서비스 (AU_OL_0005) [tier=easy]
* au_ol_0005.pgc - 승인 한도복원(취소분 가산) (AU_OL_0005) [tier=medium]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 au 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 임베디드 SQL / 표준
* DBIO / tx_call 로 처리한 뒤 응답 TXBUF 를 구성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -16,32 +17,50 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AU_OL_0005, ctx)
{
au_rec_t rec;
char key[16];
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0005] 승인한도 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0005] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
long h_amount, h_bal;
EXEC SQL END DECLARE SECTION;
memset(&rec, 0, sizeof(rec));
rc = au_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AU_OL_0005] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
long amount = 0;
tx_log(TX_LOG_INFO, "[AU_OL_0005] 승인 한도복원 진입");
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
if (amount <= 0) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
strncpy(h_key, key, 15); h_key[15] = '\0';
h_amount = amount;
if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[AU_OL_0005] tx_begin 경고");
EXEC SQL UPDATE au_ledger
SET amount = amount + :h_amount, status = 'R', upd_ts = now()
WHERE key = :h_key AND status IN ('U', 'M');
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0005 복원");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
if (sqlca.sqlerrd[2] == 0) {
tx_abort();
tx_log(TX_LOG_WARN, "[AU_OL_0005] 복원 대상없음 key=%s", key);
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
EXEC SQL SELECT amount INTO :h_bal FROM au_ledger WHERE key = :h_key;
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AU_OL_0005] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "REMAIN", h_bal);
tx_log(TX_LOG_INFO, "[AU_OL_0005] 복원완료 key=%s 잔액=%ld", key, h_bal);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -6,17 +6,18 @@
/* End of automatic include section */
#line 1 "app/online/au_ol_0006.pgc"
/* @tier medium @module au @transform authorization-online */
/* @tier easy @module au @transform authorization-online */
/*
* au_ol_0006.pgc - (AU_OL_0006) [tier=medium]
* au_ol_0006.pgc - ( ) (AU_OL_0006) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF au DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* TxCore TX_SERVICE . TXBUF SQL /
* DBIO / tx_call TXBUF .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -89,60 +90,70 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/au_ol_0006.pgc"
#line 16 "app/online/au_ol_0006.pgc"
TX_SERVICE(AU_OL_0006, ctx)
{
au_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0006] 승인한도 등록 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0006] 필수 필드 누락");
char key[16];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0006] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
/* exec sql begin declare section */
#line 27 "app/online/au_ol_0006.pgc"
char h_key [ 16 ] , h_status [ 2 ] ;
#line 28 "app/online/au_ol_0006.pgc"
long h_amount ;
/* exec sql end declare section */
#line 29 "app/online/au_ol_0006.pgc"
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AU_OL_0006] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
tx_log(TX_LOG_INFO, "[AU_OL_0006] 승인 전체취소 진입");
strncpy(h_key, key, 15); h_key[15] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount , status from au_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 35 "app/online/au_ol_0006.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0006] 영업일 오류 date=%s", bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
if (h_status[0] == 'S') {
tx_log(TX_LOG_WARN, "[AU_OL_0006] 정산완료건 취소불가 key=%s", key);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AU_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[AU_OL_0006] tx_begin 경고");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update au_ledger set status = 'U' , upd_ts = now ( ) where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 49 "app/online/au_ol_0006.pgc"
rc = au_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0006] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0006 취소");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
cnt = au_rec_count(bizdate, AU_ST_RECV);
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AU_OL_0006] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_setlong(ctx->out, "CANCELAMT", h_amount);
tx_log(TX_LOG_INFO, "[AU_OL_0006] 취소완료 key=%s 금액=%ld", key, h_amount);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier medium @module au @transform authorization-online */
/* @tier easy @module au @transform authorization-online */
/*
* au_ol_0006.pgc - 승인한도 온라인 서비스 (AU_OL_0006) [tier=medium]
* au_ol_0006.pgc - 승인 취소(전체취소 상태전이) (AU_OL_0006) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 au 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 임베디드 SQL / 표준
* DBIO / tx_call 로 처리한 뒤 응답 TXBUF 를 구성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -16,55 +17,48 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AU_OL_0006, ctx)
{
au_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0006] 승인한도 등록 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0006] 필수 필드 누락");
char key[16];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0006] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16], h_status[2];
long h_amount;
EXEC SQL END DECLARE SECTION;
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AU_OL_0006] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
tx_log(TX_LOG_INFO, "[AU_OL_0006] 승인 전체취소 진입");
strncpy(h_key, key, 15); h_key[15] = '\0';
EXEC SQL SELECT amount, status INTO :h_amount, :h_status
FROM au_ledger WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0006] 영업일 오류 date=%s", bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
if (h_status[0] == 'S') {
tx_log(TX_LOG_WARN, "[AU_OL_0006] 정산완료건 취소불가 key=%s", key);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AU_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
rc = au_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0006] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[AU_OL_0006] tx_begin 경고");
EXEC SQL UPDATE au_ledger
SET status = 'U', upd_ts = now()
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0006 취소");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
cnt = au_rec_count(bizdate, AU_ST_RECV);
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AU_OL_0006] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_setlong(ctx->out, "CANCELAMT", h_amount);
tx_log(TX_LOG_INFO, "[AU_OL_0006] 취소완료 key=%s 금액=%ld", key, h_amount);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -6,17 +6,18 @@
/* End of automatic include section */
#line 1 "app/online/au_ol_0007.pgc"
/* @tier easy @module au @transform authorization-online */
/* @tier medium @module au @transform authorization-online */
/*
* au_ol_0007.pgc - (AU_OL_0007) [tier=easy]
* au_ol_0007.pgc - ( ) (AU_OL_0007) [tier=medium]
*
* TxCore TX_SERVICE . TXBUF au DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* TxCore TX_SERVICE . TXBUF SQL /
* DBIO / tx_call TXBUF .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -89,37 +90,86 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/au_ol_0007.pgc"
#line 16 "app/online/au_ol_0007.pgc"
TX_SERVICE(AU_OL_0007, ctx)
{
au_rec_t rec;
char key[16];
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0007] 승인한도 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0007] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* exec sql begin declare section */
#line 27 "app/online/au_ol_0007.pgc"
char h_key [ 16 ] ;
#line 28 "app/online/au_ol_0007.pgc"
long h_part , h_orig , h_new ;
/* exec sql end declare section */
#line 29 "app/online/au_ol_0007.pgc"
memset(&rec, 0, sizeof(rec));
rc = au_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AU_OL_0007] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
long part = 0;
tx_log(TX_LOG_INFO, "[AU_OL_0007] 승인 부분취소 진입");
tx_buf_getlong(ctx->in, "CANCELAMT", &part);
if (part <= 0) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
strncpy(h_key, key, 15); h_key[15] = '\0';
h_part = part;
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount from au_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_orig),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 42 "app/online/au_ol_0007.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (h_part > h_orig) {
tx_log(TX_LOG_WARN, "[AU_OL_0007] 취소금액 초과 orig=%ld req=%ld", h_orig, h_part);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[AU_OL_0007] tx_begin 경고");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update au_ledger set amount = amount - $1 , fee = ( amount - $2 ) / 100 , upd_ts = now ( ) where key = $3 ",
ECPGt_long,&(h_part),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_part),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 56 "app/online/au_ol_0007.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0007 부분취소");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount from au_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_new),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 63 "app/online/au_ol_0007.pgc"
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AU_OL_0007] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_setlong(ctx->out, "REMAINAMT", h_new);
tx_log(TX_LOG_INFO, "[AU_OL_0007] 부분취소 완료 잔액=%ld", h_new);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier easy @module au @transform authorization-online */
/* @tier medium @module au @transform authorization-online */
/*
* au_ol_0007.pgc - 승인한도 온라인 서비스 (AU_OL_0007) [tier=easy]
* au_ol_0007.pgc - 승인 부분취소(부분금액 차감) (AU_OL_0007) [tier=medium]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 au 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 임베디드 SQL / 표준
* DBIO / tx_call 로 처리한 뒤 응답 TXBUF 를 구성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -16,32 +17,55 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AU_OL_0007, ctx)
{
au_rec_t rec;
char key[16];
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0007] 승인한도 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0007] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
long h_part, h_orig, h_new;
EXEC SQL END DECLARE SECTION;
memset(&rec, 0, sizeof(rec));
rc = au_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AU_OL_0007] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
long part = 0;
tx_log(TX_LOG_INFO, "[AU_OL_0007] 승인 부분취소 진입");
tx_buf_getlong(ctx->in, "CANCELAMT", &part);
if (part <= 0) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
strncpy(h_key, key, 15); h_key[15] = '\0';
h_part = part;
EXEC SQL SELECT amount INTO :h_orig FROM au_ledger WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (h_part > h_orig) {
tx_log(TX_LOG_WARN, "[AU_OL_0007] 취소금액 초과 orig=%ld req=%ld", h_orig, h_part);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[AU_OL_0007] tx_begin 경고");
EXEC SQL UPDATE au_ledger
SET amount = amount - :h_part, fee = (amount - :h_part) / 100, upd_ts = now()
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0007 부분취소");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
EXEC SQL SELECT amount INTO :h_new FROM au_ledger WHERE key = :h_key;
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AU_OL_0007] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_setlong(ctx->out, "REMAINAMT", h_new);
tx_log(TX_LOG_INFO, "[AU_OL_0007] 부분취소 완료 잔액=%ld", h_new);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -8,15 +8,16 @@
#line 1 "app/online/au_ol_0008.pgc"
/* @tier hard @module au @transform authorization-online */
/*
* au_ol_0008.pgc - (AU_OL_0008) [tier=hard]
* au_ol_0008.pgc - (tx_call) (AU_OL_0008) [tier=hard]
*
* TxCore TX_SERVICE . TXBUF au DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* TxCore TX_SERVICE . TXBUF SQL /
* DBIO / tx_call TXBUF .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -89,88 +90,53 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/au_ol_0008.pgc"
#line 16 "app/online/au_ol_0008.pgc"
TX_SERVICE(AU_OL_0008, ctx)
{
au_rec_t rec;
char key[16], merch[16], bizdate[16], nextbiz[9];
long amount = 0, daysum = 0;
char key[16];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0008] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
TXBUF *req;
char merch[16], card[20], resp[8];
long amount = 0;
int rc;
TXBUF *sub_in;
TXBUF *sub_out;
tx_log(TX_LOG_INFO, "[AU_OL_0008] 승인한도 트랜잭션 오케스트레이션 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0008] 필수 필드 누락");
tx_log(TX_LOG_INFO, "[AU_OL_0008] 승인요청 중계 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "CARDNO", card, sizeof(card)) != TX_OK) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
if (!amount_is_valid(amount) || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0008] 입력 검증 실패 amount=%ld date=%s",
amount, bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
req = tx_buf_alloc();
if (!req) {
tx_return(ctx, TX_ENOMEM, ctx->out);
return;
}
tx_buf_sets(req, "KEY", key);
tx_buf_sets(req, "MERCHID", merch);
tx_buf_sets(req, "CARDNO", card);
tx_buf_setlong(req, "AMOUNT", amount);
tx_buf_sets(req, "MTI", MSG_TYPE_RECV);
/* 트랜잭션 시작 → 원장 반영 → 후속 서비스 연계 → 커밋 */
if (tx_begin() != TX_OK) {
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AU_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100;
rc = au_rec_insert(&rec);
rc = tx_call("AU_ISSUER", req, ctx->out);
tx_buf_free(req);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0008] 원장반영 실패 rc=%d", rc);
tx_abort();
tx_log(TX_LOG_ERROR, "[AU_OL_0008] 매입사 중계 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, rc, ctx->out);
return;
}
/* 정산 영업일 = 거래일의 다음 영업일 */
if (date_next_business(bizdate, nextbiz) != 0) {
memcpy(nextbiz, bizdate, 8);
nextbiz[8] = '\0';
}
/* 후속 정산집계 서비스 연계 (레지스트리 문자열 디스패치) */
sub_in = tx_buf_alloc();
sub_out = tx_buf_alloc();
if (sub_in && sub_out) {
tx_buf_sets(sub_in, "MERCHID", merch);
tx_buf_sets(sub_in, "BIZDATE", nextbiz);
tx_buf_setlong(sub_in, "AMOUNT", amount);
rc = tx_call("AU_POST", sub_in, sub_out);
if (rc != TX_OK)
tx_log(TX_LOG_WARN, "[AU_OL_0008] 후속연계 경고 rc=%d", rc);
}
tx_buf_free(sub_in);
tx_buf_free(sub_out);
/* 교차 검증: 당일 합계 재계산 */
if (au_rec_sum(bizdate, &daysum) != TX_OK)
daysum = 0;
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYSUM", daysum);
tx_log(TX_LOG_INFO, "[AU_OL_0008] 완료 key=%s 당일합계=%ld", key, daysum);
if (tx_buf_get(ctx->out, "RESPCODE", resp, sizeof(resp)) != TX_OK)
strcpy(resp, RESP_OK);
tx_log(TX_LOG_INFO, "[AU_OL_0008] 중계 응답 key=%s resp=%s", key, resp);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier hard @module au @transform authorization-online */
/*
* au_ol_0008.pgc - 승인한도 온라인 서비스 (AU_OL_0008) [tier=hard]
* au_ol_0008.pgc - 승인요청 매입사 중계(tx_call) (AU_OL_0008) [tier=hard]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 au 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 임베디드 SQL / 표준
* DBIO / tx_call 로 처리한 뒤 응답 TXBUF 를 구성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -16,83 +17,48 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AU_OL_0008, ctx)
{
au_rec_t rec;
char key[16], merch[16], bizdate[16], nextbiz[9];
long amount = 0, daysum = 0;
char key[16];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0008] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
TXBUF *req;
char merch[16], card[20], resp[8];
long amount = 0;
int rc;
TXBUF *sub_in;
TXBUF *sub_out;
tx_log(TX_LOG_INFO, "[AU_OL_0008] 승인한도 트랜잭션 오케스트레이션 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0008] 필수 필드 누락");
tx_log(TX_LOG_INFO, "[AU_OL_0008] 승인요청 중계 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "CARDNO", card, sizeof(card)) != TX_OK) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
if (!amount_is_valid(amount) || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0008] 입력 검증 실패 amount=%ld date=%s",
amount, bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
req = tx_buf_alloc();
if (!req) {
tx_return(ctx, TX_ENOMEM, ctx->out);
return;
}
tx_buf_sets(req, "KEY", key);
tx_buf_sets(req, "MERCHID", merch);
tx_buf_sets(req, "CARDNO", card);
tx_buf_setlong(req, "AMOUNT", amount);
tx_buf_sets(req, "MTI", MSG_TYPE_RECV);
/* 트랜잭션 시작 → 원장 반영 → 후속 서비스 연계 → 커밋 */
if (tx_begin() != TX_OK) {
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AU_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100;
rc = au_rec_insert(&rec);
rc = tx_call("AU_ISSUER", req, ctx->out);
tx_buf_free(req);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0008] 원장반영 실패 rc=%d", rc);
tx_abort();
tx_log(TX_LOG_ERROR, "[AU_OL_0008] 매입사 중계 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, rc, ctx->out);
return;
}
/* 정산 영업일 = 거래일의 다음 영업일 */
if (date_next_business(bizdate, nextbiz) != 0) {
memcpy(nextbiz, bizdate, 8);
nextbiz[8] = '\0';
}
/* 후속 정산집계 서비스 연계 (레지스트리 문자열 디스패치) */
sub_in = tx_buf_alloc();
sub_out = tx_buf_alloc();
if (sub_in && sub_out) {
tx_buf_sets(sub_in, "MERCHID", merch);
tx_buf_sets(sub_in, "BIZDATE", nextbiz);
tx_buf_setlong(sub_in, "AMOUNT", amount);
rc = tx_call("AU_POST", sub_in, sub_out);
if (rc != TX_OK)
tx_log(TX_LOG_WARN, "[AU_OL_0008] 후속연계 경고 rc=%d", rc);
}
tx_buf_free(sub_in);
tx_buf_free(sub_out);
/* 교차 검증: 당일 합계 재계산 */
if (au_rec_sum(bizdate, &daysum) != TX_OK)
daysum = 0;
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYSUM", daysum);
tx_log(TX_LOG_INFO, "[AU_OL_0008] 완료 key=%s 당일합계=%ld", key, daysum);
if (tx_buf_get(ctx->out, "RESPCODE", resp, sizeof(resp)) != TX_OK)
strcpy(resp, RESP_OK);
tx_log(TX_LOG_INFO, "[AU_OL_0008] 중계 응답 key=%s resp=%s", key, resp);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -6,17 +6,18 @@
/* End of automatic include section */
#line 1 "app/online/au_ol_0009.pgc"
/* @tier easy @module au @transform authorization-online */
/* @tier hard @module au @transform authorization-online */
/*
* au_ol_0009.pgc - (AU_OL_0009) [tier=easy]
* au_ol_0009.pgc - fallback( ) (AU_OL_0009) [tier=hard]
*
* TxCore TX_SERVICE . TXBUF au DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* TxCore TX_SERVICE . TXBUF SQL /
* DBIO / tx_call TXBUF .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -89,37 +90,50 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/au_ol_0009.pgc"
#line 16 "app/online/au_ol_0009.pgc"
TX_SERVICE(AU_OL_0009, ctx)
{
au_rec_t rec;
char key[16];
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0009] 승인한도 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0009] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
TXBUF *req;
long amount = 0;
int rc;
memset(&rec, 0, sizeof(rec));
rc = au_rec_select(key, &rec);
tx_log(TX_LOG_INFO, "[AU_OL_0009] 대행승인 fallback 진입");
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
req = tx_buf_alloc();
if (!req) {
tx_return(ctx, TX_ENOMEM, ctx->out);
return;
}
tx_buf_sets(req, "KEY", key);
tx_buf_setlong(req, "AMOUNT", amount);
rc = tx_call("AU_ISSUER", req, ctx->out);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AU_OL_0009] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_log(TX_LOG_WARN, "[AU_OL_0009] 주센터 실패 rc=%d, 대행센터 전환", rc);
tx_buf_reset(ctx->out);
rc = tx_call("AU_STANDIN", req, ctx->out);
if (rc == TX_OK)
tx_buf_sets(ctx->out, "STANDIN", "Y");
} else {
tx_buf_sets(ctx->out, "STANDIN", "N");
}
tx_buf_free(req);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0009] 대행승인까지 실패 rc=%d", rc);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, rc, ctx->out);
return;
}
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AU_OL_0009] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_log(TX_LOG_INFO, "[AU_OL_0009] fallback 처리완료 key=%s", key);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier easy @module au @transform authorization-online */
/* @tier hard @module au @transform authorization-online */
/*
* au_ol_0009.pgc - 승인한도 온라인 서비스 (AU_OL_0009) [tier=easy]
* au_ol_0009.pgc - 대행승인 fallback(주센터 실패시 백업) (AU_OL_0009) [tier=hard]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 au 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 임베디드 SQL / 표준
* DBIO / tx_call 로 처리한 뒤 응답 TXBUF 를 구성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -16,32 +17,45 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AU_OL_0009, ctx)
{
au_rec_t rec;
char key[16];
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0009] 승인한도 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0009] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
TXBUF *req;
long amount = 0;
int rc;
memset(&rec, 0, sizeof(rec));
rc = au_rec_select(key, &rec);
tx_log(TX_LOG_INFO, "[AU_OL_0009] 대행승인 fallback 진입");
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
req = tx_buf_alloc();
if (!req) {
tx_return(ctx, TX_ENOMEM, ctx->out);
return;
}
tx_buf_sets(req, "KEY", key);
tx_buf_setlong(req, "AMOUNT", amount);
rc = tx_call("AU_ISSUER", req, ctx->out);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AU_OL_0009] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_log(TX_LOG_WARN, "[AU_OL_0009] 주센터 실패 rc=%d, 대행센터 전환", rc);
tx_buf_reset(ctx->out);
rc = tx_call("AU_STANDIN", req, ctx->out);
if (rc == TX_OK)
tx_buf_sets(ctx->out, "STANDIN", "Y");
} else {
tx_buf_sets(ctx->out, "STANDIN", "N");
}
tx_buf_free(req);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0009] 대행승인까지 실패 rc=%d", rc);
tx_buf_sets(ctx->out, "RESPCODE", RESP_SYSERR);
tx_return(ctx, rc, ctx->out);
return;
}
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AU_OL_0009] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_log(TX_LOG_INFO, "[AU_OL_0009] fallback 처리완료 key=%s", key);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -6,17 +6,18 @@
/* End of automatic include section */
#line 1 "app/online/au_ol_0010.pgc"
/* @tier easy @module au @transform authorization-online */
/* @tier hard @module au @transform authorization-online */
/*
* au_ol_0010.pgc - (AU_OL_0010) [tier=easy]
* au_ol_0010.pgc - (AU_OL_0010) [tier=hard]
*
* TxCore TX_SERVICE . TXBUF au DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* TxCore TX_SERVICE . TXBUF SQL /
* DBIO / tx_call TXBUF .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -89,37 +90,88 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/au_ol_0010.pgc"
#line 16 "app/online/au_ol_0010.pgc"
TX_SERVICE(AU_OL_0010, ctx)
{
au_rec_t rec;
char key[16];
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0010] 승인한도 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0010] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* exec sql begin declare section */
#line 27 "app/online/au_ol_0010.pgc"
char h_key [ 16 ] , h_card [ 20 ] , h_bdate [ 9 ] , h_status [ 2 ] ;
#line 28 "app/online/au_ol_0010.pgc"
long h_amount ;
/* exec sql end declare section */
#line 29 "app/online/au_ol_0010.pgc"
memset(&rec, 0, sizeof(rec));
rc = au_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AU_OL_0010] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
TXBUF *req;
char card[20], vresp[8];
long amount = 0;
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0010] 카드유효성 연계승인 진입");
if (tx_buf_get(ctx->in, "CARDNO", card, sizeof(card)) != TX_OK) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
req = tx_buf_alloc();
if (!req) { tx_return(ctx, TX_ENOMEM, ctx->out); return; }
tx_buf_sets(req, "CARDNO", card);
rc = tx_call("VL_CARD", req, ctx->out);
tx_buf_free(req);
if (rc != TX_OK ||
(tx_buf_get(ctx->out, "RESPCODE", vresp, sizeof(vresp)) == TX_OK &&
strcmp(vresp, RESP_OK) != 0)) {
tx_log(TX_LOG_WARN, "[AU_OL_0010] 카드 유효성 실패 card=%s", card);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
strncpy(h_key, key, 15); h_key[15] = '\0';
strncpy(h_card, card, 19); h_card[19] = '\0';
date_today(h_bdate);
strncpy(h_status, AU_ST_RECV, 1); h_status[1] = '\0';
h_amount = amount;
if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[AU_OL_0010] tx_begin 경고");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into au_ledger ( key , merch_id , card_no , amount , biz_date , status , fee ) values ( $1 , 'ONLINE' , $2 , $3 , $4 , $5 , 0 )",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_card),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_bdate),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 66 "app/online/au_ol_0010.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0010 접수");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AU_OL_0010] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_log(TX_LOG_INFO, "[AU_OL_0010] 카드검증+접수 완료 key=%s", key);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier easy @module au @transform authorization-online */
/* @tier hard @module au @transform authorization-online */
/*
* au_ol_0010.pgc - 승인한도 온라인 서비스 (AU_OL_0010) [tier=easy]
* au_ol_0010.pgc - 카드유효성 연계 후 승인접수 (AU_OL_0010) [tier=hard]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 au 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 임베디드 SQL / 표준
* DBIO / tx_call 로 처리한 뒤 응답 TXBUF 를 구성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -16,32 +17,64 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AU_OL_0010, ctx)
{
au_rec_t rec;
char key[16];
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0010] 승인한도 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0010] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16], h_card[20], h_bdate[9], h_status[2];
long h_amount;
EXEC SQL END DECLARE SECTION;
memset(&rec, 0, sizeof(rec));
rc = au_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AU_OL_0010] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
TXBUF *req;
char card[20], vresp[8];
long amount = 0;
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0010] 카드유효성 연계승인 진입");
if (tx_buf_get(ctx->in, "CARDNO", card, sizeof(card)) != TX_OK) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
req = tx_buf_alloc();
if (!req) { tx_return(ctx, TX_ENOMEM, ctx->out); return; }
tx_buf_sets(req, "CARDNO", card);
rc = tx_call("VL_CARD", req, ctx->out);
tx_buf_free(req);
if (rc != TX_OK ||
(tx_buf_get(ctx->out, "RESPCODE", vresp, sizeof(vresp)) == TX_OK &&
strcmp(vresp, RESP_OK) != 0)) {
tx_log(TX_LOG_WARN, "[AU_OL_0010] 카드 유효성 실패 card=%s", card);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
strncpy(h_key, key, 15); h_key[15] = '\0';
strncpy(h_card, card, 19); h_card[19] = '\0';
date_today(h_bdate);
strncpy(h_status, AU_ST_RECV, 1); h_status[1] = '\0';
h_amount = amount;
if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[AU_OL_0010] tx_begin 경고");
EXEC SQL INSERT INTO au_ledger (key, merch_id, card_no, amount, biz_date, status, fee)
VALUES (:h_key, 'ONLINE', :h_card, :h_amount, :h_bdate, :h_status, 0);
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0010 접수");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AU_OL_0010] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_log(TX_LOG_INFO, "[AU_OL_0010] 카드검증+접수 완료 key=%s", key);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -6,17 +6,18 @@
/* End of automatic include section */
#line 1 "app/online/au_ol_0011.pgc"
/* @tier medium @module au @transform authorization-online */
/* @tier hard @module au @transform authorization-online */
/*
* au_ol_0011.pgc - (AU_OL_0011) [tier=medium]
* au_ol_0011.pgc - ( ) (AU_OL_0011) [tier=hard]
*
* TxCore TX_SERVICE . TXBUF au DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* TxCore TX_SERVICE . TXBUF SQL /
* DBIO / tx_call TXBUF .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -89,60 +90,75 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/au_ol_0011.pgc"
#line 16 "app/online/au_ol_0011.pgc"
TX_SERVICE(AU_OL_0011, ctx)
{
au_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0011] 승인한도 등록 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0011] 필수 필드 누락");
char key[16];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0011] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
/* exec sql begin declare section */
#line 27 "app/online/au_ol_0011.pgc"
char h_card [ 20 ] , h_bdate [ 9 ] ;
#line 28 "app/online/au_ol_0011.pgc"
int h_cnt ;
#line 29 "app/online/au_ol_0011.pgc"
long h_sum ;
/* exec sql end declare section */
#line 30 "app/online/au_ol_0011.pgc"
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AU_OL_0011] 금액 범위 오류 amount=%ld", amount);
char card[20], bdate[16];
int fraud = 0;
tx_log(TX_LOG_INFO, "[AU_OL_0011] 이상거래 탐지 진입");
if (tx_buf_get(ctx->in, "CARDNO", card, sizeof(card)) != TX_OK) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0011] 영업일 오류 date=%s", bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
if (tx_buf_get(ctx->in, "BIZDATE", bdate, sizeof(bdate)) != TX_OK)
date_today(bdate);
strncpy(h_card, card, 19); h_card[19] = '\0';
strncpy(h_bdate, bdate, 8); h_bdate[8] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select count ( * ) , coalesce ( sum ( amount ) , 0 ) from au_ledger where card_no = $1 and biz_date = $2 ",
ECPGt_char,(h_card),(long)20,(long)1,(20)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_bdate),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_int,&(h_cnt),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_sum),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 49 "app/online/au_ol_0011.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0011 탐지");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AU_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
rc = au_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0011] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
return;
}
cnt = au_rec_count(bizdate, AU_ST_RECV);
if (h_cnt >= 10 || h_sum >= 30000000L)
fraud = 1;
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AU_OL_0011] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_return(ctx, TX_OK, ctx->out);
tx_buf_sets(ctx->out, "CARDNO", card);
tx_buf_setlong(ctx->out, "TXNCNT", h_cnt);
tx_buf_setlong(ctx->out, "TXNSUM", h_sum);
tx_buf_sets(ctx->out, "FRAUD", fraud ? "Y" : "N");
tx_buf_sets(ctx->out, "RESPCODE", fraud ? RESP_INVALID : RESP_OK);
tx_log(TX_LOG_INFO, "[AU_OL_0011] 탐지결과 card=%s cnt=%d sum=%ld fraud=%d",
card, h_cnt, h_sum, fraud);
tx_return(ctx, fraud ? TX_FAIL : TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier medium @module au @transform authorization-online */
/* @tier hard @module au @transform authorization-online */
/*
* au_ol_0011.pgc - 승인한도 온라인 서비스 (AU_OL_0011) [tier=medium]
* au_ol_0011.pgc - 이상거래 탐지(카드 단시간 다건) (AU_OL_0011) [tier=hard]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 au 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 임베디드 SQL / 표준
* DBIO / tx_call 로 처리한 뒤 응답 TXBUF 를 구성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -16,55 +17,52 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AU_OL_0011, ctx)
{
au_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0011] 승인한도 등록 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0011] 필수 필드 누락");
char key[16];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0011] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
EXEC SQL BEGIN DECLARE SECTION;
char h_card[20], h_bdate[9];
int h_cnt;
long h_sum;
EXEC SQL END DECLARE SECTION;
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AU_OL_0011] 금액 범위 오류 amount=%ld", amount);
char card[20], bdate[16];
int fraud = 0;
tx_log(TX_LOG_INFO, "[AU_OL_0011] 이상거래 탐지 진입");
if (tx_buf_get(ctx->in, "CARDNO", card, sizeof(card)) != TX_OK) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0011] 영업일 오류 date=%s", bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
if (tx_buf_get(ctx->in, "BIZDATE", bdate, sizeof(bdate)) != TX_OK)
date_today(bdate);
strncpy(h_card, card, 19); h_card[19] = '\0';
strncpy(h_bdate, bdate, 8); h_bdate[8] = '\0';
EXEC SQL SELECT count(*), coalesce(sum(amount), 0)
INTO :h_cnt, :h_sum
FROM au_ledger
WHERE card_no = :h_card AND biz_date = :h_bdate;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0011 탐지");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AU_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
rc = au_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0011] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
return;
}
cnt = au_rec_count(bizdate, AU_ST_RECV);
if (h_cnt >= 10 || h_sum >= 30000000L)
fraud = 1;
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AU_OL_0011] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_return(ctx, TX_OK, ctx->out);
tx_buf_sets(ctx->out, "CARDNO", card);
tx_buf_setlong(ctx->out, "TXNCNT", h_cnt);
tx_buf_setlong(ctx->out, "TXNSUM", h_sum);
tx_buf_sets(ctx->out, "FRAUD", fraud ? "Y" : "N");
tx_buf_sets(ctx->out, "RESPCODE", fraud ? RESP_INVALID : RESP_OK);
tx_log(TX_LOG_INFO, "[AU_OL_0011] 탐지결과 card=%s cnt=%d sum=%ld fraud=%d",
card, h_cnt, h_sum, fraud);
tx_return(ctx, fraud ? TX_FAIL : TX_OK, ctx->out);
}

View file

@ -6,17 +6,18 @@
/* End of automatic include section */
#line 1 "app/online/au_ol_0012.pgc"
/* @tier easy @module au @transform authorization-online */
/* @tier hard @module au @transform authorization-online */
/*
* au_ol_0012.pgc - (AU_OL_0012) [tier=easy]
* au_ol_0012.pgc - ( ) (AU_OL_0012) [tier=hard]
*
* TxCore TX_SERVICE . TXBUF au DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* TxCore TX_SERVICE . TXBUF SQL /
* DBIO / tx_call TXBUF .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -89,37 +90,77 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/au_ol_0012.pgc"
#line 16 "app/online/au_ol_0012.pgc"
TX_SERVICE(AU_OL_0012, ctx)
{
au_rec_t rec;
char key[16];
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0012] 승인한도 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0012] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* exec sql begin declare section */
#line 27 "app/online/au_ol_0012.pgc"
char h_key [ 16 ] , h_status [ 2 ] ;
#line 28 "app/online/au_ol_0012.pgc"
long h_amount ;
/* exec sql end declare section */
#line 29 "app/online/au_ol_0012.pgc"
memset(&rec, 0, sizeof(rec));
rc = au_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AU_OL_0012] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
TXBUF *req;
int rc, attempt;
tx_log(TX_LOG_INFO, "[AU_OL_0012] 승인 재시도 진입");
strncpy(h_key, key, 15); h_key[15] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount , status from au_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 38 "app/online/au_ol_0012.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (h_status[0] != 'U') {
tx_log(TX_LOG_WARN, "[AU_OL_0012] 재시도 대상아님 status=%s", h_status);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AU_OL_0012] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_return(ctx, TX_OK, ctx->out);
req = tx_buf_alloc();
if (!req) { tx_return(ctx, TX_ENOMEM, ctx->out); return; }
tx_buf_sets(req, "KEY", key);
tx_buf_setlong(req, "AMOUNT", h_amount);
rc = TX_FAIL;
for (attempt = 1; attempt <= 3; attempt++) {
tx_buf_reset(ctx->out);
rc = tx_call("AU_ISSUER", req, ctx->out);
tx_log(TX_LOG_INFO, "[AU_OL_0012] 재시도 %d회 rc=%d", attempt, rc);
if (rc == TX_OK) break;
}
tx_buf_free(req);
if (rc == TX_OK) {
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update au_ledger set status = 'M' , upd_ts = now ( ) where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 65 "app/online/au_ol_0012.pgc"
tx_commit();
}
tx_buf_setlong(ctx->out, "ATTEMPTS", attempt);
tx_return(ctx, rc, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier easy @module au @transform authorization-online */
/* @tier hard @module au @transform authorization-online */
/*
* au_ol_0012.pgc - 승인한도 온라인 서비스 (AU_OL_0012) [tier=easy]
* au_ol_0012.pgc - 승인 재시도(실패건 매입사 재요청) (AU_OL_0012) [tier=hard]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 au 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 임베디드 SQL / 표준
* DBIO / tx_call 로 처리한 뒤 응답 TXBUF 를 구성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -16,32 +17,54 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AU_OL_0012, ctx)
{
au_rec_t rec;
char key[16];
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0012] 승인한도 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0012] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16], h_status[2];
long h_amount;
EXEC SQL END DECLARE SECTION;
memset(&rec, 0, sizeof(rec));
rc = au_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AU_OL_0012] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
TXBUF *req;
int rc, attempt;
tx_log(TX_LOG_INFO, "[AU_OL_0012] 승인 재시도 진입");
strncpy(h_key, key, 15); h_key[15] = '\0';
EXEC SQL SELECT amount, status INTO :h_amount, :h_status
FROM au_ledger WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (h_status[0] != 'U') {
tx_log(TX_LOG_WARN, "[AU_OL_0012] 재시도 대상아님 status=%s", h_status);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AU_OL_0012] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_return(ctx, TX_OK, ctx->out);
req = tx_buf_alloc();
if (!req) { tx_return(ctx, TX_ENOMEM, ctx->out); return; }
tx_buf_sets(req, "KEY", key);
tx_buf_setlong(req, "AMOUNT", h_amount);
rc = TX_FAIL;
for (attempt = 1; attempt <= 3; attempt++) {
tx_buf_reset(ctx->out);
rc = tx_call("AU_ISSUER", req, ctx->out);
tx_log(TX_LOG_INFO, "[AU_OL_0012] 재시도 %d회 rc=%d", attempt, rc);
if (rc == TX_OK) break;
}
tx_buf_free(req);
if (rc == TX_OK) {
EXEC SQL UPDATE au_ledger SET status = 'M', upd_ts = now()
WHERE key = :h_key;
tx_commit();
}
tx_buf_setlong(ctx->out, "ATTEMPTS", attempt);
tx_return(ctx, rc, ctx->out);
}

View file

@ -8,15 +8,16 @@
#line 1 "app/online/au_ol_0013.pgc"
/* @tier medium @module au @transform authorization-online */
/*
* au_ol_0013.pgc - (AU_OL_0013) [tier=medium]
* au_ol_0013.pgc - ( +) (AU_OL_0013) [tier=medium]
*
* TxCore TX_SERVICE . TXBUF au DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* TxCore TX_SERVICE . TXBUF SQL /
* DBIO / tx_call TXBUF .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -89,60 +90,88 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/au_ol_0013.pgc"
#line 16 "app/online/au_ol_0013.pgc"
TX_SERVICE(AU_OL_0013, ctx)
{
au_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
char key[16];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0013] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* exec sql begin declare section */
#line 27 "app/online/au_ol_0013.pgc"
char h_key [ 16 ] , h_merch [ 16 ] , h_bdate [ 9 ] ;
#line 28 "app/online/au_ol_0013.pgc"
long h_amount , h_fee ;
#line 29 "app/online/au_ol_0013.pgc"
int h_inst ;
/* exec sql end declare section */
#line 30 "app/online/au_ol_0013.pgc"
tx_log(TX_LOG_INFO, "[AU_OL_0013] 승인한도 등록 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0013] 필수 필드 누락");
char merch[16];
long amount = 0;
int inst = 0;
tx_log(TX_LOG_INFO, "[AU_OL_0013] 무이자할부 승인 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
{ long v = 0; tx_buf_getlong(ctx->in, "INSTMONTH", &v); inst = (int)v; }
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AU_OL_0013] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0013] 영업일 오류 date=%s", bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
if (inst < 2 || inst > 12 || amount < 50000L) {
tx_log(TX_LOG_WARN, "[AU_OL_0013] 무이자 조건미달 inst=%d amt=%ld", inst, amount);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AU_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_key, key, 15); h_key[15] = '\0';
strncpy(h_merch, merch, 15); h_merch[15] = '\0';
date_today(h_bdate);
h_amount = amount;
h_inst = inst;
h_fee = 0; /* 무이자: 수수료 0 */
rc = au_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0013] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[AU_OL_0013] tx_begin 경고");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into au_ledger ( key , merch_id , card_no , amount , biz_date , status , fee ) values ( $1 , $2 , 'INSTALLMENT' , $3 , $4 , 'R' , $5 )",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_bdate),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_fee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 61 "app/online/au_ol_0013.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0013 할부등록");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
cnt = au_rec_count(bizdate, AU_ST_RECV);
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AU_OL_0013] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_setlong(ctx->out, "INSTMONTH", h_inst);
tx_buf_setlong(ctx->out, "MONTHLYAMT", h_amount / h_inst);
tx_log(TX_LOG_INFO, "[AU_OL_0013] 무이자할부 승인 %d개월 월납=%ld",
h_inst, h_amount / h_inst);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier medium @module au @transform authorization-online */
/*
* au_ol_0013.pgc - 승인한도 온라인 서비스 (AU_OL_0013) [tier=medium]
* au_ol_0013.pgc - 무이자할부 승인(할부개월 검증+등록) (AU_OL_0013) [tier=medium]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 au 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 임베디드 SQL / 표준
* DBIO / tx_call 로 처리한 뒤 응답 TXBUF 를 구성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -16,55 +17,61 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AU_OL_0013, ctx)
{
au_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
char key[16];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0013] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16], h_merch[16], h_bdate[9];
long h_amount, h_fee;
int h_inst;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AU_OL_0013] 승인한도 등록 서비스 진입");
char merch[16];
long amount = 0;
int inst = 0;
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0013] 필수 필드 누락");
tx_log(TX_LOG_INFO, "[AU_OL_0013] 무이자할부 승인 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
{ long v = 0; tx_buf_getlong(ctx->in, "INSTMONTH", &v); inst = (int)v; }
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AU_OL_0013] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0013] 영업일 오류 date=%s", bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
if (inst < 2 || inst > 12 || amount < 50000L) {
tx_log(TX_LOG_WARN, "[AU_OL_0013] 무이자 조건미달 inst=%d amt=%ld", inst, amount);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AU_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
strncpy(h_key, key, 15); h_key[15] = '\0';
strncpy(h_merch, merch, 15); h_merch[15] = '\0';
date_today(h_bdate);
h_amount = amount;
h_inst = inst;
h_fee = 0; /* 무이자: 수수료 0 */
rc = au_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0013] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[AU_OL_0013] tx_begin 경고");
EXEC SQL INSERT INTO au_ledger (key, merch_id, card_no, amount, biz_date, status, fee)
VALUES (:h_key, :h_merch, 'INSTALLMENT', :h_amount, :h_bdate, 'R', :h_fee);
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0013 할부등록");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
cnt = au_rec_count(bizdate, AU_ST_RECV);
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AU_OL_0013] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_setlong(ctx->out, "INSTMONTH", h_inst);
tx_buf_setlong(ctx->out, "MONTHLYAMT", h_amount / h_inst);
tx_log(TX_LOG_INFO, "[AU_OL_0013] 무이자할부 승인 %d개월 월납=%ld",
h_inst, h_amount / h_inst);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -6,17 +6,18 @@
/* End of automatic include section */
#line 1 "app/online/au_ol_0014.pgc"
/* @tier easy @module au @transform authorization-online */
/* @tier hard @module au @transform authorization-online */
/*
* au_ol_0014.pgc - (AU_OL_0014) [tier=easy]
* au_ol_0014.pgc - ( ) (AU_OL_0014) [tier=hard]
*
* TxCore TX_SERVICE . TXBUF au DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* TxCore TX_SERVICE . TXBUF SQL /
* DBIO / tx_call TXBUF .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -89,37 +90,74 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/au_ol_0014.pgc"
#line 16 "app/online/au_ol_0014.pgc"
TX_SERVICE(AU_OL_0014, ctx)
{
au_rec_t rec;
char key[16];
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0014] 승인한도 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0014] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* exec sql begin declare section */
#line 27 "app/online/au_ol_0014.pgc"
char h_merch [ 16 ] , h_bdate [ 9 ] ;
#line 28 "app/online/au_ol_0014.pgc"
long h_used , h_req ;
/* exec sql end declare section */
#line 29 "app/online/au_ol_0014.pgc"
memset(&rec, 0, sizeof(rec));
rc = au_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AU_OL_0014] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
char merch[16], bdate[16];
long req = 0, limit_amt = 100000000L;
tx_log(TX_LOG_INFO, "[AU_OL_0014] 승인 한도초과 처리 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (tx_buf_get(ctx->in, "BIZDATE", bdate, sizeof(bdate)) != TX_OK)
date_today(bdate);
tx_buf_getlong(ctx->in, "AMOUNT", &req);
strncpy(h_merch, merch, 15); h_merch[15] = '\0';
strncpy(h_bdate, bdate, 8); h_bdate[8] = '\0';
h_req = req;
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select coalesce ( sum ( amount ) , 0 ) from au_ledger where merch_id = $1 and biz_date = $2 and status = 'M'",
ECPGt_char,(h_merch),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_bdate),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_used),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 49 "app/online/au_ol_0014.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0014 누적조회");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AU_OL_0014] 조회완료 key=%s amount=%ld", key, rec.amount);
if (h_used + h_req > limit_amt) {
tx_log(TX_LOG_WARN, "[AU_OL_0014] 한도초과 used=%ld req=%ld limit=%ld",
h_used, h_req, limit_amt);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_buf_sets(ctx->out, "OVERLIMIT", "Y");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "OVERLIMIT", "N");
tx_buf_setlong(ctx->out, "AVAIL", limit_amt - h_used - h_req);
tx_log(TX_LOG_INFO, "[AU_OL_0014] 한도내 승인가능 잔여=%ld",
limit_amt - h_used - h_req);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier easy @module au @transform authorization-online */
/* @tier hard @module au @transform authorization-online */
/*
* au_ol_0014.pgc - 승인한도 온라인 서비스 (AU_OL_0014) [tier=easy]
* au_ol_0014.pgc - 승인 한도초과 처리(누적합 판정) (AU_OL_0014) [tier=hard]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 au 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 임베디드 SQL / 표준
* DBIO / tx_call 로 처리한 뒤 응답 TXBUF 를 구성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -16,32 +17,55 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AU_OL_0014, ctx)
{
au_rec_t rec;
char key[16];
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0014] 승인한도 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0014] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
EXEC SQL BEGIN DECLARE SECTION;
char h_merch[16], h_bdate[9];
long h_used, h_req;
EXEC SQL END DECLARE SECTION;
memset(&rec, 0, sizeof(rec));
rc = au_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AU_OL_0014] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
char merch[16], bdate[16];
long req = 0, limit_amt = 100000000L;
tx_log(TX_LOG_INFO, "[AU_OL_0014] 승인 한도초과 처리 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
if (tx_buf_get(ctx->in, "BIZDATE", bdate, sizeof(bdate)) != TX_OK)
date_today(bdate);
tx_buf_getlong(ctx->in, "AMOUNT", &req);
strncpy(h_merch, merch, 15); h_merch[15] = '\0';
strncpy(h_bdate, bdate, 8); h_bdate[8] = '\0';
h_req = req;
EXEC SQL SELECT coalesce(sum(amount), 0) INTO :h_used
FROM au_ledger
WHERE merch_id = :h_merch AND biz_date = :h_bdate AND status = 'M';
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0014 누적조회");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AU_OL_0014] 조회완료 key=%s amount=%ld", key, rec.amount);
if (h_used + h_req > limit_amt) {
tx_log(TX_LOG_WARN, "[AU_OL_0014] 한도초과 used=%ld req=%ld limit=%ld",
h_used, h_req, limit_amt);
tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
tx_buf_sets(ctx->out, "OVERLIMIT", "Y");
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "OVERLIMIT", "N");
tx_buf_setlong(ctx->out, "AVAIL", limit_amt - h_used - h_req);
tx_log(TX_LOG_INFO, "[AU_OL_0014] 한도내 승인가능 잔여=%ld",
limit_amt - h_used - h_req);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -6,17 +6,18 @@
/* End of automatic include section */
#line 1 "app/online/au_ol_0015.pgc"
/* @tier medium @module au @transform authorization-online */
/* @tier easy @module au @transform authorization-online */
/*
* au_ol_0015.pgc - (AU_OL_0015) [tier=medium]
* au_ol_0015.pgc - (: /) (AU_OL_0015) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF au DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* TxCore TX_SERVICE . TXBUF SQL /
* DBIO / tx_call TXBUF .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -89,60 +90,72 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/au_ol_0015.pgc"
#line 16 "app/online/au_ol_0015.pgc"
TX_SERVICE(AU_OL_0015, ctx)
{
au_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0015] 승인한도 등록 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0015] 필수 필드 누락");
char key[16];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0015] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
/* exec sql begin declare section */
#line 27 "app/online/au_ol_0015.pgc"
char h_key [ 16 ] , h_status [ 2 ] , h_bdate [ 9 ] ;
#line 28 "app/online/au_ol_0015.pgc"
long h_amount , h_fee ;
/* exec sql end declare section */
#line 29 "app/online/au_ol_0015.pgc"
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AU_OL_0015] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
const char *label;
tx_log(TX_LOG_INFO, "[AU_OL_0015] 승인 상태조회 진입");
strncpy(h_key, key, 15); h_key[15] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount , fee , status , biz_date from au_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_fee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_bdate),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 38 "app/online/au_ol_0015.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0015] 영업일 오류 date=%s", bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0015 상태조회");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AU_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
rc = au_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0015] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
return;
switch (h_status[0]) {
case 'R': label = "접수"; break;
case 'M': label = "승인완료"; break;
case 'U': label = "거절/취소"; break;
case 'S': label = "정산완료"; break;
default: label = "미상"; break;
}
cnt = au_rec_count(bizdate, AU_ST_RECV);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AU_OL_0015] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_sets(ctx->out, "STATUS", h_status);
tx_buf_sets(ctx->out, "STATUSLBL", label);
tx_buf_setlong(ctx->out, "AMOUNT", h_amount);
tx_buf_setlong(ctx->out, "FEE", h_fee);
tx_log(TX_LOG_INFO, "[AU_OL_0015] 상태 key=%s status=%s(%s)", key, h_status, label);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier medium @module au @transform authorization-online */
/* @tier easy @module au @transform authorization-online */
/*
* au_ol_0015.pgc - 승인한도 온라인 서비스 (AU_OL_0015) [tier=medium]
* au_ol_0015.pgc - 승인 상태조회(상세: 상태/수수료) (AU_OL_0015) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 au 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 임베디드 SQL / 표준
* DBIO / tx_call 로 처리한 뒤 응답 TXBUF 를 구성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -16,55 +17,49 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AU_OL_0015, ctx)
{
au_rec_t rec;
char key[16], merch[16], bizdate[16];
long amount = 0, cnt;
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0015] 승인한도 등록 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0015] 필수 필드 누락");
char key[16];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0015] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16], h_status[2], h_bdate[9];
long h_amount, h_fee;
EXEC SQL END DECLARE SECTION;
/* 업무검증: 금액 범위 + 영업일 형식 */
if (!amount_is_valid(amount)) {
tx_log(TX_LOG_WARN, "[AU_OL_0015] 금액 범위 오류 amount=%ld", amount);
tx_return(ctx, TX_EINVAL, ctx->out);
const char *label;
tx_log(TX_LOG_INFO, "[AU_OL_0015] 승인 상태조회 진입");
strncpy(h_key, key, 15); h_key[15] = '\0';
EXEC SQL SELECT amount, fee, status, biz_date
INTO :h_amount, :h_fee, :h_status, :h_bdate
FROM au_ledger WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
if (!date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0015] 영업일 오류 date=%s", bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0015 상태조회");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AU_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100; /* 수수료 1% 가정 */
rc = au_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0015] 등록 실패 rc=%d(%s)", rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
return;
switch (h_status[0]) {
case 'R': label = "접수"; break;
case 'M': label = "승인완료"; break;
case 'U': label = "거절/취소"; break;
case 'S': label = "정산완료"; break;
default: label = "미상"; break;
}
cnt = au_rec_count(bizdate, AU_ST_RECV);
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYCNT", (cnt < 0) ? 0 : cnt);
tx_log(TX_LOG_INFO, "[AU_OL_0015] 등록완료 key=%s 당일건수=%ld", key, cnt);
tx_buf_sets(ctx->out, "STATUS", h_status);
tx_buf_sets(ctx->out, "STATUSLBL", label);
tx_buf_setlong(ctx->out, "AMOUNT", h_amount);
tx_buf_setlong(ctx->out, "FEE", h_fee);
tx_log(TX_LOG_INFO, "[AU_OL_0015] 상태 key=%s status=%s(%s)", key, h_status, label);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -8,15 +8,16 @@
#line 1 "app/online/au_ol_0016.pgc"
/* @tier easy @module au @transform authorization-online */
/*
* au_ol_0016.pgc - (AU_OL_0016) [tier=easy]
* au_ol_0016.pgc - ( INSERT) (AU_OL_0016) [tier=easy]
*
* TxCore TX_SERVICE . TXBUF au DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* TxCore TX_SERVICE . TXBUF SQL /
* DBIO / tx_call TXBUF .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -89,37 +90,76 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/au_ol_0016.pgc"
#line 16 "app/online/au_ol_0016.pgc"
TX_SERVICE(AU_OL_0016, ctx)
{
au_rec_t rec;
char key[16];
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0016] 승인한도 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0016] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
/* exec sql begin declare section */
#line 27 "app/online/au_ol_0016.pgc"
char h_key [ 16 ] , h_merch [ 16 ] , h_bdate [ 9 ] , h_status [ 2 ] ;
#line 28 "app/online/au_ol_0016.pgc"
long h_amount ;
/* exec sql end declare section */
#line 29 "app/online/au_ol_0016.pgc"
memset(&rec, 0, sizeof(rec));
rc = au_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AU_OL_0016] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
char merch[16], evt[8];
long amount = 0;
tx_log(TX_LOG_INFO, "[AU_OL_0016] 승인 로그적재 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK)
strcpy(merch, "SYS");
if (tx_buf_get(ctx->in, "EVENT", evt, sizeof(evt)) != TX_OK)
strcpy(evt, "APPROVE");
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
strncpy(h_key, key, 15); h_key[15] = '\0';
strncpy(h_merch, merch, 15); h_merch[15] = '\0';
date_today(h_bdate);
strncpy(h_status, AU_ST_RECV, 1); h_status[1] = '\0';
h_amount = amount;
if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[AU_OL_0016] tx_begin 경고");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into au_ledger ( key , merch_id , card_no , amount , biz_date , status , fee ) values ( $1 , $2 , $3 , $4 , $5 , $6 , 0 ) on conflict ( key ) do update set amount = $7 , upd_ts = now ( )",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_merch),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_bdate),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_bdate),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_status),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 50 "app/online/au_ol_0016.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0016 로그적재");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AU_OL_0016] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "LOGKEY", key);
tx_buf_sets(ctx->out, "EVENT", evt);
tx_log(TX_LOG_INFO, "[AU_OL_0016] 로그적재 완료 key=%s event=%s", key, evt);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier easy @module au @transform authorization-online */
/*
* au_ol_0016.pgc - 승인한도 온라인 서비스 (AU_OL_0016) [tier=easy]
* au_ol_0016.pgc - 승인 로그적재(감사원장 INSERT) (AU_OL_0016) [tier=easy]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 au 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 임베디드 SQL / 표준
* DBIO / tx_call 로 처리한 뒤 응답 TXBUF 를 구성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -16,32 +17,49 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AU_OL_0016, ctx)
{
au_rec_t rec;
char key[16];
int rc;
tx_log(TX_LOG_INFO, "[AU_OL_0016] 승인한도 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0016] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16], h_merch[16], h_bdate[9], h_status[2];
long h_amount;
EXEC SQL END DECLARE SECTION;
memset(&rec, 0, sizeof(rec));
rc = au_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AU_OL_0016] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
char merch[16], evt[8];
long amount = 0;
tx_log(TX_LOG_INFO, "[AU_OL_0016] 승인 로그적재 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK)
strcpy(merch, "SYS");
if (tx_buf_get(ctx->in, "EVENT", evt, sizeof(evt)) != TX_OK)
strcpy(evt, "APPROVE");
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
strncpy(h_key, key, 15); h_key[15] = '\0';
strncpy(h_merch, merch, 15); h_merch[15] = '\0';
date_today(h_bdate);
strncpy(h_status, AU_ST_RECV, 1); h_status[1] = '\0';
h_amount = amount;
if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[AU_OL_0016] tx_begin 경고");
EXEC SQL INSERT INTO au_ledger (key, merch_id, card_no, amount, biz_date, status, fee)
VALUES (:h_key, :h_merch, :h_bdate, :h_amount, :h_bdate, :h_status, 0)
ON CONFLICT (key) DO UPDATE SET amount = :h_amount, upd_ts = now();
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0016 로그적재");
tx_abort();
tx_return(ctx, TX_EDB, ctx->out);
return;
}
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AU_OL_0016] 조회완료 key=%s amount=%ld", key, rec.amount);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "LOGKEY", key);
tx_buf_sets(ctx->out, "EVENT", evt);
tx_log(TX_LOG_INFO, "[AU_OL_0016] 로그적재 완료 key=%s event=%s", key, evt);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -6,17 +6,18 @@
/* End of automatic include section */
#line 1 "app/online/au_ol_0017.pgc"
/* @tier hard @module au @transform authorization-online */
/* @tier medium @module au @transform authorization-online */
/*
* au_ol_0017.pgc - (AU_OL_0017) [tier=hard]
* au_ol_0017.pgc - ( ) (AU_OL_0017) [tier=medium]
*
* TxCore TX_SERVICE . TXBUF au DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* TxCore TX_SERVICE . TXBUF SQL /
* DBIO / tx_call TXBUF .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -89,88 +90,67 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/au_ol_0017.pgc"
#line 16 "app/online/au_ol_0017.pgc"
TX_SERVICE(AU_OL_0017, ctx)
{
au_rec_t rec;
char key[16], merch[16], bizdate[16], nextbiz[9];
long amount = 0, daysum = 0;
int rc;
TXBUF *sub_in;
TXBUF *sub_out;
/* exec sql begin declare section */
#line 21 "app/online/au_ol_0017.pgc"
char h_merch [ 16 ] , h_bdate [ 9 ] ;
#line 22 "app/online/au_ol_0017.pgc"
long h_sum , h_fee ;
#line 23 "app/online/au_ol_0017.pgc"
int h_cnt ;
/* exec sql end declare section */
#line 24 "app/online/au_ol_0017.pgc"
tx_log(TX_LOG_INFO, "[AU_OL_0017] 승인한도 트랜잭션 오케스트레이션 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0017] 필수 필드 누락");
char merch[16], bdate[16], won[32];
tx_log(TX_LOG_INFO, "[AU_OL_0017] 승인 금액집계 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
if (tx_buf_get(ctx->in, "BIZDATE", bdate, sizeof(bdate)) != TX_OK)
date_today(bdate);
if (!amount_is_valid(amount) || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0017] 입력 검증 실패 amount=%ld date=%s",
amount, bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
strncpy(h_merch, merch, 15); h_merch[15] = '\0';
strncpy(h_bdate, bdate, 8); h_bdate[8] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select count ( * ) , coalesce ( sum ( amount ) , 0 ) , coalesce ( sum ( fee ) , 0 ) from au_ledger where merch_id = $1 and biz_date = $2 and status in ( 'M' , 'S' )",
ECPGt_char,(h_merch),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_bdate),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_int,&(h_cnt),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_sum),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_long,&(h_fee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 43 "app/online/au_ol_0017.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0017 집계");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 트랜잭션 시작 → 원장 반영 → 후속 서비스 연계 → 커밋 */
if (tx_begin() != TX_OK) {
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AU_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100;
rc = au_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0017] 원장반영 실패 rc=%d", rc);
tx_abort();
tx_return(ctx, rc, ctx->out);
return;
}
/* 정산 영업일 = 거래일의 다음 영업일 */
if (date_next_business(bizdate, nextbiz) != 0) {
memcpy(nextbiz, bizdate, 8);
nextbiz[8] = '\0';
}
/* 후속 정산집계 서비스 연계 (레지스트리 문자열 디스패치) */
sub_in = tx_buf_alloc();
sub_out = tx_buf_alloc();
if (sub_in && sub_out) {
tx_buf_sets(sub_in, "MERCHID", merch);
tx_buf_sets(sub_in, "BIZDATE", nextbiz);
tx_buf_setlong(sub_in, "AMOUNT", amount);
rc = tx_call("AU_POST", sub_in, sub_out);
if (rc != TX_OK)
tx_log(TX_LOG_WARN, "[AU_OL_0017] 후속연계 경고 rc=%d", rc);
}
tx_buf_free(sub_in);
tx_buf_free(sub_out);
/* 교차 검증: 당일 합계 재계산 */
if (au_rec_sum(bizdate, &daysum) != TX_OK)
daysum = 0;
tx_commit();
amount_format_won(h_sum, won, sizeof(won));
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYSUM", daysum);
tx_log(TX_LOG_INFO, "[AU_OL_0017] 완료 key=%s 당일합계=%ld", key, daysum);
tx_buf_sets(ctx->out, "MERCHID", merch);
tx_buf_setlong(ctx->out, "CNT", h_cnt);
tx_buf_setlong(ctx->out, "SUMAMT", h_sum);
tx_buf_setlong(ctx->out, "SUMFEE", h_fee);
tx_buf_sets(ctx->out, "SUMWON", won);
tx_log(TX_LOG_INFO, "[AU_OL_0017] 집계 merch=%s cnt=%d sum=%ld", merch, h_cnt, h_sum);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier hard @module au @transform authorization-online */
/* @tier medium @module au @transform authorization-online */
/*
* au_ol_0017.pgc - 승인한도 온라인 서비스 (AU_OL_0017) [tier=hard]
* au_ol_0017.pgc - 승인 금액집계(가맹점 당일 합계) (AU_OL_0017) [tier=medium]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 au 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 임베디드 SQL / 표준
* DBIO / tx_call 로 처리한 뒤 응답 TXBUF 를 구성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -16,83 +17,43 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AU_OL_0017, ctx)
{
au_rec_t rec;
char key[16], merch[16], bizdate[16], nextbiz[9];
long amount = 0, daysum = 0;
int rc;
TXBUF *sub_in;
TXBUF *sub_out;
EXEC SQL BEGIN DECLARE SECTION;
char h_merch[16], h_bdate[9];
long h_sum, h_fee;
int h_cnt;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AU_OL_0017] 승인한도 트랜잭션 오케스트레이션 진입");
char merch[16], bdate[16], won[32];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0017] 필수 필드 누락");
tx_log(TX_LOG_INFO, "[AU_OL_0017] 승인 금액집계 진입");
if (tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK) {
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
if (tx_buf_get(ctx->in, "BIZDATE", bdate, sizeof(bdate)) != TX_OK)
date_today(bdate);
if (!amount_is_valid(amount) || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0017] 입력 검증 실패 amount=%ld date=%s",
amount, bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
strncpy(h_merch, merch, 15); h_merch[15] = '\0';
strncpy(h_bdate, bdate, 8); h_bdate[8] = '\0';
EXEC SQL SELECT count(*), coalesce(sum(amount), 0), coalesce(sum(fee), 0)
INTO :h_cnt, :h_sum, :h_fee
FROM au_ledger
WHERE merch_id = :h_merch AND biz_date = :h_bdate
AND status IN ('M', 'S');
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0017 집계");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 트랜잭션 시작 → 원장 반영 → 후속 서비스 연계 → 커밋 */
if (tx_begin() != TX_OK) {
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AU_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100;
rc = au_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0017] 원장반영 실패 rc=%d", rc);
tx_abort();
tx_return(ctx, rc, ctx->out);
return;
}
/* 정산 영업일 = 거래일의 다음 영업일 */
if (date_next_business(bizdate, nextbiz) != 0) {
memcpy(nextbiz, bizdate, 8);
nextbiz[8] = '\0';
}
/* 후속 정산집계 서비스 연계 (레지스트리 문자열 디스패치) */
sub_in = tx_buf_alloc();
sub_out = tx_buf_alloc();
if (sub_in && sub_out) {
tx_buf_sets(sub_in, "MERCHID", merch);
tx_buf_sets(sub_in, "BIZDATE", nextbiz);
tx_buf_setlong(sub_in, "AMOUNT", amount);
rc = tx_call("AU_POST", sub_in, sub_out);
if (rc != TX_OK)
tx_log(TX_LOG_WARN, "[AU_OL_0017] 후속연계 경고 rc=%d", rc);
}
tx_buf_free(sub_in);
tx_buf_free(sub_out);
/* 교차 검증: 당일 합계 재계산 */
if (au_rec_sum(bizdate, &daysum) != TX_OK)
daysum = 0;
tx_commit();
amount_format_won(h_sum, won, sizeof(won));
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYSUM", daysum);
tx_log(TX_LOG_INFO, "[AU_OL_0017] 완료 key=%s 당일합계=%ld", key, daysum);
tx_buf_sets(ctx->out, "MERCHID", merch);
tx_buf_setlong(ctx->out, "CNT", h_cnt);
tx_buf_setlong(ctx->out, "SUMAMT", h_sum);
tx_buf_setlong(ctx->out, "SUMFEE", h_fee);
tx_buf_sets(ctx->out, "SUMWON", won);
tx_log(TX_LOG_INFO, "[AU_OL_0017] 집계 merch=%s cnt=%d sum=%ld", merch, h_cnt, h_sum);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -6,17 +6,18 @@
/* End of automatic include section */
#line 1 "app/online/au_ol_0018.pgc"
/* @tier easy @module au @transform authorization-online */
/* @tier medium @module au @transform authorization-online */
/*
* au_ol_0018.pgc - (AU_OL_0018) [tier=easy]
* au_ol_0018.pgc - ( ) (AU_OL_0018) [tier=medium]
*
* TxCore TX_SERVICE . TXBUF au DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* TxCore TX_SERVICE . TXBUF SQL /
* DBIO / tx_call TXBUF .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -89,37 +90,60 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/au_ol_0018.pgc"
#line 16 "app/online/au_ol_0018.pgc"
TX_SERVICE(AU_OL_0018, ctx)
{
au_rec_t rec;
char key[16];
int rc;
/* exec sql begin declare section */
#line 21 "app/online/au_ol_0018.pgc"
char h_bdate [ 9 ] , h_st [ 2 ] ;
#line 22 "app/online/au_ol_0018.pgc"
int h_cnt ;
/* exec sql end declare section */
#line 23 "app/online/au_ol_0018.pgc"
tx_log(TX_LOG_INFO, "[AU_OL_0018] 승인한도 단건조회 서비스 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0018] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
char bdate[16];
const char *codes = "RMUS";
int i, total = 0;
memset(&rec, 0, sizeof(rec));
rc = au_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AU_OL_0018] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
return;
}
tx_log(TX_LOG_INFO, "[AU_OL_0018] 승인 통계조회 진입");
if (tx_buf_get(ctx->in, "BIZDATE", bdate, sizeof(bdate)) != TX_OK)
date_today(bdate);
strncpy(h_bdate, bdate, 8); h_bdate[8] = '\0';
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AU_OL_0018] 조회완료 key=%s amount=%ld", key, rec.amount);
for (i = 0; codes[i]; i++) {
char field[8] = "CNT_";
h_st[0] = codes[i];
h_st[1] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select count ( * ) from au_ledger where biz_date = $1 and status = $2 ",
ECPGt_char,(h_bdate),(long)9,(long)1,(9)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_st),(long)2,(long)1,(2)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_int,&(h_cnt),(long)1,(long)1,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 41 "app/online/au_ol_0018.pgc"
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0018 통계");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
field[4] = codes[i];
field[5] = '\0';
tx_buf_setlong(ctx->out, field, h_cnt);
total += h_cnt;
}
tx_buf_sets(ctx->out, "BIZDATE", bdate);
tx_buf_setlong(ctx->out, "TOTAL", total);
tx_log(TX_LOG_INFO, "[AU_OL_0018] 통계 date=%s total=%d", bdate, total);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier easy @module au @transform authorization-online */
/* @tier medium @module au @transform authorization-online */
/*
* au_ol_0018.pgc - 승인한도 온라인 서비스 (AU_OL_0018) [tier=easy]
* au_ol_0018.pgc - 승인 통계조회(상태별 건수 집계) (AU_OL_0018) [tier=medium]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 au 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 임베디드 SQL / 표준
* DBIO / tx_call 로 처리한 뒤 응답 TXBUF 를 구성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -16,32 +17,41 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AU_OL_0018, ctx)
{
au_rec_t rec;
char key[16];
int rc;
EXEC SQL BEGIN DECLARE SECTION;
char h_bdate[9], h_st[2];
int h_cnt;
EXEC SQL END DECLARE SECTION;
tx_log(TX_LOG_INFO, "[AU_OL_0018] 승인한도 단건조회 서비스 진입");
char bdate[16];
const char *codes = "RMUS";
int i, total = 0;
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0018] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
rc = au_rec_select(key, &rec);
if (rc != TX_OK) {
tx_log(TX_LOG_WARN, "[AU_OL_0018] 조회 실패 key=%s rc=%d(%s)",
key, rc, tx_strerror(rc));
tx_return(ctx, rc, ctx->out);
return;
}
tx_log(TX_LOG_INFO, "[AU_OL_0018] 승인 통계조회 진입");
if (tx_buf_get(ctx->in, "BIZDATE", bdate, sizeof(bdate)) != TX_OK)
date_today(bdate);
strncpy(h_bdate, bdate, 8); h_bdate[8] = '\0';
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "KEY", rec.key);
tx_buf_sets(ctx->out, "MERCHID", rec.merch_id);
tx_buf_setlong(ctx->out, "AMOUNT", rec.amount);
tx_buf_sets(ctx->out, "STATUS", rec.status);
tx_log(TX_LOG_INFO, "[AU_OL_0018] 조회완료 key=%s amount=%ld", key, rec.amount);
for (i = 0; codes[i]; i++) {
char field[8] = "CNT_";
h_st[0] = codes[i];
h_st[1] = '\0';
EXEC SQL SELECT count(*) INTO :h_cnt
FROM au_ledger
WHERE biz_date = :h_bdate AND status = :h_st;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0018 통계");
tx_return(ctx, TX_EDB, ctx->out);
return;
}
field[4] = codes[i];
field[5] = '\0';
tx_buf_setlong(ctx->out, field, h_cnt);
total += h_cnt;
}
tx_buf_sets(ctx->out, "BIZDATE", bdate);
tx_buf_setlong(ctx->out, "TOTAL", total);
tx_log(TX_LOG_INFO, "[AU_OL_0018] 통계 date=%s total=%d", bdate, total);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -6,17 +6,18 @@
/* End of automatic include section */
#line 1 "app/online/au_ol_0019.pgc"
/* @tier hard @module au @transform authorization-online */
/* @tier medium @module au @transform authorization-online */
/*
* au_ol_0019.pgc - (AU_OL_0019) [tier=hard]
* au_ol_0019.pgc - ( UPDATE) (AU_OL_0019) [tier=medium]
*
* TxCore TX_SERVICE . TXBUF au DBIO
* TXBUF . (ATMI void SVC(TPSVCINFO*) )
* TxCore TX_SERVICE . TXBUF SQL /
* DBIO / tx_call TXBUF .
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -89,88 +90,75 @@ struct sqlca_t *ECPGget_sqlca(void);
#endif
#line 15 "app/online/au_ol_0019.pgc"
#line 16 "app/online/au_ol_0019.pgc"
TX_SERVICE(AU_OL_0019, ctx)
{
au_rec_t rec;
char key[16], merch[16], bizdate[16], nextbiz[9];
long amount = 0, daysum = 0;
int rc;
TXBUF *sub_in;
TXBUF *sub_out;
tx_log(TX_LOG_INFO, "[AU_OL_0019] 승인한도 트랜잭션 오케스트레이션 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0019] 필수 필드 누락");
char key[16];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0019] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
/* exec sql begin declare section */
#line 27 "app/online/au_ol_0019.pgc"
char h_key [ 16 ] ;
#line 28 "app/online/au_ol_0019.pgc"
long h_amount , h_fee ;
#line 29 "app/online/au_ol_0019.pgc"
int h_rate ;
/* exec sql end declare section */
#line 30 "app/online/au_ol_0019.pgc"
if (!amount_is_valid(amount) || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0019] 입력 검증 실패 amount=%ld date=%s",
amount, bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
long rate = 0;
tx_log(TX_LOG_INFO, "[AU_OL_0019] 승인 수수료 재계산 진입");
tx_buf_getlong(ctx->in, "RATEBP", &rate); /* basis point */
if (rate <= 0 || rate > 1000) rate = 100; /* 기본 1.00% */
h_rate = (int)rate;
strncpy(h_key, key, 15); h_key[15] = '\0';
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "select amount from au_ledger where key = $1 ",
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_long,&(h_amount),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);}
#line 40 "app/online/au_ol_0019.pgc"
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
h_fee = h_amount * h_rate / 10000;
/* 트랜잭션 시작 → 원장 반영 → 후속 서비스 연계 → 커밋 */
if (tx_begin() != TX_OK) {
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[AU_OL_0019] tx_begin 경고");
{ ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "update au_ledger set fee = $1 , upd_ts = now ( ) where key = $2 ",
ECPGt_long,&(h_fee),(long)1,(long)1,sizeof(long),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
ECPGt_char,(h_key),(long)16,(long)1,(16)*sizeof(char),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);}
#line 49 "app/online/au_ol_0019.pgc"
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AU_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100;
rc = au_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0019] 원장반영 실패 rc=%d", rc);
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0019 수수료");
tx_abort();
tx_return(ctx, rc, ctx->out);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 정산 영업일 = 거래일의 다음 영업일 */
if (date_next_business(bizdate, nextbiz) != 0) {
memcpy(nextbiz, bizdate, 8);
nextbiz[8] = '\0';
}
/* 후속 정산집계 서비스 연계 (레지스트리 문자열 디스패치) */
sub_in = tx_buf_alloc();
sub_out = tx_buf_alloc();
if (sub_in && sub_out) {
tx_buf_sets(sub_in, "MERCHID", merch);
tx_buf_sets(sub_in, "BIZDATE", nextbiz);
tx_buf_setlong(sub_in, "AMOUNT", amount);
rc = tx_call("AU_POST", sub_in, sub_out);
if (rc != TX_OK)
tx_log(TX_LOG_WARN, "[AU_OL_0019] 후속연계 경고 rc=%d", rc);
}
tx_buf_free(sub_in);
tx_buf_free(sub_out);
/* 교차 검증: 당일 합계 재계산 */
if (au_rec_sum(bizdate, &daysum) != TX_OK)
daysum = 0;
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYSUM", daysum);
tx_log(TX_LOG_INFO, "[AU_OL_0019] 완료 key=%s 당일합계=%ld", key, daysum);
tx_buf_setlong(ctx->out, "AMOUNT", h_amount);
tx_buf_setlong(ctx->out, "RATEBP", h_rate);
tx_buf_setlong(ctx->out, "FEE", h_fee);
tx_log(TX_LOG_INFO, "[AU_OL_0019] 수수료 재계산 fee=%ld(rate=%dbp)", h_fee, h_rate);
tx_return(ctx, TX_OK, ctx->out);
}

View file

@ -1,14 +1,15 @@
/* @tier hard @module au @transform authorization-online */
/* @tier medium @module au @transform authorization-online */
/*
* au_ol_0019.pgc - 승인한도 온라인 서비스 (AU_OL_0019) [tier=hard]
* au_ol_0019.pgc - 승인 수수료 재계산(요율 적용 UPDATE) (AU_OL_0019) [tier=medium]
*
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 au 표준 DBIO 를
* 통해 처리한 뒤 응답 TXBUF 를 구성한다. (ATMI void SVC(TPSVCINFO*) 대응)
* TxCore TX_SERVICE 엔트리. 요청 TXBUF 를 검증하고 임베디드 SQL / 표준
* DBIO / tx_call 로 처리한 뒤 응답 TXBUF 를 구성한다.
*/
#include <stdio.h>
#include <string.h>
#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "au_core.h"
@ -16,83 +17,48 @@ EXEC SQL INCLUDE sqlca;
TX_SERVICE(AU_OL_0019, ctx)
{
au_rec_t rec;
char key[16], merch[16], bizdate[16], nextbiz[9];
long amount = 0, daysum = 0;
int rc;
TXBUF *sub_in;
TXBUF *sub_out;
tx_log(TX_LOG_INFO, "[AU_OL_0019] 승인한도 트랜잭션 오케스트레이션 진입");
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK ||
tx_buf_get(ctx->in, "MERCHID", merch, sizeof(merch)) != TX_OK ||
tx_buf_get(ctx->in, "BIZDATE", bizdate, sizeof(bizdate)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0019] 필수 필드 누락");
char key[16];
if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0019] KEY 누락");
tx_return(ctx, TX_EINVAL, ctx->out);
return;
}
tx_buf_getlong(ctx->in, "AMOUNT", &amount);
EXEC SQL BEGIN DECLARE SECTION;
char h_key[16];
long h_amount, h_fee;
int h_rate;
EXEC SQL END DECLARE SECTION;
if (!amount_is_valid(amount) || !date_is_valid(bizdate)) {
tx_log(TX_LOG_WARN, "[AU_OL_0019] 입력 검증 실패 amount=%ld date=%s",
amount, bizdate);
tx_return(ctx, TX_EINVAL, ctx->out);
long rate = 0;
tx_log(TX_LOG_INFO, "[AU_OL_0019] 승인 수수료 재계산 진입");
tx_buf_getlong(ctx->in, "RATEBP", &rate); /* basis point */
if (rate <= 0 || rate > 1000) rate = 100; /* 기본 1.00% */
h_rate = (int)rate;
strncpy(h_key, key, 15); h_key[15] = '\0';
EXEC SQL SELECT amount INTO :h_amount FROM au_ledger WHERE key = :h_key;
if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
tx_return(ctx, TX_ENOENT, ctx->out);
return;
}
h_fee = h_amount * h_rate / 10000;
/* 트랜잭션 시작 → 원장 반영 → 후속 서비스 연계 → 커밋 */
if (tx_begin() != TX_OK) {
tx_return(ctx, TX_FAIL, ctx->out);
return;
}
memset(&rec, 0, sizeof(rec));
strncpy(rec.key, key, sizeof(rec.key) - 1);
strncpy(rec.merch_id, merch, sizeof(rec.merch_id) - 1);
strncpy(rec.biz_date, bizdate, sizeof(rec.biz_date) - 1);
strncpy(rec.status, AU_ST_RECV, sizeof(rec.status) - 1);
rec.amount = amount;
rec.fee = amount / 100;
rc = au_rec_insert(&rec);
if (rc != TX_OK) {
tx_log(TX_LOG_ERROR, "[AU_OL_0019] 원장반영 실패 rc=%d", rc);
if (tx_begin() != TX_OK) tx_log(TX_LOG_WARN, "[AU_OL_0019] tx_begin 경고");
EXEC SQL UPDATE au_ledger SET fee = :h_fee, upd_ts = now()
WHERE key = :h_key;
if (sqlca.sqlcode != TX_SQL_OK) {
TX_DBIO_LOG_ERR("au_ol_0019 수수료");
tx_abort();
tx_return(ctx, rc, ctx->out);
tx_return(ctx, TX_EDB, ctx->out);
return;
}
/* 정산 영업일 = 거래일의 다음 영업일 */
if (date_next_business(bizdate, nextbiz) != 0) {
memcpy(nextbiz, bizdate, 8);
nextbiz[8] = '\0';
}
/* 후속 정산집계 서비스 연계 (레지스트리 문자열 디스패치) */
sub_in = tx_buf_alloc();
sub_out = tx_buf_alloc();
if (sub_in && sub_out) {
tx_buf_sets(sub_in, "MERCHID", merch);
tx_buf_sets(sub_in, "BIZDATE", nextbiz);
tx_buf_setlong(sub_in, "AMOUNT", amount);
rc = tx_call("AU_POST", sub_in, sub_out);
if (rc != TX_OK)
tx_log(TX_LOG_WARN, "[AU_OL_0019] 후속연계 경고 rc=%d", rc);
}
tx_buf_free(sub_in);
tx_buf_free(sub_out);
/* 교차 검증: 당일 합계 재계산 */
if (au_rec_sum(bizdate, &daysum) != TX_OK)
daysum = 0;
tx_commit();
tx_buf_reset(ctx->out);
tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
tx_buf_sets(ctx->out, "KEY", key);
tx_buf_setlong(ctx->out, "DAYSUM", daysum);
tx_log(TX_LOG_INFO, "[AU_OL_0019] 완료 key=%s 당일합계=%ld", key, daysum);
tx_buf_setlong(ctx->out, "AMOUNT", h_amount);
tx_buf_setlong(ctx->out, "RATEBP", h_rate);
tx_buf_setlong(ctx->out, "FEE", h_fee);
tx_log(TX_LOG_INFO, "[AU_OL_0019] 수수료 재계산 fee=%ld(rate=%dbp)", h_fee, h_rate);
tx_return(ctx, TX_OK, ctx->out);
}

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