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