DBA Data[Home] [Help]

PACKAGE BODY: APPS.AHL_LTP_MTL_REQ_PVT

Source


1 PACKAGE BODY AHL_LTP_MTL_REQ_PVT AS
2 /* $Header: AHLVLMRB.pls 120.5.12020000.2 2012/12/10 13:48:28 shnatu ship $ */
3 
4 -----------------------
5 -- Declare Constants --
6 -----------------------
7 G_PKG_NAME          CONSTANT VARCHAR2(30) := 'AHL_LTP_MTL_REQ_PVT';
8 
9 G_LOG_PREFIX        CONSTANT VARCHAR2(100) := 'ahl.plsql.AHL_LTP_MTL_REQ_PVT';
10 
11 G_NO_FLAG           CONSTANT VARCHAR2(1)  := 'N';
12 G_YES_FLAG          CONSTANT VARCHAR2(1)  := 'Y';
13 
14 G_APP_MODULE        CONSTANT VARCHAR2(30) := 'AHL';
15 
16 -- Mtl Req Association Types
17 G_ASSOC_TYPE_DISPOSITION    CONSTANT VARCHAR2(30) := 'DISPOSITION';
18 G_ASSOC_TYPE_ROUTE          CONSTANT VARCHAR2(30) := 'ROUTE';
19 G_ASSOC_TYPE_OPERATION      CONSTANT VARCHAR2(30) := 'OPERATION';
20 
21 -- Requirement Types
22 G_REQ_TYPE_FORECAST         CONSTANT VARCHAR2(30) := 'FORECAST';
23 G_REQ_TYPE_PLANNED          CONSTANT VARCHAR2(30) := 'PLANNED';
24 
25 -- Mapping Status for Position
26 G_MAPPING_STATUS_MATCH      CONSTANT VARCHAR2(30) := 'MATCH';
27 G_MAPPING_STATUS_EMPTY      CONSTANT VARCHAR2(30) := 'EMPTY';
28 G_MAPPING_STATUS_NA         CONSTANT VARCHAR2(30) := 'NA';
29 
30 -- Added by skpathak on 06-NOV-2008 for bug-7336824
31 G_CURRENT_RUNTIME_LEVEL CONSTANT NUMBER := FND_LOG.G_CURRENT_RUNTIME_LEVEL;
32 G_LEVEL_ERROR           CONSTANT NUMBER := FND_LOG.LEVEL_ERROR;
33 G_LEVEL_EVENT           CONSTANT NUMBER := FND_LOG.LEVEL_EVENT;
34 G_LEVEL_PROCEDURE       CONSTANT NUMBER := FND_LOG.LEVEL_PROCEDURE;
35 G_LEVEL_STATEMENT       CONSTANT NUMBER := FND_LOG.LEVEL_STATEMENT;
36 
37 -------------------------------------------------
38 -- Declare Locally used Record and Table Types --
39 -------------------------------------------------
40 
41 -------------------------------------------
42 -- Declare Local Procedures and Function --
43 -------------------------------------------
44 
45   -- This Procedure validates the input for the Get_Route_Mtl_Req API
46   -- Modified by surrkuma for bug# 13998921 on 26-Apr-12
47   -- Added Visit ID as a parameter for validating visit task instance.
48   PROCEDURE Validate_Mtl_Req_Input(
49      p_route_id          IN         NUMBER,
50      p_mr_route_id       IN         NUMBER,
51      p_item_instance_id  IN         NUMBER,
52      p_requirement_date  IN         DATE,
53      p_request_type      IN         VARCHAR2,
54      p_visit_id          IN         NUMBER    := null,
55      x_route_id          OUT NOCOPY NUMBER);
56 
57   -- This Procedure gets the requirements from the Disposition List
58   PROCEDURE Get_Disp_List_Requirements(
59      p_route_id          IN         NUMBER,
60      p_item_instance_id  IN         NUMBER,
61      p_requirement_date  IN         DATE,
62      p_request_type      IN         VARCHAR2,
63      p_unit_instance_id  IN         NUMBER,
64      p_inst_item_id      IN         NUMBER,
65      p_mc_header_id      IN         NUMBER,
66      p_mc_id             IN         NUMBER,
67      p_mc_version        IN         NUMBER,
68      x_disp_req_list     OUT NOCOPY Route_Mtl_Req_Tbl_Type);
69 
70   -- This Procedure gets the Position Path Requirement
71   PROCEDURE Get_Pos_Path_Requirement(
72      p_position_path_id  IN         NUMBER,
73      p_requirement_date  IN         DATE,
74      p_unit_instance_id  IN         NUMBER,
75      p_mc_header_id      IN         NUMBER,
76      p_mc_id             IN         NUMBER,
77      p_mc_version        IN         NUMBER,
78      p_rt_oper_mtl_id    IN         NUMBER,
79      p_quantity          IN         NUMBER,
80      p_uom               IN         VARCHAR2,
81      p_x_disp_req_list   IN OUT NOCOPY Route_Mtl_Req_Tbl_Type);
82 
83   -- Modified by surrkuma for Service Bulletin :: 07-Jun-2011
84   -- Added the parameters MC_ID, MC_HEADER_ID, UC_HEADER_ID and VISIT_ID
85   -- This Procedure gets the requirements from the Route (or Operation)
86   PROCEDURE Get_Route_Requirements(
87      p_route_id          IN         NUMBER,
88      p_request_type      IN         VARCHAR2,
89      p_mc_id             IN         NUMBER,
90      p_mc_header_id      IN         NUMBER,
91      p_uc_header_id      IN         NUMBER,
92      p_visit_id          IN         NUMBER,
93      x_route_req_list    OUT NOCOPY Route_Mtl_Req_Tbl_Type);
94 
95   -- This Procedure validates a Position Path against a given unit and date.
96   -- It returns a status flag and if valid, it get the details about the position.
97   PROCEDURE Validate_Path_Position(
98      p_path_position_id          IN  NUMBER,
99      p_unit_instance_id          IN  NUMBER,
100      p_requirement_date          IN  DATE,
101      x_valid_flag                OUT NOCOPY VARCHAR2,
102      x_relationship_id           OUT NOCOPY NUMBER,
103      x_item_group_id             OUT NOCOPY NUMBER,
104      x_pos_instance_id           OUT NOCOPY NUMBER);
105 
106   -- This Function gets the unit's instance id
107   FUNCTION Get_Unit_Instance(
108      p_item_instance_id IN NUMBER) RETURN NUMBER;
109 
110 -- SURRKUMA :: Service Bulletin :: 07-Jun-2011
111 -- Gets an highest priority item from item group if SB rule doesn't exists for the position,
112 -- else get the highest priority item which satisfies the SB rule condition.
113 PROCEDURE Get_Item_Group_Item(
114     p_item_group_id         IN            NUMBER,
115     p_rule_id               IN            NUMBER,
116     p_visit_org_id          IN            NUMBER,
117     x_inventory_item_id     OUT   NOCOPY  NUMBER,
118     x_inventory_org_id      OUT   NOCOPY  NUMBER,
119     x_quantity              OUT   NOCOPY  NUMBER,
120     x_uom_code              OUT   NOCOPY  VARCHAR2);
121 
122 
123 -------------------------------------
124 -- End Local Procedures Declaration--
125 -------------------------------------
126 
127 -----------------------------------------
128 -- Public Procedure Definitions follow --
129 -----------------------------------------
130 -- Start of Comments --
131 --  Procedure name    : Get_Route_Mtl_Req
132 --  Type              : Private
133 --  Function          : Private API to get the Material requirements for a Route.
134 --                      For FORECAST request type, it aggregates requirements at the
135 --                      route level (across operations), and gets the highest priority item
136 --                      ignoring the inventory org. Also, a disposition list requirement is
137 --                      considered for FORECAST only if the REPLACE_PERCENT = 100%.
138 --                      For PLANNED, no aggregation is done, NO specific item is obtained
139 --                      within an item group and the REPLACE_PERCENT is not considered.
140 --  Pre-reqs    :
141 --  Parameters  :
142 --
143 --  Standard IN  Parameters :
144 --      p_api_version                   IN      NUMBER       Required
145 --      p_init_msg_list                 IN      VARCHAR2     Default  FND_API.G_FALSE
146 --      p_validation_level              IN      NUMBER       Default  FND_API.G_VALID_LEVEL_FULL
147 --
148 --  Standard OUT Parameters :
149 --      x_return_status                 OUT     VARCHAR2     Required
150 --      x_msg_count                     OUT     NUMBER       Required
151 --      x_msg_data                      OUT     VARCHAR2     Required
152 --
153 --  Get_Route_Mtl_Req Parameters:
154 --      p_route_id                      IN      NUMBER       Not Required only if p_mr_route_id is not null
155 --         The Id of Route for which to determine the material requirements
156 --      p_mr_route_id                   IN      NUMBER       Not Required only if p_route_id is not null
157 --         The Id of MR Route for which to determine the material requirements
158 --      p_item_instance_id              IN      NUMBER       Required
159 --         The Id of Instance for which to plan the material requirements
160 --      p_visit_id                      IN      NUMBER       Not Requried
161 --         The Id of Visit for which to determine the material requirements
162 --      p_requirement_date              IN      DATE         Not Required
163 --         The date when the materials are required. If provided, the positions of Master Configs
164 --         (for position path based disposition list requirement) are validated against this date.
165 --      p_request_type                  IN      VARCHAR2     Required
166 --         Should be either 'FORECAST' or 'PLANNED'
167 --      x_route_mtl_req_tbl             OUT     AHL_LTP_MTL_REQ_PVT.Route_Mtl_Req_Tbl  Required
168 --         The Table of records containing the material requirements for the route
169 --
170 --  Version :
171 --      Initial Version   1.0
172 --
173 --  End of Comments.
174 
175 PROCEDURE Get_Route_Mtl_Req
176 (
177    p_api_version           IN            NUMBER,
178    p_init_msg_list         IN            VARCHAR2  := FND_API.G_FALSE,
179    p_validation_level      IN            NUMBER    := FND_API.G_VALID_LEVEL_FULL,
180    x_return_status         OUT  NOCOPY   VARCHAR2,
181    x_msg_count             OUT  NOCOPY   NUMBER,
182    x_msg_data              OUT  NOCOPY   VARCHAR2,
183    p_route_id              IN            NUMBER,
184    p_mr_route_id           IN            NUMBER,
185    p_item_instance_id      IN            NUMBER,
186    p_visit_id              IN            NUMBER    := null, -- Added by surrkuma for Service Bulletin, 07-Jun-2011
187    p_requirement_date      IN            DATE      := null,
188    p_request_type          IN            VARCHAR2,
189    x_route_mtl_req_tbl     OUT  NOCOPY   AHL_LTP_MTL_REQ_PVT.Route_Mtl_Req_Tbl_Type) IS
190 
191   -- SURRKUMA :: Service Bulletin :: 07-Jun-2011
192   -- Modified the cursor to fetch UC header id too, for getting the affected SB rule later
193   CURSOR get_mc_dtls_csr(c_instance_id IN NUMBER) IS
194     select UC.MASTER_CONFIG_ID, MC.MC_ID, MC.VERSION_NUMBER,UC.UNIT_CONFIG_HEADER_ID
195     from AHL_UNIT_CONFIG_HEADERS UC, AHL_MC_HEADERS_B MC
196     where UC.CSI_ITEM_INSTANCE_ID = c_instance_id AND
197           MC.MC_HEADER_ID = UC.MASTER_CONFIG_ID;
198 
199   CURSOR get_item_from_instance_csr(c_instance_id IN NUMBER) IS
200     select INVENTORY_ITEM_ID from CSI_ITEM_INSTANCES
201     where INSTANCE_ID = c_instance_id;
202 
203   CURSOR get_item_group_item_csr(c_item_group_id IN NUMBER) IS
204     SELECT inventory_item_id, inventory_org_id
205     FROM ahl_item_associations_b
206     WHERE item_group_id = c_item_group_id
207       AND interchange_type_code in ('1-WAY INTERCHANGEABLE', '2-WAY INTERCHANGEABLE')
208     ORDER BY priority;
209 
210    l_route_id              NUMBER;
211    l_unit_instance_id      NUMBER;
212    l_inst_item_id          NUMBER;
213    l_mc_header_id          NUMBER;
214    l_mc_id                 NUMBER;
215    l_mc_version            NUMBER;
216    -- SURRKUMA :: Service Bulletin :: 07-Jun-2011
217    -- Added a local variable for UC header id
218    l_uc_header_id          NUMBER;
219    l_disp_req_list         AHL_LTP_MTL_REQ_PVT.Route_Mtl_Req_Tbl_Type;
220    l_route_req_list        AHL_LTP_MTL_REQ_PVT.Route_Mtl_Req_Tbl_Type;
221    l_index                 NUMBER;
222    l_temp_item_id          NUMBER;
223    l_temp_ig_id            NUMBER;
224    l_found                 BOOLEAN;
225    l_api_version  CONSTANT NUMBER := 1.0;
226    l_api_name     CONSTANT VARCHAR2(30) := 'Get_Route_Mtl_Req';
227    L_DEBUG_KEY    CONSTANT VARCHAR2(150) := G_LOG_PREFIX || '.Get_Route_Mtl_Req';
228 
229 BEGIN
230 
231   IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
232     FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.begin', 'Entering Procedure');
233   END IF;
234   IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
235     FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Input values for the Procedure: ' ||
236                                                          'p_route_id = ' || p_route_id ||
237                                                          ', p_mr_route_id = ' || p_mr_route_id ||
238                                                          ', p_item_instance_id = ' || p_item_instance_id ||
239                                                          ', p_requirement_date = ' || p_requirement_date ||
240                                                          ', p_visit_id = ' || p_visit_id ||
241                                                          ', p_request_type = ' || p_request_type);
242   END IF;
243 
244   -- Standard call to check for call compatibility
245   IF NOT FND_API.Compatible_API_Call(l_api_version, p_api_version, l_api_name, G_PKG_NAME) THEN
246     RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
247   END IF;
248 
249     -- Initialize message list if p_init_msg_list is set to TRUE
250   IF FND_API.To_Boolean(p_init_msg_list) THEN
251     FND_MSG_PUB.Initialize;
252   END IF;
253 
254   -- Initialize API return status to success
255   x_return_status := FND_API.G_RET_STS_SUCCESS;
256 
257   -- Begin Processing
258   -- First Validate the input parameters
259   Validate_Mtl_Req_Input(p_route_id         => p_route_id,
260                          p_mr_route_id      => p_mr_route_id,
261                          p_item_instance_id => p_item_instance_id,
262                          p_requirement_date => p_requirement_date,
263                          p_request_type     => p_request_type,
264                          p_visit_id         => p_visit_id,
265                          x_route_id         => l_route_id);
266 
267   IF (FND_MSG_PUB.Count_Msg > 0) THEN
268     -- There are validation errors: Raise error
269     RAISE FND_API.G_EXC_ERROR;
270   END IF;
271 
272   -- Get the Unit Instance
273   l_unit_instance_id := Get_Unit_Instance(p_item_instance_id);
274   IF (l_unit_instance_id IS NOT NULL) THEN
275     -- Instance is in a UC: Get the MC Details
276     OPEN get_mc_dtls_csr(c_instance_id => l_unit_instance_id);
277     FETCH get_mc_dtls_csr INTO l_mc_header_id, l_mc_id, l_mc_version, l_uc_header_id;
278     CLOSE get_mc_dtls_csr;
279   END IF;
280 
281   -- Get item of instance
282   OPEN get_item_from_instance_csr(c_instance_id => p_item_instance_id);
283   FETCH get_item_from_instance_csr INTO l_inst_item_id;
284   CLOSE get_item_from_instance_csr;
285 
286   -- Get the Requirements from the Disposition List
287   Get_Disp_List_Requirements(p_route_id         => l_route_id,
288                              p_item_instance_id => p_item_instance_id,
289                              p_requirement_date => p_requirement_date,
290                              p_request_type     => p_request_type,
291                              p_unit_instance_id => l_unit_instance_id,
292                              p_inst_item_id     => l_inst_item_id,
293                              p_mc_header_id     => l_mc_header_id,
294                              p_mc_id            => l_mc_id,
295                              p_mc_version       => l_mc_version,
296                              x_disp_req_list    => l_disp_req_list);
297 
298   -- Get the Requirements from the Route
299   -- SURRKUMA :: Service Bulletin :: 07-Jun-2011
300   -- Adding parameters mc_id, mc_header_id and uc_header_id to validate position based requirements
301   Get_Route_Requirements(p_route_id         => l_route_id,
302                          p_request_type     => p_request_type,
303                          p_mc_id            => l_mc_id,
304                          p_mc_header_id     => l_mc_header_id,
305                          p_uc_header_id     => l_uc_header_id,
306                          p_visit_id         => p_visit_id,
307                          x_route_req_list   => l_route_req_list);
308 
309   -- Merge the two list of requirements
310   IF (l_disp_req_list.COUNT = 0) THEN
311     x_route_mtl_req_tbl := l_route_req_list;
312   ELSIF (l_route_req_list.COUNT = 0) THEN
313     x_route_mtl_req_tbl := l_disp_req_list;
314   ELSE
315     IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
316       FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'l_disp_req_list.COUNT = ' || l_disp_req_list.COUNT);
317       FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'l_route_req_list.COUNT = ' || l_route_req_list.COUNT);
318       FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Both lists are non-empty. Merging...');
319     END IF;
320     x_route_mtl_req_tbl := l_disp_req_list;
321     l_index := x_route_mtl_req_tbl.COUNT;
322     FOR i in l_route_req_list.FIRST .. l_route_req_list.LAST LOOP
323       l_temp_item_id := NVL(l_route_req_list(i).INVENTORY_ITEM_ID, -1);
324       l_temp_ig_id := NVL(l_route_req_list(i).ITEM_GROUP_ID, -1);
325       l_found := FALSE;
326       FOR j in l_disp_req_list.FIRST .. l_disp_req_list.LAST LOOP
327         IF ((NVL(l_disp_req_list(j).INVENTORY_ITEM_ID, -2) = l_temp_item_id) OR
328             (NVL(l_disp_req_list(j).ITEM_GROUP_ID, -2) = l_temp_ig_id)) THEN
329           -- The route requirement exists in the Disposition list also
330           l_found := TRUE;
331           EXIT;
332         END IF;
333       END LOOP;
334       IF(l_found = FALSE) THEN
335         -- Add this Route requirement to the combined list
336         IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
337           FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Adding Route requirement with index ' || i ||
338                                                                ' to the combined list.');
339         END IF;
340         l_index := l_index + 1;
341         x_route_mtl_req_tbl(l_index) := l_route_req_list(i);
342       ELSE
343         -- Duplicate: Ignore
344         IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
345           FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Route requirement with index ' || i || ' is a duplicate. Ignoring.');
346         END IF;
347       END IF;
348     END LOOP;
349   END IF;
350 
351   IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
352     FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Size of the merged list: ' || x_route_mtl_req_tbl.COUNT);
353   END IF;
354 
355   -- Get the first item for item groups if forecasting
356   IF(x_route_mtl_req_tbl.COUNT > 0 AND p_request_type = G_REQ_TYPE_FORECAST) THEN
357     FOR i in x_route_mtl_req_tbl.FIRST .. x_route_mtl_req_tbl.LAST LOOP
358       IF (x_route_mtl_req_tbl(i).INVENTORY_ITEM_ID IS NULL AND
359           x_route_mtl_req_tbl(i).ITEM_GROUP_ID IS NOT NULL) THEN
360         -- Get the highest prority item from the item group
361         OPEN get_item_group_item_csr(c_item_group_id => x_route_mtl_req_tbl(i).ITEM_GROUP_ID);
362         FETCH get_item_group_item_csr INTO x_route_mtl_req_tbl(i).INVENTORY_ITEM_ID,
363                                            x_route_mtl_req_tbl(i).INV_MASTER_ORG_ID;
364         CLOSE get_item_group_item_csr;
365         IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
366           FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'For merged requirement ' || i ||
367                                                                ', Got Item Id as ' || x_route_mtl_req_tbl(i).INVENTORY_ITEM_ID ||
368                                                                ' for item group id ' || x_route_mtl_req_tbl(i).ITEM_GROUP_ID);
369         END IF;
370       END IF;
371     END LOOP;
372   END IF;
373 
374   -- Standard call to get message count and if count is 1, get message info
375   FND_MSG_PUB.Count_And_Get
376     ( p_count => x_msg_count,
377       p_data  => x_msg_data,
378       p_encoded => fnd_api.g_false
379     );
380 
381   IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
382     FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.end', 'Exiting Procedure');
383   END IF;
384 
385 EXCEPTION
386  WHEN FND_API.G_EXC_ERROR THEN
387    x_return_status := FND_API.G_RET_STS_ERROR;
388    FND_MSG_PUB.count_and_get( p_count => x_msg_count,
389                               p_data  => x_msg_data,
390                               p_encoded => fnd_api.g_false);
391 
392  WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
393    x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
394    FND_MSG_PUB.count_and_get( p_count => x_msg_count,
395                               p_data  => x_msg_data,
396                               p_encoded => fnd_api.g_false);
397 
398  WHEN OTHERS THEN
399     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
400     IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
401        fnd_msg_pub.add_exc_msg(p_pkg_name       => G_PKG_NAME,
402                                p_procedure_name => 'Get_Route_Mtl_Req',
403                                p_error_text     => SUBSTR(SQLERRM,1,240));
404     END IF;
405     FND_MSG_PUB.count_and_get( p_count => x_msg_count,
406                                p_data  => x_msg_data,
407                                p_encoded => fnd_api.g_false);
408 
409 END Get_Route_Mtl_Req;
410 
411 --------------------------------------
412 -- End Public Procedure Definitions --
413 --------------------------------------
414 
415 -----------------------------------------
416 -- Public Function Definitions follow --
417 -----------------------------------------
418 -- Start of Comments --
419 --  Function name     : Get_Primary_UOM_Qty
420 --  Type              : Private
421 --  Function          : Private helper function to convert a quantity of an item from one
422 --                      UOM to the Primary UOM. The inputs are the item id, the quantity
423 --                      and the source UOM. The output is the quantity in the primary uom.
424 --  Pre-reqs    :
425 --  Parameters  :
426 --
427 --
428 --  Get_Primary_UOM_Qty Parameters:
429 --      p_inventory_item_id             IN      NUMBER       Required
430 --         The Id of Inventory item. If this is null, this function returns null.
431 --      p_source_uom_code               IN      VARCHAR2     Required
432 --         The code of the UOM in which the quantity is currently mentioned.
433 --         If this is null, this function returns null.
434 --      p_quantity                      IN      NUMBER       Required
435 --         The quantity of the item in the indicated UOM.
436 --         If this is null, this function returns null.
437 --
438 --  Version :
439 --      Initial Version   1.0
440 --
441 --  End of Comments.
442 
443 FUNCTION Get_Primary_UOM_Qty(p_inventory_item_id IN NUMBER,
444                              p_source_uom_code IN VARCHAR2,
445                              p_quantity IN NUMBER) RETURN NUMBER IS
446 
447   CURSOR get_primary_uom_csr IS
448     select primary_uom_code from mtl_system_items
449     where inventory_item_id = p_inventory_item_id;
450 
451   l_primary_uom VARCHAR2(10);
452   l_converted_qty NUMBER;
453   L_DEBUG_KEY    CONSTANT VARCHAR2(150) := G_LOG_PREFIX || '.Get_Primary_UOM_Qty';
454 
455 BEGIN
456   IF (p_inventory_item_id IS NULL OR p_source_uom_code IS NULL OR p_quantity IS NULL) THEN
457     RETURN NULL;
458   END IF;
459   OPEN get_primary_uom_csr;
460   FETCH get_primary_uom_csr INTO l_primary_uom;
461   IF (get_primary_uom_csr%NOTFOUND) THEN
462     CLOSE get_primary_uom_csr;
463     RETURN null;
464   END IF;
465   CLOSE get_primary_uom_csr;
466   IF(p_source_uom_code = l_primary_uom) THEN
467     RETURN p_quantity;
468   END IF;
469 
470   l_converted_qty := inv_convert.inv_um_convert(item_id => p_inventory_item_id,
471                                                 precision => 2,
472                                                 from_quantity => p_quantity,
473                                                 from_unit => p_source_uom_code,
474                                                 to_unit => l_primary_uom,
475                                                 from_name => null,
476                                                 to_name => null);
477   IF (l_converted_qty < 0) THEN
478     l_converted_qty := null;
479     IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
480       FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Could not convert from ' || p_source_uom_code ||
481                                                            ' to ' || l_primary_uom || '. Returning null quantity.');
482     END IF;
483   END IF;
484   RETURN l_converted_qty;
485 END Get_Primary_UOM_Qty;
486 
487 -- Start of Comments --
488 --  Function name     : Get_Primary_UOM
489 --  Type              : Private
490 --  Function          : Private helper function to get the Primary UOM of an item
491 --                      The inputs are the item id and the inventory org id.
492 --  Pre-reqs    :
493 --  Parameters  :
494 --
495 --
496 --  Get_Primary_UOM Parameters:
497 --      p_inventory_item_id             IN      NUMBER       Required
498 --         The Id of Inventory item. If this is null, this function returns null.
499 --      p_inventory_org_id              IN      NUMBER       Required
500 --         The inventory org id of the item. If this is null, this function returns null.
501 --
502 --  Version :
503 --      Initial Version   1.0
504 --
505 --  End of Comments.
506 
507 FUNCTION Get_Primary_UOM
508 (
509    p_inventory_item_id     IN  NUMBER,
510    p_inventory_org_id      IN  NUMBER
511 ) RETURN VARCHAR2 IS
512   CURSOR get_primary_uom_csr IS
513     select primary_uom_code from mtl_system_items
514     where inventory_item_id = p_inventory_item_id and
515           organization_id = p_inventory_org_id;
516 
517   l_primary_uom VARCHAR2(10);
518   L_DEBUG_KEY    CONSTANT VARCHAR2(150) := G_LOG_PREFIX || '.Get_Primary_UOM';
519 
520 BEGIN
521   IF (p_inventory_item_id IS NULL OR p_inventory_org_id IS NULL) THEN
522     RETURN NULL;
523   END IF;
524   OPEN get_primary_uom_csr;
525   FETCH get_primary_uom_csr INTO l_primary_uom;
526   IF (get_primary_uom_csr%NOTFOUND) THEN
527     CLOSE get_primary_uom_csr;
528     RETURN null;
529   END IF;
530   CLOSE get_primary_uom_csr;
531   RETURN l_primary_uom;
532 END Get_Primary_UOM;
533 
534 -------------------------------------
535 -- End Public Function Definitions --
536 -------------------------------------
537 
538 ----------------------------------------
539 -- Local Procedure Definitions follow --
540 ----------------------------------------
541 ----------------------------------------------------------------------
542 -- This Procedure validates the input for the Get_Route_Mtl_Req API --
543 ----------------------------------------------------------------------
544 -- Modified by surrkuma for bug# 13998921 on 26-Apr-12
545 -- Added Visit ID as a parameter for validating visit task instance.
546 PROCEDURE Validate_Mtl_Req_Input
547 (
548    p_route_id          IN         NUMBER,
549    p_mr_route_id       IN         NUMBER,
550    p_item_instance_id  IN         NUMBER,
551    p_requirement_date  IN         DATE,
552    p_request_type      IN         VARCHAR2,
553    p_visit_id          IN         NUMBER    := null,
554    x_route_id          OUT NOCOPY NUMBER) IS
555 
556   CURSOR get_route_id_csr IS
557     select route_id from ahl_mr_routes
558     where mr_route_id = p_mr_route_id;
559 
560   CURSOR validate_route_id_csr(c_route_id IN NUMBER) IS
561 -- Changes by skpathak on 06-NOV-2008 for bug-7336824
562 --    select 'x' from AHL_ROUTES_APP_V
563     select 'x' from AHL_ROUTES_B
564     where route_id = c_route_id;
565 
566   CURSOR validate_instance_id_csr IS
567     select 'x' from CSI_ITEM_INSTANCES
568     where instance_id = p_item_instance_id
569       and nvl(active_end_date, sysdate + 1) > sysdate;
570 
571 -- Added by surrkuma for bug# 13998921 on 26-Apr-12
572 -- Check the Visit tasks for the given instance in PLANNING status
573   CURSOR check_visit_tasks_status_csr IS
574     SELECT 'x' FROM ahl_visit_tasks_b
575     WHERE visit_id  = p_visit_id
576     AND instance_id = p_item_instance_id
577     AND status_code = 'PLANNING';
578 
579    l_dummy                VARCHAR2(1);
580    L_DEBUG_KEY   CONSTANT VARCHAR2(150) := G_LOG_PREFIX || '.Validate_Mtl_Req_Input';
581 
582 BEGIN
583 
584   IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
585     FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.begin', 'Entering Procedure');
586   END IF;
587 
588   -- Get the Route Id
589   IF (p_route_id IS NULL AND p_mr_route_id IS NULL) THEN
590     FND_MESSAGE.Set_Name('AHL', 'AHL_LTP_APS_ROUTE_ID_NULL');
591     FND_MSG_PUB.ADD;
592     IF (G_LEVEL_ERROR >= G_CURRENT_RUNTIME_LEVEL) THEN
593       FND_LOG.MESSAGE(G_LEVEL_ERROR, L_DEBUG_KEY, FALSE);
594     END IF;
595   ELSIF (p_route_id IS NULL) THEN
596     OPEN get_route_id_csr;
597     FETCH get_route_id_csr INTO x_route_id;
598     CLOSE get_route_id_csr;
599   ELSE
600     x_route_id := p_route_id;
601   END IF;
602 
603   -- Validate the Route Id
604   OPEN validate_route_id_csr(c_route_id => x_route_id);
605   FETCH validate_route_id_csr INTO l_dummy;
606   IF (validate_route_id_csr%NOTFOUND) THEN
607     FND_MESSAGE.Set_Name('AHL', 'AHL_LTP_APS_ROUTE_ID_INVALID');
608     FND_MESSAGE.Set_Token('ROUTE_ID', x_route_id);
609     FND_MSG_PUB.ADD;
610     IF (G_LEVEL_ERROR >= G_CURRENT_RUNTIME_LEVEL) THEN
611       FND_LOG.MESSAGE(G_LEVEL_ERROR, L_DEBUG_KEY, FALSE);
612     END IF;
613   END IF;
614   CLOSE validate_route_id_csr;
615 
616   -- Validate the Instance Id
617   IF (p_item_instance_id IS NULL) THEN
618     FND_MESSAGE.Set_Name('AHL', 'AHL_LTP_APS_INST_ID_NULL');
619     FND_MSG_PUB.ADD;
620     IF (G_LEVEL_ERROR >= G_CURRENT_RUNTIME_LEVEL) THEN
621       FND_LOG.MESSAGE(G_LEVEL_ERROR, L_DEBUG_KEY, FALSE);
622     END IF;
623   ELSE
624     OPEN check_visit_tasks_status_csr;
625     FETCH check_visit_tasks_status_csr INTO l_dummy;
626     IF (check_visit_tasks_status_csr%FOUND) THEN
627         OPEN validate_instance_id_csr;
628         FETCH validate_instance_id_csr INTO l_dummy;
629         IF (validate_instance_id_csr%NOTFOUND) THEN
630           FND_MESSAGE.Set_Name('AHL', 'AHL_LTP_APS_INST_ID_INVALID');
631           FND_MESSAGE.Set_Token('INST_ID', p_item_instance_id);
632           FND_MSG_PUB.ADD;
633           IF (G_LEVEL_ERROR >= G_CURRENT_RUNTIME_LEVEL) THEN
634             FND_LOG.MESSAGE(G_LEVEL_ERROR, L_DEBUG_KEY, FALSE);
635           END IF;
636         END IF;
637         CLOSE validate_instance_id_csr;
638     END IF;
639     CLOSE check_visit_tasks_status_csr;
640   END IF;
641 
642   -- Validate the Request Type
643   IF (p_request_type IS NULL) THEN
644     FND_MESSAGE.Set_Name('AHL', 'AHL_LTP_APS_REQ_TYPE_NULL');
645     FND_MSG_PUB.ADD;
646     IF (G_LEVEL_ERROR >= G_CURRENT_RUNTIME_LEVEL) THEN
647       FND_LOG.MESSAGE(G_LEVEL_ERROR, L_DEBUG_KEY, FALSE);
648     END IF;
649   ELSIF (p_request_type NOT IN (G_REQ_TYPE_FORECAST, G_REQ_TYPE_PLANNED)) THEN
650     FND_MESSAGE.Set_Name('AHL', 'AHL_LTP_APS_REQ_TYPE_INVALID');
651     FND_MESSAGE.Set_Token('REQ_TYPE', p_request_type);
652     FND_MSG_PUB.ADD;
653     IF (G_LEVEL_ERROR >= G_CURRENT_RUNTIME_LEVEL) THEN
654       FND_LOG.MESSAGE(G_LEVEL_ERROR, L_DEBUG_KEY, FALSE);
655     END IF;
656   END IF;
657 
658   -- Validate the Requirement Date
659   IF (p_requirement_date IS NULL) THEN
660     FND_MESSAGE.Set_Name('AHL', 'AHL_LTP_APS_REQ_DATE_NULL');
661     FND_MSG_PUB.ADD;
662     IF (G_LEVEL_ERROR >= G_CURRENT_RUNTIME_LEVEL) THEN
663       FND_LOG.MESSAGE(G_LEVEL_ERROR, L_DEBUG_KEY, FALSE);
664     END IF;
665     -- SKPATHAK :: Bug 8343599 :: 13-APR-2009
666     -- Removing the check to allow creation of Material Requirements in the past.
667     /**
668   ELSIF (TRUNC(p_requirement_date) < TRUNC(SYSDATE)) THEN
669     FND_MESSAGE.Set_Name('AHL', 'AHL_LTP_APS_REQ_DATE_PAST');
670     FND_MESSAGE.Set_Token('REQ_DATE', p_requirement_date);
671     FND_MSG_PUB.ADD;
672     IF (G_LEVEL_ERROR >= G_CURRENT_RUNTIME_LEVEL) THEN
673       FND_LOG.MESSAGE(G_LEVEL_ERROR, L_DEBUG_KEY, FALSE);
674     END IF;
675     **/
676   END IF;
677 
678   IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
679     FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.end', 'Exiting Procedure');
680   END IF;
681 
682 END Validate_Mtl_Req_Input;
683 
684 --------------------------------------------------------------------
685 -- This Procedure gets the requirements from the Disposition List --
686 --------------------------------------------------------------------
687 PROCEDURE Get_Disp_List_Requirements
688 (
689    p_route_id          IN         NUMBER,
690    p_item_instance_id  IN         NUMBER,
691    p_requirement_date  IN         DATE,
692    p_request_type      IN         VARCHAR2,
693    p_unit_instance_id  IN         NUMBER,
694    p_inst_item_id      IN         NUMBER,
695    p_mc_header_id      IN         NUMBER,
696    p_mc_id             IN         NUMBER,
697    p_mc_version        IN         NUMBER,
698    x_disp_req_list     OUT NOCOPY Route_Mtl_Req_Tbl_Type) IS
699 
700   CURSOR get_mc_route_eff_id_csr IS
701     SELECT RE.route_effectivity_id
702     FROM AHL_ROUTE_EFFECTIVITIES RE
703     WHERE RE.route_id = p_route_id
704      AND (RE.mc_header_id = NVL(p_mc_header_id, -1)  -- Match MC Header Id first
705           OR (RE.mc_id = NVL(p_mc_id, -1)            -- Match MC Id next
706               AND RE.mc_header_id IS NULL   -- Added on 10/28/03 since Version specific also has stores the MC Id
707               AND NOT EXISTS (SELECT 'x' FROM AHL_ROUTE_EFFECTIVITIES RE1
708                               WHERE RE1.route_id = p_route_id
709                                 AND RE1.mc_header_id = NVL(p_mc_header_id, -1))
710              )
711          );
712 
713   CURSOR get_item_route_eff_id_csr IS
714     SELECT RE.route_effectivity_id
715     FROM AHL_ROUTE_EFFECTIVITIES RE
716     WHERE RE.route_id = p_route_id
717       AND RE.inventory_item_id = p_inst_item_id;  -- Match the inventory item id
718 
719   CURSOR get_disp_req_dtls_csr(c_mc_route_eff_id   IN NUMBER,
720                                c_item_route_eff_id IN NUMBER) IS
721     SELECT ROM.RT_OPER_MATERIAL_ID,
722            ROM.INVENTORY_ITEM_ID,
723            ROM.INVENTORY_ORG_ID,
724            ROM.UOM_CODE,
725            ROM.QUANTITY,
726            AHL_LTP_MTL_REQ_PVT.Get_Primary_UOM_Qty(INVENTORY_ITEM_ID, UOM_CODE, QUANTITY) AS PRIMARY_QUANTITY,
727            AHL_LTP_MTL_REQ_PVT.Get_Primary_UOM(INVENTORY_ITEM_ID, INVENTORY_ORG_ID) AS PRIMARY_UOM_CODE,
728            ITEM_GROUP_ID,
729            ITEM_COMP_DETAIL_ID,
730            POSITION_PATH_ID,
731            PP.PATH_POS_COMMON_ID,
732            PP.VER_SPEC_SCORE
733     FROM AHL_RT_OPER_MATERIALS ROM, AHL_MC_PATH_POSITIONS PP
734     WHERE OBJECT_ID in (NVL(c_mc_route_eff_id, -1), NVL(c_item_route_eff_id, -1)) AND
735           ROM.POSITION_PATH_ID = PP.PATH_POSITION_ID (+) AND
736           ASSOCIATION_TYPE_CODE = G_ASSOC_TYPE_DISPOSITION AND
737           ((REPLACE_PERCENT = 100 AND p_request_type = G_REQ_TYPE_FORECAST) OR
738            (p_request_type = G_REQ_TYPE_PLANNED)
739           )
740     ORDER BY PATH_POS_COMMON_ID, VER_SPEC_SCORE DESC;
741 
742   CURSOR get_item_comp_dtls_csr(c_item_comp_detail_id IN NUMBER,
743                                 c_quantity            IN NUMBER,
744                                 c_uom                 IN VARCHAR2) IS
745     SELECT ICD.inventory_item_id, ICD.inventory_master_org_id, ICD.item_group_id,
746            DECODE(ICD.inventory_item_id, null, c_quantity, AHL_LTP_MTL_REQ_PVT.Get_Primary_UOM_Qty(ICD.inventory_item_id, c_uom, c_quantity)) QUANTITY,
747            DECODE(ICD.inventory_item_id, null, c_uom, AHL_LTP_MTL_REQ_PVT.Get_Primary_UOM(ICD.inventory_item_id, inventory_master_org_id)) UOM
748     FROM AHL_ITEM_COMP_DETAILS ICD
749     WHERE ITEM_COMP_DETAIL_ID = c_item_comp_detail_id;
750 
751    l_mc_route_effectivity_id    NUMBER;
752    l_item_route_effectivity_id  NUMBER;
753    l_index                      NUMBER;
754    l_last_common_id             NUMBER := -1;
755    l_prior_count                NUMBER;
756    L_DEBUG_KEY   CONSTANT       VARCHAR2(150) := G_LOG_PREFIX || '.Get_Disp_List_Requirements';
757 
758 BEGIN
759 
760   IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
761     FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.begin', 'Entering Procedure');
762   END IF;
763 
764   -- Get the Route Effectivity
765   OPEN get_mc_route_eff_id_csr;
766   FETCH get_mc_route_eff_id_csr INTO l_mc_route_effectivity_id;
767   IF (get_mc_route_eff_id_csr%NOTFOUND) THEN
768     l_mc_route_effectivity_id := -1;
769   END IF;
770   CLOSE get_mc_route_eff_id_csr;
771 
772   OPEN get_item_route_eff_id_csr;
773   FETCH get_item_route_eff_id_csr INTO l_item_route_effectivity_id;
774   IF (get_item_route_eff_id_csr%NOTFOUND) THEN
775     l_item_route_effectivity_id := -1;
776   END IF;
777   CLOSE get_item_route_eff_id_csr;
778 
779   IF(l_item_route_effectivity_id = -1 AND l_mc_route_effectivity_id = -1) THEN
780     -- No Disposition List available
781     IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
782       FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'No disposition list found for MC Header Id: ' || p_mc_header_id
783                                                             || ', MC Id: ' || p_mc_id
784                                                             || ', Item Id: ' || p_inst_item_id);
785     END IF;
786     RETURN;
787   END IF;
788 
789   l_index := 0;
790   FOR l_disp_req_rec IN get_disp_req_dtls_csr(c_mc_route_eff_id   => l_mc_route_effectivity_id,
791                                               c_item_route_eff_id => l_item_route_effectivity_id) LOOP
792     l_index := l_index + 1;
793     IF ((l_disp_req_rec.INVENTORY_ITEM_ID IS NOT NULL) AND (l_disp_req_rec.ITEM_COMP_DETAIL_ID IS NULL)) THEN
794       -- Simple Item requirement with no reference to any Item composition
795       x_disp_req_list(l_index).RT_OPER_MATERIAL_ID := l_disp_req_rec.RT_OPER_MATERIAL_ID;
796       x_disp_req_list(l_index).INVENTORY_ITEM_ID := l_disp_req_rec.INVENTORY_ITEM_ID;
797       x_disp_req_list(l_index).INV_MASTER_ORG_ID := l_disp_req_rec.INVENTORY_ORG_ID;
798       -- Quantity in Item's Primary UOM
799       x_disp_req_list(l_index).QUANTITY := l_disp_req_rec.PRIMARY_QUANTITY;
800       x_disp_req_list(l_index).UOM_CODE := l_disp_req_rec.PRIMARY_UOM_CODE;
801       IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
802         FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Requirement ' || l_index || ': RT_OPER_MATERIAL_ID = ' || l_disp_req_rec.RT_OPER_MATERIAL_ID ||
803                                                              ', INVENTORY_ITEM_ID = ' || l_disp_req_rec.INVENTORY_ITEM_ID ||
804                                                              ', INV_MASTER_ORG_ID = ' || l_disp_req_rec.INVENTORY_ORG_ID ||
805                                                              ', QUANTITY = ' || l_disp_req_rec.PRIMARY_QUANTITY ||
806                                                              ', UOM_CODE = ' || l_disp_req_rec.PRIMARY_UOM_CODE);
807       END IF;
808     ELSIF ((l_disp_req_rec.ITEM_GROUP_ID IS NOT NULL) AND (l_disp_req_rec.ITEM_COMP_DETAIL_ID IS NULL)) THEN
809       -- Simple Item Group requirement with no reference to any Item composition
810       x_disp_req_list(l_index).RT_OPER_MATERIAL_ID := l_disp_req_rec.RT_OPER_MATERIAL_ID;
811       x_disp_req_list(l_index).ITEM_GROUP_ID := l_disp_req_rec.ITEM_GROUP_ID;
812       x_disp_req_list(l_index).QUANTITY := l_disp_req_rec.QUANTITY;
813       x_disp_req_list(l_index).UOM_CODE := l_disp_req_rec.UOM_CODE;
814       IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
815         FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Requirement ' || l_index || ': RT_OPER_MATERIAL_ID = ' || l_disp_req_rec.RT_OPER_MATERIAL_ID ||
816                                                              ', ITEM_GROUP_ID = ' || l_disp_req_rec.ITEM_GROUP_ID ||
817                                                              ', QUANTITY = ' || l_disp_req_rec.QUANTITY ||
818                                                              ', UOM_CODE = ' || l_disp_req_rec.UOM_CODE);
819       END IF;
820     ELSIF (l_disp_req_rec.ITEM_COMP_DETAIL_ID IS NOT NULL) THEN
821       -- Item Composition requirement
822       x_disp_req_list(l_index).RT_OPER_MATERIAL_ID := l_disp_req_rec.RT_OPER_MATERIAL_ID;
823       x_disp_req_list(l_index).ITEM_COMP_DETAIL_ID := l_disp_req_rec.ITEM_COMP_DETAIL_ID;
824       -- Get the details from the Item Composition Details table
825       OPEN get_item_comp_dtls_csr(c_item_comp_detail_id => l_disp_req_rec.ITEM_COMP_DETAIL_ID,
826                                   c_quantity            => l_disp_req_rec.QUANTITY,
827                                   c_uom                 => l_disp_req_rec.UOM_CODE);
828       FETCH get_item_comp_dtls_csr INTO x_disp_req_list(l_index).INVENTORY_ITEM_ID,
829                                         x_disp_req_list(l_index).INV_MASTER_ORG_ID,
830                                         x_disp_req_list(l_index).ITEM_GROUP_ID,
831                                         x_disp_req_list(l_index).QUANTITY,
832                                         x_disp_req_list(l_index).UOM_CODE;
833       CLOSE get_item_comp_dtls_csr;
834       IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
835         FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Requirement ' || l_index || ': RT_OPER_MATERIAL_ID = ' || l_disp_req_rec.RT_OPER_MATERIAL_ID ||
836                                                              ', ITEM_COMP_DETAIL_ID = ' || l_disp_req_rec.ITEM_COMP_DETAIL_ID ||
837                                                              ', INVENTORY_ITEM_ID = ' || x_disp_req_list(l_index).INVENTORY_ITEM_ID ||
838                                                              ', INV_MASTER_ORG_ID = ' || x_disp_req_list(l_index).INV_MASTER_ORG_ID ||
839                                                              ', ITEM_GROUP_ID = ' || x_disp_req_list(l_index).ITEM_GROUP_ID ||
840                                                              ', QUANTITY = ' || x_disp_req_list(l_index).QUANTITY ||
841                                                              ', UOM_CODE = ' || x_disp_req_list(l_index).UOM_CODE);
842       END IF;
843     ELSE
844       -- Requirement with only Position path reference
845       IF (p_mc_header_id IS NULL) THEN
846         -- Ignore this Position Path specific requirement since the current instance
847         -- is not a UC unit (is not of any MC type)
848         IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
849           FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Ignoring Disp. List Requirement with Position Path Id ' || l_disp_req_rec.POSITION_PATH_ID);
850         END IF;
851       ELSE
852         -- Get the Position Path requirement if applicable
853         IF (l_disp_req_rec.PATH_POS_COMMON_ID <> l_last_common_id) THEN
854           -- Consider this Position Path since it is has a new common id
855           l_prior_count := x_disp_req_list.COUNT;
856           Get_Pos_Path_Requirement(p_position_path_id => l_disp_req_rec.POSITION_PATH_ID,
857                                    p_requirement_date => p_requirement_date,
858                                    p_unit_instance_id => p_unit_instance_id,
859                                    p_mc_header_id     => p_mc_header_id,
860                                    p_mc_id            => p_mc_id,
861                                    p_mc_version       => p_mc_version,
862                                    p_rt_oper_mtl_id   => l_disp_req_rec.RT_OPER_MATERIAL_ID,
863                                    p_quantity         => l_disp_req_rec.QUANTITY,
864                                    p_uom              => l_disp_req_rec.UOM_CODE,
865                                    p_x_disp_req_list  => x_disp_req_list);
866           IF (x_disp_req_list.COUNT > l_prior_count) THEN
867             -- The last Position Path requirement was valid and added.
868             -- Set the l_last_common_id so that subsequent records
869             -- with the same common id (but lower score) can be ignored.
870             l_last_common_id := l_disp_req_rec.PATH_POS_COMMON_ID;
871           ELSE
872             -- Not applicable: Hence not added: Continue to the next lower score.
873             null;
874           END IF;  -- if count has increased
875         ELSE
876           -- Common id is same as last added, but lower score: ignore this record
877           null;
878         END IF;  -- Common Id is different
879       END IF;
880       l_index := x_disp_req_list.COUNT;  -- Set output table index to always point to the last added record.
881     END IF;
882   END LOOP;
883   IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
884     FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Total number of disposition requirements: ' || x_disp_req_list.COUNT);
885   END IF;
886 
887   IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
888     FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.end', 'Exiting Procedure');
889   END IF;
890 
891 END Get_Disp_List_Requirements;
892 
893 -------------------------------------------------------
894 -- This Procedure gets the Position Path Requirement --
895 -------------------------------------------------------
896 PROCEDURE Get_Pos_Path_Requirement
897 (
898    p_position_path_id  IN         NUMBER,
899    p_requirement_date  IN         DATE,
900    p_unit_instance_id  IN         NUMBER,
901    p_mc_header_id      IN         NUMBER,
902    p_mc_id             IN         NUMBER,
903    p_mc_version        IN         NUMBER,
904    p_rt_oper_mtl_id    IN         NUMBER,
905    p_quantity          IN         NUMBER,
906    p_uom               IN         VARCHAR2,
907    p_x_disp_req_list   IN OUT NOCOPY Route_Mtl_Req_Tbl_Type) IS
908 
909   CURSOR get_sub_unit_mc_csr(c_pos_instance_id IN NUMBER) IS
910     SELECT master_config_id
911     FROM AHL_UNIT_CONFIG_HEADERS
912     WHERE CSI_ITEM_INSTANCE_ID = c_pos_instance_id;
913 
914   CURSOR get_item_grp_for_mc_csr(c_mc_header_id IN NUMBER) IS
915     SELECT item_group_id
916     FROM AHL_MC_RELATIONSHIPS
917     WHERE mc_header_id = c_mc_header_id
918       AND parent_relationship_id is null;
919 
920   CURSOR get_sub_mc_for_pos_csr(c_position_id IN NUMBER) IS
921     SELECT CR.mc_header_id
922     FROM AHL_MC_CONFIG_RELATIONS CR, AHL_MC_HEADERS_B MC
923     WHERE CR.relationship_id = c_position_id
924       AND MC.mc_header_id = CR.mc_header_id
925     ORDER BY MC.name;
926 
927    l_position_id           NUMBER;
928    l_pos_item_group_id     NUMBER;
929    l_pos_instance_id       NUMBER;
930    l_sub_unit_mc           NUMBER;
931    l_next_index            NUMBER := p_x_disp_req_list.COUNT + 1;
932    l_valid_flag            VARCHAR2(1);
933    L_DEBUG_KEY   CONSTANT  VARCHAR2(150) := G_LOG_PREFIX || '.Get_Pos_Path_Requirement';
934 
935 BEGIN
936 
937   IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
938     FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.begin', 'Entering Procedure');
939   END IF;
940 
941   -- First validate the Position Path and get the Position Details
942   IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
943     FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Calling Validate_Path_Position with ' ||
944                                                          'p_position_path_id = ' || p_position_path_id ||
945                                                          ', p_unit_instance_id = ' || p_unit_instance_id ||
946                                                          ', p_requirement_date = ' || p_requirement_date);
947   END IF;
948   Validate_Path_Position(p_path_position_id => p_position_path_id,
949                          p_unit_instance_id => p_unit_instance_id,
950                          p_requirement_date => p_requirement_date,
951                          x_valid_flag       => l_valid_flag,
952                          x_relationship_id  => l_position_id,
953                          x_item_group_id    => l_pos_item_group_id,
954                          x_pos_instance_id  => l_pos_instance_id);
955 
956   IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
957     FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Validate_Path_Position returned ' ||
958                                                          'x_valid_flag = ' || l_valid_flag ||
959                                                          ', x_relationship_id = ' || l_position_id ||
960                                                          ', x_item_group_id = ' || l_pos_item_group_id ||
961                                                          ', x_pos_instance_id = ' || l_pos_instance_id);
962   END IF;
963 
964   IF (l_valid_flag = FND_API.G_FALSE) THEN
965     -- Don't include the requirement if the position path is not valid
966     RETURN;
967   END IF;
968 
969   IF (l_pos_instance_id IS NULL) THEN
970     -- The position is empty
971     -- If the position has an item group associated, copy that as the requirement
972     IF (l_pos_item_group_id IS NOT NULL) THEN
973       IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
974         FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Position ' || l_position_id || ' is empty and has item group ' ||
975                                                               l_pos_item_group_id || ' associated with it.');
976       END IF;
977       p_x_disp_req_list(l_next_index).ITEM_GROUP_ID := l_pos_item_group_id;
978     ELSE
979       -- No Item group for the empty position: Pick one Sub config for the position
980       OPEN get_sub_mc_for_pos_csr(c_position_id => l_position_id);
981       FETCH get_sub_mc_for_pos_csr INTO l_sub_unit_mc;
982       CLOSE get_sub_mc_for_pos_csr;
983       -- Get the Item group for the root node of the chosen Sub MC
984       IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
985         FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Chosen Sub MC Header Id ' || l_sub_unit_mc ||
986                                                              ' for empty position with id ' || l_position_id);
987       END IF;
988       OPEN get_item_grp_for_mc_csr(c_mc_header_id => l_sub_unit_mc);
989       FETCH get_item_grp_for_mc_csr INTO p_x_disp_req_list(l_next_index).ITEM_GROUP_ID;
990       CLOSE get_item_grp_for_mc_csr;
991     END IF;
992   ELSE
993     -- The position is not empty
994     -- Check if the position corresponds to the root node
995     IF (l_pos_instance_id <> p_unit_instance_id) THEN
996       -- Not root node: Check if a sub-unit is installed in the position
997       OPEN get_sub_unit_mc_csr(c_pos_instance_id => l_pos_instance_id);
998       FETCH get_sub_unit_mc_csr INTO l_sub_unit_mc;
999       IF(get_sub_unit_mc_csr%FOUND) THEN
1000         -- A sub unit (UC) is installed in the position
1001         IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
1002           FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Sub unit with Sub MC Header Id ' || l_sub_unit_mc ||
1003                                                                ' installed at position with id ' || l_position_id);
1004         END IF;
1005         -- Get the Item group for the root node of the Sub unit's MC
1006         OPEN get_item_grp_for_mc_csr(c_mc_header_id => l_sub_unit_mc);
1007         FETCH get_item_grp_for_mc_csr INTO p_x_disp_req_list(l_next_index).ITEM_GROUP_ID;
1008         CLOSE get_item_grp_for_mc_csr;
1009       ELSE
1010         -- An instance (not a sub unit) is installed in the position
1011         -- Add this position's item group as requirement to the list
1012         IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
1013             FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Simple instance with id ' || l_pos_instance_id ||
1014                                                                  ' installed at position with id ' || l_position_id);
1015         END IF;
1016         p_x_disp_req_list(l_next_index).ITEM_GROUP_ID := l_pos_item_group_id;
1017       END IF;  -- Sub unit or instance
1018       CLOSE get_sub_unit_mc_csr;
1019     ELSE
1020       -- Root Node
1021       -- Add the item group requirement to the list
1022       IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
1023         FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Position Id ' || l_position_id || ' corresponds to the root node.');
1024       END IF;
1025       p_x_disp_req_list(l_next_index).ITEM_GROUP_ID := l_pos_item_group_id;
1026     END IF;  -- Root node or not
1027   END IF;  -- Position is empty or not
1028 
1029   -- Copy the remaining attributes
1030   p_x_disp_req_list(l_next_index).RT_OPER_MATERIAL_ID := p_rt_oper_mtl_id;
1031   p_x_disp_req_list(l_next_index).POSITION_PATH_ID := p_position_path_id;
1032   p_x_disp_req_list(l_next_index).RELATIONSHIP_ID := l_position_id;
1033   p_x_disp_req_list(l_next_index).QUANTITY := p_quantity;
1034   p_x_disp_req_list(l_next_index).UOM_CODE := p_uom;
1035   IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
1036     FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Requirement ' || l_next_index || ': RT_OPER_MATERIAL_ID = ' || p_rt_oper_mtl_id ||
1037                                                          ', ITEM_GROUP_ID = ' || p_x_disp_req_list(l_next_index).ITEM_GROUP_ID ||
1038                                                          ', POSITION_PATH_ID = ' || p_position_path_id ||
1039                                                          ', RELATIONSHIP_ID = ' || l_position_id ||
1040                                                          ', QUANTITY = ' || p_quantity ||
1041                                                          ', UOM_CODE = ' || p_uom);
1042   END IF;
1043 
1044   IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
1045     FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.end', 'Exiting Procedure');
1046   END IF;
1047 
1048 END Get_Pos_Path_Requirement;
1049 
1050 -- Modified by surrkuma for Service Bulletin, 07-Jun-2011
1051 -- Added the parameters MC_ID, MC_HEADER_ID, UC_HEADER_ID and VISIT_ID
1052 ------------------------------------------------------------------------
1053 -- This Procedure gets the requirements from the Route (or Operation) --
1054 ------------------------------------------------------------------------
1055 PROCEDURE Get_Route_Requirements
1056 (
1057    p_route_id          IN         NUMBER,
1058    p_request_type      IN         VARCHAR2,
1059    p_mc_id             IN         NUMBER,
1060    p_mc_header_id      IN         NUMBER,
1061    p_uc_header_id      IN         NUMBER,
1062    p_visit_id          IN         NUMBER,
1063    x_route_req_list    OUT NOCOPY Route_Mtl_Req_Tbl_Type) IS
1064 
1065   -- SURRKUMA :: Service Bulletin :: 07-Jun-2011
1066   -- Modified the cursor to fetch details required for position level requirements
1067   -- like MC_ID, POSITION_KEY, QUANTITY and UOM_CODE from AHL_RT_OPER_MATERIALS table.
1068   -- NOTE: The same modifications are done for the rest of the cursors too, listing the cursor names.
1069   --        get_op_level_reqs_forecast_csr, get_op_level_reqs_planned_csr and l_op_requirement_neither_csr
1070   CURSOR get_route_level_reqs_csr IS
1071     SELECT ROM.RT_OPER_MATERIAL_ID,
1072            NULL AS ROUTE_OPERATION_ID,
1073            ROM.INVENTORY_ITEM_ID,
1074            ROM.INVENTORY_ORG_ID,
1075            ROM.MC_ID,
1076            ROM.POSITION_KEY,
1077            ROM.QUANTITY,
1078            ROM.UOM_CODE,
1079            AHL_LTP_MTL_REQ_PVT.Get_Primary_UOM_Qty(INVENTORY_ITEM_ID, UOM_CODE, QUANTITY) AS PRIMARY_QUANTITY,
1080            AHL_LTP_MTL_REQ_PVT.Get_Primary_UOM(INVENTORY_ITEM_ID, INVENTORY_ORG_ID) AS PRIMARY_UOM_CODE,
1081            ROM.ITEM_GROUP_ID
1082     FROM AHL_RT_OPER_MATERIALS ROM
1083     WHERE OBJECT_ID = p_route_id
1084     AND ASSOCIATION_TYPE_CODE = G_ASSOC_TYPE_ROUTE;
1085 
1086 -- AnRaj : Start for fixing perf bug 4919527
1087 /*
1088   CURSOR get_op_level_reqs_csr IS
1089     --SELECT NULL AS RT_OPER_MATERIAL_ID,
1090            --NULL AS ROUTE_OPERATION_ID,
1091     -- support for Oracle 8
1092     SELECT TO_NUMBER(NULL) AS RT_OPER_MATERIAL_ID,
1093            TO_NUMBER(NULL) AS ROUTE_OPERATION_ID,
1094            INVENTORY_ITEM_ID,
1095            INVENTORY_ORG_ID,
1096            -- Aggregate item quantities across operations when forecasting
1097            SUM(AHL_LTP_MTL_REQ_PVT.Get_Primary_UOM_Qty(INVENTORY_ITEM_ID, UOM_CODE, QUANTITY)) AS QUANTITY, --Total Primary Qty
1098            AHL_LTP_MTL_REQ_PVT.Get_Primary_UOM(INVENTORY_ITEM_ID, INVENTORY_ORG_ID) AS UOM_CODE,
1099            -- support for Oracle 8
1100            --NULL AS ITEM_GROUP_ID
1101            TO_NUMBER(NULL) AS ITEM_GROUP_ID
1102     FROM AHL_RT_OPER_MATERIALS ROM
1103     WHERE OBJECT_ID in (SELECT RO.operation_id
1104                         FROM ahl_operations_vl O, ahl_route_operations RO
1105                         WHERE O.operation_id = RO.operation_id and
1106                               RO.route_id = p_route_id and
1107                               O.revision_status_code = 'COMPLETE' and
1108                               O.revision_number in (SELECT max(revision_number)
1109                                                     FROM ahl_operations_b_kfv
1110                                                     WHERE concatenated_segments =
1111                                                       O.concatenated_segments and
1112                                                       trunc(sysdate) between
1113                                                       trunc(start_date_active) and
1114                                                       trunc(NVL(end_date_active,SYSDATE+1)))
1115                        )
1116       AND ASSOCIATION_TYPE_CODE = G_ASSOC_TYPE_OPERATION
1117       AND INVENTORY_ITEM_ID IS NOT NULL
1118       AND p_request_type = G_REQ_TYPE_FORECAST
1119     GROUP BY INVENTORY_ITEM_ID, INVENTORY_ORG_ID
1120     UNION
1121     -- Don't aggregate for Operation items when Firm Planning
1122     SELECT RT_OPER_MATERIAL_ID,
1123            OBJECT_ID AS ROUTE_OPERATION_ID,
1124            INVENTORY_ITEM_ID,
1125            INVENTORY_ORG_ID,
1126            AHL_LTP_MTL_REQ_PVT.Get_Primary_UOM_Qty(INVENTORY_ITEM_ID, UOM_CODE, QUANTITY) AS QUANTITY, -- Primary Qty
1127            AHL_LTP_MTL_REQ_PVT.Get_Primary_UOM(INVENTORY_ITEM_ID, INVENTORY_ORG_ID) AS UOM_CODE,
1128            --NULL AS ITEM_GROUP_ID
1129            -- support for Oracle 8
1130            TO_NUMBER(NULL) AS ITEM_GROUP_ID
1131     FROM AHL_RT_OPER_MATERIALS ROM
1132     WHERE OBJECT_ID in (SELECT RO.operation_id
1133                         FROM ahl_operations_vl O, ahl_route_operations RO
1134                         WHERE O.operation_id = RO.operation_id and
1135                               RO.route_id = p_route_id and
1136                               O.revision_status_code = 'COMPLETE' and
1137                               O.revision_number in (SELECT max(revision_number)
1138                                                     FROM ahl_operations_b_kfv
1139                                                     WHERE concatenated_segments =
1140                                                       O.concatenated_segments and
1141                                                       trunc(sysdate) between
1142                                                       trunc(start_date_active) and
1143                                                       trunc(NVL(end_date_active,SYSDATE+1)))
1144                        )
1145       AND ASSOCIATION_TYPE_CODE = G_ASSOC_TYPE_OPERATION
1146       AND INVENTORY_ITEM_ID IS NOT NULL
1147       AND p_request_type = G_REQ_TYPE_PLANNED
1148     UNION
1149     -- Item Group: No need to aggregate or convert to Primary UOM
1150     SELECT RT_OPER_MATERIAL_ID,
1151            OBJECT_ID AS ROUTE_OPERATION_ID,
1152            --NULL AS INVENTORY_ITEM_ID,
1153            --NULL AS INVENTORY_ORG_ID,
1154            -- support for Oracle 8
1155            TO_NUMBER(NULL) AS INVENTORY_ITEM_ID,
1156            TO_NUMBER(NULL) AS INVENTORY_ORG_ID,
1157            QUANTITY,
1158            UOM_CODE,
1159            ITEM_GROUP_ID
1160     FROM AHL_RT_OPER_MATERIALS ROM
1161     WHERE OBJECT_ID in (SELECT RO.operation_id
1162                         FROM ahl_operations_vl O, ahl_route_operations RO
1163                         WHERE O.operation_id = RO.operation_id and
1164                               RO.route_id = p_route_id and
1165                               O.revision_status_code = 'COMPLETE' and
1166                               O.revision_number in (SELECT max(revision_number)
1167                                                     FROM ahl_operations_b_kfv
1168                                                     WHERE concatenated_segments =
1169                                                       O.concatenated_segments and
1170                                                       trunc(sysdate) between
1171                                                       trunc(start_date_active) and
1172                                                       trunc(NVL(end_date_active,SYSDATE+1)))
1173                        )
1174       AND ASSOCIATION_TYPE_CODE = G_ASSOC_TYPE_OPERATION
1175       AND INVENTORY_ITEM_ID IS NULL;*/
1176 
1177 CURSOR get_op_level_reqs_forecast_csr IS
1178    SELECT   TO_NUMBER(NULL) AS RT_OPER_MATERIAL_ID,
1179             TO_NUMBER(NULL) AS ROUTE_OPERATION_ID,
1180             INVENTORY_ITEM_ID,
1181             INVENTORY_ORG_ID,
1182             TO_NUMBER(NULL) AS MC_ID,
1183             TO_NUMBER(NULL) AS POSITION_KEY,
1184             TO_NUMBER(NULL) AS QUANTITY,
1185             NULL AS UOM_CODE,
1186             -- Aggregate item quantities across operations when forecasting
1187             SUM(AHL_LTP_MTL_REQ_PVT.Get_Primary_UOM_Qty(INVENTORY_ITEM_ID, UOM_CODE, QUANTITY)) AS PRIMARY_QUANTITY, /*Total Primary Qty */
1188             AHL_LTP_MTL_REQ_PVT.Get_Primary_UOM(INVENTORY_ITEM_ID, INVENTORY_ORG_ID) AS PRIMARY_UOM_CODE,
1189             TO_NUMBER(NULL) AS ITEM_GROUP_ID
1190    FROM  AHL_RT_OPER_MATERIALS ROM
1191    WHERE OBJECT_ID in (    SELECT RO.operation_id
1192                            FROM AHL_OPERATIONS_B_KFV O, ahl_route_operations RO
1193                            WHERE O.operation_id = RO.operation_id and
1194                                  RO.route_id = p_route_id and
1195                                  O.revision_status_code = 'COMPLETE' and
1196                                  O.revision_number in (  SELECT max(revision_number)
1197                                                          FROM ahl_operations_b_kfv
1198                                                          WHERE concatenated_segments = O.concatenated_segments
1199                                                          -- manisaga : Bug# 9726667 : 22-Jun-2010
1200                                                          -- added the below condition to fetch the latest revision of
1201                                                          -- operations with only 'complete' status
1202                                                          and revision_status_code = 'COMPLETE'
1203                                                          and   trunc(sysdate) between
1204                                                                trunc(start_date_active) and
1205                                                                trunc(NVL(end_date_active,SYSDATE+1)))
1206                        )
1207    AND   ASSOCIATION_TYPE_CODE = G_ASSOC_TYPE_OPERATION
1208    AND   INVENTORY_ITEM_ID IS NOT NULL
1209    GROUP BY INVENTORY_ITEM_ID, INVENTORY_ORG_ID
1210    UNION
1211    SELECT RT_OPER_MATERIAL_ID,
1212            OBJECT_ID AS ROUTE_OPERATION_ID,
1213            TO_NUMBER(NULL) AS INVENTORY_ITEM_ID,
1214            TO_NUMBER(NULL) AS INVENTORY_ORG_ID,
1215            MC_ID,
1216            POSITION_KEY,
1217            QUANTITY,
1218            UOM_CODE,
1219            QUANTITY AS PRIMARY_QUANTITY,
1220            UOM_CODE AS PRIMARY_UOM_CODE,
1221            ITEM_GROUP_ID
1222    FROM AHL_RT_OPER_MATERIALS ROM
1223    WHERE OBJECT_ID in ( SELECT RO.operation_id
1224                         FROM AHL_OPERATIONS_B_KFV O, ahl_route_operations RO
1225                         WHERE O.operation_id = RO.operation_id and
1226                               RO.route_id = p_route_id and
1227                               O.revision_status_code = 'COMPLETE' and
1228                               O.revision_number in (SELECT max(revision_number)
1229                                                     FROM ahl_operations_b_kfv
1230                                                     WHERE concatenated_segments = O.concatenated_segments
1231                                                     -- manisaga : Bug# 9726667 : 22-Jun-2010
1232                                                     and revision_status_code = 'COMPLETE'
1233                                                     and
1234                                                       trunc(sysdate) between
1235                                                       trunc(start_date_active) and
1236                                                       trunc(NVL(end_date_active,SYSDATE+1)))
1237                        )
1238       AND ASSOCIATION_TYPE_CODE = G_ASSOC_TYPE_OPERATION
1239       AND INVENTORY_ITEM_ID IS NULL;
1240 
1241 CURSOR get_op_level_reqs_planned_csr IS
1242    SELECT   RT_OPER_MATERIAL_ID,
1243             OBJECT_ID AS ROUTE_OPERATION_ID,
1244             INVENTORY_ITEM_ID,
1245             INVENTORY_ORG_ID,
1246             MC_ID,
1247             POSITION_KEY,
1248             QUANTITY,
1249             UOM_CODE,
1250             AHL_LTP_MTL_REQ_PVT.Get_Primary_UOM_Qty(INVENTORY_ITEM_ID, UOM_CODE, QUANTITY) AS PRIMARY_QUANTITY, /* Primary Qty */
1251             AHL_LTP_MTL_REQ_PVT.Get_Primary_UOM(INVENTORY_ITEM_ID, INVENTORY_ORG_ID) AS PRIMARY_UOM_CODE,
1252             TO_NUMBER(NULL) AS ITEM_GROUP_ID
1253    FROM     AHL_RT_OPER_MATERIALS ROM
1254    WHERE    OBJECT_ID in ( SELECT   RO.operation_id
1255                            FROM     AHL_OPERATIONS_B_KFV O, ahl_route_operations RO
1256                            WHERE    O.operation_id = RO.operation_id
1257                            and      RO.route_id = p_route_id
1258                            and      O.revision_status_code = 'COMPLETE'
1259                            and      O.revision_number in (  SELECT   max(revision_number)
1260                                                             FROM     ahl_operations_b_kfv
1261                                                             WHERE    concatenated_segments =O.concatenated_segments
1262                                                             -- manisaga : Bug# 9726667 : 22-Jun-2010
1263                                                             and revision_status_code = 'COMPLETE'
1264                                                             and
1265                                                                      trunc(sysdate) between
1266                                                                      trunc(start_date_active) and
1267                                                                      trunc(NVL(end_date_active,SYSDATE+1)))
1268                         )
1269       AND   ASSOCIATION_TYPE_CODE = G_ASSOC_TYPE_OPERATION
1270       AND   INVENTORY_ITEM_ID IS NOT NULL
1271    UNION
1272     -- Item Group: No need to aggregate or convert to Primary UOM
1273    SELECT   RT_OPER_MATERIAL_ID,
1274             OBJECT_ID AS ROUTE_OPERATION_ID,
1275             TO_NUMBER(NULL) AS INVENTORY_ITEM_ID,
1276             TO_NUMBER(NULL) AS INVENTORY_ORG_ID,
1277             MC_ID,
1278             POSITION_KEY,
1279             QUANTITY,
1280             UOM_CODE,
1281             QUANTITY AS PRIMARY_QUANTITY,
1282             UOM_CODE AS PRIMARY_UOM_CODE,
1283             ITEM_GROUP_ID
1284    FROM     AHL_RT_OPER_MATERIALS ROM
1285    WHERE    OBJECT_ID in (SELECT RO.operation_id
1286                         FROM AHL_OPERATIONS_B_KFV O, ahl_route_operations RO
1287                         WHERE O.operation_id = RO.operation_id and
1288                               RO.route_id = p_route_id and
1289                               O.revision_status_code = 'COMPLETE' and
1290                               O.revision_number in (SELECT max(revision_number)
1291                                                     FROM ahl_operations_b_kfv
1292                                                     WHERE concatenated_segments = O.concatenated_segments
1293                                                     -- manisaga : Bug# 9726667 : 22-Jun-2010
1294                                                     and revision_status_code = 'COMPLETE'
1295                                                     and
1296                                                       trunc(sysdate) between
1297                                                       trunc(start_date_active) and
1298                                                       trunc(NVL(end_date_active,SYSDATE+1)))
1299                        )
1300       AND ASSOCIATION_TYPE_CODE = G_ASSOC_TYPE_OPERATION
1301       AND INVENTORY_ITEM_ID IS NULL;
1302 
1303 CURSOR l_op_requirement_neither_csr IS
1304     SELECT RT_OPER_MATERIAL_ID,
1305            OBJECT_ID AS ROUTE_OPERATION_ID,
1306            TO_NUMBER(NULL) AS INVENTORY_ITEM_ID,
1307            TO_NUMBER(NULL) AS INVENTORY_ORG_ID,
1308            MC_ID,
1309            POSITION_KEY,
1310            QUANTITY,
1311            UOM_CODE,
1312            ITEM_GROUP_ID
1313     FROM AHL_RT_OPER_MATERIALS ROM
1314     WHERE OBJECT_ID in (SELECT RO.operation_id
1315                         FROM AHL_OPERATIONS_B_KFV O, ahl_route_operations RO
1316                         WHERE O.operation_id = RO.operation_id and
1317                               RO.route_id = p_route_id and
1318                               O.revision_status_code = 'COMPLETE' and
1319                               O.revision_number in (SELECT max(revision_number)
1320                                                     FROM ahl_operations_b_kfv
1321                                                     WHERE concatenated_segments = O.concatenated_segments
1322                                                     -- manisaga : Bug# 9726667 : 22-Jun-2010
1323                                                     and revision_status_code = 'COMPLETE'
1324                                                     and
1325                                                       trunc(sysdate) between
1326                                                       trunc(start_date_active) and
1327                                                       trunc(NVL(end_date_active,SYSDATE+1)))
1328                        )
1329       AND ASSOCIATION_TYPE_CODE = G_ASSOC_TYPE_OPERATION
1330       AND INVENTORY_ITEM_ID IS NULL;
1331 -- AnRaj : End for fixing perf bug 4919527
1332 
1333 -- Added by jaramana on 22-OCT-2009 for bug 9037150
1334 -- Use the following cursor to do a high level check for presence of operation level mtl requirements
1335 CURSOR op_level_planned_reqs_exist IS
1336    SELECT ROM.RT_OPER_MATERIAL_ID
1337      FROM AHL_RT_OPER_MATERIALS ROM, AHL_ROUTE_OPERATIONS RO
1338     WHERE ROM.OBJECT_ID = RO.operation_id
1339       AND RO.route_id = p_route_id
1340       AND ROM.ASSOCIATION_TYPE_CODE = G_ASSOC_TYPE_OPERATION;
1341    l_dummy                 op_level_planned_reqs_exist%ROWTYPE;
1342 
1343    -- Added by SURRKUMA for Service Bulletin :: 07-Jun-2011
1344    l_api_version CONSTANT NUMBER          := 1.0;
1345    l_msg_data             VARCHAR2(2000);
1346    l_return_status        VARCHAR2(1);
1347    l_msg_count             NUMBER;
1348 
1349    l_rt_requirement_rec    get_route_level_reqs_csr%ROWTYPE;
1350    l_index                 NUMBER := 0;
1351    L_DEBUG_KEY   CONSTANT  VARCHAR2(150) := G_LOG_PREFIX || '.Get_Route_Requirements';
1352 
1353 BEGIN
1354 
1355   IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
1356     FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.begin', 'Entering Procedure');
1357   END IF;
1358 
1359   -- Get the requirements defined at the route level (if any)
1360   OPEN get_route_level_reqs_csr;
1361   FETCH get_route_level_reqs_csr INTO l_rt_requirement_rec;
1362   IF(get_route_level_reqs_csr%FOUND) THEN
1363     -- Requirements defined at the Route level
1364     IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
1365       FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Requirements for Route with Id ' || p_route_id || ' are defined at the Route level itself.');
1366     END IF;
1367     LOOP
1368       EXIT WHEN get_route_level_reqs_csr%NOTFOUND;
1369       -- Process this requirement
1370       l_index := l_index + 1;
1371       x_route_req_list(l_index).RT_OPER_MATERIAL_ID := l_rt_requirement_rec.RT_OPER_MATERIAL_ID;
1372       -- SURRKUMA :: Service Bulletin :: 07-Jun-2011
1373       -- Added condition for position based requirement
1374       IF (l_rt_requirement_rec. MC_ID IS NOT NULL AND l_rt_requirement_rec.POSITION_KEY IS NOT NULL) THEN
1375         -- Position Based requirement
1376         IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
1377             FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Route MC:' || l_rt_requirement_rec.MC_ID || ', Visit MC: '||p_mc_id);
1378         END IF;
1379         IF (l_rt_requirement_rec.MC_ID = p_mc_id) THEN
1380         -- MC specified in route level and MC part of visit are same.
1381             x_route_req_list(l_index).MC_HEADER_ID := p_mc_header_id;
1382             x_route_req_list(l_index).POSITION_KEY := l_rt_requirement_rec.POSITION_KEY;
1383 
1384            Get_Material_Req_For_Pos(
1385                 p_api_version         => l_api_version,
1386                 x_return_status       => l_return_status,
1387                 x_msg_count           => l_msg_count,
1388                 x_msg_data            => l_msg_data,
1389                 p_uc_header_id        => p_uc_header_id,
1390                 p_visit_id            => p_visit_id,
1391                 p_quantity            => l_rt_requirement_rec.QUANTITY,
1392                 p_uom_code            => l_rt_requirement_rec.UOM_CODE,
1393                 p_x_index             => l_index,
1394                 p_x_route_mtl_reqs    => x_route_req_list
1395             );
1396         END IF;
1397 
1398         -- The position based requirement is not valid, so removing the record index by 1.
1399         -- This happen in two cases.
1400         -- 1. The UC's MC and Material Requirement's MC doesn't match.
1401         -- 2. The Position is not part of the MC.
1402         IF ( x_route_req_list(l_index).INVENTORY_ITEM_ID IS NULL) THEN
1403             x_route_req_list(l_index).MC_HEADER_ID := NULL;
1404             x_route_req_list(l_index).POSITION_KEY := NULL;
1405             l_index := l_index - 1;
1406         END IF;
1407 
1408       ELSIF (l_rt_requirement_rec.INVENTORY_ITEM_ID IS NULL) THEN
1409         -- Item Group Requirement
1410         x_route_req_list(l_index).ITEM_GROUP_ID := l_rt_requirement_rec.ITEM_GROUP_ID;
1411         x_route_req_list(l_index).QUANTITY := l_rt_requirement_rec.QUANTITY;
1412         x_route_req_list(l_index).UOM_CODE := l_rt_requirement_rec.UOM_CODE;
1413       ELSE
1414         -- Specific Item Requirement
1415         x_route_req_list(l_index).INVENTORY_ITEM_ID := l_rt_requirement_rec.INVENTORY_ITEM_ID;
1416         x_route_req_list(l_index).INV_MASTER_ORG_ID := l_rt_requirement_rec.INVENTORY_ORG_ID;
1417         x_route_req_list(l_index).QUANTITY := l_rt_requirement_rec.PRIMARY_QUANTITY;
1418         x_route_req_list(l_index).UOM_CODE := l_rt_requirement_rec.PRIMARY_UOM_CODE;
1419       END IF;
1420 
1421       -- Modified by surrkuma for Service Bulletin on 27-Jun-2011
1422       IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL AND l_index > 0) THEN
1423         FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Requirement ' || l_index || ': RT_OPER_MATERIAL_ID = ' || l_rt_requirement_rec.RT_OPER_MATERIAL_ID ||
1424                                                              ', ITEM_GROUP_ID = ' || x_route_req_list(l_index).ITEM_GROUP_ID ||
1425                                                              ', INVENTORY_ITEM_ID = ' || x_route_req_list(l_index).INVENTORY_ITEM_ID ||
1426                                                              ', INV_MASTER_ORG_ID = ' || x_route_req_list(l_index).INV_MASTER_ORG_ID ||
1427                                                              ', QUANTITY = ' || x_route_req_list(l_index).QUANTITY ||
1428                                                              ', UOM_CODE = ' || x_route_req_list(l_index).UOM_CODE);
1429       END IF;
1430       -- Get the next requirement
1431       FETCH get_route_level_reqs_csr INTO l_rt_requirement_rec;
1432     END LOOP;
1433     CLOSE get_route_level_reqs_csr;
1434   ELSE
1435     -- No requirement defined at route level
1436     CLOSE get_route_level_reqs_csr;
1437     IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
1438       FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Requirements for Route with Id ' || p_route_id ||
1439                                                            ' are NOT defined at the Route level. Checking at the operation level.');
1440     END IF;
1441    -- AnRaj : Start for fixing perf bug 4919527
1442    -- AnRaj : Changed the code for fixing the performance bug# 4919527
1443    -- Split the query into 3 to avoid the  cursor get_op_level_reqs_csr
1444       IF p_request_type = G_REQ_TYPE_FORECAST THEN
1445          IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
1446             FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'p_request type is G_REQ_TYPE_FORECAST');
1447          END IF;
1448 
1449          FOR  l_op_requirement_rec  IN get_op_level_reqs_forecast_csr  LOOP
1450             l_index := l_index + 1;
1451             x_route_req_list(l_index).RT_OPER_MATERIAL_ID := l_op_requirement_rec.RT_OPER_MATERIAL_ID;
1452             x_route_req_list(l_index).ROUTE_OPERATION_ID := l_op_requirement_rec.ROUTE_OPERATION_ID;
1453             -- SURRKUMA :: Service Bulletin :: 07-Jun-2011
1454             -- Added condition for position based requirement
1455             IF (l_op_requirement_rec. MC_ID IS NOT NULL AND l_op_requirement_rec.POSITION_KEY IS NOT NULL) THEN
1456                 -- Position Based requirement
1457                 IF (l_op_requirement_rec.MC_ID = p_mc_id) THEN
1458                 -- MC specified in route level and MC part of visit are same.
1459                     x_route_req_list(l_index).MC_HEADER_ID := p_mc_header_id;
1460                     x_route_req_list(l_index).POSITION_KEY := l_op_requirement_rec.POSITION_KEY;
1461 
1462                     Get_Material_Req_For_Pos(
1463                         p_api_version         => l_api_version,
1464                         x_return_status       => l_return_status,
1465                         x_msg_count           => l_msg_count,
1466                         x_msg_data            => l_msg_data,
1467                         p_uc_header_id        => p_uc_header_id,
1468                         p_visit_id            => p_visit_id,
1469                         p_quantity            => l_op_requirement_rec.QUANTITY,
1470                         p_uom_code            => l_op_requirement_rec.UOM_CODE,
1471                         p_x_index             => l_index,
1472                         p_x_route_mtl_reqs    => x_route_req_list
1473                 );
1474                 END IF;
1475 
1476                 -- The position based requirement is not valid, so removing the record index by 1.
1477                 -- This happen in two cases.
1478                 -- 1. The UC's MC and Material Requirement's MC doesn't match.
1479                 -- 2. The Position is not part of the MC.
1480                 IF ( x_route_req_list(l_index).INVENTORY_ITEM_ID IS NULL) THEN
1481                     x_route_req_list(l_index).MC_HEADER_ID := NULL;
1482                     x_route_req_list(l_index).POSITION_KEY := NULL;
1483                     l_index := l_index - 1;
1484                 END IF;
1485             ELSE
1486                 x_route_req_list(l_index).ITEM_GROUP_ID := l_op_requirement_rec.ITEM_GROUP_ID;
1487                 x_route_req_list(l_index).INVENTORY_ITEM_ID := l_op_requirement_rec.INVENTORY_ITEM_ID;
1488                 x_route_req_list(l_index).INV_MASTER_ORG_ID := l_op_requirement_rec.INVENTORY_ORG_ID;
1489                 x_route_req_list(l_index).QUANTITY := l_op_requirement_rec.PRIMARY_QUANTITY;
1490                 x_route_req_list(l_index).UOM_CODE := l_op_requirement_rec.PRIMARY_UOM_CODE;
1491             END IF;
1492 
1493             -- Modified by surrkuma for Service Bulletin on 27-Jun-2011
1494             IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL AND l_index > 0) THEN
1495                FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Requirement ' || l_index || ': RT_OPER_MATERIAL_ID = ' || x_route_req_list(l_index).RT_OPER_MATERIAL_ID ||
1496                                                                    ', ROUTE_OPERATION_ID = ' || x_route_req_list(l_index).ROUTE_OPERATION_ID ||
1497                                                                    ', ITEM_GROUP_ID = ' || x_route_req_list(l_index).ITEM_GROUP_ID ||
1498                                                                    ', INVENTORY_ITEM_ID = ' || x_route_req_list(l_index).INVENTORY_ITEM_ID ||
1499                                                                    ', INV_MASTER_ORG_ID = ' || x_route_req_list(l_index).INV_MASTER_ORG_ID ||
1500                                                                    ', QUANTITY = ' || x_route_req_list(l_index).QUANTITY ||
1501                                                                    ', UOM_CODE = ' || x_route_req_list(l_index).UOM_CODE);
1502             END IF;
1503          END LOOP;
1504       ELSIF p_request_type = G_REQ_TYPE_PLANNED THEN
1505          IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
1506             FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'p_request type is G_REQ_TYPE_PLANNED');
1507          END IF;
1508 
1509          -- Begin changes by jaramana on 22-OCT-2009 for bug 9037150
1510          -- Do a high level check for presence of operation level mtl requirements before
1511          -- attempting to get the details of the requirements to avoid performance hit
1512          OPEN op_level_planned_reqs_exist;
1513          FETCH op_level_planned_reqs_exist INTO l_dummy;
1514          IF (op_level_planned_reqs_exist%FOUND) THEN
1515            -- Operation Level Requirements seem to exist. Get these if they are effective
1516            -- and if they are applicable to the latest revision
1517            FOR l_op_requirement_rec IN  get_op_level_reqs_planned_csr   LOOP
1518             l_index := l_index + 1;
1519             x_route_req_list(l_index).RT_OPER_MATERIAL_ID := l_op_requirement_rec.RT_OPER_MATERIAL_ID;
1520             x_route_req_list(l_index).ROUTE_OPERATION_ID := l_op_requirement_rec.ROUTE_OPERATION_ID;
1521 
1522             -- SURRKUMA :: Service Bulletin :: 07-Jun-2011
1523             -- Added condition for position based requirement
1524             IF (l_op_requirement_rec. MC_ID IS NOT NULL AND l_op_requirement_rec.POSITION_KEY IS NOT NULL) THEN
1525                 -- Position Based requirement
1526                 IF (l_op_requirement_rec.MC_ID = p_mc_id) THEN
1527                 -- MC specified in route level and MC part of visit are same.
1528                     x_route_req_list(l_index).MC_HEADER_ID := p_mc_header_id;
1529                     x_route_req_list(l_index).POSITION_KEY := l_op_requirement_rec.POSITION_KEY;
1530 
1531                     Get_Material_Req_For_Pos(
1532                         p_api_version         => l_api_version,
1533                         x_return_status       => l_return_status,
1534                         x_msg_count           => l_msg_count,
1535                         x_msg_data            => l_msg_data,
1536                         p_uc_header_id        => p_uc_header_id,
1537                         p_visit_id            => p_visit_id,
1538                         p_quantity            => l_op_requirement_rec.QUANTITY,
1539                         p_uom_code            => l_op_requirement_rec.UOM_CODE,
1540                         p_x_index             => l_index,
1541                         p_x_route_mtl_reqs    => x_route_req_list
1542                 );
1543                 END IF;
1544 
1545                 -- The position based requirement is not valid, so removing the record index by 1.
1546                 -- This happen in two cases.
1547                 -- 1. The UC's MC and Material Requirement's MC doesn't match.
1548                 -- 2. The Position is not part of the MC.
1549                 IF ( x_route_req_list(l_index).INVENTORY_ITEM_ID IS NULL) THEN
1550                     x_route_req_list(l_index).MC_HEADER_ID := NULL;
1551                     x_route_req_list(l_index).POSITION_KEY := NULL;
1552                     l_index := l_index - 1;
1553                 END IF;
1554             ELSE
1555                 x_route_req_list(l_index).ITEM_GROUP_ID := l_op_requirement_rec.ITEM_GROUP_ID;
1556                 x_route_req_list(l_index).INVENTORY_ITEM_ID := l_op_requirement_rec.INVENTORY_ITEM_ID;
1557                 x_route_req_list(l_index).INV_MASTER_ORG_ID := l_op_requirement_rec.INVENTORY_ORG_ID;
1558                 x_route_req_list(l_index).QUANTITY := l_op_requirement_rec.PRIMARY_QUANTITY;
1559                 x_route_req_list(l_index).UOM_CODE := l_op_requirement_rec.PRIMARY_UOM_CODE;
1560             END IF;
1561             -- Modified by surrkuma for Service Bulletin on 27-Jun-2011
1562             IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL AND l_index > 0) THEN
1563                 FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Requirement ' || l_index || ': RT_OPER_MATERIAL_ID = ' || x_route_req_list(l_index).RT_OPER_MATERIAL_ID ||
1564                                                                     ', ROUTE_OPERATION_ID = ' || x_route_req_list(l_index).ROUTE_OPERATION_ID ||
1565                                                                     ', ITEM_GROUP_ID = ' || x_route_req_list(l_index).ITEM_GROUP_ID ||
1566                                                                     ', INVENTORY_ITEM_ID = ' || x_route_req_list(l_index).INVENTORY_ITEM_ID ||
1567                                                                     ', INV_MASTER_ORG_ID = ' || x_route_req_list(l_index).INV_MASTER_ORG_ID ||
1568                                                                     ', QUANTITY = ' || x_route_req_list(l_index).QUANTITY ||
1569                                                                     ', UOM_CODE = ' || x_route_req_list(l_index).UOM_CODE);
1570             END IF;
1571 
1572            END LOOP;
1573          END IF;
1574          CLOSE op_level_planned_reqs_exist;
1575          -- End changes by jaramana on 22-OCT-2009 for bug 9037150
1576 
1577       -- Not too sure whether the value of p_request_type can be anything other than G_REQ_TYPE_FORECAST and G_REQ_TYPE_PLANNED
1578       -- Adding this part for safety purpose, so that no records are missed out
1579       ELSE
1580          IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
1581             FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'p_request type is neither G_REQ_TYPE_PLANNED nor G_REQ_TYPE_FORECAST');
1582          END IF;
1583 
1584          FOR l_op_requirement_rec IN l_op_requirement_neither_csr LOOP
1585             l_index := l_index + 1;
1586             x_route_req_list(l_index).RT_OPER_MATERIAL_ID := l_op_requirement_rec.RT_OPER_MATERIAL_ID;
1587             x_route_req_list(l_index).ROUTE_OPERATION_ID := l_op_requirement_rec.ROUTE_OPERATION_ID;
1588 
1589             -- SURRKUMA :: Service Bulletin :: 07-Jun-2011
1590             -- Added condition for position based requirement
1591             IF (l_op_requirement_rec. MC_ID IS NOT NULL AND l_op_requirement_rec.POSITION_KEY IS NOT NULL) THEN
1592                 -- Position Based requirement
1593                 IF (l_op_requirement_rec.MC_ID = p_mc_id) THEN
1594                 -- MC specified in route level and MC part of visit are same.
1595                     x_route_req_list(l_index).MC_HEADER_ID := p_mc_header_id;
1596                     x_route_req_list(l_index).POSITION_KEY := l_op_requirement_rec.POSITION_KEY;
1597 
1598                     Get_Material_Req_For_Pos(
1599                         p_api_version         => l_api_version,
1600                         x_return_status       => l_return_status,
1601                         x_msg_count           => l_msg_count,
1602                         x_msg_data            => l_msg_data,
1603                         p_uc_header_id        => p_uc_header_id,
1604                         p_visit_id            => p_visit_id,
1605                         p_quantity            => l_op_requirement_rec.QUANTITY,
1606                         p_uom_code            => l_op_requirement_rec.UOM_CODE,
1607                         p_x_index             => l_index,
1608                         p_x_route_mtl_reqs    => x_route_req_list
1609                 );
1610                 END IF;
1611 
1612                 -- The position based requirement is not valid, so removing the record index by 1.
1613                 -- This happen in two cases.
1614                 -- 1. The UC's MC and Material Requirement's MC doesn't match.
1615                 -- 2. The Position is not part of the MC.
1616                 IF ( x_route_req_list(l_index).INVENTORY_ITEM_ID IS NULL) THEN
1617                     x_route_req_list(l_index).MC_HEADER_ID := NULL;
1618                     x_route_req_list(l_index).POSITION_KEY := NULL;
1619                     l_index := l_index - 1;
1620                 END IF;
1621             ELSE
1622                 x_route_req_list(l_index).ITEM_GROUP_ID := l_op_requirement_rec.ITEM_GROUP_ID;
1623                 x_route_req_list(l_index).INVENTORY_ITEM_ID := l_op_requirement_rec.INVENTORY_ITEM_ID;
1624                 x_route_req_list(l_index).INV_MASTER_ORG_ID := l_op_requirement_rec.INVENTORY_ORG_ID;
1625                 x_route_req_list(l_index).QUANTITY := l_op_requirement_rec.QUANTITY;
1626                 x_route_req_list(l_index).UOM_CODE := l_op_requirement_rec.UOM_CODE;
1627             END IF;
1628 
1629             -- Modified by surrkuma for Service Bulletin on 27-Jun-2011
1630             IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL AND l_index > 0) THEN
1631                FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Requirement ' || l_index || ': RT_OPER_MATERIAL_ID = ' || x_route_req_list(l_index).RT_OPER_MATERIAL_ID ||
1632                                                                    ', ROUTE_OPERATION_ID = ' || x_route_req_list(l_index).ROUTE_OPERATION_ID ||
1633                                                                    ', ITEM_GROUP_ID = ' || x_route_req_list(l_index).ITEM_GROUP_ID ||
1634                                                                    ', INVENTORY_ITEM_ID = ' || x_route_req_list(l_index).INVENTORY_ITEM_ID ||
1635                                                                    ', INV_MASTER_ORG_ID = ' || x_route_req_list(l_index).INV_MASTER_ORG_ID ||
1636                                                                    ', QUANTITY = ' || x_route_req_list(l_index).QUANTITY ||
1637                                                                    ', UOM_CODE = ' || x_route_req_list(l_index).UOM_CODE);
1638             END IF;
1639 
1640          END LOOP;
1641       END IF;  -- request_type check
1642 
1643     -- Check operation level
1644    /*    FOR l_op_requirement_rec IN get_op_level_reqs_csr LOOP
1645       l_index := l_index + 1;
1646       x_route_req_list(l_index).RT_OPER_MATERIAL_ID := l_op_requirement_rec.RT_OPER_MATERIAL_ID;
1647       x_route_req_list(l_index).ROUTE_OPERATION_ID := l_op_requirement_rec.ROUTE_OPERATION_ID;
1648       x_route_req_list(l_index).ITEM_GROUP_ID := l_op_requirement_rec.ITEM_GROUP_ID;
1649       x_route_req_list(l_index).INVENTORY_ITEM_ID := l_op_requirement_rec.INVENTORY_ITEM_ID;
1650       x_route_req_list(l_index).INV_MASTER_ORG_ID := l_op_requirement_rec.INVENTORY_ORG_ID;
1651       x_route_req_list(l_index).QUANTITY := l_op_requirement_rec.QUANTITY;
1652       x_route_req_list(l_index).UOM_CODE := l_op_requirement_rec.UOM_CODE;
1653       IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
1654         FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Requirement ' || l_index || ': RT_OPER_MATERIAL_ID = ' || x_route_req_list(l_index).RT_OPER_MATERIAL_ID ||
1655                                                              ', ROUTE_OPERATION_ID = ' || x_route_req_list(l_index).ROUTE_OPERATION_ID ||
1656                                                              ', ITEM_GROUP_ID = ' || x_route_req_list(l_index).ITEM_GROUP_ID ||
1657                                                              ', INVENTORY_ITEM_ID = ' || x_route_req_list(l_index).INVENTORY_ITEM_ID ||
1658                                                              ', INV_MASTER_ORG_ID = ' || x_route_req_list(l_index).INV_MASTER_ORG_ID ||
1659                                                              ', QUANTITY = ' || x_route_req_list(l_index).QUANTITY ||
1660                                                              ', UOM_CODE = ' || x_route_req_list(l_index).UOM_CODE);
1661       END IF;
1662     END LOOP;
1663     */
1664 -- AnRaj : End for fixing perf bug 4919527
1665   END IF;
1666   IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
1667     FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Total number of Route requirements: ' || l_index);
1668   END IF;
1669   IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
1670     FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.end', 'Exiting Procedure');
1671   END IF;
1672 
1673 END Get_Route_Requirements;
1674 
1675 ------------------------------------------------------------------------
1676 -- This Procedure validates a Position Path against a given unit and date.
1677 -- It returns a status flag and if valid, it get the details about the position.
1678 ------------------------------------------------------------------------
1679 PROCEDURE Validate_Path_Position
1680 (
1681    p_path_position_id          IN  NUMBER,
1682    p_unit_instance_id          IN  NUMBER,
1683    p_requirement_date          IN  DATE,
1684    x_valid_flag                OUT NOCOPY VARCHAR2,
1685    x_relationship_id           OUT NOCOPY NUMBER,
1686    x_item_group_id             OUT NOCOPY NUMBER,
1687    x_pos_instance_id           OUT NOCOPY NUMBER) IS
1688 
1689   CURSOR get_pos_path_dtls_csr IS
1690     SELECT position_key
1691     FROM AHL_MC_PATH_POSITION_NODES
1692     WHERE PATH_POSITION_ID = p_path_position_id AND
1693           SEQUENCE = (SELECT MAX(SEQUENCE) FROM AHL_MC_PATH_POSITION_NODES
1694                       WHERE PATH_POSITION_ID = p_path_position_id);
1695 
1696   CURSOR get_position_dtls_csr(c_pos_key      IN NUMBER,
1697                                c_mc_header_id IN NUMBER) IS
1698     SELECT relationship_id, item_group_id
1699     FROM AHL_MC_RELATIONSHIPS
1700     WHERE POSITION_KEY = c_pos_key AND
1701           MC_HEADER_ID = c_mc_header_id;
1702 
1703   CURSOR get_config_dtls_csr(c_unit_instance_id IN NUMBER) IS
1704     SELECT master_config_id
1705     FROM ahl_unit_config_headers
1706     WHERE CSI_ITEM_INSTANCE_ID = c_unit_instance_id AND
1707           NVL(ACTIVE_START_DATE, SYSDATE - 1) <= SYSDATE AND
1708           NVL(ACTIVE_END_DATE, SYSDATE + 1) > SYSDATE;
1709 
1710   CURSOR get_all_position_dates_csr(c_start_pos_key IN NUMBER,
1711                                     c_mc_header_id  IN NUMBER) IS
1712     SELECT ACTIVE_START_DATE,
1713            ACTIVE_END_DATE
1714     FROM AHL_MC_RELATIONSHIPS
1715     START WITH POSITION_KEY = c_start_pos_key AND
1716                MC_HEADER_ID = c_mc_header_id
1717     CONNECT BY RELATIONSHIP_ID = PRIOR PARENT_RELATIONSHIP_ID;
1718 
1719   CURSOR get_ii_position_csr(c_start_instance_id IN NUMBER) IS
1720     SELECT II.OBJECT_ID,
1721            II.SUBJECT_ID,
1722            REL.RELATIONSHIP_ID,
1723            REL.ACTIVE_START_DATE,
1724            REL.ACTIVE_END_DATE
1725     FROM CSI_II_RELATIONSHIPS II, AHL_MC_RELATIONSHIPS REL
1726     WHERE NVL(II.ACTIVE_START_DATE, SYSDATE - 1) <= SYSDATE AND
1727           NVL(II.ACTIVE_END_DATE, SYSDATE + 1) > SYSDATE AND
1728           II.RELATIONSHIP_TYPE_CODE = 'COMPONENT-OF' AND
1729           REL.RELATIONSHIP_ID =TO_NUMBER(II.POSITION_REFERENCE)
1730           AND II.RELATIONSHIP_ID IN
1731           (SELECT RELATIONSHIP_ID
1732           FROM CSI_II_RELATIONSHIPS
1733     START WITH SUBJECT_ID = c_start_instance_id AND
1734                NVL(ACTIVE_START_DATE, SYSDATE - 1) <= SYSDATE AND
1735                NVL(ACTIVE_END_DATE, SYSDATE + 1) > SYSDATE AND
1736                RELATIONSHIP_TYPE_CODE = 'COMPONENT-OF'
1737     CONNECT BY SUBJECT_ID = PRIOR OBJECT_ID AND
1738                NVL(ACTIVE_START_DATE, SYSDATE - 1) <= SYSDATE AND
1739                NVL(ACTIVE_END_DATE, SYSDATE + 1) > SYSDATE AND
1740                RELATIONSHIP_TYPE_CODE = 'COMPONENT-OF');
1741 
1742    L_DEBUG_KEY   CONSTANT  VARCHAR2(150) := G_LOG_PREFIX || '.Validate_Path_Position';
1743    l_return_status         VARCHAR2(1);
1744    l_msg_count             NUMBER;
1745    l_msg_data              VARCHAR2(1000);
1746    l_installed_inst_id     NUMBER;
1747    l_lowest_unit_inst_id   NUMBER;
1748    l_lowest_mc_header_id   NUMBER;
1749    l_mapping_status        VARCHAR2(30);
1750    l_position_key          AHL_MC_PATH_POSITION_NODES.POSITION_KEY%TYPE;
1751    l_last_instance_id      NUMBER;
1752    l_requirement_date      DATE := p_requirement_date;
1753 
1754 BEGIN
1755 
1756   IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
1757     FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.begin', 'Entering Procedure');
1758   END IF;
1759 
1760   IF (G_LEVEL_EVENT >= G_CURRENT_RUNTIME_LEVEL) THEN
1761     FND_LOG.STRING(G_LEVEL_EVENT, L_DEBUG_KEY, 'About to call AHL_MC_PATH_POSITION_PVT.Get_Pos_Instance with ' ||
1762                                                      ' p_position_id = ' || p_path_position_id ||
1763                                                      ' p_csi_item_instance_id = ' || p_unit_instance_id);
1764   END IF;
1765 
1766   AHL_MC_PATH_POSITION_PVT.Get_Pos_Instance(p_api_version          => 1.0,
1767                                             p_init_msg_list        => FND_API.G_FALSE,
1768                                             p_commit               => FND_API.G_FALSE,
1769                                             p_validation_level     => FND_API.G_VALID_LEVEL_FULL,
1770                                             x_return_status        => l_return_status,
1771                                             x_msg_count            => l_msg_count,
1772                                             x_msg_data             => l_msg_data,
1773                                             p_position_id          => p_path_position_id,
1774                                             p_csi_item_instance_id => p_unit_instance_id,
1775                                             x_item_instance_id     => l_installed_inst_id,
1776                                             x_lowest_uc_csi_id     => l_lowest_unit_inst_id,
1777                                             x_mapping_status       => l_mapping_status);
1778 
1779   IF (G_LEVEL_EVENT >= G_CURRENT_RUNTIME_LEVEL) THEN
1780     FND_LOG.STRING(G_LEVEL_EVENT, L_DEBUG_KEY, 'Returned from call to AHL_MC_PATH_POSITION_PVT.Get_Pos_Instance:' ||
1781                                                      ' x_return_status = ' || l_return_status ||
1782                                                      ', x_mapping_status = ' || l_mapping_status ||
1783                                                      ', x_item_instance_id = ' || l_installed_inst_id ||
1784                                                      ', x_lowest_uc_csi_id = ' || l_lowest_unit_inst_id);
1785   END IF;
1786 
1787   IF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
1788     RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1789   ELSIF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
1790     RAISE FND_API.G_EXC_ERROR;
1791   END IF;
1792 
1793   IF(l_mapping_status = G_MAPPING_STATUS_NA) THEN
1794     -- Position does not apply to current unit
1795     x_valid_flag := FND_API.G_FALSE;
1796     RETURN;
1797   END IF;
1798 
1799   OPEN get_pos_path_dtls_csr;
1800   FETCH get_pos_path_dtls_csr INTO l_position_key;
1801   CLOSE get_pos_path_dtls_csr;
1802 
1803   OPEN get_config_dtls_csr(c_unit_instance_id => l_lowest_unit_inst_id);
1804   FETCH get_config_dtls_csr INTO l_lowest_mc_header_id;
1805   CLOSE get_config_dtls_csr;
1806 
1807   IF l_requirement_date IS NULL THEN
1808     l_requirement_date := SYSDATE;
1809   END IF;
1810 
1811   -- Check if the Position is valid on the requirement date
1812   -- by traversing the tree from the position up to the unit's root node.
1813   IF (l_mapping_status = G_MAPPING_STATUS_EMPTY) THEN
1814     -- If the position is empty, do a separate traversal from
1815     -- the position up to l_lowest_unit_inst_id first.
1816     FOR position_dates_rec IN get_all_position_dates_csr(l_position_key, l_lowest_mc_header_id)  LOOP
1817       IF ((position_dates_rec.ACTIVE_START_DATE IS NOT NULL AND
1818            position_dates_rec.ACTIVE_START_DATE > l_requirement_date) OR
1819           (position_dates_rec.ACTIVE_END_DATE IS NOT NULL AND
1820            position_dates_rec.ACTIVE_END_DATE <= l_requirement_date)) THEN
1821         -- Position is not valid on the requirement date
1822         x_valid_flag := FND_API.G_FALSE;
1823         RETURN;
1824       END IF;
1825     END LOOP;
1826     l_last_instance_id := l_lowest_unit_inst_id;
1827   ELSE
1828     -- Position is not empty
1829     l_last_instance_id := l_installed_inst_id;
1830   END IF;
1831 
1832   IF (l_last_instance_id <> p_unit_instance_id) THEN
1833     -- Now traverse up the instance tree to validate positions.
1834     FOR position_rec IN get_ii_position_csr(l_last_instance_id) LOOP
1835       -- Check if the position is valid in the last mc
1836       IF ((position_rec.ACTIVE_START_DATE IS NOT NULL AND
1837            position_rec.ACTIVE_START_DATE > l_requirement_date) OR
1838           (position_rec.ACTIVE_END_DATE IS NOT NULL AND
1839            position_rec.ACTIVE_END_DATE <= l_requirement_date)) THEN
1840         -- Position is not valid on the requirement date
1841         x_valid_flag := FND_API.G_FALSE;
1842         RETURN;
1843       END IF;
1844     END LOOP;
1845   END IF;
1846 
1847   -- The Position hierarchy is valid on the requirement Date
1848   x_valid_flag := FND_API.G_TRUE;
1849 
1850   -- Information available: l_position_key, l_lowest_mc_header_id, l_mapping_status, l_installed_inst_id
1851   -- Get the relationship id and the item group id for the position
1852   OPEN get_position_dtls_csr(c_pos_key      => l_position_key,
1853                              c_mc_header_id => l_lowest_mc_header_id);
1854   FETCH get_position_dtls_csr INTO x_relationship_id, x_item_group_id;
1855   CLOSE get_position_dtls_csr;
1856   IF (l_mapping_status = G_MAPPING_STATUS_MATCH) THEN
1857     x_pos_instance_id := l_installed_inst_id;
1858   ELSE
1859     x_pos_instance_id := NULL;
1860   END IF;
1861 
1862   IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
1863     FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.end', 'Exiting Procedure');
1864   END IF;
1865 
1866 END Validate_Path_Position;
1867 
1868 
1869 -------------------------------------
1870 -- End Local Procedure Definitions --
1871 -------------------------------------
1872 ---------------------------------------
1873 -- Local Function Definitions follow --
1874 ---------------------------------------
1875 -----------------------------------------------
1876 -- This Function gets the unit's instance id --
1877 -- If p_item_instance_id does not belong to an UC (stand-alone or IB Tree), it
1878 -- returns null. If p_item_instance_id itself is a UC's top node, it returns itself.
1879 -----------------------------------------------
1880 
1881 FUNCTION Get_Unit_Instance(
1882    p_item_instance_id IN NUMBER) RETURN NUMBER IS
1883 
1884   CURSOR chk_inst_is_unit_csr IS
1885     SELECT 'x'
1886     FROM ahl_unit_config_headers
1887     WHERE csi_item_instance_id = p_item_instance_id
1888       AND nvl(active_end_date, SYSDATE+1) > SYSDATE
1889       AND nvl(active_start_date, SYSDATE) <= SYSDATE;
1890 
1891   CURSOR get_parent_instance_csr IS
1892     SELECT object_id
1893     FROM csi_ii_relationships
1894     WHERE object_id IN (SELECT csi_item_instance_id
1895                         FROM ahl_unit_config_headers
1896                         WHERE nvl(active_end_date, SYSDATE+1) > SYSDATE
1897                           AND nvl(active_start_date, SYSDATE) <= SYSDATE)
1898     START WITH subject_id = p_item_instance_id
1899            AND relationship_type_code = 'COMPONENT-OF'
1900            AND nvl(active_start_date, SYSDATE) <= SYSDATE
1901            AND nvl(active_end_date, SYSDATE+1) > SYSDATE
1902     CONNECT BY subject_id = PRIOR object_id
1903          AND relationship_type_code = 'COMPONENT-OF'
1904          AND trunc(nvl(active_start_date, SYSDATE)) <= trunc(SYSDATE)
1905          AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE)
1906     ORDER BY LEVEL;
1907 
1908   l_instance_id  NUMBER := null;
1909   l_dummy        VARCHAR2(1);
1910 
1911   L_DEBUG_KEY CONSTANT VARCHAR2(150) := G_LOG_PREFIX || '.Get_Unit_Instance';
1912 
1913 BEGIN
1914   IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
1915     FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.begin', 'Entering Function');
1916   END IF;
1917 
1918   IF(p_item_instance_id IS NULL) THEN
1919     IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
1920       FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'p_item_instance_id is null. So, returning null.');
1921     END IF;
1922     l_instance_id := null;
1923   ELSE
1924     OPEN chk_inst_is_unit_csr;
1925     FETCH chk_inst_is_unit_csr INTO l_dummy;
1926     IF (chk_inst_is_unit_csr%FOUND) THEN
1927       IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
1928         FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'p_item_instance_id (' || p_item_instance_id || ') itself is a unit.');
1929       END IF;
1930       l_instance_id := p_item_instance_id;
1931     ELSE
1932       OPEN get_parent_instance_csr;
1933       FETCH get_parent_instance_csr INTO l_instance_id;
1934       CLOSE get_parent_instance_csr;
1935       IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
1936         FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Unit Instance of ' || p_item_instance_id || ' is ' || l_instance_id);
1937       END IF;
1938     END IF;
1939     CLOSE chk_inst_is_unit_csr;
1940   END IF;
1941 
1942   IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
1943     FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.end', 'Exiting Function');
1944   END IF;
1945   RETURN l_instance_id;
1946 
1947 END Get_Unit_Instance;
1948 
1949 -- Start of Comments --
1950 --  Procedure name     : Get_Material_Req_For_Pos
1951 --  Type               : Private
1952 --  Function           : Gets the Material requirement for a position specified in
1953 --                       Route/Operation level requriements
1954 --  Pre-reqs    :
1955 --  Parameters  :
1956 --
1957 --  Standard IN  Parameters :
1958 --      p_api_version                   IN      NUMBER       Required
1959 --      p_init_msg_list                 IN      VARCHAR2     Default  FND_API.G_FALSE
1960 --      p_validation_level              IN      NUMBER       Default  FND_API.G_VALID_LEVEL_FULL
1961 --
1962 --  Standard OUT Parameters :
1963 --      x_return_status                    OUT     VARCHAR2     Required
1964 --      x_msg_count                        OUT     NUMBER       Required
1965 --      x_msg_data                         OUT     VARCHAR2     Required
1966 --
1967 --  Get_Material_Req_For_Pos Parameters:
1968 --      p_uc_header_id                  IN      NUMBER       Required
1969 --         Unit Configuration Header ID of the Visit's Unit
1970 --      p_visit_id                      IN      NUMBER       Not Requried when p_visit_id is NULL
1971 --         The Id of the Visit for which material requirements calculated.
1972 --      p_quantity                      IN      NUMBER       Not Required when p_quantity is NULL
1973 --         Requested Quanity.
1974 --      p_uom_code                      IN      VARCHAR2     Not Required when p_uom_code is NULL
1975 --         Unit of Measure of the defined at requirement request level.
1976 --      p_x_index                       IN OUT  NUMBER       Not Required
1977 --         p_x_route_mtl_reqs material requirements table index
1978 --      p_x_route_mtl_reqs              IN OUT  Route_Mtl_Req_Tbl_Type  Required
1979 --         The table containing the route based material requirements.
1980 --
1981 --  Version :
1982 --      Initial Version   1.0
1983 --      Modified by surrkuma on 29-Jul-2011
1984 --          Changed the method signature to support control position based
1985 --          Material requirements
1986 --
1987 --  End of Comments.
1988 
1989 PROCEDURE Get_Material_Req_For_Pos (
1990     p_api_version                 IN             NUMBER,
1991     p_init_msg_list               IN             VARCHAR2  := FND_API.G_FALSE,
1992     p_validation_level            IN             NUMBER    := FND_API.G_VALID_LEVEL_FULL,
1993     x_return_status                  OUT  NOCOPY VARCHAR2,
1994     x_msg_count                      OUT  NOCOPY NUMBER,
1995     x_msg_data                       OUT  NOCOPY VARCHAR2,
1996     p_uc_header_id                IN             NUMBER,
1997     p_visit_id                    IN             NUMBER    := NULL,
1998     p_quantity                    IN             NUMBER    := NULL,
1999     p_uom_code                    IN             VARCHAR2  := NULL,
2000     p_x_index                     IN OUT NOCOPY  NUMBER,
2001     p_x_route_mtl_reqs            IN OUT NOCOPY  Route_Mtl_Req_Tbl_Type
2002 ) IS
2003 
2004 -- Cursor get the MC relation ship details for given mc and position
2005 CURSOR get_mc_relationship_detail_csr (c_mc_header_id NUMBER,
2006                                        c_position_key NUMBER) IS
2007    SELECT relationship_id,
2008           item_group_id,
2009           quantity,
2010           uom_code
2011    FROM   ahl_mc_relationships
2012    WHERE  mc_header_id = c_mc_header_id
2013    AND    position_key = c_position_key;
2014 
2015 -- cursor to get applicable SB rules for the given unit and position
2016 -- NOTE::Fetch only once from this cursor. UNION ALL is fine as it will be fetched only once.
2017 CURSOR get_appl_sb_rules_csr (c_uc_header_id    NUMBER,
2018                               c_relationship_id NUMBER,
2019                               c_visit_id        NUMBER) IS
2020     SELECT DISTINCT rule_id,
2021                     rule_sequence
2022     FROM (
2023     SELECT SB.rule_id,
2024            SB.rule_sequence
2025     FROM   ahl_sb_position_rules SB,
2026            ahl_unit_config_headers UC
2027     WHERE  UC.unit_config_header_id = c_uc_header_id
2028     AND    SB.mc_header_id          = UC.master_config_id
2029     -- take only the rules which have MRs accomplished on the unit
2030     AND    EXISTS (SELECT 'X'
2031                    FROM   ahl_unit_effectivities_b UE
2032                    WHERE  UE.mr_header_id         = SB.mr_header_id
2033                    AND    UE.csi_item_instance_id = UC.csi_item_instance_id -- SB MRs are effective on root node
2034                    AND    UE.accomplished_date    IS NOT NULL)
2035     -- take only the MAX sequence rules for a position, among the accomplished MRs
2036     AND    SB.rule_sequence = (SELECT MAX(SB2.rule_sequence)
2037                                FROM   ahl_sb_position_rules SB2
2038                                WHERE  SB2.relationship_id = SB.relationship_id
2039                                AND    EXISTS (SELECT 'X'
2040                                               FROM   ahl_unit_effectivities_b UE
2041                                               WHERE  UE.mr_header_id         = SB2.mr_header_id
2042                                               AND    UE.csi_item_instance_id = UC.csi_item_instance_id
2043                                               AND    UE.accomplished_date    IS NOT NULL))
2044     AND    SB.relationship_id                         = c_relationship_id
2045     AND    TRUNC(NVL(SB.active_start_date, SYSDATE)) <= TRUNC(SYSDATE)
2046     AND    TRUNC(NVL(SB.active_end_date, SYSDATE+1))  > TRUNC(SYSDATE)
2047     UNION ALL
2048     SELECT SB.rule_id,
2049            SB.rule_sequence
2050     FROM   AHL_SB_POSITION_RULES SB,
2051            AHL_VISIT_TASKS_B VT,
2052            AHL_UNIT_CONFIG_HEADERS UC
2053     WHERE  UC.unit_config_header_id = c_uc_header_id
2054     AND    SB.mc_header_id          = UC.master_config_id
2055     -- take only the rules which have MRs attached to the visit
2056     AND    VT.visit_id              = c_visit_id
2057     AND    VT.mr_id                 = SB.mr_header_id
2058     AND    VT.status_code           NOT IN ('CANCELLED', 'DELETED')
2059     -- take only the MAX sequence rules for a position
2060     AND    SB.rule_sequence = (SELECT MAX(SB2.rule_sequence)
2061                                FROM   AHL_SB_POSITION_RULES SB2
2062                                WHERE  SB2.relationship_id = SB.relationship_id
2063                                AND    SB2.mr_header_id    = SB.mr_header_id)
2064     AND    SB.relationship_id                         = c_relationship_id
2065     AND    TRUNC(NVL(SB.active_start_date, SYSDATE)) <= TRUNC(SYSDATE)
2066     AND    TRUNC(NVL(SB.active_end_date, SYSDATE+1))  > TRUNC(SYSDATE)
2067     ) ORDER BY rule_sequence DESC;
2068 
2069 -- Cursor to get allowable sub configuration item group ids for the given position
2070 CURSOR get_sub_config_item_group(c_relationship_id IN NUMBER) IS
2071    SELECT mcr.item_group_id
2072    FROM   ahl_mc_relationships mcr, ahl_mc_config_relations smc
2073    WHERE  mcr.mc_header_id = smc.mc_header_id
2074    AND    mcr.parent_relationship_id is null
2075    AND    smc.relationship_id = c_relationship_id
2076    ORDER BY smc.priority;
2077 
2078 -- Cursor to get Visit Org Id from the visit.
2079 CURSOR get_visit_org_id_cur(c_visit_id IN NUMBER)IS
2080    SELECT organization_id
2081    FROM ahl_visits_b
2082    WHERE visit_id = C_VISIT_ID
2083    AND ( organization_id IS NOT NULL
2084        OR start_date_time IS NOT NULL
2085        OR department_id IS NOT NULL);
2086 
2087 -- Added by SURRKUMA for Service Bulletin on 26-Jul-2011
2088 -- Use to following cursor to check for controlled position with total quantity mc rule.
2089 CURSOR control_position_check_csr(c_mc_header_id IN NUMBER,
2090                                   c_position_key IN NUMBER,
2091                                   c_quantity     IN NUMBER) IS
2092     SELECT  rel.relationship_id, NVL(c_quantity, mcrs.object_attribute1)
2093     FROM    ahl_mc_path_position_nodes mcpp,
2094             ahl_mc_rule_statements mcrs,
2095             ahl_mc_headers_b mch,
2096             ahl_mc_relationships rel,
2097 			ahl_mc_rules_b mcr
2098     WHERE mch.mc_header_id    = c_mc_header_id
2099     AND   mcpp.mc_id          = mch.mc_id
2100     AND   mch.version_number  = NVL(mcpp.version_number, mch.version_number)
2101     AND   mcpp.position_key   = c_position_key
2102     AND   mcrs.subject_id     = mcpp.path_position_id
2103     AND   mcrs.subject_type   = 'POSITION'
2104     AND   mcrs.operator      IN ('MUST_HAVE', 'HAVE')
2105     AND   mcrs.object_type    = 'TOT_CHILD_QUANTITY'
2106     AND   rel.mc_header_id    = c_mc_header_id
2107     AND   rel.position_key    = mcpp.position_key
2108     AND   mch.config_status_code = 'COMPLETE'
2109     AND   NVL(rel.active_end_date, SYSDATE + 1) > SYSDATE
2110 	AND   mcr.rule_id         = mcrs.rule_id
2111     AND   mcr.rule_type_code  = 'MANDATORY'
2112     AND   NVL(mcr.active_start_date, SYSDATE - 1) < SYSDATE
2113     AND   NVL(mcr.active_end_date, SYSDATE + 1) > SYSDATE;
2114 
2115 -- Added by SURRKUMA for Service Bulletin on 26-Jul-2011
2116 -- Use the followig cursor to get the child positions of a parent position.
2117 CURSOR get_child_positions_csr(c_relationship_id IN NUMBER) IS
2118     SELECT mcr.position_key
2119     FROM ahl_mc_relationships mcr
2120     WHERE mcr.parent_relationship_id = c_relationship_id
2121     AND   NVL(mcr.active_end_date, SYSDATE + 1) > SYSDATE
2122     ORDER BY display_order;
2123 
2124 l_api_name       CONSTANT   VARCHAR2(30)   := 'Get_Material_Req_For_Pos';
2125 l_api_version    CONSTANT   NUMBER         := 1.0;
2126 l_mc_header_id   CONSTANT   NUMBER         := p_x_route_mtl_reqs(p_x_index).mc_header_id;
2127 l_rt_oper_mtl_id CONSTANT   NUMBER         := p_x_route_mtl_reqs(p_x_index).rt_oper_material_id;
2128 l_return_status             VARCHAR2(1);
2129 l_msg_count                 NUMBER;
2130 l_relationship_id           NUMBER;
2131 l_sb_rule_id                NUMBER;
2132 l_pos_item_group_id         NUMBER;
2133 l_pos_quantity              NUMBER;
2134 l_pos_uom_code              VARCHAR2(3);
2135 l_ig_quantity               NUMBER;
2136 l_ig_uom_code               VARCHAR2(3);
2137 l_rt_quantity               NUMBER         := p_quantity;
2138 l_uom_code                  VARCHAR2(3);
2139 l_quantity                  NUMBER;
2140 l_visit_org_id              NUMBER;
2141 l_dummy                     NUMBER;
2142 l_cp_relationship_id        NUMBER;
2143 l_remaining_qty             NUMBER         := 0;
2144 l_cp_uom                    VARCHAR2(3)    := p_uom_code;
2145 l_child_position_key        NUMBER;
2146 
2147 L_DEBUG_KEY CONSTANT VARCHAR2(150) := G_LOG_PREFIX || '.Get_Material_Req_For_Pos';
2148 BEGIN
2149     --Initialize API return status to success
2150     x_return_status := FND_API.G_RET_STS_SUCCESS;
2151 
2152     --Standard Start of API savepoint
2153     SAVEPOINT get_material_req_for_pos;
2154 
2155     --Standard call to check for call compatibility.
2156     IF NOT FND_API.compatible_api_call(
2157         l_api_version,
2158         p_api_version,
2159         l_api_name,
2160         G_PKG_NAME)
2161     THEN
2162         RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
2163     END IF;
2164 
2165     --Initialize message list if p_init_msg_list is set to TRUE.
2166     IF FND_API.to_boolean( p_init_msg_list ) THEN
2167         FND_MSG_PUB.initialize;
2168     END IF;
2169 
2170     IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
2171         FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.begin', 'Entering Procedure');
2172     END IF;
2173 
2174     -- Getting the Org Id for given visit
2175     OPEN get_visit_org_id_cur(p_visit_id);
2176     FETCH get_visit_org_id_cur INTO l_visit_org_id;
2177     CLOSE get_visit_org_id_cur;
2178 
2179     IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
2180         FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'mc_header_id: ' || l_mc_header_id ||
2181                                                        ', mc_pos_key: ' || p_x_route_mtl_reqs(p_x_index).position_key ||
2182                                                        ', uc_header_id: '|| p_uc_header_id ||
2183                                                        ', visit_id: '|| p_visit_id ||
2184                                                        ', visit_org_id: '|| l_visit_org_id ||
2185                                                        ', quantity: '|| l_rt_quantity ||
2186                                                        ', uom_code: '|| p_uom_code);
2187     END IF;
2188 
2189     -- Checking whether the position is control position or not.
2190     OPEN control_position_check_csr(l_mc_header_id, p_x_route_mtl_reqs(p_x_index).position_key, l_rt_quantity);
2191     FETCH control_position_check_csr INTO l_cp_relationship_id, l_remaining_qty;
2192     -- If position is control position then use the derived quantity (l_remaining_qty).
2193     -- Else use the quantity defined at route level.
2194     IF (control_position_check_csr%FOUND) THEN
2195         l_rt_quantity := NULL;
2196     ELSE
2197         l_remaining_qty := l_rt_quantity;
2198     END IF;
2199     CLOSE control_position_check_csr;
2200 
2201     -- Get the child positions for the control position.
2202     OPEN get_child_positions_csr(l_cp_relationship_id);
2203     FETCH get_child_positions_csr INTO l_child_position_key;
2204     IF (get_child_positions_csr%FOUND) THEN
2205         p_x_route_mtl_reqs(p_x_index).position_key := l_child_position_key;
2206     END IF;
2207     LOOP
2208         OPEN get_mc_relationship_detail_csr(l_mc_header_id, p_x_route_mtl_reqs(p_x_index).position_key);
2209         FETCH get_mc_relationship_detail_csr INTO l_relationship_id, l_pos_item_group_id, l_pos_quantity, l_pos_uom_code;
2210         CLOSE get_mc_relationship_detail_csr;
2211 
2212         IF (l_relationship_id IS NOT NULL) THEN
2213             -- Position is part of given MC
2214 
2215             IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
2216                 FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Position Key: ' || p_x_route_mtl_reqs(p_x_index).position_key ||
2217                                                                ', Remaining Qty: ' || l_remaining_qty ||
2218                                                                ', l_relationship_id: ' || l_relationship_id ||
2219                                                                ', l_pos_item_group_id: ' || l_pos_item_group_id);
2220             END IF;
2221 
2222             -- Gets Last accomplised SB rule id.
2223             OPEN get_appl_sb_rules_csr (p_uc_header_id, l_relationship_id, p_visit_id);
2224             FETCH get_appl_sb_rules_csr INTO l_sb_rule_id, l_dummy;
2225             CLOSE get_appl_sb_rules_csr;
2226 
2227             p_x_route_mtl_reqs(p_x_index).relationship_id := l_relationship_id;
2228 
2229             -- Deriving the item from the highest priority Sub Config's item group
2230             -- associated to the position for which requirement is created.
2231             -- IF SB rule defined for the position then derive the item from the highest
2232             -- priority Sub Config's item group which has item satifies the SB rule.
2233             FOR l_sc_item_group_id IN get_sub_config_item_group(l_relationship_id) LOOP
2234                 EXIT WHEN p_x_route_mtl_reqs(p_x_index).inventory_item_id IS NOT NULL;
2235 
2236                 Get_Item_Group_Item(
2237                     p_item_group_id     =>  l_sc_item_group_id.item_group_id,
2238                     p_rule_id           =>  l_sb_rule_id,
2239                     p_visit_org_id      =>  l_visit_org_id,
2240                     x_inventory_item_id =>  p_x_route_mtl_reqs(p_x_index).inventory_item_id,
2241                     x_inventory_org_id  =>  p_x_route_mtl_reqs(p_x_index).inv_master_org_id,
2242                     x_quantity          =>  l_ig_quantity,
2243                     x_uom_code          =>  l_ig_uom_code);
2244 
2245             END LOOP;
2246 
2247             -- If no Sub Config defined for the position or the Sub Configs doesn't have an item
2248             -- which satisfies SB rule then derive the item from the position level item group.
2249             IF p_x_route_mtl_reqs(p_x_index).inventory_item_id IS NULL AND l_pos_item_group_id IS NOT NULL THEN
2250 
2251                 Get_Item_Group_Item(
2252                     p_item_group_id     =>  l_pos_item_group_id,
2253                     p_rule_id           =>  l_sb_rule_id,
2254                     p_visit_org_id      =>  l_visit_org_id,
2255                     x_inventory_item_id =>  p_x_route_mtl_reqs(p_x_index).inventory_item_id,
2256                     x_inventory_org_id  =>  p_x_route_mtl_reqs(p_x_index).inv_master_org_id,
2257                     x_quantity          =>  l_ig_quantity,
2258                     x_uom_code          =>  l_ig_uom_code);
2259 
2260             END IF;
2261 
2262             IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
2263                 FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'inventory_item_id: ' || p_x_route_mtl_reqs(p_x_index).inventory_item_id ||
2264                                                                ', inv_master_org_id: ' || p_x_route_mtl_reqs(p_x_index).inv_master_org_id);
2265             END IF;
2266 
2267             IF p_x_route_mtl_reqs(p_x_index).inventory_item_id IS NOT NULL THEN
2268                 -- If quantity and uom code defined at requirement level then convert those to
2269                 -- primary quantity and primary uom code.
2270                 -- Else if quantity and uom code is defined at item group level then convert
2271                 -- those to primary quantity and primary uom code.
2272                 -- Else get the quantity and uom code defined at position level convert those
2273                 -- to primary quantity and primary uom code.
2274                 IF (l_rt_quantity IS NOT NULL AND p_uom_code IS NOT NULL) THEN
2275                     l_quantity := Get_Primary_UOM_Qty(
2276                                         p_x_route_mtl_reqs(p_x_index).inventory_item_id,
2277                                         p_uom_code,
2278                                         l_rt_quantity);
2279                     l_uom_code := p_uom_code;
2280                 ELSIF (l_ig_quantity IS NOT NULL AND l_ig_uom_code IS NOT NULL) THEN
2281                     l_quantity := Get_Primary_UOM_Qty(
2282                                         p_x_route_mtl_reqs(p_x_index).inventory_item_id,
2283                                         l_ig_uom_code,
2284                                         l_ig_quantity);
2285                     l_uom_code := l_ig_uom_code;
2286                 ELSE
2287                     l_quantity := Get_Primary_UOM_Qty(
2288                                         p_x_route_mtl_reqs(p_x_index).inventory_item_id,
2289                                         l_pos_uom_code,
2290                                         l_pos_quantity);
2291                     l_uom_code := l_pos_uom_code;
2292                 END IF;
2293 
2294                 -- Required to check the UOM Conversion exists in mtl_units_of_measure
2295                 IF l_quantity IS NULL THEN
2296                     FND_MESSAGE.Set_Name( 'AHL','AHL_LTP_UOM_CONV_NOT_EXIST' );
2297                     FND_MESSAGE.Set_Token('FUOM', l_uom_code);
2298                     FND_MESSAGE.Set_Token('TUOM', p_x_route_mtl_reqs(p_x_index).uom_code);
2299                     FND_MSG_PUB.add;
2300                     RAISE  FND_API.G_EXC_ERROR;
2301                 END IF;
2302 
2303                 -- Fetching the primary UOM defined for the derived item
2304                 p_x_route_mtl_reqs(p_x_index).uom_code := Get_Primary_UOM(
2305                                                     p_x_route_mtl_reqs(p_x_index).inventory_item_id,
2306                                                     p_x_route_mtl_reqs(p_x_index).inv_master_org_id);
2307                 IF (l_cp_uom IS NULL) THEN
2308                     l_cp_uom := p_x_route_mtl_reqs(p_x_index).uom_code;
2309                 ELSIF l_cp_uom <> p_x_route_mtl_reqs(p_x_index).uom_code THEN
2310                     l_remaining_qty := Get_Primary_UOM_Qty(
2311                                             p_x_route_mtl_reqs(p_x_index).inventory_item_id,
2312                                             l_cp_uom,
2313                                             l_remaining_qty);
2314                     -- Required to check the UOM Conversion exists in mtl_units_of_measure
2315                     IF l_remaining_qty IS NULL THEN
2316                         FND_MESSAGE.Set_Name( 'AHL','AHL_LTP_UOM_CONV_NOT_EXIST' );
2317                         FND_MESSAGE.Set_Token('FUOM', l_cp_uom);
2318                         FND_MESSAGE.Set_Token('TUOM', p_x_route_mtl_reqs(p_x_index).uom_code);
2319                         FND_MSG_PUB.add;
2320                         RAISE  FND_API.G_EXC_ERROR;
2321                     END IF;
2322 
2323                     -- Fetching the primary UOM defined for the derived item
2324                     l_cp_uom := Get_Primary_UOM(
2325                                     p_x_route_mtl_reqs(p_x_index).inventory_item_id,
2326                                     p_x_route_mtl_reqs(p_x_index).inv_master_org_id);
2327                 END IF;
2328                 IF l_remaining_qty IS NULL THEN
2329                     l_remaining_qty := l_quantity;
2330                 END IF;
2331                 -- If the material requirement created for the demanded quantity then
2332                 -- make the remaining quantity as zero. Else subtract the scheduled
2333                 -- quantity from the remaining quantity.
2334                 IF (l_quantity > l_remaining_qty) THEN
2335                     p_x_route_mtl_reqs(p_x_index).quantity := l_remaining_qty;
2336                     l_remaining_qty := 0;
2337                 ELSE
2338                     p_x_route_mtl_reqs(p_x_index).quantity := l_quantity;
2339                     l_remaining_qty := l_remaining_qty - l_quantity;
2340                 END IF;
2341             END IF;
2342         END IF;
2343         -- If material requirement is created for requested quantity then exit.
2344         EXIT WHEN (l_remaining_qty = 0);
2345         FETCH get_child_positions_csr INTO l_child_position_key;
2346         -- If all the child positions were parsed then exit.
2347         EXIT WHEN get_child_positions_csr%NOTFOUND;
2348         -- Setting the route operation id , mc header id and position key for the next child position requirement.
2349         IF p_x_route_mtl_reqs(p_x_index).inventory_item_id IS NOT NULL THEN
2350             p_x_index := p_x_index + 1;
2351             p_x_route_mtl_reqs(p_x_index).rt_oper_material_id := l_rt_oper_mtl_id;
2352             p_x_route_mtl_reqs(p_x_index).MC_HEADER_ID := l_mc_header_id;
2353             p_x_route_mtl_reqs(p_x_index).position_key := l_child_position_key;
2354         END IF;
2355     END LOOP;
2356     CLOSE get_child_positions_csr;
2357     IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
2358         FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Item_Id: ' || p_x_route_mtl_reqs(p_x_index).inventory_item_id ||
2359                                                        ', Org_Id:' || p_x_route_mtl_reqs(p_x_index).inv_master_org_id ||
2360                                                        ', Quantity:' || p_x_route_mtl_reqs(p_x_index).quantity ||
2361                                                        ', UOM:' || p_x_route_mtl_reqs(p_x_index).uom_code);
2362     END IF;
2363 
2364     IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
2365       FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.end', 'Exiting Procedure');
2366     END IF;
2367 
2368     -- Get all the error messages from the previous steps (if any) and raise the appropriate Exception
2369     l_msg_count := FND_MSG_PUB.count_msg;
2370     IF l_msg_count > 0 THEN
2371         x_msg_count := l_msg_count;
2372         RAISE FND_API.G_EXC_ERROR;
2373     END IF;
2374 
2375     -- Count and Get messages (optional)
2376     FND_MSG_PUB.count_and_get(
2377     p_encoded  => FND_API.G_FALSE,
2378     p_count    => x_msg_count,
2379     p_data     => x_msg_data);
2380 
2381 EXCEPTION
2382   WHEN FND_API.G_EXC_ERROR THEN
2383     ROLLBACK TO get_material_req_for_pos;
2384     x_return_status := FND_API.G_RET_STS_ERROR ;
2385     FND_MSG_PUB.count_and_get(
2386       p_encoded  => FND_API.G_FALSE,
2387       p_count    => x_msg_count,
2388       p_data     => x_msg_data);
2389 
2390   WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
2391     ROLLBACK TO get_material_req_for_pos;
2392     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
2393     FND_MSG_PUB.count_and_get(
2394       p_encoded  => FND_API.G_FALSE,
2395       p_count    => x_msg_count,
2396       p_data     => x_msg_data);
2397 
2398   WHEN OTHERS THEN
2399     ROLLBACK TO get_material_req_for_pos;
2400     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
2401     IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR)
2402     THEN
2403       FND_MSG_PUB.add_exc_msg(
2404         p_pkg_name         => G_PKG_NAME,
2405         p_procedure_name   => l_api_name,
2406         p_error_text       => SUBSTRB(SQLERRM,1,240));
2407     END IF;
2408     FND_MSG_PUB.count_and_get(
2409       p_encoded  => FND_API.G_FALSE,
2410       p_count    => x_msg_count,
2411       p_data     => x_msg_data);
2412 
2413 
2414 END Get_Material_Req_For_Pos;
2415 ------------------------------------------------------------------------------------
2416 
2417 ------------------------------------------------------------------------------------
2418 -- Start of Comments
2419 --  Procedure name    : Get_Item_Group_Item
2420 --  Type              : Public
2421 --  Function          : Gets an highest priority item from item group if SB rule doesn't
2422 --                      exists for the position, else get the highest priority item which
2423 --                      satisfies the SB rule condition.
2424 --  Pre-reqs          :
2425 --  Parameters        :
2426 --
2427 --  Get_Item_Group_Item Parameters:
2428 --       p_item_group_id       IN     Given MC header id.                            Required
2429 --       p_rule_id             IN     Given MC position key.                         Required
2430 --       p_visit_org_id        IN     Organisation Id associated to the visit        Optional
2431 --  End of Comments
2432 
2433 PROCEDURE Get_Item_Group_Item(
2434     p_item_group_id         IN            NUMBER,
2435     p_rule_id               IN            NUMBER,
2436     p_visit_org_id          IN            NUMBER,
2437     x_inventory_item_id     OUT   NOCOPY  NUMBER,
2438     x_inventory_org_id      OUT   NOCOPY  NUMBER,
2439     x_quantity              OUT   NOCOPY  NUMBER,
2440     x_uom_code              OUT   NOCOPY  VARCHAR2
2441 ) IS
2442 -- To Get highest priority item when SB is not present
2443   CURSOR get_item_group_item_csr IS
2444     SELECT ia.inventory_item_id, NVL(p_visit_org_id, ia.inventory_org_id), ia.quantity, ia.uom_code
2445     FROM ahl_item_associations_b ia, mtl_system_items_b msi
2446     WHERE  ia.item_group_id         = p_item_group_id
2447     AND    ia.interchange_type_code = '2-WAY INTERCHANGEABLE'
2448     AND    ia.inventory_item_id     = msi.inventory_item_id
2449     AND    msi.organization_id      = NVL(p_visit_org_id, ia.inventory_org_id)
2450     ORDER BY ia.priority;
2451 
2452 -- To Get the highest priority item when SB is present
2453 CURSOR get_item_group_sb_item_csr IS
2454    SELECT ia.inventory_item_id, NVL(p_visit_org_id, ia.inventory_org_id), ia.quantity, ia.uom_code
2455    FROM   ahl_item_associations_b ia, mtl_system_items_b msi
2456    WHERE  ia.item_group_id         = p_item_group_id
2457    AND    ia.interchange_type_code = '2-WAY INTERCHANGEABLE'
2458    AND    ia.inventory_item_id     = msi.inventory_item_id
2459    AND    msi.organization_id      = NVL(p_visit_org_id, ia.inventory_org_id)
2460    AND    ia.item_association_id   IN (SELECT item_association_id
2461                                        FROM   ahl_sb_rule_items
2462                                        WHERE  rule_id = p_rule_id
2463                                        AND    item_group_id = p_item_group_id)
2464    ORDER BY ia.priority;
2465 
2466 L_DEBUG_KEY CONSTANT VARCHAR2(150) := G_LOG_PREFIX || '.Get_Item_Group_Item';
2467 BEGIN
2468     IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
2469         FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.begin', 'Entering Procedure');
2470     END IF;
2471 
2472     IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
2473         FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'p_item_group_id: ' || p_item_group_id ||
2474                                                        ', p_rule_id: ' || p_rule_id||
2475                                                        ', p_visit_org_id' || p_visit_org_id);
2476     END IF;
2477 
2478     IF ( p_item_group_id IS NULL ) THEN
2479         RETURN;
2480     END IF;
2481 
2482     -- If SB rule is not defined then get the highest priority item from the item group.
2483     -- Else, get the highest priority item which satisfies the SB rule.
2484     IF (p_rule_id IS NULL) THEN
2485         OPEN get_item_group_item_csr;
2486         FETCH get_item_group_item_csr INTO x_inventory_item_id, x_inventory_org_id, x_quantity, x_uom_code;
2487         CLOSE get_item_group_item_csr;
2488     ELSE
2489         OPEN get_item_group_sb_item_csr;
2490         FETCH get_item_group_sb_item_csr INTO x_inventory_item_id, x_inventory_org_id, x_quantity, x_uom_code;
2491         CLOSE get_item_group_sb_item_csr;
2492     END IF;
2493 
2494     IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
2495       FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.end', 'Exiting Procedure');
2496     END IF;
2497 END Get_Item_Group_Item;
2498 
2499 ------------------------------------------------------------------------------------
2500 
2501 ------------------------------------------------------------------------------------
2502 -- Start of Comments
2503 --  Procedure name    : Get_Alternate_Items
2504 --  Type              : Public
2505 --  Function          : Gets all the applicable alternate items for given ahl_schedule_material
2506 --                      requirement.
2507 --  Pre-reqs          :
2508 --  Parameters        :
2509 --
2510 --  Get_Alternate_Items Parameters:
2511 --       p_schedule_material_id         IN      NUMBER               schedule material id   Required
2512 --       x_alt_items                       OUT  Alt_Items_Tbl_Type   Alternate Items for material requirement
2513 --  End of Comments
2514 PROCEDURE Get_Alternate_Items(
2515     p_api_version                 IN             NUMBER,
2516     p_init_msg_list               IN             VARCHAR2  := FND_API.G_FALSE,
2517     p_validation_level            IN             NUMBER    := FND_API.G_VALID_LEVEL_FULL,
2518     p_schedule_material_id        IN             NUMBER,
2519     p_curr_item_flag              IN             VARCHAR2  := FND_API.G_FALSE,
2520     x_alt_items                      OUT  NOCOPY Alt_Items_Tbl_Type,
2521     x_return_status                  OUT  NOCOPY VARCHAR2,
2522     x_msg_count                      OUT  NOCOPY NUMBER,
2523     x_msg_data                       OUT  NOCOPY VARCHAR2
2524 ) IS
2525 
2526 -- Cursor to get the details from ahl_schedule_materials table
2527 CURSOR get_asm_req_details_csr(c_asm_id IN NUMBER) IS
2528    SELECT asm.mc_header_id,
2529           asm.position_key,
2530           asm.inventory_item_id,
2531           asm.visit_id,
2532           asm.visit_task_id,
2533           asm.item_group_id,
2534           asm.organization_id,
2535           asm.relationship_id,
2536           vt.instance_id
2537    FROM   ahl_schedule_materials asm,
2538           ahl_visit_tasks_b vt
2539    WHERE  asm.scheduled_material_id = c_asm_id
2540    AND    vt.visit_task_id          = asm.visit_task_id;
2541 
2542 -- Cursor to get the UC header Id from the instance Id
2543 CURSOR get_uc_header_csr(c_instance_id IN NUMBER) IS
2544    SELECT unit_config_header_id uc_header_id
2545    FROM   ahl_unit_config_headers
2546    WHERE  csi_item_instance_id = c_instance_id;
2547 
2548 -- cursor to get applicable SB rules for the given unit and position
2549 -- NOTE::Fetch only once from this cursor. UNION ALL is fine as it will be fetched only once.
2550 CURSOR get_appl_sb_rules_csr (c_uc_header_id    NUMBER,
2551                               c_relationship_id NUMBER,
2552                               c_visit_id        NUMBER) IS
2553     SELECT DISTINCT rule_id,
2554                     rule_sequence
2555     FROM (
2556     SELECT SB.rule_id,
2557            SB.rule_sequence
2558     FROM   ahl_sb_position_rules SB,
2559            ahl_unit_config_headers UC
2560     WHERE  UC.unit_config_header_id = c_uc_header_id
2561     AND    SB.mc_header_id          = UC.master_config_id
2562     -- take only the rules which have MRs accomplished on the unit
2563     AND    EXISTS (SELECT 'X'
2564                    FROM   ahl_unit_effectivities_b UE
2565                    WHERE  UE.mr_header_id         = SB.mr_header_id
2566                    AND    UE.csi_item_instance_id = UC.csi_item_instance_id -- SB MRs are effective on root node
2567                    AND    UE.accomplished_date    IS NOT NULL)
2568     -- take only the MAX sequence rules for a position, among the accomplished MRs
2569     AND    SB.rule_sequence = (SELECT MAX(SB2.rule_sequence)
2570                                FROM   ahl_sb_position_rules SB2
2571                                WHERE  SB2.relationship_id = SB.relationship_id
2572                                AND    EXISTS (SELECT 'X'
2573                                               FROM   ahl_unit_effectivities_b UE
2574                                               WHERE  UE.mr_header_id         = SB2.mr_header_id
2575                                               AND    UE.csi_item_instance_id = UC.csi_item_instance_id
2576                                               AND    UE.accomplished_date    IS NOT NULL))
2577     AND    SB.relationship_id                         = c_relationship_id
2578     AND    TRUNC(NVL(SB.active_start_date, SYSDATE)) <= TRUNC(SYSDATE)
2579     AND    TRUNC(NVL(SB.active_end_date, SYSDATE+1))  > TRUNC(SYSDATE)
2580     UNION ALL
2581     SELECT SB.rule_id,
2582            SB.rule_sequence
2583     FROM   AHL_SB_POSITION_RULES SB,
2584            AHL_VISIT_TASKS_B VT,
2585            AHL_UNIT_CONFIG_HEADERS UC
2586     WHERE  UC.unit_config_header_id = c_uc_header_id
2587     AND    SB.mc_header_id          = UC.master_config_id
2588     -- take only the rules which have MRs attached to the visit
2589     AND    VT.visit_id              = c_visit_id
2590     AND    VT.mr_id                 = SB.mr_header_id
2591     AND    VT.status_code           NOT IN ('CANCELLED', 'DELETED')
2592     -- take only the MAX sequence rules for a position
2593     AND    SB.rule_sequence = (SELECT MAX(SB2.rule_sequence)
2594                                FROM   AHL_SB_POSITION_RULES SB2
2595                                WHERE  SB2.relationship_id = SB.relationship_id
2596                                AND    SB2.mr_header_id    = SB.mr_header_id)
2597     AND    SB.relationship_id                         = c_relationship_id
2598     AND    TRUNC(NVL(SB.active_start_date, SYSDATE)) <= TRUNC(SYSDATE)
2599     AND    TRUNC(NVL(SB.active_end_date, SYSDATE+1))  > TRUNC(SYSDATE)
2600     ) ORDER BY rule_sequence DESC;
2601 
2602 -- Cursor to get all the applicable alternate items if the requirement is
2603 -- Item Group based.
2604 CURSOR get_alt_items_ig_csr(c_item_group_id     IN NUMBER,
2605                             c_inventory_item_id IN NUMBER,
2606                             c_organization_id   IN NUMBER) IS
2607    SELECT ia.inventory_item_id
2608    FROM ahl_item_associations_b ia,
2609         mtl_system_items_b msi
2610    WHERE  ia.item_group_id         = c_item_group_id
2611    AND    ia.interchange_type_code = '2-WAY INTERCHANGEABLE'
2612    AND    ia.inventory_item_id     = msi.inventory_item_id
2613    AND    msi.organization_id      = c_organization_id
2614    AND    ia.inventory_item_id     <> nvl(c_inventory_item_id, -1)
2615    ORDER BY ia.priority;
2616 
2617 -- Cursor to get all the applicable alternate items if the requirement is
2618 -- position based and no SB rule accomplished for that position
2619 CURSOR get_alt_items_pos_csr(c_relationship_id   IN NUMBER,
2620                              c_inventory_item_id IN NUMBER,
2621                              c_organization_id   IN NUMBER) IS
2622    SELECT ia.inventory_item_id,
2623           smc.priority smc_priority,
2624           ia.priority item_priority
2625    FROM   ahl_item_associations_b ia,
2626           mtl_system_items_b msi,
2627           ahl_mc_relationships mcr,
2628           ahl_mc_config_relations smc
2629    WHERE  mcr.mc_header_id = smc.mc_header_id
2630    AND    mcr.parent_relationship_id is null
2631    AND    smc.relationship_id = c_relationship_id
2632    AND    ia.item_group_id    = mcr.item_group_id
2633    AND    ia.interchange_type_code = '2-WAY INTERCHANGEABLE'
2634    AND    ia.inventory_item_id     = msi.inventory_item_id
2635    AND    msi.organization_id      = c_organization_id
2636    AND    ia.inventory_item_id     <> nvl(c_inventory_item_id,-1)
2637    UNION
2638    SELECT ia.inventory_item_id,
2639           TO_NUMBER(NULL) AS smc_priority,
2640           ia.priority item_priority
2641    FROM   ahl_item_associations_b ia,
2642           mtl_system_items_b msi,
2643           ahl_mc_relationships mcr
2644    WHERE  mcr.relationship_id = c_relationship_id
2645    AND    ia.item_group_id    = mcr.item_group_id
2646    AND    ia.interchange_type_code = '2-WAY INTERCHANGEABLE'
2647    AND    ia.inventory_item_id     = msi.inventory_item_id
2648    AND    msi.organization_id      = c_organization_id
2649    AND    ia.inventory_item_id     <> nvl(c_inventory_item_id,-1)
2650    order by smc_priority, item_priority;
2651 
2652 -- Cursor to get all the applicable alternate items if the requirement is
2653 -- position based and a SB rule accomplished for that position
2654 CURSOR get_alt_items_sb_pos_csr(c_relationship_id   IN NUMBER,
2655                                 c_inventory_item_id IN NUMBER,
2656                                 c_organization_id   IN NUMBER,
2657                                 c_sb_rule_id        IN NUMBER) IS
2658    SELECT ia.inventory_item_id,
2659           smc.priority smc_priority,
2660           ia.priority item_priority
2661    FROM   ahl_item_associations_b ia,
2662           mtl_system_items_b msi,
2663           ahl_mc_relationships mcr,
2664           ahl_mc_config_relations smc
2665    WHERE  mcr.mc_header_id = smc.mc_header_id
2666    AND    mcr.parent_relationship_id is null
2667    AND    smc.relationship_id = c_relationship_id
2668    AND    ia.item_group_id    = mcr.item_group_id
2669    AND    ia.interchange_type_code = '2-WAY INTERCHANGEABLE'
2670    AND    ia.inventory_item_id     = msi.inventory_item_id
2671    AND    msi.organization_id      = c_organization_id
2672    AND    ia.inventory_item_id     <> nvl(c_inventory_item_id, -1)
2673    AND    ia.item_association_id   IN (SELECT item_association_id
2674                                        FROM   ahl_sb_rule_items
2675                                        WHERE  rule_id = c_sb_rule_id
2676                                        AND    item_group_id = mcr.item_group_id)
2677    UNION
2678    SELECT ia.inventory_item_id,
2679           TO_NUMBER(NULL) AS smc_priority,
2680           ia.priority item_priority
2681    FROM   ahl_item_associations_b ia,
2682           mtl_system_items_b msi,
2683           ahl_mc_relationships mcr
2684    WHERE  mcr.relationship_id = c_relationship_id
2685    AND    ia.item_group_id    = mcr.item_group_id
2686    AND    ia.interchange_type_code = '2-WAY INTERCHANGEABLE'
2687    AND    ia.inventory_item_id     = msi.inventory_item_id
2688    AND    msi.organization_id      = c_organization_id
2689    AND    ia.inventory_item_id     <> nvl(c_inventory_item_id, -1)
2690    AND    ia.item_association_id   IN (SELECT item_association_id
2691                                        FROM   ahl_sb_rule_items
2692                                        WHERE  rule_id = c_sb_rule_id
2693                                        AND    item_group_id = mcr.item_group_id)
2694    order by smc_priority, item_priority;
2695 
2696 l_api_name       CONSTANT   VARCHAR2(30)   := 'Get_Alternate_Items';
2697 l_api_version    CONSTANT   NUMBER         := 1.0;
2698 L_DEBUG_KEY      CONSTANT   VARCHAR2(150)  := G_LOG_PREFIX || '.Get_Alternate_Items';
2699 l_msg_count                 NUMBER;
2700 l_asm_req_rec               get_asm_req_details_csr%ROWTYPE;
2701 l_instance_id               NUMBER;
2702 l_uc_header_id              NUMBER;
2703 l_index                     NUMBER         := 1;
2704 l_dummy                     NUMBER;
2705 l_sb_rule_id                NUMBER;
2706 l_inventory_item_id         NUMBER         := NULL;
2707 l_duplicate_item            BOOLEAN        := FALSE;
2708 BEGIN
2709 --Initialize API return status to success
2710     x_return_status := FND_API.G_RET_STS_SUCCESS;
2711 
2712     --Standard call to check for call compatibility.
2713     IF NOT FND_API.compatible_api_call(
2714         l_api_version,
2715         p_api_version,
2716         l_api_name,
2717         G_PKG_NAME)
2718     THEN
2719         RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
2720     END IF;
2721 
2722     --Initialize message list if p_init_msg_list is set to TRUE.
2723     IF FND_API.to_boolean( p_init_msg_list ) THEN
2724         FND_MSG_PUB.initialize;
2725     END IF;
2726 
2727     IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
2728         FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.begin', 'Entering Procedure');
2729     END IF;
2730 
2731     IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
2732         FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Schedule Material ID: '|| p_schedule_material_id);
2733     END IF;
2734 
2735     IF p_schedule_material_id IS NULL THEN
2736         Fnd_Message.SET_NAME('AHL','AHL_LTP_MAT_ID_INVALID');
2737         Fnd_Msg_Pub.ADD;
2738         RAISE Fnd_Api.G_EXC_ERROR;
2739     END IF;
2740 
2741     OPEN get_asm_req_details_csr(p_schedule_material_id);
2742     FETCH get_asm_req_details_csr INTO l_asm_req_rec;
2743     IF get_asm_req_details_csr%NOTFOUND THEN
2744         Fnd_Message.SET_NAME('AHL','AHL_LTP_MAT_ID_INVALID');
2745         Fnd_Msg_Pub.ADD;
2746         CLOSE get_asm_req_details_csr;
2747         RAISE Fnd_Api.G_EXC_ERROR;
2748     END IF;
2749     CLOSE get_asm_req_details_csr;
2750 
2751     IF p_curr_item_flag IS NOT NULL AND p_curr_item_flag = FND_API.G_TRUE THEN
2752        l_inventory_item_id := NULL;
2753     ELSE
2754        l_inventory_item_id := l_asm_req_rec.inventory_item_id;
2755     END IF;
2756 
2757     l_instance_id := Get_Unit_Instance(l_asm_req_rec.instance_id);
2758 
2759     OPEN get_uc_header_csr(l_instance_id);
2760     FETCH get_uc_header_csr INTO l_uc_header_id;
2761     CLOSE get_uc_header_csr;
2762 
2763     IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
2764         FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'mc_header_id: ' || l_asm_req_rec.mc_header_id ||
2765                                                        ', mc_pos_key: ' || l_asm_req_rec.position_key ||
2766                                                        ', Inventory Item Id: ' || l_asm_req_rec.inventory_item_id ||
2767                                                        ', uc_header_id: '|| l_uc_header_id ||
2768                                                        ', visit_id: '|| l_asm_req_rec.visit_id ||
2769                                                        ', visit_org_id: '|| l_asm_req_rec.organization_id ||
2770                                                        ', visit_task_id: '|| l_asm_req_rec.visit_task_id ||
2771                                                        ', relationship_id: '|| l_asm_req_rec.relationship_id ||
2772                                                        ', item_group_id: '|| l_asm_req_rec.item_group_id);
2773     END IF;
2774 
2775     -- Item Group Based Requirement
2776     IF l_asm_req_rec.item_group_id IS NOT NULL THEN
2777         FOR inv_item_id_rec IN get_alt_items_ig_csr(l_asm_req_rec.item_group_id,
2778                                                     l_inventory_item_id,
2779                                                     l_asm_req_rec.organization_id)
2780         LOOP
2781             x_alt_items(l_index) := inv_item_id_rec.inventory_item_id;
2782             l_index := l_index + 1;
2783         END LOOP;
2784     -- Position Based Material Requirement
2785     ELSIF l_asm_req_rec.mc_header_id IS NOT NULL AND l_asm_req_rec.position_key IS NOT NULL THEN
2786         -- Gets Last accomplised SB rule id.
2787         OPEN get_appl_sb_rules_csr (l_uc_header_id, l_asm_req_rec.relationship_id, l_asm_req_rec.visit_id);
2788         FETCH get_appl_sb_rules_csr INTO l_sb_rule_id, l_dummy;
2789         CLOSE get_appl_sb_rules_csr;
2790 
2791         -- If no SB rule is accomplished or applicable for current position
2792         IF l_sb_rule_id IS NULL THEN
2793             FOR inv_item_id_rec IN get_alt_items_pos_csr(l_asm_req_rec.relationship_id,
2794                                                          l_inventory_item_id,
2795                                                          l_asm_req_rec.organization_id)
2796             LOOP
2797                 l_duplicate_item := FALSE;
2798                 -- Don't insert into the alt_items table if the inventory item is already
2799                 -- present
2800                 FOR i IN 1 .. x_alt_items.COUNT
2801                 LOOP
2802                     IF x_alt_items(i) = inv_item_id_rec.inventory_item_id THEN
2803                         l_duplicate_item := TRUE;
2804                     END IF;
2805                     EXIT WHEN (l_duplicate_item = TRUE);
2806                 END LOOP;
2807                 IF l_duplicate_item = FALSE THEN
2808                     x_alt_items(l_index) := inv_item_id_rec.inventory_item_id;
2809                     l_index := l_index + 1;
2810                 END IF;
2811             END LOOP;
2812         -- If SB rule accomplished for that position
2813         ELSE
2814             FOR inv_item_id_rec IN get_alt_items_sb_pos_csr(l_asm_req_rec.relationship_id,
2815                                                             l_inventory_item_id,
2816                                                             l_asm_req_rec.organization_id,
2817                                                             l_sb_rule_id)
2818             LOOP
2819                 l_duplicate_item := FALSE;
2820                 -- Don't insert into the alt_items table if the inventory item is already
2821                 -- present
2822                 FOR i IN 1 .. x_alt_items.COUNT
2823                 LOOP
2824                     IF x_alt_items(i) = inv_item_id_rec.inventory_item_id THEN
2825                         l_duplicate_item := TRUE;
2826                     END IF;
2827                     EXIT WHEN (l_duplicate_item = TRUE);
2828                 END LOOP;
2829                 IF l_duplicate_item = FALSE THEN
2830                     x_alt_items(l_index) := inv_item_id_rec.inventory_item_id;
2831                     l_index := l_index + 1;
2832                 END IF;
2833             END LOOP;
2834         END IF;
2835     END IF;
2836 
2837     IF (G_LEVEL_STATEMENT >= G_CURRENT_RUNTIME_LEVEL) THEN
2838         FND_LOG.STRING(G_LEVEL_STATEMENT, L_DEBUG_KEY, 'Alt Items Count: '|| x_alt_items.COUNT );
2839     END IF;
2840 
2841     IF (G_LEVEL_PROCEDURE >= G_CURRENT_RUNTIME_LEVEL) THEN
2842         FND_LOG.STRING(G_LEVEL_PROCEDURE, L_DEBUG_KEY || '.end', 'Exiting Procedure');
2843     END IF;
2844 
2845     -- Get all the error messages from the previous steps (if any) and raise the appropriate Exception
2846     l_msg_count := FND_MSG_PUB.count_msg;
2847     IF l_msg_count > 0 THEN
2848         x_msg_count := l_msg_count;
2849         RAISE FND_API.G_EXC_ERROR;
2850     END IF;
2851 
2852     -- Count and Get messages (optional)
2853     FND_MSG_PUB.count_and_get(
2854     p_encoded  => FND_API.G_FALSE,
2855     p_count    => x_msg_count,
2856     p_data     => x_msg_data);
2857 
2858 EXCEPTION
2859   WHEN FND_API.G_EXC_ERROR THEN
2860     x_return_status := FND_API.G_RET_STS_ERROR ;
2861     FND_MSG_PUB.count_and_get(
2862       p_encoded  => FND_API.G_FALSE,
2863       p_count    => x_msg_count,
2864       p_data     => x_msg_data);
2865 
2866   WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
2867     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
2868     FND_MSG_PUB.count_and_get(
2869       p_encoded  => FND_API.G_FALSE,
2870       p_count    => x_msg_count,
2871       p_data     => x_msg_data);
2872 
2873   WHEN OTHERS THEN
2874     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
2875     IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR)
2876     THEN
2877       FND_MSG_PUB.add_exc_msg(
2878         p_pkg_name         => G_PKG_NAME,
2879         p_procedure_name   => l_api_name,
2880         p_error_text       => SUBSTRB(SQLERRM,1,240));
2881     END IF;
2882     FND_MSG_PUB.count_and_get(
2883       p_encoded  => FND_API.G_FALSE,
2884       p_count    => x_msg_count,
2885       p_data     => x_msg_data);
2886 END Get_Alternate_Items;
2887 ------------------------------------------------------------------------------------
2888 
2889 ------------------------------------
2890 -- End Local Function Definitions --
2891 ------------------------------------
2892 
2893 END AHL_LTP_MTL_REQ_PVT;