一个入门级存储过程

create or replace procedure proc_autoAuditCreditAmount
as
  --声明游标 结果集A:需要核销的机构(有未核销单据)
  cursor ivan_cur is
    select customerDepaID, min(CreditAccount_ID) acBeginID, max(CreditAccount_ID) acEndID
    from Tbl_Creditaccount
    where alterationType<=0 and isPayback=0
    group by customerDepaID
    order by customerDepaID;
  --声明游标(带参数) 结果集B:某机构需要核销的单据,某机构的id来源于结果集A的循环
  cursor ivan_cur_b(
         p_depa_id Tbl_Creditaccount.Creditaccount_Id%type
         ,p_beginID Tbl_Creditaccount.Creditaccount_Id%type
         ,p_endID Tbl_Creditaccount.Creditaccount_Id%type ) 
    is
    select *
    from Tbl_Creditaccount
    where alterationType<=0 and isPayback=0 and customerDepaID=p_depa_id
    and CreditAccount_ID between p_beginID and p_endID
    order by alterationTime asc, CreditAccount_ID asc;

    
  --声明变量paybackmoney,它的类型是表Tbl_Creditaccount中字段Alterationamount的类型,初始化为0
  v_paybackNum number := 0; --某机构还款单数量
  v_paybackmoney Tbl_Creditaccount.Alterationamount%type := 0;--某机构还款单总金额
  v_minPaybackID Tbl_Creditaccount.Creditaccount_Id%type; --某机构还款单开始ID
  v_maxPaybackID Tbl_Creditaccount.Creditaccount_Id%type; --某机构还款单结束ID
  v_checkNum number := 0; --某机构已核销记录数量 
  v_lastSettleBalance Tbl_Cancelrecord.Settlebalance%type := 0; --某机构最后一次结余金额
  v_settleBalance Tbl_Cancelrecord.Settlebalance%type := 0;--某机构本次可用来还款的总金额
  v_totalAmount Tbl_Cancelrecord.totalamount%type := 0;--某机构本次的核销了的单据的总金额
  v_recordNo number := 0; --核销单编号yyyyMMddsys00001
  v_index number;
  v_depaName Tbl_Depa.Depaname%type := 0; --机构名称(确保最新)
  v_cancelrecord_id Tbl_Cancelrecord.cancelrecord_id%type := 0; --核销主表ID
  v_calculateenddatetime Tbl_Cancelrecord.calculateenddatetime%type; --核销结束时间
  --v_alterationAmount Tbl_Creditaccount.Alterationamount%type := 0;--某机构每笔借贷的金额
