****************************************************************************************************
*                                           PROGRAM OVERVIEW
****************************************************************************************************
*
* PROGRAM: ms_shaveinside.sas  
*
* Created (mm/dd/yyyy): 07/31/2014
* Last modified: 07/31/2014
* Version: 1.0
*
*--------------------------------------------------------------------------------------------------
* PURPOSE:
* 	This program will identify overlapping claims and trim exposure that is inside the  
*  	reference period
*
*  Program inputs:                                                                                   
* 	-Dataset containing the period that claims must overlap         
*	-Dataset containing the claims that must overlap the reference period 
*
*  Program outputs:                                                                                                                                       
*  	-Dataset containing the shaved claims
* 
* PARAMETERS:
*  	-reffile		= Dataset containing the periods that claims must overlap
*   -refstart		= variable name containing the date claims cannot go before
*   -refend			= Variable name containing the date claims cannot go beyond
*   -ToShaveFile	= Dataset containing the claims that must overlap the reference period
*   -ToShaveStart	= Variable containing the begin date of the claims to be shaven
*   -ToShaveEnd		= Variable containing the end date of the claims to be shaven
*   -outfile		= Output dataset containing the shaved claims
*
*  Programming Notes:                                                                                
*                                                                           
*
*
*--------------------------------------------------------------------------------------------------
* CONTACT INFO: 
*  Mini-Sentinel Coordinating Center
*  info@mini-sentinel.org
*
*--------------------------------------------------------------------------------------------------
*  CHANGE LOG: 
*
*   Version   Date       Initials	   Comment (reference external documentation when available)
*   -------   --------   --------   ---------------------------------------------------------------
*             mm/dd/yy
*
***************************************************************************************************;


%macro ms_shaveinside( reffile=,
                       refstart=,
                       refend=,
                       id=,                       
                       ToShaveFile=,
                       ToShaveStart=,
                       ToShaveEnd=,
                       outfile=);

    %put =====> MACRO CALLED: ms_shaveinside v1.0;

    %let id2=;
    %if %str("&id.") ne %str("") %then %let id2=,&id.;

   	* Cartesian product;
	proc sql noprint;
	create table  _Shave as 
		select ref.PatId,				   
			   case when in.&ToShaveEnd. < ref.&refstart. or in.&ToShaveStart. > ref.&refend. then . else in.&ToShaveStart. end as &ToShaveStart. format date9.,
			   case when in.&ToShaveEnd. < ref.&refstart. or in.&ToShaveStart. > ref.&refend. then . else in.&ToShaveEnd. end as &ToShaveEnd. format date9.,				   
			   case when in.&ToShaveEnd. < ref.&refstart. or in.&ToShaveStart. > ref.&refend. then 0 else 1 end as ToShave,
			   ref.&refstart.,
			   ref.&refend.
               &id2.
		from &reffile. as ref
		left join &ToShaveFile. as in                 
	    on in.PatId=ref.PatId
		order by PatId, ref.&refstart., in.&ToShaveStart.; 
	quit;		
    
	* Identify segments where the shave applies;
	proc sort nodupkey data = _shave(where=(ToShave=1)) 
					   out=_ForShave(keep=PatId &refstart. ToShave); 
	by PatId &refstart.; 
	run;
	
	data _shave;
	merge _Shave(drop=ToShave)
		  _ForShave;
	by PatId &refstart.;
	* Segments without a period to remove must be deleted;
	if ToShave=1 and &ToShaveStart.=. then delete;
	run;

	* Put segments that do not need shaving aside;
	proc sort nodupkey data=_shave (where=(ToShave=.))
					   out=&outfile.(drop=Toshave &ToShaveStart. &ToShaveEnd.);
	by _ALL_;
	run;

	* Calculate new segments;
	proc sort data = _shave(where=(ToShave=1)); 
	by PatId &refstart. &ToShaveStart.; 
	run;	

	data _shave(rename=New&refstart.=&refstart. rename=New&refend.=&refend. where=(durat>0));
	set _shave;
	by PatId &refstart. &ToShaveStart.;
	format New&refstart. New&refend. L&ToShaveEnd. date9.;

	if first.&refstart. then do;
		if &refstart. < &ToShaveStart. then New&refstart.=&refstart.;
		else New&refstart.=&ToShaveEnd.+1;	
	end;
	else New&refstart.=L&ToShaveEnd.+1;

	if New&refstart. < &ToShaveEnd. then do;
		New&refend.=&ToShaveStart.-1;
		durat=New&refend.-New&refstart.+1;
		output;
	end;

	L&ToShaveEnd. = &ToShaveEnd.;
	retain L&ToShaveEnd.;

	if last.&refstart. /*and  New&refend. ne &refend.*/ then do;
		New&refstart.=&ToShaveEnd.+1;
		New&refend.=&refend.;
		durat=New&refend.-New&refstart.+1;
		output;
	end;

	drop &refstart. &refend. L&ToShaveEnd. Toshave &ToShaveStart. &ToShaveEnd.; 
	run;

	proc append base=&outfile.
                data=_shave (drop=durat) force;

   	%if %str("&reffile.") ne %str("") %then %do;  
		proc datasets library=work nolist nowarn;
        *delete  _Shave _ForShave _NoShave;
        quit;
    %end;

    %put NOTE: ********END OF MACRO: ms_shaveinside v1.0********;

%mend ms_shaveinside;