DBA Data[Home] [Help]

PACKAGE BODY: APPS.MRP_LINE_SCHEDULE_ALGORITHM

Source


1 PACKAGE BODY MRP_LINE_SCHEDULE_ALGORITHM AS
2 /* $Header: MRPLSCHB.pls 120.1.12010000.2 2008/08/20 19:25:03 adasa ship $ */
3 
4 -- Global Variable to hold min wip_entity Id
5   G_WIP_ENTITY_ID NUMBER;
6 
7 -- This cursor is a list of unique items in the flow schedules to be scheduled on
8 -- the specified line.
9 
10   CURSOR item_list (p_org_id NUMBER) IS
11     SELECT DISTINCT primary_item_id
12     FROM   wip_flow_schedules
13     WHERE  request_id = USERENV('SESSIONID')
14       AND  organization_id = p_org_id
15       AND wip_entity_id >= G_WIP_ENTITY_ID;
16 
17 -- This cursor is a list of unique schedule groups in the flow schedules to be
18 -- scheduled on the specified line.
19 
20   CURSOR schedule_group_list (p_org_id NUMBER) IS
21     SELECT DISTINCT schedule_group_id schedule_group
22     FROM   wip_flow_schedules
23     WHERE  request_id = USERENV('SESSIONID')
24       AND  organization_id = p_org_id
25       AND wip_entity_id >= G_WIP_ENTITY_ID;
26 
27 /* Fix for bug 2977987: Added columns primary_item_id, bom_revision_date
28    and routing_revision_date to be selected by the sursor. */
29   CURSOR fs_list (p_line_id NUMBER, p_org_id NUMBER) IS
30     SELECT wip_entity_id, schedule_group_id, scheduled_completion_date,
31            primary_item_id, bom_revision_date, routing_revision_date
32     FROM   wip_flow_schedules
33     WHERE  request_id = USERENV('SESSIONID')
34       AND  line_id = p_line_id
35       AND  organization_id = p_org_id
36       AND  scheduled_flag = C_YES
37       AND  wip_entity_id >= G_WIP_ENTITY_ID
38     ORDER BY scheduled_completion_date;
39 
40 -- This cursor is used in the level daily rate algorithm.  It retrieves the items
41 -- to be scheduled, ordered in descending order the fraction from calculation of
42 -- the production plan for each item.  This is used for rounding.
43 
44   CURSOR production_round (p_date NUMBER, p_query_id IN NUMBER) IS
45     SELECT number1, number2,number3
46     FROM   mrp_form_query
47     WHERE  date1 = to_date(p_date,'J')
48     AND    query_id = p_query_id
49     ORDER BY number3 DESC;
50 
51 -- This cursor is a list of existing flow schedules ordered by schedule group
52 -- and build sequence so that time stamps can be assigned to them.
53 -- hwenas: query never used, so decided to not change for bug#3783650
54   CURSOR flow_schedule_list (p_line_id NUMBER, p_org_id NUMBER, p_date NUMBER)
55   IS
56     SELECT  wip_entity_id,planned_quantity,quantity_completed,
57 	    schedule_group_id,build_sequence,primary_item_id
58     FROM    wip_flow_schedules
59     WHERE   to_number(to_char(scheduled_completion_date,'J'))
60 		= p_date
61       AND   line_id = p_line_id
62       AND   organization_id = p_org_id
63       AND   scheduled_flag = C_YES
64     ORDER BY schedule_group_id,build_sequence;
65 
66 -- This procedure constructs the main select cursor and returns
67 -- a handle to the calling functions
68 
69 FUNCTION Create_Cursor( p_rule_id IN NUMBER,
70 			p_org_id IN NUMBER,
71 		        p_line_id IN NUMBER,
72 			p_order IN NUMBER,
73 			p_type IN NUMBER,
74 			p_item_id IN NUMBER)
75 RETURN INTEGER
76 IS
77   v_select 		VARCHAR2(5000);
78   dummy                 INTEGER;
79   cursor_name           INTEGER;
80   v_seq_criteria	VARCHAR2(500);
81   fs_select_rec	        fs_select_type;
82 
83 BEGIN
84   V_PROCEDURE_NAME := 'Create_Cursor';
85   V_ERROR_LINE := 1;
86 
87   v_seq_criteria := order_scheduling_rule(p_rule_id, p_order);
88 
89   v_select := 'SELECT '||
90          ' fs.wip_entity_id wip_entity, '||
91 	 ' sol.creation_date creation_date, '||
92         ' NVL(sol.schedule_ship_date,fs.scheduled_completion_date) schedule_date,'||
93          ' sol.promise_date promise_date, '||
94          ' sol.request_date request_date, '||
95          ' sol.planning_priority planning_priority, '||
96          ' fs.primary_item_id primary_item_id, '||
97 	 ' fs.planned_quantity planned_quantity, '||
98 	 ' fs.schedule_group_id schedule_group_id '||
99   ' FROM   oe_order_lines_all sol,wip_flow_schedules fs  '||
100   ' WHERE  fs.request_id = :v_session_id '||
101     ' AND  fs.organization_id = :p_org_id '||
102     ' AND  fs.line_id = :p_line_id '||
103     ' AND  sol.line_id(+) = fs.demand_source_line '||
104     ' AND  fs.scheduled_flag = 3 '||
105     ' AND  :p_item_id > 0 ';
106 
107   IF p_type <> C_NORM THEN
108     v_select := v_select || ' AND fs.primary_item_id = :p_item_id ';
109   END IF;
110 
111   v_select := v_select || ' ORDER BY '|| v_seq_criteria;
112 
113   cursor_name := dbms_sql.open_cursor;
114   dbms_sql.parse(cursor_name, v_select, dbms_sql.v7);
115   dbms_sql.bind_variable(cursor_name, ':v_session_id', USERENV('SESSIONID'));
116   dbms_sql.bind_variable(cursor_name, ':p_org_id', p_org_id);
117   dbms_sql.bind_variable(cursor_name, ':p_line_id', p_line_id);
118   dbms_sql.bind_variable(cursor_name, ':p_item_id', p_item_id);
119 
120   dbms_sql.define_column(cursor_name,1, fs_select_rec.wip_entity);
121   dbms_sql.define_column(cursor_name,2, fs_select_rec.creation_date);
122   dbms_sql.define_column(cursor_name,3, fs_select_rec.schedule_date);
123   dbms_sql.define_column(cursor_name,4, fs_select_rec.promise_date);
124   dbms_sql.define_column(cursor_name,5, fs_select_rec.request_date);
125   dbms_sql.define_column(cursor_name,6, fs_select_rec.planning_priority);
126   dbms_sql.define_column(cursor_name,7, fs_select_rec.primary_item_id);
127   dbms_sql.define_column(cursor_name,8, fs_select_rec.planned_quantity);
128   dbms_sql.define_column(cursor_name,9, fs_select_rec.schedule_group_id);
129   dummy := dbms_sql.execute(cursor_name);
130 
131   return(cursor_name);
132 
133 EXCEPTION
134   WHEN OTHERS THEN
135     IF (dbms_sql.is_open(cursor_name)) THEN
136       dbms_sql.close_cursor(cursor_name);
137     END IF;
138 
139     IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
140       FND_MSG_PUB.Add_Exc_Msg(
141 	V_PKG_NAME,V_PROCEDURE_NAME||': Line '||to_char(V_ERROR_LINE));
142     END IF;
143 
144     RETURN NULL;
145 END Create_Cursor;
146 
147 FUNCTION get_flex_tolerance( p_org_id IN NUMBER,
148                              p_line_id IN NUMBER,
149                              p_date IN NUMBER) RETURN NUMBER
150 IS
151   v_days_out NUMBER;
152   v_fence_days NUMBER;
153   v_tol_percent NUMBER;
154 BEGIN
155 
156   v_days_out := mrp_calendar.DAYS_BETWEEN(p_org_id,1,sysdate,to_date(p_date,'J'));
157 
158   select nvl(max(FENCE_DAYS),-1)
159   into v_fence_days
160   from bom_resource_flex_fences
161   where fence_days <= v_days_out
162     and department_id = p_line_id;
163 
164   if v_fence_days > -1 then
165     select max(tolerance_percentage)
166     into v_tol_percent
167     from bom_resource_flex_fences
168     where fence_days = v_fence_days
169       and department_id = p_line_id;
170   else
171     return 0;
172   end if;
173 
174   return ( v_tol_percent/100);
175 END get_flex_tolerance;
176 
177 
178 -- This procedure calculates the daily net available capacity on the line
179 -- by subtracting the line rate by the capacity used by existing work orders.
180 
181 PROCEDURE calculate_linecap(
182 				p_line_id IN NUMBER,
183 				p_org_id IN NUMBER,
184 				p_flex_tolerance IN NUMBER,
185                                 p_cap_tab IN OUT NOCOPY CapTabTyp,
186                                 p_time_tab IN TimeTabTyp,
187                                 p_schedule_start_date IN NUMBER,
188                                 p_schedule_start_time IN NUMBER,
189                                 p_schedule_end_date IN NUMBER,
190                                 p_schedule_end_time IN NUMBER
191 )
192 IS
193 
194   v_cal_code	VARCHAR2(10);
195   v_excep_code	NUMBER;
196   v_line_rate 	NUMBER;
197   v_sum_dj	NUMBER;
198   v_sum_fs	NUMBER;
199   v_sum_rs	NUMBER;
200   v_date	DATE;
201   v_capacity    NUMBER;
202   v_hr_rate	NUMBER;
203   v_line_start_time	NUMBER;
204   v_line_stop_time 	NUMBER;
205   v_start_time	NUMBER;
206   v_stop_time 	NUMBER;
207   v_current_date NUMBER;
208   v_current_date2 NUMBER;
209   v_qty_to_sched NUMBER;
210   v_add_capacity NUMBER;
211   v_adj_add_capacity NUMBER;
212   v_flex_tol NUMBER;
213   v_line_rate_cur NUMBER;
214   v_line_rate_new NUMBER;
215 
216   v_current_date_in_client00 DATE;  --fix bug#3783650
217 
218 BEGIN
219 
220   V_PROCEDURE_NAME := 'calculate_linecap';
221   V_ERROR_LINE := 1;
222 
223   SELECT calendar_code,calendar_exception_set_id
224   INTO   v_cal_code,v_excep_code
225   FROM   mtl_parameters
226   WHERE  organization_id = p_org_id;
227 
228   V_ERROR_LINE := 2;
229 
230   -- For each work day, loop through all the dates and initialize the capacity to the
231   -- line rate. Calculate the sum of all existing work orders, discrete jobs,
232   -- repetitive schedules, and flow schedules and decrement the sum from the line rate
233   -- for each day.
234 
235   -- Fix bug 939061, add 24 hrs to stop_time if stop_time <= start_time
236   SELECT maximum_rate, start_time, stop_time
237   INTO   v_hr_rate, v_line_start_time, v_line_stop_time
238   FROM   wip_lines
239   WHERE  line_id = p_line_id
240   AND    organization_id = p_org_id;
241 
242   if (v_line_stop_time <= v_line_start_time) then
243     v_line_stop_time := v_line_stop_time + 24*3600;
244   end if;
245 
246   v_line_rate := v_hr_rate * (v_line_stop_time - v_line_start_time)/3600;
247 
248   V_ERROR_LINE := 3;
249 
250   -- Get total_quantity to be scheduled
251   select sum(planned_quantity)
252   into v_qty_to_sched
253   from wip_flow_schedules
254   where request_id = USERENV('SESSIONID')
255     and line_id = p_line_id
256     and organization_id = p_org_id
257     and scheduled_flag = C_NO
258     and wip_entity_id >= G_WIP_ENTITY_ID;
259 
260   v_current_date := p_time_tab.FIRST;
261 
262   LOOP
263 
264     p_cap_tab(v_current_date).capacity := v_line_rate;
265 
266     --fix bug#3783650
267     v_date := to_date(v_current_date,'J');
268     v_current_date_in_client00 := flm_timezone.client00_in_server(v_date+(v_line_start_time/86400));
269     --end of fix bug#3783650
270 
271     SELECT NVL(SUM(NVL(start_quantity,0)
272 		- NVL(quantity_completed,0)
273                 - NVL(quantity_scrapped,0)),0)
274     INTO   v_sum_dj
275     FROM   wip_discrete_jobs
276     WHERE  line_id = p_line_id
277     AND    organization_id = p_org_id
278     --fix bug#3783650
279     --AND    to_number(to_char(scheduled_completion_date,'J'))
280     --       = v_current_date;
281     AND    scheduled_completion_date BETWEEN v_current_date_in_client00
282     AND    v_current_date_in_client00+1-(1/86400);
283     --end of fix bug#3783650
284 
285     V_ERROR_LINE := 4;
286 
287     --fix bug#3783650: move up    v_date := to_date(v_current_date,'J');
288 
289     IF (v_sum_dj > 0) THEN
290 
291       p_cap_tab(v_current_date).capacity :=
292 		p_cap_tab(v_current_date).capacity - v_sum_dj;
293     END IF;
294 
295     SELECT NVL(SUM(NVL(planned_quantity,0)
296                 -NVL(quantity_completed,0)),0)
297     INTO   v_sum_fs
298     FROM   wip_flow_schedules
299     WHERE  line_id = p_line_id
300     AND    organization_id = p_org_id
301     --fix bug#3783650
302     --AND    to_number(to_char(scheduled_completion_date,'J'))
303     -- 	     = v_current_date
304     AND    scheduled_completion_date BETWEEN v_current_date_in_client00
305     AND    v_current_date_in_client00+1-(1/86400)
306     AND    scheduled_flag = C_YES;
307     --end of fix bug#3783650
308 
309     V_ERROR_LINE := 5;
310 
311     IF (v_sum_fs > 0) THEN
312 
313       p_cap_tab(v_current_date).capacity :=
314 	 	p_cap_tab(v_current_date).capacity - v_sum_fs;
315 
316     END IF;
317 
318     SELECT NVL(SUM(NVL(MRP_HORIZONTAL_PLAN_SC.compute_daily_rate_t(
319 		v_cal_code,
320 		v_excep_code,
321 		wip_repetitive_schedules.daily_production_rate,
322 		wip_repetitive_schedules.quantity_completed,
323 		wip_repetitive_schedules.first_unit_completion_date,
324 		to_date(v_current_date,'J')),0)),0)
325     INTO   v_sum_rs
326     FROM   wip_repetitive_schedules
327     WHERE  line_id = p_line_id
328     AND    organization_id = p_org_id
329     --fix bug#3783650
330     --AND    v_current_date BETWEEN
331     --       to_number(to_char(first_unit_completion_date,'J'))
332     --AND to_number(to_char(last_unit_completion_date,'J'));
333     AND    v_current_date_in_client00 BETWEEN
334  		flm_timezone.client00_in_server(first_unit_completion_date)
335     AND flm_timezone.client00_in_server(last_unit_completion_date+1)-1/86400;
336     --end of fix bug#3783650
337 
338     V_ERROR_LINE := 6;
339 
340     IF (v_sum_rs > 0) THEN
341 
342       p_cap_tab(v_current_date).capacity :=
343       p_cap_tab(v_current_date).capacity - v_sum_rs;
344 
345     END IF;
346 
347     v_capacity := v_hr_rate * (p_time_tab(v_current_date).end_completion_time -
348                   p_time_tab(v_current_date).start_completion_time) / 3600;
349     -- if v_capacity < 0 means that schedule_end_time is less than line start time
350     if (v_capacity < 0) then
351       v_capacity := 0;
352     end if;
353     if (v_capacity < p_cap_tab(v_current_date).capacity) then
354       p_cap_tab(v_current_date).capacity := v_capacity;
355     end if;
356 
357     -- The capacity left in the line will be used  to fulfill the quantity to
358     -- be scheduled. Thus, we reduce the quantity to be scheduled with the
359     -- capacity left in the line.
360     if (v_qty_to_sched > 0) then
361       v_qty_to_sched := v_qty_to_sched -
362                         p_cap_tab(v_current_date).capacity;
363     end if;
364 
365     exit when p_time_tab.LAST = v_current_date;
366     v_current_date := p_time_tab.NEXT(v_current_date);
367   END LOOP;
368 
369   -- This variable hold the additional capacity that can be used.
370   -- It's the different between previous line rate and current line rate.
371   v_add_capacity := 0;
372 
373   -- If there is quantity to be scheduled, it means that the system can't
374   -- schedule all quantity using the capacity defined for that line.
375   -- Then it will use flex tolerances if any, to increase the line capacity
376   -- that will be used to schedule the remaining quantity.
377   -- The line capacity will be increased in steps. It will use the
378   -- flex tolerance starting from the start schedule date to the
379   -- end schedule date. Using the tolerance from day X (which start from
380   -- start schedule date to end schedule date), it will increase the
381   -- line capacity from day X till end schedule date. At any point, it
382   -- will exit, if the capacity is enough for scheduling the remaining
383   -- quantity. Then it will use the flex tolerance from day X+1 to
384   -- increase the line capacity from day X+1 till end schedule date.
385   -- Remember that this capacity increase should be the increment from
386   -- the previous capacity increase. e.g : in day X. the flex tolerance = 10
387   -- , and in day X+1, the flex tolerance = 15, the capacity increase
388   -- in day X+1 must be 5 (15-10).
389 
390   if (p_flex_tolerance = 1 and v_qty_to_sched > 0) then
391 
392     -- Start the loop to get the day from schedule start date to
393     -- schedule end date.
394     v_current_date := p_cap_tab.FIRST;
395     v_line_rate_cur := v_line_rate;
396 
397     loop
398 
399       -- Get the flex tolerance for a given day
400       v_flex_tol := get_flex_tolerance(p_org_id, p_line_id, v_current_date);
401       v_line_rate_new := round(v_line_rate * (1+v_flex_tol));
402 
403       -- The additional capacity that can be added to the line is the
404       -- increment between previous line rate (v_line_rate_cur) and
405       -- the new line rate v_line_rate_new
406       v_add_capacity := v_line_rate_new - v_line_rate_cur;
407 
408       -- Set the current line rate to the new line rate
409       v_line_rate_cur := v_line_rate_new;
410 
411       v_current_date2 := v_current_date;
412 
413       loop
414         -- Adjust the additional capacity with over capacity on the current schedule.
415         if (p_cap_tab(v_current_date2).capacity < 0) then
416           v_adj_add_capacity := v_add_capacity + p_cap_tab(v_current_date2).capacity;
417         else
418           v_adj_add_capacity := v_add_capacity;
419         end if;
420 
421         v_start_time := v_line_start_time;
422         v_stop_time := v_line_stop_time;
423         if (v_current_date2 = p_schedule_start_date and p_schedule_start_time > v_start_time) then
424           v_start_time := p_schedule_start_time;
425         elsif (v_current_date2 = p_schedule_end_date and p_schedule_end_time < v_stop_time) then
426           v_stop_time := p_schedule_end_time;
427         end if;
428 
429         -- To adjust the capacity based on the user defined schedule start and end time.
430         v_adj_add_capacity := round((v_stop_time-v_start_time)/
431                               (v_line_stop_time-v_line_start_time)*v_adj_add_capacity);
432 
433         if (v_adj_add_capacity > 0) then
434           -- If all the remaning quantity can be fulfill by the addition
435           -- of the capacity, increase line capacity on that day with the
436           -- remaning quantity. Then we complete.
437           -- Otherwise, increase the line capacity with the additional
438           -- capacity. Also need to decrease the quantity to be scheduled with
439           -- additional capacity, because some portion of that quantity can
440           -- be fulfilled with this additional capacity
441           if (v_qty_to_sched <= v_adj_add_capacity) then
442             p_cap_tab(v_current_date2).capacity := p_cap_tab(v_current_date2).capacity + v_qty_to_sched;
443             return;
444           else
445             p_cap_tab(v_current_date2).capacity := p_cap_tab(v_current_date2).capacity + v_adj_add_capacity;
446             v_qty_to_sched := v_qty_to_sched - v_adj_add_capacity;
447           end if;
448         end if;
449         exit when v_current_date2 = p_cap_tab.LAST;
450         v_current_date2 := p_cap_tab.NEXT(v_current_date2);
451       end loop;
452 
453       exit when v_current_date = p_cap_tab.LAST;
454       v_current_date := p_cap_tab.NEXT(v_current_date);
455 
456     end loop;
457 
458   end if;
459 
460   -- Set the capacity to 0 for any negative value on the capacity
461   v_current_date := p_cap_tab.FIRST;
462   loop
463     if (p_cap_tab(v_current_date).capacity < 0) then
464       p_cap_tab(v_current_date).capacity := 0;
465     end if;
466     exit when v_current_date = p_cap_tab.LAST;
467     v_current_date := p_cap_tab.NEXT(v_current_date);
468   end loop;
469 
470 EXCEPTION
471   WHEN NO_DATA_FOUND THEN
472     RETURN;
473 
474   WHEN OTHERS THEN
475 
476     IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
477       FND_MSG_PUB.Add_Exc_Msg(
478 	V_PKG_NAME,V_PROCEDURE_NAME||': Line '||to_char(V_ERROR_LINE));
479     END IF;
480 
481     return;
482 
483 END calculate_linecap;
484 
485 -- This function returns a string containing the sequencing criteria of a scheduling
486 -- rule, ordered by the priority of each criteria.
487 
488 FUNCTION order_scheduling_rule(p_rule_id IN NUMBER,
489 			       p_order IN NUMBER) RETURN VARCHAR2
490 IS
491   v_ordered_criteria 	VARCHAR2(500);
492   v_source_type	 	NUMBER;
493   i			NUMBER;
494 
495   CURSOR criteria_select IS
496     SELECT usage_code
497     FROM mrp_scheduling_rules
498     WHERE rule_id = p_rule_id
499     AND   NVL(user_defined,C_USER_DEFINE_NO) = C_USER_DEFINE_NO
500     ORDER BY sequence_number;
501 
502 BEGIN
503   V_PROCEDURE_NAME := 'order_scheduling_rule';
504   V_ERROR_LINE := 1;
505 
506   -- Determine if flow schedules originate from sales orders or planned orders
507   SELECT demand_source_type
508   INTO   v_source_type
509   FROM   wip_flow_schedules
510   WHERE  request_id = USERENV('SESSIONID')
511     AND  scheduled_flag = C_NO
512     AND  rownum = 1
513     AND  wip_entity_id >= G_WIP_ENTITY_ID;
514 
515   V_ERROR_LINE := 2;
516 
517   IF v_source_type = C_PLANNED_ORDER THEN
518     v_ordered_criteria := 'fs.scheduled_completion_date';
519 
520     RETURN(v_ordered_criteria);
521 
522   ELSIF v_source_type IN (C_EXT_SALES_ORDER, C_INT_SALES_ORDER) THEN
523 
524     v_ordered_criteria := NULL;
525 
526     i := 1;
527 
528     FOR criteria_select_rec IN criteria_select LOOP
529 
530       IF i > 1 THEN
531         v_ordered_criteria := v_ordered_criteria ||',';
532       END IF;
533 
534       IF criteria_select_rec.usage_code = 1 THEN
535         v_ordered_criteria := v_ordered_criteria || 'sol.request_date';
536 
537       ELSIF criteria_select_rec.usage_code = 2 THEN
538         v_ordered_criteria := v_ordered_criteria || 'sol.schedule_ship_date';
539 
540       ELSIF criteria_select_rec.usage_code = 3 THEN
541         v_ordered_criteria := v_ordered_criteria || 'sol.promise_date';
542 
543       ELSIF criteria_select_rec.usage_code = 4 THEN
544         v_ordered_criteria := v_ordered_criteria || 'sol.creation_date';
545 
546       ELSIF criteria_select_rec.usage_code = 5 THEN
547         v_ordered_criteria := v_ordered_criteria || 'sol.planning_priority';
548 
549       ELSIF criteria_select_rec.usage_code = 7 THEN
550         v_ordered_criteria := v_ordered_criteria || 'sol.cust_production_seq_num';
551 
552       ELSIF criteria_select_rec.usage_code = 8 THEN
553         v_ordered_criteria := v_ordered_criteria || 'sol.cust_production_seq_num desc';
554 
555       END IF;
556 
557       IF p_order = C_DESC THEN
558 	v_ordered_criteria := v_ordered_criteria || ' DESC';
559       END IF;
560 
561       i := i + 1;
562 
563     END LOOP;
564 
565     IF v_ordered_criteria IS NULL THEN
566       v_ordered_criteria := 'fs.scheduled_completion_date';
567     END IF;
568     RETURN(v_ordered_criteria);
569 
570   END IF;
571 
572 EXCEPTION
573   WHEN NO_DATA_FOUND THEN
574     RETURN(NULL);
575 
576   WHEN OTHERS THEN
577     IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
578       FND_MSG_PUB.Add_Exc_Msg(
579 	V_PKG_NAME,V_PROCEDURE_NAME||': Line '||to_char(V_ERROR_LINE));
580     END IF;
581 
582   return(NULL);
583 
584 END order_scheduling_rule;
585 
586 -- This procedure takes each item that has unscheduled flow schedules on the
587 -- line and calculates the acceptable order quantities depending on the order
588 -- modifiers associated with the item.
589 
590 PROCEDURE calculate_order_quantities(
591 					p_org_id  IN NUMBER,
592 					p_order_mod_tab IN OUT NOCOPY OrderModTabTyp)
593 IS
594   v_fixed_qty	   NUMBER;
595   v_lot_multiple   NUMBER;
596   v_min_qty	   NUMBER;
597   v_max_qty	   NUMBER;
598 
599 BEGIN
600 
601   V_PROCEDURE_NAME := 'Calculate_Order_Quantities';
602   V_ERROR_LINE := 1;
603 
604   -- From the order modifiers for each item, find out what order quantities can be
605   -- used.  The order modifier columns are fixed_order_qty, fixed_lot_multiplier,
606   -- min_qty, and max_qty.
607 
608   -- The calculated order quantities are stored in a pl/sql table.
609 
610   FOR item_list_rec IN item_list(p_org_id) LOOP
611 
612     SELECT NVL(fixed_order_quantity,0), NVL(fixed_lot_multiplier,0),
613            NVL(minimum_order_quantity,0), NVL(maximum_order_quantity,0)
614     INTO   v_fixed_qty, v_lot_multiple, v_min_qty, v_max_qty
615     FROM   mtl_system_items
616     WHERE  inventory_item_id = item_list_rec.primary_item_id
617       AND  organization_id = p_org_id;
618 
619     V_ERROR_LINE := 2;
620 
621     -- If fixed order quantity exists for the item, then that will simply be
622     -- the order quantity
623 
624     IF v_fixed_qty > 0 THEN
625 
626       p_order_mod_tab(item_list_rec.primary_item_id).minVal := v_fixed_qty;
627       p_order_mod_tab(item_list_rec.primary_item_id).maxVal := v_fixed_qty;
628 
629     -- If the fixed order quantity does not exist for the item, and the fixed lot
630     -- multiplier exists, make sure that the fixed lot multiple quantity is between
631     -- the minimum and maximum values.
632 
633     ELSIF v_lot_multiple > 0 THEN
634 
635       IF (v_lot_multiple >= v_min_qty AND v_lot_multiple <= v_max_qty) OR
636 	(v_min_qty = 0 AND v_max_qty = 0) THEN
637 
638 	p_order_mod_tab(item_list_rec.primary_item_id).minVal := v_lot_multiple;
639 	p_order_mod_tab(item_list_rec.primary_item_id).maxVal := v_lot_multiple;
640 
641       ELSIF v_lot_multiple < v_min_qty THEN
642         p_order_mod_tab(item_list_rec.primary_item_id).minVal := v_min_qty;
643         p_order_mod_tab(item_list_rec.primary_item_id).maxVal := v_min_qty;
644 
645       ELSIF v_lot_multiple > v_max_qty THEN
646         p_order_mod_tab(item_list_rec.primary_item_id).minVal := v_max_qty;
647         p_order_mod_tab(item_list_rec.primary_item_id).maxVal := v_max_qty;
648       END IF;
649 
650     -- If only the minimum and maximum order quantities exist, both values
651     -- will be stored.  However, at this point, we will only consider the
652     -- minimum value.  In the future, we need to figure out a way to consider
653     -- the maximum value so that order quantities can take different values as
654     -- long as they fall within the minimum and maximum values.
655 
656     ELSIF (v_min_qty > 0) AND (v_max_qty > 0) THEN
657       	  p_order_mod_tab(item_list_rec.primary_item_id).minVal := v_min_qty;
658 	  p_order_mod_tab(item_list_rec.primary_item_id).maxVal := v_max_qty;
659 
660     -- If only the minimum or maximum order quantity is defined:
661 
662     ELSIF (v_min_qty > 0) THEN
663       p_order_mod_tab(item_list_rec.primary_item_id).minVal := v_min_qty;
664       p_order_mod_tab(item_list_rec.primary_item_id).maxVal := v_min_qty;
665 
666     ELSIF (v_max_qty > 0) THEN
667       p_order_mod_tab(item_list_rec.primary_item_id).minVal := v_max_qty;
668       p_order_mod_tab(item_list_rec.primary_item_id).maxVal := v_max_qty;
669 
670     -- If there are no order modifier values, then no order modifier constraints exist.
671     ELSE
672       p_order_mod_tab(item_list_rec.primary_item_id).minVal := 0;
673       p_order_mod_tab(item_list_rec.primary_item_id).maxVal := 0;
674     END IF;
675 
676   END LOOP;
677 
678 EXCEPTION
679   WHEN NO_DATA_FOUND THEN
680     RETURN;
681 
682   WHEN OTHERS THEN
683 
684     IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
685       FND_MSG_PUB.Add_Exc_Msg(
686 	V_PKG_NAME,V_PROCEDURE_NAME||': Line '||to_char(V_ERROR_LINE));
687     END IF;
688 
689     return;
690 
691 END calculate_order_quantities;
692 
693 -- This procedure obtains the highest build sequence for each schedule group and
694 -- populates that information in a pl/sql table.
695 
696 PROCEDURE calculate_build_sequences (
697 				p_org_id  IN NUMBER,
698 				p_line_id IN NUMBER,
699 				p_build_seq_tab IN OUT NOCOPY BuildSeqTabTyp)
700 IS
701 
702 v_null_build_seq NUMBER;
703 
704 BEGIN
705 
706   V_PROCEDURE_NAME := 'Calculate_Build_Sequences';
707   V_ERROR_LINE := 1;
708 
709   FOR schedule_group_rec IN schedule_group_list(p_org_id) LOOP
710 
711     IF schedule_group_rec.schedule_group IS NOT NULL THEN
712       SELECT NVL(MAX(build_sequence),0)
713       INTO   p_build_seq_tab(schedule_group_rec.schedule_group).buildseq
714       FROM   wip_flow_schedules fs
715       WHERE  fs.schedule_group_id = schedule_group_rec.schedule_group
716         AND  fs.line_id = p_line_id
717         AND  fs.organization_id = p_org_id
718         AND  scheduled_flag = C_YES;
719 
720       V_ERROR_LINE := 2;
721 
722     ELSE
723 
724       SELECT NVL(MAX(build_sequence),0)
725       INTO   v_null_build_seq
726       FROM   wip_flow_schedules fs
727       WHERE  fs.schedule_group_id IS NULL
728 	AND  fs.line_id = p_line_id
729 	AND  fs.organization_id = p_org_id
730         AND  scheduled_flag = C_YES;
731 
732       V_ERROR_LINE := 3;
733 
734     END IF;
735   END LOOP;
736 
737 EXCEPTION
738   WHEN NO_DATA_FOUND THEN
739     RETURN;
740 
741   WHEN OTHERS THEN
742 
743     IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
744       FND_MSG_PUB.Add_Exc_Msg(
745 	V_PKG_NAME,V_PROCEDURE_NAME||': Line '||to_char(V_ERROR_LINE));
746     END IF;
747 
748     return;
749 
750 END calculate_build_sequences;
751 
752 -- This procedure time stamps all existing flow schedules on the line for all valid
753 -- days within the scheduling window before scheduling new flow schedules on the line.
754 
755 PROCEDURE time_existing_fs(
756 				p_org_id  IN NUMBER,
757 				p_line_id IN NUMBER,
758                                 p_schedule_start_date IN NUMBER,
759                                 p_schedule_start_time IN NUMBER,
760                                 p_schedule_end_date IN NUMBER,
761                                 p_schedule_end_time IN NUMBER,
762 				p_time_tab IN OUT NOCOPY TimeTabTyp)
763 IS
764 
765 /* Performance fix for Bug No #2720049
766 Description : Changed the sql so that index on calendar_date could be used. */
767 
768   CURSOR valid_dates(l_cal_code IN VARCHAR2, l_excep_code IN NUMBER,
769   l_schedule_start_date IN NUMBER, l_schedule_end_date IN NUMBER) IS
770     SELECT to_number(to_char(bom_cal.calendar_date,'J')) workday
771     FROM   bom_calendar_dates bom_cal
772     WHERE  bom_cal.calendar_code = l_cal_code
773     AND    bom_cal.exception_set_id = l_excep_code
774     AND    bom_cal.calendar_date between to_date(l_schedule_start_date,'j') and
775 	   to_date(l_schedule_end_date,'j')
776 --  AND    to_number(to_char(bom_cal.calendar_date,'J'))
777 --               between l_schedule_start_date and l_schedule_end_date
778     AND    bom_cal.seq_num is NOT NULL
779     ORDER BY bom_cal.calendar_date;
780 
781   v_date		NUMBER;
782   v_hr_line_rate	NUMBER;
783   v_line_rate		NUMBER;
784   v_start_time		NUMBER;
785   v_end_time		NUMBER;
786   v_required_time 	NUMBER;
787   v_begin_time		DATE;
788   v_completion_time	DATE;
789   v_final_time		NUMBER;
790   l_fixed_lead_time	NUMBER;
791   l_variable_lead_time	NUMBER;
792   l_lead_time		NUMBER;
793   l_cal_code    VARCHAR2(10);
794   l_excep_code  NUMBER;
795   l_last_comp_time	NUMBER;
796   l_last_comp_date	DATE;
797   l_user_start_time	NUMBER;
798   l_sec			NUMBER;
799   l_schedule_start_time	NUMBER;
800   l_schedule_start_date	NUMBER;
801 
802 BEGIN
803 
804   V_PROCEDURE_NAME := 'Time_Existing_fs';
805   V_ERROR_LINE := 1;
806 
807   l_schedule_start_date := p_schedule_start_date;
808   l_schedule_start_time := p_schedule_start_time;
809 
810   -- Obtain information on the hourly line rate, start time and end time of the line.
811 
812   SELECT maximum_rate, start_time, stop_time
813   INTO   v_hr_line_rate, v_start_time, v_end_time
814   FROM   wip_lines
815   WHERE  line_id = p_line_id
816     AND  organization_id = p_org_id;
817 
818   V_ERROR_LINE := 2;
819 
820   -- The line rate per day is the hourly line rate multiplied by the number of hours
821   -- in a day.
822 
823   -- Fix bug 939061, add 24 hrs to stop_time if stop_time <= start_time
824   if (v_end_time <= v_start_time) then
825     if (p_schedule_start_time < v_end_time ) then
826       l_schedule_start_date := l_schedule_start_date - 1;
827       l_schedule_start_time := l_schedule_start_time + 24*3600;
828     end if;
829     v_end_time := v_end_time + 24*3600;
830   end if;
831 
832   SELECT calendar_code,calendar_exception_set_id
833   INTO   l_cal_code,l_excep_code
834   FROM   mtl_parameters
835   WHERE  organization_id = p_org_id;
836 
837   FOR valid_dates_rec IN valid_dates(l_cal_code,l_excep_code,
838         l_schedule_start_date,p_schedule_end_date) LOOP
839 
840     v_date := valid_dates_rec.workday;
841 
842     -- The value of v_end_time can be one of the following :
843     -- 1. line_end_time if the date is not schedule end date
844     -- 2. if the date is schedule end date :
845     --    a. schedule_end_time if schedule_end_time in between line start and stop time
846     --    b. line start time if schedule_end_time is smaller than line start time
847     --    c. line end time if schedule_end_time is higher than line start time
848     if (v_date = p_schedule_end_date) then
849       if (p_schedule_end_time < v_end_time and p_schedule_end_time > v_start_time) then
850         v_end_time := p_schedule_end_time;
851       elsif (p_schedule_end_time < v_start_time) then
852         v_end_time := v_start_time;
853       end if;
854     end if;
855     v_line_rate := TRUNC(v_hr_line_rate * (v_end_time - v_start_time)/3600);
856 
857     SELECT max(scheduled_completion_date)
858     INTO l_last_comp_date
859     FROM wip_flow_schedules
860     WHERE scheduled_completion_date >= to_date(v_date,'J')+v_start_time/86400
861       AND scheduled_completion_date <= to_date(v_date,'J')+v_end_time/86400
862       AND line_id = p_line_id
863       AND organization_id = p_org_id
864       AND scheduled_flag = C_YES;
865 
866     if (l_last_comp_date IS NOT NULL) then
867       l_last_comp_time := to_char(l_last_comp_date,'SSSSS');
868       if (trunc(l_last_comp_date) > to_date(v_date,'J')) then
869         l_last_comp_time := l_last_comp_time + 24*3600;
870       end if;
871       if l_last_comp_time < v_start_time then
872         l_last_comp_time := v_start_time;
873       end if;
874     else
875       l_last_comp_time := v_start_time;
876     end if;
877 
878     if (v_date = l_schedule_start_date) then
879       if (l_schedule_start_time > v_end_time) then
880         l_last_comp_time := v_end_time;
881       elsif (l_schedule_start_time > l_last_comp_time) then
882         l_sec := 3600/v_hr_line_rate; -- Time to produce 1 qty in seconds
883         l_last_comp_time := v_start_time+
884           ceil((l_schedule_start_time-v_start_time)/l_sec) * l_sec;
885         l_last_comp_time := l_last_comp_time - l_sec;
886       end if;
887     end if;
888 
889     p_time_tab(v_date).start_completion_time := l_last_comp_time;
890     p_time_tab(v_date).end_completion_time := v_end_time;
891 
892   END LOOP;
893 
894 EXCEPTION
895   WHEN NO_DATA_FOUND THEN
896     RETURN;
897 
898   WHEN OTHERS THEN
899 
900     IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
901       FND_MSG_PUB.Add_Exc_Msg(
902 	V_PKG_NAME,V_PROCEDURE_NAME||': Line '||to_char(V_ERROR_LINE));
903     END IF;
904 
905     return;
906 END time_existing_fs;
907 
908 -- This procedure calculates the total demand for each item and populates these
909 -- values into the PL/SQL table.  The procedure also calculates the global demand
910 -- across all items and populates this value into the pl/sql table.  The table also
911 -- contains the round type of the item.
912 
913 PROCEDURE calculate_demand(
914 				    p_line_id IN NUMBER,
915 				    p_org_id IN NUMBER,
916 				    p_demand_tab IN OUT NOCOPY DemandTabTyp)
917 IS
918 
919 -- Define Variables and Cursors
920 
921   v_demand_total 	NUMBER;
922 
923 BEGIN
924 
925   V_PROCEDURE_NAME := 'Calculate_Demand';
926   V_ERROR_LINE := 1;
927 
928   -- Calculate total demand for each item and populate into PS/SQL table indexed
929   -- by the item id.  Also, calculate the global demand across all items.
930 
931   v_demand_total := 0;
932 
933   FOR item_list_rec IN item_list(p_org_id) LOOP
934 
935     -- Find the round type of the item and populate into table.
936 
937     SELECT NVL(rounding_control_type,2)
938     INTO   p_demand_tab(item_list_rec.primary_item_id).roundType
939     FROM   mtl_system_items
940     WHERE  inventory_item_id = item_list_rec.primary_item_id
941     AND    organization_id = p_org_id;
942 
943     V_ERROR_LINE := 2;
944 
945     p_demand_tab(item_list_rec.primary_item_id).sequence := 0;
946 
947 --   For each item, calculate the total demand from flow schedules to be scheduled.
948 
949     SELECT NVL(SUM(NVL(planned_quantity,0)
950                 -NVL(quantity_completed,0)),0)
951     INTO   p_demand_tab(item_list_rec.primary_item_id).totalDemand
952     FROM   wip_flow_schedules fs
953     WHERE  fs.request_id = USERENV('SESSIONID')
954       AND  fs.primary_item_id = item_list_rec.primary_item_id
955       AND  fs.line_id = p_line_id
956       AND  fs.organization_id = p_org_id
957       AND  fs.scheduled_flag = C_NO
958       AND  wip_entity_id >= G_WIP_ENTITY_ID;
959 
960     V_ERROR_LINE := 3;
961 
962     v_demand_total := v_demand_total +
963 	p_demand_tab(item_list_rec.primary_item_id).totalDemand;
964 
965   END LOOP;
966 
967   V_GLOBAL_DEMAND := v_demand_total;
968 
969 EXCEPTION
970   WHEN NO_DATA_FOUND THEN
971     RETURN;
972   WHEN OTHERS THEN
973 
974     IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
975       FND_MSG_PUB.Add_Exc_Msg(
976 	V_PKG_NAME,V_PROCEDURE_NAME||': Line '||to_char(V_ERROR_LINE));
977     END IF;
978 
979 END calculate_demand;
980 
981 -- This procedure calculates the total demand for each item and populates this
982 -- information into a pl/sql table ordered by the value of the demand.
983 
984 PROCEDURE calculate_demand_mix (
985 				    p_line_id IN NUMBER,
986 				    p_org_id IN NUMBER,
987 				    p_item_demand_tab IN OUT NOCOPY ItemDemandTabTyp)
988 IS
989 
990 -- Define Variables and Cursors
991   v_item_id	    	NUMBER;
992   v_quantity		NUMBER;
993   v_fixed_lead_time	NUMBER;
994   v_var_lead_time	NUMBER;
995   i			NUMBER;
996 
997   CURSOR item_demand_cursor IS
998     SELECT primary_item_id, SUM(TRUNC(NVL(planned_quantity,0)
999                -NVL(quantity_completed,0)-0.00000001)+1) quantity
1000     FROM   wip_flow_schedules fs
1001     WHERE  fs.request_id = USERENV('SESSIONID')
1002       AND  fs.line_id = p_line_id
1003       AND  fs.organization_id = p_org_id
1004       AND  fs.scheduled_flag = C_NO
1005       AND  wip_entity_id >= G_WIP_ENTITY_ID
1006     GROUP BY primary_item_id
1007     ORDER BY quantity;
1008 
1009 BEGIN
1010 
1011   V_PROCEDURE_NAME := 'Calculate_Demand_Mix';
1012   V_ERROR_LINE := 1;
1013 
1014   -- Calculate total demand for each item and populate into PS/SQL table.
1015   -- Populate the item column and the demand column for the item.
1016 
1017   i := 1;
1018 
1019   OPEN item_demand_cursor;
1020   LOOP
1021 
1022     FETCH item_demand_cursor INTO v_item_id, v_quantity;
1023     EXIT WHEN item_demand_cursor%NOTFOUND;
1024 
1025     SELECT NVL(fixed_lead_time, 0), NVL(variable_lead_time, 0)
1026     INTO   v_fixed_lead_time, v_var_lead_time
1027     FROM   MTL_SYSTEM_ITEMS
1028     WHERE  inventory_item_id = v_item_id
1029     AND    organization_id = p_org_id;
1030 
1031     p_item_demand_tab(i).item := v_item_id;
1032 
1033     p_item_demand_tab(i).qty := v_quantity;
1034 
1035     p_item_demand_tab(i).fixed_lead_time := v_fixed_lead_time;
1036 
1037     p_item_demand_tab(i).var_lead_time := v_var_lead_time;
1038 
1039     i := i + 1;
1040 
1041   END LOOP;
1042   CLOSE item_demand_cursor;
1043 
1044 EXCEPTION
1045   WHEN NO_DATA_FOUND THEN
1046     RETURN;
1047   WHEN OTHERS THEN
1048     IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
1049       FND_MSG_PUB.Add_Exc_Msg(
1050 	V_PKG_NAME,V_PROCEDURE_NAME||': Line '||to_char(V_ERROR_LINE));
1051     END IF;
1052 
1053 END calculate_demand_mix;
1054 
1055 -- This procedure establishes the manufacturing pattern for the mix model
1056 -- scheduling algorithm.
1057 
1058 FUNCTION mix_model (
1059 			p_item_demand_tab IN ItemDemandTabTyp) RETURN LONG
1060 IS
1061 
1062 -- Define Variables and Cursors
1063   mmm_tab1  ItemDemandTabTyp;
1064   mmm_tab2  ItemDemandTabTyp;
1065   curr_total_pattern  long;
1066   final_total_pattern  long;
1067   tmp_total_pattern  long;
1068   num_pos Number := -1;
1069   new_num_pos Number;
1070   curr_pos Number;
1071   occur_num Number;
1072   curr_sub_cnt Number ;
1073   tmp_cnt Number;
1074   curr_qty Number;
1075   curr_ind_qty Number;
1076   curr_ind Number :=1;
1077   next_ind Number;
1078 
1079 BEGIN
1080 
1081   V_PROCEDURE_NAME := 'mix_model';
1082 
1083   mmm_tab1 := p_item_demand_tab;
1084 
1085   FOR i in 1..mmm_tab1.COUNT Loop
1086     mmm_tab2(i).item := mmm_tab1(i).item;
1087 --    dbms_output.put_line('The index is: '||to_char(i));
1088 --    dbms_output.put_line('The item is: '||to_char(mmm_tab2(i).item));
1089     mmm_tab2(i).qty := mmm_tab1(i).qty;
1090 --    dbms_output.put_line(mmm_tab2(i).qty);
1091 
1092   END LOOP;
1093 
1094 /*  FOR i in 1..3 Loop
1095     mmm_tab2(i).item := i;
1096     mmm_tab2(i).qty := 10;
1097   END LOOP;
1098   mmm_tab2(4).item := 4;
1099     mmm_tab2(4).qty := 30;*/
1100   Loop
1101    declare
1102     curr_pat_tab pat_tab_type;
1103     curr_pattern  long;
1104     curr_sub_pattern  long;
1105    BEGIN
1106 --      dbms_output.put_line('curr_pat_tab count: '||to_char(curr_pat_tab.COUNT));
1107 --      dbms_output.put_line('curr_ind: '||to_char(curr_ind));
1108 --      dbms_output.put_line('mmm_tab2 count: '||to_char(mmm_tab2.COUNT));
1109      curr_pattern := null;
1110      curr_sub_pattern := null;
1111      for i in REVERSE curr_ind..mmm_tab2.COUNT LOOP
1112        if (i <> curr_ind ) then
1113          curr_sub_pattern := curr_sub_pattern || to_char(i)|| '*';
1114        else
1115          curr_sub_pattern := curr_sub_pattern || to_char(i);
1116        end if;
1117      end loop;
1118 --      dbms_output.put_line('curr_sub_pattern: '||curr_sub_pattern);
1119      if (num_pos = -1 ) then
1120         curr_pat_tab(1).curr_pattern := curr_sub_pattern;
1121         num_pos := 1;
1122         FOR i in 1..mmm_tab2(curr_ind).qty Loop
1123           curr_total_pattern := curr_total_pattern || '*-'||curr_sub_pattern ;
1124           num_pos := num_pos +1;
1125         end loop;
1126         curr_total_pattern := curr_total_pattern || '*-' ;
1127 --        dbms_output.put_line('initial curr_total_pattern: '||curr_total_pattern);
1128 --       dbms_output.put_line('initial num_pos: '||to_char(num_pos));
1129      else
1130 --     dbms_output.put_line('curr_qty: '||to_char(mmm_tab2(curr_ind).qty));
1131         if (mmm_tab2(curr_ind).qty > num_pos) then
1132 
1133           curr_qty := mmm_tab2(curr_ind).qty;
1134           tmp_cnt := 1;
1135           Loop
1136            curr_sub_cnt := ceil(curr_qty / (num_pos-tmp_cnt+1));
1137 --        dbms_output.put_line('i am here '||to_char(curr_sub_cnt));
1138            curr_pattern:=null;
1139            FOR i in 1..curr_sub_cnt Loop
1140               if (curr_pattern is null) then
1141                  curr_pattern := curr_sub_pattern;
1142               else
1143                  curr_pattern := curr_pattern ||'*'|| curr_sub_pattern;
1144               end if;
1145            end loop;
1146 --        dbms_output.put_line('i am here curr_pattern '||curr_pattern);
1147            curr_pat_tab(tmp_cnt).curr_pattern := curr_pattern;
1148            curr_qty := curr_qty - curr_sub_cnt;
1149            exit when curr_qty <= 0;
1150            tmp_cnt := tmp_cnt +1;
1151           end Loop;
1152         elsif (mmm_tab2(curr_ind).qty < num_pos) then
1153          -- need to choose positions
1154            FOR i in 1..mmm_tab2(curr_ind).qty Loop
1155              curr_pat_tab(i).curr_pattern := curr_sub_pattern;
1156            end loop;
1157         else
1158            FOR i in 1..mmm_tab2(curr_ind).qty Loop
1159              curr_pat_tab(i).curr_pattern := curr_sub_pattern;
1160            end loop;
1161         end if;
1162        -- insert strings into positions
1163         occur_num := 1;
1164         new_num_pos := num_pos;
1165 --      dbms_output.put_line('mid curr_pat_tab count: '||to_char(curr_pat_tab.COUNT));
1166 
1167         For i in 1..curr_pat_tab.COUNT Loop
1168           curr_pos := instr(curr_total_pattern,'-',1,occur_num);
1169 --    dbms_output.put_line('in loop curr_pattern: '||curr_pat_tab(i).curr_pattern);
1170           curr_total_pattern := substr(curr_total_pattern,1,curr_pos) || curr_pat_tab(i).curr_pattern || '*'||substr(curr_total_pattern,curr_pos);
1171 --    dbms_output.put_line('curr_total_pattern: '||curr_total_pattern);
1172 --    dbms_output.put_line('tmp_total_pattern: '||tmp_total_pattern);
1173           new_num_pos := new_num_pos +1;
1174           num_pos := new_num_pos;
1175           occur_num := occur_num +2;
1176          /*  if (occur_num > num_pos) then
1177 --            dbms_output.put_line('error condition ');
1178             exit;
1179           end if; */
1180         end Loop;
1181         -- curr_total_pattern := tmp_total_pattern;
1182 --   dbms_output.put_line('final curr_total_pattern: '||curr_total_pattern);
1183         num_pos := new_num_pos;
1184 --      dbms_output.put_line('new num_pos: '||to_char(num_pos));
1185         -- curr_pat_tab :=  NULL;
1186      end if;
1187 --      dbms_output.put_line('i am here curr_pattern: '||curr_pattern);
1188      next_ind := null;
1189      curr_ind_qty := mmm_tab2(curr_ind).qty;
1190      For i in 1..mmm_tab2.COUNT Loop
1191 --      dbms_output.put_line('i am here22 curr_pattern: '||curr_pattern);
1192        mmm_tab2(i).qty :=mmm_tab2(i).qty - curr_ind_qty;
1193        if (mmm_tab2(i).qty > 0 and next_ind is null) then
1194          next_ind := i;
1195        end if;
1196      end loop;
1197      exit when next_ind is null;
1198      curr_ind := next_ind;
1199 --      dbms_output.put_line('next_ind: '||to_char(next_ind));
1200 --      dbms_output.put_line(' ENDcurr_pat_tab count: '||to_char(curr_pat_tab.COUNT));
1201    END;
1202   END Loop;
1203   final_total_pattern := replace(curr_total_pattern,'-');
1204 --  dbms_output.put_line('The pattern in mix model: '||final_total_pattern);
1205 
1206   tmp_cnt :=  ceil(length(curr_total_pattern) / 255);
1207 --   for i in 1..tmp_cnt Loop
1208 --    dbms_output.put_line(substr(curr_total_pattern,255*(i-1),255));
1209 --  end loop;
1210 --  dbms_output.put_line('length: '||to_char(length(curr_total_pattern)));
1211 --  dbms_output.put_line('actual length: '||to_char(length(replace(replace(curr_total_pattern,'-'),'*'))));
1212 
1213 --  dbms_output.put_line('FINAL PATTERN:');
1214 --  tmp_cnt :=  ceil(length(final_total_pattern) / 255);
1215 --  for i in 1..tmp_cnt Loop
1216 --    dbms_output.put_line(substr(final_total_pattern,255*(i-1),255));
1217 --  end loop;
1218 --  dbms_output.put_line('The pattern in mix model: '||final_total_pattern);
1219 
1220   RETURN final_total_pattern;
1221 
1222 EXCEPTION
1223   WHEN NO_DATA_FOUND THEN
1224     RETURN NULL;
1225   WHEN OTHERS THEN
1226 
1227     IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
1228       FND_MSG_PUB.Add_Exc_Msg(V_PKG_NAME, V_PROCEDURE_NAME);
1229     END IF;
1230 
1231 END mix_model;
1232 
1233 -- This procedure converts flow schedules of type planned order into new flow
1234 -- schedules that respect the order modifiers of the items.  After the conversion,
1235 -- the flow schedules can be scheduled on the line.
1236 
1237 PROCEDURE create_po_fs(
1238 				p_org_id  IN NUMBER,
1239 				p_line_id IN NUMBER,
1240 				p_rule_id IN NUMBER,
1241 				p_orderMod_tab IN OUT NOCOPY OrderModTabTyp)
1242 
1243 IS
1244 
1245   v_order_quantity	NUMBER;
1246   v_temp		NUMBER;
1247   v_num_flow		NUMBER;
1248   v_itemQty_tab		ItemQtyTabTyp;
1249   fs_select_rec	fs_select_type;
1250   cursor_name           INTEGER;
1251   v_last_wip		NUMBER;
1252   v_schedule_number	VARCHAR2(30);
1253   to_schedule_qty	NUMBER;
1254   v_planned_quantity	NUMBER;
1255 
1256 BEGIN
1257 
1258   V_PROCEDURE_NAME := 'Create_Po_Fs';
1259   V_ERROR_LINE := 1;
1260 
1261   cursor_name := Create_Cursor(p_rule_id,p_org_id,p_line_id,C_ASC,C_NORM,C_NORM);
1262 
1263 --  dbms_output.put_line('Looping through each planned order flow schedule
1264 --  and creating new flow schedules with order modifier quantities.');
1265 
1266   LOOP
1267     if dbms_sql.fetch_rows(cursor_name) > 0 then
1268        dbms_sql.column_value(cursor_name,1, fs_select_rec.wip_entity);
1269        dbms_sql.column_value(cursor_name,7, fs_select_rec.primary_item_id);
1270        dbms_sql.column_value(cursor_name,8, fs_select_rec.planned_quantity);
1271        dbms_sql.column_value(cursor_name,9, fs_select_rec.schedule_group_id);
1272     end if;
1273 
1274     IF v_last_wip = fs_select_rec.wip_entity THEN
1275       EXIT;
1276     END IF;
1277 
1278     v_last_wip := fs_select_rec.wip_entity;
1279 
1280 --    dbms_output.put_line('Current flow schedule is: '||
1281 --    to_char(fs_select_rec.wip_entity));
1282 --    dbms_output.put_line('Current item is: '||
1283 --    to_char(fs_select_rec.primary_item_id));
1284 
1285     -- Check the item quantity table to see what the remaining quantity of the
1286     -- newest flow schedule is.  If the remaining quantity is greater than the
1287     -- quantity we are trying to schedule,then leave the flow schedule as is.
1288 
1289     -- If the remaining quantity is less than the quantity we need to
1290     -- schedule, then split the flow schedule into multiple flow schedules
1291     -- to correspond to the original flow schedule.
1292     -- Update the item quantity table.
1293 
1294     IF v_itemQty_tab.EXISTS(fs_select_rec.primary_item_id) = FALSE THEN
1295       v_itemQty_tab(fs_select_rec.primary_item_id).remainQty := 0;
1296     END IF;
1297 
1298 --  dbms_output.put_line('Remain Qty in ItemQty table is '||to_char
1299 --    (v_itemQty_tab(fs_select_rec.primary_item_id).remainQty));
1300 
1301 --  dbms_output.put_line('Planned quantity is '||
1302 --	to_char(fs_select_rec.planned_quantity));
1303 
1304     IF v_itemQty_tab(fs_select_rec.primary_item_id).remainQty >=
1305 		fs_select_rec.planned_quantity THEN
1306 
1307       v_itemQty_tab(fs_select_rec.primary_item_id).remainQty :=
1308         v_itemQty_tab(fs_select_rec.primary_item_id).remainQty - fs_select_rec.planned_quantity;
1309 
1310 --    dbms_output.put_line('Enough quantity remaining for allocation...');
1311 --    dbms_output.put_line('Remaining quantity = '||
1312 --	to_char(v_itemQty_tab(fs_select_rec.primary_item_id).remainQty));
1313 
1314     ELSIF v_itemQty_tab(fs_select_rec.primary_item_id).remainQty <
1315 		fs_select_rec.planned_quantity THEN
1316 --      dbms_output.put_line('NOT enough quantity remaining for allocation.');
1317 
1318       IF  p_orderMod_tab(fs_select_rec.primary_item_id).minVal = 0 AND
1319 	p_orderMod_tab(fs_select_rec.primary_item_id).maxVal = 0 THEN
1320 
1321 --	dbms_output.put_line('no meaningful values for min and max values!!');
1322 --	dbms_output.put_line('Order quantity = planned quantity');
1323 
1324 	v_order_quantity := fs_select_rec.planned_quantity;
1325 
1326       ELSIF p_orderMod_tab(fs_select_rec.primary_item_id).minVal > 0 THEN
1327 
1328 --	dbms_output.put_line('minimum value exists and = order quantity!!');
1329 
1330 	v_order_quantity := p_orderMod_tab(fs_select_rec.primary_item_id).minVal;
1331 
1332 	-- We need to find a way to include the maximum in the future.
1333       END IF;
1334 
1335       V_ERROR_LINE := 2;
1336 
1337       SELECT TRUNC((fs_select_rec.planned_quantity -
1338 		v_itemQty_tab(fs_select_rec.primary_item_id).remainQty)/
1339 	v_order_quantity-0.000000001)+1
1340       INTO v_num_flow
1341       FROM DUAL;
1342 
1343       V_ERROR_LINE := 3;
1344 
1345       UPDATE wip_flow_schedules
1346       SET    planned_quantity =
1347 		v_itemQty_tab(fs_select_rec.primary_item_id).remainQty
1348       WHERE  wip_entity_id = fs_select_rec.wip_entity
1349       AND    organization_id = p_org_id;
1350 
1351       V_ERROR_LINE := 4;
1352 
1353 --      dbms_output.put_line('We need to create this number of new flow schedules:'
1354 --	||v_num_flow);
1355 
1356       to_schedule_qty := fs_select_rec.planned_quantity -
1357 	v_itemQty_tab(fs_select_rec.primary_item_id).remainQty;
1358 
1359       FOR i IN 1..v_num_flow LOOP
1360 
1361         -- Create a new flow schedule to carry over the unscheduled quantity
1362         SELECT wip_entities_s.nextval
1363         INTO   v_temp
1364         FROM   dual;
1365 
1366         V_ERROR_LINE := 5;
1367 
1368 	IF to_schedule_qty >= v_order_quantity THEN
1369           v_planned_quantity := v_order_quantity;
1370  	ELSE
1371 	  v_planned_quantity := to_schedule_qty;
1372   	END IF;
1373 
1374         --Bug 6122344
1375         --v_schedule_number := NVL(substr(FND_PROFILE.value('WIP_JOB_PREFIX'),1,20),'X')
1376 	--		|| to_char(v_temp);
1377         v_schedule_number := 'FLM-INTERNAL'|| to_char(v_temp);
1378 
1379 	INSERT INTO wip_flow_schedules(
1380 				scheduled_flag,
1381 				wip_entity_id,
1382 				organization_id,
1383 				last_update_date,
1384 				last_updated_by,
1385 				creation_date,
1386 				created_by,
1387 				class_code,
1388 				line_id,
1389 				primary_item_id,
1390 				scheduled_start_date,
1391 				planned_quantity,
1392 				quantity_completed,
1393 				quantity_scrapped,
1394 				scheduled_completion_date,
1395 				schedule_group_id,
1396 				status,
1397 				schedule_number,
1398 				demand_source_header_id,
1399 				demand_source_line,
1400 				demand_source_delivery,
1401 				demand_source_type,
1402 				project_id,
1403 				task_id,
1404 				end_item_unit_number,
1405                                 request_id,
1406                                 attribute1,
1407                                 attribute2,
1408                                 attribute3,
1409                                 attribute4,
1410                                 attribute5,
1411                                 attribute6,
1412                                 attribute7,
1413                                 attribute8,
1414                                 attribute9,
1415                                 attribute10,
1416                                 attribute11,
1417                                 attribute12,
1418                                 attribute13,
1419                                 attribute14,
1420                                 attribute15,
1421                                 material_account,
1422                                 material_overhead_account,
1423                                 resource_account,
1424                                 outside_processing_account,
1425                                 material_variance_account,
1426                                 resource_variance_account,
1427                                 outside_proc_variance_account,
1428                                 std_cost_adjustment_account,
1429                                 overhead_account,
1430                                 overhead_variance_account,
1431                                 bom_revision,      /* Added for bug 2185087 */
1432                                 routing_revision,
1433                                 bom_revision_date,
1434                                 routing_revision_date,
1435                                 alternate_bom_designator,
1436                                 alternate_routing_designator,
1437                                 completion_subinventory,
1438                                 completion_locator_id,
1439                                 demand_class,
1440                                 attribute_category,
1441                                 kanban_card_id)
1442 	SELECT		   	C_NO,
1443 				v_temp,
1444 				p_org_id,
1445 				SYSDATE,
1446 				fs.last_updated_by,
1447 				SYSDATE,
1448 				fs.created_by,
1449 				fs.class_code,
1450 				fs.line_id,
1451 				fs.primary_item_id,
1452 				fs.scheduled_completion_date,
1453 				v_planned_quantity,
1454 				0,
1455 				0,
1456 				fs.scheduled_completion_date,
1457 				fs.schedule_group_id,
1458 				fs.status,
1459 				v_schedule_number,
1460 				fs.demand_source_header_id,
1461 			       	fs.demand_source_line,
1462 			     	fs.demand_source_delivery,
1463 				fs.demand_source_type,
1464 				fs.project_id,
1465 				fs.task_id,
1466 				fs.end_item_unit_number,
1467                                 USERENV('SESSIONID'),
1468                                 fs.attribute1,
1469                                 fs.attribute2,
1470                                 fs.attribute3,
1471                                 fs.attribute4,
1472                                 fs.attribute5,
1473                                 fs.attribute6,
1474                                 fs.attribute7,
1475                                 fs.attribute8,
1476                                 fs.attribute9,
1477                                 fs.attribute10,
1478                                 fs.attribute11,
1479                                 fs.attribute12,
1480                                 fs.attribute13,
1481                                 fs.attribute14,
1482                                 fs.attribute15,
1483                                 fs.material_account,
1484                                 fs.material_overhead_account,
1485                                 fs.resource_account,
1486                                 fs.outside_processing_account,
1487                                 fs.material_variance_account,
1488                                 fs.resource_variance_account,
1489                                 fs.outside_proc_variance_account,
1490                                 fs.std_cost_adjustment_account,
1491                                 fs.overhead_account,
1492                                 fs.overhead_variance_account,
1493                                 fs.bom_revision,      /* Added for bug 2185087 */
1494                                 fs.routing_revision,
1495                                 fs.bom_revision_date,
1496                                 fs.routing_revision_date,
1497                                 fs.alternate_bom_designator,
1498                                 fs.alternate_routing_designator,
1499                                 fs.completion_subinventory,
1500                                 fs.completion_locator_id,
1501                                 fs.demand_class,
1502                                 fs.attribute_category,
1503                                 fs.kanban_card_id
1504 	FROM  wip_flow_schedules fs
1505 	WHERE fs.wip_entity_id = fs_select_rec.wip_entity
1506 	AND   line_id = p_line_id
1507         AND organization_id = p_org_id;
1508 
1509 	V_ERROR_LINE := 6;
1510 
1511 	to_schedule_qty := to_schedule_qty - v_planned_quantity;
1512 
1513 --	dbms_output.put_line('Number '||to_char(i)||'flow schedule created!!!');
1514 --	dbms_output.put_line('Planned quantity = '||to_char(v_planned_quantity));
1515 
1516       END LOOP;
1517 
1518       -- Calculate the remaining quantity that can be scheduled in the newest
1519       -- flow schedule for the item.
1520 
1521       v_itemQty_tab(fs_select_rec.primary_item_id).remainQty :=
1522 	v_order_quantity - v_planned_quantity;
1523 
1524       v_itemQty_tab(fs_select_rec.primary_item_id).wip_id := fs_select_rec.wip_entity;
1525 
1526 --      dbms_output.put_line('Remain quantity is:'||
1527 --		to_char(v_itemQty_tab(fs_select_rec.primary_item_id).remainQty));
1528 
1529     END IF;
1530   END LOOP;
1531 
1532   FOR item_list_rec IN item_list(p_org_id) LOOP
1533     IF v_itemQty_tab(item_list_rec.primary_item_id).remainQty > 0 THEN
1534 
1535       V_ERROR_LINE := 7;
1536 
1537       SELECT wip_entities_s.nextval
1538       INTO   v_temp
1539       FROM   dual;
1540 
1541       V_ERROR_LINE := 8;
1542 
1543       --Bug 6122344
1544       --v_schedule_number := NVL(substr(FND_PROFILE.value('WIP_JOB_PREFIX'),1,20),'X')
1545       --		|| to_char(v_temp);
1546       v_schedule_number := 'FLM-INTERNAL'|| to_char(v_temp);
1547 
1548       INSERT INTO wip_flow_schedules(
1549 				scheduled_flag,
1550 				wip_entity_id,
1551 				organization_id,
1552 				last_update_date,
1553 				last_updated_by,
1554 				creation_date,
1555 				created_by,
1556 				class_code,
1557 				line_id,
1558 				primary_item_id,
1559 				scheduled_start_date,
1560 				planned_quantity,
1561 				quantity_completed,
1562 				quantity_scrapped,
1563 				scheduled_completion_date,
1564 				schedule_group_id,
1565 				status,
1566 				schedule_number,
1567 				demand_source_header_id,
1568 				demand_source_line,
1569 				demand_source_delivery,
1570 				demand_source_type,
1571 				project_id,
1572 				task_id,
1573 				end_item_unit_number,
1574                                 request_id,
1575                                 attribute1,
1576                                 attribute2,
1577                                 attribute3,
1578                                 attribute4,
1579                                 attribute5,
1580                                 attribute6,
1581                                 attribute7,
1582                                 attribute8,
1583                                 attribute9,
1584                                 attribute10,
1585                                 attribute11,
1586                                 attribute12,
1587                                 attribute13,
1588                                 attribute14,
1589                                 attribute15,
1590                                 material_account,
1591                                 material_overhead_account,
1592                                 resource_account,
1593                                 outside_processing_account,
1594                                 material_variance_account,
1595                                 resource_variance_account,
1596                                 outside_proc_variance_account,
1597                                 std_cost_adjustment_account,
1598                                 overhead_account,
1599                                 overhead_variance_account,
1600                                 bom_revision,  /* Added for bug 2185087 */
1601                                 routing_revision,
1602                                 bom_revision_date,
1603                                 routing_revision_date,
1604                                 alternate_bom_designator,
1605                                 alternate_routing_designator,
1606                                 completion_subinventory,
1607                                 completion_locator_id,
1608                                 demand_class,
1609                                 attribute_category,
1610                                 kanban_card_id)
1611 
1612 
1613       SELECT		   	C_NO,
1614 				v_temp,
1615 				p_org_id,
1616 				SYSDATE,
1617 				fs.last_updated_by,
1618 				SYSDATE,
1619 				fs.created_by,
1620 				fs.class_code,
1621 				fs.line_id,
1622 				fs.primary_item_id,
1623 				fs.scheduled_completion_date,
1624 				v_itemQty_tab(item_list_rec.primary_item_id).remainQty,
1625 				0,
1626 				0,
1627 				fs.scheduled_completion_date,
1628 				fs.schedule_group_id,
1629 				fs.status,
1630 				v_schedule_number,
1631 				fs.demand_source_header_id,
1632 			       	fs.demand_source_line,
1633 			     	fs.demand_source_delivery,
1634 				fs.demand_source_type,
1635 				fs.project_id,
1636 				fs.task_id,
1637 				fs.end_item_unit_number,
1638                                 USERENV('SESSIONID'),
1639                                 fs.attribute1,
1640                                 fs.attribute2,
1641                                 fs.attribute3,
1642                                 fs.attribute4,
1643                                 fs.attribute5,
1644                                 fs.attribute6,
1645                                 fs.attribute7,
1646                                 fs.attribute8,
1647                                 fs.attribute9,
1648                                 fs.attribute10,
1649                                 fs.attribute11,
1650                                 fs.attribute12,
1651                                 fs.attribute13,
1652                                 fs.attribute14,
1653                                 fs.attribute15,
1654                                 fs.material_account,
1655                                 fs.material_overhead_account,
1656                                 fs.resource_account,
1657                                 fs.outside_processing_account,
1658                                 fs.material_variance_account,
1659                                 fs.resource_variance_account,
1660                                 fs.outside_proc_variance_account,
1661                                 fs.std_cost_adjustment_account,
1662                                 fs.overhead_account,
1663                                 fs.overhead_variance_account,
1664                                 fs.bom_revision,    /* Added for bug 2185087 */
1665                                 fs.routing_revision,
1666                                 fs.bom_revision_date,
1667                                 fs.routing_revision_date,
1668                                 fs.alternate_bom_designator,
1669                                 fs.alternate_routing_designator,
1670                                 fs.completion_subinventory,
1671                                 fs.completion_locator_id,
1672                                 fs.demand_class,
1673                                 fs.attribute_category,
1674                                 fs.kanban_card_id
1675       FROM  wip_flow_schedules fs
1676       WHERE fs.wip_entity_id = v_itemQty_tab(item_list_rec.primary_item_id).wip_id
1677       AND   line_id = p_line_id
1678       AND   organization_id = p_org_id;
1679 
1680       V_ERROR_LINE := 9;
1681 
1682     END IF;
1683   END LOOP;
1684 
1685   DELETE
1686   FROM	  wip_flow_schedules
1687   WHERE   planned_quantity = 0
1688   AND     line_id = p_line_id
1689   AND     organization_id = p_org_id;
1690 
1691 
1692   IF (dbms_sql.is_open(cursor_name)) THEN
1693     dbms_sql.close_cursor(cursor_name);
1694   END IF;
1695 EXCEPTION
1696   WHEN NO_DATA_FOUND THEN
1697 --    dbms_output.put_line('i did not find data');
1698     IF (dbms_sql.is_open(cursor_name)) THEN
1699     dbms_sql.close_cursor(cursor_name);
1700   END IF;
1701     RETURN;
1702   WHEN OTHERS THEN
1703 
1704     IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
1705       FND_MSG_PUB.Add_Exc_Msg(
1706 	V_PKG_NAME,V_PROCEDURE_NAME||': Line '||to_char(V_ERROR_LINE));
1707     END IF;
1708 
1709     IF (dbms_sql.is_open(cursor_name)) THEN
1710       dbms_sql.close_cursor(cursor_name);
1711     END IF;
1712 --    dbms_output.put_line('!!!ERROR!!!:' || to_char(sqlcode) ||
1713 --            substr(sqlerrm,1,60));
1714     RETURN;
1715 
1716 END create_po_fs;
1717 
1718 -- This procedure rounds up the planned quantity of all flow schedules
1719 -- that have fractional quantities with item rounding attribute set to yes
1720 -- Excess is trimmed off from flow schedules starting from the end of the sequence.
1721 
1722 PROCEDURE rounding_process(
1723 				p_org_id IN NUMBER,
1724 				p_line_id IN NUMBER,
1725 				p_rule_id IN NUMBER,
1726 				p_demand_tab IN OUT NOCOPY DemandTabTyp)
1727 IS
1728 
1729   cursor_name   INTEGER;
1730   fs_select_rec	fs_select_type;
1731   v_last_wip    NUMBER;
1732   v_round_total	NUMBER;
1733   v_round_qty	NUMBER;
1734 
1735 BEGIN
1736 
1737   V_PROCEDURE_NAME := 'Rounding_Process';
1738   V_ERROR_LINE := 1;
1739 
1740    v_last_wip := 0;
1741       v_round_total := 0;
1742 
1743   FOR item_list_rec IN item_list(p_org_id) LOOP
1744 
1745     IF p_demand_tab(item_list_rec.primary_item_id).roundType = C_ROUND_TYPE THEN
1746 
1747       V_ERROR_LINE := 2;
1748       cursor_name := Create_Cursor(p_rule_id,p_org_id,p_line_id,C_ASC,C_ITEM,
1749 	item_list_rec.primary_item_id);
1750 
1751       V_ERROR_LINE := 3;
1752 
1753       LOOP
1754         if dbms_sql.fetch_rows(cursor_name) > 0 then
1755           dbms_sql.column_value(cursor_name,1, fs_select_rec.wip_entity);
1756           dbms_sql.column_value(cursor_name,7, fs_select_rec.primary_item_id);
1757           dbms_sql.column_value(cursor_name,8, fs_select_rec.planned_quantity);
1758         end if;
1759 
1760         IF v_last_wip = fs_select_rec.wip_entity THEN
1761           EXIT;
1762         END IF;
1763 
1764         v_round_qty := TRUNC(fs_select_rec.planned_quantity-0.0000000001) + 1;
1765 
1766         IF v_round_qty > fs_select_rec.planned_quantity THEN
1767 
1768 	  v_round_total := v_round_total +
1769 		(v_round_qty - fs_select_rec.planned_quantity);
1770 
1771 	  UPDATE wip_flow_schedules fs
1772           SET    planned_quantity = v_round_qty
1773       	  WHERE  fs.wip_entity_id = fs_select_rec.wip_entity
1774 	  AND    organization_id = p_org_id;
1775 
1776           V_ERROR_LINE := 4;
1777 
1778         END IF;
1779 
1780         v_last_wip := fs_select_rec.wip_entity;
1781 
1782       END LOOP;
1783 
1784       v_round_total := TRUNC(v_round_total);
1785 
1786       v_last_wip := 0;
1787 
1788       V_ERROR_LINE := 5;
1789 
1790       cursor_name := Create_Cursor(p_rule_id,p_org_id,p_line_id,C_DESC,C_ITEM,
1791 	item_list_rec.primary_item_id);
1792 
1793       V_ERROR_LINE := 6;
1794 
1795 
1796 
1797       LOOP
1798         if dbms_sql.fetch_rows(cursor_name) > 0 then
1799           dbms_sql.column_value(cursor_name,1, fs_select_rec.wip_entity);
1800           dbms_sql.column_value(cursor_name,7, fs_select_rec.primary_item_id);
1801           dbms_sql.column_value(cursor_name,8, fs_select_rec.planned_quantity);
1802         end if;
1803 
1804         IF v_last_wip = fs_select_rec.wip_entity THEN
1805           EXIT;
1806         END IF;
1807 
1808         IF fs_select_rec.planned_quantity > v_round_total THEN
1809 
1810           V_ERROR_LINE := 7;
1811 
1812 	  UPDATE wip_flow_schedules fs
1813           SET    planned_quantity = fs_select_rec.planned_quantity -
1814 		  v_round_total
1815       	  WHERE  fs.wip_entity_id = fs_select_rec.wip_entity
1816 	  AND    organization_id = p_org_id;
1817 
1818 	  V_ERROR_LINE := 8;
1819 
1820 	  v_round_total := 0;
1821 
1822         ELSE
1823 	  v_round_total := v_round_total - fs_select_rec.planned_quantity;
1824 
1825           V_ERROR_LINE := 9;
1826 
1827 	  DELETE
1828 	  FROM    wip_flow_schedules
1829 	  WHERE   wip_entity_id = fs_select_rec.wip_entity
1830 	  AND     organization_id = p_org_id;
1831 
1832   	  V_ERROR_LINE := 10;
1833 
1834         END IF;
1835 
1836         IF v_round_total = 0 THEN
1837 	  EXIT;
1838         END IF;
1839 
1840         v_last_wip := fs_select_rec.wip_entity;
1841 
1842       END LOOP;
1843     END IF;
1844   END LOOP;
1845 
1846 EXCEPTION
1847   WHEN NO_DATA_FOUND THEN
1848 --    IF (dbms_sql.is_open(cursor_name)) THEN
1849 --    dbms_sql.close_cursor(cursor_name);
1850 --    END IF;
1851 
1852   RETURN;
1853 
1854   WHEN OTHERS THEN
1855 
1856     IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
1857       FND_MSG_PUB.Add_Exc_Msg(
1858 	V_PKG_NAME,V_PROCEDURE_NAME||': Line '||to_char(V_ERROR_LINE));
1859     END IF;
1860 
1861     IF (dbms_sql.is_open(cursor_name)) THEN
1862       dbms_sql.close_cursor(cursor_name);
1863     end IF;
1864 
1865     return;
1866 
1867 END rounding_process;
1868 
1869 
1870 -- This procedure sequences the unscheduled flow schedules on the line using
1871 -- the specified criteria and then schedules them on the line.
1872 
1873 PROCEDURE schedule_orders (
1874 				p_line_id IN NUMBER,
1875 				p_org_id IN NUMBER,
1876 				p_rule_id IN NUMBER,
1877 				p_cap_tab IN CapTabTyp,
1878 				p_demand_tab IN DemandTabTyp,
1879 				p_time_tab IN OUT NOCOPY TimeTabTyp)
1880 IS
1881 
1882   v_current_date	NUMBER;
1883   v_current_cap		NUMBER;
1884   v_remain_qty		NUMBER;
1885   v_current_wip		NUMBER;
1886   v_build_seq		NUMBER;
1887   v_temp		NUMBER;
1888   v_null_build_seq	NUMBER;
1889   v_build_seq_tab  BuildSeqTabTyp;
1890   v_start_time		NUMBER;
1891   v_end_time		NUMBER;
1892   v_hr_line_rate	NUMBER;
1893   v_line_rate		NUMBER;
1894   v_required_time	NUMBER;
1895   v_begin_time		DATE;
1896   v_completion_time	DATE;
1897   v_final_time		NUMBER;
1898   fs_select_rec	fs_select_type;
1899   cursor_name           INTEGER;
1900   v_last_wip	   	NUMBER;
1901   v_schedule_number	VARCHAR2(30);
1902   v_current_item	NUMBER;
1903   qty_temp		NUMBER;
1904   date_temp		date;
1905   trans_temp		number;
1906   l_fixed_lead_time	NUMBER;
1907   l_variable_lead_time	NUMBER;
1908   l_lead_time		NUMBER;
1909 
1910 BEGIN
1911 
1912   V_PROCEDURE_NAME := 'Schedule_Orders';
1913   V_ERROR_LINE := 1;
1914 
1915   -- Set current date to be the first valid date in the scheduling window.
1916   -- This is the first index in the capacity table.
1917 
1918   v_current_date := p_cap_tab.FIRST;
1919   v_current_cap := p_cap_tab(v_current_date).capacity;
1920 
1921 -- dbms_output.put_line('First valid date in scheduling window is:' ||
1922 --	to_date(v_current_date,'J'));
1923 --dbms_output.put_line('Available capacity on this date is:' ||
1924 --   	to_char(v_current_cap));
1925 
1926 --  dbms_output.put_line('Calculating max build sequences');
1927   -- Obtain the maximum build sequence for each schedule group from scheduled
1928   -- flow schedules on the line.
1929 
1930   calculate_build_sequences(p_org_id, p_line_id, v_build_seq_tab);
1931 
1932 --dbms_output.put_line('AFTER the Schedule group loop!!!');
1933 --    dbms_output.put_line('AFTER the Schedule group loop!!!');
1934 
1935    -- Obtain the maximum sequence for the null schedule group
1936     SELECT NVL(MAX(build_sequence),0)
1937     INTO   v_null_build_seq
1938     FROM   wip_flow_schedules fs
1939     WHERE  fs.schedule_group_id IS NULL
1940       AND  fs.line_id = p_line_id
1941       AND  fs.organization_id = p_org_id
1942       AND  scheduled_flag = C_YES;
1943 
1944     V_ERROR_LINE := 2;
1945 
1946 --  dbms_output.put_line('The max sequence for the null schedule group is: '||
1947 --	to_char(v_null_build_seq));
1948 
1949   -- Obtain information on the start time and end time of the line for
1950   -- time stamping flow schedules.
1951 
1952   SELECT maximum_rate, start_time, stop_time
1953   INTO   v_hr_line_rate, v_start_time, v_end_time
1954   FROM   wip_lines
1955   WHERE  line_id = p_line_id
1956     AND  organization_id = p_org_id;
1957 
1958   V_ERROR_LINE := 3;
1959 
1960   -- Fix bug 939061, add 24 hrs to stop_time if stop_time <= start_time
1961   if (v_end_time <= v_start_time) then
1962     v_end_time := v_end_time+24*3600;
1963   end if;
1964 
1965   v_line_rate := TRUNC(v_hr_line_rate * (v_end_time - v_start_time)/3600);
1966 
1967 --  dbms_output.put_line('Maximum rate = '||to_char(v_line_rate));
1968 --  dbms_output.put_line('Start time = '||to_char(v_start_time));
1969 --  dbms_output.put_line('Maximum rate = '||to_char(v_end_time));
1970 
1971   -- New and existing flow schedules will be time stamped and
1972   -- scheduled before existing wip jobs and repetitive schedules.
1973 
1974   -- Order the existing flow schedules by schedule group id and build sequence
1975   -- and assign the appropriate time stamps to these flow schedules first.
1976 --  dbms_output.put_line('Putting time stamps on existing flow schedules');
1977 
1978 --  time_existing_fs(p_org_id, p_line_id, p_cap_tab, v_time_tab);
1979 
1980   V_ERROR_LINE := 4;
1981 
1982   cursor_name := Create_Cursor(p_rule_id,p_org_id,p_line_id,C_ASC,C_NORM,C_NORM);
1983 
1984   V_ERROR_LINE := 5;
1985 
1986   LOOP
1987     if dbms_sql.fetch_rows(cursor_name) > 0 then
1988        dbms_sql.column_value(cursor_name,1, fs_select_rec.wip_entity);
1989        dbms_sql.column_value(cursor_name,2, fs_select_rec.creation_date);
1990        dbms_sql.column_value(cursor_name,3, fs_select_rec.schedule_date);
1991        dbms_sql.column_value(cursor_name,4, fs_select_rec.promise_date);
1992        dbms_sql.column_value(cursor_name,5, fs_select_rec.request_date);
1993        dbms_sql.column_value(cursor_name,6, fs_select_rec.planning_priority);
1994        dbms_sql.column_value(cursor_name,7, fs_select_rec.primary_item_id);
1995        dbms_sql.column_value(cursor_name,8, fs_select_rec.planned_quantity);
1996        dbms_sql.column_value(cursor_name,9, fs_select_rec.schedule_group_id);
1997 
1998     end if;
1999 
2000 
2001     SELECT NVL(fixed_lead_time, 0), NVL(variable_lead_time, 0)
2002     INTO   l_fixed_lead_time, l_variable_lead_time
2003     FROM   MTL_SYSTEM_ITEMS
2004     WHERE  inventory_item_id = fs_select_rec.primary_item_id
2005     AND    organization_id = p_org_id;
2006 
2007 
2008 --  dbms_output.put_line('INSIDE the FLOW SCHEDULE CURSOR loop!!!');
2009 
2010     IF v_last_wip = fs_select_rec.wip_entity THEN
2011       RETURN;
2012     END IF;
2013 
2014     v_last_wip := fs_select_rec.wip_entity;
2015     v_remain_qty := fs_select_rec.planned_quantity;
2016     v_current_wip := fs_select_rec.wip_entity;
2017 
2018     select scheduled_completion_date, demand_source_line
2019     into date_temp, trans_temp
2020     from wip_flow_schedules
2021     where  wip_entity_id = v_current_wip
2022     and    organization_id = p_org_id;
2023 
2024     -- LOOP used for making sure that all quantity of the flow schedule has
2025     -- been scheduled.
2026 
2027 --    dbms_output.put_line('Inside the flow schedule loop');
2028 
2029     WHILE v_remain_qty > 0  LOOP
2030 
2031 
2032 
2033 --    dbms_output.put_line('The current flow schedule is:  ' ||to_char
2034 --	(v_current_wip));
2035 --      dbms_output.put_line('Remain quantity for current flow schedule ' ||
2036 --	to_char(v_current_wip)||' is ' ||to_char(v_remain_qty));
2037 
2038       -- Get the next build sequence for the schedule group of the current
2039       -- flow schedule.
2040 
2041       IF fs_select_rec.schedule_group_id IS NOT NULL THEN
2042         v_build_seq :=
2043         v_build_seq_tab(fs_select_rec.schedule_group_id).buildseq + 1;
2044         v_build_seq_tab(fs_select_rec.schedule_group_id).buildseq := v_build_seq;
2045       ELSE
2046         v_build_seq := v_null_build_seq + 1;
2047 	v_null_build_seq := v_build_seq;
2048       END IF;
2049 
2050 --    dbms_output.put_line('The next build sequence is '||to_char
2051 --	(v_build_seq)|| 'for schedule group '||
2052 --	to_char(fs_select_rec.schedule_group_id));
2053 
2054       -- If the capacity of the current date is 0, get the next valid work
2055       -- date and set the capacity to the capacity of this new date.
2056       -- If there is no next valid work date, we are at the end of the
2057       -- scheduling window and we are finished with scheduling.
2058 
2059       WHILE v_current_cap = 0 LOOP
2060 --      dbms_output.put_line('0 capacity on '||to_date(v_current_date,'J'));
2061 
2062 	IF v_current_date = p_cap_tab.LAST THEN
2063 --        dbms_output.put_line(to_date(v_current_date,'J')||'was the last day
2064 --	  of the scheduling window.  scheduling is completed. exiting ...');
2065 	  RETURN;
2066 	ELSE
2067 	  v_current_date := p_cap_tab.NEXT(v_current_date);
2068           v_current_cap := p_cap_tab(v_current_date).capacity;
2069 
2070 --	  dbms_output.put_line('Next valid work date is: '||
2071 --	  to_date(v_current_date,'J'));
2072 --	  dbms_output.put_line('Capacity available = '||to_char(v_current_cap));
2073 
2074         END IF;
2075       END LOOP;
2076 
2077       -- If there is no entry in the completion time table for the date
2078       -- initialize it with the start time
2079 
2080       IF p_time_tab.EXISTS(v_current_date) = FALSE THEN
2081         SELECT start_time
2082         INTO   v_final_time
2083         FROM   wip_lines
2084         WHERE  line_id = p_line_id
2085           AND  organization_id = p_org_id;
2086 
2087         V_ERROR_LINE := 6;
2088 
2089 	p_time_tab(v_current_date).start_completion_time := v_final_time;
2090 
2091 --      dbms_output.put_line('Initialization:
2092 --	For '||to_date(v_current_date,'J')||',the completion time is '||
2093 --	 to_char(p_time_tab(v_current_date).start_time));
2094       END IF;
2095 
2096       -- After scheduling, set the completion date to today's date and
2097       -- set the scheduled flag to yes.  Update the build sequence of the
2098       -- flow schedule.
2099 
2100       IF v_remain_qty <= v_current_cap THEN
2101 --	dbms_output.put_line(to_char(v_current_wip)||'can be scheduled');
2102 
2103 	v_required_time := TRUNC(v_remain_qty * 3600/v_hr_line_rate);
2104         if (p_time_tab(v_current_date).start_completion_time+v_required_time > p_time_tab(v_current_date).end_completion_time) then
2105           v_required_time := p_time_tab(v_current_date).end_completion_time -
2106                              p_time_tab(v_current_date).start_completion_time;
2107         end if;
2108 
2109 	v_completion_time := to_date(v_current_date,'J') +
2110 	((p_time_tab(v_current_date).start_completion_time+v_required_time)/86400);
2111 
2112 	l_lead_time := l_fixed_lead_time +
2113 		      (l_variable_lead_time * (v_remain_qty-1));
2114 
2115         IF l_lead_time = 0 THEN
2116           v_begin_time := v_completion_time;
2117         ELSE
2118 	  v_begin_time := mrp_line_schedule_algorithm.calculate_begin_time(
2119 				p_org_id,
2120 				v_completion_time,
2121 				l_lead_time,
2122 				v_start_time,
2123 				v_end_time);
2124         END IF;
2125 
2126 
2127 	UPDATE wip_flow_schedules
2128 	SET    scheduled_start_date = v_begin_time,
2129 	       scheduled_completion_date = v_completion_time,
2130 	       scheduled_flag = C_YES,
2131 	       build_sequence = v_build_seq
2132 	WHERE  wip_entity_id = v_current_wip
2133 	AND    organization_id = p_org_id;
2134 
2135 	select planned_quantity
2136 	into   qty_temp
2137 	from   wip_flow_schedules
2138  	where  wip_entity_id = v_current_wip
2139 	and    organization_id = p_org_id;
2140 
2141         V_ERROR_LINE := 7;
2142 
2143         p_time_tab(v_current_date).start_completion_time :=
2144 	p_time_tab(v_current_date).start_completion_time + v_required_time;
2145 
2146 	-- Decrement capacity on the line for the current date by the scheduled
2147 	-- quantity.
2148 
2149 	v_current_cap := v_current_cap - v_remain_qty;
2150 
2151 --	  dbms_output.put_line('Capacity on '||to_date(v_current_date,'J')||' = '||
2152 --	  to_char(v_current_cap));
2153 
2154 	-- The entire flow schedule has been scheduled and the
2155 	-- remaining quantity = 0
2156 
2157 	v_remain_qty := 0;
2158 
2159       ELSIF (v_remain_qty > v_current_cap) THEN
2160 --	dbms_output.put_line(to_char(v_current_wip)||'can not be scheduled');
2161 --	dbms_output.put_line('Capacity on '||to_date(v_current_date,'J')||' = '||
2162 --	  to_char(v_current_cap));
2163 
2164 	SELECT primary_item_id
2165 	INTO   v_current_item
2166 	FROM   wip_flow_schedules
2167 	WHERE  wip_entity_id = v_current_wip
2168 	AND    organization_id = p_org_id;
2169 
2170 	V_ERROR_LINE := 8;
2171 
2172 	IF p_demand_tab(v_current_item).roundType = 1 THEN
2173 	  v_current_cap := TRUNC(v_current_cap);
2174 
2175 	  WHILE v_current_cap = 0 LOOP
2176 
2177 	    IF v_current_date = p_cap_tab.LAST THEN
2178 	      RETURN;
2179 	    ELSE
2180 	      v_current_date := p_cap_tab.NEXT(v_current_date);
2181               v_current_cap := p_cap_tab(v_current_date).capacity;
2182 	      v_current_cap := TRUNC(v_current_cap);
2183 	    END IF;
2184  	  END LOOP;
2185 	END IF;
2186 
2187 --	dbms_output.put_line('current date is: '||to_char(v_current_date));
2188 --        dbms_output.put_line('Current cap is: '||to_char(v_current_cap));
2189 
2190 	IF v_current_cap < v_remain_qty THEN
2191 	  -- If there is no entry in the completion time table for the date
2192           -- initialize it with the start time
2193 
2194           IF p_time_tab.EXISTS(v_current_date) = FALSE THEN
2195             SELECT start_time
2196             INTO   v_final_time
2197             FROM   wip_lines
2198             WHERE  line_id = p_line_id
2199             AND  organization_id = p_org_id;
2200 
2201 	    V_ERROR_LINE := 9;
2202 
2203 	    p_time_tab(v_current_date).start_completion_time := v_final_time;
2204           END IF;
2205 
2206           v_required_time := TRUNC(v_current_cap * 3600/v_hr_line_rate);
2207 
2208           if (p_time_tab(v_current_date).start_completion_time+v_required_time > p_time_tab(v_current_date).end_completion_time) then
2209             v_required_time := p_time_tab(v_current_date).end_completion_time -
2210                                p_time_tab(v_current_date).start_completion_time;
2211           end if;
2212 
2213           v_completion_time := to_date(v_current_date,'J') +
2214           ((p_time_tab(v_current_date).start_completion_time+v_required_time)/86400);
2215 
2216 	  l_lead_time := l_fixed_lead_time +
2217 		        (l_variable_lead_time * (v_current_cap-1));
2218 
2219           IF l_lead_time = 0 THEN
2220             v_begin_time := v_completion_time;
2221           ELSE
2222   	    v_begin_time := mrp_line_schedule_algorithm.calculate_begin_time(
2223 				p_org_id,
2224 				v_completion_time,
2225 				l_lead_time,
2226 				v_start_time,
2227 				v_end_time);
2228           END IF;
2229 
2230 
2231 	  UPDATE wip_flow_schedules
2232 	  SET    scheduled_start_date = v_begin_time,
2233 	         scheduled_completion_date = v_completion_time,
2234 	         planned_quantity = v_current_cap,
2235 	         scheduled_flag = C_YES,
2236 	         build_sequence = v_build_seq
2237 	  WHERE  wip_entity_id = v_current_wip
2238 	  AND  organization_id = p_org_id;
2239 
2240 	  select planned_quantity
2241 	  into   qty_temp
2242 	  from   wip_flow_schedules
2243  	  where  wip_entity_id = v_current_wip
2244 	  and    organization_id = p_org_id;
2245 
2246 	  V_ERROR_LINE := 10;
2247 
2248           p_time_tab(v_current_date).start_completion_time :=
2249 	    p_time_tab(v_current_date).start_completion_time + v_required_time;
2250 
2251 	  -- Create a new flow schedule to carry over the unscheduled quantity
2252           SELECT wip_entities_s.nextval
2253           INTO   v_temp
2254           FROM   dual;
2255 
2256 	  V_ERROR_LINE := 11;
2257 
2258           --Bug 6122344
2259    	  --v_schedule_number := NVL(substr(FND_PROFILE.value('WIP_JOB_PREFIX'),1,20),'X') || to_char(v_temp);
2260           v_schedule_number := 'FLM-INTERNAL'|| to_char(v_temp);
2261 
2262    	  INSERT INTO wip_flow_schedules(
2263 				scheduled_flag,
2264 				wip_entity_id,
2265 				organization_id,
2266 				last_update_date,
2267 				last_updated_by,
2268 				creation_date,
2269 				created_by,
2270 				class_code,
2271 				line_id,
2272 				primary_item_id,
2273 				scheduled_start_date,
2274 				planned_quantity,
2275 				quantity_completed,
2276 				quantity_scrapped,
2277 				scheduled_completion_date,
2278 				schedule_group_id,
2279 				status,
2280 				schedule_number,
2281 				demand_source_header_id,
2282 				demand_source_line,
2283 				demand_source_delivery,
2284 				demand_source_type,
2285 				project_id,
2286 				task_id,
2287 				end_item_unit_number,
2288                                 request_id,
2289                                 attribute1,
2290                                 attribute2,
2291                                 attribute3,
2292                                 attribute4,
2293                                 attribute5,
2294                                 attribute6,
2295                                 attribute7,
2296                                 attribute8,
2297                                 attribute9,
2298                                 attribute10,
2299                                 attribute11,
2300                                 attribute12,
2301                                 attribute13,
2302                                 attribute14,
2303                                 attribute15,
2304                                 material_account,
2305                                 material_overhead_account,
2306                                 resource_account,
2307                                 outside_processing_account,
2308                                 material_variance_account,
2309                                 resource_variance_account,
2310                                 outside_proc_variance_account,
2311                                 std_cost_adjustment_account,
2312                                 overhead_account,
2313                                 overhead_variance_account,
2314                                 bom_revision,  /* Added for bug 2185087 */
2315                                 routing_revision,
2316                                 bom_revision_date,
2317                                 routing_revision_date,
2318                                 alternate_bom_designator,
2319                                 alternate_routing_designator,
2320                                 completion_subinventory,
2321                                 completion_locator_id,
2322                                 demand_class,
2323                                 attribute_category,
2324                                 kanban_card_id)
2325 
2326 	  SELECT		C_NO,
2327 				v_temp,
2328 				p_org_id,
2329 				SYSDATE,
2330 				fs.last_updated_by,
2331 				SYSDATE,
2332 				fs.created_by,
2333 				fs.class_code,
2334 				fs.line_id,
2335 				fs.primary_item_id,
2336 				to_date(v_current_date,'J'),
2337 				v_remain_qty - v_current_cap,
2338 				0,
2339 				0,
2340 				to_date(v_current_date,'J'),
2341 				fs.schedule_group_id,
2342 				fs.status,
2343 				v_schedule_number,
2344 				fs.demand_source_header_id,
2345 			       	fs.demand_source_line,
2346 			     	fs.demand_source_delivery,
2347 				fs.demand_source_type,
2348 				fs.project_id,
2349 				fs.task_id,
2350 				fs.end_item_unit_number,
2351 				USERENV('SESSIONID'),
2352                                 fs.attribute1,
2353                                 fs.attribute2,
2354                                 fs.attribute3,
2355                                 fs.attribute4,
2356                                 fs.attribute5,
2357                                 fs.attribute6,
2358                                 fs.attribute7,
2359                                 fs.attribute8,
2360                                 fs.attribute9,
2361                                 fs.attribute10,
2362                                 fs.attribute11,
2363                                 fs.attribute12,
2364                                 fs.attribute13,
2365                                 fs.attribute14,
2366                                 fs.attribute15,
2367                                 fs.material_account,
2368                                 fs.material_overhead_account,
2369                                 fs.resource_account,
2370                                 fs.outside_processing_account,
2371                                 fs.material_variance_account,
2372                                 fs.resource_variance_account,
2373                                 fs.outside_proc_variance_account,
2374                                 fs.std_cost_adjustment_account,
2375                                 fs.overhead_account,
2376                                 fs.overhead_variance_account,
2377                                 fs.bom_revision,  /* Added for bug 2185087 */
2378                                 fs.routing_revision,
2379                                 fs.bom_revision_date,
2380                                 fs.routing_revision_date,
2381                                 fs.alternate_bom_designator,
2382                                 fs.alternate_routing_designator,
2383                                 fs.completion_subinventory,
2384                                 fs.completion_locator_id,
2385                                 fs.demand_class,
2386                                 fs.attribute_category,
2387                                 fs.kanban_card_id
2388 	  FROM  wip_flow_schedules fs
2389 	  WHERE fs.wip_entity_id = fs_select_rec.wip_entity
2390 	  AND organization_id = p_org_id;
2391 
2392  	  V_ERROR_LINE := 12;
2393 
2394 	  -- Reset the remaining quantity to be scheduled as the
2395 	  -- left over quantity from the last flow schedule.
2396 
2397 	  v_remain_qty := v_remain_qty - v_current_cap;
2398 
2399 	  -- Set the capacity for current date to 0.
2400 
2401 	  v_current_cap := 0;
2402 
2403 	  -- Point to the newly created flow schedule in order to
2404 	  -- schedule the quantity.
2405 
2406 	  v_current_wip := v_temp;
2407         END IF;
2408       END IF;
2409     END LOOP;
2410   END LOOP;
2411 
2412   IF (dbms_sql.is_open(cursor_name)) THEN
2413     dbms_sql.close_cursor(cursor_name);
2414   END IF;
2415 
2416 EXCEPTION
2417   WHEN NO_DATA_FOUND THEN
2418     IF (dbms_sql.is_open(cursor_name)) THEN
2419     dbms_sql.close_cursor(cursor_name);
2420     END IF;
2421   RETURN;
2422 
2423   WHEN OTHERS THEN
2424 
2425     IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
2426       FND_MSG_PUB.Add_Exc_Msg(
2427 	V_PKG_NAME,V_PROCEDURE_NAME||': Line '||to_char(V_ERROR_LINE));
2428     END IF;
2429 
2430     IF (dbms_sql.is_open(cursor_name)) THEN
2431     dbms_sql.close_cursor(cursor_name);
2432     end IF;
2433 --  dbms_output.put_line('!!!ERROR!!!:' || to_char(sqlcode) ||
2434 --              substr(sqlerrm,1,60));
2435     return;
2436 
2437 END schedule_orders;
2438 
2439 -- This procedure calculates the production plan for each item for each date
2440 -- between the first date to the calculated end date in the scheduling window.
2441 
2442 PROCEDURE calculate_production_plan(
2443 				p_org_id IN NUMBER,
2444 				p_line_id IN NUMBER,
2445 				p_first_date IN DATE,
2446 				p_last_date IN DATE,
2447 				p_cap_tab IN CapTabTyp,
2448 				p_demand_tab IN OUT NOCOPY DemandTabTyp)
2449 IS
2450   v_begin_date 		NUMBER;
2451   v_finish_date		NUMBER;
2452   v_current_date	NUMBER;
2453   v_ratio		NUMBER;
2454   v_production		NUMBER;
2455   v_trunc_sum		NUMBER;
2456   v_cap_diff		NUMBER;
2457   v_item_id		NUMBER;
2458   v_quantity		NUMBER;
2459   v_max_diff		NUMBER;
2460   v_decrement_qty	NUMBER;
2461   v_finish_flag		NUMBER;
2462   v_round_type		NUMBER;
2463   v_item_round		NUMBER;
2464   v_item_round_qty	NUMBER;
2465 
2466   -- Cursor used to determine if any items of no rounding exists.
2467   CURSOR no_round_cursor IS
2468     SELECT number1,number2
2469     FROM   mrp_form_query mfq, mtl_system_items mtl
2470     WHERE  mfq.date1 = to_date(v_current_date,'J')
2471     AND    mfq.query_id = v_query_id
2472     AND    mfq.number1 = mtl.inventory_item_id
2473     AND    NVL(mtl.rounding_control_type,2) <> C_ROUND_TYPE
2474     AND    mtl.organization_id = p_org_id
2475     ORDER BY number2;
2476 
2477 BEGIN
2478 
2479   V_PROCEDURE_NAME := 'Calculate_Production_Plan';
2480   V_ERROR_LINE := 1;
2481 
2482   v_begin_date := to_number(to_char(p_first_date,'J'));
2483   v_finish_date := to_number(to_char(p_last_date,'J'));
2484 
2485   SELECT mrp_form_query_s.nextval
2486   INTO v_query_id
2487   FROM DUAL;
2488 
2489   V_ERROR_LINE := 2;
2490 
2491   FOR i in v_begin_date..v_finish_date LOOP
2492 
2493     v_current_date := i;
2494 
2495 --    dbms_output.put_line('The date is: '||to_date(v_current_date,'J'));
2496 
2497     IF p_cap_tab.EXISTS(v_current_date)AND
2498 	p_cap_tab(v_current_date).capacity > 0 THEN
2499 
2500 --      dbms_output.put_line('The capacity is: '||
2501 --	to_char(p_cap_tab(v_current_date).capacity));
2502 
2503       FOR item_list_rec IN item_list(p_org_id) LOOP
2504 
2505 --	dbms_output.put_line('The item is: '||to_char(item_list_rec.primary_item_id));
2506 	v_ratio := p_demand_tab(item_list_rec.primary_item_id).totalDemand/
2507 			V_GLOBAL_DEMAND;
2508 
2509 --	dbms_output.put_line('The ratio is: '||to_char(v_ratio));
2510 
2511 	-- Use whole number for line capacity
2512 
2513 	v_production := TRUNC((v_ratio *
2514 		p_cap_tab(v_current_date).capacity),2);
2515 
2516 --	dbms_output.put_line('The production is: '||to_char(v_production));
2517 
2518 	INSERT INTO MRP_FORM_QUERY (
2519 			QUERY_ID,
2520 			LAST_UPDATE_DATE,
2521 			LAST_UPDATED_BY,
2522 			CREATION_DATE,
2523 			CREATED_BY,
2524 			DATE1,
2525 			NUMBER1,
2526 			NUMBER2,
2527 			NUMBER3)
2528 	VALUES (
2529 			v_query_id,
2530 			SYSDATE,
2531 			1,
2532 			SYSDATE,
2533 			1,
2534 			to_date(v_current_date,'J'),
2535 			item_list_rec.primary_item_id,
2536 			TRUNC(v_production),
2537 			v_production - TRUNC(v_production));
2538 
2539       	-- If the item is of no round type, then we don't want to round.
2540 	-- Therefore, we use the original production plan and we set
2541 	-- the difference between production and truncated production to 0.
2542 
2543 	IF p_demand_tab(item_list_rec.primary_item_id).roundType <> C_ROUND_TYPE THEN
2544 
2545 --dbms_output.put_line('Item '||to_char(item_list_rec.primary_item_id)||'is not a round item');
2546 
2547 	  UPDATE MRP_FORM_QUERY
2548 	  SET    number2 = v_production,
2549 	         number3 = 0
2550 	  WHERE  number1 = item_list_rec.primary_item_id
2551 	  AND    query_id = v_query_id
2552 	  AND    date1 = to_date(v_current_date,'J');
2553 
2554 	END IF;
2555 
2556 	V_ERROR_LINE := 3;
2557 
2558 --      dbms_output.put_line('The diff for item is: '||
2559 --	to_char(v_production - TRUNC(v_production)));
2560 
2561       END LOOP;
2562 
2563       -- Find the sum of all production for the current date.
2564 
2565       SELECT SUM(number2)
2566       INTO   v_trunc_sum
2567       FROM   mrp_form_query
2568       WHERE  query_id = v_query_id
2569       AND    date1 = to_date(v_current_date,'J');
2570 
2571       V_ERROR_LINE := 4;
2572 
2573 --      dbms_output.put_line('The planned sum is: '||to_char(v_trunc_sum));
2574 
2575       -- Find the difference between line capacity and sum of all planned
2576       -- production.
2577 
2578       v_cap_diff := p_cap_tab(v_current_date).capacity - v_trunc_sum;
2579 
2580 --      dbms_output.put_line('The diff is: '||to_char(v_cap_diff));
2581 
2582       FOR production_round_rec IN production_round(v_current_date,v_query_id)
2583 	LOOP
2584 
2585 	IF v_cap_diff = 0 THEN
2586 	  EXIT;
2587 
2588 	ELSIF v_cap_diff < 1 THEN
2589 
2590 	  OPEN no_round_cursor;
2591   	  FETCH no_round_cursor INTO v_item_round, v_item_round_qty;
2592 	  IF no_round_cursor%NOTFOUND THEN
2593 	    CLOSE no_round_cursor;
2594 	    EXIT;
2595 
2596 	  ELSE
2597 
2598 	    UPDATE mrp_form_query
2599 	    SET    number2 = v_item_round_qty + v_cap_diff
2600 	    WHERE  number1 = v_item_round
2601  	    AND    date1 = to_date(v_current_date,'J')
2602 	    AND    query_id = v_query_id;
2603 	    CLOSE no_round_cursor;
2604 	    EXIT;
2605 	  END IF;
2606 
2607      	ELSE
2608 
2609 --	  dbms_output.put_line('Updating ...'||to_char(production_round_rec.number1));
2610 
2611 	  UPDATE mrp_form_query
2612 	  SET    number2 =(SELECT number2 +1
2613 			 FROM   mrp_form_query
2614 			 WHERE  date1 = to_date(v_current_date,'J')
2615 			 AND    query_id = v_query_id
2616 			 AND    number1 = production_round_rec.number1)
2617 	  WHERE date1 = to_date(v_current_date,'J')
2618 	  AND   query_id = v_query_id
2619 	  AND   number1 = production_round_rec.number1;
2620 
2621      	  V_ERROR_LINE := 5;
2622 
2623 	  v_cap_diff := v_cap_diff - 1 ;
2624 
2625 --	dbms_output.put_line('Max item is: '||to_char(v_item_id));
2626 --	dbms_output.put_line('Quantity of item is: '||to_char(v_quantity));
2627 --	dbms_output.put_line('Max diff is: '||to_char(v_max_diff));
2628 	END IF;
2629       END LOOP;
2630 
2631       -- Update the total demand for each item as well as the global demand
2632       -- to reflect what has been allocated.
2633       FOR item_list_rec IN item_list(p_org_id) LOOP
2634 
2635 	v_finish_flag := -1;
2636 
2637 	SELECT number2
2638         INTO   v_decrement_qty
2639 	FROM   mrp_form_query
2640 	WHERE  query_id = v_query_id
2641 	AND    number1 = item_list_rec.primary_item_id
2642 	AND    date1 = to_date(v_current_date,'J');
2643 
2644  	V_ERROR_LINE := 6;
2645 
2646 	-- If the current production plan is greater than the demand left
2647 	-- for the item, then the decrement quantity is the demand itself.
2648 
2649 	IF p_demand_tab(item_list_rec.primary_item_id).totalDemand -
2650 		v_decrement_qty < 0 THEN
2651 	  v_decrement_qty :=
2652 		p_demand_tab(item_list_rec.primary_item_id).totalDemand;
2653 	END IF;
2654 
2655 	p_demand_tab(item_list_rec.primary_item_id).totalDemand :=
2656 	p_demand_tab(item_list_rec.primary_item_id).totalDemand -
2657 		v_decrement_qty;
2658 
2659 	V_GLOBAL_DEMAND := V_GLOBAL_DEMAND - v_decrement_qty;
2660 --	dbms_output.put_line('GLOBAL DEMAND IS: '||to_char(V_GLOBAL_DEMAND));
2661 
2662 	-- If the global demand becomes 0, then the production allocation
2663 	-- process is finished.
2664 
2665 	IF V_GLOBAL_DEMAND > 0 THEN
2666 	  v_finish_flag := 1;
2667 	END IF;
2668 
2669       END LOOP;
2670     ELSE
2671       FOR item_list_rec IN item_list(p_org_id) LOOP
2672         INSERT INTO MRP_FORM_QUERY (
2673 			QUERY_ID,
2674 			LAST_UPDATE_DATE,
2675 			LAST_UPDATED_BY,
2676 			CREATION_DATE,
2677 			CREATED_BY,
2678 			DATE1,
2679 			NUMBER1,
2680 			NUMBER2,
2681 			NUMBER3)
2682 	VALUES (
2683 			v_query_id,
2684 			SYSDATE,
2685 			1,
2686 			SYSDATE,
2687 			1,
2688 			to_date(v_current_date,'J'),
2689 			item_list_rec.primary_item_id,
2690 			0,
2691 			0);
2692       END LOOP;
2693     END IF;
2694 
2695     IF v_finish_flag = -1 THEN
2696 --    dbms_output.put_line('ALL FINISHED!!!');
2697       RETURN;
2698     END IF;
2699 
2700     -- Roll the date forward to next date
2701     IF v_current_date = p_cap_tab.LAST THEN
2702 	return;
2703     END IF;
2704 
2705   END LOOP;
2706 
2707 EXCEPTION
2708   WHEN OTHERS THEN
2709 
2710     IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
2711       FND_MSG_PUB.Add_Exc_Msg(
2712 	V_PKG_NAME,V_PROCEDURE_NAME||': Line '||to_char(V_ERROR_LINE));
2713     END IF;
2714 
2715     RETURN;
2716 
2717 END calculate_production_plan;
2718 
2719 -- This procedure schedules the flow schedules on the line using the level
2720 -- daily rate algorithm
2721 
2722 PROCEDURE schedule_orders_level(
2723 				p_line_id IN NUMBER,
2724 				p_org_id  IN NUMBER,
2725 				p_rule_id IN NUMBER,
2726 				p_cap_tab IN CapTabTyp,
2727                                 p_time_tab IN OUT NOCOPY TimeTabTyp)
2728 
2729 IS
2730 
2731   v_demand_tab		DemandTabTyp;
2732   v_build_seq_tab 	BuildSeqTabTyp;
2733   v_null_build_seq	NUMBER;
2734   v_hr_line_rate	NUMBER;
2735   v_line_rate		NUMBER;
2736   v_start_time		NUMBER;
2737   v_end_time		NUMBER;
2738   v_item_alloc_tab	ItemAllocTabTyp;
2739   v_remain_qty 		NUMBER;
2740   v_current_wip 	NUMBER;
2741   v_current_date 	NUMBER;
2742   v_alloc_qty 		NUMBER;
2743   v_build_seq		NUMBER;
2744   v_final_time		NUMBER;
2745   v_required_time	NUMBER;
2746   v_completion_time	DATE;
2747   v_begin_time		DATE;
2748   v_temp		NUMBER;
2749   fs_select_rec	fs_select_type;
2750   cursor_name           INTEGER;
2751   v_last_wip		NUMBER;
2752   v_schedule_number	VARCHAR2(30);
2753   v_end_date 		DATE;
2754   v_first_date		DATE;
2755   v_finish_flag		NUMBER;
2756   l_fixed_lead_time	NUMBER;
2757   l_variable_lead_time	NUMBER;
2758   l_lead_time		NUMBER;
2759 
2760 BEGIN
2761 
2762   V_PROCEDURE_NAME := 'Schedule_Orders_Level';
2763   V_ERROR_LINE := 1;
2764 
2765   -- Calculate total demand and demand ratio for each item
2766   calculate_demand(p_line_id, p_org_id, v_demand_tab);
2767 
2768   -- Obtain information on the start time and end time of the line for
2769   -- time stamping flow schedules.
2770 
2771   SELECT maximum_rate, start_time, stop_time
2772   INTO   v_hr_line_rate, v_start_time, v_end_time
2773   FROM   wip_lines
2774   WHERE  line_id = p_line_id
2775     AND  organization_id = p_org_id;
2776 
2777   if (v_end_time <= v_start_time) then
2778     v_end_time := v_end_time+24*3600;
2779   end if;
2780 
2781   V_ERROR_LINE := 2;
2782 
2783   -- Calculate the production plan for each item on each date from the first
2784   -- date of the scheduling horizon to the date where all demand has been
2785   -- met or until the end of the scheduling window.
2786 
2787   v_first_date := to_date(p_cap_tab.FIRST,'J');
2788   v_end_date := to_date(p_cap_tab.LAST,'J');
2789 
2790 --  dbms_output.put_line('Calculating production plan ...');
2791 
2792   calculate_production_plan(p_org_id, p_line_id, v_first_date, v_end_date,
2793 	p_cap_tab, v_demand_tab);
2794 
2795 --  dbms_output.put_line('Finished calculating production plan ...');
2796 
2797   -- New and existing flow schedules will be time stamped and
2798   -- scheduled before existing wip jobs and repetitive schedules.
2799   -- Order the existing flow schedules by schedule group id and build sequence
2800   -- and assign the appropriate time stamps to these flow schedules first.
2801 
2802 --  time_existing_fs(p_org_id, p_line_id, p_cap_tab, v_time_tab);
2803 
2804   V_ERROR_LINE := 3;
2805 
2806   cursor_name := Create_Cursor(p_rule_id, p_org_id, p_line_id, C_ASC,
2807 	C_NORM,C_NORM);
2808 
2809   V_ERROR_LINE := 4;
2810 
2811   -- Set initial current date
2812 
2813   v_current_date := p_cap_tab.FIRST;
2814 
2815   UPDATE mrp_form_query
2816   SET    number4 = C_DATE_ON
2817   WHERE  query_id = v_query_id
2818   AND    date1 = to_date(v_current_date,'J');
2819 
2820   V_ERROR_LINE := 5;
2821 
2822   LOOP
2823     IF dbms_sql.fetch_rows(cursor_name) > 0 THEN
2824       dbms_sql.column_value(cursor_name,1, fs_select_rec.wip_entity);
2825       dbms_sql.column_value(cursor_name,2, fs_select_rec.creation_date);
2826       dbms_sql.column_value(cursor_name,3, fs_select_rec.schedule_date);
2827       dbms_sql.column_value(cursor_name,4, fs_select_rec.promise_date);
2828       dbms_sql.column_value(cursor_name,5, fs_select_rec.request_date);
2829       dbms_sql.column_value(cursor_name,6, fs_select_rec.planning_priority);
2830       dbms_sql.column_value(cursor_name,7, fs_select_rec.primary_item_id);
2831       dbms_sql.column_value(cursor_name,8, fs_select_rec.planned_quantity);
2832       dbms_sql.column_value(cursor_name,9, fs_select_rec.schedule_group_id);
2833     END IF;
2834 
2835 
2836     SELECT NVL(fixed_lead_time, 0), NVL(variable_lead_time, 0)
2837     INTO   l_fixed_lead_time, l_variable_lead_time
2838     FROM   MTL_SYSTEM_ITEMS
2839     WHERE  inventory_item_id = fs_select_rec.primary_item_id
2840     AND    organization_id = p_org_id;
2841 
2842 
2843     IF v_last_wip = fs_select_rec.wip_entity THEN
2844       EXIT;
2845     END IF;
2846 
2847     v_last_wip := fs_select_rec.wip_entity;
2848 
2849     SELECT number2, to_number(to_char(date1,'J'))
2850     INTO   v_alloc_qty, v_current_date
2851     FROM   mrp_form_query
2852     WHERE  query_id = v_query_id
2853     AND    number1 = fs_select_rec.primary_item_id
2854     AND    number4 = C_DATE_ON;
2855 
2856     V_ERROR_LINE := 6;
2857 
2858     v_remain_qty := fs_select_rec.planned_quantity;
2859     v_current_wip := fs_select_rec.wip_entity;
2860 
2861     WHILE v_remain_qty > 0 LOOP
2862 
2863       SELECT number5
2864       INTO   v_finish_flag
2865       FROM   mrp_form_query
2866       WHERE  number1 = fs_select_rec.primary_item_id
2867       AND    number4 = C_DATE_ON
2868       AND    query_id = v_query_id;
2869 
2870       V_ERROR_LINE := 7;
2871 
2872       IF v_finish_flag = C_COMPLETE THEN
2873 	EXIT;
2874       END IF;
2875 
2876       -- If the remaining planned production of the current date is 0,
2877       -- get the planned production of the next valid work date until
2878       -- a date that allows a quantity for planned production greater
2879       -- than 0 for the item.
2880 
2881       -- If we reach the last date of the scheduling window, we are finished
2882       -- and may exit the procedure.
2883 
2884       WHILE v_alloc_qty = 0 LOOP
2885 
2886 	SELECT number5
2887         INTO   v_finish_flag
2888 	FROM   mrp_form_query
2889         WHERE  number1 = fs_select_rec.primary_item_id
2890         AND    number4 = C_DATE_ON
2891         AND    query_id = v_query_id;
2892 
2893 	V_ERROR_LINE := 8;
2894 
2895         IF v_finish_flag = C_COMPLETE THEN
2896 	  EXIT;
2897         END IF;
2898 
2899 	IF v_current_date = p_cap_tab.LAST THEN
2900 
2901 	  UPDATE mrp_form_query
2902 	  SET    number5 = C_COMPLETE
2903 	  WHERE  number4 = C_DATE_ON
2904     	  AND    query_id = v_query_id
2905     	  AND    number1 = fs_select_rec.primary_item_id;
2906 
2907 	  V_ERROR_LINE := 9;
2908 
2909 	ELSE
2910 
2911 	  UPDATE mrp_form_query
2912   	  SET    number4 = NULL
2913 	  WHERE  date1 = to_date(v_current_date,'J')
2914     	  AND    query_id = v_query_id
2915     	  AND    number1 = fs_select_rec.primary_item_id;
2916 
2917 	  V_ERROR_LINE := 10;
2918 
2919 	  v_current_date := p_cap_tab.NEXT(v_current_date);
2920 
2921 	  UPDATE mrp_form_query
2922   	  SET    number4 = C_DATE_ON
2923 	  WHERE  date1 = to_date(v_current_date,'J')
2924     	  AND    query_id = v_query_id
2925     	  AND    number1 = fs_select_rec.primary_item_id;
2926 
2927 	  V_ERROR_LINE := 11;
2928 
2929 	  SELECT number2
2930     	  INTO   v_alloc_qty
2931     	  FROM   mrp_form_query
2932     	  WHERE  query_id = v_query_id
2933     	  AND    number1 = fs_select_rec.primary_item_id
2934     	  AND    number4 = C_DATE_ON;
2935 
2936 	  V_ERROR_LINE := 12;
2937 
2938 	END IF;
2939       END LOOP;
2940 
2941       SELECT number5
2942       INTO   v_finish_flag
2943       FROM   mrp_form_query
2944       WHERE  number1 = fs_select_rec.primary_item_id
2945       AND    number4 = C_DATE_ON
2946       AND    query_id = v_query_id;
2947 
2948       V_ERROR_LINE := 13;
2949 
2950       IF v_finish_flag = C_COMPLETE THEN
2951 	EXIT;
2952       END IF;
2953 
2954       -- If there is no entry in the completion time table for the date
2955       -- initialize it with the start time
2956 
2957       IF p_time_tab.EXISTS(v_current_date) = FALSE THEN
2958         SELECT start_time
2959         INTO   v_final_time
2960         FROM   wip_lines
2961         WHERE  line_id = p_line_id
2962           AND  organization_id = p_org_id;
2963 
2964 	V_ERROR_LINE := 14;
2965 
2966 	p_time_tab(v_current_date).start_completion_time := v_final_time;
2967 
2968       END IF;
2969 
2970       IF v_remain_qty <= v_alloc_qty THEN
2971 
2972 	v_required_time := TRUNC(v_remain_qty * 3600/v_hr_line_rate);
2973         if (p_time_tab(v_current_date).start_completion_time+v_required_time > p_time_tab(v_current_date).end_completion_time) then
2974           v_required_time := p_time_tab(v_current_date).end_completion_time -
2975                              p_time_tab(v_current_date).start_completion_time;
2976         end if;
2977 
2978         v_completion_time := to_date(v_current_date,'J') +
2979         ((p_time_tab(v_current_date).start_completion_time+v_required_time)/86400);
2980 
2981 	l_lead_time := l_fixed_lead_time +
2982 		      (l_variable_lead_time * (v_remain_qty-1));
2983 
2984         IF l_lead_time = 0 THEN
2985           v_begin_time := v_completion_time;
2986         ELSE
2987 	  v_begin_time := mrp_line_schedule_algorithm.calculate_begin_time(
2988 				p_org_id,
2989 				v_completion_time,
2990 				l_lead_time,
2991 				v_start_time,
2992 				v_end_time);
2993         END IF;
2994 
2995 
2996 	UPDATE wip_flow_schedules
2997 	SET    scheduled_start_date = v_begin_time,
2998 	           scheduled_completion_date = v_completion_time,
2999 	           scheduled_flag = C_YES
3000 	WHERE  wip_entity_id = v_current_wip
3001 	  AND  organization_id = p_org_id;
3002 
3003 	V_ERROR_LINE := 15;
3004 
3005         p_time_tab(v_current_date).start_completion_time :=
3006 	p_time_tab(v_current_date).start_completion_time + v_required_time;
3007 
3008 	-- Decrement remaining allocation quantity for the date by the
3009 	-- scheduled quantity
3010 
3011 	UPDATE mrp_form_query
3012   	SET    number2 = (SELECT number2 - v_remain_qty
3013 			  FROM   mrp_form_query
3014 			  WHERE  date1 = to_date(v_current_date,'J')
3015 			  AND    query_id = v_query_id
3016 			  AND    number1 = fs_select_rec.primary_item_id)
3017 	WHERE  date1 = to_date(v_current_date,'J')
3018     	AND    query_id = v_query_id
3019     	AND    number1 = fs_select_rec.primary_item_id;
3020 
3021 	V_ERROR_LINE := 16;
3022 
3023 	-- The entire flow schedule has been scheduled and the
3024 	-- remaining quantity = 0
3025 
3026 	v_remain_qty := 0;
3027 
3028       ELSIF v_remain_qty > v_alloc_qty THEN
3029 	v_required_time := TRUNC(v_alloc_qty * 3600/v_hr_line_rate);
3030         if (p_time_tab(v_current_date).start_completion_time+v_required_time > p_time_tab(v_current_date).end_completion_time) then
3031           v_required_time := p_time_tab(v_current_date).end_completion_time -
3032                              p_time_tab(v_current_date).start_completion_time;
3033         end if;
3034 
3035         v_completion_time := to_date(v_current_date,'J') +
3036         ((p_time_tab(v_current_date).start_completion_time+v_required_time)/86400);
3037 
3038 	l_lead_time := l_fixed_lead_time +
3039 		      (l_variable_lead_time * (v_alloc_qty-1));
3040 
3041         IF l_lead_time = 0 THEN
3042           v_begin_time := v_completion_time;
3043         ELSE
3044 	  v_begin_time := mrp_line_schedule_algorithm.calculate_begin_time(
3045 				p_org_id,
3046 				v_completion_time,
3047 				l_lead_time,
3048 				v_start_time,
3049 				v_end_time);
3050         END IF;
3051 
3052 
3053 	UPDATE wip_flow_schedules
3054 	SET      scheduled_start_date = v_begin_time,
3055 	           scheduled_completion_date = v_completion_time,
3056 	           planned_quantity = v_alloc_qty,
3057 	           scheduled_flag = C_YES
3058 	WHERE  wip_entity_id = v_current_wip
3059 	  AND  organization_id = p_org_id;
3060 
3061 	V_ERROR_LINE := 17;
3062 
3063         p_time_tab(v_current_date).start_completion_time :=
3064 	  p_time_tab(v_current_date).start_completion_time + v_required_time;
3065 
3066 	-- Create a new flow schedule to carry over the unscheduled quantity
3067         SELECT wip_entities_s.nextval
3068         INTO   v_temp
3069         FROM   dual;
3070 
3071 	V_ERROR_LINE := 18;
3072 
3073         --Bug 6122344
3074         --v_schedule_number := NVL(substr(FND_PROFILE.value('WIP_JOB_PREFIX'),1,20),'X')
3075 	--		|| to_char(v_temp);
3076         v_schedule_number := 'FLM-INTERNAL'|| to_char(v_temp);
3077 
3078    	INSERT INTO wip_flow_schedules(
3079 				scheduled_flag,
3080 				wip_entity_id,
3081 				organization_id,
3082 				last_update_date,
3083 				last_updated_by,
3084 				creation_date,
3085 				created_by,
3086 				class_code,
3087 				line_id,
3088 				primary_item_id,
3089 				scheduled_start_date,
3090 				planned_quantity,
3091 				quantity_completed,
3092 				quantity_scrapped,
3093 				scheduled_completion_date,
3094 				schedule_group_id,
3095 				status,
3096 				schedule_number,
3097 				demand_source_header_id,
3098 				demand_source_line,
3099 				demand_source_delivery,
3100 				demand_source_type,
3101 				project_id,
3102 				task_id,
3103 				end_item_unit_number,
3104                                 request_id,
3105                                 attribute1,
3106                                 attribute2,
3107                                 attribute3,
3108                                 attribute4,
3109                                 attribute5,
3110                                 attribute6,
3111                                 attribute7,
3112                                 attribute8,
3113                                 attribute9,
3114                                 attribute10,
3115                                 attribute11,
3116                                 attribute12,
3117                                 attribute13,
3118                                 attribute14,
3119                                 attribute15,
3120                                 material_account,
3121                                 material_overhead_account,
3122                                 resource_account,
3123                                 outside_processing_account,
3124                                 material_variance_account,
3125                                 resource_variance_account,
3126                                 outside_proc_variance_account,
3127                                 std_cost_adjustment_account,
3128                                 overhead_account,
3129                                 overhead_variance_account,
3130                                 bom_revision,   /* Added for bug 2185087 */
3131                                 routing_revision,
3132                                 bom_revision_date,
3133                                 routing_revision_date,
3134                                 alternate_bom_designator,
3135                                 alternate_routing_designator,
3136                                 completion_subinventory,
3137                                 completion_locator_id,
3138                                 demand_class,
3139                                 attribute_category,
3140                                 kanban_card_id)
3141 
3142 	SELECT			C_NO,
3143 				v_temp,
3144 				p_org_id,
3145 				SYSDATE,
3146 				fs.last_updated_by,
3147 				SYSDATE,
3148 				fs.created_by,
3149 				fs.class_code,
3150 				fs.line_id,
3151 				fs.primary_item_id,
3152 				to_date(v_current_date,'J'),
3153 				v_remain_qty - v_alloc_qty,
3154 				0,
3155 				0,
3156 				to_date(v_current_date,'J'),
3157 				fs.schedule_group_id,
3158 				fs.status,
3159 				v_schedule_number,
3160 				fs.demand_source_header_id,
3161 			       	fs.demand_source_line,
3162 			     	fs.demand_source_delivery,
3163 				fs.demand_source_type,
3164 				fs.project_id,
3165 				fs.task_id,
3166 				fs.end_item_unit_number,
3167 				USERENV('SESSIONID'),
3168                                 fs.attribute1,
3169                                 fs.attribute2,
3170                                 fs.attribute3,
3171                                 fs.attribute4,
3172                                 fs.attribute5,
3173                                 fs.attribute6,
3174                                 fs.attribute7,
3175                                 fs.attribute8,
3176                                 fs.attribute9,
3177                                 fs.attribute10,
3178                                 fs.attribute11,
3179                                 fs.attribute12,
3180                                 fs.attribute13,
3181                                 fs.attribute14,
3182                                 fs.attribute15,
3183                                 fs.material_account,
3184                                 fs.material_overhead_account,
3185                                 fs.resource_account,
3186                                 fs.outside_processing_account,
3187                                 fs.material_variance_account,
3188                                 fs.resource_variance_account,
3189                                 fs.outside_proc_variance_account,
3190                                 fs.std_cost_adjustment_account,
3191                                 fs.overhead_account,
3192                                 fs.overhead_variance_account,
3193                                 fs.bom_revision,  /* added for bug 2185087 */
3194                                 fs.routing_revision,
3195                                 fs.bom_revision_date,
3196                                 fs.routing_revision_date,
3197                                 fs.alternate_bom_designator,
3198                                 fs.alternate_routing_designator,
3199                                 fs.completion_subinventory,
3200                                 fs.completion_locator_id,
3201                                 fs.demand_class,
3202                                 fs.attribute_category,
3203                                 fs.kanban_card_id
3204 	FROM  wip_flow_schedules fs
3205 	WHERE fs.wip_entity_id = fs_select_rec.wip_entity
3206 	  AND organization_id = p_org_id;
3207 
3208 	V_ERROR_LINE := 19;
3209 
3210 	-- Reset the remaining quantity to be scheduled as the
3211 	-- left over quantity from the last flow schedule.
3212 
3213 	v_remain_qty := v_remain_qty - v_alloc_qty;
3214 
3215 	-- Set the remaining allocation for current date to 0.
3216 
3217 	v_alloc_qty := 0;
3218 
3219 	-- Point to the newly created flow schedule in order to
3220 	-- schedule the quantity.
3221 
3222 	v_current_wip := v_temp;
3223       END IF;
3224     END LOOP;
3225 
3226   END LOOP;
3227 
3228   IF (dbms_sql.is_open(cursor_name)) THEN
3229     dbms_sql.close_cursor(cursor_name);
3230   END IF;
3231 
3232 EXCEPTION
3233   WHEN NO_DATA_FOUND THEN
3234     IF (dbms_sql.is_open(cursor_name)) THEN
3235       dbms_sql.close_cursor(cursor_name);
3236     END IF;
3237   RETURN;
3238 
3239   WHEN OTHERS THEN
3240 
3241     IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
3242       FND_MSG_PUB.Add_Exc_Msg(
3243 	V_PKG_NAME,V_PROCEDURE_NAME||': Line '||to_char(V_ERROR_LINE));
3244     END IF;
3245 
3246     IF (dbms_sql.is_open(cursor_name)) THEN
3247       dbms_sql.close_cursor(cursor_name);
3248     END IF;
3249 
3250     return;
3251 
3252 END schedule_orders_level;
3253 
3254 PROCEDURE update_buildseq(
3255 			p_line_id IN NUMBER,
3256 			p_org_id  IN NUMBER)
3257 
3258 IS
3259 
3260   v_build_seq 	NUMBER;
3261   v_null_build_seq NUMBER;
3262   v_build_seq_tab BuildSeqTabTyp;
3263 
3264 BEGIN
3265 
3266   V_PROCEDURE_NAME := 'Update_Buildseq';
3267   V_ERROR_LINE := 1;
3268 
3269   -- Obtain the maximum build sequence for each schedule group from scheduled
3270   -- flow schedules on the line.
3271   calculate_build_sequences(p_org_id, p_line_id, v_build_seq_tab);
3272 
3273   -- Obtain the maximum sequence for the null schedule group
3274   SELECT NVL(MAX(build_sequence),0)
3275   INTO   v_null_build_seq
3276   FROM   wip_flow_schedules fs
3277   WHERE  fs.schedule_group_id IS NULL
3278     AND  fs.line_id = p_line_id
3279     AND  fs.organization_id = p_org_id
3280     AND  scheduled_flag = C_YES;
3281 
3282   V_ERROR_LINE := 2;
3283 
3284 --  dbms_output.put_line('The max build sequence for null schedule group is: '||
3285 --	to_char(v_null_build_seq));
3286 
3287   FOR fs_list_rec IN fs_list(p_line_id,p_org_id) LOOP
3288     -- Get the next build sequence for the schedule group of the current
3289       -- flow schedule.
3290 
3291 --      dbms_output.put_line('The flow schedule is: '||
3292 --	to_char(fs_list_rec.wip_entity_id));
3293 --      dbms_output.put_line('The schedule group id is: '||
3294 --	to_char(fs_list_rec.schedule_group_id));
3295 
3296       IF fs_list_rec.schedule_group_id IS NOT NULL THEN
3297 	v_build_seq :=
3298 	v_build_seq_tab(fs_list_rec.schedule_group_id).buildseq + 1;
3299 	v_build_seq_tab(fs_list_rec.schedule_group_id).buildseq := v_build_seq;
3300 
3301 --	dbms_output.put_line('The build sequence is: '||to_char(v_build_seq));
3302       ELSE
3303 --	dbms_output.put_line('The schedule group is null.');
3304 	v_build_seq := v_null_build_seq + 1;
3305 	v_null_build_seq := v_build_seq;
3306 --  	dbms_output.put_line('The build sequence is: '||to_char(v_build_seq));
3307 
3308       END IF;
3309 
3310       UPDATE wip_flow_schedules
3311 	SET    build_sequence = v_build_seq
3312 	WHERE  wip_entity_id = fs_list_rec.wip_entity_id
3313 	  AND  organization_id = p_org_id;
3314 
3315       V_ERROR_LINE := 3;
3316 
3317   END LOOP;
3318 
3319 EXCEPTION
3320 
3321   WHEN OTHERS THEN
3322 
3323     IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
3324       FND_MSG_PUB.Add_Exc_Msg(
3325 	V_PKG_NAME,V_PROCEDURE_NAME||': Line '||to_char(V_ERROR_LINE));
3326     END IF;
3327 
3328     return;
3329 
3330 END update_buildseq;
3331 
3332 -- This procedure schedules the flow schedules using the mix model algorithm.
3333 -- The flow schedules are first temporarily populated in a pl/sql table
3334 -- and then written to the wip_flow_schedules table.
3335 
3336 PROCEDURE schedule_mix_model(
3337 				p_line_id IN NUMBER,
3338 				p_org_id  IN NUMBER,
3339 				p_rule_id IN NUMBER,
3340 				p_cap_tab IN CapTabTyp,
3341 				p_demand_tab IN OUT NOCOPY DemandTabTyp,
3342 				p_item_demand_tab IN ItemDemandTabTyp,
3343                                 p_time_tab IN OUT NOCOPY TimeTabTyp)
3344 
3345 
3346 IS
3347 
3348   v_hr_line_rate  	NUMBER;
3349   v_start_time	  	NUMBER;
3350   v_end_time	  	NUMBER;
3351   v_line_rate	  	NUMBER;
3352   v_build_seq_tab  	BuildSeqTabTyp;
3353   v_pattern	 	LONG;
3354   v_current_num	  	NUMBER;
3355   v_current_date	NUMBER;
3356   v_current_wip	   	NUMBER;
3357   v_position	  	NUMBER;
3358   fs_select_rec	  	fs_select_type;
3359   cursor_name     	INTEGER;
3360   v_last_wip		NUMBER;
3361   v_min_build_seq	NUMBER;
3362   v_current_cap		NUMBER;
3363   v_schedule_number	VARCHAR2(30);
3364   v_schedule_group	NUMBER;
3365   v_sequence		NUMBER;
3366   v_flow_schedule_tab	FlowScheduleTabTyp;
3367   v_update_date		DATE;
3368   v_updated_by		NUMBER;
3369   v_creation_date	DATE;
3370   v_created_by		NUMBER;
3371   v_class_code		VARCHAR2(10);
3372   v_status		NUMBER;
3373   v_schedule		VARCHAR2(30);
3374   v_header_id 		NUMBER;
3375   v_source_line		VARCHAR2(30);
3376   v_source_delivery	VARCHAR2(30);
3377   v_current_schedule	NUMBER;
3378   v_build_seq	   	NUMBER;
3379   v_null_build_seq 	NUMBER;
3380   v_planned_quantity 	NUMBER;
3381   v_final_time	   	NUMBER;
3382   v_required_time  	NUMBER;
3383   v_completion_time 	DATE;
3384   v_begin_time	    	DATE;
3385   v_source_type	   	NUMBER;
3386   v_project_id		NUMBER;
3387   v_task_id		NUMBER;
3388   v_end_item_unit_number VARCHAR2(30);
3389   v_temp	   	NUMBER;
3390   v_finish		NUMBER;
3391   l_fixed_lead_time	NUMBER;
3392   l_variable_lead_time	NUMBER;
3393   l_lead_time		NUMBER;
3394   v_attribute1          VARCHAR2(150);
3395   v_attribute2          VARCHAR2(150);
3396   v_attribute3          VARCHAR2(150);
3397   v_attribute4          VARCHAR2(150);
3398   v_attribute5          VARCHAR2(150);
3399   v_attribute6          VARCHAR2(150);
3400   v_attribute7          VARCHAR2(150);
3401   v_attribute8          VARCHAR2(150);
3402   v_attribute9          VARCHAR2(150);
3403   v_attribute10         VARCHAR2(150);
3404   v_attribute11         VARCHAR2(150);
3405   v_attribute12         VARCHAR2(150);
3406   v_attribute13         VARCHAR2(150);
3407   v_attribute14         VARCHAR2(150);
3408   v_attribute15         VARCHAR2(150);
3409   v_material_account            NUMBER;
3410   v_material_overhead_account   NUMBER;
3411   v_resource_account            NUMBER;
3412   v_outside_processing_account  NUMBER;
3413   v_material_variance_account   NUMBER;
3414   v_resource_variance_account   NUMBER;
3415   v_outside_proc_var_account    NUMBER;
3416   v_std_cost_adjustment_account NUMBER;
3417   v_overhead_account            NUMBER;
3418   v_overhead_variance_account   NUMBER;
3419   v_bom_revision             VARCHAR2(3);  /* Added for bug 2185087 */
3420   v_routing_revision         VARCHAR2(3);
3421   v_bom_revision_date     DATE ;
3422   v_routing_revision_date DATE ;
3423   v_alternate_bom_designator  VARCHAR2(10);
3424   v_alternate_routing_designator VARCHAR2(10);
3425   v_completion_subinventory      VARCHAR2(10);
3426   v_completion_locator_id        NUMBER;
3427   v_demand_class              VARCHAR2(30);
3428   v_attribute_category        VARCHAR2(30);
3429   v_kanban_card_id            NUMBER;
3430 
3431 
3432 BEGIN
3433 
3434   V_PROCEDURE_NAME := 'Schedule_mix_model';
3435   V_ERROR_LINE := 1;
3436 
3437 --  dbms_output.put_line('Beginning of mix model procedure ...');
3438 
3439   -- Obtain information on the start time and end time of the line for
3440   -- time stamping flow schedules.
3441 
3442   SELECT maximum_rate, start_time, stop_time
3443   INTO   v_hr_line_rate, v_start_time, v_end_time
3444   FROM   wip_lines
3445   WHERE  line_id = p_line_id
3446     AND  organization_id = p_org_id;
3447 
3448   V_ERROR_LINE := 2;
3449 
3450   -- Fix bug 939061, add 24 hrs to stop_time if stop_time <= start_time
3451   if (v_end_time <= v_start_time) then
3452     v_end_time := v_end_time+24*3600;
3453   end if;
3454   v_line_rate := TRUNC(v_hr_line_rate * (v_end_time - v_start_time)/3600);
3455 
3456   -- New and existing flow schedules will be time stamped and
3457   -- scheduled before existing wip jobs and repetitive schedules.
3458 
3459   -- Order the existing flow schedules by schedule group id and build sequence
3460   -- and assign the appropriate time stamps to these flow schedules first.
3461 
3462 --    dbms_output.put_line('Time stamping existing flow schedules');
3463 
3464 --    MRP_UTIL.MRP_TIMING('Before taking care of existing flow schedules');
3465 --  time_existing_fs(p_org_id, p_line_id, p_cap_tab, v_time_tab);
3466 
3467 --     MRP_UTIL.MRP_TIMING('After taking care of existing flow schedules');
3468 --    dbms_output.put_line('Establishing the mix model pattern');
3469 
3470 --    MRP_UTIL.MRP_TIMING('Before establishing mix model');
3471   v_pattern := mix_model(p_item_demand_tab);
3472 
3473 --    MRP_UTIL.MRP_TIMING('After establishing mix model');
3474 --  dbms_output.put_line('After establishing mix model');
3475 
3476 --    dbms_output.put_line('The pattern is: '||v_pattern);
3477 
3478     -- Trim off the first asterisk
3479   v_pattern := LTRIM(v_pattern,'*');
3480 --    dbms_output.put_line('The pattern is now: '||v_pattern);
3481 
3482   V_ERROR_LINE := 3;
3483 
3484 --    MRP_UTIL.MRP_TIMING('Before establishing main cursor');
3485   cursor_name := Create_Cursor(p_rule_id, p_org_id, p_line_id, C_ASC,
3486 	C_NORM, C_NORM);
3487 
3488 --    MRP_UTIL.MRP_TIMING('After creating main cursor');
3489 
3490   V_ERROR_LINE := 4;
3491 
3492     -- In this loop, populate build sequences of all flow schedules to
3493     -- be scheduled.
3494 
3495   LOOP
3496     IF dbms_sql.fetch_rows(cursor_name) > 0 THEN
3497         dbms_sql.column_value(cursor_name,1, fs_select_rec.wip_entity);
3498         dbms_sql.column_value(cursor_name,6, fs_select_rec.planning_priority);
3499         dbms_sql.column_value(cursor_name,7, fs_select_rec.primary_item_id);
3500         dbms_sql.column_value(cursor_name,8, fs_select_rec.planned_quantity);
3501         dbms_sql.column_value(cursor_name,9, fs_select_rec.schedule_group_id);
3502     END IF;
3503 
3504 
3505 
3506     IF v_last_wip = fs_select_rec.wip_entity THEN
3507       EXIT;
3508     END IF;
3509 
3510     v_last_wip := fs_select_rec.wip_entity;
3511 
3512 --      dbms_output.put_line('Inside the cursor loop');
3513 
3514       -- Order the flow schedules by the item id by populating the order in
3515       -- the build sequence column.  The latest sequence for the item is stored
3516       -- in the v_item_demand_tab table.
3517 
3518     v_sequence :=
3519 	p_demand_tab(fs_select_rec.primary_item_id).sequence + 1;
3520 	p_demand_tab(fs_select_rec.primary_item_id).sequence := v_sequence;
3521 
3522 --      dbms_output.put_line('The item is: '||to_char(fs_select_rec.primary_item_id));
3523 --      dbms_output.put_line('The sequence is: '||to_char(v_sequence));
3524 
3525 --      MRP_UTIL.MRP_TIMING('Inside cursor loop, BEGIN update flow schedule');
3526 
3527     UPDATE wip_flow_schedules
3528     SET    build_sequence = v_sequence
3529     WHERE  wip_entity_id = fs_select_rec.wip_entity
3530     AND    organization_id = p_org_id;
3531 
3532 --      MRP_UTIL.MRP_TIMING('Inside cursor loop, FINISH update flow schedule');
3533 
3534     V_ERROR_LINE := 5;
3535 
3536   END LOOP;
3537 
3538   -- Reset sequence of all item to 1 to be used for keeping track of latest
3539   -- sequence for an item to be scheduled.
3540 
3541   FOR item_list_rec IN item_list(p_org_id) LOOP
3542     p_demand_tab(item_list_rec.primary_item_id).sequence := 1;
3543   END LOOP;
3544 
3545   IF (dbms_sql.is_open(cursor_name)) THEN
3546     dbms_sql.close_cursor(cursor_name);
3547   END IF;
3548 
3549   -- Set current date to be the first valid date in the scheduling window.
3550   -- This is the first index in the capacity table.
3551 
3552   v_current_date := p_cap_tab.FIRST;
3553   v_current_cap := p_cap_tab(v_current_date).capacity;
3554 
3555 --     dbms_output.put_line('First valid date in scheduling window is:' ||
3556 --    	to_date(v_current_date,'J'));
3557 --     dbms_output.put_line('Available capacity on this date is:' ||
3558 --       	to_char(v_current_cap));
3559 
3560   -- Obtain the maximum build sequence for each schedule group from scheduled
3561   -- flow schedules on the line.
3562   calculate_build_sequences(p_org_id, p_line_id, v_build_seq_tab);
3563 
3564   -- Obtain the maximum sequence for the null schedule group
3565   SELECT NVL(MAX(build_sequence),0)
3566   INTO   v_null_build_seq
3567   FROM   wip_flow_schedules fs
3568   WHERE  fs.schedule_group_id IS NULL
3569   AND    fs.line_id = p_line_id
3570   AND    fs.organization_id = p_org_id
3571   AND    scheduled_flag = C_YES;
3572 
3573 --    MRP_UTIL.MRP_TIMING('BEGIN OF GOING THROUGH MIX MODEL PATTERN');
3574   WHILE instr(v_pattern,'*') <> 0 LOOP
3575 --      MRP_UTIL.MRP_TIMING('Find out pattern');
3576     IF v_finish = 1 THEN
3577 --    MRP_UTIL.MRP_TIMING('Finished');
3578       EXIT;
3579     END IF;
3580 
3581     WHILE v_current_cap = 0 LOOP
3582 
3583       IF v_current_date = p_cap_tab.LAST THEN
3584 --	  MRP_UTIL.MRP_TIMING('This is last day of scheduling window.');
3585         V_FINISH := 1;
3586 	EXIT;
3587       ELSE
3588 	v_current_date := p_cap_tab.NEXT(v_current_date);
3589         v_current_cap := p_cap_tab(v_current_date).capacity;
3590       END IF;
3591     END LOOP;
3592 
3593     IF v_finish = 1 THEN
3594 	EXIT;
3595     END IF;
3596 
3597     -- Find out the item that is to be scheduled next.
3598 
3599     v_position := instr(v_pattern,'*');
3600     v_current_num := TO_NUMBER(RTRIM(SUBSTR(v_pattern,1,v_position),'*'));
3601     v_pattern := SUBSTR(v_pattern,v_position+1);
3602     v_sequence := p_demand_tab(p_item_demand_tab(v_current_num).item).sequence;
3603 
3604 --     MRP_UTIL.MRP_TIMING('Inside pattern, BEGIN select statement');
3605 
3606     SELECT wip_entity_id,planned_quantity,schedule_group_id
3607     INTO   v_current_wip,v_planned_quantity,v_schedule_group
3608     FROM   wip_flow_schedules
3609     WHERE  primary_item_id = p_item_demand_tab(v_current_num).item
3610     AND    organization_id = p_org_id
3611     AND    line_id = p_line_id
3612     AND    scheduled_flag = C_NO
3613     AND    build_sequence = v_sequence
3614     AND    request_id = USERENV('SESSIONID')
3615     AND    rownum = 1
3616     AND    wip_entity_id >= G_WIP_ENTITY_ID;
3617 
3618     l_fixed_lead_time := p_item_demand_tab(v_current_num).fixed_lead_time;
3619     l_variable_lead_time := p_item_demand_tab(v_current_num).var_lead_time;
3620 
3621 --      MRP_UTIL.MRP_TIMING('Inside pattern, FINISH select statement');
3622 
3623     V_ERROR_LINE := 6;
3624 
3625     -- Get the next build sequence for the schedule group of the current
3626     -- flow schedule.
3627 
3628     IF v_schedule_group IS NOT NULL THEN
3629       v_build_seq :=
3630       v_build_seq_tab(v_schedule_group).buildseq + 1;
3631       v_build_seq_tab(v_schedule_group).buildseq := v_build_seq;
3632 
3633     ELSE
3634       v_build_seq := v_null_build_seq + 1;
3635       v_null_build_seq := v_build_seq;
3636     END IF;
3637 
3638     -- If the flow schedule has 1 or less than 1 unit to be scheduled
3639     IF v_planned_quantity <= 1 THEN
3640 
3641       -- If the capacity is less than what needs to be scheduled
3642 
3643       WHILE v_current_cap < v_planned_quantity LOOP
3644 	IF v_current_date = p_cap_tab.LAST THEN
3645 	  V_FINISH := 1;
3646 	  EXIT;
3647         ELSE
3648 	  v_current_date := p_cap_tab.NEXT(v_current_date);
3649 	  v_current_cap := p_cap_tab(v_current_date).capacity;
3650         END IF;
3651       END LOOP;
3652 
3653       IF v_finish = 1 THEN
3654 	  EXIT;
3655       END IF;
3656 
3657       -- If there is no entry in the completion time table for the date
3658       -- initialize it with the start time
3659 
3660       IF p_time_tab.EXISTS(v_current_date) = FALSE THEN
3661         SELECT start_time
3662         INTO   v_final_time
3663         FROM   wip_lines
3664         WHERE  line_id = p_line_id
3665         AND  organization_id = p_org_id;
3666 
3667 	V_ERROR_LINE := 8;
3668 
3669 	p_time_tab(v_current_date).start_completion_time := v_final_time;
3670       END IF;
3671 
3672       v_required_time := v_planned_quantity*TRUNC(3600/v_hr_line_rate);
3673       if (p_time_tab(v_current_date).start_completion_time+v_required_time > p_time_tab(v_current_date).end_completion_time) then
3674         v_required_time := p_time_tab(v_current_date).end_completion_time -
3675                            p_time_tab(v_current_date).start_completion_time;
3676       end if;
3677 
3678 
3679       v_completion_time := to_date(v_current_date,'J') +
3680       ((p_time_tab(v_current_date).start_completion_time+v_required_time)/86400);
3681 
3682       l_lead_time := l_fixed_lead_time +
3683 		    (l_variable_lead_time * (v_planned_quantity-1));
3684 
3685       IF l_lead_time = 0 THEN
3686         v_begin_time := v_completion_time;
3687       ELSE
3688         v_begin_time := mrp_line_schedule_algorithm.calculate_begin_time(
3689 				p_org_id,
3690 				v_completion_time,
3691 				l_lead_time,
3692 				v_start_time,
3693 				v_end_time);
3694       END IF;
3695 
3696 
3697       p_time_tab(v_current_date).start_completion_time :=
3698       p_time_tab(v_current_date).start_completion_time + v_required_time;
3699 
3700 --	MRP_UTIL.MRP_TIMING('BEGIN select information');
3701 
3702       SELECT last_update_date, last_updated_by, creation_date, created_by,
3703 	     class_code, status, schedule_number, demand_source_header_id,
3704 	     demand_source_line, demand_source_delivery, demand_source_type,
3705 	     project_id, task_id, end_item_unit_number, attribute1, attribute2, attribute3, attribute4,
3706              attribute5, attribute6, attribute7, attribute8, attribute9, attribute10,
3707              attribute11, attribute12, attribute13, attribute14, attribute15,
3708              material_account, material_overhead_account, resource_account,
3709              outside_processing_account, material_variance_account, resource_variance_account,
3710              outside_proc_variance_account, std_cost_adjustment_account, overhead_account,
3711              overhead_variance_account,bom_revision,routing_revision,/*Added for bug2185087*/
3712              bom_revision_date, routing_revision_date,
3713              alternate_bom_designator, alternate_routing_designator,
3714              completion_subinventory,completion_locator_id,
3715              demand_class, attribute_category, kanban_card_id
3716       INTO   v_update_date, v_updated_by, v_creation_date, v_created_by,
3717 	       v_class_code, v_status, v_schedule, v_header_id, v_source_line,
3718 	       v_source_delivery, v_source_type, v_project_id, v_task_id, v_end_item_unit_number, v_attribute1,
3719              v_attribute2, v_attribute3, v_attribute4,
3720              v_attribute5, v_attribute6, v_attribute7, v_attribute8, v_attribute9, v_attribute10,
3721              v_attribute11, v_attribute12, v_attribute13, v_attribute14, v_attribute15,
3722              v_material_account, v_material_overhead_account, v_resource_account,
3723              v_outside_processing_account, v_material_variance_account, v_resource_variance_account,
3724              v_outside_proc_var_account, v_std_cost_adjustment_account, v_overhead_account,
3725              v_overhead_variance_account,v_bom_revision,v_routing_revision, /* 2185087*/
3726              v_bom_revision_date, v_routing_revision_date,
3727              v_alternate_bom_designator,v_alternate_routing_designator,
3728              v_completion_subinventory, v_completion_locator_id,
3729              v_demand_class, v_attribute_category,v_kanban_card_id
3730       FROM   wip_flow_schedules
3731       WHERE  wip_entity_id = v_current_wip
3732       AND    organization_id = p_org_id
3733       AND    request_id = userenv('sessionid')
3734       AND    wip_entity_id >= G_WIP_ENTITY_ID;
3735 
3736 --	MRP_UTIL.MRP_TIMING('BEGIN Insert');
3737 
3738 
3739       -- Insert into pl/sql table
3740       v_flow_schedule_tab(v_current_wip).scheduled_flag := C_YES;
3741       v_flow_schedule_tab(v_current_wip).organization_id := p_org_id;
3742       v_flow_schedule_tab(v_current_wip).last_update_date := v_update_date;
3743       v_flow_schedule_tab(v_current_wip).last_updated_by := v_updated_by;
3744       v_flow_schedule_tab(v_current_wip).creation_date := v_creation_date;
3745       v_flow_schedule_tab(v_current_wip).created_by := v_created_by;
3746       v_flow_schedule_tab(v_current_wip).class_code := v_class_code;
3747       v_flow_schedule_tab(v_current_wip).line_id := p_line_id;
3748       v_flow_schedule_tab(v_current_wip).primary_item_id
3749 		:= p_item_demand_tab(v_current_num).item;
3750       v_flow_schedule_tab(v_current_wip).scheduled_start_date := v_begin_time;
3751       v_flow_schedule_tab(v_current_wip).planned_quantity := v_planned_quantity;
3752       v_flow_schedule_tab(v_current_wip).quantity_completed := 0;
3753       v_flow_schedule_tab(v_current_wip).scheduled_completion_date := v_completion_time;
3754       v_flow_schedule_tab(v_current_wip).schedule_group_id := v_schedule_group;
3755       v_flow_schedule_tab(v_current_wip).build_sequence := v_build_seq;
3756       v_flow_schedule_tab(v_current_wip).status := v_status;
3757       v_flow_schedule_tab(v_current_wip).schedule_number := v_schedule;
3758       v_flow_schedule_tab(v_current_wip).demand_source_header_id := v_header_id;
3759       v_flow_schedule_tab(v_current_wip).demand_source_line := v_source_line;
3760       v_flow_schedule_tab(v_current_wip).demand_source_delivery := v_source_delivery;
3761       v_flow_schedule_tab(v_current_wip).demand_source_type := v_source_type;
3762       v_flow_schedule_tab(v_current_wip).project_id := v_project_id;
3763       v_flow_schedule_tab(v_current_wip).task_id := v_task_id;
3764       v_flow_schedule_tab(v_current_wip).end_item_unit_number := v_end_item_unit_number;
3765       v_flow_schedule_tab(v_current_wip).request_id := userenv('sessionid');
3766       v_flow_schedule_tab(v_current_wip).attribute1 := v_attribute1;
3767       v_flow_schedule_tab(v_current_wip).attribute2 := v_attribute2;
3768       v_flow_schedule_tab(v_current_wip).attribute3 := v_attribute3;
3769       v_flow_schedule_tab(v_current_wip).attribute4 := v_attribute4;
3770       v_flow_schedule_tab(v_current_wip).attribute5 := v_attribute5;
3771       v_flow_schedule_tab(v_current_wip).attribute6 := v_attribute6;
3772       v_flow_schedule_tab(v_current_wip).attribute7 := v_attribute7;
3773       v_flow_schedule_tab(v_current_wip).attribute8 := v_attribute8;
3774       v_flow_schedule_tab(v_current_wip).attribute9 := v_attribute9;
3775       v_flow_schedule_tab(v_current_wip).attribute10 := v_attribute10;
3776       v_flow_schedule_tab(v_current_wip).attribute11 := v_attribute11;
3777       v_flow_schedule_tab(v_current_wip).attribute12 := v_attribute12;
3778       v_flow_schedule_tab(v_current_wip).attribute13 := v_attribute13;
3779       v_flow_schedule_tab(v_current_wip).attribute14 := v_attribute14;
3780       v_flow_schedule_tab(v_current_wip).attribute15 := v_attribute15;
3781       v_flow_schedule_tab(v_current_wip).material_account := v_material_account;
3782       v_flow_schedule_tab(v_current_wip).material_overhead_account := v_material_overhead_account;
3783       v_flow_schedule_tab(v_current_wip).resource_account := v_resource_account;
3784       v_flow_schedule_tab(v_current_wip).outside_processing_account := v_outside_processing_account;
3785       v_flow_schedule_tab(v_current_wip).material_variance_account := v_material_variance_account;
3786       v_flow_schedule_tab(v_current_wip).resource_variance_account := v_resource_variance_account;
3787       v_flow_schedule_tab(v_current_wip).outside_proc_var_account := v_outside_proc_var_account;
3788       v_flow_schedule_tab(v_current_wip).std_cost_adjustment_account := v_std_cost_adjustment_account;
3789       v_flow_schedule_tab(v_current_wip).overhead_account := v_overhead_account;
3790       v_flow_schedule_tab(v_current_wip).overhead_variance_account := v_overhead_variance_account;
3791      /* Added for bug 2185087 */
3792       v_flow_schedule_tab(v_current_wip).bom_revision := v_bom_revision;
3793       v_flow_schedule_tab(v_current_wip).routing_revision := v_routing_revision;
3794       v_flow_schedule_tab(v_current_wip).bom_revision_date := v_bom_revision_date;
3795       v_flow_schedule_tab(v_current_wip).routing_revision_date := v_routing_revision_date;
3796       v_flow_schedule_tab(v_current_wip).alternate_bom_designator := v_alternate_bom_designator;
3797       v_flow_schedule_tab(v_current_wip).alternate_routing_designator := v_alternate_routing_designator;
3798       v_flow_schedule_tab(v_current_wip).completion_subinventory := v_completion_subinventory;
3799       v_flow_schedule_tab(v_current_wip).completion_locator_id := v_completion_locator_id;
3800       v_flow_schedule_tab(v_current_wip).demand_class := v_demand_class;
3801       v_flow_schedule_tab(v_current_wip).attribute_category := v_attribute_category;
3802       v_flow_schedule_tab(v_current_wip).kanban_card_id := v_kanban_card_id;
3803 
3804 --	MRP_UTIL.MRP_TIMING('END insert');
3805 
3806       DELETE
3807       FROM   wip_flow_schedules
3808       WHERE  wip_entity_id = v_current_wip
3809       AND    organization_id = p_org_id;
3810 
3811       V_ERROR_LINE := 9;
3812 
3813       v_current_cap := v_current_cap - v_planned_quantity;
3814       p_demand_tab(p_item_demand_tab(v_current_num).item).sequence :=
3815         p_demand_tab(p_item_demand_tab(v_current_num).item).sequence + 1;
3816 
3817     ELSE
3818 
3819       -- Create a new flow schedule since the flow schedule has quantity greater than 1.
3820 
3821       -- If the capacity of the current date is less than 1, then check
3822       -- capacity of subsequent dates
3823       WHILE v_current_cap < 1 LOOP
3824 	IF v_current_date = p_cap_tab.LAST THEN
3825 	  V_FINISH := 1;
3826 	  EXIT;
3827 	ELSE
3828 	  v_current_date := p_cap_tab.NEXT(v_current_date);
3829 	  v_current_cap := p_cap_tab(v_current_date).capacity;
3830 	END IF;
3831       END LOOP;
3832 
3833       IF v_finish = 1 THEN
3834        	EXIT;
3835       END IF;
3836 
3837       -- If there is no entry in the completion time table for the date
3838       -- initialize it with the start time
3839 
3840       IF p_time_tab.EXISTS(v_current_date) = FALSE THEN
3841         SELECT start_time
3842         INTO   v_final_time
3843         FROM   wip_lines
3844         WHERE  line_id = p_line_id
3845         AND  organization_id = p_org_id;
3846 
3847 	V_ERROR_LINE := 10;
3848 
3849 	p_time_tab(v_current_date).start_completion_time := v_final_time;
3850       END IF;
3851 
3852       v_required_time := TRUNC(3600/v_hr_line_rate);
3853       if (p_time_tab(v_current_date).start_completion_time+v_required_time > p_time_tab(v_current_date).end_completion_time) then
3854         v_required_time := p_time_tab(v_current_date).end_completion_time -
3855                            p_time_tab(v_current_date).start_completion_time;
3856       end if;
3857 
3858       v_completion_time := to_date(v_current_date,'J') +
3859       ((p_time_tab(v_current_date).start_completion_time+v_required_time)/86400);
3860 
3861       -- planned quantity will be '1'
3862       l_lead_time := l_fixed_lead_time ;
3863 
3864       IF l_lead_time = 0 THEN
3865         v_begin_time := v_completion_time;
3866       ELSE
3867         v_begin_time := mrp_line_schedule_algorithm.calculate_begin_time(
3868 				p_org_id,
3869 				v_completion_time,
3870 				l_lead_time,
3871 				v_start_time,
3872 				v_end_time);
3873       END IF;
3874 
3875 
3876       p_time_tab(v_current_date).start_completion_time :=
3877 	p_time_tab(v_current_date).start_completion_time + v_required_time;
3878 
3879       SELECT wip_entities_s.nextval
3880       INTO   v_temp
3881       FROM   dual;
3882 
3883       V_ERROR_LINE := 11;
3884 
3885       --Bug 6122344
3886       --v_schedule_number := NVL(substr(FND_PROFILE.value('WIP_JOB_PREFIX'),1,20),'X')
3887       --	|| to_char(v_temp);
3888       v_schedule_number := 'FLM-INTERNAL'|| to_char(v_temp);
3889 
3890 
3891 --        dbms_output.put_line('The schedule number is: '||v_schedule_number);
3892 
3893 
3894 --	MRP_UTIL.MRP_TIMING('BEGIN select information');
3895       SELECT last_update_date, last_updated_by, creation_date, created_by,
3896 	     class_code, status, schedule_number, demand_source_header_id,
3897 	     demand_source_line, demand_source_delivery, demand_source_type,
3898 	     project_id, task_id, end_item_unit_number, attribute1, attribute2, attribute3, attribute4,
3899              attribute5, attribute6, attribute7, attribute8, attribute9, attribute10,
3900              attribute11, attribute12, attribute13, attribute14, attribute15,
3901              material_account, material_overhead_account, resource_account,
3902              outside_processing_account, material_variance_account, resource_variance_account,
3903              outside_proc_variance_account, std_cost_adjustment_account, overhead_account,
3904              overhead_variance_account,bom_revision,routing_revision , /*2185087 */
3905              bom_revision_date, routing_revision_date,
3906              alternate_bom_designator, alternate_routing_designator,
3907              completion_subinventory, completion_locator_id,
3908              demand_class,attribute_category, kanban_card_id
3909       INTO   v_update_date, v_updated_by, v_creation_date, v_created_by,
3910 	       v_class_code, v_status, v_schedule, v_header_id, v_source_line,
3911 	       v_source_delivery, v_source_type, v_project_id, v_task_id, v_end_item_unit_number,
3912              v_attribute1, v_attribute2, v_attribute3, v_attribute4,
3913              v_attribute5, v_attribute6, v_attribute7, v_attribute8, v_attribute9, v_attribute10,
3914              v_attribute11, v_attribute12, v_attribute13, v_attribute14, v_attribute15,
3915              v_material_account, v_material_overhead_account, v_resource_account,
3916              v_outside_processing_account, v_material_variance_account, v_resource_variance_account,
3917              v_outside_proc_var_account, v_std_cost_adjustment_account, v_overhead_account,
3918              v_overhead_variance_account,v_bom_revision,v_routing_revision, /*2185087*/
3919              v_bom_revision_date, v_routing_revision_date,
3920              v_alternate_bom_designator,v_alternate_routing_designator,
3921              v_completion_subinventory, v_completion_locator_id,
3922              v_demand_class, v_attribute_category, v_kanban_card_id
3923       FROM   wip_flow_schedules
3924       WHERE  wip_entity_id = v_current_wip
3925       AND    organization_id = p_org_id;
3926 
3927 --	MRP_UTIL.MRP_TIMING('BEGIN insert');
3928 
3929       -- Insert into pl/sql table
3930 
3931       v_flow_schedule_tab(v_temp).scheduled_flag := C_YES;
3932       v_flow_schedule_tab(v_temp).organization_id := p_org_id;
3933       v_flow_schedule_tab(v_temp).last_update_date := v_update_date;
3934       v_flow_schedule_tab(v_temp).last_updated_by := v_updated_by;
3935       v_flow_schedule_tab(v_temp).creation_date := v_creation_date;
3936       v_flow_schedule_tab(v_temp).created_by := v_created_by;
3937       v_flow_schedule_tab(v_temp).class_code := v_class_code;
3938       v_flow_schedule_tab(v_temp).line_id := p_line_id;
3939       v_flow_schedule_tab(v_temp).primary_item_id := p_item_demand_tab(v_current_num).item;
3940       v_flow_schedule_tab(v_temp).scheduled_start_date := v_begin_time;
3941       v_flow_schedule_tab(v_temp).planned_quantity := 1;
3942       v_flow_schedule_tab(v_temp).quantity_completed := 0;
3943       v_flow_schedule_tab(v_temp).scheduled_completion_date := v_completion_time;
3944       v_flow_schedule_tab(v_temp).schedule_group_id := v_schedule_group;
3945       v_flow_schedule_tab(v_temp).build_sequence := v_build_seq;
3946       v_flow_schedule_tab(v_temp).status := v_status;
3947       v_flow_schedule_tab(v_temp).schedule_number := v_schedule_number;
3948       v_flow_schedule_tab(v_temp).demand_source_header_id := v_header_id;
3949       v_flow_schedule_tab(v_temp).demand_source_line := v_source_line;
3950       v_flow_schedule_tab(v_temp).demand_source_delivery := v_source_delivery;
3951       v_flow_schedule_tab(v_temp).demand_source_type := v_source_type;
3952       v_flow_schedule_tab(v_temp).project_id := v_project_id;
3953       v_flow_schedule_tab(v_temp).task_id := v_task_id;
3954       v_flow_schedule_tab(v_temp).end_item_unit_number := v_end_item_unit_number;
3955       v_flow_schedule_tab(v_temp).request_id := userenv('sessionid');
3956       v_flow_schedule_tab(v_temp).attribute1 := v_attribute1;
3957       v_flow_schedule_tab(v_temp).attribute2 := v_attribute2;
3958       v_flow_schedule_tab(v_temp).attribute3 := v_attribute3;
3959       v_flow_schedule_tab(v_temp).attribute4 := v_attribute4;
3960       v_flow_schedule_tab(v_temp).attribute5 := v_attribute5;
3961       v_flow_schedule_tab(v_temp).attribute6 := v_attribute6;
3962       v_flow_schedule_tab(v_temp).attribute7 := v_attribute7;
3963       v_flow_schedule_tab(v_temp).attribute8 := v_attribute8;
3964       v_flow_schedule_tab(v_temp).attribute9 := v_attribute9;
3965       v_flow_schedule_tab(v_temp).attribute10 := v_attribute10;
3966       v_flow_schedule_tab(v_temp).attribute11 := v_attribute11;
3967       v_flow_schedule_tab(v_temp).attribute12 := v_attribute12;
3968       v_flow_schedule_tab(v_temp).attribute13 := v_attribute13;
3969       v_flow_schedule_tab(v_temp).attribute14 := v_attribute14;
3970       v_flow_schedule_tab(v_temp).attribute15 := v_attribute15;
3971       v_flow_schedule_tab(v_temp).material_account := v_material_account;
3972       v_flow_schedule_tab(v_temp).material_overhead_account := v_material_overhead_account;
3973       v_flow_schedule_tab(v_temp).resource_account := v_resource_account;
3974       v_flow_schedule_tab(v_temp).outside_processing_account := v_outside_processing_account;
3975       v_flow_schedule_tab(v_temp).material_variance_account := v_material_variance_account;
3976       v_flow_schedule_tab(v_temp).resource_variance_account := v_resource_variance_account;
3977       v_flow_schedule_tab(v_temp).outside_proc_var_account := v_outside_proc_var_account;
3978       v_flow_schedule_tab(v_temp).std_cost_adjustment_account := v_std_cost_adjustment_account;
3979       v_flow_schedule_tab(v_temp).overhead_account := v_overhead_account;
3980       v_flow_schedule_tab(v_temp).overhead_variance_account := v_overhead_variance_account;
3981       v_flow_schedule_tab(v_temp).bom_revision := v_bom_revision; /*2185087 */
3982       v_flow_schedule_tab(v_temp).routing_revision := v_routing_revision;
3983       v_flow_schedule_tab(v_temp).bom_revision_date := v_bom_revision_date;
3984       v_flow_schedule_tab(v_temp).routing_revision_date := v_routing_revision_date;
3985       v_flow_schedule_tab(v_temp).alternate_bom_designator := v_alternate_bom_designator;
3986       v_flow_schedule_tab(v_temp).alternate_routing_designator := v_alternate_routing_designator;
3987       v_flow_schedule_tab(v_temp).completion_subinventory := v_completion_subinventory;
3988       v_flow_schedule_tab(v_temp).completion_locator_id := v_completion_locator_id;
3989       v_flow_schedule_tab(v_temp).demand_class := v_demand_class;
3990       v_flow_schedule_tab(v_temp).attribute_category := v_attribute_category;
3991       v_flow_schedule_tab(v_temp).kanban_card_id := v_kanban_card_id;
3992 
3993 
3994 
3995 --	MRP_UTIL.MRP_TIMING('end insert');
3996 
3997       UPDATE wip_flow_schedules
3998       SET    planned_quantity = planned_quantity - 1
3999       WHERE  wip_entity_id = v_current_wip
4000       AND    organization_id = p_org_id;
4001 
4002 --	MRP_UTIL.MRP_TIMING('end update');
4003 
4004       V_ERROR_LINE := 12;
4005 
4006     -- Decrement capacity on the line for the current date by the scheduled quantity.
4007 
4008     v_current_cap := v_current_cap - 1;
4009 
4010     END IF;
4011 
4012 
4013 --    dbms_output.put_line('Capacity on '||to_date(v_current_date,'J')||' = '||
4014 --	  to_char(v_current_cap));
4015 
4016   END LOOP;
4017 
4018   -- Insert flow schedules from pl/sql table to wip flow schedules table.
4019 
4020   v_current_schedule := v_flow_schedule_tab.FIRST;
4021 
4022 --    MRP_UTIL.MRP_TIMING('BEGIN INSERTING INTO wip flow schedules table');
4023 
4024   WHILE v_current_schedule IS NOT NULL LOOP
4025 
4026 --    MRP_UTIL.MRP_TIMING('Begin insert');
4027 
4028     INSERT INTO wip_flow_schedules(
4029 				scheduled_flag,
4030 				wip_entity_id,
4031 				organization_id,
4032 				last_update_date,
4033 				last_updated_by,
4034 				creation_date,
4035 				created_by,
4036 				class_code,
4037 				line_id,
4038 				primary_item_id,
4039 				scheduled_start_date,
4040 				planned_quantity,
4041 				quantity_completed,
4042 				quantity_scrapped,
4043 				scheduled_completion_date,
4044 				schedule_group_id,
4045 				build_sequence,
4046 				status,
4047 				schedule_number,
4048 				demand_source_header_id,
4049 				demand_source_line,
4050 				demand_source_delivery,
4051 				demand_source_type,
4052 				project_id,
4053 				task_id,
4054 				end_item_unit_number,
4055                                 request_id,
4056                                 attribute1,
4057                                 attribute2,
4058                                 attribute3,
4059                                 attribute4,
4060                                 attribute5,
4061                                 attribute6,
4062                                 attribute7,
4063                                 attribute8,
4064                                 attribute9,
4065                                 attribute10,
4066                                 attribute11,
4067                                 attribute12,
4068                                 attribute13,
4069                                 attribute14,
4070                                 attribute15,
4071                                 material_account,
4072                                 material_overhead_account,
4073                                 resource_account,
4074                                 outside_processing_account,
4075                                 material_variance_account,
4076                                 resource_variance_account,
4077                                 outside_proc_variance_account,
4078                                 std_cost_adjustment_account,
4079                                 overhead_account,
4080                                 overhead_variance_account,
4081                                 bom_revision,   /* 2185087 */
4082                                 routing_revision,
4083                                 bom_revision_date,
4084                                 routing_revision_date,
4085                                 alternate_bom_designator,
4086                                 alternate_routing_designator,
4087                                 completion_subinventory,
4088                                 completion_locator_id,
4089                                 demand_class,
4090                                 attribute_category,
4091                                 kanban_card_id)
4092     VALUES (
4093 				v_flow_schedule_tab(v_current_schedule).scheduled_flag,
4094 				v_current_schedule,
4095 				v_flow_schedule_tab(v_current_schedule).organization_id,
4096 				v_flow_schedule_tab(v_current_schedule).last_update_date,
4097 				v_flow_schedule_tab(v_current_schedule).last_updated_by,
4098 				v_flow_schedule_tab(v_current_schedule).creation_date,
4099 				v_flow_schedule_tab(v_current_schedule).created_by,
4100 				v_flow_schedule_tab(v_current_schedule).class_code,
4101 				v_flow_schedule_tab(v_current_schedule).line_id,
4102 				v_flow_schedule_tab(v_current_schedule).primary_item_id,
4103 				v_flow_schedule_tab(v_current_schedule).scheduled_start_date,
4104 				v_flow_schedule_tab(v_current_schedule).planned_quantity,
4105 				v_flow_schedule_tab(v_current_schedule).quantity_completed,
4106 				0,
4107 				v_flow_schedule_tab(v_current_schedule).scheduled_completion_date,
4108 				v_flow_schedule_tab(v_current_schedule).schedule_group_id,
4109 				v_flow_schedule_tab(v_current_schedule).build_sequence,
4110 				v_flow_schedule_tab(v_current_schedule).status,
4111 				v_flow_schedule_tab(v_current_schedule).schedule_number,
4112 				v_flow_schedule_tab(v_current_schedule).demand_source_header_id,
4113 				v_flow_schedule_tab(v_current_schedule).demand_source_line,
4114 				v_flow_schedule_tab(v_current_schedule).demand_source_delivery,
4115 				v_flow_schedule_tab(v_current_schedule).demand_source_type,
4116 				v_flow_schedule_tab(v_current_schedule).project_id,						   v_flow_schedule_tab(v_current_schedule).task_id,
4117 				v_flow_schedule_tab(v_current_schedule).end_item_unit_number,
4118                                 userenv('sessionid'),
4119                                 v_flow_schedule_tab(v_current_schedule).attribute1,
4120                                 v_flow_schedule_tab(v_current_schedule).attribute2,
4121                                 v_flow_schedule_tab(v_current_schedule).attribute3,
4122                                 v_flow_schedule_tab(v_current_schedule).attribute4,
4123                                 v_flow_schedule_tab(v_current_schedule).attribute5,
4124                                 v_flow_schedule_tab(v_current_schedule).attribute6,
4125                                 v_flow_schedule_tab(v_current_schedule).attribute7,
4126                                 v_flow_schedule_tab(v_current_schedule).attribute8,
4127                                 v_flow_schedule_tab(v_current_schedule).attribute9,
4128                                 v_flow_schedule_tab(v_current_schedule).attribute10,
4129                                 v_flow_schedule_tab(v_current_schedule).attribute11,
4130                                 v_flow_schedule_tab(v_current_schedule).attribute12,
4131                                 v_flow_schedule_tab(v_current_schedule).attribute13,
4132                                 v_flow_schedule_tab(v_current_schedule).attribute14,
4133                                 v_flow_schedule_tab(v_current_schedule).attribute15,
4134                                 v_flow_schedule_tab(v_current_schedule).material_account,
4135                                 v_flow_schedule_tab(v_current_schedule).material_overhead_account,
4136                                 v_flow_schedule_tab(v_current_schedule).resource_account,
4137                                 v_flow_schedule_tab(v_current_schedule).outside_processing_account,
4138                                 v_flow_schedule_tab(v_current_schedule).material_variance_account,
4139                                 v_flow_schedule_tab(v_current_schedule).resource_variance_account,
4140                                 v_flow_schedule_tab(v_current_schedule).outside_proc_var_account,
4141                                 v_flow_schedule_tab(v_current_schedule).std_cost_adjustment_account,
4142                                 v_flow_schedule_tab(v_current_schedule).overhead_account,
4143                                 v_flow_schedule_tab(v_current_schedule).overhead_variance_account,
4144                                 v_flow_schedule_tab(v_current_schedule).bom_revision, /*2185087*/
4145                                 v_flow_schedule_tab(v_current_schedule).routing_revision,
4146                                 v_flow_schedule_tab(v_current_schedule).bom_revision_date,
4147                                 v_flow_schedule_tab(v_current_schedule).routing_revision_date,
4148                                 v_flow_schedule_tab(v_current_schedule).alternate_bom_designator,
4149                                 v_flow_schedule_tab(v_current_schedule).alternate_routing_designator,
4150                                 v_flow_schedule_tab(v_current_schedule).completion_subinventory,
4151                                 v_flow_schedule_tab(v_current_schedule).completion_locator_id,
4152                                 v_flow_schedule_tab(v_current_schedule).demand_class,
4153                                 v_flow_schedule_tab(v_current_schedule).attribute_category,
4154                                 v_flow_schedule_tab(v_current_schedule).kanban_card_id
4155 
4156 );
4157 --      MRP_UTIL.MRP_TIMING('End of insert into wip flow schedules.');
4158 
4159     v_current_schedule := v_flow_schedule_tab.NEXT(v_current_schedule);
4160 
4161   END LOOP;
4162 
4163 EXCEPTION
4164   WHEN NO_DATA_FOUND THEN
4165     IF (dbms_sql.is_open(cursor_name)) THEN
4166     dbms_sql.close_cursor(cursor_name);
4167     END IF;
4168 
4169     RETURN;
4170 
4171   WHEN OTHERS THEN
4172 
4173     IF (dbms_sql.is_open(cursor_name)) THEN
4174       dbms_sql.close_cursor(cursor_name);
4175     END IF;
4176 
4177     IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
4178       FND_MSG_PUB.Add_Exc_Msg(
4179 	V_PKG_NAME,V_PROCEDURE_NAME||': Line '||to_char(V_ERROR_LINE));
4180     END IF;
4181 
4182     return;
4183 
4184 END schedule_mix_model;
4185 
4186 -- This procedure schedules the new flow schedules created from
4187 -- unscheduled orders on the line within the defined scheduling window.
4188 
4189 PROCEDURE Schedule(
4190 	             p_rule_id  IN NUMBER,
4191              	     p_line_id  IN NUMBER,
4192              	     p_org_id   IN NUMBER,
4193              	     p_scheduling_start_date IN DATE,
4194              	     p_scheduling_end_date   IN DATE,
4195              	     p_flex_tolerance   IN NUMBER,
4196 		     x_return_status OUT NOCOPY VARCHAR2,
4197 		     x_msg_count OUT NOCOPY NUMBER,
4198   		     x_msg_data  OUT NOCOPY VARCHAR2)
4199 IS
4200 
4201   v_algorithm      	NUMBER;
4202   v_start_date     	NUMBER;
4203   v_end_date       	NUMBER;
4204   v_cap_tab        	CapTabTyp;
4205   v_itemQty_tab	   	ItemQtyTabTyp;
4206   v_orderMod_tab   	OrderModTabTyp;
4207   v_item_alloc_tab 	ItemAllocTabTyp;
4208   v_early_date	   	DATE;
4209   v_num_flow       	NUMBER;
4210   v_item_id	   	NUMBER;
4211   v_order_quantity 	NUMBER;
4212   i 		   	NUMBER;
4213   v_source_type	   	NUMBER;
4214   v_current_item   	NUMBER;
4215   v_remain_qty	   	NUMBER;
4216   v_alloc_qty	   	NUMBER;
4217   v_item_demand_tab 	ItemDemandTabTyp;
4218   v_demand_tab	   	DemandTabTyp;
4219   v_time_tab            TimeTabTyp;
4220   v_start_time		NUMBER;
4221   v_end_time		NUMBER;
4222   v_bom_rev             VARCHAR2(3); /* Added for bug 2977987 */
4223   v_bom_rev_date        DATE;
4224   v_rout_rev            VARCHAR2(3);
4225   v_rout_rev_date       DATE;
4226 
4227 BEGIN
4228 
4229   SAVEPOINT MRP_begin_PVT;
4230 
4231   V_PROCEDURE_NAME := 'Schedule';
4232   V_ERROR_LINE := 1;
4233 
4234   -- Lets convert the schedule dates to julian format
4235   SELECT to_number(to_char(p_scheduling_start_date,'J')),
4236          to_number(to_char(p_scheduling_end_date,'J')),
4237          to_char(p_scheduling_start_date,'SSSSS'),
4238          to_char(p_scheduling_end_date,'SSSSS')
4239   INTO   v_start_date, v_end_date, v_start_time, v_end_time
4240   FROM   dual;
4241 
4242   -- Get the minimum wip_entity_id that having request id
4243 
4244   SELECT MIN(wip_entity_id)
4245   INTO G_WIP_ENTITY_ID
4246   FROM wip_flow_schedules
4247   WHERE line_id = p_line_id
4248     and organization_id = p_org_id
4249     and request_id =  USERENV('SESSIONID');
4250 
4251   -- Time stamp the existing flow schedules
4252   time_existing_fs(p_org_id, p_line_id, v_start_date, v_start_time,
4253                    v_end_date, v_end_time,  v_time_tab);
4254 
4255   -- First off, lets find the net capacity of the line in question
4256   -- Note that this procedure populates the plsql table
4257 
4258 --  MRP_UTIL.MRP_TIMING('Before calculating line capacity ...');
4259 
4260   calculate_linecap(
4261         p_line_id,
4262         p_org_id,
4263         p_flex_tolerance,
4264         v_cap_tab,
4265         v_time_tab,
4266 	v_start_date,
4267 	v_start_time,
4268 	v_end_date,
4269 	v_end_time);
4270 
4271 --  dbms_output.put_line('Hi there!!!');
4272 
4273 --  MRP_UTIL.MRP_TIMING('After calculating line capacity ...');
4274 
4275   --Check the algorithm associated with the scheduling rule
4276 
4277   SELECT DISTINCT heuristic_code
4278   INTO   v_algorithm
4279   FROM   mrp_scheduling_rules
4280   WHERE  rule_id = p_rule_id
4281   AND    NVL(user_defined,C_USER_DEFINE_NO) = C_USER_DEFINE_NO ;
4282 
4283   V_ERROR_LINE := 2;
4284 
4285   -- Check for the mode of operation or type of unscheduled orders,
4286   -- Sales Orders or Planned Orders
4287 
4288   SELECT demand_source_type
4289     INTO   v_source_type
4290     FROM   wip_flow_schedules
4291     WHERE  request_id = USERENV('SESSIONID')
4292       AND  organization_id = p_org_id
4293       AND  scheduled_flag = C_NO
4294       AND  rownum = 1
4295       AND  wip_entity_id >= G_WIP_ENTITY_ID;
4296 
4297   V_ERROR_LINE := 3;
4298 
4299 --  MRP_UTIL.MRP_TIMING('Before calculating demand and round type for each item');
4300   -- Calculate demand and find round type for all items
4301 
4302   calculate_demand(p_line_id, p_org_id, v_demand_tab);
4303 
4304 --  MRP_UTIL.MRP_TIMING('After calculating demand and round type for each item');
4305 
4306   IF v_algorithm = C_NO_LEVEL_LOAD THEN
4307 --   dbms_output.put_line('Algorithm is no level load');
4308 
4309     -- If source type is sales orders
4310 
4311     IF v_source_type IN (C_INT_SALES_ORDER,C_EXT_SALES_ORDER) THEN
4312 --      dbms_output.put_line('Source type is SALES ORDERS');
4313 
4314       -- round up planned quantities of all flow schedules which are fractional
4315       -- with round attribute = yes.
4316 
4317       rounding_process(p_org_id, p_line_id, p_rule_id, v_demand_tab);
4318 
4319 --      dbms_output.put_line('Scheduling...');
4320       schedule_orders(p_line_id, p_org_id, p_rule_id, v_cap_tab, v_demand_tab,
4321 			v_time_tab);
4322 
4323     END IF;
4324 
4325     -- IF demand source of the flow schedules is planned orders, order modifiers
4326     -- will be applied.
4327 
4328     IF v_source_type = C_PLANNED_ORDER THEN
4329 
4330 --	Find round type for all items
4331 	calculate_demand(p_line_id, p_org_id, v_demand_tab);
4332 
4333 --      dbms_output.put_line('Source type is PLANNED ORDERS');
4334 
4335       -- Calculate the order quantities for each item based on order modifiers
4336       -- that have associated unscheduled flow schedules.
4337 
4338 --      dbms_output.put_line('Calculating order quantities...');
4339       calculate_order_quantities(p_org_id, v_orderMod_tab);
4340 
4341       -- Create new flow schedules to replace the original ones to respect order
4342       -- modifiers.
4343 
4344 --      dbms_output.put_line('Creating new flow schedules with order modifiers');
4345       create_po_fs(p_org_id, p_line_id, p_rule_id, v_orderMod_tab);
4346 
4347       -- round up planned quantities of all flow schedules which are fractional
4348       -- with round attribute = yes.
4349 
4350       rounding_process(p_org_id, p_line_id, p_rule_id, v_demand_tab);
4351 
4352       -- NOW, we need to sequence the flow schedules and then schedule them.
4353       -- The algorithm used here is same as that used for sales orders.
4354 --      dbms_output.put_line('Scheduling...');
4355 
4356        schedule_orders(p_line_id, p_org_id, p_rule_id, v_cap_tab, v_demand_tab,
4357 			v_time_tab);
4358 
4359     END IF;
4360   ELSIF v_algorithm = C_LEVEL_LOAD THEN
4361 --    dbms_output.put_line('Algorithm is level load');
4362 
4363     IF v_source_type IN (C_INT_SALES_ORDER,C_EXT_SALES_ORDER) THEN
4364 --      dbms_output.put_line('Source type is SALES ORDERS');
4365 
4366       -- round up planned quantities of all flow schedules which are fractional
4367       -- with round attribute = yes.
4368 --      dbms_output.put_line('Rounding...');
4369       rounding_process(p_org_id, p_line_id, p_rule_id, v_demand_tab);
4370 
4371       -- Schedule sales orders to match the production rate by updating
4372       -- the scheduled completion date and the build sequence for the
4373       -- schedule group.  If only a partial flow schedule quantity is
4374       -- required to fill the production rate, then the flow schedule
4375       -- will be split into more than one flow schedules.
4376 
4377 --      dbms_output.put_line('Scheduling...');
4378       schedule_orders_level(p_line_id, p_org_id, p_rule_id, v_cap_tab,
4379 				v_time_tab);
4380 
4381 --      dbms_output.put_line('updatiing build sequences...');
4382       update_buildseq(p_line_id, p_org_id);
4383 
4384     ELSIF v_source_type = C_PLANNED_ORDER THEN
4385 
4386 --      dbms_output.put_line('Source type is PLANNED ORDERS');
4387 
4388       -- Calculate the order quantities for each item based on order modifiers
4389       -- that have associated unscheduled flow schedules.
4390 
4391 --      dbms_output.put_line('Calculating order modifier quantities...');
4392 --      dbms_output.put_line('Calculating order modifier quantities...');
4393 
4394       calculate_order_quantities(p_org_id, v_orderMod_tab);
4395 
4396       -- Create new flow schedules to replace the original ones to respect order
4397       -- modifiers.
4398 
4399 --      dbms_output.put_line('Creating new flow schedules with order modifier quantities.');
4400 
4401 --      dbms_output.put_line('Creating new flow schedules with order modifier quantities.');
4402       create_po_fs(p_org_id, p_line_id, p_rule_id, v_orderMod_tab);
4403 
4404       -- round up planned quantities of all flow schedules which are fractional
4405       -- with round attribute = yes.
4406 
4407       rounding_process(p_org_id, p_line_id, p_rule_id, v_demand_tab);
4408 --      dbms_output.put_line('Scheduling ...');
4409       schedule_orders_level(p_line_id, p_org_id, p_rule_id, v_cap_tab, v_time_tab);
4410 
4411 --     dbms_output.put_line('updateing build sequences...');
4412      update_buildseq(p_line_id, p_org_id);
4413 
4414     END IF;
4415   ELSIF v_algorithm = C_MIXED_MODEL THEN
4416 
4417 --    MRP_UTIL.MRP_TIMING('Beginning of MIX MODEL ALGORITHM');
4418 
4419 --    dbms_output.put_line('Algorithm is mixed model');
4420 
4421     -- In the mixed model algorithm, flow schedules from sales orders and
4422     -- planned orders are manipulated in the same manner.  A manufacturing
4423     -- pattern of items is first established based on the demand of each
4424     -- item with respect to the total demand of all unscheduled flow schedules.
4425     -- The flow schedules are then scheduled respecting this pattern and
4426     -- the order of the flow schedules which is established using the user-
4427     -- chosen criteria.
4428 
4429     -- Round up planned quantities of all flow schedules which are fractional
4430     -- with round attribute = yes for the item.
4431 
4432 --    MRP_UTIL.MRP_TIMING('Before Rounding Process');
4433 
4434     rounding_process(p_org_id, p_line_id, p_rule_id, v_demand_tab);
4435 
4436     -- Calculate total demand for each item
4437 
4438 --    MRP_UTIL.MRP_TIMING('Before Calculating total demand for each item');
4439 
4440     calculate_demand_mix(p_line_id, p_org_id, v_item_demand_tab);
4441 
4442 --    MRP_UTIL.MRP_TIMING('After Calculating total demand for each item');
4443     schedule_mix_model(p_line_id, p_org_id, p_rule_id, v_cap_tab, v_demand_tab,
4444 		v_item_demand_tab, v_time_tab);
4445 
4446   END IF;
4447 
4448   -- Delete all flow schedules which have not been scheduled within the
4449   -- scheduling window.
4450 
4451   DELETE
4452   FROM   wip_flow_schedules
4453   WHERE  scheduled_flag = C_NO
4454     AND  request_id = USERENV('SESSIONID')
4455     AND  organization_id = p_org_id
4456     AND  wip_entity_id >= G_WIP_ENTITY_ID;
4457 
4458 
4459   /* Start of fix for bug 2977987: We get each flow schedule record
4460      scheduled in the present run, set bom and routing revision dates
4461      to its scheduled_completion_date and then re-calculate the
4462      effective bom and routing revisions active on that date */
4463 
4464    FOR fs_list_rec IN fs_list(p_line_id,p_org_id) LOOP
4465 
4466      v_bom_rev_date := NULL;
4467      v_bom_rev := NULL;
4468      v_rout_rev_date := NULL;
4469      v_rout_rev := NULL;
4470      v_item_id := fs_list_rec.primary_item_id;
4471 
4472      if (fs_list_rec.bom_revision_date is not null) then
4473 
4474        v_bom_rev_date := fs_list_rec.scheduled_completion_date;
4475 
4476        BOM_REVISIONS.Get_Revision(
4477          type          => 'PART',
4478          eco_status    => 'EXCLUDE_OPEN_HOLD',
4479          examine_type  => 'ALL',
4480          org_id        => p_org_id,
4481          item_id       => v_item_id,
4482          rev_date      => v_bom_rev_date,
4483          itm_rev       => v_bom_rev);
4484 
4485      end if;
4486 
4487      if (fs_list_rec.routing_revision_date is not null) then
4488 
4489        v_rout_rev_date := fs_list_rec.scheduled_completion_date;
4490 
4491        BOM_REVISIONS.Get_Revision(
4492          type          => 'PROCESS',
4493          eco_status    => 'EXCLUDE_OPEN_HOLD',
4494          examine_type  => 'ALL',
4495          org_id        => p_org_id,
4496          item_id       => v_item_id,
4497          rev_date      => v_rout_rev_date,
4498          itm_rev       => v_rout_rev);
4499 
4500      end if;
4501 
4502      UPDATE wip_flow_schedules
4503         SET bom_revision = v_bom_rev,
4504             bom_revision_date = v_bom_rev_date,
4505             routing_revision = v_rout_rev,
4506             routing_revision_date = v_rout_rev_date
4507       WHERE wip_entity_id = fs_list_rec.wip_entity_id
4508         AND organization_id = p_org_id;
4509 
4510   END LOOP;
4511 
4512   /* End of fix for bug 2977987 */
4513 
4514   V_ERROR_LINE := 4;
4515 
4516   x_return_status := FND_API.G_RET_STS_SUCCESS;
4517 
4518 --  dbms_output.put_line('End of Scheduling...');
4519 
4520 --  MRP_UTIL.MRP_TIMING('End of Scheduling');
4521 
4522 EXCEPTION
4523 
4524   WHEN OTHERS THEN
4525     ROLLBACK TO MRP_begin_PVT;
4526 
4527 --    dbms_output.put_line('There is an error!!!!');
4528 
4529     IF FND_MSG_PUB.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
4530       FND_MSG_PUB.Add_Exc_Msg(
4531 	V_PKG_NAME,V_PROCEDURE_NAME||': Line '||to_char(V_ERROR_LINE));
4532     END IF;
4533 
4534     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
4535 --    dbms_output.put_line('!!!ERROR!!!:' || to_char(sqlcode) ||
4536 --              substr(sqlerrm,1,60));
4537     FND_MSG_PUB.Count_And_Get
4538 		(p_count 	=>	x_msg_count,
4539 		 p_data		=>	x_msg_data
4540 		);
4541     return;
4542 END Schedule;
4543 
4544 
4545 -- This function calculates proper schedule start time
4546 -- based on completion_date, completion_time, and lead_time.
4547 -- All time formats are Julian calendar format.
4548 FUNCTION calculate_begin_time(
4549 		p_org_id	IN NUMBER,
4550 		p_completion_date IN DATE,
4551 		p_lead_time	IN NUMBER,
4552 		p_start_time	IN NUMBER,
4553 		p_end_time	IN NUMBER) RETURN DATE IS
4554   l_completion_time NUMBER;
4555   l_completion_date DATE;
4556   l_begin_date	 DATE;
4557   l_working_time NUMBER;
4558   l_lead_time	 NUMBER;
4559   l_offset_time	 NUMBER;
4560   l_temp_date	 DATE;
4561   l_end_time     NUMBER;
4562 BEGIN
4563 
4564 
4565   l_completion_date := trunc(p_completion_date);
4566   l_completion_time := to_char(p_completion_date,'SSSSS');
4567 
4568   l_end_time := p_end_time;
4569   if (p_end_time <= p_start_time) then
4570     if (l_completion_time < l_end_time ) then
4571       l_completion_date := trunc(p_completion_date)-1;
4572       l_completion_time := to_char(p_completion_date,'SSSSS')+24*3600;
4573     end if;
4574     l_end_time := l_end_time + 24*3600;
4575   end if;
4576 
4577 
4578   -- total working hrs in workday
4579   l_working_time := l_end_time - p_start_time;
4580 
4581 
4582 
4583   -- exclude workable time in completion_date from lead_time
4584   l_lead_time := (p_lead_time*l_working_time) - (l_completion_time-p_start_time);
4585   if (l_lead_time <= 0) then
4586     l_lead_time := p_lead_time*l_working_time;
4587     l_temp_date := trunc(l_completion_date);
4588     l_end_time := l_completion_time;
4589   else
4590     -- find out the schedule start_date based on the offset
4591     -- first, we find out the offset date and then use MOD function
4592     -- to find out the offset time
4593     l_temp_date := mrp_calendar.date_offset(
4594                         p_org_id,
4595                         1,  -- daily bucket
4596                         l_completion_date,
4597                         -ceil(l_lead_time/l_working_time));
4598   end if;
4599 
4600 
4601   -- find out specific time to start
4602   -- exception case, when lead_time is same as working_hrs
4603   -- MOD function will return '0', thus, offset_time should be start_time
4604   IF l_lead_time = l_working_time THEN
4605     l_offset_time := p_start_time;
4606   ELSE
4607     l_offset_time := l_end_time - mod(l_lead_time, l_working_time);
4608 
4609   END IF;
4610 
4611   l_begin_date := l_temp_date + l_offset_time/86400;
4612 
4613   return l_begin_date;
4614 
4615 END calculate_begin_time;
4616 
4617 FUNCTION calculate_completion_time(
4618 		p_org_id	IN NUMBER,
4619 		p_item_id	IN NUMBER,
4620 		p_qty		IN NUMBER,
4621 		p_line_id	IN NUMBER,
4622 		p_start_date	IN DATE) RETURN DATE IS
4623   l_lead_time	NUMBER;
4624   l_fixed_time	NUMBER;
4625   l_variable_time NUMBER;/*Added for bugfix:7211657 */
4626   l_line_start_time 	NUMBER;
4627   l_line_end_time 	NUMBER;
4628   l_working_time NUMBER;
4629   l_time 	NUMBER;
4630   l_date DATE;
4631   l_offset_time NUMBER;
4632   l_offset_day NUMBER;
4633   l_remain_time NUMBER;
4634   l_start_time NUMBER;
4635   l_start_date DATE;
4636   l_sec_rate NUMBER; -- time to produce 1 quantity in seconds
4637 BEGIN
4638 
4639   l_start_date := trunc(p_start_date);
4640   l_start_time := to_char(p_start_date,'SSSSS');
4641 
4642   select start_time, stop_time, 3600/maximum_rate
4643   into l_line_start_time, l_line_end_time, l_sec_rate
4644   from wip_lines
4645   where organization_id = p_org_id
4646     and line_id = p_line_id;
4647 
4648   if (l_line_end_time <= l_line_start_time) then
4649     l_line_end_time := l_line_end_time + 24*3600;
4650   end if;
4651 
4652   l_working_time := l_line_end_time - l_line_start_time;
4653 
4654   /*Changed the query to fetch variable_lead_time also for bug fix 7211657 */
4655 
4656   select NVL(fixed_lead_time,0)*l_working_time,NVL(variable_lead_time,0)*l_working_time
4657   into l_fixed_time,l_variable_time
4658   from mtl_system_items
4659   where organization_id = p_org_id
4660     and inventory_item_id = p_item_id;
4661 
4662  -- l_lead_time := l_fixed_time;
4663  /*Changed lead time calculation for bugfix:7211657 */
4664     l_lead_time := l_fixed_time + ((p_qty-1)*l_variable_time);
4665   -- l_date and l_time to store the possible start date and time
4666 
4667   -- get the first workday. If it's not the same as p_start_date, need
4668   -- to move it to next workday and also set the l_time to start of line
4669   l_date := mrp_calendar.next_work_day(p_org_id,1,p_start_date);
4670   if (trunc(l_start_date) <>  trunc(l_date)) then
4671     l_time := l_line_start_time;
4672   else
4673     l_time := l_start_time;
4674     if (l_time > l_line_start_time) then
4675       l_time := l_line_start_time + ceil((l_time-l_line_start_time)/l_sec_rate)*l_sec_rate;
4676     end if;
4677   end if;
4678 
4679   -- If the l_time greater than the end time of line, move it to the
4680   -- workday at the line start time
4681   -- If l_time less than the start of line, move the start time to
4682   -- line start time of the day.
4683   -- If it's between start and end time of line, use up the line and
4684   -- move to next workday.
4685   if (l_time > l_line_end_time) then
4686     l_date := mrp_calendar.next_work_day(p_org_id,1,l_date+1);
4687     l_time := l_line_start_time;
4688   elsif (l_time < l_line_start_time) then
4689     l_time := l_line_start_time;
4690   else
4691     l_remain_time := l_line_end_time-l_time;
4692     if (l_lead_time - l_remain_time > 0) then
4693       l_lead_time := l_lead_time - l_remain_time;
4694       l_date := mrp_calendar.next_work_day(p_org_id,1,l_date+1);
4695       l_time := l_line_start_time;
4696     end if;
4697   end if;
4698 
4699 
4700   if l_lead_time = l_working_time then
4701     l_offset_time := l_line_end_time;
4702     l_offset_day := l_lead_time/l_working_time - 1;
4703   else
4704     l_offset_time := l_time + mod(l_lead_time, l_working_time);
4705     l_offset_day := floor(l_lead_time/l_working_time);
4706   end if;
4707 
4708   l_date := mrp_calendar.date_offset(
4709                         p_org_id,
4710                         1,  -- daily bucket
4711                         l_date,
4712                         l_offset_day);
4713 
4714 
4715   if (l_offset_time = l_line_start_time and l_fixed_time <> 0) then
4716     l_date := mrp_calendar.prev_work_day(p_org_id,1,l_date-1);
4717     l_offset_time := l_line_end_time;
4718   end if;
4719 
4720   return ( l_date + l_offset_time/86400 );
4721 
4722 END calculate_completion_time;
4723 
4724 END;