[Home] [Help]
PACKAGE BODY: APPS.BEN_DM_INIT
Source
1 PACKAGE BODY ben_dm_init AS
2 /* $Header: benfdmdini.pkb 120.0 2006/06/13 14:56:19 nkkrishn noship $ */
3
4 -- ------------------------- populate_pi_table_i ------------------------
5 -- Description: The phase items for the initialization phase are seeded
6 -- into the hr_dm_phase_items. (currently none required)
7 --
8 --
9 -- Input Parameters
10 -- r_migration_data - record containing migration information
11 --
12 --
13 -- Output Parameters
14 -- <none>
15 --
16 --
17 -- ------------------------------------------------------------------------
18 --
19 PROCEDURE populate_pi_table_i(r_migration_data IN
20 ben_dm_utility.r_migration_rec) IS
21 --
22
23 --
24 BEGIN
25 --
26
27 ben_dm_utility.message('ROUT','entry:ben_dm_init.populate_pi_table_i', 5);
28 ben_dm_utility.message('PARA','(r_migration_data - record)', 10);
29
30 --
31 -- phase specific code to be inserted here
32 --
33 -- no code required
34 --
35
36 ben_dm_utility.message('INFO','Populate Phase Items table - I phase', 15);
37 ben_dm_utility.message('SUMM','Populate Phase Items table - I phase', 20);
38 ben_dm_utility.message('ROUT','exit:ben_dm_init.populate_pi_table_i', 25);
39 ben_dm_utility.message('PARA','(none)', 30);
40
41 -- error handling
42 EXCEPTION
43 WHEN OTHERS THEN
44 ben_dm_utility.error(SQLCODE,'ben_dm_init.populate_pi_table_i','(none)',
45 'R');
46 RAISE;
47
48 --
49 END populate_pi_table_i;
50 --
51
52 -- ------------------------- populate_pi_table_g ------------------------
53 -- Description: The phase items for the generator phase are seeded
54 -- into the ben_dm_phase_items.
55 --
56 --
57 -- Input Parameters
58 -- r_migration_data - record containing migration information
59 --
60 --
61 -- Output Parameters
62 -- <none>
63 --
64 --
65 -- ------------------------------------------------------------------------
66
67 --
68 PROCEDURE populate_pi_table_g(r_migration_data IN
69 ben_dm_utility.r_migration_rec) IS
70 --
71
72 l_phase_id NUMBER;
73 l_loader_name VARCHAR2(30);
74 l_group_id NUMBER;
75 l_table_name VARCHAR2(30);
76 l_generator_version VARCHAR2(2000);
77 l_status varchar2(50);
78 l_industry varchar2(50);
79 l_per_owner varchar2(30);
80 l_ben_owner varchar2(30);
81 l_pay_owner varchar2(30);
82 l_ff_owner varchar2(30);
83 l_fnd_owner varchar2(30);
84 l_apps_owner varchar2(30);
85
86 l_ret1 boolean := FND_INSTALLATION.GET_APP_INFO ('PAY', l_status,
87 l_industry, l_pay_owner);
88 l_ret2 boolean := FND_INSTALLATION.GET_APP_INFO ('BEN', l_status,
89 l_industry, l_ben_owner);
90 l_ret3 boolean := FND_INSTALLATION.GET_APP_INFO ('FF', l_status,
91 l_industry, l_ff_owner);
92 l_ret5 boolean := FND_INSTALLATION.GET_APP_INFO ('PER', l_status,
93 l_industry, l_per_owner);
94 l_ret6 boolean := FND_INSTALLATION.GET_APP_INFO ('APPS', l_status,
95 l_industry, l_apps_owner);
96
97 -- select tables for generating where
98 -- 1. generator not yet run (last_generated_date is null) OR
99 -- 2. table updated since last run (last_ddl_time >= last_generated_date) OR
100 -- 3. generator updated (generator_version(table) <>
101 -- generator version(generator))
102 -- 4. row in hr_dm_tables has been updated since the last generation
103 -- (last_update_date > last_generated_date)
104
105 CURSOR csr_select_pi IS
106 SELECT DISTINCT tbl.table_name
107 FROM ben_dm_tables tbl, ben_dm_table_order tbo,
108 all_objects obj
109 WHERE (tbo.table_id = tbl.table_id)
110 AND (obj.object_name = tbl.table_name)
111 AND (obj.object_type = 'TABLE')
112 AND obj.owner in
113 (l_apps_owner,
114 l_ff_owner,
115 l_ben_owner,
116 l_pay_owner,
117 l_per_owner);
118 -- AND (
119 -- (obj.last_ddl_time >= NVL(tbl.last_generated_date,
120 -- obj.last_ddl_time))
121 -- OR (l_generator_version <> NVL(tbl.generator_version,
122 -- 'none'))
123 -- OR (tbl.last_update_date > NVL(tbl.last_generated_date,
124 -- tbl.last_update_date))
125 -- );
126
127 --
128 BEGIN
129 --
130
131 ben_dm_utility.message('ROUT','entry:ben_dm_init.populate_pi_table_g', 5);
132 ben_dm_utility.message('PARA','(r_migration_data - record)', 10);
133
134 -- get phase id
135 l_phase_id := ben_dm_utility.get_phase_id('G',
136 r_migration_data.migration_id);
137
138 -- read generator version (Tilak)
139 -- hr_dm_library.get_generator_version(p_generator_version =>
140 -- l_generator_version);
141
142 OPEN csr_select_pi;
143 LOOP
144 FETCH csr_select_pi INTO l_table_name;
145 EXIT WHEN csr_select_pi%NOTFOUND;
146
147 INSERT INTO ben_dm_phase_items (PHASE_ITEM_ID,
148 PHASE_ID,
149 GROUP_ORDER,
150 TABLE_NAME,
151 STATUS,
152 START_TIME,
153 END_TIME,
154 CREATED_BY,
155 CREATION_DATE,
156 LAST_UPDATED_BY,
157 LAST_UPDATE_DATE,
158 LAST_UPDATE_LOGIN)
159 SELECT ben_dm_phase_items_s.nextval,
160 l_phase_id,
161 NULL,
162 l_table_name,
163 'NS',
164 NULL,
165 NULL,
166 1,
167 SYSDATE,
168 1,
169 SYSDATE,
170 NULL
171 FROM dual
172 WHERE NOT EXISTS
173 (SELECT NULL FROM ben_dm_phase_items
174 WHERE ((phase_id = l_phase_id)
175 AND (table_name = l_table_name)));
176
177 COMMIT;
178
179 ben_dm_utility.message('INFO','Seeding ' || l_table_name, 11);
180
181 END LOOP;
182 CLOSE csr_select_pi;
183
184 ben_dm_utility.message('INFO','Populate Phase Items table - G phase', 15);
185 ben_dm_utility.message('SUMM','Populate Phase Items table - G phase', 20);
186 ben_dm_utility.message('ROUT','exit:ben_dm_init.populate_pi_table_g', 25);
187 ben_dm_utility.message('PARA','(none)', 30);
188
189 -- error handling
190 EXCEPTION
191 WHEN OTHERS THEN
192 ben_dm_utility.error(SQLCODE,'ben_dm_init.populate_pi_table_g','(none)',
193 'R');
194 RAISE;
195
196 --
197 END populate_pi_table_g;
198 --
199 --
200 -- ------------------------- populate_pi_table_dp ------------------------
201 -- Description: The phase items for the download phase are seeded
202 -- into the ben_dm_phase_items. An entry is made for each group that is
203 -- applicable for the current migration.
204 --
205 --
206 --
207 -- Input Parameters
208 -- r_migration_data - record containing migration information
209 --
210 --
211 -- Output Parameters
212 -- <none>
213 --
214 --
215 -- ------------------------------------------------------------------------
216
217
218 --
219 PROCEDURE populate_pi_table_dp(r_migration_data IN
220 ben_dm_utility.r_migration_rec) IS
221 --
222
223 --
224
225 l_phase_id NUMBER;
226 l_group_order NUMBER;
227 l_input_file_id NUMBER;
228
229 CURSOR csr_select_pi IS
230 SELECT input_file_id, group_order
231 FROM ben_dm_input_file
232 ORDER BY group_order asc;
233
237
234 --
235 BEGIN
236 --
238 ben_dm_utility.message('ROUT','entry:ben_dm_init.populate_pi_table_dp', 5);
239 ben_dm_utility.message('PARA','(r_migration_data - record)', 10);
240
241 l_phase_id := ben_dm_utility.get_phase_id('DP',
242 r_migration_data.migration_id);
243
244
245 OPEN csr_select_pi;
246 LOOP
247 FETCH csr_select_pi INTO l_input_file_id, l_group_order;
248 EXIT WHEN csr_select_pi%NOTFOUND;
249
250 INSERT INTO ben_dm_phase_items (PHASE_ITEM_ID,
251 PHASE_ID,
252 GROUP_ORDER,
253 TABLE_NAME,
254 INPUT_FILE_ID,
255 STATUS,
256 START_TIME,
257 END_TIME,
258 CREATED_BY,
259 CREATION_DATE,
260 LAST_UPDATED_BY,
261 LAST_UPDATE_DATE,
262 LAST_UPDATE_LOGIN)
263 SELECT ben_dm_phase_items_s.nextval,
264 l_phase_id,
265 l_group_order,
266 NULL,
267 l_input_file_id,
268 'NS',
269 NULL,
270 NULL,
271 1,
272 SYSDATE,
273 1,
274 SYSDATE,
275 NULL
276 FROM dual
277 WHERE NOT EXISTS
278 (SELECT NULL FROM ben_dm_phase_items
279 WHERE ((phase_id = l_phase_id)
280 AND (input_file_id = l_input_file_id)));
281
282 COMMIT;
283
284 ben_dm_utility.message('INFO','Seeding ' || l_input_file_id, 11);
285
286
287 END LOOP;
288 CLOSE csr_select_pi;
289
290
291 ben_dm_utility.message('INFO','Populate Phase Items table - DP phase', 15);
292 ben_dm_utility.message('SUMM','Populate Phase Items table - DP phase', 20);
293 ben_dm_utility.message('ROUT','exit:ben_dm_init.populate_pi_table_dp', 25);
294 ben_dm_utility.message('PARA','(none)', 30);
295
296 -- error handling
297 EXCEPTION
298 WHEN OTHERS THEN
299 ben_dm_utility.error(SQLCODE,'ben_dm_init.populate_pi_table_dp','(none)',
300 'R');
301 RAISE;
302
303 --
304 END populate_pi_table_dp;
305 --
306
307 -- ------------------------- populate_pi_table_up ------------------------
308 -- Description: The phase items for the upload phase are seeded
309 -- into the ben_dm_phase_items. An entry is made for each group that is
310 -- applicable for the current migration.
311 --
312 -- Input Parameters
313 -- r_migration_data - record containing migration information
314 --
315 --
316 -- Output Parameters
317 -- <none>
318 --
319 --
320 -- ------------------------------------------------------------------------
321
322
323
324 --
325 PROCEDURE populate_pi_table_up(r_migration_data IN
326 ben_dm_utility.r_migration_rec) IS
327 --
328
329 l_phase_id NUMBER;
330 l_group_order NUMBER;
331
332 CURSOR csr_select_pi IS
333 SELECT distinct group_order
334 FROM ben_dm_input_file
335 -- WHERE migration_id = r_migration_data.migration_id
336 ORDER BY group_order asc;
337
338 --
339 BEGIN
340 --
341
342 ben_dm_utility.message('ROUT','entry:ben_dm_init.populate_pi_table_up', 5);
343 ben_dm_utility.message('PARA','(r_migration_data - record)', 10);
344
345 l_phase_id := ben_dm_utility.get_phase_id('UP',
346 r_migration_data.migration_id);
347
348 OPEN csr_select_pi;
349 LOOP
350 FETCH csr_select_pi INTO l_group_order;
351 EXIT WHEN csr_select_pi%NOTFOUND;
352
353 INSERT INTO ben_dm_phase_items (PHASE_ITEM_ID,
354 PHASE_ID,
355 GROUP_ORDER,
356 TABLE_NAME,
357 STATUS,
358 START_TIME,
359 END_TIME,
360 CREATED_BY,
361 CREATION_DATE,
362 LAST_UPDATED_BY,
363 LAST_UPDATE_DATE,
364 LAST_UPDATE_LOGIN)
365 SELECT ben_dm_phase_items_s.nextval,
366 l_phase_id,
367 l_group_order,
368 NULL,
369 'NS',
370 NULL,
371 NULL,
372 1,
373 SYSDATE,
374 1,
375 SYSDATE,
376 NULL
377 FROM dual
378 WHERE NOT EXISTS
379 (SELECT NULL FROM ben_dm_phase_items
380 WHERE ((phase_id = l_phase_id)
381 AND (group_order = l_group_order)));
382
383 COMMIT;
384
385 ben_dm_utility.message('INFO','Seeding ' || l_group_order, 11);
386
387 END LOOP;
388 CLOSE csr_select_pi;
389
390 -- error handling
391 EXCEPTION
392 WHEN OTHERS THEN
393 ben_dm_utility.error(SQLCODE,'ben_dm_init.populate_pi_table_up','(none)',
394 'R');
395 RAISE;
396
397 --
398 END populate_pi_table_up;
399 --
400 -- ------------------------- populate_pi_table ------------------------
401 -- Description: The code to populate the current phase is called.
402 --
403 --
404 -- Input Parameters
408 --
405 -- r_migration_data - record containing migration information
406 --
407 -- p_phase_name - phase code
409 --
410 -- Output Parameters
411 -- <none>
412 --
413 --
414 -- ------------------------------------------------------------------------
415
416
417 --
418 PROCEDURE populate_pi_table(r_migration_data IN
419 ben_dm_utility.r_migration_rec,
420 p_phase_name IN VARCHAR2) IS
421 --
422
423 --
424 BEGIN
425 --
426
427 ben_dm_utility.message('ROUT','entry:ben_dm_init.populate_pi_table', 5);
428 ben_dm_utility.message('PARA','(r_migration_data - record' ||
429 ')(p_phase_name - ' || p_phase_name || ')', 10);
430
431 IF (p_phase_name = 'I') THEN
432 populate_pi_table_i(r_migration_data);
433 ELSIF (p_phase_name = 'G') THEN
434 populate_pi_table_g(r_migration_data);
435 ELSIF (p_phase_name = 'DP') THEN
436 populate_pi_table_dp(r_migration_data);
437 ELSIF (p_phase_name = 'UP') THEN
438 populate_pi_table_up(r_migration_data);
439 END IF;
440
441 ben_dm_utility.message('INFO','Populate Phase Items table -' ||
442 ' calling phase code', 15);
443 ben_dm_utility.message('SUMM','Populate Phase Items table -' ||
444 ' calling phase code', 20);
445 ben_dm_utility.message('ROUT','exit:ben_dm_init.populate_pi_table', 25);
446 ben_dm_utility.message('PARA','(none)', 30);
447
448 -- error handling
449 EXCEPTION
450 WHEN OTHERS THEN
451 ben_dm_utility.error(SQLCODE,'ben_dm_init.populate_pi_table','(none)','R');
452 RAISE;
453
454 --
455 END populate_pi_table;
456 --
457
458
459 -- ------------------------- populate_phase_items ------------------------
460 -- Description: The phases applicable to the current migration and the
461 -- database location (ie source / destination) are populated by calling
462 -- populate_pi_table.
463 --
464 --
465 -- Input Parameters
466 -- r_migration_data - record containing migration information
467 --
468 --
469 -- Output Parameters
470 -- <none>
471 --
472 --
473 -- ------------------------------------------------------------------------
474
475 --
476 PROCEDURE populate_phase_items(r_migration_data IN
477 ben_dm_utility.r_migration_rec) IS
478
479 --
480
481 l_search_phase VARCHAR2(30);
482 l_phase_name VARCHAR2(30);
483 l_previous_phase VARCHAR2(30);
484 l_next_phase VARCHAR2(30);
485 l_database_location VARCHAR2(30);
486
487 CURSOR csr_phase_rule IS
488 SELECT phase_name, previous_phase, next_phase, database_location
489 FROM hr_dm_phase_rules
490 WHERE ((migration_type = 'SP')
491 AND (previous_phase = l_search_phase))
492 AND database_location = r_migration_data.database_location;
493 --
494 BEGIN
495 --
496
497 ben_dm_utility.message('ROUT','entry:ben_dm_init.populate_phase_items', 5);
498 ben_dm_utility.message('PARA','(r_migration_data - record)', 10);
499
500 -- seed first phase
501 l_search_phase := 'START';
502 l_next_phase := '?';
503
504 WHILE (l_next_phase <> 'END') LOOP
505 OPEN csr_phase_rule;
506 FETCH csr_phase_rule INTO l_phase_name, l_previous_phase,
507 l_next_phase, l_database_location;
508 -- add check to exit if table is not seed/problem
509 EXIT WHEN csr_phase_rule%NOTFOUND;
510
511 -- does it apply?
512 IF (INSTR(l_database_location, r_migration_data.database_location) >0) THEN
513 populate_pi_table(r_migration_data, l_phase_name);
514 END IF;
515 l_search_phase := l_phase_name;
516 CLOSE csr_phase_rule;
517 END LOOP;
518 ben_dm_utility.message('INFO','Populate Phase Items table', 15);
519 ben_dm_utility.message('SUMM','Populate Phase Items table', 20);
520 ben_dm_utility.message('ROUT','exit:ben_dm_init.populate_phase_items', 25);
521 ben_dm_utility.message('PARA','(none)', 30);
522
523 -- error handling
524 EXCEPTION
525 WHEN OTHERS THEN
526 ben_dm_utility.error(SQLCODE,'ben_dm_init.populate_phase_items',
527 '(none)','R');
528 RAISE;
529
530 --
531 END populate_phase_items;
532 --
533
534 -- ------------------------- populate_p_table ----------------------
535 -- Description: The phases applicable to the current migration and the
536 -- database location (ie source / destination) are seeded into the
537 -- hr_dm_phases table.
538 --
539 --
540 -- Input Parameters
541 -- r_migration_data - record containing migration information
542 --
543 --
544 -- Output Parameters
545 -- <none>
546 --
547 --
548 -- ------------------------------------------------------------------------
549
550 --
551 PROCEDURE populate_p_table(r_migration_data IN ben_dm_utility.r_migration_rec,
552 p_phase_name IN VARCHAR2) IS
553 --
554
555 --
556 BEGIN
557 --
558
559 ben_dm_utility.message('ROUT','entry:ben_dm_init.populate_p_table', 5);
560 ben_dm_utility.message('PARA','(r_migration_data - record' ||
561 ')(p_phase_name - ' || p_phase_name || ')', 10);
562
563 INSERT INTO ben_dm_phases (PHASE_ID,
564 MIGRATION_ID,
565 PHASE_NAME,
566 STATUS,
567 START_TIME,
568 END_TIME,
569 CREATED_BY,
570 CREATION_DATE,
574 SELECT ben_dm_phases_s.nextval,
571 LAST_UPDATED_BY,
572 LAST_UPDATE_DATE,
573 LAST_UPDATE_LOGIN)
575 r_migration_data.migration_id,
576 p_phase_name,
577 'NS',
578 NULL,
579 NULL,
580 1,
581 SYSDATE,
582 1,
583 SYSDATE,
584 NULL
588 WHERE ((migration_id = r_migration_data.migration_id)
585 FROM dual
586 WHERE NOT EXISTS
587 (SELECT NULL FROM ben_dm_phases
589 AND (phase_name = p_phase_name)));
590
591 COMMIT;
592
593 ben_dm_utility.message('INFO','Populate Phases table', 15);
594 ben_dm_utility.message('SUMM','Populate Phases table', 20);
595 ben_dm_utility.message('ROUT','exit:ben_dm_init.populate_p_table', 25);
596 ben_dm_utility.message('PARA','(none)', 30);
597
598 -- error handling
599 EXCEPTION
600 WHEN OTHERS THEN
601 ben_dm_utility.error(SQLCODE,'ben_dm_init.populate_p_table','(none)','R');
602 RAISE;
603
604 --
605 END populate_p_table;
606 --
607
608
609 -- ------------------------- populate_populate_phases ----------------------
610 -- Description: The phases applicable to the current migration and the
611 -- database location (ie source / destination) are populated by calling
612 -- populate_p_table.
613 --
614 --
615 -- Input Parameters
616 -- r_migration_data - record containing migration information
617 --
618 --
619 -- Output Parameters
620 -- <none>
621 --
622 --
623 -- ------------------------------------------------------------------------
624
625 --
626 PROCEDURE populate_phases(r_migration_data IN
627 ben_dm_utility.r_migration_rec) IS
628 --
629
630 l_phase_name VARCHAR2(30);
631 l_database_location VARCHAR2(30);
632
633 CURSOR csr_phase_rule IS
634 SELECT phase_name, database_location
635 FROM hr_dm_phase_rules
636 WHERE ((migration_type = 'SP')
637 AND database_location = r_migration_data.database_location);
638 -- AND (INSTR(database_location,
639 -- r_migration_data.database_location) >0));
640
641 --
642 BEGIN
643 --
644
645 ben_dm_utility.message('ROUT','entry:ben_dm_init.populate_phases', 5);
646 ben_dm_utility.message('PARA','(r_migration_data - record)', 10);
647
648
649 OPEN csr_phase_rule;
650 LOOP
651 FETCH csr_phase_rule INTO l_phase_name, l_database_location;
652 EXIT WHEN csr_phase_rule%NOTFOUND;
653 populate_p_table(r_migration_data, l_phase_name);
654 END LOOP;
655 CLOSE csr_phase_rule;
656
657 ben_dm_utility.message('INFO','Populate Phase Items table', 15);
658 ben_dm_utility.message('SUMM','Populate Phase Items table', 20);
659 ben_dm_utility.message('ROUT','exit:ben_dm_init.populate_phases', 25);
660 ben_dm_utility.message('PARA','(none)', 30);
661
662 -- error handling
663 EXCEPTION
664 WHEN OTHERS THEN
665 ben_dm_utility.error(SQLCODE,'ben_dm_init.populate_phases','(none)','R');
666 RAISE;
667
668 --
669 END populate_phases;
670 --
671
672
673
674
675 /*-------------------------- PUBLIC ROUTINES ---------------------------*/
676
677 -- ------------------------- main ----------------------
678 -- Description: The phases and associated phase items that are applicable
679 -- to the current migration and the database location (ie source /
680 -- destination) are seeded.
681 --
682 --
683 -- Input Parameters
684 -- r_migration_data - record containing migration information
685 --
686 --
687 -- Output Parameters
688 -- <none>
689 --
690 --
691 -- ------------------------------------------------------------------------
692 --
693 PROCEDURE main(r_migration_data IN ben_dm_utility.r_migration_rec) IS
694 --
695
696 l_current_phase_status VARCHAR2(30);
697
698 --
699 BEGIN
700 --
701
702 ben_dm_utility.message('ROUT','entry:ben_dm_init.main', 5);
703 ben_dm_utility.message('PARA','(r_migration_data - record)', 10);
704
705
706 -- get status of initialization phase, is phase completed?
707 -- if null returned, then assume it is NS.
708 l_current_phase_status := NVL(ben_dm_utility.get_phase_status('I',
709 r_migration_data.migration_id), 'NS');
710
711 -- is phase complete?
712 -- if so, skip all processing
713 IF (l_current_phase_status <> 'C') THEN
714 -- do we need to explicitly rollback using rollback utility?
718 END IF;
715 IF (l_current_phase_status IN('S', 'E')) THEN
716 ben_dm_utility.rollback(p_phase => 'I',
717 p_migration_id => r_migration_data.migration_id);
719
720 -- populate phases table
721 populate_phases(r_migration_data);
722
723
724 -- update status to started
725 ben_dm_utility.update_phases(p_new_status => 'S',
726 p_id => ben_dm_utility.get_phase_id('I',
727 r_migration_data.migration_id));
728
729 -- populate phase_items table
730 populate_phase_items(r_migration_data);
731
732 -- delete the contents of hr_dm_exp_imps table
733 -- if we are on the source database only
734 IF (r_migration_data.database_location = 'S') THEN
735 DELETE ben_dm_entity_results;
736 COMMIT;
737 END IF;
738
739 -- update status to completed
740 ben_dm_utility.update_phases(p_new_status => 'C',
741 p_id => ben_dm_utility.get_phase_id('I',
742 r_migration_data.migration_id));
743
744 END IF;
745
746 ben_dm_utility.message('INFO','Initialization Phase', 15);
747 ben_dm_utility.message('SUMM','Initialization Phase', 20);
748 ben_dm_utility.message('ROUT','exit:ben_dm_init.main', 25);
749 ben_dm_utility.message('PARA','(none)', 30);
750
751 -- error handling
752 EXCEPTION
753 WHEN OTHERS THEN
754 ben_dm_utility.error(SQLCODE,'ben_dm_init.main','(none)','R');
755 RAISE;
756
757 --
758 END main;
759 --
760
761 END ben_dm_init;