DBA Data[Home] [Help]

PACKAGE BODY: APPS.AHL_UC_TREE_PVT

Source


1 PACKAGE BODY AHL_UC_TREE_PVT AS
2 /* $Header: AHLVUCTB.pls 120.3.12020000.2 2012/12/07 15:42:28 sareepar ship $ */
3 
4 -- Define global internal variables and cursors
5 G_PKG_NAME VARCHAR2(30) := 'AHL_UC_TREE_PVT';
6 
7 ------------------------------------------------------------------------------------
8 -- Common variables
9 ------------------------------------------------------------------------------------
10 l_log_current_level        NUMBER       := FND_LOG.g_current_runtime_level;
11 l_log_statement            NUMBER       := FND_LOG.level_statement;
12 l_log_procedure            NUMBER       := FND_LOG.level_procedure;
13 l_log_error                NUMBER       := FND_LOG.level_error;
14 l_log_exception            NUMBER       := FND_LOG.level_exception;
15 l_log_unexpected           NUMBER       := FND_LOG.level_unexpected;
16 ------------------------------------------------------------------------------------
17 
18 -- Added by rbhavsar on July 25, 2007 to remap IB Tree Nodes to fix FP bug 6276991
19 TYPE T_ID_TBL IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
20 
21 PROCEDURE Remap_IB_Tree(p_instance_id     IN  NUMBER,
22                         p_relationship_id IN  NUMBER);
23 
24 PROCEDURE Process_instances(p_x_extra_instances_tbl IN OUT NOCOPY T_ID_TBL,
25                             p_x_relations_tbl       IN OUT NOCOPY T_ID_TBL);
26 
27 -- Define procedure get_immediate_children
28 -- This API is used to draw the UC tree. For a given node, it will list all of its
29 -- immediate children nodes.
30 /*
31 PROCEDURE get_immediate_children(
32   p_api_version           IN  NUMBER := 1.0,
33   p_init_msg_list         IN  VARCHAR2 := FND_API.G_FALSE,
34   --p_commit                IN  VARCHAR2 := FND_API.G_FALSE,
35   p_validation_level      IN  NUMBER := FND_API.G_VALID_LEVEL_FULL,
36   x_return_status         OUT NOCOPY VARCHAR2,
37   x_msg_count             OUT NOCOPY NUMBER,
38   x_msg_data              OUT NOCOPY VARCHAR2,
39   p_uc_parent_rec         IN  uc_child_rec_type,
40   x_uc_child_tbl          OUT NOCOPY uc_child_tbl_type)
41 IS
42   l_api_name       CONSTANT   VARCHAR2(30)   := 'get_immediate_children';
43   l_api_version    CONSTANT   NUMBER         := 1.0;
44   l_return_status             VARCHAR2(1);
45   l_msg_count                 NUMBER;
46   l_relationship_id           NUMBER;
47   l_children_no               NUMBER;
48   l_dummy                     VARCHAR2(1);
49   i                           NUMBER;
50   CURSOR check_installed_instance IS
51     SELECT 'x'
52       FROM ahl_unit_config_headers U,
53            ahl_mc_relationships R
54      WHERE U.master_config_id = R.mc_header_id
55        AND R.parent_relationship_id IS NULL
56        AND U.csi_item_instance_id = p_uc_parent_rec.instance_id
57        AND R.relationship_id = p_uc_parent_rec.relationship_id
58        AND nvl(trunc(U.active_end_date), trunc(SYSDATE)+1) > trunc(SYSDATE)
59      UNION
60     SELECT 'x'
61       FROM csi_ii_relationships
62      WHERE subject_id =  p_uc_parent_rec.instance_id
63        AND position_reference = to_char(p_uc_parent_rec.relationship_id)
64        AND nvl(trunc(active_end_date), trunc(SYSDATE)+1) > trunc(SYSDATE);
65   CURSOR check_relationship IS
66     SELECT 'x'
67       FROM ahl_mc_relationships
68      WHERE relationship_id = p_uc_parent_rec.relationship_id;
69   CURSOR check_instance IS
70     SELECT 'x'
71       FROM csi_item_instances
72      WHERE instance_id = p_uc_parent_rec.instance_id;
73   CURSOR get_top_position(c_instance_id number) IS
74     SELECT B.relationship_id
75       FROM ahl_unit_config_headers A,
76            ahl_mc_relationships B
77      WHERE A.master_config_id = B.mc_header_id
78        AND B.parent_relationship_id IS NULL
79        AND A.csi_item_instance_id = c_instance_id;
80   -- get immediate children for installed node
81   CURSOR get_child_nodes_i(c_instance_id number, c_relationship_id number) IS
82     SELECT 'X' node_type, subject_id instance_id, NULL relationship_id
83       FROM csi_ii_relationships
84      WHERE object_id = c_instance_id
85        AND position_reference IS NULL
86      UNION
87     SELECT 'I' node_type, subject_id instance_id, to_number(position_reference) relationship_id
88       FROM csi_ii_relationships
89      WHERE object_id = c_instance_id
90        AND position_reference IS NOT NULL
91        AND nvl(trunc(active_end_date), trunc(SYSDATE)+1) > trunc(SYSDATE)
92      UNION
93     SELECT 'E' node_type, NULL instance_id, relationship_id
94       FROM ahl_mc_relationships
95      WHERE parent_relationship_id = c_relationship_id
96        AND relationship_id NOT IN (SELECT position_reference
97                                      FROM csi_ii_relationships
98                                     WHERE object_id = c_instance_id
99                                       AND position_reference IS NOT NULL
100                                       AND nvl(trunc(active_end_date), trunc(SYSDATE)+1) > trunc(SYSDATE));
101   l_get_child_nodes_i         get_child_nodes_i%ROWTYPE;
102   -- get immediate children for empty node
103   CURSOR get_child_nodes_m(c_relationship_id number) IS
104     SELECT 'E' node_type, NULL instance_id, relationship_id
105       FROM ahl_mc_relationships
106      WHERE parent_relationship_id = c_relationship_id;
107   -- get immediate children for extra node
108   CURSOR get_child_nodes_x(c_instance_id number) IS
109     SELECT 'X' node_type, subject_id instance_id, to_number(position_reference) relationship_id
110       FROM csi_ii_relationships
111      WHERE object_id  = c_instance_id
112        AND nvl(trunc(active_end_date), trunc(SYSDATE)+1) > trunc(SYSDATE);
113 BEGIN
114   -- Initialize API return status to success
115   x_return_status := FND_API.G_RET_STS_SUCCESS;
116 
117   -- Standard call to check for call compatibility.
118   IF NOT FND_API.compatible_api_call(
119     l_api_version,
120     p_api_version,
121     l_api_name,
122     G_PKG_NAME)
123   THEN
124     RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
125   END IF;
126 
127   -- Initialize message list if p_init_msg_list is set to TRUE.
128   IF FND_API.to_boolean( p_init_msg_list ) THEN
129     FND_MSG_PUB.initialize;
130   END IF;
131 
132   IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
133 	FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
134                    'ahl.plsql.'||G_PKG_NAME||'.'||l_api_name||': Begin API',
135 			       'At the start of the procedure');
136   END IF;
137 
138   -- Validate the input parameter
139   IF (p_uc_parent_rec.node_type IS NULL OR p_uc_parent_rec.node_type NOT IN ('I', 'E', 'X') OR
140       (p_uc_parent_rec.instance_id IS NULL AND p_uc_parent_rec.relationship_id IS NULL))THEN
141     FND_MESSAGE.set_name( 'AHL','AHL_UC_NODE_INVALID' );
142     FND_MSG_PUB.add;
143   END IF;
144   IF p_uc_parent_rec.node_type = 'I' THEN
145     IF p_uc_parent_rec.instance_id IS NULL OR p_uc_parent_rec.relationship_id IS NULL THEN
146       FND_MESSAGE.set_name( 'AHL','AHL_UC_NODE_INVALID' );
147       FND_MSG_PUB.add;
148     ELSE
149       OPEN check_installed_instance;
150       FETCH check_installed_instance INTO l_dummy;
151       IF check_installed_instance%NOTFOUND THEN
152         FND_MESSAGE.set_name( 'AHL','AHL_UC_NODE_INVALID' );
153         FND_MSG_PUB.add;
154       END IF;
155       CLOSE check_installed_instance;
156     END IF;
157   ELSIF p_uc_parent_rec.node_type = 'M' THEN
158     IF p_uc_parent_rec.instance_id IS NOT NULL OR p_uc_parent_rec.relationship_id IS NULL THEN
159       FND_MESSAGE.set_name( 'AHL','AHL_UC_NODE_INVALID' );
160       FND_MSG_PUB.add;
161     ELSE
162       OPEN check_relationship;
163       FETCH check_relationship INTO l_dummy;
164       IF check_relationship%NOTFOUND THEN
165         FND_MESSAGE.set_name( 'AHL','AHL_UC_NODE_INVALID' );
166         FND_MSG_PUB.add;
167       END IF;
168       CLOSE check_relationship;
169     END IF;
170   ELSIF p_uc_parent_rec.node_type = 'X' THEN
171     IF p_uc_parent_rec.instance_id IS NULL THEN
172       FND_MESSAGE.set_name( 'AHL','AHL_UC_NODE_INVALID' );
173       FND_MSG_PUB.add;
174     ELSE
175       OPEN check_instance;
176       FETCH check_instance INTO l_dummy;
177       IF check_instance%NOTFOUND THEN
178         FND_MESSAGE.set_name( 'AHL','AHL_UC_NODE_INVALID' );
179         FND_MSG_PUB.add;
180       END IF;
181       CLOSE check_instance;
182     END IF;
183   END IF;
184   -- If the node is a sub-UC's top node, then replace the relationship_id (leaf node
185   -- of its parent UC) with its own relationship_id (sub-UC's top node)
186   OPEN get_top_position(p_uc_parent_rec.instance_id);
187   FETCH get_top_position INTO l_relationship_id;
188   IF get_top_position%NOTFOUND THEN
189     l_relationship_id := p_uc_parent_rec.relationship_id;
190   END IF;
191   CLOSE get_top_position;
192   i := 1;
193   IF p_uc_parent_rec.node_type = 'I' THEN
194     FOR l_get_child_nodes IN get_child_nodes_i(p_uc_parent_rec.instance_id, l_relationship_id) LOOP
195       x_uc_child_tbl(i).node_type := l_get_child_nodes.node_type;
196       x_uc_child_tbl(i).instance_id := l_get_child_nodes.instance_id;
197       x_uc_child_tbl(i).relationship_id := l_get_child_nodes.relationship_id;
198       i := i+1;
199     END LOOP;
200   ELSIF p_uc_parent_rec.node_type = 'M' THEN
201     FOR l_get_child_nodes IN get_child_nodes_m(l_relationship_id) LOOP
202       x_uc_child_tbl(i).node_type := l_get_child_nodes.node_type;
203       x_uc_child_tbl(i).instance_id := l_get_child_nodes.instance_id;
204       x_uc_child_tbl(i).relationship_id := l_get_child_nodes.relationship_id;
205       i := i+1;
206     END LOOP;
207   ELSIF p_uc_parent_rec.node_type = 'X' THEN
208     FOR l_get_child_nodes IN get_child_nodes_x(p_uc_parent_rec.instance_id) LOOP
209       x_uc_child_tbl(i).node_type := l_get_child_nodes.node_type;
210       x_uc_child_tbl(i).instance_id := l_get_child_nodes.instance_id;
211       x_uc_child_tbl(i).relationship_id := l_get_child_nodes.relationship_id;
212       i := i+1;
213     END LOOP;
214   END IF;
215   IF x_uc_child_tbl.COUNT >0 THEN
216     FOR j IN x_uc_child_tbl.FIRST .. x_uc_child_tbl.LAST LOOP
217       IF x_uc_child_tbl(j).node_type = 'I' THEN
218         x_uc_child_tbl(j).has_subconfig_flag := 'N';
219         OPEN get_top_position(x_uc_child_tbl(j).instance_id);
220         FETCH get_top_position INTO l_relationship_id;
221         IF get_top_position%NOTFOUND THEN
222           l_relationship_id := x_uc_child_tbl(j).relationship_id;
223         END IF;
224         CLOSE get_top_position;
225         OPEN get_child_nodes_i(x_uc_child_tbl(j).instance_id, l_relationship_id);
226         FETCH get_child_nodes_i INTO l_get_child_nodes_i;
227         IF get_child_nodes_i%FOUND THEN
228           x_uc_child_tbl(j).leaf_node_flag := 'Y';
229         ELSE
230           x_uc_child_tbl(j).leaf_node_flag := 'N';
231         END IF;
232       ELSIF x_uc_child_tbl(j).node_type = 'M' THEN
233         SELECT count(relationship_id) INTO l_children_no
234           FROM ahl_mc_relationships
235          WHERE parent_relationship_id = x_uc_child_tbl(j).relationship_id;
236         IF l_children_no > 0 THEN
237           x_uc_child_tbl(j).has_subconfig_flag := 'N';
238           x_uc_child_tbl(j).leaf_node_flag := 'N';
239         ELSE
240           x_uc_child_tbl(j).leaf_node_flag := 'Y';
241           SELECT count(mc_header_id) INTO l_children_no
242             FROM ahl_mc_config_relations
243            WHERE relationship_id = x_uc_child_tbl(j).relationship_id;
244           IF l_children_no > 0 THEN
245             x_uc_child_tbl(j).has_subconfig_flag := 'Y';
246           ELSE
247             x_uc_child_tbl(j).has_subconfig_flag := 'N';
248           END IF;
249         END IF;
250       ELSIF x_uc_child_tbl(j).node_type = 'X' THEN
251         x_uc_child_tbl(j).has_subconfig_flag := 'N';
252         SELECT count(subject_id) INTO l_children_no
253           FROM csi_ii_relationships
254          WHERE object_id = x_uc_child_tbl(j).instance_id;
255         IF l_children_no > 0 THEN
256           x_uc_child_tbl(j).leaf_node_flag := 'Y';
257         ELSE
258           x_uc_child_tbl(j).leaf_node_flag := 'N';
259         END IF;
260       END IF;
261     END LOOP;
262   END IF;
263 
264   IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
265 	FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
266                    'ahl.plsql.'||G_PKG_NAME||'.'||l_api_name||': After normal execution',
267 			       'At the end of the procedure');
268   END IF;
269 
270   -- Get all the error messages from the previous steps (if any) and raise the appropriate Exception
271   l_msg_count := FND_MSG_PUB.count_msg;
272   IF l_msg_count > 0 THEN
273     x_msg_count := l_msg_count;
274     RAISE FND_API.G_EXC_ERROR;
275   END IF;
276   -- Count and Get messages (optional)
277   FND_MSG_PUB.count_and_get(
278     p_encoded  => FND_API.G_FALSE,
279     p_count    => x_msg_count,
280     p_data     => x_msg_data);
281 
282 EXCEPTION
283   WHEN FND_API.G_EXC_ERROR THEN
284     x_return_status := FND_API.G_RET_STS_ERROR ;
285     FND_MSG_PUB.count_and_get(
286       p_encoded  => FND_API.G_FALSE,
287       p_count    => x_msg_count,
288       p_data     => x_msg_data);
289 
290   WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
291     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
292     FND_MSG_PUB.count_and_get(
293       p_encoded  => FND_API.G_FALSE,
294       p_count    => x_msg_count,
295       p_data     => x_msg_data);
296 
297   WHEN OTHERS THEN
298     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
299     IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR)
300     THEN
301       FND_MSG_PUB.add_exc_msg(
302         p_pkg_name         => G_PKG_NAME,
303         p_procedure_name   => l_api_name,
304         p_error_text       => SUBSTRB(SQLERRM,1,240));
305     END IF;
306     FND_MSG_PUB.count_and_get(
307       p_encoded  => FND_API.G_FALSE,
308       p_count    => x_msg_count,
309       p_data     => x_msg_data);
310 
311 END get_immediate_children;
312 */
313 
314 PROCEDURE get_whole_uc_tree(
315   p_api_version           IN  NUMBER := 1.0,
316   p_init_msg_list         IN  VARCHAR2 := FND_API.G_FALSE,
317   --p_commit                IN  VARCHAR2 := FND_API.G_FALSE,
318   p_validation_level      IN  NUMBER := FND_API.G_VALID_LEVEL_FULL,
319   x_return_status         OUT NOCOPY VARCHAR2,
320   x_msg_count             OUT NOCOPY NUMBER,
321   x_msg_data              OUT NOCOPY VARCHAR2,
322   p_uc_header_id          IN  NUMBER,
323   x_uc_descendant_tbl     OUT NOCOPY uc_descendant_tbl_type)
324 IS
325   -- rbhavsar::FP Bug# 6268202, performance tuning
326   -- use PL/SQL tables for BULK COLLECT instead of looping through the cursor records
327   /*
328   TYPE l_uc_children_rec_type IS RECORD (
329     instance_id               NUMBER,
330     relationship_id           NUMBER,
331     matched_flag              VARCHAR2(1));
332   TYPE l_uc_children_tbl_type IS TABLE OF l_uc_children_rec_type INDEX BY BINARY_INTEGER;*/
333 
334   TYPE t_id_tbl       IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
335   TYPE t_flag_tbl     IS TABLE OF VARCHAR2(1) INDEX BY BINARY_INTEGER;
336   TYPE t_partinfo_tbl IS TABLE OF VARCHAR2(80) INDEX BY BINARY_INTEGER;
337 
338   l_api_name       CONSTANT   VARCHAR2(30)   := 'get_whole_uc_tree';
339   l_api_version    CONSTANT   NUMBER         := 1.0;
340   l_return_status             VARCHAR2(1);
341   l_msg_count                 NUMBER;
342   l_relationship_id           NUMBER;
343   l_mc_header_id              NUMBER;
344   l_root_instance_id          NUMBER;
345   l_root_relationship_id      NUMBER;
346   l_dummy                     VARCHAR2(1);
347   l_dummy_num                 NUMBER;
348   i                           NUMBER;
349   -- l_uc_children_tbl           l_uc_children_tbl_type;
350   l_child_inst_tbl            t_id_tbl;
351   l_child_rel_tbl             t_id_tbl;
352   l_child_matchflag_tbl       t_flag_tbl;
353   l_child_partinfo_tbl        t_partinfo_tbl;
354   l_pos_ref                   FND_LOOKUPS.meaning%TYPE;
355   l_root_mc_hdr_id            NUMBER;
356   l_root_mc_part              BOOLEAN;
357   l_root_ata_code             AHL_MC_RELATIONSHIPS.ATA_CODE%TYPE; -- SATHAPLI::Enigma code changes, 02-Sep-2008
358 
359   l_matched                   boolean;
360   total_i                     NUMBER; --index of output table
361   i_uc_child                  NUMBER; --index of MC siblings
362   l_uc_header_id              NUMBER;
363 
364   -- SATHAPLI::Service Bulletin Effectivity, 25-Mar-2011, associative array variable to hold SB rules' violated instances
365   l_violated_inst_tbl         AHL_SB_RULES_PVT.Violated_Inst_Tbl_Type;
366 
367   --Check the given uc_heder_id is valid and if yes, get the UC top node's instance_id
368   --and relationship_id
369   -- rbhavsar::FP Bug# 6268202, performance tuning
370   -- fetch the root UC's mc_header_id too
371   -- SATHAPLI::Enigma code changes, 02-Sep-2008 - fetch the ata_code as well
372   CURSOR get_uc_header_attr(c_uc_header_id NUMBER) IS
373     SELECT A.csi_item_instance_id instance_id,
374            A.master_config_id,
375            B.relationship_id,
376            B.ata_code
377       FROM ahl_unit_config_headers A,
378            ahl_mc_relationships B
379      WHERE A.unit_config_header_id = c_uc_header_id
380        AND A.master_config_id = B.mc_header_id
381        AND B.parent_relationship_id IS NULL;
382 
383   --Given an instance_id, get all of its immediate children from csi_ii_relationships
384   -- rbhavsar::FP Bug# 6268202, performance tuning
385   -- Object_id is not used in the code, so removing it.
386   -- Also, no need for ORDER BY for extra nodes.
387   CURSOR get_csi_children(c_instance_id NUMBER) IS
388     SELECT R.subject_id instance_id,
389            to_number(R.position_reference) relationship_id,
390            M.concatenated_segments||'-'||NVL(C.serial_number, C.instance_number) part_info,
391            'N'
392       FROM csi_ii_relationships R,
393            csi_item_instances C,
394            mtl_system_items_kfv M
395      WHERE R.object_id                              = c_instance_id
396        AND R.subject_id                             = C.instance_id
397        AND C.inventory_item_id                      = M.inventory_item_id
398        AND C.inv_master_organization_id             = M.organization_id
399        AND R.relationship_type_code                 = 'COMPONENT-OF'
400        AND trunc(nvl(R.active_start_date,SYSDATE)) <= trunc(SYSDATE)
401        AND trunc(nvl(R.active_end_date, SYSDATE+1)) > trunc(SYSDATE);
402 
403   -- rbhavsar::FP Bug# 6268202, performance tuning
404   -- cursor to check if the instance is leaf node or not
405   CURSOR chk_csi_leaf_node_csr(c_instance_id NUMBER) IS
406     SELECT 'X'
407       FROM csi_ii_relationships
408      WHERE object_id = c_instance_id
409        AND relationship_type_code = 'COMPONENT-OF'
410        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
411        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE);
412 
413   --Given an relationship_id, get all of its immediate children from MC
414   --display_order will determine the sequence of installed and empty sibling nodes
415   -- rbhavsar::FP Bug# 6268202, performance tuning
416   -- Fetch the mc_header_id.
417   -- Fetch the position reference meaning and necessity from fnd_lookups too.
418   -- SATHAPLI::Enigma code changes, 02-Sep-2008 - fetch the ata_code as well
419   CURSOR get_mc_children(c_relationship_id NUMBER) IS
420     SELECT rel.mc_header_id,
421            rel.parent_relationship_id parent_rel_id,
422            rel.relationship_id,
423            rel.display_order,
424            rel.ata_code,
425            (SELECT fnd.meaning
426             FROM   fnd_lookups fnd
427             WHERE  fnd.lookup_type                            = 'AHL_POSITION_REFERENCE'
428               AND  fnd.lookup_code                            = rel.position_ref_code
429               AND  trunc(nvl(fnd.start_date_active, SYSDATE)) <= trunc(SYSDATE)
430               AND  trunc(nvl(fnd.end_date_active, SYSDATE+1))  > trunc(SYSDATE)
431            ) pos_ref_meaning,
432            (SELECT fnd.meaning
433             FROM   fnd_lookups fnd
434             WHERE  fnd.lookup_type                             = 'AHL_POSITION_NECESSITY'
435               AND  fnd.lookup_code                             = rel.position_necessity_code
436               AND  trunc(nvl(fnd.start_date_active, SYSDATE)) <= trunc(SYSDATE)
437               AND  trunc(nvl(fnd.end_date_active, SYSDATE+1))  > trunc(SYSDATE)
438            ) pos_necessity
439       FROM ahl_mc_relationships rel
440      WHERE rel.parent_relationship_id                  = c_relationship_id
441        AND trunc(nvl(rel.active_start_date,SYSDATE))  <= trunc(SYSDATE)
442        AND trunc(nvl(rel.active_end_date, SYSDATE+1))  > trunc(SYSDATE)
443   ORDER BY display_order;
444 
445   -- rbhavsar::FP Bug# 6268202, performance tuning
446   -- cursor to check if the position is leaf node or not
447   CURSOR chk_mc_leaf_node_csr(c_relationship_id NUMBER) IS
448     SELECT 'X'
449       FROM ahl_mc_relationships
450      WHERE parent_relationship_id = c_relationship_id
451        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
452        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE);
453 
454   --Given an relationship_id, get all of its descendants from MC
455   -- rbhavsar::FP Bug# 6268202, performance tuning
456   -- fetch the position reference meaning and necessity from fnd_lookups too
457   -- SATHAPLI::Enigma code changes, 02-Sep-2008 - fetch the ata_code as well
458   CURSOR get_mc_descendants(c_relationship_id NUMBER) IS
459     SELECT rel.parent_relationship_id parent_rel_id,
460            rel.relationship_id,
461            rel.display_order,
462            rel.ata_code,
463            (SELECT fnd.meaning
464             FROM   fnd_lookups fnd
465             WHERE  fnd.lookup_type                            = 'AHL_POSITION_REFERENCE'
466               AND  fnd.lookup_code                            = rel.position_ref_code
467               AND  trunc(nvl(fnd.start_date_active, SYSDATE)) <= trunc(SYSDATE)
468               AND  trunc(nvl(fnd.end_date_active, SYSDATE+1))  > trunc(SYSDATE)
469            ) pos_ref_meaning,
470            (SELECT fnd.meaning
471             FROM   fnd_lookups fnd
472             WHERE  fnd.lookup_type                             = 'AHL_POSITION_NECESSITY'
473               AND  fnd.lookup_code                             = rel.position_necessity_code
474               AND  trunc(nvl(fnd.start_date_active, SYSDATE)) <= trunc(SYSDATE)
475               AND  trunc(nvl(fnd.end_date_active, SYSDATE+1))  > trunc(SYSDATE)
476            ) pos_necessity
477       FROM ahl_mc_relationships rel
478 START WITH rel.parent_relationship_id                  = c_relationship_id
479        AND trunc(nvl(rel.active_start_date,SYSDATE))  <= trunc(SYSDATE)
480        AND trunc(nvl(rel.active_end_date, SYSDATE+1))  > trunc(SYSDATE)
481 CONNECT BY rel.parent_relationship_id                  = PRIOR rel.relationship_id
482        AND trunc(nvl(rel.active_start_date,SYSDATE))  <= trunc(SYSDATE)
483        AND trunc(nvl(rel.active_end_date, SYSDATE+1))  > trunc(SYSDATE)
484     ORDER BY LEVEL, display_order;
485 -- keyword SIBLINGS is not supported in 8i, so we replace it with level
486 --  ORDER SIBLINGS BY display_order;
487 
488 
489   --Check whether an instance in UC is the top node of a sub UC, if yes, then get the
490   --relationship of the sub UC's top node
491   CURSOR check_sub_uc(c_instance_id NUMBER) IS
492     SELECT A.unit_config_header_id,
493            A.master_config_id,
494            B.relationship_id
495       FROM ahl_unit_config_headers A,
496            ahl_mc_relationships B
497      WHERE A.csi_item_instance_id = c_instance_id
498        AND trunc(nvl(A.active_end_date, SYSDATE+1)) > trunc(SYSDATE)
499        AND B.mc_header_id = A.master_config_id
500        AND B.parent_relationship_id IS NULL
501        AND trunc(nvl(B.active_start_date,SYSDATE)) <= trunc(SYSDATE)
502        AND trunc(nvl(B.active_end_date, SYSDATE+1)) > trunc(SYSDATE);
503 
504   -- rbhavsar:: FP Bug# 6268202, performance tuning
505   -- check if the MC has sub MCs or not
506   CURSOR has_sub_mc_csr(c_relationship_id NUMBER) IS
507     SELECT 'X'
508       FROM ahl_mc_config_relations
509      WHERE relationship_id = c_relationship_id
510        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
511        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE)
512        AND rownum = 1;
513 
514   -- rbhavsar:: FP Bug# 6268202, performance tuning
515   -- Cursor to get the position reference for a given relationship id.
516   CURSOR get_pos_ref_csr(c_relationship_id NUMBER) IS
517     SELECT fnd.meaning
518     FROM   ahl_mc_relationships rel, fnd_lookups fnd
519     WHERE  rel.relationship_id                         = c_relationship_id AND
520            fnd.lookup_code                             = rel.position_ref_code AND
521            fnd.lookup_type                             = 'AHL_POSITION_REFERENCE' AND
522            TRUNC(NVL(fnd.start_date_active, SYSDATE)) <= TRUNC(SYSDATE) AND
523            TRUNC(NVL(fnd.end_date_active, SYSDATE+1))  > TRUNC(SYSDATE);
524 
525   --Based on the UC, list all of the non leaf nodes(including the root node) and the leaf nodes
526   --in UC but are non-leaf nodes in MC
527 -- rbhavsar::FP Bug# 6268202, performance tuning
528   CURSOR get_non_leaf_nodes(c_instance_id NUMBER) IS
529 SELECT  TO_NUMBER(NULL) PARENT_INSTANCE_ID,
530         B.CSI_ITEM_INSTANCE_ID INSTANCE_ID,
531         A.RELATIONSHIP_ID,
532          'I' NODE_TYPE,
533         0 OWN_LEVEL
534 FROM    AHL_UNIT_CONFIG_HEADERS B,
535         AHL_MC_RELATIONSHIPS A
536 WHERE   B.UNIT_CONFIG_HEADER_ID = p_uc_header_id  /*UC header id*/
537     AND B.CSI_ITEM_INSTANCE_ID  = c_instance_id  /*root instance id*/
538     AND A.MC_HEADER_ID          = B.MASTER_CONFIG_ID
539     AND A.PARENT_RELATIONSHIP_ID IS NULL
540 UNION ALL
541 SELECT  OBJECT_ID PARENT_INSTANCE_ID,
542         SUBJECT_ID INSTANCE_ID,
543         TO_NUMBER(POSITION_REFERENCE) RELATIONSHIP_ID,
544         DECODE(POSITION_REFERENCE, NULL, 'X', 'I') NODE_TYPE,
545         LEVEL OWN_LEVEL
546 FROM    CSI_II_RELATIONSHIPS A
547 WHERE   (
548          EXISTS (SELECT 'x'
549                  FROM    CSI_II_RELATIONSHIPS B
550                  WHERE   B.OBJECT_ID                              = A.SUBJECT_ID
551                    AND   B.RELATIONSHIP_TYPE_CODE                 = 'COMPONENT-OF'
552                    AND   TRUNC(NVL(B.ACTIVE_START_DATE,SYSDATE)) <= TRUNC(SYSDATE)
553                    AND   TRUNC(NVL(B.ACTIVE_END_DATE, SYSDATE+1)) > TRUNC(SYSDATE)
554                )
555         )
556         OR
557         (
558          EXISTS (SELECT 'x'
559                  FROM    AHL_MC_RELATIONSHIPS D
560                  WHERE   D.PARENT_RELATIONSHIP_ID = TO_NUMBER(A.POSITION_REFERENCE)
561                    AND   TRUNC(NVL(D.ACTIVE_START_DATE,SYSDATE)) <= TRUNC(SYSDATE)
562                    AND   TRUNC(NVL(D.ACTIVE_END_DATE, SYSDATE+1)) > TRUNC(SYSDATE)
563                 )
564          OR
565          EXISTS (SELECT 'x'
566                  FROM    AHL_MC_RELATIONSHIPS D
567                  WHERE   D.RELATIONSHIP_ID      = TO_NUMBER(A.POSITION_REFERENCE)
568                    AND   EXISTS (SELECT 'x'
569                                  FROM    AHL_UNIT_CONFIG_HEADERS E
570                                  WHERE   CSI_ITEM_INSTANCE_ID                     = A.SUBJECT_ID
571                                    AND   TRUNC(NVL(E.ACTIVE_END_DATE, SYSDATE+1)) > TRUNC(SYSDATE)
572                                 )
573                    AND   TRUNC(NVL(D.ACTIVE_START_DATE,SYSDATE)) <= TRUNC(SYSDATE)
574                    AND   TRUNC(NVL(D.ACTIVE_END_DATE, SYSDATE+1)) > TRUNC(SYSDATE)
575                 )
576         )
577 START WITH OBJECT_ID                           = c_instance_id  /*root instance id*/
578     AND RELATIONSHIP_TYPE_CODE                 = 'COMPONENT-OF'
579     AND TRUNC(NVL(ACTIVE_START_DATE,SYSDATE)) <= TRUNC(SYSDATE)
580     AND TRUNC(NVL(ACTIVE_END_DATE, SYSDATE+1)) > TRUNC(SYSDATE)
581 CONNECT BY OBJECT_ID = PRIOR SUBJECT_ID
582     AND RELATIONSHIP_TYPE_CODE                 = 'COMPONENT-OF'
583     AND TRUNC(NVL(ACTIVE_START_DATE,SYSDATE)) <= TRUNC(SYSDATE)
584     AND TRUNC(NVL(ACTIVE_END_DATE, SYSDATE+1)) > TRUNC(SYSDATE)
585 ORDER BY OWN_LEVEL, NODE_TYPE;
586 
587   l_get_csi_child get_csi_children%ROWTYPE;
588   l_get_mc_child get_mc_children%ROWTYPE;
589 
590   --Function to get position_necessity meaning for a given relationship_id
591   FUNCTION position_necessity(p_relationship_id NUMBER) RETURN VARCHAR2 IS
592     l_pos_necessity_meaning fnd_lookups.meaning%TYPE;
593     CURSOR get_position_necessity(c_relationship_id NUMBER) IS
594     SELECT F.meaning
595       FROM ahl_mc_relationships A,
596            fnd_lookup_values_vl F
597      WHERE A.relationship_id = c_relationship_id
598        AND A.position_necessity_code = F.lookup_code (+)
599        AND F.lookup_type (+) = 'AHL_POSITION_NECESSITY';
600   BEGIN
601     IF p_relationship_id IS NULL THEN
602       l_pos_necessity_meaning := NULL;
603     ELSE
604       OPEN get_position_necessity(p_relationship_id);
605       FETCH get_position_necessity INTO l_pos_necessity_meaning;
606       IF get_position_necessity%NOTFOUND THEN
607         FND_MESSAGE.set_name( 'AHL','AHL_UC_POSITION_INVALID' );
608         FND_MESSAGE.set_token('POSITION', p_relationship_id);
609         FND_MSG_PUB.add;
610         CLOSE get_position_necessity;
611         RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
612       ELSE
613         CLOSE get_position_necessity;
614       END IF;
615     END IF;
616     RETURN l_pos_necessity_meaning;
617   END;
618 
619   --Function to get instance information(part number plus serial number or
620   --instance number for a given instance_id
621   FUNCTION part_info(p_instance_id NUMBER) RETURN VARCHAR2 IS
622     l_part_info        VARCHAR2(80);
623     CURSOR get_part_info(c_instance_id NUMBER) IS
624       SELECT M.concatenated_segments||'-'||NVL(C.serial_number, C.instance_number) part_info
625         FROM mtl_system_items_kfv M,
626              csi_item_instances C
627        WHERE C.instance_id = c_instance_id
628          AND C.inventory_item_id = M.inventory_item_id
629          AND C.inv_master_organization_id = M.organization_id;
630   BEGIN
631     OPEN get_part_info(p_instance_id);
632     FETCH get_part_info INTO l_part_info;
633     IF get_part_info%NOTFOUND THEN
634       FND_MESSAGE.set_name( 'AHL','AHL_UC_INSTANCE_INVALID' );
635       FND_MESSAGE.set_token('INSTANCE', p_instance_id);
636       FND_MSG_PUB.add;
637       CLOSE get_part_info;
638       RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
639     ELSE
640       CLOSE get_part_info;
641     END IF;
642     RETURN l_part_info;
643   END;
644 
645 
646 BEGIN
647   --Initialize API return status to success
648   x_return_status := FND_API.G_RET_STS_SUCCESS;
649 
650   --Standard call to check for call compatibility.
651   IF NOT FND_API.compatible_api_call(
652     l_api_version,
653     p_api_version,
654     l_api_name,
655     G_PKG_NAME)
656   THEN
657     RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
658   END IF;
659   --Initialize message list if p_init_msg_list is set to TRUE.
660   IF FND_API.to_boolean( p_init_msg_list ) THEN
661     FND_MSG_PUB.initialize;
662   END IF;
663 
664   IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
665 	FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
666                    'ahl.plsql.'||G_PKG_NAME||'.'||l_api_name||': Begin API',
667 			       'At the start of the procedure');
668   END IF;
669   --Validate the input parameter and get the root instance_id and relationship_id
670   -- SATHAPLI::Enigma code changes, 02-Sep-2008 - fetch the ata_code as well
671   OPEN get_uc_header_attr(p_uc_header_id);
672   FETCH get_uc_header_attr INTO l_root_instance_id, l_root_mc_hdr_id, l_root_relationship_id, l_root_ata_code;
673   IF get_uc_header_attr%NOTFOUND THEN
674     FND_MESSAGE.set_name( 'AHL','AHL_UC_HEADER_ID_INVALID' );
675     FND_MESSAGE.set_token('UC_HEADER_ID', p_uc_header_id);
676     FND_MSG_PUB.add;
677     CLOSE get_uc_header_attr;
678     RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
679   ELSE
680     CLOSE get_uc_header_attr;
681   END IF;
682 
683   --Initialize l_uc_header_id
684   l_uc_header_id := p_uc_header_id;
685 
686   --add the root node to the output table
687   total_i := 1; --index of the output table
688   x_uc_descendant_tbl(total_i).instance_id := l_root_instance_id;
689   x_uc_descendant_tbl(total_i).relationship_id := l_root_relationship_id;
690   x_uc_descendant_tbl(total_i).parent_instance_id := NULL;
691   x_uc_descendant_tbl(total_i).parent_rel_id := NULL;
692   x_uc_descendant_tbl(total_i).node_type := 'I';
693   x_uc_descendant_tbl(total_i).leaf_node_flag := 'N'; --might be 'Y' very seldomly?
694   x_uc_descendant_tbl(total_i).has_subconfig_flag := 'N'; --not applicable for root node
695 
696   -- SATHAPLI::Enigma code changes, 02-Sep-2008 - populate the ata_code for the root
697   x_uc_descendant_tbl(total_i).ata_code := l_root_ata_code;
698 
699   -- rbhavsar::FP Bug# 6268202, performance tuning
700   -- API ahl_mc_path_position_pvt.get_posref_for_uc need not be called for root
701   -- x_uc_descendant_tbl(total_i).position_reference := ahl_mc_path_position_pvt.get_posref_for_uc(l_uc_header_id, l_root_relationship_id);
702   OPEN get_pos_ref_csr(l_root_relationship_id);
703   FETCH get_pos_ref_csr INTO l_pos_ref;
704   CLOSE get_pos_ref_csr;
705   x_uc_descendant_tbl(total_i).position_reference := l_pos_ref;
706 
707   --Even if p_uc_header_id is a subunit(installed or extra), when displaying its own tree, we pass its own
708   --p_uc_header_id instead of its parent_uc_header_id
709   x_uc_descendant_tbl(total_i).position_necessity := position_necessity(l_root_relationship_id);
710   x_uc_descendant_tbl(total_i).part_info := part_info(l_root_instance_id);
711   total_i := total_i + 1;
712 
713   -- SATHAPLI::Service Bulletin Effectivity, 25-Mar-2011, get SB rules' violated instances, if any
714   AHL_SB_RULES_PVT.Get_Violated_Instances(
715     p_api_version       => p_api_version,
716     p_init_msg_list     => p_init_msg_list,
717     p_validation_level  => p_validation_level,
718     p_uc_header_id      => p_uc_header_id,
719     x_violated_inst_tbl => l_violated_inst_tbl,
720     x_return_status     => x_return_status,
721     x_msg_count         => x_msg_count,
722     x_msg_data          => x_msg_data
723   );
724 
725   IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
726     IF (l_log_statement >= l_log_current_level) THEN
727       FND_LOG.string(l_log_statement, 'ahl.plsql.'||G_PKG_NAME||'.'||l_api_name,
728                      ' AHL_SB_RULES_PVT.Get_Violated_Instances call errored out');
729     END IF;
730     RAISE FND_API.G_EXC_ERROR;
731   END IF;
732 
733   --Loop through all of the non leaf nodes of the UC tree, including the root node and extra node
734   FOR l_non_leaf_node IN get_non_leaf_nodes(l_root_instance_id) LOOP
735 
736     --dbms_output.put_line('rel_id='||l_non_leaf_node.relationship_id||' uc_instance='||l_root_instance_id);
737     IF (l_non_leaf_node.relationship_id IS NOT NULL AND
738         NOT ahl_util_uc_pkg.extra_node(l_non_leaf_node.instance_id, l_root_instance_id)) THEN
739 
740       --If the UC instance happens to be the top node of a sub UC, then when getting the
741       --MC descendants, the sub UC top node's relationship_id(got from uc headers table)
742       --instead of the relationship_id(got from position_reference in csi_ii_relationships)
743       --should be used. For UC root instance, the following cursor is also applicable.
744       OPEN check_sub_uc(l_non_leaf_node.instance_id);
745       FETCH check_sub_uc INTO l_uc_header_id, l_mc_header_id, l_relationship_id;
746 
747       IF check_sub_uc%NOTFOUND THEN --not a sub UC's top node
748         l_relationship_id := l_non_leaf_node.relationship_id;
749         ahl_util_uc_pkg.get_parent_uc_header(l_non_leaf_node.instance_id, l_uc_header_id, l_dummy_num);
750 
751         IF l_uc_header_id IS NULL THEN
752           l_uc_header_id := p_uc_header_id;
753         END IF;
754       END IF;
755       CLOSE check_sub_uc;
756 
757       --Get all the immediate children of the corresponding UC node
758 
759       --This is used to reset the l_uc_children_tbl and it is required, otherwise the elements
760       --left in the previous loop especially when the previous loop has more elements than the
761       --current loop, then these elements belonging to the previous loop will be inherited to
762       --the current loop.
763       -- rbhavsar::FP Bug# 6268202, performance tuning
764       -- use PL/SQL tables for BULK COLLECT instead of looping through the cursor records
765       /*
766       IF l_uc_children_tbl.COUNT > 0 THEN
767         l_uc_children_tbl.DELETE;
768       END IF;
769 
770 
771       i_uc_child := 0;
772       FOR l_get_csi_child IN get_csi_children(l_non_leaf_node.instance_id) LOOP
773         i_uc_child := i_uc_child + 1;
774         l_uc_children_tbl(i_uc_child).instance_id := l_get_csi_child.instance_id;
775         l_uc_children_tbl(i_uc_child).relationship_id := l_get_csi_child.relationship_id;
776         l_uc_children_tbl(i_uc_child).matched_flag := 'N'; -- default to 'N'
777       END LOOP;
778       */
779 
780       IF l_child_inst_tbl.COUNT > 0 THEN
781         l_child_inst_tbl.DELETE;
782         l_child_rel_tbl.DELETE;
783         l_child_matchflag_tbl.DELETE;
784         l_child_partinfo_tbl.DELETE;
785       END IF;
786 
787       OPEN get_csi_children(l_non_leaf_node.instance_id);
788       FETCH get_csi_children BULK COLLECT INTO l_child_inst_tbl,
789                                                l_child_rel_tbl,
790                                                l_child_partinfo_tbl,
791                                                l_child_matchflag_tbl;
792       CLOSE get_csi_children;
793 
794       --Loop through all the immediate children of the MC node
795       FOR l_get_mc_child IN get_mc_children(l_relationship_id) LOOP
796         l_matched := FALSE;
797         IF l_child_inst_tbl.COUNT > 0 THEN
798           FOR i IN l_child_inst_tbl.FIRST..l_child_inst_tbl.LAST LOOP
799             IF (l_child_matchflag_tbl(i) = 'N' AND
800                 l_get_mc_child.relationship_id = l_child_rel_tbl(i)) THEN
801               --Add these installed nodes to the output table
802               x_uc_descendant_tbl(total_i).instance_id := l_child_inst_tbl(i);
803               x_uc_descendant_tbl(total_i).relationship_id := l_child_rel_tbl(i);
804               x_uc_descendant_tbl(total_i).parent_instance_id := l_non_leaf_node.instance_id;
805               x_uc_descendant_tbl(total_i).parent_rel_id := l_non_leaf_node.relationship_id;
806 
807               -- SATHAPLI::Service Bulletin Effectivity, 25-Mar-2011
808               -- if the instance exists in l_violated_inst_tbl, then its node type is 'S'
809               -- otherwise, its 'I'
810               IF (l_violated_inst_tbl.EXISTS(l_child_inst_tbl(i))) THEN
811                 x_uc_descendant_tbl(total_i).node_type := 'S';
812               ELSE
813                 x_uc_descendant_tbl(total_i).node_type := 'I';
814               END IF;
815 
816               -- SATHAPLI::Enigma code changes, 02-Sep-2008 - populate the ata_code for the non-extra node
817               x_uc_descendant_tbl(total_i).ata_code := l_get_mc_child.ata_code;
818 
819               -- rbhavsar::FP Bug# 6268202, performance tuning
820               -- API ahl_mc_path_position_pvt.get_posref_for_uc need not be called if
821               -- this relationship belongs to the root MC.
822               IF (l_get_mc_child.mc_header_id = l_root_mc_hdr_id) THEN
823                 x_uc_descendant_tbl(total_i).position_reference := l_get_mc_child.pos_ref_meaning;
824               ELSE
825                 x_uc_descendant_tbl(total_i).position_reference :=
826                 ahl_mc_path_position_pvt.get_posref_for_uc(l_uc_header_id, l_child_rel_tbl(i));
827               END IF;
828 
829               x_uc_descendant_tbl(total_i).position_necessity := l_get_mc_child.pos_necessity;
830               x_uc_descendant_tbl(total_i).part_info := l_child_partinfo_tbl(i);
831 
832               --Leaf_node_flag is for front end display purpose, so we have to
833               --First check to see wether this installed node is a leaf node in CSI, if it is
834               --then we need to check whether the corresponding relationship_id is a leaf node
835               --in MC. Again we need to check whether this installed node happens to be a sub UC top node.
836               OPEN check_sub_uc(x_uc_descendant_tbl(total_i).instance_id);
837               FETCH check_sub_uc INTO l_dummy_num, l_mc_header_id, l_relationship_id;
838               IF check_sub_uc%NOTFOUND THEN --not a sub UC's top node
839                 l_relationship_id := x_uc_descendant_tbl(total_i).relationship_id;
840                 x_uc_descendant_tbl(total_i).has_subconfig_flag := 'N';
841               ELSE
842                 x_uc_descendant_tbl(total_i).has_subconfig_flag := 'Y';
843               END IF;
844               CLOSE check_sub_uc;
845 
846               -- rbhavsar::FP Bug# 6268202, performance tuning
847               OPEN chk_csi_leaf_node_csr(x_uc_descendant_tbl(total_i).instance_id);
848               FETCH chk_csi_leaf_node_csr INTO l_dummy;
849               IF chk_csi_leaf_node_csr%FOUND THEN
850                 x_uc_descendant_tbl(total_i).leaf_node_flag := 'N';
851               ELSE
852                 -- check from the MC
853                 OPEN chk_mc_leaf_node_csr(l_relationship_id);
854                 FETCH chk_mc_leaf_node_csr INTO l_dummy;
855                 IF chk_mc_leaf_node_csr%FOUND THEN
856                   x_uc_descendant_tbl(total_i).leaf_node_flag := 'N';
857                 ELSE
858                   x_uc_descendant_tbl(total_i).leaf_node_flag := 'Y';
859                 END IF;
860                 CLOSE chk_mc_leaf_node_csr;
861               END IF;
862               CLOSE chk_csi_leaf_node_csr;
863 
864               total_i := total_i + 1;
865               l_matched := TRUE;
866               l_child_matchflag_tbl(i) := 'Y';
867               EXIT;
868             END IF; --whether relationship_id match condition
869           END LOOP; --l_uc_children_tbl
870         END IF; --whether table l_uc_children_tbl is empty
871 
872         --dbms_output.put_line('Not installed node...');
873         IF NOT l_matched THEN -- empty node
874         --Add this empty node and all of its descendants to the output table
875         --dbms_output.put_line('i='||to_char(i)||':l_mc_children_table(i).installed_flag='||l_mc_children_tbl(i).installed_flag);
876           x_uc_descendant_tbl(total_i).instance_id := NULL;
877           x_uc_descendant_tbl(total_i).relationship_id := l_get_mc_child.relationship_id;
878           x_uc_descendant_tbl(total_i).parent_instance_id := l_non_leaf_node.instance_id;
879           x_uc_descendant_tbl(total_i).parent_rel_id := l_non_leaf_node.relationship_id;
880           x_uc_descendant_tbl(total_i).node_type := 'E';
881 
882           -- SATHAPLI::Enigma code changes, 02-Sep-2008 - populate the ata_code for the non-extra node
883           x_uc_descendant_tbl(total_i).ata_code := l_get_mc_child.ata_code;
884 
885           -- rbhavsar::FP Bug# 6268202, performance tuning
886           -- API ahl_mc_path_position_pvt.get_posref_for_uc need not be called if
887           -- this relationship belongs to the root MC.
888           IF (l_get_mc_child.mc_header_id = l_root_mc_hdr_id) THEN
889             l_root_mc_part := TRUE;
890             x_uc_descendant_tbl(total_i).position_reference := l_get_mc_child.pos_ref_meaning;
891           ELSE
892             l_root_mc_part := FALSE;
893             x_uc_descendant_tbl(total_i).position_reference :=
894             ahl_mc_path_position_pvt.get_posref_for_uc(l_uc_header_id, l_get_mc_child.relationship_id);
895           END IF;
896 
897           x_uc_descendant_tbl(total_i).position_necessity := l_get_mc_child.pos_necessity;
898           x_uc_descendant_tbl(total_i).part_info := NULL;
899 
900           -- rbhavsar::FP Bug# 6268202, performance tuning
901           OPEN chk_mc_leaf_node_csr(x_uc_descendant_tbl(total_i).relationship_id);
902           FETCH chk_mc_leaf_node_csr INTO l_dummy;
903           IF chk_mc_leaf_node_csr%FOUND THEN
904             x_uc_descendant_tbl(total_i).leaf_node_flag := 'N';
905           ELSE
906             x_uc_descendant_tbl(total_i).leaf_node_flag := 'Y';
907           END IF;
908           CLOSE chk_mc_leaf_node_csr;
909 
910           OPEN has_sub_mc_csr(x_uc_descendant_tbl(total_i).relationship_id);
911           FETCH has_sub_mc_csr INTO l_dummy;
912           IF has_sub_mc_csr%FOUND THEN
913             x_uc_descendant_tbl(total_i).has_subconfig_flag := 'Y';
914           ELSE
915             x_uc_descendant_tbl(total_i).has_subconfig_flag := 'N';
916           END IF;
917           CLOSE has_sub_mc_csr;
918 
919           total_i := total_i + 1;
920           FOR l_get_mc_descendant IN get_mc_descendants(l_get_mc_child.relationship_id) LOOP
921             x_uc_descendant_tbl(total_i).instance_id := NULL;
922             x_uc_descendant_tbl(total_i).relationship_id := l_get_mc_descendant.relationship_id;
923 
924             --Changed on 02/04/2004 per Cheng's requirement. Actually using parent_instance_id to
925             --represent the lowest ancestor instance for the empty node
926             x_uc_descendant_tbl(total_i).parent_instance_id := l_non_leaf_node.instance_id;
927             --x_uc_descendant_tbl(total_i).parent_instance_id := NULL;
928 
929             x_uc_descendant_tbl(total_i).parent_rel_id := l_get_mc_descendant.parent_rel_id;
930             x_uc_descendant_tbl(total_i).node_type := 'E';
931 
932             -- SATHAPLI::Enigma code changes, 02-Sep-2008 - populate the ata_code for the non-extra node
933             x_uc_descendant_tbl(total_i).ata_code := l_get_mc_descendant.ata_code;
934 
935             -- rbhavsar::FP Bug# 6268202, performance tuning
936             -- API ahl_mc_path_position_pvt.get_posref_for_uc need not be called if
937             -- the ancestor relationship belongs to the root MC.
938             IF (l_root_mc_part) THEN
939               x_uc_descendant_tbl(total_i).position_reference := l_get_mc_descendant.pos_ref_meaning;
940             ELSE
941               x_uc_descendant_tbl(total_i).position_reference :=
942               ahl_mc_path_position_pvt.get_posref_for_uc(l_uc_header_id, l_get_mc_descendant.relationship_id);
943             END IF;
944 
945             x_uc_descendant_tbl(total_i).position_necessity := l_get_mc_descendant.pos_necessity;
946             x_uc_descendant_tbl(total_i).part_info := NULL;
947 
948             -- rbhavsar::FP Bug# 6268202, performance tuning
949             OPEN chk_mc_leaf_node_csr(x_uc_descendant_tbl(total_i).relationship_id);
950             FETCH chk_mc_leaf_node_csr INTO l_dummy;
951             IF chk_mc_leaf_node_csr%FOUND THEN
952               x_uc_descendant_tbl(total_i).leaf_node_flag := 'N';
953               x_uc_descendant_tbl(total_i).has_subconfig_flag := 'N';
954             ELSE
955               x_uc_descendant_tbl(total_i).leaf_node_flag := 'Y';
956               --Only if it is empty leaf node in MC then it is necessary to check whether there
957               --are some sub MCs can be associated to this node
958               OPEN has_sub_mc_csr(x_uc_descendant_tbl(total_i).relationship_id);
959               FETCH has_sub_mc_csr INTO l_dummy;
960               IF has_sub_mc_csr%FOUND THEN
961                 x_uc_descendant_tbl(total_i).has_subconfig_flag := 'Y';
962               ELSE
963                 x_uc_descendant_tbl(total_i).has_subconfig_flag := 'N';
964               END IF;
965               CLOSE has_sub_mc_csr;
966             END IF;
967             CLOSE chk_mc_leaf_node_csr;
968 
969             total_i := total_i + 1;
970           END LOOP; --loop of get_mc_descendants
971         END IF; --l_matched condition
972       END LOOP; --loop of get_mc_children
973 
974       --dbms_output.put_line('After empty node...');
975       --Check each instance in the temporary UC children table, if it is not matched,
976       --then it is an extra node. Add this extra node's immediate children to the output table
977       IF l_child_inst_tbl.COUNT > 0 THEN
978         FOR i IN l_child_inst_tbl.FIRST..l_child_inst_tbl.LAST LOOP
979           IF l_child_matchflag_tbl(i) = 'N' THEN
980             x_uc_descendant_tbl(total_i).instance_id := l_child_inst_tbl(i);
981             x_uc_descendant_tbl(total_i).relationship_id := l_child_rel_tbl(i);
982             x_uc_descendant_tbl(total_i).parent_instance_id := l_non_leaf_node.instance_id;
983             x_uc_descendant_tbl(total_i).parent_rel_id := l_non_leaf_node.relationship_id;
984             x_uc_descendant_tbl(total_i).node_type := 'X';
985             x_uc_descendant_tbl(total_i).position_reference := NULL;
986             --  ahl_mc_path_position_pvt.get_posref_for_uc(l_uc_header_id, l_uc_children_tbl(i).relationship_id);
987             x_uc_descendant_tbl(total_i).position_necessity := NULL;
988             x_uc_descendant_tbl(total_i).part_info := l_child_partinfo_tbl(i);
989 
990             -- rbhavsar::FP Bug# 6268202, performance tuning
991             OPEN chk_csi_leaf_node_csr(x_uc_descendant_tbl(total_i).instance_id);
992             FETCH chk_csi_leaf_node_csr INTO l_dummy;
993             IF chk_csi_leaf_node_csr%FOUND THEN
994               x_uc_descendant_tbl(total_i).leaf_node_flag := 'N';
995             ELSE
996               x_uc_descendant_tbl(total_i).leaf_node_flag := 'Y';
997             END IF;
998             CLOSE chk_csi_leaf_node_csr;
999 
1000             OPEN check_sub_uc(x_uc_descendant_tbl(total_i).instance_id);
1001             FETCH check_sub_uc INTO l_uc_header_id, l_mc_header_id, l_relationship_id;
1002             IF check_sub_uc%NOTFOUND THEN --not a sub UC's top node
1003               x_uc_descendant_tbl(total_i).has_subconfig_flag := 'N';
1004             ELSE
1005               x_uc_descendant_tbl(total_i).has_subconfig_flag := 'Y';
1006             END IF;
1007             CLOSE check_sub_uc;
1008 
1009             total_i := total_i + 1;
1010           END IF; --matched_flag condition
1011         END LOOP; --loop of l_uc_children_tbl
1012       END IF; --whether table l_uc_children_tbl is empty
1013 
1014     ELSE --an extra node in all non leaf nodes
1015       --add this node's immediate children instead of itself into the output table,
1016       --because this node has already been added into the output table when processing its
1017       --parent node.
1018       FOR l_get_csi_child IN get_csi_children(l_non_leaf_node.instance_id) LOOP
1019         x_uc_descendant_tbl(total_i).node_type := 'X';
1020         x_uc_descendant_tbl(total_i).instance_id := l_get_csi_child.instance_id;
1021         x_uc_descendant_tbl(total_i).relationship_id := l_get_csi_child.relationship_id;
1022         x_uc_descendant_tbl(total_i).parent_instance_id := l_non_leaf_node.instance_id;
1023         x_uc_descendant_tbl(total_i).parent_rel_id := NULL;
1024         x_uc_descendant_tbl(total_i).position_reference := NULL;
1025         --  ahl_mc_path_position_pvt.get_posref_for_uc(l_uc_header_id, l_get_csi_child.relationship_id);
1026         x_uc_descendant_tbl(total_i).position_necessity := NULL;
1027         x_uc_descendant_tbl(total_i).part_info := l_get_csi_child.part_info;
1028 
1029         -- rbhavsar::FP Bug# 6268202, performance tuning
1030         OPEN chk_csi_leaf_node_csr(x_uc_descendant_tbl(total_i).instance_id);
1031         FETCH chk_csi_leaf_node_csr INTO l_dummy;
1032         IF chk_csi_leaf_node_csr%FOUND THEN
1033           x_uc_descendant_tbl(total_i).leaf_node_flag := 'N';
1034         ELSE
1035           x_uc_descendant_tbl(total_i).leaf_node_flag := 'Y';
1036         END IF;
1037         CLOSE chk_csi_leaf_node_csr;
1038 
1039         OPEN check_sub_uc(x_uc_descendant_tbl(total_i).instance_id);
1040         FETCH check_sub_uc INTO l_uc_header_id, l_mc_header_id, l_relationship_id;
1041         IF check_sub_uc%NOTFOUND THEN --not a sub UC's top node
1042           x_uc_descendant_tbl(total_i).has_subconfig_flag := 'N';
1043         ELSE
1044           x_uc_descendant_tbl(total_i).has_subconfig_flag := 'Y';
1045         END IF;
1046         CLOSE check_sub_uc;
1047 
1048         total_i := total_i + 1;
1049       END LOOP;
1050     END IF; --whether l_non_leaf_node is extra node
1051   END LOOP; --loop of get_non_leaf_nodes
1052 
1053   IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
1054 	FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
1055                    'ahl.plsql.'||G_PKG_NAME||'.'||l_api_name||': After normal execution',
1056 			       'At the end of the procedure');
1057   END IF;
1058   -- Get all the error messages from the previous steps (if any) and raise the appropriate Exception
1059   l_msg_count := FND_MSG_PUB.count_msg;
1060   IF l_msg_count > 0 THEN
1061     x_msg_count := l_msg_count;
1062     RAISE FND_API.G_EXC_ERROR;
1063   END IF;
1064   -- Count and Get messages (optional)
1065   FND_MSG_PUB.count_and_get(
1066     p_encoded  => FND_API.G_FALSE,
1067     p_count    => x_msg_count,
1068     p_data     => x_msg_data);
1069 
1070 EXCEPTION
1071   WHEN FND_API.G_EXC_ERROR THEN
1072     x_return_status := FND_API.G_RET_STS_ERROR ;
1073     FND_MSG_PUB.count_and_get(
1074       p_encoded  => FND_API.G_FALSE,
1075       p_count    => x_msg_count,
1076       p_data     => x_msg_data);
1077 
1078   WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
1079     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
1080     FND_MSG_PUB.count_and_get(
1081       p_encoded  => FND_API.G_FALSE,
1082       p_count    => x_msg_count,
1083       p_data     => x_msg_data);
1084 
1085   WHEN OTHERS THEN
1086     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
1087     IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR)
1088     THEN
1089       FND_MSG_PUB.add_exc_msg(
1090         p_pkg_name         => G_PKG_NAME,
1091         p_procedure_name   => l_api_name,
1092         p_error_text       => SUBSTRB(SQLERRM,1,240));
1093     END IF;
1094     FND_MSG_PUB.count_and_get(
1095       p_encoded  => FND_API.G_FALSE,
1096       p_count    => x_msg_count,
1097       p_data     => x_msg_data);
1098 END;
1099 
1100 -- Define Procedure migrate_uc_tree --
1101 -- This API is used to migrate a UC tree to a new MC revision or copy
1102 PROCEDURE migrate_uc_tree(
1103   p_api_version           IN  NUMBER,
1104   p_init_msg_list         IN  VARCHAR2  := FND_API.G_FALSE,
1105   p_commit                IN  VARCHAR2  := FND_API.G_FALSE,
1106   p_validation_level      IN  NUMBER    := FND_API.G_VALID_LEVEL_FULL,
1107   x_return_status         OUT NOCOPY VARCHAR2,
1108   x_msg_count             OUT NOCOPY NUMBER,
1109   x_msg_data              OUT NOCOPY VARCHAR2,
1110   p_uc_header_id          IN  NUMBER,
1111   p_mc_header_id          IN  NUMBER)
1112 IS
1113   TYPE l_mc_children_rec_type IS RECORD(
1114     relationship_id           NUMBER,
1115     position_key              NUMBER,
1116     position_ref_code         VARCHAR2(30),
1117     item_group_id             NUMBER,
1118     matched_flag              VARCHAR2(1));
1119   TYPE l_mc_children_tbl_type IS TABLE OF l_mc_children_rec_type INDEX BY BINARY_INTEGER;
1120   l_mc_children_tbl           l_mc_children_tbl_type;
1121   l_api_name       CONSTANT   VARCHAR2(30)   := 'migrate_uc_tree';
1122   l_api_version    CONSTANT   NUMBER         := 1.0;
1123   l_return_status             VARCHAR2(1);
1124   l_evaluation_status         VARCHAR2(1);
1125   l_msg_count                 NUMBER;
1126   l_msg_data                  VARCHAR2(2000);
1127   l_relationship_id           NUMBER;
1128   l_mc_header_id              NUMBER;
1129   l_mc_name                   ahl_mc_headers_b.name%TYPE;
1130   l_mc_revision               ahl_mc_headers_b.revision%TYPE;
1131   l_mc_status_code            FND_LOOKUP_VALUES.lookup_code%TYPE;
1132   l_root_instance_id          NUMBER;
1133   l_root_relationship_id      NUMBER;
1134   l_mc_top_rel_id             NUMBER;
1135   l_parent_uc_header_id       NUMBER;
1136   l_parent_instance_id        NUMBER;
1137   l_sub_top_rel_id            NUMBER;
1138   l_sub_mc_header_id          NUMBER;
1139   l_boolean_var               BOOLEAN;
1140   l_dummy                     NUMBER;
1141   i                           NUMBER;
1142   i_mc_child                  NUMBER;
1143   l_item_match                BOOLEAN;
1144   l_matched                   BOOLEAN;
1145   l_return_value              BOOLEAN;
1146   l_transaction_type_id       NUMBER;
1147   l_version_no                NUMBER;
1148   l_uc_header_all  ahl_unit_config_headers%ROWTYPE;
1149   l_csi_relationship_rec      csi_datastructures_pub.ii_relationship_rec;
1150   l_csi_relationship_tbl      csi_datastructures_pub.ii_relationship_tbl;
1151   l_csi_transaction_rec       csi_datastructures_pub.transaction_rec;
1152   l_root_uc_header_id         NUMBER;
1153   l_root_uc_status_code       FND_LOOKUP_VALUES.lookup_code%TYPE;
1154   l_root_active_uc_status_code FND_LOOKUP_VALUES.lookup_code%TYPE;
1155   l_root_uc_ovn               NUMBER;
1156   l_new_relationship_id       NUMBER;
1157   --In order to check whether the instance belongs to a sub unit or an extra node branch
1158   CURSOR check_subuc_extra(c_instance_id NUMBER, c_top_instance_id NUMBER) IS
1159     SELECT object_id, subject_id, position_reference
1160       FROM csi_ii_relationships
1161      WHERE subject_id IN (SELECT csi_item_instance_id
1162                             FROM ahl_unit_config_headers
1163                            WHERE trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE))
1164         OR position_reference IS NULL
1165 START WITH subject_id = c_instance_id
1166        AND relationship_type_code = 'COMPONENT-OF'
1167        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
1168        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE)
1169 CONNECT BY subject_id = PRIOR object_id
1170        AND relationship_type_code = 'COMPONENT-OF'
1171        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
1172        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE)
1173        AND subject_id <> c_top_instance_id;
1174   l_check_subuc_extra    check_subuc_extra%ROWTYPE;
1175   --Check the given uc_heder_id is existing and if yes, get its status and other information
1176   CURSOR check_uc_header IS
1177     SELECT U.unit_config_status_code uc_status_code,
1178            U.active_uc_status_code,
1179            U.csi_item_instance_id instance_id,
1180            U.master_config_id mc_header_id,
1181            U.object_version_number,
1182            C.inventory_item_id inventory_item_id,
1183            C.inv_master_organization_id inventory_org_id,
1184            C.inventory_revision,
1185            C.quantity,
1186            C.unit_of_measure
1187       FROM ahl_unit_config_headers U,
1188            csi_item_instances C
1189      WHERE U.unit_config_header_id = p_uc_header_id
1190        AND trunc(nvl(U.active_end_date, SYSDATE+1)) > trunc(SYSDATE)
1191        AND U.csi_item_instance_id = C.instance_id;
1192   l_uc_header_attr check_uc_header%ROWTYPE;
1193   CURSOR check_mc_header IS
1194     SELECT H.mc_header_id,
1195            H.config_status_code,
1196            R.relationship_id,
1197            H.name,
1198            H.revision
1199       FROM ahl_mc_headers_b H,
1200            ahl_mc_relationships R
1201      WHERE H.mc_header_id = p_mc_header_id
1202        AND R.mc_header_id = H.mc_header_id
1203        AND R.parent_relationship_id IS NULL
1204        AND trunc(nvl(R.active_start_date,SYSDATE)) <= trunc(SYSDATE)
1205        AND trunc(nvl(R.active_end_date, SYSDATE+1)) > trunc(SYSDATE);
1206   CURSOR get_mc_header_items(c_mc_header_id NUMBER) IS
1207     SELECT M.relationship_id,
1208            I.inventory_item_id,
1209            I.inventory_org_id
1210       FROM ahl_mc_relationships M,
1211            ahl_item_associations_b I
1212      WHERE M.mc_header_id = c_mc_header_id
1213        AND M.parent_relationship_id IS NULL
1214        AND M.item_group_id = I.item_group_id;
1215   /*
1216   CURSOR get_associated_items(c_item_group_id NUMBER) IS
1217     SELECT inventory_item_id,
1218            inventory_org_id
1219       FROM ahl_item_associations_b
1220      WHERE item_group_id = c_item_group_id;
1221   l_get_associated_item        get_associated_items%ROWTYPE;
1222   */
1223 
1224   --Given an instance_id, get all of its immediate children from csi_ii_relationships
1225   CURSOR get_csi_children(c_instance_id NUMBER) IS
1226     SELECT C.relationship_id csi_ii_relationship_id,
1227            C.object_version_number csi_ii_relationship_ovn,
1228            C.object_id parent_instance_id,
1229            C.subject_id instance_id,
1230            to_number(C.position_reference) relationship_id,
1231            M.position_key,
1232            M.position_ref_code,
1233            I.inventory_item_id,
1234            I.inv_master_organization_id inventory_org_id,
1235            I.inventory_revision,
1236            I.quantity,
1237            I.unit_of_measure
1238       FROM csi_ii_relationships C,
1239            ahl_mc_relationships M,
1240            csi_item_instances I
1241      WHERE to_number(C.position_reference) = M.relationship_id (+)
1242        AND C.subject_id = I.instance_id
1243        AND C.object_id = c_instance_id
1244        AND C.relationship_type_code = 'COMPONENT-OF'
1245        AND trunc(nvl(C.active_start_date,SYSDATE)) <= trunc(SYSDATE)
1246        AND trunc(nvl(C.active_end_date, SYSDATE+1)) > trunc(SYSDATE);
1247   --Given an relationship_id, get all of its immediate children from MC
1248   CURSOR get_mc_children(c_relationship_id NUMBER) IS
1249     SELECT parent_relationship_id parent_rel_id,
1250            relationship_id,
1251            position_key,
1252            position_ref_code,
1253            item_group_id
1254       FROM ahl_mc_relationships
1255      WHERE parent_relationship_id = c_relationship_id
1256        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
1257        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE);
1258   --Check whether an instance in UC is the top node of a sub UC, if yes, then get the
1259   --relationship of the sub UC's top node
1260   CURSOR check_sub_uc(c_instance_id NUMBER) IS
1261     SELECT A.master_config_id mc_header_id,
1262            B.relationship_id
1263       FROM ahl_unit_config_headers A,
1264            ahl_mc_relationships B
1265      WHERE A.csi_item_instance_id = c_instance_id
1266        AND trunc(nvl(A.active_end_date, SYSDATE+1)) > trunc(SYSDATE)
1267        AND B.mc_header_id = A.master_config_id
1268        AND B.parent_relationship_id IS NULL
1269        AND trunc(nvl(B.active_start_date,SYSDATE)) <= trunc(SYSDATE)
1270        AND trunc(nvl(B.active_end_date, SYSDATE+1)) > trunc(SYSDATE);
1271   l_check_sub_uc        check_sub_uc%ROWTYPE;
1272   --Given a position(leaf) in MC, get all the sub MCs which can be associated to this position
1273   CURSOR get_sub_mcs(c_relationship_id NUMBER) IS
1274     SELECT mc_header_id
1275       FROM ahl_mc_config_relations
1276      WHERE relationship_id = c_relationship_id
1277        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
1278        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE);
1279   --Based on the UC, list all of the non leaf nodes including the root node
1280   CURSOR get_non_leaf_nodes(c_instance_id NUMBER) IS
1281     SELECT TO_NUMBER(NULL) parent_instance_id, --just include the root uc node
1282            B.csi_item_instance_id instance_id,
1283            A.relationship_id
1284       FROM ahl_unit_config_headers B,
1285            ahl_mc_relationships A
1286      WHERE B.csi_item_instance_id = c_instance_id
1287        AND trunc(nvl(B.active_end_date, SYSDATE+1)) > trunc(SYSDATE)
1288        AND A.mc_header_id = B.master_config_id
1289        AND A.parent_relationship_id IS NULL
1290      UNION ALL
1291     SELECT object_id parent_instance_id,
1292            subject_id instance_id,
1293            to_number(position_reference) relationship_id
1294       FROM csi_ii_relationships A
1295       --remove all of the leaf node after finishing the hierarchical query
1296      WHERE EXISTS (SELECT 'x'
1297                      FROM csi_ii_relationships B
1298                     WHERE B.object_id = A.subject_id
1299                       AND relationship_type_code = 'COMPONENT-OF'
1300                       AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
1301                       AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE))
1302 START WITH object_id = c_instance_id
1303        AND relationship_type_code = 'COMPONENT-OF'
1304        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
1305        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE)
1306 CONNECT BY object_id = PRIOR subject_id
1307        AND relationship_type_code = 'COMPONENT-OF'
1308        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
1309        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE);
1310 
1311   -- SKPATHAK :: Bug 13574991 :: 16-FEB-2012 :: FPed all fixes on R121 codeline
1312   -- SATHAPLI::Bug 10245398, 10-Feb-2011
1313   -- The provided c_object_id is the root instance of the immediate parent unit of c_subject_id.
1314   -- As it may not be the immediate parent in the hierarchy, start with it and go down the tree.
1315   /*
1316   CURSOR get_position_reference(c_object_id NUMBER, c_subject_id NUMBER) IS
1317     SELECT relationship_id csi_ii_relationship_id,
1318            object_version_number csi_ii_relationship_ovn,
1319            to_number(position_reference) relationship_id
1320       FROM csi_ii_relationships
1321      WHERE object_id = c_object_id
1322        AND subject_id = c_subject_id
1323        AND relationship_type_code = 'COMPONENT-OF'
1324        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
1325        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE);
1326   -- SKPATHAK :: Bug 13574991 :: 16-FEB-2012 :: FPed all fixes on R121 codeline
1327   */
1328   CURSOR get_position_reference(c_object_id NUMBER, c_subject_id NUMBER) IS
1329     SELECT relationship_id csi_ii_relationship_id,
1330            object_version_number csi_ii_relationship_ovn,
1331            to_number(position_reference) relationship_id
1332       FROM csi_ii_relationships
1333      WHERE subject_id = c_subject_id
1334     START WITH object_id = c_object_id
1335        AND relationship_type_code = 'COMPONENT-OF'
1336        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
1337        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE)
1338     CONNECT BY object_id = PRIOR subject_id
1339        AND relationship_type_code = 'COMPONENT-OF'
1340        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
1341        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE);
1342   l_position_info              get_position_reference%ROWTYPE;
1343 
1344 BEGIN
1345   --Initialize API return status to success
1346   x_return_status := FND_API.G_RET_STS_SUCCESS;
1347 
1348   -- Standard Start of API savepoint
1349   SAVEPOINT migrate_uc_tree;
1350 
1351   --Standard call to check for call compatibility.
1352   IF NOT FND_API.compatible_api_call(
1353     l_api_version,
1354     p_api_version,
1355     l_api_name,
1356     G_PKG_NAME)
1357   THEN
1358     RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1359   END IF;
1360 
1361   --Initialize message list if p_init_msg_list is set to TRUE.
1362   IF FND_API.to_boolean( p_init_msg_list ) THEN
1363     FND_MSG_PUB.initialize;
1364   END IF;
1365 
1366   IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
1367 	FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
1368                    'ahl.plsql.'||G_PKG_NAME||'.'||l_api_name||': Begin API',
1369 			       'At the start of the procedure');
1370   END IF;
1371 
1372   --Validate the input parameter p_uc_header_id and its status
1373   --Validate input parameter p_uc_header_id, its two status
1374   OPEN check_uc_header;
1375   FETCH check_uc_header INTO l_uc_header_attr;
1376   IF check_uc_header%NOTFOUND THEN
1377     FND_MESSAGE.set_name( 'AHL','AHL_UC_API_PARAMETER_INVALID');
1378     FND_MESSAGE.set_token('NAME', 'uc_header_id');
1379     FND_MESSAGE.set_token('VALUE', p_uc_header_id);
1380     FND_MSG_PUB.add;
1381     CLOSE check_uc_header;
1382     RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1383   ELSE
1384 
1385     -- ACL :: Changes for R12
1386     IF (ahl_util_uc_pkg.IS_UNIT_QUARANTINED(p_unit_header_id => p_uc_header_id , p_instance_id => null) = FND_API.G_TRUE) THEN
1387       FND_MESSAGE.set_name( 'AHL','AHL_UC_INVALID_Q_ACTION' );
1388       FND_MSG_PUB.add;
1389       CLOSE check_uc_header;
1390       RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1391     END IF;
1392 
1393     ahl_util_uc_pkg.get_root_uc_attr(p_uc_header_id,
1394                                      l_root_uc_header_id,
1395                                      l_root_instance_id,
1396                                      l_root_uc_status_code,
1397                                      l_root_active_uc_status_code,
1398                                      l_root_uc_ovn);
1399     IF (l_root_uc_status_code = 'APPROVAL_PENDING' OR
1400         l_root_active_uc_status_code = 'APPROVAL_PENDING') THEN
1401       FND_MESSAGE.set_name( 'AHL','AHL_UC_STATUS_PENDING' );
1402       FND_MESSAGE.set_token('UC_HEADER_ID', l_root_uc_header_id);
1403       FND_MSG_PUB.add;
1404       CLOSE check_uc_header;
1405       RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1406     ELSE
1407       CLOSE check_uc_header;
1408     END IF;
1409   END IF;
1410 
1411   --Validate the input parameter p_mc_header_id and get its status
1412   OPEN check_mc_header;
1413   FETCH check_mc_header INTO l_mc_header_id,
1414                              l_mc_status_code,
1415                              l_mc_top_rel_id,
1416                              l_mc_name,
1417                              l_mc_revision;
1418   IF check_mc_header%NOTFOUND THEN
1419     FND_MESSAGE.set_name( 'AHL','AHL_UC_API_PARAMETER_INVALID');
1420     FND_MESSAGE.set_token('NAME', 'mc_header_id');
1421     FND_MESSAGE.set_token('VALUE', p_mc_header_id);
1422     FND_MSG_PUB.add;
1423     CLOSE check_mc_header;
1424     RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1425   ELSE
1426     IF l_mc_status_code <> 'COMPLETE' THEN
1427       FND_MESSAGE.set_name( 'AHL','AHL_UC_MC_NOT_COMPLETE' );
1428       FND_MESSAGE.set_token('NAME', l_mc_name);
1429       FND_MESSAGE.set_token('REVISION', l_mc_revision);
1430       FND_MSG_PUB.add;
1431       CLOSE check_mc_header;
1432       RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1433     ELSIF l_mc_header_id = l_uc_header_attr.mc_header_id THEN
1434       FND_MESSAGE.set_name( 'AHL','AHL_UC_MC_MIGRATE_SAME' );
1435       FND_MESSAGE.set_token('NAME', l_mc_name);
1436       FND_MESSAGE.set_token('REVISION', l_mc_revision);
1437       FND_MSG_PUB.add;
1438       CLOSE check_mc_header;
1439       RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1440     ELSE
1441       CLOSE check_mc_header;
1442     END IF;
1443   END IF;
1444 
1445   --The following lines are used to update the position_reference column in csi_ii_relationships
1446   --First, get transaction_type_id .
1447   AHL_UTIL_UC_PKG.getcsi_transaction_id('UC_UPDATE',l_transaction_type_id, l_return_value);
1448   IF NOT l_return_value THEN
1449     RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1450   END IF;
1451 
1452   --For UC root node, only need to ensure item matches, no need to check position key
1453   --and position_reference
1454   IF p_uc_header_id = l_root_uc_header_id THEN
1455     --Standalone UC or UC installed in a CSI instance, only need to check whether
1456     --item match for the top node
1457     l_item_match := AHL_UTIL_UC_PKG.item_match(l_mc_top_rel_id,
1458                              l_uc_header_attr.inventory_item_id,
1459                              l_uc_header_attr.inventory_org_id,
1460                              l_uc_header_attr.inventory_revision,
1461                              l_uc_header_attr.quantity,
1462                              l_uc_header_attr.unit_of_measure);
1463     IF NOT l_item_match THEN
1464       --dbms_output.put_line('l_root_uc_header_id='||l_root_uc_header_id||' l_mc_top_rel_id='||l_mc_top_rel_id);
1465       --dbms_output.put_line('inventory_item_id='||l_uc_header_attr.inventory_item_id||' inventory_org_id='||l_uc_header_attr.inventory_org_id);
1466       --dbms_output.put_line('revision='||l_uc_header_attr.inventory_revision||' quantity='||l_uc_header_attr.quantity);
1467       --dbms_output.put_line('uom='||l_uc_header_attr.unit_of_measure);
1468       FND_MESSAGE.set_name( 'AHL','AHL_UC_HEADER_NOT_MATCH' );
1469       FND_MSG_PUB.add;
1470       RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1471     ELSE
1472     --Item matches, can be migrated and thus change the mc_header_id of the UC header
1473       NULL;
1474     END IF;
1475   ELSIF (p_uc_header_id <> l_root_uc_header_id) THEN
1476     --Sub unit installed on another unit, either extra node or non extra node
1477     ahl_util_uc_pkg.get_parent_uc_header(l_uc_header_attr.instance_id,
1478                                          l_parent_uc_header_id,
1479                                          l_parent_instance_id);
1480     --Get its parent_instance_id in order to check whether it is an extra node within
1481     --the context of its parent UC
1482     IF NOT ahl_util_uc_pkg.extra_node(l_uc_header_attr.instance_id, l_parent_instance_id) THEN
1483     --Non extra sub unit within the context of its parent unit
1484     --Get its position_reference
1485       OPEN get_position_reference(l_parent_instance_id, l_uc_header_attr.instance_id);
1486       FETCH get_position_reference INTO l_position_info;
1487       IF get_position_reference%NOTFOUND THEN
1488         FND_MESSAGE.set_name( 'AHL','AHL_UC_UNIT_UNINSTALLED' );
1489         FND_MESSAGE.set_token('CHILD',l_uc_header_attr.instance_id);
1490         FND_MESSAGE.set_token('PARENT',l_parent_instance_id);
1491         FND_MSG_PUB.add;
1492         CLOSE get_position_reference;
1493         RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1494       END IF;
1495       CLOSE get_position_reference;
1496       --Check whether the new mc_header_id to which to be migrated could be an alternate sub MC
1497       --in position
1498       l_boolean_var := FALSE;
1499       FOR l_get_sub_mcs IN get_sub_mcs(l_position_info.relationship_id) LOOP
1500         l_sub_mc_header_id := l_get_sub_mcs.mc_header_id;
1501         IF l_sub_mc_header_id = p_mc_header_id THEN
1502           l_boolean_var := TRUE;
1503           EXIT;
1504         END IF;
1505       END LOOP;
1506       IF NOT l_boolean_var THEN
1507       --Again check whether item match
1508         l_item_match := AHL_UTIL_UC_PKG.item_match(l_mc_top_rel_id,
1509                              l_uc_header_attr.inventory_item_id,
1510                              l_uc_header_attr.inventory_org_id,
1511                              l_uc_header_attr.inventory_revision,
1512                              l_uc_header_attr.quantity,
1513                              l_uc_header_attr.unit_of_measure);
1514         IF NOT l_item_match THEN
1515           FND_MESSAGE.set_name( 'AHL','AHL_UC_HEADER_NOT_MATCH' );
1516           FND_MSG_PUB.add;
1517           RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1518         ELSE
1519           --Make the sub unit an extra node in its parent unit context and
1520           --update its own mc_header_id to the new p_mc_header_id
1521 
1522           --Set the CSI transaction record
1523           l_csi_transaction_rec.source_transaction_date := SYSDATE;
1524           l_csi_transaction_rec.transaction_type_id := l_transaction_type_id;
1525           --Set CSI relationship record
1526           l_csi_relationship_rec.relationship_id := l_position_info.csi_ii_relationship_id;
1527           l_csi_relationship_rec.object_version_number := l_position_info.csi_ii_relationship_ovn;
1528           l_csi_relationship_rec.position_reference := NULL;
1529           l_csi_relationship_rec.relationship_type_code := 'COMPONENT-OF';
1530           l_csi_relationship_rec.object_id := l_parent_instance_id;
1531           l_csi_relationship_rec.subject_id := l_uc_header_attr.instance_id;
1532           l_csi_relationship_tbl(1) := l_csi_relationship_rec;
1533           CSI_II_RELATIONSHIPS_PUB.update_relationship(
1534                                    p_api_version      => 1.0,
1535                                    p_relationship_tbl => l_csi_relationship_tbl,
1536                                    p_txn_rec          => l_csi_transaction_rec,
1537                                    x_return_status    => l_return_status,
1538                                    x_msg_count        => l_msg_count,
1539                                    x_msg_data         => l_msg_data);
1540           IF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
1541             RAISE FND_API.G_EXC_ERROR;
1542           ELSIF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
1543             RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1544           END IF;
1545           --Could be migrated and thus change the mc_header_id of the UC header
1546           NULL;
1547         END IF;
1548       ELSE
1549         --The sub unit is still an alternate sub unit so only need to update
1550         --its own mc_header_id to the new p_mc_header_id
1551         NULL;
1552       END IF;
1553     ELSE
1554     --Extra node and check whether item match
1555       l_item_match := AHL_UTIL_UC_PKG.item_match(l_mc_top_rel_id,
1556                              l_uc_header_attr.inventory_item_id,
1557                              l_uc_header_attr.inventory_org_id,
1558                              l_uc_header_attr.inventory_revision,
1559                              l_uc_header_attr.quantity,
1560                              l_uc_header_attr.unit_of_measure);
1561       IF NOT l_item_match THEN
1562         FND_MESSAGE.set_name( 'AHL','AHL_UC_HEADER_NOT_MATCH' );
1563         FND_MSG_PUB.add;
1564         RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1565       ELSE
1566       --Could be migrated but will be still extra node to its parent unit
1567       --Not necessary to update position_reference to NULL because it is already an
1568       --extra node to its parent unit
1569         NULL;
1570       END IF;
1571     END IF;
1572   END IF;
1573   --Update the master_config_id of p_uc_header_id to the new p_mc_header_id
1574   IF p_uc_header_id = l_root_uc_header_id THEN
1575   --For standalone no object_version_number change here because we have to update the
1576   --status for the same record after migration
1577     UPDATE ahl_unit_config_headers
1578        SET master_config_id = p_mc_header_id,
1579            last_updated_by = fnd_global.user_id,
1580            last_update_date = SYSDATE,
1581            last_update_login = fnd_global.login_id
1582      WHERE unit_config_header_id = p_uc_header_id
1583        AND object_version_number = l_uc_header_attr.object_version_number;
1584   ELSE
1585     UPDATE ahl_unit_config_headers
1586        SET master_config_id = p_mc_header_id,
1587            object_version_number = object_version_number + 1,
1588            last_updated_by = fnd_global.user_id,
1589            last_update_date = SYSDATE,
1590            last_update_login = fnd_global.login_id
1591      WHERE unit_config_header_id = p_uc_header_id
1592        AND object_version_number = l_uc_header_attr.object_version_number;
1593   END IF;
1594   IF SQL%ROWCOUNT = 0 THEN
1595     FND_MESSAGE.set_name( 'AHL','AHL_COM_RECORD_CHANGED' );
1596     FND_MSG_PUB.add;
1597     RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1598   END IF;
1599 
1600   --Copy the change to UC history table
1601   ahl_util_uc_pkg.copy_uc_header_to_history(p_uc_header_id, l_return_status);
1602   --IF history copy failed, then don't raise exception, just add the messageto the message stack
1603   IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
1604     FND_MESSAGE.set_name('AHL', 'AHL_UC_HISTORY_COPY_FAILED');
1605     FND_MSG_PUB.add;
1606   END IF;
1607 
1608   IF (FND_LOG.LEVEL_STATEMENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
1609 	FND_LOG.STRING(FND_LOG.LEVEL_STATEMENT,
1610                    'ahl.plsql.'||G_PKG_NAME||'.'||l_api_name||':Within API',
1611 			       'After updating the master_config_id');
1612   END IF;
1613 
1614   --Loop through all the non leaf nodes including the root node
1615   FOR l_get_non_leaf_node IN get_non_leaf_nodes(l_uc_header_attr.instance_id) LOOP
1616     --Make sure the node doesn't belong to a sub unit or extra node branch, because for
1617     --all the nodes in the sub unit or extra node branch including the top most extra node
1618     --it is not necessary to process them and the sub unit top node is processed in the loop
1619     --of its parent node
1620     OPEN check_subuc_extra(l_get_non_leaf_node.instance_id, l_uc_header_attr.instance_id);
1621     FETCH check_subuc_extra INTO l_check_subuc_extra;
1622     IF check_subuc_extra%NOTFOUND THEN
1623       --Get all the immediate children of the corresponding MC node
1624       --First get the non leaf node's new relationship_id to which it has been migrated
1625       --This is a bug fix found by Barry on Nov 6, 2003
1626       IF l_uc_header_attr.instance_id = l_get_non_leaf_node.instance_id THEN
1627         l_new_relationship_id := l_get_non_leaf_node.relationship_id;
1628       ELSE
1629         SELECT to_number(position_reference) into l_new_relationship_id
1630           FROM csi_ii_relationships
1631          WHERE subject_id = l_get_non_leaf_node.instance_id
1632            AND relationship_type_code='COMPONENT-OF'
1633            AND trunc(nvl(active_start_date, sysdate)) <= trunc(sysdate)
1634            AND trunc(nvl(active_end_date, sysdate+1)) > trunc(sysdate);
1635       END IF;
1636 
1637       i_mc_child := 1;
1638       FOR l_get_mc_child IN get_mc_children(l_new_relationship_id) LOOP
1639         l_mc_children_tbl(i_mc_child).relationship_id := l_get_mc_child.relationship_id;
1640         l_mc_children_tbl(i_mc_child).position_key := l_get_mc_child.position_key;
1641         l_mc_children_tbl(i_mc_child).position_ref_code := l_get_mc_child.position_ref_code;
1642         l_mc_children_tbl(i_mc_child).item_group_id := l_get_mc_child.item_group_id;
1643         l_mc_children_tbl(i_mc_child).matched_flag := 'N'; -- default to 'N'
1644         i_mc_child := i_mc_child + 1;
1645       END LOOP;
1646       FOR l_get_csi_child IN get_csi_children(l_get_non_leaf_node.instance_id) LOOP
1647         --No processing for the extra node
1648         IF l_get_csi_child.relationship_id IS NOT NULL THEN
1649           l_matched := FALSE;
1650           l_relationship_id := NULL;
1651           IF l_mc_children_tbl.COUNT > 0 THEN
1652           <<OUTER>>
1653           FOR i IN l_mc_children_tbl.FIRST..l_mc_children_tbl.LAST LOOP
1654             IF l_mc_children_tbl(i).matched_flag <> 'Y' THEN
1655               IF l_get_csi_child.position_key = l_mc_children_tbl(i).position_key OR
1656                  l_get_csi_child.position_ref_code = l_mc_children_tbl(i).position_ref_code THEN
1657                 --Check whether this node is a sub unit top node, if YES compare the sub
1658                 --mc_header_id, otherwise compare item
1659                 OPEN check_sub_uc(l_get_csi_child.instance_id);
1660                 FETCH check_sub_uc INTO l_check_sub_uc;
1661                 IF check_sub_uc%FOUND THEN
1662                   FOR l_get_sub_mc IN get_sub_mcs(l_mc_children_tbl(i).relationship_id) LOOP
1663                     IF l_check_sub_uc.mc_header_id = l_get_sub_mc.mc_header_id THEN
1664                       l_matched := TRUE;
1665                       l_mc_children_tbl(i).matched_flag := 'Y';
1666                       l_relationship_id := l_mc_children_tbl(i).relationship_id;
1667                       CLOSE check_sub_uc;
1668                       EXIT OUTER;
1669                     END IF;
1670                   END LOOP;
1671                 ELSE
1672                   l_matched := AHL_UTIL_UC_PKG.item_match(l_mc_children_tbl(i).relationship_id,
1673                                                 l_get_csi_child.inventory_item_id,
1674                                                 l_get_csi_child.inventory_org_id,
1675                                                 l_get_csi_child.inventory_revision,
1676                                                 l_get_csi_child.quantity,
1677                                                 l_get_csi_child.unit_of_measure);
1678                   IF l_matched THEN
1679                     l_mc_children_tbl(i).matched_flag := 'Y';
1680                     l_relationship_id := l_mc_children_tbl(i).relationship_id;
1681                     CLOSE check_sub_uc;
1682                     EXIT OUTER;
1683                   END IF;
1684                   /*
1685                   FOR l_get_associated_item IN get_associated_items(l_mc_children_tbl(i).item_group_id) LOOP
1686                     IF l_get_csi_child.inventory_item_id = l_get_associated_item.inventory_item_id AND
1687                        l_get_csi_child.inventory_org_id = l_get_associated_item.inventory_org_id THEN
1688                       l_matched := TRUE;
1689                       l_relationship_id := l_mc_children_tbl(i).relationship_id;
1690                       EXIT OUTER;
1691                     END IF;
1692                   END LOOP;
1693                   */
1694 
1695                 END IF;
1696                 CLOSE check_sub_uc;
1697               END IF; --whether position_key or position_ref_code matches
1698             END IF; --whether the MC chilren node has already been matched
1699           END LOOP; --of all the MC children
1700           END IF;
1701 
1702           --Set the CSI transaction record
1703           l_csi_transaction_rec.source_transaction_date := SYSDATE;
1704           l_csi_transaction_rec.transaction_type_id := l_transaction_type_id;
1705           --Set CSI relationship record
1706           l_csi_relationship_rec.relationship_id := l_get_csi_child.csi_ii_relationship_id;
1707           l_csi_relationship_rec.object_version_number := l_get_csi_child.csi_ii_relationship_ovn;
1708           l_csi_relationship_rec.position_reference := to_char(l_relationship_id);
1709           l_csi_relationship_rec.relationship_type_code := 'COMPONENT-OF';
1710           l_csi_relationship_rec.object_id := l_get_csi_child.parent_instance_id;
1711           l_csi_relationship_rec.subject_id := l_get_csi_child.instance_id;
1712           l_csi_relationship_tbl(1) := l_csi_relationship_rec;
1713           CSI_II_RELATIONSHIPS_PUB.update_relationship(
1714                                    p_api_version      => 1.0,
1715                                    p_relationship_tbl => l_csi_relationship_tbl,
1716                                    p_txn_rec          => l_csi_transaction_rec,
1717                                    x_return_status    => l_return_status,
1718                                    x_msg_count        => l_msg_count,
1719                                    x_msg_data         => l_msg_data);
1720           IF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
1721             RAISE FND_API.G_EXC_ERROR;
1722           ELSIF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
1723             RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1724           END IF;
1725         END IF; --whether the UC node is an extra node
1726       END LOOP; --of all the UC children
1727     END IF; --whether it is a node belonging to subuc or extra node branch
1728     CLOSE check_subuc_extra;
1729   END LOOP; --of all non leaf nodes
1730 
1731   IF (FND_LOG.LEVEL_STATEMENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
1732 	FND_LOG.STRING(FND_LOG.LEVEL_STATEMENT,
1733                    'ahl.plsql.'||G_PKG_NAME||'.'||l_api_name||':Within API',
1734 			       'After migration the whole UC tree');
1735   END IF;
1736 
1737   --Call check_completeness API to check the completeness of the root UC
1738   IF (l_root_uc_status_code IN ('COMPLETE', 'INCOMPLETE')) THEN
1739     AHL_UC_VALIDATION_PUB.check_completeness(
1740       p_api_version       => 1.0,
1741       p_init_msg_list     => FND_API.G_FALSE,
1742       p_commit            => FND_API.G_FALSE,
1743       p_validation_level  => FND_API.G_VALID_LEVEL_FULL,
1744       x_return_status     => l_return_status,
1745       x_msg_count         => l_msg_count,
1746       x_msg_data          => l_msg_data,
1747       p_unit_header_id	  => l_root_uc_header_id,
1748       x_evaluation_status => l_evaluation_status);
1749     IF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
1750       RAISE FND_API.G_EXC_ERROR;
1751     ELSIF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
1752       RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1753     END IF;
1754   END IF;
1755   --dbms_output.put_line('l_root_uc_ovn(a)='||l_root_uc_ovn);
1756   select object_version_number into l_root_uc_ovn
1757     from ahl_unit_config_headers
1758    where unit_config_header_id = l_root_uc_header_id;
1759   --dbms_output.put_line('l_root_uc_ovn(b)='||l_root_uc_ovn);
1760 
1761   --After migration, UC(root) status change should be made.
1762   IF (l_evaluation_status = 'T' AND l_root_uc_status_code = 'INCOMPLETE') THEN
1763     UPDATE ahl_unit_config_headers
1764        SET unit_config_status_code = 'COMPLETE',
1765            active_uc_status_code = 'UNAPPROVED',
1766            object_version_number = object_version_number + 1,
1767            last_updated_by = fnd_global.user_id,
1768            last_update_date = SYSDATE,
1769            last_update_login = fnd_global.login_id
1770      WHERE unit_config_header_id = l_root_uc_header_id
1771        AND object_version_number = l_root_uc_ovn;
1772     IF SQL%ROWCOUNT = 0 THEN
1773       FND_MESSAGE.set_name( 'AHL','AHL_COM_RECORD_CHANGED' );
1774       FND_MSG_PUB.add;
1775       RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1776     END IF;
1777 
1778     --Copy the change to UC history table
1779     ahl_util_uc_pkg.copy_uc_header_to_history(l_root_uc_header_id, l_return_status);
1780     --IF history copy failed, then don't raise exception, just add the messageto the message stack
1781     IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
1782       FND_MESSAGE.set_name('AHL', 'AHL_UC_HISTORY_COPY_FAILED');
1783       FND_MSG_PUB.add;
1784     END IF;
1785   ELSIF (l_evaluation_status = 'F' AND l_root_uc_status_code = 'COMPLETE') THEN
1786     UPDATE ahl_unit_config_headers
1787        SET unit_config_status_code = 'INCOMPLETE',
1788            active_uc_status_code = 'UNAPPROVED',
1789            object_version_number = object_version_number + 1,
1790            last_updated_by = fnd_global.user_id,
1791            last_update_date = SYSDATE,
1792            last_update_login = fnd_global.login_id
1793      WHERE unit_config_header_id = l_root_uc_header_id
1794        AND object_version_number = l_root_uc_ovn;
1795     IF SQL%ROWCOUNT = 0 THEN
1796       FND_MESSAGE.set_name( 'AHL','AHL_COM_RECORD_CHANGED' );
1797       FND_MSG_PUB.add;
1798       RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1799     END IF;
1800 
1801     --Copy the change to UC history table
1802     ahl_util_uc_pkg.copy_uc_header_to_history(l_root_uc_header_id, l_return_status);
1803     --IF history copy failed, then don't raise exception, just add the messageto the message stack
1804     IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
1805       FND_MESSAGE.set_name('AHL', 'AHL_UC_HISTORY_COPY_FAILED');
1806       FND_MSG_PUB.add;
1807     END IF;
1808   ELSIF (l_root_uc_status_code IN ('COMPLETE', 'INCOMPLETE') AND
1809          (l_root_active_uc_status_code IS NULL OR
1810           l_root_active_uc_status_code <> 'UNAPPROVED')) THEN
1811     UPDATE ahl_unit_config_headers
1812        SET active_uc_status_code = 'UNAPPROVED',
1813            object_version_number = object_version_number + 1,
1814            last_updated_by = fnd_global.user_id,
1815            last_update_date = SYSDATE,
1816            last_update_login = fnd_global.login_id
1817      WHERE unit_config_header_id = l_root_uc_header_id
1818        AND object_version_number = l_root_uc_ovn;
1819     IF SQL%ROWCOUNT = 0 THEN
1820       FND_MESSAGE.set_name( 'AHL','AHL_COM_RECORD_CHANGED' );
1821       FND_MSG_PUB.add;
1822       RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1823     END IF;
1824 
1825     --Copy the change to UC history table
1826     ahl_util_uc_pkg.copy_uc_header_to_history(l_root_uc_header_id, l_return_status);
1827     --IF history copy failed, then don't raise exception, just add the messageto the message stack
1828     IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
1829       FND_MESSAGE.set_name('AHL', 'AHL_UC_HISTORY_COPY_FAILED');
1830       FND_MSG_PUB.add;
1831     END IF;
1832   END IF;
1833 
1834   IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
1835 	FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
1836                    'ahl.plsql.'||G_PKG_NAME||'.'||l_api_name||':After normal execution',
1837 			       'Status changed and at the end of the procedure');
1838   END IF;
1839 
1840   -- Get all the error messages from the previous steps (if any) and raise the appropriate Exception
1841   l_msg_count := FND_MSG_PUB.count_msg;
1842   IF l_msg_count > 0 THEN
1843     x_msg_count := l_msg_count;
1844     RAISE FND_API.G_EXC_ERROR;
1845   END IF;
1846 
1847   -- Perform the Commit (if requested)
1848   IF FND_API.to_boolean(p_commit) THEN
1849     COMMIT;
1850   END IF;
1851 
1852   -- Count and Get messages (optional)
1853   FND_MSG_PUB.count_and_get(
1854     p_encoded  => FND_API.G_FALSE,
1855     p_count    => x_msg_count,
1856     p_data     => x_msg_data);
1857 
1858 EXCEPTION
1859   WHEN FND_API.G_EXC_ERROR THEN
1860     ROLLBACK TO migrate_uc_tree;
1861     x_return_status := FND_API.G_RET_STS_ERROR ;
1862     FND_MSG_PUB.count_and_get(
1863       p_encoded  => FND_API.G_FALSE,
1864       p_count    => x_msg_count,
1865       p_data     => x_msg_data);
1866   WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
1867     ROLLBACK TO migrate_uc_tree;
1868     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
1869     FND_MSG_PUB.count_and_get(
1870       p_encoded  => FND_API.G_FALSE,
1871       p_count    => x_msg_count,
1872       p_data     => x_msg_data);
1873   WHEN OTHERS THEN
1874     ROLLBACK TO migrate_uc_tree;
1875     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
1876     IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR)
1877     THEN
1878       FND_MSG_PUB.add_exc_msg(
1879         p_pkg_name         => G_PKG_NAME,
1880         p_procedure_name   => l_api_name,
1881         p_error_text       => SUBSTRB(SQLERRM,1,240));
1882     END IF;
1883     FND_MSG_PUB.count_and_get(
1884       p_encoded  => FND_API.G_FALSE,
1885       p_count    => x_msg_count,
1886       p_data     => x_msg_data);
1887 END;
1888 
1889 -- Define Procedure remap_uc_subtree --
1890 -- This API is used to remap a UC subtree (not a sub-unit) to a MC branch. It is called
1891 -- by ahl_uc_instnace_pvt.install_existing_instance.
1892 PROCEDURE remap_uc_subtree (
1893   p_api_version           IN  NUMBER,
1894   p_init_msg_list         IN  VARCHAR2  := FND_API.G_FALSE,
1895   p_commit                IN  VARCHAR2  := FND_API.G_FALSE,
1896   p_validation_level      IN  NUMBER    := FND_API.G_VALID_LEVEL_FULL,
1897   x_return_status         OUT NOCOPY VARCHAR2,
1898   x_msg_count             OUT NOCOPY NUMBER,
1899   x_msg_data              OUT NOCOPY VARCHAR2,
1900   p_instance_id           IN  NUMBER,
1901   p_relationship_id       IN  NUMBER)
1902 IS
1903   TYPE l_mc_children_rec_type IS RECORD(
1904     relationship_id           NUMBER,
1905     position_key              NUMBER,
1906     position_ref_code         VARCHAR2(30),
1907     item_group_id             NUMBER,
1908     matched_flag              VARCHAR2(1));
1909   TYPE l_mc_children_tbl_type IS TABLE OF l_mc_children_rec_type INDEX BY BINARY_INTEGER;
1910   l_mc_children_tbl           l_mc_children_tbl_type;
1911   l_api_name       CONSTANT   VARCHAR2(30)   := 'remap_uc_subtree';
1912   l_api_version    CONSTANT   NUMBER         := 1.0;
1913   l_return_status             VARCHAR2(1);
1914   l_msg_count                 NUMBER;
1915   l_msg_data                  VARCHAR2(2000);
1916   l_relationship_id           NUMBER;
1917   l_mc_header_id              NUMBER;
1918   l_root_instance_id          NUMBER;
1919   l_root_relationship_id      NUMBER;
1920   l_dummy                     NUMBER;
1921   i                           NUMBER;
1922   i_mc_child                  NUMBER;
1923   l_item_match                BOOLEAN;
1924   l_matched                   BOOLEAN;
1925   l_return_value              BOOLEAN;
1926   l_transaction_type_id       NUMBER;
1927   l_version_no                NUMBER;
1928   l_csi_relationship_rec      csi_datastructures_pub.ii_relationship_rec;
1929   l_csi_relationship_tbl      csi_datastructures_pub.ii_relationship_tbl;
1930   l_csi_transaction_rec       csi_datastructures_pub.transaction_rec;
1931   l_new_relationship_id       NUMBER;
1932   --In order to check whether the instance belongs to a sub unit or an extra node branch
1933   CURSOR check_subuc_extra(c_instance_id NUMBER, c_top_instance_id NUMBER) IS
1934     SELECT object_id, subject_id, position_reference
1935       FROM csi_ii_relationships
1936      WHERE subject_id IN (SELECT csi_item_instance_id
1937                             FROM ahl_unit_config_headers
1938                            WHERE trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE))
1939         OR position_reference IS NULL
1940 START WITH subject_id = c_instance_id
1941        AND relationship_type_code = 'COMPONENT-OF'
1942        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
1943        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE)
1944 CONNECT BY subject_id = PRIOR object_id
1945        AND subject_id <> c_top_instance_id
1946        --This hierarchy query is from bottom up and the top node is not a UC root node, so we
1947        --have to discontinue the hierarchy query when it comes to the given node
1948        AND relationship_type_code = 'COMPONENT-OF'
1949        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
1950        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE);
1951   l_check_subuc_extra    check_subuc_extra%ROWTYPE;
1952   --Check the given instance_id is existing, with children instances and not a unit's or sub-unit's top node. But doesn't check whether this instance is installed or not, which is checked in get_available_instances and install_existing_instance.
1953   CURSOR check_uc_instance IS
1954     SELECT R.object_id instance_id,
1955            to_number(R.position_reference) relationship_id,
1956            C.inventory_item_id inventory_item_id,
1957            C.inv_master_organization_id inventory_org_id,
1958            C.inventory_revision,
1959            C.quantity,
1960            C.unit_of_measure
1961       FROM csi_ii_relationships R,
1962            csi_item_instances C
1963      WHERE R.object_id = p_instance_id
1964        AND R.object_id = C.instance_id
1965        AND R.relationship_type_code = 'COMPONENT-OF'
1966        AND trunc(nvl(R.active_start_date,SYSDATE)) <= trunc(SYSDATE)
1967        AND trunc(nvl(R.active_end_date, SYSDATE+1)) > trunc(SYSDATE)
1968        AND NOT EXISTS (SELECT 'X'
1969                          FROM ahl_unit_config_headers
1970                         WHERE csi_item_instance_id = R.object_id
1971                           AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE));
1972   l_check_uc_instance check_uc_instance%ROWTYPE;
1973   --Check the given relationship_id exists and also get its item
1974   CURSOR check_mc_relationship IS
1975     SELECT M.relationship_id,
1976            I.inventory_item_id,
1977            I.inventory_org_id
1978       FROM ahl_mc_relationships M,
1979            ahl_item_associations_b I
1980      WHERE M.relationship_id = p_relationship_id
1981        AND M.item_group_id = I.item_group_id
1982        AND trunc(nvl(M.active_start_date,SYSDATE)) <= trunc(SYSDATE)
1983        AND trunc(nvl(M.active_end_date, SYSDATE+1)) > trunc(SYSDATE);
1984   l_check_mc_relationship check_mc_relationship%ROWTYPE;
1985   --Get the associated items for a given item_group_id
1986   /*
1987   CURSOR get_associated_items(c_item_group_id NUMBER) IS
1988     SELECT inventory_item_id,
1989            inventory_org_id
1990       FROM ahl_item_associations_b
1991      WHERE item_group_id = c_item_group_id;
1992   l_get_associated_item        get_associated_items%ROWTYPE;
1993   */
1994   --Given an instance_id, get all of its immediate children from csi_ii_relationships
1995   CURSOR get_csi_children(c_instance_id NUMBER) IS
1996     SELECT C.relationship_id csi_ii_relationship_id,
1997            C.object_version_number csi_ii_relationship_ovn,
1998            C.object_id parent_instance_id,
1999            C.subject_id instance_id,
2000            to_number(C.position_reference) relationship_id,
2001            M.position_key,
2002            M.position_ref_code,
2003            I.inventory_item_id,
2004            I.inv_master_organization_id inventory_org_id,
2005            I.inventory_revision,
2006            I.quantity,
2007            I.unit_of_measure
2008       FROM csi_ii_relationships C,
2009            ahl_mc_relationships M,
2010            csi_item_instances I
2011      WHERE to_number(C.position_reference) = M.relationship_id (+)
2012        AND C.subject_id = I.instance_id
2013        AND C.object_id = c_instance_id
2014        AND C.relationship_type_code = 'COMPONENT-OF'
2015        AND trunc(nvl(C.active_start_date,SYSDATE)) <= trunc(SYSDATE)
2016        AND trunc(nvl(C.active_end_date, SYSDATE+1)) > trunc(SYSDATE);
2017   --Given an relationship_id, get all of its immediate children from MC
2018   CURSOR get_mc_children(c_relationship_id NUMBER) IS
2019     SELECT parent_relationship_id parent_rel_id,
2020            relationship_id,
2021            position_key,
2022            position_ref_code,
2023            item_group_id
2024       FROM ahl_mc_relationships
2025      WHERE parent_relationship_id = c_relationship_id
2026        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
2027        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE);
2028   --Check whether an instance in UC is the top node of a sub UC, if yes, then get the
2029   --relationship of the sub UC's top node
2030   CURSOR check_sub_uc(c_instance_id NUMBER) IS
2031     SELECT A.master_config_id mc_header_id,
2032            B.relationship_id
2033       FROM ahl_unit_config_headers A,
2034            ahl_mc_relationships B
2035      WHERE A.csi_item_instance_id = c_instance_id
2036        AND trunc(nvl(A.active_end_date, SYSDATE+1)) > trunc(SYSDATE)
2037        AND B.mc_header_id = A.master_config_id
2038        AND B.parent_relationship_id IS NULL
2039        AND trunc(nvl(B.active_start_date,SYSDATE)) <= trunc(SYSDATE)
2040        AND trunc(nvl(B.active_end_date, SYSDATE+1)) > trunc(SYSDATE);
2041   l_check_sub_uc        check_sub_uc%ROWTYPE;
2042   --Given a position(leaf) in MC, get all the sub MCs which can be associated to this position
2043   CURSOR get_sub_mcs(c_relationship_id NUMBER) IS
2044     SELECT mc_header_id
2045       FROM ahl_mc_config_relations
2046      WHERE relationship_id = c_relationship_id
2047        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
2048        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE);
2049   --Based on the UC, list all of the non leaf nodes including the root node
2050   CURSOR get_non_leaf_nodes(c_instance_id NUMBER) IS
2051     SELECT object_id parent_instance_id,
2052            subject_id instance_id,
2053            to_number(position_reference) relationship_id
2054       FROM csi_ii_relationships A
2055       --remove all of the leaf node after finishing the hierarchical query
2056      WHERE EXISTS (SELECT 'X'
2057                      FROM csi_ii_relationships B
2058                     WHERE B.object_id = A.subject_id
2059                       AND relationship_type_code = 'COMPONENT-OF'
2060                       AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
2061                       AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE))
2062 START WITH subject_id = c_instance_id
2063        AND relationship_type_code = 'COMPONENT-OF'
2064        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
2065        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE)
2066 CONNECT BY object_id = PRIOR subject_id
2067        AND relationship_type_code = 'COMPONENT-OF'
2068        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
2069        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE);
2070 BEGIN
2071   --Initialize API return status to success
2072   x_return_status := FND_API.G_RET_STS_SUCCESS;
2073 
2074   -- Standard Start of API savepoint
2075   SAVEPOINT remap_uc_subtree;
2076 
2077   --Standard call to check for call compatibility.
2078   IF NOT FND_API.compatible_api_call(
2079     l_api_version,
2080     p_api_version,
2081     l_api_name,
2082     G_PKG_NAME)
2083   THEN
2084     RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
2085   END IF;
2086   --Initialize message list if p_init_msg_list is set to TRUE.
2087   IF FND_API.to_boolean( p_init_msg_list ) THEN
2088     FND_MSG_PUB.initialize;
2089   END IF;
2090   IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
2091     FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
2092                    'ahl.plsql.'||G_PKG_NAME||'.'||l_api_name||'.begin',
2093                    'At the start of the procedure, p_instance_id = ' || p_instance_id || ', p_relationship_id = ' || p_relationship_id);
2094   END IF;
2095   --Validate the input parameter p_instance_id
2096   OPEN check_uc_instance;
2097   FETCH check_uc_instance INTO l_check_uc_instance;
2098   IF check_uc_instance%NOTFOUND THEN
2099     FND_MESSAGE.set_name('AHL','AHL_UC_API_PARAMETER_INVALID');
2100     FND_MESSAGE.set_token('NAME', 'instance_id');
2101     FND_MESSAGE.set_token('VALUE', p_instance_id);
2102     FND_MSG_PUB.add;
2103    CLOSE check_uc_instance;
2104     RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
2105   ELSE
2106     CLOSE check_uc_instance;
2107   END IF;
2108 
2109   --Validate the input parameter p_relationship_id
2110   OPEN check_mc_relationship;
2111   FETCH check_mc_relationship INTO l_check_mc_relationship;
2112   IF check_mc_relationship%NOTFOUND THEN
2113     FND_MESSAGE.set_name('AHL','AHL_UC_API_PARAMETER_INVALID');
2114     FND_MESSAGE.set_token('NAME', 'relationship_id');
2115     FND_MESSAGE.set_token('VALUE', p_relationship_id);
2116     FND_MSG_PUB.add;
2117     CLOSE check_mc_relationship;
2118     RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
2119   ELSE
2120     CLOSE check_mc_relationship;
2121   END IF;
2122 
2123   --For UC branch top node, only need to ensure item matches, no need to check position key
2124   --and position_reference
2125   l_item_match := AHL_UTIL_UC_PKG.item_match(p_relationship_id,
2126                                              l_check_uc_instance.inventory_item_id,
2127                                              l_check_uc_instance.inventory_org_id,
2128                                              l_check_uc_instance.inventory_revision,
2129                                              l_check_uc_instance.quantity,
2130                                              l_check_uc_instance.unit_of_measure);
2131   /*
2132   FOR l_check_mc_relationship IN check_mc_relationship LOOP
2133     IF l_check_uc_instance.inventory_item_id = l_check_mc_relationship.inventory_item_id AND
2134        l_check_uc_instance.inventory_org_id = l_check_mc_relationship.inventory_org_id THEN
2135       l_item_match := TRUE;
2136       EXIT;
2137     END IF;
2138   END LOOP;
2139   */
2140   IF NOT l_item_match THEN
2141     FND_MESSAGE.set_name( 'AHL','AHL_UC_INSTANCE_NOT_MATCH' );
2142     FND_MESSAGE.set_token('INSTANCE', p_instance_id);
2143     FND_MSG_PUB.add;
2144     RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
2145   END IF;
2146 
2147   --Loop through all the non leaf nodes including the top node
2148   FOR l_get_non_leaf_node IN get_non_leaf_nodes(p_instance_id) LOOP
2149     --Make sure the node doesn't belong to a sub unit or extra node branch, because for
2150     --all the nodes in the sub unit or extra node branch including the top most extra node
2151     --it is not necessary to process them and the sub unit top node itself has been processed in the loop
2152     --of its parent node
2153     OPEN check_subuc_extra(l_get_non_leaf_node.instance_id, p_instance_id);
2154     FETCH check_subuc_extra INTO l_check_subuc_extra;
2155     IF check_subuc_extra%NOTFOUND THEN
2156       --Get all the immediate children of the corresponding MC node
2157       --First get the non leaf node's new relationship_id to which it has been migrated
2158       --This is a bug fix found by Barry on Nov 6, 2003
2159       IF p_instance_id = l_get_non_leaf_node.instance_id THEN
2160         l_new_relationship_id := p_relationship_id;
2161       ELSE
2162         SELECT to_number(position_reference) into l_new_relationship_id
2163           FROM csi_ii_relationships
2164          WHERE subject_id = l_get_non_leaf_node.instance_id
2165            AND relationship_type_code='COMPONENT-OF'
2166            AND trunc(nvl(active_start_date, sysdate)) <= trunc(sysdate)
2167            AND trunc(nvl(active_end_date, sysdate+1)) > trunc(sysdate);
2168       END IF;
2169 
2170       i_mc_child := 1;
2171       FOR l_get_mc_child IN get_mc_children(l_new_relationship_id) LOOP
2172         l_mc_children_tbl(i_mc_child).relationship_id := l_get_mc_child.relationship_id;
2173         l_mc_children_tbl(i_mc_child).position_key := l_get_mc_child.position_key;
2174         l_mc_children_tbl(i_mc_child).position_ref_code := l_get_mc_child.position_ref_code;
2175         l_mc_children_tbl(i_mc_child).item_group_id := l_get_mc_child.item_group_id;
2176         l_mc_children_tbl(i_mc_child).matched_flag := 'N'; -- default to 'N'
2177         i_mc_child := i_mc_child + 1;
2178       END LOOP;
2179       FOR l_get_csi_child IN get_csi_children(l_get_non_leaf_node.instance_id) LOOP
2180         --No processing for the extra node
2181         IF l_get_csi_child.relationship_id IS NOT NULL THEN
2182           l_matched := FALSE;
2183           l_relationship_id := NULL;
2184           <<OUTER>>
2185           FOR i IN l_mc_children_tbl.FIRST..l_mc_children_tbl.LAST LOOP
2186             IF l_mc_children_tbl(i).matched_flag <> 'Y' THEN
2187               IF l_get_csi_child.position_key = l_mc_children_tbl(i).position_key OR
2188                  l_get_csi_child.position_ref_code = l_mc_children_tbl(i).position_ref_code THEN
2189                 --Check whether this node is a sub unit top node, if YES compare the sub
2190                 --mc_header_id(not necessary to compare the top node's item), otherwise compare item
2191                 OPEN check_sub_uc(l_get_csi_child.instance_id);
2192                 FETCH check_sub_uc INTO l_check_sub_uc;
2193                 IF check_sub_uc%FOUND THEN
2194                   FOR l_get_sub_mc IN get_sub_mcs(l_mc_children_tbl(i).relationship_id) LOOP
2195                     IF l_check_sub_uc.mc_header_id = l_get_sub_mc.mc_header_id THEN
2196                       l_matched := TRUE;
2197                       l_mc_children_tbl(i).matched_flag := 'Y';
2198                       l_relationship_id := l_mc_children_tbl(i).relationship_id;
2199                       CLOSE check_sub_uc;
2200                       EXIT OUTER;
2201                     END IF;
2202                   END LOOP;
2203                 ELSE
2204                   l_matched := AHL_UTIL_UC_PKG.item_match(l_mc_children_tbl(i).relationship_id,
2205                                                           l_get_csi_child.inventory_item_id,
2206                                                           l_get_csi_child.inventory_org_id,
2207                                                           l_get_csi_child.inventory_revision,
2208                                                           l_get_csi_child.quantity,
2209                                                           l_get_csi_child.unit_of_measure);
2210                   /*
2211                   FOR l_get_associated_item IN get_associated_items(l_mc_children_tbl(i).item_group_id) LOOP
2212                     IF l_get_csi_child.inventory_item_id = l_get_associated_item.inventory_item_id AND
2213                        l_get_csi_child.inventory_org_id = l_get_associated_item.inventory_org_id THEN
2214                       l_matched := TRUE;
2215                       l_relationship_id := l_mc_children_tbl(i).relationship_id;
2216                       EXIT OUTER;
2217                     END IF;
2218                   END LOOP;
2219                   */
2220                   IF l_matched THEN
2221                     l_mc_children_tbl(i).matched_flag := 'Y';
2222                     l_relationship_id := l_mc_children_tbl(i).relationship_id;
2223                     CLOSE check_sub_uc;
2224                     EXIT OUTER;
2225                   END IF;
2226                 END IF;
2227                 CLOSE check_sub_uc;
2228                 --Positions match but items or sub-configs don't match, then we define it as a hard failure
2229                 --in Part Change but still an extra node in migration. Both position_key and position_ref_code
2230                 --are unique across siblings.
2231                 IF NOT l_matched THEN
2232                   FND_MESSAGE.set_name( 'AHL','AHL_UC_INSTANCE_HARD_FAIL' );
2233                   FND_MESSAGE.set_token('INSTANCE', l_get_csi_child.instance_id);
2234                   FND_MSG_PUB.add;
2235                   RAISE FND_API.G_EXC_ERROR;
2236                 END IF;
2237               END IF; --whether position_key or position_ref_code matches
2238             END IF; --whether the MC chilren node has already been matched
2239           END LOOP; --of all the MC children
2240           --The following lines are used to update the position_reference column in csi_ii_relationships
2241           --First, get transaction_type_id .
2242           AHL_UTIL_UC_PKG.getcsi_transaction_id('UC_UPDATE',l_transaction_type_id, l_return_value);
2243           IF NOT l_return_value THEN
2244             RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
2245           END IF;
2246           --Set the CSI transaction record
2247           l_csi_transaction_rec.source_transaction_date := SYSDATE;
2248           l_csi_transaction_rec.transaction_type_id := l_transaction_type_id;
2249           --Set CSI relationship record
2250           l_csi_relationship_rec.relationship_id := l_get_csi_child.csi_ii_relationship_id;
2251           l_csi_relationship_rec.object_version_number := l_get_csi_child.csi_ii_relationship_ovn;
2252           l_csi_relationship_rec.position_reference := to_char(l_relationship_id);
2253           l_csi_relationship_rec.relationship_type_code := 'COMPONENT-OF';
2254           l_csi_relationship_rec.object_id := l_get_csi_child.parent_instance_id;
2255           l_csi_relationship_rec.subject_id := l_get_csi_child.instance_id;
2256           l_csi_relationship_tbl(1) := l_csi_relationship_rec;
2257           CSI_II_RELATIONSHIPS_PUB.update_relationship(
2258                                    p_api_version      => 1.0,
2259                                    p_relationship_tbl => l_csi_relationship_tbl,
2260                                    p_txn_rec          => l_csi_transaction_rec,
2261                                    x_return_status    => l_return_status,
2262                                    x_msg_count        => l_msg_count,
2263                                    x_msg_data         => l_msg_data);
2264           IF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
2265             RAISE FND_API.G_EXC_ERROR;
2266           ELSIF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
2267             RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
2268           END IF;
2269         END IF; --whether the UC node is an extra node
2270       END LOOP; --of all the UC children
2271     END IF; --whether it is a node belonging to subuc or extra node branch
2272     CLOSE check_subuc_extra;
2273   END LOOP; --of all non leaf nodes
2274 
2275   -- Added by rbhavsar on July 25, 2007 to remap IB Tree Nodes to fix FP bug 6276991
2276   Remap_IB_Tree(p_instance_id, p_relationship_id);
2277 
2278   IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
2279     FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE,
2280                    'ahl.plsql.'||G_PKG_NAME||'.'||l_api_name||'.end',
2281                    'At the end of the procedure');
2282   END IF;
2283   -- Get all the error messages from the previous steps (if any) and raise the appropriate Exception
2284   l_msg_count := FND_MSG_PUB.count_msg;
2285   IF l_msg_count > 0 THEN
2286     x_msg_count := l_msg_count;
2287     RAISE FND_API.G_EXC_ERROR;
2288   END IF;
2289   -- Perform the Commit (if requested)
2290   IF FND_API.to_boolean(p_commit) THEN
2291     COMMIT;
2292   END IF;
2293   -- Count and Get messages (optional)
2294   FND_MSG_PUB.count_and_get(
2295     p_encoded  => FND_API.G_FALSE,
2296     p_count    => x_msg_count,
2297     p_data     => x_msg_data);
2298 
2299 EXCEPTION
2300   WHEN FND_API.G_EXC_ERROR THEN
2301     ROLLBACK TO remap_uc_subtree;
2302     x_return_status := FND_API.G_RET_STS_ERROR ;
2303     FND_MSG_PUB.count_and_get(
2304       p_encoded  => FND_API.G_FALSE,
2305       p_count    => x_msg_count,
2306       p_data     => x_msg_data);
2307   WHEN FND_API.G_EXC_UNEXPECTED_ERROR THEN
2308     ROLLBACK TO remap_uc_subtree;
2309     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
2310     FND_MSG_PUB.count_and_get(
2311       p_encoded  => FND_API.G_FALSE,
2312       p_count    => x_msg_count,
2313       p_data     => x_msg_data);
2314   WHEN OTHERS THEN
2315     ROLLBACK TO remap_uc_subtree;
2316     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
2317     IF FND_MSG_PUB.check_msg_level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR)
2318     THEN
2319       FND_MSG_PUB.add_exc_msg(
2320         p_pkg_name         => G_PKG_NAME,
2321         p_procedure_name   => l_api_name,
2322         p_error_text       => SUBSTRB(SQLERRM,1,240));
2323     END IF;
2324     FND_MSG_PUB.count_and_get(
2325       p_encoded  => FND_API.G_FALSE,
2326       p_count    => x_msg_count,
2327       p_data     => x_msg_data);
2328 END;
2329 
2330 -- Following two procedures added by rbhavsar on July 25, 2007
2331 -- to remap IB Tree Nodes to fix FP bug 6276991
2332 PROCEDURE Remap_IB_Tree(p_instance_id     IN  NUMBER,
2333                         p_relationship_id IN  NUMBER)
2334 IS
2335 
2336   -- Get all the children of the current instance that are extra nodes
2337   CURSOR get_extra_children_csr IS
2338    SELECT subject_id
2339      FROM csi_ii_relationships
2340     WHERE object_id = p_instance_id
2341       AND relationship_type_code = 'COMPONENT-OF'
2342       AND position_reference IS NULL
2343       AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
2344       AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE)
2345       AND NOT EXISTS (SELECT 'X'
2346                         FROM ahl_unit_config_headers
2347                        WHERE csi_item_instance_id = subject_id
2348                          AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE));
2349 
2350   -- Get all the children of the current instance that are NOT extra nodes
2351   CURSOR get_premapped_instances_csr IS
2352    SELECT subject_id, position_reference
2353      FROM csi_ii_relationships
2354     WHERE object_id = p_instance_id
2355       AND relationship_type_code = 'COMPONENT-OF'
2356       AND position_reference IS NOT NULL
2357       AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
2358       AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE)
2359       AND NOT EXISTS (SELECT 'X'
2360                         FROM ahl_unit_config_headers
2361                        WHERE csi_item_instance_id = subject_id
2362                          AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE));
2363 
2364   -- Validate that the child position is still valid under the parent position
2365   CURSOR validate_position_csr(c_child_relationship_id IN NUMBER) IS
2366    SELECT 1 from ahl_mc_relationships
2367    where relationship_id = c_child_relationship_id
2368      AND parent_relationship_id = p_relationship_id
2369      AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
2370      AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE);
2371 
2372   -- Get all children of current position that are empty positions
2373   CURSOR get_all_empty_positions_csr IS
2374    SELECT relationship_id
2375      FROM ahl_mc_relationships
2376      WHERE parent_relationship_id = p_relationship_id
2377        AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
2378        AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE)
2379    MINUS
2380    SELECT to_number(position_reference) relationship_id
2381     FROM csi_ii_relationships relationship_id
2382     WHERE object_id = p_instance_id
2383      AND relationship_type_code = 'COMPONENT-OF'
2384      AND position_reference IS NOT NULL
2385      AND trunc(nvl(active_start_date,SYSDATE)) <= trunc(SYSDATE)
2386      AND trunc(nvl(active_end_date, SYSDATE+1)) > trunc(SYSDATE);
2387 
2388   CURSOR get_ii_rel_dtls_csr(c_instance_id NUMBER) IS
2389    SELECT C.relationship_id,
2390           C.object_version_number,
2391           C.object_id,
2392           C.subject_id
2393      FROM csi_ii_relationships C
2394     WHERE C.subject_id = c_instance_id
2395       AND C.relationship_type_code = 'COMPONENT-OF'
2396       AND trunc(nvl(C.active_start_date,SYSDATE)) <= trunc(SYSDATE)
2397       AND trunc(nvl(C.active_end_date, SYSDATE+1)) > trunc(SYSDATE);
2398 
2399   L_DEBUG_KEY   CONSTANT VARCHAR2(150) := 'ahl.plsql.AHL_UC_TREE_PVT.Remap_IB_Tree';
2400   l_extra_instances_tbl T_ID_TBL;
2401   l_relations_tbl T_ID_TBL;
2402   l_premapped_instances_tbl T_ID_TBL;
2403   l_temp NUMBER;
2404   l_csi_relationship_rec csi_datastructures_pub.ii_relationship_rec;
2405   l_csi_relationship_tbl csi_datastructures_pub.ii_relationship_tbl;
2406   l_csi_transaction_rec  csi_datastructures_pub.transaction_rec;
2407   l_ii_rel_dtls          get_ii_rel_dtls_csr%ROWTYPE;
2408   l_return_status        VARCHAR2(1);
2409   l_msg_count            NUMBER;
2410   l_msg_data             VARCHAR2(2000);
2411   l_return_value         BOOLEAN;
2412   l_transaction_type_id  NUMBER;
2413 
2414 BEGIN
2415   IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
2416     FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE, L_DEBUG_KEY || '.begin',
2417                    'At the start of the procedure, p_instance_id = ' || p_instance_id || ', p_relationship_id = ' || p_relationship_id);
2418   END IF;
2419 
2420   -- Get the transaction_type_id for use later by the CSI_II_RELATIONSHIPS_PUB.update_relationship API
2421   AHL_UTIL_UC_PKG.getcsi_transaction_id('UC_UPDATE', l_transaction_type_id, l_return_value);
2422   IF NOT l_return_value THEN
2423     RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
2424   END IF;
2425   l_csi_transaction_rec.transaction_type_id := l_transaction_type_id;
2426   l_csi_transaction_rec.source_transaction_date := SYSDATE;
2427   l_csi_relationship_rec.relationship_type_code := 'COMPONENT-OF';
2428 
2429   -- Get all nodes that are non-extra nodes
2430   FOR l_nonextra_instances IN get_premapped_instances_csr LOOP
2431     -- Validate if the instance still matches the position
2432     -- Check if l_nonextra_instances.position_reference is under the position p_relationship_id
2433     IF (FND_LOG.LEVEL_STATEMENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
2434       FND_LOG.STRING(FND_LOG.LEVEL_STATEMENT, L_DEBUG_KEY,
2435                      'Non Extra Node: l_nonextra_instances.subject_id = ' || l_nonextra_instances.subject_id ||
2436                      ', l_nonextra_instances.position_reference = ' || l_nonextra_instances.position_reference);
2437     END IF;
2438     OPEN validate_position_csr(TO_NUMBER(l_nonextra_instances.position_reference));
2439     FETCH validate_position_csr INTO l_temp;
2440     IF (validate_position_csr%NOTFOUND) THEN
2441       -- Reset the position reference so that the instance becomes an extra node node
2442       OPEN get_ii_rel_dtls_csr( l_nonextra_instances.subject_id);
2443       FETCH get_ii_rel_dtls_csr INTO l_ii_rel_dtls;
2444       CLOSE get_ii_rel_dtls_csr;
2445       --Set CSI relationship record
2446       l_csi_relationship_rec.relationship_id := l_ii_rel_dtls.relationship_id;
2447       l_csi_relationship_rec.object_version_number := l_ii_rel_dtls.object_version_number;
2448       l_csi_relationship_rec.position_reference := null;  -- Nullify the relationship
2449       l_csi_relationship_rec.object_id := l_ii_rel_dtls.object_id;
2450       l_csi_relationship_rec.subject_id := l_ii_rel_dtls.subject_id;
2451       l_csi_relationship_tbl(1) := l_csi_relationship_rec;
2452       IF (FND_LOG.LEVEL_STATEMENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
2453         FND_LOG.STRING(FND_LOG.LEVEL_STATEMENT, L_DEBUG_KEY,
2454                        'About to call CSI_II_RELATIONSHIPS_PUB.update_relationship to update CSI II relationship with id ' ||
2455                        l_ii_rel_dtls.relationship_id || ' between ' ||
2456                        l_ii_rel_dtls.object_id || ' (object) and ' ||
2457                        l_ii_rel_dtls.subject_id || '(subject) with NULL position_reference ');
2458       END IF;
2459       CSI_II_RELATIONSHIPS_PUB.update_relationship(
2460                                p_api_version      => 1.0,
2461                                p_relationship_tbl => l_csi_relationship_tbl,
2462                                p_txn_rec          => l_csi_transaction_rec,
2463                                x_return_status    => l_return_status,
2464                                x_msg_count        => l_msg_count,
2465                                x_msg_data         => l_msg_data);
2466       IF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
2467         RAISE FND_API.G_EXC_ERROR;
2468       ELSIF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
2469         RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
2470       END IF;
2471     ELSE
2472       -- Position Matches at current level: Drill down by calling Remap_IB_Tree recursively
2473       IF (FND_LOG.LEVEL_STATEMENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
2474         FND_LOG.STRING(FND_LOG.LEVEL_STATEMENT, L_DEBUG_KEY,
2475                        'About to recursively call Remap_IB_Tree with p_instance_id = ' || l_nonextra_instances.subject_id ||
2476                        ', p_relationship_id =' || l_nonextra_instances.position_reference);
2477       END IF;
2478       Remap_IB_Tree(p_instance_id     => l_nonextra_instances.subject_id,
2479                     p_relationship_id => TO_NUMBER(l_nonextra_instances.position_reference));
2480       IF (FND_LOG.LEVEL_STATEMENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
2481         FND_LOG.STRING(FND_LOG.LEVEL_STATEMENT, L_DEBUG_KEY,
2482                        'Returned from recursive call to Remap_IB_Tree.');
2483       END IF;
2484     END IF;
2485     CLOSE validate_position_csr;
2486   END LOOP;  -- All non-extra nodes
2487 
2488   -- Get all the children of the current instance that are extra nodes
2489   OPEN get_extra_children_csr;
2490   FETCH get_extra_children_csr BULK COLLECT INTO l_extra_instances_tbl;
2491   CLOSE get_extra_children_csr;
2492 
2493   IF (FND_LOG.LEVEL_STATEMENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
2494     FND_LOG.STRING(FND_LOG.LEVEL_STATEMENT, L_DEBUG_KEY,
2495                    'Number of extra nodes: ' || l_extra_instances_tbl.COUNT ||
2496                    ', Number of non-extra nodes: ' || l_premapped_instances_tbl.COUNT);
2497   END IF;
2498   IF (l_extra_instances_tbl.COUNT > 0) THEN
2499     -- There are child nodes present
2500     -- Get all children of current position that are empty positions
2501     OPEN get_all_empty_positions_csr;
2502     FETCH get_all_empty_positions_csr BULK COLLECT INTO l_relations_tbl;
2503     CLOSE get_all_empty_positions_csr;
2504 
2505     IF (FND_LOG.LEVEL_STATEMENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
2506       FND_LOG.STRING(FND_LOG.LEVEL_STATEMENT, L_DEBUG_KEY,
2507                      'Number of empty positions: ' || l_relations_tbl.COUNT);
2508     END IF;
2509     IF (l_relations_tbl.COUNT > 0) THEN
2510       -- Analyse and process instances with matching positions
2511       Process_Instances(p_x_extra_instances_tbl => l_extra_instances_tbl,
2512                         p_x_relations_tbl       => l_relations_tbl);
2513       IF (FND_LOG.LEVEL_STATEMENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
2514           FND_LOG.STRING(FND_LOG.LEVEL_STATEMENT, L_DEBUG_KEY,
2515                        'Number of extra nodes after processing: ' || l_extra_instances_tbl.COUNT ||
2516                        ', Number of empty positions after processing: ' || l_relations_tbl.COUNT);
2517       END IF;
2518     END IF;
2519   END IF;  -- There are child nodes
2520 
2521   IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
2522     FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE, L_DEBUG_KEY || '.end',
2523                    'At the end of the procedure.');
2524   END IF;
2525 END Remap_IB_Tree;
2526 
2527 -------
2528 -- This procedure is called by Remap_IB_Tree and checks if an instance matches an unique
2529 -- relationship and if so, sets the position_reference. All relations are searched and
2530 -- if multiple are matching, position_reference is not set.
2531 -- This procedure also calls Remap_IB_Tree (mutual recursion) to process children.
2532 PROCEDURE Process_instances(p_x_extra_instances_tbl IN OUT NOCOPY T_ID_TBL,
2533                             p_x_relations_tbl       IN OUT NOCOPY T_ID_TBL) IS
2534 
2535   CURSOR get_instance_dtls_csr(c_instance_id IN NUMBER) IS
2536    SELECT inventory_item_id,
2537           inv_master_organization_id,
2538           inventory_revision,
2539           quantity,
2540           unit_of_measure
2541      FROM csi_item_instances
2542      WHERE instance_id = c_instance_id;
2543 
2544   CURSOR get_ii_rel_dtls_csr(c_instance_id NUMBER) IS
2545    SELECT C.relationship_id,
2546           C.object_version_number,
2547           C.object_id,
2548           C.subject_id
2549      FROM csi_ii_relationships C
2550     WHERE C.subject_id = c_instance_id
2551       AND C.relationship_type_code = 'COMPONENT-OF'
2552       AND trunc(nvl(C.active_start_date,SYSDATE)) <= trunc(SYSDATE)
2553       AND trunc(nvl(C.active_end_date, SYSDATE+1)) > trunc(SYSDATE);
2554 
2555   l_instance_dtls        get_instance_dtls_csr%ROWTYPE;
2556   l_ii_rel_dtls          get_ii_rel_dtls_csr%ROWTYPE;
2557   L_DEBUG_KEY            CONSTANT VARCHAR2(150) := 'ahl.plsql.AHL_UC_TREE_PVT.Process_instances';
2558   l_map_tbl              T_ID_TBL;
2559   l_item_match           BOOLEAN;
2560   l_csi_relationship_rec csi_datastructures_pub.ii_relationship_rec;
2561   l_csi_relationship_tbl csi_datastructures_pub.ii_relationship_tbl;
2562   l_csi_transaction_rec  csi_datastructures_pub.transaction_rec;
2563   l_return_value         BOOLEAN;
2564   l_transaction_type_id  NUMBER;
2565   l_return_status        VARCHAR2(1);
2566   l_msg_count            NUMBER;
2567   l_msg_data             VARCHAR2(2000);
2568   i                      NUMBER;
2569   j                      NUMBER;
2570   k                      NUMBER;
2571   l_matched_flag         BOOLEAN;
2572   l_current_position     NUMBER;
2573 
2574 BEGIN
2575   IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
2576     FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE, L_DEBUG_KEY || '.begin',
2577                    'At the start of the procedure, p_x_extra_instances_tbl.count = ' || p_x_extra_instances_tbl.count || ',p_x_relations_tbl.count = ' ||p_x_relations_tbl.count);
2578   END IF;
2579 
2580   -- Get the transaction_type_id for use later by the CSI_II_RELATIONSHIPS_PUB.update_relationship API
2581   AHL_UTIL_UC_PKG.getcsi_transaction_id('UC_UPDATE', l_transaction_type_id, l_return_value);
2582   IF NOT l_return_value THEN
2583     RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
2584   END IF;
2585   l_csi_transaction_rec.transaction_type_id := l_transaction_type_id;
2586   l_csi_transaction_rec.source_transaction_date := SYSDATE;
2587   l_csi_relationship_rec.relationship_type_code := 'COMPONENT-OF';
2588 
2589   -- There are extra nodes present
2590   i := p_x_extra_instances_tbl.FIRST;
2591   WHILE (i IS NOT NULL) LOOP
2592     IF (FND_LOG.LEVEL_STATEMENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
2593       FND_LOG.STRING(FND_LOG.LEVEL_STATEMENT, L_DEBUG_KEY,
2594                      'i = ' || i || ', p_x_extra_instances_tbl(i) = ' || p_x_extra_instances_tbl(i));
2595     END IF;
2596     -- Initialize associative array
2597     l_map_tbl(p_x_extra_instances_tbl(i)) := 0;
2598     OPEN get_instance_dtls_csr(p_x_extra_instances_tbl(i));
2599     FETCH get_instance_dtls_csr INTO l_instance_dtls;
2600     CLOSE get_instance_dtls_csr;
2601     j := p_x_relations_tbl.FIRST;
2602     WHILE (j IS NOT NULL) LOOP
2603       -- See if instance i matches position j
2604       l_item_match := AHL_UTIL_UC_PKG.item_match(p_x_relations_tbl(j),
2605                                                  l_instance_dtls.inventory_item_id,
2606                                                  l_instance_dtls.inv_master_organization_id,
2607                                                  l_instance_dtls.inventory_revision,
2608                                                  l_instance_dtls.quantity,
2609                                                  l_instance_dtls.unit_of_measure);
2610       IF (l_item_match) THEN
2611         IF (FND_LOG.LEVEL_STATEMENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
2612           FND_LOG.STRING(FND_LOG.LEVEL_STATEMENT, L_DEBUG_KEY,
2613                          'Instance ' || p_x_extra_instances_tbl(i) || ' fits position ' || p_x_relations_tbl(j));
2614         END IF;
2615         IF (l_map_tbl(p_x_extra_instances_tbl(i))) <> 0 THEN
2616           -- More than one match
2617           l_map_tbl(p_x_extra_instances_tbl(i)) := -1;
2618           EXIT;  -- No need to check more positions: go to the next instance
2619         ELSE
2620           -- First Match
2621           l_map_tbl(p_x_extra_instances_tbl(i)) := p_x_relations_tbl(j);
2622         END IF;
2623       END IF;  -- l_item_match is true
2624       j := p_x_relations_tbl.NEXT(j);
2625     END LOOP;  -- For all Positions
2626     i := p_x_extra_instances_tbl.NEXT(i);
2627   END LOOP;  -- For all instances (Extra Nodes)
2628 
2629   -- Now that analysis is done, process the instances
2630   i := p_x_extra_instances_tbl.FIRST;
2631   WHILE (i IS NOT NULL) LOOP
2632     IF (l_map_tbl(p_x_extra_instances_tbl(i))) = 0 THEN
2633       -- No Matching position found: Delete and Ignore this instance
2634       -- Instance will continue to remain an extra node.
2635       p_x_extra_instances_tbl.DELETE(i);
2636     ELSIF (l_map_tbl(p_x_extra_instances_tbl(i))) > 0 THEN
2637       -- Exactly one matching position has been found: Check if this matched relationship
2638       -- is also a match for any other instance
2639       l_current_position := l_map_tbl(p_x_extra_instances_tbl(i));
2640       k := p_x_extra_instances_tbl.NEXT(i);
2641       l_matched_flag := FALSE;
2642       WHILE (k IS NOT NULL) LOOP
2643         IF (l_map_tbl(p_x_extra_instances_tbl(k)) = l_current_position) THEN
2644           -- Another instance also has been matched to this position: Ignore that instance
2645           l_map_tbl(p_x_extra_instances_tbl(k)) := -1;
2646           l_matched_flag := TRUE;
2647         END IF;
2648         k := p_x_extra_instances_tbl.NEXT(k);
2649       END LOOP;
2650       IF (l_matched_flag = TRUE) THEN
2651         -- One or more instance also has been matched to this instance's position:
2652         -- Ignore the current instance. Let the user associate manually.
2653         l_map_tbl(p_x_extra_instances_tbl(i)) := -1;
2654       ELSE
2655         -- Exactly one matching position has been found
2656         -- Set the Position reference for the csi_ii_relationship
2657         OPEN get_ii_rel_dtls_csr(p_x_extra_instances_tbl(i));
2658         FETCH get_ii_rel_dtls_csr INTO l_ii_rel_dtls;
2659         CLOSE get_ii_rel_dtls_csr;
2660         --Set CSI relationship record
2661         l_csi_relationship_rec.relationship_id := l_ii_rel_dtls.relationship_id;
2662         l_csi_relationship_rec.object_version_number := l_ii_rel_dtls.object_version_number;
2663         l_csi_relationship_rec.position_reference := to_char(l_current_position);
2664         l_csi_relationship_rec.object_id := l_ii_rel_dtls.object_id;
2665         l_csi_relationship_rec.subject_id := l_ii_rel_dtls.subject_id;
2666         l_csi_relationship_tbl(1) := l_csi_relationship_rec;
2667         IF (FND_LOG.LEVEL_STATEMENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
2668           FND_LOG.STRING(FND_LOG.LEVEL_STATEMENT, L_DEBUG_KEY,
2669                          'About to call CSI_II_RELATIONSHIPS_PUB.update_relationship to update CSI II relationship with id ' ||
2670                          l_ii_rel_dtls.relationship_id || ' between ' ||
2671                          l_ii_rel_dtls.object_id || ' (object) and ' ||
2672                          l_ii_rel_dtls.subject_id || '(subject) with position_reference ' ||
2673                          to_char(l_current_position));
2674         END IF;
2675         CSI_II_RELATIONSHIPS_PUB.update_relationship(
2676                                  p_api_version      => 1.0,
2677                                  p_relationship_tbl => l_csi_relationship_tbl,
2678                                  p_txn_rec          => l_csi_transaction_rec,
2679                                  x_return_status    => l_return_status,
2680                                  x_msg_count        => l_msg_count,
2681                                  x_msg_data         => l_msg_data);
2682         IF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
2683           RAISE FND_API.G_EXC_ERROR;
2684         ELSIF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
2685           RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
2686         END IF;
2687         -- Now recursively match all the children of the current instance/position
2688         IF (FND_LOG.LEVEL_STATEMENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
2689           FND_LOG.STRING(FND_LOG.LEVEL_STATEMENT, L_DEBUG_KEY,
2690                          'About to recursively call Remap_IB_Tree');
2691         END IF;
2692         Remap_IB_Tree(p_instance_id     => p_x_extra_instances_tbl(i),
2693                       p_relationship_id => l_current_position);
2694         IF (FND_LOG.LEVEL_STATEMENT >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
2695           FND_LOG.STRING(FND_LOG.LEVEL_STATEMENT, L_DEBUG_KEY,
2696                          'Returned from recursive call to Remap_IB_Tree');
2697         END IF;
2698         -- Now delete the matched relationship
2699         j := p_x_relations_tbl.FIRST;
2700         WHILE (j IS NOT NULL) LOOP
2701           IF p_x_relations_tbl(j) = l_current_position THEN
2702             p_x_relations_tbl.DELETE(j);
2703             EXIT;
2704           END IF;
2705           j := p_x_relations_tbl.NEXT(j);
2706         END LOOP;
2707         -- Now delete the matched instance
2708         p_x_extra_instances_tbl.DELETE(i);
2709       END IF;  -- l_matched_flag is TRUE or FALSE
2710     ELSE
2711       -- Multiple matching positions found: Do nothing and let the user associate manually
2712       null;
2713     END IF;
2714     i := p_x_extra_instances_tbl.NEXT(i);
2715   END LOOP;
2716   l_map_tbl.DELETE;  -- Clear up the temporary Associative Array
2717 
2718   IF (FND_LOG.LEVEL_PROCEDURE >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
2719     FND_LOG.STRING(FND_LOG.LEVEL_PROCEDURE, L_DEBUG_KEY || '.end',
2720                    'At the end of the procedure. Remaining Instances: ' ||  p_x_extra_instances_tbl.count);
2721   END IF;
2722 END Process_instances;
2723 
2724 
2725 END AHL_UC_TREE_PVT; -- Package body