DBA Data[Home] [Help]

PACKAGE BODY: APPS.FLM_AUTO_REPLENISHMENT

Source


1 PACKAGE BODY FLM_AUTO_REPLENISHMENT AS
2 /* $Header: FLMCPARB.pls 120.2.12010000.2 2008/08/07 06:20:56 bgaddam ship $ */
3 
4 /************************************************************************
5  *	Package variables                                               *
6  ************************************************************************/
7 G_DEBUG         BOOLEAN := (FND_PROFILE.VALUE('MRP_DEBUG') = 'Y');
8 
9 /************************************************************************
10  *	Private Procedures and Functions                             	*
11  ************************************************************************/
12 
13 /************************************************************************
14  * PROCEDURE log							*
15  * 	Inserts error msg into log file.				*
16  *	                                                                *
17  ************************************************************************/
18 PROCEDURE log(info	VARCHAR2) is
19 BEGIN
20   FND_FILE.PUT_LINE(FND_FILE.LOG, info);
21 END;
22 
23 
24 /************************************************************************
25  * PROCEDURE Show_Exception_Messagees					*
26  * 	This procedure gets Exception Messages from the message stack   *
27  *	and prints it into the log file.				*
28  *	                                                                *
29  ************************************************************************/
30 PROCEDURE Show_Exception_Messages(
31 		p_msg_count		IN	NUMBER,
32 		p_msg_data		IN	VARCHAR2,
33 		p_schedule_number	IN	NUMBER,
34 		p_comp_id		IN	NUMBER,
35 		p_organization_id	IN	NUMBER,
36 		p_error_position	IN	VARCHAR2) IS
37 
38   l_comp_name	VARCHAR2(600);
39 
40 BEGIN
41 
42   SELECT concatenated_segments
43     INTO l_comp_name
44     FROM mtl_system_items_kfv
45    WHERE inventory_item_id = p_comp_id
46      AND organization_id = p_organization_id;
47 
48   IF (p_error_position = G_Error_Create_Cards) THEN
49     fnd_message.set_name('FLM', 'FLM_AR_ERR_CREATE_CARDS');
50   ELSIF (p_error_position = G_Error_Replenish_Cards) THEN
51     fnd_message.set_name('FLM', 'FLM_AR_ERR_REPLENISH_CARDS');
52   END IF;
53 
54   fnd_message.set_token('COMPONENT', l_comp_name);
55   fnd_message.set_token('SCHEDULE', p_schedule_number);
56   log(fnd_message.get);
57 
58   IF (p_msg_count >= 1) THEN
59     FOR l_count IN 1..p_msg_count LOOP
60       log(FND_MSG_PUB.Get(l_count, 'F'));
61     END LOOP;
62   END IF;
63 
64 
65 END Show_Exception_Messages;
66 
67 /************************************************************************
68  * FUNCTION Is_Valid_Seq						*
69  * 	Returns true if the particular Line Operation sequence is a     *
70  *      Valid Line Operation.                                           *
71  *	A Line Operation Sequence is a Valid Line Operation :           *
72  *      a) If the LOP is present in the From_Op_Seq_id and is not part  *
73  *         of a pure rework loop or                                     *
74  *      b) If the LOP is present in the To_Op_Seq_id or this LOP is     *
75  *         the only operation for this routing (i.e. no network exists  *
76  *         for this routing).                                           *
77  *                                                                      *
78  ************************************************************************/
79 FUNCTION Is_Valid_Seq (p_op_seq_id IN NUMBER) RETURN BOOLEAN IS
80   l_cnt NUMBER;
81 
82 BEGIN
83 
84   IF (p_op_seq_id is null) then
85     return false;
86   END IF;
87 
88   /*---------------------------------------------------------------------+
89    | Look at the from_op_seq_id to find out if the line-op               |
90    | has a primary path originating from it.                             |
91    +---------------------------------------------------------------------*/
92   SELECT count(*)
93     INTO l_cnt
94     FROM bom_operation_networks
95    WHERE from_op_seq_id = p_op_seq_id
96      AND nvl(transition_type, 3) = 1;
97 
98   IF (l_cnt = 0) THEN
99 
100     /*---------------------------------------------------------------------+
101      | Look at the to_op_seq_id to find out if the line-op                 |
102      | is in primary path. This is the exception for the                   |
103      | last line-op                                                        |
104      +---------------------------------------------------------------------*/
105     SELECT count(*)
106       INTO l_cnt
107       FROM bom_operation_networks
108      WHERE to_op_seq_id = p_op_seq_id
109        AND nvl(transition_type, 3) = 1;
110 
111     IF (l_cnt = 0) THEN
112       /*---------------------------------------------------------------------+
113        | If no network exists, then if only one line operation exists        |
114        | for this routing, it's valid, otherwise it's not valid.             |
115        +---------------------------------------------------------------------*/
116       SELECT count(*)
117         INTO l_cnt
118         FROM bom_operation_sequences
119        WHERE operation_type = 3
120          AND routing_sequence_id = (
121               SELECT max(routing_sequence_id)
122                 FROM bom_operation_sequences
123                WHERE operation_sequence_id = p_op_seq_id
124             );
125 
126       IF (l_cnt = 1) THEN
127         return true;
128       END IF;
129 
130       return false;
131     END IF; -- end of (l_cnt = 0)
132 
133   END IF; -- end of (l_cnt = 0)
134 
135   return true;
136 
137 END is_valid_seq;
138 
139 
140 /************************************************************************
141  * FUNCTION get_valid_pull_sequence					*
142  *      Returns the pull sequence id of the given Item if the pull      *
143  *      sequence is a valid pull sequence else it returns -1.           *
144  *      An item's pull sequence is valid if it satisfies following      *
145  *      conditions :                                                    *
146  *      a) The POU in the Pull Sequence match with those in BOM         *
147  *         Inventory Components or if POU is not specified in BOM, then *
148  *	   POU in Pull Sequence match with those specified in the Item  *
149  *	   Master (where POU comprises of a subinventory name and the   *
150  *	   the locator present).					*
151  *      b) The Pull Sequence has Auto_Request flag set to 'Y'.          *
152  *      c) Pull Sequence is not a Planning Only Pull sequence i.e.      *
153  *         release_kanban_flag is set to 1.                             *
154  *      d) The item has Supply type as Pull in Bom Inventory Components *
155  *	e) The Item has Release Time Fence set to "Kanban Item (Do not  *
156  *	   Release)" in the Organization Items.				*
157  *                                                                      *
158  ************************************************************************/
159 FUNCTION Get_Valid_Pull_Sequence(
160 			p_item_id		IN	NUMBER,
161 			p_organization_id	IN	NUMBER,
162 			p_item_sequence_id	IN	NUMBER) RETURN NUMBER
163 IS
164 
165   l_pull_sequence_id	NUMBER;
166 
167 BEGIN
168 
169   BEGIN
170     SELECT mkps.pull_sequence_id
171       INTO l_pull_sequence_id
172       FROM mtl_kanban_pull_sequences mkps,
173            bom_inventory_components bic,
174 	   mtl_system_items msi
175      WHERE mkps.inventory_item_id = p_item_id
176        AND mkps.organization_id = p_organization_id
177        AND mkps.auto_request = 'Y'
178        AND mkps.release_kanban_flag = 1
179        AND mkps.inventory_item_id = bic.component_item_id
180        AND msi.inventory_item_id = p_item_id
181        AND msi.organization_id = p_organization_id
182        AND msi.release_time_fence_code = G_Release_Time_Kanban_Item
183        AND bic.component_sequence_id = p_item_sequence_id
184        AND ( (bic.supply_subinventory IS NOT NULL AND mkps.subinventory_name = bic.supply_subinventory)
185            OR (bic.supply_subinventory IS NULL AND mkps.subinventory_name = msi.wip_supply_subinventory) )
186        AND ( (bic.supply_subinventory IS NOT NULL AND nvl(mkps.locator_id, '-0909090909') = nvl(bic.supply_locator_id, '-0909090909'))
187            OR (bic.supply_subinventory IS NULL AND nvl(mkps.locator_id, '-0909090909') = nvl(msi.wip_supply_locator_id, '-0909090909')) )
188        AND bic.wip_supply_type IN (G_Supply_Type_Assembly_Pull, G_Supply_Type_Operation_Pull);
189 
190   EXCEPTION
191     WHEN OTHERS THEN
192       l_pull_sequence_id := -1;
193   END;
194 
195   return l_pull_sequence_id;
196 
197 END Get_Valid_Pull_Sequence;
198 
199 
200 /************************************************************************
201  * PROCEDURE Get_Subassemlies						*
202  * 	This function returns the subassemblies that are being supplied *
203  *      from another line. It takes all subassemblies that are being    *
204  *      used in the line operations which are in the primary path or in *
205  *      the alternate path. It ignores any subassemblies that are used  *
206  *      in the rework operations.					*
207  *      This routine also explodes the phantom component.		*
208  *	                                                                *
209  ************************************************************************/
210 PROCEDURE Get_Subassemblies(
211                     p_org_id          	IN      NUMBER,
212                     p_schedule_number   IN      VARCHAR2,
213                     p_top_assy_id     	IN      NUMBER,
214                     p_alt_bom_desig   	IN      VARCHAR2,
215                     p_alt_rtg_desig   	IN      VARCHAR2,
216                     p_sched_start_date	IN      DATE,
217                     p_comp_table      	IN OUT  NOCOPY comp_list)
218 IS
219 
220     l_assy_id                       NUMBER;
221     assy_table                      comp_list;
222     max_assy_count                  NUMBER;
223     max_comp_count                  NUMBER;
224     curr_assy_count                 NUMBER;
225     l_comp_id                       NUMBER;
226     l_comp_name                     VARCHAR(40);
227     l_usage                         NUMBER;
228     l_wip_supply_type               NUMBER;
229     l_line_id                       NUMBER;
230     l_operation_seq_num             NUMBER;
231     l_component_sequence_id         NUMBER;
232     l_routing_sequence_id           NUMBER;
233     l_line_op_seq_id         	    NUMBER;
234     l_count         	    	    NUMBER;
235     l_status			    BOOLEAN;
236     l_inherit_phantom		    NUMBER;
237     l_pull_sequence_id              NUMBER;
238     l_stmt_no                       NUMBER;
239     l_top_bill_sequence_id	    NUMBER;
240     l_bill_sequence_id		    NUMBER;
241     l_basis_type		    NUMBER;
242     l_qty_per_lot		    NUMBER;
243 
244     cnt NUMBER :=0;
245     CURSOR comp(l_assy_id number) IS
246             SELECT  expl.component_item_id component_item_id,
247 		    comp.operation_seq_num operation_seq_num,
248                     SUM(comp.component_quantity) extended_quantity,
249                     MIN(DECODE(comp.wip_supply_type, NULL,
250                             DECODE(sys.wip_supply_type, NULL,
251                                     1, sys.wip_supply_type),
252                             comp.wip_supply_type)) wip_supply_type,
253 		    MIN(comp.component_quantity) component_quantity,
254 		    MIN(nvl(comp.basis_type,WIP_CONSTANTS.ITEM_BASED_MTL)) basis_type
255               FROM  mtl_system_items sys,
256                     bom_inventory_components comp,
257                     bom_explosions expl,
258                     bom_bill_of_materials bbm
259              WHERE  bbm.organization_id = sys.organization_id
260                AND  comp.component_item_id = sys.inventory_item_id
261                AND  comp.component_sequence_id = expl.component_sequence_id
262                AND  sys.bom_item_type = 4
263                AND  comp.component_item_id = expl.component_item_id
264                AND  comp.bill_sequence_id =  expl.bill_sequence_id
265                AND  bbm.organization_id = p_org_id
266                AND  bbm.assembly_item_id = l_assy_id
267                AND  (NVL(bbm.alternate_bom_designator, 'ABD756fhh466')
268                         = NVL(p_alt_bom_desig, 'ABD756fhh466')
269                     OR
270                     (bbm.alternate_bom_designator is null AND
271                     NOT EXISTS
272                     (SELECT null
273                        FROM bom_bill_of_materials bbm1
274                       WHERE bbm1.alternate_bom_designator = p_alt_bom_desig
275                         AND bbm1.organization_id = bbm.organization_id
276                         AND bbm1.assembly_item_id = bbm.assembly_item_id)))
277                AND  bbm.common_bill_sequence_id = expl.bill_sequence_id
278 	       AND  expl.top_bill_sequence_id = l_top_bill_sequence_id
279                AND  expl.assembly_item_id is not null
280 --Bug 6691128  Removing Trunc So that Time to be considered
281 --             AND  trunc(expl.effectivity_date) <= trunc(p_sched_start_date)
282 --             AND  NVL(expl.disable_date, p_sched_start_date + 1)
283 --                     > trunc(p_sched_start_date)
284                AND  expl.effectivity_date <= p_sched_start_date
285                AND  NVL(expl.disable_date, p_sched_start_date + 1)
286                      > p_sched_start_date
287                AND  expl.explosion_type = 'ALL'
288           GROUP BY  expl.component_item_id,comp.operation_seq_num;
289 
290     CURSOR component_sequence_cur IS
291 	SELECT component_sequence_id
292 	  FROM bom_explosions
293 	 WHERE top_bill_sequence_id = l_top_bill_sequence_id
294 	   AND explosion_type = 'ALL'
295 	   AND component_item_id = l_comp_id
296 	   AND operation_seq_num = l_operation_seq_num
297 --Bug 6691128 Removing Trunc So that Time to be considered
298 --         AND trunc(effectivity_date) <= trunc(p_sched_start_date);
299            AND effectivity_date <= p_sched_start_date
300            AND  NVL(disable_date, p_sched_start_date + 1)
301                      > p_sched_start_date;
302 
303 BEGIN
304 
308   SELECT routing_sequence_id
305   l_stmt_no := 100;
306 
307   -- Find the routing for the p_top_assy_id
309     INTO l_routing_sequence_id
310     FROM bom_operational_routings
311    WHERE organization_id = p_org_id
312      AND assembly_item_id = p_top_assy_id
313      AND NVL(alternate_routing_designator, 'ABD756fhh456') =
314          NVL(p_alt_rtg_desig, 'ABD756fhh456');
315 
316   l_stmt_no := 105;
317 
318   max_assy_count := 1;
319   curr_assy_count := 0;
320   assy_table(1).item_id := p_top_assy_id;
321   assy_table(1).usage := 1;
322   max_comp_count := 0;
323 
324   l_stmt_no := 110;
325 
326   -- To retrive inherit_phantom_op_seq value
327   SELECT inherit_phantom_op_seq
328     INTO l_inherit_phantom
329     FROM bom_parameters
330    WHERE organization_id = p_org_id;
331 
332   BEGIN
333     l_stmt_no := 115;
334 
335     l_bill_sequence_id := null;
336 
337     SELECT bill_sequence_id
338       INTO l_bill_sequence_id
339       FROM bom_bill_of_materials
340      WHERE organization_id = p_org_id
341        AND assembly_item_id = p_top_assy_id
342        AND nvl(alternate_bom_designator, '@@@@') =
343 	    nvl(p_alt_bom_desig, '@@@@');
344 
345     l_top_bill_sequence_id := l_bill_sequence_id;
346 
347     l_stmt_no := 120;
348 
349     SELECT max(top_bill_sequence_id)
350       INTO l_top_bill_sequence_id
351       FROM bom_explosions
352      WHERE component_item_id = p_top_assy_id
353        AND organization_id = p_org_id;
354   EXCEPTION
355     WHEN OTHERS THEN
356 	l_top_bill_sequence_id := l_bill_sequence_id;
357   END;
358 
359   LOOP
360     cnt := cnt + 1;
361     curr_assy_count := curr_assy_count + 1;
362 
363     IF curr_assy_count > max_assy_count THEN
364        EXIT;
365     END IF;
366 
367     l_assy_id := assy_table(curr_assy_count).item_id;
368 
369 
370     FOR comp_record IN comp(l_assy_id) LOOP
371       l_comp_id := comp_record.component_item_id;
372       l_usage := comp_record.extended_quantity;
373       l_wip_supply_type := comp_record.wip_supply_type;
374 
375       -- This stores the operation_seq_num from the parent's BOM
376       l_operation_seq_num := comp_record.operation_seq_num;
377 
378       -- Added for Lot Based Material Support
379       -- Retrieve the basis type and component quantity from the bom_explosions table.
380       l_basis_type := comp_record.basis_type;
381       l_qty_per_lot := comp_record.component_quantity;
382 
383       IF l_wip_supply_type = G_Supply_Type_Phantom THEN
384         max_assy_count := max_assy_count + 1;
385         assy_table(max_assy_count).item_id := l_comp_id;
386         assy_table(max_assy_count).usage :=
387         assy_table(curr_assy_count).usage * l_usage;
388 
389         /*---------------------------------------------------------------------+
390 	 | Two cases :                                                         |
391          | a. For 1st level Subassembly, the operation_seq_num is the          |
392          |    obtained from the BOM of its parent which is the top assembly.   |
393          | b. Otherwise, the operation_seq_num is the operation_seq_num of     |
394          |    its parent.                                                      |
395 	 +---------------------------------------------------------------------*/
396         IF (l_inherit_phantom = 1) THEN
397           IF (curr_assy_count = 1) THEN
398             assy_table(max_assy_count).operation_seq_num := l_operation_seq_num;
399           ELSE
400             assy_table(max_assy_count).operation_seq_num :=
401                   assy_table(curr_assy_count).operation_seq_num;
402           END IF;
403         END IF;
404 
405         IF (l_inherit_phantom = 2) THEN
406           assy_table(max_assy_count).operation_seq_num := l_operation_seq_num;
407         END IF;
408 
409       ELSE  /* l_wip_supply_type != G_Supply_Type_Phantom */
410 
411         l_stmt_no := 125;
412 
413 	-- Get the Component sequence id
414 	FOR l_component_seequence_cur IN component_sequence_cur
415 	LOOP
416 	  l_component_sequence_id := l_component_seequence_cur.component_sequence_id;
417 
418   	  /*---------------------------------------------------------------------+
419 	   | If it's 1st level Subassembly, the component operation_seq_num      |
420            | is the operation_seq_num obtained from the BOM. Otherwise,          |
421            | it's the operation_seq_num of the 1st subassembly parent.           |
422 	   +---------------------------------------------------------------------*/
423           IF ((l_inherit_phantom = 1) and (curr_assy_count <> 1)) THEN
424 	    l_operation_seq_num := assy_table(curr_assy_count).operation_seq_num;
425   	  END IF;
426 
427           /*---------------------------------------------------------------------+
428 	   | Get the corresponding line_op_seq_id for the given operation_seq_num|
429 	   | in the routing of the top assembly                                  |
430 	   +---------------------------------------------------------------------*/
431           BEGIN
432             l_stmt_no := 130;
433 
434 	    SELECT line_op_seq_id
435               INTO l_line_op_seq_id
436               FROM bom_operation_sequences
437              WHERE routing_sequence_id = l_routing_sequence_id
441                    (SELECT max(effectivity_date)
438                AND operation_seq_num = l_operation_seq_num
439                AND operation_type = 1
440                AND effectivity_date =
442                       FROM bom_operation_sequences
443                      WHERE routing_sequence_id = l_routing_sequence_id
444                        AND operation_seq_num = l_operation_seq_num
445                        AND operation_type = 1);
446 
447           EXCEPTION
448             WHEN no_data_found THEN
449               l_line_op_seq_id := NULL;
450           END;
451 
452           l_stmt_no := 135;
453 
454   	  -- Get pull sequence id of the component
455  	  l_pull_sequence_id := Get_Valid_Pull_Sequence(l_comp_id, p_org_id, l_component_sequence_id);
456 
457           /*---------------------------------------------------------------------+
458 	   | Include only components that :                                      |
459            |  1. Has a valid Line Operation Sequence.                            |
460            |  2. Has a valid Pull Sequence                                       |
461 	   +---------------------------------------------------------------------*/
462 
463           IF (is_valid_seq(l_line_op_seq_id) and l_pull_sequence_id <> -1) THEN
464             l_stmt_no := 140;
465             IF (G_DEBUG) THEN
466               log('Valid Component is '||l_comp_id);
467             END IF;
468             max_comp_count                                 := max_comp_count + 1;
469             p_comp_table(max_comp_count).item_id           := l_comp_id;
470             p_comp_table(max_comp_count).usage             := l_usage * assy_table(curr_assy_count).usage;
471             p_comp_table(max_comp_count).line_id           := l_line_id;
472             p_comp_table(max_comp_count).operation_seq_num := l_operation_seq_num;
473             p_comp_table(max_comp_count).line_op_seq_id    := l_line_op_seq_id;
474 	    p_comp_table(max_comp_count).pull_sequence_id  := l_pull_sequence_id;
475   	    p_comp_table(max_comp_count).schedule_number   := p_schedule_number;
476 
477             -- Added for Lot Based Material Support
478             -- Storing the basis type and qty per lot in the p_comp_table.
479   	    p_comp_table(max_comp_count).basis_type   	   := l_basis_type;
480   	    p_comp_table(max_comp_count).qty_per_lot       := l_qty_per_lot;
481           END IF;
482 
483         END LOOP; -- end of For Loop for component_sequence_cur
484 
485       END IF; -- end of if for l_wip_supply_type = G_Supply_Type_Phantom
486 
487     END LOOP; -- end of FOR LOOP
488 
489   END LOOP;
490 EXCEPTION
491   WHEN OTHERS THEN
492     IF (G_DEBUG) THEN
493       log ('Exception in Get_subassemblies at line number '||l_stmt_no);
494     END IF;
495 
496 END Get_Subassemblies;    -- end of procedure
497 
498 
499 /************************************************************************
500  * FUNCTION Get_Operation_Times						*
501  * 	Returns the Operation Time of a given Line Operation rounded	*
502  *      up to the next takt time.                                       *
503  *                                                                      *
504  ************************************************************************/
505 FUNCTION Get_Operation_Times(
506 		p_line_op_seq_id	NUMBER,
507 		p_takt_time		NUMBER) RETURN NUMBER
508 IS
509 
510   l_total_time	NUMBER;
511 
512 BEGIN
513 
514   SELECT CEIL(NVL(total_time_calc, 0) / p_takt_time) * p_takt_time
515     INTO l_total_time
516     FROM bom_operation_sequences
517    WHERE operation_sequence_id = p_line_op_seq_id;
518 
519   RETURN l_total_time;
520 
521 END Get_Operation_Times;
522 
523 
524 /************************************************************************
525  * FUNCTION Need_By_Date						*
526  * 	Returns the need by date of a component at a particular Line    *
527  *      operation for the given assembly item routing on a given line.  *
528  *	                                                                *
529  ************************************************************************/
530 FUNCTION Need_By_Date(
531 		p_organization_id	NUMBER,
532 		p_line_id		NUMBER,
533 		p_assembly_item_id	NUMBER,
534 		p_assembly_comp_date	DATE,
535 		p_assembly_start_date	DATE,
536 		p_line_op_seq_id	NUMBER,
537 		p_quantity		NUMBER) RETURN DATE
538 IS
539 
540   l_start_time		NUMBER;
541   l_stop_time		NUMBER;
542   l_takt_time		NUMBER;
543   l_working_hours	NUMBER;
544   l_operation_times	NUMBER;
545   l_lead_time		NUMBER;
546   l_op_comp_date	DATE;
547   l_op_start_date	DATE;
548 
549   CURSOR Network_Csr (i_start_operation_sequence_id	NUMBER) IS
550     SELECT to_op_seq_id
551       FROM Bom_Operation_Networks
552           CONNECT BY PRIOR to_op_seq_id = from_op_seq_id
553 	               AND nvl(transition_type, 0) NOT IN (2,3)
554                 START WITH from_op_seq_id = i_start_operation_sequence_id
555 		       AND nvl(transition_type, 0) NOT IN (2,3);
556 
557 BEGIN
558 
559   SELECT start_time,
560          stop_time,
561 	 1/maximum_rate
562     INTO l_start_time,
563          l_stop_time,
564 	 l_takt_time
565     FROM wip_lines
566    WHERE line_id = p_line_id
567      AND organization_id = p_organization_id;
568 
572     l_working_hours := (l_stop_time + 24 * 3600 - l_start_time) / 3600;
569   IF (l_stop_time > l_start_time) THEN
570     l_working_hours := (l_stop_time - l_start_time) / 3600;
571   ELSE
573   END IF;
574 
575   l_operation_times := Get_Operation_Times(p_line_op_seq_id, l_takt_time);
576 
577   FOR l_Network_Rec in Network_Csr(p_line_op_seq_id)
578   LOOP
579     l_operation_times := l_operation_times +
580 		Get_Operation_Times(l_Network_Rec.to_op_seq_id, l_takt_time);
581   END LOOP;
582 
583   -- Operation completion time
584   l_op_comp_date := MRP_LINE_SCHEDULE_ALGORITHM.calculate_begin_time(
585 			p_organization_id,
586 			p_assembly_comp_date,
587 			l_operation_times / l_working_hours,
588 			l_start_time,
589 			l_stop_time);
590 
591   SELECT nvl(fixed_lead_time, 0) + (p_quantity - 1) * nvl(variable_lead_time, 0)
592     INTO l_lead_time
593     FROM mtl_system_items
594    WHERE inventory_item_id = p_assembly_item_id
595      AND organization_id = p_organization_id;
596 
597   -- Operation Start time
598   l_op_start_date := MRP_LINE_SCHEDULE_ALGORITHM.calculate_begin_time(
599 			p_organization_id,
600 			l_op_comp_date,
601 			l_lead_time,
602 			l_start_time,
603 			l_stop_time);
604 
605   return l_op_start_date;
606 
607 END Need_By_Date;
608 
609 
610 /************************************************************************
611  * PROCEDURE Update_Flow_Schedule					*
612  * 	Updates the Auto Replenish flag of the given Flow Schedule.	*
613  *	                                                                *
614  ************************************************************************/
615 PROCEDURE Update_Flow_Schedule(
616 		p_schedule_number	IN	VARCHAR2) IS
617 
618 BEGIN
619 
620     UPDATE wip_flow_schedules
621        SET auto_replenish = 'Y'
622      WHERE schedule_number = p_Schedule_Number;
623 
624 END Update_Flow_Schedule;
625 
626 
627 /************************************************************************
628  * PROCEDURE Print_Kanban_Cards						*
629  * 	Prints the Kanban Cards.					*
630  *	                                                                *
631  ************************************************************************/
632 PROCEDURE Print_Kanban_Cards(
633 	p_Kanban_Card_Ids	IN	Kanban_Card_Id_Tbl_Type) IS
634 
635   l_report_id	NUMBER;
636   l_card_count	NUMBER;
637   l_req_id	NUMBER;
638   l_sort_by	NUMBER;
639   l_call_from	NUMBER;
640 BEGIN
641 
642   SELECT MTL_KANBAN_CARD_PRINT_TEMP_S.nextval
643     INTO l_report_id
644     FROM dual;
645 
646   FOR l_card_count in 1..p_Kanban_Card_Ids.COUNT
647   LOOP
648 
649     INSERT into MTL_KANBAN_CARD_PRINT_TEMP(
650 		REPORT_ID,
651 		KANBAN_CARD_ID)
652 	 VALUES (l_report_id,
653 	         p_Kanban_Card_Ids(l_card_count));
654 
655   END LOOP; -- end of for loop
656 
657   l_sort_by	:= 3; -- for sort by Subinventory, locator
658   l_call_from	:= 2; -- as we are passing report_id
659 
660   l_req_id := fnd_request.submit_request( 'INV',
661                                           'INVKBCPR',
662                                            NULL,
663                                            NULL,
664                                            FALSE,
665                                            NULL, /* p_org_id */
666                                            NULL, /* p_date_created_low */
667                                            NULL, /* p_date_created_high */
668                                            NULL, /* p_kanban_card_number_low */
669                                            NULL, /* p_kanban_card_number_high */
670                                            NULL, /* p_item_low */
671                                            NULL, /* p_item_high */
672                                            NULL, /* p_subinv */
673                                            NULL, /* p_locator_low */
674                                            NULL, /* p_locator_high */
675                                            NULL, /* p_source_type */
676                                            NULL, /* p_kanban_card_type */
677                                            NULL, /* p_supplier */
678                                            NULL, /* p_supplier_site */
679                                            NULL, /* p_source_org_id */
680                                            NULL, /* p_source_subinv */
681                                            NULL, /* p_source_loc_id */
682                                            l_sort_by,   /* p_sort_by */
683                                            l_call_from, /* p_call_from */
684                                            NULL,        /* p_kanban_card_id */
685                                            l_report_id  /* p_report_id */
686                                         );
687 
688   IF l_req_id = 0 THEN
689     DELETE FROM mtl_kanban_card_print_temp
690           WHERE report_id = l_report_id;
691   END IF;
692   Commit;
693 
694 END Print_Kanban_Cards;
695 
696 
697 /************************************************************************
698  *	Public Procedures and Functions                             	*
699  ************************************************************************/
700 
701 
705  *	The Input parameters for this procedure are :			*
702 /************************************************************************
703  * PROCEDURE Create_And_Replenish_Cards					*
704  *  	This is the procedure which is called by the Concurrent	Request *
706  *	p_organization_id - Organization Identifier			*
707  *	p_min_line_code   - From Line Identifier			*
708  *	p_max_line_code   - To Line Identifier				*
709  *			  - To find flow schedules which are on lines	*
710 			    between From and To Lines identifier	*
711  *	p_completion_date - Completion Date of Flow Schedules		*
712  *			  - To find flow schedules which have scheduled *
713  *			    completion date less than the given date 	*
714  *			    greater than the sysdate			*
715  *	p_build_sequence  - Build Sequence of Flow Schedules		*
716  *			  - To find flow schedules which have build	*
717  *			    sequence less than or equal to the given	*
718  *			    build sequence and if this parameter is null*
719  *			    then find all flow schedules which have not *
720  *			    not build sequence				*
721  *	p_print_card	  - Print Kanban Cards Option (Yes/No)		*
722  ************************************************************************/
723 PROCEDURE Create_And_Replenish_Cards(
724 	o_error_code			OUT NOCOPY	NUMBER,
725 	o_error_msg			OUT NOCOPY	VARCHAR2,
726 	p_organization_id		IN	NUMBER,
727 	p_min_line_code			IN	VARCHAR2,
728 	p_max_line_code			IN	VARCHAR2,
729 	p_completion_date		IN	VARCHAR2,
730 	p_build_sequence		IN	NUMBER,
731 	p_print_card			IN	VARCHAR2) IS
732 
733   l_api_version_number	CONSTANT NUMBER := 1.0;
734 
735   l_comp_count		NUMBER;
736   l_Card_Count		NUMBER := 0;
737   l_schedule_number	VARCHAR2(30);
738   l_auto_replenish	VARCHAR2(1);
739   l_wip_entity_id	NUMBER;
740   l_build_sequence	NUMBER;
741   l_primary_item_id	NUMBER;
742   l_line_id		NUMBER;
743   l_open_qty		NUMBER;
744   l_alt_bom		VARCHAR2(10);
745   l_alt_rtg		VARCHAR2(10);
746   l_Kanban_Card_Id	NUMBER;
747   l_msg_count		NUMBER;
748   l_msg_data		VARCHAR2(2000);
749   l_return_status	VARCHAR2(10);
750   l_comp_name		VARCHAR2(600);
751   l_client_tz_id	NUMBER;
752   l_server_tz_id	NUMBER;
753 
754   /*------------------------------------------------------------------------+
755    | l_program_status signifies the status of concurrent program. It has    |
756    | following values :-                                                    |
757    |    'I' - Initial Status (default), when program is picking schedules   |
758    |    'F' - Fail Status, which signfies that all schedules have component |
759    |          to be picked, and none of them resulted in replenishment of   |
760    |          the card and thus status is fail.                             |
761    |    'S' - Success Status, which signifies that status was not fail      |
762    |          (Note : Even if program status has value 'S', still program   |
763    |                  may finish with Warning status                        |
764    +------------------------------------------------------------------------*/
765   l_program_status	VARCHAR2(1) := 'I';
766 
767   l_start_date		DATE;
768   l_completion_date	DATE;
769   l_need_by_date	DATE;
770   l_server_compl_date	DATE;
771 
772   l_Request_Status	BOOLEAN;
773 
774   l_comp_table		comp_list;
775   l_Kanban_Card_Ids	Kanban_Card_Id_Tbl_Type;
776 
777   create_exception	EXCEPTION;
778   update_exception	EXCEPTION;
779   replenish_exception	EXCEPTION;
780   timezone_exception	EXCEPTION;
781 
782   l_usage		NUMBER;
783   -- cursor to retrieve the flow schedules based on the criteria
784   CURSOR flow_schedule_csr IS
785     SELECT      flow.schedule_number,
786 		flow.build_sequence build_sequence,
787                 flow.primary_item_id primary_item_id,
788                 flow.line_id line_id,
789                 (flow.planned_quantity - nvl(flow.quantity_completed, 0)) open_quantity,
790                 flow.scheduled_start_date scheduled_start_date,
791                 flow.scheduled_completion_date scheduled_completion_date,
792                 flow.alternate_bom_designator alternate_bom_designator,
793                 flow.alternate_routing_designator alternate_routing_designator
794     FROM        wip_flow_schedules flow,
795                 wip_lines lines
796     WHERE       flow.planned_quantity - nvl(flow.quantity_completed, 0) > 0
797     AND         flow.status <> 2
798     AND         flow.scheduled_completion_date <= (l_server_compl_date + 1)
799     AND         flow.scheduled_completion_date >= sysdate
800     AND         flow.line_id = lines.line_id
801     AND         flow.organization_id = lines.organization_id
802     AND         lines.organization_id = p_organization_id
803     AND         lines.line_code BETWEEN p_min_line_code AND p_max_line_code
804     AND         ( (p_build_sequence is not null AND flow.build_sequence <= p_build_sequence)
805 		 OR (p_build_sequence is null AND flow.build_sequence is not null))
806     AND		nvl(flow.auto_replenish, 'N') = 'N';
807 
808 BEGIN
809 
810   Savepoint spBegin;
811 
812   IF (G_DEBUG) THEN
813     log('Welcome to Auto Replenishment');
814     log('Org = '||p_organization_id);
815     log('Min Line = '||p_min_line_code);
816     log('Max Line = '||p_max_line_code);
817     log('Compl Date = '||p_completion_date);
818     log('Build Seq = '||p_build_sequence);
819     log('Print = '||p_print_card);
820   END IF;
821 
825   l_server_tz_id := to_number(fnd_profile.value_specific('SERVER_TIMEZONE_ID'));
822   /* To convert the completion date entered by the user in the concurrent program to the
823      Server timezone */
824   l_client_tz_id := to_number(fnd_profile.value_specific('CLIENT_TIMEZONE_ID'));
826 
827   HZ_TIMEZONE_PUB.Get_Time(
828 		p_api_version		=> 1.0,
829 		p_init_msg_list		=> 'F',
830 		p_source_tz_id		=> l_client_tz_id,
831 		p_dest_tz_id		=> l_server_tz_id,
832 		p_source_day_time	=> fnd_date.canonical_to_date(p_completion_date),
833 		x_dest_day_time		=> l_server_compl_date,
834 		x_return_status		=> l_return_status,
835 		x_msg_count		=> l_msg_count,
836 		x_msg_data		=> l_msg_data);
837 
838   IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
839     raise timezone_exception;
840   END IF;
841 
842   FOR l_flow_schedule_csr IN flow_schedule_csr
843   LOOP
844     l_schedule_number := l_flow_schedule_csr.schedule_number;
845     l_build_sequence  := l_flow_schedule_csr.build_sequence;
846     l_primary_item_id := l_flow_schedule_csr.primary_item_id;
847     l_line_id         := l_flow_schedule_csr.line_id;
848     l_open_qty        := l_flow_schedule_csr.open_quantity;
849     l_start_date      := l_flow_schedule_csr.scheduled_start_date;
850     l_completion_date := l_flow_schedule_csr.scheduled_completion_date;
851     l_alt_bom         := l_flow_schedule_csr.alternate_bom_designator;
852     l_alt_rtg         := l_flow_schedule_csr.alternate_routing_designator;
853 
854     IF (G_DEBUG) THEN
855       log('Retrieved Schedules, Schedule = '|| l_schedule_number ||
856                              ', Assy = '|| l_primary_item_id ||
857 	                     ', Line = '|| l_line_id ||
858 			     ', Qty = '|| l_open_qty ||
859 			     ', Completion Date = '|| l_completion_date ||
860 			     ', Alt BOM = '|| l_alt_bom ||
861 			     ', Alt Routing = '|| l_alt_rtg);
862     END IF;
863 
864     BEGIN
865       Savepoint spSchedule;
866 
867       -- Lock the flow schedule for update of auto_replenish flag
868       BEGIN
869            SELECT auto_replenish
870              INTO l_auto_replenish
871              FROM wip_flow_schedules
872             WHERE schedule_number = l_schedule_number
873        FOR UPDATE OF auto_replenish NOWAIT;
874       EXCEPTION
875         WHEN OTHERS THEN
876           raise update_exception;
877       END;
878 
879 
880       IF (l_comp_table.COUNT <> 0) THEN
881         l_comp_table.DELETE;
882       END IF;
883 
884       -- Get all the components
885       get_subassemblies(p_organization_id,
886 			l_schedule_number,
887 			l_primary_item_id,
888 			l_alt_bom,
889 			l_alt_rtg,
890 			l_start_date,
891 			l_comp_table);
892 
893       l_comp_count := 1;
894       while l_comp_table.EXISTS(l_comp_count) LOOP
895         IF (G_DEBUG) THEN
896           log('Retrieved Valid Components in Assembly, Comp = '|| l_comp_table(l_comp_count).item_id ||
897 	                              ', Comp Pull Sequence = '|| l_comp_table(l_comp_count).pull_sequence_id);
898         END IF;
899 
900 	IF (nvl(l_program_status, 'I') <> 'S') THEN
901 	  l_program_status := 'F';
902 	END IF;
903 
904         -- Added for Lot Based Material Support
905         -- For item basis type, the usage is the component cumulative usage * flow schedule open qty
906         -- For lot basis type, the usage is the qty per assembly for that component.
907 	if (l_comp_table(l_comp_count).basis_type = WIP_CONSTANTS.ITEM_BASED_MTL) then
908 	  l_usage:=l_comp_table(l_comp_count).usage*l_open_qty;
909 	else
910           l_usage:=l_comp_table(l_comp_count).qty_per_lot;
911 	end if;
912 
913         -- Create Non-replenishable Kanban Card
914         INV_Kanban_GRP.Create_Non_Replenishable_Card(
915 		X_return_status		=> l_return_status,
916 		X_msg_data		=> l_msg_data,
917 		X_msg_count		=> l_msg_count,
918 		X_Kanban_Card_Id	=> l_Kanban_Card_id,
919 		p_pull_sequence_id	=> l_comp_table(l_comp_count).pull_sequence_id,
920 		p_kanban_size		=> l_usage);
921 
922         IF (l_return_status <> FND_API.G_RET_STS_SUCCESS and l_Kanban_Card_Id IS NULL) THEN
923 
924 	  Show_Exception_Messages(
925 		p_msg_count		=> l_msg_count,
926 		p_msg_data		=> l_msg_data,
927 		p_schedule_number	=> l_schedule_number,
928 		p_comp_id		=> l_comp_table(l_comp_count).item_id,
929 		p_organization_id	=> p_organization_id,
930 		p_error_position	=> G_Error_Create_Cards);
931 
932 	  l_Request_Status := fnd_concurrent.set_completion_status(status	=> 'WARNING',
933                                                                    message	=> '');
934 	  raise create_exception;
935 
936         END IF;
937 
938         IF (G_DEBUG) THEN
939           log('Created Non-Replenishable Kanban Card, Card Id = '|| l_Kanban_Card_Id);
940         END IF;
941 
942         -- Get Need By date for the component
943         l_need_by_date := Need_By_Date(p_organization_id,
944 				l_line_id,
945 				l_comp_table(l_comp_count).item_id,
946 				l_completion_date,
947 				l_start_date,
948 				l_comp_table(l_comp_count).line_op_seq_id,
949 				l_usage);
950 
951         -- Replenish the Cards
952         SELECT wip_entity_id
953           INTO l_wip_entity_id
954    	  FROM wip_flow_schedules
958         INV_Kanban_GRP.Update_Card_Supply_Status(
955          WHERE schedule_number = l_comp_table(l_comp_count).schedule_number
956 	   AND organization_id = p_organization_id;
957 
959 		x_msg_count		=> l_msg_count,
960 		x_msg_data		=> l_msg_data,
961 		x_return_status		=> l_return_status,
962 		p_api_version_number	=> l_api_version_number,
963 		p_init_msg_list		=> NULL,
964 		p_commit		=> NULL,
965 		p_Kanban_Card_Id	=> l_Kanban_Card_Id,
966 		p_Supply_Status		=> G_Supply_Status_Empty,
967 		p_Document_Type		=> NULL,
968 		p_Document_Header_Id	=> NULL,
969 		p_Document_Detail_Id	=> NULL,
970 		p_Need_By_Date		=> l_need_by_date,
971 		p_Source_Wip_Entity_Id	=> l_wip_entity_id);
972 
973 	IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
974 
975 	  Show_Exception_Messages(
976 		p_msg_count		=> l_msg_count,
977 		p_msg_data		=> l_msg_data,
978 		p_schedule_number	=> l_schedule_number,
979 		p_comp_id		=> l_comp_table(l_comp_count).item_id,
980 		p_organization_id	=> p_organization_id,
981 		p_error_position	=> G_Error_Replenish_Cards);
982 
983 	  l_Request_Status := fnd_concurrent.set_completion_status(status	=> 'WARNING',
984                                                                    message	=> '');
985 	  raise replenish_exception;
986 
987         END IF;
988 
989         IF (G_DEBUG) THEN
990           log('Replenished Kanban Card, Card Id = '|| l_Kanban_Card_Id);
991         END IF;
992 
993         -- Update Auto_Replenish flag in Flow Scheules
994         Update_Flow_Schedule(l_comp_table(l_comp_count).schedule_number);
995 
996         IF (G_DEBUG) THEN
997           log('Updated Auto Replenish flag of Flow schedules, Schedule number = '|| l_comp_table(l_comp_count).schedule_number);
998         END IF;
999 
1000         l_Card_Count := l_Card_Count + 1;
1001         l_Kanban_Card_Ids(l_Card_Count) := l_Kanban_Card_Id;
1002 
1003         l_comp_count := l_comp_count + 1;
1004 
1005 	l_program_status := 'S';
1006 
1007       END LOOP; -- end of while loop
1008 
1009       l_program_status := 'S';
1010 
1011     EXCEPTION
1012       WHEN create_exception THEN
1013         Rollback to spSchedule;
1014       WHEN replenish_exception THEN
1015         Rollback to spSchedule;
1016       WHEN update_exception THEN
1017         fnd_message.set_name('FLM', 'FLM_AR_ERR_LOCK_SCHEDULE');
1018         log(fnd_message.get);
1019         Rollback to spSchedule;
1020       WHEN OTHERS THEN
1021         Rollback to spSchedule;
1022 
1023     END; -- end of Begin
1024 
1025   END LOOP; -- end of for loop
1026 
1027   /*-------------------------------------------------------------------------------------------+
1028    | Print Kanban Cards                                                                        |
1029    | If Print Kanban Cards option is selected and cards have been created then only print cards|
1030    +-------------------------------------------------------------------------------------------*/
1031   IF (p_print_card = 1 AND l_Kanban_Card_Ids.COUNT > 0) THEN
1032 
1033     Print_Kanban_Cards(l_Kanban_Card_Ids);
1034 
1035     IF (G_DEBUG) THEN
1036       log('Print request generated for creating Kanban Cards');
1037     END IF;
1038 
1039   END IF;
1040 
1041   /*-------------------------------------------------------------------------------------------+
1042    | If program_status has not been set to 'S', it signifies that all the flow schedules have  |
1043    | failed, i.e. all schedules have components to be replenished and none of the flow schedule|
1044    | succeeded, thus setting the request completion status to ERROR.                           |
1045    +-------------------------------------------------------------------------------------------*/
1046 
1047   IF ( nvl(l_program_status, 'I') = 'F' ) THEN
1048     l_Request_Status := fnd_concurrent.set_completion_status(status	=> 'ERROR',
1049                                                              message	=> '');
1050   END IF;
1051 
1052 EXCEPTION
1053   WHEN timezone_exception THEN
1054     fnd_message.set_name('FLM', 'FLM_AR_ERR_TIMEZONE');
1055     log(fnd_message.get);
1056   WHEN OTHERS THEN
1057     fnd_message.set_name('FLM', 'FLM_AR_ERR_UNEXP');
1058     log(fnd_message.get);
1059 END create_and_replenish_cards;
1060 
1061 
1062 END FLM_AUTO_REPLENISHMENT;