/* * purchase_dbio.pgc - 매입/정산 DBIO (ECPG 임베디드 SQL) * * Pro*C 상당의 PostgreSQL ECPG 로 매입/승인/정산 테이블에 대한 * INSERT/SELECT/UPDATE 를 캡슐화한다. 서비스/배치는 이 함수만 호출. */ #include #include #include "txcore.h" #include "txcore_dbio.h" #include "purchase_dbio.h" EXEC SQL INCLUDE sqlca; /* 컴파일 시 접속하지 않지만, 실환경 접속 규약을 그대로 둔다. */ int dbio_connect(const char *target) { EXEC SQL BEGIN DECLARE SECTION; const char *h_target; EXEC SQL END DECLARE SECTION; h_target = (target && target[0]) ? target : "acquire@localhost"; EXEC SQL CONNECT TO :h_target; if (sqlca.sqlcode != TX_SQL_OK) { TX_DBIO_LOG_ERR("CONNECT"); return TX_EDB; } tx_log(TX_LOG_INFO, "DB 접속 완료 target=%s", h_target); return TX_OK; } int dbio_disconnect(void) { EXEC SQL DISCONNECT CURRENT; return TX_OK; } int purchase_insert(const purchase_rec_t *rec) { EXEC SQL BEGIN DECLARE SECTION; char h_appr_no[10]; char h_merch_id[16]; char h_card_no[17]; long h_amount; char h_txn_date[9]; char h_status[2]; EXEC SQL END DECLARE SECTION; if (!rec) return TX_EINVAL; strncpy(h_appr_no, rec->appr_no, sizeof(h_appr_no) - 1); h_appr_no[sizeof(h_appr_no) - 1] = '\0'; strncpy(h_merch_id, rec->merch_id, sizeof(h_merch_id) - 1); h_merch_id[sizeof(h_merch_id) - 1] = '\0'; strncpy(h_card_no, rec->card_no, sizeof(h_card_no) - 1); h_card_no[sizeof(h_card_no) - 1] = '\0'; strncpy(h_txn_date, rec->txn_date, sizeof(h_txn_date) - 1); h_txn_date[sizeof(h_txn_date) - 1] = '\0'; strncpy(h_status, rec->status, sizeof(h_status) - 1); h_status[sizeof(h_status) - 1] = '\0'; h_amount = rec->amount; EXEC SQL INSERT INTO purchase (appr_no, merch_id, card_no, amount, txn_date, status) VALUES (:h_appr_no, :h_merch_id, :h_card_no, :h_amount, :h_txn_date, :h_status); if (sqlca.sqlcode != TX_SQL_OK) { TX_DBIO_LOG_ERR("purchase_insert"); return TX_EDB; } return TX_OK; } int purchase_select_by_appr(const char *appr_no, purchase_rec_t *out) { EXEC SQL BEGIN DECLARE SECTION; char h_appr_no[10]; char h_merch_id[16]; char h_card_no[17]; long h_amount; char h_txn_date[9]; char h_status[2]; EXEC SQL END DECLARE SECTION; if (!appr_no || !out) return TX_EINVAL; strncpy(h_appr_no, appr_no, sizeof(h_appr_no) - 1); h_appr_no[sizeof(h_appr_no) - 1] = '\0'; EXEC SQL SELECT merch_id, card_no, amount, txn_date, status INTO :h_merch_id, :h_card_no, :h_amount, :h_txn_date, :h_status FROM purchase WHERE appr_no = :h_appr_no; if (sqlca.sqlcode == TX_SQL_NOTFOUND) return TX_ENOENT; if (sqlca.sqlcode != TX_SQL_OK) { TX_DBIO_LOG_ERR("purchase_select_by_appr"); return TX_EDB; } memset(out, 0, sizeof(*out)); strncpy(out->appr_no, h_appr_no, sizeof(out->appr_no) - 1); strncpy(out->merch_id, h_merch_id, sizeof(out->merch_id) - 1); strncpy(out->card_no, h_card_no, sizeof(out->card_no) - 1); strncpy(out->txn_date, h_txn_date, sizeof(out->txn_date) - 1); strncpy(out->status, h_status, sizeof(out->status) - 1); out->amount = h_amount; return TX_OK; } int purchase_update_status(const char *appr_no, const char *status) { EXEC SQL BEGIN DECLARE SECTION; char h_appr_no[10]; char h_status[2]; EXEC SQL END DECLARE SECTION; if (!appr_no || !status) return TX_EINVAL; strncpy(h_appr_no, appr_no, sizeof(h_appr_no) - 1); h_appr_no[sizeof(h_appr_no) - 1] = '\0'; strncpy(h_status, status, sizeof(h_status) - 1); h_status[sizeof(h_status) - 1] = '\0'; EXEC SQL UPDATE purchase SET status = :h_status, upd_ts = now() WHERE appr_no = :h_appr_no; if (sqlca.sqlcode != TX_SQL_OK) { TX_DBIO_LOG_ERR("purchase_update_status"); return TX_EDB; } if (sqlca.sqlerrd[2] == 0) /* 갱신된 행 수 0 = 대상 없음 */ return TX_ENOENT; return TX_OK; } int approval_match(const char *appr_no, long amount) { EXEC SQL BEGIN DECLARE SECTION; char h_appr_no[10]; long h_amount; int h_cnt; EXEC SQL END DECLARE SECTION; if (!appr_no) return TX_EINVAL; strncpy(h_appr_no, appr_no, sizeof(h_appr_no) - 1); h_appr_no[sizeof(h_appr_no) - 1] = '\0'; h_amount = amount; EXEC SQL SELECT count(*) INTO :h_cnt FROM approval WHERE appr_no = :h_appr_no AND amount = :h_amount AND status = 'A'; if (sqlca.sqlcode != TX_SQL_OK) { TX_DBIO_LOG_ERR("approval_match"); return TX_EDB; } return (h_cnt > 0) ? TX_OK : TX_ENOENT; } int settlement_accumulate(const char *merch_id, const char *biz_date, long amount) { EXEC SQL BEGIN DECLARE SECTION; char h_merch_id[16]; char h_biz_date[9]; long h_amount; EXEC SQL END DECLARE SECTION; if (!merch_id || !biz_date) return TX_EINVAL; strncpy(h_merch_id, merch_id, sizeof(h_merch_id) - 1); h_merch_id[sizeof(h_merch_id) - 1] = '\0'; strncpy(h_biz_date, biz_date, sizeof(h_biz_date) - 1); h_biz_date[sizeof(h_biz_date) - 1] = '\0'; h_amount = amount; /* 가맹점/영업일 단위 정산집계 upsert */ EXEC SQL INSERT INTO settlement (merch_id, biz_date, total_amount, txn_cnt) VALUES (:h_merch_id, :h_biz_date, :h_amount, 1) ON CONFLICT (merch_id, biz_date) DO UPDATE SET total_amount = settlement.total_amount + EXCLUDED.total_amount, txn_cnt = settlement.txn_cnt + 1; if (sqlca.sqlcode != TX_SQL_OK) { TX_DBIO_LOG_ERR("settlement_accumulate"); return TX_EDB; } return TX_OK; }