DBA Data[Home] [Help]

PACKAGE BODY: APPS.EAM_PMDEF_PUB

Source


1 PACKAGE BODY EAM_PMDef_Pub AS
2 /* $Header: EAMPPMDB.pls 120.20.12010000.3 2008/12/01 12:39:47 srkotika ship $*/
3 -- Start of comments
4 --    API name     : package EAM_PMDef_Pub; API's: instantiate_PM_def, create_PM_def, update_PM_def
5 --    Type        : Public
6 --    Function    : Copy, create, and update PM definition and associated PM rules.
7 --    Pre-reqs    : None.
8 --    Version    :     Current version: 1.0
9 --            Initial version: 1.0
10 --
11 --    Notes
12 --
13 -- End of comments
14 
15 G_PKG_NAME     CONSTANT VARCHAR2(30):='EAM_PMDef_Pub';
16 g_sysdate       DATE        :=sysdate;
17 /* for de-bugging */
18 PROCEDURE print_log(info varchar2) is
19 PRAGMA  AUTONOMOUS_TRANSACTION;
20 l_dummy number;
21 BEGIN
22 
23    FND_FILE.PUT_LINE(FND_FILE.LOG, info);
24 
25 END;
26 
27 -- Given an activity association id of an activity association instance,
28 -- and a pm_schedule_id of a pm template,
29 -- create a new pm definition from the template, where the new pm definition
30 -- is associated to the given activity_association_id.
31 
32 PROCEDURE instantiate_PM_def
33 (
34     p_pm_schedule_id    IN    NUMBER,
35     p_activity_assoc_id    IN     NUMBER,
36     x_new_pm_schedule_id    OUT NOCOPY     NUMBER,     -- this is the pm_schedule_id of the newly copied pm schedule
37     x_return_status        OUT NOCOPY     VARCHAR2,
38     x_msg_count             OUT NOCOPY     NUMBER  ,
39         x_msg_data              OUT NOCOPY     VARCHAR2
40 )
41 IS
42 
43 l_pm_schedule_id        number;
44 pm_header_row            pm_scheduling_rec_type;
45 pm_activity_row            pm_activities_grp_rec_type;
46 pm_rule_row            pm_rule_rec_type;
47 l_rule_id            number;
48 l_validated            boolean;
49 l_reason_failed            varchar2(30);
50 l_initial_reading        number;
51 l_maintenance_object_type    number;
52 l_maintenance_object_id        number;
53 l_meter_id            number;
54 l_return_status varchar2(1);
55 l_msg_count number;
56 l_msg_data varchar2(2000);
57 l_update_failed varchar2(1);
58 l_error_message varchar2(2000);
59 l_prev_pm_schedule_id        number;
60 l_last_act               number;
61 l_count  number;-- for bug 7230256
62 
63 cursor pm_rules_csr IS
64         select
65          PM_SCHEDULE_ID,
66          RULE_TYPE,
67          DAY_INTERVAL,
68          METER_ID,
69          RUNTIME_INTERVAL,
70          EFFECTIVE_READING_FROM,
71          EFFECTIVE_READING_TO,
72          EFFECTIVE_DATE_FROM,
73          EFFECTIVE_DATE_TO,
74      LIST_DATE,
75      LIST_DATE_DESC
76         from eam_pm_scheduling_rules
77         where pm_schedule_id = p_pm_schedule_id;
78 
79 cursor pm_activities_csr IS
80     select
81     epa.pm_schedule_id,
82     meaa.activity_association_id,
83     epa.interval_multiple,
84         epa.allow_repeat_in_cycle,
85     epa.day_tolerance,
86     epa.next_service_start_date,
87     epa.next_service_end_date
88         from eam_pm_activities epa, mtl_eam_asset_activities meaa
89     where epa.pm_schedule_id=p_pm_schedule_id
90     and epa.activity_association_id =meaa.source_tmpl_id
91     and meaa.maintenance_object_id=l_maintenance_object_id;
92 
93 
94 BEGIN
95 
96     x_return_status:=FND_API.G_RET_STS_SUCCESS;
97 
98 -- Check that enough info is supplied to identify which pm schedule to copy from.
99     if (p_pm_schedule_id is null) then
100         FND_MESSAGE.SET_NAME ('EAM', 'EAM_MT_SUPPLY_PARAMS');
101                 FND_MSG_PUB.Add;
102                 RAISE FND_API.G_EXC_ERROR;
103     end if;
104 
105       begin
106     select
107      PM_SCHEDULE_ID,
108      ACTIVITY_ASSOCIATION_ID,
109      NON_SCHEDULED_FLAG,
110      FROM_EFFECTIVE_DATE,
111      TO_EFFECTIVE_DATE,
112      RESCHEDULING_POINT,
113      LEAD_TIME,
114      ATTRIBUTE_CATEGORY,
115      ATTRIBUTE1,
116      ATTRIBUTE2                               ,
117      ATTRIBUTE3                               ,
118      ATTRIBUTE4                               ,
119      ATTRIBUTE5                               ,
120      ATTRIBUTE6                               ,
121      ATTRIBUTE7                               ,
122      ATTRIBUTE8                               ,
123      ATTRIBUTE9                               ,
124      ATTRIBUTE10                              ,
125      ATTRIBUTE11                              ,
126      ATTRIBUTE12                              ,
127      ATTRIBUTE13                              ,
128      ATTRIBUTE14                              ,
129      ATTRIBUTE15                              ,
130      DAY_TOLERANCE    ,
131      SOURCE_CODE   ,
132      SOURCE_LINE   ,
133      DEFAULT_IMPLEMENT,
134      WHICHEVER_FIRST  ,
135      INCLUDE_MANUAL   ,
136      SET_NAME_ID     ,
137      SCHEDULING_METHOD_CODE,
138      TYPE_CODE,
139       NEXT_SERVICE_START_DATE,
140       NEXT_SERVICE_END_DATE,
141      SOURCE_TMPL_ID                           ,
142      AUTO_INSTANTIATION_FLAG                  ,
143      NAME                                     ,
144      TMPL_FLAG                       ,
145      GENERATE_WO_STATUS              ,
146      INTERVAL_PER_CYCLE                      ,
147      CURRENT_CYCLE                           ,
148      CURRENT_SEQ                             ,
149      CURRENT_WO_SEQ                          ,
150      BASE_DATE                               ,
151      BASE_READING                            ,
152      EAM_LAST_CYCLIC_ACT                     ,
153      MAINTENANCE_OBJECT_ID                   ,
154      MAINTENANCE_OBJECT_TYPE         ,
155 /* added for PM Reviewer -- start-- */
156      LAST_REVIEWED_DATE             ,
157      Last_reviewed_by              ,
158 /* ---PM reviewer--- end---- */
159     generate_next_work_order
160     into pm_header_row
161     from eam_pm_schedulings
162     where pm_schedule_id=p_pm_schedule_id;
163      exception
164     when no_data_found then
165                 FND_MESSAGE.SET_NAME ('EAM', 'EAM_MT_SUPPLY_PARAMS');
166                 FND_MSG_PUB.Add;
167                 RAISE FND_API.G_EXC_ERROR;
168      end;
169 
170          select eam_pm_schedulings_s.nextval into l_pm_schedule_id from dual;
171 
172 -- If the source pm is not a template, raise error
173         if (not (pm_header_row.tmpl_flag = 'Y')) then
174             FND_MESSAGE.SET_NAME('EAM', 'EAM_PM_INST_NOT_TMPL');
175             FND_MSG_PUB.Add;
176             RAISE FND_API.G_EXC_ERROR;
177         else
178         -- When instantiating, tmpl_flag should be 'N'
179             pm_header_row.tmpl_flag:='N';
180             pm_header_row.source_tmpl_id:=pm_header_row.pm_schedule_id;
181             pm_header_row.auto_instantiation_flag:='N';
182             pm_header_row.name:=pm_header_row.name || '-' || l_pm_schedule_id;
183 
184             begin
185 
186             select maintenance_object_id, maintenance_object_type
187             into l_maintenance_object_id, l_maintenance_object_type
188             from mtl_eam_asset_activities
189             where activity_association_id=p_activity_assoc_id;
190 
191             pm_header_row.maintenance_object_id := l_maintenance_object_id;
192             pm_header_row.maintenance_object_type := 3;
193             pm_header_row.current_cycle := 1;
194             pm_header_row.current_seq := 0;
195 
196             exception
197                 when no_data_found then
198                         FND_MESSAGE.SET_NAME ('EAM', 'EAM_MT_SUPPLY_PARAMS');
199                 FND_MSG_PUB.Add;
200                         RAISE FND_API.G_EXC_ERROR;
201             end;
202         end if;
203 
204 
205     l_validated:=validate_pm_header(pm_header_row, l_reason_failed);
206 
207 
208     if (l_validated) then
209 
210     insert into eam_pm_schedulings (
211          PM_SCHEDULE_ID,
212          ACTIVITY_ASSOCIATION_ID,
213          NON_SCHEDULED_FLAG,
214          FROM_EFFECTIVE_DATE,
215          TO_EFFECTIVE_DATE,
216          RESCHEDULING_POINT,
217          LEAD_TIME,
218          ATTRIBUTE_CATEGORY,
219          ATTRIBUTE1,
220          ATTRIBUTE2,
221          ATTRIBUTE3,
222          ATTRIBUTE4,
223          ATTRIBUTE5,
224          ATTRIBUTE6,
225          ATTRIBUTE7,
226          ATTRIBUTE8,
227          ATTRIBUTE9,
228          ATTRIBUTE10,
229          ATTRIBUTE11,
230          ATTRIBUTE12,
231          ATTRIBUTE13,
232          ATTRIBUTE14,
233          ATTRIBUTE15,
234          DAY_TOLERANCE    ,
235          SOURCE_CODE   ,
236          SOURCE_LINE   ,
237          DEFAULT_IMPLEMENT,
238          WHICHEVER_FIRST  ,
239          INCLUDE_MANUAL   ,
240          SET_NAME_ID,
241      SCHEDULING_METHOD_CODE,
242      TYPE_CODE,
243       NEXT_SERVICE_START_DATE,
244       NEXT_SERVICE_END_DATE,
245      SOURCE_TMPL_ID,
246      AUTO_INSTANTIATION_FLAG,
247      NAME                 ,
248      TMPL_FLAG           ,
249      GENERATE_WO_STATUS              ,
250      INTERVAL_PER_CYCLE                      ,
251      CURRENT_CYCLE                           ,
252      CURRENT_SEQ                             ,
253      CURRENT_WO_SEQ                          ,
254      BASE_DATE                               ,
255      BASE_READING                            ,
256      EAM_LAST_CYCLIC_ACT                     ,
257      MAINTENANCE_OBJECT_ID                   ,
258      MAINTENANCE_OBJECT_TYPE                 ,
259      /* added for PM Reviewer -- start-- */
260       LAST_REVIEWED_DATE             ,
261      Last_reviewed_by             ,
262      /* ---PM reviewer--- end---- */
263      created_by,
264      creation_date,
265      last_update_login,
266      last_updated_by,
267      last_update_date ,
268      generate_next_work_order   )
269     values (
270      l_pm_schedule_id,
271      pm_header_row.ACTIVITY_ASSOCIATION_ID,
272      pm_header_row.NON_SCHEDULED_FLAG,
273      pm_header_row.FROM_EFFECTIVE_DATE,
274      pm_header_row.TO_EFFECTIVE_DATE,
275      pm_header_row.RESCHEDULING_POINT,
276      pm_header_row.LEAD_TIME,
277      pm_header_row.ATTRIBUTE_CATEGORY,
278      pm_header_row.ATTRIBUTE1,
279      pm_header_row.ATTRIBUTE2                               ,
280      pm_header_row.ATTRIBUTE3                               ,
281      pm_header_row.ATTRIBUTE4                               ,
282      pm_header_row.ATTRIBUTE5                               ,
283      pm_header_row.ATTRIBUTE6                               ,
284      pm_header_row.ATTRIBUTE7                               ,
285      pm_header_row.ATTRIBUTE8                               ,
286      pm_header_row.ATTRIBUTE9                               ,
287      pm_header_row.ATTRIBUTE10                              ,
288      pm_header_row.ATTRIBUTE11                              ,
289      pm_header_row.ATTRIBUTE12                              ,
290      pm_header_row.ATTRIBUTE13                              ,
291      pm_header_row.ATTRIBUTE14                              ,
292      pm_header_row.ATTRIBUTE15                              ,
293      pm_header_row.DAY_TOLERANCE    ,
294      pm_header_row.SOURCE_CODE   ,
295      pm_header_row.SOURCE_LINE   ,
296      pm_header_row.DEFAULT_IMPLEMENT,
297      pm_header_row.WHICHEVER_FIRST  ,
298      pm_header_row.INCLUDE_MANUAL   ,
299      pm_header_row.SET_NAME_ID,
300      pm_header_row.SCHEDULING_METHOD_CODE ,
301     pm_header_row.TYPE_CODE,
302     pm_header_row.NEXT_SERVICE_START_DATE,
303     pm_header_row.NEXT_SERVICE_END_DATE,
304         pm_header_row.SOURCE_TMPL_ID,
305         pm_header_row.AUTO_INSTANTIATION_FLAG,
306         pm_header_row.NAME                 ,
307         pm_header_row.TMPL_FLAG           ,
308      pm_header_row.GENERATE_WO_STATUS              ,
309      pm_header_row.INTERVAL_PER_CYCLE                      ,
310      pm_header_row.CURRENT_CYCLE                           ,
311      pm_header_row.CURRENT_SEQ                             ,
312      pm_header_row.CURRENT_WO_SEQ                          ,
313      pm_header_row.BASE_DATE                               ,
314      pm_header_row.BASE_READING                            ,
315      pm_header_row.EAM_LAST_CYCLIC_ACT                     ,
316      pm_header_row.MAINTENANCE_OBJECT_ID                   ,
317      pm_header_row.MAINTENANCE_OBJECT_TYPE                 ,
318      /* added for PM Reviewer -- start-- */
319       pm_header_row.LAST_REVIEWED_DATE               ,
320      pm_header_row.Last_reviewed_by                   ,
321      /* ---PM reviewer--- end---- */
322     fnd_global.user_id,
323     sysdate,
324     fnd_global.login_id,
325     fnd_global.user_id,
326     sysdate ,
327     pm_header_row.generate_next_work_order     );
328 
329 --now start copying the activities.
330 
331     for a_pm_activity in pm_activities_csr loop
332 
333     --creating an new activity row
334     pm_activity_row.pm_schedule_id := a_pm_activity.pm_schedule_id;
335     pm_activity_row.activity_association_id := a_pm_activity.activity_association_id;
336     pm_activity_row.interval_multiple := a_pm_activity.interval_multiple;
337     pm_activity_row.allow_repeat_in_cycle := a_pm_activity.allow_repeat_in_cycle;
338     pm_activity_row.day_tolerance := a_pm_activity.day_tolerance;
339 
340     --validating the activity row
341        l_validated := validate_pm_activity
342             ( pm_activity_row,
343               pm_header_row,
344                       l_reason_failed);
345 
346     if (l_validated) then
347 
348         insert into eam_pm_activities
349         (pm_schedule_id,
350          activity_association_id,
351          interval_multiple,
352          allow_repeat_in_cycle,
353          day_tolerance,
354          created_by,
355          creation_date,
356          last_update_login,
357          last_updated_by,
358          last_update_date   )
359          values
360          (l_pm_schedule_id,
361           a_pm_activity.activity_association_id,
362           a_pm_activity.interval_multiple,
363           a_pm_activity.allow_repeat_in_cycle,
364           a_pm_activity.day_tolerance,
365           fnd_global.user_id,
366           sysdate,
367           fnd_global.login_id,
368           fnd_global.user_id,
369           sysdate     );
370 
371       end if;
372 
373     end loop;
374 
375     eam_pmdef_pub.update_pm_last_cyclic_act
376     (      p_api_version => 1.0 ,
377         p_init_msg_list     => 'F' ,
378            p_commit            => 'F' ,
379            p_validation_level  => 100 ,
380         x_return_status => l_return_status,
381             x_msg_count => l_msg_count,
382             x_msg_data => l_msg_data,
383         p_pm_schedule_id => l_pm_schedule_id
384      );
385 
386 
387      if x_return_status <> FND_API.G_RET_STS_SUCCESS then
388          l_update_failed := 'Y';
389          RAISE FND_API.G_EXC_ERROR;
390      end if;
391 
392      -- now start copying over the rules
393      for a_pm_rule in pm_rules_csr loop
394 
395 
396         -- Get maintenance object id and maintenance type
397         select maintenance_object_id, maintenance_object_type
398         into l_maintenance_object_id, l_maintenance_object_type
399         from mtl_eam_asset_activities
400         where activity_association_id=p_activity_assoc_id;
401 
402         -- for runtime rule, get the meter id
403         if (a_pm_rule.meter_id is not null) then
404 
405              --added for performance issues.
406                 select cca.counter_id into l_meter_id
407             from CSI_COUNTER_ASSOCIATIONS cca, CSI_COUNTERS_B ccb
408             where  cca.counter_id = ccb.counter_id
409                      and   ccb.created_from_counter_tmpl_id=a_pm_rule.meter_id
410              and   cca.source_object_id= l_maintenance_object_id ;
411 
412         end if;
413 
414         insert into eam_pm_scheduling_rules
415                 ( PM_SCHEDULE_ID,
416                  RULE_TYPE,
417                 DAY_INTERVAL,
418                 METER_ID  ,
419                 RUNTIME_INTERVAL,
420                 CREATED_BY         ,
421                 CREATION_DATE     ,
422                 LAST_UPDATE_LOGIN,
423                 LAST_UPDATE_DATE,
424                 LAST_UPDATED_BY,
425                 EFFECTIVE_READING_FROM ,
426                 EFFECTIVE_READING_TO  ,
427                 EFFECTIVE_DATE_FROM  ,
428                 EFFECTIVE_DATE_TO   ,
429                 LIST_DATE          ,
430                 LIST_DATE_DESC,
431                 RULE_ID)
432             values
433                                 (l_pm_schedule_id,
434                                 a_pm_rule.RULE_TYPE,
435                                 a_pm_rule.DAY_INTERVAL,
436                                 l_meter_id,
437                                 a_pm_rule.RUNTIME_INTERVAL,
438                     fnd_global.user_id,
439                     sysdate,
440                     fnd_global.login_id,
441                     sysdate    ,
442                     fnd_global.user_id,
443                                 a_pm_rule.EFFECTIVE_READING_FROM ,
444                                 a_pm_rule.EFFECTIVE_READING_TO  ,
445                                 a_pm_rule.EFFECTIVE_DATE_FROM  ,
446                                 a_pm_rule.EFFECTIVE_DATE_TO   ,
447                                 a_pm_rule.LIST_DATE          ,
448                                 a_pm_rule.LIST_DATE_DESC    ,
449                 eam_pm_scheduling_rules_s.nextval);
450 
451 -- if it's a runtime rule, insert meter initial reading into eam_pm_last_services table
452         if a_pm_rule.meter_id is not null then
453 
454             --added for  performance issues
455              select initial_reading into l_initial_reading from
456                       (select initial_reading from CSI_COUNTERS_B where counter_id = a_pm_rule.meter_id
457                          union
458                     select initial_reading from CSI_COUNTER_TEMPLATE_B where counter_id = a_pm_rule.meter_id
459                       );
460             select EAM_LAST_CYCLIC_ACT into l_last_act    from eam_pm_schedulings
461             where pm_schedule_id = l_pm_schedule_id;
462 
463             -- for bug 7230256
464             l_count := 0;
465             select count (*) into l_count
466             from eam_pm_last_service
467             where meter_id=l_meter_id and ACTIVITY_ASSOCIATION_ID =l_last_act;
468 
469             if l_count = 0 then
470 
471                 insert into eam_pm_last_service
472                 ( METER_ID ,
473                    ACTIVITY_ASSOCIATION_ID        ,
474                    LAST_SERVICE_READING         ,
475                    PREV_SERVICE_READING        ,
476                    WIP_ENTITY_ID              ,
477                    LAST_UPDATE_DATE          ,
478                    LAST_UPDATED_BY          ,
479                    CREATION_DATE           ,
480                    CREATED_BY             ,
481                    LAST_UPDATE_LOGIN
482                 )
483                 values
484                 (
485                 l_meter_id,
486                 l_last_act,
487                 l_initial_reading,
488                 null,
489                 null,
490                 sysdate,
491                     fnd_global.user_id,
492                             sysdate,
493                     fnd_global.user_id,
494                             fnd_global.login_id
495                 );
496             end if;
497       end if;
498 
499     end loop;
500 
501     eam_pmdef_pub.update_pm_last_service_reading
502     (      p_api_version => 1.0 ,
503         p_init_msg_list     => 'F' ,
504            p_commit            => 'F' ,
505            p_validation_level  => 100 ,
506             x_return_status => l_return_status,
507             x_msg_count => l_msg_count,
508         x_msg_data => l_msg_data,
509         p_pm_schedule_id => l_pm_schedule_id
510      );
511 
512      if x_return_status <> FND_API.G_RET_STS_SUCCESS then
513         l_update_failed := 'Y';
514             RAISE FND_API.G_EXC_ERROR;
515     end if;
516 
517     end if;
518 
519     l_prev_pm_schedule_id := p_pm_schedule_id;
520 
521 
522 EXCEPTION
523      WHEN FND_API.G_EXC_ERROR THEN
524          if  l_update_failed = 'Y' then
525         x_return_status := fnd_api.g_ret_sts_error;
526         x_msg_count := 1;
527         x_msg_data := l_msg_data;
528      else
529         FND_MSG_PUB.get
530             (      p_msg_index_out             =>      x_msg_count         ,
531                     p_data              =>      x_msg_data
532             );
533         x_msg_data := substr(x_msg_data,1,2000);
534      end if;
535 
536      when others then
537        l_msg_count := 1;
538        x_return_status := fnd_api.g_ret_sts_error;
539            l_error_message := substrb(sqlerrm,1,512);
540            x_msg_data      := l_error_message;
541 
542     -- End of API body.
543 END instantiate_PM_def;
544 
545 
546 
547 /* This procedure instantiates a set of PM definitions for all asset_association_id's in the activity_assoc_id_tbl table.
548  */
549 
550 PROCEDURE instantiate_PM_Defs
551 (
552         p_api_version                   IN      NUMBER                          ,
553         p_init_msg_list                 IN      VARCHAR2 := FND_API.G_FALSE     ,
554         p_commit                        IN      VARCHAR2 := FND_API.G_FALSE     ,
555         p_validation_level              IN      NUMBER  :=
556                                                 FND_API.G_VALID_LEVEL_FULL      ,
557         x_return_status                 OUT NOCOPY     VARCHAR2                        ,
558         x_msg_count                     OUT NOCOPY     NUMBER                          ,
559         x_msg_data                      OUT NOCOPY     VARCHAR2                        ,
560         p_activity_assoc_id_tbl         IN      EAM_ObjectInstantiation_PUB.Association_Id_Tbl_Type
561 )
562 IS
563         l_api_name                      CONSTANT VARCHAR2(30)   := 'instantiate_PM_defs';
564         l_api_version                   CONSTANT NUMBER         := 1.0;
565     l_activity_assoc_id        number;
566     l_return_status            varchar2(1);
567     l_msg_count            number;
568     l_msg_data            varchar2(2000);
569 
570     --record and table type added to identify the instantiated pm templates
571     TYPE l_pm_schedule_templ_rec_type is RECORD
572     ( PM_SCHEDULE_ID                  NUMBER );
573 
574         TYPE l_pm_schedule_templ_tbl_type IS TABLE OF l_pm_schedule_templ_rec_type index by binary_integer;
575 
576     l_pm_schedule_templ_tbl l_pm_schedule_templ_tbl_type;
577 
578 -- This following cursor, given an activity association instance (l_activity_assoc_id), it returns
579 -- all the pm templates that are associated with the SOURCE activity association TEMPLATES
580 -- of l_activity_assoc_id, that have auto_instantiation_flag as "Y"
581 
582     cursor pm_template_csr_old IS
583         select pm_schedule_id
584         from eam_pm_schedulings eps, mtl_eam_asset_activities meaa, eam_pm_set_names epsn
585         where eps.activity_association_id=meaa.source_tmpl_id
586     and meaa.activity_association_id=l_activity_assoc_id
587         and eps.tmpl_flag='Y'
588     and eps.auto_instantiation_flag='Y'
589     and eps.set_name_id=epsn.set_name_id
590     and (epsn.end_date is null or (epsn.end_date > sysdate and epsn.end_date > nvl(eps.to_effective_date, sysdate)));
591 
592     cursor pm_template_csr IS
593         select distinct eps.pm_schedule_id
594         from eam_pm_schedulings eps, eam_pm_activities epa,mtl_eam_asset_activities meaa, eam_pm_set_names epsn
595         where eps.pm_schedule_id=epa.pm_schedule_id
596     and epa.activity_association_id=meaa.source_tmpl_id
597     and meaa.activity_association_id=l_activity_assoc_id
598         and eps.tmpl_flag='Y'
599     and eps.auto_instantiation_flag='Y'
600     and eps.set_name_id=epsn.set_name_id
601     and (epsn.end_date is null or (epsn.end_date > sysdate and epsn.end_date > nvl(eps.to_effective_date, sysdate)));
602 
603     l_new_pm_schedule_id number;
604     l_pm_schedule_id number;
605     l_pm_template_instantiated varchar2(1);
606     k number :=0; -- for bug 7230256
607 
608 BEGIN
609         -- Standard Start of API savepoint
610     SAVEPOINT   instantiate_PM_Defs_pvt;
611     -- Standard call to check for call compatibility.
612     IF NOT FND_API.Compatible_API_Call (        l_api_version           ,
613                                                 p_api_version           ,
614                                                 l_api_name              ,
615                                                 G_PKG_NAME )
616         THEN
617                 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
618         END IF;
619         -- Initialize message list if p_init_msg_list is set to TRUE.
620         IF FND_API.to_Boolean( p_init_msg_list ) THEN
621                 FND_MSG_PUB.initialize;
622         END IF;
623         --  Initialize API return status to success
624         x_return_status := FND_API.G_RET_STS_SUCCESS;
625         -- API body
626 
627 
628     if p_activity_assoc_id_tbl.count>0 then
629 
630         for i in p_activity_assoc_id_tbl.first..p_activity_assoc_id_tbl.last loop
631         l_activity_assoc_id:=p_activity_assoc_id_tbl(i);
632 
633         for l_pm_row in pm_template_csr loop
634             --defaulting the flag
635             l_pm_template_instantiated := 'N';
636 
637             --To check whether the template is already instantiated
638             if l_pm_schedule_templ_tbl.count >0 then
639 
640                    for jj in l_pm_schedule_templ_tbl.first..l_pm_schedule_templ_tbl.last loop
641 
642                 if l_pm_schedule_templ_tbl(jj).pm_schedule_id = l_pm_row.pm_schedule_id then
643                     l_pm_template_instantiated := 'Y';
644                 end if;
645 
646                   end loop;
647               end if;
648 
649         --instantiate the pm def only if the pm template is not earlier instantiated
650            if l_pm_template_instantiated = 'N' then
651                     instantiate_PM_def
652                     (
653             p_activity_assoc_id => l_activity_assoc_id,
654                     p_pm_schedule_id => l_pm_row.pm_schedule_id,
655                     x_return_status => l_return_status,
656                     x_new_pm_schedule_id => l_new_pm_schedule_id,
657             x_msg_count => l_msg_count,
658                     x_msg_data => l_msg_data
659                     );
660 
661              if l_return_status <> FND_API.G_RET_STS_SUCCESS then
662                  x_return_status := l_return_status;
663              x_msg_count := l_msg_count;
664              x_msg_data := l_msg_data;
665                  exit;
666              end if;
667 
668         	l_pm_schedule_templ_tbl(k).pm_schedule_id := l_pm_row.pm_schedule_id; -- replaced i with k for bug 7230256
669                 k := k + 1; --for bug 7230256
670 
671         end if;
672 
673         end loop;
674 
675     end loop;
676 
677     end if;
678         -- End of API body.
679         -- Standard check of p_commit.
680         IF FND_API.To_Boolean( p_commit ) THEN
681                 COMMIT WORK;
682         END IF;
683         -- Standard call to get message count and if count is 1, get message info.
684         FND_MSG_PUB.get
685         (       p_msg_index_out                 =>      x_msg_count             ,
686                         p_data                  =>      x_msg_data
687         );
688     x_msg_data := substr(x_msg_data,1,2000);
689 EXCEPTION
690     WHEN FND_API.G_EXC_ERROR THEN
691                 ROLLBACK TO instantiate_PM_Defs_pvt;
692                 x_return_status := FND_API.G_RET_STS_ERROR ;
693                 FND_MSG_PUB.get
694                 (       p_msg_index_out                 =>      x_msg_count             ,
695                                 p_data                  =>      x_msg_data
696                 );
697         x_msg_data := substr(x_msg_data,1,2000);
698         WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
699                 ROLLBACK TO instantiate_PM_Defs_pvt;
700                 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
701                 FND_MSG_PUB.get
702                 (       p_msg_index_out                 =>      x_msg_count             ,
703                                 p_data                  =>      x_msg_data
704                 );
705         x_msg_data := substr(x_msg_data,1,2000);
706         WHEN OTHERS THEN
707                 ROLLBACK TO instantiate_PM_Defs_pvt;
708                 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
709                 IF      FND_MSG_PUB.Check_Msg_Level
710                         (FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR)
711                 THEN
712                         FND_MSG_PUB.Add_Exc_Msg
713                         (       G_PKG_NAME          ,
714                                 l_api_name
715                         );
716                 END IF;
717                 FND_MSG_PUB.get
718                 (       p_msg_index_out                 =>      x_msg_count             ,
719                                 p_data                  =>      x_msg_data
720                 );
721         x_msg_data := substr(x_msg_data,1,2000);
722 END instantiate_PM_Defs;
723 
724 
725 
726 
727 PROCEDURE create_PM_def
728 (       p_api_version                   IN      NUMBER ,
729         p_init_msg_list                 IN      VARCHAR2 := FND_API.G_FALSE
730 ,
731         p_commit                        IN      VARCHAR2 := FND_API.G_FALSE ,
732         p_validation_level              IN      NUMBER  := FND_API.G_VALID_LEVEL_FULL ,
733         x_return_status                 OUT NOCOPY     VARCHAR2
734 ,
735         x_msg_count                     OUT NOCOPY     NUMBER ,
736         x_msg_data                      OUT NOCOPY     VARCHAR2 ,
737         p_pm_schedule_rec                IN      pm_scheduling_rec_type,
738     p_pm_activities_tbl        IN       pm_activities_grp_tbl_type,
739         p_pm_day_interval_rules_tbl      IN      pm_rule_tbl_type,
740         p_pm_runtime_rules_tbl          IN      pm_rule_tbl_type,
741         p_pm_list_date_rules_tbl          IN      pm_rule_tbl_type,
742         x_new_pm_schedule_id            OUT NOCOPY     NUMBER     -- this is the pm_schedule_id of the newly created pm schedule
743 ) is
744 
745 
746 l_api_name            CONSTANT VARCHAR2(30)    := 'create_PM_def';
747 l_api_version               CONSTANT NUMBER         := 1.0;
748 l_pm_schedule_id        number;
749 i                number;
750 l_validated            boolean;
751 l_reason_failed            varchar2(30);
752 l_rule_id            number;
753 x_error_segments        NUMBER;
754 x_error_message         VARCHAR2(5000);
755 l_act_names             varchar2(500);
756 l_message        varchar2(30);
757 
758 BEGIN
759     -- Standard Start of API savepoint
760     SAVEPOINT    create_PM_def_pub;
761     -- Standard call to check for call compatibility.
762     IF NOT FND_API.Compatible_API_Call (     l_api_version            ,
763                                          p_api_version            ,
764                                        l_api_name             ,
765                                         G_PKG_NAME )
766     THEN
767         RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
768     END IF;
769     -- Initialize message list if p_init_msg_list is set to TRUE.
770     IF FND_API.to_Boolean( p_init_msg_list ) THEN
771         FND_MSG_PUB.initialize;
772     END IF;
773     --  Initialize API return status to success
774     x_return_status := FND_API.G_RET_STS_SUCCESS;
775 
776 
777     -- API body
778 
779 
780 
781 -- validate header and all rules
782     l_validated:=validate_pm_header_and_rules
783     (
784             p_pm_schedule_rec,
785             p_pm_day_interval_rules_tbl,
786             p_pm_runtime_rules_tbl,
787             p_pm_list_date_rules_tbl,
788             l_reason_failed
789     );
790 
791     if (not l_validated) then
792                 FND_MESSAGE.SET_NAME ('EAM', l_reason_failed);
793                 FND_MSG_PUB.Add;
794                 RAISE FND_API.G_EXC_ERROR;
795         end if;
796 
797     l_validated := validate_pm_activities
798     (
799         p_pm_activities_tbl,
800         p_pm_runtime_rules_tbl,
801         p_pm_schedule_rec,
802         l_reason_failed,
803         l_message,
804         l_act_names
805     );
806     if (not l_validated) then
807                 FND_MESSAGE.SET_NAME ('EAM', l_reason_failed);
808                 FND_MSG_PUB.Add;
809                 RAISE FND_API.G_EXC_ERROR;
810         end if;
811      /* Validation generate_next_work_order */
812     if ( not (p_pm_schedule_rec.generate_next_work_order  = 'Y'
813             OR p_pm_schedule_rec.generate_next_work_order = 'N'
814             OR p_pm_schedule_rec.generate_next_work_order is null)) then
815 
816      FND_MESSAGE.SET_NAME ('EAM', 'INVALID_GENERATE_NEXT_WORK_ORDER');
817                 FND_MSG_PUB.Add;
818                 RAISE FND_API.G_EXC_ERROR;
819 
820     end if;
821 
822     /* Validating the DFF */
823 
824     l_validated := EAM_COMMON_UTILITIES_PVT.validate_desc_flex_field (
825             p_app_short_name    =>    'EAM',
826             p_desc_flex_name    =>    'EAM_PM_SCHEDULE',
827             p_ATTRIBUTE_CATEGORY    =>    p_pm_schedule_rec.attribute_category ,
828             p_ATTRIBUTE1            =>    p_pm_schedule_rec.attribute1          ,
829             p_ATTRIBUTE2            =>    p_pm_schedule_rec.attribute2           ,
830             p_ATTRIBUTE3            =>    p_pm_schedule_rec.attribute3            ,
831             p_ATTRIBUTE4            =>    p_pm_schedule_rec.attribute4            ,
832             p_ATTRIBUTE5            =>    p_pm_schedule_rec.attribute5            ,
833             p_ATTRIBUTE6            =>    p_pm_schedule_rec.attribute6            ,
834             p_ATTRIBUTE7            =>    p_pm_schedule_rec.attribute7            ,
835             p_ATTRIBUTE8            =>    p_pm_schedule_rec.attribute8            ,
836             p_ATTRIBUTE9            =>    p_pm_schedule_rec.attribute9            ,
837             p_ATTRIBUTE10           =>    p_pm_schedule_rec.attribute10           ,
838             p_ATTRIBUTE11           =>    p_pm_schedule_rec.attribute11           ,
839             p_ATTRIBUTE12           =>    p_pm_schedule_rec.attribute12           ,
840             p_ATTRIBUTE13           =>    p_pm_schedule_rec.attribute13           ,
841             p_ATTRIBUTE14           =>    p_pm_schedule_rec.attribute14           ,
842             p_ATTRIBUTE15           =>    p_pm_schedule_rec.attribute15 ,
843             x_error_segments    =>    x_error_segments ,
844             x_error_message        =>    x_error_message);
845 
846     IF (not l_validated) THEN
847           FND_MESSAGE.SET_NAME('EAM', 'EAM_INVALID_DESC_FLEX');
848           FND_MESSAGE.SET_TOKEN('ERROR_MSG', x_error_message);
849           FND_MSG_PUB.Add;
850           RAISE FND_API.G_EXC_ERROR;
851     END IF;
852 
853         select eam_pm_schedulings_s.nextval into l_pm_schedule_id from dual;
854 
855 
856     insert into eam_pm_schedulings (
857          PM_SCHEDULE_ID,
858          ACTIVITY_ASSOCIATION_ID,
859          NON_SCHEDULED_FLAG,
860          FROM_EFFECTIVE_DATE,
861          TO_EFFECTIVE_DATE,
862          RESCHEDULING_POINT,
863          LEAD_TIME,
864          ATTRIBUTE_CATEGORY,
865          ATTRIBUTE1,
866          ATTRIBUTE2                               ,
867          ATTRIBUTE3                               ,
868          ATTRIBUTE4                               ,
869          ATTRIBUTE5                               ,
870          ATTRIBUTE6                               ,
871          ATTRIBUTE7                               ,
872          ATTRIBUTE8                               ,
873          ATTRIBUTE9                               ,
874          ATTRIBUTE10                              ,
875          ATTRIBUTE11                              ,
876          ATTRIBUTE12                              ,
877          ATTRIBUTE13                              ,
878          ATTRIBUTE14                              ,
879          ATTRIBUTE15                              ,
880          DAY_TOLERANCE    ,
881          SOURCE_CODE   ,
882          SOURCE_LINE   ,
883          DEFAULT_IMPLEMENT,
884          WHICHEVER_FIRST  ,
885          INCLUDE_MANUAL   ,
886          SET_NAME_ID,
887      SCHEDULING_METHOD_CODE,
888      TYPE_CODE,
889       NEXT_SERVICE_START_DATE,
890       NEXT_SERVICE_END_DATE,
891      SOURCE_TMPL_ID ,
892      AUTO_INSTANTIATION_FLAG,
893      NAME                  ,
894      TMPL_FLAG            ,
895      created_by,
896      creation_date,
897      last_update_login,
898      last_updated_by,
899      last_update_date,
900      GENERATE_WO_STATUS,
901      INTERVAL_PER_CYCLE,
902      CURRENT_CYCLE,
903      CURRENT_SEQ,
904      CURRENT_WO_SEQ,
905      BASE_DATE,
906      BASE_READING,
907      EAM_LAST_CYCLIC_ACT,
908      MAINTENANCE_OBJECT_ID,
909      MAINTENANCE_OBJECT_TYPE,
910      /* added for PM Reviewer -- start-- */
911      LAST_REVIEWED_DATE,
912      Last_reviewed_by
913 /* ---PM reviewer--- end---- */,
914         GENERATE_NEXT_WORK_ORDER )
915     values (
916      l_pm_schedule_id,
917      p_pm_schedule_rec.ACTIVITY_ASSOCIATION_ID,
918      p_pm_schedule_rec.NON_SCHEDULED_FLAG,
919      p_pm_schedule_rec.FROM_EFFECTIVE_DATE,
920      p_pm_schedule_rec.TO_EFFECTIVE_DATE,
921      p_pm_schedule_rec.RESCHEDULING_POINT,
922      p_pm_schedule_rec.LEAD_TIME,
923      p_pm_schedule_rec.ATTRIBUTE_CATEGORY,
924      p_pm_schedule_rec.ATTRIBUTE1,
925      p_pm_schedule_rec.ATTRIBUTE2                               ,
926      p_pm_schedule_rec.ATTRIBUTE3                               ,
927      p_pm_schedule_rec.ATTRIBUTE4                               ,
928      p_pm_schedule_rec.ATTRIBUTE5                               ,
929      p_pm_schedule_rec.ATTRIBUTE6                               ,
930      p_pm_schedule_rec.ATTRIBUTE7                               ,
931      p_pm_schedule_rec.ATTRIBUTE8                               ,
932      p_pm_schedule_rec.ATTRIBUTE9                               ,
933      p_pm_schedule_rec.ATTRIBUTE10                              ,
934      p_pm_schedule_rec.ATTRIBUTE11                              ,
935      p_pm_schedule_rec.ATTRIBUTE12                              ,
936      p_pm_schedule_rec.ATTRIBUTE13                              ,
937      p_pm_schedule_rec.ATTRIBUTE14                              ,
938      p_pm_schedule_rec.ATTRIBUTE15                              ,
939      p_pm_schedule_rec.DAY_TOLERANCE    ,
940      p_pm_schedule_rec.SOURCE_CODE   ,
941      p_pm_schedule_rec.SOURCE_LINE   ,
942      p_pm_schedule_rec.DEFAULT_IMPLEMENT,
943      p_pm_schedule_rec.WHICHEVER_FIRST  ,
944      p_pm_schedule_rec.INCLUDE_MANUAL   ,
945      p_pm_schedule_rec.SET_NAME_ID,
946      p_pm_schedule_rec.SCHEDULING_METHOD_CODE ,
947     p_pm_schedule_rec.TYPE_CODE,
948     p_pm_schedule_rec.NEXT_SERVICE_START_DATE,
949      p_pm_schedule_rec.NEXT_SERVICE_END_DATE,
950         p_pm_schedule_rec.SOURCE_TMPL_ID ,
951         p_pm_schedule_rec.AUTO_INSTANTIATION_FLAG,
952         p_pm_schedule_rec.NAME                  ,
953         p_pm_schedule_rec.TMPL_FLAG            ,
954     fnd_global.user_id,
955     sysdate,
956     fnd_global.login_id,
957     fnd_global.user_id,
958     sysdate,
959     p_pm_schedule_rec.GENERATE_WO_STATUS  ,
960     p_pm_schedule_rec.INTERVAL_PER_CYCLE   ,
961     p_pm_schedule_rec.CURRENT_CYCLE        ,
962     p_pm_schedule_rec.CURRENT_SEQ          ,
963     p_pm_schedule_rec.CURRENT_WO_SEQ       ,
964     p_pm_schedule_rec.BASE_DATE            ,
965     p_pm_schedule_rec.BASE_READING         ,
966     p_pm_schedule_rec.EAM_LAST_CYCLIC_ACT  ,
967     p_pm_schedule_rec.MAINTENANCE_OBJECT_ID ,
968     p_pm_schedule_rec.MAINTENANCE_OBJECT_TYPE,
969     /* added for PM Reviewer -- start-- */
970      p_pm_schedule_rec.LAST_REVIEWED_DATE,
971      p_pm_schedule_rec.Last_reviewed_by,
972     /* ---PM reviewer--- end---- */
973      p_pm_schedule_rec.generate_next_work_order );
974 
975     i:=1;
976     while (p_pm_activities_tbl.exists(i))    loop
977     insert into eam_pm_activities(
978               pm_schedule_id,
979               activity_association_id,
980               interval_multiple,
981               allow_repeat_in_cycle,
982               day_tolerance,
983               created_by,
984               creation_date,
985               last_update_login,
986               last_update_date,
987               last_updated_by
988               )
989         values(
990             l_pm_schedule_id,
991             p_pm_activities_tbl(i).activity_association_id,
992             p_pm_activities_tbl(i).interval_multiple,
993                 p_pm_activities_tbl(i).allow_repeat_in_cycle,
994             p_pm_activities_tbl(i).day_tolerance,
995             fnd_global.user_id,
996                     sysdate,
997                     fnd_global.login_id,
998                     sysdate    ,
999                     fnd_global.user_id
1000            );
1001         i:=i+1;
1002     end loop;
1003 
1004 
1005     i:=1;
1006     while (p_pm_day_interval_rules_tbl.exists(i))    loop
1007 
1008         insert into eam_pm_scheduling_rules
1009                 (RULE_ID,
1010                                 PM_SCHEDULE_ID,
1011                                 RULE_TYPE,
1012                                 DAY_INTERVAL,
1013                                 METER_ID  ,
1014                                 RUNTIME_INTERVAL,
1015                                 CREATED_BY         ,
1016                                 CREATION_DATE     ,
1017                                 LAST_UPDATE_LOGIN,
1018                                 LAST_UPDATE_DATE,
1019                                 LAST_UPDATED_BY,
1020                                 EFFECTIVE_READING_FROM ,
1021                                 EFFECTIVE_READING_TO  ,
1022                                 EFFECTIVE_DATE_FROM  ,
1023                                 EFFECTIVE_DATE_TO   ,
1024                                 LIST_DATE          ,
1025                                 LIST_DATE_DESC
1026                 )
1027                 values
1028                                 (eam_pm_scheduling_rules_s.nextval,
1029                 l_pm_schedule_id,
1030                                 p_pm_day_interval_rules_tbl(i).RULE_TYPE,
1031                                 p_pm_day_interval_rules_tbl(i).DAY_INTERVAL,
1032                                 p_pm_day_interval_rules_tbl(i).METER_ID  ,
1033                                 p_pm_day_interval_rules_tbl(i).RUNTIME_INTERVAL,
1034                                 fnd_global.user_id,
1035                                 sysdate,
1036                                 fnd_global.login_id,
1037                                 sysdate    ,
1038                                 fnd_global.user_id,
1039                                 p_pm_day_interval_rules_tbl(i).EFFECTIVE_READING_FROM ,
1040                                 p_pm_day_interval_rules_tbl(i).EFFECTIVE_READING_TO  ,
1041                                 p_pm_day_interval_rules_tbl(i).EFFECTIVE_DATE_FROM  ,
1042                                 p_pm_day_interval_rules_tbl(i).EFFECTIVE_DATE_TO   ,
1043                                 p_pm_day_interval_rules_tbl(i).LIST_DATE          ,
1044                                 p_pm_day_interval_rules_tbl(i).LIST_DATE_DESC
1045                 );
1046 
1047         i:=i+1;
1048     end loop;
1049 
1050     i:=1;
1051     while (p_pm_runtime_rules_tbl.exists(i))    loop
1052 
1053         insert into eam_pm_scheduling_rules
1054                                 ( RULE_ID,
1055                 PM_SCHEDULE_ID,
1056                                 RULE_TYPE,
1057                                 DAY_INTERVAL,
1058                                 METER_ID  ,
1059                                 RUNTIME_INTERVAL,
1060                                 CREATED_BY         ,
1061                                 CREATION_DATE     ,
1062                                 LAST_UPDATE_LOGIN,
1063                                 LAST_UPDATE_DATE,
1064                                 LAST_UPDATED_BY,
1065                                 EFFECTIVE_READING_FROM ,
1066                                 EFFECTIVE_READING_TO  ,
1067                                 EFFECTIVE_DATE_FROM  ,
1068                                 EFFECTIVE_DATE_TO   ,
1069                                 LIST_DATE          ,
1070                                 LIST_DATE_DESC
1071                 )
1072                         values
1073                                 (eam_pm_scheduling_rules_s.nextval,
1074                 l_pm_schedule_id,
1075                                 p_pm_runtime_rules_tbl(i).RULE_TYPE,
1076                                 p_pm_runtime_rules_tbl(i).DAY_INTERVAL,
1077                                 p_pm_runtime_rules_tbl(i).METER_ID  ,
1078                                 p_pm_runtime_rules_tbl(i).RUNTIME_INTERVAL,
1079                                 fnd_global.user_id,
1080                                 sysdate,
1081                                 fnd_global.login_id,
1082                                 sysdate    ,
1083                                 fnd_global.user_id,
1084                                 p_pm_runtime_rules_tbl(i).EFFECTIVE_READING_FROM ,
1085                                 p_pm_runtime_rules_tbl(i).EFFECTIVE_READING_TO  ,
1086                                 p_pm_runtime_rules_tbl(i).EFFECTIVE_DATE_FROM  ,
1087                                 p_pm_runtime_rules_tbl(i).EFFECTIVE_DATE_TO   ,
1088                                 p_pm_runtime_rules_tbl(i).LIST_DATE          ,
1089                                 p_pm_runtime_rules_tbl(i).LIST_DATE_DESC
1090                                 );
1091         i:=i+1;
1092     end loop;
1093 
1094     i:=1;
1095     while (p_pm_list_date_rules_tbl.exists(i))    loop
1096 
1097         insert into eam_pm_scheduling_rules
1098                                 ( RULE_ID,
1099                 PM_SCHEDULE_ID,
1100                                 RULE_TYPE,
1101                                 DAY_INTERVAL,
1102                                 METER_ID  ,
1103                                 RUNTIME_INTERVAL,
1104                                 CREATED_BY         ,
1105                                 CREATION_DATE     ,
1106                                 LAST_UPDATE_LOGIN,
1107                                 LAST_UPDATE_DATE,
1108                                 LAST_UPDATED_BY,
1109                                 EFFECTIVE_READING_FROM ,
1110                                 EFFECTIVE_READING_TO  ,
1111                                 EFFECTIVE_DATE_FROM  ,
1112                                 EFFECTIVE_DATE_TO   ,
1113                                 LIST_DATE          ,
1114                                 LIST_DATE_DESC
1115                 )
1116                         values
1117                                 (eam_pm_scheduling_rules_s.nextval,
1118                 l_pm_schedule_id,
1119                                 p_pm_list_date_rules_tbl(i).RULE_TYPE,
1120                                 p_pm_list_date_rules_tbl(i).DAY_INTERVAL,
1121                                 p_pm_list_date_rules_tbl(i).METER_ID  ,
1122                                 p_pm_list_date_rules_tbl(i).RUNTIME_INTERVAL,
1123                                 fnd_global.user_id,
1124                                 sysdate,
1125                                 fnd_global.login_id,
1126                                 sysdate    ,
1127                                 fnd_global.user_id,
1128                                 p_pm_list_date_rules_tbl(i).EFFECTIVE_READING_FROM ,
1129                                 p_pm_list_date_rules_tbl(i).EFFECTIVE_READING_TO  ,
1130                                 p_pm_list_date_rules_tbl(i).EFFECTIVE_DATE_FROM  ,
1131                                 p_pm_list_date_rules_tbl(i).EFFECTIVE_DATE_TO   ,
1132                                 p_pm_list_date_rules_tbl(i).LIST_DATE          ,
1133                                 p_pm_list_date_rules_tbl(i).LIST_DATE_DESC
1134                                 );
1135         i:=i+1;
1136     end loop;
1137     x_new_pm_schedule_id:=l_pm_schedule_id;
1138 
1139     -- End of API body.
1140 
1141 
1142     -- Standard check of p_commit.
1143     IF FND_API.To_Boolean( p_commit ) THEN
1144         COMMIT WORK;
1145     END IF;
1146     -- Standard call to get message count and if count is 1, get message info.
1147     FND_MSG_PUB.get
1148         (      p_msg_index_out             =>      x_msg_count         ,
1149                 p_data              =>      x_msg_data
1150         );
1151     x_msg_data := substr(x_msg_data,1,2000);
1152 EXCEPTION
1153     WHEN FND_API.G_EXC_ERROR THEN
1154         ROLLBACK TO create_PM_def_pub;
1155         x_return_status := FND_API.G_RET_STS_ERROR ;
1156         FND_MSG_PUB.get
1157             (      p_msg_index_out             =>      x_msg_count         ,
1158                     p_data              =>      x_msg_data
1159             );
1160         x_msg_data := substr(x_msg_data,1,2000);
1161     WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
1162         ROLLBACK TO create_PM_def_pub;
1163         x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
1164         FND_MSG_PUB.get
1165             (      p_msg_index_out             =>      x_msg_count         ,
1166                     p_data              =>      x_msg_data
1167             );
1168         x_msg_data := substr(x_msg_data,1,2000);
1169     WHEN OTHERS THEN
1170         ROLLBACK TO create_PM_def_pub;
1171         x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
1172           IF     FND_MSG_PUB.Check_Msg_Level
1173             (FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR)
1174         THEN
1175                 FND_MSG_PUB.Add_Exc_Msg
1176                     (    G_PKG_NAME          ,
1177                         l_api_name
1178                 );
1179         END IF;
1180         FND_MSG_PUB.get
1181             (      p_msg_index_out             =>      x_msg_count         ,
1182                     p_data              =>      x_msg_data
1183             );
1184         x_msg_data := substr(x_msg_data,1,2000);
1185 END create_PM_def;
1186 
1187 
1188 
1189 procedure update_pm_def
1190 (       p_api_version                   IN      NUMBER ,
1191         p_init_msg_list                 IN      VARCHAR2 := FND_API.G_FALSE ,
1192         p_commit                        IN      VARCHAR2 := FND_API.G_FALSE ,
1193         p_validation_level              IN      NUMBER  := FND_API.G_VALID_LEVEL_FULL ,
1194         x_return_status                 OUT NOCOPY     VARCHAR2 ,
1195         x_msg_count                     OUT NOCOPY     NUMBER ,
1196         x_msg_data                      OUT NOCOPY     VARCHAR2 ,
1197         p_pm_schedule_rec               IN      pm_scheduling_rec_type:=null,
1198     p_pm_activities_tbl        IN      pm_activities_grp_tbl_type,
1199         p_pm_day_interval_rules_tbl     IN      pm_rule_tbl_type,
1200         p_pm_runtime_rules_tbl          IN      pm_rule_tbl_type,
1201         p_pm_list_date_rules_tbl        IN      pm_rule_tbl_type
1202 )
1203 is
1204 l_api_name            CONSTANT VARCHAR2(30)    :='update_pm_def';
1205 l_api_version               CONSTANT NUMBER         := 1.0;
1206 l_pm_header            pm_scheduling_rec_type;
1207 l_day_interval_counter        number;
1208 l_runtime_counter        number;
1209 l_list_date_counter        number;
1210 l_pm_rule            pm_rule_rec_type;
1211 l_selected_day_rules_tbl    pm_rule_tbl_type;
1212 l_selected_runtime_rules_tbl    pm_rule_tbl_type;
1213 l_selected_list_date_rules_tbl  pm_rule_tbl_type;
1214 l_merged_day_rules_tbl         pm_rule_tbl_type;
1215 l_merged_runtime_rules_tbl    pm_rule_tbl_type;
1216 l_merged_list_date_rules_tbl    pm_rule_tbl_type;
1217 l_validated            boolean;
1218 l_validated_act            boolean;
1219 l_reason_failed            varchar2(30);
1220 l_current_rules_tbl        pm_rule_tbl_type;
1221 n                number;
1222 i                number;
1223 l_pm_schedule_id        number;
1224 l_rule_id            number;
1225 l_act_names             varchar2(500);
1226 l_message        varchar2(30);
1227 
1228 x_error_segments        NUMBER;
1229 x_error_message         VARCHAR2(5000);
1230 
1231 
1232 BEGIN
1233     -- Standard Start of API savepoint
1234     SAVEPOINT    update_pm_def_pub;
1235     -- Standard call to check for call compatibility.
1236     IF NOT FND_API.Compatible_API_Call (     l_api_version            ,
1237                                          p_api_version            ,
1238                                        l_api_name             ,
1239                                         G_PKG_NAME )
1240     THEN
1241         RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1242     END IF;
1243     -- Initialize message list if p_init_msg_list is set to TRUE.
1244     IF FND_API.to_Boolean( p_init_msg_list ) THEN
1245         FND_MSG_PUB.initialize;
1246     END IF;
1247     --  Initialize API return status to success
1248     x_return_status := FND_API.G_RET_STS_SUCCESS;
1249     -- API body
1250 
1251     if (p_pm_schedule_rec.pm_schedule_id is null) then
1252         FND_MESSAGE.SET_NAME ('EAM', 'EAM_PM_SCHEDULE_ID_MISSING');
1253                 FND_MSG_PUB.Add;
1254                 RAISE FND_API.G_EXC_ERROR;
1255     else
1256         l_pm_schedule_id:=p_pm_schedule_rec.pm_schedule_id;
1257     end if;
1258 
1259 
1260     /* Validation generate_next_work_order */
1261        if ( not (p_pm_schedule_rec.generate_next_work_order  = 'Y'
1262             OR p_pm_schedule_rec.generate_next_work_order = 'N'
1263             OR p_pm_schedule_rec.generate_next_work_order is null)) then
1264             FND_MESSAGE.SET_NAME ('EAM', 'INVALID_GENERATE_NEXT_WORK_ORDER');
1265                 FND_MSG_PUB.Add;
1266                 RAISE FND_API.G_EXC_ERROR;
1267 
1268     end if;
1269     /* Validating the DFF */
1270 
1271     l_validated := EAM_COMMON_UTILITIES_PVT.validate_desc_flex_field (
1272             p_app_short_name    =>    'EAM',
1273             p_desc_flex_name    =>    'EAM_PM_SCHEDULE',
1274             p_ATTRIBUTE_CATEGORY    =>    p_pm_schedule_rec.attribute_category ,
1275             p_ATTRIBUTE1            =>    p_pm_schedule_rec.attribute1          ,
1276             p_ATTRIBUTE2            =>    p_pm_schedule_rec.attribute2           ,
1277             p_ATTRIBUTE3            =>    p_pm_schedule_rec.attribute3            ,
1278             p_ATTRIBUTE4            =>    p_pm_schedule_rec.attribute4            ,
1279             p_ATTRIBUTE5            =>    p_pm_schedule_rec.attribute5            ,
1280             p_ATTRIBUTE6            =>    p_pm_schedule_rec.attribute6            ,
1281             p_ATTRIBUTE7            =>    p_pm_schedule_rec.attribute7            ,
1282             p_ATTRIBUTE8            =>    p_pm_schedule_rec.attribute8            ,
1283             p_ATTRIBUTE9            =>    p_pm_schedule_rec.attribute9            ,
1284             p_ATTRIBUTE10           =>    p_pm_schedule_rec.attribute10           ,
1285             p_ATTRIBUTE11           =>    p_pm_schedule_rec.attribute11           ,
1286             p_ATTRIBUTE12           =>    p_pm_schedule_rec.attribute12           ,
1287             p_ATTRIBUTE13           =>    p_pm_schedule_rec.attribute13           ,
1288             p_ATTRIBUTE14           =>    p_pm_schedule_rec.attribute14           ,
1289             p_ATTRIBUTE15           =>    p_pm_schedule_rec.attribute15 ,
1290             x_error_segments    =>    x_error_segments ,
1291             x_error_message        =>    x_error_message);
1292     IF (not l_validated) THEN
1293         FND_MESSAGE.SET_NAME ('EAM', x_error_message);
1294                 FND_MSG_PUB.Add;
1295                 RAISE FND_API.G_EXC_ERROR;
1296         END IF;
1297 
1298 
1299 
1300 
1301     l_validated:=validate_pm_header_and_rules(p_pm_schedule_rec,
1302                 p_pm_day_interval_rules_tbl,
1303                 p_pm_runtime_rules_tbl,
1304                 p_pm_list_date_rules_tbl,
1305                 l_reason_failed);
1306     l_validated_act := validate_pm_activities
1307     (
1308         p_pm_activities_tbl,
1309         p_pm_runtime_rules_tbl,
1310         p_pm_schedule_rec,
1311         l_reason_failed,
1312         l_message,
1313         l_act_names
1314     );
1315       if (l_validated  and  l_validated_act) then
1316 
1317     update eam_pm_schedulings set
1318         ACTIVITY_ASSOCIATION_ID=p_pm_schedule_rec.ACTIVITY_ASSOCIATION_ID,
1319         NON_SCHEDULED_FLAG=p_pm_schedule_rec.NON_SCHEDULED_FLAG,
1320         FROM_EFFECTIVE_DATE=p_pm_schedule_rec.FROM_EFFECTIVE_DATE,
1321         TO_EFFECTIVE_DATE=p_pm_schedule_rec.TO_EFFECTIVE_DATE,
1322         RESCHEDULING_POINT=p_pm_schedule_rec.RESCHEDULING_POINT,
1323         LEAD_TIME=p_pm_schedule_rec.LEAD_TIME,
1324         ATTRIBUTE_CATEGORY=p_pm_schedule_rec.ATTRIBUTE_CATEGORY,
1325         ATTRIBUTE1=p_pm_schedule_rec.ATTRIBUTE1,
1326         ATTRIBUTE2=p_pm_schedule_rec.ATTRIBUTE2                    ,
1327         ATTRIBUTE3=p_pm_schedule_rec.ATTRIBUTE3                               ,
1328         ATTRIBUTE4=p_pm_schedule_rec.ATTRIBUTE4                               ,
1329         ATTRIBUTE5=p_pm_schedule_rec.ATTRIBUTE5                               ,
1330         ATTRIBUTE6=p_pm_schedule_rec.ATTRIBUTE6                               ,
1331         ATTRIBUTE7=p_pm_schedule_rec.ATTRIBUTE7                               ,
1332         ATTRIBUTE8=p_pm_schedule_rec.ATTRIBUTE8                               ,
1333         ATTRIBUTE9=p_pm_schedule_rec.ATTRIBUTE9                               ,
1334         ATTRIBUTE10=p_pm_schedule_rec.ATTRIBUTE10                              ,
1335         ATTRIBUTE11=p_pm_schedule_rec.ATTRIBUTE11                              ,
1336         ATTRIBUTE12=p_pm_schedule_rec.ATTRIBUTE12                              ,
1337         ATTRIBUTE13=p_pm_schedule_rec.ATTRIBUTE13                              ,
1338         ATTRIBUTE14=p_pm_schedule_rec.ATTRIBUTE14                              ,
1339         ATTRIBUTE15=p_pm_schedule_rec.ATTRIBUTE15                              ,
1340         DAY_TOLERANCE    =p_pm_schedule_rec.DAY_TOLERANCE   ,
1341         SOURCE_CODE=p_pm_schedule_rec.SOURCE_CODE   ,
1342         SOURCE_LINE=  p_pm_schedule_rec.SOURCE_LINE   ,
1343         DEFAULT_IMPLEMENT=p_pm_schedule_rec.DEFAULT_IMPLEMENT,
1344         WHICHEVER_FIRST = p_pm_schedule_rec.WHICHEVER_FIRST  ,
1345         INCLUDE_MANUAL  = p_pm_schedule_rec.INCLUDE_MANUAL   ,
1346         SET_NAME_ID=p_pm_schedule_rec.SET_NAME_ID,
1347         SCHEDULING_METHOD_CODE= p_pm_schedule_rec.SCHEDULING_METHOD_CODE ,
1348         TYPE_CODE=p_pm_schedule_rec.TYPE_CODE,
1349     NEXT_SERVICE_START_DATE=p_pm_schedule_rec.NEXT_SERVICE_START_DATE,
1350     NEXT_SERVICE_END_DATE=p_pm_schedule_rec.NEXT_SERVICE_END_DATE,
1351     SOURCE_TMPL_ID = p_pm_schedule_rec.SOURCE_TMPL_ID,
1352      AUTO_INSTANTIATION_FLAG          =p_pm_schedule_rec.AUTO_INSTANTIATION_FLAG,
1353      NAME  =p_pm_schedule_rec.NAME,
1354      TMPL_FLAG   =p_pm_schedule_rec.TMPL_FLAG,
1355     LAST_REVIEWED_BY = p_pm_schedule_rec.LAST_REVIEWED_BY,
1356     LAST_REVIEWED_DATE = p_pm_schedule_rec.LAST_REVIEWED_DATE ,
1357         CREATED_BY=fnd_global.user_id,
1358         CREATION_DATE=sysdate,
1359         LAST_UPDATE_LOGIN=fnd_global.login_id,
1360         LAST_UPDATED_BY=fnd_global.user_id,
1361         LAST_UPDATE_DATE=sysdate    ,
1362         generate_next_work_order =p_pm_schedule_rec.generate_next_work_order
1363         where PM_SCHEDULE_ID=l_pm_schedule_id;
1364 
1365     delete from eam_pm_activities
1366     where pm_schedule_id=l_pm_schedule_id;
1367 
1368     n:=1;
1369     while (p_pm_activities_tbl.exists(n)) loop /*FP of 7030271*/
1370 
1371         insert into eam_pm_activities(
1372               pm_schedule_id,
1373               activity_association_id,
1374               interval_multiple,
1375               allow_repeat_in_cycle,
1376               day_tolerance,
1377               created_by,
1378               creation_date,
1379               last_update_login,
1380               last_update_date,
1381               last_updated_by
1382               )
1383         values(
1384             l_pm_schedule_id,
1385             p_pm_activities_tbl(i).activity_association_id,
1386             p_pm_activities_tbl(i).interval_multiple,
1387                 p_pm_activities_tbl(i).allow_repeat_in_cycle,
1388             p_pm_activities_tbl(i).day_tolerance,
1389             fnd_global.user_id,
1390                     sysdate,
1391                     fnd_global.login_id,
1392                     sysdate    ,
1393                     fnd_global.user_id
1394            );
1395     n:=n+1;
1396 
1397     end loop;
1398 
1399     delete from eam_pm_scheduling_rules
1400     where pm_schedule_id=l_pm_schedule_id;
1401 
1402       for i in 1..3 loop
1403     if (i=1) then
1404         l_current_rules_tbl:=p_pm_day_interval_rules_tbl;
1405     elsif (i=2) then
1406         l_current_rules_tbl:=p_pm_runtime_rules_tbl;
1407     elsif (i=3) then
1408         l_current_rules_tbl:=p_pm_list_date_rules_tbl;
1409     end if;
1410     n:=1;
1411     while (l_current_rules_tbl.exists(n)) loop
1412 
1413                     select eam_pm_scheduling_rules_s.nextval into l_rule_id from dual; --Bug#5453536
1414 
1415             insert into eam_pm_scheduling_rules
1416                                 ( rule_id,
1417                 PM_SCHEDULE_ID,
1418                                 RULE_TYPE,
1419                                 DAY_INTERVAL,
1420                                 METER_ID  ,
1421                                 RUNTIME_INTERVAL,
1422                                 CREATED_BY         ,
1423                                 CREATION_DATE     ,
1424                                 LAST_UPDATE_LOGIN,
1425                                 LAST_UPDATE_DATE,
1426                                 LAST_UPDATED_BY,
1427                                 EFFECTIVE_READING_FROM ,
1428                                 EFFECTIVE_READING_TO  ,
1429                                 EFFECTIVE_DATE_FROM  ,
1430                                 EFFECTIVE_DATE_TO   ,
1431                                 LIST_DATE          ,
1432                                 LIST_DATE_DESC
1433                 )
1434                         values
1435                                 (l_rule_id,
1436                 l_pm_schedule_id,
1437                                 l_current_rules_tbl(n).RULE_TYPE,
1438                                 l_current_rules_tbl(n).DAY_INTERVAL,
1439                                 l_current_rules_tbl(n).METER_ID  ,
1440                                 l_current_rules_tbl(n).RUNTIME_INTERVAL,
1441                                 fnd_global.user_id,
1442                                 sysdate,
1443                                 fnd_global.login_id,
1444                                 sysdate    ,
1445                                 fnd_global.user_id,
1446                                 l_current_rules_tbl(n).EFFECTIVE_READING_FROM ,
1447                                 l_current_rules_tbl(n).EFFECTIVE_READING_TO  ,
1448                                 l_current_rules_tbl(n).EFFECTIVE_DATE_FROM  ,
1449                                 l_current_rules_tbl(n).EFFECTIVE_DATE_TO   ,
1450                                 l_current_rules_tbl(n).LIST_DATE          ,
1451                                 l_current_rules_tbl(n).LIST_DATE_DESC
1452                                 );
1453         n:=n+1;
1454     end loop;    -- end while loop that loops through each record
1455       end loop;         -- end for loop that loop through 3 tables
1456 
1457     else   -- rules did not validate
1458                 FND_MESSAGE.SET_NAME ('EAM', l_reason_failed);
1459                 FND_MSG_PUB.Add;
1460                 RAISE FND_API.G_EXC_ERROR;
1461     end if;
1462 
1463     -- End of API body.
1464     -- Standard check of p_commit.
1465     IF FND_API.To_Boolean( p_commit ) THEN
1466         COMMIT WORK;
1467     END IF;
1468     -- Standard call to get message count and if count is 1, get message info.
1469     FND_MSG_PUB.get
1470         (      p_msg_index_out             =>      x_msg_count         ,
1471                 p_data              =>      x_msg_data
1472         );
1473     x_msg_data := substr(x_msg_data,1,2000);
1474 EXCEPTION
1475     WHEN FND_API.G_EXC_ERROR THEN
1476         ROLLBACK TO update_pm_def_pub;
1477         x_return_status := FND_API.G_RET_STS_ERROR ;
1478         FND_MSG_PUB.get
1479             (      p_msg_index_out             =>      x_msg_count         ,
1480                     p_data              =>      x_msg_data
1481             );
1482         x_msg_data := substr(x_msg_data,1,2000);
1483     WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
1484         ROLLBACK TO update_pm_def_pub;
1485         x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
1486         FND_MSG_PUB.get
1487             (      p_msg_index_out             =>      x_msg_count         ,
1488                     p_data              =>      x_msg_data
1489             );
1490         x_msg_data := substr(x_msg_data,1,2000);
1491     WHEN OTHERS THEN
1492         ROLLBACK TO update_pm_def_pub;
1493         x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
1494           IF     FND_MSG_PUB.Check_Msg_Level
1495             (FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR)
1496         THEN
1497                 FND_MSG_PUB.Add_Exc_Msg
1498                     (    G_PKG_NAME          ,
1499                         l_api_name
1500                 );
1501         END IF;
1502         FND_MSG_PUB.get
1503             (      p_msg_index_out             =>      x_msg_count         ,
1504                     p_data              =>      x_msg_data
1505             );
1506         x_msg_data := substr(x_msg_data,1,2000);
1507 END update_PM_def;
1508 
1509 
1510 
1511 function validate_pm_header
1512 (
1513   p_pm_schedule_rec               IN      pm_scheduling_rec_type,
1514   x_reason_failed                 OUT NOCOPY     varchar2
1515 ) return BOOLEAN
1516 is
1517 
1518 l_count                number;
1519 l_asset_activity_id        number;
1520 l_last_service_start_date     date;
1521 l_last_service_end_date         date;
1522 l_pm_schedule_id        number;
1523 l_lookup_type                   mfg_lookups.lookup_type%type;
1524 l_status_id number;
1525 
1526 
1527 begin
1528 -- Check all the "not null" fields
1529     if (p_pm_schedule_rec.rescheduling_point is null
1530         or p_pm_schedule_rec.set_name_id is null
1531         or p_pm_schedule_rec.type_code is null
1532         or p_pm_schedule_rec.scheduling_method_code is null
1533         or p_pm_schedule_rec.whichever_first is null
1534         or p_pm_schedule_rec.name is null
1535         or p_pm_schedule_rec.generate_wo_status is null
1536         or p_pm_schedule_rec.interval_per_cycle is null
1537         or p_pm_schedule_rec.maintenance_object_id is null
1538         or p_pm_schedule_rec.maintenance_object_type is null)
1539     then
1540         x_reason_failed:='EAM_PM_HD_NOT_ENOUGH_PARAM';
1541         return false;
1542     end if;
1543 
1544 
1545 -- default_implement(Y/N), whichever_first(Y/N), include_manual(Y/N),  type_code(list_dates, rule_based ) scheduling_method_code(forward, backward)
1546 
1547     if (p_pm_schedule_rec.default_implement is not null
1548         and p_pm_schedule_rec.default_implement <> 'Y'
1549         and p_pm_schedule_rec.default_implement <> 'N') then
1550         x_reason_failed:='EAM_PM_HD_INVALID_DEFAULT_IMPL';
1551         return false;
1552     end if;
1553 
1554      /* added for PM Reviewer -- start-- */
1555 
1556      if( (p_pm_schedule_rec.Last_reviewed_by is null and p_pm_schedule_rec.Last_reviewed_date is not null)
1557         or (p_pm_schedule_rec.Last_reviewed_by is not null and p_pm_schedule_rec.Last_reviewed_date is null)) then
1558         x_reason_failed:='EAM_PM_REVIEW_BY_DATE';
1559         return false;
1560      else
1561         if (p_pm_schedule_rec.Last_reviewed_by is not null and p_pm_schedule_rec.Last_reviewed_date is null) then
1562                 if(p_pm_schedule_rec.Last_reviewed_date<>trunc(sysdate)) then
1563                     x_reason_failed:='EAM_PM_REVIEW_DATE_BY';
1564                     return false;
1565                 end if ;
1566         end if;
1567      end if;
1568 
1569 
1570      /* ---PM reviewer--- end---- */
1571 
1572     if (p_pm_schedule_rec.whichever_first is not null
1573         and p_pm_schedule_rec.whichever_first <> 'Y'
1574         and p_pm_schedule_rec.whichever_first <> 'N') then
1575         x_reason_failed:='EAM_PM_HD_INVALID_WHICHEVER';
1576         return false;
1577     end if;
1578 
1579         if (p_pm_schedule_rec.include_manual is not null
1580         and p_pm_schedule_rec.include_manual <> 'Y'
1581             and p_pm_schedule_rec.include_manual <> 'N') then
1582                 x_reason_failed:='EAM_PM_HD_INVALID_INC_MANUAL';
1583                 return false;
1584         end if;
1585 
1586 
1587         /* Bug # 3840702 : Need to replace literals by bind variable */
1588     l_lookup_type := 'EAM_PM_TYPE';
1589     select count(*) into l_count
1590     from mfg_lookups
1591     where lookup_type = l_lookup_type
1592     and lookup_code=p_pm_schedule_rec.type_code;
1593 
1594     if (l_count=0) then
1595         x_reason_failed:='EAM_PM_HD_INVALID_PM_TYPE';
1596         return false;
1597     end if;
1598 
1599     l_lookup_type := 'EAM_PM_SCHEDULING_METHOD';
1600     select count(*) into l_count
1601     from mfg_lookups
1602     where lookup_type = l_lookup_type
1603     and lookup_code=p_pm_schedule_rec.scheduling_method_code;
1604 
1605     if (l_count=0) then
1606         x_reason_failed:='EAM_PM_HD_INVALID_SCH_METHOD';
1607         return false;
1608     end if;
1609 
1610 -- header validation: when it's not a template, auto_instantiation flag must be 'N' or null
1611     if (p_pm_schedule_rec.tmpl_flag='N' and p_pm_schedule_rec.auto_instantiation_flag='Y') then
1612         x_reason_failed:='EAM_PM_HD_NOT_TMPL_INST';
1613         return false;
1614     end if;
1615 
1616 -- header validation: effective to > effective from
1617     if (p_pm_schedule_rec.from_effective_date is not null
1618         and p_pm_schedule_rec.to_effective_date is not null
1619         and p_pm_schedule_rec.from_effective_date > p_pm_schedule_rec.to_effective_date)
1620     then
1621         x_reason_failed:='EAM_PM_HD_INVALID_DATES';
1622         return false;
1623     end if;
1624 
1625 -- header validation: activity association id is valid
1626 -- header validation: header effective from / to within asset activity effective from / to
1627 
1628 -- header validation: Check that the asset activity has last service reading start/end date.
1629 -- header validation : Check that the set name is valid
1630 -- header validation : set name effective end date > sysdate
1631 -- header validation: pm start and end date is within effective dates of set name
1632 
1633         select count(*) into l_count
1634         from eam_pm_set_names
1635         where set_name_id = p_pm_schedule_rec.set_name_id;
1636 
1637     if (l_count=0) then
1638         x_reason_failed:='EAM_PM_HD_INVALID_SET_NAME';
1639         return false;
1640     end if;
1641 
1642 
1643 
1644 -- set name is unique for this asset activity association and for this type of tmpl_flag
1645 -- (at most one template and one definition for each asset activity association)
1646 
1647     /* Bug # 3890075 : Modified the logic so that the query is executed only once. */
1648 
1649 -- header validation: there can be only one default
1650        /* Bug # 3890075 : Modified the logic so that the query is executed only once. */
1651 -- header validation: PM Name must be unique
1652         /* Bug # 3890075 : Modified the logic so that the query is executed only once. */
1653         BEGIN
1654            SELECT pm_schedule_id into l_pm_schedule_id
1655            FROM eam_pm_schedulings
1656            WHERE name=p_pm_schedule_rec.name
1657        AND tmpl_flag=p_pm_schedule_rec.tmpl_flag;
1658 
1659            if (p_pm_schedule_rec.pm_schedule_id is null) then
1660         x_reason_failed:='EAM_PM_HD_NAME_NOT_UNIQUE';
1661         return false;
1662            else
1663                 if (l_pm_schedule_id <> p_pm_schedule_rec.pm_schedule_id) then
1664                     x_reason_failed:='EAM_PM_HD_NAME_NOT_UNIQUE';
1665                     return false;
1666                 end if;
1667            end if;
1668     EXCEPTION
1669        WHEN NO_DATA_FOUND THEN
1670               null;
1671        WHEN TOO_MANY_ROWS THEN
1672           x_reason_failed:='EAM_PM_HD_NAME_NOT_UNIQUE';
1673           return false;
1674     END;
1675 
1676     --For list dates pm schedule cyclic attributes should have default values
1677 
1678     if p_pm_schedule_rec.TYPE_CODE = 20  and
1679        (p_pm_schedule_rec.current_seq > 0 or p_pm_schedule_rec.interval_per_cycle >1 or
1680         p_pm_schedule_rec.current_cycle > 1 ) then
1681 
1682         x_reason_failed := 'EAM_PM_HD_LIST_DATES_VLD';
1683         return false;
1684 
1685     end if;
1686 
1687 
1688     --New options of Base Date and meter are not applicable for list dates schedule type
1689 
1690        if p_pm_schedule_rec.type_code = 20 and p_pm_schedule_rec.rescheduling_point in (5,6) then
1691         x_reason_failed:='EAM_PM_HD_SCHED_TYPE_NA';
1692         return false;
1693        end if;
1694 
1695        --validation for current interval count cannot be greater than interval per cycle
1696 
1697        if p_pm_schedule_rec.current_seq > p_pm_schedule_rec.interval_per_cycle then
1698              x_reason_failed := 'EAM_PM_HD_CURRENT_SEQ';
1699          return false;
1700        end if;
1701 
1702        --validation for generate wo status
1703 
1704        begin
1705 
1706        SELECT status_id into l_status_id
1707        FROM EAM_WO_STATUSES_V
1708        WHERE ENABLED_FLAG='Y' AND SYSTEM_STATUS IN (1,3,6,17)
1709        and status_id=p_pm_schedule_rec.generate_wo_status;
1710 
1711        exception when no_data_found then
1712              x_reason_failed := 'EAM_PM_HD_INVALID_WO_STATUS';
1713          return false;
1714            when too_many_rows then
1715             null;
1716        end;
1717 
1718        return true;
1719 
1720 end;
1721 
1722 
1723 function validate_pm_day_interval_rule
1724 (
1725         p_pm_rule_rec                   IN      pm_rule_rec_type,
1726     x_reason_failed            OUT NOCOPY     varchar2
1727 ) return BOOLEAN
1728 is
1729 begin
1730 
1731 -- rule type is day interval rule
1732     if (p_pm_rule_rec.rule_type is null or p_pm_rule_rec.rule_type<>1) then
1733         x_reason_failed:='EAM_PM_DAY_WRONG_RULE_TYPE';
1734         return false;
1735     end if;
1736 
1737 -- day interval is not null
1738     if (p_pm_rule_rec.day_interval is null) then
1739         x_reason_failed:='EAM_PM_DAY_NO_DAY_INTERVAL';
1740         return false;
1741     end if;
1742 
1743 -- meter id,  runtime_interval, effective_reading_from, and effective_reading_to, list_date, and list_date_desc must be null
1744 
1745     if (p_pm_rule_rec.meter_id is not null
1746         or p_pm_rule_rec.runtime_interval is not null
1747         or p_pm_rule_rec.effective_reading_from is not null
1748         or p_pm_rule_rec.effective_reading_to is not null
1749         or p_pm_rule_rec.list_date is not null
1750         or p_pm_rule_rec.list_date_desc is not null)
1751     then
1752         x_reason_failed:='EAM_PM_DAY_TOO_MANY_PARAMS';
1753         return false;
1754     end if;
1755 
1756 -- effective to > effective from
1757 
1758     if (p_pm_rule_rec.effective_date_from is not null
1759         and p_pm_rule_rec.effective_date_to is not null
1760         and p_pm_rule_rec.effective_date_from > p_pm_rule_rec.effective_date_to) then
1761             x_reason_failed:='EAM_PM_DAY_INVALID_DATE';
1762             return false;
1763     end if;
1764 
1765     return true;
1766 
1767 
1768 end;
1769 
1770 
1771 
1772 function validate_pm_runtime_rule
1773 (
1774         p_pm_rule_rec                   IN      pm_rule_rec_type,
1775     x_reason_failed            OUT NOCOPY      varchar2
1776 ) return BOOLEAN
1777 is
1778     l_meter_id            number;
1779     l_value_change_dir        varchar2(1);
1780     l_count                number;
1781 begin
1782 
1783 -- rule type must be run time rule
1784     if (p_pm_rule_rec.rule_type is null or p_pm_rule_rec.rule_type<>2) then
1785         x_reason_failed:='EAM_PM_RUN_WRONG_RULE_TYPE';
1786         return false;
1787     end if;
1788 
1789 -- not null: meter_id, runtime_interval not null
1790     if (p_pm_rule_rec.meter_id is null
1791         or p_pm_rule_rec.runtime_interval is null) then
1792         x_reason_failed:='EAM_PM_RUN_MISSING_PARAMS';
1793         return false;
1794     end if;
1795 
1796 -- must be null: day_interval, effective_date_from, effective_date_to, list_date, list_date_desc
1797     if (p_pm_rule_rec.day_interval is not null
1798         or p_pm_rule_rec.effective_date_from is not null
1799         or p_pm_rule_rec.effective_date_to is not null
1800         or p_pm_rule_rec.list_date is not null
1801         or p_pm_rule_rec.list_date_desc is not null)
1802     then
1803         x_reason_failed:='EAM_PM_RUN_TOO_MANY_PARAMS';
1804         return false;
1805     end if;
1806 
1807 
1808 -- validate that the meter id is valid
1809          --added for perofrmance issues
1810     select 1 into l_count from dual where exists
1811         (select COUNTER_ID from CSI_COUNTERS_B where counter_id =  p_pm_rule_rec.meter_id
1812          union
1813          select COUNTER_ID from CSI_COUNTER_TEMPLATE_B where counter_id =  p_pm_rule_rec.meter_id) ;
1814 
1815 
1816     if (l_count=0) then
1817         x_reason_failed:='EAM_PM_RUN_INVALID_METER_ID';
1818         return false;
1819     end if;
1820 
1821 -- ascending: effective to > effective from, and vice versa
1822 
1823      --added for perofrmance issues
1824      select direction into l_value_change_dir from
1825            (select direction from CSI_COUNTERS_B where counter_id = p_pm_rule_rec.meter_id
1826                    union
1827                 select direction from CSI_COUNTER_TEMPLATE_B where counter_id = p_pm_rule_rec.meter_id);
1828 
1829     if ((l_value_change_dir='A' -- ascending
1830          and p_pm_rule_rec.effective_reading_from > p_pm_rule_rec.effective_reading_to)
1831         or
1832         (l_value_change_dir='D' --descending
1833          and p_pm_rule_rec.effective_reading_to > p_pm_rule_rec.effective_reading_from))
1834     then
1835         x_reason_failed:='EAM_PM_RUN_INVALID_FROM_TO';
1836         return false;
1837     end if;
1838 
1839        /* Check for whether meter has last service reading has been moved
1840           to validate_pm_header_and_rules */
1841 
1842     return true;
1843 end;
1844 
1845 
1846 
1847 function validate_pm_list_date
1848 (
1849         p_pm_rule_rec                   IN      pm_rule_rec_type,
1850     x_reason_failed            OUT NOCOPY     varchar2
1851 ) return BOOLEAN
1852 is
1853 begin
1854 
1855 -- rule_type must be list date
1856     if (p_pm_rule_rec.rule_type is null or p_pm_rule_rec.rule_type<>3) then
1857         x_reason_failed:='EAM_PM_LIST_WRONG_RULE_TYPE';
1858         return false;
1859     end if;
1860 
1861 -- not null: list_date, (list_date_desc is not required)
1862     if (p_pm_rule_rec.list_date is null) then
1863         x_reason_failed:='EAM_PM_LIST_NO_DATE';
1864         return false;
1865     end if;
1866 
1867 -- null: day_interval, meter_id, runtime_interval, effective_reading_from, effective_reading_to, effective_date_from, effective_date_to???
1868     if (p_pm_rule_rec.day_interval is not null
1869             or p_pm_rule_rec.meter_id is not null
1870             or p_pm_rule_rec.runtime_interval is not null
1871             or p_pm_rule_rec.effective_reading_from is not null
1872             or p_pm_rule_rec.effective_reading_to is not null
1873             or p_pm_rule_rec.effective_date_from is not null
1874             or p_pm_rule_rec.effective_date_to is not null) then
1875         x_reason_failed:='EAM_PM_LIST_TOO_MANY_PARAMS';
1876         return false;
1877     end if;
1878 
1879 
1880 -- list date greater than sysdate
1881     if (trunc(p_pm_rule_rec.list_date) < trunc(sysdate)) then
1882         x_reason_failed:='EAM_PM_LIST_INVALID_DATE_PAST';
1883         return false;
1884     end if;
1885 
1886     return true;
1887 
1888 end;
1889 
1890 
1891 
1892 function validate_pm_day_interval_rules
1893 (
1894         p_pm_rules_tbl                  IN      pm_rule_tbl_type,
1895     x_reason_failed            OUT NOCOPY    varchar2
1896 ) return BOOLEAN
1897 is
1898     i            number;
1899     j            number;
1900     k            number;
1901     l_temp_date_tbl     pm_date_tbl_type;
1902     l_sorted_date_tbl     pm_date_tbl_type;
1903     l_reason_failed     varchar2(30);
1904     l_validated         boolean;
1905     l_min_index         number;
1906     l_max_index         number;
1907     l_num_rules        number;
1908     l_num_sortable_rules     number;
1909     l_pm_rule_rec        pm_rule_rec_type;
1910 begin
1911 -- validate each day interval rule
1912 
1913     -- Go through the table one by one,
1914     -- validate each rule individually
1915     -- pick out the one(s) without effective_from or effective_date_to
1916     -- make sure that there can be at most one w/o effective_from_date and at most one w/o effective_date_to,
1917     --and copy the rest to another table.
1918 
1919         i:=1;   -- counter for all rules
1920     j:=1;   -- counter for sortable rules
1921         while (p_pm_rules_tbl.exists(i))        loop
1922         l_pm_rule_rec:=p_pm_rules_tbl(i);
1923         l_validated:=validate_pm_day_interval_rule(l_pm_rule_rec, l_reason_failed);
1924         if (not l_validated) then
1925             x_reason_failed:=l_reason_failed;
1926             return false;
1927         end if;
1928 
1929         -- At most one day interval rule can exist such that effective_date_from is null
1930         -- this rule is the first rule after sorting.
1931         if l_pm_rule_rec.effective_date_from is null then
1932             if (l_min_index is not null) then
1933                 x_reason_failed:='EAM_PM_DAY_MANY_NO_FROM';
1934                 return false;
1935             else
1936                 l_min_index:=i;
1937             end if;
1938         end if;
1939 
1940                 -- At most one day interval rule can exist such that effective_date_to is null
1941                 -- this rule is the last rule after sorting.
1942         if l_pm_rule_rec.effective_date_to is null then
1943             if (l_max_index is not null) then
1944                 x_reason_failed:='EAM_PM_DAY_MANY_NO_TO';
1945                 return false;
1946             else
1947                 l_max_index:=i;
1948             end if;
1949         end if;
1950 
1951         -- If both effective from and effective to are null, then only one day interval rule can exist
1952         if (l_min_index=l_max_index and i>1) then
1953             x_reason_failed:='EAM_PM_DAY_OVERLAP';
1954             return false;
1955         end if;
1956 
1957         -- If the both effective from and effective to are present,
1958         -- then put the index and start date of this record into
1959         -- another temp table for sorting.
1960         if ((l_max_index is null or l_max_index<>i)
1961                  and (l_min_index is null or l_min_index<>i)) then
1962             l_temp_date_tbl(j).index1:=i;
1963             l_temp_date_tbl(j).date1:=p_pm_rules_tbl(i).effective_date_from;
1964             j:=j+1;
1965         end if;
1966 
1967         i:=i+1;
1968     end loop;
1969     l_num_rules:=i-1;
1970     l_num_sortable_rules:=j-1;
1971 
1972 
1973 -- validate: no overlap; at most one rule with no effective from, and at most one rule with no effective to.
1974     sort_table_by_date(l_temp_date_tbl, l_num_sortable_rules, l_sorted_date_tbl);
1975 
1976     -- If there is a rule w/o effective_to date, then put this rule's index and effective_from date
1977     -- as the last record in the sorted table
1978     if (l_max_index is not null) then
1979         l_sorted_date_tbl(l_num_sortable_rules+1).index1:=l_max_index;
1980         l_sorted_date_tbl(l_num_sortable_rules+1).date1:=p_pm_rules_tbl(l_max_index).effective_date_from;
1981     end if;
1982 
1983     -- First, check whether the first record (with no effective_date_from) overlaps with the next record
1984     if (l_min_index is not null and l_num_rules > 1
1985         and p_pm_rules_tbl(l_min_index).effective_date_to > p_pm_rules_tbl(l_sorted_date_tbl(1).index1).effective_date_from)
1986     then
1987         x_reason_failed:='EAM_PM_DAY_OVERLAP';
1988         return false;
1989     end if;
1990 
1991 
1992     k:=1;
1993     while (l_sorted_date_tbl.exists(k+1)) loop
1994         if (p_pm_rules_tbl(l_sorted_date_tbl(k).index1).effective_date_to > p_pm_rules_tbl(l_sorted_date_tbl(k+1).index1).effective_date_from)
1995         then
1996             x_reason_failed:='EAM_PM_DAY_OVERLAP';
1997             return false;
1998         end if;
1999         k:=k+1;
2000 
2001     end loop;
2002     return true;
2003 
2004 end;
2005 
2006 
2007 
2008 function validate_pm_runtime_rules
2009 (
2010         p_pm_rules_tbl                  IN      pm_rule_tbl_type,
2011     x_reason_failed            OUT NOCOPY    varchar2
2012 ) return BOOLEAN
2013 is
2014     i            number;
2015     j            number;
2016     k            number;
2017     l_temp_num_tbl         pm_num_tbl_type;
2018     l_sorted_num_tbl     pm_num_tbl_type;
2019     l_reason_failed     varchar2(30);
2020     l_validated         boolean;
2021     l_min_index         number;
2022     l_max_index         number;
2023     l_num_rules        number;
2024     l_num_sortable_rules     number;
2025     l_pm_rule_rec        pm_rule_rec_type;
2026     l_meter_id_tbl        pm_num_tbl_type;
2027     l_num_rules_for_meter   pm_num_tbl_type;
2028     l_sorted_meter_id_tbl   pm_num_tbl_type;
2029     l_meter_from_tbl         pm_num_tbl_type;
2030     l_current_meter_index    number;
2031     l_start_rule_index    number;
2032     l_end_rule_index    number;
2033     l_current_rule_index    number;
2034     l_temp_reading_from_tbl        pm_num_tbl_type;
2035     l_sorted_meter_from_tbl        pm_num_tbl_type;
2036     l_num_meters        number;
2037     l_num_rules_counter    number;
2038     l_cur_p_tbl_rule_index    number;
2039 
2040 
2041 begin
2042 
2043 
2044         i:=1;  -- counter for all rules
2045 
2046     -- First, validate each rule, and put meter id's into a meter id table
2047     while (p_pm_rules_tbl.exists(i)) loop
2048 
2049         l_pm_rule_rec:=p_pm_rules_tbl(i);
2050         l_validated:=validate_pm_runtime_rule(l_pm_rule_rec, l_reason_failed);
2051         if (not l_validated) then
2052             x_reason_failed:=l_reason_failed;
2053             return false;
2054         end if;
2055 
2056         l_meter_id_tbl(i).index1:=i;
2057         l_meter_id_tbl(i).num1:=p_pm_rules_tbl(i).meter_id;
2058         i:=i+1;
2059     end loop;
2060 
2061     l_num_rules:=i-1;
2062 
2063     -- Now, l_meter_id_tbl.index is the index of p_pm_rules_tbl, and l_meter_id_tbl.num1
2064     -- is p_pm_rules_tbl.meter_id
2065 
2066     -- sort the meter id table by meter id
2067 
2068     sort_table_by_number(l_meter_id_tbl, l_num_rules, l_sorted_meter_id_tbl);
2069 
2070     -- Go through sorted meter id to determine the number of meters involved
2071     -- and how many rules there are for each meter
2072     -- put different meter rules effective reading from into different sections of
2073     -- l_meter_from_tbl
2074 
2075 
2076     i:=1;
2077     l_num_meters:=0;
2078 
2079     while (l_sorted_meter_id_tbl.exists(i)) loop
2080         if (i=1) then
2081             l_num_meters:=1;
2082             l_num_rules_for_meter(l_num_meters).num1:=1;
2083         elsif (l_sorted_meter_id_tbl(i).num1<> l_sorted_meter_id_tbl(i-1).num1) then
2084             l_num_meters:=l_num_meters+1;
2085                         l_num_rules_for_meter(l_num_meters).num1:=1;
2086         else
2087             l_num_rules_for_meter(l_num_meters).num1:=l_num_rules_for_meter(l_num_meters).num1+1;
2088         end if;
2089 
2090         -- following two lines put index and reading_from into l_meter_from_tbl
2091         l_meter_from_tbl(i).index1:=l_sorted_meter_id_tbl(i).index1;
2092         l_meter_from_tbl(i).num1:=p_pm_rules_tbl(l_sorted_meter_id_tbl(i).index1).effective_reading_from;
2093         i:=i+1;
2094     end loop;
2095 
2096 
2097     -- loop through each meter and do cross validation for all rules of each meter
2098 
2099     l_num_rules_counter:=0;
2100     for l_current_meter_index in 1..l_num_meters loop
2101         l_start_rule_index:=l_num_rules_counter+1;
2102         l_end_rule_index:=l_num_rules_counter+l_num_rules_for_meter(l_current_meter_index).num1;
2103 
2104         l_min_index:=null;
2105         l_max_index:=null;
2106 
2107         -- loop through each rule, validate that there is at most one rule w/o effective from,
2108         -- at most one rule w/o effective to, and if one rule has no effective from and no
2109         -- effective to, then there cannot be more than one rules.
2110         -- At the end of the loop, put all the rules with both effective from and effective to
2111         -- into a table for sorting.
2112 
2113         l_num_sortable_rules:=0;
2114 
2115         -- Following for loop:
2116         -- Go through the section of rule table for the current meter one by one,
2117         -- pick out the one(s) without effective_from or effective_date_to
2118         -- make sure that there can be at most one w/o effective_from_reading and at
2119         -- most one w/o effective_reading_to
2120 
2121         for l_current_rule_index in l_start_rule_index .. l_end_rule_index loop
2122             l_cur_p_tbl_rule_index:=l_meter_from_tbl(l_current_rule_index).index1;
2123             l_pm_rule_rec:=p_pm_rules_tbl(l_cur_p_tbl_rule_index);
2124 
2125             -- For each meter, at most one runtime rule can exist such that
2126             -- effective_reading_from is null
2127             -- this rule is the first rule after sorting.
2128             if l_pm_rule_rec.effective_reading_from is null then
2129                 if (l_min_index is not null) then
2130                     x_reason_failed:='EAM_PM_RUN_MANY_NO_FROM';
2131                     return false;
2132                 else
2133                     l_min_index:=l_cur_p_tbl_rule_index;
2134                 end if;
2135             end if;
2136 
2137                     -- for each meter, At most one runtime rule can exist such that
2138             -- effective_reading_to is null
2139                     -- this rule is the last rule after sorting.
2140 
2141             if l_pm_rule_rec.effective_reading_to is null then
2142                 if (l_max_index is not null) then
2143                     x_reason_failed:='EAM_PM_RUN_MANY_NO_TO';
2144                     return false;
2145                 else
2146                     l_max_index:=l_cur_p_tbl_rule_index;
2147                 end if;
2148             end if;
2149 
2150             -- If both effective from and effective to are null, then only one day interval rule can exist
2151             if (l_min_index=l_max_index and l_num_rules_for_meter(l_current_meter_index).num1>1) then
2152                 x_reason_failed:='EAM_PM_RUN_OVERLAP';
2153                 return false;
2154             end if;
2155 
2156             -- If both effective from and effective to are present,
2157             -- then put the index and start reading of this record into
2158             -- another temp table for sorting.
2159 
2160 
2161             if ((l_max_index is null or l_max_index<>l_cur_p_tbl_rule_index)
2162                       and (l_min_index is null or l_min_index<>l_cur_p_tbl_rule_index))
2163             then
2164                 l_num_sortable_rules:=l_num_sortable_rules+1;
2165                 l_temp_reading_from_tbl(l_num_sortable_rules).index1:=l_meter_from_tbl(l_current_rule_index).index1;
2166                 l_temp_reading_from_tbl(l_num_sortable_rules).num1:=p_pm_rules_tbl(l_cur_p_tbl_rule_index).effective_reading_from;
2167             end if;
2168         end loop;  -- end for loop that loops through each rule within a meter
2169 
2170 
2171 
2172         -- validate: no overlap; at most one rule with no effective from, and at most one rule with no effective to.
2173 
2174         -- following loop for debugging
2175         i:=l_num_rules_counter;
2176 
2177         sort_table_by_number(l_temp_reading_from_tbl,
2178                     l_num_sortable_rules,
2179                     l_sorted_meter_from_tbl);
2180 
2181         -- Now, l_sorted_meter_from_tbl is a table of rules for ONE meter.
2182         -- The index of this table starts at 1.
2183 
2184         -- If there is a rule w/o effective_to reading,
2185         -- then put this rule's index and effective_from reading
2186         -- as the last record in the sorted table
2187         if (l_max_index is not null) then
2188             l_sorted_meter_from_tbl(l_num_sortable_rules+1).index1:=l_max_index;
2189             l_sorted_meter_from_tbl(l_num_sortable_rules+1).num1:=p_pm_rules_tbl(l_max_index).effective_reading_from;
2190             l_num_sortable_rules:=l_num_sortable_rules+1;
2191         end if;
2192 
2193         -- First, check whether the first record (with no effective_reading_from) overlaps with the next record
2194         if (l_min_index is not null
2195         and l_num_sortable_rules >0
2196         and l_min_index <> l_max_index
2197             and p_pm_rules_tbl(l_min_index).effective_reading_to > p_pm_rules_tbl(l_sorted_meter_from_tbl(l_num_rules_counter+1).index1).effective_reading_from)
2198         then
2199             x_reason_failed:='EAM_PM_RUN_OVERLAP';
2200             return false;
2201         end if;
2202 
2203 
2204 
2205 
2206         -- This loop goes through each pair of adjacent rules and checks for overlap
2207         for k in 1 .. l_num_sortable_rules-1 loop
2208             if (p_pm_rules_tbl(l_sorted_meter_from_tbl(k).index1).effective_reading_to > p_pm_rules_tbl(l_sorted_meter_from_tbl(k+1).index1).effective_reading_from)
2209             then
2210                 x_reason_failed:='EAM_PM_RUN_OVERLAP';
2211                 return false;
2212             end if;
2213         end loop;    -- end while loop that checks overlap
2214         l_num_rules_counter:=l_num_rules_counter+l_num_rules_for_meter(l_current_meter_index).num1;
2215     end loop;      -- end for loop that loops through each meter
2216     return true;
2217 
2218 end;
2219 
2220 
2221 
2222 
2223 
2224 function validate_pm_list_date_rules
2225 (
2226         p_pm_rules_tbl                  IN      pm_rule_tbl_type,
2227     x_reason_failed            OUT NOCOPY    varchar2
2228 ) return BOOLEAN
2229 is
2230     l_reason_failed        varchar2(30);
2231     l_validated        boolean;
2232     l_temp_date_tbl        pm_date_tbl_type;
2233     l_sorted_date_tbl    pm_date_tbl_type;
2234     l_num_rules        number;
2235     i            number;
2236 begin
2237 -- validate each list date; copy each list date and index into l_temp_date_tbl
2238     i:=1;
2239     while p_pm_rules_tbl.exists(i) loop
2240         l_validated:=validate_pm_list_date(p_pm_rules_tbl(i), l_reason_failed);
2241         if (not l_validated) then
2242             x_reason_failed:=l_reason_failed;
2243             return false;
2244         end if;
2245         l_temp_date_tbl(i).index1:=i;
2246         l_temp_date_tbl(i).date1:=p_pm_rules_tbl(i).list_date;
2247         i:=i+1;
2248     end loop;
2249     l_num_rules:=i-1;
2250 
2251 -- no list dates can be the same
2252     sort_table_by_date (l_temp_date_tbl, l_num_rules, l_sorted_date_tbl);
2253     i:=1;
2254     while p_pm_rules_tbl.exists(i+1) loop
2255         if (p_pm_rules_tbl(l_sorted_date_tbl(i).index1).list_date=p_pm_rules_tbl(l_sorted_date_tbl(i+1).index1).list_date) then
2256             x_reason_failed:='EAM_PM_LIST_SAME_DATES';
2257             return false;
2258         end if;
2259         i:=i+1;
2260     end loop;
2261     return true;
2262 end;
2263 
2264 
2265 
2266 function validate_pm_header_and_rules
2267 (
2268         p_pm_schedule_rec               IN      pm_scheduling_rec_type,
2269         p_pm_day_interval_rules_tbl     IN      pm_rule_tbl_type,
2270         p_pm_runtime_rules_tbl         IN      pm_rule_tbl_type,
2271         p_pm_list_date_rules_tbl         IN      pm_rule_tbl_type,
2272     x_reason_failed            OUT NOCOPY    varchar2
2273 ) return BOOLEAN
2274 is
2275     l_validated            boolean;
2276     l_reason_failed            varchar2(30);
2277     i                number;
2278     l_count                number;
2279     l_meter_id            number;
2280 
2281 begin
2282 
2283 -- validate header
2284     l_validated:=validate_pm_header(p_pm_schedule_rec, l_reason_failed);
2285     if (not l_validated) then
2286         x_reason_failed:=l_reason_failed;
2287         return false;
2288     end if;
2289 
2290 -- rules tables cannot be all empty
2291     if (p_pm_day_interval_rules_tbl.count=0 and p_pm_runtime_rules_tbl.count=0 and p_pm_list_date_rules_tbl.count=0) then
2292         x_reason_failed:='EAM_PM_EMPTY_HEADER';
2293         return false;
2294     end if;
2295 
2296 -- If header is of type rule_based, then list_date rule table should be empty
2297     if (p_pm_schedule_rec.type_code=10       --'Rule Based, meter and day time'
2298         and p_pm_list_date_rules_tbl.count>0) then
2299         x_reason_failed:='EAM_PM_RULE_NOT_MATCH_PM_TYPE';
2300         return false;
2301     end if;
2302 
2303 -- If header is of type rule_based, then list_date rule table should be empty
2304         if (p_pm_schedule_rec.type_code=17       --'day time only'
2305             and (p_pm_list_date_rules_tbl.count>0 or p_pm_runtime_rules_tbl.count>0)) then
2306                 x_reason_failed:='EAM_PM_RULE_NOT_MATCH_PM_TYPE';
2307                 return false;
2308         end if;
2309 
2310 
2311 -- If header is of type list date, then day interval rules and runtime rules table should be empty
2312     if (p_pm_schedule_rec.type_code=20     -- 'List Dates'
2313         and (p_pm_day_interval_rules_tbl.count>0 or p_pm_runtime_rules_tbl.count>0))
2314     then
2315         x_reason_failed:='EAM_PM_RULE_NOT_MATCH_PM_TYPE';
2316         return false;
2317     end if;
2318 
2319 
2320 -- validate each type of rules
2321     l_validated:=validate_pm_day_interval_rules(p_pm_day_interval_rules_tbl, l_reason_failed);
2322         if (not l_validated) then
2323                 x_reason_failed:=l_reason_failed;
2324                 return false;
2325         end if;
2326 
2327     l_validated:=validate_pm_runtime_rules(p_pm_runtime_rules_tbl, l_reason_failed);
2328         if (not l_validated) then
2329                 x_reason_failed:=l_reason_failed;
2330                 return false;
2331         end if;
2332 
2333     l_validated:=validate_pm_list_date_rules(p_pm_list_date_rules_tbl, l_reason_failed);
2334         if (not l_validated) then
2335                 x_reason_failed:=l_reason_failed;
2336                 return false;
2337         end if;
2338 
2339 
2340 -- Check that effective date from and effective date to in the day interval rules are within the effective dates of the header
2341     i:=1;
2342     while (p_pm_day_interval_rules_tbl.exists(i)) loop
2343         if (p_pm_day_interval_rules_tbl(i).effective_date_from < p_pm_schedule_rec.from_effective_date
2344             or p_pm_day_interval_rules_tbl(i).effective_date_to > p_pm_schedule_rec.to_effective_date)
2345         then
2346             x_reason_failed:='EAM_PM_HD_DAY_INVALID_DATE';
2347             return false;
2348         end if;
2349         i:=i+1;
2350     end loop;
2351 
2352 -- Check that list dates in the list date rules are within effective dates of the header
2353     i:=1;
2354     while (p_pm_list_date_rules_tbl.exists(i)) loop
2355         if (p_pm_list_date_rules_tbl(i).list_date < p_pm_schedule_rec.from_effective_date
2356             or p_pm_list_date_rules_tbl(i).list_date > p_pm_schedule_rec.to_effective_date)
2357         then
2358             x_reason_failed:='EAM_PM_HD_LIST_INVALID_DATE';
2359             return false;
2360         end if;
2361         i:=i+1;
2362     end loop;
2363 
2364   return true;
2365 end;
2366 
2367 --this is an overloaded method to include logic of meter last service reading
2368 
2369 function validate_pm_activity
2370 (
2371     p_pm_activity_grp_rec                   IN      pm_activities_grp_rec_type,
2372     p_pm_runtime_rules_tbl             IN      pm_rule_tbl_type,
2373     p_pm_schedule_rec            IN    PM_Scheduling_Rec_Type,
2374     x_reason_failed            OUT NOCOPY     varchar2,
2375     x_message            OUT NOCOPY     varchar2,
2376     x_activities                    OUT NOCOPY     varchar2
2377 ) return BOOLEAN
2378 
2379 is
2380 l_pm_schedule_id        number;
2381 l_last_service_start_date     date;
2382 l_last_service_end_date         date;
2383 i number;
2384 l_count number;
2385 l_lsi_updated varchar2(1);
2386 l_maintenance_object_id number;
2387 l_asset_activity_id number;
2388 l_last_scheduled_start_date date;
2389 l_last_scheduled_end_date date;
2390 l_actual_end_date date;
2391 l_wip_entity_id number;
2392 l_act_name      varchar2(50);
2393 l_transaction_id number;
2394 begin
2395 
2396 -- activity validation: Check that the asset activity has last service reading start/end date.
2397 
2398     if (p_pm_schedule_rec.tmpl_flag='N') then
2399 
2400         select last_service_start_date, last_service_end_date,last_scheduled_start_date,last_scheduled_end_date,
2401         maintenance_object_id,asset_activity_id
2402         into l_last_service_start_date, l_last_service_end_date,l_last_scheduled_start_date,l_last_scheduled_end_date,
2403         l_maintenance_object_id,l_asset_activity_id
2404            from mtl_eam_asset_activities
2405            where activity_association_id=p_pm_activity_grp_rec.activity_association_id;
2406 
2407         select distinct msi.concatenated_segments  into l_act_name
2408         from mtl_system_items_b_kfv msi
2409     where msi.inventory_item_id=l_asset_activity_id
2410         and msi.eam_item_type=2;
2411 
2412 
2413         if (l_last_service_start_date is null or l_last_service_end_date is null) then
2414 
2415           select max(ejct.actual_start_date),
2416                   max(ejct.actual_end_date) into
2417           l_last_service_start_date,
2418           l_last_service_end_date
2419 
2420           from eam_job_completion_txns ejct, wip_discrete_jobs wdj
2421                   where wdj.wip_entity_id = ejct.wip_entity_id
2422           and wdj.maintenance_object_id=l_maintenance_object_id
2423                   and wdj.primary_item_id=l_asset_activity_id
2424           and ejct.transaction_type=1;
2425 
2426           if (l_last_service_start_date is null or l_last_service_end_date is null) then
2427 
2428             l_last_service_start_date := g_sysdate;
2429             l_last_service_end_date := g_sysdate;
2430                         l_lsi_updated := 'Y';
2431             x_activities :=l_act_name;
2432           end if;
2433 
2434                      UPDATE mtl_eam_asset_activities
2435                   SET last_service_start_date = l_last_service_start_date,
2436           last_service_end_date = l_last_service_end_date,
2437           last_update_date=sysdate, last_updated_by=fnd_global.user_id, creation_date=sysdate,
2438                 last_update_login=fnd_global.login_id, created_by = fnd_global.user_id
2439                   WHERE activity_association_id = p_pm_activity_grp_rec.activity_association_id;
2440 
2441 
2442         end if;
2443 
2444         if (l_last_scheduled_start_date is null or l_last_scheduled_end_date is null) then
2445 
2446 
2447                           begin
2448 
2449               select transaction_id into l_transaction_id from
2450               ( select max(actual_end_date),transaction_id  from eam_job_completion_txns ejct,
2451                   wip_discrete_jobs wdj
2452                   where ejct.transaction_type=1 and
2453                   wdj.wip_entity_id = ejct.wip_entity_id and
2454                   wdj.maintenance_object_id = l_maintenance_object_id and
2455                   wdj.primary_item_id =  l_asset_activity_id group by ejct.transaction_id order by ejct.transaction_id desc) where rownum = 1;
2456 
2457               exception when no_data_found then
2458                 l_last_scheduled_start_date := g_sysdate;
2459                 l_last_scheduled_end_date := g_sysdate;
2460                 l_lsi_updated := 'Y';
2461                 x_activities :=l_act_name;
2462                   end;
2463 
2464                if l_transaction_id is not null then
2465                 begin
2466 
2467                 SELECT wdj.scheduled_start_date,
2468                 wdj.scheduled_completion_date,wdj.wip_entity_id
2469                 into l_last_scheduled_start_date,l_last_scheduled_end_date,l_wip_entity_id
2470                 FROM eam_job_completion_txns ejct, wip_discrete_jobs wdj WHERE wdj.primary_item_id=l_asset_activity_id
2471                 and
2472                 wdj.maintenance_object_id=l_maintenance_object_id and
2473                 ejct.transaction_id=l_transaction_id and ejct.transaction_type=1 and
2474                 ejct.wip_entity_id=wdj.wip_entity_id;
2475 
2476                 exception when no_data_found then
2477                 l_last_scheduled_start_date := g_sysdate;
2478                 l_last_scheduled_end_date := g_sysdate;
2479                 l_lsi_updated := 'Y';
2480                 x_activities :=l_act_name;
2481                 end;
2482             end if;
2483 
2484                    UPDATE mtl_eam_asset_activities meaa
2485                    SET meaa.last_scheduled_start_date = l_last_scheduled_start_date,
2486                    meaa.last_scheduled_end_date    = l_last_scheduled_end_date,
2487            meaa.wip_entity_id=l_wip_entity_id,
2488            last_update_date=sysdate, last_updated_by=fnd_global.user_id, creation_date=sysdate,
2489                  last_update_login=fnd_global.login_id, created_by = fnd_global.user_id
2490                    WHERE (meaa.last_scheduled_start_date is null OR
2491                         meaa.last_scheduled_end_date is null) AND
2492                         meaa.activity_association_id = p_pm_activity_grp_rec.activity_association_id;
2493 
2494         end if;
2495 
2496     end if;
2497 
2498 --in case of runtime rules check for last service reading.if not insert the same with default values
2499     i:=1;
2500     if (p_pm_schedule_rec.tmpl_flag='N') then
2501             while (p_pm_runtime_rules_tbl.exists(i)) loop
2502 
2503                 select count(*) into l_count
2504                 from eam_pm_last_service
2505                 where meter_id=p_pm_runtime_rules_tbl(i).meter_id
2506                 and activity_association_id=p_pm_activity_grp_rec.activity_association_id;
2507 
2508                 if (l_count = 0) then
2509 
2510             INSERT INTO eam_pm_last_service (activity_association_id, meter_id,
2511                         last_service_reading, last_update_date, last_updated_by, creation_date,
2512                     last_update_login, created_by)
2513             VALUES (p_pm_activity_grp_rec.activity_association_id,
2514                     p_pm_runtime_rules_tbl(i).meter_id,
2515                 nvl(p_pm_runtime_rules_tbl(i).last_service_reading, 0),
2516                         sysdate,
2517                 fnd_global.user_id,
2518                 sysdate,
2519                     fnd_global.login_id,
2520                 fnd_global.user_id);
2521 
2522                 l_lsi_updated := 'Y';
2523                 x_activities :=l_act_name;
2524                     end if;
2525             i:=i+1;
2526         end loop;
2527       end if;
2528 
2529 -- set name is unique for this asset activity association and for this type of tmpl_flag
2530 -- (at most one template and one definition for each asset activity association)
2531 
2532     /* Bug # 3890075 : Modified the logic so that the query is executed only once. */
2533         BEGIN
2534 
2535        select eps.pm_schedule_id into l_pm_schedule_id from
2536            eam_pm_schedulings eps,eam_pm_activities epa
2537        where eps.pm_schedule_id=epa.pm_schedule_id
2538        and epa.activity_association_id=p_pm_activity_grp_rec.activity_association_id
2539        and eps.set_name_id=p_pm_schedule_rec.set_name_id
2540        and eps.tmpl_flag=p_pm_schedule_rec.tmpl_flag;
2541 
2542            if (p_pm_schedule_rec.pm_schedule_id is null) then
2543            -- If it's not an update action
2544         x_reason_failed:='EAM_PM_HD_NOT_UNIQUE_SET_NAME';
2545         return false;
2546        else
2547         -- it's an update action
2548         if (l_pm_schedule_id <> p_pm_schedule_rec.pm_schedule_id) then
2549            x_reason_failed:='EAM_PM_HD_NOT_UNIQUE_SET_NAME';
2550            return false;
2551         end if;
2552 
2553            end if;
2554 
2555     EXCEPTION
2556        WHEN NO_DATA_FOUND THEN
2557               null;
2558            WHEN TOO_MANY_ROWS THEN
2559           x_reason_failed:='EAM_PM_HD_NOT_UNIQUE_SET_NAME';
2560               return false;
2561     END;
2562 
2563 -- activity validation: there can be only one default
2564 
2565     if (p_pm_schedule_rec.default_implement is not null and p_pm_schedule_rec.default_implement='Y') then
2566 
2567        /* Bug # 3890075 : Modified the logic so that the query is executed only once. */
2568            BEGIN
2569 
2570           select eps.pm_schedule_id into l_pm_schedule_id from
2571                  eam_pm_schedulings eps,eam_pm_activities epa
2572           where eps.pm_schedule_id=epa.pm_schedule_id
2573           and epa.activity_association_id=p_pm_activity_grp_rec.activity_association_id
2574           and eps.default_implement = 'Y'
2575           and eps.tmpl_flag=p_pm_schedule_rec.tmpl_flag;
2576 
2577         -- If there is one default, check if it is the same one
2578         -- as the one that's being validated.
2579                    if (p_pm_schedule_rec.pm_schedule_id is null) then
2580                       x_reason_failed:='EAM_PM_HD_NOT_UNIQUE_DEFAULT';
2581                       return false;
2582                    else
2583                    if (l_pm_schedule_id <> p_pm_schedule_rec.pm_schedule_id) then
2584                          x_reason_failed:='EAM_PM_HD_NOT_UNIQUE_DEFAULT';
2585                          return false;
2586                    end if;
2587         end if;
2588 
2589        EXCEPTION
2590             WHEN NO_DATA_FOUND THEN
2591                    null;
2592         WHEN TOO_MANY_ROWS THEN
2593            x_reason_failed:='EAM_PM_HD_NOT_UNIQUE_DEFAULT';
2594            return false;
2595        END;
2596     end if;
2597 
2598     --For list dates pm schedule activity cyclic attributes should have default values
2599 
2600     if p_pm_schedule_rec.TYPE_CODE = 20 and
2601        (p_pm_activity_grp_rec.interval_multiple > 1 or p_pm_activity_grp_rec.allow_repeat_in_cycle <> 'N') then
2602 
2603         x_reason_failed := 'EAM_PM_HD_LIST_DATES_VLD';
2604         return false;
2605 
2606     end if;
2607 
2608         if l_lsi_updated = 'Y' then
2609          x_message := 'EAM_PM_LAST_SERVICE_DEFAULT';
2610     end if;
2611 
2612     return true;
2613 
2614 end validate_pm_activity;
2615 
2616 --this will be called from instantiation api
2617 
2618 function validate_pm_activity
2619 (
2620         p_pm_activity_grp_rec                   IN      pm_activities_grp_rec_type,
2621     p_pm_schedule_rec            IN    PM_Scheduling_Rec_Type,
2622     x_reason_failed            OUT NOCOPY     varchar2
2623 ) return BOOLEAN
2624 
2625 is
2626 l_pm_schedule_id        number;
2627 l_last_service_start_date     date;
2628 l_last_service_end_date         date;
2629 i number;
2630 begin
2631 
2632 -- activity validation: Check that the asset activity has last service reading start/end date.
2633 
2634     if (p_pm_schedule_rec.tmpl_flag='N') then
2635 
2636             select last_service_start_date, last_service_end_date
2637         into l_last_service_start_date, l_last_service_end_date
2638             from mtl_eam_asset_activities
2639             where activity_association_id=p_pm_activity_grp_rec.activity_association_id;
2640 
2641         if (l_last_service_start_date is null or l_last_service_end_date is null) then
2642             x_reason_failed:='EAM_PM_HD_ACT_NO_SERVICE_DATE';
2643             return false;
2644         end if;
2645 
2646     end if;
2647 
2648     --For list dates pm schedule activity cyclic attributes should have default values
2649 
2650     if p_pm_schedule_rec.TYPE_CODE = 20 and
2651        (p_pm_activity_grp_rec.interval_multiple > 1 or p_pm_activity_grp_rec.allow_repeat_in_cycle <> 'N') then
2652 
2653         x_reason_failed := 'EAM_PM_HD_LIST_DATES_VLD';
2654         return false;
2655 
2656     end if;
2657 
2658 -- set name is unique for this asset activity association and for this type of tmpl_flag
2659 -- (at most one template and one definition for each asset activity association)
2660 
2661     /* Bug # 3890075 : Modified the logic so that the query is executed only once. */
2662         BEGIN
2663 
2664        select eps.pm_schedule_id into l_pm_schedule_id from
2665            eam_pm_schedulings eps,eam_pm_activities epa
2666        where eps.pm_schedule_id=epa.pm_schedule_id
2667        and epa.activity_association_id=p_pm_activity_grp_rec.activity_association_id
2668        and eps.set_name_id=p_pm_schedule_rec.set_name_id
2669        and eps.tmpl_flag=p_pm_schedule_rec.tmpl_flag;
2670 
2671            if (p_pm_schedule_rec.pm_schedule_id is null) then
2672            -- If it's not an update action
2673         x_reason_failed:='EAM_PM_HD_NOT_UNIQUE_SET_NAME';
2674         return false;
2675        else
2676         -- it's an update action
2677         if (l_pm_schedule_id <> p_pm_schedule_rec.pm_schedule_id) then
2678            x_reason_failed:='EAM_PM_HD_NOT_UNIQUE_SET_NAME';
2679            return false;
2680         end if;
2681 
2682            end if;
2683 
2684     EXCEPTION
2685        WHEN NO_DATA_FOUND THEN
2686               null;
2687            WHEN TOO_MANY_ROWS THEN
2688           x_reason_failed:='EAM_PM_HD_NOT_UNIQUE_SET_NAME';
2689               return false;
2690     END;
2691 
2692 -- activity validation: there can be only one default
2693 
2694     if (p_pm_schedule_rec.default_implement is not null and p_pm_schedule_rec.default_implement='Y') then
2695 
2696        /* Bug # 3890075 : Modified the logic so that the query is executed only once. */
2697            BEGIN
2698 
2699           select eps.pm_schedule_id into l_pm_schedule_id from
2700                  eam_pm_schedulings eps,eam_pm_activities epa
2701           where eps.pm_schedule_id=epa.pm_schedule_id
2702           and epa.activity_association_id=p_pm_activity_grp_rec.activity_association_id
2703           and eps.default_implement = 'Y'
2704           and eps.tmpl_flag=p_pm_schedule_rec.tmpl_flag;
2705 
2706         -- If there is one default, check if it is the same one
2707         -- as the one that's being validated.
2708                    if (p_pm_schedule_rec.pm_schedule_id is null) then
2709                       x_reason_failed:='EAM_PM_HD_NOT_UNIQUE_DEFAULT';
2710                       return false;
2711                    else
2712                    if (l_pm_schedule_id <> p_pm_schedule_rec.pm_schedule_id) then
2713                          x_reason_failed:='EAM_PM_HD_NOT_UNIQUE_DEFAULT';
2714                          return false;
2715                    end if;
2716         end if;
2717 
2718        EXCEPTION
2719             WHEN NO_DATA_FOUND THEN
2720                    null;
2721         WHEN TOO_MANY_ROWS THEN
2722            x_reason_failed:='EAM_PM_HD_NOT_UNIQUE_DEFAULT';
2723            return false;
2724        END;
2725     end if;
2726 
2727     return true;
2728 
2729 end validate_pm_activity;
2730 
2731 function validate_pm_activities
2732 (      p_pm_activities_grp_tbl           IN      pm_activities_grp_tbl_type,
2733        p_pm_runtime_rules_tbl         IN      pm_rule_tbl_type,
2734        p_pm_schedule_rec               IN      pm_scheduling_rec_type,
2735        x_reason_failed               OUT NOCOPY varchar2,
2736        x_message                   OUT NOCOPY varchar2,
2737        x_activities                OUT NOCOPY varchar2
2738  ) return boolean
2739  is
2740   i                number;
2741   l_validated            boolean;
2742   l_reason_failed        varchar2(30);
2743   l_pm_activities_grp_rec       pm_activities_grp_rec_type;
2744   l_message varchar2(30);
2745   l_activity     varchar2(50);
2746 begin
2747         --added so that the LSI defaulting happens consistenly for all the activities consitently bug:4768304
2748     g_sysdate := sysdate;
2749     i:=1;   -- counter for all activities
2750 
2751     if ( p_pm_activities_grp_tbl.count = 0 ) then
2752        x_reason_failed:='EAM_PM_NO_ACT';
2753        return false;
2754     end if;
2755 
2756         while (p_pm_activities_grp_tbl.exists(i))        loop
2757 
2758         -- check for reschedule manual work order option applicable only
2759         --in case of single activity PM
2760 
2761         if i > 1 and p_pm_schedule_rec.include_manual='Y' then
2762         x_reason_failed := 'EAM_PM_HD_RESCHED_MAN_NA';
2763         return false;
2764         end if;
2765 
2766             l_pm_activities_grp_rec:=p_pm_activities_grp_tbl(i);
2767 
2768         l_validated:=validate_pm_activity(l_pm_activities_grp_rec, p_pm_runtime_rules_tbl,p_pm_schedule_rec,l_reason_failed,l_message,l_activity);
2769 
2770         if (not l_validated) then
2771         x_reason_failed := l_reason_failed;
2772         return false;
2773         end if;
2774 
2775         if (l_validated) and l_message is not null then
2776             x_message := l_message;
2777         if(x_activities is null ) then
2778            x_activities := l_activity;
2779         else
2780            x_activities := x_activities ||' , ' || l_activity;
2781         end if;
2782             end if;
2783 
2784         i:= i+1;
2785 
2786     end loop;
2787     return true;
2788 end;
2789 
2790 
2791 procedure sort_table_by_date
2792 (
2793     p_date_table             IN    pm_date_tbl_type,
2794     p_num_rows            IN     number,
2795     x_sorted_date_table        OUT NOCOPY     pm_date_tbl_type
2796 )
2797 is
2798 
2799     i         number;
2800     j        number;
2801     l_min_index    number;
2802     l_temp_date_rec    pm_date_rec_type;
2803 
2804 begin
2805     x_sorted_date_table:=p_date_table;
2806     for i in 1..p_num_rows loop
2807         l_min_index:=i;
2808         for j in i+1..p_num_rows loop
2809             if x_sorted_date_table(j).date1 < x_sorted_date_table(l_min_index).date1 then
2810                 l_min_index:=j;
2811             end if;
2812         end loop;
2813         l_temp_date_rec:=x_sorted_date_table(i);
2814         x_sorted_date_table(i):=x_sorted_date_table(l_min_index);
2815         x_sorted_date_table(l_min_index):=l_temp_date_rec;
2816     end loop;
2817 end;
2818 
2819 
2820 procedure sort_table_by_number
2821 (
2822         p_num_table                    IN      pm_num_tbl_type,
2823         p_num_rows                      IN      number,
2824         x_sorted_num_table             OUT NOCOPY     pm_num_tbl_type
2825 )
2826 is
2827 
2828         i               number;
2829         j               number;
2830         l_min_index     number;
2831         l_temp_num_rec     pm_num_rec_type;
2832 
2833 begin
2834         x_sorted_num_table:=p_num_table;
2835         for i in 1..p_num_rows loop
2836                 l_min_index:=i;
2837                 for j in i+1..p_num_rows loop
2838                         if x_sorted_num_table(j).num1 < x_sorted_num_table(l_min_index).num1 then
2839                                 l_min_index:=j;
2840                         end if;
2841                 end loop;
2842                 l_temp_num_rec:=x_sorted_num_table(i);
2843                 x_sorted_num_table(i):=x_sorted_num_table(l_min_index);
2844                 x_sorted_num_table(l_min_index):=l_temp_num_rec;
2845         end loop;
2846 end;
2847 
2848 
2849 -- merge two rule tables; p_rules_tbl1 overrides p_rules_tbl2
2850 procedure merge_rules
2851 (p_rules_tbl1           IN      pm_rule_tbl_type,
2852 p_rules_tbl2            IN      pm_rule_tbl_type,
2853 x_merged_rules_tbl      OUT NOCOPY     pm_rule_tbl_type)
2854 is
2855     i        number;
2856     j        number;
2857     l_num_tbl1    pm_num_tbl_type;
2858     l_sorted_num_tbl1    pm_num_tbl_type;
2859 begin
2860     i:=1;
2861     while (p_rules_tbl1.exists(i)) loop
2862         if (p_rules_tbl1(i).rule_id is not null) then
2863             l_num_tbl1(i).index1:=i;
2864             l_num_tbl1(i).num1:=p_rules_tbl1(i).rule_id;
2865             l_num_tbl1(i).other:=1;
2866         end if;
2867         i:=i+1;
2868     end loop;
2869 
2870     while (p_rules_tbl2.exists(i)) loop
2871         if (p_rules_tbl2(i).rule_id is not null) then
2872             l_num_tbl1(i).index1:=i;
2873             l_num_tbl1(i).num1:=p_rules_tbl2(i).rule_id;
2874             l_num_tbl1(i).other:=2;
2875         end if;
2876         i:=i+1;
2877     end loop;
2878 
2879     sort_table_by_number(l_num_tbl1, i-1, l_sorted_num_tbl1);
2880 
2881     i:=1;     -- counter for the sorted number table
2882     j:=1;     -- counter for the merged rules table; j<=i at any time
2883     while (l_num_tbl1.exists(i)) loop
2884         if (i>1 and l_num_tbl1(i).index1=l_num_tbl1(i-1).index1
2885                and l_num_tbl1(i).other=1) then
2886             x_merged_rules_tbl(j):=p_rules_tbl1(l_num_tbl1(i).index1);
2887         else
2888             j:=j+1;
2889         end if;
2890 
2891         if (l_num_tbl1(i).other=1) then
2892             x_merged_rules_tbl(j):=p_rules_tbl1(l_num_tbl1(i).index1);
2893         else   -- if l_num_tbl1(i).other=2
2894             x_merged_rules_tbl(j):=p_rules_tbl2(l_num_tbl1(i).index1);
2895         end if;
2896         i:=i+1;
2897     end loop;
2898 
2899 end;
2900 
2901 --this will be called by pm form and also called from the new api update_pm_last_cyclic_act
2902 
2903 procedure get_pm_last_activity
2904 (    p_pm_schedule_id        IN     NUMBER,
2905      p_activity_association_id  OUT NOCOPY NUMBER,
2906      x_return_status        OUT NOCOPY VARCHAR2,
2907      x_msg_count                     OUT NOCOPY     NUMBER ,
2908      x_msg_data                      OUT NOCOPY     VARCHAR2
2909  )
2910 is
2911 
2912 l_rescheduling_point number;
2913 l_last_service_date date;
2914 l_act_assoc_id number;
2915 l_current_seq number;
2916 l_msg_data varchar2(2000);
2917 l_error_message varchar2(2000);
2918 
2919 
2920 BEGIN
2921 x_return_status:='S';
2922 -- Check that enough info is supplied to identify which pm schedule to copy from.
2923     if (p_pm_schedule_id is null) then
2924         FND_MESSAGE.SET_NAME ('EAM', 'EAM_MT_SUPPLY_PARAMS');
2925                 FND_MSG_PUB.Add;
2926                 RAISE FND_API.G_EXC_ERROR;
2927     end if;
2928 
2929 --getting the scheduling option for the pm schedule
2930 
2931 select rescheduling_point,current_seq into l_rescheduling_point,l_current_seq
2932 from eam_pm_schedulings
2933 where pm_schedule_id = p_pm_schedule_id;
2934 
2935 --mandatory checking for rescheduling and current interval values
2936     if (l_rescheduling_point is null) then
2937         FND_MESSAGE.SET_NAME ('EAM', 'EAM_PM_NO_RESCHED');
2938                 FND_MSG_PUB.Add;
2939                 RAISE FND_API.G_EXC_ERROR;
2940     end if;
2941 
2942     if (l_current_seq is null) then
2943         FND_MESSAGE.SET_NAME ('EAM', 'EAM_PM_NO_CURRENTSEQ');
2944                 FND_MSG_PUB.Add;
2945                 RAISE FND_API.G_EXC_ERROR;
2946     end if;
2947 
2948 --based on current sequence retrieve
2949 
2950 if l_current_seq > 0 then
2951 
2952 --based on scheduling option retrieve the last service date
2953 
2954     if (l_rescheduling_point in (1,5,6)) then
2955 
2956         select max(meaa.last_service_start_date) into l_last_service_date
2957         from mtl_eam_asset_activities meaa, eam_pm_activities epa, eam_pm_schedulings eps
2958         where epa.activity_association_id=meaa.activity_association_id and
2959         epa.pm_schedule_id=eps.pm_schedule_id and eps.pm_schedule_id=p_pm_schedule_id and
2960         ((epa.ALLOW_REPEAT_IN_CYCLE='N' and epa.interval_multiple=eps.current_seq) or
2961         (epa.ALLOW_REPEAT_IN_CYCLE='Y' and mod(eps.current_seq, epa.interval_multiple)=0));
2962 
2963         elsif (l_rescheduling_point = 2) then
2964 
2965         select max(meaa.last_service_end_date) into l_last_service_date
2966         from mtl_eam_asset_activities meaa, eam_pm_activities epa, eam_pm_schedulings eps
2967         where epa.activity_association_id=meaa.activity_association_id and
2968         epa.pm_schedule_id=eps.pm_schedule_id and eps.pm_schedule_id=p_pm_schedule_id and
2969         ((epa.ALLOW_REPEAT_IN_CYCLE='N' and epa.interval_multiple=eps.current_seq) or
2970         (epa.ALLOW_REPEAT_IN_CYCLE='Y' and mod(eps.current_seq, epa.interval_multiple)=0));
2971 
2972          elsif (l_rescheduling_point = 3) then
2973 
2974         select max(meaa.last_scheduled_start_date) into l_last_service_date
2975         from mtl_eam_asset_activities meaa, eam_pm_activities epa, eam_pm_schedulings eps
2976         where epa.activity_association_id=meaa.activity_association_id and
2977         epa.pm_schedule_id=eps.pm_schedule_id and eps.pm_schedule_id=p_pm_schedule_id and
2978         ((epa.ALLOW_REPEAT_IN_CYCLE='N' and epa.interval_multiple=eps.current_seq) or
2979         (epa.ALLOW_REPEAT_IN_CYCLE='Y' and mod(eps.current_seq, epa.interval_multiple)=0));
2980 
2981          elsif (l_rescheduling_point = 4) then
2982 
2983         select max(meaa.last_scheduled_end_date) into l_last_service_date
2984         from mtl_eam_asset_activities meaa, eam_pm_activities epa, eam_pm_schedulings eps
2985         where epa.activity_association_id=meaa.activity_association_id and
2986         epa.pm_schedule_id=eps.pm_schedule_id and eps.pm_schedule_id=p_pm_schedule_id and
2987         ((epa.ALLOW_REPEAT_IN_CYCLE='N' and epa.interval_multiple=eps.current_seq) or
2988         (epa.ALLOW_REPEAT_IN_CYCLE='Y' and mod(eps.current_seq, epa.interval_multiple)=0));
2989 
2990     end if;
2991 
2992 
2993 elsif l_current_seq = 0 then
2994 
2995     if (l_rescheduling_point in (1,5,6)) then
2996 
2997         select max(meaa.last_service_start_date) into l_last_service_date
2998         from mtl_eam_asset_activities meaa, eam_pm_activities epa, eam_pm_schedulings eps
2999         where epa.activity_association_id=meaa.activity_association_id and
3000         epa.pm_schedule_id=eps.pm_schedule_id and eps.pm_schedule_id=p_pm_schedule_id;
3001 
3002         elsif (l_rescheduling_point = 2) then
3003 
3004         select max(meaa.last_service_end_date) into l_last_service_date
3005         from mtl_eam_asset_activities meaa, eam_pm_activities epa, eam_pm_schedulings eps
3006         where epa.activity_association_id=meaa.activity_association_id and
3007         epa.pm_schedule_id=eps.pm_schedule_id and eps.pm_schedule_id=p_pm_schedule_id;
3008 
3009          elsif (l_rescheduling_point = 3) then
3010 
3011         select max(meaa.last_scheduled_start_date) into l_last_service_date
3012         from mtl_eam_asset_activities meaa, eam_pm_activities epa, eam_pm_schedulings eps
3013         where epa.activity_association_id=meaa.activity_association_id and
3014         epa.pm_schedule_id=eps.pm_schedule_id and eps.pm_schedule_id=p_pm_schedule_id;
3015 
3016          elsif (l_rescheduling_point = 4) then
3017 
3018         select max(meaa.last_scheduled_end_date) into l_last_service_date
3019         from mtl_eam_asset_activities meaa, eam_pm_activities epa, eam_pm_schedulings eps
3020         where epa.activity_association_id=meaa.activity_association_id and
3021         epa.pm_schedule_id=eps.pm_schedule_id and eps.pm_schedule_id=p_pm_schedule_id;
3022 
3023     end if;
3024 
3025 end if;
3026 
3027 --based on last service date get the last activity association id of the
3028 --lowest interval multiple activity in case of a tie
3029 
3030 select * into l_act_assoc_id from (
3031  SELECT  meaa.activity_association_id  FROM mtl_eam_asset_activities meaa, eam_pm_activities epa
3032  WHERE decode(l_rescheduling_point,2,last_service_end_date ,3,last_scheduled_start_date, 4,last_scheduled_end_date ,last_service_start_date)
3033  = l_last_service_date
3034  AND meaa.activity_association_id = epa.activity_association_id AND epa.pm_schedule_id = p_pm_schedule_id
3035  order by interval_multiple
3036  )
3037  where rownum=1 ;
3038 
3039 --assigning the last activity
3040 p_activity_association_id := l_act_assoc_id;
3041 
3042 EXCEPTION
3043        WHEN FND_API.G_EXC_ERROR THEN
3044                 x_return_status := FND_API.G_RET_STS_ERROR ;
3045                 FND_MSG_PUB.get
3046                 (       p_msg_index_out                 =>      x_msg_count             ,
3047                                 p_data                  =>      x_msg_data
3048                 );
3049         x_msg_data := substr(x_msg_data,1,2000);
3050     WHEN OTHERS THEN
3051        x_msg_count := 1;
3052        x_return_status := fnd_api.g_ret_sts_error;
3053            l_error_message := substrb(sqlerrm,1,512);
3054            x_msg_data      := l_error_message;
3055 END get_pm_last_activity;
3056 
3057 --this will be called by work order completion
3058 
3059 
3060 procedure update_pm_last_cyclic_act
3061 (       p_api_version                   IN      NUMBER ,
3062         p_init_msg_list                 IN      VARCHAR2 := FND_API.G_FALSE     ,
3063         p_commit                        IN      VARCHAR2 := FND_API.G_FALSE ,
3064         p_validation_level              IN      NUMBER  := FND_API.G_VALID_LEVEL_FULL ,
3065         x_return_status             OUT NOCOPY     VARCHAR2                        ,
3066         x_msg_count                     OUT NOCOPY     NUMBER ,
3067         x_msg_data                      OUT NOCOPY     VARCHAR2 ,
3068     p_pm_schedule_id        IN     NUMBER
3069  )
3070 
3071 is
3072 l_api_name            CONSTANT VARCHAR2(30)    :='update_pm_last_cyclic_act';
3073 l_api_version               CONSTANT NUMBER         := 1.0;
3074 x_error_message         VARCHAR2(2000);
3075 
3076 l_rescheduling_point number;
3077 l_last_service_date date;
3078 l_act_assoc_id number;
3079 l_pm_schedule_id number;
3080 l_return_status            varchar2(1);
3081 l_msg_count number;
3082 l_msg_data varchar2(2000);
3083 l_get_failed varchar2(1);
3084 
3085 BEGIN
3086 
3087 l_pm_schedule_id := p_pm_schedule_id;
3088 -- Standard Start of API savepoint
3089 SAVEPOINT update_pm_last_cyclic_act;
3090 
3091 x_return_status := FND_API.G_RET_STS_SUCCESS;
3092 
3093 --mandatory checking
3094 if (p_pm_schedule_id is null) then
3095     FND_MESSAGE.SET_NAME ('EAM', 'EAM_PM_SCHEDULE_ID_MISSING');
3096         FND_MSG_PUB.Add;
3097         RAISE FND_API.G_EXC_ERROR;
3098 end if;
3099 
3100 --call to get the last activity of the pm schedule
3101 
3102 eam_pmdef_pub.get_pm_last_activity(p_pm_schedule_id => l_pm_schedule_id,
3103                      p_activity_association_id =>l_act_assoc_id,
3104              x_return_status => l_return_status,
3105              x_msg_count => l_msg_count,
3106                      x_msg_data  => l_msg_data);
3107 
3108 if l_return_status <> FND_API.G_RET_STS_SUCCESS then
3109             l_get_failed := 'Y';
3110             RAISE FND_API.G_EXC_ERROR;
3111 end if;
3112 
3113 -- updating the eam_last_cyclic_act field
3114 
3115 update eam_pm_schedulings set EAM_LAST_CYCLIC_ACT = l_act_assoc_id,
3116                              last_update_date=sysdate,
3117                  last_updated_by=fnd_global.user_id,
3118                  creation_date=sysdate,
3119                            last_update_login=fnd_global.login_id,
3120                  created_by = fnd_global.user_id where
3121 pm_schedule_id = p_pm_schedule_id;
3122 
3123 --standard commit to be checked
3124 
3125 IF FND_API.To_Boolean( p_commit ) THEN
3126         COMMIT WORK;
3127 END IF;
3128 
3129 EXCEPTION
3130 
3131     WHEN FND_API.G_EXC_ERROR THEN
3132         ROLLBACK TO update_pm_last_cyclic_act;
3133         x_return_status := FND_API.G_RET_STS_ERROR ;
3134 
3135         if l_get_failed = 'Y' then
3136             x_msg_count := l_msg_count;
3137             x_msg_data := l_msg_data;
3138         else
3139             FND_MSG_PUB.get
3140             (      p_msg_index_out             =>      x_msg_count         ,
3141                 p_data              =>      x_msg_data
3142             );
3143             x_msg_data := substr(x_msg_data,1,2000);
3144         end if;
3145     WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
3146         ROLLBACK TO update_pm_last_cyclic_act;
3147         x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
3148         FND_MSG_PUB.get
3149             (      p_msg_index_out             =>      x_msg_count         ,
3150                     p_data              =>      x_msg_data
3151             );
3152         x_msg_data := substr(x_msg_data,1,2000);
3153     WHEN OTHERS THEN
3154         ROLLBACK TO update_pm_last_cyclic_act;
3155         x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
3156           IF     FND_MSG_PUB.Check_Msg_Level
3157             (FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR)
3158         THEN
3159                 FND_MSG_PUB.Add_Exc_Msg
3160                     (    G_PKG_NAME          ,
3161                         l_api_name
3162                 );
3163         END IF;
3164         FND_MSG_PUB.get
3165             (      p_msg_index_out             =>      x_msg_count         ,
3166                     p_data              =>      x_msg_data
3167             );
3168         x_msg_data := substr(x_msg_data,1,2000);
3169 END update_pm_last_cyclic_act;
3170 
3171 procedure update_pm_last_service_reading
3172 (       p_api_version                   IN      NUMBER ,
3173         p_init_msg_list                 IN      VARCHAR2 := FND_API.G_FALSE     ,
3174         p_commit                        IN      VARCHAR2 := FND_API.G_FALSE ,
3175         p_validation_level              IN      NUMBER  := FND_API.G_VALID_LEVEL_FULL ,
3176         x_return_status             OUT NOCOPY     VARCHAR2                        ,
3177         x_msg_count                     OUT NOCOPY     NUMBER ,
3178         x_msg_data                      OUT NOCOPY     VARCHAR2 ,
3179     p_pm_schedule_id        IN     NUMBER
3180  )
3181 is
3182 l_api_name            CONSTANT VARCHAR2(30)    :='update_pm_last_service_reading';
3183 l_api_version               CONSTANT NUMBER         := 1.0;
3184 x_error_message         VARCHAR2(2000);
3185 
3186 l_rescheduling_point number;
3187 l_last_service_date date;
3188 l_act_assoc_id number;
3189 l_pm_schedule_id number;
3190 l_return_status            varchar2(1);
3191 lsr number;
3192 l_msg_count number;
3193 l_msg_data varchar2(2000);
3194 l_get_failed varchar2(1);
3195 
3196 cursor c_pm_runtime_rule is
3197     select pm_schedule_id,
3198         meter_id,
3199         rule_id
3200     from eam_pm_scheduling_rules
3201     where pm_schedule_id = l_pm_schedule_id
3202     and rule_type = 2;
3203 
3204 BEGIN
3205 
3206 l_pm_schedule_id := p_pm_schedule_id;
3207 
3208 -- Standard Start of API savepoint
3209 SAVEPOINT update_pm_last_service_reading;
3210 
3211 x_return_status := FND_API.G_RET_STS_SUCCESS;
3212 
3213 --mandatory checking
3214 
3215 if (p_pm_schedule_id is null) then
3216     FND_MESSAGE.SET_NAME ('EAM', 'EAM_PM_SCHEDULE_ID_MISSING');
3217         FND_MSG_PUB.Add;
3218         RAISE FND_API.G_EXC_ERROR;
3219 end if;
3220 
3221 --call to get the last activity of the pm schedule
3222 
3223 eam_pmdef_pub.get_pm_last_activity(p_pm_schedule_id => l_pm_schedule_id,
3224                      p_activity_association_id =>l_act_assoc_id,
3225              x_return_status => l_return_status,
3226              x_msg_count => l_msg_count,
3227                      x_msg_data  => l_msg_data);
3228 
3229 if l_return_status <> FND_API.G_RET_STS_SUCCESS then
3230             l_get_failed := 'Y';
3231             RAISE FND_API.G_EXC_ERROR;
3232 end if;
3233 
3234 --get the last service reading and update the same in epsr
3235 
3236 for runtime_rec in c_pm_runtime_rule loop
3237 
3238     select last_service_reading into lsr
3239     from eam_pm_last_service
3240     where meter_id = runtime_rec.meter_id and activity_association_id = l_act_assoc_id;
3241 
3242     update eam_pm_scheduling_rules set last_service_reading = lsr,
3243                  last_update_date=sysdate,
3244                  last_updated_by=fnd_global.user_id,
3245                  creation_date=sysdate,
3246                            last_update_login=fnd_global.login_id,
3247                  created_by = fnd_global.user_id
3248     where pm_schedule_id=runtime_rec.pm_schedule_id and
3249     meter_id = runtime_rec.meter_id and
3250     rule_id = runtime_rec.rule_id;
3251 
3252  end loop;
3253 
3254 --standard commit to be checked
3255 IF FND_API.To_Boolean( p_commit ) THEN
3256         COMMIT WORK;
3257 END IF;
3258 
3259 EXCEPTION
3260     WHEN FND_API.G_EXC_ERROR THEN
3261         ROLLBACK TO update_pm_last_service_reading;
3262         x_return_status := FND_API.G_RET_STS_ERROR ;
3263         if l_get_failed = 'Y' then
3264             x_msg_count := l_msg_count;
3265             x_msg_data := l_msg_data;
3266         else
3267             FND_MSG_PUB.get
3268             (      p_msg_index_out             =>      x_msg_count         ,
3269                     p_data              =>      x_msg_data
3270             );
3271             x_msg_data := substr(x_msg_data,1,2000);
3272         end if;
3273     WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
3274         ROLLBACK TO update_pm_last_service_reading;
3275         x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
3276         FND_MSG_PUB.get
3277             (      p_msg_index_out             =>      x_msg_count         ,
3278                     p_data              =>      x_msg_data
3279             );
3280         x_msg_data := substr(x_msg_data,1,2000);
3281     WHEN OTHERS THEN
3282         ROLLBACK TO update_pm_last_service_reading;
3283         x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
3284           IF     FND_MSG_PUB.Check_Msg_Level
3285             (FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR)
3286         THEN
3287                 FND_MSG_PUB.Add_Exc_Msg
3288                     (    G_PKG_NAME          ,
3289                         l_api_name
3290                 );
3291         END IF;
3292         FND_MSG_PUB.get
3293             (      p_msg_index_out             =>      x_msg_count         ,
3294                     p_data              =>      x_msg_data
3295             );
3296         x_msg_data := substr(x_msg_data,1,2000);
3297 END update_pm_last_service_reading;
3298 
3299 
3300 
3301 
3302 END;
3303