Thursday, August 8, 2024

Coding tutorials - Sql*Procedure

 

Coding tutorials - Sql *Procedure



DECLARE

v_account_num                                     bsnl_deposit_interest.account_num%Type;

v_tot_rebate                                      bsnl_deposit_interest.rebate%Type;

v_depo_ob                                         bsnl_deposit_interest.deposit_amount%Type;

v_depo_cb                                         bsnl_deposit_interest.deposit_amount%Type;

v_tot_accchrg                                     bsnl_deposit_interest.acc_charges%Type;

v_dep_status                                      bsnl_servicelevel_deposit_dtls.prospect_status%Type;

v_max_seq                                         bsnl_deposit_interest.sequence_id%Type;                                                                           

i_count                                           number default 0 ; 


cursor boss is 


SELECT DISTINCT account_num FROM bsnl_deposit_interest WHERE  REBATE>0 and deposit_id='2'

/*and account_num='1000971357'*/

 HAVING COUNT(*)>1 

GROUP BY ACCOUNT_NUM,ORDER_ID ,TELEPHONE_NO,DEPOSIT_ID,SEQUENCE_ID,DEPOSIT_AMOUNT,

INTEREST_ON_DEPOSIT,REBATE,ACC_CHARGES,START_DT,END_DT,INTEREST_CALCULATION_DT,EXECUTION_STATUS,ACCOUNT_TYPE,REC_MD_DT

;


BEGIN 

   for x  in boss

  loop

    begin


   v_account_num           :=x.account_num;

   

   select prospect_status into v_dep_status from bsnl_servicelevel_deposit_dtls where account_num=v_account_num and deposit_id='2';

   SELECT deposit_amount into v_depo_ob    FROM BSNL_DEPOSIT_INTEREST WHERE ACCOUNT_NUM=v_account_num and deposit_id='2' and sequence_id='1';

   SELECT max(sequence_id) into v_max_seq    FROM BSNL_DEPOSIT_INTEREST WHERE ACCOUNT_NUM=v_account_num and deposit_id='2';

   SELECT deposit_amount into v_depo_cb    FROM BSNL_DEPOSIT_INTEREST WHERE ACCOUNT_NUM=v_account_num and deposit_id='2' and sequence_id=v_max_seq;

   SELECT sum(rebate) into v_tot_rebate    FROM BSNL_DEPOSIT_INTEREST WHERE ACCOUNT_NUM=v_account_num and deposit_id='2';

   select sum(acc_charges) into v_tot_accchrg  FROM BSNL_DEPOSIT_INTEREST WHERE ACCOUNT_NUM=v_account_num and deposit_id='2';

     

        

  if v_dep_status<>'R' -----refunded accounts are eliminated

   then

        if round(v_depo_ob-v_depo_cb)<>round(v_tot_rebate+v_tot_accchrg,0)

          then  

             DBMS_OUTPUT.put_line (v_account_num ||','||v_depo_ob||','||v_tot_rebate||','||v_tot_accchrg||','||v_depo_cb); 

             i_count:=i_count+1;

        end if;

  end if;

  

EXCEPTION 

       WHEN others THEN DBMS_OUTPUT.put_line (v_account_num);

     end;

   end loop;

dbms_output.put_line(i_count);

END;

===============


---NOTE : BEFORE RUNNING PL SEE $# (USE CTRL-F)

DECLARE
v_ssa_code                                              accountattributes.ssa_code%Type;
v_actual_bill_dtm_upto                                  billsummary.actual_bill_dtm%type;
v_payment_upto                                          accountpayment.account_payment_dat%Type;
v_account_num                                           billsummary.account_num%Type;
v_inv_mny                                               number (18,3) default 0;
v_NEG_inv_mny                                           number (18,3) default 0;
v_adj_mny                                               number (18,3) default 0;
v_inv_tax_mny                                           number (18,3) default 0;
v_tot_debit                                             number (18,3) default 0;
v_tot_credit                                            number (18,3) default 0;
v_net_os                                                number (18,3) default 0;
v_bal_fwd_mny                                           number (18,3) default 0;
v_bal_out_mny                                           number (18,3) default 0;
v_bill_seq                                              billsummary.bill_seq%Type;
v_bill_status                                           billsummary.bill_status%Type; 
v_act_pmt_mny                                           number (18,3) default 0;
v_legacy_id                                             accountattributes.legacy_system_account_num%Type;
v_name                                                  contact.address_name%Type;
v_address                                               varchar2(400);
v_event_source                                          custeventsource.event_source%Type;
v_status                                                varchar2(10);
V_FINAL_BILL_STATUS                                     varchar2(20);
V_EXG_CODE                                              varchar2(10); 
v_unadj_dep                                             number (18,3) default 0;
v_act_type                                              varchar2(75);
V_IC_START_DT                                           DATE;
v_open_dt                                               date;
v_close_dt                                              date;
v_ic_bar_status                                         varchar2(15);
i_count                                                 number default 0 ; 
v_cnt                                                   number default 0 ; 
v_cnt1                                                  number default 0 ; 
v_cnt2                                                  number default 0 ; 
v_cnt3                                                  number default 0 ; 
v_cnt4                                                  number default 0 ; 
v_cnt5                                                  number default 0 ; 
v_cnt6                                                  number default 0 ; 
v_cnt7                                                  number default 0 ;








 ---    use this for ACTIVE as well as INACTIVE accounts
cursor boss is 

       select aa.account_num from accountattributes aa,billsummary bs
       where aa.account_num=bs.account_num
       and ssa_code=v_ssa_code
       and BILL_STATUS IN ('1','7','8')
       AND TRUNC(BS.ACTUAL_BILL_DTM) <=v_actual_bill_dtm_upto    
       AND BS.INVOICE_NET_MNY/1000+BS.INVOICE_TAX_MNY/1000>0
       /*AND AA.ACCOUNT_NUM ='1005938405'*/
       ;

 



BEGIN 

      delete from  oper_rem.boss_os_list;  -----output data is overwritten in this table everytime this plsql is run
      commit;
      
     /* select sysdate into v_payment_upto from dual;*/


----- PARAMETERS TO BE DEFINED BEFORE RUNNING   $#

v_ssa_code:='NND';
v_actual_bill_dtm_upto:='31-MAR-2004';
v_payment_upto:='08-AUG-2011';

   for x  in boss
          loop
              begin

                   v_account_num           :=x.account_num;
   
  
  
                       select   NVL(sum(BS.INVOICE_NET_MNY/1000),0), NVL(sum(BS.INVOICE_TAX_MNY/1000),0) into v_inv_mny,v_inv_tax_mny  from billsummary bs, accountattributes aa
                    where bs.account_num=aa.account_num
                    and BILL_STATUS IN ('1','7','8')
                    AND TRUNC(BS.ACTUAL_BILL_DTM) <=v_actual_bill_dtm_upto    
                    and aa.account_num=v_account_num
                    AND BS.INVOICE_NET_MNY/1000+BS.INVOICE_TAX_MNY/1000>0
                    ;
                    
                    -----FOR TREATMENT OF NEGATIVE INVOICE MNY CONSIDERED IN LEDGER AS PAYMENT----(e.g.) ACCOUNT NUM 1008381501  
                    
                     select   NVL(sum(BS.INVOICE_NET_MNY/1000)+sum(BS.INVOICE_TAX_MNY/1000),0) into v_NEG_inv_mny   from billsummary bs, accountattributes aa
                    where bs.account_num=aa.account_num
                    and BILL_STATUS IN ('1','7','8')
                    AND TRUNC(BS.ACTUAL_BILL_DTM) <=v_payment_upto  ----since negative inv mny is taken as payment in ledger
                    and aa.account_num=v_account_num
                    AND BS.INVOICE_NET_MNY/1000+BS.INVOICE_TAX_MNY/1000<0
                    ;
                    
                    select  NVL(sum(ap.account_payment_mny/1000),0) into v_act_pmt_mny from accountpayment ap 
                    where account_payment_status='1'
                    and account_payment_dat <=v_payment_upto  ---- if this line is commented, payments up-to-date will be considered, else value read from variable above
                    and ap.account_num=v_account_num
                    and deposit_boo='F'
                    and account_payment_txt!='ACCOUNT_SETTLEMENT'
                    ;
                    
                    v_NEG_inv_mny:=abs(v_NEG_inv_mny);
                    v_tot_debit:=v_inv_mny+v_inv_tax_mny ;
                    v_tot_credit:=v_act_pmt_mny+v_NEG_inv_mny ;
                    v_net_os:=v_tot_debit-v_tot_credit;


 if V_NET_OS>0    
            then 

---- FOR STATUS SELECTION


         SELECT COUNT(*) INTO V_CNT FROM (SELECT  cpd.customer_ref FROM  custproductdetails cpd, ACCOUNTATTRIBUTES  aA
         WHERE cpd.customer_ref=aA.account_num
         AND  cpd.End_Dat IS NOT  NULL  
         AND SSA_CODE=v_ssa_code       
         MINUS
          SELECT  cpd.customer_ref FROM  custproductdetails cpd, ACCOUNTATTRIBUTES  aA
          WHERE cpd.customer_ref=aA.account_num
          AND  cpd.End_Dat IS   NULL
          AND SSA_CODE=v_ssa_code )  A
          WHERE A.CUSTOMER_REF=v_account_num;

                IF V_CNT>0
                THEN V_STATUS:='INACTIVE';
                ELSE V_STATUS:='ACTIVE';  ----- IN CASE OF "ES PARENT" ACCOUNTS, THIS NEEDS TO BE VFD AS THEY DO NOT HAVE ANY PRODUCTS
                END IF;

               
      
      
------- FOR LEGACY ID, NAME, ADDRESS SELECTION

        SELECT count(*) into v_cnt1
        FROM ADDRESS AD,ACCOUNTATTRIBUTES AA,CONTACT CT,ACCOUNT ACT
        WHERE AD.CUSTOMER_REF=ACT.CUSTOMER_REF
        AND ACT.ACCOUNT_NUM=AA.ACCOUNT_NUM
        AND AD.CUSTOMER_REF=CT.CUSTOMER_REF
        AND ADDRESS_SEQ='2'
        AND CONTACT_SEQ='2'
        and AA.ACCOUNT_NUM=v_account_num
        ;
 
 if v_cnt1>0
 then 
      SELECT DISTINCT nvl(LEGACY_SYSTEM_ACCOUNT_NUM,0),nvl(ADDRESS_NAME,'NA'),
      NVL(ADDRESS_1||','||ADDRESS_2||','||ADDRESS_3||','||ADDRESS_4||','||ADDRESS_5||','||ZIPCODE,'NA') into v_legacy_id,v_name,v_address
      FROM ADDRESS AD,ACCOUNTATTRIBUTES AA,CONTACT CT,ACCOUNT ACT
      WHERE AD.CUSTOMER_REF=ACT.CUSTOMER_REF
      AND ACT.ACCOUNT_NUM=AA.ACCOUNT_NUM
      AND AD.CUSTOMER_REF=CT.CUSTOMER_REF
      AND ADDRESS_SEQ='2'
      AND CONTACT_SEQ='2'
      and AA.ACCOUNT_NUM=v_account_num
      ;

else   
       SELECT DISTINCT nvl(LEGACY_SYSTEM_ACCOUNT_NUM,0),nvl(ADDRESS_NAME,'NA'),
       NVL(ADDRESS_1||','||ADDRESS_2||','||ADDRESS_3||','||ADDRESS_4||','||ADDRESS_5||','||ZIPCODE,'NA') into v_legacy_id,v_name,v_address
       FROM ADDRESS AD,ACCOUNTATTRIBUTES AA,CONTACT CT,ACCOUNT ACT
       WHERE AD.CUSTOMER_REF=ACT.CUSTOMER_REF
       AND ACT.ACCOUNT_NUM=AA.ACCOUNT_NUM
       AND AD.CUSTOMER_REF=CT.CUSTOMER_REF
       AND ADDRESS_SEQ='1'
       AND CONTACT_SEQ='1'
       and AA.ACCOUNT_NUM=v_account_num
       ;
end if;


---- FOR EVENT_SOURCE SELECTION

begin
if v_status='INACTIVE'
    THEN
       begin

        SELECT product_label into v_event_source FROM custhasproduct chp,CUSTPRODUCTDETAILS cpd 
        WHERE chp.customer_ref=cpd.customer_ref
        and chp.product_seq=cpd.product_seq
        and chp.product_id='111'
        AND chp.PRODUCT_SEQ='1'
        and cpd.end_dat is not null
        and cpd.customer_ref=V_ACCOUNT_NUM;
        
   

   exception
    when no_data_found then v_event_source:='NOT FOUND';
    when too_many_rows then v_event_source:='MORE THAN ONE';
    WHEN others THEN v_event_source:='NOT FOUND';
    END;

   
        
ELSIF v_status='ACTIVE'

   THEN
      begin

        SELECT product_label into v_event_source  FROM custhasproduct chp,CUSTPRODUCTDETAILS cpd 
        WHERE chp.customer_ref=cpd.customer_ref
        and chp.product_seq=cpd.product_seq
        and chp.product_id='111'
        and cpd.end_dat is  null
        and cpd.customer_ref=V_ACCOUNT_NUM
        and rownum<2;
        
   

      exception
          when no_data_found then v_event_source:='NOT FOUND';
          when too_many_rows then v_event_source:='MORE THAN ONE';
          WHEN others THEN v_event_source:='NOT FOUND';
END;
   
END IF;

exception
    when no_data_found then v_event_source:='NOT FOUND';
    when too_many_rows then v_event_source:='MORE THAN ONE';
    WHEN others THEN v_event_source:='NOT FOUND';
END;



----- FOR ACT TYPE SUB TYPE SELECTION
BEGIN
    SELECT COUNT(*) INTO V_CNT5 FROM ACCOUNTATTRIBUTES 
    WHERE ACCOUNT_NUM =V_ACCOUNT_NUM;

        IF V_CNT5>0 THEN 
        SELECT NVL( ACCOUNT_TYPE,'NA')||' + '||NVL(ACCOUNT_SUBTYPE,'NA') INTO V_ACT_TYPE FROM ACCOUNTATTRIBUTES 
        WHERE ACCOUNT_NUM =V_ACCOUNT_NUM;
        ELSE 
          V_ACT_TYPE:='NA';
        END IF;

EXCEPTION
     WHEN OTHERS THEN V_ACT_TYPE:='NA';
END;


------- FOR EXG CODE SELECTION
BEGIN
        SELECT COUNT(*) INTO V_CNT4 FROM CUSTPRODUCTATTRDETAILS CPAD WHERE CUSTOMER_REF=v_account_num
         AND PRODUCT_ID='6' AND CPAD.PRODUCT_ATTRIBUTE_SUBID='3' AND CPAD.END_DAT IS NULL;
 
               IF V_CNT4>0 THEN
                  SELECT DISTINCT  CPAD.ATTRIBUTE_VALUE INTO V_EXG_CODE FROM CUSTPRODUCTATTRDETAILS CPAD WHERE CUSTOMER_REF=v_account_num
                  AND PRODUCT_ID='6' AND CPAD.PRODUCT_ATTRIBUTE_SUBID='3' AND CPAD.END_DAT IS NULL;
               ELSE
                  SELECT DISTINCT CPAD.ATTRIBUTE_VALUE INTO V_EXG_CODE FROM CUSTPRODUCTATTRDETAILS CPAD WHERE CUSTOMER_REF=v_account_num
                  AND PRODUCT_ID='6' AND CPAD.PRODUCT_ATTRIBUTE_SUBID='3' AND CPAD.END_DAT IS NOT NULL;
               END IF;
 
exception

  when OTHERS then  V_EXG_CODE:='NA';
  
END;
 

----- FOR UNADJUSTED DEPOSIT SELECTION
BEGIN
      SELECT count(*) INTO V_cnt3 FROM BSNL_SERVICELEVEL_DEPOSIT_DTLS BSDD, ACCOUNTATTRIBUTES AA
      WHERE BSDD.ACCOUNT_NUM=AA.ACCOUNT_NUM
      AND BSDD.PROSPECT_STATUS='C'
      and LENGTH(TRIM(TRANSLATE(telephone_no, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ' '))) is not null-----very important : CDR creates a deposit credit for pre-migration billable deposit billed and paid in CDR eg. 1009235816
      and aa.account_num =V_ACCOUNT_NUM;

if v_cnt3>0 
   then

       SELECT NVL(SUM(BSDD.DEPOSIT_AMOUNT_SUBMITTED),0) INTO V_UNADJ_DEP FROM BSNL_SERVICELEVEL_DEPOSIT_DTLS BSDD, ACCOUNTATTRIBUTES AA
       WHERE BSDD.ACCOUNT_NUM=AA.ACCOUNT_NUM
       AND BSDD.PROSPECT_STATUS='C'
       and LENGTH(TRIM(TRANSLATE(telephone_no, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ' '))) is not null-----very important : CDR creates a deposit credit for pre-migration billable deposit billed and paid in CDR eg. 1009235816
       and aa.account_num =V_ACCOUNT_NUM;
    else
        V_UNADJ_DEP:=0;
end if;

exception

  when OTHERS then  V_UNADJ_DEP:=0;
  
