DBA Data[Home] [Help]

PACKAGE BODY: APPS.PAY_NL_SI_PKG

Source


1 PACKAGE BODY pay_nl_si_pkg AS
2 	/* $Header: pynlsoci.pkb 120.24.12010000.3 2008/08/06 08:01:59 ubhat ship $ */
3 	g_package                  varchar2(33) := '  pay_nl_si_pkg.';
4 	g_legislation_code         varchar2(2)  :='NL';
5 	g_udt_name VARCHAR2(50) := 'PQP_COMPANY_WORK_PATTERNS';
6     	g_ptp_formula_exists  BOOLEAN := TRUE;
7     	g_ptp_formula_cached  BOOLEAN := FALSE;
8     	g_ptp_formula_id      ff_formulas_f.formula_id%TYPE;
9    	    g_ptp_formula_name    ff_formulas_f.formula_name%TYPE;
10   /* Global Variables for Standard SI Part Time Percentage */
11      g_std_ptp_formula_exists  BOOLEAN := TRUE;
12      g_std_ptp_formula_cached  BOOLEAN := FALSE;
13      g_std_ptp_formula_id      ff_formulas_f.formula_id%TYPE;
14    	 g_std_ptp_formula_name    ff_formulas_f.formula_name%TYPE;
15   /* Global Variables for Pseudo SI Part Time Percentage */
16      g_pse_ptp_formula_exists  BOOLEAN := TRUE;
17      g_pse_ptp_formula_cached  BOOLEAN := FALSE;
18      g_pse_ptp_formula_id      ff_formulas_f.formula_id%TYPE;
19    	 g_pse_ptp_formula_name    ff_formulas_f.formula_name%TYPE;
20   /* Global Variables for Standard SI Reporting Part Time Percentage */
21      g_std_rep_ptp_formula_exists  BOOLEAN := TRUE;
22      g_std_rep_ptp_formula_cached  BOOLEAN := FALSE;
23      g_std_rep_ptp_formula_id      ff_formulas_f.formula_id%TYPE;
24    	 g_std_rep_ptp_formula_name    ff_formulas_f.formula_name%TYPE;
25   /* Global variables for Override Real SI Days */
26      g_real_si_days_formula_exists  BOOLEAN := TRUE;
27      g_real_si_days_formula_cached  BOOLEAN := FALSE;
28      g_real_si_days_formula_id      ff_formulas_f.formula_id%TYPE;
29      	g_real_si_days_formula_name    ff_formulas_f.formula_name%TYPE;
30   /* Global Variables for Pseudo SI Reporting Part Time Percentage */
31      g_pse_rep_ptp_formula_exists  BOOLEAN := TRUE;
32      g_pse_rep_ptp_formula_cached  BOOLEAN := FALSE;
33      g_pse_rep_ptp_formula_id      ff_formulas_f.formula_id%TYPE;
34    	 g_pse_rep_ptp_formula_name    ff_formulas_f.formula_name%TYPE;
35  /* Global Variables for Override SI Days */
36      g_si_days_formula_exists  BOOLEAN := TRUE;
37      g_si_days_formula_cached  BOOLEAN := FALSE;
38      g_si_days_formula_id      ff_formulas_f.formula_id%TYPE;
39      g_si_days_formula_name    ff_formulas_f.formula_name%TYPE;
40      g_si_days		       NUMBER;
41  /* Global Variables for Tax Proration Days */
42      g_assignment_id	       per_all_assignments_f.assignment_id%TYPE;
43      g_tax_proration_days      NUMBER;
44      g_tax_proration_flag      VARCHAR2(1);
45 
46 	cursor c_wp_dets(p_assignment_id NUMBER ) is
47 	select *
48 	from pqp_assignment_attributes_f paa,
49 	fnd_sessions ses
50 	where assignment_id = p_assignment_id
51     and ses.session_id = userenv('sessionid')
52     and ses.effective_date between paa.effective_start_date and paa.effective_end_date;
53 	--
54 	-- Returns the SI Status
55 	-- are entered for a employee
56 	Function get_si_status
57 	  ( p_assignment_id  in number,
58 	    p_date_earned    in date,
59 	    p_si_class       in    varchar2
60 	  ) return number IS
61 	  CURSOR Cur_SI_Status IS
62 	  SELECT paei.AEI_INFORMATION4 SI_Status,
63 	  paei.AEI_INFORMATION3 SI_Class,
64 	  DECODE(paei.AEI_INFORMATION3,'AMI',0,1) si_class_order
65 	  FROM
66 	  per_assignment_extra_info  paei
67 	  WHERE
68 	  assignment_id = p_assignment_id
69 	  and paei.aei_information_category='NL_SII'
70 	  and (paei.AEI_INFORMATION3 = p_si_class  or
71 	       paei.AEI_INFORMATION3 = DECODE(p_si_class,'ZFW','AMI','ZW','AMI','WW','AMI','WAO','AMI',
72                                               'ZVW','AMI','WGA','AMI','IVA','AMI','UFO','AMI',p_si_class))
73 	  and p_date_earned between
74 	  FND_DATE.CANONICAL_TO_DATE(paei.AEI_INFORMATION1)
75 	  and nvl(FND_DATE.CANONICAL_TO_DATE(paei.AEI_INFORMATION2),hr_general.END_OF_TIME)
76 	  order by si_class_order desc;
77 
78       CURSOR Cur_ZVW_Excluded(p_dt_earned NUMBER)
79       IS
80 	  SELECT nvl(paei.AEI_INFORMATION2,'N')    ZVW_Excluded
81 	  FROM
82 	  per_assignment_extra_info  paei
83 	  WHERE assignment_id = p_assignment_id
84 	  and   paei.aei_information_category='NL_EXCL_ZVW'
85       and   (to_char(fnd_date.canonical_to_date(paei.AEI_INFORMATION1),'RRRR') <= p_dt_earned
86              AND nvl(to_char(fnd_date.canonical_to_date(paei.AEI_INFORMATION3),'RRRR'),'4712') >= p_dt_earned);
87 
88 
89 	  vCur_SI_Status Cur_SI_Status%ROWTYPE;
90       vCur_ZVW_Excluded  Cur_ZVW_Excluded%ROWTYPE;
91       l_zvw_status           NUMBER;
92       l_zvw_excluded         VARCHAR2(1);
93       /*l_exclusion_date       VARCHAR2(4);*/
94       l_date_earned          VARCHAR2(8);
95 	  l_proc varchar2(100) := g_package||'get_si_status';
96 	BEGIN
97 	  hr_utility.set_location('Entering ' || l_proc, 100);
98 	  hr_utility.set_location('p_assignment_id ' || p_assignment_id, 110);
99 	  hr_utility.set_location('p_si_class ' || p_si_class, 110);
100 	  hr_utility.set_location('p_date_earned ' || p_date_earned, 110);
101       l_zvw_status := 1;
102 	  OPEN Cur_SI_Status;
103 	  FETCH Cur_SI_Status INTO vCur_SI_Status;
104 	  IF Cur_SI_Status%NOTFOUND THEN
105             l_zvw_status := 0;
106       END IF;
107       CLOSE Cur_SI_Status;
108 	  -- If the
109 
110       IF p_si_class = 'ZVW' THEN
111         l_date_earned := TO_CHAR(p_date_earned,'RRRR');
112         OPEN Cur_ZVW_Excluded(l_date_earned);
113         FETCH Cur_ZVW_Excluded INTO vCur_ZVW_Excluded;
114         IF(Cur_ZVW_Excluded%NOTFOUND) THEN
115           l_zvw_excluded := 'N';
116          /* l_exclusion_date := l_date_earned;*/
117         ELSE
118           l_zvw_excluded := vCur_ZVW_Excluded.ZVW_Excluded;
119          /* l_exclusion_date := vCur_ZVW_Excluded.Excluded_Year;*/
120         END IF;
121         CLOSE Cur_ZVW_Excluded;
122 
123         IF l_zvw_excluded = 'N' THEN
124           IF l_zvw_status = 0 THEN
125             RETURN -3;
126           END IF;
127         ELSE
128           RETURN -5;
129         END IF;
130       END IF;
131 
132       IF (vCur_SI_Status.SI_Class='AMI' and p_si_class <>'ZFW') and
133 	     vCur_SI_Status.SI_Status='4' THEN
134 	  	 vCur_SI_Status.SI_Status:=1;
135 	  END IF;
136 	  IF vCur_SI_Status.SI_Status='4' and p_date_earned > to_date('31/12/2005', 'dd/mm/yyyy') THEN
137 	    	 vCur_SI_Status.SI_Status:=-4;
138 	  END IF;
139 	  IF vCur_SI_Status.SI_Status>0 and p_date_earned > to_date('31/12/2005', 'dd/mm/yyyy') and p_si_class ='ZFW' THEN
140 	     IF vCur_SI_Status.SI_Class='AMI' THEN
141 	    	 vCur_SI_Status.SI_Status:=0;
142     	     ELSE
143     	 	 vCur_SI_Status.SI_Status:=-1;
144     	     END IF;
145 	  END IF;
146  	  IF nvl(vCur_SI_Status.SI_Status, 0)<=0 and p_date_earned > to_date('31/12/2005', 'dd/mm/yyyy') and p_si_class ='ZVW' THEN
147 	    	 vCur_SI_Status.SI_Status:=-2;
148 	  END IF;
149 
150      /* IF vCur_SI_Status.SI_Class = 'AMI' and vCur_SI_Status.SI_Status > 0 THEN
151          IF  hr_nl_org_info.Get_SI_Provider_Excl_Info(p_assignment_id,p_si_class,p_date_earned) = 0 THEN
152             vCur_SI_Status.SI_Status := 0;
153           END IF;
154       END IF;*/
155 
156       hr_utility.set_location('Leaving' || l_proc, 500);
157 	  RETURN vCur_SI_Status.SI_Status;
158 	EXCEPTION
159 	   WHEN OTHERS THEN
160 	    hr_utility.set_location(' Others :' || SQLERRM(SQLCODE),900);
161 	END get_si_status;
162 	--
163 	-- Function to check if All Mandatory Insurances is chosen at the assignment level
164 	--
165 	  Function is_ami
166 	  ( p_assignment_id  in number,
167 	    p_date_earned    in date
168 	  ) return number IS
169 	  CURSOR Cur_SI_AMI IS
170 	  SELECT
171 	  DECODE(paei.AEI_INFORMATION3,'AMI',1,0) si_class_order
172 	  FROM
173 	  per_assignment_extra_info  paei
174 	  WHERE
175 	  assignment_id = p_assignment_id
176 	  and paei.aei_information_category='NL_SII'
177 	  and p_date_earned between
178 	  FND_DATE.CANONICAL_TO_DATE(paei.AEI_INFORMATION1)
179 	  and nvl(FND_DATE.CANONICAL_TO_DATE(paei.AEI_INFORMATION2),hr_general.END_OF_TIME)
180 	  order by si_class_order desc;
181 	  vCur_SI_AMI Cur_SI_AMI%ROWTYPE;
182 	  l_proc varchar2(100) := g_package||'get_si_status';
183 	BEGIN
184 	  hr_utility.set_location('Entering ' || l_proc, 100);
185 	  hr_utility.set_location('p_assignment_id ' || p_assignment_id, 110);
186 	  hr_utility.set_location('p_date_earned ' || p_date_earned, 110);
187 	  OPEN Cur_SI_AMI;
188 	  FETCH Cur_SI_AMI INTO vCur_SI_AMI;
189 	  CLOSE Cur_SI_AMI;
190 	  RETURN vCur_SI_AMI.si_class_order;
191 	EXCEPTION
192 	   WHEN OTHERS THEN
193 	    hr_utility.set_location(' Others :' || SQLERRM(SQLCODE),900);
194 	END is_ami;
195 	--
196 	-- Function to get payroll type
197 	--
198 	Function get_payroll_type
199 		(p_payroll_id      in   number
200 		) return varchar2 is
201 		--
202 		cursor cur_get_payroll is
203 		select period_type
204 		from   pay_all_payrolls_f pap
205 		where  payroll_id = p_payroll_id;
206 		v_period_type  varchar2(30);
207 	--
208 	begin
209 		open cur_get_payroll;
210 		fetch cur_get_payroll into v_period_type;
211 		close cur_get_payroll;
212 		return (v_period_type);
213 	end get_payroll_type;
214 	--
215 	-- Determines the Number if Week Days(Monday to Friday )
216 	-- between two dates
217 	FUNCTION Get_Week_Days(P_Start_Date Date,
218 							P_End_Date Date) return NUMBER IS
219     v_st_date date :=P_Start_Date;
220     v_en_date date :=P_End_Date;
221     v_beg_of_week date;
222     v_end_of_week date;
223     v_days number := 0;
224    begin
225 		if P_Start_Date > P_end_Date then
226 		return v_days;
227 		end if;
228 		--Determine the Beginning of Week Date for Start Date
229 		--and End of Week Date for End Date
230 		v_beg_of_week := v_st_date - (get_day_of_week(v_st_date)-1);
231 		v_end_of_week  := v_en_date;
232 		if get_day_of_week(v_en_date) NOT IN('1') then
233 			v_end_of_week := v_en_date + (7- get_day_of_week(v_en_date)+1);
234 		end if;
235 		--Calculate the Total Week Days @ of 5 per week
236 		v_days := ((v_end_of_week-v_beg_of_week)/7)*5;
237 		--Adjust the Total Week Days by subtracting
238 		--No of Days before the Start Date
239 		if (v_st_date > (v_beg_of_week+1)) then
240 			v_days := v_days - (v_st_date - (v_beg_of_week+1)) ;
241 		end if;
242 		if v_end_of_week <> v_en_date then
243 			v_end_of_week := v_end_of_week -2;
244 		else
245 			if v_st_date = v_en_date then
246 				v_days := 0;
247 			end if;
248 		end if;
249 		--Adjust the Total Week Days by subtracting
250 		--No of Days After the End Date
251 		if (v_end_of_week - v_en_date) >= 0 then
252 			v_days := v_days - (v_end_of_week - v_en_date) ;
253 		end if;
254 		return (v_days);
255    end Get_Week_Days;
256 	--
257 	-- Determines the Maximum SI Days between two dates
258 	--  based on the method of 5 days per week
259 	FUNCTION Get_Max_SI_Days(P_Assignment_Id Number,
260 							P_Start_Date Date,
261 							P_End_Date Date) return NUMBER IS
262 		l_assgn_attr c_wp_dets%rowtype;
263 		l_curr_date           DATE;
264 		l_temp1               DATE;
265 		l_temp2               DATE;
266 		l_max_si_days         NUMBER:=0;
267 		l_error_code          NUMBER;
268 		l_counter             NUMBER:=0;
269 		l_error_msg           fnd_new_messages.message_text%TYPE;
270 		l_is_wrking_day       VARCHAR2(1);
271 	BEGIN
272 		OPEN c_wp_dets(P_Assignment_Id);
273 		FETCH c_wp_dets INTO l_assgn_attr;
274 		CLOSE c_wp_dets;
275 		l_temp1 :=p_start_date + (7 - get_day_of_week(p_start_date))+1;
276 		l_temp2 :=p_end_date - to_number(get_day_of_week(p_end_date))+1;
277 		IF  p_end_date <  l_temp1  THEN
278 		l_temp1 := p_end_date;
279 		end if;
280 		l_curr_date:=p_start_date;
281 		l_counter:=0;
282 		while l_curr_date <= l_temp1
283 		loop
284 			l_is_wrking_day:=PQP_SCHEDULE_CALCULATION_PKG.is_working_day
285 			(p_assignment_id      =>  l_assgn_attr.assignment_id
286 			,p_business_group_id  =>  l_assgn_attr. business_group_id
287 			,p_date               =>  l_curr_date
288 			,p_error_code         =>  l_error_code
289 			,p_error_message      =>  l_error_msg
290 			,p_default_wp         =>  null
291 			);
292 			if (l_is_wrking_day ='Y' and l_counter < 5) then
293 				l_counter:=l_counter+1;
294 			end if;
295 			l_curr_date:=l_curr_date+1;
296 		end loop;
297 		--3082046
298 		l_max_si_days:=l_max_si_days + l_counter;
299 		l_counter := 0;
300 		IF  p_end_date - l_temp1 + 1 >= 7 THEN
301 			l_curr_date := l_temp1 +1;
302 			while l_curr_date <= l_temp2
303 			loop
304 				l_is_wrking_day:= PQP_SCHEDULE_CALCULATION_PKG.is_working_day
305 				(p_assignment_id      =>  l_assgn_attr.assignment_id
306 				,p_business_group_id  =>  l_assgn_attr. business_group_id
307 				,p_date               =>  l_curr_date
308 				,p_error_code         =>  l_error_code
309 				,p_error_message      =>  l_error_msg
310 				,p_default_wp         =>  null
311 				);
312 				if l_is_wrking_day ='Y' then
313 					l_max_si_days := l_max_si_days +5;
314 					if get_day_of_week(l_curr_date) <> '1' then
315 						l_curr_date:=l_curr_date + (7 - get_day_of_week(l_curr_date) +2);
316 					else
317 						l_curr_date:=l_curr_date+1;
318 					end if;
319 				else
320 					l_curr_date := l_curr_date+1;
321 				end if;
322 			end loop;
323 		END IF;
324 		l_curr_date:=l_temp2 + 1;
325 		while l_curr_date <= P_End_Date
326 		loop
327 			l_is_wrking_day:= PQP_SCHEDULE_CALCULATION_PKG.is_working_day
328 			(p_assignment_id      =>  l_assgn_attr.assignment_id
329 			,p_business_group_id  =>  l_assgn_attr. business_group_id
330 			,p_date               =>  l_curr_date
331 			,p_error_code         =>  l_error_code
332 			,p_error_message      =>  l_error_msg
333 			,p_default_wp         =>  null
334 			);
335 			if (l_is_wrking_day ='Y' and l_counter < 5) then
336 				l_counter:=l_counter+1;
337 			end if;
338 			l_curr_date:=l_curr_date+1;
339 		end loop;
340 		l_max_si_days:=l_max_si_days + l_counter;
341 		return l_max_si_days;
342    END Get_Max_SI_Days;
343 	--
344 	-- Determines the Number of Unpaid absence Days that reduce
345 	-- SI Days indicated by the segment on the Absence
346 	FUNCTION Get_Non_SI_Days(P_Assignment_Id Number,
347 							P_Start_Date Date,
348 							P_End_Date Date) return NUMBER IS
349 		CURSOR Get_Non_SI_Absence(p_person_id number) is
350 		select date_start,date_end,time_start,time_end
351 		from per_absence_attendances_v
352 		where person_id=p_person_id
353 		and ((ABS_INFORMATION_CATEGORY='NL' and ABS_INFORMATION1='Y')
354 		OR  (ABS_INFORMATION_CATEGORY='NL_S' and ABS_INFORMATION2='Y'))
355 		and (((p_start_date between date_start and date_end)
356 		or (p_end_date between date_start and date_end))
357 		or ((date_start between p_start_date and p_end_date)
358 		or (date_end between p_start_date and p_end_date)));
359 		l_hrs_wrked NUMBER;
360 		l_assgn_attr c_wp_dets%rowtype;
361 		l_error_code NUMBER;
362 		l_non_si_days NUMBER:=0;
363 		l_error_msg  fnd_new_messages.message_text%TYPE;
364 		l_person_id number;
365 		l_start_date per_absence_attendances_v.date_start%type;
366 		l_end_date per_absence_attendances_v.date_end%type;
367 		l_time_start per_absence_attendances_v.time_start%type;
368 		l_time_end per_absence_attendances_v.time_end%type;
369 		l_temp1 date;
370 		l_temp2 date;
371 		l_curr_date date;
372 		l_absence_hours per_absence_attendances_v.absence_hours%type;
373 		l_wrking_day varchar2(1):='N';
374 	BEGIN
375 		OPEN c_wp_dets(P_Assignment_Id);
376 		FETCH c_wp_dets INTO l_assgn_attr;
377 		CLOSE c_wp_dets;
378 		select person_id into l_person_id
379 		from per_all_assignments_f paa,
380 		fnd_sessions ses
381 		where paa.assignment_id =p_assignment_id
382 		and ses.session_id = userenv('sessionid')
383 		and ses.effective_date between paa.effective_start_date and paa.effective_end_date;
384 		for  l_absence_record in Get_Non_SI_Absence(l_person_id)
385 		loop
386 			--hr_utility.set_location(' date_start'||l_absence_record.date_start,100);
387 			--hr_utility.set_location(' date_end'||l_absence_record.date_end,100);
388 			/*Check whether the start date and end date of the abscence period are equal*/
389 			if l_absence_record.date_start = l_absence_record.date_end then
390 				l_hrs_wrked:=pqp_schedule_calculation_pkg.get_hours_worked
391 				(p_assignment_id   =>  l_assgn_attr.assignment_id
392 				,p_business_group_id   =>  l_assgn_attr.business_group_id
393 				,p_date_start          =>  l_absence_record.date_start
394 				,p_date_end            =>  l_absence_record.date_end
395 				,p_error_code          =>  l_error_code
396 				,p_error_message       =>  l_error_msg
397 				,p_default_wp          =>  NULL
398 				);
399 				--hr_utility.set_location('l_absence_record.time_end'||l_absence_record.time_end,110);
400 				--hr_utility.set_location('l_absence_record.time_start'||l_absence_record.time_start,110);
401          			--Bug 3085937
402          			--shveerab
403          			/*Added code to check time_end and time_start is null for the abscence defined*/
404 				if  (l_absence_record.time_end is null and
405 				     l_absence_record.time_start is null ) then
406                                 /*If the time_end and time_start are null then l_absene_hours should be assigned
407                                 to the actual working hours of l_absence_record.date_start*/
408 					l_absence_hours := l_hrs_wrked;
409 				else
410 				/*Else the actual time difference between time_end and time_stard of the absence
411 				should be assigned*/
412 					l_absence_hours := (to_date('0001/01/01 '||l_absence_record.time_end,'yyyy/mm/dd hh24:mi') - to_date('0001/01/01 '||l_absence_record.time_start,'yyyy/mm/dd hh24:mi'))*24;
413 				end if;
414 				--hr_utility.set_location('l_absence_hours'||l_absence_hours,120);
415 				l_wrking_day:= pqp_schedule_calculation_pkg.is_working_day
416 				(p_assignment_id     => l_assgn_attr.assignment_id
417 				,p_business_group_id => l_assgn_attr.business_group_id
418 				,p_date              => l_absence_record.date_start
419 				,p_error_code        => l_error_code
420 				,p_error_message     => l_error_msg
421 				,p_default_wp        => NULL
422 				,p_override_wp       => NULL
423 				);
424 			        /*If the absence hours is greater than the actual working hours and its a
425 			        working day then non si absence days should be incremented by one*/
426 				if l_absence_hours >= l_hrs_wrked and l_wrking_day='Y' then
427 					l_non_si_days := l_non_si_days + 1;
428 				end if;
429 				--hr_utility.set_location('l_non_si_days'||l_non_si_days,150);
430 			else
431 				if l_absence_record.date_start > p_start_date then
432 					l_temp1:= l_absence_record.date_start;
433 				else
434 					l_temp1:=p_start_date;
435 				end if;
436 				if l_absence_record.date_end > p_end_date then
437 					l_temp2:=p_end_date;
438 				else
439 					l_temp2:=l_absence_record.date_end;
440 				end if;
441 				l_curr_date:=l_temp1;
442 				--Bug 3085937
443 				--shveerab
444             			/* The Absence should be considered including the end date of the absence period*/
445 				while l_curr_date <= l_temp2
446 				loop
447 					l_wrking_day:= pqp_schedule_calculation_pkg.is_working_day
448 					(p_assignment_id     => l_assgn_attr.assignment_id
449 					,p_business_group_id => l_assgn_attr.business_group_id
450 					,p_date              => l_curr_date
451 					,p_error_code        => l_error_code
452 					,p_error_message     => l_error_msg
453 					,p_default_wp        => NULL
454 					,p_override_wp       => NULL
455 					);
456 					if l_wrking_day='Y' then
457 						l_non_si_days:=l_non_si_days + 1;
458 					end if;
459 					l_curr_date:=l_curr_date+1;
460 				end loop;
461 			end if;
462 		end loop; /*End of for  l_absence_record Loop*/
463      return l_non_si_days;
464    END  Get_Non_SI_Days;
465 	--
466 	-- Determines the Total Number of days a Work pattern has been
467 	-- setup for regardless of the work pattern start date on
468 	-- employee assignment or dates of payroll period.
469 	FUNCTION Get_Total_Work_Pattern_days(P_Assignment_Id Number) return NUMBER IS
470 		cursor c_get_days(p_wrk_pattern pqp_assignment_attributes_f.work_pattern%type,
471 				  p_business_group_id pqp_assignment_attributes_f.business_group_id%type ) is
472 		select count(uci.value)
473 		from pay_user_tables put,
474 		pay_user_columns puc,
475 		pay_user_column_instances_f uci,
476 		fnd_sessions ses
477 		where put.user_table_id = puc.user_table_id
478 		and puc.business_group_id = p_business_group_id      -- Fix for bug 3977437
479 		and uci.user_column_id = puc.user_column_id
480 		and put.user_table_name = g_udt_name
481 		and puc.user_column_name = p_wrk_pattern
482 		and ses.session_id = userenv('sessionid')
483 		and ses.effective_date between uci.effective_start_date and uci.effective_end_date;
484 		l_assgn_attr c_wp_dets%rowtype;
485 		l_wrk_pattern_days NUMBER;
486    BEGIN
487 		OPEN c_wp_dets(P_Assignment_Id);
488 		FETCH c_wp_dets INTO l_assgn_attr;
489 		CLOSE c_wp_dets;
490 		OPEN c_get_days(l_assgn_attr.work_pattern , l_assgn_attr.business_group_id);
491 		FETCH c_get_days INTO l_wrk_pattern_days;
492 		CLOSE c_get_days;
493 		RETURN l_wrk_pattern_days;
494 	END Get_Total_Work_Pattern_days;
495 	--
496 	-- Determines the Total Number of days marked as Working Days in a
497 	-- work pattern regardless of the work pattern start date on
498 	-- employee assignment or dates of payroll period.
499 	FUNCTION Get_Working_Work_Pattern_days(P_Assignment_Id Number) return NUMBER IS
500 		cursor c_get_wrk_days	(p_wrk_pattern pqp_assignment_attributes_f.work_pattern%type ,
501 					p_business_group_id pqp_assignment_attributes_f.business_group_id%type) is
502 		select count(uci.value)
503 		from pay_user_tables put,
504 		pay_user_columns puc,
505 		pay_user_column_instances_f uci,
506 		fnd_sessions ses
507 		where put.user_table_id = puc.user_table_id
508 		and puc.business_group_id = p_business_group_id    -- Fix for bug 3977437
509 		and uci.user_column_id = puc.user_column_id
510 		and put.user_table_name = g_udt_name
511 		and puc.user_column_name = p_wrk_pattern
512 		and uci.value <> '0'
513 		and ses.session_id = userenv('sessionid')
514 		and ses.effective_date between uci.effective_start_date and uci.effective_end_date;
515 		l_assgn_attr c_wp_dets%rowtype;
516 		l_working_days number;
517    BEGIN
518 		OPEN c_wp_dets(P_Assignment_Id);
519 		FETCH c_wp_dets INTO l_assgn_attr;
520 		CLOSE c_wp_dets;
521 		OPEN c_get_wrk_days(l_assgn_attr.work_pattern , l_assgn_attr.business_group_id);
522 		FETCH c_get_wrk_days INTO l_working_days;
523 		CLOSE c_get_wrk_days;
524 		RETURN l_working_days;
525 	END Get_Working_Work_Pattern_days;
526        FUNCTION get_part_time_perc (p_assignment_id IN NUMBER
527                                    ,p_date_earned IN DATE
528                                    ,p_business_group_id IN NUMBER
529                                    ,p_assignment_action_id IN NUMBER) RETURN number IS
530        --
531        CURSOR csr_get_pay_action_id(c_assignment_action_id NUMBER) IS
532 	   SELECT payroll_action_id
533 	   FROM   pay_assignment_actions
534 	   WHERE  assignment_action_id = c_assignment_action_id;
535 	   --
536        l_payroll_action_id number;
537        l_part_time_perc varchar2(35);
538        l_inputs  ff_exec.inputs_t;
539        l_outputs ff_exec.outputs_t;
540        l_formula_exists  BOOLEAN := TRUE;
541        l_formula_cached  BOOLEAN := FALSE;
542        l_formula_id      ff_formulas_f.formula_id%TYPE;
543        BEGIN
544        g_ptp_formula_name := 'NL_PART_TIME_PERCENTAGE';
545        --
546        OPEN  csr_get_pay_action_id(p_assignment_action_id);
547        FETCH csr_get_pay_action_id INTO l_payroll_action_id;
548 	   CLOSE csr_get_pay_action_id;
549 	   --
550            IF g_ptp_formula_exists = TRUE THEN
551                IF g_ptp_formula_cached = FALSE THEN
552                    pay_nl_general.cache_formula('NL_PART_TIME_PERCENTAGE',p_business_group_id,p_date_earned,l_formula_id,l_formula_exists,l_formula_cached);
553                    g_ptp_formula_exists:=l_formula_exists;
554                    g_ptp_formula_cached:=l_formula_cached;
555                    g_ptp_formula_id:=l_formula_id;
556                END IF;
557    		--
558                IF g_ptp_formula_exists = TRUE THEN
559              --  hr_utility.trace('FORMULA EXISTS');
560    		  --
561                    l_inputs(1).name  := 'ASSIGNMENT_ID';
562                    l_inputs(1).value := p_assignment_id;
563                    l_inputs(2).name  := 'DATE_EARNED';
564                    l_inputs(2).value := fnd_date.date_to_canonical(p_date_earned);
565                    l_inputs(3).name  := 'BUSINESS_GROUP_ID';
566                    l_inputs(3).value := p_business_group_id;
567                    l_inputs(4).name := 'ASSIGNMENT_ACTION_ID';
568                    l_inputs(4).value := p_assignment_action_id;
569                    l_inputs(5).name := 'PAYROLL_ACTION_ID';
570                    l_inputs(5).value := l_payroll_action_id;
571                    l_inputs(6).name := 'BALANCE_DATE';
572                    l_inputs(6).value := fnd_date.date_to_canonical(p_date_earned);
573    		  --
574                    l_outputs(1).name := 'PART_TIME_PERCENTAGE';
575    		  --
576                    pay_nl_general.run_formula(p_formula_id       => g_ptp_formula_id,
577                                               p_effective_date   => p_date_earned,
578                                               p_formula_name     => g_ptp_formula_name,
579                                               p_inputs           => l_inputs,
580                                               p_outputs          => l_outputs);
581    		  --
582                    l_part_time_perc := l_outputs(1).value;
583          --    hr_utility.trace('l_part_time_perc'||l_part_time_perc);
584                ELSE
585            --  hr_utility.trace('FORMULA DOESNT EXISTS');
586                    l_part_time_perc := NULL;
587            --  hr_utility.trace('l_part_time_perc'||l_part_time_perc);
588                END IF;
589            ELSIF g_ptp_formula_exists = FALSE THEN
590                l_part_time_perc := NULL;
591            END IF;
592            RETURN fnd_number.canonical_to_number(l_part_time_perc);
593        END get_part_time_perc;
594 -------------------------------------------------------------------------------
595 -- Function : get_standard_si_part_time_perc
596 -- To get the Standard SI Part time Percentage using
597 -- Assignment Id,Date Earned, Business Group Id and Assignment action Id.
598 ---------------------------------------------------------------------------------
599        FUNCTION get_standard_si_part_time_perc (p_assignment_id IN NUMBER
600                                    ,p_date_earned IN DATE
601                                    ,p_business_group_id IN NUMBER
602                                    ,p_assignment_action_id IN NUMBER) RETURN number IS
603        --
604        CURSOR csr_get_pay_action_id(c_assignment_action_id NUMBER) IS
605 	   SELECT payroll_action_id
606 	   FROM   pay_assignment_actions
607 	   WHERE  assignment_action_id = c_assignment_action_id;
608 	   --
609        l_payroll_action_id number;
610        l_part_time_perc varchar2(35);
611        l_inputs  ff_exec.inputs_t;
612        l_outputs ff_exec.outputs_t;
613        l_formula_exists  BOOLEAN := TRUE;
614        l_formula_cached  BOOLEAN := FALSE;
615        l_formula_id      ff_formulas_f.formula_id%TYPE;
616        BEGIN
617        g_std_ptp_formula_name := 'NL_STANDARD_SI_PART_TIME_PERCENTAGE';
618        --
619        OPEN  csr_get_pay_action_id(p_assignment_action_id);
620        FETCH csr_get_pay_action_id INTO l_payroll_action_id;
621 	   CLOSE csr_get_pay_action_id;
622 	   --
623 
624            IF g_std_ptp_formula_exists = TRUE THEN
625                IF g_std_ptp_formula_cached = FALSE THEN
626                    pay_nl_general.cache_formula('NL_STANDARD_SI_PART_TIME_PERCENTAGE',p_business_group_id,p_date_earned,l_formula_id,l_formula_exists,l_formula_cached);
627                    g_std_ptp_formula_exists:=l_formula_exists;
628                    g_std_ptp_formula_cached:=l_formula_cached;
629                    g_std_ptp_formula_id:=l_formula_id;
630                END IF;
631    		--
632                IF g_std_ptp_formula_exists = TRUE THEN
633              --  hr_utility.trace('FORMULA EXISTS');
634    		  --
635                    l_inputs(1).name  := 'ASSIGNMENT_ID';
636                    l_inputs(1).value := p_assignment_id;
637                    l_inputs(2).name  := 'DATE_EARNED';
638                    l_inputs(2).value := fnd_date.date_to_canonical(p_date_earned);
639                    l_inputs(3).name  := 'BUSINESS_GROUP_ID';
640                    l_inputs(3).value := p_business_group_id;
641                    l_inputs(4).name := 'ASSIGNMENT_ACTION_ID';
642                    l_inputs(4).value := p_assignment_action_id;
643                    l_inputs(5).name := 'PAYROLL_ACTION_ID';
644                    l_inputs(5).value := l_payroll_action_id;
645                    l_inputs(6).name := 'BALANCE_DATE';
646                    l_inputs(6).value := fnd_date.date_to_canonical(p_date_earned);
647    		  --
648                    l_outputs(1).name := 'STANDARD_SI_PART_TIME_PERCENTAGE';
649    		  --
650                    pay_nl_general.run_formula(p_formula_id       => g_std_ptp_formula_id,
651                                               p_effective_date   => p_date_earned,
652                                               p_formula_name     => g_std_ptp_formula_name,
653                                               p_inputs           => l_inputs,
654                                               p_outputs          => l_outputs);
655    		  --
656                    l_part_time_perc := l_outputs(1).value;
657          --    hr_utility.trace('l_part_time_perc'||l_part_time_perc);
658                ELSE
659            --  hr_utility.trace('FORMULA DOESNT EXISTS');
660                    l_part_time_perc := NULL;
661            --  hr_utility.trace('l_part_time_perc'||l_part_time_perc);
662                END IF;
663            ELSIF g_std_ptp_formula_exists = FALSE THEN
664                l_part_time_perc := NULL;
665            END IF;
666            RETURN fnd_number.canonical_to_number(l_part_time_perc);
667        END get_standard_si_part_time_perc;
668 -------------------------------------------------------------------------------
669 -- Function : get_pseudo_si_part_time_perc
670 -- To get the Pseudo SI Part time Percentage  using
671 -- Assignment Id,Date Earned, Business Group Id and Assignment action Id.
672 ---------------------------------------------------------------------------------
673        FUNCTION get_pseudo_si_part_time_perc (p_assignment_id IN NUMBER
674                                    ,p_date_earned IN DATE
675                                    ,p_business_group_id IN NUMBER
676                                    ,p_assignment_action_id IN NUMBER) RETURN number IS
677        --
678        CURSOR csr_get_pay_action_id(c_assignment_action_id NUMBER) IS
679 	   SELECT payroll_action_id
680 	   FROM   pay_assignment_actions
681 	   WHERE  assignment_action_id = c_assignment_action_id;
682 	   --
683        l_payroll_action_id number;
684        l_part_time_perc varchar2(35);
685        l_inputs  ff_exec.inputs_t;
686        l_outputs ff_exec.outputs_t;
687        l_formula_exists  BOOLEAN := TRUE;
688        l_formula_cached  BOOLEAN := FALSE;
689        l_formula_id      ff_formulas_f.formula_id%TYPE;
690        BEGIN
691        g_pse_ptp_formula_name := 'NL_PSEUDO_SI_PART_TIME_PERCENTAGE';
692        --
693        OPEN  csr_get_pay_action_id(p_assignment_action_id);
694        FETCH csr_get_pay_action_id INTO l_payroll_action_id;
695 	   CLOSE csr_get_pay_action_id;
696 	   --
697 
698            IF g_pse_ptp_formula_exists = TRUE THEN
699                IF g_pse_ptp_formula_cached = FALSE THEN
700                    pay_nl_general.cache_formula('NL_PSEUDO_SI_PART_TIME_PERCENTAGE',p_business_group_id,p_date_earned,l_formula_id,l_formula_exists,l_formula_cached);
701                    g_pse_ptp_formula_exists:=l_formula_exists;
702                    g_pse_ptp_formula_cached:=l_formula_cached;
703                    g_pse_ptp_formula_id:=l_formula_id;
704                END IF;
705    		--
706                IF g_pse_ptp_formula_exists = TRUE THEN
707              --  hr_utility.trace('FORMULA EXISTS');
708    		  --
709                    l_inputs(1).name  := 'ASSIGNMENT_ID';
710                    l_inputs(1).value := p_assignment_id;
711                    l_inputs(2).name  := 'DATE_EARNED';
712                    l_inputs(2).value := fnd_date.date_to_canonical(p_date_earned);
713                    l_inputs(3).name  := 'BUSINESS_GROUP_ID';
714                    l_inputs(3).value := p_business_group_id;
715                    l_inputs(4).name := 'ASSIGNMENT_ACTION_ID';
716                    l_inputs(4).value := p_assignment_action_id;
717                    l_inputs(5).name := 'PAYROLL_ACTION_ID';
718                    l_inputs(5).value := l_payroll_action_id;
719                    l_inputs(6).name := 'BALANCE_DATE';
720                    l_inputs(6).value := fnd_date.date_to_canonical(p_date_earned);
721    		  --
722                    l_outputs(1).name := 'PSEUDO_SI_PART_TIME_PERCENTAGE';
723    		  --
724                    pay_nl_general.run_formula(p_formula_id       => g_pse_ptp_formula_id,
725                                               p_effective_date   => p_date_earned,
726                                               p_formula_name     => g_pse_ptp_formula_name,
727                                               p_inputs           => l_inputs,
728                                               p_outputs          => l_outputs);
729    		  --
730                    l_part_time_perc := l_outputs(1).value;
731          --    hr_utility.trace('l_part_time_perc'||l_part_time_perc);
732                ELSE
733            --  hr_utility.trace('FORMULA DOESNT EXISTS');
734                    l_part_time_perc := NULL;
735            --  hr_utility.trace('l_part_time_perc'||l_part_time_perc);
736                END IF;
737            ELSIF g_pse_ptp_formula_exists = FALSE THEN
738                l_part_time_perc := NULL;
739            END IF;
740            RETURN fnd_number.canonical_to_number(l_part_time_perc);
741        END get_pseudo_si_part_time_perc;
742 -------------------------------------------------------------------------------
743 -- Function : get_std_si_rep_part_time_perc
744 -- To get the Standard SI Part time Percentage for Reporting using
745 -- Assignment Id,Date Earned, Business Group Id and Assignment action Id.
746 ---------------------------------------------------------------------------------
747          FUNCTION get_std_si_rep_part_time_perc (p_assignment_id IN NUMBER
748                                    ,p_date_earned IN DATE
749                                    ,p_business_group_id IN NUMBER
750                                    ,p_assignment_action_id IN NUMBER) RETURN number IS
751        --
752        CURSOR csr_get_pay_action_id(c_assignment_action_id NUMBER) IS
753 	   SELECT payroll_action_id
754 	   FROM   pay_assignment_actions
755 	   WHERE  assignment_action_id = c_assignment_action_id;
756 	   --
757        l_payroll_action_id number;
758        l_part_time_perc varchar2(35);
759        l_inputs  ff_exec.inputs_t;
760        l_outputs ff_exec.outputs_t;
761        l_formula_exists  BOOLEAN := TRUE;
762        l_formula_cached  BOOLEAN := FALSE;
763        l_formula_id      ff_formulas_f.formula_id%TYPE;
764        BEGIN
765        g_std_rep_ptp_formula_name := 'NL_STANDARD_SI_REPORTING_PART_TIME_PERCENTAGE';
766        --
767        OPEN  csr_get_pay_action_id(p_assignment_action_id);
768        FETCH csr_get_pay_action_id INTO l_payroll_action_id;
769 	   CLOSE csr_get_pay_action_id;
770 	   --
771            IF g_std_rep_ptp_formula_exists = TRUE THEN
772                IF g_std_rep_ptp_formula_cached = FALSE THEN
773                    pay_nl_general.cache_formula('NL_STANDARD_SI_REPORTING_PART_TIME_PERCENTAGE',p_business_group_id,p_date_earned,l_formula_id,l_formula_exists,l_formula_cached);
774                    g_std_rep_ptp_formula_exists:=l_formula_exists;
775                    g_std_rep_ptp_formula_cached:=l_formula_cached;
776                    g_std_rep_ptp_formula_id:=l_formula_id;
777                END IF;
778    		--
779                IF g_std_rep_ptp_formula_exists = TRUE THEN
780              --  hr_utility.trace('FORMULA EXISTS');
781    		  --
782                    l_inputs(1).name  := 'ASSIGNMENT_ID';
783                    l_inputs(1).value := p_assignment_id;
784                    l_inputs(2).name  := 'DATE_EARNED';
785                    l_inputs(2).value := fnd_date.date_to_canonical(p_date_earned);
786                    l_inputs(3).name  := 'BUSINESS_GROUP_ID';
787                    l_inputs(3).value := p_business_group_id;
788                    l_inputs(4).name := 'ASSIGNMENT_ACTION_ID';
789                    l_inputs(4).value := p_assignment_action_id;
790                    l_inputs(5).name := 'PAYROLL_ACTION_ID';
791                    l_inputs(5).value := l_payroll_action_id;
792                    l_inputs(6).name := 'BALANCE_DATE';
793                    l_inputs(6).value := fnd_date.date_to_canonical(p_date_earned);
794    		  --
795                    l_outputs(1).name := 'STANDARD_SI_REPORTING_PART_TIME_PERCENTAGE';
796    		  --
797                    pay_nl_general.run_formula(p_formula_id       => g_std_rep_ptp_formula_id,
798                                               p_effective_date   => p_date_earned,
799                                               p_formula_name     => g_std_rep_ptp_formula_name,
800                                               p_inputs           => l_inputs,
801                                               p_outputs          => l_outputs);
802    		  --
803                    l_part_time_perc := l_outputs(1).value;
804          --    hr_utility.trace('l_part_time_perc'||l_part_time_perc);
805                ELSE
806            --  hr_utility.trace('FORMULA DOESNT EXISTS');
807                    l_part_time_perc := NULL;
808            --  hr_utility.trace('l_part_time_perc'||l_part_time_perc);
809                END IF;
810            ELSIF g_std_rep_ptp_formula_exists = FALSE THEN
811                l_part_time_perc := NULL;
812            END IF;
813            RETURN fnd_number.canonical_to_number(l_part_time_perc);
814        END get_std_si_rep_part_time_perc;
815  -------------------------------------------------------------------------------
816 -- Function : get_pse_si_rep_part_time_perc
817 -- To get the Pseudo SI Part time Percentage for reporting using
818 -- Assignment Id,Date Earned, Business Group Id and Assignment action Id.
819 ---------------------------------------------------------------------------------
820  FUNCTION get_pse_si_rep_part_time_perc (p_assignment_id IN NUMBER
821                                    ,p_date_earned IN DATE
822                                    ,p_business_group_id IN NUMBER
823                                    ,p_assignment_action_id IN NUMBER) RETURN number IS
824        --
825        CURSOR csr_get_pay_action_id(c_assignment_action_id NUMBER) IS
826 	   SELECT payroll_action_id
827 	   FROM   pay_assignment_actions
828 	   WHERE  assignment_action_id = c_assignment_action_id;
829 	   --
830        l_payroll_action_id number;
831        l_part_time_perc varchar2(35);
832        l_inputs  ff_exec.inputs_t;
833        l_outputs ff_exec.outputs_t;
834        l_formula_exists  BOOLEAN := TRUE;
835        l_formula_cached  BOOLEAN := FALSE;
836        l_formula_id      ff_formulas_f.formula_id%TYPE;
837        BEGIN
838        g_pse_rep_ptp_formula_name := 'NL_PSEUDO_SI_REPORTING_PART_TIME_PERCENTAGE';
839        --
840        OPEN  csr_get_pay_action_id(p_assignment_action_id);
841        FETCH csr_get_pay_action_id INTO l_payroll_action_id;
842 	   CLOSE csr_get_pay_action_id;
843 	   --
844            IF g_pse_rep_ptp_formula_exists = TRUE THEN
845                IF g_pse_rep_ptp_formula_cached = FALSE THEN
846                    pay_nl_general.cache_formula('NL_PSEUDO_SI_REPORTING_PART_TIME_PERCENTAGE',p_business_group_id,p_date_earned,l_formula_id,l_formula_exists,l_formula_cached);
847                    g_pse_rep_ptp_formula_exists:=l_formula_exists;
848                    g_pse_rep_ptp_formula_cached:=l_formula_cached;
849                    g_pse_rep_ptp_formula_id:=l_formula_id;
850                END IF;
851    		--
852                IF g_pse_rep_ptp_formula_exists = TRUE THEN
853              --  hr_utility.trace('FORMULA EXISTS');
854    		  --
855                    l_inputs(1).name  := 'ASSIGNMENT_ID';
856                    l_inputs(1).value := p_assignment_id;
857                    l_inputs(2).name  := 'DATE_EARNED';
858                    l_inputs(2).value := fnd_date.date_to_canonical(p_date_earned);
859                    l_inputs(3).name  := 'BUSINESS_GROUP_ID';
860                    l_inputs(3).value := p_business_group_id;
861                    l_inputs(4).name := 'ASSIGNMENT_ACTION_ID';
862                    l_inputs(4).value := p_assignment_action_id;
863                    l_inputs(5).name := 'PAYROLL_ACTION_ID';
864                    l_inputs(5).value := l_payroll_action_id;
865                    l_inputs(6).name := 'BALANCE_DATE';
866                    l_inputs(6).value := fnd_date.date_to_canonical(p_date_earned);
867    		  --
868                    l_outputs(1).name := 'PSEUDO_SI_REPORTING_PART_TIME_PERCENTAGE';
869    		  --
870                    pay_nl_general.run_formula(p_formula_id       => g_pse_rep_ptp_formula_id,
871                                               p_effective_date   => p_date_earned,
872                                               p_formula_name     => g_pse_rep_ptp_formula_name,
873                                               p_inputs           => l_inputs,
874                                               p_outputs          => l_outputs);
875    		  --
876                    l_part_time_perc := l_outputs(1).value;
877          --    hr_utility.trace('l_part_time_perc'||l_part_time_perc);
878                ELSE
879            --  hr_utility.trace('FORMULA DOESNT EXISTS');
880                    l_part_time_perc := NULL;
881            --  hr_utility.trace('l_part_time_perc'||l_part_time_perc);
882                END IF;
883            ELSIF g_pse_rep_ptp_formula_exists = FALSE THEN
884                l_part_time_perc := NULL;
885            END IF;
886            RETURN fnd_number.canonical_to_number(l_part_time_perc);
887        END get_pse_si_rep_part_time_perc;
888 /* This Function returns the day of the week.
889 Sunday is considered to be the first day of the week*/
890 FUNCTION  get_day_of_week(p_date date)
891 return number is
892 l_reference_date date:=to_date('01/01/1984','DD/MM/YYYY');
893 v_index number;
894 begin
895 v_index:=abs(p_date - l_reference_date);
896 v_index:=mod(v_index,7);
897 return v_index+1;
898 end get_day_of_week;
899 
900 -----------------------------------------------------------------------------------------------
901 -- Function : get_avg_part_time_percentage
902 -- To get the average Pseudo SI Part time Percentage
903 -- Assignment Id,Period Start Date,Period End Date
904 -----------------------------------------------------------------------------------------------
905 FUNCTION get_avg_part_time_percentage
906 	(	p_assignment_id		IN	per_all_assignments_f.assignment_id%type 	,
907 		p_period_start_date	IN	DATE	,
908 		p_period_end_date	IN	DATE
909 	)
910 	RETURN NUMBER IS
911 -- Cursor to retrieve part time percentages and effective start and end dates for an assignment.
912 CURSOR
913 	csr_get_part_time_per(	p_assignment_id 	per_all_assignments_f.assignment_id%type,
914 				p_period_start_date	DATE ,
915 				p_period_end_date	DATE
916 		             ) IS
917 SELECT 	FND_NUMBER.CANONICAL_TO_NUMBER(hs.segment29)	 	segment29	,
918 	pas.effective_start_date 				effective_start_date,
919 	pas.effective_end_date 					effective_end_date
920 FROM
921 	hr_soft_coding_keyflex hs 	,
922 	per_all_assignments_f pas
923 WHERE
924      pas.assignment_id		  	=	p_assignment_id 			AND
925      hs.soft_coding_keyflex_id	  	=	pas.soft_coding_keyflex_id 		AND
926      pas.effective_start_date 		<=     	p_period_end_date   			AND
927      pas.effective_end_date		>=	p_period_start_date ;
928 l_ef_start_date		per_all_assignments_f.effective_start_date%type;
929 l_ef_end_date		per_all_assignments_f.effective_end_date%type	;
930 l_period_start_date	DATE;
931 l_period_end_date	DATE;
932 l_asg_start_date	DATE;
933 l_asg_end_date		DATE;
934 l_days			NUMBER := 0;
935 l_part_time_perc	NUMBER := 0;
936 l_part_time_days	NUMBER := 0;
937 l_part_time_days_add	NUMBER := 0;
938 l_period_days		NUMBER := 0;
939 l_part_time_percentage	NUMBER := 0;
940 a			NUMBER;
941 BEGIN
942 a := PAY_NL_GENERAL.get_period_asg_dates
943 			(	p_assignment_id		=>  p_assignment_id
944 			,	p_period_start_date	=>  p_period_start_date
945 			,	p_period_end_date	=>  p_period_end_date
946 			,	p_asg_start_date	=>  l_asg_start_date
947 			,	p_asg_end_date		=>  l_asg_end_date
948 			);
949 l_period_start_date	:=	GREATEST( p_period_start_date , l_asg_start_date);
950 l_period_end_date	:=	LEAST( p_period_end_date   , l_asg_end_date  );
951 
952 FOR  	l_part_time_parameters IN
953 	csr_get_part_time_per(p_assignment_id ,l_period_start_date,l_period_end_date)
954 LOOP
955 	l_ef_start_date		:=	l_part_time_parameters.effective_start_date;
956 	l_ef_end_date		:=	l_part_time_parameters.effective_end_date;
957 	l_ef_end_date  		:=      LEAST(l_period_end_date, l_ef_end_date ) ;
958 	l_ef_start_date		:=      GREATEST(l_period_start_date, l_ef_start_date);
959 	l_days			:=      (l_ef_end_date -l_ef_start_date ) + 1;
960 	l_part_time_perc 	:=	nvl(l_part_time_parameters.segment29 ,100);
961 	l_part_time_days 	:=	l_part_time_perc*l_days;
962 	l_part_time_days_add	:=	l_part_time_days_add + l_part_time_days;
963 END LOOP;
964 l_period_days		:= 	( l_period_end_date - l_period_start_date )+ 1;
965 l_part_time_percentage  := 	l_part_time_days_add/l_period_days;
966 RETURN ROUND(l_part_time_percentage,4);
967 END get_avg_part_time_percentage;
968 
969 -----------------------------------------------------------------------------------------------
970 -- Function : get_real_si_days
971 -- To get the override for Real SI Days
972 -- Assignment Id,Date Earned, Business Group Id and Assignment action Id.
973 -----------------------------------------------------------------------------------------------
974 FUNCTION get_real_si_days
975 	(       p_assignment_id 	IN 	NUMBER
976 	       ,p_date_earned 		IN	DATE
977 	       ,p_business_group_id 	IN 	NUMBER
978 	       ,p_assignment_action_id 	IN 	NUMBER
979 	       ,p_payroll_action_id 	IN 	NUMBER
980 	)
981 	RETURN NUMBER IS
982 l_real_si_days   varchar2(35);
983 l_inputs  ff_exec.inputs_t;
984 l_outputs ff_exec.outputs_t;
985 l_formula_exists  BOOLEAN := TRUE;
986 l_formula_cached  BOOLEAN := FALSE;
987 l_formula_id      ff_formulas_f.formula_id%TYPE;
988 BEGIN
989 g_real_si_days_formula_name := 'NL_REAL_SOCIAL_INSURANCE_DAYS';
990    IF g_real_si_days_formula_exists = TRUE THEN
991        IF g_real_si_days_formula_cached = FALSE THEN
992 	   pay_nl_general.cache_formula('NL_REAL_SOCIAL_INSURANCE_DAYS',p_business_group_id,p_date_earned,l_formula_id,l_formula_exists,l_formula_cached);
993 	   g_real_si_days_formula_exists:=l_formula_exists;
994 	   g_real_si_days_formula_cached:=l_formula_cached;
995 	   g_real_si_days_formula_id:=l_formula_id;
996        END IF;
997 	--
998        IF g_real_si_days_formula_exists = TRUE THEN
999  	  --
1000 	   l_inputs(1).name  := 'ASSIGNMENT_ID';
1001 	   l_inputs(1).value := p_assignment_id;
1002 	   l_inputs(2).name  := 'DATE_EARNED';
1003 	   l_inputs(2).value := fnd_date.date_to_canonical(p_date_earned);
1004 	   l_inputs(3).name  := 'BUSINESS_GROUP_ID';
1005 	   l_inputs(3).value := p_business_group_id;
1006 	   l_inputs(4).name := 'ASSIGNMENT_ACTION_ID';
1007 	   l_inputs(4).value := p_assignment_action_id;
1008 	   l_inputs(5).name := 'PAYROLL_ACTION_ID';
1009 	   l_inputs(5).value := p_payroll_action_id;
1010        l_inputs(6).name := 'BALANCE_DATE';
1011        l_inputs(6).value := fnd_date.date_to_canonical(p_date_earned);
1012 	  --
1013 	   l_outputs(1).name := 'REAL_SOCIAL_INSURANCE_DAYS';
1014 	  --
1015 	   pay_nl_general.run_formula(p_formula_id       => g_real_si_days_formula_id,
1016 				      p_effective_date   => p_date_earned,
1017 				      p_formula_name     => g_real_si_days_formula_name,
1018 				      p_inputs           => l_inputs,
1019 				      p_outputs          => l_outputs);
1020 	  --
1021 	   l_real_si_days := l_outputs(1).value;
1022        ELSE
1023 	   l_real_si_days := NULL;
1024        END IF;
1025    ELSIF g_real_si_days_formula_exists = FALSE THEN
1026        l_real_si_days := NULL;
1027    END IF;
1028    RETURN fnd_number.canonical_to_number(l_real_si_days);
1029 END get_real_si_days;
1030 
1031 
1032 Function IsLeapYear(p_year NUMBER) RETURN NUMBER IS
1033 l_year NUMBER;
1034 BEGIN
1035 If (p_year  Mod 4 = 0) And
1036 ((p_year  Mod 100 <> 0) Or (p_year Mod 400 = 0)) Then
1037 l_year :=1;
1038 Else
1039 l_year :=0;
1040 End If;
1041 return l_year;
1042 End IsLeapYear ;
1043 
1044 
1045 FUNCTION get_asg_ind_work_hours
1046 	(	p_assignment_id		IN	per_all_assignments_f.assignment_id%type 	,
1047 		p_period_start_date	IN	DATE	,
1048 		p_period_end_date	IN	DATE
1049 	)
1050 	RETURN NUMBER IS
1051 -- Cursor to retrieve part time percentages and effective start and end dates for an assignment.
1052 CURSOR
1053 	csr_get_ind_work_hrs(	p_assignment_id 	per_all_assignments_f.assignment_id%type,
1054 				p_period_start_date	DATE ,
1055 				p_period_end_date	DATE
1056 		             ) IS
1057 SELECT 	FND_NUMBER.CANONICAL_TO_NUMBER(scl.segment28)	 	segment28	,
1058         paa.frequency ,
1059 	paa.effective_start_date 				effective_start_date,
1060 	paa.effective_end_date 					effective_end_date
1061 FROM
1062 	hr_soft_coding_keyflex scl 	,
1063 	per_all_assignments_f paa
1064 WHERE
1065      paa.assignment_id		  	=	p_assignment_id 			AND
1066      scl.soft_coding_keyflex_id	  	=	paa.soft_coding_keyflex_id 		AND
1067      paa.effective_start_date 		<=     	p_period_end_date   			AND
1068      paa.effective_end_date		>=	p_period_start_date ;
1069 
1070 TYPE days_month IS TABLE OF NUMBER;
1071  days_in  days_month;
1072 
1073 l_ef_start_date		per_all_assignments_f.effective_start_date%type;
1074 l_ef_end_date		per_all_assignments_f.effective_end_date%type	;
1075 l_period_start_date	DATE;
1076 l_period_end_date	DATE;
1077 l_asg_start_date	DATE;
1078 l_asg_end_date		DATE;
1079 l_days			NUMBER := 0;
1080 l_ind_wrk_hrs           NUMBER := 0;
1081 l_cum_ind_wrk_hrs	NUMBER := 0;
1082 l_part_time_days_add	NUMBER := 0;
1083 l_temp			NUMBER;
1084 l_mon_days              NUMBER := 0;
1085 l_freq                  VARCHAR2(10);
1086 
1087 
1088 
1089 BEGIN
1090 
1091 l_mon_days := ( p_period_end_date - p_period_start_date )+ 1;
1092 
1093 l_temp := PAY_NL_GENERAL.get_period_asg_dates
1094 			(	p_assignment_id		=>  p_assignment_id
1095 			,	p_period_start_date	=>  p_period_start_date
1096 			,	p_period_end_date	=>  p_period_end_date
1097 			,	p_asg_start_date	=>  l_asg_start_date
1098 			,	p_asg_end_date		=>  l_asg_end_date
1099 			);
1100 l_period_start_date	:=	GREATEST( p_period_start_date , l_asg_start_date);
1101 l_period_end_date	:=	LEAST( p_period_end_date   , l_asg_end_date  );
1102 
1103 FOR  	l_ind_wrk_hrs_csr IN
1104 	csr_get_ind_work_hrs (p_assignment_id ,l_period_start_date,l_period_end_date)
1105 LOOP
1106 	l_ef_start_date		:=	l_ind_wrk_hrs_csr.effective_start_date;
1107 	l_ef_end_date		:=	l_ind_wrk_hrs_csr.effective_end_date;
1108 	l_ef_end_date  		:=      LEAST(l_period_end_date, l_ef_end_date ) ;
1109 	l_ef_start_date		:=      GREATEST(l_period_start_date, l_ef_start_date);
1110 	l_days			:=      (l_ef_end_date -l_ef_start_date ) + 1;
1111 	l_ind_wrk_hrs   	:=	nvl(l_ind_wrk_hrs_csr.segment28 ,0);
1112 	l_freq                  :=      l_ind_wrk_hrs_csr.frequency;
1113 
1114 	if l_freq = 'D' then
1115 	l_cum_ind_wrk_hrs := l_cum_ind_wrk_hrs + (((l_ind_wrk_hrs*260)/12/l_mon_days)*l_days);
1116 	end if;
1117 
1118 	if l_freq = 'W' then
1119 	l_cum_ind_wrk_hrs := l_cum_ind_wrk_hrs + (((l_ind_wrk_hrs*52)/12/l_mon_days)*l_days);
1120 	end if;
1121 
1122 	if l_freq = 'M' then
1123         l_cum_ind_wrk_hrs := l_cum_ind_wrk_hrs + (((l_ind_wrk_hrs)/l_mon_days)*l_days);
1124 	end if;
1125 
1126 	if l_freq = 'Y' then
1127          l_cum_ind_wrk_hrs := l_cum_ind_wrk_hrs + (((l_ind_wrk_hrs)/12/l_mon_days)*l_days);
1128 	end if;
1129 
1130 END LOOP;
1131 
1132 RETURN  l_cum_ind_wrk_hrs;
1133 END get_asg_ind_work_hours;
1134 
1135 FUNCTION get_period_si_days(	 p_assignment_id 	NUMBER
1136 				,p_payroll_id		NUMBER
1137 				,p_effective_date       DATE
1138 				,p_source_text		VARCHAR2
1139 				,p_override_day_method 	VARCHAR2
1140 				,p_override_day_value   VARCHAR2
1141 				,p_avg_ws_si_days	NUMBER
1142 				,p_override_si_days	NUMBER
1143  				,p_real_si_days		NUMBER
1144 				,p_si_day_method	VARCHAR2
1145 				,p_max_si_method	VARCHAR2
1146 				,p_multi_asg_si_days	NUMBER
1147 				,p_year_calc 		VARCHAR2
1148 				,p_override_real_si_days NUMBER
1149 				,p_override   OUT NOCOPY VARCHAR2
1150 				,p_period_si_days_year_calc NUMBER
1151 							    )
1152 			    RETURN NUMBER
1153 			    IS
1154 l_number 		NUMBER;
1155 l_period_start_date	DATE;
1156 l_period_end_date	DATE;
1157 period_start_date	DATE;
1158 period_end_date		DATE;
1159 l_asg_start_date 	DATE;
1160 l_asg_end_date 		DATE;
1161 l_period_type		VARCHAR2(50);
1162 Average_SI_days 	NUMBER;
1163 Total_Days		NUMBER;
1164 Work_Days		NUMBER;
1165 Override		VARCHAR2(10);
1166 Period_SI_Days		NUMBER := 0;
1167 Max_SI_Days		NUMBER;
1168 Available_SI_Days	NUMBER;
1169 Multi_Assign_Max_Days 	NUMBER;
1170 l_si_day_method			VARCHAR2(10) := '0';
1171 CURSOR get_payroll_period( p_payroll_id	     NUMBER
1172 			   ,p_effective_date DATE  )   IS
1173 select 	START_DATE
1174        ,END_DATE
1175 from
1176 per_time_periods
1177 where payroll_id=p_payroll_id
1178 and p_effective_date between START_DATE and END_DATE;
1179 BEGIN
1180 
1181 OPEN get_payroll_period(p_payroll_id,p_effective_date);
1182 FETCH get_payroll_period INTO l_period_start_date, l_period_end_date;
1183 CLOSE get_payroll_period;
1184 l_number := pay_nl_general.get_period_asg_dates (p_assignment_id ,l_period_start_date ,l_period_end_date
1185 		      				,l_asg_start_date , l_asg_end_date );
1186 
1187 
1188 l_period_type := pay_nl_si_pkg.get_payroll_type(p_payroll_id);
1189 IF l_period_type = 'Calendar Month' THEN
1190 	Average_SI_days:= fnd_number.canonical_to_number(pay_nl_general.get_global_value(p_effective_date,'NL_SI_AVERAGE_DAYS_MONTHLY'));
1191 END IF;
1192 IF l_period_type = 'Week' THEN
1193 	Average_SI_days:= fnd_number.canonical_to_number(pay_nl_general.get_global_value(p_effective_date,'NL_SI_AVERAGE_DAYS_WEEKLY'));
1194 END IF;
1195 IF l_period_type = 'Quarter' THEN
1196 	Average_SI_days:= fnd_number.canonical_to_number(pay_nl_general.get_global_value(p_effective_date,'NL_SI_AVERAGE_DAYS_QUARTERLY'));
1197 END IF;
1198 IF l_period_type = 'Lunar Month' THEN
1199 	Average_SI_days:= fnd_number.canonical_to_number(pay_nl_general.get_global_value(p_effective_date,'NL_SI_AVERAGE_DAYS_4WEEKLY'));
1200 END IF;
1201 IF l_asg_start_date > l_period_start_date THEN
1202 	  Total_Days := fffunc.days_between(l_period_end_date, l_period_start_date) + 1;
1203 	  IF l_Asg_End_Date < l_period_end_date THEN
1204 	    Work_Days := fffunc.days_between(l_asg_end_date, l_asg_start_date) + 1;
1205 	  ELSE
1206 	    Work_Days := fffunc.days_between(l_period_end_date, l_asg_start_date) + 1;
1207 	  END If;
1208 	  Average_SI_Days := round((Average_SI_Days / Total_Days * Work_Days),2);
1209 
1210 ELSE
1211 	  IF l_asg_end_date < l_period_end_date THEN
1212 		    Total_Days := fffunc.days_between(l_period_end_date, l_period_start_date) + 1;
1213 		    Work_Days := fffunc.days_between(l_asg_end_date, l_period_start_date) + 1;
1214 		    Average_SI_Days := round((Average_SI_Days / Total_Days * Work_Days),2);
1215 	  END IF;
1216 END IF;
1217 
1218 Period_Start_Date	:=	GREATEST( l_period_start_date , l_asg_start_date);
1219 Period_End_Date		:=	LEAST( l_period_end_date   , l_asg_end_date  );
1220 IF p_max_si_method = '1' THEN
1221    /* If the selected method is the number of week days in a payroll period/year.  This is
1222    forced if there are multi assignments.  Then call relevant formula function.*/
1223   Max_SI_Days := GET_WEEK_DAYS (Period_Start_Date, Period_End_Date);
1224 ELSE
1225   /* If the selected method is 5 days per week for the weeks worked. Then call relevant formula
1226    function */
1227   Max_SI_Days := GET_MAX_SI_DAYS (p_assignment_id,Period_Start_Date, Period_End_Date);
1228 END IF;
1229 
1230 Override := 'N';
1231 
1232 IF p_override_si_days <> -1 THEN
1233    	Period_SI_Days := p_override_si_days;
1234    	Override := 'Y';
1235 ELSE
1236       IF p_override_day_method = '0' THEN
1237          Period_SI_Days := to_number(p_override_day_value);
1238          Override := 'Y';
1239       ELSE
1240          IF p_override_day_method = '1' THEN
1241  	       	Period_SI_Days := (Average_SI_Days / 100) * to_number(p_override_day_value);
1242  	       	Period_SI_Days := Round(Period_SI_Days,2);
1243  	       	Override := 'Y';
1244          ELSE
1245  	     	IF p_override_day_method = '2' THEN
1246  			Period_SI_Days := (Max_SI_Days / 100) * to_number(p_override_day_value);
1247  			Period_SI_Days := Round(Period_SI_Days, 2);
1248  			Override := 'Y';
1249  		END IF;
1250  	 END IF;
1251       END IF;
1252 END IF;
1253 
1254 Multi_Assign_Max_Days := Max_SI_Days;
1255 
1256 IF p_si_day_method = '0' AND p_year_calc= 'N' AND Override = 'N' THEN
1257  	/* Average Days */
1258    	Period_SI_Days := Average_SI_Days;
1259    	Period_SI_Days := Period_SI_Days - p_multi_asg_si_days  ;
1260    	IF (Period_SI_Days <0) THEN
1261    	   Period_SI_Days := 0 ;
1262    	END IF;
1263 ELSE
1264    	IF p_si_day_method = '2' AND p_year_calc= 'N' AND Override = 'N' THEN
1265            	/* Average Days with Work Schedules*/
1266         	Period_SI_Days := p_avg_ws_si_days;
1267         	Period_SI_Days := Period_SI_Days - p_multi_asg_si_days  ;
1268         	IF (Period_SI_Days <0) THEN
1269    	   		Period_SI_Days :=0;
1270    		END IF;
1271    	ELSE
1272       		IF (p_si_day_method = '1' AND p_year_calc = 'N') AND Override = 'N' THEN
1273           		/*  Real SI Days */
1274          		 Period_SI_Days := p_real_si_days;
1275           		/* Check if override of real SI days was used.  If so then re-set override indicator */
1276           		IF p_override_real_si_days <> -1 THEN
1277           			Override := 'Y';
1278           		END IF;
1279        		ELSE
1280        			IF p_year_calc = 'Y' AND Override = 'N' AND p_si_day_method <> '3' THEN
1281 				/* Adjusted year value */
1282 				Period_SI_Days := p_period_si_days_year_calc;
1283 				l_si_day_method := '1';
1284 				/* Adjust Max SI Days for multi assignments*/
1285 		 		Multi_Assign_Max_Days := Period_SI_Days;
1286 		 	END IF;
1287        		END IF;
1288    	END IF;
1289 END IF;
1290 Available_SI_Days:= 0 ;
1291 /*Max Si Days Rule is applicable only for Real SI Days*/
1292 IF (p_si_day_method = '1' or l_si_day_method = '1') AND Override = 'N' THEN
1293      IF Multi_Assign_Max_Days > p_multi_asg_si_days THEN
1294          Available_SI_Days := Multi_Assign_Max_Days - p_multi_asg_si_days;
1295      ELSE
1296          Available_SI_Days := 0;
1297      END IF;
1298      IF Period_SI_Days > Available_SI_Days THEN
1299            Period_SI_Days := Available_SI_Days;
1300      END IF;
1301 END IF;
1302 
1303 p_override := Override;
1304 
1305 
1306 RETURN Period_SI_Days;
1307 END get_period_si_days;
1308 
1309 FUNCTION get_ret_real_si_days    ( 	 p_assignment_id 		NUMBER
1310 					,p_payroll_id			NUMBER
1311 					,p_effective_date 		DATE
1312 					,p_source_text			VARCHAR2
1313 					,p_source_text2			VARCHAR2
1314 					,p_real_si_days			NUMBER
1315 					,p_override_real_si_days	NUMBER
1316 					,p_max_si_method		VARCHAR2
1317 					,p_real_si_sit_ytd		NUMBER
1318 					,p_real_si_sit_ptd		NUMBER
1319 					,p_ret_real_si_sit_ytd		NUMBER
1320 					,p_real_si_per_pay_sitp_ptd	NUMBER
1321 				 )
1322 				 RETURN NUMBER IS
1323 l_period_start_date		DATE;
1324 l_period_end_date		DATE;
1325 l_asg_start_date		DATE;
1326 l_asg_end_date			DATE;
1327 Period_Start_Date		DATE;
1328 Period_End_Date			DATE;
1329 p_ret_real_si_days		NUMBER  := 0;
1330 l_number			NUMBER;
1331 l_avail_real_si_days		NUMBER;
1332 l_cum_real_si_days		NUMBER;
1333 Max_SI_Days			NUMBER;
1334 l_multi_asg_real_si		NUMBER;
1335 l_si_avg_days_yr		NUMBER;
1336 CURSOR get_payroll_period( p_payroll_id	     NUMBER
1337 			   ,p_effective_date DATE  )   IS
1338 select 	START_DATE
1339        ,END_DATE
1340 from
1341 per_time_periods
1342 where payroll_id=p_payroll_id
1343 and p_effective_date between START_DATE and END_DATE;
1344 BEGIN
1345 OPEN get_payroll_period(p_payroll_id,p_effective_date);
1346 FETCH get_payroll_period INTO l_period_start_date, l_period_end_date;
1347 CLOSE get_payroll_period;
1348 l_number := pay_nl_general.get_period_asg_dates (p_assignment_id ,l_period_start_date ,l_period_end_date
1349 		      				,l_asg_start_date , l_asg_end_date );
1350 
1351 
1352 Period_Start_Date	:=	GREATEST( l_period_start_date , l_asg_start_date);
1353 Period_End_Date		:=	LEAST( l_period_end_date   , l_asg_end_date  );
1354 
1355 IF p_max_si_method = '1' THEN
1356    /* If the selected method is the number of week days in a payroll period/year.  This is
1357    forced if there are multi assignments.  Then call relevant formula function.*/
1358   Max_SI_Days := GET_WEEK_DAYS (Period_Start_Date, Period_End_Date);
1359 ELSE
1360   /* If the selected method is 5 days per week for the weeks worked. Then call relevant formula
1361    function */
1362   Max_SI_Days := GET_MAX_SI_DAYS (p_assignment_id,Period_Start_Date, Period_End_Date);
1363 END IF;
1364 /* Set return value for real SI days */
1365 p_ret_real_si_days  := p_real_si_days;
1366 l_multi_asg_real_si := p_real_si_per_pay_sitp_ptd - p_real_si_sit_ptd;
1367 IF p_override_real_si_days = -1 THEN
1368   IF Max_SI_Days >l_multi_asg_real_si THEN
1369     l_avail_real_si_days := Max_SI_Days - l_multi_asg_real_si ;
1370   ELSE
1371     l_avail_real_si_days := 0;
1372   END IF;
1373   IF p_real_si_days > l_avail_real_si_days THEN
1374     p_ret_real_si_days := l_avail_real_si_days;
1375   END IF;
1376 END IF;
1377 l_si_avg_days_yr := fnd_number.canonical_to_number(pay_nl_general.get_global_value(p_effective_date,'NL_SI_AVERAGE_DAYS_YEARLY'));
1378 IF p_override_real_si_days = -1 THEN
1379   l_cum_real_si_days := (p_real_si_sit_ytd - p_real_si_sit_ptd) + p_ret_real_si_days + p_ret_real_si_sit_ytd;
1380 	  IF l_cum_real_si_days > l_si_avg_days_yr THEN
1381 	    p_ret_real_si_days := p_ret_real_si_days - (l_cum_real_si_days - l_si_avg_days_yr);
1382 	  END IF;
1383 END IF;
1384 p_ret_real_si_days := p_ret_real_si_days - p_real_si_sit_ptd;
1385 RETURN p_ret_real_si_days;
1386 END get_ret_real_si_days;
1387 
1388 FUNCTION get_thres_or_max_si  ( 	 p_assignment_id 	NUMBER
1389 					,p_payroll_id		NUMBER
1390 					,p_effective_date	DATE
1391 					,p_calc_code		NUMBER
1392 					,p_part_time_perc	NUMBER
1393 					,p_si_days		NUMBER
1394 					,p_thre_max_si		NUMBER
1395 				  )
1396 				  RETURN NUMBER IS
1397 
1398 l_period_start_date		DATE;
1399 l_period_end_date		DATE;
1400 l_asg_start_date		DATE;
1401 l_asg_end_date			DATE;
1402 Period_Start_Date		DATE;
1403 Period_End_Date			DATE;
1404 l_number 			NUMBER;
1405 Non_SI_Days			NUMBER;
1406 Total_Days			NUMBER;
1407 Work_Days			NUMBER;
1408 Absence_Factor			NUMBER;
1409 Threshold_or_Max_SI			NUMBER;
1410 l_avg_si_days_monthly		NUMBER;
1411 
1412 CURSOR get_payroll_period(  p_payroll_id	     NUMBER
1413 			   ,p_effective_date DATE  )   IS
1414 select 	START_DATE
1415        ,END_DATE
1416 from
1417 per_time_periods
1418 where payroll_id=p_payroll_id
1419 and p_effective_date between START_DATE and END_DATE;
1420 
1421 BEGIN
1422 
1423 OPEN get_payroll_period(p_payroll_id,p_effective_date);
1424 FETCH get_payroll_period INTO l_period_start_date, l_period_end_date;
1425 CLOSE get_payroll_period;
1426 l_number := pay_nl_general.get_period_asg_dates (p_assignment_id ,l_period_start_date ,l_period_end_date
1427 		      				,l_asg_start_date , l_asg_end_date );
1428 
1429 Period_Start_Date	:=	GREATEST( l_period_start_date , l_asg_start_date);
1430 Period_End_Date		:=	LEAST( l_period_end_date   , l_asg_end_date  );
1431 
1432 l_avg_si_days_monthly := fnd_number.canonical_to_number(pay_nl_general.get_global_value(p_effective_date,'NL_SI_AVERAGE_DAYS_MONTHLY'));
1433 
1434 IF (p_calc_code = 0 OR p_calc_code =1 OR p_calc_code = 3 ) then
1435 
1436 		Threshold_or_Max_SI := p_si_days * to_number(p_thre_max_si);
1437 
1438 ELSE
1439 
1440 		Threshold_or_Max_SI := to_number(p_thre_max_si) * (p_part_time_perc / 100);
1441 
1442 		/* Added Proration code for Bug 3412227
1443 		Pro-rate SI base and threshold if employee started or left during the payroll period */
1444 		IF l_Asg_Start_Date > l_period_start_date THEN
1445 
1446 			Total_Days := fffunc.days_between(l_period_end_date, l_period_start_date) + 1;
1447 			IF l_Asg_End_Date < l_period_end_date THEN
1448 			  	Work_Days := fffunc.days_between(l_Asg_End_Date, l_Asg_Start_Date) + 1;
1449 			ELSE
1450 			  	Work_Days := fffunc.days_between(l_period_end_date, l_Asg_Start_Date) + 1;
1451 			END IF;
1452 			Threshold_or_Max_SI := round((Threshold_or_Max_SI / Total_Days * Work_Days),2);
1453 
1454 		ELSE
1455 
1456 			IF l_Asg_End_Date < l_period_end_date THEN
1457 
1458 			  	Total_Days := fffunc.days_between(l_period_end_date, l_period_start_date) + 1;
1459 			  	Work_Days := fffunc.days_between(l_Asg_End_Date, l_period_start_date) + 1;
1460 			  	Threshold_or_Max_SI := round((Threshold_or_Max_SI / Total_Days * Work_Days),2) ;
1461 
1462 			END IF;
1463 		END IF;
1464 
1465 
1466 		Non_SI_Days := GET_NON_SI_DAYS(p_assignment_id,Period_Start_Date, Period_End_Date);
1467 
1468 
1469 		IF Non_SI_Days > 0 THEN
1470 
1471 			/* Determine factor to reduce Maximum SI Salary and Thresholds by any non SI absences*/
1472 			IF l_avg_si_days_monthly > Non_SI_Days then
1473 				Absence_Factor := (l_avg_si_days_monthly - Non_SI_Days) / l_avg_si_days_monthly ;
1474 			ELSE
1475 				Absence_Factor := 0;
1476 			END IF;
1477 
1478 			Threshold_or_Max_SI := Threshold_or_Max_SI * Absence_Factor;
1479 
1480 	   	END IF;
1481 
1482 END IF;
1483 
1484 RETURN Threshold_or_Max_SI;
1485 
1486 END get_thres_or_max_si;
1487 
1488 FUNCTION get_si_proration_days (p_assignment_id NUMBER
1489                                ,p_period_start_date DATE
1490                                ,p_period_end_date DATE
1491                                ,p_proration_start_date DATE
1492                                ,p_proration_end_date DATE
1493                                ,p_period_si_days NUMBER
1494                                )
1495                                RETURN NUMBER IS
1496 CURSOR csr_asg_dates (p_other_assignment_id NUMBER) IS
1497        SELECT MIN(asg.effective_start_date) asg_start_date
1498               ,MAX(asg.effective_end_date) asg_end_date
1499        FROM PER_ASSIGNMENTS_F asg
1500             ,PER_ASSIGNMENT_STATUS_TYPES past
1501        WHERE asg.assignment_id = p_other_assignment_id
1502        AND   past.per_system_status = 'ACTIVE_ASSIGN'
1503        AND   asg.assignment_status_type_id = past.assignment_status_type_id
1504        AND   asg.effective_start_date <= p_period_end_date
1505        AND   NVL(asg.effective_end_date,p_period_end_date) >= p_period_start_date;
1506 
1507 CURSOR csr_any_other_asg IS
1508        SELECT DISTINCT asg1.assignment_id asgid
1509        FROM per_assignments_f asg1
1510             ,per_assignments_f asg2
1511             ,pay_object_groups pog1
1512             ,pay_object_groups pog2
1513        WHERE asg1.person_id = asg2.person_id
1514        AND   asg2.assignment_id = p_assignment_id
1515        AND   asg1.assignment_id <> p_assignment_id
1516        AND   pog1.source_id = asg1.assignment_id
1517        AND   pog1.source_type = 'PAF'
1518        AND   pog2.source_id = asg2.assignment_id
1519        AND   pog2.source_type = 'PAF'
1520        AND   pog1.parent_object_group_id = pog2.parent_object_group_id;
1521 
1522 CURSOR csr_person_dates IS
1523        SELECT MIN(asg.effective_start_date) per_start_date
1524               ,MAX(asg.effective_end_date) per_end_date
1525        FROM PER_ASSIGNMENTS_F asg,
1526             PER_ASSIGNMENT_STATUS_TYPES past,
1527             PAY_OBJECT_GROUPS pog
1528        WHERE asg.person_id in
1529        (select asg2.person_id from PER_ASSIGNMENTS_F asg2, PAY_OBJECT_GROUPS pog2
1530        where asg2.assignment_id = p_assignment_id
1531        and pog2.source_id = asg2.assignment_id
1532        and pog2.source_type = 'PAF'
1533        and pog.parent_object_group_id = pog2.parent_object_group_id)
1534        AND   past.per_system_status = 'ACTIVE_ASSIGN'
1535        AND   asg.assignment_status_type_id = past.assignment_status_type_id
1536        AND   asg.effective_start_date <= p_period_end_date
1537        AND   NVL(asg.effective_end_date,p_period_end_date) >= p_period_start_date
1538        AND   pog.source_id = asg.assignment_id
1539        AND   pog.source_type = 'PAF';
1540 
1541 
1542 l_proration_start_date DATE;
1543 l_proration_end_date DATE;
1544 other_asg_start_date DATE;
1545 other_asg_end_date DATE;
1546 l_other_asg_start_date DATE;
1547 l_other_asg_end_date DATE;
1548 proration_days NUMBER := 0;
1549 overlap_with_main VARCHAR2(10);
1550 other_asg_no NUMBER := 0;
1551 l_other_asg1_start_date DATE;
1552 l_other_asg1_end_date DATE;
1553 l_other_asg2_start_date DATE;
1554 l_other_asg2_end_date DATE;
1555 
1556 l_per_start_date DATE;
1557 l_per_end_date   DATE;
1558 
1559 --6887820
1560 l_element_type_id pay_element_types_f.element_type_id%TYPE;
1561 l_input_value_id pay_input_values_f.input_value_id%TYPE;
1562 l_prorate_flag pay_element_entry_values_f.screen_entry_value%TYPE;
1563 
1564 --6887820
1565 CURSOR ele_typ_id
1566 IS
1567 select element_type_id
1568 from pay_element_types_f
1569 where
1570 element_name = 'NL Tax and SI Proration Indicator'
1571 and p_proration_start_date between effective_start_date and effective_end_date
1572 and legislation_code = 'NL';
1573 
1574 CURSOR inp_val_id(p_element_type_id NUMBER)
1575 IS
1576 select input_value_id from pay_input_values_f
1577 where element_type_id = p_element_type_id
1578 and p_proration_start_date between effective_start_date and effective_end_date
1579 and legislation_code = 'NL';
1580 
1581 /* Cursor to get the override value of proration flag from
1582 seeded element "NL Tax and SI Proration Indicator" */
1583 
1584 CURSOR part_time_prorate_flag
1585 IS
1586 SELECT EEV.screen_entry_value
1587 FROM
1588         pay_element_entry_values_f               EEV,
1589         pay_element_entries_f                    EE,
1590         pay_link_input_values_f                  LIV,
1591         pay_input_values_f                       INPUTV
1592 WHERE   INPUTV.input_value_id                  = l_input_value_id
1593 AND     p_proration_start_date BETWEEN INPUTV.effective_start_date AND INPUTV.effective_end_date
1594 AND     INPUTV.element_type_id		     = l_element_type_id
1595 AND     LIV.input_value_id                     = INPUTV.input_value_id
1596 AND     p_proration_start_date BETWEEN LIV.effective_start_date AND LIV.effective_end_date
1597 AND     EEV.input_value_id                     = INPUTV.input_value_id
1598 AND     EEV.element_entry_id                   = EE.element_entry_id
1599 AND     EEV.effective_start_date               = EE.effective_start_date
1600 AND     EEV.effective_end_date                 = EE.effective_end_date
1601 AND     EE.element_link_id                     = LIV.element_link_id
1602 AND     EE.assignment_id                       = p_assignment_id
1603 AND     p_proration_start_date BETWEEN EE.effective_start_date AND EE.effective_end_date
1604 AND     nvl(EE.ENTRY_TYPE, 'E')                = 'E';
1605 --6887820
1606 
1607 
1608 BEGIN
1609 --6887820
1610 	OPEN ele_typ_id;
1611 	FETCH ele_typ_id into l_element_type_id;
1612 	CLOSE ele_typ_id;
1613 
1614 	OPEN inp_val_id(l_element_type_id);
1615 	FETCH inp_val_id INTO l_input_value_id;
1616 	CLOSE inp_val_id;
1617 
1618 	OPEN part_time_prorate_flag;
1619 	FETCH part_time_prorate_flag INTO l_prorate_flag;
1620 	CLOSE part_time_prorate_flag;
1621 
1622 --6887820 % if seeded element exists with assignment
1623    IF l_prorate_flag = 'N' THEN
1624     l_proration_start_date := p_period_start_date;
1625     l_proration_end_date := p_period_end_date;
1626 --6887820
1627    ELSE
1628     l_proration_start_date := p_proration_start_date;
1629     l_proration_end_date := p_proration_end_date;
1630    END IF;
1631 
1632    /* loop for other assignments for the employee */
1633    FOR c1rec IN csr_any_other_asg LOOP
1634     OPEN csr_asg_dates(c1rec.asgid);
1635     FETCH csr_asg_dates INTO l_other_asg_start_date, l_other_asg_end_date;
1636     CLOSE csr_asg_dates;
1637 
1638     /* If other assignment of the employee is active in the payroll period calculate working days using daily table */
1639     IF l_other_asg_start_date IS NOT NULL AND l_other_asg_end_date IS NOT NULL THEN
1640         other_asg_no := other_asg_no + 1;
1641         other_asg_start_date := GREATEST(p_period_start_date, l_other_asg_start_date);
1642         other_asg_end_date := LEAST(p_period_end_date, l_other_asg_end_date);
1643         IF other_asg_no = 1 THEN
1644            l_other_asg1_start_date := other_asg_start_date;
1645            l_other_asg1_end_date := other_asg_end_date;
1646         END IF;
1647         IF other_asg_no = 2 THEN
1648            l_other_asg2_start_date := other_asg_start_date;
1649            l_other_asg2_end_date := other_asg_end_date;
1650         END IF;
1651         IF other_asg_start_date < l_proration_start_date THEN
1652             IF other_asg_end_date < l_proration_start_date - 1 THEN
1653                 IF other_asg_no = 1 THEN
1654                     overlap_with_main := 'N';
1655                 END IF;
1656                 proration_days := proration_days + Get_Week_Days (other_asg_start_date, other_asg_end_date);
1657              ELSE
1658                 l_proration_start_date := other_asg_start_date;
1659              END IF;
1660         END IF;
1661 
1662         IF other_asg_end_date > l_proration_end_date THEN
1663             IF other_asg_start_date > l_proration_end_date + 1 THEN
1664                 IF other_asg_no = 1 THEN
1665                     overlap_with_main := 'N';
1666                 END IF;
1667                 proration_days := proration_days + Get_Week_Days (other_asg_start_date, other_asg_end_date);
1668             ELSE
1669                 l_proration_end_date := other_asg_end_date;
1670             END IF;
1671         END IF;
1672     END IF;
1673   END LOOP;
1674 
1675   /* If there are one or more days in the payroll period having no active assignments, then use daily table only*/
1676   IF l_proration_start_date = p_period_start_date and l_proration_end_date = p_period_end_date and p_period_si_days > 0 THEN
1677     proration_days := p_period_si_days;
1678     RETURN proration_days;
1679   END IF;
1680   proration_days := proration_days + Get_Week_Days (l_proration_start_date, l_proration_end_date);
1681 
1682   /* Remove overlaps between the first other assignment and second other assignment, if any */
1683   IF other_asg_no = 2 AND overlap_with_main = 'N' THEN
1684     IF l_other_asg2_start_date BETWEEN l_other_asg1_start_date AND l_other_asg1_end_date THEN
1685         proration_days := proration_days - Get_Week_Days (l_other_asg2_start_date, LEAST(l_other_asg2_end_date, l_other_asg1_end_date));
1686     ELSIF l_other_asg2_end_date BETWEEN l_other_asg1_start_date and l_other_asg1_end_date THEN
1687         proration_days := proration_days - Get_Week_Days (l_other_asg1_start_date, l_other_asg2_end_date);
1688     ELSIF l_other_asg1_start_date BETWEEN l_other_asg2_start_date AND l_other_asg2_end_date THEN
1689         proration_days := proration_days - Get_Week_Days (l_other_asg1_start_date, l_other_asg1_end_date);
1690     END IF;
1691   END IF;
1692 
1693   /*For more than 3 active assignments, proration days are returned with assumption that person
1694   is active for every day in the payroll period. Otherwise user feeds the days manually */
1695   IF other_asg_no > 2 THEN
1696     OPEN csr_person_dates;
1697     FETCH csr_person_dates INTO l_per_start_date, l_per_end_date;
1698     CLOSE csr_person_dates;
1699     l_per_start_date := GREATEST(p_period_start_date, l_per_start_date);
1700     l_per_end_date := LEAST(p_period_end_date, l_per_end_date);
1701     IF l_per_start_date = p_period_start_date and l_per_end_date = p_period_end_date and p_period_si_days > 0 THEN
1702 	proration_days := p_period_si_days;
1703     ELSE
1704     	proration_days := Get_Week_Days (l_per_start_date, l_per_end_date);
1705     END IF;
1706   END IF;
1707 RETURN proration_days;
1708 END get_si_proration_days;
1709 
1710 -----------------------------------------------------------------------------------------------
1711 -- Function : get_override_si_days
1712 -- To get the override for SI Days
1713 -- Assignment Id,Date Earned, Business Group Id and Assignment action Id.
1714 -----------------------------------------------------------------------------------------------
1715 FUNCTION get_override_si_days
1716 	(       p_assignment_id 	IN 	NUMBER
1717 	       ,p_date_earned 		IN	DATE
1718 	       ,p_business_group_id 	IN 	NUMBER
1719 	       ,p_assignment_action_id 	IN 	NUMBER
1720 	       ,p_payroll_action_id 	IN 	NUMBER
1721 	)
1722 	RETURN NUMBER IS
1723 l_override_si_days  varchar2(35);
1724 l_inputs  ff_exec.inputs_t;
1725 l_outputs ff_exec.outputs_t;
1726 l_formula_exists    BOOLEAN := TRUE;
1727 l_formula_cached    BOOLEAN := FALSE;
1728 l_formula_id        ff_formulas_f.formula_id%TYPE;
1729 BEGIN
1730 g_si_days_formula_name := 'NL_OVERRIDE_SOCIAL_INSURANCE_DAYS';
1731    IF g_si_days_formula_exists = TRUE THEN
1732        IF g_si_days_formula_cached = FALSE THEN
1733 	   pay_nl_general.cache_formula('NL_OVERRIDE_SOCIAL_INSURANCE_DAYS',p_business_group_id,p_date_earned,l_formula_id,l_formula_exists,l_formula_cached);
1734 	   g_si_days_formula_exists:=l_formula_exists;
1735 	   g_si_days_formula_cached:=l_formula_cached;
1736 	   g_si_days_formula_id:=l_formula_id;
1737        END IF;
1738 	--
1739        IF g_si_days_formula_exists = TRUE THEN
1740  	  --
1741 	   l_inputs(1).name  := 'ASSIGNMENT_ID';
1742 	   l_inputs(1).value := p_assignment_id;
1743 	   l_inputs(2).name  := 'DATE_EARNED';
1744 	   l_inputs(2).value := fnd_date.date_to_canonical(p_date_earned);
1745 	   l_inputs(3).name  := 'BUSINESS_GROUP_ID';
1746 	   l_inputs(3).value := p_business_group_id;
1747 	   l_inputs(4).name := 'ASSIGNMENT_ACTION_ID';
1748 	   l_inputs(4).value := p_assignment_action_id;
1749 	   l_inputs(5).name := 'PAYROLL_ACTION_ID';
1750 	   l_inputs(5).value := p_payroll_action_id;
1751        l_inputs(6).name := 'BALANCE_DATE';
1752        l_inputs(6).value := fnd_date.date_to_canonical(p_date_earned);
1753 	  --
1754 	   l_outputs(1).name := 'OVERRIDE_SOCIAL_INSURANCE_DAYS';
1755 	   l_outputs(2).name := 'PRORATION_FLAG';
1756 	  --
1757 	   pay_nl_general.run_formula(p_formula_id       => g_si_days_formula_id,
1758 				      p_effective_date   => p_date_earned,
1759 				      p_formula_name     => g_si_days_formula_name,
1760 				      p_inputs           => l_inputs,
1761 				      p_outputs          => l_outputs);
1762 	  --
1763 	   g_si_days := fnd_number.canonical_to_number(l_outputs(1).value);
1764 	   g_tax_proration_days := fnd_number.canonical_to_number(l_outputs(1).value);
1765 	   g_tax_proration_flag := l_outputs(2).value;
1766        ELSE
1767 	   g_si_days := '-1';
1768 	   g_tax_proration_days := '-1';
1769 	   g_tax_proration_flag := 'X';
1770        END IF;
1771    ELSIF g_si_days_formula_exists = FALSE THEN
1772        g_si_days := '-1';
1773        g_tax_proration_days := '-1';
1774        g_tax_proration_flag := 'X';
1775    END IF;
1776    RETURN fnd_number.canonical_to_number(g_si_days);
1777 
1778 END get_override_si_days;
1779 
1780 -----------------------------------------------------------------------------------------------
1781 -- Function : get_tax_proration_days
1782 -- To get the number of days for tax proration by executing user formula
1783 -- Assignment Id,Date Earned, Business Group Id and Assignment action Id.
1784 -----------------------------------------------------------------------------------------------
1785 Function get_tax_proration_days
1786 	(       p_assignment_id 	IN 	NUMBER
1787 	       ,p_date_earned 		IN	DATE
1788 	       ,p_assignment_action_id 	IN 	NUMBER
1789 	       ,p_payroll_action_id 	IN 	NUMBER
1790 	       ,p_business_group_id 	IN 	NUMBER
1791 	)
1792 	 RETURN number IS
1793 l_override_si_days  varchar2(35);
1794 BEGIN
1795 	IF g_assignment_id = p_assignment_id THEN
1796 		RETURN fnd_number.canonical_to_number(g_tax_proration_days);
1797 	ELSE
1798 		l_override_si_days := get_override_si_days
1799 			(        p_assignment_id
1800 			        ,p_date_earned
1801 				,p_business_group_id
1802 				,p_assignment_action_id
1803 				,p_payroll_action_id
1804 			);
1805 		g_assignment_id := p_assignment_id;
1806 		RETURN fnd_number.canonical_to_number(g_tax_proration_days);
1807 	END IF;
1808 END get_tax_proration_days;
1809 
1810 -----------------------------------------------------------------------------------------------
1811 -- Function : get_tax_proration_flag
1812 -- To return the flag to determine whether proration is required or not by executing user formula
1813 -- Assignment Id,Date Earned, Business Group Id and Assignment action Id.
1814 -----------------------------------------------------------------------------------------------
1815 Function get_tax_proration_flag
1816 	(       p_assignment_id 	IN 	NUMBER
1817 	       ,p_date_earned 		IN	DATE
1818 	       ,p_assignment_action_id 	IN 	NUMBER
1819 	       ,p_payroll_action_id 	IN 	NUMBER
1820 	       ,p_business_group_id 	IN 	NUMBER
1821 	)
1822          RETURN varchar2 IS
1823 l_override_si_days  varchar2(35);
1824 
1825 l_element_type_id pay_element_types_f.element_type_id%TYPE;
1826 l_input_value_id pay_input_values_f.input_value_id%TYPE;
1827 l_prorate_flag pay_element_entry_values_f.screen_entry_value%TYPE;
1828 
1829 --6887820
1830 CURSOR ele_typ_id
1831 IS
1832 select element_type_id
1833 from pay_element_types_f
1834 where
1835 element_name = 'NL Tax and SI Proration Indicator'
1836 and p_date_earned between effective_start_date and effective_end_date
1837 and legislation_code = 'NL';
1838 
1839 CURSOR inp_val_id(p_element_type_id NUMBER)
1840 IS
1841 select input_value_id from pay_input_values_f
1842 where element_type_id = p_element_type_id
1843 and p_date_earned between effective_start_date and effective_end_date
1844 and legislation_code = 'NL';
1845 
1846 /* Cursor to get the override value of proration flag from
1847 seeded element "NL Tax and SI Proration Indicator" */
1848 
1849 CURSOR part_time_prorate_flag
1850 IS
1851 SELECT EEV.screen_entry_value
1852 FROM
1853         pay_element_entry_values_f               EEV,
1854         pay_element_entries_f                    EE,
1855         pay_link_input_values_f                  LIV,
1856         pay_input_values_f                       INPUTV
1857 WHERE   INPUTV.input_value_id                  = l_input_value_id
1858 AND     p_date_earned BETWEEN INPUTV.effective_start_date AND INPUTV.effective_end_date
1859 AND     INPUTV.element_type_id		     = l_element_type_id
1860 AND     LIV.input_value_id                     = INPUTV.input_value_id
1861 AND     p_date_earned BETWEEN LIV.effective_start_date AND LIV.effective_end_date
1862 AND     EEV.input_value_id                     = INPUTV.input_value_id
1863 AND     EEV.element_entry_id                   = EE.element_entry_id
1864 AND     EEV.effective_start_date               = EE.effective_start_date
1865 AND     EEV.effective_end_date                 = EE.effective_end_date
1866 AND     EE.element_link_id                     = LIV.element_link_id
1867 AND     EE.assignment_id                       = p_assignment_id
1868 AND     p_date_earned BETWEEN EE.effective_start_date AND EE.effective_end_date
1869 AND     nvl(EE.ENTRY_TYPE, 'E')                = 'E';
1870 --6887820
1871 BEGIN
1872 --6887820
1873 	OPEN ele_typ_id;
1874 	FETCH ele_typ_id into l_element_type_id;
1875 	CLOSE ele_typ_id;
1876 
1877 	OPEN inp_val_id(l_element_type_id);
1878 	FETCH inp_val_id INTO l_input_value_id;
1879 	CLOSE inp_val_id;
1880 
1881 	OPEN part_time_prorate_flag;
1882 	FETCH part_time_prorate_flag INTO l_prorate_flag;
1883 	CLOSE part_time_prorate_flag;
1884 --6887820
1885 
1886 	IF g_assignment_id = p_assignment_id THEN
1887 		--6887820
1888 		IF g_tax_proration_flag = 'X' THEN
1889 		  g_tax_proration_flag := NVL(l_prorate_flag,g_tax_proration_flag);
1890 		END IF;
1891 		--6887820
1892 		RETURN g_tax_proration_flag;
1893 	ELSE
1894 		l_override_si_days := get_override_si_days
1895 			(        p_assignment_id
1896 			        ,p_date_earned
1897 				,p_business_group_id
1898 				,p_assignment_action_id
1899 				,p_payroll_action_id
1900 			);
1901 		g_assignment_id := p_assignment_id;
1902 		--6887820
1903 		IF g_tax_proration_flag = 'X' THEN
1904 		  g_tax_proration_flag := NVL(l_prorate_flag,g_tax_proration_flag);
1905 		END IF;
1906 		--6887820
1907 		RETURN g_tax_proration_flag;
1908 	END IF;
1909 END get_tax_proration_flag;
1910 
1911 ---------------------------------------------------------------------------------------
1912 -- Function : get_tax_proration_cal_days
1913 -- To return number of Tax Days for proration based on calender days
1914 ---------------------------------------------------------------------------------------
1915 
1916 FUNCTION get_tax_proration_cal_days
1917 	(	p_assignment_id		IN	NUMBER
1918                 ,p_period_start_date	IN	DATE
1919                 ,p_period_end_date	IN	DATE
1920                 ,p_proration_start_date IN	DATE
1921                 ,p_proration_end_date	IN	DATE
1922         )
1923         RETURN NUMBER IS
1924 CURSOR csr_asg_dates (p_other_assignment_id NUMBER) IS
1925        SELECT MIN(asg.effective_start_date) asg_start_date
1926               ,MAX(asg.effective_end_date) asg_end_date
1927        FROM PER_ASSIGNMENTS_F asg
1928             ,PER_ASSIGNMENT_STATUS_TYPES past
1929        WHERE asg.assignment_id = p_other_assignment_id
1930        AND   past.per_system_status = 'ACTIVE_ASSIGN'
1931        AND   asg.assignment_status_type_id = past.assignment_status_type_id
1932        AND   asg.effective_start_date <= p_period_end_date
1933        AND   NVL(asg.effective_end_date,p_period_end_date) >= p_period_start_date;
1934 
1935 CURSOR csr_any_other_asg IS
1936        SELECT DISTINCT asg1.assignment_id asgid
1937        FROM per_assignments_f asg1
1938             ,per_assignments_f asg2
1939             ,pay_object_groups pog1
1940             ,pay_object_groups pog2
1941        WHERE asg1.person_id = asg2.person_id
1942        AND   asg2.assignment_id = p_assignment_id
1943        AND   asg1.assignment_id <> p_assignment_id
1944        AND   pog1.source_id = asg1.assignment_id
1945        AND   pog1.source_type = 'PAF'
1946        AND   pog2.source_id = asg2.assignment_id
1947        AND   pog2.source_type = 'PAF'
1948        AND   pog1.parent_object_group_id = pog2.parent_object_group_id;
1949 
1950 
1951 CURSOR csr_person_dates IS
1952        SELECT MIN(asg.effective_start_date) per_start_date
1953               ,MAX(asg.effective_end_date) per_end_date
1954        FROM PER_ASSIGNMENTS_F asg,
1955             PER_ASSIGNMENT_STATUS_TYPES past,
1956             PAY_OBJECT_GROUPS pog
1957        WHERE asg.person_id in
1958        (select asg2.person_id from PER_ASSIGNMENTS_F asg2, PAY_OBJECT_GROUPS pog2
1959        where asg2.assignment_id = p_assignment_id
1960        and pog2.source_id = asg2.assignment_id
1961        and pog2.source_type = 'PAF'
1962        and pog.parent_object_group_id = pog2.parent_object_group_id)
1963        AND   past.per_system_status = 'ACTIVE_ASSIGN'
1964        AND   asg.assignment_status_type_id = past.assignment_status_type_id
1965        AND   asg.effective_start_date <= p_period_end_date
1966        AND   NVL(asg.effective_end_date,p_period_end_date) >= p_period_start_date
1967        AND   pog.source_id = asg.assignment_id
1968        AND   pog.source_type = 'PAF';
1969 
1970 
1971 l_proration_start_date DATE;
1972 l_proration_end_date DATE;
1973 other_asg_start_date DATE;
1974 other_asg_end_date DATE;
1975 l_other_asg_start_date DATE;
1976 l_other_asg_end_date DATE;
1977 proration_days NUMBER := 0;
1978 overlap_with_main VARCHAR2(10);
1979 other_asg_no NUMBER := 0;
1980 l_other_asg1_start_date DATE;
1981 l_other_asg1_end_date DATE;
1982 l_other_asg2_start_date DATE;
1983 l_other_asg2_end_date DATE;
1984 
1985 l_per_start_date DATE;
1986 l_per_end_date   DATE;
1987 
1988 
1989 BEGIN
1990 
1991    l_proration_start_date := p_proration_start_date;
1992    l_proration_end_date := p_proration_end_date;
1993 
1994    /* loop for other assignments for the employee */
1995    FOR c1rec IN csr_any_other_asg LOOP
1996     OPEN csr_asg_dates(c1rec.asgid);
1997     FETCH csr_asg_dates INTO l_other_asg_start_date, l_other_asg_end_date;
1998     CLOSE csr_asg_dates;
1999 
2000     /* If other assignment of the employee is active in the payroll period calculate working days using daily table */
2001     IF l_other_asg_start_date IS NOT NULL AND l_other_asg_end_date IS NOT NULL THEN
2002         other_asg_no := other_asg_no + 1;
2003         other_asg_start_date := GREATEST(p_period_start_date, l_other_asg_start_date);
2004         other_asg_end_date := LEAST(p_period_end_date, l_other_asg_end_date);
2005         IF other_asg_no = 1 THEN
2006            l_other_asg1_start_date := other_asg_start_date;
2007            l_other_asg1_end_date := other_asg_end_date;
2008         END IF;
2009         IF other_asg_no = 2 THEN
2010            l_other_asg2_start_date := other_asg_start_date;
2011            l_other_asg2_end_date := other_asg_end_date;
2012         END IF;
2013         IF other_asg_start_date < l_proration_start_date THEN
2014             IF other_asg_end_date < l_proration_start_date - 1 THEN
2015                 IF other_asg_no = 1 THEN
2016                     overlap_with_main := 'N';
2017                 END IF;
2018                 proration_days := proration_days + (other_asg_end_date - other_asg_start_date) + 1;
2019              ELSE
2020                 l_proration_start_date := other_asg_start_date;
2021              END IF;
2022         END IF;
2023 
2024         IF other_asg_end_date > l_proration_end_date THEN
2025             IF other_asg_start_date > l_proration_end_date + 1 THEN
2026                 IF other_asg_no = 1 THEN
2027                     overlap_with_main := 'N';
2028                 END IF;
2029                 proration_days := proration_days + (other_asg_end_date - other_asg_start_date) + 1;
2030             ELSE
2031                 l_proration_end_date := other_asg_end_date;
2032             END IF;
2033         END IF;
2034     END IF;
2035   END LOOP;
2036 
2037   /* If there are one or more days in the payroll period having no active assignments, then use daily table only*/
2038   IF l_proration_start_date = p_period_start_date and l_proration_end_date = p_period_end_date THEN
2039     proration_days := (p_period_end_date - p_period_start_date) + 1;
2040     RETURN proration_days;
2041   END IF;
2042   proration_days := proration_days + (l_proration_end_date - l_proration_start_date) + 1;
2043 
2044   /* Remove overlaps between the first other assignment and second other assignment, if any */
2045   IF other_asg_no = 2 AND overlap_with_main = 'N' THEN
2046     IF l_other_asg2_start_date BETWEEN l_other_asg1_start_date AND l_other_asg1_end_date THEN
2047         proration_days := proration_days - (LEAST(l_other_asg2_end_date, l_other_asg1_end_date) - l_other_asg2_start_date);
2048     ELSIF l_other_asg2_end_date BETWEEN l_other_asg1_start_date and l_other_asg1_end_date THEN
2049         proration_days := proration_days - (l_other_asg2_end_date - l_other_asg1_start_date);
2050     ELSIF l_other_asg1_start_date BETWEEN l_other_asg2_start_date AND l_other_asg2_end_date THEN
2051         proration_days := proration_days - (l_other_asg1_end_date - l_other_asg1_start_date);
2052     END IF;
2053   END IF;
2054 
2055   /*For more than 3 active assignments, proration days are returned with assumption that person
2056   is active for every day in the payroll period. Otherwise user feeds the days manually */
2057   IF other_asg_no > 2 THEN
2058     OPEN csr_person_dates;
2059     FETCH csr_person_dates INTO l_per_start_date, l_per_end_date;
2060     CLOSE csr_person_dates;
2061     l_per_start_date := GREATEST(p_period_start_date, l_per_start_date);
2062     l_per_end_date := LEAST(p_period_end_date, l_per_end_date);
2063     proration_days := (l_per_end_date - l_per_start_date) + 1;
2064   END IF;
2065 RETURN proration_days;
2066 END get_tax_proration_cal_days;
2067 
2068 END pay_nl_si_pkg;