
* PROGRAM: COST_SHARING_PREVENTIVE_DENTAL.SAS;
* DESCRIPTION: PERFORM COST SHARING ALGORITHM FOR PREVENTIVE DENTAL CLAIMS;


%MACRO DENTAL_PREV_COST_SHARE(SERV_CAT);

  DATA DENTAL_BASEID;
    RETAIN JOIN_ID '1';
    SET &INC(WHERE=(CATEGORY='16'));
    SRVCNT = 0;
    SRVCNT = SUM(DVPERIOD,DVEXTRAC,DVRTCNAL,DVCROWN,DVBRIDGE,DVOTHER,DVORTHO,DVCLEAN,DVEXAM,DVXRAYS,DVFILLNG);
    CATEGORY='16a';
  RUN;

  DATA DENTAL_FILE;
    SET PBP_FILE (KEEP =
                  CONTRACT_ID PLAN_ID SEGMENT_ID HPLAN
                  PBP_B16A_MAXENR_AMT PBP_B16A_MAXENR_PER
                  PBP_B16B_MAXENR_AMT PBP_B16B_MAXENR_PER
                  PBP_B16A_BENDESC_AMO_PC PBP_B16A_BENDESC_AMO_DX PBP_B16A_BENDESC_AMO_OE
                  PBP_B16B_MAXBENE_TYPE PBP_B16B_BENDESC_AMO_END PBP_B16B_BENDESC_AMO_EXT
                  PBP_B16B_BENDESC_AMO_PERI PBP_B16B_BENDESC_AMO_RS
                  PBP_B16B_BENDESC_AMO_POO
                  PBP_B16A_COPAY_AMT_PCMIN
                  PBP_B16A_COPAY_AMT_DXMIN
                  PBP_B16A_COPAY_AMT_OEMIN
                  PBP_B16B_COPAY_AMT_END_MIN
                  PBP_B16B_COPAY_AMT_EXT_MIN
                  PBP_B16B_COPAY_AMT_PERI_MIN
                  PBP_B16B_COPAY_AMT_RS_MIN
                  PBP_B16B_COPAY_AMT_POO_MIN
                  PBP_B16A_COINS_PCT_PC PBP_B16A_DED_AMT PBP_B16B_DED_AMT
                  PBP_B16A_COINS_PCT_DX
                  PBP_B16A_COINS_PCT_OE
                  PBP_B16B_COINS_PCT_END_MIN
                  PBP_B16B_COINS_PCT_EXT_MIN
                  PBP_B16B_COINS_PCT_PERI_MIN
                  PBP_B16B_COINS_PCT_RS_MIN
                  PBP_B16B_COINS_PCT_POO_MIN
                  PBP_B16A_COPAY_AMT_OVMIN
                  PBP_B16A_COPAY_AMT_OVMAX
                  PBP_B16A_COINS_PCT_MINOV
                  PBP_B16A_COINS_PCT_MAXOV
                  PBP_B16A_COINS_CSERV_SC_POV
                  PBP_B16A_COPAY_CSERV_SC_POV
                  PBP_B16A_MAXPLAN_AMT
                  PBP_B16A_MAXPLAN_PER
                  PBP_B16B_MAXPLAN_AMT
                  PBP_B16B_MAXPLAN_PER
                  PBP_B16B_MAXBENE_TYPE
                  PBP_B16B_MAXENR_TYPE
                  PBP_B16A_BENDESC_NUMV_OE
                  PBP_B16A_BENDESC_NUMV_PC
                  PBP_B16A_BENDESC_NUMV_DX
                  PBP_B16B_BENDESC_NUMV_RS
                  PBP_B16B_BENDESC_NUM_END
                  PBP_B16B_BENDESC_NUM_EXT
                  PBP_B16B_BENDESC_NUM_PERI
                  PBP_B16B_BENDESC_NUMV_POO
                  PBP_B16A_BENDESC_PER_OE
                  PBP_B16A_BENDESC_PER_PC
                  PBP_B16A_BENDESC_PER_DX
                  PBP_B16B_BENDESC_PER_RS
                  PBP_B16B_BENDESC_PER_END
                  PBP_B16B_BENDESC_PER_EXT
                  PBP_B16B_BENDESC_PER_PERI
                  PBP_B16B_BENDESC_PER_POO
                  
                  PBP_B16A_COPAY_EHC
                  PBP_B16A_COINS_EHC
                  PBP_B16B_COPAY_EHC
                  PBP_B16B_COINS_EHC
                  PBP_A_PLAN_TYPE
                  PBP_D_DIFF_DEDUCT_16A_AMT
                  PBP_D_NMC_DEDUCT_YN
                  PBP_D_DEDUCT_PREVDENTAL_AMT);
    JOIN_ID = '1';
  
    ARRAY MX PBP_B16A_BENDESC_NUMV_OE PBP_B16A_BENDESC_NUMV_PC PBP_B16A_BENDESC_NUMV_DX
             PBP_B16B_BENDESC_NUMV_RS PBP_B16B_BENDESC_NUM_END PBP_B16B_BENDESC_NUM_EXT 
             PBP_B16B_BENDESC_NUM_PERI PBP_B16B_BENDESC_NUMV_POO
             PBP_B16A_MAXENR_AMT PBP_B16B_MAXENR_AMT PBP_B16A_MAXPLAN_AMT PBP_B16B_MAXPLAN_AMT;
    ARRAY PX PBP_B16A_BENDESC_PER_OE PBP_B16A_BENDESC_PER_PC PBP_B16A_BENDESC_PER_DX
             PBP_B16B_BENDESC_PER_RS PBP_B16B_BENDESC_PER_END PBP_B16B_BENDESC_PER_EXT 
             PBP_B16B_BENDESC_PER_PERI PBP_B16B_BENDESC_PER_POO
             PBP_B16A_MAXENR_PER PBP_B16B_MAXENR_PER PBP_B16A_MAXPLAN_PER PBP_B16B_MAXPLAN_PER;
  
    DO I = 1 TO 12;
      IF MX(I) NE . THEN DO;
        IF PX(I)  = '1' THEN MX(I) = MX(I)  / 3; * EVERY THREE YEARS;
        ELSE IF PX(I)  = '2' THEN MX(I) = MX(I)  / 2; * EVERY TWO YEARS;
        ELSE IF PX(I)  = '3' THEN MX(I) = MX(I) / 1; * EVERY YEAR;
        ELSE IF PX(I)  = '4' THEN MX(I) = MX(I)  * 2; * EVERY SIX MONTHS;
        ELSE IF PX(I)  = '5' THEN MX(I) = MX(I)  * 4; * EVERY THREE MONTHS;
        ELSE IF PX(I)  = '6' THEN MX(I) = MX(I) ; * OTHER;
      END;
    END;
  RUN;

  PROC SQL;
    CREATE TABLE CAT_JOIN AS
      (SELECT B.CATEGORY, B.BASEID, B.YEAR, B.AMTTOT, B.DVCLEAN, B.DVEXAM, B.DVXRAYS, B.DVFILLNG,
      B.DVPERIOD, B.DVEXTRAC, B.DVRTCNAL, B.DVCROWN, B.DVBRIDGE, B.DVOTHER, B.DVORTHO, B.SRVCNT, 
      B.PREVENT_DENTAL_SHARE, P.*
      FROM DENTAL_BASEID B, DENTAL_FILE P
      WHERE B.JOIN_ID = P.JOIN_ID)
      ORDER BY HPLAN, BASEID, YEAR, CATEGORY;
    QUIT;
  RUN;
  
  DATA CAT_JOIN;
    MERGE CAT_JOIN (IN = A) 
          PBPCATS_MCCOST_DED (IN = B WHERE=(CATEGORY='16a'));
    BY HPLAN BASEID YEAR CATEGORY;
    IF A;
    LENGTH PLAN_DED_CAT $1;
    IF B THEN PLAN_DED_CAT='1';
    ELSE PLAN_DED_CAT='0';
  RUN;

  DATA &SERV_CAT;
    ARRAY MX PBP_B16A_BENDESC_NUMV_OE PBP_B16A_BENDESC_NUMV_PC PBP_B16A_BENDESC_NUMV_DX
          PBP_B16B_BENDESC_NUMV_RS PBP_B16B_BENDESC_NUM_END PBP_B16B_BENDESC_NUM_EXT 
          PBP_B16B_BENDESC_NUM_PERI PBP_B16B_BENDESC_NUMV_POO
          PBP_B16A_MAXENR_AMT PBP_B16B_MAXENR_AMT PBP_B16A_MAXPLAN_AMT PBP_B16B_MAXPLAN_AMT;
    ARRAY SX SERVICE_MAX_OE SERVICE_MAX_PC SERVICE_MAX_DX
          SERVICE_MAX_RS SERVICE_MAX_END SERVICE_MAX_EXT SERVICE_MAX_PERI SERVICE_MAX_POO
          BENE_MAXIMUM_P BENE_MAXIMUM_C PLAN_MAXIMUM_P PLAN_MAXIMUM_C;
    SET CAT_JOIN (DROP = JOIN_ID);

    PREV_SERVICE_CNT = SUM(DVCLEAN,DVEXAM,DVXRAYS);
    
    IF PREV_SERVICE_CNT>0;

    DO I = 1 TO 12;
      IF MX(I) NE . THEN DO;
        SX(I) = MX(I);
      END;
    END;
    
    IF PLAN_DED_CAT='1' THEN DO;
      PLAN_DED_AMTTOT_AMO_PTB=SUM(PLAN_DEDUCT_PTB,-PLAN_DED_AMTTOT_MC_PTB);
      IF PLAN_DED_AMTTOT_AMO_PTB>0 THEN CAT_DEDUCTIBLE=PLAN_DED_AMTTOT_AMO_PTB;
      ELSE CAT_DEDUCTIBLE=SUM(PLAN_DED_AMTTOT,-PLAN_DED_AMTTOT_MC);
    END;
    ELSE IF PBP_A_PLAN_TYPE IN('04','31','44','47') THEN 
      CAT_DEDUCTIBLE=PBP_D_DIFF_DEDUCT_16A_AMT;
    ELSE CAT_DEDUCTIBLE=PBP_B16A_DED_AMT;

    CAT_DEDUCTIBLE_SUP=0; 
    IF PBP_D_DEDUCT_PREVDENTAL_AMT>0 THEN CAT_DEDUCTIBLE_SUP=PBP_D_DEDUCT_PREVDENTAL_AMT;
    
    PREV_AM = '000';
    IF PBP_B16A_BENDESC_AMO_PC IN ('1','2') THEN SUBSTR(PREV_AM,1,1) = '1';
    IF PBP_B16A_BENDESC_AMO_DX IN ('1','2') THEN SUBSTR(PREV_AM,2,1) = '1';
    IF PBP_B16A_BENDESC_AMO_OE IN ('1','2') THEN SUBSTR(PREV_AM,3,1) = '1';
 
    OV_SVCS_COINS = '000';
    IF SUBSTR(PBP_B16A_COINS_CSERV_SC_POV,3,1) = '1' THEN SUBSTR(OV_SVCS_COINS,1,1) = '1';
    IF SUBSTR(PBP_B16A_COINS_CSERV_SC_POV,1,1) = '1' THEN SUBSTR(OV_SVCS_COINS,2,1) = '1';
    IF SUBSTR(PBP_B16A_COINS_CSERV_SC_POV,2,1) = '1' THEN SUBSTR(OV_SVCS_COINS,3,1) = '1';

    OV_SVCS_COPAY = '000';
    IF SUBSTR(PBP_B16A_COPAY_CSERV_SC_POV,3,1) = '1' THEN SUBSTR(OV_SVCS_COPAY,1,1) = '1';
    IF SUBSTR(PBP_B16A_COPAY_CSERV_SC_POV,1,1) = '1' THEN SUBSTR(OV_SVCS_COPAY,2,1) = '1';
    IF SUBSTR(PBP_B16A_COPAY_CSERV_SC_POV,2,1) = '1' THEN SUBSTR(OV_SVCS_COPAY,3,1) = '1';

    *PER_SERVICE_AMT = AMTTOT / SRVCNT;
    
    PREV_SERVICE_CNT = SUM(DVCLEAN,DVEXAM,DVXRAYS);
    COMP_SERVICE_CNT = SUM(DVFILLNG, DVPERIOD, DVEXTRAC, DVRTCNAL, DVCROWN, DVBRIDGE, DVOTHER, DVORTHO);

    AMTTOT_PREV = PREVENT_DENTAL_SHARE * AMTTOT; 
    AMTTOT_COMP = (1-PREVENT_DENTAL_SHARE) * AMTTOT; 

    PER_SERVICE_AMT = AMTTOT_PREV / PREV_SERVICE_CNT;

    IF SUM(AMTTOT_PREV,AMTTOT_COMP) > 0 THEN 
      PREVENTIVE_SHARE=PREVENT_DENTAL_SHARE;
    ELSE PREVENTIVE_SHARE=0;
    
    IF PBP_B16B_MAXBENE_TYPE = '1' THEN PLAN_MAXIMUM_P=PLAN_MAXIMUM_P*PREVENTIVE_SHARE;
    
    NONCOV_COST = 0;

    ARRAY DP DVCLEAN DVEXAM DVXRAYS;

    IF AMTTOT_PREV <= SUM(CAT_DEDUCTIBLE,CAT_DEDUCTIBLE_SUP) THEN DO;
      NONCOV_COST = SUM(NONCOV_COST,AMTTOT_PREV);
      DO OVER DP;
        DP = 0;
      END;
    END;
    ELSE IF SUM(CAT_DEDUCTIBLE,CAT_DEDUCTIBLE_SUP) > 0 THEN DO;
      NONCOV_COST = SUM(NONCOV_COST,SUM(CAT_DEDUCTIBLE,CAT_DEDUCTIBLE_SUP));
      DED_SHARE = SUM(CAT_DEDUCTIBLE,CAT_DEDUCTIBLE_SUP) / AMTTOT_PREV;
      AMTTOT_PREV = SUM(AMTTOT_PREV,-(SUM(CAT_DEDUCTIBLE,CAT_DEDUCTIBLE_SUP)));
      DO OVER DP;
        DP = DP * (1 - DED_SHARE);
      END;
    END;

    * APPLY SERVICE COUNT MAX FIRST;
    IF SERVICE_MAX_OE > 0 AND SERVICE_MAX_OE < DVEXAM THEN DO;
      NONCOV_COST = SUM(NONCOV_COST,SUM(DVEXAM,-SERVICE_MAX_OE) * PER_SERVICE_AMT);
      DVEXAM = SERVICE_MAX_OE;
    END;
    IF SERVICE_MAX_PC > 0 AND SERVICE_MAX_PC < DVCLEAN THEN DO;
      NONCOV_COST = SUM(NONCOV_COST,SUM(DVCLEAN,-SERVICE_MAX_PC) * PER_SERVICE_AMT);
      DVCLEAN = SERVICE_MAX_PC;
    END;
    IF SERVICE_MAX_DX > 0 AND SERVICE_MAX_DX < DVXRAYS THEN DO;
      NONCOV_COST = SUM(NONCOV_COST,SUM(DVXRAYS,-SERVICE_MAX_DX) * PER_SERVICE_AMT);
      DVXRAYS = SERVICE_MAX_DX;
    END;
    
    PREV_SERVICE_CNT = SUM(DVCLEAN,DVEXAM,DVXRAYS);
    
    AMTTOT_PREV = PREV_SERVICE_CNT * PER_SERVICE_AMT;
    
    NONCOV_COST_MAXDOL = 0;
    NONCOV_COST_MAXDOL_P = 0;
    
    * APPLY PLAN MAXIMUM;
    IF PLAN_MAXIMUM_P > 0 THEN NONCOV_COST_MAXDOL_P = MAX(0,SUM(AMTTOT_PREV,-PLAN_MAXIMUM_P));
      
    NONCOV_COST_MAXDOL = NONCOV_COST_MAXDOL_P;

    IF AMTTOT_PREV > 0 THEN
      COVERED_SHARE_P = SUM(AMTTOT_PREV,-NONCOV_COST_MAXDOL_P) / AMTTOT_PREV;
      
    DO OVER DP;
      DP = DP * COVERED_SHARE_P;
    END;
      
    *APPLY INDIVIDUAL COSTS FOR PREV BENEFITS;

    IF DVCLEAN > 0 THEN DO;
      IF SUBSTR(PREV_AM,1,1) = '1' THEN DO;
        IF SUBSTR(OV_SVCS_COPAY,1,1) = '0' & SUBSTR(PBP_B16A_COPAY_EHC,3,1)='1' THEN 
          PC_COST_SHARE = PBP_B16A_COPAY_AMT_PCMIN * DVCLEAN;
        IF SUBSTR(OV_SVCS_COINS,1,1) = '0' & SUBSTR(PBP_B16A_COINS_EHC,3,1)='1' THEN
          PC_COST_SHARE = SUM(PC_COST_SHARE,(PER_SERVICE_AMT * DVCLEAN * PBP_B16A_COINS_PCT_PC));
      END;
      ELSE DO;
        PC_OTHER_COST = PER_SERVICE_AMT * DVCLEAN;
      END;
    END;

    IF DVXRAYS > 0 THEN DO;
      IF SUBSTR(PREV_AM,2,1) = '1' THEN DO;
        IF SUBSTR(OV_SVCS_COPAY,2,1) = '0' & SUBSTR(PBP_B16A_COPAY_EHC,1,1)='1' THEN 
          DX_COST_SHARE = PBP_B16A_COPAY_AMT_DXMIN * DVXRAYS;
        IF SUBSTR(OV_SVCS_COINS,2,1) = '0' & SUBSTR(PBP_B16A_COINS_EHC,1,1)='1' THEN
          DX_COST_SHARE = SUM(DX_COST_SHARE,(PER_SERVICE_AMT * DVXRAYS * PBP_B16A_COINS_PCT_DX));
      END;
      ELSE DO;
        DX_OTHER_COST = PER_SERVICE_AMT * DVXRAYS;
      END;
    END;

    IF DVEXAM > 0 THEN DO;
      IF SUBSTR(PREV_AM,3,1) = '1' THEN DO;
        IF SUBSTR(OV_SVCS_COPAY,3,1) = '0' & SUBSTR(PBP_B16A_COPAY_EHC,2,1)='1' THEN 
          OE_COST_SHARE = PBP_B16A_COPAY_AMT_OEMIN * DVEXAM;
        IF SUBSTR(OV_SVCS_COINS,3,1) = '0' & SUBSTR(PBP_B16A_COINS_EHC,2,1)='1' THEN
          OE_COST_SHARE = SUM(OE_COST_SHARE,(PER_SERVICE_AMT * DVEXAM * PBP_B16A_COINS_PCT_OE));
      END;
      ELSE DO;
        OE_OTHER_COST = PER_SERVICE_AMT * DVEXAM;
      END;
    END;

    *APPLY OFFICE VISIT COSTS FOR PREV BENEFITS;

    IF SUBSTR(PREV_AM,1,1) = '1' AND SUBSTR(OV_SVCS_COPAY,1,1) = '1' THEN
       OV_COST_SHARE = PBP_B16A_COPAY_AMT_OVMIN * DVCLEAN;
    ELSE IF SUBSTR(PREV_AM,3,1) = '1' AND SUBSTR(OV_SVCS_COPAY,3,1) = 1 THEN
       OV_COST_SHARE = PBP_B16A_COPAY_AMT_OVMIN * DVEXAM;
    ELSE IF SUBSTR(PREV_AM,2,1) = '1' AND SUBSTR(OV_SVCS_COPAY,2,1) = 1 THEN
       OV_COST_SHARE = PBP_B16A_COPAY_AMT_OVMIN * DVXRAYS;

    IF SUBSTR(PREV_AM,1,1) = '1' AND SUBSTR(OV_SVCS_COINS,1,1) = '1' THEN
      OV_COST_SHARE = SUM(OV_COST_SHARE,PER_SERVICE_AMT * DVCLEAN * PBP_B16A_COINS_PCT_MINOV);
    ELSE IF SUBSTR(PREV_AM,3,1) = '1' AND SUBSTR(OV_SVCS_COINS,3,1) = '1' THEN
      OV_COST_SHARE = SUM(OV_COST_SHARE,PER_SERVICE_AMT * DVEXAM * PBP_B16A_COINS_PCT_MINOV);
    ELSE IF SUBSTR(PREV_AM,2,1) = '1' AND SUBSTR(OV_SVCS_COINS,2,1) = '1' THEN
      OV_COST_SHARE = SUM(OV_COST_SHARE,PER_SERVICE_AMT * DVXRAYS * PBP_B16A_COINS_PCT_MINOV);

    COST_SHARE_COST_P = SUM(PC_COST_SHARE,DX_COST_SHARE,OE_COST_SHARE,OV_COST_SHARE);
    
    COST_SHARE_COST = MIN(BENE_MAXIMUM_P,MAX(COST_SHARE_COST_P,0));
        
    OTHER_COST = SUM(PC_OTHER_COST, DX_OTHER_COST, OE_OTHER_COST, 
      NONCOV_COST, NONCOV_COST_MAXDOL);
    
    COST_SHARE_COST_MC  = 0;
    COST_SHARE_COST_AMO = COST_SHARE_COST;

    CATEGORY = "16a";
  RUN;
  
  PROC SORT DATA = DENTAL;
    BY HPLAN;
  RUN;

  PROC SUMMARY DATA = DENTAL NWAY MISSING;
    CLASS YEAR BASEID;
    BY HPLAN;
    VAR COST_SHARE_COST COST_SHARE_COST_MC COST_SHARE_COST_AMO 
      OTHER_COST AMTTOT;
    ID CATEGORY;
    OUTPUT OUT = TOTDENTAL(RENAME = _FREQ_=RCCNT) SUM = ;
  RUN;

  DATA TOTDENTAL;
    RETAIN COST 0;
    SET TOTDENTAL;
  RUN;

  PROC APPEND DATA=TOTDENTAL(KEEP=HPLAN YEAR BASEID COST_SHARE_COST 
    COST_SHARE_COST_MC COST_SHARE_COST_AMO
    OTHER_COST COST CATEGORY AMTTOT)  BASE= COSTDATA FORCE;
  RUN;

  PROC DATASETS LIBRARY=WORK NODETAILS NOLIST;
    DELETE DENTAL TOTDENTAL DENTAL_BASEID DENTAL_FILE CAT_JOIN;
    QUIT;
  RUN;

%MEND;



