DBA Data[Home] [Help]

PACKAGE BODY: APPS.SSP_ERN_BUS

Source


1 Package Body ssp_ern_bus as
2 /* $Header: spernrhi.pkb 120.8 2010/07/07 13:26:55 pbalu ship $ */
3 --
4 -- ----------------------------------------------------------------------------
5 -- |                     Private Global Definitions                           |
6 -- ----------------------------------------------------------------------------
7 --
8 g_package  varchar2(33) := '  ssp_ern_bus.';  -- Global package name
9 --
10 -- global variable used to pass the number of payment_periods, calculated in
11 -- procedure do_standard_calculation, to the form SSPWSENT.
12 form_variable number := null;
13 --
14 --
15 --  Business Validation Rules
16 --
17 --
18 -----------------------------------------------------------------------------
19 -- |---------------------------------< Check_Person_id >---------------------
20 -- --------------------------------------------------------------------------
21 --
22 -- PUBLIC
23 -- Description:
24 --    Ensure that a valid person id is entered
25 --
26 Procedure check_person_id  (p_person_id      in number,
27                             p_effective_date in date) is
28  l_proc  varchar2(72) := g_package||'Check_Person_id';
29  cursor c1 is
30    select p.rowid
31    from   per_all_people_f p
32    where  p.person_id = p_person_id
33      and  p_effective_date between p.effective_start_date and
34                                    p.effective_end_date;
35  c1_rec c1%ROWTYPE;
36 Begin
37   hr_utility.set_location('Entering:'||l_proc, 1);
38   open c1;
39   fetch c1 into c1_rec;
40   if c1%NOTFOUND then
41     fnd_message.set_name ('SSP' , 'SSP_35049_INV_PERSON_EFF_DATE' );
42     fnd_message.raise_error;
43   end if;
44   close c1;
45   hr_utility.set_location('Leaving :'||l_proc, 100);
46 End  check_person_id;
47 --
48 --
49 --  ------------------------------------------------------------------------
50 -- |-----------------------------< Check_Effective_Date >-------------------
51 --  ------------------------------------------------------------------------
52 --
53 -- PUBLIC
54 -- Description:
55 --   Ensure that a valid effective date is entered for a PErson
56 --
57 Procedure check_effective_date (p_person_id      in number,
58                                 p_effective_date in date) is
59 
60  l_proc  varchar2(72) := g_package||'Check_Effective_Date';
61 
62   cursor c2 is
63     select s.person_id
64     from   per_periods_of_service s
65     where  s.person_id = p_person_id
66      and  p_effective_date between s.date_start and
67            nvl(s.actual_termination_date,hr_general.end_of_time);
68 
69   c2_rec c2%ROWTYPE;
70 
71 BEGIN
72   hr_utility.set_location('Entering:'||l_proc, 1);
73 
74   open c2;
75   fetch c2 into c2_rec;
76   if c2%NOTFOUND then
77     fnd_message.set_name ('SSP' , 'SSP_35050_INV_EFFECTIVE_DATE' );
78     fnd_message.raise_error;
79   end if;
80   close c2;
81   hr_utility.set_location('Leaving :'||l_proc, 100);
82 END check_effective_date;
83 --
84 --
85 -- ------------------------------------------------------------------------
86 -- |----------------------< calculate_average_earnings >-------------------
87 -- ------------------------------------------------------------------------
88 --
89 -- PUBLIC
90 -- Description:
91 --
92 -- Calculate the average weekly earnings of a person over an approximate
93 -- 8 week period prior to a specified date. The calculation method is in
94 -- accordance with the requirements laid down for SSP/SMP in DSS document
95 -- CA30 (NI270) from April 1995
96 --
97 --
98 PROCEDURE CALCULATE_AVERAGE_EARNINGS (
99         p_person_id                     in number,
100         p_effective_date                in date,
101         p_average_earnings_amount       out nocopy number,
102         p_user_entered                  in varchar2 default 'Y',
103 	p_absence_category		in varchar2 --DFoster 1304683
104         ) is
105         --
106 l_proc                          varchar2(72) := g_package
107                                                 ||'calculate_average_earnings';
108 type date_table is table of date index by binary_integer;
109 l_assignment_average            number := 0;
110 l_person_average                number := 0;
111 l_period_of_service_id          number := null;
112 l_hire_date                     date := null;
113 l_payroll_frequency             varchar2 (30);
114 l_payday                        date_table;
115 l_start_of_relevant_period      date := null;
116 l_end_of_relevant_period        date := null;
117 l_start_of_coverage             date := null;
118 l_end_of_coverage               date := null;
119 l_assignment_id                 number := null;
120 l_payroll_id                    number := null;
121 l_new_employee                  boolean := FALSE;
122 cannot_derive_earnings          exception;
123 --
124 -- added variables for checking re-hired employees(abhaduri)
125 l_earlier_term_date            date;
126 l_noof_periods_service         number :=0;
127 --
128 cursor csr_NIable_earnings (p_balance_name in varchar2) is
129         --
130         -- Calculate the total of all NIable pay in a given period for an
131         -- assignment.
132         --
133         select  /*+ ORDERED USE_NL(RUN_VALUE, RUN_RESULT, FEED, BALANCE) */
134                 nvl (sum (nvl (run_value.result_value, 0) * feed.scale),0) EARNINGS
135         from    pay_assignment_actions  ASG_ACTION,
136                 pay_payroll_actions     PAY_ACTION,
137                 per_time_periods        PERIOD,
138                 pay_balance_types       BALANCE,
139                 pay_balance_feeds_f     FEED,
140                 pay_run_results         RUN_RESULT,
141                 pay_run_result_values   RUN_VALUE
142                 --
143         -- where the tables join via primary/foreign keys
144         where   pay_action.payroll_action_id = asg_action.payroll_action_id
145         and     run_result.assignment_action_id=asg_action.assignment_action_id
146         and     run_result.run_result_id = run_value.run_result_id
147         and     run_value.input_value_id = feed.input_value_id
148         and     feed.balance_type_id = balance.balance_type_id
149         and     period.time_period_id = pay_action.time_period_id
150         and     period.regular_payment_date between feed.effective_start_date and feed.effective_end_date
151         --
152         -- and the earnings are for the specified assignment
153         and     asg_action.assignment_id = L_ASSIGNMENT_ID
154         --
155         -- and the run result has been processed
156         and     run_result.status in ('P','PA') --like 'P%'
157         --
158         and     balance.balance_name = p_balance_name
159         and     period.end_date between L_START_OF_RELEVANT_PERIOD and L_END_OF_RELEVANT_PERIOD;
160         --
161 cursor csr_set_of_current_assignments is
162         --
163         -- Get all a person's assignments which fall within a period of service.
164         -- Retrieve a row for each assignment/payroll combination so that we can
165         -- treat payroll transfers effectively as if they were separate
166         -- assignments.
167         --
168         -- Payroll_id not returned as causes do_standard_calculation /
169         -- do_monthly_calculation to be called twice if there has been a change
170         -- of payroll, and the relevant period ends up being calculated
171         -- incorrectly.
172         --
173         select  distinct
174                 asg.assignment_id
175         from    per_all_assignments_f       ASG
176         where   asg.period_of_service_id = L_PERIOD_OF_SERVICE_ID
177         and     asg.payroll_id is not null
178         --6791913 begin  - To treat adoption in the same way as Maternity
179         --and     ((      p_absence_category = 'M'
180         and     ((      p_absence_category in ('M','GB_ADO')
181         --6791913 end
182                     and effective_end_date >= (p_effective_date - 68))
183                  or -- p_absence = 'S'
184                     effective_end_date >= (p_effective_date - 62)
185                  );
186         --
187 -- (abhaduri)added cursor to check whether employee has been re-hired
188 cursor csr_noof_periods_service is
189         -- check the no of rows in per_periods_of_service table
190         -- to calculate the no of times
191         -- the employee has been employed by the employer
192        select count(*) from per_periods_of_service
193        where person_id = p_person_id;
194 --
195 -- (abhaduri) added cursor to get the last termination date
196 -- if employer has been employed more than once by the employer
197 cursor csr_earlier_term is
198       -- get the termination date if it is not null
199         select nvl(max(actual_termination_date),to_date('01/01/01','DD/MM/YY'))
200         from per_periods_of_service
201         where person_id = p_person_id
202         and actual_termination_date is not null;
203 --
204 
205 procedure derive_relevant_period is
206         --
207         -- Derive the 8-week period before the latest payday before the
208         -- effective date.
209         --
210         l_proc varchar2 (72) := g_package||'derive_relevant_period';
211         l_temp number;
212         --
213         cursor csr_end_period_m is
214                 --
215                 -- Get the end date of the last payroll period prior to the
216                 -- end of the week of the effective date for Maternities.
217                 --
218 
219                 select  max (period.end_date)
220                 from    per_time_periods        PERIOD
221                 where   period.payroll_id = L_PAYROLL_ID
222                 and     period.regular_payment_date <= P_EFFECTIVE_DATE +6;
223 
224 	--
225 
226         cursor csr_end_period_m2 is
227                 --
228                 -- Get the end date of the last payroll period prior to the
229                 -- end of the week of the effective date for Maternities.
230 
231                 -- This cursor will be called when a new payroll has been
232 		    -- assigned to the employee and there has been no
233 		    -- payroll runs and the employee is going on a maternity leave.
234 		    -- The cursor csr_end_period_m would return null, which is incorrect.
235 
236 
237 			select max(ptp.end_date)
238 			from per_time_periods ptp
239 			where ptp.payroll_id in
240 		        	(	select papf.payroll_id
241 				        from pay_all_payrolls_f papf,
242 				        per_all_assignments_f paf,
243 				        per_all_people_f ppf,
244 				        per_time_periods ptp
245 				        where ppf.person_id = paf.person_id
246 					        and papf.payroll_id = paf.payroll_id
247 					        and paf.payroll_id = ptp.payroll_id
248 					        and ptp.regular_payment_date <=
249 						  P_EFFECTIVE_DATE  + 6
250 					        and paf.assignment_id = l_assignment_id)
251 			       and ptp.regular_payment_date <= P_EFFECTIVE_DATE + 6 ;
252 	--
253 	cursor csr_end_period_s is
254 		--
255 		-- Get the end date of the last payroll period prior to the
256 		-- end of the week of the effective date for Sicknesses.
257 		--
258 		select max (period.end_date)
259 		from	per_time_periods	PERIOD
260 		where	period.payroll_id = L_PAYROLL_ID
261 		and	period.regular_payment_date <= P_EFFECTIVE_DATE;
262 
263 	--
264       cursor csr_end_period_s2 is
265 			--
266 			-- Get the end date of the last payroll period prior to the
267 			-- end of the week of the effective date for Sicknesses.
268 			--
269 	            -- This cursor will be called when a new payroll has been
270 	   	      -- assigned to the employee and there has been no
271 			-- payroll runs and the employee is going on a leave.
272 			-- The cursor csr_end_period_s would return null, which is incorrect.
273 
274 			select max(ptp.end_date)
275 			from per_time_periods ptp
276 			where ptp.payroll_id in
277 		        	(	select papf.payroll_id
278 				        from pay_all_payrolls_f papf,
279 				        per_all_assignments_f paf,
280 				        per_all_people_f ppf,
281 				        per_time_periods ptp
282 				        where ppf.person_id = paf.person_id
283 					        and papf.payroll_id = paf.payroll_id
284 					        and paf.payroll_id = ptp.payroll_id
285 					        and ptp.regular_payment_date <=
286 						  P_EFFECTIVE_DATE
287 					        and paf.assignment_id = l_assignment_id)
288 			       and ptp.regular_payment_date <= P_EFFECTIVE_DATE ;
289 	--
290         cursor csr_start_period is
291                 --
292                 -- Get the start date of the payroll period which was at least
293                 -- 8 weeks prior to the end of the relevant period.
294                 --
295                 select  max (period.end_date) +1
296                 from    per_time_periods        PERIOD
297                 where   period.payroll_id = L_PAYROLL_ID
298                 and     period.end_date <= L_END_OF_RELEVANT_PERIOD - 56;
299 --
300 -- Cursor to return the payroll_id, as is no longer returned in
301 -- csr_set_of_current_assignments above, but is required in the
302 -- calculation of the relevant_period_start_date. The cursor returns
303 -- the payroll_id that the assignment is on, 56 days before the
304 -- l_end_of_relevant_period.
305 --
306 	cursor csr_get_payroll_id_start is
307 		select ppf.payroll_id
308 	        from pay_all_payrolls_f ppf
309 	        ,    per_all_assignments_f paf
310 	        where   ppf.payroll_id = paf.payroll_id
311 	        and     paf.assignment_id = l_assignment_id
312 	        and     l_start_of_relevant_period between
313 			paf.effective_start_date and paf.effective_end_date;
314 --
315 -- Get payroll id for this assignment just before the start of the absence so
316 -- we can then find the regular payment date which is used to identify the end
317 -- of the last eight weeks for calculating average earnings.
318 --
319         cursor csr_get_payroll_id_end is
320                 select  payroll_id
321                 from    per_all_assignments_f paf
322                 where   paf.assignment_id = L_ASSIGNMENT_ID
323                 and     P_EFFECTIVE_DATE between
324                 	paf.effective_start_date and paf.effective_end_date;
325 
326 --
327 --
328      cursor csr_chk_asg is
329      select 1
330      from   per_all_assignments_f
331      where  assignment_id = L_ASSIGNMENT_ID
332      and    l_start_of_relevant_period between	effective_start_date and effective_end_date;
333 
334      cursor csr_get_start_date is
335      select min(effective_start_date)
336      from   per_all_assignments_f
337      where  assignment_id = L_ASSIGNMENT_ID;
338 --
339      /* Bug 9411096
340         Added cursor to identify TERM_ASSIGN, and handle the relavant dates accordingly. */
341      cursor get_asg_status is
342      select past.per_system_status
343      from   per_all_assignments_f paaf, per_assignment_status_types past
344      where  paaf.assignment_id = L_ASSIGNMENT_ID
345      and    paaf.effective_start_date <= P_EFFECTIVE_DATE
346      and    paaf.assignment_status_type_id = past.assignment_status_type_id
347      order by paaf.effective_start_date desc;
348 
349      v_asg_status varchar2(100); -- bug 9411096
350 --
351         begin
352         --
353         hr_utility.set_location('Entering:'||l_proc,1);
354         --
355         l_payroll_id := null; -- bug 9411096
356         v_asg_status := null;
357 
358         open csr_get_payroll_id_end;
359         fetch csr_get_payroll_id_end into l_payroll_id;
360         close csr_get_payroll_id_end;
361 
362         --
363 	-- Bug 1304683 DFoster
364         -- Get the end date of the last pay period where the regular payment
365 	-- date is just before the effective date depending on whether a
366 	-- Sickness or a Maternity.
367         --
368         --6791913 Begin
369         --if p_absence_category = 'M' then
370         if p_absence_category in ('M','GB_ADO') then
371         --6791913 End
372 		open csr_end_period_m;
373 		fetch csr_end_period_m into l_end_of_relevant_period;
374 		close csr_end_period_m;
375 
376 		if l_end_of_relevant_period is null then
377 		      hr_utility.trace (l_proc||' finding the end of relevant period using the assignment id and not using the payroll id');
378 			open csr_end_period_m2;
379 			fetch csr_end_period_m2 into l_end_of_relevant_period;
380 			close csr_end_period_m2;
381 		end if;
382 
383 	else --if p_absence_category = 'S' then
384 		open csr_end_period_s;
385 		fetch csr_end_period_s into l_end_of_relevant_period;
386 		close csr_end_period_s;
387 
388 		if l_end_of_relevant_period is null then
389 		      hr_utility.trace (l_proc||' finding the end of relevant period using the assignment id and not using the payroll id');
390 			open csr_end_period_s2;
391 			fetch csr_end_period_s2 into l_end_of_relevant_period;
392 			close csr_end_period_s2;
393 		end if;
394 
395 	end if;
396 	--
397         -- the above csrs can return null when a new employee is hired
398         -- assigned to new payroll and goes on sick leave!
399 
400         l_start_of_relevant_period := l_end_of_relevant_period - 56;
401 
402         /* Bug 9411096 start */
403         open get_asg_status;
404         fetch get_asg_status into v_asg_status;
405         hr_utility.trace('v_asg_status IS: '||v_asg_status);
406         close get_asg_status;
407         /* Bug 9411096 end */
408         --
409         --
410         -- the payrll id is reset to null as if the csr_get_payroll_id_start
411         -- returns no rows, the old value of payroll id is retained
412         -- and this causes error as l_start_of_relevant_period is not
413         -- set to l_hire_date;
414         -- the above csr can return null when a new employee is hired
415         -- assigned to new payroll and foes on sick leave!
416 
417         -- l_payroll_id := null; bug 9411096
418 
419         open csr_get_payroll_id_start;
420         fetch csr_get_payroll_id_start into l_payroll_id;
421         /* Bug 9411096 start */
422         if csr_get_payroll_id_start%notfound then
423            l_payroll_id := null;
424         end if;
425         /* Bug 9411096 end */
426         close csr_get_payroll_id_start;
427         --
428         -- if l_payroll_id is null then bug 9411096
429         if l_payroll_id is null and (nvl(v_asg_status,'x') = 'ACTIVE_ASSIGN') then
430             if l_end_of_relevant_period is null then
431                -- -1 because, the end date is the previous months payroll
432                -- end date
433                 l_end_of_relevant_period := l_hire_date - 1 ;
434                 l_start_of_relevant_period := l_end_of_relevant_period - 56;
435             else
436                 l_start_of_relevant_period := l_hire_date;
437                 -- if the assignment doesn't exits at the hire date (ie, multiple asg)
438                 -- then get the assignment start date
439                 open csr_chk_asg;
440                 fetch csr_chk_asg into l_temp;
441                 if csr_chk_asg%notfound then
442                    open csr_get_start_date;
443                    fetch csr_get_start_date into l_start_of_relevant_period;
444                    close csr_get_start_date;
445                 end if;
446                 close csr_chk_asg;
447             end if;
448         else
449             open csr_start_period;
450             fetch csr_start_period into l_start_of_relevant_period;
451             close csr_start_period;
452         end if;
453         --
454         hr_utility.trace (l_proc||'     start of relevant period = '
455                 ||to_char (l_start_of_relevant_period));
456         hr_utility.trace (l_proc||'     end of relevant period = '
457                 ||to_char (l_end_of_relevant_period));
458         --
459         hr_utility.set_location('Leaving :'||l_proc,100);
460         --
461         end derive_relevant_period;
462         --
463 procedure get_payroll_frequency is
464         --
465         -- Find out what payroll frequency the assignment is using
466         --
467         l_proc varchar2 (72) := g_package||'get_payroll_frequency';
468         --
469         cursor csr_payroll_frequency is
470                 --
471                 -- Get the payroll frequency for an assignment
472                 --
473         -- This now returns all the payrolls that the person is on between the
474         -- start and end of the 'relevant period', rather than just the payroll
475         -- that the person is on as of the p_effective_date which is the
476         -- PIW_start_date(SSP) or QW_start_date(SMP).
477         --
478         select  period_type.number_per_fiscal_year fiscal_year
479         from    pay_all_payrolls_f          PAYROLL,
480                 per_all_assignments_f       ASSIGNMENT,
481                 per_time_period_types   PERIOD_TYPE
482         where   assignment.assignment_id = l_assignment_id
483         and     assignment.effective_start_date <= l_end_of_relevant_period
484         and     assignment.effective_end_date >= l_start_of_relevant_period
485         and     payroll.payroll_id = assignment.payroll_id
486         and     payroll.period_type = period_type.period_type
487         and     payroll.effective_start_date <= l_end_of_relevant_period
488         and     payroll.effective_end_date >= l_start_of_relevant_period;
489         --
490         periods_per_fiscal_year number := 0;
491         --
492         begin
493         --
494         hr_utility.set_location('Entering:'||l_proc,1);
495         --
496         l_payroll_frequency := 'MONTHLY';
497         --
498         for each_payroll in csr_payroll_frequency loop
499             if each_payroll.fiscal_year <> 12 then
500                 l_payroll_frequency := 'NOT MONTHLY';
501             end if;
502         end loop;
503         --
504         hr_utility.trace ('l_payroll_frequency = '||l_payroll_frequency);
505         --
506         hr_utility.set_location('Leaving :'||l_proc,100);
507         --
508         end get_payroll_frequency;
509         --
510 procedure get_period_of_service is
511         --
512         -- Get the current period of service for the person
513         --
514         l_proc varchar2 (72) := g_package||'get_period_of_service';
515         --
516         cursor csr_period_of_service is
517                 --
518                 -- Get the period of service current as of a specified date
519                 --
520                 select  service.period_of_service_id,
521                         service.date_start
522                 from    per_periods_of_service  SERVICE
523                 where   person_id = p_person_id
524                 and     p_effective_date between service.date_start
525                                 and nvl (service.actual_termination_date,
526                                                 hr_general.end_of_time);
527                 --
528         begin
529         --
530         hr_utility.set_location('Entering:'||l_proc,1);
531         --
532         -- Get the period of service current as of the effective date
533         --
534         open csr_period_of_service;
535         fetch csr_period_of_service into l_period_of_service_id, l_hire_date;
536         close csr_period_of_service;
537         --
538         hr_utility.trace (l_proc||'     l_period_of_service_id = '
539                 ||to_char (l_period_of_service_id));
540         hr_utility.trace (l_proc||'     l_hire_date = '
541                 ||to_char (l_hire_date));
542         --
543         hr_utility.set_location('Leaving :'||l_proc,100);
544         --
545         end get_period_of_service;
546         --
547 procedure check_payroll_installed is
548         --
549         -- Checks that Payroll is installed before calculation of earnings is
550         -- attempted.
551         -- This code was copied and modified from hrapiapi.pkb
552         --
553         l_proc varchar2 (72) := g_package||'check_payroll_installed';
554         l_pa_installed  fnd_product_installations.status%TYPE;
555         l_industry      fnd_product_installations.industry%TYPE;
556         l_pa_appid      fnd_product_installations.application_id%TYPE := 801;
557         payroll_not_found       exception;
558         --
559         Begin
560         --
561         hr_utility.set_location('Entering:'||l_proc,1);
562         --
563         -- We need to determine if Payroll is installed.
564         if (fnd_installation.get(
565                 --
566                 appl_id     => l_pa_appid,
567                 dep_appl_id => l_pa_appid,
568                 status      => l_pa_installed,
569                 industry    => l_industry))
570         then
571           --
572           -- Check to see if the status = 'I'
573           --
574           If (l_pa_installed = 'I') then
575             return; -- Payroll is installed
576           else
577             raise payroll_not_found;
578           end If;
579           --
580         else
581           raise payroll_not_found;
582         end If;
583         --
584         hr_utility.set_location('Leaving :'||l_proc,100);
585         --
586         exception
587         when payroll_not_found then
588           --
589           -- Set warning message:
590           -- "Average Earnings cannot be calculated automatically unless
591           -- you have installed Oracle Payroll. You must enter the figure
592           -- yourself."
593           --
594           ssp_smp_support_pkg.reason_for_no_earnings
595                         := 'SSP_35024_NEED_PAYROLL_FOR_ERN';
596           raise cannot_derive_earnings;
597           --
598         end check_payroll_installed;
599         --
600 procedure stop_if_a_director is
601         --
602         cursor csr_director is
603                 select  1
604                 from    per_all_people_f
605                 where   per_information2 = 'Y' -- Director_flag
606                 and     person_id = p_person_id
607                 and     p_effective_date between effective_start_date
608                                         and effective_end_date;
609                 --
610         l_proc varchar2 (72) := g_package||'stop_if_a_director';
611         l_dummy                 integer (1) := null;
612         l_person_is_director    boolean := FALSE;
613         --
614         begin
615         --
616         hr_utility.set_location('Entering:'||l_proc,1);
617         --
618         open csr_director;
619         fetch csr_director into l_dummy;
620         l_person_is_director := csr_director%found;
621         close csr_director;
622         --
623         if l_person_is_director then
624           --
625           -- Set the warning message text to:
626           -- "Oracle Payroll is unable to calculate the earnings of directors
627           -- because it has no way to distinguish between voted fees and fees
628           -- drawn in anticipation of voting. Please enter the average earnings
629           -- figure for directors yourself."
630           --
631           ssp_smp_support_pkg.reason_for_no_earnings
632                         := 'SSP_35025_NO_DIRECTOR_EARNINGS';
633           raise cannot_derive_earnings;
634           --
635         end if;
636         --
637         hr_utility.set_location('Leaving :'||l_proc,100);
638         --
639         end stop_if_a_director;
640         --
641 function gross_NIable_pay
642         --
643         -- Calculate the gross NIable pay for an 8 week period
644         --
645         return number is
646         --
647         l_proc varchar2 (72) := g_package||'gross_NIable_pay';
648         l_lel                   number := 0;
649         l_weekly_pay            number(18,8) := 0;
650         l_gross_NIable_pay      number := 0;
651         l_gross_NIable_pay_acc  number(18,8) := 0;
652         --
653         begin
654         --
655         hr_utility.set_location('Entering:'||l_proc,1);
656         --
657         for csr_Ne in csr_NIable_earnings ('NIable Pay')
658         loop
659            l_gross_NIable_pay_acc := csr_Ne.EARNINGS;
660            l_gross_NIable_pay := l_gross_NIable_pay_acc;
661         end loop;
662         --
663         hr_utility.trace('L_GROSS_NIABLE: '||l_gross_NIable_pay);
664         --
665         l_weekly_pay := l_gross_NIable_pay_acc * 6 / 52;
666         l_lel := SSP_SMP_SUPPORT_PKG.NI_Lower_Earnings_Limit(
667                                                      L_END_OF_RELEVANT_PERIOD);
668         hr_utility.trace('l_lel: '||l_lel);
669         --
670         if l_weekly_pay < l_lel
671         then
672            for csr_Ne in csr_NIable_earnings ('NIable Earnings 1B')
673            loop
674               l_gross_NIable_pay_acc := l_gross_NIable_pay_acc+csr_Ne.EARNINGS;
675               l_gross_NIable_pay := l_gross_NIable_pay_acc;
676               --
677               hr_utility.trace('L_GROSS_NIABLE inc 1B: '||l_gross_NIable_pay);
678            end loop;
679         end if;
680         --
681         hr_utility.set_location('Leaving :'||l_proc,100);
682         --
683         return l_gross_NIable_pay;
684         --
685         end gross_NIable_pay;
686         --
687 procedure do_monthly_calculation is
688         --
689         -- Calculate average earnings for an assignment on a monthly payroll.
690         -- We handle calendar monthly payrolls separately because they have
691         -- unequal numbers of days and so using the normal calculation method
692         -- would give different results depending upon which months were being
693         -- studied.
694         --
695         l_proc varchar2 (72) := g_package||'do_monthly_calculation';
696         --
697         begin
698         --
699         hr_utility.set_location('Entering:'||l_proc,1);
700         --
701         -- Take the gross payments from the last 2 months, multiply by 6 for
702         -- the annual figure and divide by 52 for the weekly average
703         --
704         l_assignment_average :=
705                 l_assignment_average + ((gross_NIable_pay * 6) / 52);
706         --
707         hr_utility.trace (l_proc||'    gross_NIable_pay = '
708                 ||to_char (gross_NIable_pay));
709         --
710         hr_utility.set_location('Leaving :'||l_proc,100);
711         --
712         end do_monthly_calculation;
713         --
714 procedure do_standard_calculation is
715         --
716         -- Calculate average weekly earnings for an assignment with any payroll
717         -- frequency other than monthly, ie those consisting of equal numbers
718         -- of days.
719         --
720         l_proc varchar2 (72) := g_package||'do_standard_calculation';
721         l_days_covered  number := (l_end_of_relevant_period
722                                         - greatest (l_start_of_relevant_period,
723                                                         l_hire_date))
724                                 +1;
725         --
726         -- Csr_get_number_of_reg_payments is used in the new method of
727         -- calculating weekly average earnings. Users will have to enter a
728         -- value for a new element 'Average Earnings Period' to state the
729         -- number of regular payment periods being processed in the one payroll
730         -- process. If a value is returned then an irregular number of payments
731         -- have been processed within the relevant period. The average amount
732         -- is calculated as the total gross NIable pay / the number of periods
733         -- paid. The value entered in this element is used to calculate the
734         -- actual number of payment periods.
735         --
736         cursor csr_get_number_of_reg_payments is
737         select peev.screen_entry_value
738         from   per_all_assignments_f paf
739         ,      pay_element_entry_values_f peev
740         ,      pay_element_entries_f pee
741         ,      pay_element_types_f pet
742         ,      pay_element_links_f pel
743         where  pee.element_entry_id = peev.element_entry_id
744         and    pee.assignment_id = paf.assignment_id
745         and    pet.element_type_id = pel.element_type_id
746         and    pel.element_link_id = pee.element_link_id
747         and    paf.assignment_id = l_assignment_id
748         and    pet.element_name = 'Average Earnings Period'
749         and    peev.effective_start_date between paf.effective_start_date
750                                              and paf.effective_end_date
751         and    peev.effective_start_date between pee.effective_start_date
752                                              and pee.effective_end_date
753         and    peev.effective_start_date between pet.effective_start_date
754                                              and pet.effective_end_date
755         and    peev.effective_start_date between pel.effective_start_date
756                                              and pel.effective_end_date
757         and    peev.effective_start_date
758                     between greatest(l_start_of_relevant_period, l_hire_date)
759                         and l_end_of_relevant_period
760         and    peev.effective_end_date
761                     between greatest(l_start_of_relevant_period, l_hire_date)
762                         and l_end_of_relevant_period;
763         --
764         -- csr_number_of_days returns the payroll frequency that an assignment
765         -- is on during the relevant period. If a person changes payroll within
766         -- the relevant period, then they are considered to be on an irregular
767         -- payroll and as such are calculated using do_standard_calculation,
768         -- even if the person was on a Monthly payroll as some stage during the
769         -- relevant period. Thus, if do_standard_calculation is being executed
770         -- it is not for a Monthly payroll and so we never want csr_number_of
771         -- _days to return a fiscal_year value of 12 (i.e. Monthly).
772         --
773         cursor csr_number_of_days is
774             select  period_type.number_per_fiscal_year fiscal_year
775             from    pay_all_payrolls_f          PAYROLL,
776                     per_all_assignments_f       ASSIGNMENT,
777                     per_time_period_types   PERIOD_TYPE
778             where   assignment.assignment_id = l_assignment_id
779             and     payroll.payroll_id = assignment.payroll_id
780             and     payroll.period_type = period_type.period_type
781             and     payroll.effective_start_date <= l_end_of_relevant_period
782             and     payroll.effective_end_date >= l_start_of_relevant_period
783             and     period_type.number_per_fiscal_year <> 12;
784         --
785         number_of_payments      number;
786         total_number_payments   number;
787         payroll_freq            number;
788         number_of_days          number;
789         user_ent_multi_reg_pays boolean;
790         expected_num_of_periods number := null;
791         --
792         begin
793         --
794         hr_utility.set_location('Entering:'||l_proc,1);
795         hr_utility.trace('days covered orig: '||l_days_covered);
796         --
797         -- Take the gross payments from the relevant period, divide by the
798         -- number of days the payments cover, and multiply by 7.
799         --
800         number_of_payments      := 0;
801         total_number_payments   := 0;
802         --
803         for payments in csr_get_number_of_reg_payments loop
804            exit when csr_get_number_of_reg_payments%NOTFOUND
805                   or csr_get_number_of_reg_payments%NOTFOUND is null;
806             if payments.screen_entry_value < 1 then
807                number_of_payments := -1;
808             elsif payments.screen_entry_value >= 1 then
809                number_of_payments := payments.screen_entry_value  -1;
810             end if;
811 
812             total_number_payments := total_number_payments + number_of_payments;
813             user_ent_multi_reg_pays := TRUE;
814             hr_utility.trace('NUMBER OF PAYMENTS: '||number_of_payments);
815         end loop;
816 
817         hr_utility.trace('TOTAL NUM PAYMENTS: '||total_number_payments);
818 --
819         if user_ent_multi_reg_pays then
820         --
821         payroll_freq    := 0;
822         number_of_days  := 0;
823         --
824         open csr_number_of_days;
825         fetch csr_number_of_days into payroll_freq;
826         close csr_number_of_days;
827         --
828         number_of_days := round(365/payroll_freq);
829         --
830         hr_utility.trace('PAYROLL FREQ: '||payroll_freq);
831         hr_utility.trace('NUMBER OF DAYS: '||number_of_days);
832         --
833 -- Next bit of code is for outputting the number of payments to the ssp entries
834 -- form. The value in form_variable is passed to the form via the function
835 -- number_of_periods. If the total_number_payments is 0 then then number of
836 -- payments in the relevant period is the regular number, so the value is not
837 -- output to the form. The user only wants to see a value on the form if it is
838 -- an irregular number of payment periods.
839         --
840         expected_num_of_periods := l_days_covered/number_of_days;
841         --
842         if total_number_payments = 0 then
843            form_variable := null;
844         else
845            form_variable := expected_num_of_periods + total_number_payments;
846         end if;
847         --
848         hr_utility.trace('expected num of periods '||expected_num_of_periods||
849                          ', form variable '||form_variable);
850         --
851            l_days_covered := l_days_covered +
852                                 (number_of_days * total_number_payments);
853 --9819351 begin
854        else
855 
856 		if l_hire_date < l_end_of_relevant_period - 56 then
857 		--if the person is hired before the 56 days period then
858 		--the average should be calculated for the whole 56 days.
859         hr_utility.trace('DAYS COVERED is eight weeks');
860 			l_days_covered := 56 ;
861 		else
862 		--if the person is hired within the 56 days period then
863 		--the average should be calculated from hire date to end of relevant period,
864         hr_utility.trace('DAYS COVERED will be less than eight weeks');
865 		    l_days_covered := l_end_of_relevant_period - l_hire_date;
866 		end if;
867 --9819351 end
868         end if;
869         hr_utility.trace('DAYS COVERED: '||l_days_covered);
870         --
871         if l_days_covered < 1 then
872             l_assignment_average := 0;
873         else
874             l_assignment_average :=
875                 l_assignment_average + ((gross_NIable_pay
876                                         -----------------
877                                         / l_days_covered)
878                                         * 7);
879         end if;
880         --
881         hr_utility.trace('GROSS NIABLE PAY: '||gross_NIable_pay);
882         hr_utility.trace ('l_days_covered = '||to_char (l_days_covered));
883         hr_utility.trace ('l_assignment_average = '
884                 ||to_char (l_assignment_average));
885         --
886         hr_utility.set_location('Leaving :'||l_proc,100);
887         --
888 end do_standard_calculation;
889 --
890 begin
891 --
892 hr_utility.set_location('Entering:'||l_proc, 1);
893 hr_utility.trace('P_EFFECTIVE_DATE IS: '||p_effective_date);
894 --
895 check_payroll_installed;
896 stop_if_a_director;
897 get_period_of_service;
898 --
899 FOR each_assignment in csr_set_of_current_assignments
900 LOOP
901    -- Initialise assignment variables
902    --
903    l_assignment_id := each_assignment.assignment_id;
904    l_assignment_average := 0;
905    --
906    derive_relevant_period;
907    --
908    l_new_employee := FALSE;
909    --
910    -- If the employee joined within the relevant period then we must note that
911    -- fact for later  use.
912    --
913    if l_hire_date >= l_start_of_relevant_period
914    then
915      l_new_employee := TRUE;
916      --
917      hr_utility.trace ('Employee is NEW');
918    end if;
919    --
920    -- The calculation of average earnings is done differently depending upon the
921    -- payroll frequency. For new employees, we always treat them as if they were
922    -- on irregular payroll frequencies so that we can pick up any payments they
923    -- may have received.
924    --
925    get_payroll_frequency;
926    --
927    if l_payroll_frequency = 'MONTHLY' and not l_new_employee
928    then
929       do_monthly_calculation;
930    else  -- any other payroll frequency or new employee
931       do_standard_calculation;
932    end if;
933    --
934    -- Increment the person's average earnings by the average earnings for the
935    -- assignment just calculated.
936    --
937    l_person_average := l_person_average + l_assignment_average;
938 end loop;
939 --
940 if l_person_average = 0 and l_new_employee
941 then
942    --
943    -- If by the end of the calculation a new employee has zero average earnings
944    -- it means he received no pay in the period. Therefore, we cannot calculate
945    -- an average so it is determined by contracted pay. Since we cannot derive
946    -- that, set a warning message telling the user why the earnings figure is
947    -- zero: "Oracle Payroll cannot derive the average earnings for new employees
948    -- who have not yet received any pay on which to base a calculation. Please
949    -- enter the average earnings figure yourself, based upon the employee's
950    -- contracted weekly earnings."
951    --
952    -- (abhaduri) 'IF' condition added to check for employees
953    -- re-hired within 8 weeks of previous termination
954    open csr_noof_periods_service;
955    fetch csr_noof_periods_service into l_noof_periods_service;
956    close csr_noof_periods_service;
957    if l_noof_periods_service >1 then
958    -- the employee has been re-hired
959    -- check if the hiring has been within 8 weeks
960     open csr_earlier_term;
961     fetch csr_earlier_term into l_earlier_term_date;
962     close csr_earlier_term;
963     if l_hire_date - l_earlier_term_date <56 then
964      ssp_smp_support_pkg.reason_for_no_earnings:='SSP_36076_EMP_REHIRED';
965     else
966       ssp_smp_support_pkg.reason_for_no_earnings:='SSP_35026_NO_NEW_EMP_EARNINGS';
967     end if;
968    else
969    -- otherwise continue as earlier for a new employee
970     ssp_smp_support_pkg.reason_for_no_earnings:= 'SSP_35026_NO_NEW_EMP_EARNINGS';
971    end if;
972    raise cannot_derive_earnings;
973 end if;
974 --
975 p_average_earnings_amount := nvl (round (l_person_average,2),0);
976 hr_utility.trace ('average earnings is '||to_char(l_person_average));
977 --
978 hr_utility.set_location('Leaving :'||l_proc, 100);
979 --
980 exception
981 when cannot_derive_earnings then
982    hr_utility.set_location ('Leaving :'||l_proc||', exception',999);
983    --
984    p_average_earnings_amount := 0;
985    --
986    fnd_message.set_name ('SSP',ssp_smp_support_pkg.reason_for_no_earnings);
987    --
988    if p_user_entered = 'Y' then
989       --
990       -- We only fail the procedure if the user is entering the amount.
991       -- If the system is calculating it (eg as part of the SSP/SMP process)
992       -- then we must allow the process to continue and handle the error
993       --
994       fnd_message.raise_error;
995   end if;
996   --
997 end calculate_average_earnings;
998 
999 -- ----------------------------------------------------------------------------
1000 -- |---------------------------< number_of_periods >---------------------------|
1001 -- ----------------------------------------------------------------------------
1002 -- This function is used to pass the number of payment periods to the entries
1003 -- form, SSPWSENT.
1004 --
1005 function number_of_periods return number is
1006 --
1007         l_proc varchar2(72) := g_package||'number_of_periods';
1008 begin
1009         hr_utility.set_location('Entering:'||l_proc, 1);
1010         --
1011         return form_variable;
1012         hr_utility.set_location('Leaving:'||l_proc, 100);
1013 end;
1014 --
1015 -- ----------------------------------------------------------------------------
1016 -- |---------------------------< insert_validate >----------------------------|
1017 -- ----------------------------------------------------------------------------
1018 Procedure insert_validate(p_rec in out nocopy ssp_ern_shd.g_rec_type) is
1019 --
1020   l_proc  varchar2(72) := g_package||'insert_validate';
1021 --
1022 Begin
1023   hr_utility.set_location('Entering:'||l_proc, 1);
1024   --
1025   -- Call all supporting business operations
1026   --
1027   -- Following two calls are to ensure that the mandatory columns
1028   -- person_id and effective_date have been entered.
1029   hr_api.mandatory_arg_error (p_api_name       => l_proc,
1030                               p_argument       => 'person_id',
1031                               p_argument_value => p_rec.person_id);
1032 
1033   hr_api.mandatory_arg_error (p_api_name       => l_proc,
1034                               p_argument       => 'effective_date',
1035                               p_argument_value => p_rec.effective_date);
1036   --
1037   ssp_ern_bus.check_person_id(p_rec.person_id, p_rec.effective_date);
1038   --
1039   ssp_ern_bus.check_effective_date (p_rec.person_id, p_rec.effective_date);
1040   --
1041   if p_rec.average_earnings_amount is null
1042        or p_rec.average_earnings_amount = hr_api.g_number
1043   then
1044     p_rec.user_entered := 'N';
1045     ssp_ern_bus.calculate_average_earnings
1046        (p_rec.person_id,
1047         p_rec.effective_date,
1048         p_rec.average_earnings_amount,
1049         p_rec.user_entered,
1050 	p_rec.absence_category --DFoster 1305683
1051        );
1052   end if;
1053   --
1054   hr_utility.set_location('Leaving :'||l_proc, 100);
1055 End insert_validate;
1056 --
1057 -- ----------------------------------------------------------------------------
1058 -- |---------------------------< update_validate >----------------------------|
1059 -- ----------------------------------------------------------------------------
1060 Procedure update_validate(p_rec in out nocopy ssp_ern_shd.g_rec_type) is
1061 --
1062   l_proc  varchar2(72) := g_package||'update_validate';
1063 --
1064 Begin
1065   hr_utility.set_location('Entering:'||l_proc, 1);
1066   --
1067   -- Call all supporting business operations
1068   --
1069   -- Following two bits of code used to ensure that the argument values
1070   -- have not been updated.
1071   --
1072   if (ssp_ern_shd.api_updating
1073           (p_earnings_calculations_id => p_rec.earnings_calculations_id,
1074            p_object_version_number    => p_rec.object_version_number)
1075        and
1076            p_rec.person_id <> ssp_ern_shd.g_old_rec.person_id)
1077   then
1078       hr_api.argument_changed_error
1079                      (p_api_name => l_proc, p_argument => 'Person_id');
1080   end if;
1081 
1082   if (ssp_ern_shd.api_updating
1083           (p_earnings_calculations_id => p_rec.earnings_calculations_id,
1084            p_object_version_number    => p_rec.object_version_number)
1085        and
1086            p_rec.effective_date <> ssp_ern_shd.g_old_rec.effective_date)
1087   then
1088       hr_api.argument_changed_error
1089                      (p_api_name => l_proc, p_argument => 'effective_date');
1090   end if;
1091 
1092   if p_rec.average_earnings_amount is null
1093        or p_rec.average_earnings_amount = hr_api.g_number
1094   then
1095     p_rec.user_entered := 'N';
1096     ssp_ern_bus.calculate_average_earnings
1097        (ssp_ern_shd.g_old_rec.person_id,
1098         ssp_ern_shd.g_old_rec.effective_date,
1099         p_rec.average_earnings_amount,
1100         p_rec.user_entered,
1101 	p_rec.absence_category --DFoster 1304683
1102        );
1103   end if;
1104   --
1105   hr_utility.set_location('Leaving :'||l_proc, 100);
1106 End update_validate;
1107 --
1108 -- ----------------------------------------------------------------------------
1109 -- |---------------------------< delete_validate >----------------------------|
1110 -- ----------------------------------------------------------------------------
1111 Procedure delete_validate(p_rec in ssp_ern_shd.g_rec_type) is
1112 --
1113   l_proc  varchar2(72) := g_package||'delete_validate';
1114 --
1115 Begin
1116   hr_utility.set_location('Entering:'||l_proc, 1);
1117   --
1118   -- Call all supporting business operations - there are none
1119   --
1120   hr_utility.set_location('Leaving :'||l_proc, 100);
1121 End delete_validate;
1122 --
1123 end ssp_ern_bus;