DBA Data[Home] [Help]

PACKAGE BODY: APPS.AHL_LTP_RESRC_LEVL_PVT

Source


1 PACKAGE BODY AHL_LTP_RESRC_LEVL_PVT AS
2 /* $Header: AHLVRLGB.pls 120.8 2008/02/25 11:35:34 rnahata ship $ */
3 --
4 G_PKG_NAME          CONSTANT VARCHAR2(30) := 'AHL_LTP_RESRC_LEVL_PVT';
5 G_OPER_ASSOC_TYPE   CONSTANT VARCHAR2(30) := 'OPERATION';
6 G_RT_ASSOC_TYPE     CONSTANT VARCHAR2(30) := 'ROUTE';
7 G_SECS_IN_DAY       CONSTANT NUMBER := 86400;
8 G_SECS_IN_HOUR      CONSTANT NUMBER := 3600;
9 G_HOLIDAY_TYPE      CONSTANT NUMBER := 2;
10 
11 -- yazhou 17Aug2005 starts
12 -- bug fix #4559462
13 /*
14 G_MACHINE_RESOURCE  CONSTANT NUMBER := 1;
15 G_MACHINE_RES_NAME  CONSTANT VARCHAR2(10) := 'Machine';
16 G_LABOR_RESOURCE    CONSTANT NUMBER := 2;
17 G_LABOR_RES_NAME    CONSTANT VARCHAR2(10) := 'Labor';
18 */
19 -- yazhou 17Aug2005 ends
20 
21 G_JSP_MODULE_TYPE   CONSTANT VARCHAR2(3) := 'JSP';
22 G_ASO_RESOURCE      CONSTANT VARCHAR2(20) := 'ASORESOURCE';
23 G_BOM_RESOURCE      CONSTANT VARCHAR2(20) := 'BOMRESOURCE';
24 G_STATUS_PLANNING   CONSTANT VARCHAR2(20) := 'PLANNING';
25 G_PLAN_TYPE_PRIMARY CONSTANT VARCHAR2(1) := 'Y';
26 G_UOM_HOUR          CONSTANT VARCHAR2(3) := 'HR';
27 G_UOM_DAY           CONSTANT VARCHAR2(10) := 'DAYS';
28 G_UOM_WEEK          CONSTANT VARCHAR2(10) := 'WEEKS';
29 G_UOM_MONTH         CONSTANT VARCHAR2(10) := 'MONTHS';
30 
31 
32 -- Package level Global Variables used in time calculations
33 G_ZERO_TIME         DATE := NULL;
34 TYPE Dates_Tbl_Type IS TABLE OF DATE INDEX BY BINARY_INTEGER;
35 G_WORKING_DATES_TBL Dates_Tbl_Type;
36 G_EXCEPTION_DATES_TBL Dates_Tbl_Type;
37 G_CALENDAR_CODE     VARCHAR2(10) := NULL;
38 G_SHIFT_NUM         NUMBER := NULL;
39 G_SHIFT_START       NUMBER := NULL;
40 G_SHIFT_END         NUMBER := NULL;
41 G_DAYS_ON           NUMBER := NULL;
42 G_DAYS_OFF          NUMBER := NULL;
43 G_CAL_START         DATE   := NULL;
44 G_CAL_END           DATE   := NULL;
45 G_MAX_CAL_DAY       NUMBER := -1;
46 G_SHIFT_DURATION_HRS NUMBER := 0;
47 
48 -- yazhou 24Aug2005 starts
49 -- Resource Leveling Re-design
50 
51 l_log_current_level     NUMBER      := fnd_log.g_current_runtime_level;
52 l_log_statement         NUMBER      := fnd_log.level_statement;
53 l_log_procedure         NUMBER      := fnd_log.level_procedure;
54 l_log_error             NUMBER      := fnd_log.level_error;
55 l_log_unexpected        NUMBER      := fnd_log.level_unexpected;
56 
57 -- Record of Operation Details
58 TYPE Time_Period_Details_Rec_Type IS RECORD (
59         VISIT_ID                NUMBER           := NULL,  -- Visit Id
60         TASK_ID                 NUMBER           := NULL,  -- Task Id
61         ROUTE_ID                NUMBER           := NULL,  -- Route Id
62         MR_ROUTE_ID             NUMBER           := NULL, --ADDED ENAHNCEMENTS
63         OPERATION_ID            NUMBER           := NULL,  -- Operation Id (Null for Route Level)
64         STEP                    NUMBER           := NULL,  -- Operation sequence within Task
65         START_HOUR              NUMBER           := NULL,  -- Start Hour of the task/operation
66         END_HOUR                NUMBER           := NULL,  -- End Hour of the task/operation
67         MAX_DURATION            NUMBER           := NULL,  -- Max duration required for this task/op.
68         START_TIME              DATE             := NULL,  -- Start time of task/operation
69         END_TIME                DATE             := NULL,  -- End time of task/operation
70         QUANTITY                NUMBER           := NULL,  -- Quantity of a resource
71         TASK_TYPE_CODE          VARCHAR2(30)            ,
72         REQUIRED_UNITS          NUMBER           := NULL,
73       AVAILABLE_UNITS         NUMBER           := NULL,
74       ASO_RESOURCE_ID         NUMBER           := NULL,
75       DEPARTMENT_ID           NUMBER           := NULL,
76         BOM_RESOURCE_ID         NUMBER           := NULL
77         );
78 
79 TYPE Resource_Tbl_Type IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
80 
81 -- yazhou 24Aug2005 ends
82 
83 -- Record of event and quantity changes
84 TYPE Qty_Change_Rec_Type IS RECORD (
85         EVENT_TIME              DATE,
86         QTY_CHANGE              NUMBER
87         );
88 
89 TYPE Time_Period_Details_Tbl_Type IS TABLE OF Time_Period_Details_Rec_Type INDEX BY BINARY_INTEGER;
90 
91 TYPE Qty_Change_Tbl_Type IS TABLE OF Qty_Change_Rec_Type INDEX BY BINARY_INTEGER;
92 
93 TYPE Person_Tbl_Type IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
94 
95 
96 
97 -------------------------------
98 -- Declare Local Procedures --
99 -------------------------------
100 -- yazhou 24Aug2005 starts
101 -- Resource Leveling Re-design
102 
103   -- Gets all the tasks and their times for all visits for a given plan and department during a given period
104   -- If current plan is a simulation and the p_inc_primary flag is 'Y', visits in primary plan are also included.
105   PROCEDURE Get_Plan_Tasks(
106     p_dept_id               IN            NUMBER,
107     p_plan_id               IN            NUMBER,
108     p_start_time            IN            DATE,
109     p_end_time              IN            DATE,
110     p_inc_primary_flag      IN            BOOLEAN := FALSE,
111     x_tp_dtls_tbl           OUT NOCOPY Time_Period_Details_Tbl_Type,
112     x_visit_task_times_tbl  OUT NOCOPY Visit_Task_Times_Tbl_Type);
113 
114   -- Gets the task and operation times for a given visit. Also builds the
115   -- Time Period table if required
116   PROCEDURE Derive_Task_Op_Times(
117     p_visit_id              IN            NUMBER,
118     p_start_time            IN            DATE,
119     p_end_time              IN            DATE,
120     p_department_id         IN            NUMBER,
121     p_x_tp_dtls_tbl         IN OUT NOCOPY Time_Period_Details_Tbl_Type,
122     x_visit_start_time      OUT NOCOPY           DATE,
123     x_visit_end_time        OUT NOCOPY           DATE,
124     x_visit_end_hour        OUT NOCOPY           NUMBER,
125     x_visit_task_times_tbl  OUT NOCOPY    Visit_Task_Times_Tbl_Type);
126 
127 -- yazhou 24Aug2005 ends
128 
129   -- Gets the resources required by the given task
130   PROCEDURE Get_Task_Resources(
131     p_required_capacity IN      NUMBER ,
132     p_task_id           IN      NUMBER,
133     p_tstart_date       IN      DATE,
134     p_tend_date         IN      DATE,
135     p_distinct_flag     IN      BOOLEAN,  -- If true, duplicate resource are not added to table
136     p_x_task_rsrc_tbl   IN OUT  NOCOPY Plan_Rsrc_Tbl_Type);
137 
138   -- Gets the details of a resource
139   PROCEDURE Get_Resource_Details(
140     p_aso_resource_id   IN      NUMBER,
141     p_x_task_rsrc_tbl   IN OUT  NOCOPY Plan_Rsrc_Tbl_Type);
142   -- Gets the details of a recource and capacity units
143   PROCEDURE Get_Resource_Details
144 (
145     p_required_capacity IN      NUMBER,
146     p_aso_resource_id   IN      NUMBER,
147     p_bom_resource_id   IN      NUMBER,
148     p_bom_department_id IN      NUMBER,
149     p_start_date        IN      DATE,
150     p_end_date          IN      DATE,
151     p_x_task_rsrc_tbl   IN OUT  NOCOPY Plan_Rsrc_Tbl_Type);
152 
153 -- yazhou 24Aug2005 starts
154 -- Resource Leveling Re-design
155 
156   -- Populates a Time Period table with a task's requirement' start time and end time
157   -- (If the task's route has operations and if ressources are not associated at route level)
158   -- or with the task's start time and end time
159   -- Also populate the table with resource id
160 
161   PROCEDURE Get_Operation_Details(
162     p_task_dtls      IN      Visit_Task_Times_Rec_Type,
163     p_visit_id       IN      NUMBER,
164     p_department_id  IN      NUMBER,
165     p_organization_id IN     NUMBER,
166     p_start_time     IN      DATE,
167     p_end_time       IN      DATE,
168     p_x_tp_dtls_tbl  IN OUT  NOCOPY Time_Period_Details_Tbl_Type);
169 
170 -- yazhou 24Aug2005 ends
171 
172   -- Filters out tasks/operations that don't require the resource
173   -- and gets quantity of resource required by the task/operation
174   PROCEDURE Filter_By_Resource(
175     p_resource_id    IN      NUMBER,
176   p_start_time     IN      DATE,
177   p_end_time       IN      DATE,
178     p_x_tp_dtls_tbl  IN OUT NOCOPY  Time_Period_Details_Tbl_Type);
179  --
180  /* Commented by rnahata since its not being used
181  PROCEDURE get_qty_By_Resource(
182     p_resource_id    IN      NUMBER,
183     p_aso_bom_type   IN      VARCHAR2,
184     p_x_tp_dtls_tbl  IN OUT NOCOPY  Time_Period_Details_Tbl_Type);
185  */
186 
187   -- Creates Timeperiods from the start time and end time based on the UOM
188   -- and populates the table
189   PROCEDURE Create_Time_Periods(
190     p_start_time     IN DATE,
191     p_end_time       IN DATE,
192     p_UOM_code       IN VARCHAR2,
193     p_org_id         IN NUMBER,
194     p_dept_id        IN NUMBER,
195     x_per_rsrc_tbl   OUT NOCOPY Period_Rsrc_Req_Tbl_Type);
196 
197   -- Sorts the Quantity Change table based on event time
198   PROCEDURE Sort_Qty_Change_Table(
199     p_x_qty_change_tbl  IN OUT NOCOPY Qty_Change_Tbl_Type);
200 
201   -- Sorts the Time_Period_Details_Tbl By Visit/Task
202   PROCEDURE Sort_By_Visit_Task(
203     p_x_tp_tbl  IN OUT NOCOPY Time_Period_Details_Tbl_Type);
204 
205   -- Aggregates Task Quantities and gets Task and Visit Names
206   PROCEDURE Aggregate_Task_Quantities(
207     P_resource_id       IN  NUMBER,
208     p_org_name         IN VARCHAR2,
209     p_dept_name        IN  VARCHAR2,
210     p_tp_dtls_table    IN  Time_Period_Details_Tbl_Type,
211     x_task_req_tbl     OUT NOCOPY Task_Requirement_Tbl_Type);
212 
213   -- Gets the duration of a Route from its timespan column
214   PROCEDURE Get_Route_Duration(
215     p_route_id  IN  NUMBER,
216     x_duration  OUT NOCOPY NUMBER);
217 
218   -- Gets the duration of a Route from its resource requirements (directly or through the route's operations)
219   PROCEDURE Get_Rt_Ops_Duration(
220     p_route_id  IN  NUMBER,
221     x_duration  OUT NOCOPY NUMBER);
222 
223   -- Gets the duration of an operation from its resource requirements
224   PROCEDURE Get_Oper_Max_Duration(
225     p_operation_id  IN  NUMBER,
226     x_duration      OUT NOCOPY NUMBER);
227 
228   -- Gets the duration of a route directly from its resource requirements
229   PROCEDURE Get_Rt_Max_Duration(
230     p_route_id      IN  NUMBER,
231     x_duration      OUT NOCOPY NUMBER);
232 
233   -- Initializes the calendar based variables
234   PROCEDURE Init_Time_Vars(
235     p_visit_start_date IN  DATE,
236     p_department_id    IN  NUMBER);
237   -- Gets the Nth Working Day
238   FUNCTION Get_Nth_Day(p_day_index NUMBER) RETURN DATE;
239 
240   -- Determines if a specific date is a holiday
241   FUNCTION IS_DEPT_Holiday(l_curr_date DATE) RETURN BOOLEAN;
242 
243   -- Determines if a specific resource is available at a specific time
244   FUNCTION Resource_In_Duty(p_resource_id NUMBER, p_start_date_time DATE) RETURN BOOLEAN;
245 
246   -- Determines if the Resource is already present in the given table
247   FUNCTION Is_Resource_Present(p_aso_resource_id NUMBER,
248                                p_task_rsrc_tbl   Plan_Rsrc_Tbl_Type) RETURN BOOLEAN;
249   -- Function to determine if two time periods overlap
250   -- Note that If the end time of one period coincides with the
251   -- start time of the other time period, the timeperiods DON'T overlap
252   FUNCTION Periods_Overlap(p1_start_time DATE,
253                            p1_end_time DATE,
254                            p2_start_time DATE,
255                            p2_end_time DATE) RETURN BOOLEAN;
256 
257   -- Calculates the maximum required quantity during a given period
258   FUNCTION Get_Required_Quantity(p_start_time   DATE,
259                                  p_end_time     DATE,
260                                  p_tp_dtls_tbl  Time_Period_Details_Tbl_Type) RETURN NUMBER;
261   -- Compares a visit/task combination with another
262   -- Returns +1, -1 or 0 depending on whether first visit task is greater, lesser
263   -- or equal to the second visit task
264   FUNCTION Compare_Visit_Tasks(p_visit_1 NUMBER,
265                                p_task_1  NUMBER,
266                                p_visit_2 NUMBER,
267                                p_task_2  NUMBER) RETURN NUMBER;
268 
269   -- Function to determine if a specific date is not a holiday in the given department
270   FUNCTION Not_A_Holiday(p_curr_date DATE, p_dept_id NUMBER) RETURN BOOLEAN;
271  -- Get wip job requirements
272   -- AnRaj: Obsoleted Procedure
273 /*
274 PROCEDURE GET_WIP_DISC_REQ_UNITS(p_org_id            IN NUMBER,
275                                   p_bom_dept_id       IN NUMBER,
276                                   p_bom_resource_id   IN NUMBER,
277                                   p_start_date        IN DATE,
278                                   p_end_date          IN DATE,
279                                   x_assigned_units    OUT NOCOPY NUMBER);
280 */
281 -- yazhou 24Aug2005 starts
282 -- Resource Leveling Re-design
283 
284 FUNCTION Get_Available_Units(p_resource_id  NUMBER,
285                              p_dept_id      NUMBER) RETURN NUMBER;
286 
287 
288 PROCEDURE Get_Used_Resources
289 (
290    p_dept_id       IN NUMBER,
291    p_start_date    IN DATE,
292    p_end_date      IN DATE,
293    p_tp_dtls_tbl   IN Time_Period_Details_Tbl_Type,
294    x_resources_tbl OUT NOCOPY Resource_Tbl_Type
295 );
296 
297 PROCEDURE Append_WIP_Requirements
298 (
299    p_org_id       IN NUMBER,
300    p_dept_id      IN NUMBER,
301    p_start_date   IN DATE,
302    p_end_date     IN DATE,
303    p_resource_id  IN NUMBER,
304    p_x_tp_dtls_tbl  IN OUT NOCOPY Time_Period_Details_Tbl_Type
305 );
306 -- yazhou 24Aug2005 ends
307 
308 -------------------------------------
309 -- End Local Procedures Declaration--
310 -------------------------------------
311 
312 -- Start of Comments --
313 --  Procedure name    : Derive_Visit_Task_Times
314 --  Type              : Private
315 --  Function          : Derive the start and end times/hours of task associated with a visit
316 --  Pre-reqs    :
317 --  Parameters  :
318 --
319 --  Standard IN  Parameters :
320 --      p_api_version                   IN      NUMBER       Required
321 --      p_init_msg_list                 IN      VARCHAR2     Default  FND_API.G_FALSE
322 --      p_commit                        IN      VARCHAR2     Default  FND_API.G_FALSE
323 --      p_validation_level              IN      NUMBER       Default  FND_API.G_VALID_LEVEL_FULL
324 --      p_default                       IN      VARCHAR2     Default  FND_API.G_TRUE
325 --      p_module_type                   IN      VARCHAR2     Default  NULL.
326 --
327 --  Standard OUT Parameters :
328 --      x_return_status                 OUT     VARCHAR2     Required
329 --      x_msg_count                     OUT     NUMBER       Required
330 --      x_msg_data                      OUT     VARCHAR2     Required
331 --
332 --  Derive_Visit_Task_Times Parameters:
333 --      p_visit_id                      IN      NUMBER       Required
334 --         The id of the visit whose associated tasks' start and end times or hours
335 --         need to be derived
336 --      p_start_time                    IN      DATE         DEFAULT NULL
337 --         Start time filter for tasks. Only tasks that start after this time will be returned.
338 --         If null, no filtering will be done
339 --      p_end_time                      IN      DATE         DEFAULT NULL
340 --         End time filter for tasks. Only tasks that start before this time will be returned.
341 --         If null, no filtering will be done
342 --      x_visit_start_time              OUT     DATE
343 --         The start time of the visit
344 --      x_visit_end_time                OUT     DATE
345 --         The derived end time of the visit
346 --      x_visit_end_hour                OUT     NUMBER
347 --         The derived end hour (normalized) of the visit
348 --      x_visit_task_times_tbl          OUT     Visit_Task_Times_Tbl_Type
349 --         The table containing details about the tasks associated with this visit
350 --
351 --  Version :
352 --      Initial Version   1.0
353 --
354 --  End of Comments.
355 
356 --
357 -- This API has been deprecated -yazhou 24Aug2005
358 --
359 
360 PROCEDURE Derive_Visit_Task_Times
361 (
362     p_api_version           IN            NUMBER,
363     p_init_msg_list         IN            VARCHAR2  := Fnd_Api.G_FALSE,
364     p_commit                IN            VARCHAR2  := Fnd_Api.G_FALSE,
365     p_validation_level      IN            NUMBER    := Fnd_Api.G_VALID_LEVEL_FULL,
366     p_default               IN            VARCHAR2  := Fnd_Api.G_TRUE,
367     p_module_type           IN            VARCHAR2  := NULL,
368     p_visit_id              IN            NUMBER,
369     p_start_time            IN            DATE      := NULL,
370     p_end_time              IN            DATE      := NULL,
371     x_visit_start_time      OUT NOCOPY           DATE,
372     x_visit_end_time        OUT NOCOPY           DATE,
373     x_visit_end_hour        OUT NOCOPY           NUMBER,
374     x_visit_task_times_tbl  OUT  NOCOPY   AHL_LTP_RESRC_LEVL_PVT.Visit_Task_Times_Tbl_Type,
375     x_return_status         OUT NOCOPY           VARCHAR2,
376     x_msg_count             OUT NOCOPY           NUMBER,
377     x_msg_data              OUT NOCOPY           VARCHAR2
378 ) IS
379 
380   CURSOR l_validate_visit_csr(p_visit_id  IN NUMBER) IS
381     SELECT 'x' FROM ahl_visits_b
382     WHERE VISIT_ID = p_visit_id;
383 
384   l_api_version            CONSTANT NUMBER := 1.0;
385   l_api_name               CONSTANT VARCHAR2(30) := 'Derive_Visit_Task_Times';
386   l_dummy_table            Time_Period_Details_Tbl_Type;
387   l_junk                   VARCHAR2(1);
388 
389 BEGIN
390 --  dbms_output.put_line('Entering Derive_Visit_Task_Times');
391   -- Standard start of API savepoint
392   SAVEPOINT Derive_Visit_Task_Times_pvt;
393 
394   -- Standard call to check for call compatibility
395   IF NOT Fnd_Api.Compatible_API_Call(l_api_version, p_api_version, l_api_name,
396                                      G_PKG_NAME) THEN
397     RAISE Fnd_Api.G_EXC_UNEXPECTED_ERROR;
398   END IF;
399 
400     -- Initialize message list if p_init_msg_list is set to TRUE
401   IF Fnd_Api.To_Boolean(p_init_msg_list) THEN
402     Fnd_Msg_Pub.Initialize;
403   END IF;
404 
405   -- Initialize API return status to success
406   x_return_status := Fnd_Api.G_RET_STS_SUCCESS;
407 
408   -- Begin Processing
409 
410   -- Enable Debug (optional)
411   Ahl_Debug_Pub.enable_debug;
412 
413   -- ASSUMPTIONS:
414   --   A Task can appear only once for a given visit (ahl_visit_tasks_b)
415   --   A Department can have only one shift (ahl_department_shifts)
416   --   Shift_Num is unique in bom_shift_times
417 
418   -- Validate Visit Id
419   IF (p_visit_id IS NULL) THEN
420     Fnd_Message.Set_Name('AHL','AHL_LTP_VISIT_ID_NULL');
421     Fnd_Msg_Pub.ADD;
422     RAISE  Fnd_Api.G_EXC_ERROR;
423   ELSE
424     OPEN l_validate_visit_csr(p_visit_id);
425     FETCH l_validate_visit_csr INTO l_junk;
426     IF (l_validate_visit_csr%NOTFOUND) THEN
427       Fnd_Message.Set_Name('AHL','AHL_LTP_VISIT_ID_INVALID');
428       Fnd_Message.Set_Token('VISIT_ID', p_visit_id);
429       Fnd_Msg_Pub.ADD;
430       CLOSE l_validate_visit_csr;
431       RAISE  Fnd_Api.G_EXC_ERROR;
432     END IF;
433     CLOSE l_validate_visit_csr;
434   END IF;
435 
436   -- Validate Dates
437   IF (p_start_time IS NOT NULL AND p_end_time IS NOT NULL AND p_start_time > p_end_time) THEN
438     Fnd_Message.Set_Name('AHL','AHL_LTP_STIME_GT_ETIME');
439     Fnd_Message.Set_Token('STIME', p_start_time);
440     Fnd_Message.Set_Token('ETIME', p_end_time);
441     Fnd_Msg_Pub.ADD;
442     RAISE  Fnd_Api.G_EXC_ERROR;
443   END IF;
444 
445   -- Call helper method to do the actual processing
446   Ahl_Debug_Pub.debug('Beginning Processing for Visit: ' || p_visit_id, 'LTP:Derive_Visit_Task_Times');
447   Derive_Task_Op_Times(
448     p_visit_id              => p_visit_id,
449     p_start_time            => p_start_time,
450     p_end_time              => p_end_time,
451     p_department_id         => NULL, -- dummy for compliation purpose
452     p_x_tp_dtls_tbl         => l_dummy_table,  -- Dummy Table for Operation Time Periods
453     x_visit_start_time      => x_visit_start_time,
454     x_visit_end_time        => x_visit_end_time,
455     x_visit_end_hour        => x_visit_end_hour,
456     x_visit_task_times_tbl  => x_visit_task_times_tbl);
457 
458   Ahl_Debug_Pub.debug('Completed Processing. Checking for errors', 'LTP:Derive_Visit_Task_Times');
459   -- Check Error Message stack.
460   x_msg_count := Fnd_Msg_Pub.count_msg;
461   IF x_msg_count > 0 THEN
462     RAISE  Fnd_Api.G_EXC_ERROR;
463   END IF;
464 
465   -- Standard check of p_commit
466   IF Fnd_Api.TO_BOOLEAN(p_commit) THEN
467       COMMIT WORK;
468   END IF;
469 
470   -- Standard call to get message count and if count is 1, get message info
471   Fnd_Msg_Pub.Count_And_Get
472     ( p_count => x_msg_count,
473       p_data  => x_msg_data,
474       p_encoded => Fnd_Api.g_false
475     );
476 
477   -- Disable debug (if enabled)
478   Ahl_Debug_Pub.disable_debug;
479 --  dbms_output.put_line('Exiting LTP:Derive_Visit_Task_Times');
480 
481 EXCEPTION
482  WHEN Fnd_Api.G_EXC_ERROR THEN
483    ROLLBACK TO Derive_Visit_Task_Times_pvt;
484    x_return_status := Fnd_Api.G_RET_STS_ERROR;
485    Fnd_Msg_Pub.count_and_get( p_count => x_msg_count,
486                               p_data  => x_msg_data,
487                               p_encoded => Fnd_Api.g_false);
488    --AHL_UTIL_PKG.Err_Mesg_To_Table(x_err_mesg_tbl);
489 
490 
491  WHEN Fnd_Api.G_EXC_UNEXPECTED_ERROR THEN
492    ROLLBACK TO Derive_Visit_Task_Times_pvt;
493    x_return_status := Fnd_Api.G_RET_STS_UNEXP_ERROR;
494    Fnd_Msg_Pub.count_and_get( p_count => x_msg_count,
495                               p_data  => x_msg_data,
496                               p_encoded => Fnd_Api.g_false);
497    --AHL_UTIL_PKG.Err_Mesg_To_Table(x_err_mesg_tbl);
498 
499  WHEN OTHERS THEN
500     ROLLBACK TO Derive_Visit_Task_Times_pvt;
501     x_return_status := Fnd_Api.G_RET_STS_UNEXP_ERROR;
502     IF Fnd_Msg_Pub.check_msg_level(Fnd_Msg_Pub.G_MSG_LVL_UNEXP_ERROR) THEN
503        Fnd_Msg_Pub.add_exc_msg(p_pkg_name       => G_PKG_NAME,
504                                p_procedure_name => 'Derive_Visit_Task_Times',
505                                p_error_text     => SUBSTR(SQLERRM,1,240));
506     END IF;
507     Fnd_Msg_Pub.count_and_get( p_count => x_msg_count,
508                                p_data  => x_msg_data,
509                                p_encoded => Fnd_Api.g_false);
510     --AHL_UTIL_PKG.Err_Mesg_To_Table(x_err_mesg_tbl);
511 
512 END Derive_Visit_Task_Times;
513 
514 -- Start of Comments --
515 --  Procedure name    : Get_Plan_Resources
516 --  Type              : Private
517 --  Function          : Gets the distinct Resources (Name, Type, Code) required by a given
518 --                      department during a given period for a given Plan
519 --  Pre-reqs    :
520 --  Parameters  :
521 --
522 --  Standard IN  Parameters :
523 --      p_api_version                   IN      NUMBER       Required
524 --      p_init_msg_list                 IN      VARCHAR2     Default  FND_API.G_FALSE
525 --      p_commit                        IN      VARCHAR2     Default  FND_API.G_FALSE
526 --      p_validation_level              IN      NUMBER       Default  FND_API.G_VALID_LEVEL_FULL
527 --      p_default                       IN      VARCHAR2     Default  FND_API.G_TRUE
528 --      p_module_type                   IN      VARCHAR2     Default  NULL.
529 --
530 --  Standard OUT Parameters :
531 --      x_return_status                 OUT     VARCHAR2     Required
532 --      x_msg_count                     OUT     NUMBER       Required
533 --      x_msg_data                      OUT     VARCHAR2     Required
534 --
535 --  Get_Plan_Resources Parameters:
536 --      p_dept_id                       IN      NUMBER       REQUIRED
537 --         The department that is to be searched for resources
538 --      p_dept_name                     IN      VARCHAR2     REQUIRED
539 --         The name of the department (will be mapped to Id if p_dept_id is not given)
540 --      p_org_name                      IN      VARCHAR2     REQUIRED
541 --         The name of the organization where the department is
542 --      p_plan_id                       IN      NUMBER     REQUIRED
543 --         The id of the plan for which to get the resources
544 --      p_start_time                    IN      DATE         REQUIRED
545 --         Start time filter for tasks. Only tasks that are in progress at or after this
546 --         time will be considered. Tasks that end before this time will be ignored.
547 --      p_end_time                      IN      DATE         REQUIRED
548 --         End time filter for tasks. Only tasks that are in progress at or before this
549 --         time will be considered. Tasks that start after this time will be ignored.
550 --      x_plan_rsrc_tbl                 OUT  Plan_Rsrc_Tbl_Type
551 --         The table containing the distinct resources required.
552 --
553 --  Version :
554 --      Initial Version   1.0
555 --
556 --  End of Comments.
557 --
558 -- This API has been deprecated -yazhou 24Aug2005
559 --
560 
561 PROCEDURE Get_Plan_Resources
562 (
563     p_api_version           IN            NUMBER,
564     p_init_msg_list         IN            VARCHAR2  := Fnd_Api.G_FALSE,
565     p_commit                IN            VARCHAR2  := Fnd_Api.G_FALSE,
566     p_validation_level      IN            NUMBER    := Fnd_Api.G_VALID_LEVEL_FULL,
567     p_default               IN            VARCHAR2  := Fnd_Api.G_TRUE,
568     p_module_type           IN            VARCHAR2  := NULL,
569     p_dept_id               IN            NUMBER,
570     p_dept_name             IN            VARCHAR2,
571     p_org_name              IN            VARCHAR2,
572     p_plan_id               IN            NUMBER,
573     p_start_time            IN            DATE,
574     p_end_time              IN            DATE,
575     x_plan_rsrc_tbl         OUT NOCOPY    AHL_LTP_RESRC_LEVL_PVT.Plan_Rsrc_Tbl_Type,
576     x_return_status         OUT NOCOPY           VARCHAR2,
577     x_msg_count             OUT NOCOPY           NUMBER,
578     x_msg_data              OUT NOCOPY           VARCHAR2
579 ) IS
580 
581   CURSOR l_dept_id_csr(p_dept_name IN VARCHAR2, p_org_name IN VARCHAR2) IS
582     SELECT department_id FROM bom_departments dept, hr_all_organization_units org
583     WHERE org.name = p_org_name AND
584     dept.ORGANIZATION_ID = org.ORGANIZATION_ID AND
585     dept.description = p_dept_name;
586 
587   CURSOR l_validate_dept_csr(l_dept_id IN NUMBER) IS
588     SELECT 'x' FROM bom_departments WHERE
589     department_id = l_dept_id;
590 
591    CURSOR l_validate_plan_csr(l_plan_id IN NUMBER) IS
592     SELECT 'x' FROM ahl_simulation_plans_b WHERE
593     simulation_plan_id = l_plan_id;
594 
595   l_api_version     CONSTANT NUMBER := 1.0;
596   l_api_name        CONSTANT VARCHAR2(30) := 'Get_Plan_Resources';
597 
598   l_dept_id         NUMBER := NULL;
599   l_junk            VARCHAR2(1);
600   l_task_times_tbl  Visit_Task_Times_Tbl_Type;
601   l_temp_rsrc_tbl   Plan_Rsrc_Tbl_Type;
602   l_dummy_table     Time_Period_Details_Tbl_Type;
603   l_required_capacity  NUMBER;
604 BEGIN
605 --  dbms_output.put_line('Entering Get_Plan_Resources');
606   -- Standard start of API savepoint
607   SAVEPOINT Get_Plan_Resources_pvt;
608 
609   -- Standard call to check for call compatibility
610   IF NOT Fnd_Api.Compatible_API_Call(l_api_version, p_api_version, l_api_name,
611                                      G_PKG_NAME) THEN
612     RAISE Fnd_Api.G_EXC_UNEXPECTED_ERROR;
613   END IF;
614 
615     -- Initialize message list if p_init_msg_list is set to TRUE
616   IF Fnd_Api.To_Boolean(p_init_msg_list) THEN
617     Fnd_Msg_Pub.Initialize;
618   END IF;
619 
620   -- Initialize API return status to success
621   x_return_status := Fnd_Api.G_RET_STS_SUCCESS;
622 
623   -- Enable Debug (optional)
624   Ahl_Debug_Pub.enable_debug;
625 
626   -- Begin Processing
627 --  dbms_output.put_line('Begin Processing');
628   -- Map Dept Name To Dept Id
629   IF (p_module_type = G_JSP_MODULE_TYPE) THEN
630 --    dbms_output.put_line('JSP Module: Doing Value to ID Conversion');
631     OPEN l_dept_id_csr(p_dept_name, p_org_name);
632     FETCH l_dept_id_csr INTO l_dept_id;
633     IF (l_dept_id_csr%NOTFOUND) THEN
634       Fnd_Message.Set_Name('AHL','AHL_LTP_DEPT_INVALID');
635       Fnd_Message.Set_Token('DEPT', p_dept_name);
636       Fnd_Msg_Pub.ADD;
637       CLOSE l_dept_id_csr;
638       RAISE  Fnd_Api.G_EXC_ERROR;
639     END IF;
640     CLOSE l_dept_id_csr;
641 --    dbms_output.put_line('l_dept_id = ' || l_dept_id);
642   ELSE
643     -- Validate Dept Id
644     IF (p_dept_id IS NULL) THEN
645       Fnd_Message.Set_Name('AHL','AHL_LTP_DEPT_NULL');
646       Fnd_Msg_Pub.ADD;
647       RAISE  Fnd_Api.G_EXC_ERROR;
648     ELSE
649       OPEN l_validate_dept_csr(p_dept_id);
650       FETCH l_validate_dept_csr INTO l_junk;
651       IF (l_validate_dept_csr%NOTFOUND) THEN
652         Fnd_Message.Set_Name('AHL','AHL_LTP_DEPT_ID_INVALID');
653         Fnd_Message.Set_Token('DEPT', p_dept_id);
654         Fnd_Msg_Pub.ADD;
655         CLOSE l_validate_dept_csr;
656         RAISE  Fnd_Api.G_EXC_ERROR;
657       END IF;
658       CLOSE l_validate_dept_csr;
659     END IF;
660     l_dept_id := p_dept_id;
661 --    dbms_output.put_line('l_dept_id = ' || l_dept_id);
662   END IF;
663 
664   -- Validate Plan Id
665   IF (p_plan_id IS NULL) THEN
666     Fnd_Message.Set_Name('AHL','AHL_LTP_PLAN_ID_NULL');
667     Fnd_Msg_Pub.ADD;
668     RAISE  Fnd_Api.G_EXC_ERROR;
669   ELSE
670     OPEN l_validate_plan_csr(p_plan_id);
671     FETCH l_validate_plan_csr INTO l_junk;
672     IF (l_validate_plan_csr%NOTFOUND) THEN
673       Fnd_Message.Set_Name('AHL','AHL_LTP_PLAN_ID_INVALID');
674       Fnd_Message.Set_Token('PLAN', p_plan_id);
675       Fnd_Msg_Pub.ADD;
676       CLOSE l_validate_plan_csr;
677       RAISE  Fnd_Api.G_EXC_ERROR;
678     END IF;
679     CLOSE l_validate_plan_csr;
680   END IF;
681 --  dbms_output.put_line('p_plan_id = ' || p_plan_id);
682 
683   -- Validate Dates
684   IF (p_start_time IS NOT NULL AND p_end_time IS NOT NULL AND p_start_time > p_end_time) THEN
685     Fnd_Message.Set_Name('AHL','AHL_LTP_STIME_GT_ETIME');
686     Fnd_Message.Set_Token('STIME', p_start_time);
687     Fnd_Message.Set_Token('ETIME', p_end_time);
688     Fnd_Msg_Pub.ADD;
689     RAISE  Fnd_Api.G_EXC_ERROR;
690   END IF;
691 
692 --  dbms_output.put_line('Completed Mapping. Calling Get_Plan_Tasks');
693   -- Get all the tasks for the given dept/plan
694   -- that are in progress during the given timeframe
695   Get_Plan_Tasks(
696     p_dept_id              => p_dept_id,
697     p_plan_id              => p_plan_id,
698     p_start_time           => p_start_time,
699     p_end_time             => p_end_time,
700     p_inc_primary_flag     => FALSE,  -- No need to include primary plan tasks even if this plan is a simulation
701 --    p_op_times_flag        => FALSE,  -- No need to get Operation Time Period details
702     x_tp_dtls_tbl          => l_dummy_table, -- Dummy Table for Operation Time Period details
703     x_visit_task_times_tbl => l_task_times_tbl);
704 
705 --  dbms_output.put_line('Completed Get_Plan_Tasks. Calling Get_Task_Resources');
706 --  dbms_output.put_line('l_task_times_tbl.Count = ' || l_task_times_tbl.COUNT);
707   -- Get Distinct Resources for all valid visits/tasks
708   IF (l_task_times_tbl.COUNT > 0) THEN
709     FOR i IN l_task_times_tbl.FIRST .. l_task_times_tbl.LAST LOOP
710       Get_Task_Resources(
711         p_required_capacity    => l_required_capacity,
712       p_task_id              => l_task_times_tbl(i).VISIT_TASK_ID,
713         p_tstart_date      => 'SYSDATE',
714         p_tend_date        => 'SYSDATE',
715         p_distinct_flag        => TRUE,
716         p_x_task_rsrc_tbl      => l_temp_rsrc_tbl);
717     END LOOP;
718   END IF;
719 
720   -- Assign output parameters with locally generated table
721   x_plan_rsrc_tbl := l_temp_rsrc_tbl;
722 
723   Ahl_Debug_Pub.debug('Completed Processing. Checking for errors', 'LTP');
724   -- Check Error Message stack.
725   x_msg_count := Fnd_Msg_Pub.count_msg;
726   IF x_msg_count > 0 THEN
727     RAISE  Fnd_Api.G_EXC_ERROR;
728   END IF;
729 
730   -- Standard check of p_commit
731   IF Fnd_Api.TO_BOOLEAN(p_commit) THEN
732       COMMIT WORK;
733   END IF;
734 
735   -- Standard call to get message count and if count is 1, get message info
736   Fnd_Msg_Pub.Count_And_Get
737     ( p_count => x_msg_count,
738       p_data  => x_msg_data,
739       p_encoded => Fnd_Api.g_false
740     );
741 
742   -- Disable debug (if enabled)
743   Ahl_Debug_Pub.disable_debug;
744 
745 EXCEPTION
746  WHEN Fnd_Api.G_EXC_ERROR THEN
747    ROLLBACK TO Get_Plan_Resources_pvt;
748    x_return_status := Fnd_Api.G_RET_STS_ERROR;
749    Fnd_Msg_Pub.count_and_get( p_count => x_msg_count,
750                               p_data  => x_msg_data,
751                               p_encoded => Fnd_Api.g_false);
752 
753  WHEN Fnd_Api.G_EXC_UNEXPECTED_ERROR THEN
754    ROLLBACK TO Get_Plan_Resources_pvt;
755    x_return_status := Fnd_Api.G_RET_STS_UNEXP_ERROR;
756    Fnd_Msg_Pub.count_and_get( p_count => x_msg_count,
757                               p_data  => x_msg_data,
758                               p_encoded => Fnd_Api.g_false);
759 
760  WHEN OTHERS THEN
761     ROLLBACK TO Get_Plan_Resources_pvt;
762     x_return_status := Fnd_Api.G_RET_STS_UNEXP_ERROR;
763     IF Fnd_Msg_Pub.check_msg_level(Fnd_Msg_Pub.G_MSG_LVL_UNEXP_ERROR) THEN
764        Fnd_Msg_Pub.add_exc_msg(p_pkg_name       => G_PKG_NAME,
765                                p_procedure_name => 'Get_Plan_Resources',
766                                p_error_text     => SUBSTR(SQLERRM,1,240));
767     END IF;
768     Fnd_Msg_Pub.count_and_get( p_count => x_msg_count,
769                                p_data  => x_msg_data,
770                                p_encoded => Fnd_Api.g_false);
771 
772 END Get_Plan_Resources;
773 
774 -- Start of Comments --
775 --  Procedure name    : Get_Rsrc_Req_By_Period
776 --  Type              : Private
777 --  Function          : Gets the Requirements and Availability of a Resource
778 --                      by periods for a given department, during a given period,
779 --                      for a given Plan
780 --  Pre-reqs    :
781 --  Parameters  :
782 --
783 --  Standard IN  Parameters :
784 --      p_api_version                   IN      NUMBER       Required
785 --      p_init_msg_list                 IN      VARCHAR2     Default  FND_API.G_FALSE
786 --      p_commit                        IN      VARCHAR2     Default  FND_API.G_FALSE
787 --      p_validation_level              IN      NUMBER       Default  FND_API.G_VALID_LEVEL_FULL
788 --      p_default                       IN      VARCHAR2     Default  FND_API.G_TRUE
789 --      p_module_type                   IN      VARCHAR2     Default  NULL.
790 --
791 --  Standard OUT Parameters :
792 --      x_return_status                 OUT     VARCHAR2     Required
793 --      x_msg_count                     OUT     NUMBER       Required
794 --      x_msg_data                      OUT     VARCHAR2     Required
795 --
796 --  Get_Plan_Resources Parameters:
797 --      p_dept_id                       IN      NUMBER       REQUIRED
798 --         The department that is to be searched for resources
799 --      p_dept_name                     IN      VARCHAR2     REQUIRED
800 --         The name of the department (will be mapped to Id if p_dept_id is not given)
801 --      p_org_name                      IN      VARCHAR2     REQUIRED
802 --         The name of the organization where the department is
803 --      p_plan_id                       IN      NUMBER     REQUIRED
804 --         The id of the plan for which to get the resources
805 --      p_start_time                    IN      DATE         REQUIRED
806 --         Start time filter for tasks. Only tasks that are in progress at or after this
807 --         time will be considered. Tasks that end before this time will be ignored.
808 --      p_end_time                      IN      DATE         REQUIRED
809 --         End time filter for tasks. Only tasks that are in progress at or before this
810 --         time will be considered. Tasks that start after this time will be ignored.
811 --      p_UOM_id                        IN      NUMBER     REQUIRED
812 --         The id of the Period's unit of Measure (Days, Weeks, Months etc.)
813 --      p_resource_id                   IN      NUMBER     REQUIRED
814 --         The id of the Resource whose requirements/Availabilities are to be derived
815 --      p_aso_bom_rsrc_type             IN      VARCHAR2    REQUIRED
816 --         The type of the resource (ASORESOURCE or BOMRESOURCE)
817 --      x_per_rsrc_tbl                  OUT  Period_Rsrc_Req_Tbl_Type
818 --         The table containing the distinct resources required.
819 --
820 --  Version :
821 --      Initial Version   1.0
822 --
823 --  End of Comments.
824 
825 PROCEDURE Get_Rsrc_Req_By_Period
826 (
827     p_api_version           IN            NUMBER,
828     p_init_msg_list         IN            VARCHAR2  := Fnd_Api.G_FALSE,
829     p_commit                IN            VARCHAR2  := Fnd_Api.G_FALSE,
830     p_validation_level      IN            NUMBER    := Fnd_Api.G_VALID_LEVEL_FULL,
831     p_default               IN            VARCHAR2  := Fnd_Api.G_TRUE,
832     p_module_type           IN            VARCHAR2  := NULL,
833     p_dept_id               IN            NUMBER,
834     p_dept_name             IN            VARCHAR2,
835     p_org_name              IN            VARCHAR2,
836     p_plan_id               IN            NUMBER,
837     p_start_time            IN            DATE,
838     p_end_time              IN            DATE,
839     p_UOM_code              IN            VARCHAR2,
840     p_required_capacity     IN            NUMBER,
841     x_per_rsrc_tbl          OUT NOCOPY  Ahl_Ltp_Resrc_Levl_Pvt.Period_Rsrc_Req_Tbl_Type,
842     x_return_status         OUT NOCOPY           VARCHAR2,
843     x_msg_count             OUT NOCOPY           NUMBER,
844     x_msg_data              OUT NOCOPY           VARCHAR2
845 ) IS
846 
847   /* Renamed l_dept_id_csr0 to l_dept_id_csr by mpothuku on 01/18/05
848      Also added the exists condition to retrieve only departments with shifts
849   */
850 
851 -- yazhou 24Aug2005 starts
852 -- Resource Leveling Re-design
853 -- Added department name as Select field
854 
855   CURSOR l_dept_id_csr(p_dept_name IN VARCHAR2, p_org_name IN VARCHAR2) IS
856     SELECT department_id, org.organization_id, dept.description dept_name
857     FROM bom_departments dept, hr_all_organization_units org
858     WHERE org.name = p_org_name AND
859     dept.ORGANIZATION_ID = org.ORGANIZATION_ID AND
860   EXISTS ( SELECT 'x' FROM AHL_DEPARTMENT_SHIFTS WHERE DEPARTMENT_ID = dept.DEPARTMENT_ID) AND
861     (  (p_dept_name is not null and dept.description = p_dept_name)
862      or p_dept_name is null ) ;
863 
864 -- yazhou 24Aug2005 ends
865 
866   /* Added the exists condition to retrieve only departments with shifts */
867   CURSOR l_validate_dept_csr(l_dept_id IN NUMBER) IS
868     SELECT description FROM bom_departments WHERE
869     department_id = l_dept_id and exists ( SELECT 'x' FROM AHL_DEPARTMENT_SHIFTS WHERE DEPARTMENT_ID = bom_departments.DEPARTMENT_ID);
870   --
871   CURSOR l_validate_org_csr(l_org_name IN VARCHAR2) IS
872     SELECT name FROM hr_all_organization_units WHERE
873     name = l_org_name;
874   --
875   CURSOR l_validate_plan_csr(l_plan_id IN NUMBER) IS
876     SELECT 'x' FROM ahl_simulation_plans_b WHERE
877     simulation_plan_id = l_plan_id;
878   --
879 
880 -- yazhou 24Aug2005 starts
881 -- Resource Leveling Re-design
882 
883   CURSOR l_resource_dtl_csr (l_resource_id IN NUMBER) IS
884    SELECT d.resource_code,
885           d.description,
886           d.resource_type,
887           m.meaning resource_type_mean
888      FROM bom_resources d,  mfg_lookups m
889     WHERE d.resource_id = l_resource_id
890       AND d.resource_type = m.lookup_code
891       AND m.lookup_type = 'BOM_RESOURCE_TYPE';
892 
893 -- yazhou 24Aug2005 ends
894 
895   l_api_version     CONSTANT NUMBER := 1.0;
896   l_api_name        CONSTANT VARCHAR2(30) := 'Get_Rsrc_Req_By_Period';
897   l_return_status    VARCHAR2(1);
898   l_msg_data         VARCHAR2(200);
899   l_msg_count        NUMBER;
900 
901 -- yazhou 24Aug2005 starts
902 -- Resource Leveling Re-design
903 
904   l_available_quantity   NUMBER;
905   l_required_quantity    NUMBER;
906   l_unused_capacity      NUMBER;
907   l_dept_id              NUMBER := NULL;
908   l_org_id               NUMBER := NULL;
909   l_department_name       bom_departments.description%type;
910   l_period_start_time    DATE;
911   l_period_end_time      DATE;
912 
913   l_idx                  NUMBER := 0;
914 
915   l_task_times_tbl  Visit_Task_Times_Tbl_Type;
916   l_tp_dtls_table   Time_Period_Details_Tbl_Type;
917   l_tp_dtls_table_dept   Time_Period_Details_Tbl_Type;
918   l_tp_dtls_table_resc   Time_Period_Details_Tbl_Type;
919   l_per_rsrc_tbl        Period_Rsrc_Req_Tbl_Type;
920   l_resc_tbl       Resource_Tbl_Type;
921 
922   l_resource_dtl_rec    l_resource_dtl_csr%rowtype;
923 -- yazhou 24Aug2005 ends
924 
925   l_name           HR_ALL_ORGANIZATION_UNITS.NAME%TYPE;
926   l_deprt_id        NUMBER;
927   l_orga_id         NUMBER;
928   l_junk            VARCHAR2(1);
929   l_dept_name       bom_departments.description%type;
930 
931 BEGIN
932   -- Standard start of API savepoint
933   SAVEPOINT Get_Rsrc_Req_By_Period_pvt;
934 
935   -- Standard call to check for call compatibility
936   IF NOT Fnd_Api.Compatible_API_Call(l_api_version, p_api_version, l_api_name,
937                                      G_PKG_NAME) THEN
938     RAISE Fnd_Api.G_EXC_UNEXPECTED_ERROR;
939   END IF;
940 
941     -- Initialize message list if p_init_msg_list is set to TRUE
942   IF Fnd_Api.To_Boolean(p_init_msg_list) THEN
943     Fnd_Msg_Pub.Initialize;
944   END IF;
945 
946   -- Initialize API return status to success
947   x_return_status := Fnd_Api.G_RET_STS_SUCCESS;
948 
949   -- Enable Debug (optional)
950   Ahl_Debug_Pub.enable_debug;
951 
952   -- Begin Processing
953 
954 -- yazhou 24Aug2005 starts
955 -- Resource Leveling Re-design
956 -- Added Organization, start and end date mandatory check
957 
958      IF (l_log_statement >= l_log_current_level) THEN
959         fnd_log.string
960         (
961           fnd_log.level_statement,
962           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
963           'p_plan_id:'||p_plan_id
964         );
965         fnd_log.string
966         (
967           fnd_log.level_statement,
968           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
969           'p_start_time:'||TO_CHAR( p_start_time, 'DD-MON-YYYY hh24:mi')
970         );
971         fnd_log.string
972         (
973           fnd_log.level_statement,
974           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
975           'p_end_time:'||TO_CHAR( p_end_time, 'DD-MON-YYYY hh24:mi')
976         );
977         fnd_log.string
978         (
979           fnd_log.level_statement,
980           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
981           'p_UOM_code:'||p_UOM_code
982         );
983         fnd_log.string
984         (
985           fnd_log.level_statement,
986           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
987           'p_org_name:'||p_org_name
988         );
989         fnd_log.string
990         (
991           fnd_log.level_statement,
992           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
993           'p_dept_name:'||p_dept_name
994         );
995         fnd_log.string
996         (
997           fnd_log.level_statement,
998           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
999           'p_required_capacity:'||p_required_capacity
1000         );
1001      END IF;
1002 
1003   IF (p_org_name IS NULL) THEN
1004     Fnd_Message.Set_Name('AHL','AHL_LTP_ORG_MAN_JSP');
1005     Fnd_Msg_Pub.ADD;
1006     RAISE  Fnd_Api.G_EXC_ERROR;
1007   END IF;
1008 
1009   IF (p_start_time IS NULL) THEN
1010     Fnd_Message.Set_Name('AHL','AHL_LTP_STARTDATE_MAN_JSP');
1011     Fnd_Msg_Pub.ADD;
1012     RAISE  Fnd_Api.G_EXC_ERROR;
1013   END IF;
1014 
1015   IF (p_end_time IS NULL) THEN
1016     Fnd_Message.Set_Name('AHL','AHL_LTP_ENDDATE_MAN_JSP');
1017     Fnd_Msg_Pub.ADD;
1018     RAISE  Fnd_Api.G_EXC_ERROR;
1019   END IF;
1020 
1021   IF (TRUNC(p_start_time) < TRUNC(SYSDATE) ) THEN
1022     Fnd_Message.Set_Name('AHL','AHL_LTP_INVALID_START_DATE');
1023     Fnd_Msg_Pub.ADD;
1024     RAISE  Fnd_Api.G_EXC_ERROR;
1025   END IF;
1026 
1027   IF (TRUNC(p_end_time) < TRUNC(SYSDATE) ) THEN
1028     Fnd_Message.Set_Name('AHL','AHL_LTP_INVALID_END_DATE');
1029     Fnd_Msg_Pub.ADD;
1030     RAISE  Fnd_Api.G_EXC_ERROR;
1031   END IF;
1032 -- yazhou 24Aug2005 ends
1033 
1034   -- Map Dept Name To Dept Id
1035 IF (p_module_type = G_JSP_MODULE_TYPE) THEN
1036 --    dbms_output.put_line('JSP MODULE: Doing Value TO ID Conversion');
1037  -- validate org name
1038   OPEN l_validate_org_csr(p_org_name);
1039   FETCH l_validate_org_csr INTO l_name;
1040   IF (l_validate_org_csr%NOTFOUND) THEN
1041       Fnd_Message.Set_Name('AHL','AHL_LTP_ORG_ID_INVALID');
1042       Fnd_Message.Set_Token('ORG', p_org_name);
1043       Fnd_Msg_Pub.ADD;
1044     CLOSE l_validate_org_csr;
1045      RAISE  Fnd_Api.G_EXC_ERROR;
1046    END IF;
1047   --
1048   CLOSE l_validate_org_csr;
1049   -- Validate dept name
1050   OPEN l_dept_id_csr(p_dept_name,p_org_name);
1051   FETCH l_dept_id_csr INTO l_deprt_id,l_orga_id, l_department_name;
1052   IF (l_dept_id_csr%NOTFOUND) THEN
1053       Fnd_Message.Set_Name('AHL','AHL_LTP_DEPT_INV_OR_NO_SFT');
1054       Fnd_Message.Set_Token('DEPT', p_dept_name);
1055       Fnd_Msg_Pub.ADD;
1056      CLOSE l_dept_id_csr;
1057    RAISE  Fnd_Api.G_EXC_ERROR;
1058    END IF;
1059    CLOSE l_dept_id_csr;
1060    --
1061    l_dept_name := p_dept_name;
1062 
1063 ELSE
1064 -- yazhou 24Aug2005 starts
1065 -- Resource Leveling Re-design
1066 -- removed the code to throw exception when p_dept_id is null
1067 
1068     -- Validate Dept Id
1069     IF (p_dept_id IS NOT NULL) THEN
1070       OPEN l_validate_dept_csr(p_dept_id);
1071       FETCH l_validate_dept_csr INTO l_dept_name;
1072       IF (l_validate_dept_csr%NOTFOUND) THEN
1073         Fnd_Message.Set_Name('AHL','AHL_LTP_DEPT_INV_OR_NO_SFT');
1074         Fnd_Message.Set_Token('DEPT', p_dept_id);
1075         Fnd_Msg_Pub.ADD;
1076         CLOSE l_validate_dept_csr;
1077         RAISE  Fnd_Api.G_EXC_ERROR;
1078       END IF;
1079     END IF;
1080 
1081 -- yazhou 24Aug2005 ends
1082 
1083   END IF;
1084 
1085 -- yazhou 24Aug2005 starts
1086 -- Resource Leveling Re-design
1087 -- Moved out of department loop
1088 
1089   -- Validate Plan Id
1090   IF (p_plan_id IS NULL) THEN
1091     Fnd_Message.Set_Name('AHL','AHL_LTP_PLAN_ID_NULL');
1092     Fnd_Msg_Pub.ADD;
1093     RAISE  Fnd_Api.G_EXC_ERROR;
1094   ELSE
1095     OPEN l_validate_plan_csr(p_plan_id);
1096     FETCH l_validate_plan_csr INTO l_junk;
1097     IF (l_validate_plan_csr%NOTFOUND) THEN
1098       Fnd_Message.Set_Name('AHL','AHL_LTP_PLAN_ID_INVALID');
1099       Fnd_Message.Set_Token('PLAN', p_plan_id);
1100       Fnd_Msg_Pub.ADD;
1101       CLOSE l_validate_plan_csr;
1102       RAISE  Fnd_Api.G_EXC_ERROR;
1103     END IF;
1104     CLOSE l_validate_plan_csr;
1105   END IF;
1106 
1107 --  dbms_output.put_line('p_plan_id = ' || p_plan_id);
1108   Ahl_Debug_Pub.debug('p_plan_id = ' || p_plan_id);
1109 
1110   -- Validate Dates
1111   IF (p_start_time IS NOT NULL AND p_end_time IS NOT NULL AND p_start_time > p_end_time) THEN
1112     Fnd_Message.Set_Name('AHL','AHL_LTP_STIME_GT_ETIME');
1113     Fnd_Message.Set_Token('STIME', p_start_time);
1114     Fnd_Message.Set_Token('ETIME', p_end_time);
1115     Fnd_Msg_Pub.ADD;
1116     RAISE  Fnd_Api.G_EXC_ERROR;
1117   END IF;
1118 
1119 -- yazhou 24Aug2005 ends
1120 
1121 --
1122 -- Check for each department in the given organization
1123 --
1124 FOR var in l_dept_id_csr( l_dept_name , p_org_name) LOOP
1125 
1126      l_dept_id := var.department_id;
1127      l_org_id  := var.organization_id;
1128 
1129 -- yazhou 24Aug2005 starts
1130 -- Resource Leveling Re-design
1131      l_department_name := var.dept_name;
1132 -- yazhou 24Aug2005 ends
1133 
1134      IF (l_log_statement >= l_log_current_level) THEN
1135         fnd_log.string
1136         (
1137           fnd_log.level_statement,
1138           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1139           'l_org_id:'||l_org_id
1140         );
1141         fnd_log.string
1142         (
1143           fnd_log.level_statement,
1144           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1145           'l_dept_id:'||l_dept_id
1146         );
1147         fnd_log.string
1148         (
1149           fnd_log.level_statement,
1150           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1151           'l_department_name:'||l_department_name
1152         );
1153      END IF;
1154 
1155 -- yazhou 24Aug2005 starts
1156 -- Resource Leveling Re-design
1157 
1158   -- Get all the tasks for the given dept/plan
1159   -- that are in progress during the given timeframe
1160   -- since p_end_date is surfixed with "00:00", to include resources for the end date
1161    -- increase the date by 1
1162   Get_Plan_Tasks(
1163     p_dept_id              => l_dept_id,
1164     p_plan_id              => p_plan_id,
1165     p_start_time           => p_start_time,
1166     p_end_time             => p_end_time+1,
1167     p_inc_primary_flag     => TRUE,  -- Need to include primary plan tasks if this plan is a simulation
1168 --    p_op_times_flag        => TRUE,  -- Need to get Operation Time Period details
1169     x_tp_dtls_tbl          => l_tp_dtls_table, -- Table for Operation Time Period details
1170     x_visit_task_times_tbl => l_task_times_tbl);
1171 
1172   IF (l_log_statement >= l_log_current_level) THEN
1173         fnd_log.string
1174         (
1175           fnd_log.level_statement,
1176           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1177           'After calling Get_Plan_Tasks'
1178         );
1179         fnd_log.string
1180         (
1181           fnd_log.level_statement,
1182           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1183           'l_tp_dtls_table.COUNT:'||l_tp_dtls_table.COUNT
1184         );
1185         fnd_log.string
1186         (
1187           fnd_log.level_statement,
1188           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1189           'l_task_times_tbl.COUNT:'||l_task_times_tbl.COUNT
1190         );
1191   END IF;
1192 
1193  -- continue only if there are requirements for this department
1194  IF l_tp_dtls_table.count>0 THEN
1195   -- Create the timeperiods table for output
1196   -- since p_end_date is surfixed with "00:00", to create time periods that includes
1197   -- the end date, increase the date by 1
1198   Create_Time_Periods(
1199     p_start_time     => p_start_time,
1200     p_end_time       => p_end_time+1,
1201     p_UOM_code       => p_UOM_code,
1202     p_org_id         => l_org_id,
1203     p_dept_id        => l_dept_id,
1204     x_per_rsrc_tbl   => l_per_rsrc_tbl);
1205 
1206   IF (l_log_statement >= l_log_current_level) THEN
1207         fnd_log.string
1208         (
1209           fnd_log.level_statement,
1210           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1211           'After calling Create_Time_Periods'
1212         );
1213         fnd_log.string
1214         (
1215           fnd_log.level_statement,
1216           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1217           'l_per_rsrc_tbl.COUNT:'||l_per_rsrc_tbl.COUNT
1218         );
1219   END IF;
1220 
1221   -- For each time period, get all the resources required for the given department
1222 
1223   IF l_per_rsrc_tbl.COUNT > 0 THEN
1224    FOR i IN l_per_rsrc_tbl.FIRST..l_per_rsrc_tbl.LAST LOOP
1225 
1226      l_period_start_time := l_per_rsrc_tbl(i).period_start;
1227      l_period_end_time   := l_per_rsrc_tbl(i).period_end;
1228 
1229      l_tp_dtls_table_dept := l_tp_dtls_table;
1230 
1231      IF (l_log_statement >= l_log_current_level) THEN
1232         fnd_log.string
1233         (
1234           fnd_log.level_statement,
1235           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1236           'l_per_rsrc_tbl('||i||').period_start:'||TO_CHAR( l_period_start_time, 'DD-MON-YYYY hh24:mi')
1237         );
1238         fnd_log.string
1239         (
1240           fnd_log.level_statement,
1241           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1242           'l_per_rsrc_tbl('||i||').period_end:'||TO_CHAR( l_period_end_time, 'DD-MON-YYYY hh24:mi')
1243         );
1244      END IF;
1245 
1246      -- Get all the resources that are used in the given period for the given department
1247      -- by tasks in Planning
1248      Get_Used_Resources(
1249         p_dept_id              => l_dept_id,
1250         p_start_date           => l_period_start_time,
1251         p_end_date             => l_period_end_time,
1252         p_tp_dtls_tbl          => l_tp_dtls_table_dept,
1253         x_resources_tbl        => l_resc_tbl);
1254 
1255      IF (l_log_statement >= l_log_current_level) THEN
1256         fnd_log.string
1257         (
1258           fnd_log.level_statement,
1259           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1260           'After calling Get_Used_Resources'
1261         );
1262         fnd_log.string
1263         (
1264           fnd_log.level_statement,
1265           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1266           'l_resc_tbl.COUNT:'||l_resc_tbl.COUNT
1267         );
1268      END IF;
1269 
1270      -- For each resource, check for required quantity and calculate availability capacity
1271      IF l_resc_tbl.COUNT > 0 THEN
1272       FOR j IN l_resc_tbl.FIRST..l_resc_tbl.LAST LOOP
1273 
1274         l_tp_dtls_table_resc := l_tp_dtls_table_dept;
1275 
1276         IF (l_log_statement >= l_log_current_level) THEN
1277            fnd_log.string
1278            (
1279               fnd_log.level_statement,
1280               'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1281               'l_resc_tbl('||j||'):' || l_resc_tbl(j)
1282            );
1283         END IF;
1284 
1285         -- Filter resource requirements table to get only those for the given resource,
1286         -- given period and given department
1287         Filter_By_Resource(
1288            p_resource_id    =>l_resc_tbl(j),
1289          p_start_time     =>l_period_start_time,
1290          p_end_time       =>l_period_end_time,
1291            p_x_tp_dtls_tbl  =>l_tp_dtls_table_resc);
1292 
1293         IF (l_log_statement >= l_log_current_level) THEN
1294            fnd_log.string
1295            (
1296               fnd_log.level_statement,
1297               'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1298               'After Calling Filter_By_Resource'
1299            );
1300            fnd_log.string
1301            (
1302               fnd_log.level_statement,
1303               'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1304               'l_tp_dtls_table_resc.count: ' ||l_tp_dtls_table_resc.count
1305            );
1306         END IF;
1307 
1308         -- Populate output table only if there are resource requirements by tasks
1309         IF l_tp_dtls_table_resc.COUNT>0 THEN
1310 
1311           -- Add resource requirements by WIP job for the same department, resource, period
1312           Append_WIP_Requirements(
1313              p_org_id          => l_org_id,
1314              p_dept_id         => l_dept_id,
1315              p_start_date      => l_period_start_time,
1316              p_end_date        => l_period_end_time,
1317              p_resource_id     => l_resc_tbl(j),
1318              p_x_tp_dtls_tbl   => l_tp_dtls_table_resc);
1319 
1320           IF (l_log_statement >= l_log_current_level) THEN
1321             fnd_log.string
1322             (
1323               fnd_log.level_statement,
1324               'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1325               'After Calling Append_WIP_Requirements'
1326             );
1327             fnd_log.string
1328             (
1329               fnd_log.level_statement,
1330               'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1331               'l_tp_dtls_table_resc.count: ' ||l_tp_dtls_table_resc.count
1332             );
1333           END IF;
1334 
1335           l_required_quantity := Get_Required_Quantity(
1336                                   p_start_time     =>l_period_start_time,
1337                                   p_end_time       =>l_period_end_time,
1338                                     p_tp_dtls_tbl    =>l_tp_dtls_table_resc);
1339 
1340           IF (l_log_statement >= l_log_current_level) THEN
1341               fnd_log.string
1342              (
1343                 fnd_log.level_statement,
1344                 'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1345                 'l_required_quantity:'||l_required_quantity
1346              );
1347           END IF;
1348 
1349           l_available_quantity := Get_Available_Units(
1350                                     p_resource_id  =>l_resc_tbl(j),
1351                                     p_dept_id      =>l_dept_id);
1352 
1353           IF (l_log_statement >= l_log_current_level) THEN
1354               fnd_log.string
1355              (
1356                 fnd_log.level_statement,
1357                 'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1358                 'l_available_quantity:'||l_available_quantity
1359              );
1360           END IF;
1361 
1362          IF (l_available_quantity >0 AND l_required_quantity>0 ) THEN
1363 
1364              l_unused_capacity := (1-(l_required_quantity/l_available_quantity))*100;
1365 
1366              IF (l_log_statement >= l_log_current_level) THEN
1367                 fnd_log.string
1368                (
1369                  fnd_log.level_statement,
1370                 'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1371                 'l_unused_capacity:'||l_unused_capacity
1372                );
1373              END IF;
1374 
1375              IF l_unused_capacity <= p_required_capacity THEN
1376 
1377                 x_per_rsrc_tbl(l_idx).resource_id            := l_resc_tbl(j);
1378                 x_per_rsrc_tbl(l_idx).capacity_units         := round(l_unused_capacity);
1379                 x_per_rsrc_tbl(l_idx).period_start           := l_period_start_time;
1380                 x_per_rsrc_tbl(l_idx).period_end             := l_period_end_time;
1381                 x_per_rsrc_tbl(l_idx).period_string          := l_per_rsrc_tbl(i).period_string;
1382                 x_per_rsrc_tbl(l_idx).DEPARTMENT_ID          := l_dept_id;
1383                 x_per_rsrc_tbl(l_idx).REQUIRED_UNITS         := l_required_quantity;
1384                 x_per_rsrc_tbl(l_idx).AVAILABLE_UNITS       := l_available_quantity;
1385                 x_per_rsrc_tbl(l_idx).dept_description       := l_department_name;
1386 
1387                 -- Populate resource name, type code, type meaning and description
1388                 OPEN l_resource_dtl_csr(l_resc_tbl(j));
1389                 FETCH l_resource_dtl_csr into l_resource_dtl_rec;
1390                 CLOSE l_resource_dtl_csr;
1391 
1392                 x_per_rsrc_tbl(l_idx).resource_type          := l_resource_dtl_rec.RESOURCE_TYPE;
1393                 x_per_rsrc_tbl(l_idx).resource_type_meaning  := l_resource_dtl_rec.RESOURCE_TYPE_MEAN;
1394                 x_per_rsrc_tbl(l_idx).resource_name          := l_resource_dtl_rec.RESOURCE_CODE;
1395                 x_per_rsrc_tbl(l_idx).resource_description   := l_resource_dtl_rec.DESCRIPTION;
1396 
1397                 l_idx := l_idx +1;
1398 
1399                 IF (l_log_statement >= l_log_current_level) THEN
1400                    fnd_log.string
1401                   (
1402                     fnd_log.level_statement,
1403                    'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1404                    'l_idx:'||l_idx
1405                   );
1406                 END IF;
1407 
1408             END IF;--l_unused_capacity <= p_required_capacity
1409 
1410           END IF;  -- l_available_quantity >0 AND l_required_quantity>0
1411         END IF; --l_tp_dtls_table_resc.COUNT>0
1412       END LOOP; --l_resc_tbl.LOOP
1413      END IF; -- l_resc_tbl.count
1414    END LOOP; --l_per_rsrc_tbl.LOOP
1415   END IF; -- l_per_rsrc_tbl.count
1416  END IF; --l_tp_dtls_table.count>0
1417 
1418 -- yazhou 24Aug2005 ends
1419 
1420 END LOOP; --dept id
1421 
1422   -- Check Error Message stack.
1423 
1424   x_msg_count := Fnd_Msg_Pub.count_msg;
1425   IF x_msg_count > 0 THEN
1426     RAISE  Fnd_Api.G_EXC_ERROR;
1427   END IF;
1428 
1429 
1430   -- Standard check of p_commit
1431   IF Fnd_Api.TO_BOOLEAN(p_commit) THEN
1432       COMMIT WORK;
1433   END IF;
1434 
1435   -- Standard call to get message count and if count is 1, get message info
1436   Fnd_Msg_Pub.Count_And_Get
1437     ( p_count => x_msg_count,
1438       p_data  => x_msg_data,
1439       p_encoded => Fnd_Api.g_false
1440     );
1441 
1442   -- Disable debug (if enabled)
1443   Ahl_Debug_Pub.disable_debug;
1444 
1445 EXCEPTION
1446  WHEN Fnd_Api.G_EXC_ERROR THEN
1447    ROLLBACK TO Get_Rsrc_Req_By_Period_pvt;
1448    x_return_status := Fnd_Api.G_RET_STS_ERROR;
1449    Fnd_Msg_Pub.count_and_get( p_count => x_msg_count,
1450                               p_data  => x_msg_data,
1451                               p_encoded => Fnd_Api.g_false);
1452 
1453  WHEN Fnd_Api.G_EXC_UNEXPECTED_ERROR THEN
1454    ROLLBACK TO Get_Rsrc_Req_By_Period_pvt;
1455    x_return_status := Fnd_Api.G_RET_STS_UNEXP_ERROR;
1456    Fnd_Msg_Pub.count_and_get( p_count => x_msg_count,
1457                               p_data  => x_msg_data,
1458                               p_encoded => Fnd_Api.g_false);
1459 
1460  WHEN OTHERS THEN
1461     ROLLBACK TO Get_Rsrc_Req_By_Period_pvt;
1462     x_return_status := Fnd_Api.G_RET_STS_UNEXP_ERROR;
1463     IF Fnd_Msg_Pub.check_msg_level(Fnd_Msg_Pub.G_MSG_LVL_UNEXP_ERROR) THEN
1464        Fnd_Msg_Pub.add_exc_msg(p_pkg_name       => G_PKG_NAME,
1465                                p_procedure_name => 'Get_Rsrc_Req_By_Period',
1466                                p_error_text     => SUBSTR(SQLERRM,1,240));
1467     END IF;
1468     Fnd_Msg_Pub.count_and_get( p_count => x_msg_count,
1469                                p_data  => x_msg_data,
1470                                p_encoded => Fnd_Api.g_false);
1471 
1472 END Get_Rsrc_Req_By_Period;
1473 
1474 
1475 -- Start of Comments --
1476 --  Procedure name    : Get_Task_Requirements
1477 --  Type              : Private
1478 --  Function          : Gets the Requirements of a Resource by Visit/Task
1479 --                      for a given department, during a given period,
1480 --                      for a given Plan
1481 --  Pre-reqs    :
1482 --  Parameters  :
1483 --
1484 --  Standard IN  Parameters :
1485 --      p_api_version                   IN      NUMBER       Required
1486 --      p_init_msg_list                 IN      VARCHAR2     Default  FND_API.G_FALSE
1487 --      p_commit                        IN      VARCHAR2     Default  FND_API.G_FALSE
1488 --      p_validation_level              IN      NUMBER       Default  FND_API.G_VALID_LEVEL_FULL
1489 --      p_default                       IN      VARCHAR2     Default  FND_API.G_TRUE
1490 --      p_module_type                   IN      VARCHAR2     Default  NULL.
1491 --
1492 --  Standard OUT Parameters :
1493 --      x_return_status                 OUT     VARCHAR2     Required
1494 --      x_msg_count                     OUT     NUMBER       Required
1495 --      x_msg_data                      OUT     VARCHAR2     Required
1496 --
1497 --  Get_Plan_Resources Parameters:
1498 --      p_dept_id                       IN      NUMBER       REQUIRED
1499 --         The department that is to be searched for resources
1500 --      p_dept_name                     IN      VARCHAR2     REQUIRED
1501 --         The name of the department (will be mapped to Id if p_dept_id is not given)
1502 --      p_org_name                      IN      VARCHAR2     REQUIRED
1503 --         The name of the organization where the department is
1504 --      p_plan_id                       IN      NUMBER     REQUIRED
1505 --         The id of the plan for which to get the resources
1506 --      p_start_time                    IN      DATE         REQUIRED
1507 --         Start time filter for tasks. Only tasks that are in progress at or after this
1508 --         time will be considered. Tasks that end before this time will be ignored.
1509 --      p_end_time                      IN      DATE         REQUIRED
1510 --         End time filter for tasks. Only tasks that are in progress before this
1511 --         time will be considered. Tasks that start at or after this time will be ignored.
1512 --      p_resource_id                   IN      NUMBER     REQUIRED
1513 --         The id of the Resource whose requirements/Availabilities are to be derived
1514 --      p_aso_bom_rsrc_type             IN      VARCHAR2    REQUIRED
1515 --         The type of the resource (ASORESOURCE or BOMRESOURCE)
1516 --      x_task_req_tbl                  OUT     Task_Requirement_Tbl_Type
1517 --         The table containing the resource requirements.
1518 --
1519 --  Version :
1520 --      Initial Version   1.0
1521 --
1522 --  End of Comments.
1523 PROCEDURE Get_Task_Requirements
1524 (
1525     p_api_version           IN            NUMBER,
1526     p_init_msg_list         IN            VARCHAR2  := Fnd_Api.G_FALSE,
1527     p_commit                IN            VARCHAR2  := Fnd_Api.G_FALSE,
1528     p_validation_level      IN            NUMBER    := Fnd_Api.G_VALID_LEVEL_FULL,
1529     p_default               IN            VARCHAR2  := Fnd_Api.G_TRUE,
1530     p_module_type           IN            VARCHAR2  := NULL,
1531     p_dept_id               IN            NUMBER,
1532     p_dept_name             IN            VARCHAR2,
1533     p_org_name              IN            VARCHAR2,
1534     p_plan_id               IN            NUMBER,
1535     p_start_time            IN            DATE,
1536     p_end_time              IN            DATE,
1537     p_dstart_time           IN            DATE,
1538     p_dend_time             IN            DATE,
1539     p_resource_id           IN            NUMBER,
1540     p_aso_bom_rsrc_type     IN            VARCHAR2,
1541     x_task_req_tbl          OUT  NOCOPY  AHL_LTP_RESRC_LEVL_PVT.Task_Requirement_Tbl_Type,
1542     x_return_status         OUT NOCOPY           VARCHAR2,
1543     x_msg_count             OUT NOCOPY           NUMBER,
1544     x_msg_data              OUT NOCOPY           VARCHAR2
1545 ) IS
1546 
1547 
1548  /* Modified l_dept_id_csr by mpothuku on 01/18/05
1549      to add the exists condition to retrieve only department with shifts
1550   */
1551 
1552   CURSOR l_dept_id_csr(p_dept_name IN VARCHAR2, p_org_name IN VARCHAR2) IS
1553     SELECT department_id,org.organization_id FROM bom_departments dept, hr_all_organization_units org
1554     WHERE org.name = p_org_name AND
1555     dept.ORGANIZATION_ID = org.ORGANIZATION_ID AND
1556     dept.description = p_dept_name and exists ( SELECT 'x' FROM AHL_DEPARTMENT_SHIFTS WHERE DEPARTMENT_ID = dept.DEPARTMENT_ID);
1557 
1558   /* Added the exists condition to retrieve only departments with shifts */
1559   CURSOR l_validate_dept_csr(l_dept_id IN NUMBER) IS
1560     SELECT 'x' FROM bom_departments WHERE
1561     department_id = l_dept_id and exists ( SELECT 'x' FROM AHL_DEPARTMENT_SHIFTS WHERE DEPARTMENT_ID = bom_departments.DEPARTMENT_ID);
1562 
1563    CURSOR l_validate_plan_csr(l_plan_id IN NUMBER) IS
1564     SELECT 'x' FROM ahl_simulation_plans_b WHERE
1565     simulation_plan_id = l_plan_id;
1566 
1567 
1568   l_api_version     CONSTANT NUMBER := 1.0;
1569   l_api_name        CONSTANT VARCHAR2(30) := 'Get_Task_Requirements';
1570 
1571   l_dept_id         NUMBER := NULL;
1572   l_org_id          NUMBER;
1573   l_junk            VARCHAR2(1);
1574   l_task_times_tbl  Visit_Task_Times_Tbl_Type;
1575   l_temp_rsrc_tbl   Plan_Rsrc_Tbl_Type;
1576   l_tp_dtls_table     Time_Period_Details_Tbl_Type;
1577   l_start_time      DATE;
1578   l_end_time        DATE;
1579   l_aso_resource_id NUMBER;
1580 BEGIN
1581 --  dbms_output.put_line('Entering Get_Task_Requirements');
1582   -- Standard start of API savepoint
1583   SAVEPOINT Get_Task_Requirements_pvt;
1584 
1585   -- Standard call to check for call compatibility
1586   IF NOT Fnd_Api.Compatible_API_Call(l_api_version, p_api_version, l_api_name,
1587                                      G_PKG_NAME) THEN
1588     RAISE Fnd_Api.G_EXC_UNEXPECTED_ERROR;
1589   END IF;
1590 
1591     -- Initialize message list if p_init_msg_list is set to TRUE
1592   IF Fnd_Api.To_Boolean(p_init_msg_list) THEN
1593     Fnd_Msg_Pub.Initialize;
1594   END IF;
1595 
1596   -- Initialize API return status to success
1597   x_return_status := Fnd_Api.G_RET_STS_SUCCESS;
1598 
1599   -- Enable Debug (optional)
1600   Ahl_Debug_Pub.enable_debug;
1601 
1602   -- Begin Processing
1603 --  dbms_output.put_line('BEGIN Processing');
1604   -- Map Dept Name To Dept Id
1605   IF (p_module_type = G_JSP_MODULE_TYPE) THEN
1606 --    dbms_output.put_line('JSP MODULE: Doing Value TO ID Conversion');
1607     OPEN l_dept_id_csr(p_dept_name, p_org_name);
1608     FETCH l_dept_id_csr INTO l_dept_id,l_org_id;
1609     IF (l_dept_id_csr%NOTFOUND) THEN
1610       Fnd_Message.Set_Name('AHL','AHL_LTP_DEPT_INV_OR_NO_SFT');
1611       Fnd_Message.Set_Token('DEPT', p_dept_name);
1612       Fnd_Msg_Pub.ADD;
1613       CLOSE l_dept_id_csr;
1614       RAISE  Fnd_Api.G_EXC_ERROR;
1615     END IF;
1616     CLOSE l_dept_id_csr;
1617 --    dbms_output.put_line('l_dept_id = ' || l_dept_id);
1618   ELSE
1619     -- Validate Dept Id
1620     IF (p_dept_id IS NULL) THEN
1621       Fnd_Message.Set_Name('AHL','AHL_LTP_DEPT_NULL');
1622       Fnd_Msg_Pub.ADD;
1623       RAISE  Fnd_Api.G_EXC_ERROR;
1624     ELSE
1625       OPEN l_validate_dept_csr(p_dept_id);
1626       FETCH l_validate_dept_csr INTO l_junk;
1627       IF (l_validate_dept_csr%NOTFOUND) THEN
1628         Fnd_Message.Set_Name('AHL','AHL_LTP_DEPT_INV_OR_NO_SFT');
1629         Fnd_Message.Set_Token('DEPT', p_dept_id);
1630         Fnd_Msg_Pub.ADD;
1631         CLOSE l_validate_dept_csr;
1632         RAISE  Fnd_Api.G_EXC_ERROR;
1633       END IF;
1634       CLOSE l_validate_dept_csr;
1635     END IF;
1636     l_dept_id := p_dept_id;
1637 --    dbms_output.put_line('l_dept_id = ' || l_dept_id);
1638   END IF;
1639 
1640   -- Validate Plan Id
1641   IF (p_plan_id IS NULL) THEN
1642     Fnd_Message.Set_Name('AHL','AHL_LTP_PLAN_ID_NULL');
1643     Fnd_Msg_Pub.ADD;
1644     RAISE  Fnd_Api.G_EXC_ERROR;
1645   ELSE
1646     OPEN l_validate_plan_csr(p_plan_id);
1647     FETCH l_validate_plan_csr INTO l_junk;
1648     IF (l_validate_plan_csr%NOTFOUND) THEN
1649       Fnd_Message.Set_Name('AHL','AHL_LTP_PLAN_ID_INVALID');
1650       Fnd_Message.Set_Token('PLAN', p_plan_id);
1651       Fnd_Msg_Pub.ADD;
1652       CLOSE l_validate_plan_csr;
1653       RAISE  Fnd_Api.G_EXC_ERROR;
1654     END IF;
1655     CLOSE l_validate_plan_csr;
1656   END IF;
1657 --  dbms_output.put_line('p_plan_id = ' || p_plan_id);
1658 
1659   -- Validate Dates
1660   IF (p_start_time IS NOT NULL AND p_end_time IS NOT NULL AND p_start_time > p_end_time) THEN
1661     Fnd_Message.Set_Name('AHL','AHL_LTP_STIME_GT_ETIME');
1662     Fnd_Message.Set_Token('STIME', p_start_time);
1663     Fnd_Message.Set_Token('ETIME', p_end_time);
1664     Fnd_Msg_Pub.ADD;
1665     RAISE  Fnd_Api.G_EXC_ERROR;
1666   END IF;
1667 
1668 --  dbms_output.put_line('Completed Mapping. Calling Get_Plan_Tasks');
1669 --  l_start_time := trunc(p_start_time);
1670 --  l_end_time := trunc(p_start_time) + 1;
1671 
1672   -- Get all the tasks for the given dept/plan
1673   -- that are in progress during the given timeframe
1674   Get_Plan_Tasks(
1675     p_dept_id              => p_dept_id,
1676     p_plan_id              => p_plan_id,
1677     p_start_time           => p_start_time,
1678     p_end_time             => p_end_time,
1679     p_inc_primary_flag     => TRUE,  -- Need to include primary plan tasks if this plan is a simulation
1680 --    p_op_times_flag        => TRUE,  -- Need to get Operation Time Period details
1681     x_tp_dtls_tbl          => l_tp_dtls_table, -- Table for Operation Time Period details
1682     x_visit_task_times_tbl => l_task_times_tbl);
1683 
1684   --  dbms_output.put_line('Completed Get_Plan_Tasks. Calling Filter_By_Resource');
1685   Ahl_Debug_Pub.debug('before call filter l_tp_dtls_table.COUNT = ' || l_tp_dtls_table.COUNT);
1686   Ahl_Debug_Pub.debug('p_resource_id = ' || p_resource_id);
1687   Ahl_Debug_Pub.debug('p_strat_time = ' || p_start_time);
1688   Ahl_Debug_Pub.debug('p_end_time   = ' || p_end_time);
1689 
1690   -- Filter by the required resource and get quantity
1691   Filter_By_Resource(
1692     p_resource_id    => p_resource_id,
1693   p_start_time     => p_dstart_time,
1694   p_end_time       => p_dend_time,
1695     p_x_tp_dtls_tbl  => l_tp_dtls_table);
1696 
1697 --  dbms_output.put_line('l_tp_dtls_table.COUNT = ' || l_tp_dtls_table.COUNT);
1698 
1699   Ahl_Debug_Pub.debug('l_tp_dtls_tablafter filter = ' || l_tp_dtls_table.COUNT);
1700 
1701   -- Sort By Visit, Task
1702   Sort_By_Visit_Task(l_tp_dtls_table);
1703 
1704   Ahl_Debug_Pub.debug('after sort by visit = ' || l_tp_dtls_table.COUNT);
1705 
1706   -- Aggregate task quantities and get visit and task names into output table
1707   Aggregate_Task_Quantities(p_resource_id,p_org_name, p_dept_name, l_tp_dtls_table, x_task_req_tbl);
1708 
1709   Ahl_Debug_Pub.debug('x_task_req_tbl.COUNT = ' || x_task_req_tbl.COUNT);
1710 
1711 --  dbms_output.put_line('x_task_req_tbl.COUNT = ' || x_task_req_tbl.COUNT);
1712   Ahl_Debug_Pub.debug('Completed Processing. Checking FOR errors', 'LTP');
1713   -- Check Error Message stack.
1714   x_msg_count := Fnd_Msg_Pub.count_msg;
1715   IF x_msg_count > 0 THEN
1716     RAISE  Fnd_Api.G_EXC_ERROR;
1717   END IF;
1718 
1719   -- Standard check of p_commit
1720   IF Fnd_Api.TO_BOOLEAN(p_commit) THEN
1721       COMMIT WORK;
1722   END IF;
1723 
1724   -- Standard call to get message count and if count is 1, get message info
1725   Fnd_Msg_Pub.Count_And_Get
1726     ( p_count => x_msg_count,
1727       p_data  => x_msg_data,
1728       p_encoded => Fnd_Api.g_false
1729     );
1730 
1731   -- Disable debug (if enabled)
1732   Ahl_Debug_Pub.disable_debug;
1733 
1734 EXCEPTION
1735  WHEN Fnd_Api.G_EXC_ERROR THEN
1736    ROLLBACK TO Get_Task_Requirements_pvt;
1737    x_return_status := Fnd_Api.G_RET_STS_ERROR;
1738    Fnd_Msg_Pub.count_and_get( p_count => x_msg_count,
1739                               p_data  => x_msg_data,
1740                               p_encoded => Fnd_Api.g_false);
1741 
1742  WHEN Fnd_Api.G_EXC_UNEXPECTED_ERROR THEN
1743    ROLLBACK TO Get_Task_Requirements_pvt;
1744    x_return_status := Fnd_Api.G_RET_STS_UNEXP_ERROR;
1745    Fnd_Msg_Pub.count_and_get( p_count => x_msg_count,
1746                               p_data  => x_msg_data,
1747                               p_encoded => Fnd_Api.g_false);
1748 
1749  WHEN OTHERS THEN
1750     ROLLBACK TO Get_Task_Requirements_pvt;
1751     x_return_status := Fnd_Api.G_RET_STS_UNEXP_ERROR;
1752     IF Fnd_Msg_Pub.check_msg_level(Fnd_Msg_Pub.G_MSG_LVL_UNEXP_ERROR) THEN
1753        Fnd_Msg_Pub.add_exc_msg(p_pkg_name       => G_PKG_NAME,
1754                                p_procedure_name => 'Get_Task_Requirements',
1755                                p_error_text     => SUBSTR(SQLERRM,1,240));
1756     END IF;
1757     Fnd_Msg_Pub.count_and_get( p_count => x_msg_count,
1758                                p_data  => x_msg_data,
1759                                p_encoded => Fnd_Api.g_false);
1760 
1761 END Get_Task_Requirements;
1762 
1763 ----------------------------------------
1764 -- Local Procedure Definitions follow --
1765 ----------------------------------------
1766 ----------------------------------------
1767 -- Gets all the tasks and their times for all visits
1768 -- for a given plan and department during a given period
1769 -- If current plan is a simulation and the p_inc_primary flag is 'Y'
1770 -- Visits in primary plan are also included.
1771 ----------------------------------------
1772 
1773 -- yazhou 24Aug2005 starts
1774 -- Resource Leveling Re-design
1775 -- changed x_visit_task_times_tbl from in out parameter to out parameter only
1776 -- removed p_op_times_flag
1777 PROCEDURE Get_Plan_Tasks
1778 (
1779     p_dept_id               IN            NUMBER,
1780     p_plan_id               IN            NUMBER,
1781     p_start_time            IN            DATE,
1782     p_end_time              IN            DATE,
1783     p_inc_primary_flag      IN            BOOLEAN := FALSE,
1784     x_tp_dtls_tbl           OUT NOCOPY Time_Period_Details_Tbl_Type,
1785     x_visit_task_times_tbl  OUT NOCOPY    Visit_Task_Times_Tbl_Type
1786 ) IS
1787 
1788   -- Should include visits with tasks in given department as well as
1789   -- those visits with given department
1790   CURSOR l_get_plan_visits(p_dept_id  IN NUMBER,
1791                            p_plan_id  IN NUMBER,
1792                            p_start_time IN DATE,
1793                            p_end_time IN DATE) IS
1794     SELECT VISIT_ID
1795     FROM ahl_visits_b v
1796     WHERE (DEPARTMENT_ID = p_dept_id OR
1797            (DEPARTMENT_ID is not null and exists (select 1
1798                                                 FROM ahl_visit_tasks_b
1799                                                 where visit_id =v.visit_id
1800                                                 AND department_id =p_dept_id
1801                                                 AND nvl(status_code,'x') ='PLANNING'))) AND
1802     SIMULATION_PLAN_ID = p_plan_id AND
1803     STATUS_CODE IN ('PLANNING','PARTIALLY RELEASED') AND
1804     START_DATE_TIME IS NOT NULL AND
1805     trunc(START_DATE_TIME) <= p_end_time AND
1806     AHL_VWP_TIMES_PVT.get_visit_end_time(visit_id) >=p_start_time AND
1807     SIMULATION_DELETE_FLAG = 'N';
1808 
1809   CURSOR l_get_primary_visits(p_dept_id  IN NUMBER,
1810                               p_plan_id  IN NUMBER,
1811                               p_start_time IN DATE,
1812                               p_end_time IN DATE) IS
1813     SELECT VISIT_ID
1814     FROM ahl_visits_b a
1815     WHERE (DEPARTMENT_ID = p_dept_id OR
1816            (DEPARTMENT_ID is not null and exists (select 1
1817                                                 FROM ahl_visit_tasks_b
1818                                                 where visit_id =a.visit_id
1819                                                 AND department_id =p_dept_id
1820                                                 AND nvl(status_code,'x') ='PLANNING'))) AND
1821     SIMULATION_PLAN_ID IN (SELECT SIMULATION_PLAN_ID FROM ahl_simulation_plans_b WHERE
1822                            PRIMARY_PLAN_FLAG = G_PLAN_TYPE_PRIMARY) AND
1823     NOT EXISTS (SELECT 1 FROM ahl_visits_b  WHERE SIMULATION_PLAN_ID = p_plan_id
1824                                               AND ASSO_PRIMARY_VISIT_ID = a.VISIT_ID) AND
1825     STATUS_CODE IN ('PLANNING','PARTIALLY RELEASED') AND
1826     START_DATE_TIME IS NOT NULL AND
1827     trunc(START_DATE_TIME) <= p_end_time AND
1828     AHL_VWP_TIMES_PVT.get_visit_end_time(visit_id) >=p_start_time;
1829 
1830 -- yazhou 24Aug2005 ends
1831 
1832   CURSOR l_get_plan_type_csr(p_plan_id IN NUMBER) IS
1833     SELECT PRIMARY_PLAN_FLAG FROM ahl_simulation_plans_b
1834     WHERE SIMULATION_PLAN_ID = p_plan_id;
1835 
1836   l_api_version     CONSTANT NUMBER := 1.0;
1837   l_api_name        CONSTANT VARCHAR2(30) := 'Get_Plan_Tasks';
1838 
1839   l_temp_times_tbl  Visit_Task_Times_Tbl_Type;
1840   l_final_times_tbl Visit_Task_Times_Tbl_Type;
1841   l_temp_index      NUMBER := 1;
1842   l_temp_visit      NUMBER;
1843   l_temp_sttime     DATE;
1844   l_temp_endtime    DATE;
1845   l_return_status  VARCHAR2(1);
1846   l_msg_count NUMBER;
1847   l_msg_data VARCHAR2(1000);
1848   l_temp_num1 NUMBER;
1849   l_plan_type VARCHAR2(30);
1850   l_end_time   DATE := trunc(p_end_time);
1851 
1852 BEGIN
1853 
1854   IF (l_log_statement >= l_log_current_level) THEN
1855         fnd_log.string
1856         (
1857           fnd_log.level_statement,
1858           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1859           'p_start_time:'||p_start_time
1860         );
1861         fnd_log.string
1862         (
1863           fnd_log.level_statement,
1864           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1865           'l_end_time:'||l_end_time
1866         );
1867         fnd_log.string
1868         (
1869           fnd_log.level_statement,
1870           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1871           'p_dept_id:'||p_dept_id
1872         );
1873 
1874   END IF;
1875 
1876   OPEN l_get_plan_visits(p_dept_id, p_plan_id, p_start_time,l_end_time);
1877   LOOP
1878     FETCH l_get_plan_visits INTO l_temp_visit;
1879     EXIT WHEN l_get_plan_visits%NOTFOUND;
1880 
1881      IF (l_log_statement >= l_log_current_level) THEN
1882         fnd_log.string
1883         (
1884           fnd_log.level_statement,
1885           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1886           'l_temp_visit:'||l_temp_visit
1887         );
1888      END IF;
1889 
1890 -- yazhou 24Aug2005 starts
1891 -- Resource Leveling Re-design
1892 
1893 -- removed the logic to check for mr route ID
1894 --since now that's done inside Derive_Task_Op_Times already
1895 
1896      -- Call helper method to do the actual processing
1897      Derive_Task_Op_Times(
1898       p_visit_id              => l_temp_visit,
1899       p_start_time            => p_start_time,
1900       p_end_time              => p_end_time,
1901       p_department_id         => p_dept_id,
1902       p_x_tp_dtls_tbl         => x_tp_dtls_tbl, -- Table for Operation Time Periods
1903       x_visit_start_time      => l_temp_sttime,
1904       x_visit_end_time        => l_temp_endtime,
1905       x_visit_end_hour        => l_temp_num1,
1906       x_visit_task_times_tbl  => l_final_times_tbl);
1907 
1908      IF (l_log_statement >= l_log_current_level) THEN
1909         fnd_log.string
1910         (
1911           fnd_log.level_statement,
1912           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1913           'After calling Derive_Task_Op_Times'
1914         );
1915         fnd_log.string
1916         (
1917           fnd_log.level_statement,
1918           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1919           'l_final_times_tbl.count: '|| l_final_times_tbl.count
1920         );
1921      END IF;
1922 
1923 /*
1924      -- Collect the task info for the current visit into the master tasks table
1925      IF (l_temp_times_tbl.COUNT > 0) THEN
1926 
1927       l_temp_num1 := l_temp_times_tbl.FIRST;
1928 
1929       WHILE l_temp_num1 IS NOT NULL LOOP
1930         IF l_temp_times_tbl(l_temp_num1).mr_route_id IS NOT NULL
1931     THEN
1932         l_final_times_tbl(l_temp_index) := l_temp_times_tbl(l_temp_num1);
1933         l_temp_index := l_temp_index + 1;
1934 
1935         END IF;
1936     l_temp_num1 := l_temp_times_tbl.NEXT(l_temp_num1);
1937       END LOOP;  -- All valid tasks for current visit
1938     END IF;
1939 
1940 */
1941 -- yazhou 24Aug2005 ends
1942 
1943   END LOOP;  -- All valid visits for current dept
1944   CLOSE l_get_plan_visits;
1945 
1946 
1947   IF (p_inc_primary_flag) THEN
1948     -- Need to include primary plan visits also
1949 --    dbms_output.put_line('Getting PRIMARY Plans Visits');
1950     OPEN l_get_plan_type_csr(p_plan_id);
1951     FETCH l_get_plan_type_csr INTO l_plan_type;
1952     CLOSE l_get_plan_type_csr;
1953 
1954      IF (l_log_statement >= l_log_current_level) THEN
1955         fnd_log.string
1956         (
1957           fnd_log.level_statement,
1958           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1959           'l_plan_type: '|| l_plan_type
1960         );
1961      END IF;
1962 
1963     IF (l_plan_type <> G_PLAN_TYPE_PRIMARY) THEN
1964       -- Current Plan is a simulation: Include primary plan's visit tasks
1965       OPEN l_get_primary_visits(p_dept_id, p_plan_id, p_start_time, l_end_time);
1966       LOOP
1967         FETCH l_get_primary_visits INTO l_temp_visit;
1968         EXIT WHEN l_get_primary_visits%NOTFOUND;
1969 
1970         IF (l_log_statement >= l_log_current_level) THEN
1971             fnd_log.string
1972             (
1973               fnd_log.level_statement,
1974               'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1975               'l_temp_visit:'||l_temp_visit
1976              );
1977         END IF;
1978 
1979         -- Call helper method to do the actual processing
1980         Derive_Task_Op_Times(
1981           p_visit_id              => l_temp_visit,
1982           p_start_time            => p_start_time,
1983           p_end_time              => p_end_time,
1984           p_department_id         => p_dept_id,
1985           p_x_tp_dtls_tbl         => x_tp_dtls_tbl, -- Table for Operation Time Periods
1986           x_visit_start_time      => l_temp_sttime,
1987           x_visit_end_time        => l_temp_endtime,
1988           x_visit_end_hour        => l_temp_num1,
1989           x_visit_task_times_tbl  => l_temp_times_tbl);
1990 
1991         IF (l_log_statement >= l_log_current_level) THEN
1992           fnd_log.string
1993           (
1994             fnd_log.level_statement,
1995             'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
1996             'After calling Derive_Task_Op_Times'
1997           );
1998           fnd_log.string
1999           (
2000             fnd_log.level_statement,
2001             'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2002             'l_temp_times_tbl.count: '|| l_temp_times_tbl.count
2003           );
2004         END IF;
2005 
2006 
2007 -- yazhou 24Aug2005 starts
2008 -- Resource Leveling Re-design
2009 
2010 -- removed the logic to check for mr route ID
2011 --since now that's done inside Derive_Task_Op_Times already
2012 
2013         -- Collect the task info for the current visit into the master tasks table
2014         IF (l_temp_times_tbl.COUNT > 0) THEN
2015           l_temp_num1 := l_temp_times_tbl.FIRST;
2016           l_temp_index := l_final_times_tbl.LAST +1;
2017 
2018           WHILE l_temp_num1 IS NOT NULL LOOP
2019 
2020 --          IF l_temp_times_tbl(l_temp_num1).mr_route_id IS NOT NULL THEN
2021             l_final_times_tbl(l_temp_index) := l_temp_times_tbl(l_temp_num1);
2022             l_temp_index := l_temp_index + 1;
2023 
2024 --          END IF;
2025         l_temp_num1 := l_temp_times_tbl.NEXT(l_temp_num1);
2026 
2027 
2028           END LOOP;  -- All valid tasks for current visit
2029         END IF;
2030 
2031 -- yazhou 24Aug2005 ends
2032 
2033       END LOOP;  -- All valid primary plan visits for current dept
2034       CLOSE l_get_primary_visits;
2035     END IF;
2036   END IF;
2037 
2038   x_visit_task_times_tbl := l_final_times_tbl;
2039 
2040   IF (l_log_statement >= l_log_current_level) THEN
2041         fnd_log.string
2042         (
2043           fnd_log.level_statement,
2044           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2045           'x_visit_task_times_tbl.count: '|| x_visit_task_times_tbl.count
2046         );
2047   END IF;
2048 
2049   IF x_visit_task_times_tbl.COUNT >0 THEN
2050     FOR i IN x_visit_task_times_tbl.FIRST..x_visit_task_times_tbl.LAST
2051    LOOP
2052    --
2053 --   Ahl_Debug_Pub.debug('Exiting GET_PLAN_TASKS MR ID:'||x_visit_task_times_tbl(i).mr_route_id);
2054 --   Ahl_Debug_Pub.debug('Exiting GET_PLAN_TASKS VTID:'||x_visit_task_times_tbl(i).visit_task_id);
2055 --   Ahl_Debug_Pub.debug('Exiting GET_PLAN_TASKS STIME:'||x_visit_task_times_tbl(i).task_start_time);
2056 --   Ahl_Debug_Pub.debug('Exiting GET_PLAN_TASKS ETIME:'||x_visit_task_times_tbl(i).task_end_time);
2057      null;
2058    --
2059    END LOOP;
2060    END IF;
2061    --
2062 IF x_tp_dtls_tbl.COUNT >0 THEN
2063  FOR i IN x_tp_dtls_tbl.FIRST..x_tp_dtls_tbl.LAST
2064  LOOP
2065 
2066    IF (l_log_statement >= l_log_current_level) THEN
2067       fnd_log.string
2068         (
2069           fnd_log.level_statement,
2070           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2071           'x_tp_dtls_tbl('||i||').visit_id: '|| x_tp_dtls_tbl(i).visit_id
2072         );
2073       fnd_log.string
2074         (
2075           fnd_log.level_statement,
2076           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2077           'x_tp_dtls_tbl('||i||').route_id: '|| x_tp_dtls_tbl(i).route_id
2078         );
2079       fnd_log.string
2080         (
2081           fnd_log.level_statement,
2082           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2083           'x_tp_dtls_tbl('||i||').mr_route_id: '|| x_tp_dtls_tbl(i).mr_route_id
2084         );
2085       fnd_log.string
2086         (
2087           fnd_log.level_statement,
2088           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2089           'x_tp_dtls_tbl('||i||').operation_id: '|| x_tp_dtls_tbl(i).operation_id
2090         );
2091       fnd_log.string
2092         (
2093           fnd_log.level_statement,
2094           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2095           'x_tp_dtls_tbl('||i||').task_id: '|| x_tp_dtls_tbl(i).task_id
2096         );
2097       fnd_log.string
2098         (
2099           fnd_log.level_statement,
2100           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2101           'x_tp_dtls_tbl('||i||').start_time: '|| x_tp_dtls_tbl(i).start_time
2102         );
2103       fnd_log.string
2104         (
2105           fnd_log.level_statement,
2106           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2107           'x_tp_dtls_tbl('||i||').end_time: '|| x_tp_dtls_tbl(i).end_time
2108         );
2109       fnd_log.string
2110         (
2111           fnd_log.level_statement,
2112           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2113           'x_tp_dtls_tbl('||i||').bom_resource_id: '|| x_tp_dtls_tbl(i).bom_resource_id
2114         );
2115       fnd_log.string
2116         (
2117           fnd_log.level_statement,
2118           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2119           'x_tp_dtls_tbl('||i||').department_id: '|| x_tp_dtls_tbl(i).department_id
2120         );
2121       fnd_log.string
2122         (
2123           fnd_log.level_statement,
2124           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2125           'x_tp_dtls_tbl('||i||').quantity: '|| x_tp_dtls_tbl(i).quantity
2126         );
2127 
2128     END IF;
2129  END LOOP;
2130 END IF;
2131 
2132    --
2133 END Get_Plan_Tasks;
2134 
2135 ----------------------------------------
2136 -- Gets the task and operation times for a given visit
2137 -- Also builds the Time Period table if required
2138 ----------------------------------------
2139 -- yazhou 24Aug2005 starts
2140 -- Resource Leveling Re-design
2141 
2142 -- The start/end time calulation is no longer required
2143 -- since now task time is calculated and stored in VWP
2144 
2145 -- added p_department_id as input parameter
2146 -- and removed default values for start/end time and p_op_times_flag
2147 
2148 -- Return only time for tasks with MR route associated
2149 
2150 PROCEDURE Derive_Task_Op_Times
2151 (
2152     p_visit_id              IN            NUMBER,
2153     p_start_time            IN            DATE,
2154     p_end_time              IN            DATE,
2155     p_department_id         IN            NUMBER,
2156     p_x_tp_dtls_tbl         IN OUT NOCOPY Time_Period_Details_Tbl_Type,
2157     x_visit_start_time      OUT NOCOPY           DATE,
2158     x_visit_end_time        OUT NOCOPY           DATE,
2159     x_visit_end_hour        OUT NOCOPY           NUMBER,
2160     x_visit_task_times_tbl  OUT NOCOPY Visit_Task_Times_Tbl_Type
2161 ) IS
2162 
2163   -- Find all the tasks with route associated in the given department
2164 
2165   CURSOR l_tasks_csr(p_visit_id IN NUMBER, p_dept_id IN NUMBER) IS
2166     SELECT vt.visit_task_id,  mr_route_id,
2167            NVL(start_from_hour, 0) start_from_hour,
2168            NVL(duration, 0) duration,
2169            start_date_time,
2170            end_date_time
2171     FROM  ahl_visit_tasks_b vt
2172     WHERE vt.visit_id = p_visit_id AND
2173           status_code = 'PLANNING' AND
2174          (department_id = p_dept_id OR (department_id is NULL AND
2175                                    p_dept_id = (select department_id from ahl_visits_b
2176                                                 where visit_id = p_visit_id))) AND
2177          mr_route_id is not null
2178     ORDER BY vt.visit_task_id;
2179 
2180 
2181 -- Added organization_id as select field and removed template_flag
2182 
2183   CURSOR l_visit_details_csr(p_visit_id IN NUMBER) IS
2184     SELECT start_date_time,department_id,close_date_time, organization_id
2185      FROM ahl_visits_b
2186     WHERE visit_id = p_visit_id;
2187 
2188 
2189 -- yazhou 24Aug2005 ends
2190 
2191   l_task_times_tbl    visit_task_times_Tbl_Type;
2192   l_visit_dtls_rec    l_visit_details_csr%ROWTYPE;
2193 
2194   l_dept_id          NUMBER;
2195   l_temp_num1        NUMBER;
2196   l_index            NUMBER;
2197 
2198 -- yazhou 24Aug2005 starts
2199 -- Resource Leveling Re-design
2200   l_api_name        CONSTANT VARCHAR2(30) := 'Derive_Task_Op_Times';
2201   l_org_id          NUMBER;
2202   l_tasks_rec       l_tasks_csr%ROWTYPE;
2203 -- yazhou 24Aug2005 ends
2204 
2205 BEGIN
2206 
2207   IF (l_log_statement >= l_log_current_level) THEN
2208         fnd_log.string
2209         (
2210           fnd_log.level_statement,
2211           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2212           'p_start_time:'||p_start_time
2213         );
2214         fnd_log.string
2215         (
2216           fnd_log.level_statement,
2217           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2218           'p_end_time:'||p_end_time
2219         );
2220         fnd_log.string
2221         (
2222           fnd_log.level_statement,
2223           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2224           'p_department_id:'||p_department_id
2225         );
2226         fnd_log.string
2227         (
2228           fnd_log.level_statement,
2229           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2230           'p_visit_id:'||p_visit_id
2231         );
2232         fnd_log.string
2233         (
2234           fnd_log.level_statement,
2235           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2236           'p_x_tp_dtls_tbl.count:'||p_x_tp_dtls_tbl.count
2237         );
2238 
2239   END IF;
2240   -- Get the visit details
2241   OPEN l_visit_details_csr(p_visit_id);
2242 
2243 -- yazhou 24Aug2005 starts
2244 -- Resource Leveling Re-design
2245 -- Added organization_id as select field
2246   FETCH l_visit_details_csr INTO x_visit_start_time, l_dept_id,
2247                                  x_visit_end_time,l_org_id;
2248 -- yazhou 24Aug2005 ends
2249 
2250   IF(l_visit_details_csr%NOTFOUND) THEN
2251     Fnd_Message.Set_Name('AHL','AHL_LTP_VISIT_ID_NULL');
2252     Fnd_Msg_Pub.ADD;
2253     CLOSE l_visit_details_csr;
2254     Ahl_Debug_Pub.debug('Invalid visit Id', 'LTP: Derive_Visit_Task_Times');
2255     RAISE  Fnd_Api.G_EXC_UNEXPECTED_ERROR;
2256   END IF;
2257   CLOSE l_visit_details_csr;
2258 
2259 -- yazhou 24Aug2005 starts
2260 -- Resource Leveling Re-design
2261 
2262 -- x_visit_end_time null check is not required for resource leveling
2263 
2264   IF x_visit_end_time IS NOT NULL THEN
2265      x_visit_end_hour := to_number(to_char(x_visit_end_time,'HH24'));
2266   END IF;
2267 
2268 -- Get task start/end time from VWP directly
2269   OPEN l_tasks_csr(p_visit_id,p_department_id);
2270   LOOP
2271     FETCH l_tasks_csr INTO l_tasks_rec;
2272     EXIT WHEN l_tasks_csr%NOTFOUND;
2273        l_index := l_tasks_rec.visit_task_id;
2274        l_task_times_tbl(l_index).VISIT_TASK_ID := l_index;
2275        l_task_times_tbl(l_index).MR_ROUTE_ID := l_tasks_rec.mr_route_id;
2276        Get_Route_Duration(l_tasks_rec.mr_route_id, l_task_times_tbl(l_index).TASK_DURATION);
2277        l_task_times_tbl(l_index).TASK_START_TIME := l_tasks_rec.start_date_time;
2278        l_task_times_tbl(l_index).TASK_END_TIME := l_tasks_rec.end_date_time;
2279        l_task_times_tbl(l_index).TASK_START_HOUR := to_number(to_char(l_tasks_rec.start_date_time,'HH24'));
2280        l_task_times_tbl(l_index).TASK_END_HOUR := to_number(to_char(l_tasks_rec.end_date_time,'HH24'));
2281 
2282   END LOOP;
2283   CLOSE l_tasks_csr;
2284 
2285   -- yazhou: remove the IF condition since template check is no longer required
2286   -- and p_start_time/p_end_time both cannot be null
2287 
2288   -- Filter based on time period: Currenlty supporting filtering only if
2289   -- both: start time as well as end time are given
2290 
2291 --  IF (l_template_flag = 'Y' OR p_start_time IS NULL OR p_end_time IS NULL) THEN
2292 --    x_visit_task_times_tbl := l_task_times_tbl;
2293 --  ELSE
2294 
2295    IF (l_log_statement >= l_log_current_level) THEN
2296         fnd_log.string
2297         (
2298           fnd_log.level_statement,
2299           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2300           'l_task_times_tbl.COUNT:'||l_task_times_tbl.COUNT
2301         );
2302    END IF;
2303 
2304    IF l_task_times_tbl.COUNT > 0 THEN
2305 
2306       -- To set all the global constants about the Department.
2307       INIT_TIME_VARS(x_visit_start_time, p_department_id);
2308 
2309       l_index := l_task_times_tbl.FIRST;
2310       l_temp_num1 := 1;
2311       WHILE l_index IS NOT NULL LOOP
2312 
2313 -- Requirement date should be based on operation time if requirements
2314 -- are defined for operaion, so should not only use task time to decide
2315 -- whether Get_Operation_Details should be called for this task.
2316 
2317         IF (Periods_Overlap (l_task_times_tbl(l_index).TASK_START_TIME,
2318                              l_task_times_tbl(l_index).TASK_END_TIME,
2319                              p_start_time,
2320                              p_end_time)) THEN
2321           x_visit_task_times_tbl(l_temp_num1) := l_task_times_tbl(l_index);
2322           l_temp_num1 := l_temp_num1 + 1;
2323         END IF;
2324 
2325         Get_Operation_Details(p_task_dtls     => l_task_times_tbl(l_index),
2326                                   p_visit_id      => p_visit_id,
2327                                   p_department_id => p_department_id,
2328                                   p_organization_id => l_org_id,
2329                                   p_start_time      => p_start_time,
2330                                   p_end_time        => p_end_time,
2331                                   p_x_tp_dtls_tbl => p_x_tp_dtls_tbl);
2332 
2333         IF (l_log_statement >= l_log_current_level) THEN
2334            fnd_log.string
2335            (
2336               fnd_log.level_statement,
2337              'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2338              'l_index-('||l_index||') After Calling Get_Operation_Details'
2339            );
2340            fnd_log.string
2341            (
2342               fnd_log.level_statement,
2343              'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2344              'p_x_tp_dtls_tbl.COUNT:'||p_x_tp_dtls_tbl.COUNT
2345            );
2346         END IF;
2347 
2348         l_index := l_task_times_tbl.NEXT(l_index);
2349       END LOOP;
2350     END IF;
2351 --  END IF;
2352 
2353     IF (l_log_statement >= l_log_current_level) THEN
2354            fnd_log.string
2355            (
2356               fnd_log.level_statement,
2357              'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2358              'l_task_times_tbl.COUNT:'||l_task_times_tbl.COUNT
2359            );
2360     END IF;
2361 
2362 -- yazhou 24Aug2005 ends
2363 
2364 
2365 END Derive_Task_Op_Times;
2366 
2367 ----------------------------------------
2368 -- Gets the resources required by the given task
2369 ----------------------------------------
2370 PROCEDURE Get_Task_Resources
2371 (
2372     p_required_capacity IN      NUMBER ,
2373     p_task_id           IN      NUMBER,
2374     p_tstart_date       IN      DATE,
2375     p_tend_date         IN      DATE,
2376     p_distinct_flag     IN      BOOLEAN,
2377     p_x_task_rsrc_tbl   IN OUT NOCOPY Plan_Rsrc_Tbl_Type
2378 ) IS
2379 
2380   CURSOR l_get_route_csr(p_task_id IN NUMBER) IS
2381     SELECT a.MR_ROUTE_ID,B.route_id
2382     FROM ahl_visit_tasks_b a, ahl_mr_routes_app_v B
2383     WHERE VISIT_TASK_ID = p_task_id
2384     AND a.mr_route_id = B.mr_route_id;
2385 
2386   CURSOR l_get_dept_csr(p_task_id IN NUMBER) IS
2387     SELECT vt.DEPARTMENT_ID,v.department_id,v.organization_id
2388     FROM ahl_visits_b v, ahl_visit_tasks_b vt
2389     WHERE vt.VISIT_TASK_ID = p_task_id
2390     AND v.visit_id = vt.visit_id;
2391 
2392   CURSOR l_get_rt_resources_csr(c_route_id IN NUMBER) IS
2393     SELECT ASO_RESOURCE_ID
2394     FROM ahl_rt_oper_resources WHERE
2395     ASSOCIATION_TYPE_CODE = G_RT_ASSOC_TYPE
2396     /*LTP CHANGES FOR NONSCHEDULED RESOURCE REQUIREMENTS - sowsubra*/
2397     AND NVL(SCHEDULED_TYPE_ID,1) <> 2
2398     AND OBJECT_ID = c_route_id;
2399 
2400   CURSOR l_get_oper_resources_csr(c_route_id IN NUMBER) IS
2401     SELECT ASO_RESOURCE_ID
2402     FROM ahl_rt_oper_resources WHERE
2403     ASSOCIATION_TYPE_CODE = G_OPER_ASSOC_TYPE
2404     /*LTP CHANGES FOR NONSCHEDULED RESOURCE REQUIREMENTS - sowsubra*/
2405     AND NVL(SCHEDULED_TYPE_ID,1) <> 2
2406     AND OBJECT_ID IN (SELECT OPERATION_ID FROM ahl_route_operations WHERE ROUTE_ID = c_route_id);
2407 
2408   CURSOR l_get_bom_resources_csr(c_aso_resource_id IN NUMBER,
2409                                  c_org_id  IN NUMBER) IS
2410     SELECT BOM_RESOURCE_ID
2411     FROM ahl_resource_mappings WHERE
2412     ASO_RESOURCE_ID = c_aso_resource_id
2413     AND bom_org_id = c_org_id;
2414 
2415   l_mr_route_id       NUMBER := NULL;
2416   l_route_id          NUMBER := NULL;
2417   l_vdept_id          NUMBER := NULL;
2418   l_vtdept_id         NUMBER := NULL;
2419   l_dept_id           NUMBER;
2420   l_org_id            NUMBER;
2421   l_bom_resource_id   NUMBER;
2422   l_bom_org_id        NUMBER;
2423   l_rt_resource_rec    l_get_rt_resources_csr%ROWTYPE;
2424   l_oper_resource_rec  l_get_oper_resources_csr%ROWTYPE;
2425   l_qualified        BOOLEAN;
2426   l_time_period_details_tbl Time_Period_Details_Tbl_Type;
2427 BEGIN
2428 --  dbms_output.put_line('Entering Get_Task_Resources, p_task_id = ' || p_task_id);
2429 Ahl_Debug_Pub.debug('Entering Get_Task_Resources, p_task_id = ' || p_task_id);
2430 Ahl_Debug_Pub.debug('Get_Task_Resources, p_x_task_rsrc_tbl.count = ' || p_x_task_rsrc_tbl.count);
2431 Ahl_Debug_Pub.debug('Get_Task_Resources, p_x_task_rsrc_tbl.STIME = ' || p_x_task_rsrc_tbl.count);
2432 
2433   OPEN l_get_route_csr(p_task_id);
2434   FETCH l_get_route_csr INTO l_mr_route_id,l_route_id;
2435   IF l_get_route_csr%NOTFOUND OR l_route_id IS NULL THEN
2436     Fnd_Message.Set_Name('AHL','AHL_LTP_NO_ROUTE_FOR_TASK');
2437     Fnd_Message.Set_Token('TASK_ID', p_task_id);
2438     Fnd_Msg_Pub.ADD;
2439     CLOSE l_get_route_csr;
2440     RETURN;
2441   END IF;
2442   CLOSE l_get_route_csr;
2443 
2444   OPEN l_get_dept_csr(p_task_id);
2445   FETCH l_get_dept_csr INTO l_vtdept_id,l_vdept_id,l_org_id;
2446   IF l_get_dept_csr%NOTFOUND THEN
2447     Fnd_Message.Set_Name('AHL','AHL_LTP_NO_DEPT_FOR_TASK');
2448     Fnd_Message.Set_Token('TASK_ID', p_task_id);
2449     Fnd_Msg_Pub.ADD;
2450     CLOSE l_get_dept_csr;
2451     RETURN;
2452   END IF;
2453   l_dept_id := NVL(l_vtdept_id,l_vdept_id);
2454   CLOSE l_get_dept_csr;
2455 
2456 Ahl_Debug_Pub.debug('Get_Task_Resources, route id = ' || l_route_id);
2457 --
2458   OPEN l_get_rt_resources_csr(l_route_id);
2459   FETCH l_get_rt_resources_csr INTO l_rt_resource_rec;
2460   --
2461   IF (l_get_rt_resources_csr%FOUND) THEN
2462     -- Resources assigned at Route Level itself
2463     LOOP
2464       l_qualified := TRUE;
2465       -- Get Route Resource Details
2466       IF (l_qualified) THEN
2467 
2468     Ahl_Debug_Pub.debug('Get_Task_Resources, aso resource id = ' || l_rt_resource_rec.ASO_RESOURCE_ID);
2469       --  Get bom resource id for the corresponding aso resource
2470     OPEN l_get_bom_resources_csr(l_rt_resource_rec.ASO_RESOURCE_ID,l_org_id);
2471     FETCH l_get_bom_resources_csr INTO l_bom_resource_id;
2472         IF l_get_bom_resources_csr%NOTFOUND THEN
2473           Fnd_Message.Set_Name('AHL','AHL_LTP_NO_BOM_RESRC_ID');
2474           Fnd_Msg_Pub.ADD;
2475          CLOSE l_get_bom_resources_csr;
2476          RAISE  Fnd_Api.G_EXC_ERROR;
2477 --        RETURN;
2478         END IF;
2479   CLOSE l_get_bom_resources_csr;
2480     --
2481 Ahl_Debug_Pub.debug('ROUTE LEVEL, l_bom_resource_id = ' || l_bom_resource_id);
2482 Ahl_Debug_Pub.debug('ROUTE LEVEL, l_bom_org_id = ' || l_org_id);
2483     --
2484         Get_Resource_Details(
2485           p_required_capacity => p_required_capacity,
2486           p_aso_resource_id   => l_rt_resource_Rec.ASO_RESOURCE_ID,
2487         p_bom_resource_id   => l_bom_resource_id,
2488         p_bom_department_id => l_dept_id,
2489           p_start_date        => p_tstart_date,
2490           p_end_date          => p_tend_date,
2491           p_x_task_rsrc_tbl   => p_x_task_rsrc_tbl
2492         );
2493     Ahl_Debug_Pub.debug('Number of records for resources = ' ||p_x_task_rsrc_tbl.count);
2494       END IF;
2495       FETCH l_get_rt_resources_csr INTO l_rt_resource_rec;
2496       EXIT WHEN l_get_rt_resources_csr%NOTFOUND;
2497     END LOOP;
2498   ELSE
2499 
2500 Ahl_Debug_Pub.debug('Get_Task_Resources, operation level route id = ' || l_route_id);
2501 
2502     -- Get resources from operation level
2503     OPEN l_get_oper_resources_csr(l_route_id);
2504     LOOP
2505       FETCH l_get_oper_resources_csr INTO l_oper_resource_rec;
2506       EXIT WHEN l_get_oper_resources_csr%NOTFOUND;
2507       l_qualified := TRUE;
2508       -- Get Route Resource Details
2509       IF (l_qualified) THEN
2510 
2511 Ahl_Debug_Pub.debug('Get_Task_Resources, aso resource id oper = ' || l_oper_resource_rec.ASO_RESOURCE_ID);
2512 Ahl_Debug_Pub.debug('inside, l_org_id = ' || l_org_id);
2513 
2514       --  Get bom resource id for the corresponding aso resource
2515     OPEN l_get_bom_resources_csr(l_oper_resource_rec.ASO_RESOURCE_ID,l_org_id);
2516     FETCH l_get_bom_resources_csr INTO l_bom_resource_id;
2517 
2518     Ahl_Debug_Pub.debug('OPERATION LEVEL, bom resource id oper = ' || l_bom_resource_id);
2519 
2520         IF l_get_bom_resources_csr%NOTFOUND THEN
2521           Fnd_Message.Set_Name('AHL','AHL_LTP_NO_BOM_RESRC_ID');
2522           Fnd_Msg_Pub.ADD;
2523          CLOSE l_get_bom_resources_csr;
2524          RAISE  Fnd_Api.G_EXC_ERROR;
2525 --        RETURN;
2526         END IF;
2527         CLOSE l_get_bom_resources_csr;
2528   --
2529         Get_Resource_Details(
2530           p_required_capacity => p_required_capacity,
2531           p_aso_resource_id   => l_rt_resource_Rec.ASO_RESOURCE_ID,
2532           p_bom_resource_id   => l_bom_resource_id,
2533       p_bom_department_id => l_dept_id,
2534           p_start_date        => p_tstart_date,
2535           p_end_date          => p_tend_date,
2536           p_x_task_rsrc_tbl   => p_x_task_rsrc_tbl
2537         );
2538     Ahl_Debug_Pub.debug('Number of records for resources = ' ||p_x_task_rsrc_tbl.count);
2539       END IF;
2540     END LOOP;
2541     CLOSE l_get_oper_resources_csr;
2542   END IF;
2543   CLOSE l_get_rt_resources_csr;
2544 --  dbms_output.put_line('Exiting Get_Task_Resources');
2545 END Get_Task_Resources;
2546 
2547 ----------------------------------------
2548 -- Gets the details of a resource
2549 ----------------------------------------
2550 PROCEDURE Get_Resource_Details
2551 (   p_required_capacity IN      NUMBER,
2552     p_aso_resource_id   IN      NUMBER,
2553     p_bom_resource_id   IN      NUMBER,
2554     p_bom_department_id IN      NUMBER,
2555     p_start_date        IN      DATE,
2556     p_end_date          IN      DATE,
2557     p_x_task_rsrc_tbl   IN OUT  NOCOPY Plan_Rsrc_Tbl_Type
2558 ) IS
2559 
2560 -- yazhou 17Aug2005 starts
2561 -- bug fix #4559462
2562 
2563     CURSOR l_get_bom_rsrc_dtls_csr(p_bom_resource_id   IN NUMBER,
2564                                  p_bom_department_id IN NUMBER) IS
2565     SELECT a.RESOURCE_TYPE,a.RESOURCE_CODE,a.DESCRIPTION,
2566        B.CAPACITY_UNITS, M.meaning resource_type_mean
2567     FROM bom_resources A,
2568          bom_department_resources B,
2569          mfg_lookups M
2570   WHERE a.resource_id = B.resource_id
2571    AND B.resource_id = p_bom_resource_id
2572    AND B.department_id = p_bom_department_id
2573      AND A.resource_type = M.lookup_code
2574      AND M.lookup_type = 'BOM_RESOURCE_TYPE';
2575 
2576 -- yazhou 17Aug2005 ends
2577 
2578   -- Gets shift capacity
2579     CURSOR l_get_shift_dtls_csr(p_bom_resource_id   IN NUMBER,
2580                                 p_bom_department_id IN NUMBER) IS
2581     SELECT SHIFT_NUM,
2582        CAPACITY_UNITS SHIFT_CAPACITY
2583     FROM bom_resource_shifts
2584   WHERE resource_id = p_bom_resource_id
2585    AND  department_id = p_bom_department_id;
2586 
2587   --
2588   CURSOR l_get_dept_desc_cur (p_bom_department_id IN NUMBER) IS
2589    SELECT department_code,description
2590      FROM bom_departments
2591   WHERE department_id = p_bom_department_id;
2592   --
2593   l_shift_num          NUMBER;
2594   l_shift_capacity     NUMBER;
2595   l_department_code    VARCHAR2(30);
2596   --
2597   l_table_index      NUMBER := p_x_task_rsrc_tbl.COUNT + 1; -- 1 based index
2598 
2599 BEGIN
2600 Ahl_Debug_Pub.debug('enter get resource details p_bom_resource_id  = ' || p_bom_resource_id);
2601 Ahl_Debug_Pub.debug('enter get resource details p_bom_department_id = ' || p_bom_department_id);
2602 Ahl_Debug_Pub.debug('get resource details l_table_index: = ' || l_table_index);
2603 
2604   IF (p_bom_resource_id IS NOT NULL) THEN
2605     -- BOM Resource
2606     p_x_task_rsrc_tbl(l_table_index).ASO_BOM_TYPE := G_BOM_RESOURCE;
2607     p_x_task_rsrc_tbl(l_table_index).RESOURCE_ID := p_bom_resource_id;
2608     -- Get the type, name and description for this BOM Resource
2609     OPEN l_get_bom_rsrc_dtls_csr(p_bom_resource_id,p_bom_department_id);
2610 
2611     -- yazhou 17Aug2005 starts
2612     -- bug fix #4559462
2613     FETCH l_get_bom_rsrc_dtls_csr INTO p_x_task_rsrc_tbl(l_table_index).RESOURCE_TYPE,
2614                                        p_x_task_rsrc_tbl(l_table_index).RESOURCE_NAME,
2615                                        p_x_task_rsrc_tbl(l_table_index).RESOURCE_DESCRIPTION,
2616                                        p_x_task_rsrc_tbl(l_table_index).CAPACITY_UNITS,
2617                                        p_x_task_rsrc_tbl(l_table_index).RESOURCE_TYPE_MEANING;
2618     -- yazhou 17Aug2005 ends
2619 
2620     IF (l_get_bom_rsrc_dtls_csr%NOTFOUND) THEN
2621        Fnd_Message.Set_Name('AHL','AHL_LTP_BOM_RSRC_ID_INVALID');
2622        Fnd_Message.Set_Token('ASO_RSRC_ID', p_bom_resource_id);
2623        Fnd_Msg_Pub.ADD;
2624        CLOSE l_get_bom_rsrc_dtls_csr;
2625        RAISE  Fnd_Api.G_EXC_ERROR;
2626     END IF;
2627     -- Check for shift capacity
2628     OPEN  l_get_shift_dtls_csr(p_bom_resource_id,p_bom_department_id);
2629     FETCH l_get_shift_dtls_csr INTO l_shift_num,l_shift_capacity;
2630     CLOSE l_get_shift_dtls_csr;
2631     --
2632     IF l_shift_capacity IS NOT NULL THEN
2633        p_x_task_rsrc_tbl(l_table_index).CAPACITY_UNITS := (p_x_task_rsrc_tbl(l_table_index).CAPACITY_UNITS + l_shift_capacity);
2634     ELSE
2635        p_x_task_rsrc_tbl(l_table_index).CAPACITY_UNITS := p_x_task_rsrc_tbl(l_table_index).CAPACITY_UNITS ;
2636     END IF;
2637 
2638     Ahl_Debug_Pub.debug('get resource details p_capacity_units = ' || p_x_task_rsrc_tbl(l_table_index).CAPACITY_UNITS);
2639     p_x_task_rsrc_tbl(l_table_index).RESOURCE_ID := p_aso_resource_id;
2640    --
2641    OPEN l_get_dept_desc_cur(p_bom_department_id);
2642    FETCH l_get_dept_desc_cur INTO l_department_code,
2643                                   p_x_task_rsrc_tbl(l_table_index).dept_description;
2644      CLOSE l_get_dept_desc_cur;
2645    --
2646    --Assign department id
2647    p_x_task_rsrc_tbl(l_table_index).dept_id := p_bom_department_id;
2648    p_x_task_rsrc_tbl(l_table_index).period_start := p_start_date;
2649    p_x_task_rsrc_tbl(l_table_index).period_end  := p_end_date;
2650 
2651    --
2652 -- yazhou 17Aug2005 starts
2653 -- bug fix #4559462
2654 /*
2655    --
2656     -- //@@@@@ Resolve Hardcoding
2657     IF (p_x_task_rsrc_tbl(l_table_index).RESOURCE_TYPE = G_MACHINE_RESOURCE) THEN
2658       p_x_task_rsrc_tbl(l_table_index).RESOURCE_TYPE_MEANING := G_MACHINE_RES_NAME;
2659     ELSIF (p_x_task_rsrc_tbl(l_table_index).RESOURCE_TYPE = G_LABOR_RESOURCE) THEN
2660       p_x_task_rsrc_tbl(l_table_index).RESOURCE_TYPE_MEANING := G_LABOR_RES_NAME;
2661     ELSE
2662       -- Unknown Resource Type
2663       NULL;
2664     END IF;
2665 */
2666 
2667    CLOSE l_get_bom_rsrc_dtls_csr;
2668   END IF;
2669 END Get_Resource_Details;
2670 
2671 ----------------------------------------
2672 -- Gets the details of a resource
2673 ----------------------------------------
2674 PROCEDURE Get_Resource_Details
2675 (
2676     p_aso_resource_id   IN      NUMBER,
2677     p_x_task_rsrc_tbl   IN OUT  NOCOPY Plan_Rsrc_Tbl_Type
2678 ) IS
2679 
2680   CURSOR l_get_aso_rsrc_dtls_csr(p_rsrc_id IN NUMBER) IS
2681     SELECT NAME, DESCRIPTION FROM ahl_resources WHERE
2682     resource_id = p_rsrc_id;
2683 
2684 -- yazhou 17Aug2005 starts
2685 -- bug fix #4559462
2686   CURSOR l_get_bom_rsrc_dtls_csr(p_rsrc_id IN NUMBER) IS
2687     SELECT b.RESOURCE_TYPE, b.RESOURCE_CODE, b.DESCRIPTION, m.meaning
2688     FROM bom_resources b, mfg_lookups m
2689     WHERE b.resource_type = m.lookup_code
2690     AND   m.lookup_type = 'BOM_RESOURCE_TYPE'
2691     AND   resource_id = p_rsrc_id;
2692 -- yazhou 17Aug2005 ends
2693 
2694   l_table_index      NUMBER := p_x_task_rsrc_tbl.COUNT + 1; -- 1 based index
2695 
2696 BEGIN
2697   IF (p_aso_resource_id IS NOT NULL) THEN
2698     -- BOM Resource
2699     p_x_task_rsrc_tbl(l_table_index).ASO_BOM_TYPE := G_BOM_RESOURCE;
2700     p_x_task_rsrc_tbl(l_table_index).RESOURCE_ID := p_aso_resource_id;
2701     -- Get the type, name and description for this BOM Resource
2702     OPEN l_get_bom_rsrc_dtls_csr(p_aso_resource_id);
2703 
2704 -- yazhou 17Aug2005 starts
2705 -- bug fix #4559462
2706     FETCH l_get_bom_rsrc_dtls_csr INTO p_x_task_rsrc_tbl(l_table_index).RESOURCE_TYPE,
2707                                        p_x_task_rsrc_tbl(l_table_index).RESOURCE_NAME,
2708                                        p_x_task_rsrc_tbl(l_table_index).RESOURCE_DESCRIPTION,
2709                                        p_x_task_rsrc_tbl(l_table_index).RESOURCE_TYPE_MEANING;
2710 -- yazhou 17Aug2005 ends
2711 
2712     IF (l_get_bom_rsrc_dtls_csr%NOTFOUND) THEN
2713       Fnd_Message.Set_Name('AHL','AHL_LTP_BOM_RSRC_ID_INVALID');
2714       Fnd_Message.Set_Token('ASO_RSRC_ID', p_aso_resource_id);
2715       Fnd_Msg_Pub.ADD;
2716       CLOSE l_get_bom_rsrc_dtls_csr;
2717       RAISE  Fnd_Api.G_EXC_ERROR;
2718     END IF;
2719 
2720 -- yazhou 17Aug2005 starts
2721 -- bug fix #4559462
2722 /*
2723     -- //@@@@@ Resolve Hardcoding
2724     IF (p_x_task_rsrc_tbl(l_table_index).RESOURCE_TYPE = G_MACHINE_RESOURCE) THEN
2725       p_x_task_rsrc_tbl(l_table_index).RESOURCE_TYPE_MEANING := G_MACHINE_RES_NAME;
2726     ELSIF (p_x_task_rsrc_tbl(l_table_index).RESOURCE_TYPE = G_LABOR_RESOURCE) THEN
2727       p_x_task_rsrc_tbl(l_table_index).RESOURCE_TYPE_MEANING := G_LABOR_RES_NAME;
2728     ELSE
2729       -- Unknown Resource Type
2730       NULL;
2731     END IF;
2732 */
2733 
2734 -- yazhou 17Aug2005 ends
2735     CLOSE l_get_bom_rsrc_dtls_csr;
2736   END IF;
2737 END Get_Resource_Details;
2738 
2739 
2740 ----------------------------------------
2741 -- Populates a Time Period table with a task's operations' start time and end time
2742 -- (If the task's route has operations AND IF ressources are NOT associated AT route LEVEL)
2743 -- or with the task's start time and end time
2744 ----------------------------------------
2745 
2746 -- yazhou 24Aug2005 starts
2747 -- Resource Leveling Re-design
2748 
2749 -- Return all resource requirement for the given department and period
2750 -- Use requirements defined for the routes if there are any, otherwise use those for operations
2751 -- Added department_id and bom_resource_id in the output table
2752 -- And populate required quantity as well as start/end dates
2753 -- Also change to call AHL_VWP_TIMES_PVT.compute_date to calculate operation dates
2754 
2755 PROCEDURE Get_Operation_Details
2756 (
2757     p_task_dtls      IN      Visit_Task_Times_Rec_Type,
2758     p_visit_id       IN      NUMBER,
2759     p_department_id  IN      NUMBER,
2760     p_organization_id IN     NUMBER,
2761     p_start_time     IN      DATE,
2762     p_end_time       IN      DATE,
2763     p_x_tp_dtls_tbl  IN OUT  NOCOPY Time_Period_Details_Tbl_Type
2764 ) IS
2765 
2766   -- get only operations with latest revision
2767   CURSOR l_get_ops_count(p_route_id IN NUMBER) IS
2768     SELECT COUNT(ro.operation_id)
2769     FROM ahl_route_operations ro, AHL_OPERATIONS_VL OP
2770     WHERE OP.operation_id=RO.operation_id
2771       AND ro.ROUTE_ID = p_route_id
2772       AND OP.revision_number IN
2773            ( SELECT MAX(OP1.revision_number)
2774              FROM   AHL_OPERATIONS_B_KFV OP1
2775              WHERE  OP1.concatenated_segments=OP.concatenated_segments
2776              AND    OP1.revision_status_code='COMPLETE'
2777              AND    TRUNC(SYSDATE) BETWEEN TRUNC(OP1.start_date_active) AND
2778                                            TRUNC(NVL(OP1.end_date_active,SYSDATE+1))
2779            );
2780 
2781   CURSOR l_get_rt_rsrc_count(p_route_id IN NUMBER) IS
2782     SELECT COUNT(*) FROM ahl_rt_oper_resources
2783     WHERE OBJECT_ID = p_route_id AND
2784     ASSOCIATION_TYPE_CODE = G_RT_ASSOC_TYPE;
2785 
2786   -- get only operations with latest revision
2787   CURSOR l_get_rt_oper_csr(p_route_id IN NUMBER) IS
2788     SELECT RO.OPERATION_ID, RO.STEP
2789     FROM ahl_route_operations ro, AHL_OPERATIONS_VL OP
2790     WHERE OP.operation_id=RO.operation_id
2791       AND ro.ROUTE_ID = p_route_id
2792       AND OP.revision_number IN
2793            ( SELECT MAX(OP1.revision_number)
2794              FROM   AHL_OPERATIONS_B_KFV OP1
2795              WHERE  OP1.concatenated_segments=OP.concatenated_segments
2796              AND    OP1.revision_status_code='COMPLETE'
2797              AND    TRUNC(SYSDATE) BETWEEN TRUNC(OP1.start_date_active) AND
2798                                            TRUNC(NVL(OP1.end_date_active,SYSDATE+1))
2799            )
2800     ORDER BY RO.STEP;
2801 
2802   CURSOR l_get_route_id(p_mr_route_id IN NUMBER) IS
2803     SELECT ROUTE_ID FROM ahl_mr_routes_app_v
2804     WHERE MR_ROUTE_ID = p_mr_route_id;
2805 
2806  -- get resources associated to route
2807 CURSOR l_rt_resource_dtl_csr (l_route_id IN NUMBER,
2808                              l_dept_id  IN NUMBER,
2809                              l_org_id   IN NUMBER) IS
2810  SELECT a.aso_resource_id,
2811         a.quantity,
2812         b.bom_resource_id
2813  FROM ahl_rt_oper_resources a,
2814       ahl_resource_mappings b,
2815       bom_department_resources c
2816  WHERE a.aso_resource_id = b. aso_resource_id
2817    AND a.object_id = l_route_id
2818    AND b.bom_resource_id = c.resource_id
2819    AND b.bom_org_id = l_org_id
2820    AND c.department_id = l_dept_id
2821    /*B6459500 - LTP CHANGES FOR NONSCHEDULED RESOURCE REQUIREMENTS - sowsubra*/
2822    AND nvl(scheduled_type_id,1) <> 2
2823    AND ASSOCIATION_TYPE_CODE = G_RT_ASSOC_TYPE;
2824 
2825 -- get resources associated to operations
2826 CURSOR l_oper_resource_dtl_csr (l_operation_id IN NUMBER,
2827                                  l_dept_id      IN NUMBER,
2828                                  l_org_id       IN NUMBER) IS
2829  SELECT a.aso_resource_id,
2830         a.quantity,
2831         b.bom_resource_id
2832  FROM ahl_rt_oper_resources a,
2833       ahl_resource_mappings b,
2834       bom_department_resources c
2835  WHERE  a.object_id  = l_operation_id
2836   AND  a.ASSOCIATION_TYPE_CODE = 'OPERATION'
2837   AND  a.aso_resource_id = b. aso_resource_id
2838   AND  b.bom_resource_id = c.resource_id
2839   AND  c.department_id = l_dept_id
2840   /*B6459500 - LTP CHANGES FOR NONSCHEDULED RESOURCE REQUIREMENTS - sowsubra*/
2841   AND nvl(scheduled_type_id,1) <> 2
2842   AND  b.bom_org_id = l_org_id;
2843 
2844   l_dept_id          NUMBER := NULL;
2845   l_operation_id     NUMBER;
2846   l_operation_step   NUMBER;
2847   l_table_index      NUMBER := p_x_tp_dtls_tbl.COUNT + 1;  -- 1 based
2848   l_temp_count       NUMBER := 0;
2849   l_temp_duration    NUMBER;
2850 
2851   l_route_id         NUMBER;
2852   l_api_name        CONSTANT VARCHAR2(30) := 'Get_Operation_Details';
2853 
2854   l_rt_resource_dtl_rec    l_rt_resource_dtl_csr%rowtype;
2855   l_oper_resource_dtl_rec  l_oper_resource_dtl_csr%rowtype;
2856   l_oper_START_TIME   DATE;
2857   l_oper_END_TIME   DATE;
2858 
2859 BEGIN
2860 
2861   IF (l_log_statement >= l_log_current_level) THEN
2862         fnd_log.string
2863         (
2864           fnd_log.level_statement,
2865           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2866           'p_start_time:'||p_start_time
2867         );
2868         fnd_log.string
2869         (
2870           fnd_log.level_statement,
2871           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2872           'p_end_time:'||p_end_time
2873         );
2874         fnd_log.string
2875         (
2876           fnd_log.level_statement,
2877           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2878           'p_department_id:'||p_department_id
2879         );
2880         fnd_log.string
2881         (
2882           fnd_log.level_statement,
2883           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2884           'p_visit_id:'||p_visit_id
2885         );
2886         fnd_log.string
2887         (
2888           fnd_log.level_statement,
2889           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2890           'p_organization_id:'||p_organization_id
2891         );
2892         fnd_log.string
2893         (
2894           fnd_log.level_statement,
2895           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2896           'p_task_dtls.MR_ROUTE_ID:'||p_task_dtls.MR_ROUTE_ID
2897         );
2898         fnd_log.string
2899         (
2900           fnd_log.level_statement,
2901           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2902           'p_task_dtls.VISIT_TASK_ID:'||p_task_dtls.VISIT_TASK_ID
2903         );
2904   END IF;
2905 
2906   IF (p_task_dtls.MR_ROUTE_ID IS NULL) THEN
2907     -- no need to include this task
2908     RETURN;
2909   END IF;
2910 
2911   -- Find the route ID with MR_route_id associated to task
2912 
2913   OPEN l_get_route_id(p_task_dtls.MR_ROUTE_ID);
2914   FETCH l_get_route_id INTO l_route_id;
2915   CLOSE l_get_route_id;
2916 
2917   IF (l_log_statement >= l_log_current_level) THEN
2918         fnd_log.string
2919         (
2920           fnd_log.level_statement,
2921           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2922           'l_route_id:'||l_route_id
2923         );
2924   END IF;
2925 
2926   -- Check to see if route has any resource requirements defined
2927   OPEN l_get_rt_rsrc_count(l_route_id);
2928   FETCH l_get_rt_rsrc_count INTO l_temp_count;
2929   CLOSE l_get_rt_rsrc_count;
2930 
2931   IF (l_log_statement >= l_log_current_level) THEN
2932         fnd_log.string
2933         (
2934           fnd_log.level_statement,
2935           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2936           'number of resources associated to route:'||l_temp_count
2937         );
2938   END IF;
2939 
2940   IF l_temp_count >0  THEN
2941 
2942     -- Add resource requirements to output table only if task start/end date
2943     -- overlaps with the given period
2944 
2945     IF (Periods_Overlap (p_task_dtls.TASK_START_TIME,p_task_dtls.TASK_END_TIME,
2946                          p_start_time, p_end_time)) THEN
2947 
2948         -- There are resource requirements defined for the route
2949         OPEN l_rt_resource_dtl_csr(l_route_id,p_department_id,p_organization_id);
2950         LOOP
2951            FETCH l_rt_resource_dtl_csr INTO l_rt_resource_dtl_rec;
2952            EXIT WHEN l_rt_resource_dtl_csr%NOTFOUND;
2953 
2954              p_x_tp_dtls_tbl(l_table_index).VISIT_ID := p_visit_id;
2955              p_x_tp_dtls_tbl(l_table_index).TASK_ID := p_task_dtls.VISIT_TASK_ID;
2956              p_x_tp_dtls_tbl(l_table_index).ROUTE_ID := l_route_id;
2957              p_x_tp_dtls_tbl(l_table_index).MR_ROUTE_ID := p_task_dtls.MR_ROUTE_ID;
2958              p_x_tp_dtls_tbl(l_table_index).OPERATION_ID := NULL;
2959              p_x_tp_dtls_tbl(l_table_index).STEP := NULL;
2960              p_x_tp_dtls_tbl(l_table_index).START_HOUR := p_task_dtls.TASK_START_HOUR;
2961              p_x_tp_dtls_tbl(l_table_index).END_HOUR := p_task_dtls.TASK_END_HOUR;
2962              p_x_tp_dtls_tbl(l_table_index).MAX_DURATION := p_task_dtls.TASK_DURATION;
2963              p_x_tp_dtls_tbl(l_table_index).START_TIME := p_task_dtls.TASK_START_TIME;
2964              p_x_tp_dtls_tbl(l_table_index).END_TIME := p_task_dtls.TASK_END_TIME;
2965              p_x_tp_dtls_tbl(l_table_index).QUANTITY := l_rt_resource_dtl_rec.quantity;
2966              p_x_tp_dtls_tbl(l_table_index).ASO_RESOURCE_ID := l_rt_resource_dtl_rec.ASO_RESOURCE_ID;
2967              p_x_tp_dtls_tbl(l_table_index).BOM_RESOURCE_ID := l_rt_resource_dtl_rec.BOM_RESOURCE_ID;
2968              p_x_tp_dtls_tbl(l_table_index).DEPARTMENT_ID := p_department_id;
2969 
2970              IF (l_log_statement >= l_log_current_level) THEN
2971                  fnd_log.string
2972                  (
2973                     fnd_log.level_statement,
2974                     'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2975                     'p_x_tp_dtls_tbl('||l_table_index||').start_time: '|| TO_CHAR(p_x_tp_dtls_tbl(l_table_index).start_time, 'DD-MON-YYYY hh24:mi')
2976                  );
2977                  fnd_log.string
2978                  (
2979                     fnd_log.level_statement,
2980                     'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2981                     'p_x_tp_dtls_tbl('||l_table_index||').end_time: '|| TO_CHAR( p_x_tp_dtls_tbl(l_table_index).end_time, 'DD-MON-YYYY hh24:mi')
2982                  );
2983                  fnd_log.string
2984                  (
2985                      fnd_log.level_statement,
2986                     'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2987                     'p_x_tp_dtls_tbl('||l_table_index||').bom_resource_id: '|| p_x_tp_dtls_tbl(l_table_index).bom_resource_id
2988                  );
2989                  fnd_log.string
2990                  (
2991                      fnd_log.level_statement,
2992                      'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
2993                      'p_x_tp_dtls_tbl('||l_table_index||').quantity: '|| p_x_tp_dtls_tbl(l_table_index).quantity
2994                  );
2995 
2996              END IF;
2997 
2998              l_table_index := l_table_index + 1;
2999 
3000         END LOOP;-- loop through all resources
3001         CLOSE l_rt_resource_dtl_csr;
3002      END IF;  -- period overlap
3003 
3004   ELSE                     -- Check for operation resources
3005 
3006     -- Check if route has any operations
3007     OPEN l_get_ops_count(l_route_id);
3008     FETCH l_get_ops_count INTO l_temp_count;
3009     CLOSE l_get_ops_count;
3010 
3011     IF (l_log_statement >= l_log_current_level) THEN
3012         fnd_log.string
3013         (
3014           fnd_log.level_statement,
3015           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3016           'number of operations associated to route:'||l_temp_count
3017         );
3018     END IF;
3019 
3020     IF (l_temp_count = 0) THEN
3021       -- No operations
3022       RETURN;
3023     END IF;
3024 
3025 --    l_next_start_hour := p_task_dtls.TASK_START_HOUR;  -- Start hour of first operation w.r.t visit
3026     l_oper_END_TIME :=p_task_dtls.TASK_START_TIME;
3027 
3028     IF (l_log_statement >= l_log_current_level) THEN
3029         fnd_log.string
3030         (
3031           fnd_log.level_statement,
3032           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3033           'p_task_dtls.TASK_START_TIME:'||TO_CHAR(p_task_dtls.TASK_START_TIME, 'DD-MON-YYYY hh24:mi')
3034         );
3035     END IF;
3036 
3037     OPEN l_get_rt_oper_csr(l_route_id);
3038     LOOP
3039       FETCH l_get_rt_oper_csr INTO l_operation_id, l_operation_step;
3040       EXIT WHEN l_get_rt_oper_csr%NOTFOUND;
3041 
3042   --    Ahl_Debug_Pub.debug('l_operation_id:'||l_operation_id);
3043        l_temp_duration := 0;
3044 
3045        IF (l_log_statement >= l_log_current_level) THEN
3046           fnd_log.string
3047           (
3048             fnd_log.level_statement,
3049             'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3050             'l_operation_id:'||l_operation_id
3051           );
3052           fnd_log.string
3053           (
3054             fnd_log.level_statement,
3055             'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3056             'l_operation_step:'||l_operation_step
3057           );
3058        END IF;
3059 
3060        -- Get the duration of the operation
3061        Get_Oper_Max_Duration(l_operation_id, l_temp_duration);
3062 
3063        l_oper_START_TIME := l_oper_END_TIME;
3064        l_oper_END_TIME := AHL_VWP_TIMES_PVT.COMPUTE_DATE(l_oper_START_TIME,p_department_id,l_temp_duration);
3065 
3066        IF (l_log_statement >= l_log_current_level) THEN
3067           fnd_log.string
3068           (
3069             fnd_log.level_statement,
3070             'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3071             'operation duration:'||l_temp_duration
3072           );
3073           fnd_log.string
3074           (
3075             fnd_log.level_statement,
3076             'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3077             'l_oper_START_TIME:'||TO_CHAR(l_oper_START_TIME, 'DD-MON-YYYY hh24:mi')
3078           );
3079           fnd_log.string
3080           (
3081             fnd_log.level_statement,
3082             'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3083             'l_oper_END_TIME:'||TO_CHAR(l_oper_END_TIME, 'DD-MON-YYYY hh24:mi')
3084           );
3085        END IF;
3086 
3087        -- Add resource requirements to output table only if operation start/end date
3088        -- overlaps with the given period
3089 
3090        IF (Periods_Overlap(l_oper_START_TIME,l_oper_END_TIME,p_start_time, p_end_time)) THEN
3091 
3092          OPEN l_oper_resource_dtl_csr(l_operation_id,p_department_id,p_organization_id);
3093          LOOP
3094            FETCH l_oper_resource_dtl_csr INTO l_oper_resource_dtl_rec;
3095            EXIT WHEN l_oper_resource_dtl_csr%NOTFOUND;
3096 
3097                 p_x_tp_dtls_tbl(l_table_index).VISIT_ID := p_visit_id;
3098                 p_x_tp_dtls_tbl(l_table_index).TASK_ID := p_task_dtls.VISIT_TASK_ID;
3099                 p_x_tp_dtls_tbl(l_table_index).ROUTE_ID := l_route_id;
3100                 p_x_tp_dtls_tbl(l_table_index).MR_ROUTE_ID := p_task_dtls.MR_ROUTE_ID;
3101                 p_x_tp_dtls_tbl(l_table_index).OPERATION_ID := l_operation_id;
3102                 p_x_tp_dtls_tbl(l_table_index).STEP := l_operation_step;
3103 
3104                 p_x_tp_dtls_tbl(l_table_index).START_HOUR := to_number(to_char(l_oper_START_TIME,'HH24'));
3105                 p_x_tp_dtls_tbl(l_table_index).MAX_DURATION := l_temp_duration;
3106                 p_x_tp_dtls_tbl(l_table_index).END_HOUR := to_number(to_char(l_oper_END_TIME,'HH24'));
3107                 p_x_tp_dtls_tbl(l_table_index).START_TIME := l_oper_START_TIME;
3108                 p_x_tp_dtls_tbl(l_table_index).END_TIME := l_oper_END_TIME;
3109 
3110                 p_x_tp_dtls_tbl(l_table_index).QUANTITY := l_oper_resource_dtl_rec.quantity;
3111                 p_x_tp_dtls_tbl(l_table_index).ASO_RESOURCE_ID := l_oper_resource_dtl_rec.ASO_RESOURCE_ID;
3112                 p_x_tp_dtls_tbl(l_table_index).BOM_RESOURCE_ID := l_oper_resource_dtl_rec.BOM_RESOURCE_ID;
3113                 p_x_tp_dtls_tbl(l_table_index).DEPARTMENT_ID := p_department_id;
3114 
3115              IF (l_log_statement >= l_log_current_level) THEN
3116                  fnd_log.string
3117                  (
3118                      fnd_log.level_statement,
3119                     'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3120                     'p_x_tp_dtls_tbl('||l_table_index||').OPERATION_ID: '|| p_x_tp_dtls_tbl(l_table_index).OPERATION_ID
3121                  );
3122                  fnd_log.string
3123                  (
3124                     fnd_log.level_statement,
3125                     'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3126                     'p_x_tp_dtls_tbl('||l_table_index||').start_time: '|| TO_CHAR(p_x_tp_dtls_tbl(l_table_index).start_time, 'DD-MON-YYYY hh24:mi')
3127                  );
3128                  fnd_log.string
3129                  (
3130                     fnd_log.level_statement,
3131                     'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3132                     'p_x_tp_dtls_tbl('||l_table_index||').end_time: '|| TO_CHAR( p_x_tp_dtls_tbl(l_table_index).end_time, 'DD-MON-YYYY hh24:mi')
3133                  );
3134                  fnd_log.string
3135                  (
3136                      fnd_log.level_statement,
3137                     'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3138                     'p_x_tp_dtls_tbl('||l_table_index||').bom_resource_id: '|| p_x_tp_dtls_tbl(l_table_index).bom_resource_id
3139                  );
3140                  fnd_log.string
3141                  (
3142                      fnd_log.level_statement,
3143                      'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3144                      'p_x_tp_dtls_tbl('||l_table_index||').quantity: '|| p_x_tp_dtls_tbl(l_table_index).quantity
3145                  );
3146              END IF;
3147 
3148              l_table_index := l_table_index + 1;
3149 
3150          END LOOP; -- Loop through operation resources
3151          CLOSE l_oper_resource_dtl_csr;
3152 
3153        END IF; -- period overlap
3154 
3155       END LOOP; --loop through all operations
3156       CLOSE l_get_rt_oper_csr;
3157 
3158   END IF; -- l_temp_count >0 (route resource number >0)
3159 
3160 END Get_Operation_Details;
3161 -- yazhou 24Aug2005 ends
3162 
3163 -- yazhou 24Aug2005 starts
3164 -- Resource Leveling Re-design
3165 
3166 ----------------------------------------
3167 -- Filters out requirements that don't require the given resource for the given period
3168 ----------------------------------------
3169 PROCEDURE Filter_By_Resource
3170 (
3171     p_resource_id    IN      NUMBER,
3172   p_start_time     IN      DATE,
3173   p_end_time       IN      DATE,
3174     p_x_tp_dtls_tbl  IN OUT  NOCOPY Time_Period_Details_Tbl_Type
3175 ) IS
3176 
3177   l_temp_table Time_Period_Details_Tbl_Type;
3178   l_table_index NUMBER;
3179 
3180   l_api_name        CONSTANT VARCHAR2(30) := 'Filter_By_Resource';
3181 
3182 BEGIN
3183 
3184   IF (p_resource_id IS NULL) THEN
3185     -- Error
3186     FND_MESSAGE.Set_Name('AHL','AHL_LTP_RSRC_ID_NULL');
3187     FND_MSG_PUB.ADD;
3188     RAISE  FND_API.G_EXC_UNEXPECTED_ERROR;
3189   END IF;
3190 
3191    IF (l_log_statement >= l_log_current_level) THEN
3192       fnd_log.string
3193         (
3194           fnd_log.level_statement,
3195           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3196           'p_resource_id: '|| p_resource_id
3197         );
3198       fnd_log.string
3199         (
3200           fnd_log.level_statement,
3201           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3202           'p_start_time: '||  TO_CHAR( p_start_time, 'DD-MON-YYYY hh24:mi')
3203         );
3204       fnd_log.string
3205         (
3206           fnd_log.level_statement,
3207           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3208           'p_end_time: '|| TO_CHAR( p_end_time, 'DD-MON-YYYY hh24:mi')
3209         );
3210 
3211    END IF;
3212 
3213   IF (p_x_tp_dtls_tbl.COUNT > 0) THEN
3214 
3215       l_table_index := 0;
3216 
3217       FOR i in p_x_tp_dtls_tbl.FIRST .. p_x_tp_dtls_tbl.LAST LOOP
3218 
3219         -- keep the requirement only if it's for the given resource
3220         -- and falls in the given period
3221         IF p_x_tp_dtls_tbl(i).bom_resource_id = p_resource_id AND
3222           (Periods_Overlap (p_x_tp_dtls_tbl(i).START_TIME,p_x_tp_dtls_tbl(i).END_TIME,
3223              p_start_time, p_end_time)) THEN
3224 
3225             l_temp_table(l_table_index) := p_x_tp_dtls_tbl(i);
3226 
3227             l_table_index := l_table_index + 1;
3228 
3229         END IF; -- l_rsrc_exist_cur%FOUND
3230 
3231       END LOOP;
3232     END IF;
3233 
3234   -- Assign Local table to Output Parameter
3235   p_x_tp_dtls_tbl := l_temp_table;
3236 
3237 IF p_x_tp_dtls_tbl.COUNT >0 THEN
3238   FOR i IN p_x_tp_dtls_tbl.FIRST..p_x_tp_dtls_tbl.LAST
3239   LOOP
3240 
3241    IF (l_log_statement >= l_log_current_level) THEN
3242       fnd_log.string
3243         (
3244           fnd_log.level_statement,
3245           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3246           'p_x_tp_dtls_tbl('||i||').visit_id: '|| p_x_tp_dtls_tbl(i).visit_id
3247         );
3248       fnd_log.string
3249         (
3250           fnd_log.level_statement,
3251           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3252           'p_x_tp_dtls_tbl('||i||').route_id: '|| p_x_tp_dtls_tbl(i).route_id
3253         );
3254       fnd_log.string
3255         (
3256           fnd_log.level_statement,
3257           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3258           'p_x_tp_dtls_tbl('||i||').mr_route_id: '|| p_x_tp_dtls_tbl(i).mr_route_id
3259         );
3260       fnd_log.string
3261         (
3262           fnd_log.level_statement,
3263           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3264           'p_x_tp_dtls_tbl('||i||').operation_id: '|| p_x_tp_dtls_tbl(i).operation_id
3265         );
3266       fnd_log.string
3267         (
3268           fnd_log.level_statement,
3269           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3270           'p_x_tp_dtls_tbl('||i||').task_id: '|| p_x_tp_dtls_tbl(i).task_id
3271         );
3272       fnd_log.string
3273         (
3274           fnd_log.level_statement,
3275           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3276           'p_x_tp_dtls_tbl('||i||').start_time: '|| p_x_tp_dtls_tbl(i).start_time
3277         );
3278       fnd_log.string
3279         (
3280           fnd_log.level_statement,
3281           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3282           'p_x_tp_dtls_tbl('||i||').end_time: '|| p_x_tp_dtls_tbl(i).end_time
3283         );
3284 
3285       fnd_log.string
3286         (
3287           fnd_log.level_statement,
3288           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3289           'p_x_tp_dtls_tbl('||i||').quantity: '|| p_x_tp_dtls_tbl(i).quantity
3290         );
3291 
3292     END IF;
3293  END LOOP;
3294 END IF;
3295 
3296 
3297 END Filter_By_Resource;
3298 
3299 -- yazhou 24Aug2005 ends
3300 
3301 
3302 --
3303 /* Commented by rnahata since its not being used
3304 PROCEDURE get_qty_By_Resource
3305 (
3306     p_resource_id    IN      NUMBER,
3307     p_aso_bom_type   IN      VARCHAR2,
3308     p_x_tp_dtls_tbl  IN OUT  NOCOPY Time_Period_Details_Tbl_Type
3309 ) IS
3310   CURSOR l_aso_rsrc_csr(p_aso_rsrc_id IN NUMBER,
3311                          p_object_id   IN NUMBER,
3312                          p_object_type IN VARCHAR2) IS
3313     SELECT QUANTITY FROM ahl_rt_oper_resources WHERE
3314     ASO_RESOURCE_ID = p_aso_rsrc_id AND
3315     OBJECT_ID = p_object_id AND
3316     ASSOCIATION_TYPE_CODE = p_object_type;
3317 
3318 
3319   l_temp_table Time_Period_Details_Tbl_Type;
3320   l_table_index NUMBER := 1;
3321   l_quantity    NUMBER;
3322 
3323 BEGIN
3324   IF (p_resource_id IS NULL) THEN
3325     -- Error
3326     Fnd_Message.Set_Name('AHL','AHL_LTP_RSRC_ID_NULL');
3327     Fnd_Msg_Pub.ADD;
3328     RAISE  Fnd_Api.G_EXC_UNEXPECTED_ERROR;
3329   END IF;
3330 
3331   IF (p_aso_bom_type = G_ASO_RESOURCE) THEN
3332     -- ASO Resource
3333     IF (p_x_tp_dtls_tbl.COUNT > 0) THEN
3334       FOR i IN p_x_tp_dtls_tbl.FIRST .. p_x_tp_dtls_tbl.LAST LOOP
3335         l_quantity := 0;
3336         IF (p_x_tp_dtls_tbl(i).OPERATION_ID IS NULL) THEN
3337           -- Route
3338           OPEN l_aso_rsrc_csr(p_resource_id, p_x_tp_dtls_tbl(i).ROUTE_ID, G_RT_ASSOC_TYPE);
3339         ELSE
3340           -- Operation
3341           OPEN l_aso_rsrc_csr(p_resource_id, p_x_tp_dtls_tbl(i).OPERATION_ID, G_OPER_ASSOC_TYPE);
3342         END IF;
3343         FETCH l_aso_rsrc_csr INTO l_quantity;
3344         IF (l_aso_rsrc_csr%FOUND AND l_quantity > 0) THEN
3345           -- Resource used by this Route/Operation: Add to output table
3346           l_temp_table(l_table_index) := p_x_tp_dtls_tbl(i);
3347           l_temp_table(l_table_index).QUANTITY := l_quantity;
3348           l_table_index := l_table_index + 1;
3349         END IF;
3350         CLOSE l_aso_rsrc_csr;
3351       END LOOP;
3352     END IF;
3353   ELSE
3354     -- Error
3355     Fnd_Message.Set_Name('AHL','AHL_LTP_RSRC_TYPE_INVALID');
3356     Fnd_Message.Set_Token('RSRC_TYPE', p_aso_bom_type);
3357     Fnd_Msg_Pub.ADD;
3358     RAISE  Fnd_Api.G_EXC_UNEXPECTED_ERROR;
3359   END IF;
3360   -- Assign Local table to Output Parameter
3361   p_x_tp_dtls_tbl := l_temp_table;
3362 END Get_qty_By_Resource;
3363 */
3364 
3365 ----------------------------------------
3366 -- Creates Timeperiods from the start time and end time based on the UOM
3367 -- and populates the table
3368 -- //@@@@@ Formatting hardcoding to be removed
3369 ----------------------------------------
3370 PROCEDURE Create_Time_Periods
3371 (
3372     p_start_time     IN DATE,
3373     p_end_time       IN DATE,
3374     p_UOM_code       IN VARCHAR2,
3375     p_org_id         IN NUMBER,
3376     p_dept_id        IN NUMBER,
3377     x_per_rsrc_tbl OUT NOCOPY Period_Rsrc_Req_Tbl_Type
3378 ) IS
3379 
3380   CURSOR l_dept_shift_csr(p_department_id IN NUMBER) IS
3381     SELECT calendar_code, shift_num FROM ahl_department_shifts
3382     WHERE department_id = p_department_id;
3383 
3384   CURSOR l_shift_times_csr(p_calendar_code IN VARCHAR2, p_shift_num IN NUMBER) IS
3385     SELECT FROM_TIME, TO_TIME FROM bom_shift_times
3386     WHERE CALENDAR_CODE = p_calendar_code AND
3387     SHIFT_NUM = p_shift_num;
3388 
3389   CURSOR l_workday_pattern_csr(p_calendar_code IN VARCHAR2, p_shift_num IN NUMBER) IS
3390     SELECT DAYS_ON, DAYS_OFF FROM bom_workday_patterns
3391     WHERE CALENDAR_CODE = p_calendar_code AND
3392     SHIFT_NUM = p_shift_num;
3393 
3394   CURSOR l_calendar_csr(p_calendar_code IN VARCHAR2) IS
3395     SELECT CALENDAR_START_DATE, CALENDAR_END_DATE FROM bom_calendars
3396     WHERE CALENDAR_CODE = p_calendar_code;
3397 
3398   CURSOR l_dept_name_csr (c_org_id IN NUMBER,
3399                           c_dept_id IN NUMBER)
3400   IS
3401    SELECT  description FROM bom_departments
3402      WHERE organization_id = c_org_id
3403       AND department_id = c_dept_id;
3404 
3405   l_api_name        CONSTANT VARCHAR2(30) := 'Create_Time_Periods';
3406 
3407   l_temp_start  DATE;
3408   l_temp_end    DATE;
3409   l_temp_index  NUMBER := 1;
3410   l_temp_num    NUMBER;
3411   l_check_date  BOOLEAN := TRUE;
3412   l_working_day BOOLEAN;
3413   l_dept_name   VARCHAR2(80);
3414 
3415   L_CALENDAR_CODE  VARCHAR2(10);
3416   L_SHIFT_NUM   NUMBER;
3417   L_CAL_START   DATE;
3418   L_CAL_END     DATE;
3419   L_SHIFT_START NUMBER;
3420   L_SHIFT_END   NUMBER;
3421   L_DAYS_ON     NUMBER;
3422   L_DAYS_OFF    NUMBER;
3423 
3424 BEGIN
3425 
3426      IF (l_log_statement >= l_log_current_level) THEN
3427       fnd_log.string
3428         (
3429           fnd_log.level_statement,
3430           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3431           'p_start_time:'||TO_CHAR( p_start_time, 'DD-MON-YYYY hh24:mi')
3432         );
3433       fnd_log.string
3434         (
3435           fnd_log.level_statement,
3436           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3437           'p_end_time:'||TO_CHAR( p_end_time, 'DD-MON-YYYY hh24:mi')
3438         );
3439      END IF;
3440 
3441   -- First, Get all Calendar/Shift Values
3442   OPEN l_dept_name_csr(p_org_id,p_dept_id);
3443   FETCH l_dept_name_csr INTO l_dept_name;
3444   CLOSE l_dept_name_csr;
3445   --
3446   -- Get the Calendar code and Shift Num for the department
3447   OPEN l_dept_shift_csr(p_dept_id);
3448   FETCH l_dept_shift_csr INTO L_CALENDAR_CODE, L_SHIFT_NUM;
3449   IF (l_dept_shift_csr%NOTFOUND) THEN
3450     Fnd_Message.Set_Name('AHL','AHL_LTP_NO_SHIFT_FOR_DEPT');
3451     Fnd_Message.Set_Token('DEPT_ID', l_dept_name);
3452     Fnd_Msg_Pub.ADD;
3453     CLOSE l_dept_shift_csr;
3454     Ahl_Debug_Pub.debug('No shift/calendar code for department: ' || p_dept_id, 'LTP: Create_Time_Periods');
3455     RAISE  Fnd_Api.G_EXC_UNEXPECTED_ERROR;
3456   END IF;
3457   CLOSE l_dept_shift_csr;
3458 --  dbms_output.put_line('L_CALENDAR_CODE := ' || L_CALENDAR_CODE);
3459 --  dbms_output.put_line('L_SHIFT_NUM := ' || L_SHIFT_NUM);
3460 
3461   -- Get the calendar start date and the calendar end date
3462   OPEN l_calendar_csr(L_CALENDAR_CODE);
3463   FETCH l_calendar_csr INTO L_CAL_START, L_CAL_END;
3464   IF (l_calendar_csr%NOTFOUND) THEN
3465     Fnd_Message.Set_Name('AHL','AHL_LTP_CAL_CODE_INVALID');
3466     Fnd_Message.Set_Token('CAL_CODE', L_CALENDAR_CODE);
3467     Fnd_Msg_Pub.ADD;
3468     CLOSE l_calendar_csr;
3469     Ahl_Debug_Pub.debug('No BOM_CALENDARS entry for calendar code: ' || L_CALENDAR_CODE, 'LTP: Create_Time_Periods');
3470     RAISE  Fnd_Api.G_EXC_UNEXPECTED_ERROR;
3471   END IF;
3472   CLOSE l_calendar_csr;
3473   -- Truncate the date values
3474   L_CAL_START := TRUNC(L_CAL_START);
3475   L_CAL_END := TRUNC(L_CAL_END);
3476 --  dbms_output.put_line('L_CAL_START := ' || L_CAL_START);
3477 --  dbms_output.put_line('L_CAL_END := ' || L_CAL_END);
3478 
3479   -- Get Days On and Days Off
3480   OPEN l_workday_pattern_csr(L_CALENDAR_CODE, L_SHIFT_NUM);
3481   FETCH l_workday_pattern_csr INTO L_DAYS_ON, L_DAYS_OFF;
3482   IF (l_workday_pattern_csr%NOTFOUND) THEN
3483     Fnd_Message.Set_Name('AHL','AHL_LTP_NO_PTRN_FOR_DEPT');
3484     Fnd_Message.Set_Token('DEPT_ID', l_dept_name);
3485     Fnd_Msg_Pub.ADD;
3486     CLOSE l_workday_pattern_csr;
3487     Ahl_Debug_Pub.debug('No Work Day Pattern for department: ' || p_dept_id, 'LTP: Create_Time_Periods');
3488     RAISE  Fnd_Api.G_EXC_UNEXPECTED_ERROR;
3489   END IF;
3490   CLOSE l_workday_pattern_csr;
3491 
3492   -- Start processing based on UOM code
3493   IF (p_UOM_code = G_UOM_HOUR) THEN
3494 --    dbms_output.put_line('Hour UOM');
3495     -- Get the shift start and shift end times
3496     OPEN l_shift_times_csr(L_CALENDAR_CODE, L_SHIFT_NUM);
3497     FETCH l_shift_times_csr INTO L_SHIFT_START, L_SHIFT_END;
3498     IF (l_shift_times_csr%NOTFOUND) THEN
3499       Fnd_Message.Set_Name('AHL','AHL_LTP_NO_SHIFT_FOR_DEPT');
3500       Fnd_Message.Set_Token('DEPT_ID', l_dept_name);
3501       Fnd_Msg_Pub.ADD;
3502       CLOSE l_shift_times_csr;
3503       Ahl_Debug_Pub.debug('No shift start and end times for department: ' || p_dept_id, 'LTP: Create_Time_Periods');
3504       RAISE  Fnd_Api.G_EXC_UNEXPECTED_ERROR;
3505     END IF;
3506     CLOSE l_shift_times_csr;
3507 --    dbms_output.put_line('L_SHIFT_START := ' || L_SHIFT_START);
3508 --    dbms_output.put_line('L_SHIFT_END := ' || L_SHIFT_END);
3509 
3510    -- Break up into hours
3511     l_temp_start := p_start_time;
3512     l_temp_end := p_end_time;
3513     WHILE (l_temp_start < l_temp_end) LOOP
3514 --      dbms_output.put_line('l_temp_start = ' || l_temp_start);
3515       IF (l_check_date) THEN
3516         l_working_day := FALSE;
3517         l_temp_num := MOD((TRUNC(l_temp_start) - L_CAL_START), (L_DAYS_ON + L_DAYS_OFF)) + 1;
3518         IF (l_temp_num <= L_DAYS_ON) THEN
3519 --          dbms_output.put_line('Not Day Off');
3520           -- Not Day Off: Check if Holiday
3521           IF(Not_A_Holiday(l_temp_start, p_dept_id)) THEN
3522 --            dbms_output.put_line('Not a holiday');
3523             -- Working Day: Check if day is in calendar range
3524             IF(l_temp_start > L_CAL_END) THEN
3525               Fnd_Message.Set_Name('AHL','AHL_LTP_INSUFFICIENT_CAL_RANGE');
3526               Fnd_Msg_Pub.ADD;
3527               Ahl_Debug_Pub.debug('Computed date (' || l_temp_start|| ') is outside calendar range', 'LTP: Init_Time_Vars');
3528               RAISE  Fnd_Api.G_EXC_ERROR;
3529             END IF;
3530             l_working_day := TRUE;
3531           END IF;  -- Not a holiday
3532         END IF;  -- Not Day Off
3533       END IF;
3534       IF (l_working_day) THEN
3535         -- Check if hour is valid
3536         l_temp_num := (l_temp_start - TRUNC(l_temp_start)) * G_SECS_IN_DAY;
3537         IF ((L_SHIFT_START < L_SHIFT_END AND l_temp_num >= L_SHIFT_START AND l_temp_num < L_SHIFT_END) OR
3538             (L_SHIFT_START > L_SHIFT_END AND (l_temp_num >= L_SHIFT_START OR l_temp_num < L_SHIFT_END))) THEN
3539 --          dbms_output.put_line('In Shift');
3540           x_per_rsrc_tbl(l_temp_index).PERIOD_START := l_temp_start;
3541           -- //@@@@@ Remove Hardcoding
3542           x_per_rsrc_tbl(l_temp_index).PERIOD_STRING := TO_CHAR(l_temp_start, 'DD-MM-YYYY HH:MI:SS AM');
3543           x_per_rsrc_tbl(l_temp_index).PERIOD_END := l_temp_start + (1/24);  -- 1 Hour Long
3544           IF ((l_temp_num + G_SECS_IN_HOUR) = L_SHIFT_END) THEN
3545             l_check_date := TRUE;  -- Last Hour of Shift: Check if next day is a working Day
3546           ELSE
3547             l_check_date := FALSE;  -- Not Last Hour of Shift: No need to Check again if this is a working Day
3548           END IF;
3549           l_temp_index := l_temp_index + 1;
3550         END IF;  -- Hour Valid
3551         l_temp_start := l_temp_start + (1/24);  -- Next Hour
3552       ELSE
3553         -- Not a working day: Go the start of shift of next day
3554         l_temp_start := TRUNC(l_temp_start) + 1 + (L_SHIFT_START/G_SECS_IN_DAY);
3555       END IF;  -- Working Day
3556     END LOOP;
3557   ELSIF (p_UOM_code = G_UOM_DAY) THEN
3558 --    dbms_output.put_line('Day UOM');
3559     -- Break up into days
3560     l_temp_start := p_start_time;
3561     l_temp_end := p_end_time;
3562     WHILE (l_temp_start < l_temp_end) LOOP
3563 --      dbms_output.put_line('l_temp_start = ' || l_temp_start);
3564       l_temp_num := MOD((TRUNC(l_temp_start) - L_CAL_START), (L_DAYS_ON + L_DAYS_OFF)) + 1;
3565       IF (l_temp_num <= L_DAYS_ON) THEN
3566 --        dbms_output.put_line('Not Day Off');
3567         -- Not Day Off: Check if Holiday
3568         IF(Not_A_Holiday(l_temp_start, p_dept_id)) THEN
3569 --          dbms_output.put_line('Not a holiday');
3570           -- Working Day: Check if day is in calendar range
3571           IF(l_temp_start > L_CAL_END) THEN
3572             Fnd_Message.Set_Name('AHL','AHL_LTP_INSUFFICIENT_CAL_RANGE');
3573             Fnd_Msg_Pub.ADD;
3574             Ahl_Debug_Pub.debug('Computed date (' || l_temp_start || ') is outside calendar range', 'LTP: Init_Time_Vars');
3575             RAISE  Fnd_Api.G_EXC_ERROR;
3576           END IF;
3577           x_per_rsrc_tbl(l_temp_index).PERIOD_START := trunc(l_temp_start);
3578           -- //@@@@@ Remove Hardcoding
3579           x_per_rsrc_tbl(l_temp_index).PERIOD_STRING := TO_CHAR(l_temp_start, 'DD-MM-YYYY');
3580 
3581   Ahl_Debug_Pub.debug('before create time day:'||p_UOM_code||x_per_rsrc_tbl(l_temp_index).PERIOD_STRING);
3582 
3583 -- yazhou 24Aug2005 starts
3584 -- Resource Leveling Re-design
3585 
3586           x_per_rsrc_tbl(l_temp_index).PERIOD_END := l_temp_start + 1;  -- 1 Day long
3587 --          x_per_rsrc_tbl(l_temp_index).PERIOD_END := trunc(l_temp_start);  -- 1 Day long
3588 
3589 -- yazhou 24Aug2005 ends
3590 
3591           l_temp_index := l_temp_index + 1;
3592 
3593         END IF;  -- Not a holiday
3594       END IF;  -- Not Day Off
3595       l_temp_start := l_temp_start + 1;  -- Next Day
3596     END LOOP;
3597   ELSIF (p_UOM_code = G_UOM_WEEK) THEN
3598 --    dbms_output.put_line('Week UOM');
3599     -- Break up into weeks
3600     l_temp_start := p_start_time;
3601     l_temp_end := p_end_time;
3602     WHILE (l_temp_start < l_temp_end) LOOP
3603       x_per_rsrc_tbl(l_temp_index).PERIOD_START := l_temp_start;
3604       -- //@@@@@ Remove Hardcoding
3605       x_per_rsrc_tbl(l_temp_index).PERIOD_STRING := TO_CHAR(l_temp_start, 'DD-MM-YYYY');
3606 --      l_temp_start := l_temp_start + 7;  -- 7 Days
3607       l_temp_start := l_temp_start + 6;  -- 7 Days
3608       x_per_rsrc_tbl(l_temp_index).PERIOD_END := l_temp_start;
3609       l_temp_start :=  l_temp_start + 1;  -- 7 Days
3610       l_temp_index := l_temp_index + 1;
3611     END LOOP;
3612   ELSIF (p_UOM_code = G_UOM_MONTH) THEN
3613 --    dbms_output.put_line('Month UOM');
3614     -- Break up into months
3615     l_temp_start := p_start_time;
3616     l_temp_end := p_end_time;
3617     WHILE (l_temp_start < l_temp_end) LOOP
3618       x_per_rsrc_tbl(l_temp_index).PERIOD_START := l_temp_start;
3619       IF (l_temp_index = 1) THEN
3620         -- //@@@@@ Remove Hardcoding
3621         x_per_rsrc_tbl(l_temp_index).PERIOD_STRING := TO_CHAR(l_temp_start, 'DD-MM-YYYY');
3622 
3623 
3624       ELSE
3625         -- //@@@@@ Remove Hardcoding
3626         x_per_rsrc_tbl(l_temp_index).PERIOD_STRING := TO_CHAR(l_temp_start, 'fmMONTH YYYY');
3627       END IF;
3628       SELECT LAST_DAY(l_temp_start) INTO l_temp_start FROM DUAL;
3629       l_temp_start := l_temp_start + 1;  -- First day of next month
3630       x_per_rsrc_tbl(l_temp_index).PERIOD_END := l_temp_start;
3631       l_temp_index := l_temp_index + 1;
3632 
3633     END LOOP;
3634   ELSE
3635     -- Invalid UOM Code
3636     Fnd_Message.Set_Name('AHL','AHL_LTP_UOM_CODE_INVALID');
3637     Fnd_Message.Set_Token('UOM_CODE', p_UOM_code);
3638     Fnd_Msg_Pub.ADD;
3639     RAISE  Fnd_Api.G_EXC_ERROR;
3640   END IF;
3641   -- Ensure that the end time of the last period does not exceed user given end time
3642   IF (l_temp_index > 1 AND (x_per_rsrc_tbl(l_temp_index - 1).PERIOD_END > l_temp_end)) THEN
3643     x_per_rsrc_tbl(l_temp_index - 1).PERIOD_END := l_temp_end;
3644   END IF;
3645 
3646   --For debug
3647   IF x_per_rsrc_tbl.COUNT > 0 THEN
3648     FOR i in x_per_rsrc_tbl.FIRST..x_per_rsrc_tbl.LAST LOOP
3649 
3650      IF (l_log_statement >= l_log_current_level) THEN
3651       fnd_log.string
3652         (
3653           fnd_log.level_statement,
3654           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3655           'x_per_rsrc_tbl('||i||') START:'||TO_CHAR( x_per_rsrc_tbl(i).PERIOD_START, 'DD-MON-YYYY hh24:mi')
3656         );
3657       fnd_log.string
3658         (
3659           fnd_log.level_statement,
3660           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3661           'x_per_rsrc_tbl('||i||') END:'||TO_CHAR( x_per_rsrc_tbl(i).PERIOD_END, 'DD-MON-YYYY hh24:mi')
3662         );
3663       fnd_log.string
3664         (
3665           fnd_log.level_statement,
3666           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
3667           'x_per_rsrc_tbl('||i||') STRING:'||x_per_rsrc_tbl(i).PERIOD_STRING
3668         );
3669 
3670      END IF;
3671     END LOOP;
3672   END IF;
3673   --
3674 END Create_Time_Periods;
3675 
3676 ----------------------------------------
3677 -- Sorts the Quantity Change table based on event time
3678 ----------------------------------------
3679 PROCEDURE Sort_Qty_Change_Table
3680 (
3681     p_x_qty_change_tbl  IN OUT NOCOPY Qty_Change_Tbl_Type
3682 ) IS
3683 
3684   l_temp_qty_chng_rec  Qty_Change_Rec_Type;
3685 
3686 BEGIN
3687   IF (p_x_qty_change_tbl.COUNT < 2) THEN
3688     RETURN;
3689   END IF;
3690   FOR i IN p_x_qty_change_tbl.FIRST .. (p_x_qty_change_tbl.LAST - 1) LOOP
3691     FOR j IN (i + 1) .. p_x_qty_change_tbl.LAST LOOP
3692       IF (p_x_qty_change_tbl(i).EVENT_TIME > p_x_qty_change_tbl(j).EVENT_TIME) THEN
3693         -- Swap
3694         l_temp_qty_chng_rec := p_x_qty_change_tbl(i);
3695         p_x_qty_change_tbl(i) := p_x_qty_change_tbl(j);
3696         p_x_qty_change_tbl(j) := l_temp_qty_chng_rec;
3697       END IF;
3698     END LOOP;
3699   END LOOP;
3700 END Sort_Qty_Change_Table;
3701 
3702 ----------------------------------------
3703 -- Sorts the Time_Period_Details_Tbl By Visit/Task
3704 ----------------------------------------
3705 PROCEDURE Sort_By_Visit_Task
3706 (
3707     p_x_tp_tbl  IN OUT NOCOPY Time_Period_Details_Tbl_Type
3708 ) IS
3709 
3710   l_temp_tp_rec  Time_Period_Details_Rec_Type;
3711 
3712 BEGIN
3713   IF (p_x_tp_tbl.COUNT < 2) THEN
3714     RETURN;
3715   END IF;
3716   FOR i IN p_x_tp_tbl.FIRST .. (p_x_tp_tbl.LAST - 1) LOOP
3717     FOR j IN (i + 1) .. p_x_tp_tbl.LAST LOOP
3718       IF (Compare_Visit_Tasks(p_x_tp_tbl(i).VISIT_ID, p_x_tp_tbl(i).TASK_ID , p_x_tp_tbl(j).VISIT_ID, p_x_tp_tbl(j).TASK_ID) > 0) THEN
3719         -- Swap
3720         l_temp_tp_rec := p_x_tp_tbl(i);
3721         p_x_tp_tbl(i) := p_x_tp_tbl(j);
3722         p_x_tp_tbl(j) := l_temp_tp_rec;
3723       END IF;
3724     END LOOP;
3725   END LOOP;
3726 END Sort_By_Visit_Task;
3727 
3728 ----------------------------------------
3729 -- Aggregates Task Quantities and gets Task and Visit Names
3730 ----------------------------------------
3731 PROCEDURE Aggregate_Task_Quantities
3732 (   P_resource_id      IN  NUMBER,
3733     P_org_name         IN  VARCHAR2,
3734     P_dept_name        IN  VARCHAR2,
3735     p_tp_dtls_table    IN  Time_Period_Details_Tbl_Type,
3736     x_task_req_tbl     OUT NOCOPY Task_Requirement_Tbl_Type
3737 ) IS
3738 
3739   CURSOR l_get_visit_name_csr(p_visit_id IN NUMBER) IS
3740     SELECT VISIT_NAME, VISIT_NUMBER FROM ahl_visits_vl WHERE
3741     VISIT_ID = p_visit_id;
3742 
3743   CURSOR l_get_task_name_csr(p_task_id IN NUMBER) IS
3744     SELECT VISIT_TASK_NAME,TASK_TYPE_CODE FROM ahl_visit_tasks_vl WHERE
3745     VISIT_TASK_ID = p_task_id;
3746   --
3747   CURSOR l_get_dept_cur (c_dept_name IN VARCHAR2,
3748                          c_org_name  IN VARCHAR2)
3749    IS
3750    SELECT B.department_id,A.organization_id FROM
3751          HR_ALL_ORGANIZATION_UNITS A, BOM_DEPARTMENTS B
3752    WHERE A.organization_id = B.organization_id
3753      AND a.name            = c_org_name
3754      AND b.description     = c_dept_name;
3755   --
3756   l_visit_id   NUMBER;
3757   l_task_id    NUMBER;
3758   l_qty        NUMBER;
3759   l_required_qty  NUMBER;
3760   l_available_qty NUMBER;
3761   l_new_index  NUMBER := 1;
3762   l_task_name  VARCHAR2(80);
3763   l_prev_visit_id  NUMBER := -1;
3764   l_prev_visit_name VARCHAR2(80);
3765   l_prev_visit_number NUMBER;
3766   l_task_type_code VARCHAR2(30);
3767   l_dept_id     NUMBER;
3768   l_org_id      NUMBER;
3769 BEGIN
3770   IF (p_tp_dtls_table.COUNT = 0) THEN
3771     RETURN;
3772   END IF;
3773   --
3774 Ahl_Debug_Pub.debug('enter aggtegate O'||p_org_name);
3775 Ahl_Debug_Pub.debug('enter aggtegate D'||p_dept_name);
3776 
3777   --Get dept id
3778   OPEN l_get_dept_cur(p_dept_name,p_org_name);
3779   FETCH l_get_dept_cur INTO l_dept_id,l_org_id;
3780   CLOSE l_get_dept_cur;
3781   --
3782 Ahl_Debug_Pub.debug('AFTER CURSOR aggtegate'||l_org_id);
3783 Ahl_Debug_Pub.debug('AFTER CURSOR aggtegate'||l_dept_id);
3784 
3785   --
3786   l_visit_id := p_tp_dtls_table(p_tp_dtls_table.FIRST).VISIT_ID;
3787   l_task_id := p_tp_dtls_table(p_tp_dtls_table.FIRST).TASK_ID;
3788   l_qty := p_tp_dtls_table(p_tp_dtls_table.FIRST).QUANTITY;
3789   l_required_qty := p_tp_dtls_table(p_tp_dtls_table.FIRST).REQUIRED_UNITS;
3790   l_available_qty := Get_Available_Units(p_resource_id, l_dept_id);
3791 
3792 
3793   Ahl_Debug_Pub.debug('l_qty aggregate visit:'||l_qty);
3794   Ahl_Debug_Pub.debug('l_visit_id aggregate visit:'||l_visit_id);
3795   Ahl_Debug_Pub.debug('l_task_id aggregate visit:'||l_task_id);
3796 
3797   FOR i IN p_tp_dtls_table.FIRST .. p_tp_dtls_table.LAST LOOP
3798     IF (p_tp_dtls_table(i).VISIT_ID <> l_visit_id OR p_tp_dtls_table(i).TASK_ID <> l_task_id) THEN
3799       -- New Visit Task: Update x_task_req_tbl
3800       x_task_req_tbl(l_new_index).VISIT_ID := l_visit_id;
3801       x_task_req_tbl(l_new_index).TASK_ID := l_task_id;
3802       x_task_req_tbl(l_new_index).REQUIRED_UNITS := l_qty;
3803       x_task_req_tbl(l_new_index).AVAILABLE_UNITS := l_available_qty;
3804 
3805       IF (l_visit_id <> l_prev_visit_id) THEN
3806         -- Get Visit Name, Visit Number
3807         OPEN l_get_visit_name_csr(l_visit_id);
3808         FETCH l_get_visit_name_csr INTO l_prev_visit_name, l_prev_visit_number;
3809         IF (l_get_visit_name_csr%NOTFOUND) THEN
3810           Fnd_Message.Set_Name('AHL','AHL_LTP_VISIT_ID_INVALID');
3811           Fnd_Message.Set_Token('VISIT_ID', l_visit_id);
3812           Fnd_Msg_Pub.ADD;
3813           CLOSE l_get_visit_name_csr;
3814           RAISE  Fnd_Api.G_EXC_ERROR;
3815         END IF;
3816         CLOSE l_get_visit_name_csr;
3817         l_prev_visit_id := l_visit_id;
3818       END IF;
3819       x_task_req_tbl(l_new_index).VISIT_NAME := l_prev_visit_name;
3820       x_task_req_tbl(l_new_index).VISIT_NUMBER := l_prev_visit_number;
3821       x_task_req_tbl(l_new_index).REQUIRED_UNITS := l_qty;
3822       x_task_req_tbl(l_new_index).AVAILABLE_UNITS := l_available_qty;
3823       x_task_req_tbl(l_new_index).DEPT_NAME := P_dept_name;
3824 
3825       -- Get Task Name
3826       OPEN l_get_task_name_csr(l_task_id);
3827       FETCH l_get_task_name_csr INTO l_task_name,l_task_type_code;
3828       IF (l_get_task_name_csr%NOTFOUND) THEN
3829         Fnd_Message.Set_Name('AHL','AHL_LTP_TASK_ID_INVALID');
3830         Fnd_Message.Set_Token('TASK_ID', l_task_id);
3831         Fnd_Msg_Pub.ADD;
3832         CLOSE l_get_task_name_csr;
3833         RAISE  Fnd_Api.G_EXC_ERROR;
3834       END IF;
3835       CLOSE l_get_task_name_csr;
3836       x_task_req_tbl(l_new_index).VISIT_TASK_NAME := l_task_name;
3837       x_task_req_tbl(l_new_index).TASK_TYPE_CODE := l_task_type_code;
3838       x_task_req_tbl(l_new_index).REQUIRED_UNITS := l_qty;
3839       x_task_req_tbl(l_new_index).AVAILABLE_UNITS := l_available_qty;
3840       x_task_req_tbl(l_new_index).DEPT_NAME := P_dept_name;
3841 
3842       l_new_index := l_new_index + 1;
3843       -- Next, update l_visit_id, l_task_id and l_qty
3844       l_visit_id := p_tp_dtls_table(i).VISIT_ID;
3845       l_task_id := p_tp_dtls_table(i).TASK_ID;
3846       l_qty := p_tp_dtls_table(i).QUANTITY;
3847       l_required_qty := p_tp_dtls_table(i).REQUIRED_UNITS;
3848 --      l_available_qty := p_tp_dtls_table(i).AVAILABLE_UNITS;
3849     ELSE
3850       -- Same Visit/Task: Update l_qty if required
3851       IF (p_tp_dtls_table(i).QUANTITY > l_qty) THEN
3852         l_qty := p_tp_dtls_table(i).QUANTITY;
3853       END IF;
3854     END IF;
3855   END LOOP;
3856 
3857   -- Add for last visit/task
3858   x_task_req_tbl(l_new_index).VISIT_ID := l_visit_id;
3859   x_task_req_tbl(l_new_index).TASK_ID := l_task_id;
3860   x_task_req_tbl(l_new_index).REQUIRED_UNITS := l_qty;
3861   x_task_req_tbl(l_new_index).TASK_TYPE_CODE := l_task_type_code;
3862   x_task_req_tbl(l_new_index).AVAILABLE_UNITS := l_available_qty;
3863   x_task_req_tbl(l_new_index).DEPT_NAME := P_dept_name;
3864 
3865   IF (l_visit_id <> l_prev_visit_id) THEN
3866     -- Get Visit Name
3867     OPEN l_get_visit_name_csr(l_visit_id);
3868     FETCH l_get_visit_name_csr INTO l_prev_visit_name, l_prev_visit_number;
3869     IF (l_get_visit_name_csr%NOTFOUND) THEN
3870       Fnd_Message.Set_Name('AHL','AHL_LTP_VISIT_ID_INVALID');
3871       Fnd_Message.Set_Token('VISIT_ID', l_visit_id);
3872       Fnd_Msg_Pub.ADD;
3873       CLOSE l_get_visit_name_csr;
3874       RAISE  Fnd_Api.G_EXC_ERROR;
3875     END IF;
3876     CLOSE l_get_visit_name_csr;
3877   END IF;
3878   x_task_req_tbl(l_new_index).VISIT_NAME := l_prev_visit_name;
3879   x_task_req_tbl(l_new_index).VISIT_NUMBER := l_prev_visit_number;
3880   -- Get Task Name
3881   OPEN l_get_task_name_csr(l_task_id);
3882   FETCH l_get_task_name_csr INTO l_task_name,l_task_type_code;
3883   IF (l_get_task_name_csr%NOTFOUND) THEN
3884     Fnd_Message.Set_Name('AHL','AHL_LTP_TASK_ID_INVALID');
3885     Fnd_Message.Set_Token('TASK_ID', l_task_id);
3886     Fnd_Msg_Pub.ADD;
3887     CLOSE l_get_task_name_csr;
3888     RAISE  Fnd_Api.G_EXC_ERROR;
3889   END IF;
3890   CLOSE l_get_task_name_csr;
3891   x_task_req_tbl(l_new_index).VISIT_TASK_NAME := l_task_name;
3892   x_task_req_tbl(l_new_index).TASK_TYPE_CODE := l_task_type_code;
3893   x_task_req_tbl(l_new_index).DEPT_NAME := P_dept_name;
3894   x_task_req_tbl(l_new_index).REQUIRED_UNITS := l_qty;
3895   x_task_req_tbl(l_new_index).AVAILABLE_UNITS := l_available_qty;
3896   x_task_req_tbl(l_new_index).DEPT_NAME := P_dept_name;
3897   -- For debugging
3898   IF x_task_req_tbl.COUNT > 0 THEN
3899     FOR i in x_task_req_tbl.FIRST..x_task_req_tbl.LAST
3900     LOOP
3901       --
3902         Ahl_Debug_Pub.debug('END Task quantites VISIT TASK:'||x_task_req_tbl(i).visit_task_name);
3903         Ahl_Debug_Pub.debug('END Task quantites REQUNITS:'||x_task_req_tbl(i).required_units);
3904         Ahl_Debug_Pub.debug('END Task quantites AUNITS:'||x_task_req_tbl(i).available_units);
3905     --
3906     END LOOP;
3907   END IF;
3908   --
3909 END Aggregate_Task_Quantities;
3910 ----------------------------------------
3911 -- Gets the duration of a route from the timespan column
3912 -- of ahl_routes_b table
3913 ----------------------------------------
3914 PROCEDURE Get_Route_Duration
3915 (
3916     p_route_id  IN  NUMBER,
3917     x_duration  OUT NOCOPY NUMBER
3918 ) IS
3919 
3920    CURSOR l_route_csr (p_route_id IN NUMBER) IS
3921     SELECT route_id FROM ahl_mr_routes_app_v
3922     WHERE mr_route_id = p_route_id;
3923 
3924   CURSOR l_route_time_span_csr (p_route_id IN NUMBER) IS
3925     SELECT NVL(time_span, 0) FROM ahl_routes_b
3926     WHERE route_id = p_route_id;
3927   x_route_id NUMBER;
3928 BEGIN
3929 
3930   OPEN l_route_csr(p_route_id);
3931   FETCH l_route_csr INTO x_route_id;
3932   IF (l_route_csr%FOUND) THEN
3933 
3934       OPEN l_route_time_span_csr(x_route_id);
3935       FETCH l_route_time_span_csr INTO x_duration;
3936       IF (l_route_time_span_csr%NOTFOUND) THEN
3937             Fnd_Message.Set_Name('AHL', 'AHL_LTP_ROUTE_ID_INVALID');
3938             Fnd_Message.Set_Token('ROUTE_ID', p_route_id);
3939             Fnd_Msg_Pub.ADD;
3940             CLOSE l_route_time_span_csr;
3941             Ahl_Debug_Pub.debug('Invalid route Id: ' || x_duration, 'LTP: Get_Route_Duration');
3942             RAISE  Fnd_Api.G_EXC_UNEXPECTED_ERROR;
3943       END IF;
3944       CLOSE l_route_time_span_csr;
3945 
3946  CLOSE l_route_csr;
3947  END IF;
3948 
3949 END Get_Route_Duration;
3950 
3951 ----------------------------------------
3952 -- Gets the duration of a route based on the resources either directly or through
3953 -- the operations constituting the route
3954 ----------------------------------------
3955 PROCEDURE Get_Rt_Ops_Duration
3956 (
3957     p_route_id  IN  NUMBER,
3958     x_duration  OUT NOCOPY NUMBER
3959 ) IS
3960 
3961   CURSOR l_route_operations_csr(p_route_id IN NUMBER) IS
3962     SELECT OPERATION_ID FROM ahl_route_operations
3963     WHERE route_id = p_route_id;
3964 
3965   l_operation_id   NUMBER;
3966   l_temp_duration  NUMBER := 0;
3967 
3968 BEGIN
3969   x_duration := 0;
3970   Get_Rt_Max_Duration(p_route_id, l_temp_duration);
3971   IF (l_temp_duration <> 0) THEN
3972     -- Defined at Route Level itself. Not necessary to go to operations
3973     x_duration := l_temp_duration;
3974     RETURN;
3975   ELSE
3976     -- Not defined at route level. Go to operation level
3977     OPEN l_route_operations_csr(p_route_id);
3978     LOOP
3979       FETCH l_route_operations_csr INTO l_operation_id;
3980       EXIT WHEN l_route_operations_csr%NOTFOUND;
3981       Get_Oper_Max_Duration(l_operation_id, l_temp_duration);
3982       x_duration := x_duration + l_temp_duration;
3983     END LOOP;
3984   END IF;
3985   CLOSE l_route_operations_csr;
3986 END Get_Rt_Ops_Duration;
3987 
3988 ----------------------------------------
3989 -- Gets the time take for a given operation: Gets the maximum of all machines
3990 -- and labor required by this operation
3991 ----------------------------------------
3992 PROCEDURE Get_Oper_Max_Duration
3993 (
3994     p_operation_id  IN  NUMBER,
3995     x_duration      OUT NOCOPY NUMBER
3996 ) IS
3997 
3998   CURSOR l_oper_rsrc_time_csr(p_operation_id IN NUMBER) IS
3999     SELECT NVL(MAX(duration), 0) FROM ahl_rt_oper_resources
4000     WHERE OBJECT_ID = p_operation_id AND
4001     ASSOCIATION_TYPE_CODE = G_OPER_ASSOC_TYPE;
4002 
4003   l_rsrc_max   NUMBER := 0;
4004 
4005 BEGIN
4006   x_duration := 0;
4007   OPEN l_oper_rsrc_time_csr(p_operation_id);
4008   FETCH l_oper_rsrc_time_csr INTO l_rsrc_max;
4009   CLOSE l_oper_rsrc_time_csr;
4010 
4011   x_duration := l_rsrc_max;
4012 
4013 END Get_Oper_Max_Duration;
4014 
4015 ----------------------------------------
4016 -- Gets the time take for a given Route that has no operations: Gets the maximum
4017 -- of all machines and labor required by this Route
4018 ----------------------------------------
4019 PROCEDURE Get_Rt_Max_Duration
4020 (
4021     p_route_id  IN  NUMBER,
4022     x_duration  OUT NOCOPY NUMBER
4023 ) IS
4024 
4025   CURSOR l_rt_rsrc_time_csr(p_route_id IN NUMBER) IS
4026     SELECT NVL(MAX(duration), 0) FROM ahl_rt_oper_resources
4027     WHERE OBJECT_ID = p_route_id AND
4028     ASSOCIATION_TYPE_CODE = G_RT_ASSOC_TYPE;
4029 
4030   l_rsrc_max   NUMBER := 0;
4031 
4032 BEGIN
4033   x_duration := 0;
4034   OPEN l_rt_rsrc_time_csr(p_route_id);
4035   FETCH l_rt_rsrc_time_csr INTO l_rsrc_max;
4036   CLOSE l_rt_rsrc_time_csr;
4037 
4038   x_duration := l_rsrc_max;
4039 
4040 END Get_Rt_Max_Duration;
4041 
4042 ----------------------------------------
4043 -- Calculate and Initialize the global variables used for
4044 -- calculating task dates
4045 ----------------------------------------
4046 PROCEDURE Init_Time_Vars
4047 (
4048   p_visit_start_date IN  DATE,
4049   p_department_id    IN  NUMBER
4050 ) IS
4051 
4052   CURSOR l_dept_shift_csr(p_department_id IN NUMBER) IS
4053     SELECT calendar_code, shift_num FROM ahl_department_shifts
4054     WHERE department_id = p_department_id;
4055 
4056   CURSOR l_shift_times_csr(p_calendar_code IN VARCHAR2, p_shift_num IN NUMBER) IS
4057     SELECT FROM_TIME, TO_TIME FROM bom_shift_times
4058     WHERE CALENDAR_CODE = p_calendar_code AND
4059     SHIFT_NUM = p_shift_num;
4060 
4061   CURSOR l_workday_pattern_csr(p_calendar_code IN VARCHAR2, p_shift_num IN NUMBER) IS
4062     SELECT DAYS_ON, DAYS_OFF FROM bom_workday_patterns
4063     WHERE CALENDAR_CODE = p_calendar_code AND
4064     SHIFT_NUM = p_shift_num;
4065 
4066   CURSOR l_calendar_csr(p_calendar_code IN VARCHAR2) IS
4067     SELECT CALENDAR_START_DATE, CALENDAR_END_DATE FROM bom_calendars
4068     WHERE CALENDAR_CODE = p_calendar_code;
4069 
4070   CURSOR l_exceptions_csr(p_calendar_code IN VARCHAR2) IS
4071     SELECT EXCEPTION_DATE FROM bom_calendar_exceptions
4072     WHERE CALENDAR_CODE = p_calendar_code AND
4073     EXCEPTION_TYPE = G_HOLIDAY_TYPE
4074     ORDER BY EXCEPTION_DATE;
4075    --
4076    CURSOR l_dept_name_csr(c_dept_id IN NUMBER)
4077     IS
4078     SELECT description FROM bom_departments
4079     WHERE department_id = c_dept_id;
4080 
4081   l_visit_start_date DATE := TRUNC(p_visit_start_date);
4082   l_temp_date DATE;
4083   l_temp_index NUMBER := 1;
4084   l_curr_wday_index NUMBER;
4085   l_dept_name  VARCHAR2(240);
4086 BEGIN
4087   -- Clean-up any existing records
4088   G_WORKING_DATES_TBL.DELETE;
4089   --Get department name
4090   OPEN l_dept_name_csr(p_department_id);
4091   FETCH l_dept_name_csr INTO l_dept_name;
4092   CLOSE l_dept_name_csr;
4093   --
4094   -- Get the Calendar code and Shift Num for the department
4095   OPEN l_dept_shift_csr(p_department_id);
4096   FETCH l_dept_shift_csr INTO G_CALENDAR_CODE, G_SHIFT_NUM;
4097   IF (l_dept_shift_csr%NOTFOUND) THEN
4098     Fnd_Message.Set_Name('AHL','AHL_LTP_NO_SHIFT_FOR_DEPT');
4099     Fnd_Message.Set_Token('DEPT_ID', l_dept_name);
4100     Fnd_Msg_Pub.ADD;
4101     CLOSE l_dept_shift_csr;
4102     Ahl_Debug_Pub.debug('No shift/calendar code for department: ' || p_department_id, 'LTP: Init_Time_Vars');
4103     RAISE  Fnd_Api.G_EXC_UNEXPECTED_ERROR;
4104   END IF;
4105   CLOSE l_dept_shift_csr;
4106 --  dbms_output.put_line('G_CALENDAR_CODE := ' || G_CALENDAR_CODE);
4107 --  dbms_output.put_line('G_SHIFT_NUM := ' || G_SHIFT_NUM);
4108 
4109   -- Get the calendar start date and the calendar end date
4110   OPEN l_calendar_csr(G_CALENDAR_CODE);
4111   FETCH l_calendar_csr INTO G_CAL_START, G_CAL_END;
4112   IF (l_calendar_csr%NOTFOUND) THEN
4113     Fnd_Message.Set_Name('AHL','AHL_LTP_CAL_CODE_INVALID');
4114     Fnd_Message.Set_Token('CAL_CODE', G_CALENDAR_CODE);
4115     Fnd_Msg_Pub.ADD;
4116     CLOSE l_calendar_csr;
4117     Ahl_Debug_Pub.debug('No BOM_CALENDARS entry for calendar code: ' || G_CALENDAR_CODE, 'LTP: Init_Time_Vars');
4118     RAISE  Fnd_Api.G_EXC_UNEXPECTED_ERROR;
4119   END IF;
4120   CLOSE l_calendar_csr;
4121   -- Truncate the date values
4122   G_CAL_START := TRUNC(G_CAL_START);
4123   G_CAL_END := TRUNC(G_CAL_END);
4124 --  dbms_output.put_line('G_CAL_START := ' || G_CAL_START);
4125 --  dbms_output.put_line('G_CAL_END := ' || G_CAL_END);
4126 
4127   -- Get the shift start and shift end times
4128   OPEN l_shift_times_csr(G_CALENDAR_CODE, G_SHIFT_NUM);
4129   FETCH l_shift_times_csr INTO G_SHIFT_START, G_SHIFT_END;
4130   IF (l_shift_times_csr%NOTFOUND) THEN
4131     Fnd_Message.Set_Name('AHL','AHL_LTP_NO_SHIFT_FOR_DEPT');
4132     Fnd_Message.Set_Token('DEPT_ID', l_dept_name);
4133     Fnd_Msg_Pub.ADD;
4134     CLOSE l_shift_times_csr;
4135     Ahl_Debug_Pub.debug('No shift start and end times for department: ' || p_department_id, 'LTP: Init_Time_Vars');
4136     RAISE  Fnd_Api.G_EXC_UNEXPECTED_ERROR;
4137   END IF;
4138   CLOSE l_shift_times_csr;
4139 --  dbms_output.put_line('G_SHIFT_START := ' || G_SHIFT_START);
4140 --  dbms_output.put_line('G_SHIFT_END := ' || G_SHIFT_END);
4141   IF(G_SHIFT_END < G_SHIFT_START) THEN
4142      G_SHIFT_DURATION_HRS := (G_SHIFT_END + G_SECS_IN_DAY - G_SHIFT_START)/G_SECS_IN_HOUR;
4143   ELSE
4144      G_SHIFT_DURATION_HRS := (G_SHIFT_END - G_SHIFT_START)/G_SECS_IN_HOUR;
4145   END IF;
4146 --  dbms_output.put_line('G_SHIFT_DURATION_HRS := ' || G_SHIFT_DURATION_HRS);
4147 
4148   -- Get Days On and Days Off
4149   OPEN l_workday_pattern_csr(G_CALENDAR_CODE, G_SHIFT_NUM);
4150   FETCH l_workday_pattern_csr INTO G_DAYS_ON, G_DAYS_OFF;
4151   IF (l_workday_pattern_csr%NOTFOUND) THEN
4152     Fnd_Message.Set_Name('AHL','AHL_LTP_NO_PTRN_FOR_DEPT');
4153     Fnd_Message.Set_Token('DEPT_ID', l_dept_name);
4154     Fnd_Msg_Pub.ADD;
4155     CLOSE l_workday_pattern_csr;
4156     Ahl_Debug_Pub.debug('No Work Day Pattern for department: ' || p_department_id, 'LTP: Init_Time_Vars');
4157     RAISE  Fnd_Api.G_EXC_UNEXPECTED_ERROR;
4158   END IF;
4159   CLOSE l_workday_pattern_csr;
4160 
4161   -- Get the Exception (Holidays) days
4162   OPEN l_exceptions_csr(G_CALENDAR_CODE);
4163   l_temp_index := 1;
4164   LOOP
4165     FETCH l_exceptions_csr INTO l_temp_date;
4166     EXIT WHEN l_exceptions_csr%NOTFOUND;
4167     G_EXCEPTION_DATES_TBL(l_temp_index) := TRUNC(l_temp_date);
4168     l_temp_index := l_temp_index + 1;
4169   END LOOP;
4170   CLOSE l_exceptions_csr;
4171 
4172   IF (p_visit_start_date IS NULL) THEN
4173     Fnd_Message.Set_Name('AHL','AHL_LTP_VISIT_ST_DATE_NULL');
4174     Fnd_Msg_Pub.ADD;
4175     Ahl_Debug_Pub.debug('Visit start date is null', 'LTP: Init_Time_Vars');
4176     RAISE  Fnd_Api.G_EXC_ERROR;
4177   ELSIF (p_visit_start_date < G_CAL_START OR p_visit_start_date > G_CAL_END) THEN
4178     Fnd_Message.Set_Name('AHL','AHL_LTP_VISIT_ST_DATE_INVALID');
4179     Fnd_Message.Set_Token('VISIT_ST_DATE', p_visit_start_date);
4180     Fnd_Msg_Pub.ADD;
4181     Ahl_Debug_Pub.debug('Visit start date (' || p_visit_start_date || ') is outside calendar range', 'LTP: Init_Time_Vars');
4182     RAISE  Fnd_Api.G_EXC_ERROR;
4183   END IF;
4184 
4185  --Code fixed by shbhanda on 21st Oct'02
4186   -- Ensure that the visit start date falls on a working day
4187   l_curr_wday_index := MOD((l_visit_start_date - G_CAL_START), (G_DAYS_ON + G_DAYS_OFF)) + 1;
4188   WHILE (l_curr_wday_index > G_DAYS_ON) LOOP
4189     -- Day Off
4190     Ahl_Debug_Pub.debug('Visit Start Date = ' ||l_visit_start_date );
4191     l_visit_start_date := l_visit_start_date + 1;
4192     l_curr_wday_index := MOD((l_visit_start_date - G_CAL_START), (G_DAYS_ON + G_DAYS_OFF)) + 1;
4193     Ahl_Debug_Pub.debug('Inside first while loop');
4194   END LOOP;
4195 
4196     -- Not Day Off: Check if Holiday
4197   WHILE (IS_DEPT_Holiday(l_visit_start_date)) LOOP
4198       Ahl_Debug_Pub.debug('Visit Start Date = ' ||l_visit_start_date );
4199       l_visit_start_date := l_visit_start_date + 1;
4200       Ahl_Debug_Pub.debug('Inside second while loop');
4201       -- Holiday
4202   END LOOP;
4203 
4204   -- Commented by shbhanda 21 Oct '02
4205  /* -- Ensure that the visit start date falls on a working day
4206   l_curr_wday_index := MOD((l_visit_start_date - G_CAL_START), (G_DAYS_ON + G_DAYS_OFF)) + 1;
4207   IF (l_curr_wday_index > G_DAYS_ON) THEN
4208     -- Day Off
4209     Fnd_Message.Set_Name('AHL','AHL_LTP_VISIT_ST_WDATE_INVALID');
4210     Fnd_Message.Set_Token('VISIT_ST_DATE', p_visit_start_date);
4211     Fnd_Msg_Pub.ADD;
4212     Ahl_Debug_Pub.debug('Visit start date (' || p_visit_start_date || ') is not a working day', 'LTP: Init_Time_Vars');
4213     RAISE  Fnd_Api.G_EXC_ERROR;
4214   ELSE
4215     -- Not Day Off: Check if Holiday
4216     IF(IS_DEPT_Holiday(l_visit_start_date)) THEN
4217       -- Holiday
4218       Fnd_Message.Set_Name('AHL','AHL_LTP_VISIT_ST_WDATE_INVALID');
4219       Fnd_Message.Set_Token('VISIT_ST_DATE', p_visit_start_date);
4220       Fnd_Msg_Pub.ADD;
4221       Ahl_Debug_Pub.debug('Visit start date (' || p_visit_start_date || ') is not a working day', 'LTP: Init_Time_Vars');
4222       RAISE  Fnd_Api.G_EXC_ERROR;
4223     END IF;
4224   END IF;*/
4225 
4226 
4227   -- Add shift start to l_visit_start_date and set it to G_ZERO_TIME and G_WORKING_DATES_TBL(0)
4228   l_visit_start_date := l_visit_start_date + (G_SHIFT_START/G_SECS_IN_DAY);
4229   G_ZERO_TIME := l_visit_start_date;
4230 --  dbms_output.put_line('G_ZERO_TIME := ' || TO_CHAR(G_ZERO_TIME, 'MM/DD/YY HH24:MI:SS'));
4231   G_WORKING_DATES_TBL(0) := G_ZERO_TIME;
4232   G_MAX_CAL_DAY := 0;
4233 
4234 END Init_Time_Vars;
4235 
4236 ----------------------------------------
4237 -- Determine the Nth working date (including shift start time)
4238 -- based on the applicable calendar
4239 ----------------------------------------
4240 FUNCTION Get_Nth_Day(p_day_index NUMBER) RETURN DATE
4241 IS
4242 
4243   l_temp_index NUMBER;
4244   l_curr_day   DATE;
4245   l_curr_wday_index NUMBER;
4246   l_temp_flag BOOLEAN;
4247 
4248 BEGIN
4249   IF (p_day_index <= G_MAX_CAL_DAY) THEN
4250     RETURN G_WORKING_DATES_TBL(p_day_index);
4251   ELSE
4252     FOR l_temp_index IN G_MAX_CAL_DAY + 1 .. p_day_index LOOP
4253       l_curr_day := G_WORKING_DATES_TBL(l_temp_index - 1) + 1;
4254       l_temp_flag := FALSE;
4255       WHILE NOT l_temp_flag LOOP
4256         -- Check if l_curr_day is a working day
4257         l_curr_wday_index := MOD((TRUNC(l_curr_day) - G_CAL_START), (G_DAYS_ON + G_DAYS_OFF)) + 1;
4258         IF (l_curr_wday_index > G_DAYS_ON) THEN
4259           -- Day Off
4260           l_temp_flag := FALSE;
4261           l_curr_day := l_curr_day + 1;
4262         ELSE
4263           -- Not Day Off: Check if Holiday
4264           IF(IS_DEPT_Holiday(l_curr_day)) THEN
4265             -- Holiday
4266             l_temp_flag := FALSE;
4267             l_curr_day := l_curr_day + 1;
4268           ELSE
4269 -- yazhou 24Aug2005 starts
4270 -- Resource Leveling Re-design
4271 -- Remove calendar range validation to sync with time calculation in VWP
4272 /*
4273             -- Working Day: Check if day is in calendar range
4274             IF(l_curr_day > G_CAL_END) THEN
4275               Fnd_Message.Set_Name('AHL','AHL_LTP_INSUFFICIENT_CAL_RANGE');
4276               Fnd_Msg_Pub.ADD;
4277               Ahl_Debug_Pub.debug('Computed date (' || l_curr_day || ') is outside calendar range', 'LTP: Init_Time_Vars');
4278               RAISE  Fnd_Api.G_EXC_ERROR;
4279             END IF;
4280 */
4281 -- yazhou 24Aug2005 ends
4282 
4283             -- Add this day to the table
4284             G_WORKING_DATES_TBL(l_temp_index) := l_curr_day;
4285             G_MAX_CAL_DAY := l_temp_index;
4286             l_temp_flag := TRUE;
4287           END IF;
4288         END IF;
4289       END LOOP;
4290     END LOOP;
4291     RETURN G_WORKING_DATES_TBL(p_day_index);
4292   END IF;
4293 END Get_Nth_Day;
4294 
4295 ----------------------------------------
4296 -- Function to determine if a specific date is a holiday
4297 ----------------------------------------
4298 FUNCTION IS_DEPT_Holiday(l_curr_date DATE) RETURN BOOLEAN
4299 IS
4300   l_temp_date DATE := TRUNC(l_curr_date);
4301 BEGIN
4302   IF (G_EXCEPTION_DATES_TBL.COUNT = 0) THEN
4303     RETURN FALSE;
4304   END IF;
4305   FOR i IN G_EXCEPTION_DATES_TBL.FIRST .. G_EXCEPTION_DATES_TBL.LAST LOOP
4306     IF (l_temp_date = G_EXCEPTION_DATES_TBL(i)) THEN
4307       RETURN TRUE;
4308     ELSIF (l_temp_date < G_EXCEPTION_DATES_TBL(i)) THEN
4309       RETURN FALSE;
4310     END IF;
4311   END LOOP;
4312   RETURN FALSE;
4313 END IS_DEPT_Holiday;
4314 
4315 ----------------------------------------
4316 -- Function to determine if a specific date is not
4317 -- a holiday in the given department
4318 ----------------------------------------
4319 FUNCTION Not_A_Holiday(p_curr_date DATE, p_dept_id NUMBER) RETURN BOOLEAN
4320 IS
4321   l_junk      VARCHAR2(1);
4322 BEGIN
4323   SELECT 'x' INTO l_junk FROM AHL_DEPARTMENT_SHIFTS ADS, BOM_CALENDAR_EXCEPTIONS BCE
4324   WHERE ADS.DEPARTMENT_ID = p_dept_id AND
4325   BCE.CALENDAR_CODE = ADS.CALENDAR_CODE AND
4326   BCE.EXCEPTION_TYPE = G_HOLIDAY_TYPE AND
4327   TRUNC(BCE.EXCEPTION_DATE) = TRUNC(p_curr_date);
4328 
4329   IF (SQL%NOTFOUND) THEN
4330     RETURN TRUE;
4331   ELSE
4332     RETURN FALSE;
4333   END IF;
4334 
4335  EXCEPTION
4336    WHEN NO_DATA_FOUND THEN
4337     RETURN TRUE;
4338 
4339 END Not_A_Holiday;
4340 
4341 ----------------------------------------
4342 -- Function to determine if a specific resource is available
4343 -- (working in a shift) at a specific time
4344 ----------------------------------------
4345 FUNCTION Resource_In_Duty(p_resource_id NUMBER, p_start_date_time DATE) RETURN BOOLEAN
4346 IS
4347 
4348   CURSOR l_shift_details_csr(p_resource_id NUMBER) IS
4349     SELECT from_time, to_time
4350     FROM bom_shift_times st, bom_resource_shifts rs
4351     WHERE st.shift_num = rs.shift_num AND
4352     rs.resource_id = p_resource_id;
4353 
4354   l_shift_start NUMBER := 0;
4355   l_shift_end NUMBER := 0;
4356   l_start_second NUMBER := 0;
4357 
4358 BEGIN
4359 
4360   -- Get Days On and Days Off
4361   OPEN l_shift_details_csr(p_resource_id);
4362   FETCH l_shift_details_csr INTO l_shift_start, l_shift_end;
4363   IF (l_shift_details_csr%NOTFOUND) THEN
4364     Fnd_Message.Set_Name('AHL','AHL_LTP_NO_SHIFT_FOR_RSRC');
4365     Fnd_Message.Set_Token('RSRC_ID', p_resource_id);
4366     Fnd_Msg_Pub.ADD;
4367     CLOSE l_shift_details_csr;
4368     Ahl_Debug_Pub.debug('No Shift for Resource: ' || p_resource_id, 'LTP: Resource_In_Duty');
4369     RAISE  Fnd_Api.G_EXC_UNEXPECTED_ERROR;
4370   END IF;
4371   CLOSE l_shift_details_csr;
4372 
4373   l_start_second := (p_start_date_time - TRUNC(p_start_date_time)) * G_SECS_IN_DAY;
4374   IF (l_shift_start > l_shift_end) THEN
4375     RETURN (l_start_second >= l_shift_start OR l_start_second <= l_shift_end);
4376   ELSE
4377     RETURN  (l_start_second >= l_shift_start AND l_start_second <= l_shift_end);
4378   END IF;
4379 END Resource_In_Duty;
4380 
4381 ----------------------------------------
4382 -- Function to determine if the Resource is already present in the given table
4383 ----------------------------------------
4384 FUNCTION Is_Resource_Present(p_aso_resource_id NUMBER,
4385                              p_task_rsrc_tbl   Plan_Rsrc_Tbl_Type) RETURN BOOLEAN
4386 IS
4387 BEGIN
4388   IF (p_task_rsrc_tbl.COUNT = 0) THEN
4389     RETURN FALSE;
4390   ELSE
4391     IF (p_aso_resource_id IS NOT NULL) THEN
4392       FOR i IN p_task_rsrc_tbl.FIRST .. p_task_rsrc_tbl.LAST LOOP
4393         IF (p_task_rsrc_tbl(i).ASO_BOM_TYPE = G_ASO_RESOURCE AND
4394             p_task_rsrc_tbl(i).RESOURCE_ID = p_aso_resource_id) THEN
4395           RETURN TRUE;
4396         END IF;
4397       END LOOP;
4398   END IF;
4399   END IF;
4400 END Is_Resource_Present;
4401 ----------------------------------------
4402 -- Function to determine if two time periods overlap
4403 -- Note that If the end time of one period coincides with the
4404 -- start time of the other time period, the timeperiods DON'T overlap
4405 ----------------------------------------
4406 FUNCTION Periods_Overlap(p1_start_time DATE, p1_end_time DATE, p2_start_time DATE, p2_end_time DATE)
4407 RETURN BOOLEAN IS
4408   l1s DATE := p1_start_time;
4409   l1e DATE := p1_end_time;
4410   l2s DATE := p2_start_time;
4411   l2e DATE := p2_end_time;
4412 
4413   l_temp_time DATE;
4414 BEGIN
4415  IF (p1_start_time IS NULL OR p2_start_time IS NULL) THEN
4416    -- Invalid: Return false
4417    RETURN FALSE;
4418  END IF;
4419 
4420  IF(l1s > l2s) THEN
4421    -- Swap so that l1 starts first
4422    l_temp_time := l1s;
4423    l1s := l2s;
4424    l2s := l_temp_time;
4425    l_temp_time := l1e;
4426    l1e := l2e;
4427    l2e := l_temp_time;
4428  END IF;
4429  RETURN (l1e > l2s);
4430 END Periods_Overlap;
4431 
4432 ----------------------------------------
4433   -- Calculates the maximum required quantity during a given period
4434 ----------------------------------------
4435 FUNCTION Get_Required_Quantity(
4436   p_start_time   DATE,
4437   p_end_time     DATE,
4438   p_tp_dtls_tbl  Time_Period_Details_Tbl_Type)
4439 RETURN NUMBER IS
4440 
4441   l_qty_change_tbl  Qty_Change_Tbl_Type;
4442   l_temp_index      NUMBER := 1;
4443   l_initial_req     NUMBER := 0;
4444   l_max_demand      NUMBER := 0;
4445   l_cur_demand      NUMBER := 0;
4446   l_peak_instant    DATE;
4447 
4448   l_api_name        CONSTANT VARCHAR2(30) := 'Get_Required_Quantity';
4449 
4450 BEGIN
4451 
4452   IF (l_log_statement >= l_log_current_level) THEN
4453         fnd_log.string
4454         (
4455           fnd_log.level_statement,
4456           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
4457           'inside Get_Required_Quantity. p_tp_dtls_tbl.count: '||p_tp_dtls_tbl.count
4458         );
4459 
4460   END IF;
4461 
4462   -- Fill the Quantity Change table with operations/tasks that are in
4463   -- progress during the time period, Getting the Initial demand along the way
4464   FOR i IN p_tp_dtls_tbl.FIRST .. p_tp_dtls_tbl.LAST LOOP
4465 
4466     IF (l_log_statement >= l_log_current_level) THEN
4467          fnd_log.string
4468          (
4469           fnd_log.level_statement,
4470           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
4471           ' i: '||i
4472          );
4473     END IF;
4474 
4475     IF (Periods_Overlap(p_start_time, p_end_time, p_tp_dtls_tbl(i).START_TIME, p_tp_dtls_tbl(i).END_TIME)) THEN
4476 
4477        IF (l_log_statement >= l_log_current_level) THEN
4478          fnd_log.string
4479          (
4480           fnd_log.level_statement,
4481           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
4482           ' Periods_Overlap'
4483          );
4484       END IF;
4485 
4486       l_qty_change_tbl(l_temp_index).EVENT_TIME := p_tp_dtls_tbl(i).START_TIME;
4487       l_qty_change_tbl(l_temp_index).QTY_CHANGE := p_tp_dtls_tbl(i).QUANTITY;
4488 
4489        IF (l_log_statement >= l_log_current_level) THEN
4490          fnd_log.string
4491          (
4492           fnd_log.level_statement,
4493           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
4494           ' l_qty_change_tbl('||l_temp_index||').QTY_CHANGE: '||l_qty_change_tbl(l_temp_index).QTY_CHANGE
4495          );
4496 
4497        END IF;
4498 
4499       l_temp_index := l_temp_index + 1;
4500       l_qty_change_tbl(l_temp_index).EVENT_TIME := p_tp_dtls_tbl(i).END_TIME;
4501       l_qty_change_tbl(l_temp_index).QTY_CHANGE := -(p_tp_dtls_tbl(i).QUANTITY);
4502 
4503        IF (l_log_statement >= l_log_current_level) THEN
4504          fnd_log.string
4505          (
4506           fnd_log.level_statement,
4507           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
4508           ' l_qty_change_tbl('||l_temp_index||').QTY_CHANGE: '||l_qty_change_tbl(l_temp_index).QTY_CHANGE
4509          );
4510 
4511        END IF;
4512 
4513       l_temp_index := l_temp_index + 1;
4514       IF (p_tp_dtls_tbl(i).START_TIME < p_start_time) THEN
4515         l_initial_req := l_initial_req + p_tp_dtls_tbl(i).QUANTITY;
4516       END IF;
4517 
4518        IF (l_log_statement >= l_log_current_level) THEN
4519          fnd_log.string
4520          (
4521           fnd_log.level_statement,
4522           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
4523           ' l_temp_index: '||l_temp_index
4524          );
4525 
4526        END IF;
4527     END IF;
4528   END LOOP;
4529 
4530   IF (l_log_statement >= l_log_current_level) THEN
4531         fnd_log.string
4532         (
4533           fnd_log.level_statement,
4534           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
4535           'After loop l_qty_change_tbl.count: '||l_qty_change_tbl.count
4536         );
4537 
4538   END IF;
4539 
4540 
4541   IF (l_qty_change_tbl.COUNT = 0) THEN
4542     -- No Task/Operation during this period
4543     RETURN 0;
4544   ELSIF (l_qty_change_tbl.COUNT = 2) THEN
4545     -- Only one task
4546     RETURN l_qty_change_tbl(l_qty_change_tbl.FIRST).QTY_CHANGE;
4547   END IF;
4548 
4549   -- Sort Quantity Change Table on Event time
4550   Sort_Qty_Change_Table(l_qty_change_tbl);
4551 
4552   -- Get the maximum demand
4553   l_cur_demand := l_initial_req;
4554   l_max_demand := l_initial_req;
4555   l_peak_instant := l_qty_change_tbl(l_qty_change_tbl.FIRST).EVENT_TIME;
4556   FOR j IN l_qty_change_tbl.FIRST .. l_qty_change_tbl.LAST LOOP
4557     IF (l_qty_change_tbl(j).EVENT_TIME >= p_start_time) THEN
4558       l_cur_demand := l_cur_demand + l_qty_change_tbl(j).QTY_CHANGE;
4559       IF (l_cur_demand > l_max_demand) THEN
4560         l_max_demand := l_cur_demand;
4561         l_peak_instant := l_qty_change_tbl(j).EVENT_TIME;
4562       END IF;
4563     END IF;
4564   END LOOP;
4565 
4566   IF (l_log_statement >= l_log_current_level) THEN
4567         fnd_log.string
4568         (
4569           fnd_log.level_statement,
4570           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
4571           'Complete Get_Required_Quantity. l_max_demand: '||l_max_demand
4572         );
4573 
4574   END IF;
4575 --  dbms_output.put_line('Max demand = ' || l_max_demand || ' at ' || TO_CHAR(l_peak_instant, 'MM/DD/YY HH24:MI:SS'));
4576   -- Return the maximum requirement
4577   RETURN l_max_demand;
4578 END;
4579 ----------------------------------------
4580 -- Compares a visit/task combination with another
4581 -- Returns +1 If first visit task > second visit task
4582 -- Returns -1 If first visit task < second visit task
4583 -- Returns 0 If first visit task = second visit task
4584 ----------------------------------------
4585 FUNCTION Compare_Visit_Tasks(p_visit_1 NUMBER, p_task_1 NUMBER, p_visit_2 NUMBER, p_task_2 NUMBER)
4586 RETURN NUMBER IS
4587 BEGIN
4588   IF (p_visit_1 > p_visit_2) THEN
4589     RETURN 1;
4590   ELSIF (p_visit_1 < p_visit_2) THEN
4591     RETURN -1;
4592   ELSE
4593     -- Visit Ids are equal: Compare by task id
4594     IF (p_task_1 > p_task_2) THEN
4595       RETURN 1;
4596     ELSIF (p_task_1 < p_task_2) THEN
4597       RETURN -1;
4598     ELSE
4599       RETURN 0;
4600     END IF;
4601   END IF;
4602 END Compare_Visit_Tasks;
4603 /*
4604 ----------------------------------------
4605 -- Diagnostic procedure to test work day calculations
4606 ----------------------------------------
4607 PROCEDURE Dump_Working_dates_tbl
4608 (
4609 --  p_start_date IN DATE := TO_DATE('15-May-2002'),
4610   p_dept_id IN NUMBER := 1,
4611   p_num_days IN NUMBER := 100
4612 ) IS
4613 
4614   l_index NUMBER;
4615   l_temp_date DATE;
4616 BEGIN
4617 --  dbms_output.put_line('Beginning Dump_Working_dates_tbl');
4618 --  dbms_output.put_line('p_start_date = ' || p_start_date);
4619 
4620   Init_Time_Vars(p_start_date, p_dept_id);
4621 
4622   IF G_EXCEPTION_DATES_TBL.COUNT > 0 THEN
4623     l_index := G_EXCEPTION_DATES_TBL.FIRST;
4624     WHILE l_index IS NOT NULL LOOP
4625 --      dbms_output.put_line('Holiday: ' || l_index || ' Date: ' || TO_CHAR(G_EXCEPTION_DATES_TBL(l_index), 'MM/DD/YY HH24:MI:SS'));
4626       l_index := G_EXCEPTION_DATES_TBL.NEXT(l_index);
4627     END LOOP;
4628   END IF;
4629 
4630   l_temp_date := Get_Nth_Day(p_num_days);
4631 --  dbms_output.put_line('G_WORKING_DATES_TBL COUNT = ' || G_WORKING_DATES_TBL.COUNT);
4632   IF G_WORKING_DATES_TBL.COUNT > 0 THEN
4633     l_index := G_WORKING_DATES_TBL.FIRST;
4634     WHILE l_index IS NOT NULL LOOP
4635 --      dbms_output.put_line('Day: ' || l_index || ' Date: ' || TO_CHAR(G_WORKING_DATES_TBL(l_index), 'MM/DD/YY HH24:MI:SS'));
4636       l_index := G_WORKING_DATES_TBL.NEXT(l_index);
4637     END LOOP;
4638   END IF;
4639 --  dbms_output.put_line('Ending Dump_Working_dates_tbl');
4640 END;
4641 */
4642 -------------------------------
4643 -- End Local Procedures --
4644 -------------------------------
4645 
4646 ---------------------------------------
4647 -- Calculates the available units of
4648 -- a resource during a given period
4649 ----------------------------------------
4650 -- yazhou 24Aug2005 starts
4651 -- Resource Leveling Re-design
4652 -- Get the shift number for the given department
4653 -- And then retrieve shift capacity for that shift only
4654 -- Also removed p_org_id as input parameter since it's not used
4655 
4656 FUNCTION Get_Available_Units(p_resource_id  NUMBER,
4657                              p_dept_id      NUMBER)
4658 RETURN NUMBER IS
4659   --
4660     CURSOR l_get_bom_rsrc_dtls_csr(p_bom_resource_id   IN NUMBER,
4661                                  p_bom_department_id IN NUMBER) IS
4662     SELECT B.CAPACITY_UNITS,a.description
4663     FROM bom_resources A,
4664          bom_department_resources B
4665   WHERE a. resource_id = B.resource_id
4666    AND B.resource_id = p_bom_resource_id
4667    AND B.department_id = p_bom_department_id;
4668 
4669   -- Gets shift capacity
4670     CURSOR l_get_shift_dtls_csr(p_bom_resource_id   IN NUMBER,
4671                                 p_bom_department_id IN NUMBER) IS
4672     SELECT CAPACITY_UNITS SHIFT_CAPACITY
4673     FROM bom_resource_shifts
4674   WHERE resource_id = p_bom_resource_id
4675    AND  department_id = p_bom_department_id
4676      AND  SHIFT_NUM = ( select shift_num
4677                           FROM  AHL_DEPARTMENT_SHIFTS
4678                           WHERE department_id = p_bom_department_id);
4679 
4680 --  l_res_type            NUMBER;
4681 --  l_bom_org_id          NUMBER;
4682   l_total_quantity      NUMBER := 0;
4683 --  l_bom_resource_id     NUMBER;
4684   l_capacity_units      NUMBER;
4685 --  l_shift_num           NUMBER;
4686   l_shift_capacity      NUMBER;
4687   l_description         bom_resources.description%type;
4688 
4689 -- yazhou 24Aug2005 ends
4690 
4691 BEGIN
4692     Ahl_Debug_Pub.debug('enter get available p_resource_id:'||p_resource_id);
4693     Ahl_Debug_Pub.debug('enter get available p_dept_id:'||p_dept_id);
4694 
4695     --Get available units
4696     OPEN l_get_bom_rsrc_dtls_csr(p_resource_id,p_dept_id);
4697     FETCH l_get_bom_rsrc_dtls_csr INTO l_capacity_units,l_description;
4698     IF l_get_bom_rsrc_dtls_csr%NOTFOUND THEN
4699        Fnd_Message.Set_Name('AHL','AHL_LTP_RES_ID_INVALID');
4700        Fnd_Message.Set_Token('RES_ID', l_description);
4701        Fnd_Msg_Pub.ADD;
4702     END IF;
4703     CLOSE l_get_bom_rsrc_dtls_csr;
4704     Ahl_Debug_Pub.debug('Inside get available l_capacity_units:'||l_capacity_units);
4705 
4706     -- Get shift capacity
4707     OPEN l_get_shift_dtls_csr(p_resource_id,p_dept_id);
4708     FETCH l_get_shift_dtls_csr INTO l_shift_capacity;
4709     CLOSE l_get_shift_dtls_csr;
4710 
4711     Ahl_Debug_Pub.debug('Inside get available l_shift_capacity:'||l_shift_capacity);
4712 
4713    IF l_shift_capacity IS NOT NULL THEN
4714       l_total_quantity := l_shift_capacity;
4715      ELSE
4716       l_total_quantity := l_capacity_units;
4717    END IF;
4718 
4719     Ahl_Debug_Pub.debug('Inside get available l_total_quantity:'||l_total_quantity);
4720 
4721    RETURN l_total_quantity;
4722 
4723 END Get_Available_Units;
4724 --
4725 -- AnRaj: Obsoleted Procedure
4726 /*
4727 PROCEDURE GET_WIP_DISC_REQ_UNITS(
4728              p_org_id          IN NUMBER,
4729              p_bom_dept_id     IN NUMBER,
4730              p_bom_resource_id IN NUMBER,
4731              p_start_date      IN DATE,
4732              p_end_date        IN DATE,
4733              x_assigned_units  OUT NOCOPY NUMBER)
4734 IS
4735 
4736  CURSOR wip_disc_cur (c_org_id IN NUMBER)
4737     IS
4738     SELECT wip.wip_entity_id
4739     FROM wip_discrete_jobs wip
4740   WHERE wip.organization_id = c_org_id
4741    AND (p_start_date BETWEEN wip.scheduled_start_date
4742       AND wip.scheduled_completion_date
4743     OR
4744     p_end_date BETWEEN wip.scheduled_start_date
4745     AND wip.scheduled_completion_date)
4746      AND not exists (select wip_entity_id
4747      from ahl_workorders wo
4748      where wo.wip_entity_id = wip.wip_entity_id
4749      and wo.status_code = '17');
4750 
4751   --
4752   CURSOR wip_oper_cur (c_wip_entity_id IN NUMBER,
4753                        c_dept_id       IN NUMBER)
4754    IS
4755      SELECT wip_entity_id
4756        FROM wip_operations
4757     WHERE wip_entity_id = c_wip_entity_id
4758         AND department_id = c_dept_id;
4759         --
4760    CURSOR wip_res_cur (c_wip_entity_id IN NUMBER,
4761                        c_resource_id   IN NUMBER)
4762    IS
4763      SELECT SUM(assigned_units)
4764       FROM wip_operation_resources
4765      WHERE wip_entity_id = c_wip_entity_id
4766       AND  resource_id = c_resource_id;
4767   l_wip_entity_id    NUMBER;
4768   l_wip_op_entity_id NUMBER;
4769   l_assigned_units   NUMBER;
4770  BEGIN
4771     --
4772   OPEN wip_disc_cur(p_org_id);
4773   LOOP
4774   FETCH wip_disc_cur INTO l_wip_entity_id;
4775   EXIT WHEN wip_disc_cur%NOTFOUND;
4776   IF l_wip_entity_id IS NOT NULL THEN
4777       OPEN wip_oper_cur(l_wip_entity_id,p_bom_dept_id);
4778     LOOP
4779     FETCH wip_oper_cur INTO l_wip_op_entity_id;
4780     EXIT WHEN wip_oper_cur%NOTFOUND;
4781      IF wip_oper_cur%FOUND THEN
4782         OPEN wip_res_cur(l_wip_op_entity_id,p_bom_resource_id);
4783       FETCH wip_res_cur INTO x_assigned_units;
4784       CLOSE wip_res_cur;
4785      END IF;
4786        END LOOP;
4787      CLOSE wip_oper_cur;
4788      END IF;
4789     END LOOP;
4790   CLOSE wip_disc_cur;
4791   END;
4792   */
4793 --
4794 PROCEDURE GET_WIP_DISC_ASSIGN_UNITS(
4795        p_bom_resource_id   IN NUMBER,
4796        p_start_date        IN DATE,
4797        p_end_date          IN DATE,
4798        x_assigned_persons  OUT NOCOPY NUMBER)
4799 IS
4800 CURSOR get_per_ins_cur(c_resource_id IN NUMBER)
4801   IS
4802    SELECT person_id,
4803           instance_id,
4804       effective_start_date,effective_end_date
4805     FROM bom_resource_employees
4806    WHERE resource_id = c_resource_id;
4807    --
4808 CURSOR get_assign_per_cur(c_instance_id IN NUMBER,
4809                           c_start_date  IN DATE,
4810               c_end_date    IN DATE)
4811   IS
4812    SELECT COUNT(*)
4813     FROM wip_op_resource_instances
4814    WHERE instance_id = c_instance_id
4815     AND (c_start_date BETWEEN start_date AND
4816       completion_date) OR
4817     (c_end_date BETWEEN start_date AND
4818     completion_date);
4819 
4820    l_get_per_ins_rec    get_per_ins_cur%ROWTYPE;
4821    l_dummy              NUMBER;
4822    --
4823 BEGIN
4824     OPEN get_per_ins_cur(p_bom_resource_id);
4825   LOOP
4826    FETCH get_per_ins_cur INTO l_get_per_ins_rec;
4827    EXIT WHEN get_per_ins_cur%NOTFOUND;
4828    IF l_get_per_ins_rec.instance_id IS NOT NULL
4829      THEN
4830        OPEN get_assign_per_cur(l_get_per_ins_rec.instance_id,
4831                              p_start_date,p_end_date);
4832      FETCH get_assign_per_cur INTO l_dummy;
4833      CLOSE get_assign_per_cur;
4834     END IF;
4835      x_assigned_persons := l_dummy;
4836   END LOOP;
4837   CLOSE get_per_ins_cur;
4838 END;
4839 
4840 -- JARAMANA 24Aug2005 starts
4841 -- Resource Leveling Re-design
4842 
4843 -- Gets the (unique) ids of all the resources used in the
4844 -- given department and in the given time range by the given resource requirements.
4845 PROCEDURE Get_Used_Resources
4846 (
4847    p_dept_id       IN NUMBER,
4848    p_start_date    IN DATE,
4849    p_end_date      IN DATE,
4850    p_tp_dtls_tbl   IN Time_Period_Details_Tbl_Type,
4851    x_resources_tbl OUT NOCOPY Resource_Tbl_Type
4852 ) IS
4853  l_temp_index  NUMBER := 1;
4854  l_temp_index2  NUMBER;
4855  l_temp_num_tbl Resource_Tbl_Type;
4856 BEGIN
4857  IF (p_tp_dtls_tbl.COUNT > 0) THEN
4858    FOR i IN p_tp_dtls_tbl.FIRST..p_tp_dtls_tbl.LAST LOOP
4859      IF (p_tp_dtls_tbl(i).DEPARTMENT_ID = p_dept_id AND
4860          Periods_Overlap(p_tp_dtls_tbl(i).START_TIME, p_tp_dtls_tbl(i).END_TIME,
4861                          p_start_date, p_end_date)) THEN
4862        -- This reseource is required in the given dept during the given time range
4863        l_temp_num_tbl(p_tp_dtls_tbl(i).BOM_RESOURCE_ID) := p_tp_dtls_tbl(i).BOM_RESOURCE_ID;
4864      END IF;
4865    END LOOP;
4866 
4867    -- Transfer from the associative array to the 1 based output table
4868    IF (l_temp_num_tbl.COUNT > 0) THEN
4869      l_temp_index2 := l_temp_num_tbl.FIRST;
4870      WHILE (l_temp_index2 IS NOT NULL) LOOP
4871        x_resources_tbl(l_temp_index) := l_temp_index2;
4872        l_temp_index := l_temp_index + 1;
4873        l_temp_index2 := l_temp_num_tbl.NEXT(l_temp_index2);
4874      END LOOP;
4875    END IF;
4876  END IF;
4877 END Get_Used_Resources;
4878 
4879 PROCEDURE Append_WIP_Requirements
4880 (
4881    p_org_id        IN NUMBER,
4882    p_dept_id       IN NUMBER,
4883    p_start_date    IN DATE,
4884    p_end_date      IN DATE,
4885    p_resource_id   IN NUMBER,
4886    p_x_tp_dtls_tbl IN OUT NOCOPY Time_Period_Details_Tbl_Type
4887 ) IS
4888  CURSOR get_wip_req_dtls_csr IS
4889    SELECT wor.start_date, wor.completion_date, wor.assigned_units, wor.wip_entity_id
4890    FROM wip_operation_resources wor, wip_operations wo, wip_discrete_jobs wdj,
4891          AHL_WORKORDERS aw
4892    WHERE wor.resource_id = p_resource_id
4893      AND wo.department_id = p_dept_id
4894      AND wo.wip_entity_id = wor.wip_entity_id
4895      AND wdj.WIP_ENTITY_ID = aw.WIP_ENTITY_ID
4896      AND aw.STATUS_CODE not in ('17','22','7','12','18','4','5')
4897      --(17-Draft, 22-Deleted, 7-Cancelled, 12-Closed, 18-Deferrred, 4-Complete, 5-Complete No-charge)
4898      AND wdj.organization_id = p_org_id
4899      AND wdj.wip_entity_id = wo.wip_entity_id
4900      AND ((wor.start_date BETWEEN p_start_date and p_end_date) OR
4901           (wor.completion_date BETWEEN p_start_date and p_end_date) OR
4902           (wor.start_date < p_start_date AND wor.completion_date > p_end_date));
4903 
4904  l_temp_index  NUMBER := p_x_tp_dtls_tbl.LAST + 1;
4905  l_api_name        CONSTANT VARCHAR2(30) := 'Append_WIP_Requirements';
4906 
4907 BEGIN
4908  FOR wip_req_dtls IN get_wip_req_dtls_csr LOOP
4909    p_x_tp_dtls_tbl(l_temp_index).START_TIME := wip_req_dtls.start_date;
4910    p_x_tp_dtls_tbl(l_temp_index).END_TIME := wip_req_dtls.completion_date;
4911    p_x_tp_dtls_tbl(l_temp_index).QUANTITY := wip_req_dtls.assigned_units;
4912    -- None of the other fields in the p_x_tp_dtls_tbl(l_temp_index) record
4913    -- are populated since they are not relevant.
4914 
4915    IF (l_log_statement >= l_log_current_level) THEN
4916       fnd_log.string
4917       (
4918           fnd_log.level_statement,
4919          'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
4920          'wip_entity_id: '|| wip_req_dtls.wip_entity_id
4921       );
4922       fnd_log.string
4923       (
4924          fnd_log.level_statement,
4925          'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
4926          'p_x_tp_dtls_tbl('||l_temp_index||').start_time: '|| TO_CHAR(p_x_tp_dtls_tbl(l_temp_index).start_time, 'DD-MON-YYYY hh24:mi')
4927       );
4928       fnd_log.string
4929       (
4930          fnd_log.level_statement,
4931          'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
4932          'p_x_tp_dtls_tbl('||l_temp_index||').end_time: '|| TO_CHAR( p_x_tp_dtls_tbl(l_temp_index).end_time, 'DD-MON-YYYY hh24:mi')
4933       );
4934       fnd_log.string
4935       (
4936           fnd_log.level_statement,
4937           'ahl.plsql.'||g_pkg_name||'.'||l_api_name,
4938           'p_x_tp_dtls_tbl('||l_temp_index||').quantity: '|| p_x_tp_dtls_tbl(l_temp_index).quantity
4939       );
4940 
4941     END IF;
4942 
4943    l_temp_index := l_temp_index + 1;
4944  END LOOP;
4945 
4946 END Append_WIP_Requirements;
4947 
4948 -- JARAMANA 24Aug2005 ends
4949 --
4950 END Ahl_Ltp_Resrc_Levl_Pvt;