Oracle存儲過程--案例

限額控制spa

CREATE OR REPLACE PACKAGE BODY NP_PCKG_MERCHANT_LIMIT
AS
  PROCEDURE CHECK_LIMIT (
      in_iplCode         IN   VARCHAR2,       --行業編號
      in_iplState        IN   VARCHAR2,       --卡類型
      in_posNo           IN   VARCHAR2,      --商戶號
      in_tranAmt         IN   VARCHAR2,      --交易金額
      out_retcode        OUT  VARCHAR2      --返回碼
  )
  IS
      v_date             VARCHAR2(8);      --系統日期
      --v_merchantType     VARCHAR2(30);    --行業類型
      v_debitSingleMax   NUMBER(18,2);    --借記卡單筆限額
      v_debitDayMax      NUMBER(18,2);    --借記卡日累計限額
      v_debitMonthMax    NUMBER(18,2);    --借記卡月累計限額
      v_debitYearMax     NUMBER(18,2);    --借記卡年累計限額
      v_debitDaySum      NUMBER(18,2);   --借記卡日累計限額當日發生額
      v_debitMonthSum    NUMBER(18,2);   --借記卡月累計限額當月發生額
      v_debitYearSum     NUMBER(18,2);   --借記卡年累計限額當年發生額
      v_debitLastDate    NUMBER(18,2);   --借記卡限額上次交易日
      v_creditSingleMax  NUMBER(18,2);   --貸記卡單筆限額
      v_creditDayMax     NUMBER(18,2);   --貸記卡日累計限額
      v_creditMonthMax   NUMBER(18,2);   --貸記卡月累計限額
      v_creditYearMax    NUMBER(18,2);   --貸記卡年累計限額
      v_creditDaySum     NUMBER(18,2);   --貸記卡日累計限額當日發生額
      v_creditMonthSum   NUMBER(18,2);   --貸記卡月累計限額當月發生額
      v_creditYearSum    NUMBER(18,2);   --貸記卡年累計限額當年發生額
      v_creditLastDate   NUMBER(18,2);   --貸記卡限額上次交易日
      --v_stt              VARCHAR2(1);      --帳戶狀態
  BEGIN
    out_retcode := '0';


        --取當前日期
        v_date := to_char(SYSDATE, 'yyyymmdd');
        ----------------------------------------------------------------
        -- 判斷商戶收單限額(設置的客商戶日累計限額)
        ----------------------------------------------------------------
        --取收單限額 也要區分借記卡 和 貸記卡

          IF in_iplState = 1 THEN --是借記卡
            BEGIN
              SELECT
                  IPL_DEBIT_SINGLE,IPL_DEBIT_DAYMAX,IPL_DEBIT_MONTHMAX,IPL_DEBIT_YEARMAX
              INTO
                  v_debitSingleMax,v_debitDayMax,v_debitMonthMax,v_debitYearMax
              FROM
                  IM_PAY_LIMIT
              WHERE
                  IPL_CODE = in_iplCode AND --此處須要一個參數,行業的code
                  IPL_STATE in('00','01') ;  --先判斷限額狀態 00標示  若是是借記卡和貸記卡均可以用,或者借記卡和貸記卡只有一個能用,或者都不能用

              EXCEPTION
                  WHEN NO_DATA_FOUND THEN
                      NULL;
              dbms_output.put_line(v_debitSingleMax);
             END;
           ELSIF in_iplState = 2 THEN --是貸記卡
             BEGIN
                  SELECT
                        IPL_CREDIT_SINGLE,IPL_CREDIT_DAYMAX,IPL_CREDIT_MONTHMAX,IPL_CREDIT_YEARMAX
                    INTO
                        v_creditSingleMax,v_creditDayMax,v_creditMonthMax,v_creditYearMax
                    FROM
                        IM_PAY_LIMIT
                    WHERE
                        IPL_CODE = in_iplCode AND --此處須要一個參數,行業的code
                        IPL_STATE in('00','10');  --先判斷限額狀態 00標示  若是是借記卡和貸記卡均可以用,或者借記卡和貸記卡只有一個能用,或者都不能用

                    EXCEPTION
                        WHEN NO_DATA_FOUND THEN
                            NULL;
              END;
           END IF;


        --取商戶年月日累計限額 ---
       BEGIN
            SELECT
                IMD_DEBIT_DAYAMT,
                IMD_DEBIT_MONTHAMT,
                IMD_DEBIT_YEARAMT,
                IMD_DEBIT_TRANSDAY,
                IMD_CREDIT_DAYAMT,
                IMD_CREDIT_MONTHAMT,
                IMD_CREDIT_YEARAMT,
                IMD_CREDIT_TRANSDAY
            INTO
                v_debitDaySum,
                v_debitMonthSum,
                v_debitYearSum,
                v_debitLastDate,
                v_creditDaySum,
                v_creditMonthSum,
                v_creditYearSum,
                v_creditLastDate
            FROM
                IM_MERCHANT_DAYSUM
            WHERE
                IMD_POSNO = in_posNo;

            EXCEPTION
                WHEN NO_DATA_FOUND THEN
                    INSERT INTO IM_MERCHANT_DAYSUM (IMD_POSNO,IMD_DEBIT_DAYAMT,IMD_DEBIT_MONTHAMT,IMD_DEBIT_YEARAMT,IMD_CREDIT_DAYAMT,IMD_CREDIT_MONTHAMT,IMD_CREDIT_YEARAMT,IMD_DEBIT_TRANSDAY,IMD_CREDIT_TRANSDAY) VALUES (in_posNo,'0.00','0.00','0.00','0.00','0.00','0.00',v_date,v_date);
        END;
     
     
         --判斷是商戶借記卡 =1    仍是貸記卡 =2  START
        IF in_iplState = 1 THEN
          --若是是借記卡,則判斷借記卡的單筆,日累計,月累計,年累計限額  v_debitSingleMax
           IF TO_NUMBER(in_tranAmt) > v_debitSingleMax THEN
              out_retcode := 'NPML1001';                    --錯誤碼NPML1001:超過借記卡單筆限額
              --ROLLBACK;
              RETURN;
           END IF;
           -- 判斷借記卡日累計交易限額否須要清零 ,若是是昨天的交易,今天須要清零 開始
              IF v_date <> v_debitLastDate THEN --here
                  v_debitDaySum := 0;
              END IF;
           -- 判斷借記卡日累計交易限額否須要清零 ,若是是昨天的交易,今天須要清零 結束
           IF v_debitDaySum + TO_NUMBER(in_tranAmt) > v_debitDayMax THEN --借記卡日累計限額
              out_retcode := 'NPML1002';                    --錯誤碼NPML1002:超過借記卡日累計限額
              --ROLLBACK;
              RETURN;
           END IF;
           --判斷借記卡月累計交易限額是否須要清零,若是是上個月的交易,則臨時置空 開始
              IF substr(v_date,1,6) <> substr(v_debitLastDate,1,6) THEN
                 v_debitMonthSum := 0;
              END IF;
           --判斷借記卡月累計交易限額是否須要清零,若是是上個月的交易,則臨時置空 結束
           IF v_debitMonthSum + TO_NUMBER(in_tranAmt) > v_debitMonthMax THEN --借記卡月累計限額
              out_retcode := 'NPML1003';                    --錯誤碼NPML1003:超過借記卡月累計限額
              --ROLLBACK;
              RETURN;
           END IF;
           --判斷借記卡年累計交易限額是否須要清零,若是是去年的交易,則臨時置空 開始
              IF substr(v_date,1,4) <> substr(v_debitLastDate,1,4) THEN
                 v_debitYearSum := 0;
              END IF;
           --判斷借記卡年累計交易限額是否須要清零,若是是去年的交易,則臨時置空 結束
           IF v_debitYearSum + TO_NUMBER(in_tranAmt) > v_debitYearMax THEN --借記卡年累計限額
              out_retcode := 'NPML1004';                    --錯誤碼NPML1004:超過借記卡年累計限額
              --ROLLBACK;
              RETURN;
           END IF;
        ELSIF in_iplState = 2 THEN
          --若是是貸記卡
          IF TO_NUMBER(in_tranAmt) > v_creditSingleMax THEN
              out_retcode := 'NPML1005';                    --錯誤碼NPML1005:超過貸記卡單筆限額
              --ROLLBACK;
              RETURN;
           END IF;
              -- 判斷貸記卡日累計交易限額是否須要清零 開始
              IF v_date <> v_creditLastDate THEN --here
                  v_creditDaySum := 0;
              END IF;
              -- 判斷貸記卡日累計交易限額是否須要清零 結束
           IF v_creditDaySum + TO_NUMBER(in_tranAmt) > v_creditDayMax THEN --貸記卡日累計限額
              out_retcode := 'NPML1006';                    --錯誤碼NPML1006:超過貸記卡日累計限額
              --ROLLBACK;
              RETURN;
           END IF;
           --判斷貸記卡月累計交易限額是否須要清零,若是是上個月的交易,則臨時置空 開始
              IF substr(v_date,1,6) <> substr(v_creditLastDate,1,6) THEN
                 v_creditMonthSum := 0;
              END IF;
           --判斷貸記卡月累計交易限額是否須要清零,若是是上個月的交易,則臨時置空 結束
           IF v_creditMonthSum + TO_NUMBER(in_tranAmt) > v_creditMonthMax THEN --貸記卡月累計限額
              out_retcode := 'NPML1007';                    --錯誤碼NPML1007:超過貸記卡月累計限額
              --ROLLBACK;
              RETURN;
           END IF;
           --判斷貸記卡年累計交易限額是否須要清零,若是是去年的交易,則臨時置空 開始
              IF substr(v_date,1,4) <> substr(v_creditLastDate,1,4) THEN
                 v_creditYearSum := 0;
              END IF;
           --判斷貸記卡年累計交易限額是否須要清零,若是是去年的交易,則臨時置空 結束
           IF v_creditYearSum + TO_NUMBER(in_tranAmt) > v_creditYearMax THEN --貸記卡月累計限額
              out_retcode := 'NPML1008';                    --錯誤碼NPML1008:超過貸記卡年累計限額
              --ROLLBACK;
              RETURN;
           END IF;
        END IF;
        --判斷是商戶借記卡 =1    仍是貸記卡 =2  END


        COMMIT;
    END;


    PROCEDURE UPDATE_LIMIT (
        in_posNo               IN    VARCHAR2,            --商戶號
        in_iplState            IN    VARCHAR2,            --卡類型
        in_tranAmt             IN    VARCHAR2,            --交易金額
        out_retcode            OUT   VARCHAR2            --返回碼
    )
    IS
    v_date             VARCHAR2(8);      --系統日期
    v_debitDaySum      NUMBER(18,2);   --借記卡日累計限額當日發生額
    v_debitMonthSum    NUMBER(18,2);   --借記卡月累計限額當月發生額
    v_debitYearSum     NUMBER(18,2);   --借記卡年累計限額當年發生額
    v_debitLastDate    NUMBER(18,2);   --借記卡限額上次交易日

    v_creditDaySum     NUMBER(18,2);   --貸記卡日累計限額當日發生額
    v_creditMonthSum   NUMBER(18,2);   --貸記卡月累計限額當月發生額
    v_creditYearSum    NUMBER(18,2);   --貸記卡年累計限額當年發生額
    v_creditLastDate   NUMBER(18,2);   --貸記卡限額上次交易日

    BEGIN
        out_retcode := '0';

        --取當前日期
        v_date := to_char(SYSDATE, 'yyyymmdd');

        --取客戶日累計限額
    BEGIN
            SELECT
                IMD_DEBIT_DAYAMT,
                IMD_DEBIT_MONTHAMT,
                IMD_DEBIT_YEARAMT,
                IMD_CREDIT_DAYAMT,
                IMD_CREDIT_MONTHAMT,
                IMD_CREDIT_YEARAMT
            INTO
                v_debitDaySum,
                v_debitMonthSum,
                v_debitYearSum,
                v_creditDaySum,
                v_creditMonthSum,
                v_creditYearSum
            FROM
                IM_MERCHANT_DAYSUM
            WHERE
                 IMD_POSNO = in_posNo
            FOR UPDATE;

            EXCEPTION
                WHEN NO_DATA_FOUND THEN
                    NULL;
        END;
        --判斷借記卡日累計交易限額否須要清零
        IF v_date <> v_debitLastDate THEN
             v_debitDaySum := 0;
        END IF;
         -- 判斷貸記卡日累計交易限額是否須要清零
        IF v_date <> v_creditLastDate THEN --here
            v_creditDaySum := 0;
        END IF;
        --判斷借記卡月累計交易限額否須要清零
        IF substr(v_date,1,6) <> substr(v_debitLastDate,1,6) THEN
            v_debitMonthSum := 0;
        END IF;
        --判斷貸記卡月累計交易限額否須要清零
        IF substr(v_date,1,6) <> substr(v_creditLastDate,1,6) THEN
            v_creditMonthSum := 0;
        END IF;
        --判斷借記卡年累計交易限額否須要清零
        IF substr(v_date,1,4) <> substr(v_debitLastDate,1,4) THEN
            v_debitYearSum := 0;
        END IF;
        --判斷貸記卡年累計交易限額否須要清零
        IF substr(v_date,1,4) <> substr(v_creditLastDate,1,4) THEN
            v_creditYearSum := 0;
        END IF;
        --更新商戶收單限額累計表    須要區分借記卡和貸記卡
        IF in_iplState = 1 THEN --借記卡
          UPDATE IM_MERCHANT_DAYSUM --更新借記卡收單累計限額
          SET
               IMD_DEBIT_DAYAMT = v_debitDaySum + TO_NUMBER(in_tranAmt),
               IMD_DEBIT_MONTHAMT = v_debitMonthSum + TO_NUMBER(in_tranAmt),
               IMD_DEBIT_YEARAMT = v_debitYearSum + TO_NUMBER(in_tranAmt),
               IMD_DEBIT_TRANSDAY = v_date
          WHERE
              IMD_POSNO = in_posNo;

          COMMIT;
      ELSIF in_iplState = 2 THEN --貸記卡
        UPDATE IM_MERCHANT_DAYSUM --更新貸記卡收單累計限額
          SET
               IMD_CREDIT_DAYAMT = v_creditDaySum + TO_NUMBER(in_tranAmt),
               IMD_CREDIT_MONTHAMT = v_creditMonthSum + TO_NUMBER(in_tranAmt),
               IMD_CREDIT_YEARAMT = v_creditYearSum + TO_NUMBER(in_tranAmt),
               IMD_CREDIT_TRANSDAY = v_date
          WHERE
              IMD_POSNO = in_posNo;

          COMMIT;
      END IF;
    END;


    PROCEDURE ROLL_LIMIT (
    in_posNo        IN  VARCHAR2,     --商戶號
    in_iplState           IN VARCHAR2,        --卡類型
    in_orderNo        IN  VARCHAR2,     --交易流水號
    out_retcode       OUT VARCHAR2      --存儲過程返回碼
  )
  IS
    v_amt     VARCHAR2(20);
    v_transDate VARCHAR2(8);
    v_nowDate   VARCHAR2(8);
  BEGIN
    out_retcode:='0';
    v_nowDate:=to_char(SYSDATE, 'yyyymmdd');

    --取客戶日累計限額
    BEGIN
            SELECT
                substr(NPF_TRAN_TIME,1,8),
                NPF_ORDER_AMT
            INTO
                v_transDate,
                v_amt
            FROM
                NP_PAY_FLOW
            WHERE
                NPF_FLOWNO = in_orderNo
            FOR UPDATE;

            EXCEPTION
                WHEN NO_DATA_FOUND THEN
                    NULL;
        END;

        IF v_transDate ='' THEN

      out_retCode:='0';
      return;
    END IF;

    --IF v_transDate<> v_nowDate then--若是不是今天的指令,不處理當日的限額
    --  out_retCode:='0';
    --  return;
    --END IF;
        --查找到該訂單,而且回滾的是今天的訂單
        --若是是借記卡交易
        --
        IF in_iplState = 1 then --回滾借記卡
          IF v_transDate = v_nowDate then--若是交易日期小於今天當天日期,則判斷是否爲本月的交易,    回滾當月和當年的
            UPDATE IM_MERCHANT_DAYSUM--更新當天、本月、本年的累計額度
            SET
              IMD_DEBIT_DAYAMT = IMD_DEBIT_DAYAMT - v_amt,--更新當日的限額
              IMD_DEBIT_MONTHAMT = IMD_DEBIT_MONTHAMT - v_amt,--更新本月的限額
              IMD_DEBIT_YEARAMT = IMD_DEBIT_YEARAMT - v_amt--更新本年的限額
            WHERE
              IMD_POSNO = in_posNo;--商戶號
          COMMIT;
          ELSIF v_transDate < v_nowDate then --若是交易時間不是今天,則判斷是否爲本月的交易
            IF substr(v_transDate,1,6) = substr(v_nowDate,1,6) THEN--不是當天的交易,則判斷是否爲本月的交易START
              UPDATE IM_MERCHANT_DAYSUM--更新本月、本年的交易
              SET
                IMD_DEBIT_MONTHAMT = IMD_DEBIT_MONTHAMT - v_amt,--更新本月的限額
                IMD_DEBIT_YEARAMT = IMD_DEBIT_YEARAMT - v_amt --更新本年的限額
              WHERE
                IMD_POSNO = in_posNo;--商戶號
            COMMIT;
          ELSIF substr(v_transDate,1,6) < substr(v_nowDate,1,6) THEN--不是當天的交易,也不是本月的交易,則判斷是否爲本年的交易
            IF substr(v_transDate,1,4) = substr(v_nowDate,1,4) THEN--不是當天的交易,也不是本月的交易,是本年的交易
              UPDATE IM_MERCHANT_DAYSUM--更新本年的交易
                SET
                  IMD_DEBIT_YEARAMT = IMD_DEBIT_YEARAMT - v_amt--更新本年的限額
                WHERE
                  IMD_POSNO = in_posNo;--商戶號
              COMMIT;
            END IF;
            END IF;--不是當天的交易,則判斷是否爲本月的交易END
          END IF;--回滾借記卡結束
      ELSIF in_iplState = 2 then  --回滾貸記卡
        IF v_transDate = v_nowDate then--若是交易日期小於今天當天日期,則判斷是否爲本月的交易,    回滾當月和當年的
            UPDATE IM_MERCHANT_DAYSUM--更新當天、本月、本年的累計額度
            SET
              IMD_CREDIT_DAYAMT = IMD_CREDIT_DAYAMT - v_amt,--更新當日的限額
              IMD_CREDIT_MONTHAMT = IMD_CREDIT_DAYAMT - v_amt,--更新本月的限額
              IMD_CREDIT_YEARAMT = IMD_CREDIT_YEARAMT - v_amt--更新本年的限額
            WHERE
              IMD_POSNO = in_posNo;--商戶號
          COMMIT;
          ELSIF v_transDate < v_nowDate then --若是交易時間不是今天,則判斷是否爲本月的交易
            IF substr(v_transDate,1,6) = substr(v_nowDate,1,6) THEN--不是當天的交易,則判斷是否爲本月的交易START
              UPDATE IM_MERCHANT_DAYSUM--更新本月、本年的交易
              SET
                IMD_CREDIT_MONTHAMT = IMD_CREDIT_MONTHAMT - v_amt,--更新本月的限額
                IMD_CREDIT_YEARAMT = IMD_CREDIT_YEARAMT - v_amt--更新本年的限額
              WHERE
                IMD_POSNO = in_posNo;--商戶號
            COMMIT;
          ELSIF substr(v_transDate,1,6) < substr(v_nowDate,1,6) THEN--不是當天的交易,也不是本月的交易,則判斷是否爲本年的交易
            IF substr(v_transDate,1,4) = substr(v_nowDate,1,4) THEN--不是當天的交易,也不是本月的交易,是本年的交易
              UPDATE IM_MERCHANT_DAYSUM--更新本年的交易
                SET
                  IMD_CREDIT_YEARAMT = IMD_CREDIT_YEARAMT - v_amt --更新本年的限額
                WHERE
                  IMD_POSNO = in_posNo;--商戶號
              COMMIT;
            END IF;
            END IF;--不是當天的交易,則判斷是否爲本月的交易END
          END IF;--回滾借記卡結束
      END IF;--回滾借記卡、貸記卡結束
        --
  END;

END NP_PCKG_MERCHANT_LIMIT;

 表結構:code

相關文章
相關標籤/搜索