[Home] [Help]
PACKAGE BODY: APPS.MSD_FCST_PUB
Source
1 PACKAGE BODY msd_fcst_pub AS
2 /* $Header: msdfpshb.pls 120.2 2006/07/07 10:51:55 amitku noship $ */
3
4 -- this auxiliary function executes a dynamic SQL string and gets a result
5 -- I need to do it this way because Forms' version of PL/SQL does not support dynamic SQL
6 function get_result(v_sql_stmt in varchar2)
7 return varchar2 IS
8 v_res varchar2(1000);
9 begin
10 execute immediate v_sql_stmt into v_res;
11 return v_res;
12 end;
13
14 function cstring (dblink in varchar2) return varchar2 is
15 begin
16 if dblink is null then
17 return '';
18 else
19 return '@' || dblink;
20 end if;
21 end cstring;
22
23 -- this is the main routine in the package, it does everything
24 procedure MSDFPUSH_execute(
25 errbuf out NOCOPY varchar2,
26 retcode out NOCOPY varchar2,
27 p_demand_plan_id in number,
28 p_scenario_id in number,
29 p_revision in varchar2,
30 p_instance_id in number,
31 p_forecast_designator in varchar2,
32 p_forecast_set in varchar2,
33 p_demand_class in varchar2,
34 p_level_id in number,
35 p_value_id in number,
36 p_customer_id in number,
37 p_location_id in number,
38 p_use_baseline_fcst in number,
39 p_workday_control in number)
40 IS
41 TYPE CurRef IS REF CURSOR;
42 lpks CurRef;
43 sc_entries CurRef;
44 n number;
45 a number;
46 v_time_lvl_id number;
47 v_bucket_type number;
48 v_forecast_designator varchar2(10);
49 v_new_fcst boolean;
50 l_insert varchar2(3000) := 'INSERT ';
51 l_select varchar2(3000) := 'SELECT ';
52 l_from varchar2(3000):= 'FROM ';
53 l_where varchar2(3000):= 'WHERE ';
54 l_group_by varchar2(3000):= 'GROUP BY ';
55 v_sql_stmt varchar2(3000);
56 v_customer_id number;
57 v_location_id number;
58 cus_pk number;
59 loc_pk number;
60 v_level_id number;
61 v_quant varchar2(20);
62 v_item_id number;
63 v_org_id msd_level_values.sr_level_pk%TYPE;
64 org_id VARCHAR2(240);
65 org_pk number;
66 v_fcst_date date;
67 v_quantity number;
68 v_fcst_end_date date;
69 i number :=0;
70 v_organization_id number;
71 v_dblink varchar2(129);
72 cnt number;
73 lvl_id number;
74 dim varchar2(3);
75 hier number;
76 lvl number;
77 lvl2 number;
78 lvl3 number;
79 qstr varchar2(2000);
80 ltc varchar2(3);
81 cus_state number;
82
83
84 -- B1485277 added new variables for use in Process MFG queries
85 v_process_flag VARCHAR2(1) := NULL;
86 v_forecast_id NUMBER(10) := 0;
87 l_source_apps_version VARCHAR2(1) := NULL;
88
89 l_round_off number := NULL;
90
91 CURSOR c_round_off IS
92 SELECT roundoff_decimal_places
93 FROM msd_demand_plans
94 WHERE demand_plan_id = p_demand_plan_id;
95
96 CURSOR c_sr_lvl_pk(p_lvl_pk number) IS
97 select sr_level_pk
98 from msd_level_values
99 where level_pk = p_lvl_pk;
100
101 l_sr_dcs_lvl_pk varchar2(30) := NULL;
102 l_sr_org_lvl_pk varchar2(30) := NULL;
103
104 BEGIN
105
106 retcode := 0;
107 errbuf := '';
108
109 -- Before we begin, we find time level - days, weeks, or periods
110
111 select output_period_type into v_time_lvl_id from msd_dp_scenarios
112 where demand_plan_id = p_demand_plan_id and scenario_id = p_scenario_id;
113
114 if (v_time_lvl_id= 9) then v_bucket_type := 1;
115 elsif (v_time_lvl_id = 1) then v_bucket_type := 2;
116 elsif (v_time_lvl_id = 2) then v_bucket_type := 3;
117 else
118 errbuf := 'Invalid Output Period Type';
119 retcode := -1;
120 return;
121 end if;
122
123 select m2a_dblink into v_dblink from msc_apps_instances
124 where instance_id = p_instance_id;
125
126 v_dblink := cstring(v_dblink);
127
128 v_quant := 'quantity';
129
130 -- p_customer_id and p_location_id are the filters
131
132 if p_customer_id is null then
133 v_customer_id := NULL;
134 else
135 select sr_level_pk
136 into v_customer_id
137 from msd_level_values
138 where level_pk = p_customer_id;
139 end if;
140
141 if p_location_id is null then
142 v_location_id := NULL;
143 else
144 select sr_level_pk
145 into v_location_id
146 from msd_level_values
147 where level_pk = p_location_id;
148 end if;
149
150
151 /* DWK Need to change here.
152 If user choose ORG level_id, then we should only consider those
153 orgs that user has chosen from the forms */
154
155 /* For SR ORG Level PKs that exist in the scenario entries */
156 /* Begin of 1 */
157 for v_org_id in (select lv.sr_level_pk
158 from msd_level_values lv,
159 (select organization_lvl_pk opk
160 from msd_dp_scenario_entries
161 where demand_plan_id = p_demand_plan_id
162 and scenario_id = p_scenario_id
163 and revision = p_revision
164 group by organization_lvl_pk) sce
165 where lv.level_pk = sce.opk ) LOOP
166
167 BEGIN /* Begin of 2 */
168
169 /* If user selects organization as a filter condition
170 then populate forecast set only for this org */
171 l_sr_org_lvl_pk := NULL;
172 IF (p_level_id = 7) and (p_value_id is not NULL) THEN
173 OPEN c_sr_lvl_pk(p_value_id);
174 FETCH c_sr_lvl_pk INTO l_sr_org_lvl_pk;
175 CLOSE c_sr_lvl_pk;
176 END IF;
177
178 IF ( nvl(l_sr_org_lvl_pk, v_org_id.sr_level_pk) = v_org_id.sr_level_pk) THEN
179
180 /* If user selects demand class as filter condition */
181 l_sr_dcs_lvl_pk := NULL;
182 IF (p_level_id = 34) and (p_value_id is not NULL) THEN
183 OPEN c_sr_lvl_pk(p_value_id);
184 FETCH c_sr_lvl_pk INTO l_sr_dcs_lvl_pk;
185 CLOSE c_sr_lvl_pk;
186
187 /* If passed demand class value is 'Other' then treat it as NULL */
188 IF l_sr_dcs_lvl_pk = '-777' THEN
189 l_sr_dcs_lvl_pk := NULL;
190 END IF;
191 END IF;
192
193 -- Check if forecast_designator/org_id already exists
194 org_id := v_org_id.sr_level_pk;
195
196 select APPS_VER
197 into l_source_apps_version
198 from msc_apps_instances
199 where instance_id = p_instance_id;
200
201 v_process_flag := 'N';
202
203 if (l_source_apps_version = 3) then /* Only for 11i source instance */
204 -- B1485277 This query will collect the indicator as to whether an org is
205 -- process or not
206 v_sql_stmt := ' SELECT'
207 || ' process_enabled_flag'
208 || ' FROM'
209 || ' mtl_parameters'|| v_dblink
210 || ' WHERE'
211 || ' organization_id = :l_org_id ';
212 EXECUTE IMMEDIATE v_sql_stmt INTO v_process_flag USING org_id;
213 end if;
214
215 -- B1485277 If the organization is not process then execute the following
216 -- otherwise execute the discrete version
217 IF v_process_flag = 'N' THEN
218 v_sql_stmt := 'select count(*) from mrp_forecast_designators'|| v_dblink ||
219 ' where forecast_designator = :l_forecast_designator '||
220 ' and organization_id = :l_org_id ';
221 execute immediate v_sql_stmt into cnt USING p_forecast_designator, org_id;
222 --
223 -- Changes -- VM
224 -- Changed sql stmts into dynamic sql statements as inserts into mrp_forecast_designators and
225 -- other mrp tables should be done at source instance not in the planning server
226 --
227 if cnt=0 then
228 v_sql_stmt := 'insert into mrp_forecast_designators'
229 || v_dblink || '( ' ||
230 'forecast_designator,' ||
231 'organization_id,' ||
232 'forecast_set,' ||
233 'consume_forecast,' ||
234 'update_type,' ||
235 'bucket_type,' ||
236 'last_update_date,' ||
237 'last_updated_by,' ||
238 'creation_date,' ||
239 'created_by,' ||
240 'demand_class,' ||
241 'customer_id,' ||
242 'ship_id' ||
243 ') values (' ||
244 '''' || replace(p_forecast_designator, '''', '''''') || ''',' || -- forecast_designator,
245 org_id || ',' || -- organization_id,
246 '''' || replace(p_forecast_set, '''', '''''') || ''',' || -- forecast_set
247 '''' || '1' || ''',' || -- consume_forecast,
248 'decode (' || '''' || v_customer_id || '''' || ', '''',' ||
249 'decode (' || '''' || v_location_id || '''' || ', '''', 6, 2),' ||
250 'decode (' || '''' || v_location_id || '''' || ', '''', 4,2)),' || -- update_type
251 '''' || v_bucket_type || ''',' || -- bucket_type,
252 'sysdate' || ',' || -- last_update_date,
253 '''' || '1' || ''',' || -- last_updated_by,
254 'sysdate, ' || -- creation_date,
255 '''' || '1' || ''',' || -- created_by
256 '''' || nvl(l_sr_dcs_lvl_pk,replace(p_demand_class, '''', '''''')) || ''',' || -- demand_class,
257 '''' || v_customer_id || ''',' || -- customer_id,
258 '''' || V_location_id || ''')'; -- ship_id
259 -- Execute the insert.
260 execute immediate v_sql_stmt;
261 else /* else for cnt=0 */
262 v_sql_stmt := 'delete from mrp_forecast_items' || v_dblink ||
263 ' where forecast_designator = :l_forecast_designator' ||
264 ' and organization_id = :l_org_id ';
265 execute immediate v_sql_stmt USING p_forecast_designator, org_id;
266
267 v_sql_stmt := 'delete from mrp_forecast_dates ' || v_dblink ||
268 ' where forecast_designator = :l_forecast_designator' ||
269 ' and organization_id = :l_org_id ';
270 execute immediate v_sql_stmt USING p_forecast_designator, org_id;
271
272 v_sql_stmt := 'update mrp_forecast_designators' || v_dblink || ' ' ||
273 ' set ' ||
274 'forecast_set = ' || '''' || replace(p_forecast_set, '''', '''''') || ''',' ||
275 'bucket_type = ' || '''' || v_bucket_type || ''',' ||
276 'last_update_date = sysdate,' ||
277 'last_updated_by = 1,' ||
278 'demand_class = ' || '''' || nvl(l_sr_dcs_lvl_pk,replace(p_demand_class, '''', '''''')) || ''',' ||
279 'customer_id = ' || '''' || v_customer_id || ''',' ||
280 'ship_id = ''' || v_location_id || '''' ||
281 ' where forecast_designator = ' || '''' || replace(p_forecast_designator, '''', '''''')
282 || '''' ||
283 ' and organization_id = ' || org_id;
284 execute immediate v_sql_stmt;
285 end if; /* end of cnt=0 */
286
287 -- now - the same for forecast set
288
289 v_sql_stmt := 'select count(*) from mrp_forecast_designators' || v_dblink
290 || ' ' ||
291 'where forecast_designator = ''' || replace(p_forecast_set, '''', '''''') || '''' ||
292 ' and organization_id = ' || org_id;
293 execute immediate v_sql_stmt into cnt;
294
295 if cnt=0 then
296 v_sql_stmt := 'insert into mrp_forecast_designators' || v_dblink
297 || ' (' ||
298 'forecast_designator, ' ||
299 'organization_id, ' ||
300 'forecast_set, ' ||
301 'consume_forecast, ' ||
302 'update_type, ' ||
303 'bucket_type, ' ||
304 'last_update_date, ' ||
305 'last_updated_by, ' ||
306 'creation_date, ' ||
307 'created_by, ' ||
308 'demand_class, ' ||
309 'customer_id, ' ||
310 'ship_id ' ||
311 ') values ( ' ||
312 '''' || replace(p_forecast_set, '''', '''''') || ''',' || -- forecast_designator,
313 org_id || ',' || -- organization_id,
314 'NULL,' || -- forecast_set
315 '1,' || -- consume_forecast,
316 'decode (' || '''' || v_customer_id || '''' || ', '''',' ||
317 'decode (' || '''' || v_location_id || '''' || ', '''', 6, 2),' ||
318 'decode (' || '''' || v_location_id || '''' || ', '''', 4,2)),' || -- update_type
319 '''' || v_bucket_type || ''',' || -- bucket_type,
320 'sysdate,' || -- last_update_date,
321 '1,' || -- last_updated_by,
322 'sysdate,' || -- creation_date,
323 '1,' || -- created_by
324 '''' || nvl(l_sr_dcs_lvl_pk,replace(p_demand_class, '''', '''''')) || ''',' || -- demand_class,
325 'NULL, ' ||-- customer_id,
326 'NULL ' ||-- ship_id
327 ')';
328 execute immediate v_sql_stmt;
329 else /* Else of cnt=0 */
330 v_sql_stmt := 'update mrp_forecast_designators' || v_dblink || ' ' ||
331 ' set bucket_type = ' || '''' || v_bucket_type || ''',' ||
332 ' last_update_date = sysdate, ' ||
333 ' last_updated_by = 1,' ||
334 ' demand_class = ' || '''' || nvl(l_sr_dcs_lvl_pk,replace(p_demand_class, '''', '''''')) || '''' ||
335 ' where forecast_designator = ' || '''' || replace(p_forecast_set, '''', '''''') || '''' ||
336 ' and organization_id = ' || org_id;
337 execute immediate v_sql_stmt;
338 end if; /* end for cnt=0 */
339 END IF; /* END for v_process_flag = 'N' */
340
341 --
342 -- End Changes VM
343 --
344 -- we now find out whether f_desg AND dp_sc_entries are loc and/or customer specific
345
346 cus_state := 0;
347
348 v_level_id := 0;
349
350 begin
351 v_sql_stmt := 'select level_id from msd_dp_scn_output_levels_v ' ||
352 'where demand_plan_id = ' || p_demand_plan_id ||
353 ' and scenario_id = ' || p_scenario_id ||
354 ' and owning_dimension_code = ''GEO''';
355 execute immediate v_sql_stmt into v_level_id;
356
357 -- zia 4/12/01 handle NO_DATA_FOUND exception
358 exception
359 when others then
360 null;
361 end;
362
363
364 if (v_customer_id is NULL) and (v_location_id is NULL) then
365 cus_state := 4; -- simply aggregate, not customer-specific
366 elsif (v_location_id is NOT NULL) then
367 if v_level_id = 11 then -- location level
368 cus_state := 1; -- OK, loc-loc case
369 else
370 cus_state := -1; -- error
371 end if;
372 else -- i.e. customer is NOT NULL but location is NULL in f_desg
373 if v_level_id = 11 then -- location level
374 cus_state := 3; -- OK, loc-cus case
375 elsif v_level_id = 15 then -- customer level
376 cus_state := 2; -- cus-cus case
377 else
381
378 cus_state := -1; -- error
379 end if;
380 end if;
382 if cus_state = -1 then
383 errbuf:= errbuf || org_id || ' '; -- add to the list of bad orgs
384 else -- everything is OK, go to the main part
385 l_insert := 'INSERT ';
386 l_select := 'SELECT ';
387 l_from := 'FROM ';
388 l_where := 'WHERE ';
389 l_group_by := 'GROUP BY ';
390
391 select level_pk
392 into org_pk
393 from msd_level_values
394 where instance = p_instance_id
395 and sr_level_pk = org_id
396 and level_id = 7; -- level_id=7 - organization level
397
398 -- Now create the dynamic query
399
400 /* Find the round off decimal place for UOM conversion */
401 OPEN c_round_off;
402 FETCH c_round_off INTO l_round_off;
403 CLOSE c_round_off;
404
405 IF l_round_off is null THEN
406 l_round_off := 6;
407 END IF;
408
409 l_insert := l_insert || 'INTO MSD_DP_SCN_ENTRIES_TEMP' ||
410 ' (inventory_item_id, forecast_designator, organization_id, ' ||
411 ' forecast_date, quantity, bucket_type, forecast_end_date) ';
412
413 -- select
414 l_select := l_select ||
415 'sce.sr_product_lvl_pk, ' ||
416 '''' || p_forecast_designator || ''', ' ||
417 org_id || ', ' ||
418 'sce.time_lvl_val_from, ' ||
419 'ROUND(sum(sce.' || v_quant || ' * decode(sce.PRODUCT_LVL_ID, 1, 1,' ||
420 ' msd_common_utilities.msd_uom_convert(sce.sr_product_lvl_pk, ' ||
421 ' null, sce.total_quantity_uom, lp.base_uom))),' ||
422 l_round_off || '), ' ||
423 to_char(v_bucket_type) || ', ' ||
424 'sce.time_lvl_val_to ' || ' ';
425
426 -- from
427 l_from := l_from ||
428 ' msd_dp_scenario_entries sce, ' ||
429 ' msd_item_list_price lp ';
430
431 -- where
432 l_where := l_where ||
433 'sce.scenario_id = ' || to_char(p_scenario_id) || ' AND ' ||
434 'sce.demand_plan_id = ' || to_char(p_demand_plan_id) || ' AND ' ||
435 'sce.revision = ' || p_revision || ' AND ' ||
436 'sce.'||v_quant|| ' is not NULL AND ' ||
437 'lp.instance = sce.instance AND ' ||
438 'lp.sr_item_pk = sce.sr_product_lvl_pk AND ' ||
439 'sce.organization_lvl_pk = ' || org_pk || ' ';
440
441 -- now - special treatment for various customer/location cases as stored in cus_state
442
443 loc_pk := p_location_id;
444 cus_pk := p_customer_id;
445
446 if cus_state = 1 then
447 -- state 1 means that both scenario_entries and f_desg/org_id are on the location level
448 l_where := l_where || ' AND sce.geography_lvl_pk = ' || to_char(loc_pk) || ' ' ;
449 elsif cus_state = 2 then
450 -- state 1 means that both scenario_entries and f_desg/org_id are on the customer level
451 l_where := l_where || ' AND sce.geography_lvl_pk = ' || to_char(cus_pk) || ' ' ;
452 elsif cus_state = 3 then
453 -- state 3 means that scenario_entries is on the location level while
454 -- f_desg/org_id is on the customer level
455 -- so we need to include all "child" locations on the f_desg/org_id's customer
456 l_where := l_where || ' AND sce.geography_lvl_pk IN ('||
457 'SELECT level_pk from msd_level_values_v where parent_level_pk = ' || to_char(cus_pk) || ') ';
458 end if;
459 -- state 4 means that forecast_designator/org_id is aggregate across all customers
460 -- and therefore nothing should be added
461
462 -- now, if p_level_id and p_value_id are not null, we need to add yet another filter
463 if (p_level_id is not null) and (p_value_id is not null) then
464
465 select dimension_code into dim
466 from msd_levels
467 where level_id = p_level_id;
468
469 -- zia 4/12/01 handle case where this dimension is not in the plan
470 begin
471
472 SELECT mdsol.level_id into lvl
473 FROM msd_dp_scenario_output_levels mdsol
474 WHERE mdsol.demand_plan_id = p_demand_plan_id
475 and mdsol.scenario_id = p_scenario_id
476 and exists (select 1
477 from msd_levels mlv,
478 msd_dp_dimensions mdd
479 where mdd.demand_plan_id = p_demand_plan_id
480 and mdd.dimension_code = mlv.dimension_code
481 and mlv.level_id = mdsol.level_id
482 and mdd.dimension_code = dim);
483
484 exception
485 when others then
486 null;
487 end;
488 -- zia 4/12/01/ end
489
490 select min(hierarchy_id) into hier
491 from
492 (select hierarchy_id from msd_hierarchy_levels where level_id = p_level_id
493 INTERSECT
494 select hierarchy_id from msd_hierarchy_levels where level_id = lvl);
495
496 lvl2 := p_level_id;
497 qstr := '(' || to_char(p_value_id) || ')';
498
499 while (lvl2 <> lvl) loop
500
501 select level_id into lvl2
502 from msd_hierarchy_levels
503 where parent_level_id = lvl2
504 and hierarchy_id = hier;
505
506 open lpks for 'select level_pk from msd_level_values_v ' ||
507 ' where level_id = ' || to_char(lvl2) || ' ' ||
508 ' and parent_level_pk in ' || qstr;
509
510 qstr := NULL;
511
512 loop
513 fetch lpks into n;
514 exit when lpks%NOTFOUND;
515 if qstr is NULL then
516 qstr := '(' || to_char(n);
517 else
518 qstr := qstr || ',' || to_char(n);
519 end if;
520 end loop;
521
522 if qstr is NULL then
523 RAISE NO_DATA_FOUND;
524 end if;
525
526 qstr := qstr || ')';
527
528 end loop;
529
530 -- at this point qstr contains the list of "valid" level_pk's on the scenario_output_level (=== lvl)
531
532 if dim = 'PRD' then
533 l_where := l_where || ' AND sce.product_lvl_pk IN ' || qstr || ' ';
534 elsif dim = 'GEO' then
535 l_where := l_where || ' AND sce.geography_lvl_pk IN ' || qstr || ' ';
536 elsif dim = 'CHN' then
537 l_where := l_where || ' AND sce.saleschannel_lvl_pk IN ' || qstr || ' ';
538 elsif dim = 'REP' then
539 l_where := l_where || ' AND sce.sales_rep_lvl_pk IN ' || qstr || ' ';
540 elsif dim = 'ORG' then
541 l_where := l_where || ' AND sce.organization_lvl_pk IN ' || qstr || ' ';
542 elsif dim = 'UD1' then
543 l_where := l_where || ' AND sce.user_defined1_lvl_pk IN ' ||
544 qstr || ' ';
545 elsif dim = 'UD2' then
546 l_where := l_where || ' AND sce.user_defined2_lvl_pk IN ' ||
547 qstr || ' ';
548 elsif dim = 'DCS' then
549 l_where := l_where || ' AND sce.demand_class_lvl_pk IN ' || qstr || ' ';
550 else
551 null; -- we could raise an error here, but instead just ignore the filter
552 end if;
553
554 end if;
555
556 -- group_by
557 l_group_by := l_group_by || 'sce.sr_product_lvl_pk, sce.time_lvl_val_from, sce.time_lvl_val_to ';
558
559 /* Clear Temp table before insertion */
560 DELETE FROM MSD_DP_SCN_ENTRIES_TEMP;
561
562 /* Insert Forecast into MSD_DP_SCN_ENTRIES_TEMP table first */
563 v_sql_stmt := l_insert || l_select || l_from || l_where || l_group_by;
564 EXECUTE IMMEDIATE v_sql_stmt;
565
566 /* Clean up mrp_forecast_interface table before inserting new forecast */
567 v_sql_stmt := ' DELETE FROM mrp_forecast_interface'|| v_dblink ||
568 ' WHERE forecast_designator = '||
569 '''' || p_forecast_designator || '''' ||
570 ' and organization_id = nvl(' || org_id ||', organization_id)';
571 EXECUTE IMMEDIATE v_sql_stmt;
572
573 /* Insert Forecast into MRP_FORECAST_INTERFACE table */
574 -- insert
575 v_sql_stmt := 'INSERT INTO mrp_forecast_interface' || v_dblink ||
576 ' (inventory_item_id, forecast_designator, organization_id, ' ||
577 ' forecast_date, quantity, process_status, confidence_percentage, ' ||
578 ' bucket_type, forecast_end_date, last_update_date, last_updated_by, ' ||
579 ' creation_date, created_by, workday_control) ' ||
580 ' SELECT inventory_item_id, forecast_designator, organization_id, ' ||
581 ' forecast_end_date, quantity, 2, 100, ' ||
582 ' bucket_type, forecast_end_date, SYSDATE, -1, SYSDATE, -1, ' ||
583 to_char(p_workday_control) || ' ' ||
584 ' FROM MSD_DP_SCN_ENTRIES_TEMP ';
585 EXECUTE IMMEDIATE v_sql_stmt;
586
587 /* Delete temp table after insert forecast into the source */
588 DELETE FROM MSD_DP_SCN_ENTRIES_TEMP;
589
590 -- insert into dwk_test10 values(v_sql_stmt);
591
592 commit;
593
594 end if;
595
596 END IF; /* ( nvl(l_sr_org_lvl_pk, v_org_id.sr_level_pk) = v_org_id.sr_level_pk) */
597
598
599 /* Add error handler in LOOP so that any error during loop will continue to
600 the next org */
601 EXCEPTION
602 when others then
603 null;
604 END; /* End of 2 */
605
606
607 END LOOP /* End of 1 */;
608
609 EXCEPTION
610 when others then
611 errbuf := substr(SQLERRM,1,150);
612 retcode := -1;
613
614
615 -- return;
616
617 END;
618
619 END msd_fcst_pub;