/*==========================================================================*/
/*  ACQUIRE.pc  -  매입 접수 온라인 서비스 (As-Is 원본, Oracle Pro*C)         */
/*--------------------------------------------------------------------------*/
/*  대상 : BC 매입시스템 / Tuxedo ATMI 서비스 ACQUIRE                          */
/*  DBMS : Oracle 19c   전처리 : Pro*C/C++ (proc)                            */
/*  ※ 이 파일은 **As-Is 역사 원본**이다. 현행 오픈스택 이식본은               */
/*     app/src/ac/svc/ACQUIRE.pgc (ECPG/PostgreSQL). 대조는                   */
/*     docs/ORACLE_PROVENANCE.md 참조. 컴파일 대상 아님(빌드 제외).           */
/*--------------------------------------------------------------------------*/
/*  변경이력                                                                  */
/*   1998.11.02  KIM K.H   최초작성 (신용승인 연계 매입)                       */
/*   2004.06.18  PARK J.S  체크카드 매입구분 추가, DECODE 요율분기             */
/*   2011.03.30  LEE S.W   원천징수(3.3%) 반영, 세금계산서 연계                */
/*   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);

/* 전역 FML 필드 ID (FLD.h 에서 생성) */
#include "acqfld.h"

EXEC SQL BEGIN DECLARE SECTION;
    VARCHAR   h_merch[16];
    VARCHAR   h_name[64];
    VARCHAR   h_status[2];
    VARCHAR   h_bizdate[9];      /* YYYYMMDD */
    VARCHAR   h_cardtype[2];     /* C=신용 K=체크 */
    long      h_amount;
    long      h_limit;
    long      h_daysum;
    long      h_daycnt;
    long      h_mdr_bps;
    long      h_fee;
    long      h_net;
    long      h_wht;             /* 원천징수액 */
    long      h_pid;
    long      h_grade;
EXEC SQL END DECLARE SECTION;

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

    userlog("ACQUIRE 진입: 매입 접수 요청");

    /* Pro*C 오류는 즉시 라벨분기 (전형적 레거시 패턴) */
    EXEC SQL WHENEVER SQLERROR GOTO sql_error;

    /* ---- 1) 요청 FML 파싱 -------------------------------------------- */
    Fget(fb, ACQ_MERCHANT, 0, merch,   (FLDLEN32 *)NULL);
    Fget(fb, ACQ_BIZDATE,  0, bizdate, (FLDLEN32 *)NULL);
    amount = Fvall(fb, ACQ_AMOUNT, 0);

    strcpy((char *)h_merch.arr, merch);   h_merch.len   = strlen(merch);
    strcpy((char *)h_bizdate.arr, bizdate); h_bizdate.len = strlen(bizdate);
    h_amount = amount;

    if (h_amount <= 0) {
        Fchg(fb, ACQ_RC, 0, (char *)"E101", 0L);
        tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
        return;
    }

    /* 영업일 미지정시 시스템일자 (Oracle SYSDATE) */
    if (h_bizdate.len == 0) {
        EXEC SQL SELECT TO_CHAR(SYSDATE,'YYYYMMDD') INTO :h_bizdate FROM DUAL;
    }

    /* ---- 2) 가맹점 마스터 조회 (NVL 로 널가드) ----------------------- */
    EXEC SQL
        SELECT m.name,
               NVL(m.status,'N'),
               NVL(m.daily_limit, 0),
               NVL(m.mdr_bps, 25),
               DECODE(m.risk_grade, 'A',1, 'B',2, 'C',3, 9)
          INTO :h_name, :h_status, :h_limit, :h_mdr_bps, :h_grade
          FROM merchant m
         WHERE m.merchant_id = :h_merch;

    if (strncmp((char *)h_status.arr, "A", 1) != 0) {
        userlog("ACQUIRE: 비활성 가맹점 %s status=%.1s", merch, h_status.arr);
        Fchg(fb, ACQ_RC, 0, (char *)"E203", 0L);
        tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
        return;
    }

    /* ---- 3) 당일 누적 매입 조회 (한도 점검용) ------------------------ */
    EXEC SQL
        SELECT COUNT(*), NVL(SUM(amount), 0)
          INTO :h_daycnt, :h_daysum
          FROM purchase
         WHERE merchant_id = :h_merch
           AND biz_date    = TO_DATE(:h_bizdate,'YYYYMMDD')
           AND status     <> 'C';

    if (h_daysum + h_amount > h_limit) {
        userlog("ACQUIRE: 일한도 초과 merch=%s sum=%ld+%ld > %ld",
                merch, h_daysum, h_amount, h_limit);
        Fchg(fb, ACQ_RC, 0, (char *)"E210", 0L);
        tpreturn(TPFAIL, 0, (char *)fb, 0L, 0L);
        return;
    }

    /* ---- 4) 수수료/원천/정산액 산출 (DECODE 카드구분 요율) ----------- */
    /*  카드종류는 승인원장 조인으로 (외부조인 (+) — 무승인 매입 허용)      */
    EXEC SQL
        SELECT NVL(a.card_type, 'C')
          INTO :h_cardtype
          FROM au_authorization a
         WHERE a.auth_id (+) = :h_pid;

    h_fee = h_amount * h_mdr_bps / 10000;
    /* 병의원/약국(원천징수 대상 업종)만 3.3% 원천 (DECODE 업종분기) */
    EXEC SQL
        SELECT DECODE(mcc.risk_level, 1, ROUND(:h_amount * 33 / 1000), 0)
          INTO :h_wht
          FROM mm_merch_mcc mm, mm_mcc mcc
         WHERE mm.merchant_id = :h_merch
           AND mcc.mcc        = mm.mcc
           AND ROWNUM = 1;

    h_net = h_amount - h_fee - h_wht;

    /* ---- 5) 매입원장 채번 및 적재 (시퀀스 .NEXTVAL) ------------------ */
    EXEC SQL SELECT purchase_seq.NEXTVAL INTO :h_pid FROM DUAL;

    EXEC SQL
        INSERT INTO purchase
               (purchase_id, merchant_id, amount, fee, net, wht,
                status, biz_date, created_at)
        VALUES (:h_pid, :h_merch, :h_amount, :h_fee, :h_net, :h_wht,
                'A', TO_DATE(:h_bizdate,'YYYYMMDD'), SYSDATE);

    EXEC SQL
        INSERT INTO approval (approval_id, purchase_id, approved, approved_at)
        VALUES (approval_seq.NEXTVAL, :h_pid, 'Y', SYSDATE);

    /* ---- 6) 정산 PL/SQL 패키지 호출 (묶음 정산 연계) ----------------- */
    EXEC SQL EXECUTE
        BEGIN
            pkg_settle.acquire_post(:h_pid, :h_merch, :h_amount, :h_fee, :h_net);
        END;
    END-EXEC;

    /* ---- 7) 커밋 및 응답 -------------------------------------------- */
    EXEC SQL COMMIT WORK;

    Fchg(fb, ACQ_PURCHASE_ID, 0, (char *)&h_pid, 0L);
    Fchg(fb, ACQ_FEE,         0, (char *)&h_fee, 0L);
    Fchg(fb, ACQ_NET,         0, (char *)&h_net, 0L);
    Fchg(fb, ACQ_STATUS,      0, (char *)"S", 0L);

    userlog("ACQUIRE 완료: pid=%ld fee=%ld wht=%ld net=%ld", h_pid, h_fee, h_wht, h_net);
    tpreturn(TPSUCCESS, 0, (char *)fb, 0L, 0L);
    return;

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