END;

------ TO CHK IF FINAL BILL IS DONE IN CDR 

 if V_STATUS='INACTIVE'
        then
          SELECT COUNT(*) INTO v_cnt2   FROM BILLSUMMARY BS WHERE BS.ACCOUNT_NUM=V_ACCOUNT_NUM AND BILL_TYPE_ID='4' 
          AND EVENT_SEQ is not null;
   
          IF v_cnt2>0
             THEN 
                  V_FINAL_BILL_STATUS:='FINAL BILL DONE';
             ELSE
                   V_FINAL_BILL_sTATUS:='FINAL BILL NOT DONE' ;
          end if;
  else 
     V_FINAL_BILL_sTATUS:=NULL;
  end if;


      
-----DATE OF OPENING
 
 BEGIN 
         SELECT  TRUNC(EFFECTIVE_DTM) into v_open_dt  FROM ACCOUNTSTATUS  
         WHERE ACCOUNT_NUM=v_account_num
         AND ACCOUNT_STATUS='OK'
         ;
 
 exception
 
       when OTHERS then  v_open_dt:=NULL;
  
END;
 
  -----DATE OF CLOSING
BEGIN
         SELECT  count(*) into v_cnt5  FROM ACCOUNTSTATUS
         WHERE ACCOUNT_NUM=v_account_num
         AND ACCOUNT_STATUS='TX';
 
 if v_cnt5>0
   then  
      SELECT  TRUNC(EFFECTIVE_DTM) into v_close_dt  FROM ACCOUNTSTATUS
      WHERE ACCOUNT_NUM=v_account_num
      AND ACCOUNT_STATUS='TX';
    
   else
   
      SELECT  TRUNC(EFFECTIVE_DTM) into v_close_dt  FROM ACCOUNTSTATUS
      WHERE ACCOUNT_NUM=v_account_num
      AND ACCOUNT_STATUS='TA';
      
  end if;   

exception  
  when OTHERS then  v_close_dt:=NULL;  
END; 
   
 -----I/C BARRED STATUS & START DATE
 BEGIN
 IF v_status='ACTIVE'
    THEN  
    
          select COUNT(*) INTO V_CNT6
          from custhasproduct ch,custproductdetails cd 
          where cd.product_seq=ch.product_seq
          and ch.customer_ref=cd.customer_ref
          AND CH.CUSTOMER_REF=V_ACCOUNT_NUM
          and CH.product_id in('176')
          AND CD.END_DAT IS NULL;
          
          if v_cnt6>0
            then 
                 select cd.start_dat INTO V_IC_START_DT
                 from custhasproduct ch,custproductdetails cd 
                 where cd.product_seq=ch.product_seq
                 and ch.customer_ref=cd.customer_ref
                 AND CH.CUSTOMER_REF=V_ACCOUNT_NUM
                 and CH.product_id in('176')
                 AND CD.END_DAT IS NULL;
                    
          END IF;
          
     ELSE
         
         V_IC_START_DT:=NULL;
 END IF;
 
 exception
         when OTHERS then  V_IC_START_DT:=NULL;
  END; 
  
BEGIN
 IF v_status='ACTIVE'
    THEN  
    
     select COUNT(*) INTO V_CNT7
          from custhasproduct ch,custproductdetails cd 
          where cd.product_seq=ch.product_seq
          and ch.customer_ref=cd.customer_ref
          AND CH.CUSTOMER_REF=V_ACCOUNT_NUM
          and CH.product_id in('176')
          AND CD.END_DAT IS NULL;
          
          if v_cnt7>0
            then 
              v_ic_bar_status:='IC BARRED';   
            ELSE
              v_ic_bar_status:=NULL;          
          END IF;
          
     ELSE
         
         v_ic_bar_status:=NULL;
 END IF;
 
 exception
         when OTHERS then  v_ic_bar_status:=NULL;
  END; 
 

   


/*DBMS_OUTPUT.put_line (v_ssa_code||','||v_account_num||','||v_inv_mny||','||v_NEG_inv_mny||','||v_inv_tax_mny||','||
                   v_tot_debit||','||v_tot_credit||','||v_act_pmt_mny||','||v_net_os||','||v_legacy_id||','||v_name||','||v_address||','||v_event_source||','||v_status||','||v_unadj_dep||','||v_act_type||','||V_FINAL_BILL_sTATUS||','||V_EXG_CODE);
*/
                   
                   /*DBMS_OUTPUT.put_line (V_IC_START_DT);*/
 insert into oper_rem.boss_os_list values (v_account_num,v_inv_mny,v_NEG_inv_mny,v_inv_tax_mny,
                   v_tot_debit,v_tot_credit,v_act_pmt_mny,v_net_os,v_legacy_id,v_name,v_address,v_event_source,v_status,
                   v_unadj_dep,v_act_type,V_SSA_CODE,V_FINAL_BILL_sTATUS,V_EXG_CODE,v_open_dt,v_close_dt,v_ic_bar_status,V_IC_START_DT);
 
 
 V_IC_START_DT:=NULL;  
                   
        i_count:=i_count+1;
             If mod(i_count,500)=0 then
                  commit;
             end if;
end if;

       


        
EXCEPTION 
        
              WHEN others THEN DBMS_OUTPUT.put_line (v_account_num||','||V_NET_OS);
         
            end;
   end loop;
   commit;
END;



------for data extraction uncomment and run the following query after plsql is done and copy output to excel 


 /*select SSA_CODE,EXG_CODE,ACCOUNT_NUM,LEGACY_ID,EVENT_SOURCE,ACT_TYPE_SUBTYPE,NAME,
 ADDRESS, INV_MNY ,INV_TAX_MNY ,TOT_DEBIT TOT_BILLED ,ACT_PMT_MNY ,NEG_INV_MNY,TOT_CREDIT TOT_PAID,NET_OS,
 UNADJ_DEPOSIT,FINAL_BILL_STATUS,STATUS ACCOUNT_STATUS,dt_of_opening,dt_of_closure,ic_bar_status,ic_bar_date   
 from oper_rem.boss_os_list */
 
 
 
  ===========================


-----PERFORMANCE STATS :  1133 ACCOUNTS -  6413 RECORDS DONE IN 3574 SEC. @ 4 SECS/ACCT  & 0.5 SEC/RECORD

DECLARE
      v_ssa_code                                              accountattributes.ssa_code%Type;
      v_account_num                                           accountattributes.account_num%Type;
      v_account_num1                                          accountattributes.account_num%Type;
      v_actual_bill_dtm_upto                                  billsummary.actual_bill_dtm%type;
      v_bill_dt                                               billsummary.bill_dtm%Type;
      v_bill_seq                                              billsummary.bill_seq%Type;
      v_min_seq                                               billsummary.bill_seq%Type;
      v_max_seq                                               billsummary.bill_seq%Type;
      v_tot_inv_mny                                           number (18,3) default 0;
      v_os_debt_mny                                           number (18,3) default 0;
      v_invoice_num                                           number (18,3) default 0;
      v_alloc_mny                                             number (18,3) default 0;
      v_alloc_recv_id                                         allocationtobill.receivable_class_id%Type;
      v_br_inv_mny                                            number (18,3) default 0;
      v_ll_inv_mny                                            number (18,3) default 0;
      v_ll_alloc_mny                                          number (18,3) default 0;
      v_ll_os                                                 number (18,3) default 0;
      v_bb_inv_mny                                            number (18,3) default 0;
      v_bb_alloc_mny                                          number (18,3) default 0;
      v_bb_os                                                 number (18,3) default 0;
      v_dep_inv_mny                                           number (18,3) default 0;
      v_dep_alloc_mny                                         number (18,3) default 0;
      v_dep_os                                                number (18,3) default 0;
      v_tot_os                                                number (18,3) default 0;
      v_neg_os                                                number (18,3) default 0;
      v_ll_os1                                                number (18,3) default 0;
      v_bb_os1                                                number (18,3) default 0;
      v_dep_os1                                               number (18,3) default 0;
      v_tot_os1                                               number (18,3) default 0;
      v_neg_os1                                               number (18,3) default 0;
      v_cnt                                                   number default 0;
      v_cnt1                                                  number default 0;
      v_cnt2                                                  number default 0;
      v_cnt3                                                  number default 0;
      i_count                                                 number default 0; 


 
 
 cursor boss2 is 
 
 select account_num  from B198903611_DB.BOSS_acct /*where account_num='1001565820'*/;
         
 
 begin
         
         select sysdate into v_actual_bill_dtm_upto from dual;
         
           v_ssa_code:='SPR';
           /*v_actual_bill_dtm_upto:='26-SEP-2011';*/
          
       <<outerloop>>         
              for x in boss2
              
            
                   loop  
                  
                     begin
                           
                        v_account_num:=x.account_num;
                                               
                           SELECT   NVL(abs(sum(BS.OUTSTANDING_DEBT_MNY)/1000),0)  into v_neg_os 
                            FROM BILLSUMMARY bs 
                           WHERE bs.account_num=v_account_num  
                           and bill_settled_boo='F' 
                           and bill_status in ('1','7','8')
                           and  bs.outstanding_debt_mny<0;
                           
                         
                          
                                     
                           if v_neg_os>0
                               then
                                 SELECT MIN(BILL_SEQ) INTO V_MIN_SEQ  FROM B198903611_DB.BOSS_INV_WISE_OS BS
                                 WHERE BS.ACCOUNT_NUM=V_ACCOUNT_NUM
                                 and  bs.TOT_OS>0;
                                 
                              
                                 
                                 select max(bill_seq) into v_max_seq 
                                 from B198903611_DB.BOSS_INV_WISE_OS
                                 where account_num=v_account_num;
                               
                                 
                                 WHILE V_NEG_OS>0 
                                    LOOP
                                     
                                        
                                        update B198903611_DB.BOSS_INV_WISE_OS set neg_os_bal=0 where account_num=v_account_num;
                                        
                                        UPDATE B198903611_DB.BOSS_INV_WISE_OS SET FLAG='T' WHERE ACCOUNT_NUM=V_ACCOUNT_NUM;
                                        
                                        commit;
                                                                        
                                        exit  when v_min_seq>v_max_seq;
                                    
                                       
                                       SELECT COUNT(*) INTO V_CNT FROM B198903611_DB.BOSS_INV_WISE_OS
                                       WHERE ACCOUNT_NUM=V_ACCOUNT_NUM
                                       and BILL_SEQ=V_MIN_SEQ;
                          
                                  
                                                                            
                                         IF V_CNT>0 THEN
                                         
                                         
                                         
                                            SELECT TOT_OS INTO V_TOT_OS FROM B198903611_DB.BOSS_INV_WISE_OS
                                            WHERE ACCOUNT_NUM=V_ACCOUNT_NUM
                                            and BILL_SEQ=V_MIN_SEQ;
                                            
                                   
                                            
                                                  IF V_TOT_OS<V_NEG_OS THEN
                                                  
                                                     UPDATE B198903611_DB.BOSS_INV_WISE_OS SET TOT_OS=0,LL_OS=0,BB_OS=0,DEP_OS=0
                                                     WHERE ACCOUNT_NUM=V_ACCOUNT_NUM
                                                     AND BILL_SEQ=V_MIN_SEQ;
                                                     
                                                     UPDATE B198903611_DB.BOSS_INV_WISE_OS SET NEG_OS=V_TOT_OS
                                                     WHERE ACCOUNT_NUM=V_ACCOUNT_NUM
                                                     AND BILL_SEQ=V_MIN_SEQ;
                                                
                                                    
                                                     
                                                     COMMIT;
                                                     
                                                     V_NEG_OS:=V_NEG_OS-V_TOT_OS;    
                                                     
                                                                                   
                                                     
                                                     
                                                  
                                            
                                                  ELSIF V_TOT_OS>V_NEG_OS THEN
                                            
                                                        UPDATE B198903611_DB.BOSS_INV_WISE_OS SET TOT_OS=TOT_OS-V_NEG_OS
                                                        WHERE ACCOUNT_NUM=V_ACCOUNT_NUM
                                                        AND BILL_SEQ=V_MIN_SEQ;
                                                        
                                                        UPDATE B198903611_DB.BOSS_INV_WISE_OS SET NEG_OS=V_NEG_OS
                                                        WHERE ACCOUNT_NUM=V_ACCOUNT_NUM
                                                        AND BILL_SEQ=V_MIN_SEQ;
                                                        
                                                        select ll_os,bb_os,dep_os into v_ll_os1,v_bb_os1,v_dep_os1
                                                        from B198903611_DB.BOSS_INV_WISE_OS
                                                        WHERE ACCOUNT_NUM=V_ACCOUNT_NUM
                                                        AND BILL_SEQ=V_MIN_SEQ;
                                                        
                                                       if v_dep_os1>V_NEG_OS then
                                                        
                                                              UPDATE B198903611_DB.BOSS_INV_WISE_OS SET dep_os=v_dep_os1-V_NEG_OS
                                                              WHERE ACCOUNT_NUM=V_ACCOUNT_NUM
                                                              AND BILL_SEQ=V_MIN_SEQ;
                                                        
                                                              V_NEG_OS:=0;
                                                        
                                                        else 
                                                        
                                                              UPDATE B198903611_DB.BOSS_INV_WISE_OS SET dep_os=0
                                                              WHERE ACCOUNT_NUM=V_ACCOUNT_NUM
                                                              AND BILL_SEQ=V_MIN_SEQ;
                                                              
                                                              V_NEG_OS:=V_NEG_OS-v_dep_os1;
                                                              
                                                              
                                                         end if;
                                                        

                                                        
                                                        if v_ll_os1>V_NEG_OS then
                                                        
                                                              UPDATE B198903611_DB.BOSS_INV_WISE_OS SET ll_os=v_ll_os1-V_NEG_OS
                                                              WHERE ACCOUNT_NUM=V_ACCOUNT_NUM
                                                              AND BILL_SEQ=V_MIN_SEQ;
                                                        
                                                              V_NEG_OS:=0;
                                                        
                                                        else 
                                                        
                                                              UPDATE B198903611_DB.BOSS_INV_WISE_OS SET ll_os=0
                                                              WHERE ACCOUNT_NUM=V_ACCOUNT_NUM
                                                              AND BILL_SEQ=V_MIN_SEQ;
                                                              
                                                              V_NEG_OS:=V_NEG_OS-v_ll_os1;
                                                              
                                                        end if;
                                                              
                                                              
                                                        if v_bb_os1>V_NEG_OS then
                                                        
                                                              UPDATE B198903611_DB.BOSS_INV_WISE_OS SET bb_os=v_bb_os1-V_NEG_OS
                                                              WHERE ACCOUNT_NUM=V_ACCOUNT_NUM
                                                              AND BILL_SEQ=V_MIN_SEQ;
                                                        
                                                              V_NEG_OS:=0;
                                                        
                                                        else 
                                                        
                                                              UPDATE B198903611_DB.BOSS_INV_WISE_OS SET bb_os=0
                                                              WHERE ACCOUNT_NUM=V_ACCOUNT_NUM
                                                              AND BILL_SEQ=V_MIN_SEQ;
                                                              
                                                              V_NEG_OS:=V_NEG_OS-v_bb_os1;
                                                              
                                                              
                                                        end if;
                                                              
                                                        
                                                     
                                                        
                                                        COMMIT;
                                                        
                                                        V_NEG_OS:=0;
                                                   
                                                   
                                                   END IF;  
                                                   
                                                         V_MIN_SEQ:=V_MIN_SEQ+1;
                                                     
                                                         
                                                         
                                           ELSif  V_MIN_SEQ<v_max_seq then 
                                            
                                                      V_MIN_SEQ:=V_MIN_SEQ+1;
                                           
                                           
                                           
                                           END IF;
                                           
   
                                                                 
                              END LOOP;  
                              
                                   
                                                      update B198903611_DB.BOSS_INV_WISE_OS set neg_os_bal=v_neg_os 
                                                      where ACCOUNT_NUM=V_ACCOUNT_NUM 
                                                      and bill_seq=v_max_seq;  
                                                      
                                                      COMMIT;                 
 
                           END IF;
 
                  EXCEPTION 
                         WHEN others THEN DBMS_OUTPUT.put_line ( sqlerrm||' , ' ||v_account_num||' , '||V_MIN_SEQ||' , '||v_max_seq); 
                         
                            commit;           
                                    
                  END;
                  
           
            END LOOP;
            
          
                
                         
  END;


------QUERY FOR DATA TO BE SENT TO SSA.   COPY THIS QUERY TO A SEPARATE WINDOW AND RUN.


/*SELECT SSA_CODE,ACCOUNT_NUM,BILL_DATE,ACTUAL_BILL_DTM,INVOICE_NUM,
TOTAL_INV_MNY,  LL_OS, BB_OS, DEP_OS, TOT_OS FROM BOSS_INV_WISE_OS
WHERE TOT_OS>0
ORDER BY 1,2,3*/
=========================


----THIS PROCEDURE GIVES YOU DETAILS OF PRODUCTS REMAINING UNDER "SUSPENDED" STATUS EVEN AFTER TERMINATION OF I/C BARRING PRODUCT.  
---- THE SUSPENDED STATUS OF CHARGEABLE PRODUCTS RESULTS IN REVENUE LOSS DUE TO NON-BILLING OF FMC.


