1 PACKAGE BODY hr_ca_ff_udfs AS
2 /* $Header: pycaudfs.pkb 120.3.12000000.4 2007/05/15 09:48:36 amigarg noship $ */
3 /*
4 +======================================================================+
5 | Copyright (c) 1994 Oracle Corporation |
6 | Redwood Shores, California, USA |
7 | All rights reserved. |
8 +======================================================================+
9
10 Name : hr_ca_ff_udfs
11 Filename : pycaudfs.pkb
12 Change List
13 -----------
14 Date Name Vers Bug No Description
15 ---- ---- ---- ------ -----------
16 05-MAY-1999 mmukherj Created
17 This file has been copied
18 from pyusudfs.pkb
19 14-FEB-2000 SSattineni Done Flexible Dates and Multi
20 radix conversion compatible to
21 11.5 version
22 21-JUN-2000 MMukherj Changed the Meanings to Codes
23 for Bug No: 1081235
24 v_pay_basis_code,
25 v_asst_std_freq_code
26 17-SEP-2001 SSouresr Changed the insert into the
27 table fnd_sessions to use the
28 function set_effective_date
29 instead.
30 10-Jan-2002 vpandya Converted p_tax_unit_id to
31 character while comparing it
32 to segment1 in
33 hr_soft_coding_keyflex table
34 to overcome 'invali number' &
35 also added dbdrv lines for gscc
36 30-OCT-2002 pganguly 2647412 Changed Convert_Period_Type.
37 Previously it used to get the
38 day of the week via 'DT' and
39 used to pass this value to get
40 the value from
41 hruserdt.get_table_value. But
42 this was not working in the
43 Psedo translated env as
44 user_tables/row/columns are
45 not translated. Now it is
46 getting the day number and then
47 based upon the number it deter
48 mines the day. Also changed
49 standard_hours_worked to do the
50 same.
51 18-NOV-2002 tclewis 2666118 Changed convert_period_type
52 where we are querring number per
53 fiscal year. to change
54 where sysdate between ...
55 to nvl(p_period_start_date,
56 sysdate).
57 19-NOV-2002 tclewis changed nvl(p_period_start_date
58 ,sysdate) to use session date.
59 02-JAN-2003 mmukherj 115.9 2710358 get_flat_amounts,get_rates and
60 get_percentage cursors have
61 been changed to improve the
62 performance.
63 22-Jan-2003 vpandya 115.10 For Multi GRE functionality,
64 tax unit id will be stored in
65 segment1, segment11 and
66 segment12 of
67 hr_soft_coding_keyflex
68 depending on the gre type.
69 Changed all conditions wherever
70 segment1 is used for tax unit
71 id.
72 22-Jan-2003 vpandya 115.11 Added nocopy with out parameter.
73 09-JAN-2003 pganguly 115.12 Changed the select statements
74 in OT_Base_Rate which was
75 flagged in the Perf Repository
76 with cost more than 150. This
77 fixes bug# 3358735.
78 12-JUN-2004 trugless 115.13 3650170 Changed format of
79 v_from_annualizing_factor and
80 v_to_annualizing_factor from
81 number(10) to number(30,7) in
82 the Convert_Period_Type
83 function.
84 21-FEB-2005 pganguly 115.14 4118082 Added OR Condition in the select
85 which sets 1 to
86 l_eev_info_changes in the
87 calculate_period_earnings
88 procedure.
89 28-OCT-2005 mmukherj 115.15 Added extra parameters in
90 calculate_period_earnings
91 and convert_period_type
92 These parameters are coming
93 from contexts and will be used
94 to use the new core work schedule.
95 31-OCT-2005 mmukherj 115.16 Added calls to the core function
96 to calculate the actual hours
97 worked. This will make sure that
98 while calculating the hours it
99 looks into the core work pattern
100 information.
101 12-APR-2006 meshah 115.17 5155854 changed the select for the
102 condition UPPER(p_freq) <> 'HOURLY'
103 also changed the exception
104 21-NOV-2006 saikrish 115.18 5097793 Added get_earnings_and_type
105 14-DEC-2006 ssouresr 115.19 Corrected main cursor in
106 get_earnings_and_type to remove dups
107 */
108 --
109 -- **********************************************************************
110 -- CALCULATE_PERIOD_EARNINGS
111 -- Description: This function performs proration for the startup elements
112 -- Regular Salary and Regular Wages. Proration occurs in the following
113 -- scenarios:
114 -- 1. Change of assignment status to a status which is unpaid
115 -- ie. unpaid leave, termination;
116 -- 2. Change of regular rate of pay
117 -- ie. could be a change in annual salary or hourly rate.
118 --
119 -- This function also calculates and returns the actual hours worked in the
120 -- period, vacation pay, sick pay, vacation hours, and sick hours.
121
122 FUNCTION Calculate_Period_Earnings (
123 p_bus_grp_id in NUMBER,
124 p_asst_id in NUMBER,
125 p_assignment_action_id in NUMBER,
126 p_payroll_id in NUMBER,
127 p_ele_entry_id in NUMBER,
128 p_tax_unit_id in NUMBER,
129 p_date_earned in DATE,
130 p_pay_basis in VARCHAR2,
131 p_inpval_name in VARCHAR2,
132 p_ass_hrly_figure in NUMBER,
133 p_period_start in DATE,
134 p_period_end in DATE,
135 p_work_schedule in VARCHAR2,
136 p_asst_std_hrs in NUMBER,
137 p_actual_hours_worked in out nocopy NUMBER,
138 p_prorate in VARCHAR2,
139 p_asst_std_freq in VARCHAR2)
140 RETURN NUMBER IS
141 --
142 -- local vars
143 --
144 l_asg_info_changes NUMBER(1);
145 l_eev_info_changes NUMBER(1);
146 v_earnings_entry NUMBER(27,7);
147 v_inpval_id NUMBER(9);
148 v_pay_basis VARCHAR2(80);
149 v_pay_basis_code VARCHAR2(80);
150 v_pay_periods_per_year NUMBER(3);
151 v_period_earn NUMBER(27,7) := 0; -- Pay Period earnings.
152 v_hourly_earn NUMBER(27,7); -- Hourly Rate (earnings).
153 v_prorated_earnings NUMBER(27,7) := 0; -- Calc'd thru proration loops.
154 v_curr_day VARCHAR2(3); -- Currday while summing hrs for range of dates.
155 v_hrs_per_wk NUMBER(15,7);
156 v_hrs_per_range NUMBER(15,7);
157 v_asst_std_hrs NUMBER(15,7);
158 v_asst_std_freq VARCHAR2(30);
159 v_asst_std_freq_code VARCHAR2(30);
160 v_asg_status VARCHAR2(30);
161 v_hours_in_range NUMBER(15,7);
162 v_curr_hrly_rate NUMBER(27,7) := 0;
163 v_range_start DATE; -- range start of ASST rec
164 v_range_end DATE; -- range end of ASST rec
165 v_entry_start DATE; -- start date of ELE ENTRY rec
166 v_entry_end DATE; -- end date of ELE ENTRY rec
167 v_entrange_start DATE; -- max of entry or asst range start
168 v_entrange_end DATE; -- min of entry or asst range end
169 v_work_schedule VARCHAR2(60); -- Work Schedule ID (stored as varchar2
170 -- in HR_SOFT_CODING_KEYFLEX; convert
171 -- to_number when calling wshours fn.
172 v_work_sched_name VARCHAR2(80);
173 v_ws_id NUMBER(9);
174
175 b_entries_done BOOLEAN; -- flags no more entry changes in paypd
176 b_asst_changed BOOLEAN; -- flags if asst changes at least once.
177 b_on_work_schedule BOOLEAN; -- use wrk scheds or std hours
178 l_mid_period_asg_change BOOLEAN := FALSE;
179
180 lv_gre_type varchar2(80) := NULL;
181 v_return_status NUMBER;
182 v_return_message VARCHAR2(500);
183 v_schedule_source varchar2(100);
184 v_schedule varchar2(200);
185 v_total_hours NUMBER(15,7) ;
186
187 /*
188 -- ************************************************************************
189 --
190 -- The following cursor "get_asst_chgs" looks for *changes* to or from
191 -- 'ACTIVE' per_assignment
192 -- records within the supplied range of dates, *WITHIN THE SAME TAX UNIT*
193 -- (ie. the tax unit as of the end of the period specified).
194 -- If no "changes" are found, then assignment information is consistent
195 -- over entire period specified.
196 -- Before calling this cursor, will need to select tax_unit_name
197 -- according to p_tax_unit_id.
198 --
199 -- ************************************************************************
200 */
201
202 --
203 -- This cursor finds ALL ASG records that are WITHIN Period Start and End Dates
204 -- including Period End Date - NOT BETWEEN since the ASG record existing across
205 -- Period Start date has already been retrieved in SELECT (ASG1).
206 -- Work Schedule segment is segment4 on assignment DDF
207 --
208
209 CURSOR get_asst_chgs IS
210 SELECT ASG.effective_start_date,
211 ASG.effective_end_date,
212 NVL(ASG.normal_hours, 0),
213 NVL(HRL.meaning, 'NOT ENTERED'),
214 NVL(HRL.lookup_code, 'NOT ENTERED'),
215 NVL(SCL.segment4, 'NOT ENTERED')
216 FROM per_assignments_f ASG,
217 per_assignment_status_types AST,
218 hr_soft_coding_keyflex SCL,
219 hr_lookups HRL
220 WHERE ASG.assignment_id = p_asst_id
221 AND ASG.business_group_id + 0 = p_bus_grp_id
222 AND ASG.effective_start_date > p_period_start
223 AND ASG.effective_end_date <= p_period_end
224 AND AST.assignment_status_type_id = ASG.assignment_status_type_id
225 AND AST.per_system_status = 'ACTIVE_ASSIGN'
226 AND SCL.soft_coding_keyflex_id = ASG.soft_coding_keyflex_id
227 AND decode(lv_gre_type, 'T4A/RL1', segment11, 'T4A/RL2', SCL.segment12,
228 SCL.segment1) = to_char(p_tax_unit_id)
229 AND SCL.enabled_flag = 'Y'
230 AND HRL.lookup_code(+) = ASG.frequency
231 AND HRL.lookup_type(+) = 'FREQUENCY';
232 --
233 -- 25 May 1994:
234 -- Changing ASG status check to be for Payroll Status of 'Process'
235 -- AND AST.per_system_status = 'ACTIVE_ASSIGN'
236 -- AND AST.pay_system_status = 'P'
237 -- 12 Jul 1994: Now changing back!
238 -- Here's the deal:
239 -- 1) PAY_SYSTEM_STATUS needs to be 'P' in order for the payroll run to
240 -- pick up the asg for processing.
241 -- 2) The Proration function will look at 'ACTIVE_ASSIGN' *PER_SYSTEM_STATUS*
242 -- asgs for purposes of "paying" someone - ie. just b/c the "Pay Status"
243 -- is process for the asg status DOES NOT mean the person is to be paid!
244 -- ISSUE: How else can we determine whether or not to pay someone via
245 -- assignment status types? Ron doesn't like the fact that a user
246 -- status name of "Leave with Pay" has to have a PER_SYSTEM_STATUS of
247 -- 'ACTIVE_ASSIGN'...and a PAY_SYSTEM_STATUS of 'Process'.
248 -- So it currently comes down to this - all assignment statuses must have a payroll system
249 -- status of 'P' in order to be processed by Oracle Payroll. If the status is to be "with pay", then
250 -- the personnel system status MUST BE 'ACTIVE_ASSIGN'; an asg status "without pay" will
251 -- have a per system status of "SUSP_ASSIGN" or "TERM_ASSIGN".
252 --
253
254 FUNCTION Prorate_Earnings (
255 p_bg_id IN NUMBER,
256 p_assignment_id IN NUMBER,
257 p_assignment_action_id IN NUMBER,
258 p_element_entry_id IN NUMBER,
259 p_date_earned IN DATE,
260 p_asg_hrly_rate IN NUMBER,
261 p_wsched IN VARCHAR2 DEFAULT 'NOT ENTERED' ,
262 p_asg_std_hours IN NUMBER,
263 p_asg_std_freq IN VARCHAR2,
264 p_range_start_date IN DATE,
265 p_range_end_date IN DATE,
266 p_act_hrs_worked IN OUT NOCOPY NUMBER) RETURN NUMBER IS
267
268 v_prorated_earn NUMBER(27,7) := 0; -- RETURN var
269 v_hours_in_range NUMBER(15,7);
270 v_ws_id NUMBER(9);
271 v_ws_name VARCHAR2(80);
272
273 v_return_status NUMBER;
274 v_return_message VARCHAR2(500);
275 v_schedule_source varchar2(100);
276 v_schedule varchar2(200);
277 v_total_hours NUMBER(15,7) ;
278
279 BEGIN
280
281 hr_utility.set_location('Pro_Earn: actual hours worked IN = ', p_act_hrs_worked);
282 --
283 -- Prorate using hourly rate passed in as param:
284 --
285 /*
286 IF UPPER(p_wsched) = 'NOT ENTERED' THEN
287
288 hr_utility.set_location('Prorate_Earnings', 7);
289 v_hours_in_range := Standard_Hours_Worked( p_asg_std_hours,
290 p_range_start_date,
291 p_range_end_date,
292 p_asg_std_freq);
293
294 -- Keep running total of ACTUAL hours worked.
295
296 hr_utility.set_location('Prorate_Earnings', 11);
297 p_act_hrs_worked := p_act_hrs_worked + v_hours_in_range;
298 hr_utility.set_location('actual_hours_worked = ', p_act_hrs_worked);
299
300 ELSE
301
302 hr_utility.set_location('Prorate_Earnings', 17);
303
304 -- Get work schedule name:
305 -- v_ws_id := to_number(p_wsched);
306 v_ws_id := fnd_number.canonical_to_number(p_wsched);
307
308 SELECT user_column_name
309 INTO v_ws_name
310 FROM pay_user_columns
311 WHERE user_column_id = v_ws_id
312 AND NVL(legislation_code,'CA') = 'CA';
313
314 hr_utility.set_location('p_range_start_date='||to_char(p_range_start_date), 19);
315 hr_utility.set_location('p_range_end_date='||to_char(p_range_end_date), 19);
316
317 hr_utility.set_location('calling core udfs', 44);
318 */
319 v_hours_in_range := PAY_CORE_FF_UDFS.calculate_actual_hours_worked (
320 p_assignment_action_id
321 ,p_assignment_id
322 ,p_bg_id
323 ,p_element_entry_id
324 ,p_date_earned
325 ,p_range_start_date
326 ,p_range_end_date
327 ,NULL
328 ,'Y'
329 ,'BUSY'
330 ,'CA'--p_legislation_code
331 ,v_schedule_source
332 ,v_schedule
333 ,v_return_status
334 ,v_return_message);
335
336 p_act_hrs_worked := p_act_hrs_worked + v_hours_in_range;
337 hr_utility.set_location('actual_hours_worked = ', p_act_hrs_worked);
338
339 -- Hours in date range via work schedule or std hours.
340 /* END IF;*/
341
342 v_prorated_earn := v_prorated_earn + (p_asg_hrly_rate * v_hours_in_range);
343 hr_utility.set_location('v_prorated_earnings = ', v_prorated_earn);
344 hr_utility.set_location('Prorate_Earnings', 97);
345 p_act_hrs_worked := ROUND(p_act_hrs_worked, 3);
346 hr_utility.set_location('Pro_Earn: actual hours worked OUT = ', p_act_hrs_worked);
347 RETURN v_prorated_earn;
348
349 END Prorate_Earnings;
350
351 FUNCTION Prorate_EEV ( p_bus_group_id IN NUMBER,
352 p_assignment_id IN NUMBER,
353 p_assignment_action_id IN NUMBER,
354 p_date_earned IN DATE,
355 p_pay_id IN NUMBER,
356 p_work_sched IN VARCHAR2 DEFAULT 'NOT ENTERED',
357 p_asg_std_hrs IN NUMBER,
358 p_asg_std_freq IN VARCHAR2,
359 p_pay_basis IN VARCHAR2,
360 p_hrly_rate IN OUT NOCOPY NUMBER,
361 p_range_start_date IN DATE,
362 p_range_end_date IN DATE,
363 p_actual_hrs_worked IN OUT NOCOPY NUMBER,
364 p_element_entry_id IN NUMBER,
365 p_inpval_id IN NUMBER) RETURN NUMBER IS
366 --
367 -- local vars
368 --
369 v_eev_prorated_earnings NUMBER(27,7) := 0; -- Calc'd thru proration loops.
370 v_earnings_entry VARCHAR2(60);
371 v_entry_start DATE;
372 v_entry_end DATE;
373 v_hours_in_range NUMBER(15,7);
374 v_curr_hrly_rate NUMBER(27,7);
375 v_ws_id NUMBER(9);
376 v_ws_name VARCHAR2(80);
377 --
378 -- Select for ALL records that are WITHIN Range Start and End Dates
379 -- including Range End Date - NOT BETWEEN since the EEV record existing across
380 -- Range Start date has already been retrieved and dealt with in SELECT (EEV1).
381 -- A new EEV record results in a change of the current hourly rate being used
382 -- in proration calculation.
383 --
384 CURSOR get_entry_chgs ( p_range_start date,
385 p_range_end date) IS
386 SELECT EEV.screen_entry_value,
387 EEV.effective_start_date,
388 EEV.effective_end_date
389 FROM pay_element_entry_values_f EEV
390 WHERE EEV.element_entry_id = p_element_entry_id
391 AND EEV.input_value_id = p_inpval_id
392 AND EEV.effective_start_date > p_range_start
393 AND EEV.effective_end_date <= p_range_end
394 ORDER BY EEV.effective_start_date;
395 --
396 BEGIN
397 --
398 --
399 -- Find all EEV changes, calculate new hourly rate, prorate:
400 -- SELECT (EEV1):
401 -- Select for SINGLE record that includes Period Start Date but does not
402 -- span entire period.
403 -- We know this select will return a row, otherwise there would be no
404 -- EEV changes to detect.
405 --
406 hr_utility.set_location('Prorate_EEV', 103);
407 SELECT EEV.screen_entry_value,
408 GREATEST(EEV.effective_start_date, p_range_start_date),
409 EEV.effective_end_date
410 INTO v_earnings_entry,
411 v_entry_start,
412 v_entry_end
413 FROM pay_element_entry_values_f EEV
414 WHERE EEV.element_entry_id = p_element_entry_id
415 AND EEV.input_value_id = p_inpval_id
416 AND EEV.effective_start_date <= p_range_start_date
417 AND EEV.effective_end_date >= p_range_start_date
418 AND EEV.effective_end_date < p_range_end_date;
419 --
420 hr_utility.set_location('Prorate_EEV', 105);
421 hr_utility.set_location('p_asg_std_hrs=', p_asg_std_hrs);
422 hr_utility.set_location('p_pay_basis='||p_pay_basis, 105);
423 hr_utility.set_location('v_earnings_entry='||v_earnings_entry, 105);
424
425 hr_utility.set_location('calling core udfs', 45);
426 v_curr_hrly_rate := PAY_CORE_FF_UDFS.get_hourly_rate(
427 p_bus_group_id
428 ,p_assignment_id
429 ,p_pay_id
430 ,p_element_entry_id
431 ,p_date_earned
432 ,p_assignment_action_id );
433 --
434 hr_utility.set_location('v_curr_hrly_rate = ', v_curr_hrly_rate);
435 --
436 hr_utility.set_location('Prorate_EEV', 107);
437 hr_utility.set_location('v_entry_start='||to_char(v_entry_start), 107);
438 hr_utility.set_location('v_entry_end='||to_char(v_entry_end), 107);
439
440 v_eev_prorated_earnings := v_eev_prorated_earnings +
441 Prorate_Earnings (
442 p_bg_id => p_bus_group_id,
443 p_assignment_id => p_assignment_id,
444 p_assignment_action_id => p_assignment_action_id,
445 p_element_entry_id => p_element_entry_id,
446 p_date_earned => p_date_earned,
447 p_asg_hrly_rate => v_curr_hrly_rate,
448 p_wsched => p_work_sched,
449 p_asg_std_hours => p_asg_std_hrs,
450 p_asg_std_freq => p_asg_std_freq,
451 p_range_start_date => v_entry_start,
452 p_range_end_date => v_entry_end,
453 p_act_hrs_worked => p_actual_hrs_worked);
454 --
455 hr_utility.set_location('Prorate_EEV.v_eev_prorated_earnings = ', v_eev_prorated_earnings);
456 --
457 -- SELECT (EEV2):
458 OPEN get_entry_chgs (p_range_start_date, p_range_end_date);
459 LOOP
460 --
461 FETCH get_entry_chgs
462 INTO v_earnings_entry,
463 v_entry_start,
464 v_entry_end;
465 EXIT WHEN get_entry_chgs%NOTFOUND;
466 --
467 hr_utility.set_location('Prorate_EEV', 115);
468 --
469 -- For each range of dates found, add to running prorated earnings total.
470 --
471 hr_utility.set_location('Prorate_EEV', 117);
472
473 hr_utility.set_location('calling core udfs', 46);
474 v_curr_hrly_rate := PAY_CORE_FF_UDFS.get_hourly_rate(
475 p_bus_group_id
476 ,p_assignment_id
477 ,p_pay_id
478 ,p_element_entry_id
479 ,p_date_earned
480 ,p_assignment_action_id );
481
482 hr_utility.set_location('v_curr_hrly_rate = ', v_curr_hrly_rate);
483 hr_utility.set_location('Prorate_EEV', 119);
484 --
485 v_eev_prorated_earnings := v_eev_prorated_earnings +
486 Prorate_Earnings (
487 p_bg_id => p_bus_group_id,
488 p_assignment_id => p_assignment_id,
489 p_assignment_action_id => p_assignment_action_id,
490 p_element_entry_id => p_element_entry_id,
491 p_date_earned => p_date_earned,
492 p_asg_hrly_rate => v_curr_hrly_rate,
493 p_wsched => p_work_sched,
494 p_asg_std_hours => p_asg_std_hrs,
495 p_asg_std_freq => p_asg_std_freq,
496 p_range_start_date => v_entry_start,
497 p_range_end_date => v_entry_end,
498 p_act_hrs_worked => p_actual_hrs_worked);
499 --
500 hr_utility.set_location('Prorate_EEV.v_eev_prorated_earnings = ', v_eev_prorated_earnings);
501 --
502 END LOOP;
503 --
504 CLOSE get_entry_chgs;
505 --
506 -- SELECT (EEV3)
507 -- Select for SINGLE record that exists across Period End Date:
508 -- NOTE: Will only return a row if select (2) does not return a row where
509 -- Effective End Date = Period End Date !
510 --
511 hr_utility.set_location('Prorate_EEV', 141);
512 SELECT EEV.screen_entry_value,
513 EEV.effective_start_date,
514 LEAST(EEV.effective_end_date, p_range_end_date)
515 INTO v_earnings_entry,
516 v_entry_start,
517 v_entry_end
518 FROM pay_element_entry_values_f EEV
519 WHERE EEV.element_entry_id = p_element_entry_id
520 AND EEV.input_value_id = p_inpval_id
521 AND EEV.effective_start_date > p_range_start_date
522 AND EEV.effective_start_date <= p_range_end_date
523 AND EEV.effective_end_date > p_range_end_date;
524 --
525 hr_utility.set_location('Prorate_EEV', 147);
526 hr_utility.set_location('calling core udfs', 47);
527 v_curr_hrly_rate := PAY_CORE_FF_UDFS.get_hourly_rate(
528 p_bus_group_id
529 ,p_assignment_id
530 ,p_pay_id
531 ,p_element_entry_id
532 ,p_date_earned
533 ,p_assignment_action_id );
534
535 hr_utility.set_location('v_curr_hrly_rate = ', v_curr_hrly_rate);
536 hr_utility.set_location('Prorate_EEV', 151);
537
538 v_eev_prorated_earnings := v_eev_prorated_earnings +
539 Prorate_Earnings (
540 p_bg_id => p_bus_group_id,
541 p_assignment_id => p_assignment_id,
542 p_assignment_action_id => p_assignment_action_id,
543 p_element_entry_id => p_element_entry_id,
544 p_date_earned => p_date_earned,
545 p_asg_hrly_rate => v_curr_hrly_rate,
546 p_wsched => p_work_sched,
547 p_asg_std_hours => p_asg_std_hrs,
548 p_asg_std_freq => p_asg_std_freq,
549 p_range_start_date => v_entry_start,
550 p_range_end_date => v_entry_end,
551 p_act_hrs_worked => p_actual_hrs_worked);
552
553 hr_utility.set_location('Prorate_EEV.v_eev_prorated_earnings = ', v_eev_prorated_earnings);
554 -- We're Done!
555 hr_utility.set_location('Prorate_EEV', 167);
556 p_actual_hrs_worked := ROUND(p_actual_hrs_worked, 3);
557 p_hrly_rate := v_curr_hrly_rate;
558 RETURN v_eev_prorated_earnings;
559
560 EXCEPTION WHEN NO_DATA_FOUND THEN
561
562 hr_utility.set_location('Prorate_EEV', 177);
563 p_actual_hrs_worked := ROUND(p_actual_hrs_worked, 3);
564 p_hrly_rate := v_curr_hrly_rate;
565 RETURN v_eev_prorated_earnings;
566
567 END Prorate_EEV;
568
569 FUNCTION vacation_pay ( p_vac_hours IN OUT NOCOPY NUMBER,
570 p_asg_id IN NUMBER,
571 p_eff_date IN DATE,
572 p_curr_rate IN NUMBER) RETURN NUMBER IS
573
574 l_vac_pay NUMBER(27,7) DEFAULT 0;
575 l_vac_hours NUMBER(10,7);
576
577 CURSOR get_vac_hours ( v_asg_id NUMBER,
578 v_eff_date DATE) IS
579 select pev.screen_entry_value
580 from per_absence_attendance_types abt,
581 pay_element_entries_f pee,
582 pay_element_entry_values_f pev
583 where pev.input_value_id = abt.input_value_id
584 and abt.absence_category = 'V'
585 and v_eff_date between pev.effective_start_date
586 and pev.effective_end_date
587 and pee.element_entry_id = pev.element_entry_id
588 and pee.assignment_id = v_asg_id
589 and v_eff_date between pee.effective_start_date
590 and pee.effective_end_date;
591
592 -- The "vacation_pay" function looks for hours entered against absence types
593 -- in the current period. The number of hours are summed and multiplied by
594 -- the current rate of Regular Pay..
595 -- Return immediately when no vacation time has been taken.
596 -- Need to loop thru all "Vacation Plans" and check for entries in the current
597 -- period for this assignment.
598
599 BEGIN
600 hr_utility.set_location('get_vac_pay', 11);
601 OPEN get_vac_hours (p_asg_id, p_eff_date);
602 LOOP
603
604 hr_utility.set_location('get_vac_pay', 13);
605 FETCH get_vac_hours
606 INTO l_vac_hours;
607 EXIT WHEN get_vac_hours%NOTFOUND;
608
609 p_vac_hours := p_vac_hours + l_vac_hours;
610
611 END LOOP;
612 CLOSE get_vac_hours;
613 hr_utility.set_location('get_vac_pay', 15);
614
615 IF p_vac_hours <> 0 THEN
616
617 l_vac_pay := p_vac_hours * p_curr_rate;
618
619 END IF;
620
621 RETURN l_vac_pay;
622
623 END vacation_pay;
624
625 FUNCTION sick_pay ( p_sick_hours IN OUT NOCOPY NUMBER,
626 p_asg_id IN NUMBER,
627 p_eff_date IN DATE,
628 p_curr_rate IN NUMBER) RETURN NUMBER IS
629
630 l_sick_pay NUMBER(27,7) DEFAULT 0;
631 l_sick_hours NUMBER(10,7);
632
633 CURSOR get_sick_hours ( v_asg_id NUMBER,
634 v_eff_date DATE) IS
635 select pev.screen_entry_value
636 from per_absence_attendance_types abt,
637 pay_element_entries_f pee,
638 pay_element_entry_values_f pev
639 where pev.input_value_id = abt.input_value_id
640 and abt.absence_category = 'S'
641 and v_eff_date between pev.effective_start_date
642 and pev.effective_end_date
643 and pee.element_entry_id = pev.element_entry_id
644 and pee.assignment_id = v_asg_id
645 and v_eff_date between pee.effective_start_date
646 and pee.effective_end_date;
647
648 -- The "sick_pay" function looks for hours entered against Sick absence types in
649 -- the current period. The number of hours are summed and multiplied by the
650 -- current rate of Regular Pay.
651 -- Return immediately when no sick time has been taken.
652
653 BEGIN
654
655 hr_utility.set_location('get_sick_pay', 11);
656 OPEN get_sick_hours (p_asg_id, p_eff_date);
657 LOOP
658
659 hr_utility.set_location('get_sick_pay', 13);
660 FETCH get_sick_hours
661 INTO l_sick_hours;
662 EXIT WHEN get_sick_hours%NOTFOUND;
663
664 p_sick_hours := p_sick_hours + l_sick_hours;
665
666 END LOOP;
667 CLOSE get_sick_hours;
668 hr_utility.set_location('get_sick_pay', 15);
669
670 IF p_sick_hours <> 0 THEN
671
672 l_sick_pay := p_sick_hours * p_curr_rate;
673
674 END IF;
675
676 RETURN l_sick_pay;
677
678 END sick_pay;
679
680 BEGIN -- Calculate_Period_Earnings
681
682 /* Getting GRE Type of tax unit for Multi GRE functionality
683 Based on the gre type, the segment will be used in where clause.
684
685 T4/RL1 - Segment1
686 T4A/RL1 - Segment11
687 T4A/RL2 - Segment12
688 */
689
690 begin
691 select org_information5
692 into lv_gre_type
693 from hr_organization_information hoi
694 where hoi.org_information_context = 'Canada Employer Identification'
695 and hoi.organization_id = p_tax_unit_id;
696
697 exception
698 when others then
699 null;
700
701 end;
702
703 -- init out param
704 p_actual_hours_worked := 0;
705
706 -- Step (1): Find earnings element input value.
707 -- Get input value and pay basis according to salary admin (if exists).
708 -- If not using salary admin, then get "Rate", "Rate Code", or "Monthly Salary"
709 -- input value id as appropriate (according to ele name).
710
711 IF p_pay_basis IS NOT NULL THEN
712 begin
713 hr_utility.set_location('calculate_period_earnings', 10);
714 SELECT PYB.input_value_id,
715 FCL.meaning,
716 FCL.lookup_code
717 INTO v_inpval_id,
718 v_pay_basis,
719 v_pay_basis_code
720 FROM per_assignments_f ASG,
721 per_pay_bases PYB,
722 hr_lookups FCL
723 WHERE FCL.lookup_code = PYB.pay_basis
724 AND FCL.lookup_type = 'PAY_BASIS'
725 AND FCL.application_id = 800
726 AND PYB.pay_basis_id = ASG.pay_basis_id
727 AND ASG.assignment_id = p_asst_id
728 AND p_date_earned
729 BETWEEN ASG.effective_start_date
730 AND ASG.effective_end_date;
731
732 EXCEPTION WHEN NO_DATA_FOUND THEN
733
734 hr_utility.set_location('calculate_period_earnings', 11);
735 v_period_earn := 0;
736 p_actual_hours_worked := ROUND(p_actual_hours_worked, 3);
737 RETURN v_period_earn;
738
739 -- hr_utility.set_message(801, 'PAY_xxxx_NO_ASST_IN_PERIOD');
740 -- hr_utility.raise_error;
741
742 END;
743
744 ELSIF UPPER(p_inpval_name) = 'RATE' THEN
745 begin
746 hr_utility.set_location('calculate_period_earnings', 13);
747 SELECT IPV.input_value_id
748 INTO v_inpval_id
749 FROM pay_input_values_f IPV,
750 pay_element_types_f ELT
751 WHERE UPPER(ELT.element_name) = 'REGULAR WAGES'
752 AND ELT.element_type_id = IPV.element_type_id
753 AND p_period_start BETWEEN IPV.effective_start_date
754 AND IPV.effective_end_date
755 AND UPPER(IPV.name) = 'RATE';
756 --
757 v_pay_basis := 'HOURLY';
758 --
759 EXCEPTION WHEN NO_DATA_FOUND THEN
760 hr_utility.set_location('calculate_period_earnings', 14);
761 v_period_earn := 0;
762 p_actual_hours_worked := ROUND(p_actual_hours_worked, 3);
763 RETURN v_period_earn;
764 -- hr_utility.set_message(801, 'PAY_xxx_REGWAGE_RATE_NOTFOUND');
765 -- hr_utility.raise_error;
766 end;
767 --
768 ELSIF UPPER(p_inpval_name) = 'RATE CODE' THEN
769 begin
770 hr_utility.set_location('calculate_period_earnings', 15);
771 SELECT IPV.input_value_id
772 INTO v_inpval_id
773 FROM pay_input_values_f IPV,
774 pay_element_types_f ELT
775 WHERE UPPER(ELT.element_name) = 'REGULAR WAGES'
776 AND ELT.element_type_id = IPV.element_type_id
777 AND p_period_start BETWEEN IPV.effective_start_date
778 AND IPV.effective_end_date
779 AND UPPER(IPV.name) = 'RATE CODE';
780 --
781 v_pay_basis := 'HOURLY';
782 --
783 EXCEPTION WHEN NO_DATA_FOUND THEN
784 hr_utility.set_location('calculate_period_earnings', 16);
785 v_period_earn := 0;
786 p_actual_hours_worked := ROUND(p_actual_hours_worked, 3);
787 RETURN v_period_earn;
788 -- hr_utility.set_message(801, 'PAY_xxx_REGWAGE_RATECODE_NOTFOUND');
789 -- hr_utility.raise_error;
790 end;
791 --
792 ELSIF UPPER(p_inpval_name) = 'MONTHLY SALARY' THEN
793 begin
794 hr_utility.set_location('calculate_period_earnings', 17);
795 SELECT IPV.input_value_id
796 INTO v_inpval_id
797 FROM pay_input_values_f IPV,
798 pay_element_types_f ELT
799 WHERE UPPER(ELT.element_name) = 'REGULAR SALARY'
800 AND ELT.element_type_id = IPV.element_type_id
801 AND p_period_start BETWEEN IPV.effective_start_date
802 AND IPV.effective_end_date
803 AND UPPER(IPV.name) = 'MONTHLY SALARY';
804
805 v_pay_basis := 'MONTHLY';
806
807 EXCEPTION WHEN NO_DATA_FOUND THEN
808 hr_utility.set_location('calculate_period_earnings', 18);
809 v_period_earn := 0;
810 p_actual_hours_worked := ROUND(p_actual_hours_worked, 3);
811 RETURN v_period_earn;
812 -- hr_utility.set_message(801, 'PAY_xxx_REGSAL_NOTFOUND');
813 -- hr_utility.raise_error;
814 END;
815
816 END IF;
817
818 /*
819 -- Now know the pay basis for this assignment (v_pay_basis).
820 -- Want to convert entered earnings to pay period earnings.
821 -- For pay basis of Annual, Monthly, Bi-Weekly, Semi-Monthly, or Period (ie. anything
822 -- other than Hourly):
823 -- Annualize entered earnings according to pay basis;
824 -- then divide by number of payroll periods per fiscal yr for pay period earnings.
825 -- 02 Dec 1993:
826 -- Actually, passing in an "Hourly" figure from formula alleviates
827 -- having to convert in here --> we have Convert_Period_Type function
828 -- available to formulae, so a Monthly Salary can be converted before
829 -- calling this fn. Then we just find the hours scheduled for current period as
830 -- per the Hourly pay basis algorithm below.
831 --
832 -- For Hourly pay basis:
833 -- Get hours scheduled for the current period either from:
834 -- 1. ASG work schedule
835 -- 2. ORG default work schedule
836 -- 3. ASG standard hours and frequency
837 -- Multiply the hours scheduled for period by normal Hourly Rate (ie. from
838 -- pre-defined earnings, REGULAR_WAGES_RATE) pay period earnings.
839 --
840 -- In either case, need to find the payroll period type, let's do it upfront:
841 -- Assignment.payroll_id --> Payroll.period_type
842 -- --> Per_time_period_types.number_per_fiscal_year.
843 -- Actually, the number per fiscal year could be found in more than one way:
844 -- Could also go to per_time_period_rules, but would mean decoding the
845 -- payroll period type to an appropriate proc_period_type code.
846 --
847 */
848
849 -- Find # of payroll period types per fiscal year:
850
851 begin
852
853 hr_utility.set_location('calculate_period_earnings', 40);
854 SELECT TPT.number_per_fiscal_year
855 INTO v_pay_periods_per_year
856 FROM pay_payrolls_f PRL,
857 per_time_period_types TPT
858 WHERE TPT.period_type = PRL.period_type
859 AND p_period_end between PRL.effective_start_date
860 and PRL.effective_end_date
861 AND PRL.payroll_id = p_payroll_id
862 AND PRL.business_group_id + 0 = p_bus_grp_id;
863
864 exception when NO_DATA_FOUND then
865
866 hr_utility.set_location('calculate_period_earnings', 41);
867 v_period_earn := 0;
868 p_actual_hours_worked := ROUND(p_actual_hours_worked, 3);
869 RETURN v_period_earn;
870 -- hr_utility.set_message(801, 'PAY_xxxx_NUM_PER_FY_NOT_FOUND');
871 -- hr_utility.raise_error;
872
873 end;
874
875 /*
876 -- Pay basis is hourly,
877 -- Get hours scheduled for the current period either from:
878 -- 1. ASG work schedule
879 -- 2. ORG default work schedule
880 -- 3. ASG standard hours and frequency
881 -- Do we pass in Work Schedule from asst scl db item? Yes
882 -- 10-JAN-1996 hparicha : We no longer assume "standard hours" represent
883 -- a weekly figure. We also no longer use a week as the basis for annualization,
884 -- even when using work schedule - ie. need to find ACTUAL scheduled hours, not
885 -- actual hours for a week, converted to a period figure.
886 */
887 --
888 hr_utility.set_location('calculate_period_earnings', 45);
889 /* IF p_work_schedule <> 'NOT ENTERED' THEN
890 --
891 -- Find hours worked between period start and end dates.
892 --
893
894 -- v_ws_id := to_number(p_work_schedule);
895 v_ws_id := fnd_number.canonical_to_number(p_work_schedule);
896
897 --
898 SELECT user_column_name
899 INTO v_work_sched_name
900 FROM pay_user_columns
901 WHERE user_column_id = v_ws_id
902 AND NVL(business_group_id, p_bus_grp_id) = p_bus_grp_id
903 AND NVL(legislation_code,'CA') = 'CA';
904 --
905 */
906 hr_utility.set_location('calling core udfs', 45);
907 v_hrs_per_range := PAY_CORE_FF_UDFS.calculate_actual_hours_worked (
908 p_assignment_action_id
909 ,p_asst_id
910 ,p_bus_grp_id
911 ,p_ele_entry_id
912 ,p_date_earned
913 ,p_period_start
914 ,p_period_end
915 ,NULL
916 ,'Y'
917 ,'BUSY'
918 ,'CA'--p_legislation_code
919 ,v_schedule_source
920 ,v_schedule
921 ,v_return_status
922 ,v_return_message);
923 /*
924 ELSE
925
926 v_hrs_per_range := Standard_Hours_Worked( p_asst_std_hrs,
927 p_period_start,
928 p_period_end,
929 p_asst_std_freq);
930
931 END IF;
932 */
933
934 -- Compute earnings and actual hours PER PAY PERIOD.
935 -- Convert HOURLY earnings to PERIOD earnings.
936 -- Passing "NULL" freq to Convert_Period_Type will convert
937 -- to/from the payroll time period type.
938
939 hr_utility.set_location('calculate_period_earnings', 46);
940 v_period_earn := Convert_Period_Type( p_bus_grp_id,
941 p_payroll_id,
942 p_assignment_action_id,
943 p_asst_id ,
944 p_ele_entry_id,
945 p_date_earned ,
946 p_work_schedule,
947 p_asst_std_hrs,
948 p_ass_hrly_figure,
949 'HOURLY',
950 NULL,
951 p_period_start,
952 p_period_end,
953 p_asst_std_freq);
954
955 hr_utility.set_location('calculate_period_earnings', 47);
956
957 p_actual_hours_worked := v_hrs_per_range;
958 hr_utility.set_location('Calc_PE actual_hours_worked = ', p_actual_hours_worked);
959
960 -- Check that Pro-rate = 'Y' before continuing.
961
962 IF p_prorate = 'N' THEN
963
964 -- Done!!! No pro-ration...
965 hr_utility.set_location('calculate_period_earnings', 49);
966 p_actual_hours_worked := ROUND(p_actual_hours_worked, 3);
967
968 RETURN v_period_earn;
969
970 END IF;
971
972 -- Before going into proration, check for ASG and EEV changes within
973 -- period dates -> if none are found then return v_period_earn and we're done!
974 -- This is the 80-90% case so we want to get out as quickly as possible.
975
976 -- (ASG1) Select for SINGLE record that includes Period Start Date but does not
977 -- span entire period. If no row returned, then ASG record spans period
978 -- and there is no need to run selects (ASG2) or (ASG3).
979
980 hr_utility.set_location('calculate_period_earnings', 51);
981
982 /* ************************************************************** */
983
984 begin
985
986 select 1 INTO l_asg_info_changes
987 from dual
988 where exists (
989 SELECT 1
990 FROM per_assignments_f ASG,
991 per_assignment_status_types AST,
992 hr_soft_coding_keyflex SCL
993 WHERE ASG.assignment_id = p_asst_id
994 AND ASG.effective_start_date <= p_period_start
995 AND ASG.effective_end_date >= p_period_start
996 AND ASG.effective_end_date < p_period_end
997 AND AST.assignment_status_type_id = ASG.assignment_status_type_id
998 AND AST.per_system_status = 'ACTIVE_ASSIGN'
999 AND SCL.soft_coding_keyflex_id = ASG.soft_coding_keyflex_id
1000 AND decode(lv_gre_type, 'T4A/RL1', segment11, 'T4A/RL2', segment12,
1001 SCL.segment1) = to_char(p_tax_unit_id)
1002 AND SCL.enabled_flag = 'Y');
1003
1004 -- l_asg_info_changes := 1;
1005
1006 -- 25 May 1994:
1007 -- Changing ASG status check to be for Payroll Status of 'Process'
1008 -- AND AST.per_system_status = 'ACTIVE_ASSIGN'
1009 -- AND AST.pay_system_status = 'P'
1010
1011 -- Need to prorate b/c of ASG changes, but let's look for EEV changes
1012 -- for future reference:
1013
1014 l_mid_period_asg_change := TRUE;
1015
1016 hr_utility.set_location('calculate_period_earnings', 56);
1017
1018 begin
1019
1020 select 1 INTO l_eev_info_changes
1021 from dual
1022 where exists (
1023 SELECT 1
1024 FROM pay_element_entry_values_f EEV
1025 WHERE EEV.element_entry_id = p_ele_entry_id
1026 AND EEV.input_value_id+0 = v_inpval_id
1027 AND (
1028 (EEV.effective_start_date <= p_period_start
1029 AND EEV.effective_end_date >= p_period_start
1030 AND EEV.effective_end_date < p_period_end)
1031 OR (EEV.effective_start_date between p_period_start and p_period_end)
1032 )
1033 );
1034
1035 -- Prorate: l_asg_info_changes EXIST,
1036 -- l_eev_info_changes EXIST
1037
1038 exception
1039
1040 WHEN NO_DATA_FOUND THEN
1041 l_eev_info_changes := 0;
1042
1043 -- Prorate: l_asg_info_changes EXIST,
1044 -- l_eev_info_changes DO NOT EXIST
1045
1046 end;
1047
1048 exception
1049
1050 WHEN NO_DATA_FOUND THEN
1051
1052 l_asg_info_changes := 0;
1053
1054 end;
1055
1056 IF l_asg_info_changes = 0 THEN
1057
1058 -- (ASG1.1)
1059 -- Actually need to select for ASG record that STARTS within period
1060 -- ie. becomes active on a date later than start date!
1061
1062 hr_utility.set_location('calculate_period_earnings', 52);
1063
1064 begin
1065
1066 select 1 INTO l_asg_info_changes
1067 from dual
1068 where exists (
1069 SELECT 1
1070 FROM per_assignments_f ASG,
1071 per_assignment_status_types AST,
1072 hr_soft_coding_keyflex SCL
1073 WHERE ASG.assignment_id = p_asst_id
1074 AND ASG.effective_start_date > p_period_start
1075 AND ASG.effective_start_date <= p_period_end
1076 AND AST.assignment_status_type_id = ASG.assignment_status_type_id
1077 AND AST.per_system_status = 'ACTIVE_ASSIGN'
1078 AND SCL.soft_coding_keyflex_id = ASG.soft_coding_keyflex_id
1079 AND decode(lv_gre_type, 'T4A/RL1', SCL.segment11, 'T4A/RL2', SCL.segment12,
1080 SCL.segment1) = to_char(p_tax_unit_id)
1081 AND SCL.enabled_flag = 'Y');
1082
1083 l_mid_period_asg_change := TRUE;
1084
1085 -- Need to prorate b/c of mid period ASG changes, but let's look for
1086 -- EEV changes for future reference:
1087
1088 hr_utility.set_location('calculate_period_earnings', 55);
1089
1090 begin
1091
1092 select 1 INTO l_eev_info_changes
1093 from dual
1094 where exists (
1095 SELECT 1
1096 FROM pay_element_entry_values_f EEV
1097 WHERE EEV.element_entry_id = p_ele_entry_id
1098 AND EEV.input_value_id+0 = v_inpval_id
1099 AND EEV.effective_start_date <= p_period_start
1100 AND EEV.effective_end_date >= p_period_start
1101 AND EEV.effective_end_date < p_period_end);
1102
1103 -- Prorate: l_asg_info_changes EXIST,
1104 -- l_eev_info_changes EXIST
1105
1106 exception
1107
1108 WHEN NO_DATA_FOUND THEN
1109 l_eev_info_changes := 0;
1110
1111 -- Prorate: l_asg_info_changes EXIST,
1112 -- l_eev_info_changes DO NOT EXIST
1113
1114 end;
1115
1116 exception
1117
1118 WHEN NO_DATA_FOUND THEN
1119 l_asg_info_changes := 0;
1120
1121 end;
1122
1123 END IF;
1124
1125 IF l_asg_info_changes = 0 THEN -- Still
1126
1127 -- Check for EEV changes, if also none -> return v_period_earn and done:
1128 -- (EEV1) Select for SINGLE record that includes Period Start Date but
1129 -- does not span entire period. If no row returned, then EEV record
1130 -- spans period and there is no need to run selects (EEV2) or (EEV3)
1131 -- and we can stop now!
1132
1133 begin
1134
1135 hr_utility.set_location('calculate_period_earnings', 53);
1136
1137 select 1 INTO l_eev_info_changes
1138 from dual
1139 where exists (
1140 SELECT 1
1141 FROM pay_element_entry_values_f EEV
1142 WHERE EEV.element_entry_id = p_ele_entry_id
1143 AND EEV.input_value_id+0 = v_inpval_id
1144 AND EEV.effective_start_date <= p_period_start
1145 AND EEV.effective_end_date >= p_period_start
1146 AND EEV.effective_end_date < p_period_end);
1147
1148 -- Proration will occur for l_asg_info_changes DO NOT EXIST and
1149 -- l_eev_info_changes EXIST
1150
1151 exception
1152
1153 WHEN NO_DATA_FOUND THEN
1154 -- This is mainline fallthru point.
1155 -- l_asg_info_changes AND l_eev_info_changes DO NOT EXIST.
1156 -- Done!!! No pro-ration required b/c no ASG or EEV changes exist
1157 -- this period!
1158 -- Either there are no changes to an Active Assignment OR
1159 -- the assignment was not active at all this period.
1160 -- Check assignment status of current asg record.
1161
1162 SELECT AST.per_system_status
1163 INTO v_asg_status
1164 FROM per_assignments_f ASG,
1165 per_assignment_status_types AST,
1166 hr_soft_coding_keyflex SCL
1167 WHERE ASG.assignment_id = p_asst_id
1168 AND p_period_start BETWEEN ASG.effective_start_date
1169 AND ASG.effective_end_date
1170 AND AST.assignment_status_type_id = ASG.assignment_status_type_id
1171 AND SCL.soft_coding_keyflex_id = ASG.soft_coding_keyflex_id
1172 AND decode(lv_gre_type, 'T4A/RL1', segment11, 'T4A/RL2', SCL.segment12,
1173 SCL.segment1) = to_char(p_tax_unit_id)
1174 AND SCL.enabled_flag = 'Y';
1175
1176 IF v_asg_status <> 'ACTIVE_ASSIGN' THEN
1177
1178 v_period_earn := 0;
1179 p_actual_hours_worked := 0;
1180
1181 END IF;
1182
1183 p_actual_hours_worked := ROUND(p_actual_hours_worked, 3);
1184 RETURN v_period_earn;
1185
1186 end;
1187
1188 END IF;
1189
1190 /* ************************************************************** */
1191
1192 -- If code reaches here, then we're prorating for one reason or the other.
1193 -- We can check l_asg_info_changes and l_eev_info_changes to see what needs
1194 -- to be done.
1195 -- We'll use these flags in the interest of efficiency:
1196 -- l_asg_info_changes = 0 ==> No ASG changes
1197 -- l_eev_info_changes = 0 ==> No EEV changes
1198 --
1199 -- *********************************************************************
1200 -- Step (2): is Work_Schedule_Total_Hours(ws, from, to) code or fn call.
1201 -- *********************************************************************
1202 --
1203 -- *********************************************************************
1204 -- Step (3): Find pay period salary as hourly rate.
1205 -- 02 Dec 1993: We're passing in an hourly figure already!!!
1206 -- *********************************************************************
1207 /*
1208 -- Step (4): Perform any necessary pro-ration.
1209 -- In declaration we have:
1210 -- Need to check if cursor sql w/max and min works; otherwise do check after
1211 -- fetch. This cursor *FAILS* to retreive a rec if NO CHANGES occur in period.
1212 -- This is the 90% case where we want to just fall thru asap. Same will apply
1213 -- for element entry change cursor.
1214 -- Remember, we need asst recs in the same tax unit as that passed in.
1215 -- So the start date of the work info record w/the same tax unit must be less
1216 -- than or equal to the start date of the asst rec. That's all we have to
1217 -- check since a change to tax unit will cause date-effective update to asst.
1218 -- ^^^ Need to verify that tax-unit changes are date-effective and that they
1219 -- **are reflected in per_assignments_f**. Also need to know what other
1220 -- changes result in date-effective update to work_info tab and whether
1221 -- or not all changes date-effectively affect assignment. They SHOULD be
1222 -- reflected in asst since this would be consistent w/SCL keyflex behaviour.
1223 -- A: Yes they are. (13 May 1994 HParicha)
1224 -- Remember, need to check work schedule before each call to
1225 -- Work_Schedule_Total_Hours.
1226 -- OK so to pro-rate earnings, determine exactly what needs to be done up
1227 -- front in order of expected frequency:
1228 -- 1. Assignment Info Changes Only
1229 -- 2. Element Entry Info Changes Only
1230 -- 3. Both ASG and EEV info changes
1231
1232 */
1233 IF (l_asg_info_changes > 0) AND (l_eev_info_changes = 0) THEN
1234
1235 -- Use hourly rate passed in (p_ass_hrly_figure) and use this to prorate
1236 -- thru all ASG changes. No need to check for change in hourly rate.
1237
1238 -- SELECT (ASG1):
1239 -- Select for SINGLE record that includes Period Start Date but does not
1240 -- span entire period.
1241 -- We know this select will return a row, otherwise there would be no
1242 -- ASG changes to detect.
1243 -- Actually it might NOT return a row - the mid period change may have
1244 -- been a mid period hire or return from leave of absence, in which case
1245 -- you would not have an assignment record to 'Process' that spans the
1246 -- Start Date of the period!
1247
1248 p_actual_hours_worked := 0;
1249 hr_utility.set_location('calculate_period_earnings', 70);
1250 -- IF NOT l_mid_period_asg_change THEN
1251
1252 begin
1253
1254 hr_utility.set_location('calculate_period_earnings', 71);
1255 SELECT GREATEST(ASG.effective_start_date, p_period_start),
1256 ASG.effective_end_date,
1257 NVL(ASG.NORMAL_HOURS, 0),
1258 NVL(HRL.meaning, 'NOT ENTERED'),
1259 NVL(HRL.lookup_code, 'NOT ENTERED'),
1260 NVL(SCL.segment4, 'NOT ENTERED')
1261 INTO v_range_start,
1262 v_range_end,
1263 v_asst_std_hrs,
1264 v_asst_std_freq,
1265 v_asst_std_freq_code,
1266 v_work_schedule
1267 FROM per_assignments_f ASG,
1268 per_assignment_status_types AST,
1269 hr_soft_coding_keyflex SCL,
1270 hr_lookups HRL
1271 WHERE ASG.assignment_id = p_asst_id
1272 AND ASG.business_group_id + 0 = p_bus_grp_id
1273 AND ASG.effective_start_date <= p_period_start
1274 AND ASG.effective_end_date >= p_period_start
1275 AND ASG.effective_end_date < p_period_end
1276 AND AST.assignment_status_type_id = ASG.assignment_status_type_id
1277 AND AST.per_system_status = 'ACTIVE_ASSIGN'
1278 AND SCL.soft_coding_keyflex_id = ASG.soft_coding_keyflex_id
1279 AND decode(lv_gre_type, 'T4A/RL1', segment11, 'T4A/RL2', SCL.segment12,
1280 SCL.segment1) = to_char(p_tax_unit_id)
1281 AND SCL.enabled_flag = 'Y'
1282 AND HRL.lookup_code(+) = ASG.frequency
1283 AND HRL.lookup_type(+) = 'FREQUENCY';
1284
1285 -- 25 May 1994:
1286 -- Changing ASG status check to be for Payroll Status of 'Process'
1287 -- AND AST.per_system_status = 'ACTIVE_ASSIGN'
1288 -- AND AST.pay_system_status = 'P'
1289
1290 -- Prorate using hourly rate passed in as param:
1291 -- Should this become a function from here...
1292
1293 hr_utility.set_location('calculate_period_earnings', 72);
1294 v_prorated_earnings := v_prorated_earnings +
1295 Prorate_Earnings (
1296 p_bg_id => p_bus_grp_id,
1297 p_assignment_id => p_asst_id,
1298 p_assignment_action_id => p_assignment_action_id,
1299 p_element_entry_id => p_ele_entry_id,
1300 p_date_earned => p_date_earned,
1301 p_asg_hrly_rate => p_ass_hrly_figure,
1302 p_wsched => v_work_schedule,
1303 p_asg_std_hours => v_asst_std_hrs,
1304 p_asg_std_freq => v_asst_std_freq_code,
1305 p_range_start_date => v_range_start,
1306 p_range_end_date => v_range_end,
1307 p_act_hrs_worked => p_actual_hours_worked);
1308
1309 hr_utility.set_location('Calculate_Period_Earnings.v_prorated_earnings = ', v_prorated_earnings);
1310
1311 -- Just in case mid period change does not span Start of Period!
1312
1313 EXCEPTION WHEN NO_DATA_FOUND THEN
1314 NULL;
1315
1316 end;
1317
1318 -- END IF;
1319
1320 -- SELECT (ASG2)
1321 -- Select for ALL records that are WITHIN Period Start and End Dates
1322 -- including Period End Date.
1323 -- Not BETWEEN Period Start/End since we already found a record including
1324 -- Start Date in select (1) above.
1325
1326 hr_utility.set_location('calculate_period_earnings', 77);
1327 OPEN get_asst_chgs; -- SELECT (ASG2)
1328 LOOP
1329
1330 FETCH get_asst_chgs
1331 INTO v_range_start,
1332 v_range_end,
1333 v_asst_std_hrs,
1334 v_asst_std_freq,
1335 v_asst_std_freq_code,
1336 v_work_schedule;
1337 EXIT WHEN get_asst_chgs%NOTFOUND;
1338
1339 hr_utility.set_location('calculate_period_earnings', 79);
1340
1341 -- For each range of dates found, add to running prorated earnings total.
1342
1343 hr_utility.set_location('calculate_period_earnings', 81);
1344 v_prorated_earnings := v_prorated_earnings +
1345 Prorate_Earnings (
1346 p_bg_id => p_bus_grp_id,
1347 p_assignment_id => p_asst_id,
1348 p_assignment_action_id => p_assignment_action_id,
1349 p_element_entry_id => p_ele_entry_id,
1350 p_date_earned => p_date_earned,
1351 p_asg_hrly_rate => p_ass_hrly_figure,
1352 p_wsched => v_work_schedule,
1353 p_asg_std_hours => v_asst_std_hrs,
1354 p_asg_std_freq => v_asst_std_freq_code,
1355 p_range_start_date => v_range_start,
1356 p_range_end_date => v_range_end,
1357 p_act_hrs_worked => p_actual_hours_worked);
1358
1359 hr_utility.set_location('Calculate_Period_Earnings.v_prorated_earnings = ', v_prorated_earnings);
1360
1361 END LOOP;
1362
1363 CLOSE get_asst_chgs;
1364
1365 -- SELECT (ASG3)
1366 -- Select for SINGLE record that exists across Period End Date:
1367 -- NOTE: Will only return a row if select (2) does not return a row where
1368 -- Effective End Date = Period End Date !
1369
1370 begin
1371
1372 hr_utility.set_location('calculate_period_earnings', 89);
1373 SELECT ASG.effective_start_date,
1374 LEAST(ASG.effective_end_date, p_period_end),
1375 NVL(ASG.normal_hours, 0),
1376 NVL(HRL.meaning, 'NOT ENTERED'),
1377 NVL(HRL.lookup_code, 'NOT ENTERED'),
1378 NVL(SCL.segment4, 'NOT ENTERED')
1379 INTO v_range_start,
1380 v_range_end,
1381 v_asst_std_hrs,
1382 v_asst_std_freq,
1383 v_asst_std_freq_code,
1384 v_work_schedule
1385 FROM hr_soft_coding_keyflex SCL,
1386 per_assignment_status_types AST,
1387 per_assignments_f ASG,
1388 hr_lookups HRL
1389 WHERE ASG.assignment_id = p_asst_id
1390 AND ASG.business_group_id + 0 = p_bus_grp_id
1391 AND ASG.effective_start_date > p_period_start
1392 AND ASG.effective_start_date <= p_period_end
1393 AND ASG.effective_end_date > p_period_end
1394 AND AST.assignment_status_type_id = ASG.assignment_status_type_id
1395 AND AST.per_system_status = 'ACTIVE_ASSIGN'
1396 AND SCL.soft_coding_keyflex_id = ASG.soft_coding_keyflex_id
1397 AND decode(lv_gre_type, 'T4A/RL1', segment11, 'T4A/RL2', SCL.segment12,
1398 SCL.segment1) = to_char(p_tax_unit_id)
1399 AND SCL.enabled_flag = 'Y'
1400 AND HRL.lookup_code(+) = ASG.frequency
1401 AND HRL.lookup_type(+) = 'FREQUENCY';
1402
1403 -- 25 May 1994:
1404 -- Changing ASG status check to be for Payroll Status of 'Process'
1405 -- AND AST.per_system_status = 'ACTIVE_ASSIGN'
1406 -- AND AST.pay_system_status = 'P'
1407
1408 hr_utility.set_location('calculate_period_earnings', 91);
1409 v_prorated_earnings := v_prorated_earnings +
1410 Prorate_Earnings (
1411 p_bg_id => p_bus_grp_id,
1412 p_assignment_id => p_asst_id,
1413 p_assignment_action_id => p_assignment_action_id,
1414 p_element_entry_id => p_ele_entry_id,
1415 p_date_earned => p_date_earned,
1416 p_asg_hrly_rate => p_ass_hrly_figure,
1417 p_wsched => v_work_schedule,
1418 p_asg_std_hours => v_asst_std_hrs,
1419 p_asg_std_freq => v_asst_std_freq_code,
1420 p_range_start_date => v_range_start,
1421 p_range_end_date => v_range_end,
1422 p_act_hrs_worked => p_actual_hours_worked);
1423
1424 hr_utility.set_location('Calculate_Period_Earnings.v_prorated_earnings = ', v_prorated_earnings);
1425
1426 -- We're done!
1427
1428 hr_utility.set_location('calculate_period_earnings', 101);
1429
1430 p_actual_hours_worked := ROUND(p_actual_hours_worked, 3);
1431 RETURN v_prorated_earnings;
1432
1433 EXCEPTION WHEN NO_DATA_FOUND THEN
1434 -- (ASG3) returned no rows, but we're done anyway!
1435 hr_utility.set_location('calculate_period_earnings', 102);
1436
1437 p_actual_hours_worked := ROUND(p_actual_hours_worked, 3);
1438 RETURN v_prorated_earnings;
1439
1440 END;
1441
1442 ELSIF (l_asg_info_changes = 0) AND (l_eev_info_changes > 0) THEN
1443
1444 hr_utility.set_location('calculate_period_earnings', 103);
1445 p_actual_hours_worked := 0;
1446 v_prorated_earnings := v_prorated_earnings +
1447 Prorate_EEV (
1448 p_bus_group_id => p_bus_grp_id,
1449 p_assignment_id => p_asst_id,
1450 p_assignment_action_id => p_assignment_action_id,
1451 p_date_earned => p_date_earned,
1452 p_pay_id => p_payroll_id,
1453 p_work_sched => p_work_schedule,
1454 p_asg_std_hrs => p_asst_std_hrs,
1455 p_asg_std_freq => p_asst_std_freq,
1456 p_pay_basis => p_pay_basis,
1457 p_hrly_rate => v_curr_hrly_rate,
1458 p_range_start_date => p_period_start,
1459 p_range_end_date => p_period_end,
1460 p_actual_hrs_worked => p_actual_hours_worked,
1461 p_element_entry_id => p_ele_entry_id,
1462 p_inpval_id => v_inpval_id);
1463
1464 -- We're Done!
1465 hr_utility.set_location('calculate_period_earnings', 127);
1466
1467 p_actual_hours_worked := ROUND(p_actual_hours_worked, 3);
1468 RETURN v_prorated_earnings;
1469
1470 ELSE
1471
1472 -- We assume both l_asg_info_changes and l_eev_info_changes > 0 since
1473 -- we wouldn't have reached this section of code if they both = 0 !
1474 -- So cycle thru ASG changes; for each range found for ASG change,
1475 -- check for EEV changes IN THAT RANGE! If none are found, then
1476 -- prorate with current (latest) hourly rate figure. If EEV changes
1477 -- are found, then call EEV proration and continue when complete.
1478
1479 -- SELECT (ASG1.2):
1480 -- Select for SINGLE record that includes Period Start Date but does not
1481 -- span entire period.
1482 -- We know this select will return a row, otherwise there would be no
1483 -- ASG changes to detect.
1484
1485 p_actual_hours_worked := 0;
1486
1487 -- Since we KNOW both asg and eev changes occur, then we want current
1488 -- (latest) hourly rate to be figure AS OF BEGINNING OF PERIOD for starters.
1489 -- NOT! v_curr_hrly_rate := p_ass_hrly_figure;
1490
1491 begin
1492
1493 hr_utility.set_location('calculate_period_earnings', 128);
1494 SELECT EEV.screen_entry_value
1495 INTO v_earnings_entry
1496 FROM pay_element_entry_values_f EEV
1497 WHERE EEV.element_entry_id = p_ele_entry_id
1498 AND EEV.input_value_id = v_inpval_id
1499 --bug 5617540 starts
1500 AND p_period_start between EEV.effective_start_date
1501 AND EEV.effective_end_date;
1502 /* --
1503 AND EEV.effective_start_date <= p_period_start
1504 AND EEV.effective_end_date >= p_period_start
1505 AND EEV.effective_end_date < p_period_end;*/
1506 --bug 5617540 ends
1507
1508 SELECT GREATEST(ASG.effective_start_date, p_period_start),
1509 ASG.effective_end_date,
1510 NVL(ASG.NORMAL_HOURS, 0),
1511 NVL(HRL.meaning, 'NOT ENTERED'),
1512 NVL(HRL.lookup_code, 'NOT ENTERED'),
1513 NVL(SCL.segment4, 'NOT ENTERED')
1514 INTO v_range_start,
1515 v_range_end,
1516 v_asst_std_hrs,
1517 v_asst_std_freq,
1518 v_asst_std_freq_code,
1519 v_work_schedule
1520 FROM per_assignments_f ASG,
1521 per_assignment_status_types AST,
1522 hr_soft_coding_keyflex SCL,
1523 hr_lookups HRL
1524 WHERE ASG.assignment_id = p_asst_id
1525 AND ASG.business_group_id + 0 = p_bus_grp_id
1526 AND ASG.effective_start_date <= p_period_start
1527 AND ASG.effective_end_date >= p_period_start
1528 AND ASG.effective_end_date < p_period_end
1529 AND AST.assignment_status_type_id = ASG.assignment_status_type_id
1530 AND AST.per_system_status = 'ACTIVE_ASSIGN'
1531 AND SCL.soft_coding_keyflex_id = ASG.soft_coding_keyflex_id
1532 AND decode(lv_gre_type, 'T4A/RL1', segment11, 'T4A/RL2', SCL.segment12,
1533 SCL.segment1) = to_char(p_tax_unit_id)
1534 AND SCL.enabled_flag = 'Y'
1535 AND HRL.lookup_code(+) = ASG.frequency
1536 AND HRL.lookup_type(+) = 'FREQUENCY';
1537
1538 hr_utility.set_location('v_earnings_entry='||v_earnings_entry, 129);
1539 hr_utility.set_location('v_asst_std_hrs=', v_asst_std_hrs);
1540 hr_utility.set_location('calling core udfs', 48);
1541 v_curr_hrly_rate := PAY_CORE_FF_UDFS.get_hourly_rate(
1542 p_bus_grp_id
1543 ,p_asst_id
1544 ,p_payroll_id
1545 ,p_ele_entry_id
1546 ,p_date_earned
1547 ,p_assignment_action_id );
1548
1549 hr_utility.set_location('v_curr_hrly_rate = ', v_curr_hrly_rate);
1550 hr_utility.set_location('calculate_period_earnings', 130);
1551 -- IF NOT l_mid_period_asg_change THEN
1552
1553 -- Do not have to do this first bit if Mid period hire/active asg occurs:
1554
1555 -- 25 May 1994:
1556 -- Changing ASG status check to be for Payroll Status of 'Process'
1557 -- AND AST.per_system_status = 'ACTIVE_ASSIGN'
1558 -- AND AST.pay_system_status = 'P'
1559
1560 -- (EEV1) Select for SINGLE record that includes Period Start Date but
1561 -- does not span entire period.
1562
1563 hr_utility.set_location('calculate_period_earnings', 132);
1564 SELECT COUNT(EEV.element_entry_value_id)
1565 INTO l_eev_info_changes
1566 FROM pay_element_entry_values_f EEV
1567 WHERE EEV.element_entry_id = p_ele_entry_id
1568 AND EEV.input_value_id = v_inpval_id
1569 AND EEV.effective_start_date <= v_range_start
1570 AND EEV.effective_end_date >= v_range_start
1571 AND EEV.effective_end_date < v_range_end;
1572
1573 IF l_eev_info_changes = 0 THEN
1574 -- Prorate using latest hourly rate:
1575 hr_utility.set_location('calculate_period_earnings', 128);
1576 SELECT EEV.screen_entry_value
1577 INTO v_earnings_entry
1578 FROM pay_element_entry_values_f EEV
1579 WHERE EEV.element_entry_id = p_ele_entry_id
1580 AND EEV.input_value_id = v_inpval_id
1581 AND v_range_end BETWEEN EEV.effective_start_date
1582 AND EEV.effective_end_date;
1583
1584 hr_utility.set_location('v_earnings_entry='||v_earnings_entry, 129);
1585 hr_utility.set_location('v_asst_std_hrs=', v_asst_std_hrs);
1586 hr_utility.set_location('calling core udfs', 49);
1587 v_curr_hrly_rate := PAY_CORE_FF_UDFS.get_hourly_rate(
1588 p_bus_grp_id
1589 ,p_asst_id
1590 ,p_payroll_id
1591 ,p_ele_entry_id
1592 ,p_date_earned
1593 ,p_assignment_action_id );
1594
1595 hr_utility.set_location('v_curr_hrly_rate = ', v_curr_hrly_rate);
1596 -- Should this become a function from here...
1597 hr_utility.set_location('calculate_period_earnings', 133);
1598 v_prorated_earnings := v_prorated_earnings +
1599 Prorate_Earnings (
1600 p_bg_id => p_bus_grp_id,
1601 p_assignment_id => p_asst_id,
1602 p_assignment_action_id => p_assignment_action_id,
1603 p_element_entry_id => p_ele_entry_id,
1604 p_date_earned => p_date_earned,
1605 p_asg_hrly_rate => v_curr_hrly_rate,
1606 p_wsched => v_work_schedule,
1607 p_asg_std_hours => v_asst_std_hrs,
1608 p_asg_std_freq => v_asst_std_freq_code,
1609 p_range_start_date => v_range_start,
1610 p_range_end_date => v_range_end,
1611 p_act_hrs_worked => p_actual_hours_worked);
1612
1613 hr_utility.set_location('Calculate_Period_Earnings.v_prorated_earnings = ', v_prorated_earnings);
1614
1615 ELSE
1616 -- Do proration for this ASG range by EEV !
1617
1618 hr_utility.set_location('calculate_period_earnings', 134);
1619 v_prorated_earnings := v_prorated_earnings +
1620 Prorate_EEV (
1621 p_bus_group_id => p_bus_grp_id,
1622 p_assignment_id => p_asst_id,
1623 p_assignment_action_id => p_assignment_action_id,
1624 p_date_earned => p_date_earned,
1625 p_pay_id => p_payroll_id,
1626 p_work_sched => v_work_schedule,
1627 p_asg_std_hrs => v_asst_std_hrs,
1628 p_asg_std_freq => v_asst_std_freq_code,
1629 p_pay_basis => v_pay_basis_code,
1630 p_hrly_rate => v_curr_hrly_rate,
1631 p_range_start_date => v_range_start,
1632 p_range_end_date => v_range_end,
1633 p_actual_hrs_worked => p_actual_hours_worked,
1634 p_element_entry_id => p_ele_entry_id,
1635 p_inpval_id => v_inpval_id);
1636
1637 END IF; -- EEV info changes
1638
1639 EXCEPTION WHEN NO_DATA_FOUND THEN
1640 NULL;
1641
1642 end;
1643
1644 -- END IF; -- Mid Period Active ASG.
1645
1646 -- SELECT (ASG2.2)
1647 -- Select for ALL records that are WITHIN Period Start and End Dates
1648 -- including Period End Date.
1649 -- Not BETWEEN Period Start/End since we already found a record including
1650 -- Start Date in select (1) above.
1651
1652 hr_utility.set_location('calculate_period_earnings', 135);
1653 OPEN get_asst_chgs; -- SELECT (ASG2)
1654 LOOP
1655
1656 FETCH get_asst_chgs
1657 INTO v_range_start,
1658 v_range_end,
1659 v_asst_std_hrs,
1660 v_asst_std_freq,
1661 v_asst_std_freq_code,
1662 v_work_schedule;
1663 EXIT WHEN get_asst_chgs%NOTFOUND;
1664
1665 hr_utility.set_location('calculate_period_earnings', 79);
1666
1667 -- For each range of dates found, add to running prorated earnings total.
1668
1669 -- Check for EEV changes, if also none -> return v_period_earn and done:
1670 -- (EEV1) Select for SINGLE record that includes Period Start Date but
1671 -- does not span entire period. If no row returned, then EEV record
1672 -- spans period and there is no need to run selects (EEV2) or (EEV3)
1673 -- and we can stop now!
1674
1675 hr_utility.set_location('calculate_period_earnings', 133);
1676 SELECT COUNT(EEV.element_entry_value_id)
1677 INTO l_eev_info_changes
1678 FROM pay_element_entry_values_f EEV
1679 WHERE EEV.element_entry_id = p_ele_entry_id
1680 AND EEV.input_value_id = v_inpval_id
1681 AND EEV.effective_start_date <= v_range_start
1682 AND EEV.effective_end_date >= v_range_start
1683 AND EEV.effective_end_date < v_range_end;
1684
1685 IF l_eev_info_changes = 0 THEN
1686 -- Prorate using latest hourly rate:
1687 hr_utility.set_location('calculate_period_earnings', 128);
1688 SELECT EEV.screen_entry_value
1689 INTO v_earnings_entry
1690 FROM pay_element_entry_values_f EEV
1691 WHERE EEV.element_entry_id = p_ele_entry_id
1692 AND EEV.input_value_id = v_inpval_id
1693 AND v_range_end BETWEEN EEV.effective_start_date
1694 AND EEV.effective_end_date;
1695 --
1696 hr_utility.set_location('v_earnings_entry='||v_earnings_entry, 129);
1697 hr_utility.set_location('v_asst_std_hrs=', v_asst_std_hrs);
1698
1699 hr_utility.set_location('calling core udfs', 50);
1700 v_curr_hrly_rate := PAY_CORE_FF_UDFS.get_hourly_rate(
1701 p_bus_grp_id
1702 ,p_asst_id
1703 ,p_payroll_id
1704 ,p_ele_entry_id
1705 ,p_date_earned
1706 ,p_assignment_action_id );
1707 --
1708 hr_utility.set_location('v_curr_hrly_rate = ', v_curr_hrly_rate);
1709 hr_utility.set_location('calculate_period_earnings', 91);
1710 v_prorated_earnings := v_prorated_earnings +
1711 Prorate_Earnings (
1712 p_bg_id => p_bus_grp_id,
1713 p_assignment_id => p_asst_id,
1714 p_assignment_action_id => p_assignment_action_id,
1715 p_element_entry_id => p_ele_entry_id,
1716 p_date_earned => p_date_earned,
1717 p_asg_hrly_rate => v_curr_hrly_rate,
1718 p_wsched => v_work_schedule,
1719 p_asg_std_hours => v_asst_std_hrs,
1720 p_asg_std_freq => v_asst_std_freq_code,
1721 p_range_start_date => v_range_start,
1722 p_range_end_date => v_range_end,
1723 p_act_hrs_worked => p_actual_hours_worked);
1724 --
1725 hr_utility.set_location('Calculate_Period_Earnings.v_prorated_earnings = ', v_prorated_earnings);
1726 --
1727 ELSE
1728 -- Do proration for this ASG range by EEV !
1729 --
1730 v_prorated_earnings := v_prorated_earnings +
1731 Prorate_EEV (
1732 p_bus_group_id => p_bus_grp_id,
1733 p_assignment_id => p_asst_id,
1734 p_assignment_action_id => p_assignment_action_id,
1735 p_date_earned => p_date_earned,
1736 p_pay_id => p_payroll_id,
1737 p_work_sched => v_work_schedule,
1738 p_asg_std_hrs => v_asst_std_hrs,
1739 p_asg_std_freq => v_asst_std_freq_code,
1740 p_pay_basis => v_pay_basis_code,
1741 p_hrly_rate => v_curr_hrly_rate,
1742 p_range_start_date => v_range_start,
1743 p_range_end_date => v_range_end,
1744 p_actual_hrs_worked => p_actual_hours_worked,
1745 p_element_entry_id => p_ele_entry_id,
1746 p_inpval_id => v_inpval_id);
1747
1748 END IF;
1749
1750 END LOOP;
1751
1752 CLOSE get_asst_chgs;
1753
1754 -- SELECT (ASG3.2)
1755 -- Select for SINGLE record that exists across Period End Date:
1756 -- NOTE: Will only return a row if select (2) does not return a row where
1757 -- Effective End Date = Period End Date !
1758
1759 begin
1760
1761 hr_utility.set_location('calculate_period_earnings', 129);
1762 SELECT ASG.effective_start_date,
1763 LEAST(ASG.effective_end_date, p_period_end),
1764 NVL(ASG.normal_hours, 0),
1765 NVL(HRL.meaning, 'NOT ENTERED'),
1766 NVL(HRL.lookup_code, 'NOT ENTERED'),
1767 NVL(SCL.segment4, 'NOT ENTERED')
1768 INTO v_range_start,
1769 v_range_end,
1770 v_asst_std_hrs,
1771 v_asst_std_freq,
1772 v_asst_std_freq_code,
1773 v_work_schedule
1774 FROM hr_soft_coding_keyflex SCL,
1775 per_assignment_status_types AST,
1776 per_assignments_f ASG,
1777 hr_lookups HRL
1778 WHERE ASG.assignment_id = p_asst_id
1779 AND ASG.business_group_id + 0 = p_bus_grp_id
1780 AND ASG.effective_start_date > p_period_start
1781 AND ASG.effective_start_date <= p_period_end
1782 AND ASG.effective_end_date > p_period_end
1783 AND AST.assignment_status_type_id = ASG.assignment_status_type_id
1784 AND AST.per_system_status = 'ACTIVE_ASSIGN'
1785 AND SCL.soft_coding_keyflex_id = ASG.soft_coding_keyflex_id
1786 AND decode(lv_gre_type, 'T4A/RL1', segment11, 'T4A/RL2', SCL.segment12,
1787 SCL.segment1) = to_char(p_tax_unit_id)
1788 AND SCL.enabled_flag = 'Y'
1789 AND HRL.lookup_code(+) = ASG.frequency
1790 AND HRL.lookup_type(+) = 'FREQUENCY';
1791
1792 -- 25 May 1994:
1793 -- Changing ASG status check to be for Payroll Status of 'Process'
1794 -- AND AST.per_system_status = 'ACTIVE_ASSIGN'
1795 -- AND AST.pay_system_status = 'P'
1796
1797 -- Check for EEV changes, if also none -> return v_period_earn and done:
1798 -- (EEV1) Select for SINGLE record that includes Period Start Date but
1799 -- does not span entire period. If no row returned, then EEV record
1800 -- spans period and there is no need to run selects (EEV2) or (EEV3)
1801 -- and we can stop now! Remember, if eev spans period then get
1802 -- eev.screen_entry_value that spans period (ie latest hrly rate).
1803
1804 hr_utility.set_location('calculate_period_earnings', 133);
1805 SELECT COUNT(EEV.element_entry_value_id)
1806 INTO l_eev_info_changes
1807 FROM pay_element_entry_values_f EEV
1808 WHERE EEV.element_entry_id = p_ele_entry_id
1809 AND EEV.input_value_id = v_inpval_id
1810 AND EEV.effective_start_date <= v_range_start
1811 AND EEV.effective_end_date >= v_range_start
1812 AND EEV.effective_end_date < v_range_end;
1813
1814 IF l_eev_info_changes = 0 THEN
1815 -- Prorate using latest hourly rate (ie. rate as of end of period):
1816 hr_utility.set_location('calculate_period_earnings', 128);
1817 SELECT EEV.screen_entry_value
1818 INTO v_earnings_entry
1819 FROM pay_element_entry_values_f EEV
1820 WHERE EEV.element_entry_id = p_ele_entry_id
1821 AND EEV.input_value_id = v_inpval_id
1822 AND v_range_end BETWEEN EEV.effective_start_date
1823 AND EEV.effective_end_date;
1824
1825 hr_utility.set_location('v_earnings_entry='||v_earnings_entry, 129);
1826 hr_utility.set_location('calling core udfs', 51);
1827 v_curr_hrly_rate := PAY_CORE_FF_UDFS.get_hourly_rate(
1828 p_bus_grp_id
1829 ,p_asst_id
1830 ,p_payroll_id
1831 ,p_ele_entry_id
1832 ,p_date_earned
1833 ,p_assignment_action_id );
1834
1835 hr_utility.set_location('v_curr_hrly_rate = ', v_curr_hrly_rate);
1836 hr_utility.set_location('calculate_period_earnings', 130);
1837
1838 hr_utility.set_location('calculate_period_earnings', 137);
1839 v_prorated_earnings := v_prorated_earnings +
1840 Prorate_Earnings (
1841 p_bg_id => p_bus_grp_id,
1842 p_assignment_id => p_asst_id,
1843 p_assignment_action_id => p_assignment_action_id,
1844 p_element_entry_id => p_ele_entry_id,
1845 p_date_earned => p_date_earned,
1846 p_asg_hrly_rate => v_curr_hrly_rate,
1847 p_wsched => v_work_schedule,
1848 p_asg_std_hours => v_asst_std_hrs,
1849 p_asg_std_freq => v_asst_std_freq_code,
1850 p_range_start_date => v_range_start,
1851 p_range_end_date => v_range_end,
1852 p_act_hrs_worked => p_actual_hours_worked);
1853
1854 hr_utility.set_location('Calculate_Period_Earnings.v_prorated_earnings = ', v_prorated_earnings);
1855
1856 ELSE
1857 -- Do proration for this ASG range by EEV !
1858
1859 hr_utility.set_location('calculate_period_earnings', 139);
1860 v_prorated_earnings := v_prorated_earnings +
1861 Prorate_EEV (
1862 p_bus_group_id => p_bus_grp_id,
1863 p_assignment_id => p_asst_id,
1864 p_assignment_action_id => p_assignment_action_id,
1865 p_date_earned => p_date_earned,
1866 p_pay_id => p_payroll_id,
1867 p_work_sched => v_work_schedule,
1868 p_asg_std_hrs => v_asst_std_hrs,
1869 p_asg_std_freq => v_asst_std_freq_code,
1870 p_pay_basis => v_pay_basis_code,
1871 p_hrly_rate => v_curr_hrly_rate,
1872 p_range_start_date => v_range_start,
1873 p_range_end_date => v_range_end,
1874 p_actual_hrs_worked => p_actual_hours_worked,
1875 p_element_entry_id => p_ele_entry_id,
1876 p_inpval_id => v_inpval_id);
1877
1878 END IF;
1879
1880 -- We're done!
1881
1882 hr_utility.set_location('calculate_period_earnings', 141);
1883
1884 p_actual_hours_worked := ROUND(p_actual_hours_worked, 3);
1885 RETURN v_prorated_earnings;
1886
1887 EXCEPTION WHEN NO_DATA_FOUND THEN
1888 -- (ASG3.2) returned no rows, but we're done anyway!
1889 hr_utility.set_location('calculate_period_earnings', 142);
1890
1891 p_actual_hours_worked := ROUND(p_actual_hours_worked, 3);
1892 RETURN v_prorated_earnings;
1893
1894 END;
1895
1896 END IF;
1897
1898 EXCEPTION
1899 WHEN NO_DATA_FOUND THEN
1900 hr_utility.set_location('calculate_period_earnings', 190);
1901
1902 p_actual_hours_worked := ROUND(p_actual_hours_worked, 3);
1903
1904 RETURN v_prorated_earnings;
1905
1906 END Calculate_Period_Earnings;
1907
1908 -- **********************************************************************
1909
1910 FUNCTION standard_hours_worked(
1911 p_std_hrs in NUMBER,
1912 p_range_start in DATE,
1913 p_range_end in DATE,
1914 p_std_freq in VARCHAR2) RETURN NUMBER IS
1915
1916 c_wkdays_per_week NUMBER(5,2) := 5;
1917 c_wkdays_per_month NUMBER(5,2) := 20;
1918 c_wkdays_per_year NUMBER(5,2) := 250;
1919
1920 /* 353434, 368242 : Fixed number width for total hours */
1921 v_total_hours NUMBER(15,7) := 0;
1922 v_wrkday_hours NUMBER(15,7) := 0; -- std hrs/wk divided by 5 workdays/wk
1923 v_curr_date DATE := NULL;
1924 v_curr_day VARCHAR2(3) := NULL; -- 3 char abbrev for day of wk.
1925 v_day_no NUMBER;
1926
1927 BEGIN -- standard_hours_worked
1928
1929 -- Check for valid range
1930 hr_utility.set_location('standard_hours_worked', 5);
1931 IF p_range_start > p_range_end THEN
1932 hr_utility.set_location('standard_hours_worked', 7);
1933 RETURN v_total_hours;
1934 -- hr_utility.set_message(801,'PAY_xxxx_INVALID_DATE_RANGE');
1935 -- hr_utility.raise_error;
1936 END IF;
1937 --
1938
1939 IF UPPER(p_std_freq) = 'W' THEN
1940 v_wrkday_hours := p_std_hrs / c_wkdays_per_week;
1941 ELSIF UPPER(p_std_freq) = 'M' THEN
1942 v_wrkday_hours := p_std_hrs / c_wkdays_per_month;
1943 ELSIF UPPER(p_std_freq) = 'Y' THEN
1944 v_wrkday_hours := p_std_hrs / c_wkdays_per_year;
1945 ELSE
1946 v_wrkday_hours := p_std_hrs;
1947 END IF;
1948
1949 v_curr_date := p_range_start;
1950
1951 hr_utility.set_location('standard_hours_worked', 10);
1952
1953 hr_utility.trace('p_range_start is'|| to_char(p_range_start));
1954 hr_utility.trace('p_range_end is'|| to_char(p_range_end));
1955 LOOP
1956
1957 v_day_no := TO_CHAR(v_curr_date, 'D');
1958
1959 hr_utility.set_location('standard_hours_worked', 15);
1960
1961 IF v_day_no > 1 and v_day_no < 7 then
1962
1963 v_total_hours := v_total_hours + v_wrkday_hours;
1964 hr_utility.set_location('standard_hours_worked v_total_hours = ', v_total_hours);
1965 END IF;
1966 v_curr_date := v_curr_date + 1;
1967 EXIT WHEN v_curr_date > p_range_end;
1968 END LOOP;
1969 --
1970 hr_utility.set_location('v_total_hours is', to_number(v_total_hours));
1971 RETURN v_total_hours;
1972 --
1973 END standard_hours_worked;
1974 --
1975 -- **********************************************************************
1976 --
1977 FUNCTION Convert_Period_Type(
1978 p_bus_grp_id in NUMBER,
1979 p_payroll_id in NUMBER,
1980 p_assignment_action_id in NUMBER,
1981 p_assignment_id in NUMBER,
1982 p_element_entry_id in NUMBER,
1983 p_date_earned in DATE,
1984 p_asst_work_schedule in VARCHAR2,
1985 p_asst_std_hours in NUMBER ,
1986 p_figure in NUMBER,
1987 p_from_freq in VARCHAR2,
1988 p_to_freq in VARCHAR2,
1989 p_period_start_date in DATE ,
1990 p_period_end_date in DATE ,
1991 p_asst_std_freq in VARCHAR2 )
1992 RETURN NUMBER IS
1993
1994 -- local vars
1995
1996 v_converted_figure NUMBER(27,7);
1997 v_from_annualizing_factor NUMBER(30,7); --Fix for bug 3650170
1998 v_to_annualizing_factor NUMBER(30,7); --Fix for bug 3650170
1999 --v_from_annualizing_factor NUMBER(10);
2000 --v_to_annualizing_factor NUMBER(10);
2001
2002 -- local function
2003
2004 FUNCTION Get_Annualizing_Factor(p_bg in NUMBER,
2005 p_payroll in NUMBER,
2006 p_freq in VARCHAR2,
2007 p_asg_work_sched in VARCHAR2,
2008 p_asg_std_hrs in NUMBER,
2009 p_asg_std_freq in VARCHAR2)
2010 RETURN NUMBER IS
2011
2012 -- local constants
2013
2014 c_weeks_per_year NUMBER(3) := 52;
2015 c_days_per_year NUMBER(3) := 200;
2016 c_months_per_year NUMBER(3) := 12;
2017
2018 -- local vars
2019 /* 353434, 368242 : Fixed number width for total hours variables */
2020 v_annualizing_factor NUMBER(30,7);
2021 v_periods_per_fiscal_yr NUMBER(5);
2022 v_hrs_per_wk NUMBER(15,7);
2023 v_hrs_per_range NUMBER(15,7);
2024 v_use_pay_basis NUMBER(1) := 0;
2025 v_pay_basis VARCHAR2(80);
2026 v_range_start DATE;
2027 v_range_end DATE;
2028 v_work_sched_name VARCHAR2(80);
2029 v_ws_id NUMBER(9);
2030 v_period_hours BOOLEAN;
2031
2032 v_return_status NUMBER;
2033 v_return_message VARCHAR2(500);
2034 v_schedule_source varchar2(100);
2035 v_schedule varchar2(200);
2036 v_total_hours NUMBER(15,7) ;
2037 BEGIN -- Get_Annualizing_Factor
2038
2039 --
2040 -- Check for use of salary admin (ie. pay basis) as frequency.
2041 -- Selecting "count" because we want to continue processing even if
2042 -- the from_freq is not a pay basis.
2043 --
2044
2045 --hr_utility.trace_on('Y', 'ORACLE');
2046 hr_utility.set_location('Get_Annualizing_Factor', 1);
2047
2048 begin -- Is Freq pay basis?
2049
2050 --
2051 -- Decode pay basis and set v_annualizing_factor accordingly.
2052 -- PAY_BASIS "Meaning" is passed from FF !
2053 --
2054
2055 hr_utility.set_location('Get_Annualizing_Factor', 13);
2056
2057 SELECT lookup_code
2058 INTO v_pay_basis
2059 FROM hr_lookups lkp
2060 WHERE lkp.application_id = 800
2061 AND lkp.lookup_type = 'PAY_BASIS'
2062 AND lkp.lookup_code = p_freq;
2063
2064 v_pay_basis := p_freq;
2065
2066 hr_utility.trace('v_pay_basis is'|| v_pay_basis);
2067 hr_utility.set_location('Get_Annualizing_Factor', 15);
2068 v_use_pay_basis := 1;
2069
2070 IF v_pay_basis = 'MONTHLY' THEN
2071
2072 hr_utility.set_location('Get_Annualizing_Factor', 17);
2073 v_annualizing_factor := 12;
2074
2075 ELSIF v_pay_basis = 'HOURLY' THEN
2076
2077 hr_utility.set_location('Get_Annualizing_Factor', 19);
2078
2079 IF p_period_start_date IS NOT NULL THEN
2080 v_range_start := p_period_start_date;
2081 v_range_end := p_period_end_date;
2082 v_period_hours := TRUE;
2083 ELSE
2084 v_range_start := sysdate;
2085 v_range_end := sysdate + 6;
2086 v_period_hours := FALSE;
2087 END IF;
2088
2089 /* IF UPPER(p_asg_work_sched) <> 'NOT ENTERED' THEN
2090
2091 -- Hourly employee using work schedule.
2092 -- Get work schedule name
2093
2094 -- v_ws_id := to_number(p_asg_work_sched);
2095 v_ws_id := fnd_number.canonical_to_number(p_asg_work_sched);
2096
2097 SELECT user_column_name
2098 INTO v_work_sched_name
2099 FROM pay_user_columns
2100 WHERE user_column_id = v_ws_id
2101 AND NVL(business_group_id, p_bg) = p_bg
2102 AND NVL(legislation_code,'CA') = 'CA';
2103
2104 hr_utility.set_location('Get_Annualizing_Factor', 21);
2105 */
2106
2107 hr_utility.set_location('calling core udfs', 52);
2108 v_hrs_per_range := PAY_CORE_FF_UDFS.calculate_actual_hours_worked (
2109 p_assignment_action_id
2110 ,p_assignment_id
2111 ,p_bg
2112 ,p_element_entry_id
2113 ,p_date_earned
2114 ,p_period_start_date
2115 ,p_period_end_date
2116 ,NULL
2117 ,'Y'
2118 ,'BUSY'
2119 ,'CA'--p_legislation_code
2120 ,v_schedule_source
2121 ,v_schedule
2122 ,v_return_status
2123 ,v_return_message);
2124
2125 /* ELSE-- Hourly emp using Standard Hours on asg.
2126
2127 hr_utility.set_location('Get_Annualizing_Factor', 23);
2128
2129
2130 v_hrs_per_range := Standard_Hours_Worked( p_asg_std_hrs,
2131 v_range_start,
2132 v_range_end,
2133 p_asg_std_freq);
2134
2135 END IF;
2136
2137 */
2138 IF v_period_hours THEN
2139
2140 select TPT.number_per_fiscal_year
2141 into v_periods_per_fiscal_yr
2142 from pay_payrolls_f PPF,
2143 per_time_period_types TPT,
2144 fnd_sessions fs
2145 where PPF.payroll_id = p_payroll
2146 and fs.session_id = USERENV('SESSIONID')
2147 and fs.effective_date between PPF.effective_start_date and PPF.effective_end_date
2148 and TPT.period_type = PPF.period_type;
2149
2150 v_annualizing_factor := v_hrs_per_range * v_periods_per_fiscal_yr;
2151
2152 ELSE
2153
2154 hr_utility.set_location('Get_Annualizing_Factor', 230000);
2155 v_annualizing_factor := v_hrs_per_range * c_weeks_per_year;
2156
2157 END IF;
2158
2159 ELSIF v_pay_basis = 'PERIOD' THEN
2160
2161 hr_utility.set_location('Get_Annualizing_Factor', 25);
2162
2163 SELECT TPT.number_per_fiscal_year
2164 INTO v_annualizing_factor
2165 FROM pay_payrolls_f PRL,
2166 per_time_period_types TPT,
2167 fnd_sessions fs
2168 WHERE TPT.period_type = PRL.period_type
2169 and fs.session_id = USERENV('SESSIONID')
2170 and fs.effective_date BETWEEN PRL.effective_start_date
2171 AND PRL.effective_end_date
2172 AND PRL.payroll_id = p_payroll
2173 AND PRL.business_group_id + 0 = p_bg;
2174
2175 hr_utility.set_location('Get_Annualizing_Factor', 27);
2176
2177 ELSIF v_pay_basis = 'ANNUAL' THEN
2178
2179 hr_utility.set_location('Get_Annualizing_Factor', 97);
2180
2181 v_annualizing_factor := 1;
2182
2183 ELSE
2184
2185 -- Did not recognize "pay basis", return -999 as annualizing factor.
2186 -- Remember this for debugging when zeroes come out as results!!!
2187
2188 hr_utility.set_location('Get_Annualizing_Factor', 99);
2189
2190 v_annualizing_factor := 0;
2191 RETURN v_annualizing_factor;
2192
2193 END IF;
2194
2195 exception
2196
2197 WHEN NO_DATA_FOUND THEN
2198
2199 hr_utility.set_location('Get_Annualizing_Factor', 101);
2200 v_use_pay_basis := 0;
2201
2202 end;
2203
2204 IF v_use_pay_basis = 0 THEN
2205
2206 -- Not using pay basis as frequency...
2207
2208 IF (p_freq IS NULL) OR
2209 (UPPER(p_freq) = 'PERIOD') OR
2210 (UPPER(p_freq) = 'NOT ENTERED') THEN
2211
2212 -- Get "annuallizing factor" from period type of the payroll.
2213
2214 hr_utility.set_location('Get_Annualizing_Factor', 20);
2215
2216 SELECT TPT.number_per_fiscal_year
2217 INTO v_annualizing_factor
2218 FROM pay_payrolls_f PRL,
2219 per_time_period_types TPT,
2220 fnd_sessions fs
2221 WHERE TPT.period_type = PRL.period_type
2222 and fs.session_id = USERENV('SESSIONID')
2223 and fs.effective_date BETWEEN PRL.effective_start_date
2224 AND PRL.effective_end_date
2225 AND PRL.payroll_id = p_payroll
2226 AND PRL.business_group_id + 0 = p_bg;
2227
2228 hr_utility.set_location('Get_Annualizing_Factor', 22);
2229
2230 ELSIF UPPER(p_freq) <> 'HOURLY' THEN
2231
2232 -- Not hourly, an actual time period type!
2233
2234 begin
2235
2236 hr_utility.set_location('Get_Annualizing_Factor',24);
2237
2238 SELECT PT.number_per_fiscal_year
2239 INTO v_annualizing_factor
2240 FROM per_time_period_types PT
2241 WHERE UPPER(PT.period_type) = UPPER(p_freq);
2242
2243 /* changed for bug 5155854
2244 decode(UPPER(p_freq),'W','WEEK','M','MONTH','D','DAY','Y','YEAR','H','HOUR');
2245 */
2246
2247 hr_utility.set_location('Get_Annualizing_Factor',26);
2248
2249 exception when NO_DATA_FOUND then
2250
2251 -- Added as part of SALLY CLEANUP.
2252 -- Could have been passed in an ASG_FREQ dbi which might have the values of
2253 -- 'Day' or 'Month' which do not map to a time period type. So we'll do these by hand.
2254
2255 hr_utility.set_location('Get_Annualizing_Factor',27);
2256 IF UPPER(p_freq) = 'DAY' THEN /* changed D to DAY and M to Month for bug 5155854 */
2257 v_annualizing_factor := c_days_per_year;
2258 ELSIF UPPER(p_freq) = 'MONTH' THEN
2259 v_annualizing_factor := c_months_per_year;
2260 END IF;
2261
2262 end;
2263
2264 ELSE -- Hourly employee...
2265
2266 hr_utility.set_location('Get_Annualizing_Factor', 28);
2267
2268 IF p_period_start_date IS NOT NULL THEN
2269 v_range_start := p_period_start_date;
2270 v_range_end := p_period_end_date;
2271 v_period_hours := TRUE;
2272 ELSE
2273 v_range_start := sysdate;
2274 v_range_end := sysdate + 6;
2275 v_period_hours := FALSE;
2276 END IF;
2277
2278 /* IF UPPER(p_asg_work_sched) <> 'NOT ENTERED' THEN
2279
2280 -- Hourly emp using work schedule.
2281 -- Get work schedule name:
2282
2283 -- v_ws_id := to_number(p_asg_work_sched);
2284 v_ws_id := fnd_number.canonical_to_number(p_asg_work_sched);
2285
2286 SELECT user_column_name
2287 INTO v_work_sched_name
2288 FROM pay_user_columns
2289 WHERE user_column_id = v_ws_id
2290 AND NVL(business_group_id, p_bg) = p_bg
2291 AND NVL(legislation_code,'CA') = 'CA';
2292
2293 hr_utility.set_location('Get_Annualizing_Factor',30);
2294
2295 hr_utility.set_location('calling core udfs', 53);
2296 */
2297 v_hrs_per_range := PAY_CORE_FF_UDFS.calculate_actual_hours_worked (
2298 p_assignment_action_id
2299 ,p_assignment_id
2300 ,p_bg
2301 ,p_element_entry_id
2302 ,p_date_earned
2303 ,p_period_start_date
2304 ,p_period_end_date
2305 ,NULL
2306 ,'Y'
2307 ,'BUSY'
2308 ,'CA'--p_legislation_code
2309 ,v_schedule_source
2310 ,v_schedule
2311 ,v_return_status
2312 ,v_return_message);
2313
2314 /* ELSE-- Hourly emp using Standard Hours on asg.
2315
2316 hr_utility.set_location('Get_Annualizing_Factor', 23);
2317
2318
2319 v_hrs_per_range := Standard_Hours_Worked( p_asg_std_hrs,
2320 v_range_start,
2321 v_range_end,
2322 p_asg_std_freq);
2323
2324 END IF; */
2325
2326
2327 IF v_period_hours THEN
2328
2329 select TPT.number_per_fiscal_year
2330 into v_periods_per_fiscal_yr
2331 from pay_payrolls_f PPF,
2332 per_time_period_types TPT,
2333 fnd_sessions fs
2334 where PPF.payroll_id = p_payroll
2335 and fs.session_id = USERENV('SESSIONID')
2336 and fs.effective_date between PPF.effective_start_date and PPF.effective_end_date
2337 and TPT.period_type = PPF.period_type;
2338
2339 v_annualizing_factor := v_hrs_per_range * v_periods_per_fiscal_yr;
2340
2341 ELSE
2342
2343 v_annualizing_factor := v_hrs_per_range * c_weeks_per_year;
2344
2345 END IF;
2346
2347 END IF;
2348
2349 END IF; -- (v_use_pay_basis = 0)
2350
2351 hr_utility.set_location('v_annualizing_factor is', to_number(v_annualizing_factor));
2352 RETURN v_annualizing_factor;
2353
2354 END Get_Annualizing_Factor;
2355
2356
2357 BEGIN -- Convert Figure
2358
2359 --hr_utility.trace_on('Y', 'ORACLE');
2360 hr_utility.set_location('Convert_Period_Type', 10);
2361
2362 --
2363 -- If From_Freq and To_Freq are the same, then we're done.
2364 --
2365
2366 IF NVL(p_from_freq, 'NOT ENTERED') = NVL(p_to_freq, 'NOT ENTERED') THEN
2367
2368 RETURN p_figure;
2369
2370 END IF;
2371
2372 hr_utility.set_location('Mita a trace1 ',30000);
2373
2374 hr_utility.trace('v_from_freq is'|| p_from_freq);
2375 hr_utility.trace('v_to_freq is'|| p_to_freq);
2376
2377 v_from_annualizing_factor := Get_Annualizing_Factor(
2378 p_bg => p_bus_grp_id,
2379 p_payroll => p_payroll_id,
2380 p_freq => p_from_freq,
2381 p_asg_work_sched => p_asst_work_schedule,
2382 p_asg_std_hrs => p_asst_std_hours,
2383 p_asg_std_freq => p_asst_std_freq);
2384
2385 v_to_annualizing_factor := Get_Annualizing_Factor(
2386 p_bg => p_bus_grp_id,
2387 p_payroll => p_payroll_id,
2388 p_freq => p_to_freq,
2389 p_asg_work_sched => p_asst_work_schedule,
2390 p_asg_std_hrs => p_asst_std_hours,
2391 p_asg_std_freq => p_asst_std_freq);
2392
2393 --
2394 -- Annualize "Figure" and convert to To_Freq.
2395 --
2396
2397 hr_utility.set_location('v_from_annualizing_factor is', to_number(v_from_annualizing_factor));
2398 hr_utility.set_location('v_to_annualizing_factor is', to_number(v_to_annualizing_factor));
2399 hr_utility.set_location('Convert_Period_Type', 170);
2400
2401 IF v_to_annualizing_factor = 0 OR
2402 v_to_annualizing_factor = -999 OR
2403 v_from_annualizing_factor = -999 THEN
2404
2405 hr_utility.set_location('Convert_Period_Type', 175);
2406
2407 v_converted_figure := 0;
2408 RETURN v_converted_figure;
2409
2410 ELSE
2411
2412 hr_utility.set_location('Convert_Period_Type', 180);
2413 /* hard coded values are for testing */
2414
2415 -- v_from_annualizing_factor := 12;
2416 -- v_to_annualizing_factor := 1040;
2417
2418 v_converted_figure := (p_figure * v_from_annualizing_factor) / v_to_annualizing_factor;
2419
2420 END IF;
2421
2422 -- Done
2423
2424 RETURN v_converted_figure;
2425
2426 END Convert_Period_Type;
2427
2428 --
2429 -- **********************************************************************
2430 --
2431 FUNCTION work_schedule_total_hours(
2432 p_bg_id in NUMBER,
2433 p_ws_name in VARCHAR2,
2434 p_range_start in DATE ,
2435 p_range_end in DATE )
2436 RETURN NUMBER IS
2437
2438 -- local constants
2439
2440 c_ws_tab_name VARCHAR2(80) := 'COMPANY WORK SCHEDULES';
2441
2442 -- local variables
2443
2444 /* 353434, 368242 : Fixed number width for total hours */
2445 v_total_hours NUMBER(15,7) := 0;
2446 v_range_start DATE;
2447 v_range_end DATE;
2448 v_curr_date DATE;
2449 v_curr_day VARCHAR2(3); -- 3 char abbrev for day of wk.
2450 v_ws_name VARCHAR2(80); -- Work Schedule Name.
2451 v_gtv_hours VARCHAR2(80); -- get_table_value returns varchar2
2452 -- Remember to TO_NUMBER result.
2453 v_fnd_sess_row VARCHAR2(1);
2454 l_exists VARCHAR2(1);
2455 v_day_no NUMBER;
2456
2457 BEGIN -- work_schedule_total_hours
2458
2459 -- Set range to a single week if no dates are entered:
2460 -- IF (p_range_start IS NULL) AND (p_range_end IS NULL) THEN
2461 --
2462 hr_utility.set_location('work_schedule_total_hours setting dates', 3);
2463 v_range_start := NVL(p_range_start, sysdate);
2464 v_range_end := NVL(p_range_end, sysdate + 6);
2465 --
2466 -- END IF;
2467 -- Check for valid range
2468 hr_utility.set_location('work_schedule_total_hours', 5);
2469 IF v_range_start > v_range_end THEN
2470 --
2471 hr_utility.set_location('work_schedule_total_hours', 7);
2472 RETURN v_total_hours;
2473 -- hr_utility.set_message(801,'PAY_xxxx_INVALID_DATE_RANGE');
2474 -- hr_utility.raise_error;
2475 --
2476 END IF;
2477 --
2478 -- Get_Table_Value requires row in FND_SESSIONS. We must insert this
2479 -- record if one doe not already exist.
2480 --
2481 SELECT DECODE(COUNT(session_id), 0, 'N', 'Y')
2482 INTO v_fnd_sess_row
2483 FROM fnd_sessions
2484 WHERE session_id = userenv('sessionid');
2485 --
2486 IF v_fnd_sess_row = 'N' THEN
2487 --
2488 dt_fndate.set_effective_date (p_effective_date => sysdate);
2489 -- INSERT INTO fnd_sessions
2490 -- SELECT userenv('sessionid'),
2491 -- sysdate
2492 -- FROM sys.dual;
2493 --
2494 END IF;
2495 --
2496 hr_utility.set_location('work_schedule_total_hours', 10);
2497 -- Track range dates:
2498 hr_utility.set_location('range start = '||to_char(v_range_start), 5);
2499 hr_utility.set_location('range end = '||to_char(v_range_end), 6);
2500 --
2501 -- Check if the work schedule is an id or a name. If the work
2502 -- schedule does not exist, then return 0.
2503 --
2504 BEGIN
2505 select 'Y'
2506 into l_exists
2507 from pay_user_tables PUT,
2508 pay_user_columns PUC
2509 where PUC.USER_COLUMN_NAME = p_ws_name
2510 and PUC.user_table_id = PUT.user_table_id
2511 and PUT.user_table_name = c_ws_tab_name
2512 and NVL(PUC.business_group_id, p_bg_id) = p_bg_id
2513 and NVL(PUC.legislation_code,'CA') = 'CA';
2514
2515 EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
2516 END;
2517
2518 if l_exists = 'Y' then
2519 v_ws_name := p_ws_name;
2520 else
2521 BEGIN
2522 select PUC.USER_COLUMN_NAME
2523 into v_ws_name
2524 from pay_user_tables PUT,
2525 pay_user_columns PUC
2526 where PUC.USER_COLUMN_ID = p_ws_name
2527 and PUT.user_table_name = c_ws_tab_name
2528 and PUC.user_table_id = PUT.user_table_id
2529 and NVL(PUC.business_group_id, p_bg_id) = p_bg_id
2530 and NVL(PUC.legislation_code,'CA') = 'CA';
2531
2532 EXCEPTION WHEN NO_DATA_FOUND THEN
2533 RETURN v_total_hours;
2534 END;
2535 end if;
2536 --
2537 v_curr_date := v_range_start;
2538 --
2539 hr_utility.set_location('work_schedule_total_hours curr_date = '||to_char(v_curr_date), 20);
2540 --
2541 LOOP
2542 v_day_no := TO_CHAR(v_curr_date, 'D');
2543
2544 hr_utility.set_location('curr_day_no = '||to_char(v_day_no), 20);
2545
2546 SELECT decode(v_day_no,1,'SUN',2,'MON',3,'TUE',
2547 4,'WED',5,'THU',6,'FRI',7,'SAT')
2548 INTO v_curr_day
2549 FROM DUAL;
2550
2551 --
2552 hr_utility.set_location('curr_day = '||v_curr_day, 20);
2553
2554 --
2555 hr_utility.set_location('work_schedule_total_hours.gettabval', 25);
2556 v_total_hours := v_total_hours +
2557 fnd_number.canonical_to_number(hruserdt.get_table_value(p_bg_id,
2558 c_ws_tab_name,
2559 v_ws_name,
2560 v_curr_day));
2561 v_curr_date := v_curr_date + 1;
2562 --
2563 hr_utility.set_location('curr_date = '||to_char(v_curr_date), 20);
2564 --
2565 EXIT WHEN v_curr_date > v_range_end;
2566 --
2567 END LOOP;
2568 --
2569 RETURN v_total_hours;
2570 --
2571 END work_schedule_total_hours;
2572 --
2573 -- **********************************************************************
2574 --
2575 FUNCTION chained_element_exists(p_bg_id in NUMBER,
2576 p_asst_id in NUMBER,
2577 p_payroll_id in NUMBER,
2578 p_date_earned in DATE,
2579 p_ele_name IN VARCHAR2) RETURN VARCHAR2 IS
2580 -- local vars
2581 v_ele_exists VARCHAR2(1);
2582 --
2583 BEGIN
2584 --
2585 -- Get formula context values: bg, payroll, asst ids; date earned.
2586 --
2587 -- ...
2588 --
2589 SELECT DECODE(COUNT(0), 0, 'N', 'Y')
2590 INTO v_ele_exists
2591 FROM PAY_ELEMENT_ENTRIES_F ELE,
2592 PAY_ELEMENT_LINKS_F ELI,
2593 PAY_ELEMENT_TYPES_F ELT
2594 WHERE p_date_earned
2595 BETWEEN ELE.effective_start_date
2596 AND ELE.effective_end_date
2597 AND ELE.assignment_id = p_asst_id
2598 AND ELE.element_link_id = ELI.element_link_id
2599 AND ELI.business_group_id + 0 = p_bg_id
2600 AND ELI.element_type_id = ELT.element_type_id
2601 AND NVL(ELT.business_group_id, p_bg_id) = p_bg_id
2602 AND UPPER(ELT.element_name) = UPPER(p_ele_name);
2603
2604 RETURN v_ele_exists;
2605
2606 END chained_element_exists;
2607
2608 --
2609 -- **********************************************************************
2610 --
2611
2612 FUNCTION us_jurisdiction_val (p_jurisdiction_code in VARCHAR2)
2613 RETURN VARCHAR2 IS
2614
2615 v_valid_jurisdiction VARCHAR2(1) := 'E'; -- RETURN var.
2616
2617 BEGIN
2618
2619 hr_utility.set_location('Jurisdiction_Validation', 01);
2620
2621 IF substr(p_jurisdiction_code, 8,4) = '0000' THEN
2622
2623 IF substr(p_jurisdiction_code, 4,3) = '000' THEN
2624
2625 -- Only entered a state geo, check against PAY_US_STATES.
2626
2627 SELECT 'S'
2628 INTO v_valid_jurisdiction
2629 FROM PAY_US_STATES
2630 WHERE STATE_CODE = substr(p_jurisdiction_code, 1,2);
2631
2632 ELSE
2633
2634 -- State/County entered
2635
2636 SELECT 'S'
2637 INTO v_valid_jurisdiction
2638 FROM PAY_US_COUNTIES
2639 WHERE STATE_CODE = substr(p_jurisdiction_code, 1,2)
2640 AND COUNTY_CODE = substr(p_jurisdiction_code, 4,3);
2641
2642 END IF;
2643
2644 ELSE
2645
2646 -- State/County/City entered
2647
2648 SELECT 'S'
2649 INTO v_valid_jurisdiction
2650 FROM PAY_US_CITY_NAMES
2651 WHERE STATE_CODE = substr(p_jurisdiction_code, 1,2)
2652 AND COUNTY_CODE = substr(p_jurisdiction_code, 4,3)
2653 AND CITY_CODE = substr(p_jurisdiction_code, 8,4)
2654 AND PRIMARY_FLAG ='Y';
2655
2656 END IF;
2657
2658 RETURN v_valid_jurisdiction;
2659
2660 EXCEPTION
2661 WHEN NO_DATA_FOUND THEN
2662
2663 hr_utility.set_location('Jurisdiction_Validation', 03);
2664 v_valid_jurisdiction := 'E';
2665 RETURN v_valid_jurisdiction;
2666
2667 END us_jurisdiction_val;
2668
2669
2670 --
2671 -- **********************************************************************
2672 --
2673 FUNCTION get_process_run_flag ( p_date_earned IN DATE,
2674 p_ele_type_id IN NUMBER) RETURN VARCHAR2 IS
2675 --
2676 v_proc_run_type VARCHAR2(3) := 'REG';
2677 --
2678 BEGIN
2679 --
2680 --
2681 -- GET <ELE_NAME>_PROCESSING_RUN_TYPE. IF = 'ALL' then SKIP='N'.
2682 -- This DDF info is held in ELEMENT_INFORMATION3.
2683 --
2684 hr_utility.set_location('get_process_run_flag', 10);
2685 --
2686 begin
2687 SELECT element_information3
2688 INTO v_proc_run_type
2689 FROM pay_element_types_f
2690 WHERE p_date_earned
2691 BETWEEN effective_start_date
2692 AND effective_end_date
2693 AND element_type_id = p_ele_type_id;
2694 --
2695 hr_utility.set_location('get_process_run_flag', 20);
2696 RETURN v_proc_run_type;
2697 --
2698 exception when NO_DATA_FOUND then
2699 hr_utility.set_location('get_process_run_flag', 30);
2700 RETURN v_proc_run_type;
2701 end;
2702 --
2703 END get_process_run_flag;
2704 --
2705 -- **********************************************************************
2706 --
2707 FUNCTION check_dedn_freq ( p_payroll_id IN NUMBER,
2708 p_bg_id IN NUMBER,
2709 p_pay_action_id IN NUMBER,
2710 p_date_earned IN DATE,
2711 p_ele_type_id IN NUMBER) RETURN VARCHAR2 IS
2712
2713 v_skip_element VARCHAR2(1) := 'N';
2714 v_number_per_fy NUMBER(3);
2715 v_run_number NUMBER(3);
2716 v_proc_run_type VARCHAR2(3);
2717 v_freq_rule_exists NUMBER(3);
2718 v_period_end_date DATE;
2719
2720 BEGIN
2721
2722 -- Check that <ELE_NAME>_PROCESSING_RUN_TYPE = 'ALL', meaning SKIP='N'.
2723 -- This DDF info is held in ELEMENT_INFORMATION3.
2724
2725 hr_utility.set_location('check_dedn_freq', 10);
2726
2727 begin
2728 SELECT element_information3
2729 INTO v_proc_run_type
2730 FROM pay_element_types_f
2731 WHERE p_date_earned
2732 BETWEEN effective_start_date
2733 AND effective_end_date
2734 AND element_type_id = p_ele_type_id;
2735
2736 IF v_proc_run_type = 'ALL' THEN
2737 RETURN v_skip_element;
2738 END IF;
2739
2740 exception when NO_DATA_FOUND then
2741 RETURN v_skip_element;
2742 end;
2743 --
2744 -- See if freq rule even comes into play here:
2745 --
2746 hr_utility.set_location('check_dedn_freq', 45);
2747 SELECT COUNT(0)
2748 INTO v_freq_rule_exists
2749 FROM pay_ele_payroll_freq_rules EPF
2750 WHERE element_type_id = p_ele_type_id
2751 AND payroll_id = p_payroll_id
2752 AND business_group_id + 0 = p_bg_id;
2753
2754 IF v_freq_rule_exists = 0 THEN
2755 RETURN v_skip_element;
2756 END IF;
2757 --
2758 -- If we're here, then maybe freq rule will affect processing...
2759 -- Get payroll period type.number per fiscal year.
2760 --
2761 SELECT end_date
2762 INTO v_period_end_date
2763 FROM per_time_periods
2764 WHERE p_date_earned BETWEEN start_date AND end_date
2765 AND payroll_id = p_payroll_id;
2766
2767 SELECT TPT.number_per_fiscal_year
2768 INTO v_number_per_fy
2769 FROM per_time_period_types TPT,
2770 pay_payrolls_f PRL
2771 WHERE TPT.period_type = PRL.period_type
2772 AND PRL.business_group_id + 0 = p_bg_id
2773 AND PRL.payroll_id = p_payroll_id;
2774 --
2775 -- Get period number in Month or Year according to number per fiscal year.
2776 -- ...into v_run_number...
2777 -- What we NEED is the actual PERIOD # w/in Month or Year.
2778 --
2779 IF v_number_per_fy < 12 THEN
2780 hr_utility.set_location('check_dedn_freq', 20);
2781
2782 SELECT COUNT(0)
2783 INTO v_run_number
2784 FROM per_time_periods PTP
2785 WHERE PTP.end_date
2786 BETWEEN TRUNC(p_date_earned,'YEAR')
2787 AND v_period_end_date
2788 AND PTP.payroll_id = p_payroll_id;
2789
2790 ELSIF v_number_per_fy > 12 THEN
2791 hr_utility.set_location('check_dedn_freq', 30);
2792
2793 SELECT COUNT(0)
2794 INTO v_run_number
2795 FROM per_time_periods PTP
2796 WHERE PTP.end_date
2797 BETWEEN TRUNC(p_date_earned,'MONTH')
2798 AND v_period_end_date
2799 AND PTP.payroll_id = p_payroll_id;
2800
2801 ELSIF v_number_per_fy = 12 THEN
2802 hr_utility.set_location('check_dedn_freq', 40);
2803 v_skip_element := 'N';
2804 RETURN v_skip_element;
2805 END IF;
2806
2807 --
2808 -- Check frequency rule:
2809 -- If none exists, then process!
2810 --
2811
2812 hr_utility.set_location('check_dedn_freq', 50);
2813 SELECT 'N'
2814 INTO v_skip_element
2815 FROM pay_ele_payroll_freq_rules EPF,
2816 pay_freq_rule_periods FRP
2817 WHERE FRP.period_no_in_reset_period = v_run_number
2818 AND FRP.ele_payroll_freq_rule_id = EPF.ele_payroll_freq_rule_id
2819 AND EPF.business_group_id + 0 = p_bg_id
2820 AND EPF.payroll_id = p_payroll_id
2821 AND EPF.element_type_id = p_ele_type_id;
2822
2823 RETURN v_skip_element;
2824
2825 EXCEPTION
2826 WHEN NO_DATA_FOUND THEN
2827 hr_utility.set_location('check_dedn_freq', 60);
2828 v_skip_element := 'Y';
2829 RETURN v_skip_element;
2830
2831 END check_dedn_freq;
2832
2833 --
2834 -- **********************************************************************
2835 --
2836 FUNCTION Separate_Check_Skip (
2837 p_bg_id in NUMBER,
2838 p_element_type_id in NUMBER,
2839 p_assact_id in NUMBER,
2840 p_payroll_id in NUMBER,
2841 p_date_earned in DATE) RETURN VARCHAR2 IS
2842
2843 -- This function is called from skip rules attached to Deductions.
2844 -- Purpose is to check if an earnings requires special "Deduction Processing"
2845 -- ie. take only Pretax and/or Tax deductions.
2846 -- Algorithm:
2847 -- 1. Check for run results where "Deduction Processing" inpval is something
2848 -- other than 'A' for All.
2849 -- 2. If there is, then check classification of current deduction against
2850 -- the deduction processing requirement - ie. skip any deductions that
2851 -- are not pre-tax or tax deductions; further, if dedn proc is 'Tax Only'
2852 -- then skip pre-tax dedns as well - easy!
2853
2854 -- local constants
2855
2856 -- local vars
2857 v_dedn_proc VARCHAR2(3);
2858 v_dedn_proc_value VARCHAR2(80);
2859 v_ele_class_name VARCHAR2(80);
2860 v_skip_element VARCHAR2(1) := 'N';
2861
2862 --
2863 BEGIN -- Separate_Check_Skip
2864 --
2865
2866 hr_utility.set_location('Separate_Check_Skip', 7);
2867
2868 SELECT RRV.result_value
2869 INTO v_dedn_proc
2870 FROM pay_run_result_values RRV,
2871 pay_run_results PRR,
2872 pay_input_values_f IPV
2873 WHERE PRR.assignment_action_id = p_assact_id
2874 AND RRV.result_value <> 'A'
2875 AND RRV.run_result_id = PRR.run_result_id
2876 AND IPV.input_value_id = RRV.input_value_id
2877 AND p_date_earned
2878 BETWEEN IPV.effective_start_date
2879 AND IPV.effective_end_date
2880 AND UPPER(IPV.name) = 'DEDUCTION PROCESSING'
2881 AND IPV.business_group_id + 0 = p_bg_id;
2882
2883 --
2884 -- We now assume there is a value in Deduction Processing input value of
2885 -- either 'T' ("Tax Only") or 'PTT' ("Pre-Tax and Tax Only).
2886 --
2887
2888 v_skip_element := 'Y';
2889
2890 hr_utility.set_location('Separate_Check_Skip', 9);
2891
2892 begin
2893
2894 SELECT ECL.classification_name
2895 INTO v_ele_class_name
2896 FROM pay_element_types_f ELT,
2897 pay_element_classifications ECL
2898 WHERE ECL.classification_id = ELT.classification_id
2899 AND ELT.business_group_id + 0 = p_bg_id
2900 AND p_date_earned
2901 BETWEEN ELT.effective_start_date
2902 AND ELT.effective_end_date
2903 AND ELT.element_type_id = p_element_type_id;
2904
2905 IF UPPER(v_ele_class_name) = 'TAX DEDUCTIONS' THEN
2906
2907 -- Change v_skip_element back to 'N' if this a tax deduction.
2908 -- ie. we know DEDN PROC inpval is not null, meaning it's either TAX ONLY
2909 -- or PRETAX AND TAX ONLY.
2910
2911 hr_utility.set_location('Separate_Check_Skip', 10);
2912 v_skip_element := 'N';
2913 RETURN v_skip_element;
2914
2915 ELSIF UPPER(v_ele_class_name) = 'PRE-TAX DEDUCTIONS' AND
2916 v_dedn_proc = 'PTT' THEN
2917
2918 -- Change v_skip_element back to 'N' if dedn proc = 'PTT'
2919
2920 hr_utility.set_location('Separate_Check_Skip', 11);
2921 v_skip_element := 'N';
2922 RETURN v_skip_element;
2923
2924 END IF;
2925
2926 exception WHEN NO_DATA_FOUND THEN
2927 hr_utility.set_location('Separate_Check_Skip - Error EleClass NOTFOUND', 12);
2928 v_skip_element := 'Y';
2929 -- hr_utility.set_message(801, 'PAY_ELE_CLASS_NOTFOUND');
2930 -- hr_utility.raise_error;
2931 end;
2932
2933 RETURN v_skip_element;
2934
2935 EXCEPTION
2936 WHEN NO_DATA_FOUND THEN
2937 hr_utility.set_location('Separate_Check_Skip', 21);
2938 RETURN v_skip_element;
2939 -- Special Dedn Proc not required. SKIP_FLAG = 'N'.
2940 --
2941 END Separate_Check_Skip;
2942 --
2943 -- **********************************************************************
2944 --
2945 /* ( ) OTHER_NON_SEPARATE_CHECK
2946 Desc: Returns 'Y' if other ELEMENT ENTRIES exist where
2947 Separate_Check = 'N' or null ;
2948 OR
2949 Earnings element entries exist with no "Separate Check" input
2950 value at all.
2951 */
2952 FUNCTION Other_Non_Separate_Check (
2953 p_date_earned IN DATE,
2954 p_ass_id IN NUMBER) RETURN VARCHAR2 IS
2955
2956 -- local vars
2957 sepcheck_flag VARCHAR2(1) := 'N';
2958 --
2959
2960 BEGIN
2961
2962 hr_utility.set_location('Other_Non_Separate_Check', 10);
2963
2964 SELECT DECODE(COUNT(IPV.input_value_id), 0, 'N', 'Y')
2965 INTO sepcheck_flag
2966 FROM pay_element_entry_values_f EEV,
2967 pay_element_entries_f ELE,
2968 pay_input_values_f IPV
2969 WHERE ELE.assignment_id = p_ass_id
2970 AND p_date_earned
2971 BETWEEN ELE.effective_start_date AND ELE.effective_end_date
2972 AND ELE.element_entry_id = EEV.element_entry_id
2973 AND p_date_earned
2974 BETWEEN EEV.effective_start_date AND EEV.effective_end_date
2975 AND nvl(EEV.screen_entry_value,'N') = 'N'
2976 AND EEV.input_value_id = IPV.input_value_id
2977 AND UPPER(IPV.name) = 'SEPARATE CHECK';
2978 --
2979 IF sepcheck_flag = 'Y' THEN
2980 hr_utility.set_location('Other_Non_Separate_Check', 15);
2981 RETURN sepcheck_flag;
2982 END IF;
2983 --
2984 hr_utility.set_location('Other_Non_Separate_Check', 20);
2985
2986 SELECT DECODE(COUNT(ELE.element_entry_id), 0, 'N', 'Y')
2987 INTO sepcheck_flag
2988 FROM pay_element_entries_f ELE,
2989 pay_element_links_f ELL,
2990 pay_element_types_f ELT,
2991 pay_element_classifications ECL
2992 WHERE ELE.assignment_id = p_ass_id
2993 AND p_date_earned BETWEEN
2994 ELE.effective_start_date and ELE.effective_end_date
2995 AND ELE.element_link_id = ELL.element_link_id
2996 AND p_date_earned BETWEEN
2997 ELL.effective_start_date and ELL.effective_end_date
2998 AND ELL.element_type_id = ELT.element_type_id
2999 AND p_date_earned BETWEEN
3000 ELT.effective_start_date and ELT.effective_end_date
3001 AND ECL.classification_id = ELT.classification_id
3002 AND UPPER(ECL.classification_name) IN ( 'EARNINGS',
3003 'SUPPLEMENTAL EARNINGS',
3004 'IMPUTED EARNINGS',
3005 'NON-PAYROLL PAYMENTS')
3006 AND NOT EXISTS
3007 (SELECT 'X'
3008 FROM pay_input_values_f IPV
3009 WHERE IPV.element_type_id = ELT.element_type_id
3010 AND p_date_earned BETWEEN
3011 IPV.effective_start_date and IPV.effective_end_date
3012 AND UPPER(IPV.name) = 'SEPARATE CHECK');
3013 --
3014
3015 RETURN sepcheck_flag;
3016
3017 --
3018 EXCEPTION
3019 WHEN NO_DATA_FOUND THEN
3020 hr_utility.set_location('Other_Non_Separate_Check', 30);
3021 RETURN sepcheck_flag;
3022 --
3023 END Other_Non_Separate_Check;
3024 --
3025 /*
3026 *****************************************************
3027 FUNCTION NAME:
3028 *****************************************************
3029 OT_Base_Rate
3030 Inputs: p_ass_id, -- Context from formula, pass TO Convert_Figure
3031 p_date_earned -- Context
3032 p_work_sched -- Pass to Convert_Figure
3033 p_std_hours -- Pass to Convert_Figure
3034
3035 Outputs: v_ot_base_rate -- Hourly Rate for use by OT
3036
3037 12 Dec 1993 hparicha Created.
3038
3039 *****************************************************
3040 DESCRIPTION:
3041 *****************************************************
3042 1) Add hourly Rate from Regular Wages, Time Entry Wages,
3043 or equivalent hourly rate from Regular Salary to v_ot_base_rate;
3044 2) Get elements and formula names where "Include in OT Base" = 'Y'
3045 3) Get hourly rate from either input values or run result values
3046 - based on calculation method (ie. formula name).
3047 --
3048 Calc Rule Include in OT Base
3049 ============== ====================================
3050 Flat Amount Amount input value converted to hourly rate.
3051 Hours * Rate Rate input value.
3052 Hours * Rate * Multiple Rate input value.
3053 Percentage of Reg Sal Percentage input value * Monthly Salary, converted to
3054 hourly rate.
3055 Gross Up Gross Amount run result value converted to hourly rate.
3056 *****************************************************
3057 FUNCTION TEXT:
3058 *****************************************************
3059 */
3060 FUNCTION OT_Base_Rate ( p_bg_id in NUMBER,
3061 p_pay_id in NUMBER,
3062 p_ass_id in NUMBER,
3063 p_ass_action_id in NUMBER,
3064 p_date_earned in DATE,
3065 p_work_sched in VARCHAR2 ,
3066 p_std_hours in NUMBER ,
3067 p_ass_salary in NUMBER,
3068 p_ass_sal_basis in VARCHAR2,
3069 p_std_freq in VARCHAR2 )
3070 RETURN NUMBER IS
3071 --
3072 -- local constants
3073 --
3074 c_ot_scale VARCHAR2(80) := 'Hourly';
3075 c_rate_table_name VARCHAR2(80) := 'WAGE RATES';
3076 c_rate_table_column VARCHAR2(80) := 'Wage Rate';
3077 --
3078 -- local vars
3079 --
3080 v_entry_id NUMBER(9);
3081 v_ot_base_rate NUMBER(27,7) := 0;
3082 v_tew_rate NUMBER(27,7) := 0;
3083 v_regwage_rate NUMBER(27,7) := 0;
3084 v_regsal_rate NUMBER(27,7) := 0;
3085 v_regsal_mosal NUMBER(27,7) := 0;
3086 v_tew_rcode VARCHAR2(80);
3087 v_regwage_rcode VARCHAR2(80);
3088 v_use_regwage NUMBER(2);
3089 v_use_regsal NUMBER(2);
3090 v_ele_type_id NUMBER(9);
3091 v_ele_class_id NUMBER(9);
3092 v_include_in_ot VARCHAR2(1);
3093 v_equiv_hrly_rate VARCHAR2(80) := 'No OT';
3094 v_chk_sal VARCHAR2(1) := 'N';
3095 v_eletype_id NUMBER(9);
3096 v_ele_name VARCHAR2(80);
3097 v_ff_name VARCHAR2(80);
3098 v_flat_amount NUMBER(27,7) := 0;
3099 v_flat_total NUMBER(27,7) := 0;
3100 v_flat_count NUMBER(3) := 0;
3101 v_percentage NUMBER(27,7) := 0;
3102 v_pct_sal NUMBER(27,7) := 0;
3103 v_pct_total NUMBER(27,7) := 0;
3104 v_pct_count NUMBER(3) := 0;
3105 v_rate NUMBER(27,7) := 0;
3106 v_rate_total NUMBER(27,7) := 0;
3107 v_rate_count NUMBER(3) := 0;
3108 v_rate_rcode VARCHAR2(80);
3109 v_rate_multiple NUMBER(27,7) := 0;
3110 v_rate_mult_count NUMBER(3) := 0;
3111 v_gross_results NUMBER(3) := 0;
3112 v_gross_amount NUMBER(27,7) := 0;
3113 v_gross_total NUMBER(27,7) := 0;
3114 v_gross_count NUMBER(3) := 0;
3115 v_tew_count NUMBER(3) := 0;
3116 v_tew_total_rate NUMBER(27,7) := 0;
3117 v_pay_basis_rate NUMBER(27,7) := 0;
3118 v_work_sched_name VARCHAR2(80);
3119 v_ws_id NUMBER(9);
3120 v_range_start DATE;
3121 v_range_end DATE;
3122
3123 --
3124 --
3125 --
3126 CURSOR cur_element_type_id(p_element_name varchar2) IS
3127 SELECT element_type_id
3128 FROM pay_element_types_f
3129 WHERE element_name = p_element_name
3130 AND legislation_code = 'CA';
3131
3132 l_reg_sal_ele_id pay_element_types_f.element_type_id%TYPE;
3133 l_reg_wages_ele_id pay_element_types_f.element_type_id%TYPE;
3134 l_time_entry_ele_id pay_element_types_f.element_type_id%TYPE;
3135
3136 --
3137 -- local cursors
3138 --
3139 CURSOR get_tew_rate IS
3140 SELECT NVL(fnd_number.canonical_to_number(EEV.screen_entry_value), 0),
3141 EEV.element_entry_id
3142 FROM pay_element_entry_values_f EEV,
3143 pay_element_entries_f ELE,
3144 pay_input_values_f IPV
3145 WHERE ELE.assignment_id = p_ass_id
3146 AND ELE.element_entry_id = EEV.element_entry_id
3147 AND p_date_earned
3148 BETWEEN EEV.effective_start_date
3149 AND EEV.effective_end_date
3150 AND EEV.input_value_id = IPV.input_value_id
3151 AND IPV.element_type_id = l_time_entry_ele_id
3152 AND UPPER(IPV.name) = 'RATE';
3153 --
3154 --
3155 CURSOR get_include_in_ot IS
3156 SELECT ELT.element_type_id,
3157 ELT.element_name,
3158 FRA.formula_name
3159 FROM pay_element_entries_f ELE,
3160 pay_element_links_f ELI,
3161 pay_element_types_f ELT,
3162 pay_status_processing_rules_f SPR,
3163 ff_formulas_f FRA
3164 WHERE FRA.formula_id = SPR.formula_id
3165 AND p_date_earned
3166 BETWEEN SPR.effective_start_date
3167 AND SPR.effective_end_date
3168 AND SPR.assignment_status_type_id IS NULL
3169 AND SPR.element_type_id = ELT.element_type_id
3170 AND p_date_earned
3171 BETWEEN ELE.effective_start_date
3172 AND ELE.effective_end_date
3173 AND ELE.assignment_id = p_ass_id
3174 AND ELE.element_link_id = ELI.element_link_id
3175 AND p_date_earned
3176 BETWEEN ELI.effective_start_date
3177 AND ELI.effective_end_date
3178 AND ELI.element_type_id = ELT.element_type_id
3179 AND p_date_earned
3180 BETWEEN ELT.effective_start_date
3181 AND ELT.effective_end_date
3182 AND ELT.element_information8 = 'Y'
3183 AND ELT.element_information_category IN ( 'CA_EARNINGS',
3184 'CA_SUPPLEMENTAL EARNINGS');
3185 --
3186 -- These cursors get ALL entries of a particular element type during
3187 -- the period:
3188 /* Cursors get_flat_amounts, get_rates and get_percentage have been changed
3189 to improve performance.
3190 */
3191 CURSOR get_flat_amounts IS
3192 SELECT fnd_number.canonical_to_number(EEV.screen_entry_value)
3193 FROM pay_element_links_f pel,
3194 pay_element_entries_f ele,
3195 pay_element_entry_values_f eev,
3196 pay_input_values_f ipv
3197 WHERE pel.element_type_id = v_eletype_id
3198 AND p_date_earned BETWEEN pel.effective_start_date
3199 AND pel.effective_end_date
3200 AND ele.element_link_id = pel.element_link_id
3201 AND ele.assignment_id = p_ass_id
3202 AND ele.element_entry_id = eev.element_entry_id
3203 AND p_date_earned BETWEEN eev.effective_start_date
3204 AND eev.effective_end_date
3205 AND EEV.input_value_id = ipv.input_value_id
3206 AND IPV.element_type_id = pel.element_type_id --v_eletype_id
3207 AND IPV.name = 'Amount';
3208 --
3209 CURSOR get_rates IS
3210 SELECT fnd_number.canonical_to_number(EEV.screen_entry_value),
3211 EEV.element_entry_id
3212 FROM pay_element_links_f pel,
3213 pay_element_entries_f ele,
3214 pay_element_entry_values_f eev,
3215 pay_input_values_f ipv
3216 WHERE pel.element_type_id = v_eletype_id
3217 AND p_date_earned BETWEEN pel.effective_start_date
3218 AND pel.effective_end_date
3219 AND ele.element_link_id = pel.element_link_id
3220 AND ELE.assignment_id = p_ass_id
3221 AND ELE.element_entry_id = EEV.element_entry_id
3222 AND p_date_earned BETWEEN EEV.effective_start_date
3223 AND EEV.effective_end_date
3224 AND EEV.input_value_id = IPV.input_value_id
3225 AND IPV.element_type_id = pel.element_type_id --v_eletype_id
3226 AND IPV.name = 'Rate';
3227 --
3228 CURSOR get_percentages IS
3229 SELECT fnd_number.canonical_to_number(EEV.screen_entry_value)
3230 FROM pay_element_links_f pel,
3231 pay_element_entries_f ele,
3232 pay_element_entry_values_f eev,
3233 pay_input_values_f ipv
3234 WHERE pel.element_type_id = v_eletype_id
3235 AND p_date_earned BETWEEN pel.effective_start_date
3236 AND pel.effective_end_date
3237 AND ele.element_link_id = pel.element_link_id
3238 AND ele.assignment_id = p_ass_id
3239 AND ele.element_entry_id = EEV.element_entry_id
3240 AND p_date_earned BETWEEN EEV.effective_start_date
3241 AND EEV.effective_end_date
3242 AND eev.input_value_id = IPV.input_value_id
3243 AND ipv.element_type_id = pel.element_type_id --v_eletype_id
3244 AND ipv.name = 'Percentage';
3245 --
3246 CURSOR get_grosses IS
3247 SELECT RRV.result_value
3248 FROM pay_run_result_values RRV,
3249 pay_run_results RRS,
3250 pay_input_values_f IPV,
3251 pay_element_types_f ELT
3252 WHERE RRV.input_value_id = IPV.input_value_id
3253 AND RRV.run_result_id = RRS.run_result_id
3254 AND RRS.element_type_id = ELT.element_type_id
3255 AND RRS.assignment_action_id = p_ass_action_id
3256 AND p_date_earned
3257 BETWEEN IPV.effective_start_date
3258 AND IPV.effective_end_date
3259 AND IPV.name = 'Pay Value'
3260 AND IPV.element_type_id = ELT.element_type_id
3261 AND p_date_earned
3262 BETWEEN ELT.effective_start_date
3263 AND ELT.effective_end_date
3264 AND ELT.element_name = 'Vertex ' || v_ele_name || ' Gross';
3265 --
3266 -- Check with Roy on "<ELE_NAME> Gross" element being created for grossups.
3267 --
3268 --
3269 --
3270 --
3271 BEGIN -- OT_Base_Rate
3272 --
3273 -- Get "Regular" rate from either Time Entry Wages, Regular Wages,
3274 -- or Regular Salary. For Time Entry rate, we need to take an average
3275 -- of all Rates entered via Time Entry Wages.
3276 -- Remember to check for a rate via Rate Code!
3277 --
3278 -- Go ahead and set pay_basis_rate now - will most likely be used somewhere.
3279 --
3280 hr_utility.set_location('OT_Base_Rate', 5);
3281
3282 select start_date,
3283 end_date
3284 into v_range_start,
3285 v_range_end
3286 from per_time_periods
3287 where payroll_id = p_pay_id
3288 and p_date_earned between start_date and end_date;
3289
3290 OPEN cur_element_type_id('Regular Salary');
3291 FETCH cur_element_type_id
3292 INTO l_reg_sal_ele_id;
3293 CLOSE cur_element_type_id;
3294
3295 OPEN cur_element_type_id('Regular Wages');
3296 FETCH cur_element_type_id
3297 INTO l_reg_wages_ele_id;
3298 CLOSE cur_element_type_id;
3299
3300 OPEN cur_element_type_id('Times Entry Wages');
3301 FETCH cur_element_type_id
3302 INTO l_time_entry_ele_id;
3303 CLOSE cur_element_type_id;
3304
3305 v_pay_basis_rate := fnd_number.canonical_to_number(hr_ca_ff_udfs.convert_period_type(
3306 p_bus_grp_id => p_bg_id,
3307 p_payroll_id => p_pay_id,
3308 p_assignment_action_id => p_ass_action_id,
3309 p_assignment_id => p_ass_id ,
3310 p_element_entry_id => v_entry_id,
3311 p_date_earned => p_date_earned,
3312 p_asst_work_schedule => p_work_sched,
3313 p_asst_std_hours => p_std_hours,
3314 p_figure => p_ass_salary,
3315 p_from_freq => p_ass_sal_basis,
3316 p_to_freq => 'HOURLY',
3317 p_period_start_date => v_range_start,
3318 p_period_end_date => v_range_end,
3319 p_asst_std_freq => p_std_freq));
3320 --
3321 OPEN get_tew_rate;
3322 --
3323 LOOP
3324 hr_utility.set_location('OT_Base_Rate', 10);
3325 FETCH get_tew_rate
3326 INTO v_tew_rate, v_entry_id;
3327 EXIT WHEN get_tew_rate%NOTFOUND;
3328 --
3329 v_tew_count := v_tew_count + 1;
3330 IF v_tew_rate <> 0 THEN
3331 v_tew_total_rate := v_tew_total_rate + v_tew_rate;
3332 ELSE -- no Rate entered, check Rate Code
3333 hr_utility.set_location('OT_Base_Rate', 15);
3334 SELECT NVL(EEV.screen_entry_value, 'NOT ENTERED')
3335 INTO v_tew_rcode
3336 FROM pay_element_entry_values_f EEV,
3337 pay_element_entries_f ELE,
3338 pay_element_types_f ELT,
3339 pay_input_values_f IPV
3340 WHERE ELE.assignment_id = p_ass_id
3341 AND ELE.element_entry_id = EEV.element_entry_id
3342 AND p_date_earned
3343 BETWEEN EEV.effective_start_date
3344 AND EEV.effective_end_date
3345 AND EEV.element_entry_id = v_entry_id
3346 AND EEV.input_value_id = IPV.input_value_id
3347 AND UPPER(ELT.element_name) = 'TIME ENTRY WAGES'
3348 AND ELT.element_type_id = IPV.element_type_id
3349 AND UPPER(IPV.name) = 'RATE CODE';
3350 --
3351 IF v_tew_rcode = 'NOT ENTERED' THEN
3352 -- Use pay basis salary converted to hourly rate.
3353 v_tew_total_rate := v_tew_total_rate + v_pay_basis_rate;
3354 ELSE
3355 -- Find rate from rate table.
3356 hr_utility.set_location('OT_Base_Rate', 17);
3357 v_tew_total_rate := v_tew_total_rate +
3358 fnd_number.canonical_to_number(hruserdt.get_table_value(
3359 p_bg_id,
3360 c_rate_table_name,
3361 c_rate_table_column,
3362 v_tew_rcode));
3363 END IF;
3364 --
3365 END IF;
3366 --
3367 END LOOP;
3368 --
3369 CLOSE get_tew_rate;
3370 --
3371 IF v_tew_count = 0 THEN -- ie. only use "Regular" rates if TEW not entered.
3372 hr_utility.set_location('OT_Base_Rate', 20);
3373 SELECT COUNT(IPV.input_value_id)
3374 INTO v_use_regwage
3375 FROM pay_element_entry_values_f EEV,
3376 pay_element_entries_f ELE,
3377 pay_input_values_f IPV
3378 WHERE ELE.assignment_id = p_ass_id
3379 AND ELE.element_entry_id = EEV.element_entry_id
3380 AND p_date_earned
3381 BETWEEN EEV.effective_start_date
3382 AND EEV.effective_end_date
3383 AND EEV.input_value_id = IPV.input_value_id
3384 AND IPV.element_type_id = l_reg_wages_ele_id
3385 AND UPPER(IPV.name) = 'RATE';
3386 --
3387 IF v_use_regwage <> 0 THEN
3388 hr_utility.set_location('OT_Base_Rate', 30);
3389 SELECT NVL(fnd_number.canonical_to_number(EEV.screen_entry_value), 0),
3390 EEV.element_entry_id
3391 INTO v_regwage_rate,
3392 v_entry_id
3393 FROM pay_element_entry_values_f EEV,
3394 pay_element_entries_f ELE,
3395 pay_input_values_f IPV
3396 WHERE ELE.assignment_id = p_ass_id
3397 AND ELE.element_entry_id = EEV.element_entry_id
3398 AND p_date_earned
3399 BETWEEN EEV.effective_start_date
3400 AND EEV.effective_end_date
3401 AND EEV.input_value_id = IPV.input_value_id
3402 AND IPV.element_type_id = l_reg_wages_ele_id
3403 AND UPPER(IPV.name) = 'RATE';
3404 --
3405 IF v_regwage_rate = 0 THEN
3406 hr_utility.set_location('OT_Base_Rate', 40);
3407 SELECT NVL(EEV.screen_entry_value, 'NOT ENTERED')
3408 INTO v_regwage_rcode
3409 FROM pay_element_entry_values_f EEV,
3410 pay_element_entries_f ELE,
3411 pay_element_types_f ELT,
3412 pay_input_values_f IPV
3413 WHERE ELE.assignment_id = p_ass_id
3414 AND ELE.element_entry_id = EEV.element_entry_id
3415 AND p_date_earned
3416 BETWEEN EEV.effective_start_date
3417 AND EEV.effective_end_date
3418 AND EEV.element_entry_id = v_entry_id
3419 AND EEV.input_value_id = IPV.input_value_id
3420 AND UPPER(ELT.element_name) = 'REGULAR WAGES'
3421 AND ELT.element_type_id = IPV.element_type_id
3422 AND UPPER(IPV.name) = 'RATE CODE';
3423 --
3424 hr_utility.set_location('OT_Base_Rate', 41);
3425 v_regwage_rate := fnd_number.canonical_to_number(hruserdt.get_table_value(
3426 p_bus_group_id => p_bg_id,
3427 p_table_name => c_rate_table_name,
3428 p_col_name => c_rate_table_column,
3429 p_row_value => v_regwage_rcode));
3430 END IF;
3431 v_ot_base_rate := v_ot_base_rate + v_regwage_rate;
3432 --
3433 ELSE
3434 hr_utility.set_location('OT_Base_Rate', 50);
3435 SELECT COUNT(IPV.input_value_id)
3436 INTO v_use_regsal
3437 FROM pay_element_entry_values_f EEV,
3438 pay_element_entries_f ELE,
3439 pay_input_values_f IPV
3440 WHERE ELE.assignment_id = p_ass_id
3441 AND ELE.element_entry_id = EEV.element_entry_id
3442 AND p_date_earned
3443 BETWEEN EEV.effective_start_date
3444 AND EEV.effective_end_date
3445 AND EEV.input_value_id = IPV.input_value_id
3446 AND IPV.element_type_id = l_reg_sal_ele_id
3447 AND UPPER(IPV.name) = 'MONTHLY SALARY';
3448 --
3449 IF v_use_regsal <> 0 THEN
3450 hr_utility.set_location('OT_Base_Rate', 51);
3451 SELECT NVL(fnd_number.canonical_to_number(EEV.screen_entry_value), 0)
3452 INTO v_regsal_mosal
3453 FROM pay_element_entry_values_f EEV,
3454 pay_element_entries_f ELE,
3455 pay_input_values_f IPV
3456 WHERE ELE.assignment_id = p_ass_id
3457 AND ELE.element_entry_id = EEV.element_entry_id
3458 AND p_date_earned
3459 BETWEEN EEV.effective_start_date
3460 AND EEV.effective_end_date
3461 AND EEV.input_value_id = IPV.input_value_id
3462 AND IPV.element_type_id = l_reg_sal_ele_id
3463 AND UPPER(IPV.name) = 'MONTHLY SALARY';
3464 --
3465 hr_utility.set_location('OT_Base_Rate', 60);
3466
3467 v_regsal_rate := hr_ca_ff_udfs.Convert_Period_Type(
3468 p_bus_grp_id => p_bg_id,
3469 p_payroll_id => p_pay_id,
3470 p_assignment_action_id => p_ass_action_id,
3471 p_assignment_id => p_ass_id ,
3472 p_element_entry_id => v_entry_id,
3473 p_date_earned => p_date_earned,
3474 p_asst_work_schedule => p_work_sched,
3475 p_asst_std_hours => p_std_hours,
3476 p_figure => v_regsal_mosal,
3477 p_from_freq => p_ass_sal_basis,
3478 p_to_freq => 'HOURLY',
3479 p_period_start_date => v_range_start,
3480 p_period_end_date => v_range_end,
3481 p_asst_std_freq => p_std_freq);
3482 --
3483 END IF;
3484 --
3485 END IF; -- "Regular" rate done.
3486 --
3487 ELSE
3488 -- TEW entered, so take average:
3489 v_ot_base_rate := v_ot_base_rate + (v_tew_total_rate / v_tew_count);
3490 --
3491 END IF; -- TEW entered.
3492 --
3493 -- Now add all other "Include in OT Base" = 'Y' values.
3494 --
3495 OPEN get_include_in_ot;
3496 LOOP
3497 --
3498 hr_utility.set_location('OT_Base_Rate', 70);
3499 FETCH get_include_in_ot
3500 INTO v_eletype_id,
3501 v_ele_name,
3502 v_ff_name;
3503 EXIT WHEN get_include_in_ot%NOTFOUND;
3504 --
3505 IF SUBSTR(v_ff_name,1,11) = 'FLAT_AMOUNT' THEN
3506 -- Find "Amount" entered, convert to hourly figure.
3507 hr_utility.set_location('OT_Base_Rate', 80);
3508 OPEN get_flat_amounts;
3509 LOOP
3510 FETCH get_flat_amounts
3511 INTO v_flat_amount;
3512 EXIT WHEN get_flat_amounts%NOTFOUND;
3513 v_flat_count := v_flat_count + 1;
3514 hr_utility.set_location('OT_Base_Rate', 90);
3515
3516 v_flat_total := v_flat_total + hr_ca_ff_udfs.Convert_Period_Type(
3517 p_bus_grp_id => p_bg_id,
3518 p_payroll_id => p_pay_id,
3519 p_assignment_action_id => p_ass_action_id,
3520 p_assignment_id => p_ass_id ,
3521 p_element_entry_id => v_entry_id,
3522 p_date_earned => p_date_earned,
3523 p_asst_work_schedule => p_work_sched,
3524 p_asst_std_hours => p_std_hours,
3525 p_figure => v_flat_amount,
3526 p_from_freq => 'PERIOD',
3527 p_to_freq => 'HOURLY',
3528 p_period_start_date => v_range_start,
3529 p_period_end_date => v_range_end,
3530 p_asst_std_freq => p_std_freq);
3531 --
3532 END LOOP;
3533 CLOSE get_flat_amounts;
3534 --
3535 hr_utility.set_location('OT_Base_Rate', 100);
3536 v_ot_base_rate := v_ot_base_rate + (v_flat_total / v_flat_count);
3537 --
3538 ELSIF SUBSTR(v_ff_name,1,10) = 'PERCENTAGE' THEN
3539 hr_utility.set_location('OT_Base_Rate', 110);
3540 OPEN get_percentages;
3541 LOOP
3542 FETCH get_percentages
3543 INTO v_percentage;
3544 EXIT WHEN get_percentages%NOTFOUND;
3545 v_pct_count := v_pct_count + 1;
3546 --
3547 IF v_regsal_rate <> 0 THEN
3548 hr_utility.set_location('OT_Base_Rate', 105);
3549 v_pct_total := v_percentage * v_regsal_rate;
3550 END IF;
3551 --
3552 END LOOP;
3553 --
3554 CLOSE get_percentages;
3555 --
3556 hr_utility.set_location('OT_Base_Rate', 110);
3557 v_ot_base_rate := v_ot_base_rate + (v_pct_total / v_pct_count);
3558 --
3559 ELSIF SUBSTR(v_ff_name,1,12) = 'HOURS_X_RATE' THEN
3560 --
3561 -- Remember to look for "Rate Code" if necessary and "Multiple" always.
3562 --
3563 hr_utility.set_location('OT_Base_Rate', 115);
3564 OPEN get_rates;
3565 LOOP
3566 FETCH get_rates
3567 INTO v_rate, v_entry_id;
3568 EXIT WHEN get_rates%NOTFOUND;
3569 hr_utility.set_location('OT_Base_Rate', 120);
3570 v_rate_count := v_rate_count + 1;
3571 IF v_rate = 0 THEN
3572 hr_utility.set_location('OT_Base_Rate', 125);
3573 SELECT NVL(EEV.screen_entry_value, 'NOT ENTERED')
3574 INTO v_rate_rcode
3575 FROM pay_element_entry_values_f EEV,
3576 pay_element_entries_f ELE,
3577 pay_element_types_f ELT,
3578 pay_input_values_f IPV
3579 WHERE ELE.assignment_id = p_ass_id
3580 AND ELE.element_entry_id = EEV.element_entry_id
3581 AND p_date_earned
3582 BETWEEN EEV.effective_start_date
3583 AND EEV.effective_end_date
3584 AND EEV.element_entry_id = v_entry_id
3585 AND EEV.input_value_id = IPV.input_value_id
3586 AND UPPER(ELT.element_name) = UPPER(v_ele_name)
3587 AND ELT.element_type_id = IPV.element_type_id
3588 AND UPPER(IPV.name) = 'RATE CODE';
3589 --
3590 IF v_rate_rcode <> 'NOT ENTERED' THEN
3591 hr_utility.set_location('OT_Base_Rate', 130);
3592 v_rate := fnd_number.canonical_to_number(hruserdt.get_table_value(
3593 p_bg_id,
3594 c_rate_table_name,
3595 c_rate_table_column,
3596 v_rate_rcode));
3597 END IF;
3598 --
3599 END IF;
3600 -- Now get "Multiple" on this entry, if any.
3601 IF v_rate <> 0 THEN
3602 hr_utility.set_location('OT_Base_Rate', 135);
3603 SELECT COUNT(0)
3604 INTO v_rate_mult_count
3605 FROM pay_element_entry_values_f EEV,
3606 pay_element_entries_f ELE,
3607 pay_element_types_f ELT,
3608 pay_input_values_f IPV
3609 WHERE ELE.assignment_id = p_ass_id
3610 AND ELE.element_entry_id = EEV.element_entry_id
3611 AND p_date_earned
3612 BETWEEN EEV.effective_start_date
3613 AND EEV.effective_end_date
3614 AND EEV.element_entry_id = v_entry_id
3615 AND EEV.input_value_id = IPV.input_value_id
3616 AND UPPER(ELT.element_name) = UPPER(v_ele_name)
3617 AND ELT.element_type_id = IPV.element_type_id
3618 AND UPPER(IPV.name) = 'MULTIPLE';
3619 --
3620 IF v_rate_mult_count <> 0 THEN
3621 hr_utility.set_location('OT_Base_Rate', 140);
3622 SELECT NVL(EEV.screen_entry_value, 0)
3623 INTO v_rate_multiple
3624 FROM pay_element_entry_values_f EEV,
3625 pay_element_entries_f ELE,
3626 pay_element_types_f ELT,
3627 pay_input_values_f IPV
3628 WHERE ELE.assignment_id = p_ass_id
3629 AND ELE.element_entry_id = EEV.element_entry_id
3630 AND p_date_earned
3631 BETWEEN EEV.effective_start_date
3632 AND EEV.effective_end_date
3633 AND EEV.element_entry_id = v_entry_id
3634 AND EEV.input_value_id = IPV.input_value_id
3635 AND UPPER(ELT.element_name) = UPPER(v_ele_name)
3636 AND ELT.element_type_id = IPV.element_type_id
3637 AND UPPER(IPV.name) = 'MULTIPLE';
3638 --
3639 IF v_rate_multiple <> 0 THEN
3640 v_rate := v_rate * v_rate_multiple;
3641 END IF;
3642 --
3643 END IF;
3644 --
3645 END IF;
3646 --
3647 v_rate_total := v_rate_total + v_rate;
3648 --
3649 END LOOP;
3650 CLOSE get_rates;
3651 --
3652 v_ot_base_rate := v_ot_base_rate + (v_rate_total / v_rate_count);
3653 --
3654 ELSIF SUBSTR(v_ff_name,1,8) = 'GROSS_UP' THEN
3655 hr_utility.set_location('OT_Base_Rate', 150);
3656 OPEN get_grosses;
3657 LOOP
3658 FETCH get_grosses
3659 INTO v_gross_results;
3660 EXIT WHEN get_grosses%NOTFOUND;
3661 v_gross_count := v_gross_count + 1;
3662 IF v_gross_results <> 0 THEN
3663 -- Convert gross result to hourly figure.
3664 hr_utility.set_location('OT_Base_Rate', 160);
3665
3666 v_gross_total := v_gross_total + hr_ca_ff_udfs.Convert_Period_Type(
3667 p_bus_grp_id => p_bg_id,
3668 p_payroll_id => p_pay_id,
3669 p_assignment_action_id => p_ass_action_id,
3670 p_assignment_id => p_ass_id ,
3671 p_element_entry_id => v_entry_id,
3672 p_date_earned => p_date_earned,
3673 p_asst_work_schedule => p_work_sched,
3674 p_asst_std_hours => p_std_hours,
3675 p_figure => v_gross_amount,
3676 p_from_freq => NULL,
3677 p_to_freq => 'HOURLY',
3678 p_period_start_date => v_range_start,
3679 p_period_end_date => v_range_end,
3680 p_asst_std_freq => p_std_freq);
3681 --
3682 END IF;
3683 --
3684 END LOOP;
3685 CLOSE get_grosses;
3686 --
3687 v_ot_base_rate := v_ot_base_rate + (v_gross_total / v_gross_count);
3688 --
3689 END IF; -- Calc Method
3690 --
3691 END LOOP;
3692 --
3693 CLOSE get_include_in_ot;
3694 --
3695 RETURN v_ot_base_rate;
3696 --
3697 EXCEPTION
3698 WHEN NO_DATA_FOUND THEN
3699 hr_utility.set_location('OT_Base_Rate', 170);
3700 RETURN v_ot_base_rate;
3701 -- hr_utility.set_message(801, 'PAY_SCL_SEG_NOTFOUND');
3702 -- hr_utility.raise_error;
3703 --
3704 END OT_Base_Rate;
3705 --
3706 /*
3707 *****************************************************
3708 FUNCTION NAME:
3709 *****************************************************
3710 Dedn_Freq_Factor
3711 Inputs: p_payroll_id -- Context
3712 p_element_type_id -- Context
3713 p_date_earned -- Context
3714 p_ele_period_type -- DBI param
3715
3716 Outputs: v_dedn_freq_factor
3717
3718 28 JAN 1994 hparicha Created.
3719
3720 *****************************************************
3721 DESCRIPTION:
3722
3723 This function computes the "Deduction Frequency Factor" for deductions
3724 that have frequency rules and/or processing period type.
3725
3726 Algorithm:
3727
3728 IF period type IS NULL and frequency rules DO NOT exist THEN
3729
3730 dedn_freq_factor = 1 -- The deduction is assumed to be for the pay period.
3731
3732 ELSIF period type IS NULL and frequency rules EXIST THEN
3733
3734 dedn_freq_factor = 1 / (# pay periods in reset period)
3735
3736 ELSIF period type IS NOT NULL and frequency rules DO NOT exist THEN
3737
3738 dedn_freq_factor = (# per FY, eletype period type) /
3739 (# per FY, payroll period type)
3740
3741 ELSIF period type IS NOT NULL and frequency rules EXIST THEN
3742
3743 dedn_freq_factor = (# per FY, eletype period type) /
3744 (# per FY, reset period type) /
3745 (# pay periods in reset period)
3746
3747 END IF
3748 -- NOTE: "Reset Period" is either Month or Year.
3749 "# pay periods in reset period" means the number of deduction
3750 frequency rules for the ele/payroll that exist AND have a
3751 PERIOD_NO_IN_RESET_PERIOD less than the number of pay periods
3752 that will actually process.
3753 For example: if 2 bi-week pay periods will process in a month and the
3754 frequency rules say to process in the 1st and 3rd bi-wks of the month,
3755 then we need to process the deduction "in full" on the 1st run of the
3756 month. PERIOD_NO_IN_RESET_PERIOD = 1 and 3, so only one of these
3757 records has a column value less than the # pay periods that will
3758 actually process this month.
3759 --
3760 IF payroll period type is one of:
3761 Bi-Week,
3762 Calendar Month,
3763 Lunar Month,
3764 Semi-Month,
3765 Week
3766 THEN "reset period" = Month, number per fiscal year = 12.
3767 --
3768 IF payroll period type is one of:
3769 Bi-Month,
3770 Quarter,
3771 Semi-Year,
3772 Year
3773 THEN "reset period" = Year, number per fiscal year = 1.
3774
3775 *****************************************************
3776 FUNCTION TEXT:
3777 *****************************************************
3778 */
3779 FUNCTION Dedn_Freq_Factor (
3780 p_payroll_id in NUMBER,
3781 p_element_type_id in NUMBER,
3782 p_date_earned in DATE,
3783 p_ele_period_type in VARCHAR2)
3784 RETURN NUMBER IS
3785 --
3786 -- local constants
3787 --
3788 c_months_per_fy NUMBER(2) := 12;
3789 c_years_per_fy NUMBER(1) := 1;
3790 --
3791 -- local vars
3792 --
3793 v_date_earned DATE;
3794 v_dedn_freq_factor NUMBER(11,5);
3795 v_ele_period_num_per_fy NUMBER(3);
3796 v_pay_period_num_per_fy NUMBER(3);
3797 v_reset_periods_per_fy NUMBER(3);
3798 v_pay_periods_in_reset NUMBER(3);
3799 v_pay_periods_in_month NUMBER(3);
3800 v_pay_periods_in_year NUMBER(3);
3801 v_freq_rule_count NUMBER(3);
3802 v_freq_rules_exist VARCHAR2(1);
3803 v_pay_period_type VARCHAR2(30);
3804 --
3805 --
3806 BEGIN -- Dedn_Freq_Factor
3807 --
3808 -- v_date_earned := p_date_earned;
3809 --
3810 hr_utility.set_location('Dedn_Freq_Factor', 10);
3811 SELECT DECODE(COUNT(FRP.freq_rule_period_id), 0, 'N', 'Y')
3812 INTO v_freq_rules_exist
3813 FROM pay_freq_rule_periods FRP,
3814 pay_ele_payroll_freq_rules EPF
3815 WHERE FRP.ele_payroll_freq_rule_id = EPF.ele_payroll_freq_rule_id
3816 AND EPF.element_type_id = p_element_type_id
3817 AND EPF.payroll_id = p_payroll_id
3818 AND EPF.start_date <= p_date_earned;
3819 --
3820 IF p_ele_period_type = 'NOT ENTERED' THEN
3821 -- AND v_freq_rules_exist = 'N' (I say if ele period type is null, then
3822 -- dedn freq factor is 1 whether freq rules exist or not! Right, the
3823 -- freq rule will tell us WHEN to process the given Deduction amount.
3824 -- If there is no period type on the Dedn, then we take the FULL AMOUNT
3825 -- every time it is processed - according to freq rule.)
3826 --
3827 v_dedn_freq_factor := 1;
3828 --
3829 --
3830 ELSIF p_ele_period_type <> 'NOT ENTERED' AND v_freq_rules_exist = 'N' THEN
3831 --
3832 hr_utility.set_location('Dedn_Freq_Factor', 40);
3833 SELECT number_per_fiscal_year
3834 INTO v_ele_period_num_per_fy
3835 FROM per_time_period_types TPT
3836 WHERE UPPER(period_type) = UPPER(p_ele_period_type);
3837 --
3838 hr_utility.set_location('Dedn_Freq_Factor', 45);
3839 SELECT TPT.number_per_fiscal_year
3840 INTO v_pay_period_num_per_fy
3841 FROM per_time_period_types TPT,
3842 pay_payrolls_f PPF
3843 WHERE TPT.period_type = PPF.period_type
3844 AND p_date_earned
3845 BETWEEN PPF.effective_start_date
3846 AND PPF.effective_end_date
3847 AND PPF.payroll_id = p_payroll_id;
3848 --
3849 v_dedn_freq_factor := v_ele_period_num_per_fy / v_pay_period_num_per_fy;
3850 --
3851 ELSIF p_ele_period_type <> 'NOT ENTERED' AND v_freq_rules_exist = 'Y' THEN
3852 --
3853 hr_utility.set_location('Dedn_Freq_Factor', 50);
3854 SELECT number_per_fiscal_year
3855 INTO v_ele_period_num_per_fy
3856 FROM per_time_period_types TPT
3857 WHERE UPPER(period_type) = UPPER(p_ele_period_type);
3858 --
3859 hr_utility.set_location('Dedn_Freq_Factor', 55);
3860 SELECT TPT.number_per_fiscal_year
3861 INTO v_pay_period_num_per_fy
3862 FROM pay_payrolls_f PPF,
3863 per_time_period_types TPT
3864 WHERE TPT.period_type = PPF.period_type
3865 AND PPF.payroll_id = p_payroll_id
3866 AND p_date_earned
3867 BETWEEN PPF.effective_start_date
3868 AND PPF.effective_end_date;
3869 --
3870 IF v_pay_period_num_per_fy >= 12 THEN
3871 hr_utility.set_location('Dedn_Freq_Factor', 60);
3872 SELECT COUNT(0)
3873 INTO v_pay_periods_in_month
3874 FROM per_time_periods PTP
3875 WHERE PTP.end_date
3876 BETWEEN TRUNC(p_date_earned, 'MONTH')
3877 AND LAST_DAY(p_date_earned)
3878 AND PTP.payroll_id = p_payroll_id;
3879 --
3880 -- Frequency rules exist, so this select should never return 0.
3881 -- Just in case, we'll decode for 0 and set v_pay_periods_in_reset to 1.
3882 -- ie. so v_dedn_freq_factor will also equal 1.
3883 --
3884 hr_utility.set_location('Dedn_Freq_Factor', 65);
3885 SELECT COUNT(0)
3886 INTO v_pay_periods_in_reset
3887 FROM pay_ele_payroll_freq_rules EPF,
3888 pay_freq_rule_periods FRP
3889 WHERE FRP.period_no_in_reset_period <= v_pay_periods_in_month
3890 AND FRP.ele_payroll_freq_rule_id = EPF.ele_payroll_freq_rule_id
3891 AND EPF.payroll_id = p_payroll_id
3892 AND EPF.element_type_id = p_element_type_id;
3893 hr_utility.set_location('v_pay_periods_in_reset = ', v_pay_periods_in_reset);
3894 --
3895 IF v_ele_period_num_per_fy = v_pay_period_num_per_fy THEN
3896 v_dedn_freq_factor := 1;
3897 ELSIF v_pay_periods_in_reset = 0 THEN
3898 v_dedn_freq_factor := 0;
3899 -- Freq rules exist, but will not be processed enough this reset period.
3900 -- Ie. freq rule says process in 3rd bi-wk when only 2 will process in
3901 -- the current month, so NOTHING is taken for deduction (factor = 0).
3902 ELSE
3903 v_dedn_freq_factor := v_ele_period_num_per_fy / c_months_per_fy / v_pay_periods_in_reset;
3904 END IF;
3905 --
3906 ELSE
3907 hr_utility.set_location('Dedn_Freq_Factor', 70);
3908 SELECT COUNT(0)
3909 INTO v_pay_periods_in_year
3910 FROM per_time_periods PTP
3911 WHERE PTP.end_date
3912 BETWEEN TRUNC(p_date_earned,'YEAR')
3913 AND LAST_DAY(ADD_MONTHS(TRUNC(p_date_earned,'YEAR'), 11))
3914 AND PTP.payroll_id = p_payroll_id;
3915 --
3916 -- Frequency rules exist, so this select should never return 0.
3917 -- Just in case, we'll decode for 0 and set v_pay_periods_in_reset to 1.
3918 -- ie. so v_dedn_freq_factor will also equal 1.
3919 --
3920 hr_utility.set_location('Dedn_Freq_Factor', 75);
3921 SELECT DECODE(COUNT(0), 0, 1, COUNT(0))
3922 INTO v_pay_periods_in_reset
3923 FROM pay_ele_payroll_freq_rules EPF,
3924 pay_freq_rule_periods FRP
3925 WHERE FRP.period_no_in_reset_period <= v_pay_periods_in_year
3926 AND FRP.ele_payroll_freq_rule_id = EPF.ele_payroll_freq_rule_id
3927 AND EPF.payroll_id = p_payroll_id
3928 AND EPF.element_type_id = p_element_type_id;
3929 --
3930 hr_utility.set_location('v_pay_periods_in_reset = ', v_pay_periods_in_reset);
3931 IF v_ele_period_num_per_fy = v_pay_period_num_per_fy THEN
3932 v_dedn_freq_factor := 1;
3933 ELSE
3934 v_dedn_freq_factor := v_ele_period_num_per_fy / c_months_per_fy / v_pay_periods_in_reset;
3935 END IF;
3936 --
3937 END IF;
3938 --
3939 END IF;
3940 --
3941 hr_utility.set_location('Dedn_Freq_Factor', 80);
3942 RETURN v_dedn_freq_factor;
3943 --
3944 END Dedn_Freq_Factor;
3945 --
3946 FUNCTION Arrearage ( p_eletype_id IN NUMBER,
3947 p_date_earned IN DATE,
3948 p_partial_flag IN VARCHAR2,
3949 p_net_asg_run IN NUMBER,
3950 p_arrears_itd IN NUMBER,
3951 p_guaranteed_net IN NUMBER,
3952 p_dedn_amt IN NUMBER,
3953 p_to_arrears IN OUT NOCOPY NUMBER,
3954 p_not_taken IN OUT NOCOPY NUMBER)
3955 RETURN NUMBER IS
3956 --
3957 -- Call from fast formulae as:
3958 -- dedn_amt = arrearage ( <ELE_NAME>_PARTIAL_EE_CONTRIBUTIONS,
3959 -- NET_ASG_RUN,
3960 -- <ELE_NAME>_ARREARS_ASG_GRE_ITD,
3961 -- Guaranteed_Net,
3962 -- dedn_amt,
3963 -- to_arrears,
3964 -- not_taken)
3965 --
3966 -- Test cases need to be run where:
3967 -- 1. p_net_asg_run > p_guaranteed_net
3968 -- 2. p_net_asg_run < p_guaranteed_net
3969 -- 3. p_net_asg_run = 0
3970
3971 l_total_dedn NUMBER(27,7); -- local var
3972 l_dedn_amt NUMBER(27,7); -- local var
3973 v_dedn_multiple NUMBER(9);
3974 v_arrears_flag VARCHAR2(1);
3975 v_shadow_ele_name VARCHAR2(80);
3976 v_shadow_ele_id NUMBER(9);
3977 v_bg_id NUMBER(9);
3978
3979 --
3980 BEGIN
3981 --
3982 p_to_arrears := 0;
3983 p_not_taken := 0;
3984
3985 hr_utility.set_location('hr_ca_ff_udfs.arrearage', 1);
3986
3987 -- Determine if Arrears = 'Y' for this dedn
3988 -- Can do this by checking for "Clear Arrears" input value on base ele.
3989 -- This input value is only created when Arrears is marked Yes on Deductions
3990 -- screen.
3991
3992 begin
3993
3994 hr_utility.set_location('Shadow elename = '||v_shadow_ele_name, 38 );
3995
3996 select 'Y'
3997 into v_arrears_flag
3998 from pay_input_values_f ipv
3999 where ipv.name = 'Clear Arrears'
4000 and p_date_earned BETWEEN ipv.effective_start_date
4001 AND ipv.effective_end_date
4002 and ipv.element_type_id = p_eletype_id;
4003
4004 exception
4005
4006 WHEN NO_DATA_FOUND THEN
4007 hr_utility.set_location('Arrearage is NOT ON for this ele.', 99);
4008 v_arrears_flag := 'N';
4009
4010 WHEN TOO_MANY_ROWS THEN
4011 hr_utility.set_location('Too many rows returned for Clear Arrears inpval.', 99);
4012 v_arrears_flag := 'N';
4013
4014 end;
4015
4016 IF v_arrears_flag = 'N' THEN
4017
4018 IF p_net_asg_run - p_dedn_amt >= p_guaranteed_net THEN
4019
4020 p_to_arrears := 0;
4021 p_not_taken := 0;
4022 l_dedn_amt := p_dedn_amt;
4023 -- hr_utility.set_location('pycaudfs.arrearage.to_arrears = ', p_to_arrears);
4024 hr_utility.set_location('pycaudfs.arrearage.dedn_amt = ', p_dedn_amt);
4025 -- hr_utility.set_location('pycaudfs.arrearage.not_taken = ', p_not_taken);
4026
4027 ELSIF p_net_asg_run <= p_guaranteed_net THEN
4028 -- Don't take anything, no arrears contr either.
4029 p_to_arrears := 0;
4030 p_not_taken := p_dedn_amt;
4031 l_dedn_amt := 0;
4032 -- hr_utility.set_location('pycaudfs.arrearage.to_arrears = ', p_to_arrears);
4033 hr_utility.set_location('pycaudfs.arrearage.dedn_amt = ', l_dedn_amt);
4034 -- hr_utility.set_location('pycaudfs.arrearage.not_taken = ', p_not_taken);
4035
4036 ELSIF p_net_asg_run - p_dedn_amt < p_guaranteed_net THEN
4037
4038 IF p_partial_flag = 'Y' THEN
4039 --
4040 p_to_arrears := 0;
4041 p_not_taken := p_dedn_amt - (p_net_asg_run - p_guaranteed_net);
4042 l_dedn_amt := p_net_asg_run - p_guaranteed_net;
4043 -- hr_utility.set_location('pycaudfs.arrearage.to_arrears = ', p_to_arrears);
4044 -- hr_utility.set_location('pycaudfs.arrearage.not_taken = ', p_not_taken);
4045 hr_utility.set_location('pycaudfs.arrearage.dedn_amt = ', l_dedn_amt);
4046
4047 ELSE
4048
4049 p_to_arrears := 0;
4050 p_not_taken := p_dedn_amt;
4051 l_dedn_amt := 0;
4052 -- hr_utility.set_location('pycaudfs.arrearage.to_arrears = ', p_to_arrears);
4053 -- hr_utility.set_location('pycaudfs.arrearage.not_taken = ', p_not_taken);
4054 hr_utility.set_location('pycaudfs.arrearage.dedn_amt = ', l_dedn_amt);
4055
4056 END IF;
4057
4058 END IF;
4059
4060 ELSE -- Arrearage is on, try and clear any balance currently in arrears.
4061
4062 IF p_net_asg_run <= p_guaranteed_net THEN
4063
4064 -- Don't take anything, put it all in arrears.
4065 p_to_arrears := p_dedn_amt;
4066 p_not_taken := p_dedn_amt;
4067 l_dedn_amt := 0;
4068 -- hr_utility.set_location('pycaudfs.arrearage.to_arrears = ', p_to_arrears);
4069 hr_utility.set_location('pycaudfs.arrearage.dedn_amt = ', l_dedn_amt);
4070 -- hr_utility.set_location('pycaudfs.arrearage.not_taken = ', p_not_taken);
4071
4072 ELSE
4073
4074 l_total_dedn := p_dedn_amt + p_arrears_itd;
4075
4076 -- Attempt to clear any arrears bal:
4077
4078 IF p_net_asg_run - p_guaranteed_net >= l_total_dedn THEN
4079
4080 -- there's enough net to take it all, clear arrears:
4081 p_to_arrears := -1 * p_arrears_itd;
4082 l_dedn_amt := l_total_dedn;
4083 p_not_taken := 0;
4084 -- hr_utility.set_location('pycaudfs.arrearage.to_arrears = ', p_to_arrears);
4085 hr_utility.set_location('pycaudfs.arrearage.dedn_amt = ', l_dedn_amt);
4086 -- hr_utility.set_location('pycaudfs.arrearage.not_taken = ', p_not_taken);
4087
4088 /* Deleted a load of code above to fix 504970. If partial_flag = Y, then
4089 try and take as much of the total deduction amount (current dedn +
4090 arrears) and leave the rest in arrears. */
4091
4092 ELSIF p_partial_flag = 'Y' THEN
4093
4094 -- Going into arrears, not enough Net to take curr p_dedn_amt
4095 --
4096 p_to_arrears := (l_total_dedn - (p_net_asg_run - p_guaranteed_net)) +
4097 (-1 * p_arrears_itd);
4098 IF (p_net_asg_run - p_guaranteed_net) >= p_dedn_amt THEN
4099 p_not_taken := 0;
4100 ELSE
4101 p_not_taken := p_dedn_amt - (p_net_asg_run - p_guaranteed_net);
4102 END IF;
4103 l_dedn_amt := p_net_asg_run - p_guaranteed_net;
4104 -- hr_utility.set_location('pycaudfs.arrearage.to_arrears = ', p_to_arrears);
4105 hr_utility.set_location('pycaudfs.arrearage.dedn_amt = ', l_dedn_amt);
4106 -- hr_utility.set_location('pycaudfs.arrearage.not_taken = ', p_not_taken);
4107
4108 ELSE -- p_partial_flag = 'N'
4109 IF (p_net_asg_run - p_guaranteed_net) >= p_dedn_amt THEN
4110 -- Take the whole deduction amount.
4111 l_dedn_amt := p_dedn_amt;
4112 p_to_arrears := 0;
4113 p_not_taken := 0;
4114 ELSE
4115 -- Don't take anything, partial dedn = 'N'
4116 p_to_arrears := p_dedn_amt;
4117 p_not_taken := p_dedn_amt;
4118 l_dedn_amt := 0;
4119 END IF;
4120 -- hr_utility.set_location('pycaudfs.arrearage.to_arrears = ', p_to_arrears);
4121 hr_utility.set_location('pycaudfs.arrearage.dedn_amt = ', l_dedn_amt);
4122 -- hr_utility.set_location('pycaudfs.arrearage.not_taken = ', p_not_taken);
4123
4124 END IF;
4125
4126 END IF;
4127
4128 END IF;
4129 --
4130 -- p_to_arrears and p_not_taken are set and sent out as well.
4131 --
4132 RETURN l_dedn_amt;
4133 --
4134 END Arrearage;
4135 --
4136 -- G1668: Addr_Val optimization. We tune for the majority case of city/zip
4137 -- uniquely identifying a geocode and handle the exception cases
4138 -- as appropriate. The exceptions will be raise VERY RARELY.
4139 -- Part of the optimization assumes that the code which calls this fn
4140 -- verify that city/zip params are populated before making the call
4141 -- which essentially means city/zip are required params for optimal
4142 -- performance. In the event city/zip are not supplied, this function
4143 -- still works.
4144 --
4145 -- Optimization issues:
4146 -- 1. In order to get the BEST performance possible, we need to add a "mode"
4147 -- parameter in order to this function so that majority cases can be checked
4148 -- in the optimal order. The high volume users of this fn are MIX batch
4149 -- val and the payroll run (VERTEX formulae). Since we KNOW that MIX will
4150 -- only provide State and City params, we can quickly check this and return
4151 -- without going thru any of the gyrations needed for more general cases.
4152 -- The validation required for the VERTEX formulae will be the "general"
4153 -- case, tuned to succeed in the shortest possible time.
4154 -- Resolution: Make all params mandatory, make the calling modules take care
4155 -- of this requirement.
4156 --
4157 FUNCTION addr_val ( p_state_abbrev IN VARCHAR2 ,
4158 p_county_name IN VARCHAR2 ,
4159 p_city_name IN VARCHAR2 ,
4160 p_zip_code IN VARCHAR2 )
4161 RETURN VARCHAR2 IS
4162 --
4163 l_geocode VARCHAR2(11); -- Output var in "12-345-6789" format.
4164 --
4165 BEGIN -- Call main addr_val
4166
4167 l_geocode := addr_val(p_state_abbrev,
4168 p_county_name,
4169 p_city_name,
4170 p_zip_code,
4171 'N');
4172
4173 RETURN l_geocode;
4174 --
4175 EXCEPTION
4176 WHEN OTHERS THEN
4177 hr_utility.set_location('hr_ca_ff_udfs.addr_val', 20);
4178 l_geocode := '00-000-0000';
4179 RETURN l_geocode;
4180 --
4181 END addr_val; -- addr_val
4182
4183 FUNCTION addr_val ( p_state_abbrev IN VARCHAR2 ,
4184 p_county_name IN VARCHAR2 ,
4185 p_city_name IN VARCHAR2 ,
4186 p_zip_code IN VARCHAR2 ,
4187 p_skip_rule IN VARCHAR2 )
4188 RETURN VARCHAR2 IS
4189 --
4190 l_geocode VARCHAR2(11); -- Output var in "12-345-6789" format.
4191 l_state_code VARCHAR2(2);
4192 l_state_name VARCHAR2(25);
4193 l_county_code VARCHAR2(3);
4194 l_county_name VARCHAR2(20);
4195 l_city_code VARCHAR2(4);
4196 l_city_name VARCHAR2(25);
4197 l_zip_code VARCHAR2(5);
4198 --
4199 BEGIN -- Main addr_val
4200 l_zip_code := substr(p_zip_code, 1, 5);
4201 --
4202 begin -- (1)
4203 --
4204 begin -- (2)
4205 -- We're going 3-deep here in order to handle multiple raising
4206 -- of the same exception...will this work?
4207 -- 90% case, geo determined by city/zip combo:
4208
4209 IF (p_skip_rule = 'Y') THEN
4210 RAISE TOO_MANY_ROWS;
4211 END IF;
4212
4213 hr_utility.set_location('hr_ca_ff_udfs.addr_val', 1);
4214
4215 SELECT a.state_code||'-'||a.county_code||'-'||a.city_code
4216 INTO l_geocode
4217 FROM pay_us_zip_codes z,
4218 pay_us_city_names a
4219 WHERE a.city_name = INITCAP(p_city_name)
4220 AND
4221 z.state_code = a.state_code AND
4222 z.county_code = a.county_code AND
4223 z.city_code = a.city_code AND
4224 l_zip_code BETWEEN z.zip_start AND z.zip_end;
4225 --
4226 EXCEPTION -- (2)
4227 --
4228 WHEN NO_DATA_FOUND THEN -- Invalid city/zip combo
4229 hr_utility.set_location('hr_ca_ff_udfs.addr_val', 3);
4230 l_geocode := '00-000-0000';
4231 RETURN l_geocode;
4232 --
4233 WHEN TOO_MANY_ROWS THEN -- city/zip does not uniquely defn geo
4234 -- same county name can exists in many states
4235 SELECT state_code
4236 INTO l_state_code
4237 FROM pay_us_states
4238 WHERE state_abbrev = p_state_abbrev;
4239
4240 hr_utility.set_location('hr_ca_ff_udfs.addr_val', 5);
4241 SELECT a.state_code||'-'||a.county_code||'-'||a.city_code
4242 INTO l_geocode
4243 FROM pay_us_zip_codes z,
4244 pay_us_city_names a,
4245 pay_us_counties b
4246 WHERE a.city_name = INITCAP(p_city_name)
4247 AND a.county_code = b.county_code
4248 AND b.county_name = INITCAP(p_county_name)
4249 AND b.state_code = l_state_code
4250 AND z.state_code = a.state_code AND
4251 z.county_code = a.county_code AND
4252 z.city_code = a.city_code AND
4253 l_zip_code BETWEEN z.zip_start AND z.zip_end;
4254 --
4255 end; -- (2)
4256 --
4257 EXCEPTION -- (1)
4258 --
4259 -- Fallout from (2) ie. county/city/zip combo invalid or does not
4260 -- uniquely define geocode.
4261 WHEN NO_DATA_FOUND THEN
4262 hr_utility.set_location('hr_ca_ff_udfs.addr_val', 7);
4263 l_geocode := '00-000-0000';
4264 RETURN l_geocode;
4265 --
4266 WHEN TOO_MANY_ROWS THEN
4267 hr_utility.set_location('hr_ca_ff_udfs.addr_val', 9);
4268 SELECT a.state_code||'-'||a.county_code||'-'||a.city_code
4269 INTO l_geocode
4270 FROM pay_us_zip_codes z,
4271 pay_us_city_names a,
4272 pay_us_counties b,
4273 pay_us_states c
4274 WHERE c.state_code = a.state_code AND
4275 c.state_abbrev = UPPER(p_state_abbrev)
4276 AND
4277 b.county_name = INITCAP(p_county_name)AND
4278 b.state_code = c.state_code
4279 AND
4280 a.city_name = INITCAP(p_city_name) AND
4281 a.state_code = c.state_code AND
4282 a.county_code = b.county_code
4283 AND
4284 z.state_code = c.state_code AND
4285 z.county_code = b.county_code AND
4286 z.city_code = a.city_code AND
4287 l_zip_code BETWEEN z.zip_start AND z.zip_end;
4288 --
4289 end; -- (1)
4290 --
4291 -- We're in Main
4292 --
4293 hr_utility.set_location('hr_ca_ff_udfs.addr_val', 11);
4294 --
4295 if (substr(l_geocode,8,1) = 'U') THEN
4296 l_geocode := substr(l_geocode,1,7)||'0000';
4297 END IF;
4298 --
4299 RETURN l_geocode;
4300 --
4301 EXCEPTION -- Main addr_val
4302 -- Fallout from (1) state/county/city/zip does not uniquely define a geo.
4303 -- Return failure geocode.
4304 WHEN NO_DATA_FOUND THEN
4305 hr_utility.set_location('hr_ca_ff_udfs.addr_val', 13);
4306 l_geocode := '00-000-0000';
4307 RETURN l_geocode;
4308 --
4309 WHEN TOO_MANY_ROWS THEN
4310 hr_utility.set_location('hr_ca_ff_udfs.addr_val', 15);
4311 l_geocode := '00-000-0000';
4312 RETURN l_geocode;
4313 --
4314 END addr_val; -- Main addr_val
4315 --
4316
4317 /*
4318 Created for Bug 5097793.
4319 1] Fetch the regular earnings in the current period based on the salary basis code.
4320
4321 */
4322 FUNCTION get_earnings_and_type( p_bus_grp_id IN NUMBER,
4323 p_asst_id IN NUMBER,
4324 p_assignment_action_id IN NUMBER,
4325 p_payroll_id IN NUMBER,
4326 p_ele_entry_id IN NUMBER,
4327 p_tax_unit_id IN NUMBER,
4328 p_date_earned IN DATE,
4329 p_pay_basis IN VARCHAR2 DEFAULT NULL,
4330 p_period_start IN DATE,
4331 p_period_end IN DATE,
4332 p_element_type IN OUT NOCOPY VARCHAR2,
4333 p_value IN OUT NOCOPY NUMBER,
4334 p_input_value_name IN OUT NOCOPY VARCHAR2)
4335 RETURN NUMBER AS
4336
4337 CURSOR csr_reg_earnings(p_assignment_id NUMBER,
4338 p_bus_grp_id NUMBER,
4339 p_date_earned DATE) IS
4340 SELECT peev.screen_entry_value
4341 ,piv.name
4342 FROM pay_element_entry_values_f peev
4343 ,pay_element_entries_f pee
4344 ,pay_element_links_f pel
4345 ,pay_element_types_f pet
4346 ,pay_input_values_f piv
4347 ,per_pay_bases ppb
4348 ,per_all_assignments_f paa
4349 WHERE paa.assignment_id = p_assignment_id
4350 AND paa.business_group_id = p_bus_grp_id
4351 AND p_date_earned BETWEEN paa.effective_start_date AND paa.effective_end_date
4352 AND paa.pay_basis_id = ppb.pay_basis_id
4353 AND ppb.input_value_id = piv.input_value_id
4354 AND p_date_earned BETWEEN piv.effective_start_date AND piv.effective_end_date
4355 AND piv.element_type_id = pet.element_type_id
4356 AND p_date_earned BETWEEN pet.effective_start_date AND pet.effective_end_date
4357 AND pet.element_type_id = pel.element_type_id
4358 AND p_date_earned BETWEEN pel.effective_start_date AND pel.effective_end_date
4359 AND pel.element_link_id = pee.element_link_id
4360 AND pee.assignment_id = p_assignment_id
4361 AND p_date_earned BETWEEN pee.effective_start_date AND pee.effective_end_date
4362 AND pee.element_entry_id = peev.element_entry_id
4363 AND p_date_earned BETWEEN peev.effective_start_date AND peev.effective_end_date
4364 AND pee.element_type_id = pet.element_type_id
4365 AND peev.input_value_id = ppb.input_value_id;
4366
4367 l_value NUMBER;
4368 l_input_value_name VARCHAR2(200);
4369
4370 BEGIN
4371 hr_utility.set_location('in get_earnings_and_type',10);
4372 hr_utility.set_location('p_bus_grp_id -> '|| p_bus_grp_id ,10);
4373 hr_utility.set_location(' p_asst_id -> '|| p_asst_id ,10);
4374 hr_utility.set_location(' p_assignment_action_id -> '|| p_assignment_action_id,10);
4375 hr_utility.set_location(' p_date_earned -> '|| p_date_earned ,10);
4376 hr_utility.set_location(' p_period_start -> '|| to_char(p_period_start) ,10);
4377 hr_utility.set_location(' p_period_end -> '|| to_char(p_period_end),10);
4378 hr_utility.set_location(' p_pay_basis -> '|| p_pay_basis,10);
4379
4380 l_value := 0;
4381
4382 OPEN csr_reg_earnings(p_asst_id, p_bus_grp_id, p_date_earned);
4383 FETCH csr_reg_earnings INTO l_value,l_input_value_name;
4384 IF csr_reg_earnings%NOTFOUND THEN
4385 p_value := 0;
4386 p_element_type := 'DUMMY';
4387 p_input_value_name := 'DUMMY';
4388 ELSE
4389 p_value := l_value;
4390 p_element_type := 'REGULAR_SALARY';
4391 p_input_value_name := l_input_value_name;
4392 END IF;
4393 CLOSE csr_reg_earnings;
4394
4395 hr_utility.set_location('returning p_value '|| p_value,10);
4396 hr_utility.set_location('returning p_element_type '|| p_element_type,10);
4397 hr_utility.set_location('returning p_input_value_name '|| p_input_value_name,10);
4398
4399 RETURN 0;
4400
4401
4402 END get_earnings_and_type;
4403
4404
4405 END hr_ca_ff_udfs;