DBA Data[Home] [Help]

PACKAGE BODY: APPS.PA_HR_UPDATE_API

Source


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