DECLARE

v_ssa_code                                              accountattributes.ssa_code%Type;
v_account_num                                           billsummary.account_num%Type;
v_prod_id1                                              number(5);
v_max_effect_dt                                         date;
v_prod_seq                                              number (9);
v_ic_prod_seq                                           number (9);
v_subs_prod_seq                                         number (9);
v_prod_id                                               number(5);
v_prod_max_effect_dt                                    date;
v_prod_stat                                             varchar2(10);
v_parent_prod_stat                                      varchar2(10);
v_prod_stat1                                            varchar2(10);
v_prod_name                                             product.product_name%Type;
i_count                                                 number default 0 ; 
V_CNT1                                                  number default 0 ; 
V_CNT2                                                  number default 0 ; 



  cursor boss is 
                                      select distinct  cps.customer_ref, chp.product_id,chp.subs_product_seq,max(cps.effective_dtm) max_effect_dt
                                      from custproductstatus cps,custhasproduct chp, custproductdetails cpd,product p
                                      where cps.customer_ref=chp.customer_ref
                                      and cps.customer_ref=cpd.customer_ref
                                      and cps.product_seq=chp.product_seq
                                      and cps.product_seq=cpd.product_seq
                                      and chp.product_id=p.product_id
                                     /* AND CPS.CUSTOMER_REF ='1011999063'*/
                                      /*and cps.product_status='TX'*/
                                      and chp.product_id='176'
                                      and cps.customer_ref in (select account_num from oper_rem.boss_acct)
                                      group by cps.customer_ref, chp.product_id,chp.subs_product_seq;
  
   cursor boss1 is 
                               
                                    select distinct  cps.product_seq,chp.product_id,max(cps.effective_dtm) prod_max_effect_dt                                    
                                    from custproductstatus cps,custhasproduct chp, custproductdetails cpd,product p
                                    where cps.customer_ref=chp.customer_ref
                                    and cps.customer_ref=cpd.customer_ref
                                    and cps.product_seq=chp.product_seq
                                    and cps.product_seq=cpd.product_seq
                                    and chp.product_id=p.product_id
                                    and cps.customer_ref = v_account_num
                                    and chp.subs_product_seq=v_subs_prod_seq
                                    and chp.product_id not in('111','176','177','263')
                                    group by cps.product_seq,chp.product_id ;


   cursor boss2 is 

                                    select distinct   cps.product_seq
                                    from custproductstatus cps,custhasproduct chp, custproductdetails cpd,product p
                                    where cps.customer_ref=chp.customer_ref
                                    and cps.customer_ref=cpd.customer_ref
                                    and cps.product_seq=chp.product_seq
                                    and cps.product_seq=cpd.product_seq
                                    and chp.product_id=p.product_id
                                    and cpd.end_dat is null
                                    and cps.customer_ref = v_account_num
                                    and chp.product_id =v_prod_id
                                    and chp.subs_product_seq=v_subs_prod_seq
                                    and cps.effective_dtm=v_prod_max_effect_dt;       

BEGIN 

         /*  delete from oper_rem.boss_susp_product;                                                                                                                             
           commit;*/
           
   for x  in boss
          loop
              begin
                   
                   v_account_num           :=x.customer_ref;
                   v_prod_id1              :=x.product_id;
                   v_subs_prod_seq         :=x.subs_product_seq;
                   v_max_effect_dt         :=x.max_effect_dt;
                   /*dbms_output.put_line(v_account_num||','||v_max_effect_dt||','||v_subs_prod_seq);*/
                   
                   
                   select distinct cps.product_status, cps.product_seq,subs_product_seq 
                   into v_prod_stat,v_prod_seq,v_subs_prod_seq 
                   from custproductstatus cps,custhasproduct chp
                    where cps.customer_ref=chp.customer_ref
                    and cps.product_seq=chp.product_seq
                    and chp.product_id='176'
                    and cps.customer_ref=v_account_num
                    and cps.effective_dtm=v_max_effect_dt
                    and chp.subs_product_seq=v_subs_prod_seq;
                    
                    /*dbms_output.put_line(v_prod_stat||','||v_prod_seq||','||v_subs_prod_seq);*/
                    if v_prod_stat='TX' then                                 
                   
                     for x  in boss1  
                        loop                          
                                    
                            begin      
                              
                              v_prod_seq               :=x.product_seq;
                              v_prod_id               :=x.product_id;
                              v_prod_max_effect_dt    :=x.prod_max_effect_dt;
  
                              
                                    select ssa_code into v_ssa_code from accountattributes where account_num=v_account_num;
                                   
                                   SELECT COUNT(*) INTO V_CNT1 FROM CUSTPRODUCTSTATUS CPS
                                   WHERE CPS.CUSTOMER_REF=V_ACCOUNT_NUM
                                   AND CPS.PRODUCT_STATUS='SU';
                                  
                                   
                                   IF V_CNT1>0 THEN
                                       for x  in boss2 
                                       
                                           loop
                                           
                                              begin 
                                    
                           
                                                        v_prod_seq   :=x.product_seq;
                                                        
                                                        
                                                        
                                                                                                                      
                                                             select  count(*) into v_cnt2
                                                             from custhasproduct chp, custproductdetails cpd 
                                                             where cpd.customer_ref=chp.customer_ref
                                                             and cpd.product_seq=chp.product_seq
                                                             and cpd.end_dat is null
                                                             AND CPD.CUSTOMER_REF=v_account_num
                                                             and cpd.product_seq=v_subs_prod_seq;
                                                             
                                                             
                                                             if v_cnt2>0 then
                                                        
                                                             select  distinct p.product_name,cps.product_status  into v_prod_name,v_prod_stat1
                                                             from custproductstatus cps,custhasproduct chp, custproductdetails cpd,product p
                                                             where cps.customer_ref=chp.customer_ref
                                                             and cps.customer_ref=cpd.customer_ref
                                                             and cps.product_seq=chp.product_seq
                                                             and cps.product_seq=cpd.product_seq
                                                             and chp.product_id=p.product_id
                                                             and cpd.end_dat is null
                                                             and cps.customer_ref = v_account_num
                                                             and chp.product_id =v_prod_id
                                                             and cps.product_seq=v_prod_seq
                                                             and cps.effective_dtm=v_prod_max_effect_dt ;
                                                        
                                      
                                                                         if v_prod_stat1='SU' THEN
                             
                                                                            DBMS_OUTPUT.PUT_LINE(v_ssa_code||'|'||v_account_num||'|'||v_prod_id||'|'||v_prod_seq||'|'||v_prod_name||'|'||v_prod_stat1||'|'||v_prod_max_effect_dt||'|'||V_MAX_effect_DT);
                                                                            /*insert into oper_rem.boss_susp_product(ssa_code,account_num,product_id,product_name,current_status,suspended_dt,ic_bar_end_dt,PRODUCT_SEQ) 
                                                                            values(v_ssa_code, v_account_num, v_prod_id,v_prod_name,v_prod_stat1,v_prod_max_effect_dt,V_MAX_effect_DT,v_prod_seq);
                                                                            */
                                                                         end if;
                                                             end if;
                                                 end;
                                              end loop;
                                      END IF;
                               EXCEPTION  
                               
                                     WHEN OTHERS THEN dbms_output.put_line(v_account_num||'  '||SQLCODE||' - '||v_prod_id||' - PRODUCT IS '||v_prod_stat1);
                             
                             end;   
                                            /*  i_count:=i_count+1;
                                              If mod(i_count,500)=0 then
                                              commit;
                                              end if;*/
                                               
                        end loop;
                        
                        end if;
                         
        
EXCEPTION 
        
           /*  When others then raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);*/
           when others then dbms_output.put_line(v_account_num||' - '||SQLCODE||' - '||SQLERRM||' - PRODUCT IS  '||v_prod_stat1);

         
            end;
   end loop;
   commit;
END;


====================-=-=
SQL (Structured Query Language) and PL/SQL (Procedural Language/SQL) are both integral components of Oracle databases, but they serve different purposes and have distinct characteristics. Here’s a detailed comparison of SQL and PL/SQL:

Feature

SQL

PL/SQL

Definition

SQL is a standard language for managing and manipulating relational databases.

PL/SQL is Oracle's procedural extension to SQL, allowing for procedural programming capabilities within SQL.

Type

Declarative language

Procedural language

Purpose

Used for querying, updating, inserting, and deleting data in a database.

Used for writing complex programs that involve SQL statements, control structures, and procedural logic.

Structure

Consists of simple SQL statements (e.g., SELECT, INSERT, UPDATE, DELETE).

Consists of blocks of code that can contain SQL statements, variable declarations, loops, conditions, and error handling.

Execution

SQL statements are executed one at a time.

PL/SQL code blocks can be executed in one go, allowing for multiple SQL statements to run together.

Control Structures

Does not support control structures (e.g., loops, conditional statements).

Supports control structures (e.g., IF, CASE, FOR, WHILE) allowing for conditional logic and looping.

Error Handling

Limited error handling; does not provide explicit mechanisms for error management.

Has robust error handling capabilities using exceptions, allowing developers to manage errors gracefully.

Performance

Efficient for simple queries; however, performance may degrade with complex operations due to multiple round-trips to the database.

More efficient for complex operations as it minimizes the number of database calls by executing multiple SQL statements in a single block.

Variable Declaration

Does not support variable declaration.

Supports the declaration of variables and constants, enabling dynamic programming capabilities.

Usage Context

Used for direct database operations.

Used for creating stored procedures, functions, triggers, and packages.

Result Sets

Returns result sets directly (e.g., from SELECT statements).

Can return results through output parameters in stored procedures and functions.

Database Dependency

Standard SQL is used across various database systems (e.g., MySQL, PostgreSQL, SQL Server).

PL/SQL is specific to Oracle databases; similar procedural languages exist in other databases (e.g., T-SQL in SQL Server, PL/pgSQL in PostgreSQL).



### Key Points

1. **Declarative vs. Procedural**:
   - **SQL** is a declarative language where you specify what you want to retrieve or manipulate without detailing how to do it.
   - **PL/SQL** adds procedural features to SQL, enabling developers to write complex logic and control the flow of execution.

2. **Execution Environment**:
   - SQL statements are executed independently and return results immediately.
   - PL/SQL blocks can include multiple SQL statements and procedural logic, and they execute together as a unit.

3. **Use Cases**:
   - **SQL** is primarily used for data retrieval and manipulation.
   - **PL/SQL** is used for creating applications, complex business logic, batch processing, and managing database transactions.

4. **Error Handling**:
   - SQL has minimal error handling capabilities, often returning an error code or message.
   - PL/SQL allows for structured error handling using exceptions, providing better control over how errors are processed.

5. **Efficiency**:
   - For simple queries, SQL may be sufficient.
   - For complex logic requiring multiple queries or procedural logic, PL/SQL is typically more efficient due to reduced network traffic and execution overhead.

### Conclusion

In summary, while SQL and PL/SQL are both crucial for interacting with Oracle databases, they serve different roles. SQL is best suited for data manipulation and retrieval, whereas PL/SQL is ideal for developing more complex applications that require procedural programming features alongside SQL capabilities. Understanding the strengths and appropriate use cases for each can lead to more efficient database programming and application development.
====
Yes, the basic structure of PL/SQL (Procedural Language/SQL) consists of several key components that allow developers to write complex database programs. PL/SQL is organized into blocks, which can include both SQL statements and procedural logic. Below is an overview of the basic structure of PL/SQL, including the essential components:

### Basic Structure of PL/SQL

A PL/SQL block typically consists of three main sections:

1. **Declaration Section**
2. **Executable Section**
3. **Exception Handling Section**

Here’s a more detailed look at each section:

#### 1. **Declaration Section**

- This section is optional. It is used to declare variables, constants, cursors, and other program objects.
- Variables can hold data temporarily during program execution.

**Syntax:**
```plsql
DECLARE
    variable_name data_type [DEFAULT value];
    cursor_name CURSOR FOR SELECT_statement;
```

**Example:**
```plsql
DECLARE
    v_employee_name VARCHAR2(100);
    v_salary NUMBER(10, 2) DEFAULT 0;
    CURSOR emp_cursor IS SELECT employee_name FROM employees;
```

#### 2. **Executable Section**

- This section is mandatory and contains the actual code that performs the operations.
- It includes SQL statements, procedural statements (like loops and conditionals), and function calls.
- This section is where the main logic of the program is executed.

**Syntax:**
```plsql
BEGIN
    -- SQL statements
    SELECT INTO variable_name FROM table_name WHERE condition;
    
    -- PL/SQL statements (control structures, etc.)
    IF condition THEN
        -- Statements
    ELSIF condition THEN
        -- Statements
    ELSE
        -- Statements
    END IF;
    
    FOR record IN cursor_name LOOP
        -- Statements
    END LOOP;
END;
```

**Example:**
```plsql
BEGIN
    SELECT employee_name INTO v_employee_name FROM employees WHERE employee_id = 1;
    DBMS_OUTPUT.PUT_LINE('Employee Name: ' || v_employee_name);

    FOR emp_record IN emp_cursor LOOP
        DBMS_OUTPUT.PUT_LINE('Employee Name: ' || emp_record.employee_name);
    END LOOP;
END;
```

#### 3. **Exception Handling Section**

- This section is optional but highly recommended. It is used to handle exceptions or errors that may occur during the execution of the program.
- You can define specific exceptions to catch different error conditions and provide appropriate handling logic.

**Syntax:**
```plsql
EXCEPTION
    WHEN exception_name THEN
        -- Statements to handle the exception
    WHEN OTHERS THEN
        -- Statements to handle any other exceptions
END;
```

**Example:**
```plsql
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('No employee found with the given ID.');
    WHEN TOO_MANY_ROWS THEN
        DBMS_OUTPUT.PUT_LINE('More than one employee found with the given ID.');
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('An unexpected error occurred: ' || SQLERRM);
END;
```

### Complete Example of a PL/SQL Block

Here’s a complete example that combines all sections:

```plsql
DECLARE
    v_employee_name VARCHAR2(100);
    v_salary NUMBER(10, 2) DEFAULT 0;
    CURSOR emp_cursor IS SELECT employee_name FROM employees;
BEGIN
    -- Fetch a specific employee
    SELECT employee_name, salary INTO v_employee_name, v_salary
    FROM employees
    WHERE employee_id = 1;

    DBMS_OUTPUT.PUT_LINE('Employee Name: ' || v_employee_name || ', Salary: ' || v_salary);

    -- Loop through all employees
    FOR emp_record IN emp_cursor LOOP
        DBMS_OUTPUT.PUT_LINE('Employee Name: ' || emp_record.employee_name);
    END LOOP;
    
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('No employee found with the given ID.');
    WHEN TOO_MANY_ROWS THEN
        DBMS_OUTPUT.PUT_LINE('More than one employee found with the given ID.');
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('An unexpected error occurred: ' || SQLERRM);
END;
```

### Summary

- **PL/SQL Block Structure**: Each PL/SQL block consists of the Declaration section, Executable section, and (optionally) the Exception Handling section.
- **Flexibility**: The structure allows for complex programming constructs while integrating SQL seamlessly.
- **Error Handling**: Exception handling is an important feature in PL/SQL that provides control over how errors are managed during execution.

This structure allows PL/SQL to efficiently handle data operations while incorporating the advantages of procedural programming, making it a powerful tool for Oracle database developers.
===
The PL/SQL compilation process is a critical aspect of how PL/SQL code is executed in Oracle databases. This process involves several stages, from the writing of the PL/SQL code to its execution. Here’s a detailed overview of the PL/SQL compilation process:

### Steps in the PL/SQL Compilation Process

1. **Source Code Creation**
   - Developers write PL/SQL code in the form of anonymous blocks, procedures, functions, packages, or triggers using a text editor or an integrated development environment (IDE).
   - This source code can be stored in the database or in external files.

2. **Compilation Request**
   - When the PL/SQL code is executed (either directly or through a command like `CREATE` or `ALTER` for stored procedures/functions), a compilation request is sent to the Oracle database.
   - This request initiates the compilation process.

3. **Syntax Check**
   - The PL/SQL compiler first checks the syntax of the code to ensure it adheres to the PL/SQL language rules.
   - If there are any syntax errors, the compilation fails, and error messages are returned to the developer.

4. **Semantic Check**
   - After the syntax check, the compiler performs semantic analysis to ensure that the code is logically correct.
   - This includes checking:
     - Variable declarations
     - Data types
     - Scope and visibility of identifiers
     - Existence of referenced database objects (like tables, views, etc.)
   - If any semantic errors are found, they are reported, and the compilation fails.

5. **Optimization**
   - The PL/SQL compiler optimizes the code for better performance. This can include optimizing SQL statements, managing memory, and reordering operations.
   - The goal is to enhance execution efficiency while maintaining the same functionality.

6. **Code Generation**
   - The compiler generates an intermediate form of the PL/SQL code, which is often in the form of bytecode (also known as the PL/SQL intermediate representation).
   - This bytecode is stored in the database as part of the PL/SQL program unit (like a procedure or function).

