限额控制

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 := ''; --取当前日期
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标示 如果是借记卡和贷记卡都可以用,或者借记卡和贷记卡只有一个能用,或者都不能用 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标示 如果是借记卡和贷记卡都可以用,或者借记卡和贷记卡只有一个能用,或者都不能用 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 := ''; --取当前日期
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:='';
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:='';
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;

表结构:

Oracle存储过程--案例的更多相关文章

  1. Oracle存储过程案例集合

    注:使用的工具为PLSQL Developer 壹.while简单使用(替换字符串中的字符,和REPLACE效果一样) 注: 这里没有使用REPLACE函数 1.建立存储过程 CREATE OR RE ...

  2. 数据库周刊30丨数据安全法草案将亮相;2020数据库产业报告;云南电网上线达梦;达梦7误删Redo Log;Oracle存储过程性能瓶颈;易鲸捷实践案例……

    摘要:墨天轮数据库周刊第30期发布啦,每周1次推送本周数据库相关热门资讯.精选文章.干货文档. 热门资讯 1.数据安全法草案即将亮相:将确立数据分级分类管理.应急处置制度[摘要]数据安全法草案即将在本 ...

  3. Oracle存储过程和自定义函数

    新博客文章链接,欢迎大家评论探讨 概述 存储过程和存储函数是指存储在数据库中供所有用户程序调用的子程序叫存储过程.存储函数. 异同点: 存储过程和存储函数的相同点:完成特定功能的程序. 存储过程和存储 ...

  4. oracle存储过程和存储函数&触发器

    oracle存储过程和存储函数 指存储在数据库中供所有用户程序调用的子程序叫存储过程,存储函数 存储过程和存储函数的相同点:完成特定功能的程序 存储过程和存储函数的区别:是否用return语句返回值 ...

  5. oracle存储过程加密

    引言:平时大家在做项目的时候,经常会遇到把Oracle存储过程带到项目现场来测试系统.这时如果想对自己的存储过程进行保密,不使别人看到源代码,就可以对已有的存储过程进行加密保护.顾名思义,就是对Ora ...

  6. Oracle存储过程中跳出循环的写法

    注:本文来源于: <  Oracle存储过程中跳出循环的写法   > Oracle存储过程中跳出循环的写法 记录exit和return的用法 1:exit用来跳出循环 loop IF V_ ...

  7. oracle 存储过程

    来自:http://www.jb51.net/article/31805.htm Oracle存储过程基本语法 存储过程 1 CREATE OR REPLACE PROCEDURE 存储过程名 2 I ...

  8. Oracle存储过程语法

    原文链接:http://www.jb51.net/article/31805.htm Oracle存储过程基本语法 存储过程  1 CREATE OR REPLACE PROCEDURE 存储过程名  ...

  9. ORACLE存储过程调用Web Service

    1. 概述 最近在ESB项目中,客户在各个系统之间的服务调用大多都是在oracle存储过程中进行的,本文就oracle存储过程调用web service来进行说明.其他主流数据库,比如mysql和sq ...

随机推荐

  1. TCP/IP和Socket的关系

    要写网络程序就必须用Socket,这是程序员都知道的.而且,面试的时候,我们也会问对方会不会Socket编程?一般来说,很多人都会说,Socket编程基本就是listen,accept以及send,w ...

  2. ZooKeeper源码分析:Quorum请求的整个流程(转)

    Quorum请求是转发给Leader处理,并且需要得一个Follower Quorum确认的请求.这些请求包括: 1)znode的写操作(OpCode.create,OpCode.delete,OpC ...

  3. 基于Dedup的数据打包技术

    基于Dedup的数据打包技术 0.引言    Tar, winrar, winzip是最为常见的数据打包工具软件,它们把文件集体封装成一个单独的数据包,从而方便数据的分布.传输.归档以及持久保存等目的 ...

  4. android assets与 assets与res/raw 的相同、不同点

    1.获取资源的输入流 资源文件 sample.txt 位于 $PROJECT_HOME/assets/ 目录下,可以在 Activity 中通过   //也可以放置图片等资源,获取方式相同 Conte ...

  5. VS2013环境生成和调用DLL动态链接库

    http://blog.csdn.net/u010273652/article/details/25514577 创建动态库方法: 创建动态库是生成 .dll .lib 两个个文件 文件 -> ...

  6. PNG透明兼容IE6的几种方法(转)

    png 透明针对 IE6 一直是件挺麻烦的事情,使用的方法也是各有不同,大多的原理是用 IE 的滤镜来解决的. 语法: filter:progid:DXImageTransform.Microsoft ...

  7. CentOS下的一些基础问题解答

    1. 在/etc/passwd中某一行信息为“Linux01:x:505:505:/home/linux12:/bin/bash”,由此可知哪些信息? 用户名为linux01,需要密码登陆,用户ID为 ...

  8. 【Java面试题】42 TreeSet里面放对象,如果同时放入了父类和子类的实例对象,那比较时使用的是父类的compareTo方法,还是使用的子类的compareTo方法,还是抛异常!

    应该是没有针对问题的确切的答案,当前的add方法放入的是哪个对象,就调用哪个对象的compareTo方法,至于这个compareTo方法怎么做,就看当前这个对象的类中是如何编写这个方法的 试验如下: ...

  9. Linux,ubuntu14.04.5下安装软件

    没有aptitude 使用:  sudo apt-get install  ***

  10. <iOS>一个开发中值得注意的细节

    UIScrollView有一个属性叫做scrollToTop,是个BOOL值,默认为YES. 它的作用是定义当前的这个UIScrollView的delegate<UIScrollViewDele ...