/*==========================================================================*/
/*  SETTLE.pc  -  정산확정 온라인 서비스 (As-Is 원본, Oracle Pro*C)           */
/*--------------------------------------------------------------------------*/
/*  대상 : BC 매입시스템 / Tuxedo ATMI 서비스 SETTLE                          */
/*  DBMS : Oracle 19c   전처리 : Pro*C/C++ (proc)                            */
/*  기능 : 매입건 정산 확정 — 정산원장(settlement) 채번·적재 + 원장 기표.      */
/*  ※ 이 파일은 **As-Is 역사 원본**이다. 현행 오픈스택 이식본은               */
/*     app/src/st/svc/SETTLE.pgc (ECPG/PostgreSQL). 컴파일 제외.             */
/*--------------------------------------------------------------------------*/
/*  변경이력                                                                  */
/*   2000.03.21  PARK J.S  최초작성 (정산확정 원장적재)                        */
/*   2006.09.14  HAN Y.J   가맹점 지급주기(D+n) DECODE 반영                    */
/*   2012.05.08  LEE S.W   정산 중복확정 방지, ROWNUM 최근건 조회              */
/*   2019.09.01  CHOI H.W  Oracle 11g -> 19c, 시퀀스/커밋 표준화              */
/*==========================================================================*/
#include <stdio.h>
#include <string.h>
#include <atmi.h>
#include <fml32.h>
#include <userlog.h>

EXEC SQL INCLUDE sqlca;
EXEC SQL INCLUDE oraca;
EXEC ORACLE OPTION (ORACA=YES);

#include "stfld.h"

EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR   h_merch[64];
    VARCHAR   h_bizdate[9];       /* YYYYMMDD */
    VARCHAR   h_pdate[9];
    VARCHAR   h_pstat[2];
    VARCHAR   h_paycyc[4];        /* 지급주기 코드 */
    long      h_pid;
    long      h_sid;
    long      h_amount;
    long      h_fee;
    long      h_net;
    long      h_dcnt;
    long      h_dup;
    long      h_addday;
EXEC SQL END DECLARE SECTION;

