DBA Data[Home] [Help]

PACKAGE BODY: APPS.SSP_ERN_BUS

Source


1 Package Body ssp_ern_bus as
2 /* $Header: spernrhi.pkb 120.5.12010000.2 2008/08/13 13:25:38 ubhat 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 --
340         begin
341         --
342         hr_utility.set_location('Entering:'||l_proc,1);
343         --
344         open csr_get_payroll_id_end;
345         fetch csr_get_payroll_id_end into l_payroll_id;
346         close csr_get_payroll_id_end;
347 
348         --
349 	-- Bug 1304683 DFoster
350         -- Get the end date of the last pay period where the regular payment
351 	-- date is just before the effective date depending on whether a
352 	-- Sickness or a Maternity.
353         --
354         --6791913 Begin
355         --if p_absence_category = 'M' then
356         if p_absence_category in ('M','GB_ADO') then
357         --6791913 End
358 		open csr_end_period_m;
359 		fetch csr_end_period_m into l_end_of_relevant_period;
360 		close csr_end_period_m;
361 
362 		if l_end_of_relevant_period is null then
363 		      hr_utility.trace (l_proc||' finding the end of relevant period using the assignment id and not using the payroll id');
364 			open csr_end_period_m2;
365 			fetch csr_end_period_m2 into l_end_of_relevant_period;
366 			close csr_end_period_m2;
367 		end if;
368 
369 	else --if p_absence_category = 'S' then
370 		open csr_end_period_s;
371 		fetch csr_end_period_s into l_end_of_relevant_period;
372 		close csr_end_period_s;
373 
374 		if l_end_of_relevant_period is null then
375 		      hr_utility.trace (l_proc||' finding the end of relevant period using the assignment id and not using the payroll id');
376 			open csr_end_period_s2;
377 			fetch csr_end_period_s2 into l_end_of_relevant_period;
378 			close csr_end_period_s2;
379 		end if;
380 
381 	end if;
382 	--
383         -- the above csrs can return null when a new employee is hired
384         -- assigned to new payroll and goes on sick leave!
385 
386         l_start_of_relevant_period := l_end_of_relevant_period - 56;
387         --
388         --
389         -- the payrll id is reset to null as if the csr_get_payroll_id_start
390         -- returns no rows, the old value of payroll id is retained
391         -- and this causes error as l_start_of_relevant_period is not
392         -- set to l_hire_date;
393         -- the above csr can return null when a new employee is hired
394         -- assigned to new payroll and foes on sick leave!
395 
396         l_payroll_id := null;
397 
398         open csr_get_payroll_id_start;
399         fetch csr_get_payroll_id_start into l_payroll_id;
400         close csr_get_payroll_id_start;
401         --
402         if l_payroll_id is null then
403             if l_end_of_relevant_period is null then
404                -- -1 because, the end date is the previous months payroll
405                -- end date
406                 l_end_of_relevant_period := l_hire_date - 1 ;
407                 l_start_of_relevant_period := l_end_of_relevant_period - 56;
408             else
409                 l_start_of_relevant_period := l_hire_date;
410                 -- if the assignment doesn't exits at the hire date (ie, multiple asg)
411                 -- then get the assignment start date
412                 open csr_chk_asg;
413                 fetch csr_chk_asg into l_temp;
414                 if csr_chk_asg%notfound then
415                    open csr_get_start_date;
416                    fetch csr_get_start_date into l_start_of_relevant_period;
417                    close csr_get_start_date;
418                 end if;
419                 close csr_chk_asg;
420             end if;
421         else
422             open csr_start_period;
423             fetch csr_start_period into l_start_of_relevant_period;
424             close csr_start_period;
425         end if;
426         --
427         hr_utility.trace (l_proc||'     start of relevant period = '
428                 ||to_char (l_start_of_relevant_period));
429         hr_utility.trace (l_proc||'     end of relevant period = '
430                 ||to_char (l_end_of_relevant_period));
431         --
432         hr_utility.set_location('Leaving :'||l_proc,100);
433         --
434         end derive_relevant_period;
435         --
436 procedure get_payroll_frequency is
437         --
438         -- Find out what payroll frequency the assignment is using
439         --
440         l_proc varchar2 (72) := g_package||'get_payroll_frequency';
441         --
442         cursor csr_payroll_frequency is
443                 --
444                 -- Get the payroll frequency for an assignment
445                 --
446         -- This now returns all the payrolls that the person is on between the
447         -- start and end of the 'relevant period', rather than just the payroll
448         -- that the person is on as of the p_effective_date which is the
449         -- PIW_start_date(SSP) or QW_start_date(SMP).
450         --
451         select  period_type.number_per_fiscal_year fiscal_year
452         from    pay_all_payrolls_f          PAYROLL,
453                 per_all_assignments_f       ASSIGNMENT,
454                 per_time_period_types   PERIOD_TYPE
455         where   assignment.assignment_id = l_assignment_id
456         and     assignment.effective_start_date <= l_end_of_relevant_period
457         and     assignment.effective_end_date >= l_start_of_relevant_period
458         and     payroll.payroll_id = assignment.payroll_id
459         and     payroll.period_type = period_type.period_type
460         and     payroll.effective_start_date <= l_end_of_relevant_period
461         and     payroll.effective_end_date >= l_start_of_relevant_period;
462         --
463         periods_per_fiscal_year number := 0;
464         --
465         begin
466         --
467         hr_utility.set_location('Entering:'||l_proc,1);
468         --
469         l_payroll_frequency := 'MONTHLY';
470         --
471         for each_payroll in csr_payroll_frequency loop
472             if each_payroll.fiscal_year <> 12 then
473                 l_payroll_frequency := 'NOT MONTHLY';
474             end if;
475         end loop;
476         --
477         hr_utility.trace ('l_payroll_frequency = '||l_payroll_frequency);
478         --
479         hr_utility.set_location('Leaving :'||l_proc,100);
480         --
481         end get_payroll_frequency;
482         --
483 procedure get_period_of_service is
484         --
485         -- Get the current period of service for the person
486         --
487         l_proc varchar2 (72) := g_package||'get_period_of_service';
488         --
489         cursor csr_period_of_service is
490                 --
491                 -- Get the period of service current as of a specified date
492                 --
493                 select  service.period_of_service_id,
494                         service.date_start
495                 from    per_periods_of_service  SERVICE
496                 where   person_id = p_person_id
497                 and     p_effective_date between service.date_start
498                                 and nvl (service.actual_termination_date,
499                                                 hr_general.end_of_time);
500                 --
501         begin
502         --
503         hr_utility.set_location('Entering:'||l_proc,1);
504         --
505         -- Get the period of service current as of the effective date
506         --
507         open csr_period_of_service;
508         fetch csr_period_of_service into l_period_of_service_id, l_hire_date;
509         close csr_period_of_service;
510         --
511         hr_utility.trace (l_proc||'     l_period_of_service_id = '
512                 ||to_char (l_period_of_service_id));
513         hr_utility.trace (l_proc||'     l_hire_date = '
514                 ||to_char (l_hire_date));
515         --
516         hr_utility.set_location('Leaving :'||l_proc,100);
517         --
518         end get_period_of_service;
519         --
520 procedure check_payroll_installed is
521         --
522         -- Checks that Payroll is installed before calculation of earnings is
523         -- attempted.
524         -- This code was copied and modified from hrapiapi.pkb
525         --
526         l_proc varchar2 (72) := g_package||'check_payroll_installed';
527         l_pa_installed  fnd_product_installations.status%TYPE;
528         l_industry      fnd_product_installations.industry%TYPE;
529         l_pa_appid      fnd_product_installations.application_id%TYPE := 801;
530         payroll_not_found       exception;
531         --
532         Begin
533         --
534         hr_utility.set_location('Entering:'||l_proc,1);
535         --
536         -- We need to determine if Payroll is installed.
537         if (fnd_installation.get(
538                 --
539                 appl_id     => l_pa_appid,
540                 dep_appl_id => l_pa_appid,
541                 status      => l_pa_installed,
542                 industry    => l_industry))
543         then
544           --
545           -- Check to see if the status = 'I'
546           --
547           If (l_pa_installed = 'I') then
548             return; -- Payroll is installed
549           else
550             raise payroll_not_found;
551           end If;
552           --
553         else
554           raise payroll_not_found;
555         end If;
556         --
557         hr_utility.set_location('Leaving :'||l_proc,100);
558         --
559         exception
560         when payroll_not_found then
561           --
562           -- Set warning message:
563           -- "Average Earnings cannot be calculated automatically unless
564           -- you have installed Oracle Payroll. You must enter the figure
565           -- yourself."
566           --
567           ssp_smp_support_pkg.reason_for_no_earnings
568                         := 'SSP_35024_NEED_PAYROLL_FOR_ERN';
569           raise cannot_derive_earnings;
570           --
571         end check_payroll_installed;
572         --
573 procedure stop_if_a_director is
574         --
575         cursor csr_director is
576                 select  1
577                 from    per_all_people_f
578                 where   per_information2 = 'Y' -- Director_flag
579                 and     person_id = p_person_id
580                 and     p_effective_date between effective_start_date
581                                         and effective_end_date;
582                 --
583         l_proc varchar2 (72) := g_package||'stop_if_a_director';
584         l_dummy                 integer (1) := null;
585         l_person_is_director    boolean := FALSE;
586         --
587         begin
588         --
589         hr_utility.set_location('Entering:'||l_proc,1);
590         --
591         open csr_director;
592         fetch csr_director into l_dummy;
593         l_person_is_director := csr_director%found;
594         close csr_director;
595         --
596         if l_person_is_director then
597           --
598           -- Set the warning message text to:
599           -- "Oracle Payroll is unable to calculate the earnings of directors
600           -- because it has no way to distinguish between voted fees and fees
601           -- drawn in anticipation of voting. Please enter the average earnings
602           -- figure for directors yourself."
603           --
604           ssp_smp_support_pkg.reason_for_no_earnings
605                         := 'SSP_35025_NO_DIRECTOR_EARNINGS';
606           raise cannot_derive_earnings;
607           --
608         end if;
609         --
610         hr_utility.set_location('Leaving :'||l_proc,100);
611         --
612         end stop_if_a_director;
613         --
614 function gross_NIable_pay
615         --
616         -- Calculate the gross NIable pay for an 8 week period
617         --
618         return number is
619         --
620         l_proc varchar2 (72) := g_package||'gross_NIable_pay';
621         l_lel                   number := 0;
622         l_weekly_pay            number(18,8) := 0;
623         l_gross_NIable_pay      number := 0;
624         l_gross_NIable_pay_acc  number(18,8) := 0;
625         --
626         begin
627         --
628         hr_utility.set_location('Entering:'||l_proc,1);
629         --
630         for csr_Ne in csr_NIable_earnings ('NIable Pay')
631         loop
632            l_gross_NIable_pay_acc := csr_Ne.EARNINGS;
633            l_gross_NIable_pay := l_gross_NIable_pay_acc;
634         end loop;
635         --
636         hr_utility.trace('L_GROSS_NIABLE: '||l_gross_NIable_pay);
637         --
638         l_weekly_pay := l_gross_NIable_pay_acc * 6 / 52;
639         l_lel := SSP_SMP_SUPPORT_PKG.NI_Lower_Earnings_Limit(
640                                                      L_END_OF_RELEVANT_PERIOD);
641         hr_utility.trace('l_lel: '||l_lel);
642         --
643         if l_weekly_pay < l_lel
644         then
645            for csr_Ne in csr_NIable_earnings ('NIable Earnings 1B')
646            loop
647               l_gross_NIable_pay_acc := l_gross_NIable_pay_acc+csr_Ne.EARNINGS;
648               l_gross_NIable_pay := l_gross_NIable_pay_acc;
649               --
650               hr_utility.trace('L_GROSS_NIABLE inc 1B: '||l_gross_NIable_pay);
651            end loop;
652         end if;
653         --
654         hr_utility.set_location('Leaving :'||l_proc,100);
655         --
656         return l_gross_NIable_pay;
657         --
658         end gross_NIable_pay;
659         --
660 procedure do_monthly_calculation is
661         --
662         -- Calculate average earnings for an assignment on a monthly payroll.
663         -- We handle calendar monthly payrolls separately because they have
664         -- unequal numbers of days and so using the normal calculation method
665         -- would give different results depending upon which months were being
666         -- studied.
667         --
668         l_proc varchar2 (72) := g_package||'do_monthly_calculation';
669         --
670         begin
671         --
672         hr_utility.set_location('Entering:'||l_proc,1);
673         --
674         -- Take the gross payments from the last 2 months, multiply by 6 for
675         -- the annual figure and divide by 52 for the weekly average
676         --
677         l_assignment_average :=
678                 l_assignment_average + ((gross_NIable_pay * 6) / 52);
679         --
680         hr_utility.trace (l_proc||'    gross_NIable_pay = '
681                 ||to_char (gross_NIable_pay));
682         --
683         hr_utility.set_location('Leaving :'||l_proc,100);
684         --
685         end do_monthly_calculation;
686         --
687 procedure do_standard_calculation is
688         --
689         -- Calculate average weekly earnings for an assignment with any payroll
690         -- frequency other than monthly, ie those consisting of equal numbers
691         -- of days.
692         --
693         l_proc varchar2 (72) := g_package||'do_standard_calculation';
694         l_days_covered  number := (l_end_of_relevant_period
695                                         - greatest (l_start_of_relevant_period,
696                                                         l_hire_date))
697                                 +1;
698         --
699         -- Csr_get_number_of_reg_payments is used in the new method of
700         -- calculating weekly average earnings. Users will have to enter a
701         -- value for a new element 'Average Earnings Period' to state the
702         -- number of regular payment periods being processed in the one payroll
703         -- process. If a value is returned then an irregular number of payments
704         -- have been processed within the relevant period. The average amount
705         -- is calculated as the total gross NIable pay / the number of periods
706         -- paid. The value entered in this element is used to calculate the
707         -- actual number of payment periods.
708         --
709         cursor csr_get_number_of_reg_payments is
710         select peev.screen_entry_value
711         from   per_all_assignments_f paf
712         ,      pay_element_entry_values_f peev
713         ,      pay_element_entries_f pee
714         ,      pay_element_types_f pet
715         ,      pay_element_links_f pel
716         where  pee.element_entry_id = peev.element_entry_id
717         and    pee.assignment_id = paf.assignment_id
718         and    pet.element_type_id = pel.element_type_id
719         and    pel.element_link_id = pee.element_link_id
720         and    paf.assignment_id = l_assignment_id
721         and    pet.element_name = 'Average Earnings Period'
722         and    peev.effective_start_date between paf.effective_start_date
723                                              and paf.effective_end_date
724         and    peev.effective_start_date between pee.effective_start_date
725                                              and pee.effective_end_date
726         and    peev.effective_start_date between pet.effective_start_date
727                                              and pet.effective_end_date
728         and    peev.effective_start_date between pel.effective_start_date
729                                              and pel.effective_end_date
730         and    peev.effective_start_date
731                     between greatest(l_start_of_relevant_period, l_hire_date)
732                         and l_end_of_relevant_period
733         and    peev.effective_end_date
734                     between greatest(l_start_of_relevant_period, l_hire_date)
735                         and l_end_of_relevant_period;
736         --
737         -- csr_number_of_days returns the payroll frequency that an assignment
738         -- is on during the relevant period. If a person changes payroll within
739         -- the relevant period, then they are considered to be on an irregular
740         -- payroll and as such are calculated using do_standard_calculation,
741         -- even if the person was on a Monthly payroll as some stage during the
742         -- relevant period. Thus, if do_standard_calculation is being executed
743         -- it is not for a Monthly payroll and so we never want csr_number_of
744         -- _days to return a fiscal_year value of 12 (i.e. Monthly).
745         --
746         cursor csr_number_of_days is
747             select  period_type.number_per_fiscal_year fiscal_year
748             from    pay_all_payrolls_f          PAYROLL,
749                     per_all_assignments_f       ASSIGNMENT,
750                     per_time_period_types   PERIOD_TYPE
751             where   assignment.assignment_id = l_assignment_id
752             and     payroll.payroll_id = assignment.payroll_id
753             and     payroll.period_type = period_type.period_type
754             and     payroll.effective_start_date <= l_end_of_relevant_period
755             and     payroll.effective_end_date >= l_start_of_relevant_period
756             and     period_type.number_per_fiscal_year <> 12;
757         --
758         number_of_payments      number;
759         total_number_payments   number;
760         payroll_freq            number;
761         number_of_days          number;
762         user_ent_multi_reg_pays boolean;
763         expected_num_of_periods number := null;
764         --
765         begin
766         --
767         hr_utility.set_location('Entering:'||l_proc,1);
768         hr_utility.trace('days covered orig: '||l_days_covered);
769         --
770         -- Take the gross payments from the relevant period, divide by the
771         -- number of days the payments cover, and multiply by 7.
772         --
773         number_of_payments      := 0;
774         total_number_payments   := 0;
775         --
776         for payments in csr_get_number_of_reg_payments loop
777            exit when csr_get_number_of_reg_payments%NOTFOUND
778                   or csr_get_number_of_reg_payments%NOTFOUND is null;
779             if payments.screen_entry_value < 1 then
780                number_of_payments := -1;
781             elsif payments.screen_entry_value >= 1 then
782                number_of_payments := payments.screen_entry_value  -1;
783             end if;
784 
785             total_number_payments := total_number_payments + number_of_payments;
786             user_ent_multi_reg_pays := TRUE;
787             hr_utility.trace('NUMBER OF PAYMENTS: '||number_of_payments);
788         end loop;
789 
790         hr_utility.trace('TOTAL NUM PAYMENTS: '||total_number_payments);
791 --
792         if user_ent_multi_reg_pays then
793         --
794         payroll_freq    := 0;
795         number_of_days  := 0;
796         --
797         open csr_number_of_days;
798         fetch csr_number_of_days into payroll_freq;
799         close csr_number_of_days;
800         --
801         number_of_days := round(365/payroll_freq);
802         --
803         hr_utility.trace('PAYROLL FREQ: '||payroll_freq);
804         hr_utility.trace('NUMBER OF DAYS: '||number_of_days);
805         --
806 -- Next bit of code is for outputting the number of payments to the ssp entries
807 -- form. The value in form_variable is passed to the form via the function
808 -- number_of_periods. If the total_number_payments is 0 then then number of
809 -- payments in the relevant period is the regular number, so the value is not
810 -- output to the form. The user only wants to see a value on the form if it is
811 -- an irregular number of payment periods.
812         --
813         expected_num_of_periods := l_days_covered/number_of_days;
814         --
815         if total_number_payments = 0 then
816            form_variable := null;
817         else
818            form_variable := expected_num_of_periods + total_number_payments;
819         end if;
820         --
821         hr_utility.trace('expected num of periods '||expected_num_of_periods||
822                          ', form variable '||form_variable);
823         --
824            l_days_covered := l_days_covered +
825                                 (number_of_days * total_number_payments);
826         end if;
827         hr_utility.trace('DAYS COVERED: '||l_days_covered);
828         --
829         if l_days_covered < 1 then
830             l_assignment_average := 0;
831         else
832             l_assignment_average :=
833                 l_assignment_average + ((gross_NIable_pay
834                                         -----------------
835                                         / l_days_covered)
836                                         * 7);
837         end if;
838         --
839         hr_utility.trace('GROSS NIABLE PAY: '||gross_NIable_pay);
840         hr_utility.trace ('l_days_covered = '||to_char (l_days_covered));
841         hr_utility.trace ('l_assignment_average = '
842                 ||to_char (l_assignment_average));
843         --
844         hr_utility.set_location('Leaving :'||l_proc,100);
845         --
846 end do_standard_calculation;
847 --
848 begin
849 --
850 hr_utility.set_location('Entering:'||l_proc, 1);
851 hr_utility.trace('P_EFFECTIVE_DATE IS: '||p_effective_date);
852 --
853 check_payroll_installed;
854 stop_if_a_director;
855 get_period_of_service;
856 --
857 FOR each_assignment in csr_set_of_current_assignments
858 LOOP
859    -- Initialise assignment variables
860    --
861    l_assignment_id := each_assignment.assignment_id;
862    l_assignment_average := 0;
863    --
864    derive_relevant_period;
865    --
866    l_new_employee := FALSE;
867    --
868    -- If the employee joined within the relevant period then we must note that
869    -- fact for later  use.
870    --
871    if l_hire_date >= l_start_of_relevant_period
872    then
873      l_new_employee := TRUE;
874      --
875      hr_utility.trace ('Employee is NEW');
876    end if;
877    --
878    -- The calculation of average earnings is done differently depending upon the
879    -- payroll frequency. For new employees, we always treat them as if they were
880    -- on irregular payroll frequencies so that we can pick up any payments they
881    -- may have received.
882    --
883    get_payroll_frequency;
884    --
885    if l_payroll_frequency = 'MONTHLY' and not l_new_employee
886    then
887       do_monthly_calculation;
888    else  -- any other payroll frequency or new employee
889       do_standard_calculation;
890    end if;
891    --
892    -- Increment the person's average earnings by the average earnings for the
893    -- assignment just calculated.
894    --
895    l_person_average := l_person_average + l_assignment_average;
896 end loop;
897 --
898 if l_person_average = 0 and l_new_employee
899 then
900    --
901    -- If by the end of the calculation a new employee has zero average earnings
902    -- it means he received no pay in the period. Therefore, we cannot calculate
903    -- an average so it is determined by contracted pay. Since we cannot derive
904    -- that, set a warning message telling the user why the earnings figure is
905    -- zero: "Oracle Payroll cannot derive the average earnings for new employees
906    -- who have not yet received any pay on which to base a calculation. Please
907    -- enter the average earnings figure yourself, based upon the employee's
908    -- contracted weekly earnings."
909    --
910    -- (abhaduri) 'IF' condition added to check for employees
911    -- re-hired within 8 weeks of previous termination
912    open csr_noof_periods_service;
913    fetch csr_noof_periods_service into l_noof_periods_service;
914    close csr_noof_periods_service;
915    if l_noof_periods_service >1 then
916    -- the employee has been re-hired
917    -- check if the hiring has been within 8 weeks
918     open csr_earlier_term;
919     fetch csr_earlier_term into l_earlier_term_date;
920     close csr_earlier_term;
921     if l_hire_date - l_earlier_term_date <56 then
922      ssp_smp_support_pkg.reason_for_no_earnings:='SSP_36076_EMP_REHIRED';
923     else
924       ssp_smp_support_pkg.reason_for_no_earnings:='SSP_35026_NO_NEW_EMP_EARNINGS';
925     end if;
926    else
927    -- otherwise continue as earlier for a new employee
928     ssp_smp_support_pkg.reason_for_no_earnings:= 'SSP_35026_NO_NEW_EMP_EARNINGS';
929    end if;
930    raise cannot_derive_earnings;
931 end if;
932 --
933 p_average_earnings_amount := nvl (round (l_person_average,2),0);
934 hr_utility.trace ('average earnings is '||to_char(l_person_average));
935 --
936 hr_utility.set_location('Leaving :'||l_proc, 100);
937 --
938 exception
939 when cannot_derive_earnings then
940    hr_utility.set_location ('Leaving :'||l_proc||', exception',999);
941    --
942    p_average_earnings_amount := 0;
943    --
944    fnd_message.set_name ('SSP',ssp_smp_support_pkg.reason_for_no_earnings);
945    --
946    if p_user_entered = 'Y' then
947       --
948       -- We only fail the procedure if the user is entering the amount.
949       -- If the system is calculating it (eg as part of the SSP/SMP process)
950       -- then we must allow the process to continue and handle the error
951       --
952       fnd_message.raise_error;
953   end if;
954   --
955 end calculate_average_earnings;
956 
957 -- ----------------------------------------------------------------------------
958 -- |---------------------------< number_of_periods >---------------------------|
959 -- ----------------------------------------------------------------------------
960 -- This function is used to pass the number of payment periods to the entries
961 -- form, SSPWSENT.
962 --
963 function number_of_periods return number is
964 --
965         l_proc varchar2(72) := g_package||'number_of_periods';
966 begin
967         hr_utility.set_location('Entering:'||l_proc, 1);
968         --
969         return form_variable;
970         hr_utility.set_location('Leaving:'||l_proc, 100);
971 end;
972 --
973 -- ----------------------------------------------------------------------------
974 -- |---------------------------< insert_validate >----------------------------|
975 -- ----------------------------------------------------------------------------
976 Procedure insert_validate(p_rec in out nocopy ssp_ern_shd.g_rec_type) is
977 --
978   l_proc  varchar2(72) := g_package||'insert_validate';
979 --
980 Begin
981   hr_utility.set_location('Entering:'||l_proc, 1);
982   --
983   -- Call all supporting business operations
984   --
985   -- Following two calls are to ensure that the mandatory columns
986   -- person_id and effective_date have been entered.
987   hr_api.mandatory_arg_error (p_api_name       => l_proc,
988                               p_argument       => 'person_id',
989                               p_argument_value => p_rec.person_id);
990 
991   hr_api.mandatory_arg_error (p_api_name       => l_proc,
992                               p_argument       => 'effective_date',
993                               p_argument_value => p_rec.effective_date);
994   --
995   ssp_ern_bus.check_person_id(p_rec.person_id, p_rec.effective_date);
996   --
997   ssp_ern_bus.check_effective_date (p_rec.person_id, p_rec.effective_date);
998   --
999   if p_rec.average_earnings_amount is null
1000        or p_rec.average_earnings_amount = hr_api.g_number
1001   then
1002     p_rec.user_entered := 'N';
1003     ssp_ern_bus.calculate_average_earnings
1004        (p_rec.person_id,
1005         p_rec.effective_date,
1006         p_rec.average_earnings_amount,
1007         p_rec.user_entered,
1008 	p_rec.absence_category --DFoster 1305683
1009        );
1010   end if;
1011   --
1012   hr_utility.set_location('Leaving :'||l_proc, 100);
1013 End insert_validate;
1014 --
1015 -- ----------------------------------------------------------------------------
1016 -- |---------------------------< update_validate >----------------------------|
1017 -- ----------------------------------------------------------------------------
1018 Procedure update_validate(p_rec in out nocopy ssp_ern_shd.g_rec_type) is
1019 --
1020   l_proc  varchar2(72) := g_package||'update_validate';
1021 --
1022 Begin
1023   hr_utility.set_location('Entering:'||l_proc, 1);
1024   --
1025   -- Call all supporting business operations
1026   --
1027   -- Following two bits of code used to ensure that the argument values
1028   -- have not been updated.
1029   --
1030   if (ssp_ern_shd.api_updating
1031           (p_earnings_calculations_id => p_rec.earnings_calculations_id,
1032            p_object_version_number    => p_rec.object_version_number)
1033        and
1034            p_rec.person_id <> ssp_ern_shd.g_old_rec.person_id)
1035   then
1036       hr_api.argument_changed_error
1037                      (p_api_name => l_proc, p_argument => 'Person_id');
1038   end if;
1039 
1040   if (ssp_ern_shd.api_updating
1041           (p_earnings_calculations_id => p_rec.earnings_calculations_id,
1042            p_object_version_number    => p_rec.object_version_number)
1043        and
1044            p_rec.effective_date <> ssp_ern_shd.g_old_rec.effective_date)
1045   then
1046       hr_api.argument_changed_error
1047                      (p_api_name => l_proc, p_argument => 'effective_date');
1048   end if;
1049 
1050   if p_rec.average_earnings_amount is null
1051        or p_rec.average_earnings_amount = hr_api.g_number
1052   then
1053     p_rec.user_entered := 'N';
1054     ssp_ern_bus.calculate_average_earnings
1055        (ssp_ern_shd.g_old_rec.person_id,
1056         ssp_ern_shd.g_old_rec.effective_date,
1057         p_rec.average_earnings_amount,
1058         p_rec.user_entered,
1059 	p_rec.absence_category --DFoster 1304683
1060        );
1061   end if;
1062   --
1063   hr_utility.set_location('Leaving :'||l_proc, 100);
1064 End update_validate;
1065 --
1066 -- ----------------------------------------------------------------------------
1067 -- |---------------------------< delete_validate >----------------------------|
1068 -- ----------------------------------------------------------------------------
1069 Procedure delete_validate(p_rec in ssp_ern_shd.g_rec_type) is
1070 --
1071   l_proc  varchar2(72) := g_package||'delete_validate';
1072 --
1073 Begin
1074   hr_utility.set_location('Entering:'||l_proc, 1);
1075   --
1076   -- Call all supporting business operations - there are none
1077   --
1078   hr_utility.set_location('Leaving :'||l_proc, 100);
1079 End delete_validate;
1080 --
1081 end ssp_ern_bus;