DBA Data[Home] [Help]

PACKAGE BODY: APPS.JTF_BRM_PVT

Source


1 PACKAGE BODY JTF_BRM_PVT AS
2 /* $Header: jtfvbrmb.pls 120.2.12010000.2 2008/11/05 06:01:37 rkamasam ship $ */
3 
4 -----------------------------------------------------------------------------
5 --
6 -- PROCEDURE selector
7 --
8 -- Determine which process to run.
9 --
10 -- IN
11 --   itemtype  - type of the current item
12 --   itemkey   - key of the current item
13 --   actid     - process activity instance id
14 --   funcmode  - function execution mode. this is set by the engine
15 --               as either 'RUN', 'CANCEL', 'TIMEOUT'
16 -- OUT
17 --   result    - name of Workflow process to run
18 --
19 PROCEDURE selector
20 (
21   itemtype  IN     VARCHAR2,
22   itemkey   IN     VARCHAR2,
23   actid     IN     NUMBER,
24   funcmode  IN     VARCHAR2,
25   result    IN OUT NOCOPY VARCHAR2
26 ) IS
27   --
28 BEGIN
29   --
30   -- RUN mode - normal process execution
31   --
32   IF (funcmode = 'RUN') THEN
33     result  := 'MONITOR_RULES';
34     RETURN;
35   END IF;
36   --
37 EXCEPTION
38   WHEN OTHERS THEN
39     wf_core.context('JTF_BRM_PVT', 'SELECTOR',
40                     itemtype, itemkey, to_char(actid), funcmode);
41     RAISE;
42 END selector;
43 -----------------------------------------------------------------------------
44 --
45 -- FUNCTION init_monitor
46 --
47 -- Create an instance of the Business Rule Monitor, initialize it, and
48 -- start the instance.  Return TRUE if successful; otherwise return FALSE.
49 --
50 -- IN
51 --   itemkey     - key of the current item
52 --   uom_type    - unit of measure type for timer interval
53 --   uom_code    - unit of measure code for timer interval
54 --   timer_units - number of units for timer interval
55 -- OUT
56 --   TRUE        - success
57 --   FALSE       - failure
58 --
59 FUNCTION init_monitor
60 (
61   itemkey        IN NUMBER,
62   uom_type       IN VARCHAR2,
63   uom_code       IN VARCHAR2,
64   timer_units    IN NUMBER
65 ) RETURN BOOLEAN IS
66   --
67   l_itemtype VARCHAR2(10) := 'JTFBRM';
68   l_itemkey  VARCHAR2(100);
69   l_admin    VARCHAR2(80) := FND_PROFILE.Value(name => 'JTF_BRM_WF_ADMINISTRATOR');
70 
71   --
72 BEGIN
73   --
74   IF itemkey IS NULL OR uom_type IS NULL OR
75      uom_code IS NULL OR timer_units IS NULL OR
76      l_admin IS NULL THEN
77     RETURN FALSE;
78   END IF;
79   --
80   l_itemkey := to_char(itemkey);
81   --
82   wf_engine.CreateProcess(
83             itemtype => l_itemtype,
84             itemkey  => l_itemkey,
85             process  => 'MONITOR_RULES');
86   --
87   wf_engine.SetItemAttrText(
88       itemtype => l_itemtype,
89       itemkey  => l_itemkey,
90             aname    => 'WF_ADMINISTRATOR',
91       avalue   => l_admin);
92   --
93   wf_engine.SetItemOwner(
94             itemtype => l_itemtype,
95             itemkey  => l_itemkey,
96             owner    => l_admin);
97   --
98   wf_engine.SetItemAttrText(
99             itemtype => l_itemtype,
100             itemkey  => l_itemkey,
101             aname    => 'UOM_TYPE',
102             avalue   => uom_type);
103   --
104   wf_engine.SetItemAttrText(
105             itemtype => l_itemtype,
106             itemkey  => l_itemkey,
107             aname    => 'UOM_CODE',
108             avalue   => uom_code);
109   --
110   wf_engine.SetItemAttrNumber(
111             itemtype => l_itemtype,
112             itemkey  => l_itemkey,
113             aname    => 'TIMER_UNITS',
114             avalue   => timer_units);
115   --
116   wf_engine.SetItemAttrDate(
117             itemtype => l_itemtype,
118             itemkey  => l_itemkey,
119             aname    => 'MONITOR_START_TIME',
120             avalue   => SYSDATE);
121   --
122   wf_engine.StartProcess(
123             itemtype => l_itemtype,
124             itemkey  => l_itemkey);
125   --
126   COMMIT;
127   RETURN TRUE;
128   --
129 EXCEPTION
130   WHEN OTHERS THEN
131     wf_core.context('JTF_BRM_PVT', 'INIT_MONITOR');
132     raise;
133 END init_monitor;
134 -----------------------------------------------------------------------------
135 --
136 -- PROCEDURE start_monitor
137 --
138 -- Set the START command and PROCESS_ID item attributes and update the
139 -- record in the JTF_BRM_PARAMETERS table to indicate the start of the
140 -- Business Rule Monitor.  The WORKFLOW_PROCESS_ID is set to be the same
141 -- as the itemkey.
142 --
143 -- IN
144 --   itemtype  - type of the current item
145 --   itemkey   - key of the current item
146 --   actid     - process activity instance id
147 --   funcmode  - function execution mode. this is set by the engine
148 --               as either 'RUN', 'CANCEL', 'TIMEOUT'
149 -- OUT
150 --   result    - activity has completed with the indicated result:
151 --
152 --               COMPLETE:NOERROR
153 --               COMPLETE:NONCRITICAL
154 --               COMPLETE:CRITICAL
155 --
156 PROCEDURE start_monitor
157 (
158   itemtype  IN     VARCHAR2,
159   itemkey   IN     VARCHAR2,
160   actid     IN     NUMBER,
161   funcmode  IN     VARCHAR2,
162   result    IN OUT NOCOPY VARCHAR2
163 ) IS
164   --
165   l_api_version      NUMBER      := 1.0;
166   l_init_msg_list    VARCHAR2(1) := fnd_api.g_true;
167   l_commit           VARCHAR2(1) := fnd_api.g_false;
168   l_validation_level NUMBER      := fnd_api.g_valid_level_full;
169   l_return_status    VARCHAR2(1);
170   l_msg_count        NUMBER;
171   l_msg_data         VARCHAR2(2000);
172   l_bp_rec           JTF_BRMParameter_PVT.BRM_Parameter_rec_type;
173   l_found            BOOLEAN;
174   --
175   CURSOR c_parameters IS
176     SELECT *
177     FROM   jtf_brm_parameters
178     WHERE  parameter_id = 1;
179   --
180 BEGIN
181   --
182   -- RUN mode - normal process execution
183   --
184   IF (funcmode = 'RUN') THEN
185     --
186     wf_engine.SetItemAttrText(
187               itemtype => itemtype,
188               itemkey  => itemkey,
189               aname    => 'SUBPROCESS_NAME',
190               avalue   => 'START_MONITOR');
191     --
192     wf_engine.SetItemAttrText(
193               itemtype => itemtype,
194               itemkey  => itemkey,
195               aname    => 'COMMAND_TYPE',
196               avalue   => 'JTF_BRM_WF_COMMAND_TYPE');
197     --
198     wf_engine.SetItemAttrText(
199               itemtype => itemtype,
200               itemkey  => itemkey,
201               aname    => 'COMMAND_CODE',
202               avalue   => 'START');
203     --
204     wf_engine.SetItemAttrText(
205               itemtype => itemtype,
206               itemkey  => itemkey,
207               aname    => 'COMMAND',
208               avalue   => 'START');
209     --
210     wf_engine.SetItemAttrText(
211               itemtype => itemtype,
212               itemkey  => itemkey,
213               aname    => 'PROCESS_ID',
214               avalue   => itemkey);
215     --
216     -- Update columns in the JTF_BRM_PARAMETERS table to indicate
217     -- the start of the Business Rule Monitor.  But first select the
218     -- record so as not to overwrite good data.
219     --
220     OPEN  c_parameters;
221     FETCH c_parameters INTO l_bp_rec;
222     l_found := c_parameters%FOUND;
223     CLOSE c_parameters;
224     --
225     IF NOT l_found THEN
226       result := 'COMPLETE:CRITICAL';
227       RETURN;
228     END IF;
229     --
230     l_bp_rec.workflow_process_id   := itemkey;
231     l_bp_rec.workflow_item_type    := 'JTFBRM';
232     l_bp_rec.workflow_process_name := 'MONITOR_RULES';
233     l_bp_rec.brm_wf_command_type   := 'JTF_BRM_WF_COMMAND_TYPE';
234     l_bp_rec.brm_wf_command_code   := 'START';
235     --
236     JTF_BRMParameter_PVT.Update_BRMParameter(
237       p_api_version      => l_api_version,
238       p_init_msg_list    => l_init_msg_list,
239       p_commit           => l_commit,
240       p_validation_level => l_validation_level,
241       x_return_status    => l_return_status,
242       x_msg_count        => l_msg_count,
243       x_msg_data         => l_msg_data,
244       p_bp_rec           => l_bp_rec);
245     --
246     IF l_msg_count > 0 THEN
247       result := 'COMPLETE:CRITICAL';
248       RETURN;
249     END IF;
250     result := 'COMPLETE:NOERROR';
251     RETURN;
252   END IF;
253   --
254   -- CANCEL mode - activity 'compensation'
255   --
256   IF (funcmode = 'CANCEL') THEN
257     result := 'COMPLETE:NOERROR';
258     RETURN;
259   END IF;
260   --
261   -- TIMEOUT mode
262   --
263   IF (funcmode = 'TIMEOUT') THEN
264     result := 'COMPLETE:NOERROR';
265     RETURN;
266   END IF;
267   --
268 EXCEPTION
269   WHEN OTHERS THEN
270     IF c_parameters%ISOPEN THEN
271       CLOSE c_parameters;
272     END IF;
273     wf_core.context('JTF_BRM_PVT', 'START_MONITOR',
274                     itemtype, itemkey, to_char(actid), funcmode);
275     RAISE;
276 END start_monitor;
277 -----------------------------------------------------------------------------
278 --
279 -- PROCEDURE calculate_interval
280 --
281 -- Get the number of hours or minutes for the timer interval and convert to
282 -- <days>.<fraction_of_a_day>.  Set the timer interval.
283 --
284 -- IN
285 --   itemtype  - type of the current item
286 --   itemkey   - key of the current item
287 --   actid     - process activity instance id
288 --   funcmode  - function execution mode. this is set by the engine
289 --               as either 'RUN', 'CANCEL', 'TIMEOUT'
290 -- OUT
291 --   result    - activity has completed with the indicated result:
292 --
293 --               COMPLETE:NOERROR
294 --               COMPLETE:NONCRITICAL
295 --               COMPLETE:CRITICAL
296 --
297 PROCEDURE calculate_interval
298 (
299   itemtype  IN     VARCHAR2,
300   itemkey   IN     VARCHAR2,
301   actid     IN     NUMBER,
302   funcmode  IN     VARCHAR2,
303   result    IN OUT NOCOPY VARCHAR2
304 ) IS
305   l_uom_type       fnd_lookups.lookup_type%TYPE;
306   l_uom_code       fnd_lookups.lookup_code%TYPE;
307   l_timer_units    NUMBER;
308   l_timer_interval NUMBER;
309   l_meaning        fnd_lookups.meaning%TYPE;
310   l_conversion     NUMBER;
311   l_found          BOOLEAN;
312   l_now            DATE := SYSDATE;
313   --
314   CURSOR c_lookups(b_uom_type fnd_lookups.lookup_type%TYPE,
315                    b_uom_code fnd_lookups.lookup_code%TYPE,
316                    b_now      DATE) IS
317     SELECT meaning
318     FROM   fnd_lookups
319     WHERE  lookup_type        = b_uom_type
320     AND    lookup_code        = b_uom_code
321     AND    enabled_flag       = 'Y'
322     AND    start_date_active <= b_now
323     AND    nvl(end_date_active, b_now) >= b_now;
324   --
325 BEGIN
326   --
327   -- RUN mode - normal process execution
328   --
329   IF (funcmode = 'RUN') THEN
330     --
331     wf_engine.SetItemAttrText(
332               itemtype => itemtype,
333               itemkey  => itemkey,
334               aname    => 'SUBPROCESS_NAME',
335               avalue   => 'CALCULATE_INTERVAL');
336     --
337     -- Get the timer unit of measure, and the number of units.
338     --
339     l_uom_type := wf_engine.GetItemAttrText(
340                             itemtype => itemtype,
341                             itemkey  => itemkey,
342                             aname    => 'UOM_TYPE');
343     --
344     l_uom_code := wf_engine.GetItemAttrText(
345                             itemtype => itemtype,
346                             itemkey  => itemkey,
347                             aname    => 'UOM_CODE');
348     --
349     l_timer_units := wf_engine.GetItemAttrNumber(
350                                itemtype => itemtype,
351                                itemkey  => itemkey,
352                                aname    => 'TIMER_UNITS');
353     --
354     IF l_uom_type IS NULL OR l_uom_code IS NULL OR l_timer_units IS NULL THEN
355       result := 'COMPLETE:CRITICAL';
356       RETURN;
357     END IF;
358     --
359     OPEN  c_lookups(l_uom_type, l_uom_code, l_now);
360     FETCH c_lookups
361     INTO  l_meaning;
362     l_found := c_lookups%FOUND;
363     CLOSE c_lookups;
364     --
365     IF NOT l_found THEN
366       result := 'COMPLETE:CRITICAL';
367       RETURN;
368     END IF;
369     --
370     -- Convert interval to days.
371     --
372     IF l_uom_code = 'HOURS' THEN
373       l_timer_interval := l_timer_units / 24;
374     ELSIF l_uom_code = 'MINUTES' THEN
375       l_timer_interval := l_timer_units / 1440;
376     ELSE
377       result := 'COMPLETE:CRITICAL';
378       RETURN;
379     END IF;
380     --
381     wf_engine.SetItemAttrNumber(
382               itemtype => itemtype,
383               itemkey  => itemkey,
384               aname    => 'TIMER_INTERVAL',
385               avalue   => l_timer_interval);
386     --
387     result := 'COMPLETE:NOERROR';
388     RETURN;
389   END IF;
390   --
391   -- CANCEL mode - activity 'compensation'
392   --
393   IF (funcmode = 'CANCEL') THEN
394     result := 'COMPLETE:NOERROR';
395     RETURN;
396   END IF;
397   --
398   -- TIMEOUT mode
399   --
400   IF (funcmode = 'TIMEOUT') THEN
401     result := 'COMPLETE:NOERROR';
402     RETURN;
403   END IF;
404   --
405 EXCEPTION
406   WHEN OTHERS THEN
407     IF c_lookups%ISOPEN THEN
408       CLOSE c_lookups;
409     END IF;
410     wf_core.context('JTF_BRM_PVT', 'CALCULATE_INTERVAL',
411                     itemtype, itemkey, to_char(actid), funcmode);
412     RAISE;
413 END calculate_interval;
414 -----------------------------------------------------------------------------
415 --
416 -- FUNCTION get_activity_id
417 --
418 -- Return a unique ID for an activity.
419 --
420 FUNCTION get_activity_id RETURN NUMBER IS
421   --
422   CURSOR c_activity IS
423     SELECT jtf_brm_activities_s.nextval
424     FROM   DUAL;
425   l_activity_id NUMBER;
426   --
427 BEGIN
428   OPEN   c_activity;
429   FETCH  c_activity INTO l_activity_id;
430   CLOSE  c_activity;
431   RETURN l_activity_id;
432 EXCEPTION
433   WHEN OTHERS THEN
434     IF c_activity%ISOPEN THEN
435       CLOSE c_activity;
436     END IF;
437 END;
438 -----------------------------------------------------------------------------
439 --
440 -- PROCEDURE process_rules
441 --
442 -- Get the active business rules and process them.
443 --
444 -- IN
445 --   itemtype  - type of the current item
446 --   itemkey   - key of the current item
447 --   actid     - process activity instance id
448 --   funcmode  - function execution mode. this is set by the engine
449 --               as either 'RUN', 'CANCEL', 'TIMEOUT'
450 -- OUT
451 --   result    - activity has completed with the indicated result:
452 --
453 --               COMPLETE:NOERROR
454 --               COMPLETE:NONCRITICAL
455 --               COMPLETE:CRITICAL
456 --
457 PROCEDURE process_rules
458 (
459   itemtype  IN     VARCHAR2,
460   itemkey   IN     VARCHAR2,
461   actid     IN     NUMBER,
462   funcmode  IN     VARCHAR2,
463   result    IN OUT NOCOPY VARCHAR2
464 ) IS
465   CURSOR c_active_rules(b_now DATE) IS
466     SELECT jbr.view_name,
467            jbr.rule_id,
468            jbp.rowid,
469            jbp.workflow_item_type,
470            jbp.workflow_process_name
471     FROM   jtf_brm_processes jbp,
472            jtf_brm_rules_vl  jbr
473     WHERE  jbp.rule_id = jbr.rule_id
474     AND    nvl(jbr.start_date_active, b_now + 1) <= b_now
475     AND    nvl(jbr.end_date_active, b_now)       >= b_now
476     AND    nvl(jbp.brm_uom_type,'JTF_BRM_UOM_TYPE')   = 'JTF_BRM_UOM_TYPE'
477     AND    nvl(jbp.last_brm_check_date, b_now - 100) +
478            (jbp.brm_check_interval / decode(jbp.brm_check_uom_code,
479                                             'MINUTES', 1440,
480                                             'HOURS', 24)) <= b_now
481     AND    jbr.view_name IS NOT NULL
482     and    jbp.workflow_item_type is not null;
483   --
484   TYPE cur_type IS REF CURSOR;
485   c_object         cur_type;
486   l_active_rules   c_active_rules%ROWTYPE;
487   l_found          BOOLEAN;
488   l_view           VARCHAR2(30);
489   l_object_type    VARCHAR2(30);
490   l_object_id      NUMBER;
491   l_now            DATE := SYSDATE;
492   l_query          VARCHAR2(1000);
493   l_activity_id    NUMBER;
494   l_save_threshold NUMBER;
495   --
496 BEGIN
497   --
498   -- RUN mode - normal process execution
499   --
500   IF (funcmode = 'RUN') THEN
501     --
502     wf_engine.SetItemAttrText(
503               itemtype => itemtype,
504               itemkey  => itemkey,
505               aname    => 'SUBPROCESS_NAME',
506               avalue   => 'PROCESS_RULES');
507     --
508     wf_engine.SetItemAttrDate(
509               itemtype => itemtype,
510               itemkey  => itemkey,
511               aname    => 'PROCESS_RULES_START_TIME',
512               avalue   => l_now);
513     --
514     FOR i in c_active_rules(l_now) LOOP
515       --
516       -- Set the time the rule was last checked.
517       --
518       -- Get the object_type and object_id for each object in each view
519       -- and launch the appropriate Workflow activity.  The user-friendly
520       -- key will be <object_type><object_id>, e.g., DF13579.
521       --
522       UPDATE jtf_brm_processes
523       SET    last_brm_check_date = l_now
524       WHERE  rowid = i.rowid;
525       --
526       l_query := 'SELECT object_type, object_id FROM ' || i.view_name;
527       --
528       OPEN c_object FOR l_query;
529       LOOP
530         FETCH c_object INTO l_object_type, l_object_id;
531         EXIT WHEN c_object%NOTFOUND;
532         --
533         l_activity_id := get_activity_id;
534         --
535         -- Temporarily overriding the  defer threshold to make sure
536         -- the process is executed in the background.
537         --
538         l_save_threshold := WF_ENGINE.threshold;
539         WF_ENGINE.threshold := -1;
540         --
541         wf_engine.CreateProcess(
542                   itemtype => i.workflow_item_type,
543                   itemkey  => l_activity_id,
544                   process  => i.workflow_process_name);
545         --
546         wf_engine.SetItemUserKey(
547                   itemtype => i.workflow_item_type,
548                   itemkey  => l_activity_id,
549                   userkey  => l_object_type || to_char(l_object_id));
550         --
551         wf_engine.SetItemAttrText(
552                   itemtype => i.workflow_item_type,
553                   itemkey  => l_activity_id,
554                   aname    => 'PROCESS_ID',
555                   avalue   => itemkey);
556         --
557         wf_engine.SetItemAttrText(
558                   itemtype => i.workflow_item_type,
559                   itemkey  => l_activity_id,
560                   aname    => 'SUBPROCESS_NAME',
561                   avalue   => 'PROCESS_RULES');
562         --
563         wf_engine.SetItemAttrText(
564                   itemtype => i.workflow_item_type,
565                   itemkey  => l_activity_id,
566                   aname    => 'OBJECT_TYPE',
567                   avalue   => l_object_type);
568         --
569         wf_engine.SetItemAttrText(
570                   itemtype => itemtype,
571                   itemkey  => itemkey,
572                   aname    => 'OBJECT_TYPE',
573                   avalue   => l_object_type);
574         --
575         wf_engine.SetItemAttrNumber(
576                   itemtype => i.workflow_item_type,
577                   itemkey  => l_activity_id,
578                   aname    => 'OBJECT_ID',
579                   avalue   => l_object_id);
580         --
581         wf_engine.SetItemAttrNumber(
582                   itemtype => itemtype,
583                   itemkey  => itemkey,
584                   aname    => 'OBJECT_ID',
585                   avalue   => l_object_id);
586         --
587         wf_engine.SetItemAttrNumber(
588                   itemtype => i.workflow_item_type,
589                   itemkey  => l_activity_id,
590                   aname    => 'RULE_ID',
591                   avalue   => i.rule_id);
592         --
593         wf_engine.StartProcess(
594                   itemtype => i.workflow_item_type,
595                   itemkey  => l_activity_id);
596         --
597         -- Restoring the defer threshold
598         --
599         WF_ENGINE.threshold := l_save_threshold;
600 
601       END LOOP;
602       CLOSE c_object;
603     END LOOP;
604     --
605     wf_engine.SetItemAttrDate(
606               itemtype => itemtype,
607               itemkey  => itemkey,
608               aname    => 'PROCESS_RULES_STOP_TIME',
609               avalue   => SYSDATE);
610     --
611     result  := 'COMPLETE:NOERROR';
612     RETURN;
613   END IF;
614   --
615   -- CANCEL mode - activity 'compensation'
616   --
617   IF (funcmode = 'CANCEL') THEN
618     result := 'COMPLETE:NOERROR';
619     RETURN;
620   END IF;
621   --
622   -- TIMEOUT mode
623   --
624   IF (funcmode = 'TIMEOUT') THEN
625     result := 'COMPLETE:NOERROR';
626     RETURN;
627   END IF;
628   --
629 EXCEPTION
630   WHEN OTHERS THEN
631     IF c_object%ISOPEN THEN
632       CLOSE c_object;
633     END IF;
634     wf_core.context('JTF_BRM_PVT', 'PROCESS_RULES',
635                     itemtype, itemkey, to_char(actid), funcmode);
636     RAISE;
637 END process_rules;
638 -----------------------------------------------------------------------------
639 --
640 -- PROCEDURE check_interval
641 --
642 -- Check the difference between the timer interval and the actual interval
643 -- needed to process the current set of active business rules.  A negative
644 -- difference stops the Business Rule Monitor so that the timer interval can
645 -- be increased.  No difference or a positive difference sets the time to
646 -- wait before the next set of rules is processed.
647 --
648 -- IN
649 --   itemtype  - type of the current item
650 --   itemkey   - key of the current item
651 --   actid     - process activity instance id
652 --   funcmode  - function execution mode. this is set by the engine
653 --               as either 'RUN', 'CANCEL', 'TIMEOUT'
654 -- OUT
655 --   result    - activity has completed with the indicated result:
656 --
657 --               COMPLETE:NOERROR
658 --               COMPLETE:NONCRITICAL
659 --               COMPLETE:CRITICAL
660 --
661 PROCEDURE check_interval
662 (
663   itemtype  IN         VARCHAR2,
664   itemkey   IN         VARCHAR2,
665   actid     IN         NUMBER,
666   funcmode  IN         VARCHAR2,
667   result    IN OUT NOCOPY     VARCHAR2
668 ) IS
669   l_start_time         DATE;
670   l_timer_interval     NUMBER;
671   l_difference         NUMBER;
672   --
673 BEGIN
674   --
675   -- RUN mode - normal process execution
676   --
677   IF (funcmode = 'RUN') THEN
678     --
679     wf_engine.SetItemAttrText(
680               itemtype => itemtype,
681               itemkey  => itemkey,
682               aname    => 'SUBPROCESS_NAME',
683               avalue   => 'CHECK_INTERVAL');
684     --
685     -- Get the start time and the actual interval and compute the
686     -- difference between the timer interval and the actual interval.
687     --
688     l_start_time := wf_engine.GetItemAttrDate(
689                               itemtype => itemtype,
690                               itemkey  => itemkey,
691                               aname    => 'PROCESS_RULES_START_TIME');
692     --
693     l_timer_interval := wf_engine.GetItemAttrNumber(
694                                   itemtype => itemtype,
695                                   itemkey  => itemkey,
696                                   aname    => 'TIMER_INTERVAL');
697     --
698     IF l_start_time IS NULL OR l_timer_interval is NULL THEN
699       result := 'COMPLETE:NONCRITICAL';
700       RETURN;
701     END IF;
702     --
703     l_difference := l_timer_interval - (SYSDATE - l_start_time);
704     --
705     wf_engine.SetItemAttrNumber(
706               itemtype => itemtype,
707               itemkey  => itemkey,
708               aname    => 'INTERVAL_DIFF',
709               avalue   => l_difference);
710     --
711     --  A negative difference stops the Business Rule Monitor so that the
712     --  system administrator can increase the timer interval and restart it.
713     --
714     IF l_difference < 0 THEN
715       result := 'COMPLETE:CRITICAL';
716       RETURN;
717     ELSE
718       --
719       -- Time allotted was enough or more than enough.  Set the time to wait
720       -- before processing the next set of rules.
721       --
722       wf_engine.SetItemAttrNumber(
723                 itemtype => itemtype,
724                 itemkey  => itemkey,
725                 aname    => 'WAIT_TIME',
726                 avalue   => l_difference);
727       --
728       result := 'COMPLETE:NOERROR';
729       RETURN;
730     END IF;
731   END IF;
732   --
733   -- CANCEL mode - activity 'compensation'
734   --
735   IF (funcmode = 'CANCEL') THEN
736     result := 'COMPLETE:NOERROR';
737     RETURN;
738   END IF;
739   --
740   -- TIMEOUT mode
741   --
742   IF (funcmode = 'TIMEOUT') THEN
743     result := 'COMPLETE:NOERROR';
744     RETURN;
745   END IF;
746   --
747 EXCEPTION
748   WHEN OTHERS THEN
749     wf_core.context('JTF_BRM_PVT', 'CHECK_INTERVAL',
750                     itemtype, itemkey, to_char(actid), funcmode);
751     RAISE;
752 END check_interval;
753 -----------------------------------------------------------------------------
754 --
755 -- PROCEDURE get_brm_command
756 --
757 -- Get the current Business Rule Monitor command.
758 --
759 -- IN
760 --   itemtype  - type of the current item
761 --   itemkey   - key of the current item
762 --   actid     - process activity instance id
763 --   funcmode  - function execution mode. this is set by the engine
764 --               as either 'RUN', 'CANCEL', 'TIMEOUT'
765 -- OUT
766 --   result    - activity has completed with the indicated result:
767 --
768 --               COMPLETE:NOERROR
769 --               COMPLETE:NONCRITICAL
770 --               COMPLETE:CRITICAL
771 --
772 PROCEDURE get_brm_command
773 (
774   itemtype  IN     VARCHAR2,
775   itemkey   IN     VARCHAR2,
776   actid     IN     NUMBER,
777   funcmode  IN     VARCHAR2,
778   result    IN OUT NOCOPY VARCHAR2
779 ) IS
780   l_command_type fnd_lookups.lookup_type%TYPE;
781   l_command_code fnd_lookups.lookup_code%TYPE;
782   l_meaning      fnd_lookups.meaning%TYPE;
783   l_found        BOOLEAN;
784   l_now          DATE := SYSDATE;
785   --
786   CURSOR c_command IS
787     SELECT brm_wf_command_type, brm_wf_command_code
788     FROM   jtf_brm_parameters
789     WHERE  workflow_process_id = itemkey;
790   --
791   CURSOR c_lookups(b_command_type fnd_lookups.lookup_type%TYPE,
792                    b_command_code fnd_lookups.lookup_code%TYPE,
793                    b_now          DATE) IS
794     SELECT meaning
795     FROM   fnd_lookups
796     WHERE  lookup_type        = b_command_type
797     AND    lookup_code        = b_command_code
798     AND    enabled_flag       = 'Y'
799     AND    start_date_active <= b_now
800     AND    nvl(end_date_active, b_now) >= b_now;
801   --
802 BEGIN
803   --
804   -- RUN mode - normal process execution
805   --
806   IF (funcmode = 'RUN') THEN
807     --
808     wf_engine.SetItemAttrText(
809               itemtype => itemtype,
810               itemkey  => itemkey,
811               aname    => 'SUBPROCESS_NAME',
812               avalue   => 'GET_BRM_COMMAND');
813     --
814     OPEN  c_command;
815     FETCH c_command
816     INTO  l_command_type, l_command_code;
817     l_found := c_command%FOUND;
818     CLOSE c_command;
819     --
820     IF NOT l_found THEN
821       result := 'COMPLETE:CRITICAL';
822       RETURN;
823     ELSE
824       wf_engine.SetItemAttrText(
825                 itemtype => itemtype,
826                 itemkey  => itemkey,
827                 aname    => 'COMMAND_TYPE',
828                 avalue   => l_command_type);
829       --
830       wf_engine.SetItemAttrText(
831                 itemtype => itemtype,
832                 itemkey  => itemkey,
833                 aname    => 'COMMAND_CODE',
834                 avalue   => l_command_code);
835       --
836       OPEN  c_lookups(l_command_type, l_command_code, l_now);
837       FETCH c_lookups INTO l_meaning;
838       l_found := c_lookups%FOUND;
839       CLOSE c_lookups;
840       --
841       IF NOT l_found THEN
842         result := 'COMPLETE:CRITICAL';
843       ELSE
844         wf_engine.SetItemAttrText(
845                   itemtype => itemtype,
846                   itemkey  => itemkey,
847                   aname    => 'COMMAND',
848                   avalue   => l_meaning);
849         result := 'COMPLETE:NOERROR';
850       END IF;
851       RETURN;
852     END IF;
853   END IF;
854   --
855   -- CANCEL mode - activity 'compensation'
856   --
857   IF (funcmode = 'CANCEL') THEN
858     result := 'COMPLETE:NOERROR';
859     return;
860   END IF;
861   --
862   -- TIMEOUT mode
863   --
864   IF (funcmode = 'TIMEOUT') THEN
865     result := 'COMPLETE:NOERROR';
866     RETURN;
867   END IF;
868   --
869 EXCEPTION
870   WHEN OTHERS THEN
871     IF c_command%ISOPEN THEN
872       CLOSE c_command;
873     END IF;
874     IF c_lookups%ISOPEN THEN
875       CLOSE c_lookups;
876     END IF;
877     wf_core.context('JTF_BRM_PVT', 'GET_BRM_COMMAND',
878                     itemtype, itemkey, to_char(actid), funcmode);
879     RAISE;
880 END get_brm_command;
881 -----------------------------------------------------------------------------
882 --
883 -- PROCEDURE stop_monitor
884 --
885 -- Check if there is a request to stop the Business Rule Monitor.
886 -- If so, set the stop time for the process.
887 --
888 -- IN
889 --   itemtype  - type of the current item
890 --   itemkey   - key of the current item
891 --   actid     - process activity instance id
892 --   funcmode  - function execution mode. this is set by the engine
893 --               as either 'RUN', 'CANCEL', 'TIMEOUT'
894 -- OUT
895 --   result    - activity has completed with the indicated result:
896 --
897 --               COMPLETE:T
898 --               COMPLETE:F
899 --
900 PROCEDURE stop_monitor
901 (
902   itemtype  IN     VARCHAR2,
903   itemkey   IN     VARCHAR2,
904   actid     IN     NUMBER,
905   funcmode  IN     VARCHAR2,
906   result    IN OUT NOCOPY VARCHAR2
907 ) IS
908   l_command VARCHAR2(30);
909   --
910 BEGIN
911   --
912   -- RUN mode - normal process execution
913   --
914   IF (funcmode = 'RUN') THEN
915     --
916     wf_engine.SetItemAttrText(
917               itemtype => itemtype,
918               itemkey  => itemkey,
919               aname    => 'SUBPROCESS_NAME',
920               avalue   => 'STOP_MONITOR');
921     --
922     l_command := wf_engine.GetItemAttrText(
923                            itemtype => itemtype,
924                            itemkey  => itemkey,
925                            aname    => 'COMMAND_CODE');
926     --
927     IF l_command = 'STOP' THEN
928       wf_engine.SetItemAttrDate(
929                 itemtype => itemtype,
930                 itemkey  => itemkey,
931                 aname    => 'MONITOR_STOP_TIME',
932                 avalue   => SYSDATE);
933       --
934       result := 'COMPLETE:T';
935     ELSE
936       result := 'COMPLETE:F';
937     END IF;
938     RETURN;
939   END IF;
940   --
941   -- CANCEL mode - activity 'compensation'
942   --
943   IF (funcmode = 'CANCEL') THEN
944     result := 'COMPLETE:F';
945     RETURN;
946   END IF;
947   --
948   -- TIMEOUT mode
949   --
950   IF (funcmode = 'TIMEOUT') THEN
951     result := 'COMPLETE:T';
952     RETURN;
953   END IF;
954   --
955 EXCEPTION
956   WHEN OTHERS THEN
957     wf_core.context('JTF_BRM_PVT', 'STOP_MONITOR',
958                     itemtype, itemkey, to_char(actid), funcmode);
959     RAISE;
960 END stop_monitor;
961 -----------------------------------------------------------------------------
962 --
963 -- PROCEDURE commit_wf
964 --
965 -- commits all runtime WF-data for the complete scan cycle and resets the
966 -- wf_savepoint. This will prevent the rollback segments from growing to
967 -- rediculous size
968 --
969 -- IN
970 --   itemtype  - type of the current item
971 --   itemkey   - key of the current item
972 --   actid     - process activity instance id
973 --   funcmode  - function execution mode ('RUN', 'CANCEL', 'TIMEOUT')
974 -- OUT
975 --   result    - activity has completed with the indicated result:
976 --
977 --               COMPLETE:True
978 --               COMPLETE:False
979 --
980 PROCEDURE commit_wf(
981     itemtype  IN VARCHAR2,
982     itemkey   IN VARCHAR2,
983     actid     IN NUMBER,
984     funcmode  IN VARCHAR2,
985     result    IN OUT NOCOPY VARCHAR2)
986 IS
987 BEGIN
988   --
989   -- RUN mode - normal process execution
990   --
991   IF (funcmode = 'RUN')
992   THEN
993     COMMIT;
994     SAVEPOINT wf_savepoint;
995     result := 'COMPLETE:T';
996   ELSE
997     result := 'COMPLETE:F';
998   END IF;
999   RETURN;
1000 EXCEPTION
1001   WHEN OTHERS THEN
1002     wf_core.context('JTF_BRM_PVT', 'COMMIT_WF',
1003                     itemtype, itemkey, to_char(actid), funcmode);
1004     RAISE;
1005 END commit_wf;
1006 -----------------------------------------------------------------------------
1007 
1008 END JTF_BRM_PVT;