begin
  --1.循环核销每一个需要核销的机构
  for ivan_rec in ivan_cur loop
    begin
         savepoint sp1;
         v_recordNo := v_recordNo + 1;
         v_index := 0; --每次循环开头都要初始化,因为这是子循环的index
         select depaname into v_depaName from tbl_Depa where depa_id = ivan_rec.customerDepaID;--取机构此刻的名称
         --DBMS_OUTPUT.put_line('The customerID is '||ivan_rec.customerDepaID||', record from '||ivan_rec.acBeginID||' to '||ivan_rec.acEndID);
         
         --2.查找该机构可使用(未核销)的还款单总金额
         --(2.1)首先判断该机构是否有可还款的记录,防止Not_Data_Found Exception
         select count(ca.creditaccount_id) into v_paybackNum
         from Tbl_Creditaccount ca
         where alterationType=1 and isPayback=0 and customerDepaID=ivan_rec.customerDepaID;
         
         if v_paybackNum = 0 then
           v_paybackmoney := 0;
           v_minPaybackID := 0;
           v_maxPaybackID := 0;
         else 
           --(2.2)查找该机构可使用(未核销)的还款单总金额,放入变量paybackmoney
           select 
           sum(alterationamount) into v_paybackmoney
           from Tbl_Creditaccount ca
           where alterationType=1 and isPayback=0 and customerDepaID=ivan_rec.customerDepaID
           group by customerDepaID;
           
           select min(Creditaccount_Id) into v_minPaybackID
           from Tbl_Creditaccount ca
           where alterationType=1 and isPayback=0 and customerDepaID=ivan_rec.customerDepaID;
           
           select max(Creditaccount_Id) into v_maxPaybackID
           from Tbl_Creditaccount ca
           where alterationType=1 and isPayback=0 and customerDepaID=ivan_rec.customerDepaID;
         end if;
         --DBMS_OUTPUT.put_line('This agent has '||v_paybackmoney||' RMB to pay!');
         
         --3.在核销主表中,查找该机构最后一条核销记录,取出该记录的结余金额
         --(3.1)首先判断该机构是否有结余金额数据,防止Not_Data_Found Exception
         select count(cr.cancelrecord_id) into v_checkNum
         from Tbl_Cancelrecord cr
         where recordState=2 and agentDepaID=ivan_rec.customerDepaID;
         
         if v_checkNum = 0 then
           v_lastSettleBalance := 0;
         else
           --(3.2)查找机构上一次的结余金额
           select settleBalance into v_lastSettleBalance
           from (
             select rank() over(partition by agentDepaID order by cancelRecordDatetime desc, cancelRecord_ID desc) rn
             , cr.settleBalance
             from Tbl_Cancelrecord cr
             where recordState=2 and agentDepaID=ivan_rec.customerDepaID
           ) a
           where rn=1;
         end if;
         --DBMS_OUTPUT.put_line('The lastest settle Balance is '||v_lastSettleBalance||' RMB!');
         v_settleBalance := v_paybackmoney + v_lastSettleBalance;                 
         DBMS_OUTPUT.put_line('Begin : Agent '||ivan_rec.customerDepaID||'_'||v_depaName||' has '||v_settleBalance||' RMB to pay this time!' );
         
       
         
       --前面是准备工作,现在开始为机构核销单据了!
       
       --循环结果集B,核销该机构的订单
       for ivan_rec_b in ivan_cur_b(ivan_rec.customerDepaID, ivan_rec.acBeginID, ivan_rec.acEndID) loop
         begin 
           DBMS_OUTPUT.put_line('No.'||ivan_rec_b.billNo||', borrow money :'||ivan_rec_b.alterationAmount||', current settleBalance :'||v_settleBalance);
           if v_settleBalance < (-ivan_rec_b.alterationAmount) then --无法核销本单据(钱不够),跳出子循环(如果是第一笔,那么v_cancelrecord_id=0)
              DBMS_OUTPUT.put_line('无法继续核销该机构,跳出子循环!' );
              exit; 
           else 
             if v_index = 0 then --有钱核销第一笔单据,那么首先往核销主表插入一条数据
               insert into tbl_cancelrecord(
                 cancelrecord_id,agentdepaid, agentdepaname
                 ,cancelrecorddatetime,cancelrecordtype--核销种类:0人工  1自动
                 ,calculatebegindatetime--,calculateenddatetime 
                 ,cancelrecordno
                 ,createpersonid,createpersonaccount,createdepaid,createdepaname,createdatetime
                 ,lastmodifydepaid,lastmodifypersonname,lastmodifypersonid,lastmodifydepaname,lastmodifydatetime
                 ,recordstate
               )
               values(
                 seq_cancelrecord.nextval, ivan_rec_b.customerdepaid, v_depaName
                 ,sysdate, 0 --核销种类:0自动 1人工 
                 ,ivan_rec_b.alterationtime
                 ,to_char(sysdate,'yyyyMMdd')||'sys'||Lpad(v_recordNo,5,0)--核销单编号yyyyMMddsys00001
                 ,1,'Admin',3,'综合业务部',sysdate --写死
                 ,1,'Admin',3,'综合业务部',sysdate --写死
                 ,2 --已核销
               );   
               select seq_cancelrecord.currval into v_cancelrecord_id from dual; --赋值到变量,记录核销主表ID
             end if;
           end if;
           --够钱核销该单据
           --将本条单据置为已核销
           update tbl_creditaccount
           set ispayback = 1, payBackType = 0
           where creditaccount_id = ivan_rec_b.creditaccount_id;
           --插入一条核销记录至核销明细表
           insert into tbl_cancelrecorddetails(
             cancelrecorddetails_id
             ,cancelrecordid
             ,agentdepaid, agentdepaname
             ,orderid, orderno
             ,ordertype
           )
           values(
             seq_cancelrecorddetails.nextval
             ,v_cancelrecord_id
             ,ivan_rec_b.customerdepaid, v_depaName
             ,ivan_rec_b.billid, ivan_rec_b.billno
             ,ivan_rec_b.billtype
           );
           v_index := v_index + 1;
           v_settleBalance := v_settleBalance + ivan_rec_b.alterationAmount; --记住是+,因为ivan_rec_b.alterationAmount带正负号
           v_totalAmount := v_totalAmount - ivan_rec_b.alterationAmount; --记住是-,因为ivan_rec_b.alterationAmount带正负号
           v_calculateenddatetime := ivan_rec_b.alterationtime;
         end;
       end loop;
       
       if v_index > 0 then --说明本机构核销了单据      
         update tbl_cancelrecord --更新核销主表某些字段
         set calculateenddatetime = v_calculateenddatetime --本次核销最后一笔单据时间
             ,totalamount = v_totalAmount--本次共核销金额
             ,settleBalance = v_settleBalance --本次核销后,结余金额
         where cancelrecord_id = v_cancelrecord_id;
         
         update Tbl_Creditaccount --将所有未核销的还款单置为已核销(已用来还款)
         set ispayback = 1, payBackType = 0
         where alterationType=1 and isPayback=0 --单据:还款单,状态:未核销(未使用)
               and customerDepaID=ivan_rec.customerDepaID 
               --一定要加修改范围,因为这途中可能增加了未核销的还款单,虽然几率很微小
               and creditaccount_id between v_minPaybackID and v_maxPaybackID;
       end if;
       
       /*
       --测试异常
       if v_recordNo = 3 then 
         v_index := v_index / 0;
       end if;
       */
       --提交一个机构的数据
       commit;
       DBMS_OUTPUT.put_line('v_recordNo ' || v_recordNo || '-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*' );
    
    exception
    when others then
        dbms_output.put_line('Error!!!! Error on agent: ' || v_depaName); 
        rollback to savepoint sp1; --回滚数据,并继续循环下一个机构
    
    end;
  end loop;
end;

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值