/*
 * PAY_FILECANCEL.pgc - py (지급) 모듈 온라인 서비스 PAY_FILECANCEL.
 * 지급파일 취소: 확정(C) 전 파일만 취소 가능. 편성(F) 건을 승인(A)+file_id=0
 * 으로 되돌린 뒤 파일 헤더를 삭제한다. 확정/부재 파일은 사유코드로 거절.
 * 처리 구성: 입력검증 -> 마스터/정책 조회 -> 업무규칙 분기 -> 본처리 ->
 *            감사이력 적재 -> 집계 갱신 -> 예외보상 -> 응답 -> 로깅 [file].
 * Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
 */
#include "PAY_FILECANCEL.h"

void PAY_FILECANCEL(TPSVCINFO *p)
{
    UBFH *b = (UBFH *)p->data;
    EXEC SQL BEGIN DECLARE SECTION;
    long h_id2;
    char h_wfst[8];
    long h_whcnt;
    long h_whamt;
    long h_wrcnt;
    long h_wramt;
    long h_waff;
    long h_wnew;
    char h_wfname[64];
    char h_wfdate[16];
    char h_wdate[16];
    char h_lvl[4];
    char h_amsg[256];
    long h_wa1;
    long h_wa2;
    long h_wa3;
    long h_wz1;
    long h_wz2;
    long h_wz3;
    EXEC SQL END DECLARE SECTION;

    /* 1) 입력 검증부 - 모든 입력 필드의 필수/범위/형식 검사 */
    h_id2 = getl(b, T_ID2);
    if (h_id2 <= 0) {
        setl(b, T_RC, 11);
        Bchg(b, T_MSG, 0, "식별자(ID)는 1 이상이어야 함", 0L);
        FAIL(b);
    }
    EXEC SQL SELECT to_char(current_date, 'YYYY-MM-DD') INTO :h_wdate;
    if (sqlca.sqlcode < 0) strcpy(h_wdate, "1970-01-01");
    /* 2) 마스터 조회부 - 지급파일 헤더 + 실제 편성 상세 대사 */
    EXEC SQL SELECT status, record_count, total_amount,
                    to_char(biz_date, 'YYYY-MM-DD'), file_name
        INTO :h_wfst, :h_whcnt, :h_whamt, :h_wfdate, :h_wfname
        FROM py_file WHERE file_id = :h_id2;
    if (sqlca.sqlcode == 100) {
        setl(b, T_RC, 40);
        Bchg(b, T_MSG, 0, "지급파일 헤더가 존재하지 않음", 0L);
        FAIL(b);
    }
    if (sqlca.sqlcode < 0) {
        setl(b, T_RC, 41);
        Bchg(b, T_MSG, 0, "지급파일 헤더 조회 오류", 0L);
        FAIL(b);
    }
    EXEC SQL SELECT count(*), coalesce(sum(net),0) INTO :h_wrcnt, :h_wramt
        FROM py_payout WHERE file_id = :h_id2;
    if (sqlca.sqlcode < 0) {
        setl(b, T_RC, 42);
        Bchg(b, T_MSG, 0, "편성 상세 집계 오류", 0L);
        FAIL(b);
    }
    userlog("PAY_FILECANCEL 진입: file=%ld status=%s 헤더=%ld/%ld 상세=%ld/%ld",
            h_id2, h_wfst, h_whcnt, h_whamt, h_wrcnt, h_wramt);
    /* 3) 업무규칙 분기부 - 파일 상태/정합 판정 (3분기) */
    if (strcmp(h_wfst, "C") == 0) {
        setl(b, T_RC, 43);
        Bchg(b, T_MSG, 0, "확정된 파일은 취소 불가", 0L);
        FAIL(b);
    } else if (strcmp(h_wfst, "G") != 0) {
        setl(b, T_RC, 44);
        Bchg(b, T_MSG, 0, "생성(G) 상태 파일만 취소 가능", 0L);
        FAIL(b);
    }
    /* 4) 본처리부 - 편성건 승인 복원 후 헤더 삭제 */
    EXEC SQL UPDATE py_payout SET status = 'A', file_id = 0, updated_at = now()
        WHERE file_id = :h_id2 AND status = 'F';
    if (sqlca.sqlcode < 0) {
        setl(b, T_RC, 50);
        Bchg(b, T_MSG, 0, "편성 지급건 승인 복원 실패", 0L);
        FAIL(b);
    }
    h_waff = sqlca.sqlerrd[2];
    EXEC SQL DELETE FROM py_file WHERE file_id = :h_id2 AND status = 'G';
    if (sqlca.sqlcode < 0) {
        setl(b, T_RC, 51);
        Bchg(b, T_MSG, 0, "지급파일 헤더 삭제 실패", 0L);
        FAIL(b);
    }
    h_wnew = h_id2;
    strcpy(h_lvl, "I");
    snprintf(h_amsg, sizeof(h_amsg), "%s file=%ld 상세=%ld건 %ld원 반영=%ld", "PAY_FILECANCEL", h_wnew, h_wrcnt, h_wramt, h_waff);
    EXEC SQL INSERT INTO cm_log (log_id, svc_name, log_level, msg, biz_date)
        VALUES (nextval('cm_log_seq'), 'PAY_FILECANCEL', :h_lvl, :h_amsg, :h_wdate);
    if (sqlca.sqlcode < 0) {
        setl(b, T_RC, 92);
        Bchg(b, T_MSG, 0, "감사로그(cm_log) 적재 실패 - 처리 롤백", 0L);
        FAIL(b);
    }
    /* 6) 집계/요약 갱신부 - 당일 지급파일 전체 현황 재집계 */
    EXEC SQL SELECT count(*), coalesce(sum(total_amount),0) INTO :h_wa1, :h_wa2
        FROM py_file WHERE biz_date = :h_wdate;
    if (sqlca.sqlcode < 0) {
        setl(b, T_RC, 61);
        Bchg(b, T_MSG, 0, "당일 파일 현황 재집계 실패", 0L);
        FAIL(b);
    }
    EXEC SQL SELECT count(*) INTO :h_wa3 FROM py_payout
        WHERE biz_date = :h_wdate AND status = 'F';
    if (sqlca.sqlcode < 0) h_wa3 = 0;
    if (h_wa1 > 0 && h_wa3 > h_wa1) {
        userlog("%s 편성 건수 초과: 기준=%ld 실적=%ld", "PAY_FILECANCEL", h_wa1, h_wa3);
    }
    /* 8) 응답부 */
    setl(b, T_COUNT, h_wrcnt);
    if (Bpres(b, T_RC, 0) == 0) setl(b, T_RC, 0);
    userlog("PAY_FILECANCEL 완료: file=%ld 상세=%ld건 %ld원", h_wnew, h_wrcnt, h_wramt);
    /* 7) 예외/보상 점검부 - 당일 지급 원장 사후 정합 확인 */
    EXEC SQL SELECT count(*), coalesce(sum(net),0) INTO :h_wz1, :h_wz2
        FROM py_payout WHERE biz_date = :h_wdate;
    if (sqlca.sqlcode < 0) { h_wz1 = 0; h_wz2 = 0; }
    EXEC SQL SELECT count(*) INTO :h_wz3 FROM py_payout
        WHERE biz_date = :h_wdate AND amount - fee <> net;
    if (sqlca.sqlcode < 0) h_wz3 = 0;
    if (h_wz3 > 0) {
        userlog("%s 순액 정합 위반 감지: %ld건 / 당일 %ld건",
                "PAY_FILECANCEL", h_wz3, h_wz1);
    }
    if (h_wz2 < 0) {
        setl(b, T_RC, 93);
        Bchg(b, T_MSG, 0, "당일 지급 순액 합계가 음수 - 원장 정합 오류", 0L);
        FAIL(b);
    }
    OK(b);
}
