DBA Data[Home] [Help]

PACKAGE BODY: APPS.PAY_FR_TERMINATION_PKG

Source


1 package body PAY_FR_TERMINATION_PKG as
2 /* $Header: pyfrterm.pkb 120.0 2005/05/29 05:11:23 appldev noship $ */
3 /*---------------------------------------------------------------------------------------------------------------
4    This function obtains details of the number of hours an employee has worked relative to a full time employee.
5    For a full time employee the value is = to the number of hours they would normally have worked
6    (asignment.normal hours * months). For part time employees, the number of hours worked relative to the monthly
7    reference hours needs to be calculated. The procedure also splits the hours worked by pre service ( any service
8    that is greater than 10 years date and post service any hours after the pre service :
9 
10                                01-JAN-2011
11                                 |
12    Hire Date 01-JAN-01          |                  Termination Date 28-FEB-2014
13    |<------ Pre Service ------->|<--Post Service-->|
14 
15 
16 ---------------------------------------------------------------------------------------------------------------*/
17 Function get_termination_service_det     (p_business_group_id in number,
18 		  		       -- p_person_id in number,
19                                           p_assignment_id    in number,
20                                           p_termination_date in date,
21                                           p_pre_service_ratio  out NOCOPY number,
22                                           p_post_service_ratio out NOCOPY number)
23 Return number is
24 
25 ZERO_NORMAL_HOURS exception;
26 
27 -- l_greater_than_10_years_service varchar2(1) := 'N';
28 l_date_greater_than_10_years date;
29 l_total_service number :=0;
30 l_post_service_date date;
31 l_person_id number;
32 l_hire_date date;
33 l_10_years_ago date;
34 l_total_pre_service number := 0;
35 l_total_post_service number := 0;
36 l_normal_monthly_hours number := 0;
37 l_months_worked_pre_service number := 0;
38 l_months_worked_post_service number := 0;
39 l_last_day_worked DATE;
40 l_actual_months_worked number := 0;
41 l_period_of_service_id number;
42 g_package varchar2(30) := 'PAY_FR_TERMINATION_PKG';
43 l_proc               varchar2(72) := g_package||'get_termination_service_det';
44 i  number :=0;
45 
46 l_current_monthly_ref_hours number :=0;
47 l_indx PLS_INTEGER;
48 
49 TYPE assignment_rec IS RECORD
50  (business_group_id    NUMBER,
51   assignment_id        NUMBER,
52   effective_start_date DATE,
53   effective_end_date   DATE,
54   normal_hours         NUMBER,
55   frequency            VARCHAR2(1),
56   establishment_id     NUMBER,
57   period_of_service_id NUMBER,
58   part_time_flag       VARCHAR2(1));
59 
60 TYPE t_assignments IS TABLE OF assignment_rec INDEX BY BINARY_INTEGER;
61 l_assignments t_assignments;
62 
63 TYPE monthly_hours_rec IS RECORD
64  ( monthly_hours NUMBER,
65    date_from     DATE,
66    date_to      DATE);
67 
68 TYPE t_monthly_hours IS TABLE OF monthly_hours_rec INDEX BY BINARY_INTEGER;
69 l_monthly_hours t_monthly_hours;
70 
71 cursor assignments(c_person_id number) is
72 select assign.business_group_id,
73        assign.assignment_id,
74        assign.effective_start_date,
75        assign.effective_end_date,
76        -- Modified as part of time analysis changes
77        -- normal_hours,
78        -- frequency,
79        decode(contract.ctr_information12, 'HOUR', fnd_number.canonical_to_number(contract.ctr_information11), assign.normal_hours) normal_hours,
80        decode(contract.ctr_information12, 'HOUR', contract.ctr_information13, assign.frequency) frequency,
81        --
82        assign.establishment_id,
83        assign.period_of_service_id,
84        substr(hruserdt.get_table_value (assign.business_group_id,'FR_CIPDZ','CIPDZ',assign.employment_category,P_termination_date),1,1) part_time_flag
85 from
86        per_all_assignments_f assign,
87        --
88        per_contracts_f       contract
89 where  assign.person_id = c_person_id
90   --
91   and  assign.contract_id = contract.contract_id
92   --
93 order by  assign.effective_start_date;
94 
95 /* get table of historical monthly hours from org eit */
96 Cursor monthly_hours(c_org_id number) is
97 select to_number(org_information3) monthly_hours,
98        fnd_date.canonical_to_date(org_information1) date_from,
99        fnd_date.canonical_to_date(org_information2) date_to
100 from
101        hr_organization_information
102 where
103        org_information_context = 'FR_HISTORICAL_MONTHLY_REF_HRS'
104        and organization_id = c_org_id
105 order by fnd_date.canonical_to_date(org_information1);
106 
107 
108 Function Find_Hours(p_date_start date) return number is
109 l_hours_index number :=0;
110 
111 l_found varchar2(1) := 'N';
112 l_proc               varchar2(72) := g_package||'Find_Hours';
113 
114 Begin
115 
116   hr_utility.set_location('Entering:'|| l_proc, 10);
117   hr_utility.trace('p_date_start = ' || p_date_start);
118   While l_hours_index < l_monthly_hours.count and l_found = 'N' loop
119     l_hours_index := l_hours_index + 1;
120 
121 hr_utility.trace('mth hrs st and end = ' || ' ' || l_monthly_hours(l_hours_index).date_from || ' ' || l_monthly_hours(l_hours_index).date_to);
122 
123 
124     If p_date_start between l_monthly_hours(l_hours_index).date_from and
125                             l_monthly_hours(l_hours_index).date_to Then
126        l_found := 'Y';
127     End if;
128   End loop;
129 
130   If l_found = 'Y' Then
131      Return l_hours_index;
132   Else
133      hr_utility.trace('no monthly reference hours found for date ' || p_date_start);
134      Return 0;
135   End If;
136 
137   hr_utility.set_location(' Leaving:'||l_proc, 70);
138 
139 End;
140 
141 Procedure Calculate_Service(p_hours_index       in number,
142                             p_start             in date,
143                             p_end               in date) is
144 
145 l_number_of_months        number := 0;
146 l_normal_monthly_hours    number := 0;
147 l_actual_months_worked    number := 0;
148 l_proc               varchar2(72) := g_package||'Calculate_Service';
149 
150 Function Calculate_Pre_and_Post_Service (p_start_period date, p_end_period date)
151 Return number is
152 
153 l_proc          varchar2(72) := g_package||'Calculate_Service';
154 
155 Begin
156 
157     hr_utility.set_location('Entering:'|| l_proc, 10);
158     hr_utility.trace('p_start = '|| p_start_period || 'p_end_period = ' || p_end_period);
159 
160     l_number_of_months := months_between(p_end_period + 1,p_start_period);
161     IF l_assignments(i).part_time_flag = 'P' THEN
162        /* Convert the assignment normal hours to a monthly frequency if it is not monthly already */
163        IF l_assignments(i).frequency <> 'M' THEN
164           l_normal_monthly_hours := PAY_FR_GENERAL.convert_hours
165                                                 (p_effective_date       => p_start_period
166                                                 ,p_business_group_id    => l_assignments(i).business_group_id
167                                                 ,p_assignment_id        => l_assignments(i).assignment_id
168                                                 ,p_hours                => l_assignments(i).normal_hours
169                                                 ,p_from_freq_code       => l_assignments(i).frequency
170                                                 ,p_to_freq_code         => 'M');
171        ELSE
172           l_normal_monthly_hours := l_assignments(i).normal_hours;
173        END IF;
174 
175        /* multiply l_nomber_of_months by above to give hours worked during period and then divide by historical
176        monthly hours to give months worked relative to a full time employee */
177 
178        l_actual_months_worked := l_number_of_months *
179                                  (l_normal_monthly_hours/ l_monthly_hours(p_hours_index).monthly_hours);
180 
181        hr_utility.trace('l_actual_months_worked = ' || l_actual_months_worked);
182        hr_utility.trace('l_number_of_months = ' || l_number_of_months );
183        hr_utility.trace('l_normal_monthly_hours = ' || l_normal_monthly_hours);
184        hr_utility.trace('l_monthly_hours(l_indx) = ' || l_monthly_hours(p_hours_index).monthly_hours);
185 
186     ELSE
187        l_actual_months_worked := l_number_of_months;
188 
189        hr_utility.trace('l_number_of_months = ' || l_number_of_months );
190 
191     END IF;
192 
193     hr_utility.set_location(' Leaving:'||l_proc, 70);
194 
195     Return l_actual_months_worked;
196 
197 End;
198 
199 Begin
200 
201     hr_utility.set_location('Entering:'|| l_proc, 10);
202 
203 /* Is this service in the pre service period or service in the post period ? We may need to
204 split this service up so that the correct amount is processed in the pre and post periods */
205 
206     If p_start <= l_date_greater_than_10_years and p_end <= l_date_greater_than_10_years Then /* All Pre Service */
207        l_total_pre_service := l_total_pre_service  + Calculate_Pre_and_Post_Service(p_start, p_end);
208     Elsif
209        p_start <= l_date_greater_than_10_years and p_end > l_date_greater_than_10_years then /* pre and some is post */
210        l_total_pre_service := l_total_pre_service + Calculate_Pre_and_Post_Service
211  							(p_start, l_date_greater_than_10_years);
212        l_total_post_service := l_total_post_service +
213 --	 Calculate_Pre_and_Post_Service ((l_date_greater_than_10_years + 1 ), p_end);
214          Calculate_Pre_and_Post_Service (l_date_greater_than_10_years , p_end);
215     Elsif
216        p_start > l_date_greater_than_10_years Then /* then all post service */
217        l_total_post_service := l_total_post_service + Calculate_Pre_and_Post_Service (p_start, p_end);
218     End if;
219 
220     hr_utility.set_location(' Leaving:'||l_proc, 70);
221 
222 End;
223 
224 Procedure Process_days(p_hours_index in number , p_date_end in date) is
225 l_hours_index number :=0;
226 l_new_date_start date;
227 l_new_date_end date;
228 l_days_to_process number :=0;
229 l_found_hours varchar2(1) := 'Y';
230 
231 l_proc               varchar2(72) := g_package||'Process_days';
232 
233 Begin
234 
235   hr_utility.set_location('Entering:'|| l_proc, 10);
236 
237   l_hours_index := p_hours_index;
238   l_new_date_start := l_assignments(i).effective_start_date;
239   l_new_date_end   := least(p_date_end,l_assignments(i).effective_end_date);
240   While l_new_date_start <= l_assignments(i).effective_end_date And l_found_hours = 'Y' loop
241     l_days_to_process := l_new_date_end - l_new_date_start;
242     Calculate_Service(p_hours_index => l_hours_index, p_start => l_new_date_start, p_end => l_new_date_end);
243     l_hours_index := find_hours(p_date_start => (l_new_date_end + 1));
244     If l_hours_index <> 0 Then
245        l_new_date_start := l_new_date_end + 1;
246        l_new_date_end   := least(l_assignments(i).effective_end_date,l_monthly_hours(l_hours_index).date_to);
247     Else
248       l_found_hours := 'N';
249     End If;
250   End Loop;
251 
252   hr_utility.set_location(' Leaving:'||l_proc, 70);
253 
254 EXCEPTION
255   when others then
256       hr_utility.set_location('process_details',20);
257       hr_utility.trace(SQLCODE);
258       hr_utility.trace(SQLERRM);
259       Raise;
260 
261 End Process_days;
262 
263 Procedure Process_assignment_row is
264 
265 l_proc               varchar2(72) := g_package||'Process_assignment_row';
266 l_index number :=0;
267 Begin
268 
269   hr_utility.set_location('Entering:'|| l_proc, 10);
270   hr_utility.trace('l_assignments(i).effective_start_date = ' || l_assignments(i).effective_start_date);
271 
272   l_index := Find_Hours(l_assignments(i).effective_start_date); -- will always contain at least one row
273 
274   hr_utility.trace('l_monthly_hours(l_index).date_to = ' || l_monthly_hours(l_index).date_to);
275 
276   Process_days(l_index,l_monthly_hours(l_index).date_to);
277 
278   hr_utility.set_location(' Leaving:'||l_proc, 70);
279 
280 End Process_assignment_row;
281 
282 BEGIN
283 
284   hr_utility.set_location('Entering:'|| l_proc, 10);
285 
286   l_10_years_ago :=  add_months (p_termination_date,-120);
287 
288   select distinct person_id
289   into l_person_id
290   from per_all_assignments_f
291   where assignment_id = p_assignment_id
292   and business_group_id = p_business_group_id;
293 
294   select min(start_date)
295   into l_hire_date
296   from per_all_people_f
297   where person_id = l_person_id;
298 
299   If add_months(l_hire_date, 120) < p_termination_date Then
300   -- l_greater_than_10_years_service = 'Y'
301      l_date_greater_than_10_years := add_months(l_hire_date,120) -1;
302   Else
303   -- l_greater_than_10_years_service = 'N';
304      l_date_greater_than_10_years := p_termination_date + 365;
305   END IF;
306 
307   hr_utility.trace ('hire date = ' || l_hire_date);
308   hr_utility.trace ('l_date_greater_than_10_years = ' || l_date_greater_than_10_years);
309 
310   l_indx := 1;
311   For a in assignments(l_person_id) loop
312       l_assignments(l_indx).effective_start_date := a.effective_start_date;
313       l_assignments(l_indx).assignment_id        := a.assignment_id;
314       l_assignments(l_indx).effective_end_date   := a.effective_end_date;
315       l_assignments(l_indx).period_of_service_id := a.period_of_service_id;
316       If a.part_time_flag = 'P' And ( a.normal_hours is null or a.frequency is null) Then
317          RAISE ZERO_NORMAL_HOURS;
318       Else
319      	 l_assignments(l_indx).normal_hours         := a.normal_hours;
320      	 l_assignments(l_indx).frequency            := a.frequency;
321      	 l_assignments(l_indx).part_time_flag       := a.part_time_flag;
322      	 l_assignments(l_indx).business_group_id    := a.business_group_id;
323          l_assignments(l_indx).establishment_id     := a.establishment_id;
324     	 l_indx := l_indx + 1;
325       End If;
326   End loop;
327 
328 /* For the last assignment effective end date, make it equal to the last day worked */
329 
330   hr_utility.trace('last period of service_id = ' || l_assignments(l_assignments.last).period_of_service_id);
331   l_period_of_service_id := l_assignments(l_assignments.last).period_of_service_id;
332   Select fnd_date.canonical_to_date(pds_information10)
333   into
334   l_last_day_worked
335   from per_periods_of_service
336   where period_of_service_id = l_period_of_service_id;
337 
338   l_assignments(l_assignments.last).effective_end_date := l_last_day_worked;
339 
340   hr_utility.trace ('start date 1 = ' || l_assignments(1).effective_start_date);
341 
342   i :=0;
343   While i < l_assignments.last Loop
344      i := i + 1;
345      select to_number(org_information4)
346      into   l_current_monthly_ref_hours
347      from   hr_organization_information
348      where  org_information_context = 'FR_ESTAB_INFO'
349        and organization_id      = l_assignments(i).establishment_id;
350         l_monthly_hours.delete;
351         l_indx := 2;
352         For h in monthly_hours(l_assignments(i).establishment_id) loop
353             l_monthly_hours(l_indx).monthly_hours := h.monthly_hours;
354             l_monthly_hours(l_indx).date_from     := h.date_from;
355             l_monthly_hours(l_indx).date_to       := h.date_to;
356 
357             hr_utility.trace('date from and date to = ' || l_monthly_hours(l_indx).date_from || ' ' || l_monthly_hours(l_indx).date_to);
358             l_indx := l_indx + 1;
359         End loop;
360 
361         /* If any historical reference hours were found then add a row at the beginning of the table to cater
362 	   for assignments that start before the first historical monthly reference hours row. If we found
363            no historical data then we still want to process the assignments so use the current monthly reference
364            hours - store this in the last row.
365         */
366 
367         hr_utility.trace(' 1. l_indx = ' || l_indx || ' count = ' || l_monthly_hours.count);
368 
369         If l_monthly_hours.count > 0 Then
370            IF l_assignments(1).effective_start_date < l_monthly_hours(2).date_from Then
371               l_monthly_hours(1).date_from := l_assignments(1).effective_start_date - 50;
372               l_monthly_hours(1).date_to   := l_monthly_hours(2).date_from - 1;
373            Else
374               l_monthly_hours(1).date_from := l_monthly_hours(2).date_from - 50;
375               l_monthly_hours(1).date_to   := l_monthly_hours(2).date_from - 1;
376        --  l_indx := l_monthly_hours.count + 1;
377        --  l_monthly_hours(1).monthly_hours := l_monthly_hours(2).monthly_hours;
378        --  l_monthly_hours(1).date_from := to_char(to_date('01-JAN-1900','DD-MON-YYYY'),'DD-MON-YYYY');
379        --  l_monthly_hours(1).date_to   := l_monthly_hours(2).date_from - 1;
380            End If;
381            l_indx := l_monthly_hours.count + 1;
382            l_monthly_hours(1).monthly_hours := l_monthly_hours(2).monthly_hours;
383            l_monthly_hours(l_indx).monthly_hours := l_current_monthly_ref_hours;
384            l_monthly_hours(l_indx).date_from     := l_monthly_hours(l_indx - 1).date_to + 1;
385 
386            hr_utility.trace('l_indx = ' || l_indx || ' count = ' || l_monthly_hours.count);
387            hr_utility.trace(' l_monthly_hours.date to = ' || l_monthly_hours(l_monthly_hours.count).date_to);
388            hr_utility.trace(' l_monthly_hours(l_indx).date_from = ' ||  l_monthly_hours(l_indx).date_from);
389 
390            l_monthly_hours(l_indx).date_to       := l_assignments(l_assignments.last).effective_end_date + 365;
391         Else
392            l_monthly_hours(1).monthly_hours := l_current_monthly_ref_hours;
393            l_monthly_hours(1).date_from     := l_assignments(1).effective_start_date - 50;
394            l_monthly_hours(1).date_to       := l_assignments(l_assignments.last).effective_end_date + 365;
395         End if;
396 
397         process_assignment_row;
398   End loop;
399 
400   /* Bug 2859175
401   NOTE Due to bug 2859175 pre_service is now returned as the total service and post service is returned as
402   the service greater than 10 years. So if an employee had 13 years service then pre service is
403   returned as 13 years and post service is returned as 3 years. */
404 
405   -- p_pre_service_ratio := round(l_total_pre_service);
406   l_total_service := (l_total_pre_service + l_total_post_service) / 12;
407   p_pre_service_ratio := l_total_service;
408   p_post_service_ratio := l_total_post_service / 12;
409   -- p_post_service_ratio := round(l_total_post_service);
410 
411   Return 0;
412 
413   hr_utility.set_location(' Leaving:'||l_proc, 70);
414 
415   EXCEPTION
416     WHEN NO_DATA_FOUND THEN
417     hr_utility.trace('No Data Found');
418     p_pre_service_ratio := 0;
419     p_post_service_ratio := 0;
420     RETURN 999;
421 
422     WHEN ZERO_NORMAL_HOURS THEN
423     p_pre_service_ratio := 0;
424     p_post_service_ratio := 0;
425     hr_utility.trace('raised exception ZERO_NORMAL_HOURS - raised when part time employee has no values for
426                       assignment normal hours or frequency');
427     RETURN 998;
428     RAISE;
429 
430 
431     when others then
432       hr_utility.set_location('l_proc',80);
433       hr_utility.trace(SQLCODE);
434       hr_utility.trace(SQLERRM);
435       p_pre_service_ratio := 0;
436       p_post_service_ratio := 0;
437       RETURN 999;
438       Raise;
439 
440 End get_termination_service_det;
441 end PAY_FR_TERMINATION_PKG;