7. **Storage in the Database**
   - The compiled PL/SQL code is stored in the Oracle database's data dictionary. This allows the database to reference the compiled code during execution without needing to recompile it each time.
   - The database maintains metadata about the PL/SQL program units, including their names, types, and associated bytecode.

8. **Execution**
   - When the PL/SQL code is called, the database retrieves the compiled bytecode from storage.
   - The execution engine runs the bytecode, executing the PL/SQL logic and any embedded SQL statements.
   - The execution context includes memory allocation, variable values, and any exceptions that might arise during runtime.

9. **Error Handling**
   - During execution, if any runtime errors occur (like division by zero, invalid cursor operations, etc.), the PL/SQL engine raises exceptions.
   - Exception handling can be implemented in the PL/SQL code to manage these errors gracefully.

10. **Re-compilation (if necessary)**
    - If changes are made to the PL/SQL code, it must be recompiled. This may happen automatically if the program unit is modified.
    - Additionally, if dependent objects (like tables or views) change, the PL/SQL code may need recompilation to ensure compatibility.

### Summary of Key Points

- **Compilation Phases**: The compilation process includes syntax checking, semantic analysis, optimization, code generation, and storage.
- **Bytecode Generation**: The final output of the compilation process is bytecode, which is stored in the database for efficient execution.
- **Performance**: Compiling PL/SQL code reduces the need for repeated parsing and interpretation, leading to improved performance during execution.
- **Error Management**: The process includes mechanisms for error detection and handling at both the compilation and execution stages.

This compilation process allows PL/SQL to offer a powerful and efficient programming model that integrates procedural logic with SQL, making it suitable for complex database applications.

===

Stored procedures in PL/SQL are precompiled collections of PL/SQL code that are stored in the database. They can be executed as needed, allowing for efficient reuse of code, centralized logic, and better management of database operations. Here’s a detailed overview of stored procedures in PL/SQL, including their purpose, structure, advantages, and how to create and execute them.

### Overview of Stored Procedures

1. **Definition**:
   - A **stored procedure** is a named PL/SQL block that can accept parameters, perform operations (such as data manipulation or querying), and return results. It is stored in the database for reuse.

2. **Characteristics**:
   - **Precompiled**: Stored procedures are compiled and stored in the database, which improves performance as they do not require recompilation each time they are called.
   - **Modular**: They promote modular programming, allowing developers to break down complex processes into manageable sub-programs.
   - **Encapsulation**: Stored procedures encapsulate business logic and can enforce data integrity and security by controlling access to database operations.

### Structure of a Stored Procedure

A typical stored procedure has the following structure:

```plsql
CREATE [OR REPLACE] PROCEDURE procedure_name 
[(parameter_name data_type [IN | OUT | IN OUT])] 
IS
    -- Declaration section (optional)
    variable declarations
BEGIN
    -- Executable section
    SQL statements and PL/SQL logic
    -- Optional: Return values if needed
EXCEPTION
    -- Exception handling section (optional)
    WHEN exception_name THEN
        -- Handle exceptions
END procedure_name;
```

### Components of a Stored Procedure

1. **Header**:
   - **CREATE [OR REPLACE] PROCEDURE**: Specifies the creation of the procedure. `OR REPLACE` allows for modifying an existing procedure.
   - **Procedure Name**: The name used to call the procedure.
   - **Parameters**: Optional; can be input (IN), output (OUT), or both (IN OUT).

2. **Declaration Section**:
   - Optional section to declare variables, cursors, and other program entities that will be used in the procedure.

3. **Executable Section**:
   - This mandatory section contains the logic of the procedure, including SQL statements and PL/SQL constructs.

4. **Exception Handling Section**:
   - Optional section to handle exceptions or errors that may occur during execution.

### Example of a Stored Procedure

Here’s an example of a simple stored procedure that retrieves employee details based on an employee ID:

```plsql
CREATE OR REPLACE PROCEDURE GetEmployeeDetails (
    p_employee_id IN NUMBER,          -- Input parameter
    p_employee_name OUT VARCHAR2,     -- Output parameter
    p_employee_salary OUT NUMBER       -- Output parameter
IS
BEGIN
    -- SQL statement to fetch employee details
    SELECT employee_name, salary 
    INTO p_employee_name, p_employee_salary
    FROM employees
    WHERE employee_id = p_employee_id;

EXCEPTION
    WHEN NO_DATA_FOUND THEN
        p_employee_name := 'Not Found';
        p_employee_salary := 0;
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('An unexpected error occurred: ' || SQLERRM);
END GetEmployeeDetails;
```

### Calling a Stored Procedure

Stored procedures can be invoked from various interfaces, including SQL*Plus, PL/SQL blocks, and application programming languages. Here’s an example of how to call the `GetEmployeeDetails` procedure from an anonymous PL/SQL block:

```plsql
DECLARE
    v_name VARCHAR2(100);
    v_salary NUMBER;
BEGIN
    -- Calling the stored procedure
    GetEmployeeDetails(1, v_name, v_salary);
    DBMS_OUTPUT.PUT_LINE('Employee Name: ' || v_name || ', Salary: ' || v_salary);
END;
```

### Advantages of Using Stored Procedures

1. **Performance**:
   - Stored procedures are precompiled, which reduces execution time since they do not need to be parsed each time they are run.

2. **Code Reusability**:
   - Once created, stored procedures can be reused across different applications or processes, reducing code duplication.

3. **Security**:
   - Stored procedures can restrict direct access to database tables, allowing users to execute procedures without granting them full table privileges.

4. **Maintainability**:
   - Changes can be made to a stored procedure without affecting the calling applications, which can simplify maintenance and version control.

5. **Centralized Business Logic**:
   - They allow for centralized management of business logic, making it easier to enforce rules and regulations consistently across applications.

6. **Error Handling**:
   - Stored procedures can include robust error handling mechanisms to manage exceptions gracefully.

### Summary

Stored procedures in PL/SQL are powerful tools that encapsulate business logic and data manipulation within the database. They enhance performance, security, maintainability, and reusability of code, making them a critical component in developing robust database applications. Understanding how to create, manage, and call stored procedures is essential for effective Oracle database programming.
====

Triggers

In PL/SQL, a trigger is a stored procedure that is automatically executed, or "triggered," by the database when a specific event occurs. Triggers are commonly used to enforce complex business rules, audit changes, or automatically respond to changes in the database.

 

# Key Concepts of PL/SQL Triggers

 

1. Automatic Execution:

   - Triggers run automatically in response to events on a table or view, such as `INSERT`, `UPDATE`, or `DELETE`.

  

2. Event-Based Logic:

   - A trigger can be set to activate before or after an event on a table.

   - It can also be defined to fire for each row affected by the event or just once per SQL statement.

 

3. Types of Triggers:

   - DML Triggers: Triggered by Data Manipulation Language (DML) operations like `INSERT`, `UPDATE`, or `DELETE`.

   - DDL Triggers: Triggered by Data Definition Language (DDL) operations like `CREATE`, `ALTER`, or `DROP`.

   - INSTEAD OF Triggers: Used on views to handle `INSERT`, `UPDATE`, or `DELETE` operations that cannot be performed directly.

   - Compound Triggers: Special triggers that consolidate multiple timing points (like `BEFORE`, `AFTER`) in a single structure, particularly useful for managing complex row-level processing.

 

4. Structure of a Basic DML Trigger:

   ```sql

   CREATE [OR REPLACE] TRIGGER trigger_name

   {BEFORE | AFTER} {INSERT | UPDATE | DELETE}

   ON table_name

   [FOR EACH ROW]

   DECLARE

       -- Variable declarations

   BEGIN

       -- Trigger logic (PL/SQL code)

   END;

   ```

   - BEFORE or AFTER specifies whether the trigger should fire before or after the event.

   - FOR EACH ROW specifies that the trigger should execute once for each row affected (row-level trigger).

   - Without `FOR EACH ROW`, the trigger is statement-level, executing only once per SQL statement.

 

5. OLD and NEW Keywords:

   - Within a row-level trigger, the `:OLD` and `:NEW` keywords allow access to column values before and after the DML event.

   - `:OLD.column_name` refers to the value before the event.

   - `:NEW.column_name` refers to the value after the event (inserts and updates only).

 

6. Example:

   ```sql

   CREATE OR REPLACE TRIGGER trg_audit_employee

   AFTER INSERT OR UPDATE ON employees

   FOR EACH ROW

   BEGIN

       INSERT INTO employee_audit (employee_id, action, change_date)

       VALUES (:NEW.employee_id, 'INSERT or UPDATE', SYSDATE);

   END;

   ```

   This trigger records an audit entry in the `employee_audit` table every time a row is inserted or updated in the `employees` table. 

# Uses of Triggers

- Data Auditing: Logging changes to data for tracking history.

- Data Validation: Enforcing business rules before data is committed.

- Derived Columns: Automatically calculating or updating values.

- Security: Controlling access to table rows based on complex logic. 

Triggers in PL/SQL can enhance data integrity and automate common database tasks, but they should be used with caution to avoid performance impacts, especially when dealing with high-transaction tables.

====

PL/SQL, the procedural extension of SQL for Oracle databases, offers a variety of data types, allowing developers to handle different kinds of data effectively. Here’s a breakdown of key data types in PL/SQL:

 

 1. Scalar Data Types

   Scalar data types hold a single value. These include:

 

   - Numeric Types:

     - `NUMBER(p, s)`: Used for fixed and floating-point numbers with precision `p` and scale `s`.

     - `INTEGER`, `INT`, `SMALLINT`: Variants of `NUMBER` typically for whole numbers.

     - `BINARY_FLOAT`, `BINARY_DOUBLE`: Represent single and double-precision floating-point numbers, respectively.

 

   - Character Types:

     - `CHAR(n)`: Fixed-length character string, padded with spaces up to `n` characters.

     - `VARCHAR2(n)`: Variable-length character string up to `n` characters (most commonly used).

     - `NCHAR(n)`, `NVARCHAR2(n)`: Character strings that support Unicode data, with fixed and variable lengths.

 

   - Date/Time Types:

     - `DATE`: Stores date and time to the second, including day, month, year, hours, minutes, and seconds.

     - `TIMESTAMP`: Extends `DATE` to include fractional seconds.

     - `TIMESTAMP WITH TIME ZONE`, `TIMESTAMP WITH LOCAL TIME ZONE`: Store timestamps with timezone information.

 

   - Boolean Type:

     - `BOOLEAN`: Holds `TRUE`, `FALSE`, or `NULL` values. Commonly used in control statements, though not directly storable in the database.

 

 2. Composite Data Types

   Composite types allow grouping of multiple values. These are helpful for managing collections of related data.

 

   - Records:

     - `RECORD`: Allows defining a custom structure with multiple fields of different types. Useful for handling row structures.

       ```plsql

       TYPE employee_record IS RECORD (

           emp_id     NUMBER,

           emp_name   VARCHAR2(100),

           emp_salary NUMBER

       );

       ```

 

   - Collections:

     - Associative Arrays (formerly called index-by tables): Arrays with key-value pairs, where the keys are not consecutive integers.

     - Nested Tables: A one-dimensional array that can store a variable number of elements, can be stored in the database.

     - VARRAYs (Variable-Size Arrays): Similar to nested tables but have a maximum size and must be consecutive elements.

       ```plsql

       TYPE num_array IS VARRAY(10) OF NUMBER;

       ```

 

 3. LOB (Large Object) Data Types

   LOBs are used for storing large amounts of data, such as images or documents.

 

   - `BLOB`: Binary Large Object, used to store binary data like images, audio, etc.

   - `CLOB`: Character Large Object, used for large text data.

   - `NCLOB`: CLOB supporting Unicode.

   - `BFILE`: Pointer to a file stored outside the database, like on the server's filesystem.

 

 4. Reference Data Types

   Used to store pointers or references to database objects.

 

   - REF CURSOR: A pointer to a result set returned by a query. Often used in procedures and functions to pass query results.

   - SYS_REFCURSOR: A predefined weak `REF CURSOR` that can be used without explicit type declaration.

 

 5. User-Defined Data Types

   PL/SQL also allows defining custom types, which can be based on existing types or combinations of types.

 

   - User-Defined Records: Allows creating a custom structured type with fields.

   - User-Defined Collections: Using the `TABLE` or `VARRAY` types, you can define custom collections of a specific type.

 

 6. Other Special Types

   - RAW: Used to store binary or byte-oriented data, primarily for data that should not be converted to a character set.

   - UROWID: A universal row identifier used for identifying rows in tables with a primary key. 

Each of these data types in PL/SQL allows precise control over data, enabling efficient manipulation, storage, and retrieval in Oracle databases.

===

The PL/SQL compilation process converts PL/SQL code (like procedures, functions, and triggers) into an executable form that Oracle can process. It consists of several stages: syntax checking, semantic analysis, code generation, and storing the compiled code in the database. 

 Stages of the PL/SQL Compilation Process 

1. Syntax Checking:

   - Purpose: Ensures that the PL/SQL code follows correct syntax rules.

   - Process: Oracle checks for syntactical errors like missing semicolons, misspelled keywords, or improper variable declarations.

   - Outcome: If there are syntax errors, the process stops here, and Oracle returns an error to the developer with information about the issue. If no errors are found, it moves to the next stage. 

2. Semantic Analysis:

   - Purpose: Ensures that the code makes logical sense and adheres to PL/SQL semantics.

   - Process: Oracle checks for issues like:

     - Variable declarations that do not match the types used.

     - References to non-existent tables, columns, procedures, or functions.

     - Ensures that the PL/SQL logic is meaningful and valid.

   - Outcome: If any semantic issues are detected (like using an undeclared variable or calling a procedure that doesn’t exist), Oracle returns an error with details. Otherwise, it proceeds to the code generation phase. 

3. Code Generation:

   - Purpose: Translates the syntactically and semantically valid PL/SQL code into a form that can be stored and executed.

   - Process: The PL/SQL compiler generates p-code (an intermediate, portable form of code) rather than machine-level code. P-code is interpreted by the Oracle PL/SQL engine at runtime.

   - Outcome: The p-code is a platform-independent representation of the PL/SQL program, optimized for efficient execution in the Oracle environment. 

4. Storing Compiled Code:

   - Purpose: Saves the compiled code in the database to be executed when required.

   - Process: The generated p-code is stored in Oracle’s system catalog, making it available for immediate or future execution.

   - Outcome: When the code is successfully stored, it is considered a valid object (e.g., a valid procedure or function) and is ready for execution.

 

5. Execution and Runtime Checking (Post-Compilation):

   - When the PL/SQL block is executed, the Oracle PL/SQL engine interprets the stored p-code.

   - Runtime Errors: Even if the code compiles successfully, some errors might only appear during execution, such as divide-by-zero errors, `NO_DATA_FOUND`, `TOO_MANY_ROWS`, etc. These are handled using PL/SQL’s exception handling mechanisms. 

 Example: Compilation Feedback and Dependencies 

During compilation, Oracle checks dependencies (like tables or other PL/SQL code) referenced in the PL/SQL code. If any of these dependencies change (such as a table structure modification), the code may become invalid. In this case, Oracle marks it for recompilation, which will happen automatically when the code is called next. 

 Summary of PL/SQL Compilation Outcomes

- Syntax and Semantic Errors: Detected during compilation; must be resolved for successful compilation.

- Invalid State: If dependencies change, the PL/SQL code may need recompilation.

- Runtime Errors: Handled using exception handling, as they only occur during actual execution. 

This compilation process ensures that PL/SQL code is optimized, syntactically correct, logically consistent, and ready for execution in the Oracle environment.

===

PL/SQL packages are powerful tools in Oracle that bundle related procedures, functions, variables, and other PL/SQL constructs into a single unit. Using packages provides a number of benefits for performance, organization, security, and modularity in database applications. Here’s an overview of the key benefits:

 

 1. Modularity and Code Organization

   - Purpose: Packages allow grouping of related procedures, functions, variables, and constants in a single place, making code more organized and modular.

   - Benefit: By logically grouping related items, packages help maintain clean and readable code, which makes development, debugging, and maintenance easier.

 

 2. Encapsulation and Security

   - Purpose: Packages provide a way to hide specific procedures and functions by defining them as private (only accessible within the package).

   - Benefit: Sensitive data and internal implementation details can be hidden, providing a controlled interface for other applications and users. Only the package’s public (specification) part is visible to users, while private components (defined in the package body) remain hidden and inaccessible from outside.

 

 3. Improved Performance

   - Purpose: Packages improve performance through reduced I/O and better memory management.

   - Benefit:

     - Loading Efficiency: When a package is first accessed, the entire package is loaded into memory. Subsequent calls to any other parts of the package reuse this already loaded code, saving time.

     - Reduced Network Traffic: Packages minimize network traffic by bundling multiple related procedures/functions together, reducing the need to repeatedly call separate standalone procedures/functions.

 

 4. Reduced Redundancy and Reusability

   - Purpose: Packages allow you to reuse code across applications by placing common procedures and functions in one package that can be accessed by various programs.

   - Benefit: Reusability reduces redundancy and saves development time. Changes to common logic need to be made only in one place, and all applications using the package will reflect the updates automatically.

 

 5. Overloading Support

   - Purpose: Packages support overloading, which means you can define multiple procedures or functions with the same name but with different parameter lists.

   - Benefit: Overloading provides flexibility and allows for polymorphism within PL/SQL, making the package easier to use in different contexts with varying inputs. It also allows for simplified interfaces for users, as they don’t have to remember multiple function names for similar actions.

 

 6. Easier Maintenance and Version Control

   - Purpose: Packages allow code maintenance and version control without disrupting applications.

   - Benefit: Since the package specification (interface) and body (implementation) are separate, changes can be made to the package body without affecting the specification. As long as the interface remains the same, dependent applications are not affected. This separation allows for safer updates and bug fixes.

 

 7. Automatic Dependency Management

   - Purpose: Packages track dependencies automatically within the database.

   - Benefit: When a package relies on other database objects (like tables or views), Oracle manages these dependencies and automatically revalidates or recompiles them as needed, ensuring reliability and reducing error handling on the developer's part.

 

 8. Session-Scoped Global Variables

   - Purpose: Packages allow defining global variables that persist for the duration of a session.

   - Benefit: These global variables can maintain session-specific information, such as settings or counters, that can be accessed across multiple package calls within the same session, allowing for greater state management capabilities.

 

 Example Structure of a Package

 

