/*==========================================================================*/
/*  AUTH_APPROVE.pc  -  승인확정 온라인 서비스 (As-Is 원본, Oracle Pro*C)     */
/*--------------------------------------------------------------------------*/
/*  대상 : BC 매입시스템 / Tuxedo ATMI 서비스 AUTH_APPROVE                     */
/*  DBMS : Oracle 19c   전처리 : Pro*C/C++ (proc)                            */
/*  기능 : 승인 확정(pending->approved) — 원장 상태전이 + 카드 한도차감        */
/*  ※ 이 파일은 **As-Is 역사 원본**이다. 현행 오픈스택 이식본은               */
/*     app/src/au/svc/AUTH_APPROVE.pgc (ECPG/PostgreSQL). 컴파일 제외.        */
/*--------------------------------------------------------------------------*/
/*  변경이력                                                                  */
/*   1999.05.12  KIM K.H   최초작성 (승인원장 확정전이)                        */
/*   2003.10.07  YOON D.H  블랙리스트/velocity 룰 추가, DECODE 등급분기        */
/*   2010.08.24  LEE S.W   당일 상태분포 재집계, au_summary 연계               */
/*   2016.02.19  JANG M.K  이상거래 점수(au_fraud_log) 반영                    */
/*   2019.09.01  CHOI H.W  Oracle 11g -> 19c, CHAR->VARCHAR2 정비             */
/*==========================================================================*/
#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 "aufld.h"

EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR   h_card[24];
    VARCHAR   h_merch[64];
    VARCHAR   h_bizdate[9];       /* YYYYMMDD */
    VARCHAR   h_status[2];
    VARCHAR   h_cstat[16];
    long      h_auth;
    long      h_amount;
    long      h_delta;
    long      h_cnt;
    long      h_sum;
    long      h_appr;
    long      h_black;
    long      h_vel;
    long      h_risk;
    long      h_grade;
    long      h_mdr_bps;
    long      h_fee;
    long      h_vat;
    long      h_dlim;
    long      h_avail;
    long      h_led;
EXEC SQL END DECLARE SECTION;

