DBA Data[Home] [Help]

PACKAGE BODY: APPS.PAY_SG_DEDUCTIONS

Source


1 PACKAGE BODY pay_sg_deductions AS
2 /*  $Header: pysgdedn.pkb 120.24 2011/08/25 05:09:44 jalin ship $
3 **
4 **  Copyright (c) 2002 Oracle Corporation
5 **  All Rights Reserved
6 **
7 **  Procedures and functions used in SG deduction formula
8 **
9 **  Change List
10 **  ===========
11 **
12 **  Date        Author   Reference    Bug Number        Description
13 **  =========== ======== =========    ==========	=====================
14 **  26 Jun 2000 makelly  115.0     			Initial
15 **  6  Apr 2002 Ragovind 115.4     			Added Sg_get_Prorator function
16 **  10 Apr 2002 Ragovind 115.6     			Modified the sg_get_prorator function.
17 **  10 apr 2002 Ragovind 115.7     			Added comments to sg_get_prorator about functionality of CPF Proration calculation.
18 **  28 Jun 2002 SRussell 115.9     			Added CPF Retropay functions.
19 **  26 Jul 2002 SRussell 115.10    			Changed exception clause and Table order.
20 **  06 Aug 2002 Kaverma  115.11       2494173		modified sg_get_prorator function(Bug No - 2494173).
21 **  07 Aug 2002 Kaverma  115.12    			Modified fwl_amount function
22 **  02 Sep 2002 Ragoivnd 115.13    			Added Function get_prev_year_ord_ytd
23 **  19 Sep 2002 Ragovind 115.14    			Modified the cursor c_tax_unit_id
24 **  04 Oct 2002 vgsriniv 115.15    			Modified fwl_amount function
25 **  17 Oct 2002 apunekar 115.16    			Modified cursor c_get_dates to add distinct clause
26 **  17 Oct 2002 apunekar 115.17    			Added comments
27 **  06 Nov 2002 Ragovind 115.18    			Modified the cursor c_get_per_start_end_dates for CPF Calculation
28 **  11 Dec 2002 Apunekar 115.19    			Added nocopy to out or in out parameters
29 **  20 Dec 2002 Ragovind 115.20       2475324		Added CPF Report Coding.
30 **  29 Jan 2002 JLin     115.21       2772106		Modified cursor c_get_per_start_end_dates
31 **  11 Feb 2003 Ragovind 115.22       2796093   	Modified the CPF Report code for Correct CPF for Terminated Employees.
32 **  19 Mar 2003 Ragovind 115.23       2858065  		Corrected CPF prorator factor for Termination and Rehire employee in the same month
33 **  27 Mar 2003 Ragovind 115.24       2873083 	 	Corrected CPF prorator factor for Term/Rehire in same month and run Quickpay for the
34 **                                 			Terminated Employee Assignment.
35 **  02 Jan 2004 Nanuradh 115.25       3331018  		Removed the cursor c_get_prev_ord_ytd, instead used
36 **                                 			pay_balance.get_value to get prev year ordinary earnings ytd value.
37 **  02 Jan 2004 Nanuradh 115.26       3331018  		Modified the function get_prev_year_ord_ytd by initializing the
38 **                                 			variable l_prev_ord_ytd to zerio.
39 **  21 Jan 2004 agore    115.27       3279235 		Modified the function get_prev_year_ord_ytd ( ) to refer monthly balance
40 **                                 			values of following balances to arrive at Annual CPF eligible OW with monthly ceiling
41 **                                 			of 5500.CPF_ORDINARY_EARNINGS_ELIGIBLE_COMP, ORDINARY_EARNINGS_INELIGIBLE_FOR_CPF
42 **                                 			and RETRO_ORD_RETRO_PERIOD
43 **                                 			Added new functions get_cur_year_ord_ytd ( ) and get_retro_earnings( )
44 **  18 May 2004 Nanuradh 115.28       3595103 		Added new function spl_amount( ) to calculate S Pass Levy for permit type SP.
45 **  18 May 2004 Nanuradh 115.32       3595103 		Modified function sg_get_prorator() for permit type 'SP'
46 **  24 Jun 2004 abhargav 115.35        			Undo the changes of the Bug#3677801
47 **  31 Jan 2005 snimmala 115.36       4149190		Modified the function sg_get_prorator() to calculate total days as number of
48 **							working days instead of days in the payroll period.
49 **  27 Jun 2005 JLin     115.37       4267196           Performance issue, modified the function get_prev_year_ord_ytd
50 **                                                      and get_cur_year_ord_ytd to replace ppa.date_earned with ppa.effective_date
51 **  09 Jun 2006 JLin     115.39       5298298           Modified the function
52 **                                                      get_prev_year_ord_ytd and
53 **                                                      get_cur_year_ord_ytd to
54 **                                                      include all assignments.
55 **                                                      (eg.,rehire to include original assignment)
56 **  13 Jun 2006 JLin     115.40       5298298           To include the Legal Entity
57 **                                                      check for previous fix
58 **  14 Jun 2006 JLin     115.41,42    5298298           To include the multi-assignments
59 **  23 Jun 2006 snimmala 115.43       5353558           Modified the sql query of the cursor get_retro_method
60 **                                                      in the function which_retro_method.
61 **  27 Jun 2006 snimmala 115.44       5353558           Removed the check for 'Information' classification
62 **                                                      in the function which_retro_method.
63 **  14 Sep 2006 snimmala 115.45       5410589           Function fwl_amount() has been modified to check whether
64 **                                                      permit category is valid for pay period or not.
65 **  21 May 2007 snimmala 115.46       6046808           Modified the cursor c_get_dates in the function fwl_amount
66 **                                                      to move order by clause to outer query.
67 **  02 Jul 2007 jalin    115.47       6158284           Modified the cursor c_get_dates in the function fwl_amount
68 **                                                      to add currect employee check
69 ** 22 Feb 2008  jalin    115.48       6815874           Modified calling function
70 **                                                      get_retro_earnings to use
71 **                                                      l_effective as parameter
72 **                                                      Modified cursor c_pay_element_entries
73 **                                                      to get correct retro values
74 **                                                      Removed parameter ass_act_id from get_retro_earnings function
75 ** 27 Mar 2008  jalin    115.49       6815874           Added fix if retro ord
76 **                                                      is neg
77 ** 12-Mar-2009  vaisriva 115.50       7661439           Added code for the new balance 'Ordinary Earnings Ineligible
78 **                                                      For CPF Calc'
79 ** 25-May-2010  jalin    115.51       9538644           Modified code for spl_amount
80 **                                                      to work S PASS categories
81 **                                                      and,the daily rate gets from roundup monthly rate/30
82 ** 24-Nov-2010  jalin    115.53       9112449           Proration changes for
83 **                                                      calendars days or working/custom days
84 ** 30-Nov-2010  jalin    115.54,55    9112449           Removed checkfile equivalence syntax
85 ** 09-Dec-2010  dduvvuri 115.56       10381772          Changed SG_CPF_CAL_METHOD to CPF_CAL_METHOD in Function sg_get_prorator
86 ** 01-Mar-2011  jalin    115.57       11815978          Removed proration for new hire and terminated employee
87 ** 31-Mar-2011  scireddy 115.58       11880310 		Modified the FWL daily rate calculation logic in fwl_amount() and spl_amount()
88 							functions.
89 ** 02-Jun-2011  jalin    115.59,60    12564506      Modified cancel date -1 in fwl_amount() and spl_amount()
90 ** 14-Jul-2011  jalin    115.61       12639110      Modified function get_prev_year_ord_ytd and get_prev_year_ord_ytd to get the correct ORD ceiling for the month
91 ** 24-Aug-2011  jalin    115.62       12885297      Modified function get_prev_year_ord_ytd and get_prev_year_ord_ytd to not minus balance Ordinary Earnings Ineligible For CPF Calc
92 
93 **  ============== Formula Fuctions ====================
94 **  Package containing addition processing required by
95 **  formula in SG localisation
96 */
97 
98 /*
99 **  fwl_amount - returns the amount of foreign workers levy
100 **  due in a month
101 **
102 **  Error return codes used - messages raised in fast formula
103 **
104 **  -77  Invalid dates used for Work Permit
105 **  -88  Work Permit Category is null
106 **  -99  Unhandled Exception
107 */
108 
109 function  fwl_amount ( p_business_group_id in     number
110                      , p_date_earned       in     date
111                      , p_assignment_id     in     number
112                      , p_start_date        in     date
113                      , p_end_date          in     date   )
114           return number is
115 
116 
117 TYPE t_permit_dates_rec is record   (  permit_category  varchar2(60)
118                                      , date_start       date
119                                      , date_end         date
120                                      , date_cancel      date
121                                      , effective_start_date date) ;
122 
123 TYPE t_permit_dates_tab is table of t_permit_dates_rec index by binary_integer ;
124 
125 l_permit              t_permit_dates_tab;
126 l_counter             number;
127 l_amt                 number              := 0;
128 l_mth_amt             number;
129 l_dly_amt             number;
130 l_days                number              := 0;
131 l_tot_days            number              := 0;
132 l_max_days            number              := 0;
133 l_category            varchar2(60);
134 l_same_category       boolean             := TRUE;
135 l_sot                 date;
136 l_eot                 date;
137 l_proc                varchar2(60);
138 l_start		      date;
139 l_end		      date;
140 l_months	      number;
141 l_value               number;
142 
143 /*Bug#2626075-Distinct added in c_get_dates cursor*/
144 /*Bug#6046808 - Moved Order By clause to Outer Query */
145 /*Bug#6158284 - Added current employee flag check */
146 
147 cursor c_get_dates       (  p_assignment_id NUMBER
148                           , p_start_date    DATE
149                           , p_end_date      DATE   ) is
150 select distinct * from
151 (
152 select per_information8
153      , to_date(per_information9,  'YYYY/MM/DD HH24:MI:SS')
154      , to_date(per_information10, 'YYYY/MM/DD HH24:MI:SS')
155      , to_date(per_information11, 'YYYY/MM/DD HH24:MI:SS')
156      , effective_start_date
157   from per_all_people_f        per
158  where per.person_id = (select max(paf.person_id)
159                           from per_all_assignments_f paf
160                          where paf.assignment_id = p_assignment_id)
161    and per.per_information6 = 'WP'
162    and per.per_information8 not like 'SP%'
163    and nvl(per.current_employee_flag,'N') = 'Y' /* Bug 6158284 */
164    and per.effective_start_date <= p_end_date
165    and per.effective_end_date   >= p_start_date)
166    order by effective_start_date;
167 
168 /*Bug#5410589 - Following cursor has been added to check whether permit category is valid
169                 for this pay period or not*/
170 
171 cursor c_check_permit_type(p_permit_category  per_all_people_f.per_information8%type
172                           ,p_date_earned DATE)
173 is
174 select CINST.value
175 from   pay_user_tables                    tab
176       ,pay_user_columns                   col
177       ,pay_user_rows_f                    r
178       ,pay_user_column_instances_f        cinst
179 where  tab.user_table_name = 'FWL_RATES'
180 and    col.user_table_id   = tab.user_table_id
181 and    upper(col.user_column_name)= upper('Monthly Rate')
182 and    cinst.user_column_id = col.user_column_id
183 and    r.user_table_id = tab.user_table_id
184 and    r.ROW_LOW_RANGE_OR_NAME = p_permit_category
185 and    cinst.user_row_id = r.user_row_id
186 and    p_date_earned between cinst.effective_start_date and cinst.effective_end_date;
187 
188 begin
189   l_sot    := to_date('0001/01/01 00:00:00', 'YYYY/MM/DD HH24:MI:SS');
190   l_eot    := to_date('4712/12/31 00:00:00', 'YYYY/MM/DD HH24:MI:SS');
191   l_proc   := 'pay_sg_deductions.fwl_amount';
192 
193 
194   hr_utility.set_location('Entering : '||l_proc, 5);
195 
196   l_counter := 1;
197 
198   open c_get_dates( p_assignment_id, p_start_date, p_end_date) ;
199   fetch c_get_dates into l_permit(l_counter);
200   if c_get_dates%notfound then
201     hr_utility.set_location('Leaving - No fwl in month : '||l_proc, 10);
202     return 0;
203   end if;
204 
205   l_counter := l_counter + 1;
206 
207   fetch c_get_dates into l_permit(l_counter);
208 
209   while c_get_dates%found loop
210     l_counter := l_counter + 1;
211     fetch c_get_dates into l_permit(l_counter);
212   end loop;
213 
214   close c_get_dates;
215 
216   /* Bug 12564506, use cancel date -1 instead of cancel date */
217 
218     l_max_days := least (nvl(l_permit(l_permit.last).date_end, l_eot), nvl(l_permit(l_permit.last).date_cancel-1, l_eot)) -  p_start_date + 1;
219   l_category := l_permit(1).permit_category;
220 
221   if l_category is not null then
222     /*Bug#5410589 */
223     open c_check_permit_type(l_category,p_date_earned);
224     fetch c_check_permit_type into l_value;
225     if c_check_permit_type%notfound then
226          return(-66);
227     end if;
228     close c_check_permit_type;
229 
230     l_mth_amt := to_number(hruserdt.get_table_value (p_bus_group_id   => p_business_group_id
231                                                     ,p_table_name     => 'FWL_RATES'
232                                                     ,p_col_name       => 'Monthly Rate'
233                                                     ,p_row_value      => l_category
234                                                     ,p_effective_date => p_date_earned ));
235 
236 	/* Bug-11880310 : l_dly_amt calculation logic is changed as per requirement */
237     If ( p_date_earned >= to_date('2011/01/01 00:00:00', 'YYYY/MM/DD HH24:MI:SS')) then
238       l_dly_amt := fffunc.round_up(l_mth_amt*12/365,2);
239     else
240       l_dly_amt := fffunc.round_up(l_mth_amt/30,0);
241     end if;
242 
243   end if;
244 
245 
246   /* Bug 12564506, use cancel date -1 instead of cancel date */
247   FOR i in 1..l_permit.last LOOP
248 
249     if l_permit(i).permit_category is null then
250 
251         hr_utility.set_location('Error - WP Category is null : '||l_proc, 88);
252         return (-88);
253 
254     else
255 
256       if      (l_permit(i).date_start  > l_permit(i).date_end)
257            OR (l_permit(i).date_start  > l_permit(i).date_cancel-1) THEN
258 
259         hr_utility.set_location('Invalid Date Ranges Within Month: '||l_proc, 77);
260         return (-77);
261 
262 
263       elsif (l_permit(i).date_start  > p_end_date  )
264            OR (l_permit(i).date_end    < p_start_date)
265            OR (l_permit(i).date_cancel-1 < p_start_date) THEN
266 
267         null;
268 
269       else
270         /*Bug#5410589 */
271         open c_check_permit_type(l_permit(i).permit_category,p_date_earned);
272         fetch c_check_permit_type into l_value;
273         if c_check_permit_type%notfound then
274            return(-66);
275         end if;
276         close c_check_permit_type;
277 
278         if l_permit(i).permit_category <> l_category then
279 
280           l_same_category := FALSE;
281 
282         end if;
283         l_start := greatest (nvl(l_permit(i).date_start, l_sot), p_start_date);
284         l_end := least (nvl(l_permit(i).date_end, l_eot), nvl(l_permit(i).date_cancel-1, l_eot));
285         /* Bug 2610156 : Least of l_end and Pay Period end date should be
286            used to calculate number of days(i.e., l_days)
287            l_end is the least of expiry date and cancellation date */
288         l_end := least(l_end,p_end_date);
289 
290         l_days := greatest ((l_end - l_start)+1, 0 );
291         l_months := round(months_between(l_end + 1,l_start),2);
292 
293 
294         l_days := greatest ((l_end - l_start)+1, 0 );
295 
296         l_tot_days := l_tot_days + l_days;
297 
298 
299         if l_tot_days > l_max_days then
300 
301           hr_utility.set_location('Invalid Date Ranges Within Month : '||l_proc, 77);
302           return (-77);
303 
304         end if;
305 
306         if l_same_category then
307           if l_months >= 1 then
308             l_amt := l_mth_amt;
309           else
310             l_amt := least(l_mth_amt, (l_amt + (l_dly_amt * l_days)));
311           end if;
312 
313         else
314 
315           l_mth_amt  := to_number(hruserdt.get_table_value (p_bus_group_id   => p_business_group_id
316                                                            ,p_table_name     => 'FWL_RATES'
317                                                            ,p_col_name       => 'Monthly Rate'
318                                                            ,p_row_value      => l_permit(i).permit_category
319                                                            ,p_effective_date => p_date_earned ));
320 
321    	 /* Bug-11880310 : l_dly_amt calculation logic is changed as per requirement */
322     	If ( p_date_earned >= to_date('2011/01/01 00:00:00', 'YYYY/MM/DD HH24:MI:SS')) then
323     	  l_dly_amt := fffunc.round_up(l_mth_amt*12/365,2);
324    	 else
325    	   l_dly_amt := fffunc.round_up(l_mth_amt/30,0);
326   	end if;
327 
328 	  if l_months >= 1 then
329 	    l_amt := l_mth_amt;
330 	  else
331             l_amt := l_amt + least(l_mth_amt, (l_dly_amt * l_days));
332           end if;
333 
334         end if;
335 
336       end if;
337 
338     end if;
339 
340   END LOOP;
341 
342   hr_utility.set_location('Leaving:'||l_proc, 20);
343   return l_amt;
344 
345   EXCEPTION
346        WHEN others THEN
347          hr_utility.set_location('Unhandled Exception in function call fwl_amount : '||l_proc, 99);
348          RETURN -99;
349 
350 end fwl_amount;
351 
352 function  spl_amount ( p_business_group_id in     number
353                      , p_date_earned       in     date
354                      , p_assignment_id     in     number
355                      , p_start_date        in     date
356                      , p_end_date          in     date   )
357           return number is
358 
359 TYPE t_permit_dates_rec is record   (  permit_category  varchar2(60)
360                                      , date_start       date
361                                      , date_end         date
362                                      , date_cancel      date
363                                      , effective_start_date date) ;
364 
365 TYPE t_permit_dates_tab is table of t_permit_dates_rec index by binary_integer ;
366 
367 l_permit              t_permit_dates_tab;
368 l_counter             number;
369 l_amt                 number              := 0;
370 l_mth_amt             number;
371 l_dly_amt             number;
372 l_days                number              := 0;
373 l_tot_days            number              := 0;
374 l_max_days            number              := 0;
375 l_category            varchar2(60);
376 l_same_category       boolean             := TRUE;
377 l_sot                 date;
378 l_eot                 date;
379 l_proc                varchar2(60);
380 l_start           date;
381 l_end             date;
382 l_months          number;
383 l_value               number;
384 
385 cursor c_get_dates       (  p_assignment_id NUMBER
386                           , p_start_date    DATE
387                           , p_end_date      DATE   ) is
388 select distinct * from
389 (
390 select nvl(per_information8,'SP')
391      , to_date(per_information9,  'YYYY/MM/DD HH24:MI:SS')
392      , to_date(per_information10, 'YYYY/MM/DD HH24:MI:SS')
393      , to_date(per_information11, 'YYYY/MM/DD HH24:MI:SS')
394      , effective_start_date
395   from per_all_people_f        per
396  where per.person_id = (select max(paf.person_id)
397                           from per_all_assignments_f paf
398                          where paf.assignment_id = p_assignment_id)
399    and per.per_information6 = 'SP'
400    and nvl(per.current_employee_flag,'N') = 'Y' /* Bug 6158284 */
401    and per.effective_start_date <= p_end_date
402    and per.effective_end_date   >= p_start_date)
403    order by effective_start_date;
404 
405 cursor c_check_permit_type(p_permit_category  per_all_people_f.per_information8%type
406                           ,p_date_earned DATE)
407 is
408 select CINST.value
409 from   pay_user_tables                    tab
410       ,pay_user_columns                   col
411       ,pay_user_rows_f                    r
412       ,pay_user_column_instances_f        cinst
413 where  tab.user_table_name = 'FWL_RATES'
414 and    col.user_table_id   = tab.user_table_id
415 and    upper(col.user_column_name)= upper('Monthly Rate')
416 and    cinst.user_column_id = col.user_column_id
417 and    r.user_table_id = tab.user_table_id
418 and    r.ROW_LOW_RANGE_OR_NAME = p_permit_category
419 and    cinst.user_row_id = r.user_row_id
420 and    p_date_earned between cinst.effective_start_date and cinst.effective_end_date;
421 
422 
423 begin
424   l_sot    := to_date('0001/01/01 00:00:00', 'YYYY/MM/DD HH24:MI:SS');
425   l_eot    := to_date('4712/12/31 00:00:00', 'YYYY/MM/DD HH24:MI:SS');
426   l_proc   := 'pay_sg_deductions.spl_amount';
427 
428 
429   hr_utility.set_location('Entering : '||l_proc, 5);
430 
431   l_counter := 1;
432 
433   open c_get_dates( p_assignment_id, p_start_date, p_end_date) ;
434   fetch c_get_dates into l_permit(l_counter);
435   if c_get_dates%notfound then
436     hr_utility.set_location('Leaving - No spl in month : '||l_proc, 10);
437     return 0;
438   end if;
439 
440   l_counter := l_counter + 1;
441 
442   fetch c_get_dates into l_permit(l_counter);
443 
444   while c_get_dates%found loop
445     l_counter := l_counter + 1;
446     fetch c_get_dates into l_permit(l_counter);
447   end loop;
448 
449   close c_get_dates;
450 
451   /* Bug 12564506, use cancel date -1 instead of cancel date */
452     l_max_days := least (nvl(l_permit(l_permit.last).date_end, l_eot), nvl(l_permit(l_permit.last).date_cancel-1, l_eot)) -  p_start_date + 1;
453   l_category := l_permit(1).permit_category;
454 
455   if l_category is not null then
456     /*Bug#5410589 */
457     open c_check_permit_type(l_category,p_date_earned);
458     fetch c_check_permit_type into l_value;
459     if c_check_permit_type%notfound then
460          return(-66);
461     end if;
462     close c_check_permit_type;
463 
464     l_mth_amt := to_number(hruserdt.get_table_value (p_bus_group_id   => p_business_group_id
465                                                     ,p_table_name     => 'FWL_RATES'
466                                                     ,p_col_name       => 'Monthly Rate'
467                                                     ,p_row_value      => l_category
468                                                     ,p_effective_date => p_date_earned ));
469 
470     /* Bug-11880310 : l_dly_amt calculation logic is changed as per requirement */
471     If ( p_date_earned >= to_date('2011/01/01 00:00:00', 'YYYY/MM/DD HH24:MI:SS')) then
472       l_dly_amt := fffunc.round_up(l_mth_amt*12/365,2);
473     else
474       l_dly_amt := fffunc.round_up(l_mth_amt/30,0);
475     end if;
476 
477   end if;
478 
479   /* Bug 12564506, use cancel date -1 instead of cancel date */
480   FOR i in 1..l_permit.last LOOP
481 
482     if l_permit(i).permit_category is null then
483 
484         hr_utility.set_location('Error - SP Category is null : '||l_proc, 88);
485         return (-88);
486 
487     else
488 
489       if      (l_permit(i).date_start  > l_permit(i).date_end)
490            OR (l_permit(i).date_start  > l_permit(i).date_cancel-1) THEN
491 
492         hr_utility.set_location('Invalid Date Ranges Within Month: '||l_proc, 77);
493         return (-77);
494 
495 
496       elsif (l_permit(i).date_start  > p_end_date  )
497            OR (l_permit(i).date_end    < p_start_date)
498            OR (l_permit(i).date_cancel-1 < p_start_date) THEN
499 
500         null;
501 
502       else
503         /*Bug#5410589 */
504         open c_check_permit_type(l_permit(i).permit_category,p_date_earned);
505         fetch c_check_permit_type into l_value;
506         if c_check_permit_type%notfound then
507            return(-66);
508         end if;
509         close c_check_permit_type;
510 
511         if l_permit(i).permit_category <> l_category then
512 
513           l_same_category := FALSE;
514 
515         end if;
516         l_start := greatest (nvl(l_permit(i).date_start, l_sot), p_start_date);
517 
518         l_end := least (nvl(l_permit(i).date_end, l_eot), nvl(l_permit(i).date_cancel-1, l_eot));
519         /* Bug 2610156 : Least of l_end and Pay Period end date should be
520            used to calculate number of days(i.e., l_days)
521            l_end is the least of expiry date and cancellation date */
522         l_end := least(l_end,p_end_date);
523 
524         l_days := greatest ((l_end - l_start)+1, 0 );
525         l_months := round(months_between(l_end + 1,l_start),2);
526 
527 
528         l_days := greatest ((l_end - l_start)+1, 0 );
529 
530         l_tot_days := l_tot_days + l_days;
531 
532 
533         if l_tot_days > l_max_days then
534 
535           hr_utility.set_location('Invalid Date Ranges Within Month : '||l_proc, 77);
536           return (-77);
537 
538         end if;
539 
540         if l_same_category then
541           if l_months >= 1 then
542             l_amt := l_mth_amt;
543           else
544             l_amt := least(l_mth_amt, (l_amt + (l_dly_amt * l_days)));
545           end if;
546 
547         else
548 
549           l_mth_amt  := to_number(hruserdt.get_table_value (p_bus_group_id   => p_business_group_id
550                                                            ,p_table_name     => 'FWL_RATES'
551                                                            ,p_col_name       => 'Monthly Rate'
552                                                            ,p_row_value      => l_permit(i).permit_category
553                                                            ,p_effective_date => p_date_earned ));
554 
555           /* Bug-11880310 : l_dly_amt calculation logic is changed as per requirement */
556     	If ( p_date_earned >= to_date('2011/01/01 00:00:00', 'YYYY/MM/DD HH24:MI:SS')) then
557        	  l_dly_amt := fffunc.round_up(l_mth_amt*12/365,2);
558     	else
559     	  l_dly_amt := fffunc.round_up(l_mth_amt/30,0);
560     	end if;
561 
562       if l_months >= 1 then
563         l_amt := l_mth_amt;
564       else
565             l_amt := l_amt + least(l_mth_amt, (l_dly_amt * l_days));
566           end if;
567 
568         end if;
569 
570       end if;
571 
572     end if;
573 
574   END LOOP;
575 
576 
577   hr_utility.set_location('Leaving:'||l_proc, 20);
578   return l_amt;
579 
580   EXCEPTION
581        WHEN others THEN
582          hr_utility.set_location('Unhandled Exception in function call spl_amount : '||l_proc, 99);
583          RETURN -99;
584 
585 end spl_amount;
586 
587 function sg_get_prorator   ( p_assignment_id       in  number,
588                              p_date_earned         in  date,
589                              p_pay_proc_start_date in  date,
590                              p_pay_proc_end_date   in  date,
591                              p_wac		   in  varchar2,
592                              p_cpf_pro_method      in  varchar2,
593                              p_cpf_calc_type       out nocopy varchar2
594                            ) return number is
595 
596 l_wac             varchar2(2);
597 l_effective_date  date;
598 start_date        date;
599 start_wac         varchar2(2);
600 prorate_date      date;
601 prorate_wac       varchar2(2);
602 l_prorator        number;
603 l_days            number;
604 l_total_days      number;
605 l_assign_start_date date;
606 l_assign_end_date   date;
607 l_proc_start_date   date;
608 l_proc_end_date     date;
609 l_emp_start_bet_period varchar2(1);
610 l_emp_end_bet_period   varchar2(1);
611 l_proc            varchar2(60);
612 
613 /* Cursor declaration */
614 cursor c_get_per_start_end_dates (c_assignment_id       number ,
615                               c_pay_proc_start_date date,
616                               c_pay_proc_end_date   date)
617        is
618        select min(pap.effective_start_date),max(pap.effective_end_date) /*bug 2772106 */
619          from per_all_people_f pap,
620               per_all_assignments_f target
621         where target.assignment_id = c_assignment_id
622           and pap.person_id = target.person_id
623           and nvl(pap.current_employee_flag,'N') = 'Y';
624 
625 cursor c_get_wac ( c_assignment_id       NUMBER,
626                    c_date                DATE )
627        is
628        select target.PER_INFORMATION6,
629               target.EFFECTIVE_START_DATE
630          from per_all_people_f               target
631         where target.person_id = (select paf.person_id
632                                     from per_all_assignments_f paf
633                                    where paf.assignment_id = c_assignment_id
634                                      and c_date between paf.effective_start_date and paf.effective_end_date )
635           and c_date between target.effective_start_date and target.effective_end_date;
636 
637 /* Bug 9112449, added function to get working days/custom days from CPF_CAL_METHOD formula */
638 cursor c_get_pro_formula_id (c_formula_name ff_formulas_f.formula_name%type,
639                              c_date         DATE)
640        is
641        select formula_id
642          from ff_formulas_f
643         where formula_name like c_formula_name
644           and c_date between effective_start_date and effective_end_date
645           and (business_group_id is not null or legislation_code = 'SG');
646 
647 l_pro_formula_id  ff_formulas_f.formula_id%type;
648 l_pro_check   varchar2(1);
649 
650 l_inputs  ff_exec.inputs_t;
651 l_outputs ff_exec.outputs_t;
652 
653 begin
654   l_prorator  := -1.0;
655   l_emp_start_bet_period  := 'N';
656   l_emp_end_bet_period    := 'N';
657   l_proc      := 'pay_sg_deductions.sg_get_prorator';
658 
659  /* Get the WAC effective at start of the pay period */
660   hr_utility.set_location('Entering : '||l_proc, 5);
661   hr_utility.trace('p_assignment_id : '||p_assignment_id);
662   hr_utility.trace('p_pay_proc_start_date : '||p_pay_proc_start_date );
663   hr_utility.trace('p_pay_proc_end_date   : '||p_pay_proc_end_date   );
664   hr_utility.trace('p_date_earned         : '||p_date_earned         );
665   hr_utility.trace('p_wac                 : '||p_wac);
666   hr_utility.trace('p_cpf_pro_method      : '||p_cpf_pro_method      );
667 
668   p_cpf_calc_type  := p_wac ; /* assign the default value of WAC for the person as WAC exist at period end date */
669 
670   open c_get_per_start_end_dates(p_assignment_id , p_pay_proc_start_date, p_pay_proc_end_date);
671   fetch c_get_per_start_end_dates into l_assign_start_date,l_assign_end_date;
672 
673   if c_get_per_start_end_dates%NOTFOUND then
674     close c_get_per_start_end_dates;
675     hr_utility.set_location('Error : Assignment does not exist in the pay process period'||l_proc,5);
676   else
677     if (l_assign_start_date > p_pay_proc_start_date ) then
678        l_proc_start_date := l_assign_start_date;
679     else
680        l_proc_start_date := p_pay_proc_start_date;
681     end if;
682     if (l_assign_end_date < p_pay_proc_end_date ) then
683        l_proc_end_date := l_assign_end_date;
684     else
685        l_proc_end_date := p_pay_proc_end_date;
686     end if;
687   end if;
688 
689     open c_get_wac( p_assignment_id , l_proc_start_date );
690     fetch c_get_wac into l_wac, l_effective_date;
691     if c_get_wac%NOTFOUND then
692        close c_get_wac;
693        hr_utility.set_location('Error : Assignment doesnot exist at the pay proc start date'||l_proc,10);
694        return 1;  /* Bug#2858065 */
695     end if;
696     close c_get_wac;
697     /* store the wac at the start of the period */
698     start_wac := l_wac;
699     /* store the wac effective start date */
700     start_date := l_effective_date;
701 
702    /* if wac effective start date is less than pay proc start date,then
703    set the pay proc start date as the start_date */
704    if (l_effective_date < p_pay_proc_start_date) then
705     start_date := p_pay_proc_start_date;
706    end if;
707 
708    hr_utility.trace('start_wac : '||start_wac);
709    hr_utility.trace('start_date : '||start_date);
710 
711    /* Get the WAC and at the period end date*/
712 
713   open c_get_wac( p_assignment_id,l_proc_end_date);
714   fetch c_get_wac into l_wac, l_effective_date;
715   if c_get_wac%NOTFOUND then
716     close c_get_wac;
717     hr_utility.set_location('Error : Assignment doesnot exist at the pay proc end date (ie terminated)'||l_proc,20);
718     return 1; /* Bug#2873083 */
719   end if;
720   close c_get_wac;
721 
722   /* store the wac at the end of the pay period*/
723   prorate_wac  := l_wac;
724   /* store the effective start date for the above wac*/
725   prorate_date := l_effective_date;
726 
727   /* if wac effective start date is less than pay proc start date ,then
728    set the pay proc start date as the prorate_date */
729 
730   if (l_effective_date < p_pay_proc_start_date ) then
731     prorate_date := p_pay_proc_start_date;
732   end if;
733 
734   hr_utility.trace('prorate_wac : '||prorate_wac);
735   hr_utility.trace('prorate_date : '||prorate_date);
736 
737   open c_get_pro_formula_id ('CPF_CAL_METHOD', l_proc_start_date);
738   fetch c_get_pro_formula_id into l_pro_formula_id;
739   if c_get_pro_formula_id%NOTFOUND then
740     hr_utility.set_location('Error : CPF_CAL_METHOD formula doesnot exist'||l_proc,30);
741   end if;
742   close c_get_pro_formula_id;
743 
744   if (p_date_earned <> start_date ) then
745 
746   hr_utility.trace('l_proc_start_date:'||to_char(l_proc_start_date,'YYYY/MM/DD'));
747 
748    if p_cpf_pro_method = 'C' then
749        l_total_days := fffunc.days_between(p_pay_proc_end_date , p_pay_proc_start_date)+1;
750    elsif p_cpf_pro_method = 'WC' then
751        l_inputs(1).name := 'CPF_START_DATE';
752        l_inputs(1).value := p_pay_proc_start_date;
753        l_inputs(2).name := 'CPF_END_DATE';
754        l_inputs(2).value := p_pay_proc_end_date;
755 
756        l_outputs(1).name := 'TOTAL_DAYS';
757 
758        per_formula_functions.run_formula(p_formula_id => l_pro_formula_id,
759                    p_calculation_date => p_date_earned,
760                    p_inputs => l_inputs,
761                    p_outputs => l_outputs);
762 
763        l_total_days := fnd_number.canonical_to_number(l_outputs(1).value);
764    end if;
765 
766 -------------------------------------------------------------------------------------------------
767 --Bug# 4149190
768 --p_pay_proc_start_date, p_pay_proc_end_date are replaced by l_proc_start_date,
769 --l_proc_end_date respectively.
770 -------------------------------------------------------------------------------------------------
771        hr_utility.trace('l_total_days : '||l_total_days );
772   end if;
773 
774   /* Proration Calculation Block */
775   /* If the employee start date or end date is in between the pay period then
776     for proration we have to take the employee start / end date instead of period
777     start/end date .That is , if the employee has started in between the pay period,then
778     we will take this date for the calculation of proration instead of pay period start date.
779     Similarly if the emplyee is terminated in between then we will take the termination date
780     instead of period end date.In such case the proration is calculated for example
781     from employee start date to period end date divided by the number of days in the period*/
782 
783    If (l_proc_start_date > p_pay_proc_start_date and l_proc_start_date < p_pay_proc_end_date) then
784      l_emp_start_bet_period := 'Y';
785    end if;
786 
787    If (l_proc_end_date > p_pay_proc_start_date and l_proc_end_date < p_pay_proc_end_date) then
788      l_emp_end_bet_period := 'Y';
789    end if;
790 
791 /* Bug 11815978, removed l_emp_start_bet_period and l_emp_end_bet_period check*/
792    if start_wac = prorate_wac and (start_wac = 'PR' or start_wac = 'SG') then
793       p_cpf_calc_type := prorate_wac; /*2494173*/
794       l_prorator := 1.0;
795   else
796   /* Proration need to be accounted for the eligible duration of pay period */
797   /* Bug: 3595103 - Modified get_sg_prorator for Permit type S Pass - SP    */
798 
799       if ((start_wac = 'PR' or start_wac = 'SG') and (prorate_wac = 'EP' or prorate_wac = 'WP' or start_wac = 'SP'))then
800         /* Need to calculate the proration for the first period, since the wac in the second period is
801            not eligible for CPF*/
802           l_pro_check := 'Y';
803           l_proc_start_date := start_date;
804           l_proc_end_date := prorate_date-1;
805           p_cpf_calc_type := start_wac;
806           hr_utility.trace('p_cpf_calc_type :'||p_cpf_calc_type);
807 
808       elsif ((start_wac = 'WP' or start_wac = 'EP' or start_wac = 'SP') and (prorate_wac = 'PR' or prorate_wac = 'SG')) then
809         /* Need to calculate the proration for the second period and first period does not have
810            eligible for the CPF Proration */
811           l_pro_check := 'Y';
812           l_proc_start_date := prorate_date;
813           p_cpf_calc_type := prorate_wac;
814           hr_utility.trace('p_cpf_calc_type :'||p_cpf_calc_type);
815 
816       elsif ((start_wac = 'SG' or start_wac = 'PR') and (prorate_wac = 'SG' or prorate_wac = 'PR')) then
817         /* Need not calculate the CPF Calculation. Hence setting the l_prorator value to 1 and the
818         CPF Calcualtion type to prorate type */
819          if (l_emp_start_bet_period = 'Y' and l_emp_end_bet_period = 'Y' ) then
820           l_pro_check := 'Y';
821 
822          elsIf (l_emp_start_bet_period = 'Y') then
823           l_proc_end_date := p_pay_proc_end_date;
824           l_pro_check := 'Y';
825 
826          elsif (l_emp_end_bet_period = 'Y') then
827           l_proc_start_date := p_pay_proc_start_date;
828           l_pro_check := 'Y';
829 
830          else
831 	     l_prorator := 1.0;
832          end if;
833          p_cpf_calc_type := prorate_wac;
834 
835      elsif ((start_wac = 'WP' or start_wac = 'EP' or start_wac = 'SP') and
836             (prorate_wac = 'WP' or prorate_wac = 'EP' or start_wac = 'SP')) then
837      /* Need not calculate the CPF Calculation. Hence setting the l_prorator value to -1 and the
838         CPF Calcualtion type to prorate type */
839           l_prorator := -1.0;
840           p_cpf_calc_type := prorate_wac;
841 
842      end if;
843 
844    if l_pro_check = 'Y' then
845      if p_cpf_pro_method = 'C' then
846        l_days := fffunc.days_between(l_proc_end_date , l_proc_start_date)+1;
847      elsif p_cpf_pro_method = 'WC' then
848        l_inputs(1).name := 'CPF_START_DATE';
849        l_inputs(1).value := l_proc_start_date;
850        l_inputs(2).name := 'CPF_END_DATE';
851        l_inputs(2).value := l_proc_end_date;
852 
853        l_outputs(1).name := 'TOTAL_DAYS';
854 
855        per_formula_functions.run_formula(p_formula_id => l_pro_formula_id,
856                    p_calculation_date => p_date_earned,
857                    p_inputs => l_inputs,
858                    p_outputs => l_outputs);
859 
860        l_days := fnd_number.canonical_to_number(l_outputs(1).value);
861      end if;
862    l_prorator := l_days/l_total_days;
863    end if;
864 
865 
866   end if;
867  /* End of Proration Calculation */
868   hr_utility.trace('p_cpf_calc_type :'||p_cpf_calc_type);
869   hr_utility.trace('l_prorator : '||l_prorator);
870   hr_utility.set_location('Leaving : '||l_proc, 5);
871 
872   return l_prorator;
873 end sg_get_prorator;
874 
875 /*
876 **  This function will identify if the element being processed is a retropay element.
877 **  If it is a flag set to Y is returned.
878 */
879 
880 function check_if_retro
881          (
882            p_element_entry_id  in pay_element_entries_f.element_entry_id%TYPE,
883            p_date_earned in pay_payroll_actions.date_earned%TYPE
884          ) return varchar2 IS
885 
886 cursor c_get_creator_type(
887      c_element_entry_id in pay_element_entries_f.element_entry_id%TYPE,
888      c_date_earned in pay_payroll_actions.date_earned%TYPE
889                          ) is
890 SELECT creator_type
891   FROM pay_element_entries_f pee
892   WHERE pee.element_entry_id = c_element_entry_id
893   AND c_date_earned between pee.effective_start_date and pee.effective_end_date;
894 
895 l_creator_type pay_element_entries_f.creator_type%TYPE;
896 IS_retro_payment varchar2(10);
897 
898 begin
899 
900 /*  Check creator_type to identify if its a retropay element.
901 **  Creator_type of RR (updated element entry) or EE (new element entry) indicates
902 **  it's a retropay element.
903 */
904 
905    OPEN  c_get_creator_type(p_element_entry_id,p_date_earned);
906    FETCH c_get_creator_type INTO l_creator_type ;
907    CLOSE c_get_creator_type;
908    if l_creator_type = 'RR' or l_creator_type = 'EE' then
909        IS_retro_payment:='Y';
910    else
911        IS_retro_payment:='N';
912    end if;
913 
914   return IS_retro_payment;
915 
916   EXCEPTION
917       when others then
918         IS_retro_payment:='N';
919 
920 end check_if_retro;
921 
922 
923 /*
924 **  This function will identify which retropay method the retropay element was
925 **  created under.
926 **  Eg. Retropay method A indicates that CPF calculations are to be performed in the
927 **  current payroll period and therefore the Retropay By Element run had no CPF
928 **  elements in the element set.
929 **      Retropay method B indicates that CPF calculations are to be performed in the
930 **  period the retrospective payment was earnt therefore the Retropay By Element run
931 **  DID have CPF elements in the element set.
932 **
933 */
934 
935 function which_retro_method
936          (
937            p_assignment_id    in pay_assignment_actions.assignment_id%TYPE,
938            p_date_earned      in pay_payroll_actions.date_earned%TYPE,
939            p_element_entry_id in pay_element_entries_f.element_entry_id%TYPE
940          ) return varchar2 IS
941 
942 /*
943 **  Bug#5353558  Cursor to look for any CPF elements exists in the Element Set of
944 **  the retro pay, which has created this retro element.
945 */
946 
947 cursor get_retro_method
948          ( c_assignment_id in pay_element_entries_f.element_entry_id%TYPE,
949            c_date_earned   in pay_payroll_actions.date_earned%TYPE,
950            c_element_entry_id in pay_element_entries_f.element_entry_id%TYPE
951          ) is
952 select pet.element_name
953   from pay_element_entries_f pee,
954        pay_assignment_actions paa,
955        pay_payroll_actions ppa,
956        pay_element_sets pes,
957        pay_element_type_rules petr,
958        pay_element_types_f pet
959   where pee.creator_id = paa.assignment_action_id
960   and   pee.assignment_id = c_assignment_id
961   and   pee.creator_type in ('EE', 'RR')
962   and   pee.element_entry_id = c_element_entry_id
963   and   paa.payroll_action_id = ppa.payroll_action_id
964   and   ppa.element_set_id = pes.element_set_id
965   and   pes.element_set_id = petr.element_set_id
966   and   petr.element_type_id = pet.element_type_id
967   and   petr.include_or_exclude = 'I'
968   and   c_date_earned between pet.effective_start_date and pet.effective_end_date
969   and   c_date_earned between pee.effective_start_date and pee.effective_end_date
970   and pet.element_name like '%CPF%'
971   and pet.legislation_code = 'SG'
972 union all
973 select pec.classification_name
974   from pay_element_entries_f pee,
975        pay_assignment_actions paa,
976        pay_payroll_actions ppa,
977        pay_element_sets pes,
978        pay_ele_classification_rules pecr,
979        pay_element_classifications pec
980   where pee.creator_id = paa.assignment_action_id
981   and   pee.assignment_id = c_assignment_id
982   and   pee.creator_type in ('EE', 'RR')
983   and   pee.element_entry_id = c_element_entry_id
984   and   paa.payroll_action_id = ppa.payroll_action_id
985   and   ppa.element_set_id = pes.element_set_id
986   and   pes.element_set_id = pecr.element_set_id
987   and   pecr.classification_id = pec.classification_id
988   and   c_date_earned between pee.effective_start_date and pee.effective_end_date
989   and   pec.classification_name in ('Statutory Deductions', 'Employer Liabilities')
990   and   pec.legislation_code = 'SG';
991 
992 l_ele_rec        get_retro_method%ROWTYPE;
993 l_retro_method   varchar2(10);
994 
995 begin
996 
997 /*  Default to method A. */
998 
999     l_retro_method := 'A';
1000 
1001 /*
1002 **  Bug# 5353558 If any of the elements processed in the retro pay were CPF elements and
1003 **  seeded then the retropay process must have been for Method B.
1004 */
1005 
1006     open get_retro_method(p_assignment_id,p_date_earned,p_element_entry_id);
1007     fetch get_retro_method into l_ele_rec;
1008     if  get_retro_method%FOUND then
1009         l_retro_method := 'B';
1010         close get_retro_method;
1011     end if;
1012 
1013     return l_retro_method;
1014 
1015 end which_retro_method;
1016 
1017 /*
1018 **  This function will identify the earnings type of the retropay element.
1019 **  If the balance it feeds is 'CPF Ordinary Earnings Eligible Comp' then it
1020 **  must be classed as Ordinary Earnings (type O).
1021 **  If the balance it feeds is 'CPF Additional Earnings Eligible Comp' then it
1022 **  must be classed as Additional Earnings (type A).
1023 **  If neither of these then leave blank.
1024 */
1025 
1026 function earnings_type
1027          (
1028            p_element_type_id  in pay_element_types_f.element_type_id%TYPE
1029          ) return varchar2 IS
1030 
1031 cursor c_earnings_type
1032          ( c_element_type_id   in pay_element_types_f.element_type_id%TYPE,
1033            c_balance_name      in pay_balance_types.balance_name%TYPE
1034          ) is
1035   select decode(pbt.balance_name,
1036     'CPF Ordinary Earnings Eligible Comp', 'O',
1037     'CPF Additional Earnings Eligible Comp', 'A', ' ')
1038     from pay_balance_types pbt,
1039            pay_balance_feeds_f pbf,
1040            pay_input_values_f pivf,
1041            pay_element_types_f petf
1042     where pbt.balance_type_id = pbf.balance_type_id
1043     and   pbf.input_value_id = pivf.input_value_id
1044     and   pivf.element_type_id = petf.element_type_id
1045     and   pbt.balance_name = c_balance_name
1046     and   petf.element_type_id = c_element_type_id;
1047 
1048 l_earnings_type   varchar2(10);
1049 l_balance_name    pay_balance_types.balance_name%TYPE;
1050 
1051 begin
1052   l_earnings_type  := ' ';
1053   hr_utility.set_location('Entering Earnings Type : ', 5);
1054   hr_utility.set_location('Element Type Id : ' || p_element_type_id, 10);
1055 
1056   l_balance_name := 'CPF Ordinary Earnings Eligible Comp';
1057   open c_earnings_type(p_element_type_id, l_balance_name);
1058   fetch c_earnings_type into l_earnings_type;
1059   close c_earnings_type;
1060 
1061   if l_earnings_type <> 'O' then
1062      l_balance_name := 'CPF Additional Earnings Eligible Comp';
1063      open c_earnings_type(p_element_type_id, l_balance_name);
1064      fetch c_earnings_type into l_earnings_type;
1065      close c_earnings_type;
1066   end if;
1067 
1068   hr_utility.set_location('Earnings Type : ' || l_earnings_type, 15);
1069 
1070   return l_earnings_type;
1071 
1072   EXCEPTION
1073     when others then
1074       l_earnings_type := ' ';
1075       hr_utility.set_location('Exception Earnings Type : ', 20);
1076 
1077 end earnings_type;
1078 ---------------------------------------------------------------------------
1079 -- Function returns Previous Year Ordinary Earnings total with
1080 -- Monthly ceiling of 5,500
1081 ---------------------------------------------------------------------------
1082 function get_prev_year_ord_ytd
1083         (
1084            p_assignment_id   in pay_assignment_actions.assignment_id%TYPE,
1085            p_date_earned     in pay_payroll_actions.date_earned%TYPE
1086         )
1087 return number is
1088     --
1089     cursor c_tax_unit_id( c_assignment_id number,
1090                           c_assignment_action_id pay_assignment_actions.assignment_action_id%TYPE)
1091     is
1092     select paa.tax_unit_id
1093       from pay_assignment_actions paa
1094      where paa.assignment_id = c_assignment_id
1095        and paa.assignment_action_id = c_assignment_action_id;
1096     --
1097     --------------------------------------------------------------------
1098     -- Bug 5298298, need to get action sequence to include all the assignment
1099     -- for the re-hire employee, it will include the original assignment. For
1100     -- multi-assignments with the same LE will be included.
1101     --------------------------------------------------------------------
1102     cursor c_month_year_action_sequence( c_assignment_id number,
1103  			                 c_date_earned   date )
1104     is
1105     select  max(paa.action_sequence),
1106             to_number(to_char(ppa.effective_date,'MM')),
1107             max(pas.person_id)
1108       from  per_assignments_f  pas,
1109             pay_assignment_actions paa,
1110             pay_payroll_actions ppa
1111      where  (pas.person_id, paa.tax_unit_id)
1112                    IN (select pas1.person_id,
1113                              hsc1.segment1
1114                       from   per_assignments_f  pas1,
1115                              hr_soft_coding_keyflex hsc1
1116                       where  pas1.assignment_id     = c_assignment_id
1117                       and    pas1.soft_coding_keyflex_id = hsc1.soft_coding_keyflex_id
1118                       and    c_date_earned between pas1.effective_start_date and pas1.effective_end_date) /* Bug 5298298 */
1119        and  pas.assignment_id = paa.assignment_id
1120        and  ppa.payroll_action_id = paa.payroll_action_id
1121        and  ppa.action_type       in ('R','Q','B','V','I')
1122        and  ppa.effective_date       between trunc(add_months(c_date_earned,-12),'Y') /* Bug 4267196 */
1123                                       and trunc(c_date_earned,'Y') - 1
1124      group by  to_number(to_char(ppa.effective_date,'MM'))
1125      order by  to_number(to_char(ppa.effective_date,'MM')) desc;
1126     --
1127     cursor c_month_year_action ( c_person_id       number,
1128  			         c_date_earned     date,
1129                                  c_action_sequence number )
1130     is
1131     select  paa.assignment_action_id,
1132             ppa.effective_date,
1133             paa.assignment_id
1134       from  per_assignments_f pas,
1135             pay_assignment_actions paa,
1136             pay_payroll_actions ppa
1137      where  pas.person_id = c_person_id /* Bug 5298298 */
1138        and  paa.assignment_id = pas.assignment_id
1139        and  ppa.payroll_action_id = paa.payroll_action_id
1140        and  paa.action_sequence   = c_action_sequence
1141        and  ppa.effective_date between trunc(add_months(c_date_earned,-12),'Y') /* Bug 4267196 */
1142                                 and trunc(c_date_earned,'Y') - 1;
1143     --
1144     cursor c_defined_bal_id ( p_balance_name   in varchar2,
1145                               p_dimension_name in varchar2 )
1146         is
1147     select  pdb.defined_balance_id
1148       from  pay_defined_balances pdb,
1149             pay_balance_types pbt,
1150             pay_balance_dimensions pbd
1151      where  pbt.balance_name         = p_balance_name
1152        and  pbd.dimension_name       = p_dimension_name
1153        and  pbt.balance_type_id      = pdb.balance_type_id
1154        and  pdb.balance_dimension_id = pbd.balance_dimension_id
1155        and  pdb.legislation_code = 'SG';
1156     --
1157     cursor c_globals (p_date in ff_globals_f.effective_start_date%type)
1158         is
1159     select global_value, effective_start_date
1160       from ff_globals_f
1161      where global_name = 'CPF_ORD_MONTH_CAP_AMT'
1162        and p_date between effective_start_date and effective_end_date;
1163 
1164     g_balance_value_tab    pay_balance_pkg.t_balance_value_tab;
1165     g_context_tab          pay_balance_pkg.t_context_tab;
1166     g_detailed_bal_out_tab pay_balance_pkg.t_detailed_bal_out_tab;
1167     --
1168     l_assignment_action_id   pay_assignment_actions.assignment_action_id%TYPE;
1169     l_action_sequence        pay_assignment_actions.action_sequence%TYPE;
1170     l_assignment_id          pay_assignment_actions.assignment_id%TYPE;
1171     l_person_id              per_assignments_f.person_id%TYPE;
1172     l_month                  number;
1173     l_effective_date         date;
1174     l_tax_unit_id            pay_assignment_actions.tax_unit_id%TYPE;
1175     l_defined_bal_id         number;
1176     l_prev_ord_ytd           number;
1177     l_ord_mon_cap_amt        number;
1178     l_ord_mon_cap_amt_b      number;
1179     l_retro_exist            boolean := FALSE ;
1180     l_retro_ele              number;
1181     l_retro_date             date;
1182     l_ord_mon_cap_amt_date   date;
1183     l_ord_mon_cap_amt_change varchar2(1);
1184     l_ord_mon_cap_amt_tmp    date;
1185 begin
1186     l_prev_ord_ytd := 0;
1187     --
1188     -- bug 12639110, the ORD month ceiling changes.
1189     open c_globals(p_date_earned);
1190     fetch c_globals into l_ord_mon_cap_amt, l_ord_mon_cap_amt_date;
1191     close c_globals;
1192     --
1193     if l_ord_mon_cap_amt_date between trunc(p_date_earned,'Y')-1 and
1194            p_date_earned then
1195       l_ord_mon_cap_amt_change := 'Y';
1196     else
1197       l_ord_mon_cap_amt_change := 'N';
1198     end if;
1199 
1200     g_balance_value_tab.delete;
1201     --
1202     open c_defined_bal_id('CPF Ordinary Earnings Eligible Comp','_PER_LE_MONTH');
1203     fetch c_defined_bal_id into g_balance_value_tab(1).defined_balance_id;
1204     close c_defined_bal_id;
1205     --
1206     open c_defined_bal_id('Ordinary Earnings ineligible for CPF','_PER_LE_MONTH');
1207     fetch c_defined_bal_id into g_balance_value_tab(2).defined_balance_id;
1208     close c_defined_bal_id;
1209     --
1210     open c_defined_bal_id('Retro Ord Retro Period','_ASG_PTD');
1211     fetch c_defined_bal_id into g_balance_value_tab(3).defined_balance_id;
1212     close c_defined_bal_id;
1213     --
1214     -- bug 12885297, removed fix for bug 7661439. It should not take away
1215     --  balance Ordinary Earnings Ineligible For CPF
1216     --
1217     open c_month_year_action_sequence( p_assignment_id, p_date_earned );
1218     loop
1219          fetch c_month_year_action_sequence into l_action_sequence,l_month,l_person_id;
1220 
1221          exit when c_month_year_action_sequence%NOTFOUND;
1222          --
1223          open c_month_year_action( l_person_id, p_date_earned, l_action_sequence );
1224          fetch c_month_year_action into l_assignment_action_id,l_effective_date,l_assignment_id;
1225 
1226          --
1227          if c_month_year_action%FOUND then
1228               open c_tax_unit_id(l_assignment_id , l_assignment_action_id );
1229               fetch c_tax_unit_id into l_tax_unit_id;
1230               close c_tax_unit_id;
1231               --
1232               g_context_tab.delete;
1233               g_detailed_bal_out_tab.delete;
1234               --
1235               g_context_tab(1).tax_unit_id := l_tax_unit_id;
1236               g_context_tab(2).tax_unit_id := l_tax_unit_id;
1237               g_context_tab(3).tax_unit_id := l_tax_unit_id;
1238               --
1239               -- bug 12639110, the Ord Monthe ceiling changes
1240               if l_ord_mon_cap_amt_change='Y' and
1241                 l_effective_date < l_ord_mon_cap_amt_date then
1242                   open c_globals(add_months(l_effective_date,12));
1243                   fetch c_globals into l_ord_mon_cap_amt, l_ord_mon_cap_amt_tmp;
1244                   close c_globals;
1245               end if;
1246 
1247               pay_balance_pkg.get_value ( l_assignment_action_id,
1248                                           g_balance_value_tab,
1249                                           g_context_tab,
1250                                           false,
1251                                           false,
1252                                           g_detailed_bal_out_tab
1253                                         );
1254               --
1255               if l_retro_exist
1256                 or nvl(g_detailed_bal_out_tab(3).balance_value,0) <> 0  then /* Bug 6815874 */
1257                     l_retro_ele   := get_retro_earnings( p_assignment_id , l_effective_date ); /* Bug 6815874 */
1258                     if l_retro_ele = 0 then /* Bug 6815874 */
1259                         l_retro_exist := FALSE;
1260                     end if;
1261                     /* Bug 12885297, removed fix for bug 7661439 */
1262                     l_prev_ord_ytd := l_prev_ord_ytd + least( (nvl( g_detailed_bal_out_tab(1).balance_value,0 )
1263                                                            - nvl( g_detailed_bal_out_tab(2).balance_value,0 )
1264                                                            - nvl( g_detailed_bal_out_tab(3).balance_value,0 )
1265                                                            + nvl(l_retro_ele,0)),l_ord_mon_cap_amt );
1266               else
1267                     l_prev_ord_ytd := l_prev_ord_ytd + least( (nvl( g_detailed_bal_out_tab(1).balance_value,0 )
1268                                                            - nvl( g_detailed_bal_out_tab(2).balance_value,0 )
1269                                                            - nvl( g_detailed_bal_out_tab(3).balance_value,0 )),l_ord_mon_cap_amt );
1270               end if;
1271               --
1272               if nvl( g_detailed_bal_out_tab(3).balance_value,0 ) <> 0 then
1273                   l_retro_exist := TRUE;
1274               end if;
1275               --
1276          end if;
1277          --
1278          close c_month_year_action;
1279     end loop;
1280     --
1281     close c_month_year_action_sequence;
1282     --
1283     hr_utility.trace('l_prev_ord_ytd : '||l_prev_ord_ytd);
1284     return l_prev_ord_ytd;
1285     --
1286 end get_prev_year_ord_ytd;
1287 
1288 ---------------------------------------------------------------------------
1289 -- Function returns Current Year Ordinary Earnings total with
1290 -- Monthly ceiling of 5,500
1291 ---------------------------------------------------------------------------
1292 function get_cur_year_ord_ytd
1293         (
1294            p_assignment_id   in pay_assignment_actions.assignment_id%TYPE,
1295            p_date_earned     in pay_payroll_actions.date_earned%TYPE
1296         )
1297 return number is
1298     --
1299     cursor c_tax_unit_id( c_assignment_id number,
1300                           c_assignment_action_id pay_assignment_actions.assignment_action_id%TYPE)
1301     is
1302     select paa.tax_unit_id
1303       from pay_assignment_actions paa
1304      where paa.assignment_id = c_assignment_id
1305        and paa.assignment_action_id = c_assignment_action_id;
1306     --
1307     --------------------------------------------------------------------
1308     -- Bug 5298298, need to get action sequence to include all the assignment
1309     -- for the re-hire employee, it will include the original assignment. For
1310     -- multi-assignments with the same LE will be included.
1311     --------------------------------------------------------------------
1312     cursor c_month_year_action_sequence( c_assignment_id number,
1313  			                 c_date_earned   date )
1314     is
1315     select  max(paa.action_sequence),
1316             to_number(to_char(ppa.effective_date,'MM')),
1317             max(pas.person_id)
1318       from  per_assignments_f pas,
1319             pay_assignment_actions paa,
1320             pay_payroll_actions ppa
1321      where  (pas.person_id, paa.tax_unit_id)
1322                   IN (select pas1.person_id,
1323                              hsc1.segment1
1324                       from   per_assignments_f  pas1,
1325                              hr_soft_coding_keyflex hsc1
1326                       where  pas1.assignment_id     = c_assignment_id
1327                       and    pas1.soft_coding_keyflex_id = hsc1.soft_coding_keyflex_id
1328                       and    c_date_earned between pas1.effective_start_date and pas1.effective_end_date) /* Bug 5298298 */
1329        and  pas.assignment_id = paa.assignment_id
1330        and  ppa.payroll_action_id = paa.payroll_action_id
1331        and  ppa.action_type       in ('R','Q','B','V','I')
1332        and  ppa.effective_date between trunc(c_date_earned,'Y') /* Bug 4267196 */
1333                                 and last_day(add_months(c_date_earned,-1))
1334      group by  to_number(to_char(ppa.effective_date,'MM'))
1335      order by  to_number(to_char(ppa.effective_date,'MM')) desc;
1336     --
1337     cursor c_month_year_action ( c_person_id   number,
1338  			         c_date_earned     date,
1339                                  c_action_sequence number )
1340     is
1341     select  paa.assignment_action_id,
1342             ppa.effective_date,
1343             pas.assignment_id
1344       from  per_assignments_f pas,
1345             pay_assignment_actions paa,
1346             pay_payroll_actions ppa
1347      where  pas.person_id = c_person_id /* Bug 5298298 */
1348        and  paa.assignment_id = pas.assignment_id
1349        and  ppa.payroll_action_id = paa.payroll_action_id
1350        and  paa.action_sequence   = c_action_sequence
1351        and  ppa.effective_date between trunc(c_date_earned,'Y') /* Bug 4267196 */
1352                                 and last_day(add_months(c_date_earned,-1)) ;
1353     --
1354     cursor c_defined_bal_id ( p_balance_name   in varchar2,
1355                               p_dimension_name in varchar2 )
1356         is
1357     select  pdb.defined_balance_id
1358       from  pay_defined_balances pdb,
1359             pay_balance_types pbt,
1360             pay_balance_dimensions pbd
1361      where  pbt.balance_name         = p_balance_name
1362        and  pbd.dimension_name       = p_dimension_name
1363        and  pbt.balance_type_id      = pdb.balance_type_id
1364        and  pdb.balance_dimension_id = pbd.balance_dimension_id
1365        and  pdb.legislation_code = 'SG';
1366     --
1367     cursor c_globals (p_date in ff_globals_f.effective_start_date%type)
1368         is
1369     select global_value, effective_start_date
1370       from ff_globals_f
1371      where global_name = 'CPF_ORD_MONTH_CAP_AMT'
1372        and p_date between effective_start_date and effective_end_date;
1373     --
1374     g_balance_value_tab      pay_balance_pkg.t_balance_value_tab;
1375     g_context_tab            pay_balance_pkg.t_context_tab;
1376     g_detailed_bal_out_tab   pay_balance_pkg.t_detailed_bal_out_tab;
1377     --
1378     l_assignment_action_id   pay_assignment_actions.assignment_action_id%TYPE;
1379     l_action_sequence        pay_assignment_actions.action_sequence%TYPE;
1380     l_assignment_id          pay_assignment_actions.assignment_id%TYPE;
1381     l_person_id              per_assignments_f.person_id%TYPE;
1382     l_month                  number;
1383     l_effective_date         date;
1384     l_tax_unit_id            pay_assignment_actions.tax_unit_id%TYPE;
1385     l_defined_bal_id         number;
1386     l_cur_ord_ytd            number;
1387     l_ord_mon_cap_amt        number;
1388     l_ord_mon_cap_amt_date   date;
1389     l_ord_mon_cap_amt_tmp_date date;
1390     l_ord_mon_cap_amt_change varchar2(1);
1391     l_retro_exist            boolean := FALSE ;
1392     l_retro_ele              number;
1393     l_retro_date             date;
1394 begin
1395     l_cur_ord_ytd := 0;
1396     l_ord_mon_cap_amt_change := 'N';
1397     l_ord_mon_cap_amt := 0;
1398     --
1399     -- bug 12639110, the Ord monthe ceiling changes in the current year
1400     open c_globals(p_date_earned);
1401     fetch c_globals into l_ord_mon_cap_amt, l_ord_mon_cap_amt_date;
1402     close c_globals;
1403 
1404     if l_ord_mon_cap_amt_date between trunc(p_date_earned,'Y')                                 and p_date_earned then
1405         l_ord_mon_cap_amt_change := 'Y';
1406     else
1407         l_ord_mon_cap_amt_change := 'N';
1408     end if;
1409 
1410     --
1411     g_balance_value_tab.delete;
1412     --
1413     open c_defined_bal_id('CPF Ordinary Earnings Eligible Comp','_PER_LE_MONTH');
1414     fetch c_defined_bal_id into g_balance_value_tab(1).defined_balance_id;
1415     close c_defined_bal_id;
1416     --
1417     open c_defined_bal_id('Ordinary Earnings ineligible for CPF','_PER_LE_MONTH');
1418     fetch c_defined_bal_id into g_balance_value_tab(2).defined_balance_id;
1419     close c_defined_bal_id;
1420     --
1421     open c_defined_bal_id('Retro Ord Retro Period','_ASG_PTD');
1422     fetch c_defined_bal_id into g_balance_value_tab(3).defined_balance_id;
1423     close c_defined_bal_id;
1424     --
1425     -- bug 12885297, removed fix for bug 7661439. It should not take away
1426     --  balance Ordinary Earnings Ineligible For CPF
1427     --
1428     open c_month_year_action_sequence( p_assignment_id, p_date_earned );
1429     loop
1430          fetch c_month_year_action_sequence into l_action_sequence,l_month,l_person_id;
1431          exit when c_month_year_action_sequence%NOTFOUND;
1432          --
1433          open c_month_year_action( l_person_id, p_date_earned, l_action_sequence );
1434          fetch c_month_year_action into l_assignment_action_id,l_effective_date,l_assignment_id;
1435          --
1436          if c_month_year_action%FOUND then
1437               open c_tax_unit_id( l_assignment_id, l_assignment_action_id );
1438               fetch c_tax_unit_id into l_tax_unit_id;
1439               close c_tax_unit_id;
1440               --
1441               if l_ord_mon_cap_amt_change = 'Y' then
1442                 open c_globals(l_effective_date);
1443                 fetch c_globals into l_ord_mon_cap_amt, l_ord_mon_cap_amt_tmp_date;
1444                 close c_globals;
1445 
1446               end if;
1447 
1448               g_context_tab.delete;
1449               g_detailed_bal_out_tab.delete;
1450               --
1451               g_context_tab(1).tax_unit_id := l_tax_unit_id;
1452               g_context_tab(2).tax_unit_id := l_tax_unit_id;
1453               g_context_tab(3).tax_unit_id := l_tax_unit_id;
1454               --
1455               pay_balance_pkg.get_value ( l_assignment_action_id,
1456                                           g_balance_value_tab,
1457                                           g_context_tab,
1458                                           false,
1459                                           false,
1460                                           g_detailed_bal_out_tab
1461                                         );
1462               --
1463               if l_retro_exist
1464                   or nvl(g_detailed_bal_out_tab(3).balance_value,0) <> 0 then /* Bug 6815874 */
1465                     l_retro_ele   := get_retro_earnings( p_assignment_id , l_effective_date );  /* Bug 6815874 */
1466                     if l_retro_ele = 0 then /* Bug 6815874 */
1467                       l_retro_exist := FALSE;
1468                     end if;
1469                     /* Bug 12885297, removed fix for bug 7661439 */
1470                     l_cur_ord_ytd := l_cur_ord_ytd + least( (nvl( g_detailed_bal_out_tab(1).balance_value,0 )
1471                                                            - nvl( g_detailed_bal_out_tab(2).balance_value,0 )
1472                                                            - nvl( g_detailed_bal_out_tab(3).balance_value,0 )
1473                                                            + nvl(l_retro_ele,0)),l_ord_mon_cap_amt );
1474               else
1475                     l_cur_ord_ytd := l_cur_ord_ytd + least( (nvl( g_detailed_bal_out_tab(1).balance_value,0 )
1476                                                            - nvl( g_detailed_bal_out_tab(2).balance_value,0 )
1477                                                            - nvl( g_detailed_bal_out_tab(3).balance_value,0 )),l_ord_mon_cap_amt );
1478               end if;
1479               --
1480               if nvl( g_detailed_bal_out_tab(3).balance_value,0 ) <> 0 then
1481                   l_retro_exist := TRUE;
1482               end if;
1483 
1484               --
1485          end if;
1486          --
1487          close c_month_year_action;
1488     end loop;
1489     --
1490     close c_month_year_action_sequence;
1491     --
1492     hr_utility.trace('l_cur_ord_ytd: '||l_cur_ord_ytd);
1493     return l_cur_ord_ytd;
1494     --
1495 end get_cur_year_ord_ytd;
1496 --
1497 function get_retro_earnings( p_assignment_id   in pay_assignment_actions.assignment_id%TYPE,
1498                              p_date_earned     in date ) return number
1499 is
1500   cursor c_pay_element_entries
1501       is
1502   select sum(peev.screen_entry_value)
1503     from pay_element_entry_values_f peev,
1504          pay_element_entries_f pee,
1505          pay_element_types_f pet,
1506          pay_input_values_f piv,
1507          pay_element_classifications pec
1508    where pee.assignment_id         = p_assignment_id
1509      and pee.source_asg_action_id in
1510           (select   paa1.assignment_action_id
1511              from   pay_assignment_actions paa1,
1512                     pay_payroll_actions ppa1
1513             where   paa1.assignment_id = pee.assignment_id
1514               and   ppa1.payroll_action_id = paa1.payroll_action_id
1515               and   ppa1.action_type       in ('R','Q','B','V','I')
1516               and   to_char(ppa1.effective_date,'MM') = to_char(p_date_earned,'MM'))
1517      and pee.creator_type in ('EE','RR')
1518      and pee.element_type_id       = pet.element_type_id
1519      and pet.classification_id     = pec.classification_id
1520      and pec.classification_name   = 'Ordinary Earnings'
1521      and pec.legislation_code      = 'SG'
1522      and pee.element_entry_id      = peev.element_entry_id
1523      and peev.input_value_id       = piv.input_value_id
1524      and piv.name                  = 'Pay Value'
1525      and p_date_earned between pee.source_start_date
1526                            and pee.source_end_date
1527      and p_date_earned between pet.effective_start_date
1528                            and pet.effective_end_date
1529      and p_date_earned between piv.effective_start_date
1530                            and piv.effective_end_date   ;
1531   --
1532   l_retro_value  number;
1533 begin
1534   open  c_pay_element_entries;
1535   fetch c_pay_element_entries into l_retro_value;
1536   close c_pay_element_entries ;
1537   --
1538   return l_retro_value;
1539   --
1540 end get_retro_earnings;
1541 
1542 /*****************************************
1543    CPF Report section : bugno 2475324
1544 *****************************************/
1545 
1546 /* Initialize all the contexts required for SG_STAT*/
1547 Procedure init_formula (p_formula_name in varchar2,
1548                             p_effective_date in date ) is
1549 --
1550 l_effective_date        date;
1551 l_start_date            date;
1552 l_formula_id            number;
1553 --
1554 cursor c_formula_id (c_formula_name varchar2, c_effective_date date)  is
1555 select formula_id, effective_start_date
1556 from   ff_formulas_f
1557 where  formula_name = c_formula_name
1558 and    legislation_code = 'SG'
1559 and    c_effective_date between effective_start_date and effective_end_date;
1560 
1561 Begin
1562    l_effective_date  :=  to_date('1-10-2003','dd-mm-yyyy');
1563    l_start_date      :=  to_date('1-10-2003','dd-mm-yyyy');
1564 
1565    /* This function call returns -1 if the formula was not found */
1566    hr_utility.set_location('Starting init',5);
1567    hr_utility.trace('Formula_id:'||l_formula_id);
1568 
1569    open c_formula_id(p_formula_name, p_effective_date);
1570    fetch c_formula_id into l_formula_id, l_start_date;
1571    if c_formula_id%NOTFOUND then
1572       close c_formula_id;
1573    else
1574 
1575    hr_utility.trace('Formula_id:'||l_formula_id);
1576    ff_exec.init_formula (l_formula_id,
1577                          l_start_date,
1578                          g_inputs,
1579                          g_outputs);
1580    end if;
1581     --
1582    hr_utility.set_location('Leaving init',10);
1583 
1584 End init_formula;
1585 
1586 Function calc_cpf_add_YTD  (p_date_earned          in date
1587                              ,p_assignment_id      in number
1588                              ,p_process_type       in varchar2
1589                              ,p_tax_unit_id        in number
1590                              ,p_asg_action_id      in number
1591                              ,p_business_group_id  in number
1592                              ,p_payroll_action_id  in number
1593                              ,p_payroll_id         in number
1594                              ,p_balance_date       in date
1595                            ) return number is
1596 
1597 l_cpf_add_YTD  number;
1598 
1599 Begin
1600   --
1601   hr_utility.set_location('Entering get_bal',7);
1602   --
1603   init_formula('SG_STAT',p_date_earned);
1604   --
1605   -- Set up contexts for the formula
1606   for i in g_inputs.first..g_inputs.last loop
1607       --
1608 
1609       if g_inputs(i).name = 'DATE_EARNED' then
1610          hr_utility.trace('setting date earned '||p_date_earned);
1611          g_inputs(i).value := fnd_date.date_to_canonical(p_date_earned);
1612       elsif g_inputs(i).name = 'ASSIGNMENT_ID' then
1613          g_inputs(i).value := p_assignment_id;
1614       elsif g_inputs(i).name = 'SOURCE_TEXT' then
1615          hr_utility.trace('setting source text '||p_process_type);
1616          g_inputs(i).value := p_process_type;
1617       elsif g_inputs(i).name = 'PROCESS_TYPE' then
1618          g_inputs(i).value := p_process_type;
1619       elsif g_inputs(i).name = 'TAX_UNIT_ID' then
1620          g_inputs(i).value := p_tax_unit_id;
1621       elsif g_inputs(i).name = 'ASSIGNMENT_ACTION_ID' then
1622          g_inputs(i).value := p_asg_action_id;
1623       elsif g_inputs(i).name = 'BUSINESS_GROUP_ID' then
1624          g_inputs(i).value := p_business_group_id;
1625       elsif g_inputs(i).name = 'PAYROLL_ACTION_ID' then
1626          g_inputs(i).value := p_payroll_action_id;
1627       elsif g_inputs(i).name = 'PAYROLL_ID' then
1628          g_inputs(i).value := p_payroll_id;
1629       elsif g_inputs(i).name = 'BALANCE_DATE' then
1630          g_inputs(i).value := fnd_date.date_to_canonical(p_balance_date);
1631       else
1632          hr_utility.set_location('ERROR value = '||g_inputs(i).name ,7);
1633       end if;
1634       --
1635       hr_utility.trace('g_inputs(i).name : '||g_inputs(i).name);
1636       hr_utility.trace('g_inputs(i).value : '||g_inputs(i).value);
1637   end loop;
1638   --
1639   -- Run the formula
1640   --
1641   hr_utility.set_location('Prior to execute the formula',8);
1642   ff_exec.run_formula (g_inputs ,
1643                        g_outputs  );
1644   --
1645   hr_utility.set_location('End run formula',9);
1646   --
1647   for l_out_cnt in g_outputs.first..g_outputs.last loop
1648       -- only store the output of L_CPF_ADD_CALC_YEAR , ignoe others
1649       if g_outputs(l_out_cnt).name = 'L_CPF_ADD_CALC_YEAR'  then
1650         l_cpf_add_YTD  :=  g_outputs(l_out_cnt).value;
1651         hr_utility.trace('l_cpf_add_YTD:'|| g_outputs(l_out_cnt).value);
1652       end if;
1653       --
1654       hr_utility.trace('Outputs:'||g_outputs(l_out_cnt).name);
1655       hr_utility.trace('Outputs(values):'||g_outputs(l_out_cnt).value);
1656   end loop;
1657   --
1658   return l_cpf_add_YTD;
1659     --
1660 End calc_cpf_add_YTD;
1661 /* End of Function */
1662 
1663 /* Returns whether the SG_STAT is called from the REPORT or PAYROLL Run*/
1664 Function get_SG_STAT_CALLED_FROM return varchar2
1665 is
1666 begin
1667   return g_sgstat_called_from;
1668 end;
1669 
1670 /* In the before report trigger of PAYSGCPF the global g_sgstat_called_from
1671  is set to REPORT*/
1672 
1673 procedure set_SG_STAT_CALLED_FROM (p_running in varchar2)
1674 is
1675 begin
1676   g_sgstat_called_from := p_running;
1677 end;
1678 
1679 /* Populates the pl/sql table with assignment id and difference of CPF paid (values of the balances)
1680  and calculated CPF from SG_STAT with SAEOY*/
1681 
1682 procedure populate_cpf_table (p_person_id in number,
1683                               p_cpf_diff number ) is
1684 l_person_id binary_integer;
1685 begin
1686        l_person_id:= p_person_id;
1687        cpf_inputs_t(l_person_id).person_id:= p_person_id;
1688        cpf_inputs_t(l_person_id).cpf_diff := p_cpf_diff;
1689 end;
1690 
1691 /* If the assignment exists in the cpf pl/sql table (populated by populate_cpf_table)
1692 ,return 1 else 0. Used in the where clause of the report query*/
1693 
1694 function get_assignment_from_cpf_table(p_person_id in number) return number is
1695 l_person_id binary_integer;
1696 begin
1697       l_person_id:= p_person_id;
1698       if cpf_inputs_t.exists(l_person_id) then
1699          if (cpf_inputs_t(l_person_id).person_id=  p_person_id) then
1700             return (1);
1701          end if;
1702       end if;
1703       return (0);
1704 end;
1705 
1706 /* Get the overpaid value for the assignment passed from the pl/sql table populated by
1707 populate_cpf_table above*/
1708 function get_cpf_difference(p_person_id in number) return number is
1709 l_cpf_diff number;
1710 l_person_id binary_integer;
1711 begin
1712    l_cpf_diff := 0;
1713    l_person_id:= p_person_id;
1714    if cpf_inputs_t.exists(l_person_id) then
1715       if (cpf_inputs_t(l_person_id).person_id= p_person_id) then
1716          l_cpf_diff := cpf_inputs_t(l_person_id).cpf_diff;
1717       end if;
1718    end  if;
1719    return l_cpf_diff;
1720 end;
1721 
1722 /* Return last date of the year (stored in g_year_end_date_for_cpf_report)
1723 , used in the SG_STAT*/
1724 
1725 function GET_YEAR_END_DATE return date is
1726 begin
1727    return g_year_end_date_for_cpf_report;
1728 end;
1729 
1730 /* set the g_year_end_date_for_cpf_report as the last date of the year*/
1731 procedure set_year_end_date(p_year_end_date in date) is
1732 begin
1733    g_year_end_date_for_cpf_report := p_year_end_date;
1734 end;
1735 
1736 begin
1737 
1738    g_sgstat_called_from := 'PAYROLL';
1739 
1740 end pay_sg_deductions;