A package in PL/SQL has two parts: the specification and the body.

 

- Specification: Declares the public procedures, functions, types, and variables available to users.

- Body: Contains the code for the procedures and functions defined in the specification, as well as any private elements.

 

```

plsql

-- Package Specification

CREATE OR REPLACE PACKAGE Employee_Pkg AS

    PROCEDURE Add_Employee(emp_id NUMBER, emp_name VARCHAR2);

    FUNCTION Get_Employee(emp_id NUMBER) RETURN VARCHAR2;

END Employee_Pkg;

 

-- Package Body

CREATE OR REPLACE PACKAGE BODY Employee_Pkg AS

    PROCEDURE Add_Employee(emp_id NUMBER, emp_name VARCHAR2) IS

    BEGIN

        -- Procedure implementation

    END Add_Employee;

 

    FUNCTION Get_Employee(emp_id NUMBER) RETURN VARCHAR2 IS

    BEGIN

        -- Function implementation

        RETURN 'Employee Name';

    END Get_Employee;

END Employee_Pkg;


``` 

In this example, the `Employee_Pkg` package allows easy access to `Add_Employee` and `Get_Employee` functionalities, while the implementation can be modified without changing the calling code.

  Summary of Benefits :PL/SQL packages provide modularity, encapsulation, performance benefits, code reusability, and ease of maintenance, making them an essential feature in Oracle applications for building complex, scalable, and maintainable code.

===

different uses of stored procedures:

Stored procedures in PL/SQL are powerful tools that allow database developers to encapsulate logic within the database itself. They are reusable, precompiled, and can handle complex tasks efficiently. Here are some of the primary uses and benefits of stored procedures:

 

 1. Data Validation and Business Rules Enforcement

   - Purpose: Ensure data integrity by implementing complex validation and business logic directly in the database.

   - Use Case: A stored procedure can enforce validation rules for new data entries, such as checking if a value falls within an acceptable range or validating that related records exist.

   - Example: Before inserting a new employee record, a stored procedure can check that the department ID exists and the salary is within the allowed range for that department.

 

 2. Encapsulation of Complex Operations

   - Purpose: Encapsulate complex queries and data manipulation logic to simplify application development.

   - Use Case: Instead of writing complex SQL in each application layer, you can call a stored procedure that performs these operations internally.

   - Example: A stored procedure can generate an invoice by aggregating data from various tables, calculating totals, and applying discounts in a single transaction.

 

 3. Improved Performance and Reduced Network Traffic

   - Purpose: Minimize network traffic and improve performance by moving data processing logic to the database server.

   - Use Case: Stored procedures allow large data processing tasks to be handled directly in the database, reducing the amount of data that needs to be sent over the network to an application.

   - Example: A stored procedure can process and analyze large datasets within the database, sending only the final result to the application, thus saving bandwidth and reducing response times.

 

 4. Reusable Code for Consistency and Maintainability

   - Purpose: Centralize business logic and make it reusable across multiple applications or modules.

   - Use Case: A stored procedure can standardize calculations, transformations, and validations, reducing code duplication and making updates easier.

   - Example: A stored procedure for calculating employee bonuses can be reused in different applications, ensuring that the bonus calculation is consistent.

 

 5. Automating Administrative and Maintenance Tasks

   - Purpose: Automate routine administrative tasks, such as backups, log cleanup, and data archiving.

   - Use Case: Scheduling stored procedures as part of maintenance jobs can automate these tasks and reduce manual intervention.

   - Example: A stored procedure can be scheduled to delete old log entries or archive data to another table at regular intervals.

 

 6. Transactional Integrity and Error Handling

   - Purpose: Group multiple SQL operations into a single unit with transaction control, ensuring either complete success or rollback.

   - Use Case: By using stored procedures, developers can enforce ACID properties in transactions and handle errors consistently.

   - Example: A stored procedure that transfers money between two accounts can ensure that both the debit and credit operations succeed or are rolled back if an error occurs in either.

 

 7. Enhanced Security and Access Control

   - Purpose: Restrict direct access to database tables by providing controlled access through stored procedures.

   - Use Case: Stored procedures allow developers to enforce user access permissions by exposing only the operations required by specific user roles.

   - Example: Instead of giving users direct access to the `employee` table, a stored procedure allows users to access employee data through approved methods, protecting sensitive data like salaries.

 

 8. Interfacing with Applications and APIs

   - Purpose: Act as an interface between applications and the database, abstracting database complexity.

   - Use Case: Applications can call stored procedures without needing to know the database schema or SQL details, making changes to the database schema less disruptive to applications.

   - Example: An application might call a stored procedure to place an order, which then handles all the necessary steps to update stock, generate an invoice, and record the transaction in the database.

 

 9. Dynamic SQL and Flexibility in Query Execution

   - Purpose: Use dynamic SQL within stored procedures to create flexible query execution.

   - Use Case: For scenarios where the SQL query must change based on inputs, stored procedures with dynamic SQL allow constructing and executing SQL at runtime.

   - Example: A stored procedure can dynamically generate a SELECT query based on user-selected filters, making it flexible enough to handle different report types.

 

 10. Auditing and Logging Activities

   - Purpose: Record user activities and maintain an audit trail for sensitive data changes.

   - Use Case: By using stored procedures, developers can add logging to record who accessed or modified data, along with timestamps.

   - Example: A stored procedure that updates employee information can automatically insert a record in an audit table, tracking changes made to sensitive data fields.

 

 11. Batch Processing and Data Migration

   - Purpose: Facilitate batch jobs and large-scale data migrations between tables or databases.

   - Use Case: For ETL (Extract, Transform, Load) processes, stored procedures can handle large data operations efficiently.

   - Example: A stored procedure can read data from a staging table, apply necessary transformations, and insert it into a target table, ensuring data integrity and efficient processing. 

 Summary

Stored procedures provide a centralized, secure, and high-performing way to manage data operations and business logic directly within the database. They improve maintainability, support modular programming, enable reusability, reduce network overhead, and enhance security, making them essential for building robust, scalable database-driven applications.

===


#include "BSNL_DEE.h"

#define CLARITY 1

#define IVRS 3

#define PMS 2


//--------------- Host variable declaraction ---------------

exec sql begin declare section;


/* Cursor variables declaration  */

sql_cursor g_eli_acc_cursor;

sql_cursor g_col_feed_cursor;


/* Varchar variables declaration  */


VARCHAR g_bb_flag[3];

VARCHAR g_crm_dblink[20];

VARCHAR g_error_msg[ERR_MSG_LEN];

VARCHAR g_timestamp[DATE_ARR_LEN];

VARCHAR g_systemdate[DATE_ARR_LEN];

VARCHAR g_pmsfeeddate[DATE_ARR_LEN];

VARCHAR g_new_acc_num[ACC_SER_NUM_SIZE];

VARCHAR g_created_dtm[ORACLE_DATE_SIZE];

VARCHAR g_service_number[ACC_SER_NUM_SIZE];

VARCHAR g_crm_created_dtm[ORACLE_DATE_SIZE];

VARCHAR g_dun_actiontype_str[VAR_LEN_ARR_SIZE];

VARCHAR g_pms_feedfile_dir_str[VAR_LEN_ARR_SIZE];

VARCHAR g_nondun_actiontype_str[VAR_LEN_ARR_SIZE];

VARCHAR g_pms_feed_filename[VAR_LEN_ARR_SIZE];


/* int variables declaration  */

int l_action_id;

int g_action_id;

int g_return_sts;

int g_action_seq;

int g_error_code = 0;

int g_bb_prod_id;

int g_bb_bar_prod_id;

int g_ogb_vip_act_id;

int g_new_action_num;

int g_request_status;

int g_pd_act_type_info;

int g_ocb_act_type_info;

int g_icb_act_type_info;

int g_ogicb_act_type_info;

int g_dab_act_id;

int g_ogdab_act_id;


/* long variables declaration  */

long g_debt_age;

long g_credit_class;

long g_new_bill_seq;

long g_DEBTage_task_id;


/* char/string variables declaration  */

char *g_connect_str ;

char g_instance_id[22];

char g_action_id_str[3];

char *g_dun_action_ptr;

char *g_vip_act_type_ptr;

char *g_nondun_action_ptr;

char *g_pms_feedfile_dir_ptr;

char *g_act_feedfile_dir_ptr;


/* Double variables declaration  */

double g_rollup_debt;

double g_threshold_mny;

double g_outstanding_tot;


/* INDICATOR variables declaration  */

short g_ind_var; /*Indicator Variable*/


//---------- Variables for generating diffrent feed files ---------

VARCHAR g_ivrs_feedfile_dir[VAR_LEN_ARR_SIZE]; 

VARCHAR g_clarity_feedfile_dir[VAR_LEN_ARR_SIZE]; 

VARCHAR g_ivrs_act_type_info[VAR_LEN_ARR_SIZE]; 

VARCHAR g_vip_act_type_info[VAR_LEN_ARR_SIZE];


exec sql end declare section;


exec sql include sqlca;


//--------------- Global counters to keep track of Total, Errored & Success records --------------- 

long g_rec_total    = 0;

long g_suc_total    = 0;

long g_err_total    = 0;

long g_file_rec_cnt    = 0;



/*F*****************************************************

* Function for inserting ftp file in reporting directory.

*

***************************************************F*/


void insert_ftp_file ( char *ftp_filename,

       long   rec_cnt,

       char *ext_system 

     )

{

        int l_rtn;

EXEC SQL BEGIN DECLARE SECTION;

VARCHAR FTP_FILENAME[100];

VARCHAR EXTERNAL_SYSTEM[10];

EXEC SQL END DECLARE SECTION;

sprintf(traceBuf, "Creating entry in BSNL_CLARITY_FILE_RPT table for file %s", ftp_filename);

traceOutput(__LINE__, INF_LVL, traceBuf);

strcpy((char *)FTP_FILENAME.arr,ftp_filename );

FTP_FILENAME.len = strlen((char *)FTP_FILENAME.arr);


strcpy((char *)EXTERNAL_SYSTEM.arr,ext_system );

EXTERNAL_SYSTEM.len = strlen((char *)EXTERNAL_SYSTEM.arr);


sprintf(traceBuf, "File name '%s', rec count '%ld', extrnl system '%s'", ftp_filename, rec_cnt, ext_system);

traceOutput(__LINE__, INF_LVL, traceBuf);

EXEC SQL EXECUTE

BEGIN 

:l_rtn  :=  BSNL_COLLECTION_PACKAGE.BSNL_LOG_CLARITY_FILE_RPT(   P_OPERATION_FLAG  => 'C'

,p_FILENAME    => :FTP_FILENAME

,P_TOTAL_RACORDS  => :rec_cnt

,P_EXTERNAL_SYS   => :EXTERNAL_SYSTEM

,P_ERROR_CODE    => :g_error_code INDICATOR :g_ind_var

,P_ERROR_MESSAGE  => :g_error_msg INDICATOR :g_ind_var);


END;

END-EXEC;


if ( l_rtn != 0 ){

sprintf(traceBuf, "Failed to create entry in BSNL_CLARITY_FILE_RPT table for file %s. %s", ftp_filename, g_error_msg.arr);

traceOutput(__LINE__, WRN_LVL, traceBuf);

}else{

sprintf(traceBuf, "Successfully created entry in BSNL_CLARITY_FILE_RPT table for file %s ", ftp_filename);

traceOutput(__LINE__, INF_LVL, traceBuf);

return;

}

return;

}


/*F*****************************************************

* Function to search a token in string

***************************************************F*/


int tokencheck ( char *str, 

                 int token )

{

  char  temp[1000];

  char * pch;


  strcpy(temp, str);

  pch = strtok ( temp,",");

  while (pch != NULL)

  {

    if ( atoi(pch) == token )

       return 1;

    pch = strtok (NULL, " ,.-");

  }

  return 0;

}


/*F*****************************************************

* Function for ftp a file 

* Input Parameters:   

* File_Name: File to be ftp.

*       Oper_type: 1 Clarity Feed

*    2 CRM     Feed. etc.

* returns 1: Success.

* 0: Error.

***************************************************F*/


/*int bsnl_ftp( char * File_Name 

     , int   Oper_type )

{

char *l_Exec_qry;

int   l_rtn;

EXEC SQL BEGIN DECLARE SECTION;

VARCHAR IP_Address[25];

VARCHAR UserName[25];

VARCHAR Passwd[25];

VARCHAR Dest_Dir[1024];


EXEC SQL END DECLARE SECTION;

//-- Retrieve Clarity parameters if file to FTP is Clarity feed file...

if ( Oper_type == 1 ){

EXEC SQL EXECUTE

BEGIN

:l_rtn := BSNL_COLLECTION_PACKAGE.BSNL_GET_CLARITY_PARAMS  (  

    P_CLARITY_FTP_DIR            => :Dest_Dir,

    P_CLARITY_FTP_PASSWORD       => :Passwd,

    P_CLARITY_FTP_USERNAME       => :UserName,

    P_CLARITY_FTP_SERVER         => :IP_Address);

END;

END-EXEC;

if ( l_rtn != 0 ){

sprintf(traceBuf, "Error retrieving mandatory parameters for Clarity file transfer ");

traceOutput(__LINE__, WRN_LVL, traceBuf);

return 0;

}

l_Exec_qry = (char *) malloc(strlen("ftp.pl -a ")+ IP_Address.len + UserName.len + Passwd.len + Dest_Dir.len + sizeof(File_Name)+ 5);

strcpy(l_Exec_qry,        (char *)"ftp.pl -a ");

strcat(l_Exec_qry,        (char *)IP_Address.arr );

strcat(l_Exec_qry,        (char *)":" );

strcat(l_Exec_qry,        (char *)UserName.arr );

strcat(l_Exec_qry,        (char *)":" );

strcat(l_Exec_qry,        (char *)Passwd.arr );

strcat(l_Exec_qry,        (char *)":" );

strcat(l_Exec_qry,        (char *)Dest_Dir.arr );

strcat(l_Exec_qry,        (char *)":" );

strcat(l_Exec_qry,        File_Name );

  if ( system( l_Exec_qry ) != 0 ){

sprintf(traceBuf, "Failed to FTP file %s. Please do it manually after taking corrective Action ", File_Name);

traceOutput(__LINE__, WRN_LVL, traceBuf);

return 0;

  }else{

sprintf(traceBuf, "FTP has been ftp succssfully at location file '%s' of FTP server '%s'. ", Dest_Dir.arr, IP_Address.arr);

traceOutput(__LINE__, INF_LVL, traceBuf);

return 1;

  }

}

*/

/*F*****************************************************

* Function to update ProcessInstanceLog table 

* once BSNL_DEE process finishes.

***************************************************F*/

void UpdateProcessInstanceLogInfo(int l_process_sts )

{

int l_instance_id;

l_instance_id = atoi(g_instance_id);

sprintf(traceBuf, "Updating process instance now with process instance ID %d and process status %d ", l_instance_id, l_process_sts);

traceOutput(__LINE__, INF_LVL, traceBuf);


if(l_instance_id != 0)

{

sprintf(traceBuf, "total records %d, %d %d and process status %d ", g_rec_total, g_err_total, l_instance_id, l_process_sts);

traceOutput(__LINE__, INF_LVL, traceBuf);


EXEC SQL 

UPDATE PROCESSINSTANCELOG

SET WORK_DONE   = :g_rec_total,

WORK_FAILED   = :g_err_total,

TOTAL_ERRORS   = :g_err_total,

PROCESS_STATUS           = :l_process_sts

WHERE PROCESS_INSTANCE_ID = :l_instance_id;

}

}


/*F*****************************************************

* Function to update remote crm table

***************************************************F*/