/*--------------------------------------------------------------------------*/
/*  SETTLE  -  Tuxedo 서비스 엔트리                                           */
/*--------------------------------------------------------------------------*/
void SETTLE(TPSVCINFO *rqst)
{
    FBFR32 *fb = (FBFR32 *)rqst->data;
    char    merch[64], bizdate[9];

    userlog("SETTLE 진입: 정산 확정");
    EXEC SQL WHENEVER SQLERROR GOTO sql_error;

    /* ---- 1) 요청 FML 파싱 -------------------------------------------- */
    h_pid = Fvall(fb, ST_PURCHASE_ID, 0);
    h_net = Fvall(fb, ST_NET, 0);
    Fget(fb, ST_MERCHANT, 0, merch,   (FLDLEN32 *)NULL);
    Fget(fb, ST_BIZDATE,  0, bizdate, (FLDLEN32 *)NULL);
    strcpy((char *)h_merch.arr, merch);     h_merch.len   = strlen(merch);
    strcpy((char *)h_bizdate.arr, bizdate); h_bizdate.len = strlen(bizdate);
    if (h_bizdate.len == 0) {
        EXEC SQL SELECT TO_CHAR(SYSDATE,'YYYYMMDD') INTO :h_bizdate FROM DUAL;
    }
    if (h_pid <= 0) {
        userlog("SETTLE: 매입 ID 필수 pid=%ld", h_pid);
        Fchg(fb, ST_RC, 0, (char *)"E802", 0L);
        tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
        return;
    }

    /* ---- 2) 매입 상태/금액 확인 + 정산액 보정 (NVL/DECODE) ----------- */
    EXEC SQL
        SELECT NVL(p.amount,0), NVL(p.fee,0), NVL(p.net,:h_net),
               NVL(p.status,'A')
          INTO :h_amount, :h_fee, :h_net, :h_pstat
          FROM purchase p
         WHERE p.purchase_id = :h_pid;
    if (sqlca.sqlcode == 1403) {
        h_amount = Fvall(fb, ST_AMOUNT, 0);
        userlog("SETTLE: 미커밋 매입 pid=%ld — 전문 net=%ld 사용", h_pid, h_net);
    }

    /* ---- 3) 중복확정 방지: 동일 매입 확정 정산 존재여부 (ROWNUM) ---- */
    EXEC SQL
        SELECT NVL(MAX(settlement_id),0)
          INTO :h_dup
          FROM settlement
         WHERE purchase_id = :h_pid
           AND status = 'SETTLED'
           AND ROWNUM = 1;
    if (h_dup > 0) {
        userlog("SETTLE: 이미 확정된 정산 pid=%ld sid=%ld — 스킵", h_pid, h_dup);
        Fchg(fb, ST_SETTLE_ID, 0, (char *)&h_dup, 0L);
        Fchg(fb, ST_STATUS, 0, (char *)"D", 0L);
        EXEC SQL COMMIT WORK;
        tpreturn(TPSUCCESS, 0, (char *)fb, 0L, 0L);
        return;
    }

    /* ---- 4) 가맹점 지급주기 조회 → 지급예정일 산정 (DECODE D+n) ----- */
    EXEC SQL
        SELECT NVL(paycycle,'D1'),
               DECODE(NVL(paycycle,'D1'), 'D0',0, 'D1',1, 'D2',2, 'W1',7, 1)
          INTO :h_paycyc, :h_addday
          FROM merchant
         WHERE merchant_id = :h_merch;
    EXEC SQL
        SELECT TO_CHAR(TO_DATE(:h_bizdate,'YYYYMMDD') + :h_addday,'YYYYMMDD')
          INTO :h_pdate
          FROM DUAL;

    /* ---- 5) 본처리: 정산원장 채번(.NEXTVAL) 및 적재 ----------------- */
    EXEC SQL SELECT settlement_seq.NEXTVAL INTO :h_sid FROM DUAL;
    EXEC SQL
        INSERT INTO settlement
               (settlement_id, purchase_id, merchant_id, net,
                biz_date, pay_date, status, created_at)
        VALUES (:h_sid, :h_pid, :h_merch, :h_net,
                TO_DATE(:h_bizdate,'YYYYMMDD'),
                TO_DATE(:h_pdate,'YYYYMMDD'), 'SETTLED', SYSDATE);

    /* ---- 6) 정산원장 기표 (ledger SETTLE 엔트리) ------------------- */
    EXEC SQL
        INSERT INTO ledger
               (ledger_id, purchase_id, entry_type, amount, biz_date, posted_at)
        VALUES (ledger_seq.NEXTVAL, :h_pid, 'SETTLE', :h_net,
                TO_DATE(:h_bizdate,'YYYYMMDD'), SYSDATE);

    /* ---- 7) 매입 상태 정산완료 전이 ------------------------------- */
    EXEC SQL
        UPDATE purchase
           SET status = 'S', settled_at = SYSDATE
         WHERE purchase_id = :h_pid
           AND status <> 'C';

    /* ---- 8) 정산확정-수수료산출 연계 (PL/SQL 정산 패키지) ---------- */
    EXEC SQL EXECUTE
        BEGIN
            pkg_settle.settle_confirm(:h_sid, :h_pid, :h_merch, :h_net);
        END;
    END-EXEC;

    EXEC SQL COMMIT WORK;

    Fchg(fb, ST_SETTLE_ID, 0, (char *)&h_sid, 0L);
    Fchg(fb, ST_NET,       0, (char *)&h_net, 0L);
    Fchg(fb, ST_STATUS,    0, (char *)"S", 0L);
    userlog("SETTLE 완료: pid=%ld sid=%ld net=%ld paydate=%.8s",
            h_pid, h_sid, h_net, h_pdate.arr);
    tpreturn(TPSUCCESS, 0, (char *)fb, 0L, 0L);
    return;

sql_error:
    userlog("SETTLE SQL 오류: %.70s (sqlcode=%ld)",
            sqlca.sqlerrm.sqlerrmc, sqlca.sqlcode);
    EXEC SQL WHENEVER SQLERROR CONTINUE;
    EXEC SQL ROLLBACK WORK;
    Fchg(fb, ST_RC, 0, (char *)"E900", 0L);
    tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
    return;
}
