DBA Data[Home] [Help]

PACKAGE BODY: APPS.CSR_SCHEDULER_PVT

Source


1 PACKAGE BODY csr_scheduler_pvt AS
2 /* $Header: CSRVSCHB.pls 120.39 2011/05/02 10:45:58 anangupt ship $ */
3 
4   g_pkg_name            CONSTANT VARCHAR2(30) := 'CSR_SCHEDULER_PVT';
5   g_csr_appl_id         CONSTANT NUMBER       := 698;
6   g_conc_program_name   CONSTANT VARCHAR2(30) := 'SEARCH_AND_SCHEDULE_AUTO';
7 
8   g_auto_contract_flag  CONSTANT VARCHAR2(1)  := csr_scheduler_pub.get_sch_parameter_value('spPickContractResources');
9   g_auto_ib_flag        CONSTANT VARCHAR2(1)  := csr_scheduler_pub.get_sch_parameter_value('spPickIbResources');
10   g_auto_skills_flag    CONSTANT VARCHAR2(1)  := csr_scheduler_pub.get_sch_parameter_value('spPickSkilledResources');
11   g_auto_terr_flag      CONSTANT VARCHAR2(1)  := csr_scheduler_pub.get_sch_parameter_value('spPickTerritoryResources');
12   g_spares_source       CONSTANT VARCHAR2(30) := csr_scheduler_pub.get_sch_parameter_value('spSparesSource');
13   g_spares_mandatory    CONSTANT VARCHAR2(1)  := csr_scheduler_pub.get_sch_parameter_value('spSparesMandatory');
14   g_standby_shifts      CONSTANT VARCHAR2(30) := csr_scheduler_pub.get_sch_parameter_value('spConsiderStandbyShifts');
15 
16   TYPE ref_cursor_type IS REF CURSOR;
17 
18 
19   FUNCTION valid_argument(p_arg_value VARCHAR2, p_arg_name VARCHAR2, p_api_name VARCHAR2)
20     RETURN BOOLEAN IS
21   BEGIN
22     IF p_arg_value IS NULL THEN
23       fnd_message.set_name('CSR', 'CSR_MANDATORY_FIELD_MISSING');
24       fnd_message.set_token('FIELD', p_arg_name);
25       fnd_message.set_token('TASK', p_api_name);
26       fnd_msg_pub.ADD;
27       RETURN FALSE;
28     END IF;
29     RETURN TRUE;
30   END valid_argument;
31 
32 
33   /**
34    * Gets the Geocode of a Task.
35    *
36    * The API returns the Geocoded Geometry of the Task if the given Task has an address.
37    * If the Task is not yet Geocoded, then tries to resolve the Address of the Task by
38    * calling Location Finder.
39    *
40    * The Geocode is returned by stamping the values in the respective output parameters
41    * rather than as MDSYS.SDO_GEOMETRY itself because JDBC doesnt support PLSQL Record
42    * Types as of now.
43    *
44    * @param   p_api_version           API Version (1.0)
45    * @param   p_init_msg_list         Initialize Message List
46    * @param   p_commit                Commits the Work
47    * @param   x_return_status         Return Status of the Procedure.
48    * @param   x_msg_count             Number of Messages in the Stack.
49    * @param   x_msg_data              Stack of Error Messages.
50    * @param   p_task_id               Task ID
51    * @param   x_locus_segment_id      Segment ID of the Road in the Address's Geocode
52    * @param   x_locus_side            Side of the Road in the Address's Geocode
53    * @param   x_locus_spot            Offset in the Road in the Address's Geocode
54    * @param   x_locus_lat             Longitude of the Location in the Address's Geocode
55    * @param   x_locus_lon             Latitude of the Location in the Address's Geocode
56    * @param   x_should_call_lf        Should LF be called on the Address or not
57    * @param   x_location_id           Location ID of the Address.
58    * @param   x_srid                  Coordinate system id.
59    * @param   x_country_code          Country Code of the Address
60    */
61   PROCEDURE get_geometry(
62     p_api_version            IN              NUMBER
63   , p_init_msg_list          IN              VARCHAR2
64   , p_commit                 IN              VARCHAR2
65   , x_return_status          OUT NOCOPY      VARCHAR2
66   , x_msg_count              OUT NOCOPY      NUMBER
67   , x_msg_data               OUT NOCOPY      VARCHAR2
68   , p_task_id                IN              NUMBER
69   , x_locus_segment_id       OUT NOCOPY      NUMBER
70   , x_locus_side             OUT NOCOPY      NUMBER
71   , x_locus_spot             OUT NOCOPY      NUMBER
72   , x_locus_lat              OUT NOCOPY      NUMBER
73   , x_locus_lon              OUT NOCOPY      NUMBER
74   , x_should_call_lf         OUT NOCOPY      VARCHAR2
75   , x_location_id            OUT NOCOPY      NUMBER
76   , x_srid                   OUT NOCOPY      NUMBER
77   , x_country_code           OUT NOCOPY      VARCHAR2
78   ) IS
79     l_api_name      CONSTANT VARCHAR2(30)       := 'GET_GEOMETRY';
80     l_api_version   CONSTANT NUMBER             := 1.0;
81 
82     CURSOR c_address_info IS
83       SELECT l.location_id
84            , l.geometry
85            , l.house_number
86            , l.address1
87            , l.address2
88            , l.address3
89            , l.address4
90            , l.city
91            , l.state
92            , l.postal_code
93            , fnd.territory_short_name country
94            , l.country country_code
95            , l.geometry_status_code
96         FROM jtf_tasks_b t
97            , hz_locations l
98            , fnd_territories_vl fnd
99        WHERE t.task_id = p_task_id
100          AND l.location_id = csf_tasks_pub.get_task_location_id(t.task_id, t.address_id, t.location_id)
101          AND fnd.territory_code = l.country;
102 
103     l_address_info   c_address_info%ROWTYPE;
104     l_locus_valid    VARCHAR2(6);
105     l_geo_status_code hz_locations.geometry_status_code%TYPE;
106   BEGIN
107     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
108       RAISE fnd_api.g_exc_unexpected_error;
109     END IF;
110 
111     IF fnd_api.to_boolean(p_init_msg_list) THEN
112       fnd_msg_pub.initialize;
113     END IF;
114 
115     x_return_status := fnd_api.g_ret_sts_success;
116 
117     OPEN c_address_info;
118     FETCH c_address_info INTO l_address_info;
119     CLOSE c_address_info;
120 
121     -- The Task has no Address Information.
122     IF l_address_info.location_id IS NULL THEN
123       -- Need to throw with proper error message
124       RAISE fnd_api.g_exc_error;
125     END IF;
126 
127     l_geo_status_code := NVL(l_address_info.geometry_status_code, 'ERROR');
128 
129     IF l_address_info.geometry IS NULL
130        OR l_geo_status_code NOT IN ('GOOD', 'NOEXACTMATCH', 'MULTIMATCH')
131     THEN
132       l_locus_valid := 'FALSE';
133     ELSE
134       csf_locus_pub.verify_locus(
135         p_api_version                => 1
136       , x_msg_count                  => x_msg_count
137       , x_msg_data                   => x_msg_data
138       , x_return_status              => x_return_status
139       , p_locus                      => l_address_info.geometry
140       , x_result                     => l_locus_valid
141       );
142     END IF;
143 
144     -- Geocode of the Task is invalid. Try to Geocode the Task
145     IF l_locus_valid = 'FALSE' THEN
146       csf_resource_address_pvt.resolve_address(
147         p_api_version       => 1
148       , p_init_msg_list     => fnd_api.g_false
149       , x_return_status     => x_return_status
150       , x_msg_count         => x_msg_count
151       , x_msg_data          => x_msg_data
152       , p_location_id       => l_address_info.location_id
153       , p_building_num      => l_address_info.house_number
154       , p_address1          => l_address_info.address1
155       , p_address2          => l_address_info.address2
156       , p_address3          => l_address_info.address3
157       , p_address4          => l_address_info.address4
158       , p_state             => l_address_info.state
159       , p_city              => l_address_info.city
160       , p_postalcode        => l_address_info.postal_code
161       , p_country           => l_address_info.country
162       , p_country_code      => l_address_info.country_code
163       , x_geometry          => l_address_info.geometry
164       );
165       IF x_return_status = fnd_api.g_ret_sts_error THEN
166         RAISE fnd_api.g_exc_error;
167       ELSIF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
168         RAISE fnd_api.g_exc_unexpected_error;
169       END IF;
170     END IF;
171 
172     IF x_return_status = fnd_api.g_ret_sts_success AND l_address_info.geometry IS NOT NULL THEN
173       x_locus_segment_id := csf_locus_pub.get_locus_segmentid(l_address_info.geometry);
174       x_locus_side       := csf_locus_pub.get_locus_side(l_address_info.geometry);
175       x_locus_spot       := csf_locus_pub.get_locus_spot(l_address_info.geometry);
176       x_locus_lat        := csf_locus_pub.get_locus_lat(l_address_info.geometry);
177       x_locus_lon        := csf_locus_pub.get_locus_lon(l_address_info.geometry);
178       x_should_call_lf   := csf_locus_pub.should_call_lf(l_address_info.geometry);
179       x_location_id      := l_address_info.location_id;
180       x_srid             := csf_locus_pub.get_locus_srid(l_address_info.geometry);
181       x_country_code     := l_address_info.country_code;
182 
183       IF fnd_api.to_boolean(p_commit) THEN
184         COMMIT;
185       END IF;
186     END IF;
187   EXCEPTION
188     WHEN fnd_api.g_exc_error THEN
189       x_return_status := fnd_api.g_ret_sts_error;
190       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
191     WHEN fnd_api.g_exc_unexpected_error THEN
192       x_return_status := fnd_api.g_ret_sts_unexp_error;
193       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
194     WHEN OTHERS THEN
195       x_return_status := fnd_api.g_ret_sts_unexp_error;
196       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
197         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
198       END IF;
199       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
200   END get_geometry;
201 
202   /**
203    * Gets the Server Timezone configured in the E-Business Suite
204    *
205    * Gets the value of the profile SERVER_TIMEZONE_ID. Apparently SERVER_TIMEZONE_ID
206    * has been replaced by the profile SERVER_TIMEZONE. So if the former profile
207    * doesnt return any value, the API will try to return value of SERVER_TIMEZONE_ID.
208    *
209    * If either of the profiles doesnt return any value, then it returns the first
210    * profile satisfying the condition of being in GMT-8 Offset and also having
211    * Day Light Savings as Yes from HZ_TIMEZONES.
212    *
213    * @return Server Timezone ID (or Zero upon any exception).
214    */
215   FUNCTION get_server_timezone RETURN NUMBER IS
216     l_timezone_id      NUMBER;
217   BEGIN
218     fnd_profile.get('SERVER_TIMEZONE', l_timezone_id);
219     IF l_timezone_id IS NULL THEN
220       fnd_profile.get('SERVER_TIMEZONE_ID', l_timezone_id);
221     END IF;
222 
223     IF l_timezone_id IS NULL THEN
224       SELECT MIN(timezone_id)
225         INTO l_timezone_id
226         FROM hz_timezones
227        WHERE gmt_deviation_hours = -8
228          AND daylight_savings_time_flag = 'Y';
229     END IF;
230 
231     RETURN l_timezone_id;
232   EXCEPTION
233     WHEN OTHERS THEN
234       RETURN 0;
235   END;
236 
237   /**
238    * Returns the Time Zone Difference between the given Timezone
239    * and the Server Timezone in Half Hour Units
240    *
241    * @param  p_timezone_id   Timezone Identifier
242    * @return Difference in Half Hour Units
243    */
244   FUNCTION get_server_timezone_offset(p_timezone_id IN NUMBER)
245     RETURN NUMBER IS
246     l_offset_days  NUMBER;
247     l_server_date  DATE;
248   BEGIN
249     l_server_date        := hz_timezone_pub.convert_datetime(
250                               p_source_tz_id        => p_timezone_id
251                             , p_dest_tz_id          => get_server_timezone
252                             , p_source_day_time     => SYSDATE
253                             );
254     l_offset_days := l_server_date - SYSDATE;
255     RETURN TRUNC(l_offset_days * 48);  -- Output in half hours.
256   END get_server_timezone_offset;
257 
258 
259   /**
260    * Gets the Timezone corresponding to the given Address.
261    *
262    */
263   FUNCTION get_timezone(p_address_id IN NUMBER) RETURN NUMBER IS
264     CURSOR c_timezone IS
265       SELECT loc.timezone_id
266         FROM hz_party_sites par
267            , hz_locations loc
268        WHERE par.party_site_id = p_address_id
269          AND par.location_id = loc.location_id;
270 
271     l_timezone        c_timezone%ROWTYPE;
272     l_profile_value   VARCHAR2(50);
273   BEGIN
274     IF p_address_id IS NULL THEN
275       RETURN get_server_timezone;
276     ELSE
277       OPEN c_timezone;
278       FETCH c_timezone INTO l_timezone;
279       IF c_timezone%NOTFOUND THEN
280         CLOSE c_timezone;
281         RETURN get_server_timezone;
282       END IF;
283       CLOSE c_timezone;
284     END IF;
285     RETURN l_timezone.timezone_id;
286   END get_timezone;
287 
288   /**
289    * Converts the given Time from the given Timezone to Server Timezone.
290    *
291    * Calls GET_SERVER_TIMEZONE to get the Server Timezone Identifier.
292    * Note that only the Time Component of the given Time is taken and not the
293    * Date Component. The returned date has SYSDATE as the Date Component.
294    *
295    * Generally used by WTP to create the Window Slots properly converted from Task
296    * Timezone to Server Timezone.
297    *
298    * @param   p_time          Time to be converted to Server Timezone
299    * @param   p_timezone_id   Source Timezone Identifier
300    * @return  Time converted to Server Timezone.
301    */
302   FUNCTION convert_timezone(p_time IN DATE, p_timezone_id IN NUMBER)
303     RETURN DATE IS
304     l_return_status        VARCHAR2(1);
305     l_msg_count            NUMBER;
306     l_msg_data             VARCHAR2(2000);
307     l_server_timezone_id   NUMBER;
308     l_src_datetime         DATE;
309     l_dest_datetime        DATE;
310   BEGIN
311     l_src_datetime := TO_DATE(TO_CHAR( TRUNC(SYSDATE), 'DD-MM-YYYY') || TO_CHAR(p_time, 'HH24:MI')
312                                    , 'DD-MM-YYYY HH24:MI'
313                                    );
314 
315     hz_timezone_pub.get_time(p_api_version         => 1
316                            , p_init_msg_list       => fnd_api.g_false
317                            , x_return_status       => l_return_status
318                            , x_msg_count           => l_msg_count
319                            , x_msg_data            => l_msg_data
320                            , p_source_tz_id        => p_timezone_id
321                            , p_dest_tz_id          => get_server_timezone
322                            , p_source_day_time     => l_src_datetime
323                            , x_dest_day_time       => l_dest_datetime
324                             );
325     l_dest_datetime := TO_DATE( TO_CHAR(TRUNC(SYSDATE), 'DD-MM-YYYY') || TO_CHAR(l_dest_datetime, 'HH24:MI')
326                               , 'DD-MM-YYYY HH24:MI'
327                               );
328     RETURN l_dest_datetime;
329   END convert_timezone;
330 
331   /**
332    * This API Creates a scheduler search request
333 
334    * @param   p_api_version           	     API Version (1.0)
335    * @param   p_init_msg_list         	     Initialize Message List
336    * @param   p_commit                	     Commits the Work. This is set as true to allow Scheduler to see the new request created.
337    * @param   x_return_status         	     Return Status of the Procedure.
338    * @param   x_msg_count             	     Number of Messages in the Stack.
339    * @param   x_msg_data              	     Stack of Error Messages.
340    * @param   p_task_id               	     The task id for which the search request is being created.
341    * @param   The following set of parameters represents the qualifiers of resoucres for the task.
342                 1) p_contracts_flag
343                 2) p_ib_flag
344                 3) p_territory_flag
345                 4) p_skill_flag
346    * @param   p_resource_tbl          	     The set of resource to be considered for scheduling irrespective of their qualification.
347    * @param   p_request_name          	     Type of request to be created
348 	          One of the following request types are created
349                     1) SearchAssistedOptions
350                     2) SearchIntelligentOptions
351                     3) SearchWTPOptions
352    * @param   p_spares_mandatory       	      Is Spares Mandatory
353    * @param   p_spares_source          	      Spares Source to be used for this request
354    * @param   p_consider_standby_shifts       Should Standby Shifts be considered (ALWAYS, NEVER, DAY_WISE, REG_THEN_STANDBY)
355    * @param   p_route_based_flag      	      Flag to enable route based scheduling for this request
356    * @param   p_disabled_access_hours_flag    Activate access hours if any assigned for the task.
357    * @param   x_request_id                    Request id of created request
358 
359    * The API  first finds the set of qualified resoucres for the given task
360    * based on the qualifers given.
361    * It then creates appropriate serach request based on the request name
362    */
363   PROCEDURE create_search_request(
364     p_api_version                IN           NUMBER
365   , p_init_msg_list              IN           VARCHAR2
366   , p_commit                     IN           VARCHAR2
367   , x_return_status              OUT  NOCOPY  VARCHAR2
368   , x_msg_count                  OUT  NOCOPY  NUMBER
369   , x_msg_data                   OUT  NOCOPY  VARCHAR2
370   , p_request_name               IN           VARCHAR2
371   , p_task_id                    IN           NUMBER
372   , p_contracts_flag             IN           VARCHAR2
373   , p_ib_flag                    IN           VARCHAR2
374   , p_territory_flag             IN           VARCHAR2
375   , p_skill_flag                 IN           VARCHAR2
376   , p_resource_id_tbl            IN           jtf_number_table
377   , p_resource_type_tbl          IN           jtf_varchar2_table_100
378   , p_spares_mandatory           IN           VARCHAR2
379   , p_spares_source              IN           VARCHAR2
380   , p_consider_standby_shifts    IN           VARCHAR2
381   , p_route_based_flag           IN           VARCHAR2
382   , p_disabled_access_hours_flag IN           VARCHAR2
383   , x_request_id                 OUT  NOCOPY  NUMBER
384   ) IS
385     l_api_version  CONSTANT NUMBER       := 1.0;
386     l_api_name     CONSTANT VARCHAR2(30) := 'CREATE_SEARCH_REQUEST';
387 
388     l_res_qualifiers   csf_resource_pub.resource_qualifier_tbl_type;
389     l_res_tbl          csf_requests_pvt.resource_tbl_type;
390     j                  PLS_INTEGER;
391     k                  PLS_INTEGER;
392 
393     CURSOR c_task_info IS
394       SELECT planned_start_date, planned_end_date, source_object_id
395         FROM jtf_tasks_b
396        WHERE task_id = p_task_id;
397 
398     l_task_info           c_task_info%ROWTYPE;
399 
400   BEGIN
401     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
402       RAISE fnd_api.g_exc_unexpected_error;
403     END IF;
404 
405     IF fnd_api.to_boolean(p_init_msg_list) THEN
406       fnd_msg_pub.initialize;
407     END IF;
408 
409     x_return_status := fnd_api.g_ret_sts_success;
410 
411     -- Find the qualified resoucres for the task based on the given resoucer qualifiers
412 
413     OPEN c_task_info;
414     FETCH c_task_info INTO l_task_info;
415     IF c_task_info%NOTFOUND THEN
416       CLOSE c_task_info;
417       RAISE NO_DATA_FOUND;
418     END IF;
419     CLOSE c_task_info;
420 
421     -- Validate the Planned Window (same logic as that done in DC)
422     csf_tasks_pub.validate_planned_dates(l_task_info.planned_start_date, l_task_info.planned_end_date);
423 
424     csf_resource_pub.get_resources_to_schedule(
425       p_api_version             => 1
426     , p_init_msg_list           => fnd_api.g_false
427     , x_return_status           => x_return_status
428     , x_msg_count               => x_msg_count
429     , x_msg_data                => x_msg_data
430     , p_scheduling_mode         => 'X'       -- Auto Assign mode
431     , p_task_id                 => p_task_id
432     , p_incident_id             => l_task_info.source_object_id
433     , p_start                   => l_task_info.planned_start_date
434     , p_end                     => l_task_info.planned_end_date
435     , p_contracts_flag          => p_contracts_flag
436     , p_ib_flag                 => p_ib_flag
437     , p_territory_flag          => p_territory_flag
438     , p_skill_flag              => p_skill_flag
439     , p_res_qualifier_tbl       => l_res_qualifiers
440     , p_suggested_res_id_tbl    => p_resource_id_tbl
441     , p_suggested_res_type_tbl  => p_resource_type_tbl
442     , x_res_tbl                 => l_res_tbl
443     );
444 
445     -- Unless it is an Unexpected Error... continue even with
446     -- "No Resources Found" error. Java will do the proper error handling.
447     IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
448       RAISE fnd_api.g_exc_unexpected_error;
449     END IF;
450 
451     -- Create Scheduler Search Request based on the given information.
452     csf_requests_pvt.create_scheduler_request(
453       p_api_version                 => 1
454     , p_init_msg_list               => fnd_api.g_false
455     , p_commit                      => fnd_api.g_false
456     , x_return_status               => x_return_status
457     , x_msg_count                   => x_msg_count
458     , x_msg_data                    => x_msg_data
459     , p_name                        => p_request_name
460     , p_object_id                   => p_task_id
461     , p_resource_tbl                => l_res_tbl
462     , p_route_based_flag            => p_route_based_flag
463     , p_disabled_access_hours_flag  => p_disabled_access_hours_flag
464     , p_spares_mandatory            => p_spares_mandatory
465     , p_spares_source               => p_spares_source
466     , p_standby_param               => p_consider_standby_shifts
467     , x_request_id                  => x_request_id
468     );
469 
470     IF x_return_status = fnd_api.g_ret_sts_error THEN
471       RAISE fnd_api.g_exc_error;
472     ELSIF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
473       RAISE fnd_api.g_exc_unexpected_error;
474     END IF;
475 
476     IF fnd_api.to_boolean(p_commit) THEN
477       COMMIT;
478     END IF;
479 
480   EXCEPTION
481     WHEN fnd_api.g_exc_error THEN
482       x_return_status := fnd_api.g_ret_sts_error;
483       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
484     WHEN fnd_api.g_exc_unexpected_error THEN
485       x_return_status := fnd_api.g_ret_sts_unexp_error;
486       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
487     WHEN OTHERS THEN
488       x_return_status := fnd_api.g_ret_sts_unexp_error;
489       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
490         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
491       END IF;
492       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
493   END create_search_request;
494 
495   /**
496    * This API creates a request of type 'ScheduleOption'
497 
498    * @param   p_api_version           	 API Version (1.0)
499    * @param   p_init_msg_list         	 Initialize Message List
500    * @param   p_commit                	 Commits the Work. This is set as true to allow Scheduler to see the new request created.
501    * @param   x_return_status         	 Return Status of the Procedure.
502    * @param   x_msg_count             	 Number of Messages in the Stack.
503    * @param   x_msg_data              	 Stack of Error Messages.
504    * @param   p_plan_option_id           The id of the plan option to be scheduled
505    * @param   p_target_status_id     	 The status to which the task has to be changed after scheduling
506    * @param   p_set_plan_task_confirmed  Flag to indicate that customer confirmation has to be considered for the task.
507    * @param   x_request_id               Request id of created request
508 
509    * This API creates a scheduler request of type 'ScheduleOption'
510    * that is used to schedule the given plan option
511    */
512   PROCEDURE create_schedule_option_request(
513     p_api_version               IN  NUMBER
514   , p_init_msg_list             IN  VARCHAR2
515   , p_commit                    IN  VARCHAR2
516   , x_return_status             OUT  NOCOPY VARCHAR2
517   , x_msg_count                 OUT  NOCOPY NUMBER
518   , x_msg_data                  OUT  NOCOPY VARCHAR2
519   , p_plan_option_id            IN  NUMBER
520   , p_target_status_id          IN  NUMBER
521   , p_set_plan_task_confirmed   IN VARCHAR2
522   , x_request_id                OUT  NOCOPY NUMBER
523   ) IS
524     l_api_version  CONSTANT NUMBER       := 1.0;
525     l_api_name     CONSTANT VARCHAR2(30) := 'CREATE_SCHEDULE_OPTION_REQUEST';
526   BEGIN
527     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
528       RAISE fnd_api.g_exc_unexpected_error;
529     END IF;
530 
531     IF fnd_api.to_boolean(p_init_msg_list) THEN
532       fnd_msg_pub.initialize;
533     END IF;
534 
535     x_return_status := fnd_api.g_ret_sts_success;
536 
537     csf_requests_pvt.create_scheduler_request(
538       p_api_version                    => 1
539     , x_return_status                  => x_return_status
540     , x_msg_count                      => x_msg_count
541     , x_msg_data                       => x_msg_data
542     , p_name                           => 'ScheduleOption'
543     , p_object_id                      => p_plan_option_id
544     , p_status_id                      => p_target_status_id
545     , p_set_plan_task_confirmed        => p_set_plan_task_confirmed
546     , x_request_id                     => x_request_id
547     );
548 
549     IF x_return_status = fnd_api.g_ret_sts_error THEN
550       RAISE fnd_api.g_exc_error;
551     ELSIF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
552       RAISE fnd_api.g_exc_unexpected_error;
553     END IF;
554 
555     IF fnd_api.to_boolean(p_commit) THEN
556       COMMIT;
557     END IF;
558 
559   EXCEPTION
560     WHEN fnd_api.g_exc_error THEN
561       x_return_status := fnd_api.g_ret_sts_error;
562       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
563     WHEN fnd_api.g_exc_unexpected_error THEN
564       x_return_status := fnd_api.g_ret_sts_unexp_error;
565       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
566     WHEN OTHERS THEN
567       x_return_status := fnd_api.g_ret_sts_unexp_error;
568       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
569         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
570       END IF;
571       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
572   END create_schedule_option_request;
573 
574   PROCEDURE create_auto_request(
575     x_return_status   OUT NOCOPY VARCHAR2
576   , x_msg_count       OUT NOCOPY NUMBER
577   , x_msg_data        OUT NOCOPY VARCHAR2
578   , p_task_tbl        IN         csf_requests_pvt.object_tbl_type
579   , p_find_resources  IN         VARCHAR2 DEFAULT fnd_api.g_true
580   , x_request_id      OUT NOCOPY NUMBER
581   ) IS
582     l_api_name     CONSTANT VARCHAR2(30) := 'CREATE_AUTO_REQUEST';
583 
584     i                    PLS_INTEGER;
585     l_child_request_id   NUMBER;
586     l_res_tbl            csf_requests_pvt.resource_tbl_type;
587     l_res_qualifiers     csf_resource_pub.resource_qualifier_tbl_type;
588 
589     CURSOR c_task_info (p_task_id NUMBER) IS
590       SELECT t.task_id, t.planned_start_date, t.planned_end_date, t.source_object_id
591         FROM jtf_tasks_b t
592        WHERE t.task_id = p_task_id;
593 
594     l_task_info      c_task_info%ROWTYPE;
595   BEGIN
596     x_return_status := fnd_api.g_ret_sts_success;
597 
598 
599     IF p_task_tbl IS NULL OR p_task_tbl.COUNT <= 0 THEN
600       x_request_id := -1;
601       RETURN;
602     END IF;
603 
604 
605     -- Create the SearchAndScheduleAuto Request which will serve as
606     -- the Parent Request for the subsequents requests created for each Task.
607     csf_requests_pvt.create_scheduler_request(
608       p_api_version                    => 1
609     , p_init_msg_list                  => fnd_api.g_true
610     , p_commit                         => fnd_api.g_false
611     , x_return_status                  => x_return_status
612     , x_msg_count                      => x_msg_count
613     , x_msg_data                       => x_msg_data
614     , p_name                           => 'SearchAndScheduleAuto'
615     , p_object_id                      => -1
616     , x_request_id                     => x_request_id
617     );
618 
619     IF x_return_status <> fnd_api.g_ret_sts_success THEN
620       RAISE fnd_api.g_exc_error;
621     END IF;
622 
623 
624     -- For each task, create a SearchAndSchedule Request with Parent
625     -- Request being the Request created above.
626     i := p_task_tbl.FIRST;
627     WHILE i IS NOT NULL LOOP
628       IF p_find_resources = fnd_api.g_true THEN
629 
630         OPEN c_task_info(p_task_tbl(i));
631         FETCH c_task_info INTO l_task_info;
632         CLOSE c_task_info;
633 
634         -- Validate the Planned Window (same logic as that done in DC)
635         csf_tasks_pub.validate_planned_dates(l_task_info.planned_start_date, l_task_info.planned_end_date);
636 
637         -- Get the Resources for this Task.
638         csf_resource_pub.get_resources_to_schedule(
639           p_api_version             => 1
640         , p_init_msg_list           => fnd_api.g_false
641         , x_return_status           => x_return_status
642         , x_msg_count               => x_msg_count
643         , x_msg_data                => x_msg_data
644         , p_scheduling_mode         => 'X'       -- Auto Assign mode
645         , p_task_id                 => p_task_tbl(i)
646         , p_incident_id             => l_task_info.source_object_id
647         , p_start                   => l_task_info.planned_start_date
648         , p_end                     => l_task_info.planned_end_date
649         , p_contracts_flag          => g_auto_contract_flag
650         , p_ib_flag                 => g_auto_ib_flag
651         , p_territory_flag          => g_auto_terr_flag
652         , p_skill_flag              => g_auto_skills_flag
653         , p_res_qualifier_tbl       => l_res_qualifiers
654         , x_res_tbl                 => l_res_tbl
655         );
656 
657         -- Unless it is an Unexpected Error... continue even with
658         -- "No Resources Found" error. Java will do the proper error handling.
659         IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
660           RAISE fnd_api.g_exc_unexpected_error;
661         END IF;
662       END IF;
663 
664       csf_requests_pvt.create_scheduler_request(
665         p_api_version                    => 1
666       , p_init_msg_list                  => fnd_api.g_false
667       , p_commit                         => fnd_api.g_false
668       , x_return_status                  => x_return_status
669       , x_msg_count                      => x_msg_count
670       , x_msg_data                       => x_msg_data
671       , p_name                           => 'SearchAndSchedule'
672       , p_object_id                      => p_task_tbl(i)
673       , p_resource_tbl                   => l_res_tbl
674       , p_parent_id                      => x_request_id
675       , p_spares_mandatory               => g_spares_mandatory
676       , p_spares_source                  => g_spares_source
677       , p_standby_param                  => g_standby_shifts
678       , x_request_id                     => l_child_request_id
679       );
680 
681       i := p_task_tbl.NEXT(i);
682 
683     END LOOP;
684   EXCEPTION
685     WHEN fnd_api.g_exc_error THEN
686       x_return_status := fnd_api.g_ret_sts_error;
687       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
688     WHEN fnd_api.g_exc_unexpected_error THEN
689       x_return_status := fnd_api.g_ret_sts_unexp_error;
690       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
691     WHEN OTHERS THEN
692       x_return_status := fnd_api.g_ret_sts_unexp_error;
693       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
694         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
695       END IF;
696       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
697   END create_auto_request;
698 
699   PROCEDURE fill_request_resources(
700     p_api_version        IN              NUMBER
701   , p_init_msg_list      IN              VARCHAR2
702   , p_commit             IN              VARCHAR2
703   , x_return_status      OUT NOCOPY      VARCHAR2
704   , x_msg_count          OUT NOCOPY      NUMBER
705   , x_msg_data           OUT NOCOPY      VARCHAR2
706   , p_request_id         IN              NUMBER
707   , x_task_num_tbl       OUT NOCOPY      JTF_NUMBER_TABLE
708   , x_msg_tbl            OUT NOCOPY      JTF_VARCHAR2_TABLE_100
709   , x_task_id_tbl        OUT NOCOPY      JTF_NUMBER_TABLE
710   ) IS
711     l_api_version  CONSTANT NUMBER       := 1.0;
712     l_api_name     CONSTANT VARCHAR2(30) := 'FILL_REQUEST_RESOURCES';
713 
714     l_res_qualifiers  csf_resource_pub.resource_qualifier_tbl_type;
715     l_res_tbl         csf_requests_pvt.resource_tbl_type;
716     iIndex            PLS_INTEGER;
717     l_role            VARCHAR2(30);
718 
719     l_count              NUMBER := 1;
720     l_task_num_tbl       JTF_NUMBER_TABLE       := JTF_NUMBER_TABLE();
721     l_msg_tbl            JTF_VARCHAR2_TABLE_100 := JTF_VARCHAR2_TABLE_100();
722     l_task_id_tbl        JTF_NUMBER_TABLE       := JTF_NUMBER_TABLE();
723 
724     CURSOR c_request_task_list IS
725       SELECT rt.request_task_id
726            , t.task_number
727            , t.task_id
728            , t.source_object_id
729            , t.planned_start_date
730            , t.planned_end_date
731         FROM (  SELECT sched_request_id
732                   FROM csf_r_sched_requests
733                  WHERE parent_request_id = p_request_id
734                 UNION ALL
735                 SELECT sched_request_id
736                   FROM csf_r_sched_requests
737                  WHERE sched_request_id = p_request_id
738                    AND NOT EXISTS (SELECT 1
739                                      FROM csf_r_sched_requests
740                                     WHERE parent_request_id = p_request_id)
741              ) r
742            , csf_r_request_tasks rt
743            , jtf_tasks_b t
744        WHERE rt.sched_request_id = r.sched_request_id
745          AND NOT EXISTS ( SELECT 1
746                             FROM csf_r_resource_results rr
747                            WHERE rr.request_task_id = rt.request_task_id
748                          )
749          AND t.task_id = rt.task_id;
750 
751   BEGIN
752     SAVEPOINT fill_request_resources;
753 
754     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
755       RAISE fnd_api.g_exc_unexpected_error;
756     END IF;
757 
758     IF fnd_api.to_boolean(p_init_msg_list) THEN
759       fnd_msg_pub.initialize;
760     END IF;
761 
762     x_return_status := fnd_api.g_ret_sts_success;
763 
764     FOR l_task_rec IN c_request_task_list LOOP
765 
766       -- Get the Qualified Resources for this Task.
767       -- Validate the Planned Window (same logic as that done in DC)
768       csf_tasks_pub.validate_planned_dates(l_task_rec.planned_start_date, l_task_rec.planned_end_date);
769 
770       -- Get the Resources for this Task.
771       csf_resource_pub.get_resources_to_schedule(
772         p_api_version             => 1
773       , p_init_msg_list           => fnd_api.g_true
774       , x_return_status           => x_return_status
775       , x_msg_count               => x_msg_count
776       , x_msg_data                => x_msg_data
777       , p_scheduling_mode         => 'X'       -- Auto Assign mode
778       , p_task_id                 => l_task_rec.task_id
779       , p_incident_id             => l_task_rec.source_object_id
780       , p_start                   => l_task_rec.planned_start_date
781       , p_end                     => l_task_rec.planned_end_date
782       , p_contracts_flag          => g_auto_contract_flag
783       , p_ib_flag                 => g_auto_ib_flag
784       , p_territory_flag          => g_auto_terr_flag
785       , p_skill_flag              => g_auto_skills_flag
786       , p_res_qualifier_tbl       => l_res_qualifiers
787       , x_res_tbl                 => l_res_tbl
788       );
789 
790       -- Unless it is an Unexpected Error... continue even with
791       -- "No Resources Found" error. Java will do the proper error handling.
792       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
793         RAISE fnd_api.g_exc_unexpected_error;
794       END IF;
795 
796 
797       -- Filter out the Resources with Third Party Service provider Role.
798 
799       /* iIndex := l_res_tbl.FIRST;
800 
801       WHILE iIndex IS NOT NULL
802       LOOP
803         l_role := csr_scheduler_pvt.get_third_party_res_role( l_res_tbl(iIndex).resource_id
804                                                             , l_res_tbl(iIndex).resource_type
805                                                             );
806         IF l_role = 'CSF_THIRD_PARTY_SERVICE_PROVID'
807         THEN
808           l_res_tbl.DELETE(iIndex) ;
809         END IF;
810         iIndex := l_res_tbl.NEXT(iIndex);
811       END LOOP;  */
812 
813       IF x_return_status <> fnd_api.g_ret_sts_success
814       THEN
815         l_task_num_tbl.extend();
816         l_task_id_tbl.extend();
817         l_msg_tbl.extend();
818 
819         l_task_num_tbl(l_count) := l_task_rec.task_number;
820         l_task_id_tbl(l_count)  := l_task_rec.task_id;
821         l_msg_tbl(l_count)      := nvl(x_msg_data,'-999');
822 
823         l_count := l_count + 1;
824 
825         --Setting success for each task
826         x_return_status := fnd_api.g_ret_sts_success;
827       END IF;
828 
829       IF l_res_tbl.count > 0 THEN
830         csf_requests_pvt.create_resource_results(
831           p_api_version      => 1
832         , p_init_msg_list    => fnd_api.g_false
833         , p_commit           => fnd_api.g_false
834         , x_return_status    => x_return_status
835         , x_msg_count        => x_msg_count
836         , x_msg_data         => x_msg_data
837         , p_request_task_id  => l_task_rec.request_task_id
838         , p_resource_tbl     => l_res_tbl
839         );
840       END IF;
841     END LOOP;
842 
843     x_task_num_tbl := l_task_num_tbl;
844     x_task_id_tbl  := l_task_id_tbl;
845     x_msg_tbl      := l_msg_tbl;
846 
847     IF fnd_api.to_boolean(p_commit) THEN
848       COMMIT WORK;
849     END IF;
850   EXCEPTION
851     WHEN fnd_api.g_exc_error THEN
852       ROLLBACK TO fill_request_resources;
853       x_return_status := fnd_api.g_ret_sts_error;
854       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
855     WHEN fnd_api.g_exc_unexpected_error THEN
856       ROLLBACK TO fill_request_resources;
857       x_return_status := fnd_api.g_ret_sts_unexp_error;
858       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
859     WHEN OTHERS THEN
860       x_return_status := fnd_api.g_ret_sts_unexp_error;
861       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
862         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
863       END IF;
864       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
865       ROLLBACK TO fill_request_resources;
866   END fill_request_resources;
867 
868   PROCEDURE search_and_schedule_auto(
869     p_api_version        IN              NUMBER
870   , p_init_msg_list      IN              VARCHAR2
871   , p_commit             IN              VARCHAR2
872   , x_return_status      OUT NOCOPY      VARCHAR2
873   , x_msg_count          OUT NOCOPY      NUMBER
874   , x_msg_data           OUT NOCOPY      VARCHAR2
875   , p_task_tbl           IN              csf_requests_pvt.object_tbl_type
876   , x_sched_request_id   OUT NOCOPY      NUMBER
877   , x_conc_request_id    OUT NOCOPY      NUMBER
878   ) IS
879     l_api_version  CONSTANT NUMBER       := 1.0;
880     l_api_name     CONSTANT VARCHAR2(30) := 'SEARCH_AND_SCHEDULE_AUTO';
881   BEGIN
882     SAVEPOINT search_and_schedule_auto_pub;
883 
884     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
885       RAISE fnd_api.g_exc_unexpected_error;
886     END IF;
887 
888     IF fnd_api.to_boolean(p_init_msg_list) THEN
889       fnd_msg_pub.initialize;
890     END IF;
891 
892     x_return_status := fnd_api.g_ret_sts_success;
893 
894     IF NOT p_task_tbl.LAST > 0 THEN
895       IF NOT valid_argument(NULL, 'task_tbl', l_api_name) THEN
896         RAISE fnd_api.g_exc_error;
897       END IF;
898     END IF;
899 
900     -- Create the SearchAndScheduleAuto Request.
901     create_auto_request(
902       x_return_status  => x_return_status
903     , x_msg_count      => x_msg_count
904     , x_msg_data       => x_msg_data
905     , p_task_tbl       => p_task_tbl
906     , p_find_resources => fnd_api.g_false
907     , x_request_id     => x_sched_request_id
908     );
909 
910     IF x_return_status = fnd_api.g_ret_sts_error THEN
911       RAISE fnd_api.g_exc_error;
912     ELSIF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
913       RAISE fnd_api.g_exc_unexpected_error;
914     END IF;
915 
916     -- Submit the Scheduler concurrent program
917     x_conc_request_id := fnd_request.submit_request(
918                            application     => 'CSR'
919                          , program         => g_conc_program_name
920                          , description     => fnd_message.get_string('CSF', 'CSF_R_SEMI_INTERACTIVE_DESC')
921                          , sub_request     => FALSE
922                          , argument1       => TO_CHAR(x_sched_request_id)
923                          );
924 
925     IF x_conc_request_id = 0 THEN
926       -- FND_REQUEST.SUBMIT_REQUEST should have populated the Message Stack.
927       RAISE fnd_api.g_exc_error;
928     END IF;
929 
930     IF fnd_api.to_boolean(p_commit) THEN
931       COMMIT WORK;
932     END IF;
933   EXCEPTION
934     WHEN fnd_api.g_exc_error THEN
935       ROLLBACK TO search_and_schedule_auto_pub;
936       x_return_status := fnd_api.g_ret_sts_error;
937       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
938     WHEN fnd_api.g_exc_unexpected_error THEN
939       ROLLBACK TO search_and_schedule_auto_pub;
940       x_return_status := fnd_api.g_ret_sts_unexp_error;
941       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
942     WHEN OTHERS THEN
943       x_return_status := fnd_api.g_ret_sts_unexp_error;
944       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
945         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
946       END IF;
947       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
948       ROLLBACK TO search_and_schedule_auto_pub;
949   END search_and_schedule_auto;
950 
951   PROCEDURE create_auto_request(
952     p_api_version        IN              NUMBER
953   , p_init_msg_list      IN              VARCHAR2
954   , p_commit             IN              VARCHAR2
955   , x_return_status      OUT NOCOPY      VARCHAR2
956   , x_msg_count          OUT NOCOPY      NUMBER
957   , x_msg_data           OUT NOCOPY      VARCHAR2
958   , p_query_id           IN              NUMBER
959   , x_sched_request_id   OUT NOCOPY      NUMBER
960   ) IS
961     l_api_version  CONSTANT NUMBER       := 1.0;
962     l_api_name     CONSTANT VARCHAR2(30) := 'CREATE_AUTO_REQUEST';
963 
964     l_where      csf_dc_queries_b.where_clause%TYPE;
965     l_stmt       VARCHAR2(4000);
966     c_task_list  ref_cursor_type;
967     l_task_tbl   csf_requests_pvt.object_tbl_type;
968   BEGIN
969     SAVEPOINT create_auto_request_pub;
970 
971     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
972       RAISE fnd_api.g_exc_error;
973     END IF;
974 
975     IF fnd_api.to_boolean(p_init_msg_list) THEN
976       fnd_msg_pub.initialize;
977     END IF;
978 
979     IF NOT valid_argument(p_query_id, 'query_id', l_api_name) THEN
980       RAISE fnd_api.g_exc_error;
981     END IF;
982 
983     -- Get the WHERE CLAUSE for the Given Query ID.
984 
985     l_where := csf_util_pvt.get_query_where(p_query_id);
986 
987     IF l_where IS NULL THEN
988       RAISE no_data_found;
989     END IF;
990 
991     -- Create the Task List Query using the WHERE CLAUSE
992     l_stmt := 'SELECT task_id FROM csf_ct_tasks WHERE ' || l_where || ' ORDER BY scheduled_start_date NULLS FIRST, planned_end_date, creation_date';
993 
994     l_task_tbl := csf_requests_pvt.object_tbl_type();
995 
996     -- Fetch the Task List
997     OPEN c_task_list FOR l_stmt;
998     FETCH c_task_list BULK COLLECT INTO l_task_tbl;
999     CLOSE c_task_list;
1000 
1001     -- Create the SearchAndScheduleAuto Request
1002     create_auto_request(
1003       x_return_status  => x_return_status
1004     , x_msg_count      => x_msg_count
1005     , x_msg_data       => x_msg_data
1006     , p_task_tbl       => l_task_tbl
1007     , x_request_id     => x_sched_request_id
1008     );
1009 
1010     IF x_return_status = fnd_api.g_ret_sts_error THEN
1011       RAISE fnd_api.g_exc_error;
1012     ELSIF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
1013       RAISE fnd_api.g_exc_unexpected_error;
1014     END IF;
1015 
1016     IF fnd_api.to_boolean(p_commit) THEN
1017       COMMIT WORK;
1018     END IF;
1019   EXCEPTION
1020     WHEN fnd_api.g_exc_error THEN
1021       ROLLBACK TO create_auto_request_pub;
1022       x_return_status := fnd_api.g_ret_sts_error;
1023       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1024     WHEN fnd_api.g_exc_unexpected_error THEN
1025       ROLLBACK TO create_auto_request_pub;
1026       x_return_status := fnd_api.g_ret_sts_unexp_error;
1027       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1028     WHEN OTHERS THEN
1029       x_return_status := fnd_api.g_ret_sts_unexp_error;
1030       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1031         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
1032       END IF;
1033       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1034       ROLLBACK TO create_auto_request_pub;
1035   END create_auto_request;
1036 
1037   PROCEDURE create_optimize_trips_request(
1038     p_api_version        IN              NUMBER
1039   , p_init_msg_list      IN              VARCHAR2
1040   , p_commit             IN              VARCHAR2
1041   , x_return_status      OUT NOCOPY      VARCHAR2
1042   , x_msg_count          OUT NOCOPY      NUMBER
1043   , x_msg_data           OUT NOCOPY      VARCHAR2
1044   , p_terr_id            IN              NUMBER
1045   , p_start_date         IN              DATE
1046   , p_end_date           IN              DATE
1047   , x_sched_request_id   OUT NOCOPY      NUMBER
1048   ) IS
1049     l_api_version  CONSTANT NUMBER       := 1.0;
1050     l_api_name     CONSTANT VARCHAR2(30) := 'CREATE_OPTIMIZE_TRIPS_REQUEST';
1051 
1052     CURSOR c_resources IS
1053       SELECT resource_id, resource_type, terr_id FROM
1054       (SELECT /*+ cardinality(t, 1) */ DISTINCT trs.resource_id, trs.resource_type, trs.terr_id
1055                , RANK () OVER (PARTITION BY trs.resource_id, trs.resource_type ORDER BY NVL
1056                                                            (tra.absolute_rank,
1057                                                             0
1058                                                            ) DESC NULLS LAST)
1059                                                                  AS comp_rank
1060         FROM jtf_terr_rsc_all trs, jtf_terr_all tra
1061            , TABLE( CAST ( csf_util_pvt.get_selected_terr_table AS jtf_number_table ) ) t
1062        WHERE trs.terr_id = t.column_value
1063          AND (p_terr_id IS NULL OR trs.terr_id = p_terr_id))
1064           WHERE comp_rank = 1;
1065 
1066     l_res_id_tbl   jtf_number_table;
1067     l_res_type_tbl jtf_varchar2_table_100;
1068     l_res_terrid_tbl  jtf_number_table;
1069     l_resource_tbl csf_requests_pvt.resource_tbl_type;
1070   BEGIN
1071     SAVEPOINT create_opt_request_pub;
1072 
1073     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
1074       RAISE fnd_api.g_exc_error;
1075     END IF;
1076 
1077     IF fnd_api.to_boolean(p_init_msg_list) THEN
1078       fnd_msg_pub.initialize;
1079     END IF;
1080 
1081     OPEN c_resources;
1082     FETCH c_resources BULK COLLECT INTO l_res_id_tbl, l_res_type_tbl, l_res_terrid_tbl;
1083     CLOSE c_resources;
1084 
1085     l_resource_tbl := csf_requests_pvt.resource_tbl_type();
1086     FOR i IN  1..l_res_id_tbl.COUNT LOOP
1087       l_resource_tbl.EXTEND;
1088       l_resource_tbl(i).resource_id              := l_res_id_tbl(i);
1089       l_resource_tbl(i).resource_type            := l_res_type_tbl(i);
1090       l_resource_tbl(i).planwin_start            := p_start_date;
1091       l_resource_tbl(i).planwin_end              := p_end_date;
1092       l_resource_tbl(i).planwin_end              := p_end_date;
1093       l_resource_tbl(i).preferred_resources_flag := 'N';
1094       l_resource_tbl(i).TERRITORY_ID             := l_res_terrid_tbl(i);
1095     END LOOP;
1096 
1097     csf_requests_pvt.create_scheduler_request(
1098       p_api_version      => 1.0
1099     , x_return_status    => x_return_status
1100     , x_msg_count        => x_msg_count
1101     , x_msg_data         => x_msg_data
1102     , p_name             => 'OptimizeAcrossTrips'
1103     , p_object_id        => -1
1104     , p_resource_tbl     => l_resource_tbl
1105     , x_request_id       => x_sched_request_id
1106     );
1107 
1108     IF x_return_status = fnd_api.g_ret_sts_error THEN
1109       RAISE fnd_api.g_exc_error;
1110     ELSIF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
1111       RAISE fnd_api.g_exc_unexpected_error;
1112     END IF;
1113 
1114     IF fnd_api.to_boolean(p_commit) THEN
1115       COMMIT WORK;
1116     END IF;
1117   EXCEPTION
1118     WHEN fnd_api.g_exc_error THEN
1119       ROLLBACK TO create_opt_request_pub;
1120       x_return_status := fnd_api.g_ret_sts_error;
1121       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1122     WHEN fnd_api.g_exc_unexpected_error THEN
1123       ROLLBACK TO create_opt_request_pub;
1124       x_return_status := fnd_api.g_ret_sts_unexp_error;
1125       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1126     WHEN OTHERS THEN
1127       x_return_status := fnd_api.g_ret_sts_unexp_error;
1128       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1129         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
1130       END IF;
1131       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1132       ROLLBACK TO create_opt_request_pub;
1133   END create_optimize_trips_request;
1134 
1135   PROCEDURE get_qualified_resources(
1136     p_api_version        IN              NUMBER
1137   , p_init_msg_list      IN              VARCHAR2
1138   , x_return_status      OUT NOCOPY      VARCHAR2
1139   , x_msg_count          OUT NOCOPY      NUMBER
1140   , x_msg_data           OUT NOCOPY      VARCHAR2
1141   , p_task_id_tbl        IN              jtf_number_table
1142   , p_start_date_tbl     IN              jtf_date_table
1143   , p_end_date_tbl       IN              jtf_date_table
1144   , x_task_resources_tbl OUT NOCOPY      csf_task_resources_tbl_type
1145   ) IS
1146     l_api_version  CONSTANT NUMBER       := 1.0;
1147     l_api_name     CONSTANT VARCHAR2(30) := 'GET_QUALIFIED_RESOURCES';
1148     l_role         VARCHAR2(30) := NULL;
1149 
1150     CURSOR c_task_info IS
1151       SELECT source_object_id
1152         FROM jtf_tasks_b t
1153            , TABLE( CAST ( p_task_id_tbl AS jtf_number_table ) ) tt
1154        WHERE t.task_id = tt.COLUMN_VALUE;
1155 
1156     l_res_qualifiers  csf_resource_pub.resource_qualifier_tbl_type;
1157     l_res_tbl        jtf_assign_pub.assignresources_tbl_type;
1158     l_res_idx        PLS_INTEGER;
1159     l_task_res_tbl   csf_resource_tbl;
1160     l_sr_id_tbl      jtf_number_table;
1161     l_res_preferred  VARCHAR2(1);
1162     l_start_date     DATE;
1163     l_end_date       DATE;
1164 
1165   BEGIN
1166     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
1167       RAISE fnd_api.g_exc_error;
1168     END IF;
1169 
1170     IF fnd_api.to_boolean(p_init_msg_list) THEN
1171       fnd_msg_pub.initialize;
1172     END IF;
1173 
1174     x_return_status := fnd_api.g_ret_sts_success;
1175 
1176     l_task_res_tbl := csf_resource_tbl();
1177     x_task_resources_tbl := csf_task_resources_tbl_type();
1178 
1179     OPEN c_task_info;
1180     FETCH c_task_info BULK COLLECT INTO l_sr_id_tbl;
1181     CLOSE c_task_info;
1182 
1183     FOR i IN 1..p_task_id_tbl.COUNT LOOP
1184       l_start_date := p_start_date_tbl(i);
1185       l_end_date   := p_end_date_tbl(i);
1186 
1187       -- Get the Qualified Resources for this Task.
1188       -- Validate the Planned Window (same logic as that done in DC)
1189       csf_tasks_pub.validate_planned_dates(l_start_date, l_end_date);
1190 
1191       -- Get the Resources for this Task.
1192       csf_resource_pub.get_resources_to_schedule(
1193         p_api_version             => 1.0
1194       , p_init_msg_list           => fnd_api.g_false
1195       , x_return_status           => x_return_status
1196       , x_msg_count               => x_msg_count
1197       , x_msg_data                => x_msg_data
1198       , p_scheduling_mode         => 'O'       -- Optimizer mode
1199       , p_task_id                 => p_task_id_tbl(i)
1200       , p_incident_id             => l_sr_id_tbl(i)
1201       , p_start                   => l_start_date
1202       , p_end                     => l_end_date
1203       , p_contracts_flag          => g_auto_contract_flag
1204       , p_ib_flag                 => g_auto_ib_flag
1205       , p_territory_flag          => g_auto_terr_flag
1206       , p_skill_flag              => g_auto_skills_flag
1207       , p_res_qualifier_tbl       => l_res_qualifiers
1208       , x_res_tbl                 => l_res_tbl
1209       );
1210 
1211       l_task_res_tbl.DELETE;
1212       l_res_idx := l_res_tbl.FIRST;
1213       WHILE l_res_idx IS NOT NULL LOOP
1214         l_res_preferred := 'N';
1215         IF l_res_tbl(l_res_idx).preference_type IN ('I', 'C') THEN
1216           l_res_preferred := 'Y';
1217         END IF;
1218 
1219         l_role := csr_scheduler_pvt.get_third_party_res_role( l_res_tbl(l_res_idx).resource_id
1220                                                             , l_res_tbl(l_res_idx).resource_type
1221                                                             );
1222 
1223         l_task_res_tbl.EXTEND;
1224         l_task_res_tbl(l_task_res_tbl.COUNT) :=
1225               csf_resource(
1226                 l_res_preferred
1227               , NULL
1228               , NULL
1229               , l_res_tbl(l_res_idx).resource_id
1230               , l_res_tbl(l_res_idx).resource_type
1231               , NULL
1232               , l_res_tbl(l_res_idx).start_date
1233               , l_res_tbl(l_res_idx).end_date
1234               , l_role
1235               );
1236 
1237         l_res_idx := l_res_tbl.NEXT(l_res_idx);
1238       END LOOP;
1239 
1240       x_task_resources_tbl.EXTEND();
1241       x_task_resources_tbl(i) := l_task_res_tbl;
1242     END LOOP;
1243   EXCEPTION
1244     WHEN fnd_api.g_exc_error THEN
1245       x_return_status := fnd_api.g_ret_sts_error;
1246       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1247     WHEN fnd_api.g_exc_unexpected_error THEN
1248       x_return_status := fnd_api.g_ret_sts_unexp_error;
1249       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1250     WHEN OTHERS THEN
1251       x_return_status := fnd_api.g_ret_sts_unexp_error;
1252       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1253         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
1254       END IF;
1255       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1256   END get_qualified_resources;
1257 
1258   FUNCTION check_material_for_task(p_task_assignment_id IN NUMBER)
1259     RETURN VARCHAR2 IS
1260 
1261     l_has_material_transactions varchar2(1);
1262 
1263     l_order_id  NUMBER;
1264     l_status varchar2(30);
1265 
1266     CURSOR c_get_reservations is
1267       SELECT 'Y'
1268         FROM csp_req_line_details crld
1269            , csp_requirement_lines crl
1270            , csp_requirement_headers crh
1271        WHERE crh.task_assignment_id = p_task_assignment_id
1272          AND crl.requirement_header_id = crh.requirement_header_id
1273          AND crld.requirement_line_id = crl.requirement_line_id
1274          AND crld.source_type = 'RES' ;
1275 
1276     CURSOR c_get_orders is
1277       SELECT 'Y'
1278         FROM csp_req_line_details crld
1279            , csp_requirement_lines crl
1280            , csp_requirement_headers crh
1281            , oe_order_lines_all oel
1282            , oe_order_headers_all oeh
1283        WHERE crh.task_assignment_id = p_task_assignment_id
1284          AND crl.requirement_header_id = crh.requirement_header_id
1285          AND crld.requirement_line_id = crl.requirement_line_id
1286          AND crld.source_type = 'IO'
1287          AND oel.line_id = crld.source_id
1288          AND oeh.header_id =  oel.header_id
1289          AND oeh.flow_status_code <>'CANCELLED'
1290        ORDER BY oeh.header_id;
1291 
1292 
1293   BEGIN
1294 
1295     l_has_material_transactions := 'N';
1296 
1297     OPEN c_get_reservations ;
1298     FETCH c_get_reservations INTO l_has_material_transactions;
1299     CLOSE c_get_reservations;
1300 
1301     IF l_has_material_transactions <> 'Y' THEN
1302       OPEN c_get_orders;
1303       FETCH c_get_orders INTO l_has_material_transactions;
1304       CLOSE c_get_orders;
1305     END IF;
1306 
1307     RETURN  l_has_material_transactions;
1308 
1309   END check_material_for_task;
1310 
1311   /**
1312    * Lock the Trips and the Tasks of the given Resources. It will
1313    * try three times before throwing an exception that LOCK COULD
1314    * NOT BE OBTAINED.
1315    *
1316    * @param   p_api_version           API Version (1.0)
1317    * @param   p_init_msg_list         Initialize Message List
1318    * @param   x_return_status         Return Status of the Procedure.
1319    * @param   x_msg_count             Number of Messages in the Stack.
1320    * @param   x_msg_data              Stack of Error Messages.
1321    * @param   p_resource_tbl          Resources whose Trips and Tasks
1322    *                                  and Tasks needs to be locked.
1323    */
1324   PROCEDURE lock_trips_and_tasks(
1325     p_api_version        IN              NUMBER
1326   , p_init_msg_list      IN              VARCHAR2
1327   , x_return_status      OUT NOCOPY      VARCHAR2
1328   , x_msg_count          OUT NOCOPY      NUMBER
1329   , x_msg_data           OUT NOCOPY      VARCHAR2
1330   , p_resource_tbl       IN              csf_resource_tbl
1331   ) IS
1332     l_api_version  CONSTANT NUMBER       := 1.0;
1333     l_api_name     CONSTANT VARCHAR2(30) := 'LOCK_TRIPS_AND_TASKS';
1334 
1335     CURSOR c_trips_and_tasks IS
1336       SELECT t.task_id
1337            , ta.task_assignment_id
1338            , ah.access_hour_id
1339            , oc.object_capacity_id
1340         FROM jtf_tasks_b t
1341            , jtf_task_assignments ta
1342            , jtf_task_statuses_b ts
1343            , csf_access_hours_b ah
1344            , cac_sr_object_capacity oc
1345            , TABLE ( CAST ( p_resource_tbl AS CSF_RESOURCE_TBL ) ) r
1346        WHERE t.task_id = ta.task_id
1347          AND ta.assignment_status_id = ts.task_status_id
1348          AND t.task_id = ah.task_id(+)
1349          AND ta.resource_id = oc.object_id
1350          AND ta.resource_type_code = oc.object_type
1351          AND (
1352                  (     ta.object_capacity_id IS NOT NULL
1353                    AND ta.object_capacity_id = oc.object_capacity_id
1354                  )
1355               OR (
1356                        ta.object_capacity_id IS NULL
1357                    AND ta.booking_start_date < oc.end_date_time
1358                    AND ta.booking_end_date > oc.start_date_time
1359                  )
1360              )
1361          AND t.scheduled_end_date >= t.scheduled_start_date
1362          AND (t.deleted_flag = 'N' OR t.deleted_flag IS NULL)
1363          AND (
1364                  NVL(ta.actual_start_date, ta.actual_end_date) IS NOT NULL
1365               OR ((ts.cancelled_flag = 'N' OR ts.cancelled_flag IS NULL))
1366              )
1367          AND oc.object_id = r.resource_id
1368          AND oc.object_type = r.resource_type
1369          AND oc.start_date_time <= r.planwin_end
1370          AND oc.end_date_time >= r.planwin_start
1371          FOR UPDATE OF t.task_id, ta.task_assignment_id, ah.access_hour_id, oc.object_capacity_id NOWAIT;
1372 
1373     l_objects_locked BOOLEAN;
1374   BEGIN
1375     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
1376       RAISE fnd_api.g_exc_error;
1377     END IF;
1378 
1379     IF fnd_api.to_boolean(p_init_msg_list) THEN
1380       fnd_msg_pub.initialize;
1381     END IF;
1382 
1383     x_return_status := fnd_api.g_ret_sts_success;
1384 
1385     l_objects_locked := FALSE;
1386 
1387     FOR i IN 1..3 LOOP
1388       BEGIN
1389         OPEN c_trips_and_tasks;
1390         CLOSE c_trips_and_tasks;
1391 
1392         l_objects_locked := TRUE;
1393       EXCEPTION
1394         WHEN OTHERS THEN
1395           IF c_trips_and_tasks%ISOPEN THEN
1396             CLOSE c_trips_and_tasks;
1397           END IF;
1398       END;
1399 
1400       EXIT WHEN l_objects_locked;
1401       dbms_lock.sleep( i * 2 );
1402     END LOOP;
1403 
1404     IF NOT l_objects_locked THEN
1405       fnd_message.set_name ('CSR', 'CSR_LOCKING_RES_TRIPS_FAILED');
1406       fnd_msg_pub.ADD;
1407       RAISE fnd_api.g_exc_error;
1408     END IF;
1409 
1410   EXCEPTION
1411     WHEN fnd_api.g_exc_error THEN
1412       x_return_status := fnd_api.g_ret_sts_error;
1413       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1414     WHEN OTHERS THEN
1415       x_return_status := fnd_api.g_ret_sts_unexp_error;
1416       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1417         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
1418       END IF;
1419       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1420   END lock_trips_and_tasks;
1421 
1422   FUNCTION get_third_party_res_role(
1423      p_resource_id        IN              NUMBER
1424    , p_resource_type      IN              VARCHAR2
1425    ) RETURN VARCHAR2 IS
1426 
1427   -- Returns NULL for Internal or Wrong Setup
1428   -- Returns TPT or TPA or TPS role name
1429 
1430   CURSOR c_roles IS
1431   SELECT jrb.role_code
1432        , jrr.role_resource_type
1433    FROM  jtf_rs_role_relations jrr
1434        , jtf_rs_roles_b jrb
1435    WHERE jrr.role_id = jrb.role_id
1436      AND jrr.role_resource_id = p_resource_id
1437      AND jrb.role_type_code = 'CSF_THIRD_PARTY'
1438      AND jrr.role_resource_type = p_resource_type
1439      AND ( jrr.start_date_active IS NULL or trunc(jrr.start_date_active) <= sysdate )
1440      AND ( jrr.end_date_active IS NULL or trunc(jrr.end_date_active) >= sysdate )
1441      AND NVL( jrr.delete_flag, 'N') = 'N'
1442   ORDER BY 1;
1443 
1444     l_role VARCHAR2(30) := NULL;
1445     l_type VARCHAR2(30) := NULL;
1446 
1447   BEGIN
1448     IF ( p_resource_id IS NOT NULL and p_resource_type IS NOT NULL ) THEN
1449       OPEN c_roles;
1450       LOOP
1451         FETCH c_roles INTO l_role, l_type;
1452         EXIT WHEN c_roles%NOTFOUND;
1453         -- A Group Resource with TPS is eligible for third party scheduling
1454         -- Any other type of resource with TPS is considered as Internal Resource
1455         IF l_role = 'CSF_THIRD_PARTY_SERVICE_PROVID' AND l_type = 'RS_GROUP'
1456         THEN
1457           RETURN l_role;
1458         END IF;
1459         IF l_role = 'CSF_THIRD_PARTY_TECHNICIAN'
1460         THEN
1461            RETURN l_role;
1462         END IF;
1463       END LOOP;
1464       RETURN l_role;
1465     END IF;
1466     RETURN NULL;
1467   END get_third_party_res_role;
1468 
1469 END csr_scheduler_pvt;