void crm_table_update(){

long l_normal_tot, l_vip_tot;

char szInsertQuery [2500];

sprintf(traceBuf, "Writing Permanent disconnection records in CRM table now...");

traceOutput(__LINE__, INF_LVL, traceBuf);


EXEC SQL WHENEVER SQLERROR GOTO CRM_FEED_ERR;

EXEC SQL EXECUTE


BEGIN

SAVEPOINT ACC_INSERT;


BSNL_COLLECTION_PACKAGE.BSNL_CRM_FEED_UPDATE( P_CRM_DBLINK       => :g_crm_dblink

    , P_PD_ACTION_TYPE => :g_pd_act_type_info

    , P_NORMAL_TOT => :l_normal_tot INDICATOR :g_ind_var

    , P_VIP_TOT => :l_vip_tot      INDICATOR :g_ind_var

    , P_ERROR_CODE => :g_error_code   INDICATOR :g_ind_var

    , P_ERROR_MESSAGE => :g_error_msg    INDICATOR :g_ind_var );

END;

END-EXEC;

if ( g_error_code == 0 ) {

sprintf(traceBuf, "Successfully written  '%d' Permanent disconnection records for normal customers in remote zperm table", l_normal_tot);

traceOutput(__LINE__, INF_LVL, traceBuf);

sprintf(traceBuf, "Successfully written  '%d' VIP dunning records in remote zvip_dun table", l_vip_tot);

traceOutput(__LINE__, INF_LVL, traceBuf);

}else{

sprintf(traceBuf, "Error writing records in remote CRM table. %s", g_error_msg.arr);

traceOutput(__LINE__, INF_LVL, traceBuf);

}


EXEC SQL COMMIT;

return;


CRM_FEED_ERR:

strcpy( (char *)g_error_msg.arr, "Error writing Permanent disconnection records. ");

strcat ((char *)g_error_msg.arr, sqlca.sqlerrm.sqlerrmc);

g_error_msg.len = strlen((char *)g_error_msg.arr);

g_error_code     = sqlca.sqlcode;

sprintf(traceBuf, "Error inserting permanent disconnection records in CRM table. %s", g_error_msg.arr);

traceOutput(__LINE__, INF_LVL, traceBuf);

EXEC SQL EXECUTE

BEGIN 

:g_return_sts := BSNL_COLLECTION_PACKAGE.BSNL_INSERT_ERROR_DATA(BSNL_COLLECTION_PACKAGE.G_SYSDATE,

       'BSNL_DEE_CRM_FEED_ERROR',

       :g_error_code,

       :g_error_msg);

END;

END-EXEC;

g_error_code = 0;

return;


}


/*F*************************************************************************

* Create Collection Feed File.

* Retrieve all the records having Request Status as pending (1) in Error in export (3).

* If Action type Category II type, Category I PD, Letter generation & Collection Agency Transfer Actions types

* then insert into Category II feed file.

* Else if Action type Category I, SMS action type then insert into Category I SMS feed file.

* Else if Action type Category I, IVRS action type then insert into Category I IVRS feed file.

* Else if Action type Category I, CLARITY action type then insert into Category I CLARITY feed file.

* Update status of each record 'Exported for Processing (2).

* Close the file.

* If no record in file then delete it

* Else move the file to the desired location.

*

*************************************************************************F*/

void CreateFeedFile()

{

/*char l_cat2_file_name[150];*/

char l_cat1_ivrs_file_name[150];

char l_cat1_clarity_file_name[150];

char l_clarity_file_name[100];

char l_crm_dunning_file_name[150];

char l_clarity_done_file_name[150];

FILE *l_cat_done_fhandle;

/*FILE *l_cat2_fhandle;*/

FILE *l_cat1_ivrs_fhandle;

FILE *l_cat1_clarity_fhandle;

//FILE *l_crm_dunning_fhandle;

long l_cat2_file_rec_cnt         = 0;

long l_cat1_sms_file_rec_cnt     = 0;

long l_cat1_ivrs_file_rec_cnt    = 0;

long l_cat1_clarity_file_rec_cnt = 0;

long l_crm_dunning_file_rec_cnt  = 0;

char l_action_id_str[3];

char l_creclass_id_str[3];

char l_dest_file_name[200];

int l_fwrite_sts;

int l_rtn_sts;

EXEC SQL WHENEVER SQLERROR GOTO LOCAL_ERR1;

EXEC SQL SAVEPOINT COL_FILE_SAVEPOINT;

EXEC SQL ALLOCATE :g_col_feed_cursor;

//------ Excluding elgible P2P record -----

sprintf(traceBuf, "Updating Promise2Pay customers... ");

traceOutput(__LINE__, WRN_LVL, traceBuf);

EXEC SQL EXECUTE

BEGIN

BSNL_COLLECTION_PACKAGE.BSNL_P2P_MAIN ( P_ERROR_CODE => :g_error_code  

      , P_ERROR_MSG  => :g_error_msg );

END;

END-EXEC;

        sprintf(traceBuf, "Promise2Pay successfully completed... ");

traceOutput(__LINE__, WRN_LVL, traceBuf);

crm_table_update();/*To be uncommented once need to automate this process ...*/


//------- If any error in process then skip file generation process 

/* if ( g_error_code != 0 ){

sprintf(traceBuf, "%s. Feed file generation process skipping' ", g_error_msg.arr);

traceOutput(__LINE__, WRN_LVL, traceBuf);

return;

        }

*/


//------ Retrieving data to be exported -----------

EXEC SQL EXECUTE

BEGIN

OPEN :g_col_feed_cursor FOR 

SELECT ACCOUNT_NUM, DRIVING_BILL_SEQ,ACTION_NUMBER,ACTION_SEQ,ACTION_ID,

CREDIT_CLASS_ID,TO_CHAR(CREATED_DTM,'DD-MON-YYYY'),TO_CHAR(CREATED_DTM,'DDMMYYYY'),

REQUEST_STATUS, OUTSTANDING_DEBT_TOT,CHASE_DEBT_TOT,ACTION_PROCESSING_NUMBER, BROADBAND_FLAG 

FROM  BSNL_DEBTESCALATIONREQUEST

WHERE REQUEST_STATUS = 1;//in (1,3);

END;

END-EXEC;

//------------- Creating all collection feed files -------

/*sprintf( l_cat2_file_name, "%s/COL_CAT2_FEED_%s.txt", g_catII_feedfile_dir.arr, g_timestamp.arr);

l_cat2_fhandle = fopen(l_cat2_file_name,"w+");

*/

sprintf( l_clarity_file_name, "dunning_%s.data", g_timestamp.arr);

sprintf( l_cat1_clarity_file_name, "%s/%s", g_clarity_feedfile_dir.arr, l_clarity_file_name);

l_cat1_clarity_fhandle = fopen(l_cat1_clarity_file_name,"w+");


sprintf( l_cat1_ivrs_file_name, "%s/ivrs_dunning_%s.txt", g_ivrs_feedfile_dir.arr, g_timestamp.arr);

l_cat1_ivrs_fhandle = fopen(l_cat1_ivrs_file_name,"w+");


if ( /*l_cat2_fhandle == NULL ||*/ l_cat1_ivrs_fhandle == NULL || l_cat1_clarity_fhandle == NULL )

{

EXEC SQL EXECUTE

BEGIN 

:g_error_msg  :=  'Error opening Collection feed file. Feed file creation step skipped.';

:g_return_sts  :=  BSNL_COLLECTION_PACKAGE.BSNL_INSERT_ERROR_DATA(BSNL_COLLECTION_PACKAGE.G_SYSDATE,

'BSNL_DEE_COL_FEED_FILE_WRITE_PROCESS',

1,

:g_error_msg);

END;

END-EXEC;

sprintf(traceBuf, "Error opening Collection feed file. Feed file creation step skipped. Error is %s",strerror(errno));

traceOutput(__LINE__, ERR_LVL, traceBuf);

return;

}

sprintf(traceBuf, "Following Collection feed files created successfully.");

traceOutput(__LINE__, INF_LVL, traceBuf);

/*sprintf(traceBuf, "Category II Collection feed file %s.", l_cat2_file_name);

traceOutput(__LINE__, INF_LVL, traceBuf);*/

sprintf(traceBuf, "IVRS Collection feed file %s.", l_cat1_ivrs_file_name);

traceOutput(__LINE__, INF_LVL, traceBuf);

sprintf(traceBuf, "CLARITY Collection feed file %s.", l_cat1_clarity_file_name);

traceOutput(__LINE__, INF_LVL, traceBuf);

EXEC SQL WHENEVER NOT FOUND GOTO COL_LABEL1;

for(;;)

{

//---------- Retriving records -----------------

memset( g_service_number.arr, '\0', g_service_number.len );

memset( g_created_dtm.arr,   '\0', g_created_dtm.len   );

EXEC SQL FETCH :g_col_feed_cursor INTO :g_new_acc_num, :g_new_bill_seq, :g_new_action_num, :g_action_seq, :g_action_id, :g_credit_class, :g_created_dtm, :g_crm_created_dtm, :g_request_status, :g_outstanding_tot, :g_rollup_debt, :g_service_number INDICATOR :g_ind_var, :g_bb_flag;

//------- Storing into string variable for comparison ----

sprintf(l_action_id_str,"%d",g_action_id);

sprintf(l_creclass_id_str,"%d",g_credit_class);


//---------- Else If IVRS Action type then write into IVRS feed file -----

if( tokencheck( (char *)g_ivrs_act_type_info.arr, g_action_id) == 1  ) 

{

l_fwrite_sts = fprintf (l_cat1_ivrs_fhandle, "%s|%s|%d|%s\n", g_new_acc_num.arr, g_service_number.arr, g_action_id, g_created_dtm.arr);

if ( l_fwrite_sts != NULL)

l_cat1_ivrs_file_rec_cnt++;

}

//---------- Else If its OCB Action type then write into Clarity feed file -----

else if( g_ocb_act_type_info == g_action_id ) 

{ l_fwrite_sts = fprintf (l_cat1_clarity_fhandle, "%s,%s,OGB,%s,%.0f,%s\n", g_new_acc_num.arr, g_service_number.arr, g_created_dtm.arr, g_outstanding_tot, g_bb_flag.arr);

if ( l_fwrite_sts != NULL)

l_cat1_clarity_file_rec_cnt++;

}

//---------- Else If its ICB Action type then write into Clarity feed file -----

else if( g_icb_act_type_info == g_action_id  )

{       l_fwrite_sts = fprintf (l_cat1_clarity_fhandle, "%s,%s,ICB,%s,%.0f,%s\n", g_new_acc_num.arr, g_service_number.arr, g_created_dtm.arr, g_outstanding_tot, g_bb_flag.arr);

if ( l_fwrite_sts != NULL)

l_cat1_clarity_file_rec_cnt++;

}


//---------- Else If its OGICB Action type then write into Clarity feed file -----

else if( g_ogicb_act_type_info == g_action_id  )

{       l_fwrite_sts = fprintf (l_cat1_clarity_fhandle, "%s,%s,OGICB,%s,%.0f,%s\n", g_new_acc_num.arr, g_service_number.arr, g_created_dtm.arr, g_outstanding_tot, g_bb_flag.arr);

if ( l_fwrite_sts != NULL)

l_cat1_clarity_file_rec_cnt++;

}

//---------- Else If its DAB Action type then write into Clarity feed file -----

else if( g_dab_act_id == g_action_id  )

{       l_fwrite_sts = fprintf (l_cat1_clarity_fhandle, "%s,%s,DAB,%s,%.0f,%s\n", g_new_acc_num.arr, g_service_number.arr, g_created_dtm.arr, g_outstanding_tot, g_bb_flag.arr);

if ( l_fwrite_sts != NULL)

l_cat1_clarity_file_rec_cnt++;

}


//---------- Else If its OGDAB Action type then write into Clarity feed file -----

else if( g_ogdab_act_id == g_action_id  )

{       l_fwrite_sts = fprintf (l_cat1_clarity_fhandle, "%s,%s,OGDAB,%s,%.0f,%s\n", g_new_acc_num.arr, g_service_number.arr, g_created_dtm.arr, g_outstanding_tot, g_bb_flag.arr);

if ( l_fwrite_sts != NULL)

l_cat1_clarity_file_rec_cnt++;

}


//---------- Else insert record into CRM feed file -----

/*else 

{

l_fwrite_sts = fprintf (l_cat2_fhandle, "%s,%ld,%d,%d,%d,%ld,%s,%.0f,%.0f,%s\n", g_new_acc_num.arr, g_new_bill_seq, g_new_action_num, g_action_seq, g_action_id, g_credit_class, g_created_dtm.arr, g_outstanding_tot, g_rollup_debt, g_service_number.arr);

if ( l_fwrite_sts != NULL)

l_cat2_file_rec_cnt++;

}

*/

if ( l_fwrite_sts == NULL)

{

sprintf(traceBuf, "Error in writing Collection feed file for record '%s','%ld','%d','%ld','%s','%.0f','%.0f','%s'", g_new_acc_num.arr, g_new_bill_seq, g_new_action_num, g_action_id, g_created_dtm.arr, g_outstanding_tot, g_rollup_debt, g_service_number.arr);

traceOutput(__LINE__, WRN_LVL, traceBuf);

EXEC SQL EXECUTE

BEGIN 

:g_error_msg := 'Error writing in Collection feed file for record "'||:g_new_action_num|| '","' ||:g_new_bill_seq || '","'||:g_new_action_num|| '","'||:g_action_seq ||'","'||:g_action_id||'","'||:g_credit_class||'","'||:g_created_dtm|| '","' ||'","'||:g_outstanding_tot|| '","' ||:g_rollup_debt || '","' || :g_service_number ||'"';

BSNL_COLLECTION_PACKAGE.BSNL_PRO_COL_FEEDFILE_ACTION(:g_new_acc_num,:g_new_bill_seq,:g_new_action_num,:g_action_seq,1,:g_error_msg,1);

END;

END-EXEC;

} else

EXEC SQL EXECUTE

BEGIN 

BSNL_COLLECTION_PACKAGE.BSNL_PRO_COL_FEEDFILE_ACTION(:g_new_acc_num,:g_new_bill_seq,:g_new_action_num,:g_action_seq,NULL,NULL,0);

END;

END-EXEC;

}

} //---- end for loop ----

LOCAL_ERR1:

EXEC SQL CLOSE :g_col_feed_cursor;

EXEC SQL ROLLBACK TO COL_FILE_SAVEPOINT;

strcpy( (char *)g_error_msg.arr, "Error in Collection feed file processing. ");

strcat ((char *)g_error_msg.arr, sqlca.sqlerrm.sqlerrmc);

g_error_msg.len = strlen((char *)g_error_msg.arr);

g_error_code     = sqlca.sqlcode;

//------ Deleting all the feed files as these are un-necessary -----

/*if ( remove (l_cat2_file_name) == -1 )

{

sprintf(traceBuf, "Error deleting Collection feed file '%s' for Category II customers. Please delete it manually", l_cat2_file_name);

traceOutput(__LINE__, WRN_LVL, traceBuf);

}

*/

if ( remove (l_cat1_ivrs_file_name) == -1 )

{

sprintf(traceBuf, "Error deleting Collection feed file '%s' for IVRS Action types. Please delete it manually", l_cat1_ivrs_file_name);

traceOutput(__LINE__, WRN_LVL, traceBuf);

}

if ( remove (l_cat1_clarity_file_name) == -1 )

{

sprintf(traceBuf, "Error deleting Collection feed file '%s' for CLARITY Action types. Please delete it manually", l_cat1_clarity_file_name);

traceOutput(__LINE__, WRN_LVL, traceBuf);

}

EXEC SQL EXECUTE

BEGIN 

:g_return_sts := BSNL_COLLECTION_PACKAGE.BSNL_INSERT_ERROR_DATA(BSNL_COLLECTION_PACKAGE.G_SYSDATE,

'BSNL_DEE_COL_FEED_FILE_WRITE_PROCESS',

:g_error_code,

:g_error_msg);

END;

END-EXEC;

COL_LABEL1:

/*fclose(l_cat2_fhandle);*/

fclose(l_cat1_ivrs_fhandle);

fclose(l_cat1_clarity_fhandle);

//fclose(l_crm_dunning_fhandle);

EXEC SQL CLOSE :g_col_feed_cursor;

EXEC SQL COMMIT;

//-------- Deleting Category II feed file, if of zero size ---------

/*if (l_cat2_file_rec_cnt == 0 )

{

if ( remove (l_cat2_file_name) == -1 )

{

sprintf(traceBuf, "Error deleting zero size Category II Collection feed file '%s'. Please delete it manually", l_cat2_file_name);

traceOutput(__LINE__, WRN_LVL, traceBuf);

}else

{

sprintf(traceBuf, "Deleted zero size Category II Collection feed file '%s' successfully", l_cat2_file_name);

traceOutput(__LINE__, INF_LVL, traceBuf);

}

}

*/

//-------- Deleting Category I, CLARITY feed file, if of zero size ---------

if (l_cat1_clarity_file_rec_cnt == 0 )

{

if ( remove (l_cat1_clarity_file_name) == -1 )

{

sprintf(traceBuf, "Error deleting zero size Category I, CLARITY Collection feed file '%s'. Please delete it manually", l_cat1_clarity_file_name);

traceOutput(__LINE__, WRN_LVL, traceBuf);

}else

{

sprintf(traceBuf, "Deleted zero size Category I, CLARITY Collection feed file '%s' successfully", l_cat1_clarity_file_name);

traceOutput(__LINE__, INF_LVL, traceBuf);

}

}

