限额控制
CREATE OR REPLACE PACKAGE BODY NP_PCKG_MERCHANT_LIMIT ASPROCEDURE CHECK_LIMIT (in_iplCode IN VARCHAR2, --行业编号in_iplState IN VARCHAR2, --卡类型in_posNo IN VARCHAR2, --商户号in_tranAmt IN VARCHAR2, --交易金额out_retcode OUT VARCHAR2 --返回码 )ISv_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); --账户状态BEGINout_retcode := '0';--取当前日期v_date := to_char(SYSDATE, 'yyyymmdd');------------------------------------------------------------------ 判断商户收单限额(设置的客商户日累计限额)------------------------------------------------------------------取收单限额 也要区分借记卡 和 贷记卡IF in_iplState = 1 THEN --是借记卡BEGINSELECTIPL_DEBIT_SINGLE,IPL_DEBIT_DAYMAX,IPL_DEBIT_MONTHMAX,IPL_DEBIT_YEARMAXINTOv_debitSingleMax,v_debitDayMax,v_debitMonthMax,v_debitYearMaxFROMIM_PAY_LIMITWHEREIPL_CODE = in_iplCode AND --此处需要一个参数,行业的codeIPL_STATE in('00','01') ; --先判断限额状态 00标示 如果是借记卡和贷记卡都可以用,或者借记卡和贷记卡只有一个能用,或者都不能用 EXCEPTIONWHEN NO_DATA_FOUND THENNULL;dbms_output.put_line(v_debitSingleMax);END;ELSIF in_iplState = 2 THEN --是贷记卡BEGINSELECTIPL_CREDIT_SINGLE,IPL_CREDIT_DAYMAX,IPL_CREDIT_MONTHMAX,IPL_CREDIT_YEARMAXINTOv_creditSingleMax,v_creditDayMax,v_creditMonthMax,v_creditYearMaxFROMIM_PAY_LIMITWHEREIPL_CODE = in_iplCode AND --此处需要一个参数,行业的codeIPL_STATE in('00','10'); --先判断限额状态 00标示 如果是借记卡和贷记卡都可以用,或者借记卡和贷记卡只有一个能用,或者都不能用 EXCEPTIONWHEN NO_DATA_FOUND THENNULL;END;END IF;--取商户年月日累计限额 ---BEGINSELECTIMD_DEBIT_DAYAMT,IMD_DEBIT_MONTHAMT,IMD_DEBIT_YEARAMT,IMD_DEBIT_TRANSDAY,IMD_CREDIT_DAYAMT,IMD_CREDIT_MONTHAMT,IMD_CREDIT_YEARAMT,IMD_CREDIT_TRANSDAYINTOv_debitDaySum,v_debitMonthSum,v_debitYearSum,v_debitLastDate,v_creditDaySum,v_creditMonthSum,v_creditYearSum,v_creditLastDateFROMIM_MERCHANT_DAYSUMWHEREIMD_POSNO = in_posNo;EXCEPTIONWHEN NO_DATA_FOUND THENINSERT 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 STARTIF in_iplState = 1 THEN--如果是借记卡,则判断借记卡的单笔,日累计,月累计,年累计限额 v_debitSingleMaxIF TO_NUMBER(in_tranAmt) > v_debitSingleMax THENout_retcode := 'NPML1001'; --错误码NPML1001:超过借记卡单笔限额--ROLLBACK;RETURN;END IF;-- 判断借记卡日累计交易限额否需要清零 ,如果是昨天的交易,今天需要清零 开始IF v_date <> v_debitLastDate THEN --herev_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) THENv_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) THENv_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 THENout_retcode := 'NPML1005'; --错误码NPML1005:超过贷记卡单笔限额--ROLLBACK;RETURN;END IF;-- 判断贷记卡日累计交易限额是否需要清零 开始IF v_date <> v_creditLastDate THEN --herev_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) THENv_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) THENv_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 ENDCOMMIT;END;PROCEDURE UPDATE_LIMIT (in_posNo IN VARCHAR2, --商户号in_iplState IN VARCHAR2, --卡类型in_tranAmt IN VARCHAR2, --交易金额out_retcode OUT VARCHAR2 --返回码 )ISv_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); --贷记卡限额上次交易日BEGINout_retcode := '0';--取当前日期v_date := to_char(SYSDATE, 'yyyymmdd');--取客户日累计限额BEGINSELECTIMD_DEBIT_DAYAMT,IMD_DEBIT_MONTHAMT,IMD_DEBIT_YEARAMT,IMD_CREDIT_DAYAMT,IMD_CREDIT_MONTHAMT,IMD_CREDIT_YEARAMTINTOv_debitDaySum,v_debitMonthSum,v_debitYearSum,v_creditDaySum,v_creditMonthSum,v_creditYearSumFROMIM_MERCHANT_DAYSUMWHEREIMD_POSNO = in_posNoFOR UPDATE;EXCEPTIONWHEN NO_DATA_FOUND THENNULL;END;--判断借记卡日累计交易限额否需要清零IF v_date <> v_debitLastDate THENv_debitDaySum := 0;END IF;-- 判断贷记卡日累计交易限额是否需要清零IF v_date <> v_creditLastDate THEN --herev_creditDaySum := 0;END IF;--判断借记卡月累计交易限额否需要清零IF substr(v_date,1,6) <> substr(v_debitLastDate,1,6) THENv_debitMonthSum := 0;END IF;--判断贷记卡月累计交易限额否需要清零IF substr(v_date,1,6) <> substr(v_creditLastDate,1,6) THENv_creditMonthSum := 0;END IF;--判断借记卡年累计交易限额否需要清零IF substr(v_date,1,4) <> substr(v_debitLastDate,1,4) THENv_debitYearSum := 0;END IF;--判断贷记卡年累计交易限额否需要清零IF substr(v_date,1,4) <> substr(v_creditLastDate,1,4) THENv_creditYearSum := 0;END IF;--更新商户收单限额累计表 需要区分借记卡和贷记卡IF in_iplState = 1 THEN --借记卡UPDATE IM_MERCHANT_DAYSUM --更新借记卡收单累计限额SETIMD_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_dateWHEREIMD_POSNO = in_posNo;COMMIT;ELSIF in_iplState = 2 THEN --贷记卡UPDATE IM_MERCHANT_DAYSUM --更新贷记卡收单累计限额SETIMD_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_dateWHEREIMD_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 --存储过程返回码 )ISv_amt VARCHAR2(20);v_transDate VARCHAR2(8);v_nowDate VARCHAR2(8);BEGINout_retcode:='0';v_nowDate:=to_char(SYSDATE, 'yyyymmdd');--取客户日累计限额BEGINSELECTsubstr(NPF_TRAN_TIME,1,8),NPF_ORDER_AMTINTOv_transDate,v_amtFROMNP_PAY_FLOWWHERENPF_FLOWNO = in_orderNoFOR UPDATE;EXCEPTIONWHEN NO_DATA_FOUND THENNULL;END;IF v_transDate ='' THENout_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--更新当天、本月、本年的累计额度SETIMD_DEBIT_DAYAMT = IMD_DEBIT_DAYAMT - v_amt,--更新当日的限额IMD_DEBIT_MONTHAMT = IMD_DEBIT_MONTHAMT - v_amt,--更新本月的限额IMD_DEBIT_YEARAMT = IMD_DEBIT_YEARAMT - v_amt--更新本年的限额WHEREIMD_POSNO = in_posNo;--商户号COMMIT;ELSIF v_transDate < v_nowDate then --如果交易时间不是今天,则判断是否为本月的交易IF substr(v_transDate,1,6) = substr(v_nowDate,1,6) THEN--不是当天的交易,则判断是否为本月的交易STARTUPDATE IM_MERCHANT_DAYSUM--更新本月、本年的交易SETIMD_DEBIT_MONTHAMT = IMD_DEBIT_MONTHAMT - v_amt,--更新本月的限额IMD_DEBIT_YEARAMT = IMD_DEBIT_YEARAMT - v_amt --更新本年的限额WHEREIMD_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--更新本年的交易SETIMD_DEBIT_YEARAMT = IMD_DEBIT_YEARAMT - v_amt--更新本年的限额WHEREIMD_POSNO = in_posNo;--商户号COMMIT;END IF;END IF;--不是当天的交易,则判断是否为本月的交易ENDEND IF;--回滚借记卡结束ELSIF in_iplState = 2 then --回滚贷记卡IF v_transDate = v_nowDate then--如果交易日期小于今天当天日期,则判断是否为本月的交易, 回滚当月和当年的UPDATE IM_MERCHANT_DAYSUM--更新当天、本月、本年的累计额度SETIMD_CREDIT_DAYAMT = IMD_CREDIT_DAYAMT - v_amt,--更新当日的限额IMD_CREDIT_MONTHAMT = IMD_CREDIT_DAYAMT - v_amt,--更新本月的限额IMD_CREDIT_YEARAMT = IMD_CREDIT_YEARAMT - v_amt--更新本年的限额WHEREIMD_POSNO = in_posNo;--商户号COMMIT;ELSIF v_transDate < v_nowDate then --如果交易时间不是今天,则判断是否为本月的交易IF substr(v_transDate,1,6) = substr(v_nowDate,1,6) THEN--不是当天的交易,则判断是否为本月的交易STARTUPDATE IM_MERCHANT_DAYSUM--更新本月、本年的交易SETIMD_CREDIT_MONTHAMT = IMD_CREDIT_MONTHAMT - v_amt,--更新本月的限额IMD_CREDIT_YEARAMT = IMD_CREDIT_YEARAMT - v_amt--更新本年的限额WHEREIMD_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--更新本年的交易SETIMD_CREDIT_YEARAMT = IMD_CREDIT_YEARAMT - v_amt --更新本年的限额WHEREIMD_POSNO = in_posNo;--商户号COMMIT;END IF;END IF;--不是当天的交易,则判断是否为本月的交易ENDEND IF;--回滚借记卡结束END IF;--回滚借记卡、贷记卡结束-- END;END NP_PCKG_MERCHANT_LIMIT;
表结构: