1 PACKAGE BODY PA_HR_UPDATE_API AS
2 -- $Header: PARHRUPB.pls 120.30 2010/10/31 20:36:40 nisinha ship $
3
4 --FUNCTION Get_Country_name(p_country_code VARCHAR2) RETURN VARCHAR2 ;
5
6 -- Global variable for debugging. Bug 4352236.
7 -- G_DEBUG_MODE varchar2(1) := NVL(FND_PROFILE.value('PA_DEBUG_MODE'), 'N');
8 --------------------------------------------------------------------------------------------------------------
9 -- This procedure prints the text which is being passed as the input
10 -- Input parameters
11 -- Parameters Type Required Description
12 -- p_log_msg VARCHAR2 YES It stores text which you want to print on screen
13 -- Out parameters
14 ----------------------------------------------------------------------------------------------------------------
15 PROCEDURE log_message (p_log_msg IN VARCHAR2)
16
17 IS
18 -- P_DEBUG_MODE varchar2(1); -- Bug 4352236 - use global variable G_DEBUG_MODE
19 BEGIN
20 --dbms_output.put_line('log: ' || p_log_msg);
21 -- P_DEBUG_MODE := NVL(FND_PROFILE.value('PA_DEBUG_MODE'), 'N');
22 -- IF (G_DEBUG_MODE ='Y') THEN
23 pa_debug.write('HR_UPDATE_API', 'log: ' || p_log_msg, 3);
24 -- END IF;
25 -- NULL;
26 END log_message;
27
28 -- This API returns the job group id for the corresponding Job
29 FUNCTION get_job_group_id(
30 P_job_id IN per_jobs.job_id%type
31 ) RETURN per_job_groups.job_group_id%type
32 IS
33 v_job_grp_id per_job_groups.job_group_id%type;
34
35 BEGIN
36 v_job_grp_id := PA_JOB_UTILS.get_job_group_id(P_job_id);
37
38 return (v_job_grp_id);
39
40 END get_job_group_id;
41
42
43 -- This is an wrapper api for the check exp ou procedure
44 -- this function returns 'Y' if the given OU is valid otherwise it returns 'N'
45 FUNCTION validate_exp_OU (p_org_id IN NUMBER)
46 return VARCHAR2 IS
47 v_return_status varchar2(1000);
48 v_error_message_code varchar2(1000);
49 BEGIN
50
51 pa_hr_update_api.check_exp_OU(p_org_id => p_org_id
52 ,x_return_status => v_return_status
53 ,x_error_message_code => v_error_message_code
54 );
55
56 If v_return_status = FND_API.G_RET_STS_SUCCESS then
57 return 'Y';
58 else
59 return 'N';
60 End if;
61
62
63
64 END validate_exp_OU;
65
66
67
68
69 -- This Function returns the job level DFF based on the job_id and Job_group_id
70 -- 24-Dec: Move the logic of the code to PA_JOB_UTILS and call the function here
71 FUNCTION get_job_level(
72 P_job_id IN per_jobs.job_id%type
73 ,P_job_group_id IN per_job_groups.job_group_id%type
74 ) RETURN NUMBER
75 IS
76 l_job_level NUMBER;
77
78 BEGIN
79 l_job_level := PA_JOB_UTILS.get_job_level (
80 P_job_id => P_job_id
81 ,P_job_group_id => P_job_group_id
82 );
83
84 Return l_job_level;
85
86 END get_job_level;
87
88
89 -- This Procedure Adds messages to stack
90 PROCEDURE add_to_stack(P_return_status VARCHAR2,
91 P_error_message_code VARCHAR2
92 ) IS
93
94 BEGIN
95
96 if P_return_status <> FND_API.G_RET_STS_SUCCESS then
97 PA_UTILS.add_message(p_app_short_name => 'PA',
98 p_msg_name => P_error_message_code);
99 end if;
100
101
102 END add_to_stack;
103
104
105 -- This Function returns boolean value of true if a job is master job otherwise
106 -- it returns false -- IN parameter will be job_id
107 FUNCTION check_master_job(P_job_id IN per_Jobs.job_id%type)
108 RETURN boolean
109 IS
110 l_flag BOOLEAN;
111
112 BEGIN
113 l_flag := PA_JOB_UTILS.check_master_job(P_job_id);
114 return l_flag;
115
116 END check_master_job;
117
118
119 -- This API returns the utilization of job / person
120 -- The IN parameters will be Person_id and Date for Person's Billability
121 -- OR Job_id for the Job's billability
122 FUNCTION check_job_utilization
123 (
124 P_job_id IN number
125 ,P_person_id IN number
126 ,P_date IN date
127 ) RETURN VARCHAR2
128 IS
129
130 utilization_flag VARCHAR2(150);
131 v_job_id per_jobs.job_id%type;
132 v_job_info_type VARCHAR2(20) := 'Job Category';
133
134 BEGIN
135
136
137 v_job_id := P_job_id;
138 If P_person_id is NOT NULL AND P_date is NOT NULL AND P_job_id is NULL then
139
140 SELECT Job_id
141 INTO v_job_id
142 FROM per_all_assignments_f
143 WHERE Person_id = P_person_id
144 AND P_date BETWEEN effective_start_date
145 AND effective_end_date
146 AND job_id is NOT NULL
147 AND primary_flag = 'Y'
148 and assignment_type in ('E', 'C');
149
150 End if;
151
152 If v_job_id is NOT NULL then
153 SELECT jei_information3
154 INTO utilization_flag
155 FROM per_job_extra_info
156 WHERE job_id = v_job_id
157 AND information_type = v_job_info_type
158 AND jei_information3 IS NOT NULL; -- Bug 2898766
159 End if;
160
161 If utilization_flag is NULL then
162 utilization_flag := 'N';
163 End if;
164
165 return (utilization_flag);
166
167 EXCEPTION
168 /* Bug 2898766 - Handled the exception if more than one rows are returned */
169 WHEN TOO_MANY_ROWS THEN
170 utilization_flag := 'X';
171 return (utilization_flag );
172
173 WHEN NO_DATA_FOUND then
174 utilization_flag := 'N';
175 return (utilization_flag );
176
177 END check_job_utilization;
178
179
180
181
182 -- This API returns the Billability of job / person
183 -- The IN parameters will be Person_id and Date for Person's Billability
184 -- OR Job_id for the Job's billability
185 FUNCTION check_job_billability
186 (
187 P_job_id IN number
188 ,P_person_id IN number
189 ,P_date IN date
190 ) RETURN VARCHAR2
191 IS
192
193 Billable_flag VARCHAR2(150);
194 v_job_id per_jobs.job_id%type;
195 v_job_info_type VARCHAR2(20) := 'Job Category';
196
197 BEGIN
198
199
200 v_job_id := P_job_id;
201 If P_person_id is NOT NULL AND P_date is NOT NULL AND P_job_id is NULL then
202
203 SELECT Job_id
204 INTO v_job_id
205 FROM per_all_assignments_f
206 WHERE Person_id = P_person_id
207 AND P_date BETWEEN effective_start_date
208 AND effective_end_date
209 AND job_id is NOT NULL
210 AND primary_flag = 'Y'
211 AND assignment_type in ('E', 'C');
212 End if;
213
214 If v_job_id is NOT NULL then
215 SELECT jei_information2
216 INTO Billable_flag
217 FROM per_job_extra_info
218 WHERE job_id = v_job_id
219 AND information_type = v_job_info_type
220 AND jei_information2 IS NOT NULL; -- Bug 2898766
221 End if;
222
223 If Billable_flag is NULL then
224 Billable_flag := 'N';
225 End if;
226
227 return (Billable_flag);
228
229 EXCEPTION
230 /* Bug 2898766 - Handled the exception if more than one rows are returned */
231 WHEN TOO_MANY_ROWS THEN
232 Billable_flag := 'X';
233 return (Billable_flag );
234
235 WHEN NO_DATA_FOUND then
236 Billable_flag := 'N';
237 return (Billable_flag );
238
239 END check_job_billability;
240
241
242
243 ----------------------------------------------------------------
244 -- This API returns the schedulable_flag value of the passed job
245 ----------------------------------------------------------------
246 FUNCTION check_job_schedulable
247 (
248 p_job_id IN NUMBER
249 ,p_person_id IN NUMBER
250 ,p_date IN DATE
251 ) RETURN VARCHAR2
252 IS
253 l_schedulable_flag VARCHAR2(150) := 'N';
254 l_job_info_type VARCHAR2(20) := 'Job Category';
255 l_job_id NUMBER;
256 BEGIN
257 l_job_id := p_job_id;
258
259 IF p_person_id is NOT NULL AND p_date is NOT NULL THEN
260 SELECT job_id
261 INTO l_job_id
262 FROM per_all_assignments_f paaf
263 WHERE paaf.person_id = p_person_id
264 AND trunc(p_date) BETWEEN trunc(paaf.effective_start_date) -- Bug 8269512 : introduced trunc() on dates
265 AND trunc(paaf.effective_end_date) -- Bug 8269512 : introduced trunc() on dates
266 AND paaf.job_id is NOT NULL
267 AND paaf.primary_flag = 'Y'
268 AND paaf.assignment_type in ('E', 'C')
269 AND ((SELECT per_system_status
270 FROM per_assignment_status_types past
271 WHERE past.assignment_status_type_id = paaf.assignment_status_type_id) IN ('ACTIVE_ASSIGN','ACTIVE_CWK')); --Bug#8879958
272 END IF;
273
274 IF l_job_id is NOT NULL THEN
275 SELECT jei_information6
276 INTO l_schedulable_flag
277 FROM per_job_extra_info
278 WHERE job_id = l_job_id
279 AND information_type = l_job_info_type
280 AND jei_information6 IS NOT NULL;
281
282 IF l_schedulable_flag IS NULL THEN
283 l_schedulable_flag := 'N';
284 END IF;
285 END IF;
286
287 RETURN l_schedulable_flag;
288 EXCEPTION
289 WHEN TOO_MANY_ROWS THEN
290 l_schedulable_flag := 'X';
291 RETURN l_schedulable_flag;
292 WHEN NO_DATA_FOUND then
293 RETURN l_schedulable_flag;
294
295 END check_job_schedulable;
296
297
298
299 -- This Procedure checks whether the given OU is valid or Not
300 PROCEDURE check_exp_OU(p_org_id IN NUMBER
301 ,x_return_status OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
302 ,x_error_message_code OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
303 ) IS
304
305 v_error_message_code VARCHAR2(1000) := 'PA_INVALID_EXP_OU';
306 --'Invalid Operating Unit';
307 v_return_status VARCHAR2(1);
308 v_dummy VARCHAR2(1):= 'N';
309 BEGIN
310 -- Initialize the Error stack
311 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.check_exp_OU');
312 -- Initialize the error status
313 x_return_status := FND_API.G_RET_STS_SUCCESS;
314
315 If p_org_id is NOT NULL then
316
317 SELECT 'Y'
318 INTO v_dummy
319 FROM pa_implementations_all
320 WHERE org_id = p_org_id
321 AND rownum = 1;
322
323 End if;
324 /*
325
326 If v_dummy = 'Y' then
327 x_error_message_code := 'Exp Ou';
328 End if;
329 */
330 -- reset the Error stack
331 PA_DEBUG.Reset_Err_Stack;
332
333 EXCEPTION
334
335 WHEN NO_DATA_FOUND THEN
336 x_error_message_code := v_error_message_code;
337 x_return_status := FND_API.G_RET_STS_ERROR;
338
339
340 WHEN OTHERS THEN
341 -- Set the exception Message and the stack
342 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.check_exp_OU'
343 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
344 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
345 -- 4537865 : RESET x_error_message_code also
346 x_error_message_code := SQLCODE ;
347
348 raise;
349
350
351
352 END check_exp_OU;
353
354
355 -- This API makes calls to PA_REOSURCE_PVT.UPDATE_RESOURCE_DENORM api
356 -- which actually updates the pa_reosurces_denorm entity
357 PROCEDURE call_create_resource_denorm
358 (P_job_id_old per_jobs.job_id%type
359 ,P_job_id_new per_jobs.job_id%type
360 ,P_job_level_old NUMBER
361 ,P_job_level_new NUMBER
362 ,x_return_status OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
363 ,x_msg_data OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
364 ,x_msg_count OUT NOCOPY NUMBER --File.Sql.39 bug 4440895
365 ) IS
366 v_return_status VARCHAR2(2000);
367 v_error_message_code VARCHAR2(2000);
368 v_resource_rec_old PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
369 v_resource_rec_new PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
370 v_job_level_old NUMBER := 0;
371 v_job_level_new NUMBER;
372 v_job_id_old PER_JOBS.JOB_ID%type;
373 v_job_id_new PER_JOBS.JOB_ID%type;
374 v_msg_data VARCHAR2(2000);
375 v_msg_count NUMBER;
376 BEGIN
377 -- Initialize the Error stack
378 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.call_create_resoruce_denorm');
379 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
380 v_job_id_new := P_job_id_new;
381 v_job_level_new := P_job_level_new;
382 v_job_id_old := P_job_id_old;
383 v_job_level_old := 0;
384 If v_job_level_new is NULL then
385 v_job_level_new := 0; ---- to be confirmed if no job level is found
386 end if; ----- then assign joblevel to zero when grade is deleted
387
388 if P_job_level_old is NOT NULL then
389 v_job_level_old := P_job_level_old;
390 end if;
391 If P_job_id_old is NULL then
392 v_job_id_old := P_job_id_new;
393 end if;
394
395 if v_job_id_new is NOT NULL and v_job_level_new is NOT NULL then
396 v_resource_rec_old.job_id := v_job_id_old;
397 v_resource_rec_old.resource_job_level := v_job_level_old;
398 v_resource_rec_new.job_id := v_job_id_new;
399 v_resource_rec_new.resource_job_level := v_job_level_new;
400
401 -- Call PRM API update resource denorm which actually updates the
402 -- pa_resource_denorm entity
403 PA_RESOURCE_PVT.update_resource_denorm
404 ( p_resource_denorm_old_rec => v_resource_rec_old
405 ,p_resource_denorm_new_rec => v_resource_rec_new
406 ,x_return_status => x_return_status
407 ,x_msg_data => x_msg_data
408 ,x_msg_count => x_msg_count
409 );
410
411
412 End if;
413
414
415
416 -- reset the Error stack
417 PA_DEBUG.Reset_Err_Stack;
418
419 EXCEPTION
420
421 WHEN OTHERS THEN
422 -- 4537865 : RESET x_msg_count and x_msg_data also
423 x_msg_count := 1 ;
424 x_msg_data := SUBSTRB(SQLERRM ,1,240);
425
426 -- Set the exception Message and the stack
427 FND_MSG_PUB.add_exc_msg( p_pkg_name => 'PA_HR_UPDATE_API.call_create_resource_denorm'
428 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
429 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
430 raise;
431
432
433
434 END call_create_resource_denorm;
435
436 -- This API makes calls to PA_RESOURCE_PVT.UPDATE_RESOURCE_DENORM API
437 -- which actually updates the pa_resources_denorm entity
438 -- This API will update the job level of the job id passed in of the
439 -- resources denorm records
440 PROCEDURE update_job_level_res_denorm
441 ( P_job_id_old per_jobs.job_id%type
442 ,P_job_id_new per_jobs.job_id%type
443 ,P_job_level_old NUMBER
444 ,P_job_level_new NUMBER
445 ,x_return_status OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
446 ,x_msg_data OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
447 ,x_msg_count OUT NOCOPY NUMBER --File.Sql.39 bug 4440895
448 ) IS
449
450 l_resource_rec_old PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
451 l_resource_rec_new PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
452 l_job_level_old NUMBER;
453 l_job_level_new NUMBER;
454 l_job_id_old PER_JOBS.JOB_ID%type;
455 l_job_id_new PER_JOBS.JOB_ID%type;
456 P_DEBUG_MODE VARCHAR2(1) := NVL(FND_PROFILE.value('PA_DEBUG_MODE'), 'N');
457
458 BEGIN
459 -- Initialize the Error stack
460 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.update_job_level_res_denorm');
461 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
462
463 l_job_id_new := P_job_id_new;
464 l_job_level_new := P_job_level_new;
465 l_job_id_old := P_job_id_old;
466 l_job_level_old := P_job_level_old;
467
468 IF P_DEBUG_MODE = 'Y' THEN
469 log_message('====== Job Id Info ==========');
470 log_message('Job Id = ' || l_job_id_new);
471 log_message('Job Level Old = ' || l_job_level_old);
472 log_message('Job Level New = ' || l_job_level_new);
473 END IF;
474
475 l_resource_rec_old.job_id := l_job_id_old;
476 l_resource_rec_old.resource_job_level := l_job_level_old;
477 l_resource_rec_new.job_id := l_job_id_new;
478 l_resource_rec_new.resource_job_level := l_job_level_new;
479
480 -- Call PRM API update resource denorm which actually updates the
481 -- pa_resource_denorm entity
482 PA_RESOURCE_PVT.update_resource_denorm
483 ( p_resource_denorm_old_rec => l_resource_rec_old
484 ,p_resource_denorm_new_rec => l_resource_rec_new
485 ,x_return_status => x_return_status
486 ,x_msg_data => x_msg_data
487 ,x_msg_count => x_msg_count
488 );
489
490 -- reset the Error stack
491 PA_DEBUG.Reset_Err_Stack;
492
493 EXCEPTION
494
495 WHEN OTHERS THEN
496 -- 4537865 : RESET x_msg_count and x_msg_data also
497 x_msg_count := 1 ;
498 x_msg_data := SUBSTRB(SQLERRM ,1,240);
499
500 -- Set the exception Message and the stack
501 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.update_job_level_res_denorm'
502 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
503 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
504 raise;
505
506 END update_job_level_res_denorm;
507
508 -- This API gets all jobs belonging to the master job id and updates
509 -- the resource denorm records that has the affected job id
510 PROCEDURE update_all_jobs
511 ( P_job_id per_jobs.job_id%type
512 ,P_job_level_old pa_resources_denorm.resource_job_level%type
513 ,P_job_level_new pa_resources_denorm.resource_job_level%type
514 ,x_return_status OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
515 ,x_msg_data OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
516 ,x_msg_count OUT NOCOPY NUMBER --File.Sql.39 bug 4440895
517 ) IS
518
519 l_job_id PER_JOBS.JOB_ID%type;
520 l_job_level_old pa_resources_denorm.resource_job_level%type;
521 l_job_level_new pa_resources_denorm.resource_job_level%type;
522 l_resource_rec_old PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
523 l_resource_rec_new PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
524
525 -- Cursor to get all affected job ids with the P_job_id level change
526 CURSOR get_job_ids(
527 l_job_id per_jobs.job_id%type
528 ) is
529 SELECT l_job_id effected_job_id
530 FROM sys.dual
531 ,per_job_groups pjg
532 WHERE pjg.master_flag = 'Y'
533 AND pjg.job_group_id = get_job_group_id(l_job_id)
534 UNION
535 SELECT distinct pjr.from_job_id effected_job_id
536 FROM pa_job_relationships pjr
537 ,per_job_groups pjg
538 WHERE pjg.master_flag = 'Y'
539 AND pjr.to_job_id = l_job_id
540 AND pjr.to_job_group_id = pjg.job_group_id
541 UNION
542 SELECT distinct pjr.to_job_id effected_job_id
543 FROM pa_job_relationships pjr
544 ,per_job_groups pjg
545 WHERE pjg.master_flag = 'Y'
546 AND pjr.from_job_id = l_job_id
547 AND pjr.from_job_group_id = pjg.job_group_id;
548
549 -- P_DEBUG_MODE varchar2(1); -- Bug 4352236
550 P_DEBUG_MODE VARCHAR2(1) := NVL(FND_PROFILE.value('PA_DEBUG_MODE'), 'N');
551
552 BEGIN
553
554 -- Initialize the Error stack
555 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.update_all_jobs');
556 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
557
558 l_job_id := P_job_id;
559
560 -- just assign the value to the local variable because job_level can be
561 -- null and do not need a default value
562 l_job_level_old := P_job_level_old;
563 l_job_level_new := P_job_level_new;
564
565
566 -- if the job level changes then update all the jobs which are affected and
567 -- call PA_RESOURCE_PVT.UPDATE_RESOURCE_DENORM API to update the resource_denorm_table
568 OPEN get_job_ids(l_job_id) ;
569 LOOP
570 fetch get_job_ids into l_job_id;
571 Exit when get_job_ids%NOTFOUND;
572
573 If l_job_id is NOT NULL then
574 -- P_DEBUG_MODE := NVL(FND_PROFILE.value('PA_DEBUG_MODE'), 'N');
575 IF (P_DEBUG_MODE ='Y') THEN
576 pa_debug.g_err_stage := 'Log: Job Level change for job_id';
577 pa_debug.write_file('LOG',pa_debug.g_err_stage);
578 end if;
579
580 update_job_level_res_denorm
581 ( P_job_id_old => l_job_id
582 ,P_job_id_new => l_job_id
583 ,P_job_level_old => l_job_level_old
584 ,P_job_level_new => l_job_level_new
585 ,x_return_status => x_return_status
586 ,x_msg_data => x_msg_data
587 ,x_msg_count => x_msg_count
588 );
589 End if;
590
591 END LOOP;
592 CLOSE get_job_ids;
593
594 -- reset the Error stack
595 PA_DEBUG.Reset_Err_Stack;
596
597 EXCEPTION
598
599 WHEN OTHERS THEN
600 -- 4537865 : RESET x_msg_count and x_msg_data also
601 x_msg_count := 1 ;
602 x_msg_data := SUBSTRB(SQLERRM ,1,240);
603
604 -- Set the exception Message and the stack
605 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.update_all_jobs'
606 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
607 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
608 raise;
609
610 END update_all_jobs;
611
612 -- This Procedure updates all resource denorm records affected by the
613 -- changes in job mappings in pa_job_relationships table
614 -- It will update the job levels of the resource denorm records
615 PROCEDURE pa_job_relation_job_id
616 (P_calling_mode IN VARCHAR2
617 ,P_from_job_id_old IN pa_job_relationships.from_job_id%type
618 ,P_from_job_id_new IN pa_job_relationships.from_job_id%type
619 ,P_to_job_id_old IN pa_job_relationships.from_job_id%type
620 ,P_to_job_id_new IN pa_job_relationships.from_job_id%type
621 ,P_from_job_group_id IN pa_job_relationships.from_job_id%type
622 ,P_to_job_group_id IN pa_job_relationships.from_job_id%type
623 ,x_return_status OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
624 ,x_msg_data OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
625 ,x_msg_count OUT NOCOPY NUMBER) IS --File.Sql.39 bug 4440895
626
627 l_job_level_old NUMBER;
628 l_job_level_new NUMBER;
629 l_job_id PER_JOBS.JOB_ID%type;
630 l_master_job_id PER_JOBS.JOB_ID%type;
631 l_PRJG_job_id PER_JOBS.JOB_ID%type;
632 l_condition VARCHAR2(10);
633 P_DEBUG_MODE VARCHAR2(1) := NVL(FND_PROFILE.value('PA_DEBUG_MODE'), 'N');
634
635 BEGIN
636 -- Initialize the Error stack
637 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.pa_job_relation_job_id');
638 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
639
640 IF P_DEBUG_MODE = 'Y' THEN
641 log_message('P_from_job_id_old = ' || P_from_job_id_old);
642 log_message('P_from_job_id_new = ' || P_from_job_id_new);
643 log_message('P_to_job_id_old = ' || P_to_job_id_old);
644 log_message('P_to_job_id_new = ' || P_to_job_id_new);
645 log_message('P_from_job_group_id = ' || P_from_job_group_id);
646 log_message('P_to_job_group_id = ' || P_to_job_group_id);
647 END IF;
648
649 If P_calling_mode = 'INSERT' OR P_calling_mode = 'UPDATE' Then
650
651 IF P_DEBUG_MODE = 'Y' THEN
652 log_message('P_calling_mode = ' || P_calling_mode);
653 END IF;
654 ----------------------------------------------------------------------------
655 -- Need to check that the from_job_id belongs to the Proj_Res_Job_Group
656 -- If it is a PRJG job, we need to check that the to_job_id is a master job
657 -- and update the resource denorm records with the job level of the PRJG job
658 -----------------------------------------------------------------------------
659
660 If (PA_JOB_UTILS.Is_Proj_Res_Job_Group(P_from_job_id_new, P_from_job_group_id) = 'Y' AND
661 PA_JOB_UTILS.check_master_job(P_to_job_id_new)) then
662
663 IF P_DEBUG_MODE = 'Y' THEN
664 log_message('From is PRJG, To is Master');
665 END IF;
666
667 l_job_level_new := PA_JOB_UTILS.get_job_level(P_from_job_id_new,P_from_job_group_id);
668
669 l_PRJG_job_id := P_from_job_id_new;
670 l_master_job_id := P_to_job_id_new;
671 l_condition := 'PM';
672
673 End if;
674
675
676 -----------------------------------------------------------------------------
677 -- Now, need to do the opposite: check that the to_job_id belongs to the PRJG
678 -- If it is a PRJG job, we need to check that the from_job_id is a master job
679 -- and update the resource denorm records with the job level of the PRJG job
680 -----------------------------------------------------------------------------
681
682 If (PA_JOB_UTILS.Is_Proj_Res_Job_Group(P_to_job_id_new, P_to_job_group_id) = 'Y' AND
683 PA_JOB_UTILS.check_master_job(P_from_job_id_new)) then
684
685 IF P_DEBUG_MODE = 'Y' THEN
686 log_message('From is Master, To is PRJG');
687 END IF;
688 l_job_level_new := PA_JOB_UTILS.get_job_level(P_to_job_id_new,P_to_job_group_id);
689
690 l_PRJG_job_id := P_to_job_id_new;
691 l_master_job_id := P_from_job_id_new;
692 l_condition := 'PM';
693
694 End if;
695
696
697 -----------------------------------------------------------------------------
698 -- For Master and Normal job mapping, we need to get the job level of the job
699 -- and only updates the resource denorm records which has the normal job id
700 -- with the job level of the Master, PRJG job id
701 -- Case: from_job_id is Master and to_job_id is Normal job
702 ------------------------------------------------------------------------------
703
704 If (PA_JOB_UTILS.check_master_job(P_from_job_id_new) AND
705 PA_JOB_UTILS.Is_Proj_Res_Job_Group(P_to_job_id_new, P_to_job_group_id) = 'N' AND
706 NOT PA_JOB_UTILS.check_master_job(P_to_job_id_new)) THEN
707
708 IF P_DEBUG_MODE = 'Y' THEN
709 log_message('From is Master, To is Normal');
710 END IF;
711 l_job_level_new := PA_JOB_UTILS.get_job_level(P_from_job_id_new, P_from_job_group_id);
712
713 l_job_id := P_to_job_id_new;
714 l_condition := 'MN';
715
716 End If;
717
718 ----------------------------------------------------------------------------
719 -- Same as previous, but to_job_id is Master and from_job_id is normal job
720 ----------------------------------------------------------------------------
721 If (PA_JOB_UTILS.check_master_job(P_to_job_id_new) AND
722 PA_JOB_UTILS.Is_Proj_Res_Job_Group(P_from_job_id_new, P_from_job_group_id) = 'N' AND
723 NOT PA_JOB_UTILS.check_master_job(P_from_job_id_new)) THEN
724
725 IF P_DEBUG_MODE = 'Y' THEN
726 log_message('From is Normal, To is Master');
727 END IF;
728 l_job_level_new := PA_JOB_UTILS.get_job_level(P_to_job_id_new, P_to_job_group_id);
729
730 l_job_id := P_from_job_id_new;
731 l_condition := 'MN';
732
733 End If;
734
735
736 -- PRJG and Master Job Mapping
737 -- Update all jobs belonging to the Master job
738 If l_condition = 'PM' Then
739
740 IF P_DEBUG_MODE = 'Y' THEN
741 log_message('Updating records for PRJG job');
742 END IF;
743 update_job_level_res_denorm
744 ( P_job_id_old => NULL
745 ,P_job_id_new => l_PRJG_job_id
746 ,P_job_level_old => NULL
747 ,P_job_level_new => l_job_level_new
748 ,x_return_status => x_return_status
749 ,x_msg_data => x_msg_data
750 ,x_msg_count => x_msg_count
751 );
752
753 IF P_DEBUG_MODE = 'Y' THEN
754 log_message('Updating records for jobs belonging to master');
755 END IF;
756 update_all_jobs
757 ( P_job_id => l_master_job_id
758 ,P_job_level_old => NULL
759 ,P_job_level_new => l_job_level_new
760 ,x_return_status => x_return_status
761 ,x_msg_data => x_msg_data
762 ,x_msg_count => x_msg_count
763 );
764
765 -- Master and Normal Job mapping
766 -- Only update the normal job id
767 Elsif l_condition = 'MN' Then
768
769 IF P_DEBUG_MODE = 'Y' THEN
770 log_message('Updating records only for the normal job id');
771 END IF;
772 update_job_level_res_denorm
773 ( P_job_id_old => NULL
774 ,P_job_id_new => l_job_id
775 ,P_job_level_old => NULL
776 ,P_job_level_new => l_job_level_new
777 ,x_return_status => x_return_status
778 ,x_msg_data => x_msg_data
779 ,x_msg_count => x_msg_count
780 );
781
782 End If;
783
784 Elsif P_calling_mode = 'UPDATE' then
785
786 IF P_DEBUG_MODE = 'Y' THEN
787 log_message('P_calling_mode = UPDATE');
788 END IF;
789
790
791 Elsif P_calling_mode = 'DELETE' then
792
793 IF P_DEBUG_MODE = 'Y' THEN
794 log_message('P_calling_mode = DELETE');
795 END IF;
796 ------------------------------------------------------------------------------
797 -- The following condition checks if the from_job_id is a Master and to_job_id
798 -- is in the Proj_Res_Job_Group or the opposite
799 -- Also checks if the from_job_id is a Master Job and to_job_id is a normal job
800 -- id or the opposite
801 -- Sets the appropriate value for the job ids and the condition to update the
802 -- resource denorm records
803 ------------------------------------------------------------------------------
804
805 IF ((PA_JOB_UTILS.check_master_job(P_from_job_id_old) AND
806 PA_JOB_UTILS.Is_Proj_Res_Job_Group(P_to_job_id_old, P_to_job_group_id) = 'Y')) THEN
807
808 IF P_DEBUG_MODE = 'Y' THEN
809 log_message('From is Master, To is PRJG');
810 END IF;
811 l_master_job_id := P_from_job_id_old;
812 l_PRJG_job_id := P_to_job_id_old;
813 l_condition := 'PM';
814
815 ELSIF ((PA_JOB_UTILS.check_master_job(P_to_job_id_old) AND
816 PA_JOB_UTILS.Is_Proj_Res_Job_Group(P_from_job_id_old, P_from_job_group_id) = 'Y')) THEN
817
818 IF P_DEBUG_MODE = 'Y' THEN
819 log_message('From is PRJG, To is Master');
820 END IF;
821 l_master_job_id := P_to_job_id_old;
822 l_PRJG_job_id := P_from_job_id_old;
823 l_condition := 'PM';
824
825 ELSIF ( PA_JOB_UTILS.check_master_job(P_from_job_id_old) AND
826 PA_JOB_UTILS.Is_Proj_Res_Job_Group(P_to_job_id_old, P_to_job_group_id) = 'N' AND
827 NOT PA_JOB_UTILS.check_master_job(P_to_job_id_old)) THEN
828
829 IF P_DEBUG_MODE = 'Y' THEN
830 log_message('From is Master, To is Normal');
831 END IF;
832 l_master_job_id := P_from_job_id_old;
833 l_job_id := P_to_job_id_old;
834 l_condition := 'MN';
835
836 ELSIF ( PA_JOB_UTILS.check_master_job(P_to_job_id_old) AND
837 PA_JOB_UTILS.Is_Proj_Res_Job_Group(P_from_job_id_old, P_from_job_group_id) = 'N'AND
838 NOT PA_JOB_UTILS.check_master_job(P_from_job_id_old)) THEN
839
840 IF P_DEBUG_MODE = 'Y' THEN
841 log_message('From is Normal, To is Master');
842 END IF;
843 l_master_job_id := P_to_job_id_old;
844 l_job_id := P_from_job_id_old;
845 l_condition := 'MN';
846
847 END IF;
848
849
850 ------------------------------------------------------------
851 -- Next, update the resource denorm records correspondingly
852 -- If l_condition is 'PM' : PRJG and Master Jobs mapping,
853 -- We need to sets the job level to Null for all resource
854 -- denorm records with the job_id belonging to the Master,
855 -- and the Master Job itself
856 -- If l_condition is 'MN' : Master and Normal Jobs mapping,
857 -- We need to set the job level to Null ONLY for resource
858 -- denorm records with the job id of the Normal Job Id
859 ------------------------------------------------------------
860
861 If l_condition = 'PM' Then
862
863 IF P_DEBUG_MODE = 'Y' THEN
864 log_message('Updating records with job ids belong to Master');
865 log_message('Master Job Id = ' || l_master_job_id);
866 END IF;
867 update_all_jobs
868 ( P_job_id => l_master_job_id
869 ,P_job_level_old => NULL
870 ,P_job_level_new => NULL
871 ,x_return_status => x_return_status
872 ,x_msg_data => x_msg_data
873 ,x_msg_count => x_msg_count
874 );
875
876
877 Elsif l_condition = 'MN' Then
878
879 IF P_DEBUG_MODE = 'Y' THEN
880 log_message('Updating only records with the normal job id');
881 log_message('Job Id = ' || l_job_id);
882 END IF;
883 update_job_level_res_denorm
884 ( P_job_id_old => NULL
885 ,P_job_id_new => l_job_id
886 ,P_job_level_old => NULL
887 ,P_job_level_new => NULL
888 ,x_return_status => x_return_status
889 ,x_msg_data => x_msg_data
890 ,x_msg_count => x_msg_count
891 );
892 End If;
893
894 End if;
895
896
897
898 -- reset the Error stack
899 PA_DEBUG.Reset_Err_Stack;
900
901 EXCEPTION
902
903 WHEN NO_DATA_FOUND THEN
904 NULL;
905
906 WHEN OTHERS THEN
907 -- 4537865 : RESET x_msg_count and x_msg_data also
908 x_msg_count := 1 ;
909 x_msg_data := SUBSTRB(SQLERRM ,1,240);
910
911 -- Set the exception Message and the stack
912 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.pa_job_relation_job_id'
913 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
914 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
915 raise;
916
917
918 END pa_job_relation_job_id;
919
920
921 -- Do updates on job level for PRJG job, master jobs and normal jobs
922 -- which has mapping to each other
923 PROCEDURE perform_job_updates
924 ( P_job_id per_jobs.job_id%type
925 ,P_job_level_old pa_resources_denorm.resource_job_level%type
926 ,P_job_level_new pa_resources_denorm.resource_job_level%type
927 ,P_job_group_id per_job_groups.job_group_id%type
928 ,x_return_status OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
929 ,x_msg_data OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
930 ,x_msg_count OUT NOCOPY NUMBER --File.Sql.39 bug 4440895
931 ) IS
932
933 l_job_id PER_JOBS.JOB_ID%type;
934 l_master_job_id PER_JOBS.JOB_ID%type;
935 l_job_level_old pa_resources_denorm.resource_job_level%type;
936 l_job_level_new pa_resources_denorm.resource_job_level%type;
937 l_job_group_id per_job_groups.job_group_id%type;
938 P_DEBUG_MODE VARCHAR2(1) := NVL(FND_PROFILE.value('PA_DEBUG_MODE'), 'N');
939
940 -- Cursor to get the associated master job id of the PRJG job id
941 CURSOR get_master_job (
942 l_job_id per_jobs.job_id%type
943 ,l_job_group_id per_job_groups.job_group_id%type
944 ) IS
945
946 SELECT distinct pjr.from_job_id effected_job_id
947 FROM pa_job_relationships pjr
948 WHERE pjr.to_job_id = l_job_id
949 AND pjr.to_job_group_id = l_job_group_id
950 UNION
951 SELECT distinct pjr.to_job_id effected_job_id
952 FROM pa_job_relationships pjr
953 WHERE pjr.from_job_id = l_job_id
954 AND pjr.from_job_group_id = l_job_group_id;
955
956 BEGIN
957
958 -- Initialize the Error stack
959 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.perform_job_updates');
960 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
961 IF P_DEBUG_MODE = 'Y' THEN
962 log_message('**** Performing Job Level Updates ****');
963 END IF;
964
965 l_job_id := P_job_id;
966 l_job_level_old := P_job_level_old;
967 l_job_level_new := P_job_level_new;
968 l_job_group_id := P_job_group_id;
969
970 -- first updates the denorm records which has the PRJG job id
971 IF P_DEBUG_MODE = 'Y' THEN
972 log_message('Updating Denorm for PRJG job id = ' || l_job_id);
973 END IF;
974 update_job_level_res_denorm
975 ( P_job_id_old => l_job_id
976 ,P_job_id_new => l_job_id
977 ,P_job_level_old => l_job_level_old
978 ,P_job_level_new => l_job_level_new
979 ,x_return_status => x_return_status
980 ,x_msg_data => x_msg_data
981 ,x_msg_count => x_msg_count
982 );
983
984 -- next get the master job id and then updates all jobs
985 -- belonging to that master job id if the job id is NOT
986 -- a master job
987
988 If (PA_JOB_UTILS.check_master_job(l_job_id) = FALSE) Then
989
990 OPEN get_master_job(l_job_id, l_job_group_id);
991 LOOP
992 FETCH get_master_job INTO l_master_job_id;
993 Exit when get_master_job%NOTFOUND;
994
995 IF P_DEBUG_MODE = 'Y' THEN
996 log_message('Updating Denorm for jobs belongs to master job id = ' || l_master_job_id);
997 END IF;
998
999 update_all_jobs
1000 ( P_job_id => l_master_job_id
1001 ,P_job_level_old => l_job_level_old
1002 ,P_job_level_new => l_job_level_new
1003 ,x_return_status => x_return_status
1004 ,x_msg_data => x_msg_data
1005 ,x_msg_count => x_msg_count
1006 );
1007 END LOOP;
1008 CLOSE get_master_job;
1009
1010 Else
1011
1012 IF P_DEBUG_MODE = 'Y' THEN
1013 log_message('Updating Denorm for jobs belongs to master job, also PRJG job id = ' || l_job_id);
1014 END IF;
1015 update_all_jobs
1016 ( P_job_id => l_job_id
1017 ,P_job_level_old => l_job_level_old
1018 ,P_job_level_new => l_job_level_new
1019 ,x_return_status => x_return_status
1020 ,x_msg_data => x_msg_data
1021 ,x_msg_count => x_msg_count
1022 );
1023 End If;
1024
1025 EXCEPTION
1026 -- when no data found from the get_master_job cursor, then there is no
1027 -- mapping, do not do any updates
1028 WHEN NO_DATA_FOUND THEN
1029 null;
1030 WHEN OTHERS THEN -- Included WHEN OTHERS Block for 4537865
1031 -- 4537865 : RESET x_msg_count and x_msg_data also
1032 x_msg_count := 1 ;
1033 x_msg_data := SUBSTRB(SQLERRM ,1,240);
1034 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
1035 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API',
1036 p_procedure_name => 'perform_job_updates',
1037 p_error_text => x_msg_data );
1038 RAISE ;
1039 END perform_job_updates;
1040
1041
1042
1043 -- Main API for job level change, job mapping change
1044 -- This API will update the resource denorm records with the job level change of a job id.
1045 -- It depends on the type of job : whether it is in the Project Resource Job Group or not
1046 PROCEDURE update_job_level_dff
1047 ( P_job_id per_jobs.job_id%type
1048 ,P_job_level_old pa_resources_denorm.resource_job_level%type
1049 ,P_job_level_new pa_resources_denorm.resource_job_level%type
1050 ,x_return_status OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
1051 ,x_msg_data OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
1052 ,x_msg_count OUT NOCOPY NUMBER --File.Sql.39 bug 4440895
1053 ) IS
1054
1055 l_job_id PER_JOBS.JOB_ID%type;
1056 l_job_level_old pa_resources_denorm.resource_job_level%type;
1057 l_job_level_new pa_resources_denorm.resource_job_level%type;
1058 l_job_group_id per_job_groups.job_group_id%type;
1059 l_isPRJG VARCHAR2(1);
1060 P_DEBUG_MODE VARCHAR2(1) := NVL(FND_PROFILE.value('PA_DEBUG_MODE'), 'N');
1061
1062 BEGIN
1063
1064 -- Initialize the Error stack
1065 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.update_job_level_dff');
1066 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
1067
1068 l_job_id := P_job_id;
1069 l_job_level_old := P_job_level_old;
1070 l_job_level_new := P_job_level_new;
1071
1072 -- When Project Resource Job Group does not exist, we just use
1073 -- the job id and job level passed in and update the resource
1074 -- denorm records affected by this change
1075 IF PA_JOB_UTILS.Proj_Res_Job_Group_Exists(p_job_id => l_job_id) = 'N' THEN
1076 IF P_DEBUG_MODE = 'Y' THEN
1077 log_message('Proj_Res_Job_Group does not exist');
1078 log_message('Update Denorm for the Job Id and Job Level');
1079 END IF;
1080
1081 update_job_level_res_denorm
1082 ( P_job_id_old => l_job_id
1083 ,P_job_id_new => l_job_id
1084 ,P_job_level_old => l_job_level_old
1085 ,P_job_level_new => l_job_level_new
1086 ,x_return_status => x_return_status
1087 ,x_msg_data => x_msg_data
1088 ,x_msg_count => x_msg_count
1089 );
1090 ELSE
1091 -----------------------------------------------------------
1092 -- This is the case when the Proj_Res_Job_Group value exist
1093 -----------------------------------------------------------
1094 IF P_DEBUG_MODE = 'Y' THEN
1095 log_message('Proj_Res_Job_Group Exist');
1096 END IF;
1097
1098 -- get the job group id of the job id passed in
1099 l_job_group_id := PA_JOB_UTILS.get_job_group_id(l_job_id);
1100 IF P_DEBUG_MODE = 'Y' THEN
1101 log_message('Job Group Id = ' || l_job_group_id );
1102 END IF;
1103
1104 -- check whether the job group is the Proj_Res_Job_Group
1105 l_isPRJG := PA_JOB_UTILS.Is_Proj_Res_Job_Group
1106 ( p_job_id => l_job_id
1107 ,p_job_group_id => l_job_group_id);
1108
1109 -------------------------------------------------------------
1110 -- When l_isPRJG is 'Y', we need to get the master job id
1111 -- associated with the job id passed in from the job mapping
1112 -- and update all resource denorm records of the affected
1113 -- jobs
1114 -- Call procedure 'perform_job_updates' for this
1115 -- When the value is 'N', we not need to change anything
1116 -------------------------------------------------------------
1117
1118 If l_isPRJG = 'Y' Then
1119
1120 IF P_DEBUG_MODE = 'Y' THEN
1121 log_message('Job Id passed in belongs to PRJG job group');
1122 END IF;
1123
1124 perform_job_updates
1125 ( P_job_id => l_job_id
1126 ,P_job_level_old => l_job_level_old
1127 ,P_job_level_new => l_job_level_new
1128 ,P_job_group_id => l_job_group_id
1129 ,x_return_status => x_return_status
1130 ,x_msg_data => x_msg_data
1131 ,x_msg_count => x_msg_count
1132 );
1133
1134 End If;
1135
1136 END IF;
1137
1138 EXCEPTION
1139 -- when no data found from the get_master_job cursor, then there is no
1140 -- mapping, do not do any updates
1141 WHEN NO_DATA_FOUND THEN
1142 null;
1143 WHEN OTHERS THEN -- Included WHEN OTHERS Block for 4537865
1144 -- 4537865 : RESET x_msg_count and x_msg_data also
1145 x_msg_count := 1 ;
1146 x_msg_data := SUBSTRB(SQLERRM ,1,240);
1147 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
1148 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API',
1149 p_procedure_name => 'update_job_level_dff',
1150 p_error_text => x_msg_data );
1151 RAISE ;
1152 END update_job_level_dff;
1153
1154
1155
1156
1157
1158 -- This Procedure gets list of all the jobs which are afftected due to changes in
1159 -- grade_id in per_valid_grade entity
1160 PROCEDURE per_valid_grades_job_id
1161 (P_job_id IN per_jobs.job_id%type
1162 ,x_return_status OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
1163 ,x_msg_data OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
1164 ,x_msg_count OUT NOCOPY NUMBER) IS --File.Sql.39 bug 4440895
1165
1166 v_return_status VARCHAR2(2000);
1167 v_error_message_code VARCHAR2(2000);
1168 v_job_group_id PER_JOBS.JOB_GROUP_ID%type;
1169 v_job_level_old NUMBER;
1170 v_job_level_new NUMBER;
1171 v_job_id PER_JOBS.JOB_ID%type;
1172 v_msg_data VARCHAR2(2000);
1173 v_msg_count NUMBER;
1174
1175 CURSOR get_job_ids(
1176 l_job_id per_jobs.job_id%type
1177 ) is
1178 SELECT l_job_id effected_job_id
1179 FROM sys.dual
1180 ,per_job_groups pjg
1181 WHERE pjg.master_flag = 'Y'
1182 AND pjg.job_group_id = get_job_group_id(l_job_id)
1183 UNION
1184 SELECT distinct pjr.from_job_id effected_job_id
1185 FROM pa_job_relationships pjr
1186 ,per_job_groups pjg
1187 WHERE pjg.master_flag = 'Y'
1188 AND pjr.to_job_id = l_job_id
1189 AND pjr.to_job_group_id = pjg.job_group_id
1190 UNION
1191 SELECT distinct pjr.to_job_id effected_job_id
1192 FROM pa_job_relationships pjr
1193 ,per_job_groups pjg
1194 WHERE pjg.master_flag = 'Y'
1195 AND pjr.from_job_id = l_job_id
1196 AND pjr.from_job_group_id = pjg.job_group_id
1197 UNION
1198 SELECT l_job_id effected_job_id
1199 FROM sys.dual
1200 ,per_job_groups pjg
1201 WHERE pjg.master_flag = 'N'
1202 AND pjg.job_group_id = get_job_group_id(l_job_id)
1203 AND NOT EXISTS (
1204 SELECT 'Y'
1205 FROM per_job_groups
1206 WHERE master_flag = 'Y'
1207 AND job_group_id = get_job_group_id(l_job_id)
1208 );
1209 BEGIN
1210
1211 -- Initialize the Error stack
1212 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.per_valid_grades_job_id');
1213 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
1214
1215 -- if the grade id changes then update all the jobs which are affected and
1216 -- call PA_RESOURCE_PVT.UPDATE_RESOURCE_DENORM API to update the resource_denorm_table
1217 OPEN get_job_ids(P_job_id) ;
1218 LOOP
1219 fetch get_job_ids into v_job_id;
1220 Exit when get_job_ids%NOTFOUND;
1221 v_job_group_id := get_job_group_id(v_job_id);
1222 v_job_level_new := get_job_level(v_job_id,v_job_group_id);
1223 v_job_level_old := 0;
1224
1225 If v_job_id is NOT NULL then
1226 call_create_resource_denorm
1227 (P_job_id_old => v_job_id
1228 ,P_job_id_new => v_job_id
1229 ,P_job_level_old => v_job_level_old
1230 ,P_job_level_new => v_job_level_new
1231 ,x_return_status => x_return_status
1232 ,x_msg_data => x_msg_data
1233 ,x_msg_count => x_msg_count
1234 );
1235 End if;
1236
1237
1238 END LOOP;
1239 CLOSE get_job_ids;
1240
1241 -- reset the Error stack
1242 PA_DEBUG.Reset_Err_Stack;
1243
1244 EXCEPTION
1245
1246 WHEN NO_DATA_FOUND THEN
1247 NULL;
1248
1249 WHEN OTHERS THEN
1250 -- 4537865 : RESET x_msg_count and x_msg_data also
1251 x_msg_count := 1 ;
1252 x_msg_data := SUBSTRB(SQLERRM ,1,240);
1253 -- Set the exception Message and the stack
1254 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.per_valid_grades_job_id'
1255 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
1256 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
1257 raise;
1258
1259
1260 END per_valid_grades_job_id;
1261
1262 -- This Procedure gets list of all the jobs which are afftected due to changes in
1263 -- sequence(job level) in per grades entity
1264 PROCEDURE per_grades_job_id
1265 (P_grade_id IN per_grades.grade_id%type
1266 ,x_return_status OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
1267 ,x_msg_data OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
1268 ,x_msg_count OUT NOCOPY NUMBER --File.Sql.39 bug 4440895
1269 ) IS
1270
1271 v_return_status VARCHAR2(2000);
1272 v_error_message_code VARCHAR2(2000);
1273 v_job_group_id PER_JOBS.JOB_GROUP_ID%type;
1274 v_job_level_new NUMBER;
1275 v_job_level_old NUMBER;
1276 v_job_id PER_JOBS.JOB_ID%type;
1277 v_row_num NUMBER := 0;
1278 v_msg_data VARCHAR2(2000);
1279 v_msg_count NUMBER;
1280 CURSOR get_job_ids(l_grade_id per_grades.grade_id%type) is
1281 SELECT distinct pvg.job_id
1282 FROM per_valid_grades pvg
1283 ,per_job_groups pjg
1284 WHERE
1285 pvg.grade_id = l_grade_id
1286 AND pjg.master_flag = 'Y'
1287 AND pjg.job_group_id = get_job_group_id(pvg.job_id)
1288 UNION
1289 SELECT distinct pjr.from_job_id
1290 FROM per_valid_grades pvg
1291 ,pa_job_relationships pjr
1292 ,per_job_groups pjg
1293 WHERE pjg.master_flag = 'Y'
1294 AND pjr.to_job_id = pvg.job_id
1295 AND pjr.to_job_group_id = pjg.job_group_id
1296 AND pvg.grade_id = l_grade_id
1297 UNION
1298 SELECT distinct pjr.to_job_id
1299 FROM per_valid_grades pvg
1300 ,pa_job_relationships pjr
1301 ,per_job_groups pjg
1302 WHERE pjg.master_flag = 'Y'
1303 AND pjr.from_job_id = pvg.job_id
1304 AND pjr.from_job_group_id = pjg.job_group_id
1305 AND pvg.grade_id = l_grade_id
1306 UNION
1307 SELECT distinct pvg.job_id
1308 FROM per_valid_grades pvg
1309 ,per_job_groups pjg
1310 WHERE pjg.master_flag = 'N'
1311 AND pjg.job_group_id = get_job_group_id(pvg.job_id)
1312 AND pvg.grade_id = l_grade_id
1313 AND NOT EXISTS (
1314 SELECT 'Y'
1315 FROM per_job_groups
1316 WHERE master_flag = 'Y'
1317 AND job_group_id = get_job_group_id(pvg.job_id)
1318 );
1319
1320
1321 BEGIN
1322
1323
1324 -- Initialize the Error stack
1325 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.per_grades_job_id');
1326 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
1327
1328 -- if the sequence is changes then update all the jobs which are affected due to
1329 -- call PA_RESOURCE_PVT.UPDATE_RESOURCE_DENORM API to update the resource_denorm_table
1330 OPEN get_job_ids(P_grade_id) ;
1331 LOOP
1332 fetch get_job_ids into v_job_id;
1333 Exit when get_job_ids%NOTFOUND;
1334 v_job_group_id := get_job_group_id(v_job_id);
1335 v_job_level_new := get_job_level(v_job_id,v_job_group_id);
1336 v_job_level_old := 0;
1337 if v_job_id is NOT NULL then
1338 call_create_resource_denorm
1339 (P_job_id_old => v_job_id
1340 ,P_job_id_new => v_job_id
1341 ,P_job_level_old => v_job_level_old
1342 ,P_job_level_new => v_job_level_new
1343 ,x_return_status => x_return_status
1344 ,x_msg_data => x_msg_data
1345 ,x_msg_count => x_msg_count
1346 );
1347 End if;
1348
1349
1350 END LOOP;
1351 CLOSE get_job_ids;
1352
1353 -- reset the Error stack
1354 PA_DEBUG.Reset_Err_Stack;
1355 EXCEPTION
1356
1357 WHEN NO_DATA_FOUND THEN
1358 NULL;
1359
1360 WHEN OTHERS THEN
1361 -- 4537865 : RESET x_msg_count and x_msg_data also
1362 x_msg_count := 1 ;
1363 x_msg_data := SUBSTRB(SQLERRM ,1,240);
1364 -- Set the exception Message and the stack
1365 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.per_grades_job_id'
1366 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
1367 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
1368 raise;
1369
1370
1371
1372 END per_grades_job_id;
1373
1374
1375
1376 -- This Procedure will get a list of all affected jobs due to change in the job mapping
1377 -- and then calls to PRM API GET_JOB_LEVEL in a loop which actually
1378 -- updates the levels in the resource denorm table.
1379 -- Whenever job mapping columns in pa_job_relationships updated,workflow will kickoff
1380 -- this api from the database trigger on table pa_job_relationships
1381 -- Pa_Job_Relationships Entity--
1382 -- IN Parameters
1383 -- P_calling_mode,P_from_job_id_new,P_to_job_id_new,P_from_job_group_id,P_to_job_group_id -- INSERT
1384 -- P_calling_mode,P_from_job_id_new,P_to_job_id_new,P_from_job_group_id,P_to_job_group_id,
1385 -- P_from_job_id_old,P_to_job_id_old -- UPDATE
1386 -- P_calling_mode,P_from_job_id_old,P_to_job_id_old,P_from_job_group_id,P_to_job_group_id -- DELETE
1387 PROCEDURE update_job_levels
1388 ( P_calling_mode IN VARCHAR2
1389 ,P_per_grades_grade_id IN per_grades.grade_id%type DEFAULT NULL
1390 ,P_per_grades_sequence_old IN NUMBER DEFAULT NULL
1391 ,P_per_grades_sequence_new IN NUMBER DEFAULT NULL
1392 ,P_per_valid_grade_job_id IN per_valid_grades.valid_grade_id%type DEFAULT NULL
1393 ,P_per_valid_grade_id_old IN per_grades.grade_id%type DEFAULT NULL
1394 ,P_per_valid_grade_id_new IN per_grades.grade_id%type DEFAULT NULL
1395 ,P_from_job_id_old IN pa_job_relationships.from_job_id%type DEFAULT NULL
1396 ,P_from_job_id_new IN pa_job_relationships.from_job_id%type DEFAULT NULL
1397 ,P_to_job_id_old IN pa_job_relationships.to_job_id%type DEFAULT NULL
1398 ,P_to_job_id_new IN pa_job_relationships.to_job_id%type DEFAULT NULL
1399 ,P_from_job_group_id IN pa_job_relationships.to_job_id%type DEFAULT NULL
1400 ,P_to_job_group_id IN pa_job_relationships.to_job_id%type DEFAULT NULL
1401 ,x_return_status IN OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
1402 ,x_msg_data IN OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
1403 ,x_msg_count IN OUT NOCOPY NUMBER --File.Sql.39 bug 4440895
1404 )IS
1405
1406 v_return_status VARCHAR2(2000);
1407 v_error_message_code VARCHAR2(2000);
1408 v_grade_id per_grades.grade_id%type;
1409 v_msg_data VARCHAR2(2000);
1410 v_msg_count NUMBER;
1411
1412 BEGIN
1413 -- Initialize the Error stack
1414 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.Update_job_levels');
1415 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
1416
1417 -- Code for if job mapping has changed
1418
1419 If (P_from_job_group_id is NOT NULL and P_to_job_group_id is NOT NULL) and
1420 (P_from_job_id_old is NOT NULL or P_from_job_id_new is NOT NULL or
1421 P_to_job_id_old is NOT NULL or P_to_job_id_new is NOT NULL ) then
1422 pa_job_relation_job_id
1423 (p_calling_mode => p_calling_mode
1424 ,P_from_job_id_old => P_from_job_id_old
1425 ,P_from_job_id_new => P_from_job_id_new
1426 ,P_to_job_id_old => P_to_job_id_old
1427 ,P_to_job_id_new => P_to_job_id_new
1428 ,P_from_job_group_id => P_from_job_group_id
1429 ,P_to_job_group_id => P_to_job_group_id
1430 ,x_return_status => x_return_status
1431 ,x_msg_data => x_msg_data
1432 ,x_msg_count => x_msg_count
1433 );
1434 End if;
1435
1436 -- reset the Error stack
1437 PA_DEBUG.Reset_Err_Stack;
1438
1439 EXCEPTION
1440
1441 WHEN NO_DATA_FOUND THEN
1442 NULL;
1443
1444 WHEN OTHERS THEN
1445 -- 4537865 : RESET x_msg_count and x_msg_data also
1446 x_msg_count := 1 ;
1447 x_msg_data := SUBSTRB(SQLERRM ,1,240);
1448
1449 -- Set the exception Message and the stack
1450 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.Update_job_levels'
1451 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
1452 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
1453 raise;
1454
1455 END update_job_levels;
1456
1457
1458 -- This Procedure updates the pa_resource_OU and set the resources
1459 -- end date active to sysdate when pa_all_organizations.inactive_date
1460 -- is updated.
1461 PROCEDURE Update_OU_resource(P_default_OU_old IN Pa_all_organizations.org_id%type
1462 ,P_default_OU_new IN Pa_all_organizations.org_id%type
1463 ,P_resource_id IN Pa_Resources_denorm.resource_id%type
1464 default NULL
1465 ,P_person_id IN Pa_Resources_denorm.person_id%type
1466 default NULL
1467 ,P_start_date IN Date default NULL
1468 ,P_end_date_old IN Date default NULL
1469 ,P_end_date_new IN Date default NULL
1470 ,x_return_status IN OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
1471 ,x_msg_data IN OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
1472 ,x_msg_count IN OUT NOCOPY NUMBER --File.Sql.39 bug 4440895
1473 )IS
1474
1475 v_return_status VARCHAR2(2000);
1476 v_error_message_code VARCHAR2(2000);
1477 v_resource_rec_old PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
1478 v_resource_rec_new PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
1479 v_msg_data VARCHAR2(2000);
1480 v_msg_count NUMBER;
1481 CURSOR res_denorm_recs IS
1482 SELECT resource_effective_start_date,
1483 resource_effective_end_date
1484 FROM pa_resources_denorm
1485 WHERE person_id = p_person_id
1486 AND nvl(p_end_date_new, sysdate) >= resource_effective_start_date
1487 AND resource_effective_start_date >= p_start_date
1488 AND resource_effective_end_date <= p_end_date_old
1489 AND resource_effective_end_date =
1490 (Select max(resource_effective_end_date)
1491 from pa_resources_denorm rd2
1492 where rd2.person_id = p_person_id)
1493 -- bug#10235228
1494 ;
1495 BEGIN
1496
1497 v_resource_rec_old.resource_org_id := p_default_OU_old;
1498 v_resource_rec_old.person_id := p_person_id;
1499 v_resource_rec_new.resource_org_id := p_default_OU_new;
1500 v_resource_rec_new.person_id := p_person_id;
1501
1502
1503
1504 --dbms_output.put_line('Calling Update_OU_resource');
1505 --dbms_output.put_line('End date for OU:' || p_default_OU_new || 'end date:' || P_end_date_new);
1506
1507 -- Initialize the Error stack
1508 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.Update_OU_resource');
1509 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
1510
1511 FOR rec IN res_denorm_recs LOOP
1512
1513 v_resource_rec_old.resource_effective_start_date := rec.resource_effective_start_date;
1514 v_resource_rec_new.resource_effective_start_date := rec.resource_effective_start_date;
1515
1516
1517 PA_RESOURCE_PVT.update_resource_denorm (
1518 p_resource_denorm_old_rec => v_resource_rec_old
1519 ,p_resource_denorm_new_rec => v_resource_rec_new
1520 ,x_return_status => x_return_status
1521 ,x_msg_data => x_msg_data
1522 ,x_msg_count => x_msg_count );
1523
1524 END LOOP;
1525
1526 --If new end date is passed for this assignment (from make_resource_inactive api)
1527 If P_end_date_new is NOT NULL then
1528 Update_EndDate(
1529 p_person_id => p_person_id,
1530 p_old_start_date => p_start_date,
1531 p_new_start_date => p_start_date,
1532 p_old_end_date => p_end_date_old,
1533 p_new_end_date => p_end_date_new,
1534 x_return_status => x_return_status,
1535 x_msg_data => x_msg_data,
1536 x_msg_count => x_msg_count);
1537
1538 End if;
1539
1540 -- reset the Error stack
1541 PA_DEBUG.Reset_Err_Stack;
1542
1543 EXCEPTION
1544
1545 WHEN NO_DATA_FOUND THEN
1546 NULL;
1547
1548 WHEN OTHERS THEN -- Set the exception Message and the stack
1549 -- 4537865 : RESET x_msg_count and x_msg_data also
1550 x_msg_count := 1 ;
1551 x_msg_data := SUBSTRB(SQLERRM ,1,240);
1552 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.Update_OU_resource'
1553 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
1554 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
1555 raise;
1556 END Update_OU_resource;
1557
1558
1559 -- This Procedure is called from workflow process to update/create resources in projects
1560 -- the workflow would be kicked of by the database trigger on table Hr_Organization_Information
1561 -- and Pa_All_Organization entities.
1562 -- 1.Whenever the default operating Unit which is
1563 -- stored in Hr_Organization_Information.Org_information1 changes / modified ,the
1564 -- trigger kicks off the workflow and calls this api to Update the Pa_Resource_OU
1565 -- entity.
1566 -- 2.Whenever the new record is inserted into Pa_All_Organizations with Pa_Org_Use_type
1567 -- is of type 'Expenditure' or the exisitng record in Pa_all_Organiations
1568 -- is updated with inactive_date then trigger fires and kicks of the workflow,calls this
1569 -- api to Update the Pa_Resource_OU.
1570 -- Make this procedure a PRAGMA AUTONOMOUS_TRANSACTION because we'll commit or rollback
1571 -- after every resource in the loop
1572 PROCEDURE Default_OU_Change
1573 ( P_calling_mode IN VARCHAR2
1574 ,P_Organization_id IN Hr_Organization_Information.Organization_id%type
1575 ,P_Default_OU_new IN Hr_Organization_Information.Org_Information1%type
1576 ,P_Default_OU_old IN Hr_Organization_Information.Org_Information1%type
1577 ,x_return_status OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
1578 ,x_msg_data OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
1579 ,x_msg_count OUT NOCOPY NUMBER --File.Sql.39 bug 4440895
1580 ) IS
1581 PRAGMA AUTONOMOUS_TRANSACTION;
1582
1583 v_return_status VARCHAR2(2000);
1584 v_error_message_code VARCHAR2(2000);
1585 v_assn_start_date Per_all_assignments_f.Effective_Start_Date%type;
1586 v_assn_end_date Per_all_assignments_f.Effective_End_Date%type;
1587 v_Person_id Per_all_assignments_f.person_id%type;
1588 v_Default_OU Hr_Organization_Information.Org_Information1%type;
1589 v_commit VARCHAR2(200) := FND_API.G_FALSE;
1590 -- set to false since the api is being called from trigger
1591 v_validate_only VARCHAR2(200) := FND_API.G_FALSE;
1592 v_internal VARCHAR2(1) := 'Y';
1593 v_individual VARCHAR2(1) := 'Y'; -- to process single resource in loop
1594 v_resource_type VARCHAR2(15):= 'EMPLOYEE';
1595 v_org_type VARCHAR2(15):= 'YES'; --'EXPENDITURES';
1596 v_msg_data VARCHAR2(2000);
1597 v_msg_count NUMBER;
1598 v_dummy NUMBER;
1599 L_API_VERSION CONSTANT NUMBER := 1.0;
1600 v_process_further BOOLEAN := FALSE;
1601 -- get all the resources who belongs to Expenditure type of organizaion and
1602 -- belongs to Expenditure Hierarchy ,Active_Assign, and of Primary assignment type
1603 -- is 'Y' and default OU inactive date is NUll
1604
1605 CURSOR get_all_resource(l_organization_id Hr_Organization_Information.Organization_id%type) is
1606
1607 SELECT distinct
1608 ind.person_id
1609 ,ind.assignment_start_date
1610 ,ind.assignment_end_date
1611 ,to_number(hoi.org_information1) default_OU
1612 FROM pa_r_project_resources_ind_v ind
1613 ,hr_organization_information hoi
1614 WHERE ind.organization_id =
1615 /* Changed for Bug 2499051- l_organization_id */ hoi.organization_id
1616 AND ind.assignment_end_date >= sysdate
1617 AND hoi.organization_id = l_organization_id
1618 AND hoi.org_information_context = 'Exp Organization Defaults'
1619 AND ind.organization_id = l_organization_id -- 4898509
1620 ORDER BY ind.person_id,ind.assignment_start_date ;
1621
1622 BEGIN
1623
1624 -- Initialize the Error stack
1625 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.Default_OU_Change');
1626 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
1627 -- for each resource found for the default ou changes update
1628 -- pa resource ou entity with new default OU
1629
1630 -- check whether the new OU is a valid exp OU or not
1631 -- if not then donot process further
1632
1633 If P_Default_OU_new is NOT NULL then
1634
1635 v_default_OU := P_Default_OU_new;
1636 Else
1637 v_default_OU := -9999;
1638 -- For bug 5330402 Added call to make_resource_inactive
1639 -- This will take sysdate as inactive date
1640 -- Return after the call, as no further processing is required.
1641 make_resource_inactive
1642 (P_calling_mode => 'UPDATE'
1643 ,P_Organization_id => P_Organization_id
1644 ,P_Default_OU => P_Default_OU_old
1645 ,P_Default_OU_NEW => v_default_OU
1646 ,P_inactive_date => trunc(sysdate)
1647 ,x_return_status => x_return_status
1648 ,x_msg_data => x_msg_data
1649 ,x_msg_count => x_msg_count
1650 ) ;
1651 PA_DEBUG.Reset_Err_Stack;
1652 Return;
1653 End if;
1654
1655 pa_hr_update_api.check_exp_OU
1656 (p_org_id => v_default_OU
1657 ,x_return_status => v_return_status
1658 ,x_error_message_code => v_error_message_code
1659 );
1660
1661 If v_return_status <> FND_API.G_RET_STS_SUCCESS then
1662 X_RETURN_STATUS := FND_API.G_RET_STS_ERROR;
1663 x_msg_data := v_error_message_code;
1664 v_process_further := FALSE;
1665 PA_UTILS.add_message(p_app_short_name => 'PA',
1666 p_msg_name => v_error_message_code);
1667 x_msg_count := fnd_msg_pub.count_msg;
1668
1669 Elsif v_return_status = FND_API.G_RET_STS_SUCCESS then
1670
1671 v_process_further := TRUE;
1672
1673 End if;
1674
1675 -- Start Bug : 4656855
1676 IF (check_pjr_default_ou(P_Organization_id, v_default_OU) <> 'Y') THEN
1677 RETURN;
1678 END IF;
1679 -- End Bug : 4656855
1680
1681 If (v_process_further) then
1682 open get_all_resource(P_Organization_id);
1683 LOOP
1684 fetch get_all_resource into
1685 v_person_id
1686 ,v_assn_start_date
1687 ,v_assn_end_date
1688 ,v_default_OU ;
1689 Exit when get_all_resource%NOTFOUND;
1690
1691 -- call the check ou change api to update records in pa_resource_OU
1692 -- for each resource belongs to this updated OU in Hr_Organization_defaults
1693 If P_calling_mode = 'UPDATE' then
1694
1695 -- check for whether the default OU is changed if so call
1696 -- check OU change api to update the resource OU entity
1697 If (NVL(P_default_OU_old,-99) <> nvl(P_default_OU_new,-99)) then
1698 -- if OU is updated then call resource denorm api to
1699 -- reflect the changes in pa_resources_denorm entity
1700 If v_person_id is NOT NULL then
1701
1702
1703 Update_OU_resource
1704 (P_default_OU_old => p_default_OU_old
1705 ,p_default_OU_new => p_default_OU_new
1706 ,P_person_id => v_person_id
1707 ,P_start_date => v_assn_start_date
1708 ,P_end_date_old => v_assn_end_date
1709 ,x_return_status => x_return_status
1710 ,x_msg_data => x_msg_data
1711 ,x_msg_count => x_msg_count
1712 );
1713
1714 -- call forecast api to regenerate the forcast items
1715 -- for the person with the organization OU change
1716 -- update forecast data for unassigned and assigned time
1717 PA_FORECASTITEM_PVT.Create_Forecast_Item
1718 (
1719 p_person_id => v_person_id
1720 ,p_start_date => v_assn_start_date
1721 ,p_end_date => v_assn_end_date
1722 ,p_process_mode => 'GENERATE'
1723 ,x_return_status => x_return_status
1724 ,x_msg_count => x_msg_count
1725 ,x_msg_data => x_msg_data
1726 ) ;
1727
1728 if (x_return_status = FND_API.G_RET_STS_SUCCESS) then
1729 COMMIT;
1730 else
1731 ROLLBACK;
1732 end if;
1733
1734 End if;
1735
1736
1737 Elsif P_default_OU_old is NULL and P_default_OU_new is NOT NULL then
1738 -- when new OU is assigned to existing organization it must pull all
1739 -- resources belongs to this OU so call create resource api
1740
1741 PA_R_PROJECT_RESOURCES_PUB.CREATE_RESOURCE (
1742 P_API_VERSION => L_API_VERSION
1743 ,P_COMMIT => v_commit
1744 ,P_VALIDATE_ONLY => v_validate_only
1745 ,P_INTERNAL => v_internal
1746 ,P_PERSON_ID => v_person_id
1747 ,P_INDIVIDUAL => v_individual
1748 ,P_RESOURCE_TYPE => v_resource_type
1749 ,X_RETURN_STATUS => x_return_status
1750 ,X_RESOURCE_ID => v_dummy
1751 ,X_MSG_COUNT => x_msg_count
1752 ,X_MSG_DATA => x_msg_data
1753 );
1754
1755 -- call this procedure to update the forecast data for
1756 -- assigned time ONLY for this resource
1757 -- this is called only if create_resource is a success
1758 if (x_return_status = FND_API.G_RET_STS_SUCCESS) then
1759 PA_FORECASTITEM_PVT.Create_Forecast_Item
1760 ( p_person_id => v_person_id
1761 ,p_start_date => null
1762 ,p_end_date => null
1763 ,p_process_mode => 'GENERATE_ASGMT'
1764 ,x_return_status => x_return_status
1765 ,x_msg_count => x_msg_count
1766 ,x_msg_data => x_msg_data
1767 ) ;
1768
1769 if (x_return_status = FND_API.G_RET_STS_SUCCESS) then
1770 COMMIT;
1771 else
1772 ROLLBACK;
1773 end if;
1774 else
1775 ROLLBACK;
1776 end if;
1777
1778 End if;
1779
1780 /* cannot raise - because will be out from the loop and will not process other records
1781 IF x_return_status <> FND_API.G_RET_STS_SUCCESS THEN
1782 RAISE FND_API.G_EXC_ERROR;
1783 END IF;
1784 */
1785
1786 Elsif P_calling_mode = 'INSERT' then
1787 -- the P_calling_mode is 'INSERT'
1788 -- this api is called to populate resources whenever a new record is added in
1789 -- in Hr_organizatioin_information entity
1790 -- or due to insert in pa_all_organizations entity
1791
1792 PA_R_PROJECT_RESOURCES_PUB.CREATE_RESOURCE (
1793 P_API_VERSION => L_API_VERSION
1794 ,P_COMMIT => v_commit
1795 ,P_VALIDATE_ONLY => v_validate_only
1796 ,P_INTERNAL => v_internal
1797 ,P_PERSON_ID => v_person_id
1798 ,P_INDIVIDUAL => v_individual
1799 ,P_RESOURCE_TYPE => v_resource_type
1800 ,X_RETURN_STATUS => x_return_status
1801 ,X_RESOURCE_ID => v_dummy
1802 ,X_MSG_COUNT => x_msg_count
1803 ,X_MSG_DATA => x_msg_data
1804 );
1805
1806
1807 -- it is also necessary to call forecast item here,
1808 -- because this is also called from project_organization_change
1809 -- when p_calling_mode is insert
1810 -- A person can belong to Org1(belong to Exp Hier), then the org
1811 -- was changed to Org2 (not belong to Exp Hier)
1812 -- If Org2 is inserted and belong to Exp Hier, we need to fix
1813 -- the assigned time for this person when he/she was with Org1
1814 -- So, call this procedure to update the forecast data for
1815 -- assigned time ONLY for this resource
1816 -- this is called only if create_resource is a success
1817 if (x_return_status = FND_API.G_RET_STS_SUCCESS) then
1818 PA_FORECASTITEM_PVT.Create_Forecast_Item
1819 ( p_person_id => v_person_id
1820 ,p_start_date => null
1821 ,p_end_date => null
1822 ,p_process_mode => 'GENERATE_ASGMT'
1823 ,x_return_status => x_return_status
1824 ,x_msg_count => x_msg_count
1825 ,x_msg_data => x_msg_data
1826 ) ;
1827
1828 if (x_return_status = FND_API.G_RET_STS_SUCCESS) then
1829 COMMIT;
1830 else
1831 ROLLBACK;
1832 end if;
1833 else
1834 ROLLBACK;
1835 end if;
1836
1837
1838 /* cannot raise - because will be out from the loop and will not process other records
1839 IF x_return_status <> FND_API.G_RET_STS_SUCCESS THEN
1840 RAISE FND_API.G_EXC_ERROR;
1841 END IF;
1842 */
1843
1844 End if;
1845 END LOOP;
1846 close get_all_resource;
1847
1848 --set the final return status to SUCCESS after loop
1849 x_return_status := FND_API.G_RET_STS_SUCCESS;
1850
1851 End if;
1852
1853 -- reset the Error stack
1854 PA_DEBUG.Reset_Err_Stack;
1855
1856 EXCEPTION
1857 WHEN FND_API.G_EXC_ERROR THEN
1858 x_return_status := FND_API.G_RET_STS_ERROR;
1859 WHEN OTHERS THEN
1860 -- 4537865 : RESET x_msg_count and x_msg_data also
1861 x_msg_count := 1 ;
1862 x_msg_data := SUBSTRB(SQLERRM ,1,240);
1863 -- Set the exception Message and the stack
1864 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.Default_OU_Change'
1865 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
1866 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
1867 raise;
1868
1869 END Default_OU_Change;
1870
1871
1872 -- This Procedure is called from workflow process to update/create resources in projects
1873 -- The workflow would be kicked of by the database trigger on table Hr_Organization_Information
1874 -- It will update the job levels information if the Project Resource Job Group is changed
1875 -- Created by adabdull 2-JAN-2002
1876 PROCEDURE Proj_Res_Job_Group_Change
1877 ( p_calling_mode IN VARCHAR2
1878 ,p_organization_id IN Hr_Organization_Information.Organization_id%type
1879 ,p_proj_job_group_new IN Hr_Organization_Information.Org_Information1%type
1880 ,p_proj_job_group_old IN Hr_Organization_Information.Org_Information1%type
1881 ,x_return_status OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
1882 ,x_msg_data OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
1883 ,x_msg_count OUT NOCOPY NUMBER --File.Sql.39 bug 4440895
1884 ) IS
1885
1886 l_job_id per_jobs.job_id%type;
1887 l_job_level NUMBER;
1888 l_proj_job_group_new NUMBER;
1889 l_proj_job_group_old NUMBER;
1890 l_job_group_id NUMBER;
1891 P_DEBUG_MODE VARCHAR2(1) := NVL(FND_PROFILE.value('PA_DEBUG_MODE'), 'N');
1892
1893 CURSOR get_new_job_ids IS
1894 SELECT job_id
1895 FROM per_jobs
1896 WHERE job_group_id = l_proj_job_group_new
1897 AND business_group_id = p_organization_id;
1898
1899 CURSOR get_old_job_ids IS
1900 SELECT job_id
1901 FROM per_jobs
1902 WHERE job_group_id = l_proj_job_group_old
1903 AND business_group_id = p_organization_id;
1904
1905 BEGIN
1906
1907 -- Initialize the Error stack
1908 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.Proj_Res_Job_Group_Change');
1909 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
1910
1911 l_proj_job_group_old := TO_NUMBER(p_proj_job_group_old);
1912 l_proj_job_group_new := TO_NUMBER(p_proj_job_group_new);
1913
1914 IF P_DEBUG_MODE = 'Y' THEN
1915 log_message('p_calling_mode = ' || p_calling_mode);
1916 log_message('old proj res job group value = ' || l_proj_job_group_old);
1917 log_message('new proj res job group value = ' || l_proj_job_group_new);
1918 END IF;
1919
1920 IF p_calling_mode = 'INSERT' and fnd_profile.value('HR_CROSS_BUSINESS_GROUP') = 'N' THEN
1921
1922 -- When Insert, we update all resource denorm records with job_id that
1923 -- belongs to the new Project Resource Job Group Id
1924 OPEN get_new_job_ids;
1925 LOOP
1926
1927 FETCH get_new_job_ids INTO l_job_id;
1928 Exit when get_new_job_ids%NOTFOUND;
1929
1930 l_job_level := PA_JOB_UTILS.get_job_level(l_job_id);
1931 IF P_DEBUG_MODE = 'Y' THEN
1932 log_message('Job id to set level ' || l_job_level || ' = ' || l_job_id);
1933 END IF;
1934
1935 update_job_level_dff
1936 (P_job_id => l_job_id
1937 ,P_job_level_old => NULL
1938 ,P_job_level_new => l_job_level
1939 ,x_return_status => x_return_status
1940 ,x_msg_data => x_msg_data
1941 ,x_msg_count => x_msg_count
1942 );
1943 END LOOP;
1944 CLOSE get_new_job_ids;
1945
1946 ELSIF p_calling_mode = 'UPDATE' and fnd_profile.value('HR_CROSS_BUSINESS_GROUP') = 'N' THEN
1947
1948 -- When update we have to set the resource denorm records job level to NULL for job id
1949 -- that belongs to the old Project Resource Job Group Id
1950 OPEN get_old_job_ids;
1951 LOOP
1952
1953 FETCH get_old_job_ids INTO l_job_id;
1954 Exit when get_old_job_ids%NOTFOUND;
1955
1956 l_job_level := NULL;
1957
1958 IF P_DEBUG_MODE = 'Y' THEN
1959 log_message('Job id to set level Null = ' || l_job_id);
1960 END IF;
1961
1962 l_job_group_id := PA_JOB_UTILS.get_job_group_id(l_job_id);
1963
1964 perform_job_updates
1965 (P_job_id => l_job_id
1966 ,P_job_level_old => NULL
1967 ,P_job_level_new => l_job_level
1968 ,P_job_group_id => l_job_group_id
1969 ,x_return_status => x_return_status
1970 ,x_msg_data => x_msg_data
1971 ,x_msg_count => x_msg_count
1972 );
1973
1974 END LOOP;
1975 CLOSE get_old_job_ids;
1976
1977
1978 -- Also, when Update, we update all resource denorm records with job_id that
1979 -- belongs to the new Project Resource Job Group Id
1980
1981 OPEN get_new_job_ids;
1982 LOOP
1983
1984 FETCH get_new_job_ids INTO l_job_id;
1985 Exit when get_new_job_ids%NOTFOUND;
1986
1987 l_job_level := PA_JOB_UTILS.get_job_level(l_job_id);
1988 IF P_DEBUG_MODE = 'Y' THEN
1989 log_message('Job id to set level ' || l_job_level || ' = ' || l_job_id);
1990 END IF;
1991
1992 update_job_level_dff
1993 (P_job_id => l_job_id
1994 ,P_job_level_old => NULL
1995 ,P_job_level_new => l_job_level
1996 ,x_return_status => x_return_status
1997 ,x_msg_data => x_msg_data
1998 ,x_msg_count => x_msg_count
1999 );
2000
2001 END LOOP;
2002 CLOSE get_new_job_ids;
2003
2004
2005 ELSIF p_calling_mode = 'DELETE' and fnd_profile.value('HR_CROSS_BUSINESS_GROUP') = 'N' THEN
2006
2007 -- When Delete, we have to set the resource denorm records job level to NULL for job id
2008 -- that belongs to the old Project Resource Job Group Id
2009
2010 OPEN get_old_job_ids;
2011 LOOP
2012
2013 FETCH get_old_job_ids INTO l_job_id;
2014 Exit when get_old_job_ids%NOTFOUND;
2015
2016 l_job_level := NULL;
2017 IF P_DEBUG_MODE = 'Y' THEN
2018 log_message('Job id to set level Null = ' || l_job_id);
2019 END IF;
2020
2021 update_job_level_dff
2022 (P_job_id => l_job_id
2023 ,P_job_level_old => NULL
2024 ,P_job_level_new => l_job_level
2025 ,x_return_status => x_return_status
2026 ,x_msg_data => x_msg_data
2027 ,x_msg_count => x_msg_count
2028 );
2029
2030 END LOOP;
2031 CLOSE get_old_job_ids;
2032
2033 END IF;
2034
2035
2036 -- reset the Error stack
2037 PA_DEBUG.Reset_Err_Stack;
2038
2039 EXCEPTION
2040 WHEN FND_API.G_EXC_ERROR THEN
2041 x_return_status := FND_API.G_RET_STS_ERROR;
2042 WHEN OTHERS THEN
2043 -- 4537865 : RESET x_msg_count and x_msg_data also
2044 x_msg_count := 1 ;
2045 x_msg_data := SUBSTRB(SQLERRM ,1,240);
2046 -- Set the exception Message and the stack
2047 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.Proj_Res_Job_Group_Change'
2048 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
2049 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
2050 raise;
2051
2052 END Proj_Res_Job_Group_Change;
2053
2054 -- This API pulls all resources into PA from HR for a given organization
2055 -- Created by virangan 11-JUN-2001
2056 -- Make this procedure a PRAGMA AUTONOMOUS_TRANSACTION because we'll commit after every
2057 -- resource in the loop
2058 PROCEDURE pull_resources( p_organization_id IN pa_all_organizations.organization_id%type
2059 ,x_return_status OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
2060 ,x_msg_data OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
2061 ,x_msg_count OUT NOCOPY NUMBER ) --File.Sql.39 bug 4440895
2062 IS
2063 PRAGMA AUTONOMOUS_TRANSACTION;
2064 l_commit VARCHAR2(200) := FND_API.G_FALSE;
2065 -- set to false since the api is being called from trigger
2066 l_validate_only VARCHAR2(200) := FND_API.G_FALSE;
2067 l_internal VARCHAR2(1) := 'Y';
2068 l_individual VARCHAR2(1) := 'Y'; -- to process single resource in loop
2069 l_resource_type VARCHAR2(15):= 'EMPLOYEE';
2070 l_Person_id Per_all_assignments_f.person_id%type;
2071 l_return_status VARCHAR2(2000);
2072 l_msg_data VARCHAR2(2000);
2073 l_msg_count NUMBER;
2074 l_dummy NUMBER;
2075 L_API_VERSION CONSTANT NUMBER := 1.0;
2076
2077 CURSOR get_all_resource(l_organization_id Hr_Organization_Information.Organization_id%type) is
2078
2079 SELECT distinct ind.person_id
2080 FROM pa_r_project_resources_ind_v ind
2081 ,hr_organization_information hoi
2082 WHERE ind.organization_id =
2083 /* Changed for Bug 2499051- l_organization_id */ hoi.organization_id
2084 AND ind.assignment_end_date >= sysdate
2085 AND hoi.organization_id = l_organization_id
2086 AND hoi.org_information_context = 'Exp Organization Defaults'
2087 ORDER BY ind.person_id;
2088
2089 BEGIN
2090 -- Initialize the Error stack
2091 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.pull_resources');
2092 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
2093
2094 open get_all_resource(p_organization_id);
2095 LOOP
2096 fetch get_all_resource into
2097 l_person_id;
2098 Exit when get_all_resource%NOTFOUND;
2099
2100 PA_R_PROJECT_RESOURCES_PUB.CREATE_RESOURCE (
2101 P_API_VERSION => L_API_VERSION
2102 ,P_COMMIT => l_commit
2103 ,P_VALIDATE_ONLY => l_validate_only
2104 ,P_INTERNAL => l_internal
2105 ,P_PERSON_ID => l_person_id
2106 ,P_INDIVIDUAL => l_individual
2107 ,P_RESOURCE_TYPE => l_resource_type
2108 ,X_RETURN_STATUS => l_return_status
2109 ,X_RESOURCE_ID => l_dummy
2110 ,X_MSG_COUNT => l_msg_count
2111 ,X_MSG_DATA => l_msg_data );
2112
2113 -- call this procedure to update the forecast data for
2114 -- assigned time ONLY for this resource
2115 -- pass null to start date and end date
2116 -- this is called only if create_resource is a success
2117 if (l_return_status = FND_API.G_RET_STS_SUCCESS) then
2118 PA_FORECASTITEM_PVT.Create_Forecast_Item(
2119 p_person_id => l_person_id
2120 ,p_start_date => null
2121 ,p_end_date => null
2122 ,p_process_mode => 'GENERATE_ASGMT'
2123 ,x_return_status => l_return_status
2124 ,x_msg_count => l_msg_count
2125 ,x_msg_data => l_msg_data
2126 ) ;
2127
2128 if (x_return_status = FND_API.G_RET_STS_SUCCESS) then
2129 COMMIT;
2130 else
2131 ROLLBACK;
2132 end if;
2133 else
2134 ROLLBACK;
2135 end if;
2136
2137 END LOOP;
2138 close get_all_resource;
2139
2140 --set the final return status to SUCCESS after loop
2141 x_return_status := FND_API.G_RET_STS_SUCCESS;
2142
2143 -- reset the Error stack
2144 PA_DEBUG.Reset_Err_Stack;
2145
2146 EXCEPTION
2147 WHEN OTHERS THEN
2148 -- 4537865 : RESET x_msg_count and x_msg_data also
2149 x_msg_count := 1 ;
2150 x_msg_data := SUBSTRB(SQLERRM ,1,240);
2151 -- Set the exception Message and the stack
2152 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.pull_resources'
2153 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
2154
2155 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
2156 raise;
2157
2158 END pull_resources;
2159
2160
2161 -- This API will be called from workflow process to update/create resources in projects.
2162 -- The workflow would be kicked of by the database trigger on pa_all_organization entity
2163 -- whenever a inactive_date in pa_all_organization is updated this api get kicked of by the
2164 -- workflow.
2165 -- Make this procedure a PRAGMA AUTONOMOUS_TRANSACTION because we'll commit after every
2166 -- resource in the loop
2167 PROCEDURE make_resource_inactive
2168 (P_calling_mode IN VARCHAR2
2169 ,P_Organization_id IN Hr_Organization_Information.Organization_id%type
2170 ,P_Default_OU IN pa_all_organizations.org_id%type
2171 ,P_inactive_date IN pa_all_organizations.inactive_date%type
2172 ,P_Default_OU_NEW IN pa_all_organizations.org_id%type DEFAULT NULL -- Added for bug 5330402
2173 ,x_return_status OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
2174 ,x_msg_data OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
2175 ,x_msg_count OUT NOCOPY NUMBER --File.Sql.39 bug 4440895
2176 ) IS
2177 PRAGMA AUTONOMOUS_TRANSACTION;
2178 v_return_status VARCHAR2(2000);
2179 v_error_message_code VARCHAR2(2000);
2180 v_assn_start_date Per_all_assignments_f.Effective_Start_Date%type;
2181 v_assn_end_date Per_all_assignments_f.Effective_End_Date%type;
2182 v_Person_id Per_all_assignments_f.person_id%type;
2183 v_resource_id Pa_Resource_txn_attributes.resource_id%type;
2184 v_Default_OU Hr_Organization_Information.Org_Information1%type;
2185 v_msg_data VARCHAR2(2000);
2186 v_msg_count NUMBER;
2187
2188 -- get all the resources who are employees and belongs to expenditure
2189 -- organizations and in the expenditure organization hierarchy
2190 -- and have a primary assignment (Active assignment) and have assigned
2191 -- to default OU
2192
2193 -- Bug 4347907 - change to base HR tables and remove nvl on dates
2194 --MOAC changes: bug 4363092: removed nvl used with org_id
2195 CURSOR get_all_inactive_resource
2196 IS
2197 SELECT
2198 distinct
2199 assn.person_id
2200 ,assn.effective_start_date
2201 ,assn.effective_end_date
2202 , res.resource_id
2203 , hrinf.org_information1
2204 FROM per_all_assignments_f assn
2205 , hr_organization_information hrinf
2206 /* , per_person_types pertypes Commented for bug#2781713 */
2207 , per_assignment_status_types pastype
2208 , pa_resource_txn_attributes res
2209 , pa_all_organizations allorgs
2210 , per_all_people_f pep
2211 WHERE
2212 assn.assignment_status_type_id = pastype.assignment_status_type_id
2213 AND assn.person_id = res.person_id
2214 AND assn.primary_flag = 'Y'
2215 AND assn.assignment_type in ('E', 'C') -- CWK Changes
2216 AND assn.organization_id = allorgs.organization_id
2217 AND assn.organization_id = hrinf.organization_id
2218 AND assn.effective_start_date BETWEEN pep.effective_start_date
2219 AND pep.effective_end_date
2220 AND assn.effective_end_date >= trunc(sysdate)
2221 AND pastype.per_system_status in ('ACTIVE_ASSIGN', 'ACTIVE_CWK') -- CWK Changes
2222 AND hrinf.org_information_context = 'Exp Organization Defaults'
2223 /* AND pertypes.system_person_type = 'EMP' Commented for bug#2781713 */
2224 AND (pep.employee_number is not null OR pep.npw_number IS NOT NULL) -- CWK Changes
2225 /* AND pep.person_type_id = pertypes.person_type_id Commented for bug#2781713 */
2226 AND (pep.current_employee_flag = 'Y' /* added for bug#2781713 */ OR
2227 pep.current_npw_flag = 'Y') -- CWK Changes
2228 AND pep.person_id = assn.person_id
2229 AND allorgs.organization_id = P_organization_id
2230 AND allorgs.org_id = P_default_OU
2231 AND allorgs.pa_org_use_type = 'EXPENDITURES'
2232 AND allorgs.inactive_date is Not null
2233 AND (allorgs.organization_id,allorgs.org_id) = (
2234 SELECT exporg.organization_id, exporg.org_id
2235 FROM pa_all_organizations exporg
2236 WHERE exporg.pa_org_use_type = 'EXPENDITURES'
2237 AND exporg.inactive_date is Not null
2238 AND exporg.organization_id = allorgs.organization_id
2239 AND exporg.org_id = allorgs.org_id
2240 AND rownum = 1 );
2241
2242 /* -- Added for bug 5330402
2243 cursor get_all_inactive_resource_org is same as
2244 get_all_inactive_resource but commented out inactive date condition in where clause
2245 */
2246 CURSOR get_all_inactive_resource_org
2247 IS
2248 SELECT
2249 distinct
2250 assn.person_id
2251 ,assn.effective_start_date
2252 ,assn.effective_end_date
2253 , res.resource_id
2254 -- , hrinf.org_information1
2255 FROM per_all_assignments_f assn
2256 , hr_organization_information hrinf
2257 /* , per_person_types pertypes Commented for bug#2781713 */
2258 , per_assignment_status_types pastype
2259 , pa_resource_txn_attributes res
2260 , pa_all_organizations allorgs
2261 , per_all_people_f pep
2262 WHERE
2263 assn.assignment_status_type_id = pastype.assignment_status_type_id
2264 AND assn.person_id = res.person_id
2265 AND assn.primary_flag = 'Y'
2266 AND assn.assignment_type in ('E', 'C') -- CWK Changes
2267 AND assn.organization_id = allorgs.organization_id
2268 AND assn.organization_id = hrinf.organization_id
2269 AND assn.effective_start_date BETWEEN pep.effective_start_date
2270 AND pep.effective_end_date
2271 AND assn.effective_end_date >= trunc(sysdate)
2272 AND pastype.per_system_status in ('ACTIVE_ASSIGN', 'ACTIVE_CWK') -- CWK Changes
2273 AND hrinf.org_information_context = 'Exp Organization Defaults'
2274 /* AND pertypes.system_person_type = 'EMP' Commented for bug#2781713 */
2275 AND (pep.employee_number is not null OR pep.npw_number IS NOT NULL) -- CWK Changes
2276 /* AND pep.person_type_id = pertypes.person_type_id Commented for bug#2781713 */
2277 AND (pep.current_employee_flag = 'Y' /* added for bug#2781713 */ OR
2278 pep.current_npw_flag = 'Y') -- CWK Changes
2279 AND pep.person_id = assn.person_id
2280 AND allorgs.organization_id = P_organization_id
2281 AND allorgs.org_id = P_default_OU -- Removed the NVL as this is not required.Sunkalya.Bug#5330402
2282 AND allorgs.pa_org_use_type = 'EXPENDITURES'
2283 -- AND allorgs.inactive_date is Not null
2284 AND (allorgs.organization_id,allorgs.org_id) = ( -- Removed the NVL as this is not required.Sunkalya.Bug#5330402
2285 SELECT exporg.organization_id, exporg.org_id
2286 FROM pa_all_organizations exporg
2287 WHERE exporg.pa_org_use_type = 'EXPENDITURES'
2288 -- AND exporg.inactive_date is Not null
2289 AND exporg.organization_id = allorgs.organization_id
2290 AND exporg.org_id = allorgs.org_id -- Removed the NVL as this is not required.Sunkalya.Bug#5330402
2291 AND rownum = 1 );
2292
2293 BEGIN
2294 -- Initialize the Error stack
2295 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.make_resource_inactive');
2296 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
2297
2298 --dbms_output.put_line('Inside make resource inactive');
2299 --dbms_output.put_line('Default OU:' || p_default_ou);
2300 /* bug 5330402
2301 P_Default_OU_NEW will be null when called for orghierarchy update
2302 P_Default_OU_NEW will not be null when called for nulling out default OU
2303 */
2304 IF p_inactive_date is NOT NULL and p_calling_mode = 'UPDATE' then
2305 if P_Default_OU_NEW is null then
2306 open get_all_inactive_resource;
2307 else
2308 open get_all_inactive_resource_org;
2309 end if;
2310 LOOP
2311 if P_Default_OU_NEW is null then --bug 5330402
2312 fetch get_all_inactive_resource into
2313 v_person_id
2314 ,v_assn_start_date
2315 ,v_assn_end_date
2316 ,v_resource_id
2317 ,v_default_OU;
2318 Exit when get_all_inactive_resource%NOTFOUND;
2319 else
2320 fetch get_all_inactive_resource_org into
2321 v_person_id
2322 ,v_assn_start_date
2323 ,v_assn_end_date
2324 ,v_resource_id;
2325 Exit when get_all_inactive_resource_org%NOTFOUND;
2326 v_default_OU := P_Default_OU; --bug 5330402 setting OU to old value though currently it is null
2327 end if;
2328 If v_person_id is NOT NULL then
2329
2330 --dbms_output.put_line('Calling Update OU Resource');
2331 -- update the resource denorm with end date the resources
2332 Update_OU_resource (
2333 P_default_OU_old => v_default_OU
2334 ,p_default_OU_new => v_default_OU
2335 ,P_person_id => v_person_id
2336 ,P_start_date => v_assn_start_date
2337 ,P_end_date_old => v_assn_end_date
2338 ,P_end_date_new => p_inactive_date
2339 ,x_return_status => x_return_status
2340 ,x_msg_data => x_msg_data
2341 ,x_msg_count => x_msg_count );
2342
2343 if (x_return_status = FND_API.G_RET_STS_SUCCESS) then
2344 COMMIT;
2345 else
2346 ROLLBACK;
2347 end if;
2348
2349 End if;
2350
2351 END LOOP;
2352 if P_Default_OU_NEW is null then --bug 5330402
2353 close get_all_inactive_resource;
2354 else
2355 close get_all_inactive_resource_org;
2356 end if;
2357
2358 --set the final return status to SUCCESS after loop
2359 x_return_status := FND_API.G_RET_STS_SUCCESS;
2360
2361 END IF;
2362
2363 -- reset the Error stack
2364 PA_DEBUG.Reset_Err_Stack;
2365 EXCEPTION
2366 WHEN OTHERS THEN
2367 -- 4537865 : RESET x_msg_count and x_msg_data also
2368 x_msg_count := 1 ;
2369 x_msg_data := SUBSTRB(SQLERRM ,1,240);
2370 -- Set the exception Message and the stack
2371 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.make_resource_inactive'
2372 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
2373 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
2374 raise;
2375
2376
2377
2378 END make_resource_inactive;
2379
2380
2381 -- This API makes calls to PA_FORECASTITEM_PVT.Create_Forecast_Item api
2382 -- which will generate or update the forecast items
2383 -- This API performs commit and rollback because it is only called by
2384 -- per_job_extra_billability, which is an autonomous transaction
2385 -- This will not affect the workflow process when doing any commit or rollback
2386 PROCEDURE call_forcast_api
2387 (P_table_name IN VARCHAR2
2388 ,P_person_id IN PER_ALL_ASSIGNMENTS_F.PERSON_ID%TYPE default NULL
2389 ,P_Job_id IN per_jobs.job_id%type default NULL
2390 ,P_billable_flag IN VARCHAR2 default NULL
2391 ,P_organization_id IN Hr_organization_information.organization_id%type default NULL
2392 ,p_start_date IN date default NULL
2393 ,P_end_date IN date default NULL
2394 ,P_resource_OU IN NUMBER default NULL
2395 ,P_resource_type IN VARCHAR2 default NULL
2396 ,x_return_status OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
2397 ,x_msg_data OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
2398 ,x_msg_count OUT NOCOPY NUMBER --File.Sql.39 bug 4440895
2399 ) IS
2400
2401 v_person_id PER_ALL_ASSIGNMENTS_F.PERSON_ID%TYPE;
2402 v_start_date Date;
2403 v_end_date Date;
2404
2405 --- This cursor picks all the persons who are Employees category and
2406 -- belongs to Expenditure Hierarchy
2407 -- and belongs to job id = paremeter
2408 Cursor person_jobs(l_job_id per_jobs.job_id%type)is
2409 SELECT distinct
2410 assn.person_id
2411 ,assn.effective_start_date
2412 ,assn.effective_end_date
2413 FROM per_all_assignments_f assn
2414 , hr_organization_information hrinf
2415 /* , per_person_types pertypes Commented for Bug#2781713 */
2416 , per_assignment_status_types pastype
2417 , per_all_people_f pep
2418 WHERE
2419 assn.assignment_status_type_id = pastype.assignment_status_type_id
2420 AND assn.primary_flag = 'Y'
2421 AND assn.assignment_type in ('E', 'C') -- CWK Changes
2422 AND assn.job_id = l_job_id
2423 AND assn.organization_id = hrinf.organization_id
2424 AND assn.effective_start_date BETWEEN pep.effective_start_date
2425 AND pep.effective_end_date
2426 AND assn.effective_end_date >= trunc(sysdate)
2427 AND pastype.per_system_status in ('ACTIVE_ASSIGN', 'ACTIVE_CWK') -- CWK Changes
2428 AND hrinf.org_information_context = 'Exp Organization Defaults'
2429 /* AND pertypes.system_person_type = 'EMP' Commented for Bug#2781713 */
2430 AND (pep.employee_number is not null OR pep.npw_number IS NOT NULL) -- CWK Changes
2431 /* AND pep.person_type_id = pertypes.person_type_id Commented for Bug#2781713 */
2432 AND (pep.current_employee_flag = 'Y' /* added for bug#2781713 */ OR
2433 pep.current_npw_flag = 'Y') -- CWK Changes
2434 AND pep.person_id = assn.person_id
2435 AND assn.organization_id =
2436 (SELECT exporg.organization_id
2437 FROM pa_all_organizations exporg
2438 WHERE exporg.pa_org_use_type = 'EXPENDITURES'
2439 AND exporg.inactive_date is null
2440 AND exporg.organization_id = assn.organization_id
2441 AND rownum = 1 )
2442 ORDER BY 1,2;
2443
2444 -- This cursor picks all the persons who are Employees and belongs to the
2445 -- expenditure hierarchy and belongs to organzation where organization_id = l_org_id
2446 CURSOR person_orgs(l_org_id Hr_Organization_Information.Organization_id%type) is
2447 SELECT distinct
2448 assn.person_id
2449 ,assn.effective_start_date
2450 ,assn.effective_end_date
2451 FROM per_all_assignments_f assn
2452 , hr_organization_information hrinf
2453 /* , per_person_types pertypes Commented for Bug#2781713 */
2454 , per_assignment_status_types pastype
2455 , per_all_people_f pep
2456 WHERE
2457 assn.assignment_status_type_id = pastype.assignment_status_type_id
2458 AND assn.primary_flag = 'Y'
2459 AND assn.assignment_type in ('E', 'C') -- CWK Changes
2460 AND assn.organization_id = l_org_id
2461 AND assn.organization_id = hrinf.organization_id
2462 AND assn.effective_start_date BETWEEN pep.effective_start_date
2463 AND pep.effective_end_date
2464 AND assn.effective_end_date >= trunc(sysdate)
2465 AND pastype.per_system_status in ('ACTIVE_ASSIGN', 'ACTIVE_CWK') -- CWK Changes
2466 AND hrinf.org_information_context = 'Exp Organization Defaults'
2467 /* AND pertypes.system_person_type = 'EMP' Commented for Bug#2781713 */
2468 AND (pep.employee_number is not null OR pep.npw_number IS NOT NULL) -- CWK Changes
2469 /* AND pep.person_type_id = pertypes.person_type_id Commented for Bug#2781713 */
2470 AND (pep.current_employee_flag = 'Y' /* added for bug#2781713 */ OR
2471 pep.current_npw_flag = 'Y') -- CWK Changes
2472 AND pep.person_id = assn.person_id
2473 AND assn.organization_id =
2474 (SELECT exporg.organization_id
2475 FROM pa_all_organizations exporg
2476 WHERE exporg.pa_org_use_type = 'EXPENDITURES'
2477 AND exporg.inactive_date is null
2478 AND exporg.organization_id = assn.organization_id
2479 AND rownum = 1 )
2480 ORDER BY 1,2;
2481
2482
2483 BEGIN
2484 -- Initialize the Error stack
2485 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.call_forcast_api');
2486 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
2487
2488 If (P_table_name = 'PER_JOB_EXTRA_INFO' or
2489 P_table_name = 'PER_VALID_GRADES' or
2490 P_table_name = 'PER_GRADES' or
2491 P_table_name = 'PA_ALL_ORGANIZATIONS') and
2492 (P_job_id is NOT NULL) then
2493
2494 -- get all the persons belongs to this job Id and
2495 -- Call Forecast Item regeneration API to update the forecast
2496 -- data for unassigned and assigned time
2497
2498 OPEN person_jobs(P_job_id);
2499 LOOP
2500 fetch person_jobs into v_person_id,v_start_date,v_end_date;
2501 exit when person_jobs%notfound;
2502
2503 PA_FORECASTITEM_PVT.Create_Forecast_Item
2504 (
2505 p_person_id => v_person_id
2506 ,p_start_date => v_start_date
2507 ,p_end_date => v_end_date
2508 ,p_process_mode => 'GENERATE'
2509 ,x_return_status => x_return_status
2510 ,x_msg_count => x_msg_count
2511 ,x_msg_data => x_msg_data
2512 ) ;
2513
2514 if (x_return_status = FND_API.G_RET_STS_SUCCESS) then
2515 COMMIT;
2516 else
2517 ROLLBACK;
2518 end if;
2519
2520 /* cannot raise - because will be out from the loop and will not process other records
2521 IF x_return_status <> FND_API.G_RET_STS_SUCCESS THEN
2522 RAISE FND_API.G_EXC_ERROR;
2523 END IF;
2524 */
2525
2526 END LOOP;
2527 CLOSE person_jobs;
2528
2529 Elsif (P_table_name = 'HR_ORGANIZATION_INFORMATION')
2530 and (P_organization_id is NOT NULL) then
2531
2532 -- get all the persons who belongs to this organization and
2533 -- Call Forecast Item regeneration API to update the forecast
2534 -- data for unassigned and assigned time
2535
2536 OPEN person_orgs(P_organization_id);
2537 LOOP
2538 fetch person_orgs into v_person_id,v_start_date,v_end_date;
2539 exit when person_orgs%notfound;
2540
2541 PA_FORECASTITEM_PVT.Create_Forecast_Item
2542 (
2543 p_person_id => v_person_id
2544 ,p_start_date => v_start_date
2545 ,p_end_date => v_end_date
2546 ,p_process_mode => 'GENERATE'
2547 ,x_return_status => x_return_status
2548 ,x_msg_count => x_msg_count
2549 ,x_msg_data => x_msg_data
2550 ) ;
2551
2552 if (x_return_status = FND_API.G_RET_STS_SUCCESS) then
2553 COMMIT;
2554 else
2555 ROLLBACK;
2556 end if;
2557
2558 /* cannot raise - because will be out from the loop and will not process other records
2559 IF x_return_status <> FND_API.G_RET_STS_SUCCESS THEN
2560 RAISE FND_API.G_EXC_ERROR;
2561 END IF;
2562 */
2563 END LOOP;
2564 CLOSE person_orgs;
2565
2566 End if;
2567
2568 --set the final return status to SUCCESS after loop
2569 x_return_status := FND_API.G_RET_STS_SUCCESS;
2570
2571 -- reset the Error stack
2572 PA_DEBUG.Reset_Err_Stack;
2573 EXCEPTION
2574 WHEN FND_API.G_EXC_ERROR THEN
2575 x_return_status := FND_API.G_RET_STS_ERROR;
2576 WHEN OTHERS THEN
2577 -- 4537865 : RESET x_msg_count and x_msg_data also
2578 x_msg_count := 1 ;
2579 x_msg_data := SUBSTRB(SQLERRM ,1,240);
2580 -- Set the exception Message and the stack
2581 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.call_forcast_api'
2582 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
2583 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
2584 raise;
2585
2586
2587
2588 END call_forcast_api;
2589
2590
2591 -- This Procedure makes calls to PA_RESOURCE_PVT.update_resource_denorm api
2592 -- which actually updates the pa_resources_denorm entity
2593 PROCEDURE call_billable_resoruce_denorm
2594 (P_job_id_old per_jobs.job_id%type
2595 ,P_job_id_new per_jobs.job_id%type
2596 ,P_billable_flag_old pa_resources_denorm.billable_flag%type
2597 ,P_billable_flag_new pa_resources_denorm.billable_flag%type
2598 ,P_utilize_flag_old pa_resources_denorm.utilization_flag%type
2599 ,P_utilize_flag_new pa_resources_denorm.utilization_flag%type
2600 ,p_schedulable_flag_old pa_resources_denorm.schedulable_flag%type
2601 ,p_schedulable_flag_new pa_resources_denorm.schedulable_flag%type
2602 ,x_return_status OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
2603 ,x_msg_data OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
2604 ,x_msg_count OUT NOCOPY NUMBER --File.Sql.39 bug 4440895
2605 ) IS
2606 v_return_status VARCHAR2(2000);
2607 v_error_message_code VARCHAR2(2000);
2608 v_resource_rec_old PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
2609 v_resource_rec_new PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
2610 v_job_id_old PER_JOBS.JOB_ID%type;
2611 v_job_id_new PER_JOBS.JOB_ID%type;
2612 v_billable_flag_old pa_resources_denorm.billable_flag%type;
2613 v_billable_flag_new pa_resources_denorm.billable_flag%type;
2614 v_utilize_flag_old pa_resources_denorm.utilization_flag%type;
2615 v_utilize_flag_new pa_resources_denorm.utilization_flag%type;
2616 v_schedulable_flag_old pa_resources_denorm.schedulable_flag%type;
2617 v_schedulable_flag_new pa_resources_denorm.schedulable_flag%type;
2618 v_msg_data VARCHAR2(2000);
2619 v_msg_count NUMBER;
2620
2621 BEGIN
2622
2623 -- Initialize the Error stack
2624 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.call_billable_resoruce_denorm');
2625 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
2626 v_job_id_new := P_job_id_new;
2627 v_job_id_old := P_job_id_old;
2628
2629 If P_billable_flag_new is NOT NULL then
2630 v_billable_flag_new := P_billable_flag_new;
2631 Else
2632 v_billable_flag_new := 'N';
2633 End if;
2634
2635 If P_billable_flag_old is NOT NULL then
2636 v_billable_flag_old := P_billable_flag_old;
2637 Else
2638 v_billable_flag_old := 'N';
2639 End if;
2640
2641 If P_utilize_flag_new is NOT NULL then
2642 v_utilize_flag_new := P_utilize_flag_new;
2643 Else
2644 v_utilize_flag_new := 'N';
2645 End if;
2646
2647 If P_utilize_flag_old is NOT NULL then
2648 v_utilize_flag_old := P_utilize_flag_old;
2649 Else
2650 v_utilize_flag_old := 'N';
2651 End if;
2652
2653 If P_schedulable_flag_new is NOT NULL then
2654 v_schedulable_flag_new := P_schedulable_flag_new;
2655 Else
2656 v_schedulable_flag_new := 'N';
2657 End if;
2658 If P_schedulable_flag_old is NOT NULL then
2659 v_schedulable_flag_old := P_schedulable_flag_old;
2660 Else
2661 v_schedulable_flag_old := 'N';
2662 End if;
2663
2664 if v_job_id_new is NOT NULL then
2665 v_resource_rec_old.job_id := v_job_id_old;
2666 v_resource_rec_old.billable_flag := v_billable_flag_old;
2667 v_resource_rec_new.job_id := v_job_id_new;
2668 v_resource_rec_new.billable_flag := v_billable_flag_new;
2669 v_resource_rec_old.utilization_flag := v_utilize_flag_old;
2670 v_resource_rec_new.utilization_flag := v_utilize_flag_new;
2671 v_resource_rec_old.schedulable_flag := v_schedulable_flag_old;
2672 v_resource_rec_new.schedulable_flag := v_schedulable_flag_new;
2673
2674 -- Call PRM API update resource denorm which actually updates the
2675 -- pa_resource_denorm entity
2676
2677 PA_RESOURCE_PVT.update_resource_denorm
2678 ( p_resource_denorm_old_rec => v_resource_rec_old
2679 ,p_resource_denorm_new_rec => v_resource_rec_new
2680 ,x_return_status => x_return_status
2681 ,x_msg_data => x_msg_data
2682 ,x_msg_count => x_msg_count
2683 );
2684
2685
2686
2687 End if;
2688 -- reset the Error stack
2689 PA_DEBUG.Reset_Err_Stack;
2690
2691 EXCEPTION
2692
2693 WHEN OTHERS THEN
2694 -- 4537865 : RESET x_msg_count and x_msg_data also
2695 x_msg_count := 1 ;
2696 x_msg_data := SUBSTRB(SQLERRM ,1,240);
2697 -- Set the exception Message and the stack
2698 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.call_billable_resoruce_denorm'
2699 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
2700 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
2701 raise;
2702
2703 END call_billable_resoruce_denorm;
2704
2705 -- This Procedure is kicked off by the workflow when jei_infomration2
2706 -- which stores the jobs billability information. whenever the row is updated
2707 -- or inserted into per_job_extra_info entity which stores the job information
2708 -- and types a database triggers fires and kicks of the workflow
2709 -- This procedure makes calls to forecast regenerate apis and create resource
2710 -- denorm apis to to update the new billability for the resource
2711 -- Make this procedure a PRAGMA AUTONOMOUS_TRANSACTION because at the end
2712 -- this procedure call call_forcast_api which do commit after every resource
2713 -- in a loop to update the forecast items
2714 PROCEDURE per_job_extra_billability
2715 (p_calling_mode IN VARCHAR2
2716 ,P_job_id IN per_jobs.job_id%type
2717 ,P_billable_flag_new IN per_job_extra_info.jei_information2%type
2718 ,P_billable_flag_old IN per_job_extra_info.jei_information2%type
2719 ,P_utilize_flag_old IN per_job_extra_info.jei_information3%type
2720 ,P_utilize_flag_new IN per_job_extra_info.jei_information3%type
2721 ,P_job_level_new IN per_job_extra_info.jei_information4%type
2722 ,P_job_level_old IN per_job_extra_info.jei_information4%type
2723 ,p_schedulable_flag_new IN per_job_extra_info.jei_information6%type
2724 ,p_schedulable_flag_old IN per_job_extra_info.jei_information6%type
2725 ,x_return_status OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
2726 ,x_msg_data OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
2727 ,x_msg_count OUT NOCOPY NUMBER) IS --File.Sql.39 bug 4440895
2728 PRAGMA AUTONOMOUS_TRANSACTION;
2729
2730 v_return_status VARCHAR2(2000);
2731 v_error_message_code VARCHAR2(2000);
2732 v_job_id PER_JOBS.JOB_ID%type;
2733 v_msg_data VARCHAR2(2000);
2734 v_msg_count NUMBER;
2735 l_pull_res_flag VARCHAR2(1) := 'N';
2736 l_end_date_res_flag VARCHAR2(1) := 'N';
2737 l_prv_person_id NUMBER;
2738 l_resource_id NUMBER;
2739 P_DEBUG_MODE VARCHAR2(1) := NVL(FND_PROFILE.value('PA_DEBUG_MODE'), 'N');
2740
2741 /*
2742 CURSOR all_job_res_recs IS
2743 SELECT person_id, min(resource_effective_start_date) resource_effective_start_date,
2744 max(resource_effective_end_date) resource_effective_end_date
2745 FROM pa_resources_denorm
2746 WHERE job_id = p_job_id
2747 GROUP BY person_id; */
2748
2749 CURSOR all_job_res_recs IS -- Modified cursor for Bug 7336158
2750 SELECT person_id, min(resource_effective_start_date) resource_effective_start_date,
2751 max(resource_effective_end_date) resource_effective_end_date
2752 FROM pa_resources_denorm
2753 WHERE job_id = p_job_id
2754 AND resource_effective_end_date = (Select max(resource_effective_end_date)
2755 from pa_resources_denorm rd2
2756 where rd2.job_id = p_job_id
2757 AND (rd2.resource_effective_end_date >= sysdate OR rd2.resource_effective_end_date is null))
2758 GROUP BY person_id;
2759
2760 CURSOR distinct_job_res_recs IS
2761 SELECT DISTINCT res.person_id person_id
2762 FROM pa_r_project_resources_v res
2763 WHERE res.job_id = p_job_id;
2764
2765 BEGIN
2766 -- Initialize the Error stack
2767 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.per_job_extra_billability');
2768 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
2769
2770 IF P_DEBUG_MODE = 'Y' THEN
2771 log_message('beginning of per_job_extra_billability, P_calling_mode:'|| P_calling_mode || ', job_id: '||P_job_id);
2772 END IF;
2773
2774 -------------------------------------------------------------------------
2775 -- If P_calling_mode='INSERT', P_utilize_flag_new will always be 'Y' and
2776 -- we need to pull those people who has the job.
2777 -- Because if P_utilize_flag_new=N, the trigger won't launch WF which
2778 -- eventually calls this API.
2779 --------------------------------------------------------------------------
2780 If P_calling_mode = 'INSERT' THEN
2781 l_pull_res_flag := 'Y';
2782
2783 -------------------------------------------------------------------------
2784 -- If P_calling_mode='UPDATE'
2785 -------------------------------------------------------------------------
2786 ELSIF P_calling_mode = 'UPDATE' THEN
2787 -- If p_utilize_flag_old='N' AND p_utilize_flag_new='Y', we need to
2788 -- pull the people who have the job
2789 IF p_utilize_flag_old='N' AND p_utilize_flag_new='Y' THEN
2790 l_pull_res_flag := 'Y';
2791
2792 ELSE
2793 -- If p_utilize_flag_old='Y' and p_utilize_flag_new ='N', we need
2794 -- to end date the resources from pa_resources_denorm
2795 IF p_utilize_flag_old ='Y' AND p_utilize_flag_new ='N' THEN
2796 l_end_date_res_flag := 'Y';
2797 END IF;
2798
2799 IF P_DEBUG_MODE = 'Y' THEN
2800 log_message('p_utilize_flag_new: ' ||p_utilize_flag_new ||
2801 ',l_end_date_res_flag: '||l_end_date_res_flag);
2802 END IF;
2803
2804 -- Update pa_resources_denorm
2805 call_billable_resoruce_denorm
2806 (P_job_id_old => P_job_id
2807 ,P_job_id_new => P_job_id
2808 ,P_billable_flag_old => P_billable_flag_old
2809 ,P_billable_flag_new => P_billable_flag_new
2810 ,P_utilize_flag_old => P_utilize_flag_old
2811 ,P_utilize_flag_new => P_utilize_flag_new
2812 ,p_schedulable_flag_old => p_schedulable_flag_old
2813 ,p_schedulable_flag_new => p_schedulable_flag_new
2814 ,x_return_status => x_return_status
2815 ,x_msg_data => x_msg_data
2816 ,x_msg_count => x_msg_count );
2817 IF P_DEBUG_MODE = 'Y' THEN
2818 log_message('After call_billable_resoruce_denorm');
2819 END IF;
2820
2821 -- Update job level
2822 update_job_level_dff
2823 (P_job_id => P_job_id
2824 ,P_job_level_old => TO_NUMBER(P_job_level_old)
2825 ,P_job_level_new => TO_NUMBER(P_job_level_new)
2826 ,x_return_status => x_return_status
2827 ,x_msg_data => x_msg_data
2828 ,x_msg_count => x_msg_count );
2829 IF P_DEBUG_MODE = 'Y' THEN
2830 log_message('After update_job_level_dff');
2831 END IF;
2832 END IF;
2833
2834 -------------------------------------------------------------------------
2835 -- If P_calling_mode='DELETE' and p_utilize_flag_old='Y', end date those
2836 -- resources who has the job. If p_utilize_flag_old='N', there won't be
2837 -- current active data. But we still need to update the other flags on
2838 -- the past date records.
2839 -------------------------------------------------------------------------
2840 ELSIF P_calling_mode = 'DELETE' THEN
2841 IF p_utilize_flag_old ='Y' THEN
2842 l_end_date_res_flag := 'Y';
2843 END IF;
2844 IF P_DEBUG_MODE = 'Y' THEN
2845 log_message('P_calling_mode=DELETE, p_utilize_flag_old:'||p_utilize_flag_old
2846 ||', l_end_date_res_flag:'||l_end_date_res_flag);
2847 END IF;
2848
2849 call_billable_resoruce_denorm
2850 (P_job_id_old => P_job_id
2851 ,P_job_id_new => P_job_id
2852 ,P_billable_flag_old => P_billable_flag_old
2853 ,P_billable_flag_new => NULL
2854 ,P_utilize_flag_old => P_utilize_flag_old
2855 ,P_utilize_flag_new => NULL
2856 ,p_schedulable_flag_old => p_schedulable_flag_old
2857 ,p_schedulable_flag_new => NULL
2858 ,x_return_status => x_return_status
2859 ,x_msg_data => x_msg_data
2860 ,x_msg_count => x_msg_count );
2861
2862 update_job_level_dff
2863 (P_job_id => P_job_id
2864 ,P_job_level_old => TO_NUMBER(P_job_level_old)
2865 ,P_job_level_new => NULL
2866 ,x_return_status => x_return_status
2867 ,x_msg_data => x_msg_data
2868 ,x_msg_count => x_msg_count );
2869 IF P_DEBUG_MODE = 'Y' THEN
2870 log_message('After calling update_job_level_dff');
2871 END IF;
2872 END IF;
2873
2874 ----------------------------------------------------------------
2875 -- pull the people
2876 ----------------------------------------------------------------
2877 IF (l_pull_res_flag = 'Y') THEN
2878 IF P_DEBUG_MODE = 'Y' THEN
2879 log_message('it will pull the people');
2880 END IF;
2881 FOR rec IN distinct_job_res_recs LOOP
2882 BEGIN
2883 IF P_DEBUG_MODE = 'Y' THEN
2884 log_message('person Id = ' || rec.person_id);
2885 END IF;
2886
2887 PA_R_PROJECT_RESOURCES_PUB.CREATE_RESOURCE (
2888 p_api_version => 1.0
2889 ,p_commit => FND_API.G_FALSE
2890 ,p_validate_only => FND_API.G_FALSE
2891 ,p_internal => 'Y'
2892 ,p_person_id => rec.person_id
2893 ,p_individual => 'Y'
2894 ,p_resource_type => 'EMPLOYEE'
2895 ,x_resource_id => l_resource_id
2896 ,x_return_status => x_return_status
2897 ,x_msg_count => x_msg_count
2898 ,x_msg_data => x_msg_data );
2899
2900 IF P_DEBUG_MODE = 'Y' THEN
2901 log_message('Return status from CREATE_RESOURCE = ' || x_return_status);
2902 END IF;
2903 IF (x_return_status = FND_API.G_RET_STS_SUCCESS) then
2904 COMMIT;
2905 ELSE
2906 ROLLBACK;
2907 END IF;
2908
2909 EXCEPTION
2910 -- whenever an expected error is raised from this API
2911 -- will need to continue for the next record
2912 WHEN OTHERS THEN
2913 FND_MSG_PUB.get (
2914 p_encoded => FND_API.G_FALSE,
2915 p_msg_index => 1,
2916 p_data => x_msg_data,
2917 p_msg_index_out => x_msg_count );
2918 IF P_DEBUG_MODE = 'Y' THEN
2919 log_message('error msg from CREATE_RESOURCE: ' || substr(x_msg_data,1,200));
2920 END IF;
2921 END;
2922 END LOOP;
2923
2924 -----------------------------------------------------------------------------
2925 -- End date all those resources who has the job from the pa_resources_denorm
2926 -----------------------------------------------------------------------------
2927 ELSIF (l_end_date_res_flag = 'Y') THEN
2928 IF P_DEBUG_MODE = 'Y' THEN
2929 log_message('it will end date the resources');
2930 END IF;
2931 FOR rec IN all_job_res_recs LOOP
2932 BEGIN
2933 IF P_DEBUG_MODE = 'Y' THEN
2934 log_message('person Id = ' || rec.person_id ||' ,start_date: ' ||
2935 rec.resource_effective_start_date || ', end_date: '||
2936 rec.resource_effective_end_date );
2937 END IF;
2938
2939 Update_EndDate
2940 (p_person_id => rec.person_id,
2941 p_old_start_date => rec.resource_effective_start_date,
2942 p_new_start_date => rec.resource_effective_start_date,
2943 p_old_end_date => rec.resource_effective_end_date,
2944 p_new_end_date => sysdate,
2945 x_return_status => x_return_status,
2946 x_msg_count => x_msg_count,
2947 x_msg_data => x_msg_data);
2948
2949 IF P_DEBUG_MODE = 'Y' THEN
2950 log_message('Return status from Update_EndDate = ' || x_return_status);
2951 END IF;
2952 IF (x_return_status = FND_API.G_RET_STS_SUCCESS) then
2953 COMMIT;
2954 ELSE
2955 ROLLBACK;
2956 END IF;
2957 EXCEPTION
2958 -- whenever an expected error is raised from this API
2959 -- will need to continue for the next record
2960 WHEN OTHERS THEN
2961 IF P_DEBUG_MODE = 'Y' THEN
2962 log_message('error occured');
2963 END IF;
2964 ROLLBACK;
2965 FND_MSG_PUB.get (
2966 p_encoded => FND_API.G_FALSE,
2967 p_msg_index => 1,
2968 p_data => x_msg_data,
2969 p_msg_index_out => x_msg_count );
2970 IF P_DEBUG_MODE = 'Y' THEN
2971 log_message('error msg from Update_EndDate: ' || substr(x_msg_data,1,200));
2972 END IF;
2973 END;
2974 END LOOP;
2975
2976 END IF;
2977
2978
2979 -- call forecast api to regenerate the forcast items due to change in
2980 -- billability flag
2981 call_forcast_api
2982 (P_table_name => 'PER_JOB_EXTRA_INFO'
2983 ,P_Job_id => P_job_id
2984 ,x_return_status => x_return_status
2985 ,x_msg_data => x_msg_data
2986 ,x_msg_count => x_msg_count );
2987 IF P_DEBUG_MODE = 'Y' THEN
2988 log_message('After calling call_forcast_api, x_return_status: '||x_return_status);
2989 END IF;
2990
2991 IF x_return_status <> FND_API.G_RET_STS_SUCCESS THEN
2992 IF P_DEBUG_MODE = 'Y' THEN
2993 log_message('It will raise exception');
2994 END IF;
2995 RAISE FND_API.G_EXC_ERROR;
2996 ELSIF x_return_status = FND_API.G_RET_STS_SUCCESS THEN
2997 IF P_DEBUG_MODE = 'Y' THEN
2998 log_message('will commit');
2999 END IF;
3000 COMMIT;
3001 END IF;
3002
3003 -- reset the Error stack
3004 PA_DEBUG.Reset_Err_Stack;
3005 IF P_DEBUG_MODE = 'Y' THEN
3006 log_message('after Reset_Err_Stack');
3007 END IF;
3008
3009 EXCEPTION
3010 WHEN FND_API.G_EXC_ERROR THEN
3011 ROLLBACK;
3012 x_return_status := FND_API.G_RET_STS_ERROR;
3013 WHEN NO_DATA_FOUND THEN
3014 NULL;
3015 WHEN OTHERS THEN
3016 IF P_DEBUG_MODE = 'Y' THEN
3017 log_message('Error occured');
3018 END IF;
3019 -- 4537865 : RESET x_msg_count and x_msg_data also
3020 x_msg_count := 1 ;
3021 x_msg_data := SUBSTRB(SQLERRM ,1,240);
3022 -- Set the exception Message and the stack
3023 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.per_job_extra_billability'
3024 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
3025 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
3026 RAISE;
3027 END per_job_extra_billability;
3028
3029
3030 -- PROCEDURE
3031 -- withdraw_cand_nominations
3032 -- PURPOSE
3033 -- to withdraw all PJR candidate nominations for this
3034 -- person_id when the person is terminated in HR
3035 -- or the assignment organization no longer belongs to
3036 -- expenditure hierarchy
3037 --
3038 PROCEDURE withdraw_cand_nominations
3039 ( p_person_id IN NUMBER,
3040 p_effective_date IN DATE,
3041 x_return_status OUT NOCOPY VARCHAR2, --File.Sql.39 bug 4440895
3042 x_msg_count OUT NOCOPY NUMBER, --File.Sql.39 bug 4440895
3043 x_msg_data OUT NOCOPY VARCHAR2) IS --File.Sql.39 bug 4440895
3044
3045 l_resource_id NUMBER;
3046 l_status_code VARCHAR2(30);
3047 l_rec_ver_num NUMBER;
3048 P_DEBUG_MODE VARCHAR2(1) := NVL(FND_PROFILE.value('PA_DEBUG_MODE'), 'N');
3049
3050 CURSOR get_nominations(l_resource_id IN NUMBER) IS
3051 select cand.candidate_id, cand.record_version_number
3052 from pa_candidates cand,
3053 pa_project_assignments asgmt,
3054 pa_project_statuses ps
3055 where cand.resource_id = l_resource_id
3056 and cand.assignment_id = asgmt.assignment_id
3057 and asgmt.assignment_type = 'OPEN_ASSIGNMENT'
3058 and asgmt.status_code = ps.project_status_code (+)
3059 and (ps.project_system_status_code = 'OPEN_ASGMT'
3060 OR ps.project_system_status_code is null)
3061 and asgmt.start_date > trunc(p_effective_date)
3062 and cand.status_code not in
3063 (select ps2.project_status_code
3064 from pa_project_statuses ps2
3065 where ps2.status_type='CANDIDATE'
3066 and ps2.project_system_status_code IN
3067 ('CANDIDATE_DECLINED','CANDIDATE_WITHDRAWN'));
3068
3069 l_candidate_in_rec PA_RES_MANAGEMENT_AMG_PUB.CANDIDATE_IN_REC_TYPE; -- Added for bug 9187892
3070
3071
3072 BEGIN
3073
3074 -- Initialize the Error stack
3075 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.withdraw_cand_nominations');
3076 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
3077
3078 l_resource_id := PA_RESOURCE_UTILS.get_resource_id(p_person_id);
3079
3080 IF (l_resource_id <> -999) THEN
3081
3082 l_status_code := FND_PROFILE.value('PA_INV_RES_CAND_STATUS');
3083 IF P_DEBUG_MODE = 'Y' THEN
3084 log_message('Candidate status code = ' || l_status_code);
3085 END IF;
3086
3087 -- if the profile option is not set, then we use the status code
3088 -- '111' that we ship to customers for 'CANDIDATE_WITHDRAWN'
3089 -- system status code
3090 IF l_status_code is null THEN
3091 l_status_code := '111';
3092 END IF;
3093
3094 FOR rec IN get_nominations(l_resource_id) LOOP
3095
3096 BEGIN
3097 SAVEPOINT save_candidate;
3098 IF P_DEBUG_MODE = 'Y' THEN
3099 log_message('Candidate Id = ' || rec.candidate_id);
3100 END IF;
3101
3102 PA_CANDIDATE_PUB.Update_Candidate
3103 (p_candidate_id => rec.candidate_id,
3104 p_status_code => l_status_code,
3105 p_ranking => null,
3106 p_change_reason_code => null,
3107 p_record_version_number => rec.record_version_number,
3108 p_init_msg_list => FND_API.G_FALSE,
3109 p_validate_status => FND_API.G_FALSE,
3110 -- Added for bug 9187892
3111 p_attribute_category => l_candidate_in_rec.attribute_category,
3112 p_attribute1 => l_candidate_in_rec.attribute1,
3113 p_attribute2 => l_candidate_in_rec.attribute2,
3114 p_attribute3 => l_candidate_in_rec.attribute3,
3115 p_attribute4 => l_candidate_in_rec.attribute4,
3116 p_attribute5 => l_candidate_in_rec.attribute5,
3117 p_attribute6 => l_candidate_in_rec.attribute6,
3118 p_attribute7 => l_candidate_in_rec.attribute7,
3119 p_attribute8 => l_candidate_in_rec.attribute8,
3120 p_attribute9 => l_candidate_in_rec.attribute9,
3121 p_attribute10 => l_candidate_in_rec.attribute10,
3122 p_attribute11 => l_candidate_in_rec.attribute11,
3123 p_attribute12 => l_candidate_in_rec.attribute12,
3124 p_attribute13 => l_candidate_in_rec.attribute13,
3125 p_attribute14 => l_candidate_in_rec.attribute14,
3126 p_attribute15 => l_candidate_in_rec.attribute15,
3127 x_record_version_number => l_rec_ver_num,
3128 x_return_status => x_return_status,
3129 x_msg_count => x_msg_count,
3130 x_msg_data => x_msg_data);
3131
3132 IF P_DEBUG_MODE = 'Y' THEN
3133 log_message('Return status from Update Candidate = ' || x_return_status);
3134 END IF;
3135
3136 EXCEPTION
3137 -- whenever an expected error is raised from this API
3138 -- will need to continue for the next record
3139 WHEN FND_API.G_EXC_ERROR THEN
3140 ROLLBACK TO save_candidate;
3141 FND_MSG_PUB.get (
3142 p_encoded => FND_API.G_FALSE,
3143 p_msg_index => 1,
3144 p_data => x_msg_data,
3145 p_msg_index_out => x_msg_count );
3146 IF P_DEBUG_MODE = 'Y' THEN
3147 log_message('Withdraw_Cand_Nominations EXPECTED ERROR: Candidate_Id =' || rec.candidate_id);
3148 log_message('Log: ' || substr(x_msg_data,1,200));
3149 END IF;
3150 END;
3151
3152 END LOOP;
3153
3154 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
3155
3156 ELSE
3157 -- person does not exist in pa_resource_txn_attributes
3158 X_RETURN_STATUS := FND_API.G_RET_STS_ERROR;
3159 END IF;
3160
3161 -- reset the Error stack
3162 PA_DEBUG.Reset_Err_Stack;
3163
3164 EXCEPTION
3165
3166 WHEN OTHERS THEN
3167 -- 4537865 : RESET x_msg_count and x_msg_data also
3168 x_msg_count := 1 ;
3169 x_msg_data := SUBSTRB(SQLERRM ,1,240);
3170 -- Set the exception Message and the stack
3171 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.withdraw_cand_nominations'
3172 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
3173 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
3174 raise;
3175 END withdraw_cand_nominations;
3176
3177
3178 /* Procedure Update_EndDate calls Update_Resource_Denorm to update the
3179 end date in pa_resources_denorm and update FI data for the resource.
3180 This procedure now also handles automatic candidates withdrawal.
3181 It is called whenever a resource is terminated in HR, whenever
3182 the change in assignment organization which does not belong to Exp Hier,
3183 or whenever an organization is taken out from the Exp Hier. In these
3184 cases, the resource is considered no longer active in PJR.
3185 */
3186 PROCEDURE Update_EndDate(
3187 p_person_id IN per_all_people_f.person_id%TYPE,
3188 p_old_start_date IN per_all_assignments_f.effective_start_date%TYPE,
3189 p_new_start_date IN per_all_assignments_f.effective_end_date%TYPE,
3190 p_old_end_date IN per_all_assignments_f.effective_start_date%TYPE,
3191 p_new_end_date IN per_all_assignments_f.effective_end_date%TYPE,
3192 x_return_status OUT NOCOPY VARCHAR2, --File.Sql.39 bug 4440895
3193 x_msg_data OUT NOCOPY VARCHAR2, --File.Sql.39 bug 4440895
3194 x_msg_count OUT NOCOPY NUMBER) IS --File.Sql.39 bug 4440895
3195
3196 l_resource_rec_old PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
3197 l_resource_rec_new PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
3198
3199 l_return_status VARCHAR2(1);
3200
3201 l_invol_term VARCHAR2(1); --bug 5683340
3202
3203 l_count NUMBER ; -- bug 7147575
3204
3205 CURSOR res_denorm_recs IS
3206 SELECT resource_effective_start_date,
3207 resource_effective_end_date
3208 FROM pa_resources_denorm
3209 WHERE person_id = p_person_id
3210 -- AND p_new_end_date >= resource_effective_start_date
3211 AND resource_effective_start_date >= p_old_start_date
3212 AND resource_effective_end_date <= p_old_end_date
3213 ;
3214
3215 --Bug 9838014 Start
3216 CURSOR get_max_end_date_term(p_person_id IN NUMBER) IS
3217 SELECT MAX (asgn_end_date) FROM
3218 (select max(res.assignment_end_date) asgn_end_date
3219 from pa_r_project_resources_v res
3220 where res.person_id = p_person_id
3221 and res.assignment_end_date IS NOT NULL
3222 UNION
3223 select max(res.assignment_end_date) ass_end_date
3224 from pa_r_project_resources_term_v res
3225 where res.person_id = p_person_id
3226 and res.assignment_end_date IS NOT NULL );
3227
3228 l_end_date DATE;
3229 --Bug 9838014 End
3230
3231 -- Bug 8791391
3232 l_resource_effective_end_date per_all_assignments_f.effective_end_date%TYPE ;
3233 l_withdraw_nom_flag VARCHAR2(1) :='Y';
3234
3235 -- Bug 9704139
3236 l_candidate_terminated VARCHAR2(3) := 'N';
3237
3238 BEGIN
3239
3240 --dbms_output.put_line('Inside Update End Date');
3241 --dbms_output.put_line('Person Id:' || p_person_id);
3242 --dbms_output.put_line('New End Date:' || p_new_end_date);
3243
3244 -- Initialize the Error stack
3245 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.Update_EndDate');
3246 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
3247
3248 l_count := 0; -- bug 7147575 : None records in pa_resources_denorm so far.
3249
3250 FOR rec IN res_denorm_recs LOOP
3251
3252 /*Bug 9838014 Start
3253 l_count := l_count + 1 ; -- bug 7147575 :this means that there was atleast one record in pa_resources_denorm
3254
3255 --dbms_output.put_line('resource_effective_start_date:' || rec.resource_effective_start_date);
3256 --dbms_output.put_line('resource_effective_end_date:' || rec.resource_effective_end_date);
3257
3258
3259 -- Bug 4668272 - added case of p_new_end_date >
3260 -- rec.resource_effective_end_date - this case occurs when a
3261 -- reverse termination happens in HR.
3262 -- IF p_new_end_date BETWEEN rec.resource_effective_start_date AND rec.resource_effective_end_date THEN
3263 IF (p_new_end_date BETWEEN rec.resource_effective_start_date AND
3264 rec.resource_effective_end_date) OR
3265 (p_new_end_date > rec.resource_effective_end_date) THEN Bug 9838014 End */
3266
3267 --Bug 9838014 Start
3268 IF ((p_new_end_date BETWEEN rec.resource_effective_start_date AND rec.resource_effective_end_date)
3269 AND trunc(rec.resource_effective_end_date) <> trunc(p_new_end_date)) OR
3270 (p_new_end_date > rec.resource_effective_end_date AND trunc(p_old_end_date) = trunc(rec.resource_effective_end_date)) THEN
3271
3272 l_count := l_count + 1 ;
3273 --Bug 9838014 End
3274
3275 --End date this record
3276 --Set the values for the Resources Denorm Record Type
3277
3278 l_resource_rec_old.person_id := p_person_id;
3279 l_resource_rec_new.person_id := p_person_id;
3280
3281 l_resource_rec_old.resource_effective_start_date := rec.resource_effective_start_date;
3282 l_resource_rec_new.resource_effective_start_date := rec.resource_effective_start_date;
3283
3284 l_resource_rec_old.resource_effective_end_date := rec.resource_effective_end_date;
3285 l_resource_rec_new.resource_effective_end_date := p_new_end_date;
3286
3287 --Call Resource Denorm API
3288 PA_RESOURCE_PVT.update_resource_denorm(
3289 p_resource_denorm_old_rec => l_resource_rec_old
3290 ,p_resource_denorm_new_rec => l_resource_rec_new
3291 ,x_return_status => l_return_status
3292 ,x_msg_data => x_msg_data
3293 ,x_msg_count => x_msg_count);
3294
3295 IF l_return_status = FND_API.G_RET_STS_ERROR THEN
3296 x_return_status := FND_API.G_RET_STS_ERROR ;
3297 END IF;
3298
3299 ELSIF p_new_end_date < rec.resource_effective_start_date THEN
3300 --Bug 9838014 Start
3301 OPEN get_max_end_date_term(p_person_id);
3302 FETCH get_max_end_date_term INTO l_end_date;
3303 CLOSE get_max_end_date_term;
3304
3305 IF rec.resource_effective_start_date > l_end_date THEN
3306 l_count := l_count + 1;
3307 --Bug 9838014 End
3308
3309 --Delete this record
3310 pa_resource_pvt.delete_resource_denorm(
3311 p_person_id => p_person_id
3312 ,p_res_effective_start_date => rec.resource_effective_start_date
3313 ,x_return_status => l_return_status
3314 ,x_msg_data => x_msg_data
3315 ,x_msg_count => x_msg_count);
3316
3317 END IF; --Bug 9838014
3318
3319 IF l_return_status = FND_API.G_RET_STS_ERROR THEN
3320 x_return_status := FND_API.G_RET_STS_ERROR ;
3321 END IF;
3322
3323 END IF;
3324
3325 END LOOP; --end FOR
3326
3327 IF (l_count > 0 ) THEN -- bug 7147575 : so now on, only if records are there in pa_resources_denorm, then only further code will get executed.
3328
3329 /*Call added for bug 5683340*/
3330 pa_resource_utils.init_fte_sync_wf( p_person_id => p_person_id,
3331 x_invol_term => l_invol_term,
3332 x_return_status => l_return_status,
3333 x_msg_data => x_msg_data,
3334 x_msg_count => x_msg_count);
3335
3336 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
3337 x_return_status := FND_API.G_RET_STS_ERROR ;
3338 END IF ;
3339
3340 /*if block added for bug 5683340*/
3341 IF ((l_invol_term = 'N') AND (l_return_status = FND_API.G_RET_STS_SUCCESS)) THEN
3342
3343 --Call Forecast Item regeneration API
3344 --to fix forecast data after resource was end_dated
3345 --start_date passed is the date when it changes
3346 PA_FORECASTITEM_PVT.Create_Forecast_Item(
3347 p_person_id => p_person_id,
3348 --p_start_date => p_new_end_date+1, p_old_end_date Bug 6120875
3349 p_start_date => Least(p_new_end_date+1, p_old_end_date+1),
3350 p_end_date => null,
3351 p_process_mode => 'GENERATE',
3352 x_return_status => l_return_status,
3353 x_msg_count => x_msg_count,
3354 x_msg_data => x_msg_data) ;
3355
3356 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
3357 x_return_status := FND_API.G_RET_STS_ERROR ;
3358 END IF;
3359
3360
3361 -- Bug 8791391
3362 -- Candidancy should be withdrawn only if end dates have been modified
3363 -- It shouldnt get called when assignments are modified in update mode
3364 -- which causes in creation of new row and updation of teh endate of the
3365 -- existing row.
3366
3367 /*
3368 SELECT MAX(paaf.effective_end_date)
3369 INTO l_resource_effective_end_date
3370 FROM per_all_assignments_f paaf,
3371 per_assignment_status_types past
3372 WHERE paaf.person_id=p_person_id
3373 AND paaf.primary_flag = 'Y'
3374 AND paaf.assignment_type in ('E','C')
3375 AND past.assignment_status_type_id = paaf.assignment_status_type_id
3376 AND past.per_system_status in ('ACTIVE_ASSIGN','ACTIVE_CWK');
3377 */
3378
3379 -- Bug 9704139
3380 -- Use this new query to find candidate assignment end date
3381 -- If no record found then candidate is terminated
3382 -- Withdraw candidacies if the candidate is still in HR but moved org and
3383 -- no longer eligible for PJR (OR) if the candidate is terminated.
3384 BEGIN
3385
3386 SELECT max(assignment_end_date)
3387 INTO l_resource_effective_end_date
3388 FROM pa_r_project_resources_v
3389 WHERE person_id = p_person_id;
3390
3391 EXCEPTION
3392 WHEN NO_DATA_FOUND THEN
3393 -- withdraw the candidacy if the record is not found in select as the candidate is terminated
3394 l_withdraw_nom_flag := 'Y';
3395 l_candidate_terminated := 'Y';
3396
3397 END;
3398
3399 -- Bug 9704139
3400 -- check if already terminated, if not then do the below
3401 IF l_candidate_terminated = 'N' THEN
3402 -- Withdraw only when end-date is equal to the person's max effective end date.
3403 IF trunc(p_new_end_date) = trunc(l_resource_effective_end_date) THEN
3404 l_withdraw_nom_flag := 'Y';
3405 ELSE
3406 l_withdraw_nom_flag := 'N';
3407 END IF;
3408 END IF;
3409
3410
3411 -- Call this procedure to withdraw any active candidacy of this
3412 -- person in PJR whenever the person is end dated (due to termination
3413 -- or the organization no longer belong to Exp Hier)
3414 IF l_withdraw_nom_flag = 'Y' THEN --Bug 8791391
3415 withdraw_cand_nominations
3416 ( p_person_id => p_person_id,
3417 p_effective_date => p_new_end_date,
3418 x_return_status => l_return_status,
3419 x_msg_count => x_msg_count,
3420 x_msg_data => x_msg_data);
3421 END IF;
3422
3423 -- reset the Error stack
3424
3425 END IF ; --((l_invol_term = 'N') AND (l_return_status = FND_API.G_RET_STS_SUCCESS)) bug 5683340
3426
3427 END IF ; -- bug 7147575 : IF (l_count > 0 )
3428
3429 PA_DEBUG.Reset_Err_Stack;
3430
3431 EXCEPTION
3432
3433 WHEN NO_DATA_FOUND THEN
3434 x_return_status := FND_API.G_RET_STS_ERROR ;
3435
3436 WHEN OTHERS THEN
3437 -- 4537865 : RESET x_msg_count and x_msg_data also
3438 x_msg_count := 1 ;
3439 x_msg_data := SUBSTRB(SQLERRM ,1,240);
3440 -- Set the exception Message and the stack
3441 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.Update_EndDate'
3442 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
3443 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
3444 raise;
3445 END Update_EndDate;
3446
3447 /* Procedure Update_Org calls Update_Resource_Denorm and Create_Forecast_Item to update the organization and org_id for the resources in pa_resources_denorm table and regenerate forecast items for the resource respectively.
3448 */
3449 PROCEDURE Update_Org(
3450 p_person_id IN per_all_people_f.person_id%TYPE,
3451 p_old_org_id IN per_all_assignments_f.organization_id%TYPE,
3452 p_new_org_id IN per_all_assignments_f.organization_id%TYPE,
3453 p_old_start_date IN per_all_assignments_f.effective_start_date%TYPE,
3454 p_new_start_date IN per_all_assignments_f.effective_end_date%TYPE,
3455 p_old_end_date IN per_all_assignments_f.effective_start_date%TYPE,
3456 p_new_end_date IN per_all_assignments_f.effective_end_date%TYPE,
3457 x_return_status OUT NOCOPY VARCHAR2, --File.Sql.39 bug 4440895
3458 x_msg_data OUT NOCOPY VARCHAR2, --File.Sql.39 bug 4440895
3459 x_msg_count OUT NOCOPY NUMBER) IS --File.Sql.39 bug 4440895
3460
3461 l_default_ou_old pa_resources_denorm.resource_org_id%TYPE;
3462 l_default_ou_new pa_resources_denorm.resource_org_id%TYPE;
3463
3464 l_resource_rec_old PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
3465 l_resource_rec_new PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
3466
3467 l_return_status VARCHAR2(1);
3468 l_org_type VARCHAR2(20);
3469 l_resource_id NUMBER(15);
3470
3471
3472 -- Cursor to get all denormalized resource records
3473 -- for this HR assignment
3474 CURSOR res_denorm_recs IS
3475 SELECT resource_effective_start_date,
3476 resource_effective_end_date
3477 FROM pa_resources_denorm
3478 WHERE person_id = p_person_id
3479 AND resource_effective_start_date >= p_new_start_date
3480 AND resource_effective_end_date <= p_new_end_date
3481 ;
3482
3483 -- CURSOR to check whether it is a Multi or Single Org Implementation
3484 --MOAC Changes : Bug 4363092: Get the value of current org from PA_MOAC_UTILS.GET_CURRENT_ORG_ID
3485 /* CURSOR check_org_type IS
3486 select decode(substr(USERENV('CLIENT_INFO'),1,1),
3487 ' ', NULL,
3488 substr(USERENV('CLIENT_INFO'),1,10)) org from dual; */
3489
3490 BEGIN
3491
3492 --dbms_output.put_line('Inside Update Org');
3493
3494 -- Initialize the Error stack
3495 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.Update_Org');
3496
3497 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
3498
3499 /* Check if new organization belongs to an expenditure
3500 organization, if yes then get default ou for old and new organization
3501 and update pa_resource_ou.organization.*/
3502
3503 IF (Belongs_ExpOrg(p_new_org_id) = 'Y') THEN
3504
3505 -- If the old org Id does not belong to exp hier,
3506 -- we have to fix data in resource denorm (we end dated that
3507 -- record previously when the org changes from Exp Hier
3508 -- to Non Exp Hier). So calling Create_Resource
3509 IF(Belongs_ExpOrg(p_old_org_id) = 'N') THEN
3510
3511 pa_r_project_resources_pub.create_resource (
3512 p_api_version => 1.0
3513 ,p_init_msg_list => NULL
3514 ,p_commit => FND_API.G_FALSE
3515 ,p_validate_only => NULL
3516 ,p_max_msg_count => NULL
3517 ,p_internal => 'Y'
3518 ,p_person_id => p_person_id
3519 ,p_individual => 'Y'
3520 ,p_resource_type => NULL
3521 ,x_return_status => l_return_status
3522 ,x_msg_count => x_msg_count
3523 ,x_msg_data => x_msg_data
3524 ,x_resource_id => l_resource_id);
3525
3526
3527 -- call this procedure to update the forecast data for
3528 -- assigned time ONLY for this resource
3529 -- pass null to start date and end date
3530 -- this is called only if create_resource is a success
3531 if (l_return_status = 'S' and l_resource_id is not null) then
3532 PA_FORECASTITEM_PVT.Create_Forecast_Item(
3533 p_person_id => p_person_id
3534 ,p_start_date => null
3535 ,p_end_date => null
3536 ,p_process_mode => 'GENERATE_ASGMT'
3537 ,x_return_status => l_return_status
3538 ,x_msg_count => x_msg_count
3539 ,x_msg_data => x_msg_data
3540 ) ;
3541 end if;
3542
3543 ELSE
3544
3545 l_default_ou_old := Get_DefaultOU(p_old_org_id);
3546 l_default_ou_new := Get_DefaultOU(p_new_org_id);
3547
3548 IF (l_default_ou_new = -999) THEN
3549 /* Bug 4363092: Commenting this check as R12 will be multi org only */
3550 -- OPEN check_org_type;
3551 -- FETCH check_org_type into l_org_type;
3552 -- CLOSE check_org_type;
3553
3554 -- case for Multi-Org: no OU - so set return status
3555 -- to error and return
3556 -- IF l_org_type IS NOT NULL THEN
3557 PA_UTILS.Add_Message(
3558 p_app_short_name => 'PA'
3559 ,p_msg_name => 'PA_RS_DEF_OU_NULL');
3560
3561 x_msg_data := 'PA_RS_DEF_OU_NULL';
3562 X_RETURN_STATUS := FND_API.G_RET_STS_ERROR;
3563 RETURN;
3564 -- ELSE
3565 -- l_default_ou_new := NULL;
3566 -- END IF;
3567
3568 END IF;
3569
3570 --Set the values for the Resources Denorm Record Type
3571 l_resource_rec_old.person_id := p_person_id;
3572 l_resource_rec_new.person_id := p_person_id;
3573
3574 l_resource_rec_old.resource_org_id := l_default_ou_old;
3575 l_resource_rec_new.resource_org_id := l_default_ou_new;
3576
3577 l_resource_rec_old.resource_organization_id := p_old_org_id;
3578 l_resource_rec_new.resource_organization_id := p_new_org_id;
3579
3580 FOR rec IN res_denorm_recs LOOP
3581
3582 l_resource_rec_old.resource_effective_start_date := rec.resource_effective_start_date;
3583 l_resource_rec_new.resource_effective_start_date := rec.resource_effective_start_date;
3584
3585 l_resource_rec_old.resource_effective_end_date := rec.resource_effective_end_date;
3586 l_resource_rec_new.resource_effective_end_date := rec.resource_effective_end_date;
3587
3588 --Call Resource Denorm API
3589 PA_RESOURCE_PVT.update_resource_denorm(
3590 p_resource_denorm_old_rec => l_resource_rec_old
3591 ,p_resource_denorm_new_rec => l_resource_rec_new
3592 ,x_return_status => l_return_status
3593 ,x_msg_data => x_msg_data
3594 ,x_msg_count => x_msg_count);
3595
3596 IF l_return_status = FND_API.G_RET_STS_ERROR THEN
3597 x_return_status := FND_API.G_RET_STS_ERROR ;
3598 END IF;
3599
3600 END LOOP; --end FOR
3601
3602 --Bug 7690398 put an if condition for the resource id
3603 IF (pa_resource_utils.get_resource_id(p_person_id) <> -999) THEN
3604 --Call Forecast Item regeneration API
3605 PA_FORECASTITEM_PVT.Create_Forecast_Item(
3606 p_person_id => p_person_id,
3607 p_start_date => p_new_start_date,
3608 p_end_date => p_new_end_date,
3609 p_process_mode => 'GENERATE',
3610 x_return_status => l_return_status,
3611 x_msg_count => x_msg_count,
3612 x_msg_data => x_msg_data) ;
3613
3614 END IF;
3615
3616 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
3617 x_return_status := FND_API.G_RET_STS_ERROR ;
3618 END IF;
3619 END IF; -- Bug 7690398
3620 ELSE
3621 /* In case the organization does not belong to expenditure
3622 hierarchy the record in pa_resource_denorm must be end dated*/
3623
3624 Update_EndDate(
3625 p_person_id => p_person_id,
3626 p_old_start_date => p_old_start_date,
3627 p_new_start_date => p_new_start_date,
3628 p_old_end_date => p_old_end_date,
3629 p_new_end_date => sysdate,
3630 x_return_status => l_return_status,
3631 x_msg_data => x_msg_data,
3632 x_msg_count => x_msg_count);
3633
3634 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
3635 x_return_status := FND_API.G_RET_STS_ERROR ;
3636 END IF;
3637
3638 END IF;
3639
3640
3641 -- reset the Error stack
3642 PA_DEBUG.Reset_Err_Stack;
3643
3644 EXCEPTION
3645 WHEN NO_DATA_FOUND THEN
3646 X_RETURN_STATUS := fnd_api.g_ret_sts_error;
3647
3648 WHEN OTHERS THEN
3649 -- 4537865 : RESET x_msg_count and x_msg_data also
3650 x_msg_count := 1 ;
3651 x_msg_data := SUBSTRB(SQLERRM ,1,240);
3652 -- Set the exception Message and the stack
3653 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.Update_Org'
3654 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
3655 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
3656 raise;
3657 END Update_Org;
3658
3659 -- Start Bug : 4656855
3660 /* Function check_pjr_default_ou checks if org_id in pa_all_organizations = the PJR default operating unit */
3661 FUNCTION check_pjr_default_ou(P_Organization_id IN Hr_Organization_Information.Organization_id%type, P_Default_OU_new IN Hr_Organization_Information.Org_Information1%type)
3662 RETURN VARCHAR2 IS
3663 -- This function returns 'Y' if org_id in pa_all_organizations = the PJR default operating unit
3664 -- otherwise , it returns 'N'
3665
3666 CURSOR c_check_pjr_default_ou IS
3667 SELECT 'Y' FROM dual WHERE exists
3668 (SELECT 'Y' FROM hr_organization_information
3669 WHERE organization_id = P_Organization_id
3670 and org_information_context = 'Exp Organization Defaults'
3671 and org_information1 = P_Default_OU_new);
3672
3673 l_dummy VARCHAR2(1);
3674 BEGIN
3675 OPEN c_check_pjr_default_ou;
3676 FETCH c_check_pjr_default_ou INTO l_dummy;
3677
3678 IF c_check_pjr_default_ou%NOTFOUND THEN
3679 CLOSE c_check_pjr_default_ou; -- Bug 5336837
3680 RETURN 'N';
3681 ELSE
3682 CLOSE c_check_pjr_default_ou; -- Bug 5336837
3683 RETURN 'Y';
3684 END IF;
3685
3686 -- CLOSE c_check_pjr_default_ou; -- Bug 5336837
3687 EXCEPTION
3688 WHEN OTHERS THEN
3689 -- Bug 5336837
3690 IF c_check_pjr_default_ou%ISOPEN THEN
3691 CLOSE c_check_pjr_default_ou ;
3692 END IF;
3693
3694 return 'N';
3695 END check_pjr_default_ou;
3696 -- End Bug : 4656855
3697
3698 /* Function Belongs_ExpOrg checks if the given organization belongs to
3699 an expenditure/event organization
3700 */
3701 FUNCTION Belongs_ExpOrg(p_org_id IN per_all_assignments_f.organization_id%TYPE)
3702 RETURN VARCHAR2 IS
3703 -- This function returns 'Y' if a given org is a Exp organization ,
3704 -- otherwise , it returns 'N'
3705
3706 CURSOR c_exp_org IS
3707 SELECT 'x'
3708 FROM dual
3709 WHERE exists
3710 (select organization_id
3711 FROM pa_all_organizations
3712 WHERE organization_id = p_org_id
3713 AND inactive_date is null
3714 AND pa_org_use_type = 'EXPENDITURES');
3715
3716 l_dummy VARCHAR2(1);
3717 BEGIN
3718 OPEN c_exp_org;
3719 FETCH c_exp_org INTO l_dummy;
3720
3721 IF c_exp_org%NOTFOUND THEN
3722 CLOSE c_exp_org; -- Bug 5336837
3723 RETURN 'N';
3724 ELSE
3725 CLOSE c_exp_org; -- Bug 5336837
3726 RETURN 'Y';
3727 END IF;
3728
3729 -- CLOSE c_exp_org; -- Bug 5336837
3730 EXCEPTION
3731 WHEN OTHERS THEN
3732 -- Bug 5336837
3733 IF c_exp_org%ISOPEN THEN
3734 CLOSE c_exp_org ;
3735 END IF;
3736
3737 return 'N';
3738 END Belongs_ExpOrg;
3739
3740 /* Function Get_DefaultOU returns the default OU for the given organization.
3741 */
3742 FUNCTION Get_DefaultOU(p_org_id IN per_all_assignments_f.organization_id%TYPE)
3743 RETURN NUMBER IS
3744 l_default_ou number;
3745 BEGIN
3746 select to_number(org_information1)
3747 into l_default_ou
3748 from hr_organization_information
3749 where organization_id = p_org_id
3750 and org_information_context = 'Exp Organization Defaults';
3751
3752 if l_default_ou is null then
3753 l_default_ou := -999;
3754 end if;
3755
3756 return l_default_ou;
3757 EXCEPTION
3758 WHEN OTHERS THEN
3759 return -999;
3760 END Get_DefaultOU;
3761
3762 /*
3763 Procedure Update_Job retrieves the job level for the job and calls
3764 Update_Resource_Denorm and Create_Forecast_Item to update the denorm
3765 table and regenerate forecast items for the resource respectively.
3766 */
3767 PROCEDURE Update_Job(
3768 p_person_id IN per_all_people_f.person_id%TYPE,
3769 p_old_job IN per_all_assignments_f.job_id%TYPE,
3770 p_new_job IN per_all_assignments_f.job_id%TYPE,
3771 p_new_start_date IN per_all_assignments_f.effective_start_date%TYPE,
3772 p_new_end_date IN per_all_assignments_f.effective_end_date%TYPE,
3773 x_return_status OUT NOCOPY VARCHAR2, --File.Sql.39 bug 4440895
3774 x_msg_data OUT NOCOPY VARCHAR2, --File.Sql.39 bug 4440895
3775 x_msg_count OUT NOCOPY NUMBER) IS --File.Sql.39 bug 4440895
3776
3777 l_resource_rec_old PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
3778 l_resource_rec_new PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
3779 l_return_status VARCHAR2(1);
3780 l_resource_id NUMBER;
3781 l_resource_start_date DATE;
3782 l_resource_end_date DATE;
3783 l_old_job_group_id per_job_groups.job_group_id%type;
3784 l_new_job_group_id per_job_groups.job_group_id%type;
3785 l_old_job_level NUMBER;
3786 l_new_job_level NUMBER;
3787 l_old_job_billable pa_resources_denorm.billable_flag%type;
3788 l_new_job_billable pa_resources_denorm.billable_flag%type;
3789 l_old_job_utilizable pa_resources_denorm.utilization_flag%type;
3790 l_new_job_utilizable pa_resources_denorm.utilization_flag%type;
3791 l_old_job_schedulable pa_resources_denorm.schedulable_flag%type;
3792 l_new_job_schedulable pa_resources_denorm.schedulable_flag%type;
3793 P_DEBUG_MODE VARCHAR2(1) := NVL(FND_PROFILE.value('PA_DEBUG_MODE'), 'N');
3794
3795 -- Cursor to get all denormalized resource records
3796 -- for this HR assignment
3797 CURSOR res_denorm_recs IS
3798 SELECT resource_effective_start_date,
3799 resource_effective_end_date
3800 FROM pa_resources_denorm
3801 WHERE person_id = p_person_id
3802 AND resource_effective_start_date >= p_new_start_date
3803 AND resource_effective_end_date <= p_new_end_date;
3804 --Bug 9047714 Start
3805 /*CURSOR min_max_res_dates IS
3806 SELECT min(resource_effective_start_date) resource_effective_start_date,
3807 max(resource_effective_end_date) resource_effective_end_date
3808 FROM pa_resources_denorm
3809 WHERE job_id = p_old_job
3810 AND person_id = p_person_id
3811 GROUP BY person_id;*/
3812 CURSOR min_max_res_dates IS
3813 SELECT min(resource_effective_start_date) resource_effective_start_date,
3814 max(resource_effective_end_date) resource_effective_end_date
3815 FROM pa_resources_denorm
3816 WHERE job_id = p_old_job
3817 AND person_id = p_person_id
3818 AND resource_effective_end_date = (Select max(resource_effective_end_date)
3819 from pa_resources_denorm rd2
3820 where rd2.job_id = p_old_job
3821 AND rd2.person_id = p_person_id
3822 AND (rd2.resource_effective_end_date >= sysdate OR rd2.resource_effective_end_date is null))
3823 GROUP BY person_id;
3824 --Bug 9047714 End
3825
3826 BEGIN
3827 -- Initialize the Error stack
3828 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.Update_Job');
3829 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
3830 IF P_DEBUG_MODE = 'Y' THEN
3831 log_message('beginning of Update_Job');
3832 END IF;
3833
3834 --Get the job group id for the old and new job
3835 l_old_job_group_id := get_job_group_id(p_old_job);
3836 l_new_job_group_id := get_job_group_id(p_new_job);
3837
3838 --Get the old/new job level and job flags
3839 l_old_job_level := get_job_level(P_job_id => p_old_job,
3840 P_job_group_id => l_old_job_group_id);
3841 l_new_job_level := get_job_level(P_job_id => p_new_job,
3842 P_job_group_id => l_new_job_group_id);
3843 l_old_job_billable := check_job_billability(P_job_id => p_old_job,
3844 P_person_id => NULL,
3845 p_date => NULL );
3846 l_new_job_billable := check_job_billability(P_job_id => p_new_job,
3847 P_person_id => NULL,
3848 p_date => NULL );
3849 l_old_job_utilizable := check_job_utilization(P_job_id => p_old_job,
3850 P_person_id => NULL,
3851 p_date => NULL );
3852 l_new_job_utilizable := check_job_utilization(P_job_id => p_new_job,
3853 P_person_id => NULL,
3854 p_date => NULL );
3855 l_old_job_schedulable := check_job_schedulable(P_job_id => p_old_job);
3856 l_new_job_schedulable := check_job_schedulable(P_job_id => p_new_job);
3857
3858 ------------------------------------------------------------------
3859 -- If old job's util_flag=N and new job's util_flag=Y, we need to
3860 -- pull the person.
3861 ------------------------------------------------------------------
3862 IF l_old_job_utilizable='N' AND l_new_job_utilizable='Y' THEN
3863 IF P_DEBUG_MODE = 'Y' THEN
3864 log_message('pull the person_Id = ' || p_person_id);
3865 END IF;
3866
3867 PA_R_PROJECT_RESOURCES_PUB.CREATE_RESOURCE (
3868 p_api_version => 1.0
3869 ,p_commit => FND_API.G_FALSE
3870 ,p_validate_only => FND_API.G_FALSE
3871 ,p_internal => 'Y'
3872 ,p_person_id => p_person_id
3873 ,p_individual => 'Y'
3874 ,p_resource_type => 'EMPLOYEE'
3875 ,x_resource_id => l_resource_id
3876 ,x_return_status => x_return_status
3877 ,x_msg_count => x_msg_count
3878 ,x_msg_data => x_msg_data );
3879
3880 ------------------------------------------------------------------
3881 -- If old util_flag=Y and new_util_flag=N, end date the resource
3882 ------------------------------------------------------------------
3883 ELSIF l_old_job_utilizable='Y' AND l_new_job_utilizable='N' THEN
3884 OPEN min_max_res_dates;
3885 FETCH min_max_res_dates INTO l_resource_start_date, l_resource_end_date;
3886 CLOSE min_max_res_dates;
3887
3888 IF P_DEBUG_MODE = 'Y' THEN
3889 log_message('person Id = ' || p_person_id ||' ,start_date: ' ||
3890 l_resource_start_date || ', end_date: '||l_resource_end_date );
3891 END IF;
3892
3893 Update_EndDate
3894 (p_person_id => p_person_id,
3895 p_old_start_date => l_resource_start_date,
3896 p_new_start_date => l_resource_start_date,
3897 p_old_end_date => l_resource_end_date,
3898 p_new_end_date => sysdate,
3899 x_return_status => x_return_status,
3900 x_msg_count => x_msg_count,
3901 x_msg_data => x_msg_data);
3902
3903 IF P_DEBUG_MODE = 'Y' THEN
3904 log_message('Return status from Update_EndDate = ' || x_return_status);
3905 END IF;
3906
3907 ------------------------------------------------------------------
3908 -- If old util_flag=new util_flag, just update job flags
3909 ------------------------------------------------------------------
3910 ELSE
3911 --Set the values for the Resources Denorm Record Type
3912 l_resource_rec_old.person_id := p_person_id;
3913 l_resource_rec_new.person_id := p_person_id;
3914 l_resource_rec_old.job_id := p_old_job;
3915 l_resource_rec_new.job_id := p_new_job;
3916 l_resource_rec_old.resource_job_level := l_old_job_level;
3917 l_resource_rec_new.resource_job_level := l_new_job_level;
3918 l_resource_rec_old.billable_flag := l_old_job_billable;
3919 l_resource_rec_new.billable_flag := l_new_job_billable;
3920 l_resource_rec_old.utilization_flag := l_old_job_utilizable;
3921 l_resource_rec_new.utilization_flag := l_new_job_utilizable;
3922 l_resource_rec_old.schedulable_flag := l_old_job_schedulable;
3923 l_resource_rec_new.schedulable_flag := l_new_job_schedulable;
3924
3925 -- loop through all record of the person in pa_resources_denorm and update
3926 -- the job flags
3927 FOR rec IN res_denorm_recs LOOP
3928 l_resource_rec_new.resource_effective_start_date := rec.resource_effective_start_date;
3929 l_resource_rec_new.resource_effective_end_date := rec.resource_effective_end_date;
3930 IF P_DEBUG_MODE = 'Y' THEN
3931 log_message('start_date:'||rec.resource_effective_start_date||', end_Date:'||
3932 rec.resource_effective_end_date);
3933 END IF;
3934
3935 PA_RESOURCE_PVT.update_resource_denorm(
3936 p_resource_denorm_old_rec => l_resource_rec_old
3937 ,p_resource_denorm_new_rec => l_resource_rec_new
3938 ,x_return_status => l_return_status
3939 ,x_msg_data => x_msg_data
3940 ,x_msg_count => x_msg_count);
3941
3942 IF l_return_status = FND_API.G_RET_STS_ERROR THEN
3943 x_return_status := FND_API.G_RET_STS_ERROR ;
3944 END IF;
3945 END LOOP;
3946
3947 END IF;
3948
3949 IF P_DEBUG_MODE = 'Y' THEN
3950 log_message('before calling Create_Forecast_Item');
3951 END IF;
3952 --Call Forecast Item regeneration API
3953 --Bug 7690398 put an if condition for the resource id
3954 IF (pa_resource_utils.get_resource_id(p_person_id) <> -999) THEN
3955 PA_FORECASTITEM_PVT.Create_Forecast_Item(
3956 p_person_id => p_person_id,
3957 p_start_date => p_new_start_date,
3958 p_end_date => p_new_end_date,
3959 p_process_mode => 'GENERATE',
3960 x_return_status => l_return_status,
3961 x_msg_count => x_msg_count,
3962 x_msg_data => x_msg_data) ;
3963
3964 IF P_DEBUG_MODE = 'Y' THEN
3965 log_message('after calling Create_Forecast_Item, l_return_status:'||l_return_status);
3966 END IF;
3967 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
3968 x_return_status := FND_API.G_RET_STS_ERROR ;
3969 END IF;
3970 END IF; --Bug 7690398
3971 -- reset the Error stack
3972 PA_DEBUG.Reset_Err_Stack;
3973
3974 EXCEPTION
3975 WHEN OTHERS THEN
3976 IF P_DEBUG_MODE = 'Y' THEN
3977 log_message('exception was thrown');
3978 END IF;
3979 -- 4537865 : RESET x_msg_count and x_msg_data also
3980 x_msg_count := 1 ;
3981 x_msg_data := SUBSTRB(SQLERRM ,1,240);
3982 -- Set the exception Message and the stack
3983 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.Update_Job'
3984 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
3985 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
3986 RAISE;
3987 END Update_Job;
3988
3989 /* Procedure Update_Supervisor calls Update_Resource_Denorm to update
3990 the resource's supervisor in the denorm table.
3991 */
3992 PROCEDURE Update_Supervisor(
3993 p_person_id IN per_all_people_f.person_id%TYPE,
3994 p_old_supervisor IN per_all_assignments_f.supervisor_id%TYPE,
3995 p_new_supervisor IN per_all_assignments_f.supervisor_id%TYPE,
3996 p_new_start_date IN per_all_assignments_f.effective_start_date%TYPE,
3997 p_new_end_date IN per_all_assignments_f.effective_end_date%TYPE,
3998 x_return_status OUT NOCOPY VARCHAR2, --File.Sql.39 bug 4440895
3999 x_msg_data OUT NOCOPY VARCHAR2, --File.Sql.39 bug 4440895
4000 x_msg_count OUT NOCOPY NUMBER) IS --File.Sql.39 bug 4440895
4001
4002 l_resource_rec_old PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
4003 l_resource_rec_new PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
4004
4005 l_return_status VARCHAR2(1);
4006 l_manager_name pa_resources_denorm.manager_name%TYPE;
4007
4008 CURSOR res_denorm_recs IS
4009 SELECT resource_effective_start_date,
4010 resource_effective_end_date
4011 FROM pa_resources_denorm
4012 WHERE person_id = p_person_id
4013 AND p_new_end_date >= resource_effective_start_date
4014 AND resource_effective_start_date >= p_new_start_date
4015 AND resource_effective_end_date <= p_new_end_date
4016 ;
4017
4018 CURSOR manager_name IS
4019 SELECT DISTINCT resource_name
4020 FROM pa_resources_denorm
4021 WHERE person_id = p_new_supervisor
4022 ;
4023
4024 BEGIN
4025
4026 -- Initialize the Error stack
4027 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.Update_Supervisor');
4028 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
4029
4030 --Set the values for the Resources Denorm Record Type
4031 l_resource_rec_old.person_id := p_person_id;
4032 l_resource_rec_new.person_id := p_person_id;
4033
4034 l_resource_rec_old.manager_id := p_old_supervisor;
4035 l_resource_rec_new.manager_id := p_new_supervisor;
4036
4037 OPEN manager_name;
4038 FETCH manager_name INTO l_manager_name;
4039 l_resource_rec_new.manager_name := l_manager_name;
4040 CLOSE manager_name;
4041
4042 FOR rec IN res_denorm_recs LOOP
4043
4044 l_resource_rec_new.resource_effective_start_date := rec.resource_effective_start_date;
4045
4046 --Call Resource Denorm API
4047 PA_RESOURCE_PVT.update_resource_denorm(
4048 p_resource_denorm_old_rec => l_resource_rec_old
4049 ,p_resource_denorm_new_rec => l_resource_rec_new
4050 ,x_return_status => l_return_status
4051 ,x_msg_data => x_msg_data
4052 ,x_msg_count => x_msg_count);
4053
4054 IF l_return_status = FND_API.G_RET_STS_ERROR THEN
4055 x_return_status := FND_API.G_RET_STS_ERROR ;
4056 END IF;
4057
4058 END LOOP;--end FOR
4059
4060 -- reset the Error stack
4061 PA_DEBUG.Reset_Err_Stack;
4062
4063 EXCEPTION
4064 WHEN OTHERS THEN
4065 -- 4537865 : RESET x_msg_count and x_msg_data also
4066 x_msg_count := 1 ;
4067 x_msg_data := SUBSTRB(SQLERRM ,1,240);
4068 -- Set the exception Message and the stack
4069 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.Update_Supervisor'
4070 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
4071 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
4072 raise;
4073 END Update_Supervisor;
4074
4075 /* Procedure Update_PrimaryFlag calls Update_EndDate to end date the
4076 record for which the assignment record's primary flag has changed form
4077 yes to no and then calls Create_Forecast_Item to regenerate
4078 the forecast items for this resource.
4079 */
4080 PROCEDURE Update_PrimaryFlag(
4081 p_person_id IN per_all_people_f.person_id%TYPE,
4082 p_old_start_date IN per_all_assignments_f.effective_start_date%TYPE,
4083 p_new_start_date IN per_all_assignments_f.effective_end_date%TYPE,
4084 p_old_end_date IN per_all_assignments_f.effective_start_date%TYPE,
4085 p_new_end_date IN per_all_assignments_f.effective_end_date%TYPE,
4086 x_return_status OUT NOCOPY VARCHAR2, --File.Sql.39 bug 4440895
4087 x_msg_data OUT NOCOPY VARCHAR2, --File.Sql.39 bug 4440895
4088 x_msg_count OUT NOCOPY NUMBER) IS --File.Sql.39 bug 4440895
4089
4090 l_return_status VARCHAR2(1);
4091
4092 BEGIN
4093 -- Initialize the Error stack
4094 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.Update_PrimaryFlag');
4095 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
4096
4097 --Call Update_EndDate to end date the resource_ou record.
4098 -- Commented the end date change in PA as this is not required
4099 -- Solves bug 1608837
4100 /* Update_EndDate(p_person_id => p_person_id,
4101 p_old_start_date => p_old_start_date,
4102 p_new_start_date => p_new_start_date,
4103 p_old_end_date => p_old_end_date,
4104 p_new_end_date => p_new_end_date,
4105 x_return_status => x_return_status,
4106 x_msg_data => x_msg_data,
4107 x_msg_count => x_msg_count);
4108 */
4109
4110 --Bug 9665238 put an if condition for the resource id
4111 IF (pa_resource_utils.get_resource_id(p_person_id) <> -999) THEN
4112 --Call Forecast Item regeneration API
4113 PA_FORECASTITEM_PVT.Create_Forecast_Item(
4114 p_person_id => p_person_id,
4115 p_start_date => p_new_start_date,
4116 p_end_date => p_new_end_date,
4117 p_process_mode => 'GENERATE',
4118 x_return_status => l_return_status,
4119 x_msg_count => x_msg_count,
4120 x_msg_data => x_msg_data) ;
4121 END IF;
4122
4123 IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
4124 x_return_status := FND_API.G_RET_STS_ERROR ;
4125 END IF;
4126
4127 -- reset the Error stack
4128 PA_DEBUG.Reset_Err_Stack;
4129
4130 EXCEPTION
4131 WHEN OTHERS THEN
4132 -- 4537865 : RESET x_msg_count and x_msg_data also
4133 x_msg_count := 1 ;
4134 x_msg_data := SUBSTRB(SQLERRM ,1,240);
4135 -- Set the exception Message and the stack
4136 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.Update_PrimaryFlag'
4137 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
4138 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
4139 raise;
4140 END Update_PrimaryFlag;
4141
4142 /* Procedure Update_Name calls updates the resource's name in pa_resources.
4143 */
4144 PROCEDURE Update_Name(
4145 p_person_id IN per_all_people_f.person_id%TYPE,
4146 p_old_name IN per_all_people_f.full_name%TYPE,
4147 p_new_name IN per_all_people_f.full_name%TYPE,
4148 x_return_status OUT NOCOPY VARCHAR2, --File.Sql.39 bug 4440895
4149 x_msg_data OUT NOCOPY VARCHAR2, --File.Sql.39 bug 4440895
4150 x_msg_count OUT NOCOPY NUMBER) IS --File.Sql.39 bug 4440895
4151
4152 l_resource_id pa_resources.resource_id%TYPE;
4153 l_return_status VARCHAR2(1);
4154
4155 l_resource_rec_old PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
4156 l_resource_rec_new PA_RESOURCE_PVT.Resource_Denorm_Rec_Type;
4157 BEGIN
4158
4159 --Initialize the Error stack
4160 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.Update_Name');
4161 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
4162
4163 --Get resource_id for person_id
4164 l_resource_id := pa_resource_utils.get_resource_id(p_person_id);
4165
4166 IF (l_resource_id = -999) THEN
4167 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
4168 return;
4169 END IF;
4170
4171 UPDATE pa_resources
4172 SET name = p_new_name
4173 WHERE resource_id = l_resource_id;
4174
4175 --Set the values for the Resources Denorm Record Type
4176 l_resource_rec_old.person_id := p_person_id;
4177 l_resource_rec_new.person_id := p_person_id;
4178
4179 l_resource_rec_old.resource_name := p_old_name;
4180 l_resource_rec_new.resource_name := p_new_name;
4181
4182 --Call Resource Denorm API
4183 PA_RESOURCE_PVT.update_resource_denorm(
4184 p_resource_denorm_old_rec => l_resource_rec_old
4185 ,p_resource_denorm_new_rec => l_resource_rec_new
4186 ,x_return_status => l_return_status
4187 ,x_msg_data => x_msg_data
4188 ,x_msg_count => x_msg_count);
4189
4190 IF l_return_status = FND_API.G_RET_STS_ERROR THEN
4191 x_return_status := FND_API.G_RET_STS_ERROR ;
4192 END IF;
4193
4194 --Reset the Error stack
4195 PA_DEBUG.Reset_Err_Stack;
4196
4197 EXCEPTION
4198 WHEN OTHERS THEN
4199 -- 4537865 : RESET x_msg_count and x_msg_data also
4200 x_msg_count := 1 ;
4201 x_msg_data := SUBSTRB(SQLERRM ,1,240);
4202 -- Set the exception Message and the stack
4203 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.Update_Name'
4204 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
4205 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
4206 raise;
4207 END Update_Name;
4208
4209
4210
4211 -- Procedure Address_Change Modified for location denormalization
4212 -- to update the pa_resource_denorm when person address changes with respect
4213 -- date
4214 PROCEDURE address_change ( p_calling_mode in varchar2,
4215 p_person_id in number,
4216 p_country_old in varchar2,
4217 p_country_new in varchar2,
4218 p_city_old in varchar2,
4219 p_city_new in varchar2,
4220 p_region2_old in varchar2,
4221 p_region2_new in varchar2,
4222 p_date_from_old in date,
4223 p_date_from_new in date,
4224 p_date_to_old in date,
4225 p_date_to_new in date,
4226 p_addr_prim_flag_old in varchar2,
4227 p_addr_prim_flag_new in varchar2,
4228 x_return_status out NOCOPY varchar2, --File.Sql.39 bug 4440895
4229 x_msg_count out NOCOPY number, --File.Sql.39 bug 4440895
4230 x_msg_data out NOCOPY varchar2) IS --File.Sql.39 bug 4440895
4231
4232 l_return_status VARCHAR2(1);
4233 l_resource_id NUMBER;
4234
4235 BEGIN
4236
4237
4238 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
4239
4240 IF p_addr_prim_flag_new = 'Y' THEN
4241
4242 --dbms_output.put_line('Inside address Update for person id:' || p_person_id);
4243
4244 pa_r_project_resources_pub.create_resource (
4245 p_api_version => 1.0
4246 ,p_init_msg_list => NULL
4247 ,p_commit => FND_API.G_FALSE
4248 ,p_validate_only => NULL
4249 ,p_max_msg_count => NULL
4250 ,p_internal => 'Y'
4251 ,p_person_id => p_person_id
4252 ,p_individual => 'Y'
4253 ,p_resource_type => 'EMPLOYEE'
4254 ,x_return_status => l_return_status
4255 ,x_msg_count => x_msg_count
4256 ,x_msg_data => x_msg_data
4257 ,x_resource_id => l_resource_id);
4258
4259 END IF;
4260
4261 --dbms_output.put_line('After address Update');
4262
4263 IF l_return_status = FND_API.G_RET_STS_ERROR THEN
4264 x_return_status := FND_API.G_RET_STS_ERROR ;
4265 END IF;
4266
4267 EXCEPTION
4268 when others then
4269 NULL;
4270 raise;
4271
4272 END address_change;
4273
4274 FUNCTION Get_Country_name(p_country_code VARCHAR2) RETURN VARCHAR2 IS
4275
4276 l_country_code VARCHAR2(240);
4277
4278 BEGIN
4279
4280 SELECT territory_short_name
4281 INTO l_country_code
4282 FROM fnd_territories_vl
4283 WHERE territory_code = p_country_code ;
4284
4285 RETURN l_country_code ;
4286 EXCEPTION
4287
4288 WHEN NO_DATA_FOUND THEN
4289 RETURN NULL;
4290
4291 WHEN OTHERS THEN
4292
4293 RAISE ;
4294
4295 END ;
4296
4297 FUNCTION get_job_name(P_job_id IN per_jobs.job_id%type)
4298 RETURN per_jobs.name%type IS
4299
4300 l_job_name varchar2(240);
4301
4302 BEGIN
4303
4304 SELECT name
4305 INTO l_job_name
4306 FROM per_jobs
4307 WHERE job_id = P_job_id;
4308
4309 RETURN (l_job_name) ;
4310 EXCEPTION
4311
4312 WHEN NO_DATA_FOUND THEN
4313 RETURN NULL;
4314
4315 WHEN OTHERS THEN
4316
4317 RAISE ;
4318
4319 END ;
4320
4321 FUNCTION get_org_name(P_org_id IN hr_all_organization_units.organization_id%type)
4322 RETURN hr_all_organization_units.name%type IS
4323 l_org_name varchar2(240);
4324
4325 BEGIN
4326
4327 SELECT name
4328 INTO l_org_name
4329 FROM hr_all_organization_units_tl
4330 WHERE organization_id = P_org_id
4331 AND language = USERENV('LANG');
4332
4333 RETURN (l_org_name) ;
4334 EXCEPTION
4335 WHEN NO_DATA_FOUND THEN
4336 RETURN NULL;
4337
4338 WHEN OTHERS THEN
4339 RAISE ;
4340 END ;
4341
4342 FUNCTION get_grade_name(P_grade_id IN NUMBER)
4343 RETURN VARCHAR2 IS
4344 l_grade_name varchar2(240);
4345
4346 BEGIN
4347 SELECT name
4348 INTO l_grade_name
4349 FROM per_grades
4350 WHERE grade_id = P_grade_id;
4351
4352 RETURN (l_grade_name) ;
4353 EXCEPTION
4354 WHEN NO_DATA_FOUND THEN
4355 RETURN NULL;
4356
4357 WHEN OTHERS THEN
4358 RAISE ;
4359 END ;
4360
4361 -- Added for bug 3957522
4362 -- Procedure to delete records in pa_resources_denorm
4363 PROCEDURE Delete_PA_Resource_Denorm(
4364 p_person_id IN per_all_people_f.person_id%TYPE,
4365 p_old_start_date IN per_all_assignments_f.effective_start_date%TYPE,
4366 p_old_end_date IN per_all_assignments_f.effective_end_date%TYPE,
4367 x_return_status OUT NOCOPY VARCHAR2, --File.Sql.39 bug 4440895
4368 x_msg_data OUT NOCOPY VARCHAR2, --File.Sql.39 bug 4440895
4369 x_msg_count OUT NOCOPY NUMBER) IS --File.Sql.39 bug 4440895
4370
4371
4372 CURSOR res_denorm_recs IS
4373 SELECT resource_effective_start_date,
4374 resource_effective_end_date
4375 FROM pa_resources_denorm
4376 WHERE person_id = p_person_id
4377 AND resource_effective_start_date >= p_old_start_date
4378 AND resource_effective_end_date <= p_old_end_date
4379 ;
4380
4381 BEGIN
4382 -- Initialize the Error stack
4383 PA_DEBUG.init_err_stack('PA_HR_UPDATE_API.Delete_PA_Resource_Denorm');
4384 X_RETURN_STATUS := FND_API.G_RET_STS_SUCCESS;
4385
4386 FOR rec IN res_denorm_recs LOOP
4387 --Delete the record
4388 DELETE FROM PA_RESOURCES_DENORM
4389 WHERE person_id = p_person_id
4390 AND resource_effective_start_date = rec.resource_effective_start_date;
4391
4392 END LOOP; --end FOR
4393
4394 -- reset the Error stack
4395 PA_DEBUG.Reset_Err_Stack;
4396
4397 EXCEPTION
4398
4399 WHEN NO_DATA_FOUND THEN
4400 x_return_status := FND_API.G_RET_STS_ERROR ;
4401
4402 WHEN OTHERS THEN
4403 -- 4537865 : RESET x_msg_count and x_msg_data also
4404 x_msg_count := 1 ;
4405 x_msg_data := SUBSTRB(SQLERRM ,1,240);
4406 -- Set the exception Message and the stack
4407 FND_MSG_PUB.add_exc_msg(p_pkg_name => 'PA_HR_UPDATE_API.Delete_PA_Resource_Denorm'
4408 ,p_procedure_name => PA_DEBUG.G_Err_Stack );
4409 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
4410 raise;
4411 END Delete_PA_Resource_Denorm;
4412
4413 END PA_HR_UPDATE_API;