// Updating Clarity reporting table ...

else {

insert_ftp_file ( l_clarity_file_name, l_cat1_clarity_file_rec_cnt, (char *)"CLARITY" );

sprintf( l_clarity_done_file_name, "%s/dunning_%s.done", g_clarity_feedfile_dir.arr, g_timestamp.arr);

l_cat_done_fhandle = fopen(l_clarity_done_file_name,"w+");

fclose(l_cat_done_fhandle);

}


//-------- Deleting Category I, IVRS feed file, if of zero size ---------

if (l_cat1_ivrs_file_rec_cnt == 0 )

{

if ( remove (l_cat1_ivrs_file_name) == -1 )

{

sprintf(traceBuf, "Error deleting zero size Category I, IVRS Collection feed file '%s'. Please delete it manually", l_cat1_ivrs_file_name);

traceOutput(__LINE__, WRN_LVL, traceBuf);

}else

{

sprintf(traceBuf, "Deleted zero size Category I, IVRS Collection feed file '%s' successfully", l_cat1_ivrs_file_name);

traceOutput(__LINE__, INF_LVL, traceBuf);

}

}

         

return;

}

//-------------- main function starts here ---------------

main (int argc, char *argv[])

{


//--------------- General variable declaration ---------------

char l_database_env[35] ;

//--------------- PMS File operation variables ---------------

char l_local_dtm[15];

char l_file_name[250]; 

char l_pms_done_file[250]; 

char l_dest_file_name[200];

char *l_last_dun_accnum;

FILE *l_pms_fhandle;

struct tm *l_local_time;

int l_fwrite_sts;

time_t t;

//--------------- Declaring variables to keep track of old values --------------- 

int l_old_action_num = 0;

long l_old_bill_seq = 0;

int l_save_eli_cust_flag = 0;

char *l_old_acc_num;

//--------------- checking trace settings --------------

if ( strcmp( (char *)getenv(TRACE_VAR), (char *)TRC_LEVEL_FULL) == 0)

traceFlag = FLAG_ON;

else

traceFlag = FLAG_OFF;

/*S*****************************************************

* Process start notification.

***************************************************S*/

sprintf(traceBuf, "BSNL_DEE process started...");

traceOutput(__LINE__, INF_LVL, traceBuf);

/*S***********************************************************************************

* Description: Printing command line arguments.

*        

***********************************************************************************S*/

int l_char;

while(( l_char = getopt( argc, argv, "p:m:c:t:w:r:k:s:")) != -1) 

    switch(l_char) 

    { 

case 'p': 

strcpy(g_instance_id, optarg); 

sprintf(traceBuf, "Value for p flag is |%s|", optarg);

traceOutput(__LINE__, INF_LVL, traceBuf);

   break; 

case 'r': 

strcpy(g_instance_id, optarg); 

sprintf(traceBuf, "Value for r flag is |%s|", optarg);

traceOutput(__LINE__, INF_LVL, traceBuf);

    break; 

case ':': 

sprintf(traceBuf, "Option -%c requires an operand", optopt );

traceOutput(__LINE__, INF_LVL, traceBuf);

    break; 

case '?': 

sprintf(traceBuf, "Unrecognized option: -%c", optopt );

traceOutput(__LINE__, INF_LVL, traceBuf);

    break; 

default  :

    break;

  

    }  

    if ( atoi(g_instance_id) != 0)

break;

}

sprintf(traceBuf, "Process Instance ID: -%s", g_instance_id );

traceOutput(__LINE__, INF_LVL, traceBuf);

/*S*****************************************************

* Automatic Connection to Oracle. 

***************************************************S*/

EXEC SQL WHENEVER SQLERROR GOTO ERR;

EXEC SQL WHENEVER NOT FOUND CONTINUE;


strncpy(l_database_env, "DATABASE", sizeof(l_database_env));

g_connect_str = (char *)getenv(l_database_env);

if(g_connect_str == NULL)

{

sprintf(traceBuf, "Database connection failed no value for $DATABASE...");

traceOutput(__LINE__, ERR_LVL, traceBuf);

g_rec_total++;

g_err_total++;

UpdateProcessInstanceLogInfo(9);

EXEC SQL WHENEVER SQLERROR CONTINUE;

EXEC SQL COMMIT WORK RELEASE;

exit(1);

}

EXEC SQL CONNECT :g_connect_str ;

//------------------------------ Creating first savepoint ----------------------------

EXEC SQL SAVEPOINT SAVEPOINT_MAIN;

/*S***********************************************************************************

* Description: Retrieving Dunning and Non-dunning Action types, PMS Destination file 

*              and CRM Feed File Destination file location, DEBTage task ID information.

*        If error encounters then BSNL_DEE process shall be aborted.

***********************************************************************************S*/

EXEC SQL EXECUTE

BEGIN

:g_return_sts := BSNL_COLLECTION_PACKAGE.BSNL_GET_CUSTOM_PARAMS_INFO( 

P_DUN_ACTION_TYPE     => :g_dun_actiontype_str INDICATOR :g_ind_var, 

P_SMS_CALL_ACT_TYPE     => :g_nondun_actiontype_str INDICATOR :g_ind_var, 

P_BSNLDEE_DEBTAGE_ID     => :g_DEBTage_task_id INDICATOR :g_ind_var,

P_PMS_FILE_DIR     => :g_pms_feedfile_dir_str INDICATOR :g_ind_var, 

P_IVRS_FEEDFILE_DIR     => :g_ivrs_feedfile_dir INDICATOR :g_ind_var, 

P_CLARITY_FEEDFILE_DIR     => :g_clarity_feedfile_dir INDICATOR :g_ind_var, 

P_IVRS_ACTION_TYPE_INFO     => :g_ivrs_act_type_info INDICATOR :g_ind_var, 

P_BSNLDEE_OCB_ACTION_ID     => :g_ocb_act_type_info INDICATOR :g_ind_var,

P_BSNLDEE_ICB_ACTION_ID     => :g_icb_act_type_info INDICATOR :g_ind_var,

P_BSNLDEE_PD_ACTION_ID     => :g_pd_act_type_info INDICATOR :g_ind_var,

P_BSNLDEE_OGICB_ACTION_ID   => :g_ogicb_act_type_info INDICATOR :g_ind_var,

P_BSNLDEE_BB_PROD_ID     => :g_bb_prod_id INDICATOR :g_ind_var,

P_BSNLDEE_BB_BAR_PROD_ID    => :g_bb_bar_prod_id INDICATOR :g_ind_var,

P_CRM_DBLINK     => :g_crm_dblink INDICATOR :g_ind_var,

P_BSNLDEE_OGB_VIP_ACTION_ID => :g_ogb_vip_act_id INDICATOR :g_ind_var,

P_BSNLDEE_VIP_ACT_INFO     => :g_vip_act_type_info INDICATOR :g_ind_var,

P_BSNLDEE_DAB_ACTION_ID     => :g_dab_act_id INDICATOR :g_ind_var,

P_BSNLDEE_OGDAB_ACTION_ID   => :g_ogdab_act_id INDICATOR :g_ind_var);

IF :g_return_sts = :FAILURE THEN

:g_error_msg  := BSNL_COLLECTION_PACKAGE.GLOBAL_ERR;

END IF;

-- Retrieving Global date parameter.

:g_systemdate  := to_char(GNVGEN.SYSTEMDATE, 'mm/dd/yyyy');

:g_pmsfeeddate := to_char(GNVGEN.SYSTEMDATE, 'dd-mm-yy');

-- Retrieving TIMESTAMP for feed file creation.

:g_timestamp  := TO_CHAR( GNVGEN.systemDate, 'DDMMYYYYHH24MISS'); -- YYYYMMDDHH24MISS

END;

END-EXEC;

if ( g_return_sts == FAILURE )

{

sprintf(traceBuf, "%s. BSNL_DEE process terminated", g_error_msg.arr);

traceOutput(__LINE__, ERR_LVL, traceBuf);

g_rec_total++;

g_err_total++;

EXEC SQL ROLLBACK TO SAVEPOINT SAVEPOINT_MAIN;

UpdateProcessInstanceLogInfo(9);

EXEC SQL WHENEVER SQLERROR CONTINUE;

EXEC SQL COMMIT WORK RELEASE;

exit(1);

}


g_dun_action_ptr = (char *) malloc(sizeof(char) * g_dun_actiontype_str.len+1);

g_nondun_action_ptr = (char *) malloc(sizeof(char) * g_nondun_actiontype_str.len+1);

g_pms_feedfile_dir_ptr = (char *) malloc(sizeof(char) * g_pms_feedfile_dir_str.len+1);

g_vip_act_type_ptr = (char *) malloc(sizeof(char) * g_vip_act_type_info.len+1);

strcpy( g_dun_action_ptr,          (char *)g_dun_actiontype_str.arr);

strcpy( g_nondun_action_ptr,       (char *)g_nondun_actiontype_str.arr);

strcpy( g_pms_feedfile_dir_ptr,    (char *)g_pms_feedfile_dir_str.arr);

strcpy( g_vip_act_type_ptr,        (char *)g_vip_act_type_info.arr);

/*S***************************************************************

* Initializing old Dunning Account_num & old Account_num variables 

*****************************************************************S*/

l_last_dun_accnum = (char *) malloc(sizeof(char) * 2);

l_old_acc_num   = (char *) malloc(sizeof(char) * 2);

strcpy(l_last_dun_accnum, "0");

strcpy(l_old_acc_num, "0");

EXEC SQL WHENEVER SQLERROR GOTO ERR;

sprintf(traceBuf, "After retriving mandatory information successfully");

traceOutput(__LINE__, INF_LVL, traceBuf);

/***********************************************************************************

* Description: Updating BSNL_ACCOUNTATTRIBUTES table with pre IRB DEBT engine run information. 

*        If any error abort the BSNL_DEE process logging Error.

***********************************************************************************/

EXEC SQL EXECUTE 

BEGIN

:g_return_sts := BSNL_COLLECTION_PACKAGE.BSNL_UPDATE_PRE_PROCESS_DATA;

IF :g_return_sts = :FAILURE THEN

:g_error_msg := BSNL_COLLECTION_PACKAGE.GLOBAL_ERR;

END IF;

END;

END-EXEC;

if ( g_return_sts == FAILURE )

{

sprintf(traceBuf, "%s. BSNL_DEE process terminated...", g_error_msg.arr);

traceOutput(__LINE__, ERR_LVL, traceBuf);

g_rec_total++;

g_err_total++;

EXEC SQL ROLLBACK TO SAVEPOINT SAVEPOINT_MAIN;

UpdateProcessInstanceLogInfo(9);

EXEC SQL WHENEVER SQLERROR CONTINUE; 

EXEC SQL COMMIT WORK RELEASE;

exit(1);

}

sprintf(traceBuf, "Successfully updated eligible Accounts data information");

traceOutput(__LINE__, INF_LVL, traceBuf);

EXEC SQL COMMIT;

/************************************************************************************

* Description: Updating outstanding information of eligible Accounts by Running IRB debt engine.

*        If error encounters then log the error and terminate the process.

************************************************************************************/

sprintf(traceBuf, "Updating IRB DEBT engine information....%ld ", g_DEBTage_task_id);

traceOutput(__LINE__, INF_LVL, traceBuf);

EXEC SQL EXECUTE

BEGIN

:g_return_sts := BSNL_COLLECTION_PACKAGE.CREATE_DEBTAGE_TASK(:g_DEBTage_task_id);

END;

END-EXEC;

sprintf(traceBuf, "Updated IRB DEBT engine information with return status %d....", g_return_sts);

traceOutput(__LINE__, INF_LVL, traceBuf);

//----------- If IRB DEBT engine aborts then exit logging error now ----------

if ( g_return_sts != 0 && g_return_sts != 1 )

{

sprintf(traceBuf, "Error updating outstanding information by IRB debt engine (DEBTage). Aborting BSNL_DEE process. Please do the corrective action manually");

traceOutput(__LINE__, ERR_LVL, traceBuf);

EXEC SQL EXECUTE

BEGIN 

:g_error_msg  :=  'Error occured while updating outstanding information by IRB debt engine (DEBTage).';

:g_return_sts  :=  BSNL_COLLECTION_PACKAGE.BSNL_INSERT_ERROR_DATA( BSNL_COLLECTION_PACKAGE.G_SYSDATE,

   'BSNL_DEE',

   1,

   :g_error_msg);

END;

END-EXEC;

g_rec_total++;

g_err_total++;

EXEC SQL ROLLBACK TO SAVEPOINT SAVEPOINT_MAIN;

UpdateProcessInstanceLogInfo(9);

EXEC SQL WHENEVER SQLERROR CONTINUE; 

EXEC SQL COMMIT WORK RELEASE;

exit(1);

}

/************************************************************************************

* Description: If IRB DEBT engine finishes with error 

*        then exclude Errored Accounts from BSNL_DEE processing 

*        

************************************************************************************/

l_save_eli_cust_flag = 1;


if ( g_return_sts != 0 )

{

sprintf(traceBuf, "Excluding Accounts, for those error in updating outstanding information. Please do the corrective action manually");

traceOutput(__LINE__, WRN_LVL, traceBuf);

EXEC SQL

UPDATE BSNL_ACCOUNTATTRIBUTES  BAA

SET BAA.BSNLDEE_EXCLUDE_FLAG = 1

WHERE BAA.ACCOUNT_NUM IN (SELECT A.ACCOUNT_NUM FROM ACCOUNT A

      WHERE A.Debt_Analysis_Required_Dtm <= to_date(:g_systemdate, 'mm/dd/yyyy'));

}

EXEC SQL COMMIT;

//----------------- Creating second Savepoint ---------------------------------------

EXEC SQL SAVEPOINT SAVE_ELI_CUST_INFO;

/************************************************************************************

* Description: Retrieving Eligible Collection Data into cursor. 

*        If error encounters then BSNL_DEE process shall be aborted.

************************************************************************************/

EXEC SQL ALLOCATE :g_eli_acc_cursor;

strcpy( (char *)g_error_msg.arr, "Error retriving eligible customer data.");

EXEC SQL EXECUTE 

BEGIN

BSNL_COLLECTION_PACKAGE.BSNL_GET_COL_DATA ( :g_eli_acc_cursor );

END;

END-EXEC;

EXEC SQL WHENEVER SQLERROR GOTO ERR;

/***********************************************************************************

* Description: Generates PMS dunning file name dynamically & opens it if any error

*        abort the BSNL_DEE process logging Error.

***********************************************************************************/

t = time(NULL);

l_local_time =  localtime(&t);

memset( l_file_name, '\0', sizeof(l_file_name) );

sprintf( TIMESTAMP, "%02d%02d%02d%02d%02d%02d", l_local_time->tm_year+1900, l_local_time->tm_mon+1, l_local_time->tm_mday, l_local_time->tm_hour, l_local_time->tm_min, l_local_time->tm_sec);

/*sprintf( l_file_name, "%s/dunning_%s.csv", g_pms_feedfile_dir_ptr, TIMESTAMP);

//sprintf( l_file_name, "pms_col_dunning_info_%s.txt", TIMESTAMP);

l_pms_fhandle = fopen(l_file_name,"w+");

sprintf(traceBuf, "PMS dunning feed file %s created.", l_file_name);

traceOutput(__LINE__, INF_LVL, traceBuf);

if ( l_pms_fhandle == NULL)

{       

strcpy( (char *)g_error_msg.arr, "Error opening PMS DUNNING feed file.");

g_error_code = 1;

sprintf(traceBuf, "%s Error is %s.", g_error_msg.arr, strerror(errno) );

traceOutput(__LINE__, ERR_LVL, traceBuf);

goto ERR;

}

*/

EXEC SQL WHENEVER NOT FOUND GOTO FINISH;

/*S***********************************************************************************

* Description: Retrieving data from cursor record by record.

*        Checks type of Action for this record.

*        If Action type SMS or IVRS Call retrieve Contact Detail, if found then 

*        insert record else log error.

*        If Action type some Dunning Action retrieve all Event sourcess, if found then 

*        insert for each each event source record else log error.

*        If some other Action type then insert Action record else log error.

*        Update BSNL_ACCOUNTATTRIBUTES table with last processed record information

*        along with Dunning status information, and last time BSNL_DEE process 

*        run information for each Account.

*        Insert Dunning information into PMS feed file.

*        Error for each record shall be track seperatly and if any record goes into

*        error then log it seperatly and continue processing other records.

*        If any error encounters in BSNL_DEE process shall be aborted revoking full transaction.

*

***********************************************************************************S*/

for (;;)