/*--------------------------------------------------------------------------*/
/*  AUTH_APPROVE  -  Tuxedo 서비스 엔트리                                      */
/*--------------------------------------------------------------------------*/
void AUTH_APPROVE(TPSVCINFO *rqst)
{
    FBFR32 *fb = (FBFR32 *)rqst->data;
    char    card[24], merch[64];
    long    rc = 0;
    TPINIT *tpi = (TPINIT *)NULL;

    userlog("AUTH_APPROVE 진입: 승인 확정(pending->approved)");
    EXEC SQL WHENEVER SQLERROR GOTO sql_error;

    /* ---- 1) 요청 FML 파싱 -------------------------------------------- */
    h_auth = Fvall(fb, AU_AUTH_ID, 0);
    if (h_auth <= 0) {
        userlog("AUTH_APPROVE: 식별자 범위오류 auth_id=%ld", h_auth);
        Fchg(fb, AU_RC, 0, (char *)"E801", 0L);
        tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
        return;
    }
    h_delta = Fvall(fb, AU_DELTA, 0);
    if (h_delta < 0) h_delta = -h_delta;

    /* ---- 2) 대상 승인건 조회 (현재상태/금액/카드/영업일) -------------- */
    /*  무마스터 승인 허용: 카드마스터는 외부조인 (+) 으로 등급만 취득       */
    EXEC SQL
        SELECT a.status,
               NVL(a.amount, 0),
               NVL(a.card_no, ' '),
               TO_CHAR(NVL(a.biz_date, SYSDATE),'YYYYMMDD'),
               DECODE(NVL(c.risk_grade,'B'), 'A',1, 'B',2, 'C',3, 9)
          INTO :h_status, :h_amount, :h_card, :h_bizdate, :h_grade
          FROM au_authorization a, card_master c
         WHERE a.auth_id = :h_auth
           AND c.card_no (+) = a.card_no;

    if (sqlca.sqlcode == 1403) {
        userlog("AUTH_APPROVE: 대상 승인건 없음 auth_id=%ld", h_auth);
        Fchg(fb, AU_RC, 0, (char *)"E831", 0L);
        tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
        return;
    }
    strcpy(card, (char *)h_card.arr);

    /* ---- 3) 전이 가능여부 분기 (허용 상태에서만 A 로 전이) ------------ */
    if (strncmp((char *)h_status.arr, "A", 1) != 0 &&
        strncmp((char *)h_status.arr, "P", 1) != 0) {
        userlog("AUTH_APPROVE: 상태전이 불가 cur=%.1s auth_id=%ld",
                h_status.arr, h_auth);
        Fchg(fb, AU_RC, 0, (char *)"E833", 0L);
        tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
        return;
    }

    /* ---- 4) 본처리: 원장 상태전이 (+금액조정 델타) ------------------- */
    EXEC SQL
        UPDATE au_authorization
           SET status = 'A', updated_at = SYSDATE
         WHERE auth_id = :h_auth
           AND status IN ('A','P');
    if (sqlca.sqlerrd[2] == 0) {
        userlog("AUTH_APPROVE: 반영건수 0 (경합/이미전이) auth_id=%ld", h_auth);
        Fchg(fb, AU_RC, 0, (char *)"E835", 0L);
        EXEC SQL ROLLBACK WORK;
        tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
        return;
    }
    if (h_delta > 0) {
        EXEC SQL
            UPDATE au_authorization
               SET amount = amount + :h_delta, updated_at = SYSDATE
             WHERE auth_id = :h_auth;
        h_amount += h_delta;
    }

    /* ---- 5) 카드 당일 상태분포 재집계 (한도판정 기초) --------------- */
    EXEC SQL
        SELECT COUNT(*), NVL(SUM(amount),0),
               NVL(SUM(DECODE(status,'A',1,0)),0)
          INTO :h_cnt, :h_sum, :h_appr
          FROM au_authorization
         WHERE card_no = :h_card
           AND biz_date = TO_DATE(:h_bizdate,'YYYYMMDD');

    /* ---- 6) 업무규칙: 블랙리스트/카드상태/velocity/부정점수 --------- */
    EXEC SQL
        SELECT COUNT(*) INTO :h_black
          FROM au_blacklist
         WHERE card_no = :h_card;
    if (h_black > 0) { rc = 91; userlog("AUTH_APPROVE: 블랙리스트 적중 card=%s", card); }

    EXEC SQL
        SELECT NVL(MAX(status),'NONE'), NVL(MAX(avail_limit),0)
          INTO :h_cstat, :h_avail
          FROM card_limit
         WHERE card_no = :h_card;
    if (strncmp((char *)h_cstat.arr, "ACTIVE", 6) != 0 &&
        strncmp((char *)h_cstat.arr, "NONE", 4) != 0) {
        if (rc == 0) rc = 92;
        userlog("AUTH_APPROVE: 카드상태 비정상 card=%s status=%.8s", card, h_cstat.arr);
    }

    EXEC SQL
        SELECT COUNT(*) INTO :h_vel
          FROM au_authorization
         WHERE card_no = :h_card
           AND created_at > SYSDATE - 1/24;
    if (h_vel >= 10) { if (rc == 0) rc = 93;
        userlog("AUTH_APPROVE: velocity 경보 card=%s 1시간 %ld건", card, h_vel); }

    EXEC SQL
        SELECT NVL(MAX(score),0) INTO :h_risk
          FROM au_fraud_log
         WHERE card_no = :h_card
           AND ROWNUM <= 100;
    if (h_risk >= 90) userlog("AUTH_APPROVE: 고위험 카드 card=%s 최고점=%ld", card, h_risk);

    /* ---- 7) 상태전이 이력 적재 (감사원장, 시퀀스 .NEXTVAL 채번) ----- */
    EXEC SQL SELECT au_audit_seq.NEXTVAL INTO :h_led FROM DUAL;
    EXEC SQL
        INSERT INTO au_audit
               (audit_id, auth_id, card_no, from_status, to_status,
                amount, audit_rc, created_at)
        VALUES (:h_led, :h_auth, :h_card, :h_status, 'A',
                :h_amount, :rc, SYSDATE);

    /* ---- 8) 가맹점 당일 승인 집계 (au_summary upsert, PL/SQL) ------ */
    Fget(fb, AU_MERCHANT, 0, merch, (FLDLEN32 *)NULL);
    strcpy((char *)h_merch.arr, merch); h_merch.len = strlen(merch);
    if (h_merch.len > 0) {
        EXEC SQL
            SELECT COUNT(*),
                   NVL(SUM(DECODE(status,'A',1,0)),0),
                   NVL(SUM(amount),0)
              INTO :h_cnt, :h_appr, :h_sum
              FROM au_authorization
             WHERE merchant_id = :h_merch
               AND biz_date = TO_DATE(:h_bizdate,'YYYYMMDD');
        EXEC SQL EXECUTE
            BEGIN
                pkg_settle.upsert_auth_summary(:h_merch, :h_bizdate,
                                               :h_cnt, :h_appr, :h_sum);
            END;
        END-EXEC;
    }

    /* ---- 9) 정산 참고치: MDR 수수료/부가세 (DECODE 요율) ------------ */
    EXEC SQL
        SELECT NVL(m.mdr_bps, 25) INTO :h_mdr_bps
          FROM merchant m
         WHERE m.merchant_id = :h_merch;
    h_fee = ROUND(h_amount * h_mdr_bps / 10000);
    h_vat = ROUND(h_fee / 10);

    /* ---- 10) 업무체인: 승인확정 한도차감 (LIMIT_DEC PL/SQL 패키지) -- */
    EXEC SQL EXECUTE
        BEGIN
            pkg_settle.limit_dec(:h_card, :h_amount, :h_avail);
        END;
    END-EXEC;

    EXEC SQL COMMIT WORK;

    Fchg(fb, AU_STATUS, 0, (char *)"A", 0L);
    Fchg(fb, AU_FEE,    0, (char *)&h_fee, 0L);
    Fchg(fb, AU_AVAIL,  0, (char *)&h_avail, 0L);
    Fchg(fb, AU_RC, 0, (char *)&rc, 0L);
    userlog("AUTH_APPROVE 완료: auth_id=%ld amt=%ld fee=%ld rc=%ld",
            h_auth, h_amount, h_fee, rc);
    tpreturn(TPSUCCESS, 0, (char *)fb, 0L, 0L);
    return;

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