{

//-- Resetting memory for all variable length variables ---

memset( g_new_acc_num.arr, '\0', g_new_acc_num.len );

memset( g_error_msg.arr,   '\0', g_error_msg.len );

        

//l_action_id = g_action_id;


//--------------- Fetching Cursor data record by record --------------- 

exec sql fetch :g_eli_acc_cursor INTO :g_new_acc_num, :g_new_bill_seq, :g_new_action_num, :g_action_id, :g_threshold_mny, :g_debt_age, :g_rollup_debt, :g_outstanding_tot, :g_credit_class;

//--------------- Assigning New Action Id to temp varible for comparison --------------- 

sprintf(g_action_id_str,"%d",g_action_id);


//-------------- If this is a new Account then log information related to previous Account --------

if ( strcmp( l_old_acc_num, (char *)g_new_acc_num.arr ) != 0 ) 

{

//--------- If this is not first Account to be processed then update BSNL_ACCOUNTATTRIBUTES table --------

if ( strcmp (l_old_acc_num, (char *)"0") != 0 ) 

{

EXEC SQL EXECUTE

BEGIN

:g_return_sts := BSNL_COLLECTION_PACKAGE.BSNL_INSERT_ACC_ATT_DATA(

    :l_old_acc_num,

    :l_old_bill_seq,

    :l_old_action_num,

    :g_threshold_mny,

    :l_action_id);

COMMIT;

END;


END-EXEC;


}

l_action_id = g_action_id;

l_old_action_num        = g_new_action_num;

l_old_bill_seq = g_new_bill_seq;

l_old_acc_num = (char *) malloc(sizeof(char) * g_new_acc_num.len+1);

strcpy(l_old_acc_num,(char *)g_new_acc_num.arr);

}

//------------------ Creating new SAVEPOINT ---------------

EXEC SQL SAVEPOINT ROLLBACK_THIS_REC;

//--------------- If Old & New Bill Seq equals then insert this Action --------------- 

if ( l_old_bill_seq == g_new_bill_seq )

{

l_action_id = g_action_id;

l_old_action_num = g_new_action_num;

l_old_bill_seq = g_new_bill_seq;

l_old_acc_num = (char *) malloc(sizeof(char) * g_new_acc_num.len+1);

strcpy(l_old_acc_num,(char *)g_new_acc_num.arr);

//--------------- If Action type 'SMS' or 'IVRS Call' then use following logic ---------------

if ( tokencheck( g_nondun_action_ptr, g_action_id) == 1 ) 

{

        EXEC SQL EXECUTE

BEGIN

:g_return_sts := BSNL_COLLECTION_PACKAGE.BSNL_PROCESS_SOFT_ACTION(

       :g_new_acc_num,

       :g_new_bill_seq, 

       :g_new_action_num, 

       :g_action_id, 

       :g_outstanding_tot,

       :g_rollup_debt,

       :g_credit_class,

       :g_bb_prod_id,

       :g_rec_total,

       :g_err_total,

       :g_suc_total);

END;

END-EXEC;

//------ If Error then rollback updates for this record -----

if ( g_return_sts == FAILURE )

{

sprintf(traceBuf, "Error processing Account %s,for Bill Sequence %ld, Action Number %d, with Action ID %d", g_new_acc_num.arr, g_new_bill_seq, g_new_action_num, g_action_id);

traceOutput(__LINE__, WRN_LVL, traceBuf);

EXEC SQL ROLLBACK TO SAVEPOINT ROLLBACK_THIS_REC;

}

//if ( ( g_return_sts != SUCCESS) && ( g_return_sts != NOT_ELIG ))

if ( g_return_sts == SUCCESS )

{

if (traceFlag == FLAG_ON)

{

sprintf(traceBuf, "Successfully processed Account %s,for Bill Sequence %ld, Action Number %d, with Action ID %d", g_new_acc_num.arr, g_new_bill_seq, g_new_action_num, g_action_id);

traceOutput(__LINE__, INF_LVL, traceBuf);

}

}

}

//--------------- If Action type 'OGB_VIP' or 'ICB_VIP' then use following logic ---------------

if ( tokencheck( g_vip_act_type_ptr, g_action_id) == 1 ) 

{

        EXEC SQL EXECUTE

BEGIN

:g_return_sts := BSNL_COLLECTION_PACKAGE.BSNL_PROCESS_VIP_ACTION(

       :g_new_acc_num,

       :g_new_bill_seq, 

       :g_new_action_num, 

       :g_action_id, 

       :g_outstanding_tot,

       :g_rollup_debt,

       :g_credit_class,

       :g_ogb_vip_act_id,

       :g_bb_prod_id,

       :g_rec_total,

       :g_err_total,

       :g_suc_total);

END;

END-EXEC;

//------ If Error then rollback updates for this record -----

if ( g_return_sts == FAILURE )

{

sprintf(traceBuf, "Error processing VIP Account %s,for Bill Sequence %ld, Action Number %d, with Action ID %d", g_new_acc_num.arr, g_new_bill_seq, g_new_action_num, g_action_id);

traceOutput(__LINE__, WRN_LVL, traceBuf);

EXEC SQL ROLLBACK TO SAVEPOINT ROLLBACK_THIS_REC;

}

//if ( ( g_return_sts != SUCCESS) && ( g_return_sts != NOT_ELIG ))

if ( g_return_sts == SUCCESS )

{

if (traceFlag == FLAG_ON)

{

sprintf(traceBuf, "Successfully processed VIP Account %s,for Bill Sequence %ld, Action Number %d, with Action ID %d", g_new_acc_num.arr, g_new_bill_seq, g_new_action_num, g_action_id);

traceOutput(__LINE__, INF_LVL, traceBuf);

}

}

}


// --------- If action type some Dunning Action type --------------

if ( tokencheck( g_dun_action_ptr, g_action_id) == 1 )

{

        EXEC SQL EXECUTE

BEGIN

:g_return_sts := BSNL_COLLECTION_PACKAGE.BSNL_PROCESS_EVENT_ACTION(

       :g_new_acc_num,

       :g_new_bill_seq, 

       :g_new_action_num, 

       :g_action_id, 

       :g_outstanding_tot,

       :g_rollup_debt,

       :g_credit_class,

       :g_bb_prod_id,

       :g_bb_bar_prod_id,

       :g_pd_act_type_info,

       :g_rec_total,

       :g_err_total,

       :g_suc_total);

END;

END-EXEC;

if ( g_return_sts == SUCCESS )

{

//-------- Check if this Account Name already have entry in PMS Dunning file ------

if ( strcmp( l_last_dun_accnum, (char *)g_new_acc_num.arr ) != 0 )

{

l_last_dun_accnum   = (char *) malloc(sizeof(char) * g_new_acc_num.len+1);

strcpy(l_last_dun_accnum,(char *)g_new_acc_num.arr);

if ( g_action_id != g_pd_act_type_info ) {

EXEC SQL EXECUTE

   BEGIN

:g_return_sts :=BSNL_COLLECTION_PACKAGE.BSNL_INSERT_PMS_FEED_DATA(:g_new_acc_num,

  :g_threshold_mny/1000,

  :g_pmsfeeddate);

IF :g_return_sts = :FAILURE THEN

:g_error_msg  := BSNL_COLLECTION_PACKAGE.GLOBAL_ERR;

END IF;

   END;

END-EXEC;

if ( g_return_sts != SUCCESS)

{

  sprintf(traceBuf, "%s", g_error_msg.arr);

  traceOutput(__LINE__, WRN_LVL, traceBuf);

    EXEC SQL ROLLBACK TO SAVEPOINT ROLLBACK_THIS_REC;

  continue;

}


/*

l_fwrite_sts = fprintf (l_pms_fhandle,"%s,%.0f,%s\n",g_new_acc_num.arr, g_threshold_mny/1000, g_pmsfeeddate.arr);

if ( l_fwrite_sts != NULL)

{

g_file_rec_cnt++;

}else

{

sprintf(traceBuf, "Error in writing in PMS file for Account %s with threshold money %.0f and processing date %s.", g_new_acc_num.arr, g_threshold_mny, g_pmsfeeddate.arr);

traceOutput(__LINE__, WRN_LVL, traceBuf);

sprintf(traceBuf, "Error processing Account %s,for Bill Sequence %ld, Action Number %d, with Action ID %d", g_new_acc_num.arr, g_new_bill_seq, g_new_action_num, g_action_id);

traceOutput(__LINE__, WRN_LVL, traceBuf);

EXEC SQL EXECUTE

BEGIN 

:g_error_msg := 'Error writing in PMS_DUNNING file for Account "'||:g_new_action_num|| '" with threshold money "' ||:g_threshold_mny || '" and processing date "' || :g_pmsfeeddate || '".';

:g_return_sts :=  BSNL_COLLECTION_PACKAGE.BSNL_INSERT_ERROR_DATA(

BSNL_COLLECTION_PACKAGE.G_SYSDATE,

'BSNL_DEE',

:FAILURE,

:g_error_msg);

END;

END-EXEC;

EXEC SQL ROLLBACK TO SAVEPOINT ROLLBACK_THIS_REC;

}

*/

}

}//else 

//{

if (traceFlag == FLAG_ON)

{

sprintf(traceBuf, "Successfully processed Account %s,for Bill Sequence %ld, Action Number %d, with Action ID %d", g_new_acc_num.arr, g_new_bill_seq, g_new_action_num, g_action_id);

traceOutput(__LINE__, INF_LVL, traceBuf);

}

//}

}

//if ( ( g_return_sts != SUCCESS) && ( g_return_sts != NOT_ELIG ))

if ( g_return_sts == FAILURE )

{

sprintf(traceBuf, "Error processing Account %s,for Bill Sequence %ld, Action Number %d, with Action ID %d", g_new_acc_num.arr, g_new_bill_seq, g_new_action_num, g_action_id);

traceOutput(__LINE__, WRN_LVL, traceBuf);

EXEC SQL ROLLBACK TO SAVEPOINT ROLLBACK_THIS_REC;

}

}//-------------- Logic for Same Bill for this Account ends here ---------------

} //----------------------- end loop for eligible Account records processing ------------------

FINISH:

/*fclose(l_pms_fhandle); // SS

if (g_file_rec_cnt == 0 )

{

if ( remove (l_file_name) == -1 )

{

sprintf(traceBuf, "Error deleting zero size PMS file '%s'", l_file_name);

traceOutput(__LINE__, WRN_LVL, traceBuf);

}else

{

sprintf(traceBuf, "Deleted zero size PMS file '%s' successfully", l_file_name);

traceOutput(__LINE__, INF_LVL, traceBuf);

}

}else { 

        memset( l_pms_done_file, '\0', sizeof(l_pms_done_file) );

sprintf( l_pms_done_file, "%s/dunning_%s.done", g_pms_feedfile_dir_ptr, TIMESTAMP);

l_pms_fhandle = fopen(l_pms_done_file,"w+");


sprintf(traceBuf, "Created zero size pms .done file %s", l_pms_done_file);

traceOutput(__LINE__, INF_LVL, traceBuf);

fclose(l_pms_fhandle);

}

*/

sprintf(traceBuf, "Finally Total records %ld, Success records %ld, Errored records %ld...", g_rec_total, g_suc_total, g_err_total);

traceOutput(__LINE__, INF_LVL, traceBuf);


//------------- Finally inserting details for Last processed Account -------------

if ( strcmp (l_old_acc_num, (char *)"0") != 0 ) 

{       

EXEC SQL EXECUTE

BEGIN

:g_return_sts := BSNL_COLLECTION_PACKAGE.BSNL_INSERT_ACC_ATT_DATA(

    :l_old_acc_num,

    :l_old_bill_seq,

    :l_old_action_num,

    :g_threshold_mny,

    :l_action_id);

COMMIT;

END;

END-EXEC;

}

/*********************************************************************************

* Description: If file is of zero size then remove it 

*        Else, retrive the value of PMS file destination location.

*        Move the PMS file to the desired location. If error then log it.

*********************************************************************************/


//Closing the cursor and committing everything till now

EXEC SQL CLOSE :g_eli_acc_cursor;

EXEC SQL COMMIT;


EXEC SQL EXECUTE

BEGIN

BSNL_COLLECTION_PACKAGE.BSNL_SUPRESS_ACTION( P_ERROR_CODE    =>  :g_error_code INDICATOR :g_ind_var,

             P_ERROR_MESSAGE =>  :g_error_msg INDICATOR :g_ind_var);

END;

END-EXEC;


CreateFeedFile();  //To be un-commented once to make automatic


EXEC SQL EXECUTE

BEGIN

:g_return_sts :=BSNL_COLLECTION_PACKAGE.BSNL_CREATE_PMS_FILE( P_PMS_FILE_DIR  => :g_pms_feedfile_dir_str,

      P_PMS_FEED_FILE => :g_pms_feed_filename INDICATOR :g_ind_var);

IF :g_return_sts = :FAILURE THEN

:g_error_msg:= BSNL_COLLECTION_PACKAGE.GLOBAL_ERR;

END IF;

END;

END-EXEC;

if ( g_return_sts == 0) 

{

if ( strcmp( "0", (char *)g_pms_feed_filename.arr ) != 0 ) 

{

sprintf(traceBuf, "PMS feed file created at %s,with file Name %s", g_pms_feedfile_dir_str.arr, g_pms_feed_filename.arr);

traceOutput(__LINE__, INF_LVL, traceBuf);

}

}

else 

{

sprintf(traceBuf, "%s", g_error_msg.arr);

traceOutput(__LINE__, WRN_LVL, traceBuf);

}

if ( g_err_total != 0)

UpdateProcessInstanceLogInfo(8);

else

UpdateProcessInstanceLogInfo(7);




//--------------- Process finish notification --------------- 

EXEC SQL WHENEVER SQLERROR CONTINUE; 

EXEC SQL COMMIT WORK RELEASE;

sprintf(traceBuf, "Finished BSNL_DEE process");

traceOutput(__LINE__, INF_LVL, traceBuf);

exit(0);

//If error then insert into BSNL_DEBT_ERROR_LOG table...

ERR:

strcat ((char *)g_error_msg.arr, sqlca.sqlerrm.sqlerrmc);

g_error_msg.len = strlen((char *)g_error_msg.arr);

if (g_error_code != 1)

g_error_code     = sqlca.sqlcode;

sprintf(traceBuf, "Process finished with error %s", g_error_msg.arr);

traceOutput(__LINE__, INF_LVL, traceBuf);

EXEC SQL CLOSE :g_eli_acc_cursor;

//----- Following to avoid the infinite loop in case ROLLBACK fails -----

EXEC SQL EXECUTE

BEGIN 

:g_return_sts := BSNL_COLLECTION_PACKAGE.BSNL_INSERT_ERROR_DATA(BSNL_COLLECTION_PACKAGE.G_SYSDATE,

       'BSNL_DEE',

       :g_error_code,

       :g_error_msg);

END;

END-EXEC;

if (g_err_total == 0)

{

g_rec_total++;

g_err_total++;

}


if ( l_save_eli_cust_flag == 1 )

EXEC SQL ROLLBACK TO SAVEPOINT SAVE_ELI_CUST_INFO;

else

EXEC SQL ROLLBACK TO SAVEPOINT SAVEPOINT_MAIN;


UpdateProcessInstanceLogInfo(9);

//--------------- Process finish notification --------------- 

sprintf(traceBuf, "Finished BSNL_DEE process with errors");

traceOutput(__LINE__, INF_LVL, traceBuf);

EXEC SQL WHENEVER SQLERROR CONTINUE; 

EXEC SQL COMMIT WORK RELEASE;

exit(1);

}


/*F************************************************************************

 *

 * FUNCTION   :  traceOutput

 *

 * PARAMETERS : lineNo   - This is the source code line number.

 *              funcName - Name of the function for which this trace has

 *                         to be written.

 *              level    - trace level. ERR_LVL and WRN_LVL will always

 *                         be written.

 *              msg      - Message to be displayed on STDOUT.

 *

 * RETURNS    : Nothing

 *

 * Description: This function is used to write error messages in standard

 *              Convergys format to stderr.

 *

 ***************************************************************************/


void traceOutput(int lineNo, 

int level, 

const char *msg )

{

    char l_local_dtm[DATETIMELEN+1];

    struct tm *l_local_time;

    time_t t;


    memset( l_local_dtm, '\0', sizeof(l_local_dtm) );

    t = time(NULL);

    l_local_time =  localtime(&t);

    sprintf( l_local_dtm, "%02d/%02d/%02d %02d:%02d:%02d", l_local_time->tm_mday, l_local_time->tm_mon+1,

                                                         l_local_time->tm_year-100, l_local_time->tm_hour,

                                                         l_local_time->tm_min, l_local_time->tm_sec );

    if (level == TRC_LVL)

    {

        fprintf( stderr, "TRACE-----%s:%d:%s > %s\n", __FILE__, lineNo, l_local_dtm, msg );

    }

    else if (level == ERR_LVL )

    {

        fprintf( stderr, "ERROR-----%s:%d:%s > %s\n", __FILE__, lineNo, l_local_dtm, msg );

    }

    else if (level == WRN_LVL )

    {

        fprintf( stderr, "WARN------%s:%d:%s > %s\n", __FILE__, lineNo, l_local_dtm, msg );

    }

    else if (level == INF_LVL)

    {

fprintf( stderr, "INFORM----%s:%d:%s > %s\n", __FILE__, lineNo, l_local_dtm, msg );

    }


}/* end of traceOutput() */




No comments:

Post a Comment

Small coding languages

  Yes, Hack is a programming language developed by Facebook (now Meta) as a dialect of PHP. It was designed to address some of the limitatio...