1 PACKAGE BODY igs_he_create_extract_pkg AS
2 /* $Header: IGSHE28B.pls 120.3 2006/05/22 00:11:18 jbaber noship $*/
3
4 -- Field stat record stores field length and closed_flag
5 TYPE field_stats_rec IS RECORD (length NUMBER, closed VARCHAR2(1));
6
7 -- Lookup table for field stat record
8 TYPE field_lookup_tbl IS TABLE OF field_stats_rec INDEX BY BINARY_INTEGER;
9
10
11 PROCEDURE create_directory ( p_directory OUT NOCOPY VARCHAR2 ) AS
12 /******************************************************************
13 Created By : ayedubat
14 Date Created By : 24-Dec-02
15 Purpose: Private procedure created for finding the Directory of the filename.
16 This will check the value of profile 'UTL_FILE_OUT'
17 (output dir for export data file) matches with the value in v$parameter
18 for the name utl_file_dir.
19 Known limitations,enhancements,remarks:
20 Change History
21 Who When What
22 *******************************************************************/
23
24 l_start_str_index NUMBER := 1;
25 l_end_comma_index NUMBER := 1;
26 l_start_comma_index NUMBER := 1;
27 l_fndvalue VARCHAR2(80);
28 l_dbvalue V$PARAMETER.VALUE%TYPE;
29 l_db_directory V$PARAMETER.VALUE%TYPE;
30
31 CURSOR cur_parameter_value IS
32 SELECT LTRIM(RTRIM(value))
33 FROM V$PARAMETER
34 WHERE name ='utl_file_dir';
35
36 CURSOR cur_db_dir IS
37 SELECT DECODE( INSTR(l_dbvalue,',',l_start_str_index),0,LENGTH(l_dbvalue)+1, INSTR(l_dbvalue,',',l_start_str_index) )
38 FROM DUAL ;
39
40 BEGIN
41
42 -- Initialize the OUT variable
43 p_directory := NULL ;
44
45 -- Fetch the Profile value for the directory name used to export flat file
46 l_fndvalue := LTRIM(RTRIM(FND_PROFILE.VALUE('UTL_FILE_OUT')));
47
48 -- If the profile is NULL, return the procedure by assigning the NULL value to p_directory
49 IF l_fndvalue IS NULL THEN
50 p_directory := NULL ;
51 RETURN ;
52 END IF ;
53
54 -- Fetch the Value of the Database parameter, utl_file_dir
55 -- which contains list of out put directories seperated by comma
56 OPEN cur_parameter_value ;
57 FETCH cur_parameter_value INTO l_dbvalue ;
58
59 IF cur_parameter_value%FOUND AND l_dbvalue IS NOT NULL THEN
60
61 -- Find the starting position of the Profile value with in the database parameter directory's list
62 -- If not found, return the procedure by assigning the NULL value to p_directory
63 l_start_str_index := INSTR(l_dbvalue,l_fndvalue,l_end_comma_index) ;
64
65 IF l_start_str_index = 0 THEN
66 p_directory := NULL ;
67 CLOSE cur_parameter_value ;
68 RETURN ;
69 END IF;
70
71 -- Find the position of the comma, which is just before the
72 -- required directory(Profile value) in the database parameter value
73 -- If no comma found( if it first in the list), then returns 1
74 l_start_comma_index := INSTR(SUBSTR(l_dbvalue,1,l_start_str_index),',',-1) + 1 ;
75
76 -- Find the position of the comma, which is just after the
77 -- required directory(Profile value) in the database parameter value
78 -- If no comma found( if it last in the list), then returns the length of database parameter value
79 OPEN cur_db_dir ;
80 FETCH cur_db_dir INTO l_end_comma_index ;
81 CLOSE cur_db_dir ;
82
83 -- Find the value of the Database parameter value between l_start_comma_index and l_end_comma_index
84 l_db_directory := LTRIM(RTRIM(SUBSTR(l_dbvalue,l_start_comma_index, l_end_comma_index-l_start_comma_index))) ;
85
86 -- If the Profile Value is with in the Database parameter sirectory list, return the value
87 IF l_db_directory = l_fndvalue THEN
88 p_directory := l_fndvalue ;
89 END IF;
90
91 ELSE
92 p_directory := NULL ;
93
94 END IF ;
95 CLOSE cur_parameter_value ;
96
97 EXCEPTION
98 WHEN OTHERS THEN
99 p_directory := NULL ;
100 Fnd_Message.Set_name('IGS','IGS_GE_UNHANDLED_EXP');
101 FND_MESSAGE.SET_TOKEN('NAME','IGS_HE_CREATE_EXTRACT_PKG.CREATE_DIRECTORY'||' - '||SQLERRM);
102 IGS_GE_MSG_STACK.ADD;
103 App_Exception.Raise_Exception;
104
105 END create_directory ;
106
107
108 PROCEDURE create_file (errbuf OUT NOCOPY VARCHAR2,
109 retcode OUT NOCOPY NUMBER,
110 p_extract_run_id IN NUMBER,
111 p_file_format IN VARCHAR2,
112 p_use_overrides IN VARCHAR2,
113 p_person_id_grp IN NUMBER,
114 p_program_group IN VARCHAR2,
115 p_created_since_date IN VARCHAR2 ) IS
116 /******************************************************************
117 Created By : Jonathan Baber
118 Date Created By : 23-Nov-05
119 Purpose : Creates extract file
120 Known limitations,enhancements,remarks:
121 Change History
122 Who When What
123 anwest 13-FEB-2006 Bug# 4950285 R12 Disable OSS Mandate
124 *******************************************************************/
125
126 -- Get extract run details
127 CURSOR c_extract_dtls IS
128 SELECT SUBSTR(srt.record_id,4,2) recid,
129 dtls.submission_name,
130 dtls.user_return_subclass,
131 dtls.return_name,
132 dtls.file_location,
133 dtls.file_name,
134 shd.enrolment_start_date,
135 shd.enrolment_end_date
136 FROM igs_he_ext_run_dtls dtls,
137 igs_he_submsn_header shd,
138 igs_he_submsn_return srt
139 WHERE dtls.extract_run_id = p_extract_run_id
140 AND shd.submission_name = dtls.submission_name
141 AND srt.submission_name = dtls.submission_name
142 AND srt.user_return_subclass = dtls.user_return_subclass
143 AND srt.return_name = dtls.return_name;
144
145 -- Get length and closed_flag of each field in return
146 CURSOR c_field_stats (cp_user_return_subclass igs_he_usr_rtn_clas.user_return_subclass%TYPE) IS
147 SELECT sfld.field_number,
148 NVL(sfld.length,0) length,
149 sfld.closed_flag
150 FROM igs_he_sys_rt_cl_fld sfld,
151 igs_he_usr_rt_cl_fld ufld,
152 igs_he_usr_rtn_clas uclas
153 WHERE uclas.user_return_subclass = cp_user_return_subclass
154 AND sfld.system_return_class_type = uclas.system_return_class_type
155 AND ufld.field_number = sfld.field_number
156 AND ufld.user_return_subclass = uclas.user_return_subclass;
157
158 -- Get every field in an extract for given line
159 CURSOR c_extract_field(cp_line_number igs_he_ex_rn_dat_ln.line_number%type) IS
160 SELECT value, override_value, field_number
161 FROM igs_he_ex_rn_dat_fd
162 WHERE extract_run_id = p_extract_run_id
163 AND line_number = cp_line_number
164 ORDER BY field_number ASC;
165
166 -- Determine type (static or dynamic) of persion id group
167 CURSOR c_group_type IS
168 SELECT group_type
169 FROM igs_pe_persid_group_v
170 WHERE group_id = p_person_id_grp;
171
172
173 TYPE ref_extract_line IS REF CURSOR;
174 c_extract_line ref_extract_line;
175
176
177 l_filepath VARCHAR2(270);
178 l_field_stat field_stats_rec;
179 l_field_lookup field_lookup_tbl;
180 l_line_count NUMBER := 0;
181 l_final_value VARCHAR2(200);
182 l_field_length igs_he_sys_rt_cl_fld.length%TYPE;
183 l_value_field_length NUMBER(3);
184 l_prs_grp_status VARCHAR2(1) := NULL;
185 l_group_type igs_pe_persid_group_v.group_type%TYPE;
186 l_file utl_file.file_type := NULL;
187 l_sqlstmt VARCHAR2(32767);
188 l_prs_grp_sql VARCHAR2(32767);
189 l_extract_dtls c_extract_dtls%ROWTYPE;
190 l_line_number igs_he_ex_rn_dat_ln.line_number%TYPE;
191
192 l_bind2 NUMBER;
193 l_bind3 DATE;
194 l_bind4 DATE;
195 l_bind6 DATE;
196 l_bind5 VARCHAR2(10);
197
198 BEGIN
199
200 --anwest 18-JAN-2006 Bug# 4950285 R12 Disable OSS Mandate
201 IGS_GE_GEN_003.SET_ORG_ID;
202
203 -- Get extract run details
204 OPEN c_extract_dtls;
205 FETCH c_extract_dtls INTO l_extract_dtls;
206 CLOSE c_extract_dtls;
207
208
209 -- Log Header
210 fnd_message.set_name('IGS','IGS_HE_PROC_SUBM');
211 fnd_message.set_token('SUBMISSION_NAME',l_extract_dtls.submission_name);
212 fnd_message.set_token('USER_RETURN_SUBCLASS',l_extract_dtls.user_return_subclass);
213 fnd_message.set_token('RETURN_NAME',l_extract_dtls.return_name);
214 fnd_message.set_token('ENROLMENT_START_DATE',l_extract_dtls.enrolment_start_date);
215 fnd_message.set_token('ENROLMENT_END_DATE',l_extract_dtls.enrolment_end_date);
216 fnd_file.put_line(fnd_file.log,fnd_message.get());
217
218
219 -- Get file directory
220 create_directory(l_filepath);
221
222 -- If directory is NULL return with error
223 IF l_filepath IS NULL THEN
224 fnd_message.set_name('IGS','IGS_HE_FILE_DIR_ERROR');
225 errbuf := fnd_message.get;
226 fnd_file.put_line(fnd_file.log, errbuf);
227 retcode:=2;
228 RETURN;
229 END IF ;
230
231
232 -- Open file
233 BEGIN
234 l_file := NULL;
235 l_file := UTL_FILE.FOPEN (l_filepath, l_extract_dtls.file_name, 'w');
236 EXCEPTION
237 WHEN OTHERS THEN
238 fnd_message.set_name('IGS','IGS_HE_FILE_OPEN_ERROR');
239 fnd_message.set_token('1', l_filepath || '/' || l_extract_dtls.file_name);
240 errbuf := fnd_message.get;
241 fnd_file.put_line(fnd_file.log, errbuf);
242 retcode := 2;
243 RETURN;
244 END;
245
246
247 -- Construct Line SQL statement.
248 l_sqlstmt := ' SELECT line_number ' ||
249 ' FROM igs_he_ex_rn_dat_ln ln ' ||
250 ' WHERE ln.extract_run_id = :BIND1' ||
251 ' AND ln.exclude_from_file = ''N'' ';
252
253
254
255 -- Include person group criteria if required
256 -- Does not apply to MODULE return
257 IF p_person_id_grp IS NOT NULL AND l_extract_dtls.recid <> '13' THEN
258
259 -- Determine type (static or dynamic) of person id group
260 OPEN c_group_type;
261 FETCH c_group_type INTO l_group_type;
262 CLOSE c_group_type;
263
264 IF l_group_type = 'STATIC' THEN
265
266 -- Could also use the library file to get static group members but the library
267 -- uses sysdate instead of enrolment start and end date.
268
269 l_prs_grp_sql := ' AND EXISTS ' ||
270 ' (SELECT ''X'' ' ||
271 ' FROM igs_pe_prsid_grp_mem_all a ' ||
272 ' WHERE a.person_id = ln.person_id ' ||
273 ' AND a.group_id = :BIND2 ' ||
274 ' AND (a.start_date IS NULL OR a.start_date <= :BIND3) ' ||
275 ' AND (a.end_date IS NULL OR a.end_date >= :BIND4) ' ||
276 ' )';
277
278 l_sqlstmt := l_sqlstmt || l_prs_grp_sql;
279
280 -- Set bind variables
281 l_bind2 := p_person_id_grp;
282 l_bind3 := l_extract_dtls.enrolment_end_date;
283 l_bind4 := l_extract_dtls.enrolment_start_date;
284
285 ELSE
286 -- Use library to get dynamic persion id group members
287 l_prs_grp_sql := IGS_PE_DYNAMIC_PERSID_GROUP.IGS_GET_DYNAMIC_SQL(p_person_id_grp, l_prs_grp_status);
288
289 IF l_prs_grp_status <> 'S' THEN
290 fnd_message.set_name('IGS','IGS_HE_UT_PRSN_ID_GRP_ERR');
291 fnd_message.set_token('PRSNIDGRP',p_person_id_grp);
292 errbuf := fnd_message.get();
293 fnd_file.put_line(fnd_file.log, errbuf); -- this message need to be displayed to user.
294 retcode := '2';
295 RETURN;
296 END IF;
297
298 l_sqlstmt := l_sqlstmt || 'AND ln.person_id IN ('|| l_prs_grp_sql || ')';
299
300 -- Need to add consistent number of bind variables even if not used
301 l_sqlstmt := l_sqlstmt || ' AND :BIND2 IS NULL AND :BIND3 IS NULL AND :BIND4 IS NULL ';
302
303 END IF; -- Static / Dynamic
304
305 ELSE
306 -- No person_id_grp criteria, but need to add some to have consistent number of bind variables
307 l_sqlstmt := l_sqlstmt || ' AND :BIND2 IS NULL AND :BIND3 IS NULL AND :BIND4 IS NULL ';
308
309
310 END IF; -- Person ID Group Criteria
311
312
313 -- Include program group criteria if required
314 -- only applies to COMBINED or STUDENT return
315 IF p_program_group IS NOT NULL AND l_extract_dtls.recid IN ('11','12') THEN
316
317 l_sqlstmt := l_sqlstmt ||
318 ' AND EXISTS ' ||
319 ' (SELECT ''X'' ' ||
320 ' FROM igs_ps_grp_mbr b ' ||
321 ' WHERE b.course_cd = ln.course_cd ' ||
322 ' AND b.version_number = ln.crv_version_number ' ||
323 ' AND b.course_group_cd = :BIND5 ' ||
324 ' )';
325
326 l_bind5 := p_program_group;
327
328 ELSE
329
330 -- No progam_grp criteria, but need to have consistent number of bind variables
331 l_sqlstmt := l_sqlstmt || ' AND :BIND5 IS NULL ';
332
333 END IF; -- Program Group Criteria
334
335
336 -- Include created since date criteria if required
337 IF p_created_since_date IS NOT NULL THEN
338
339 l_sqlstmt := l_sqlstmt || ' AND ln.last_update_date >= :BIND6 ';
340
341 -- Created since date bind variable is formatted according to concurrent request format.
342 l_bind6 := TO_DATE(p_created_since_date,'yyyy/mm/dd HH24:MI:SS');
343
344 ELSE
345
346 -- No created since criteria criteria, but need to have consistent number of bind variables
347 l_sqlstmt := l_sqlstmt || ' AND :BIND6 IS NULL ';
348
349 END IF;
350
351 -- Finish constructing Line SQL statement
352 l_sqlstmt := l_sqlstmt || ' ORDER BY line_number ASC ';
353
354
355
356 OPEN c_extract_line FOR l_sqlstmt USING p_extract_run_id, l_bind2, l_bind3, l_bind4, l_bind5, l_bind6;
357 FETCH c_extract_line INTO l_line_number;
358
359 -- Make sure there are some lines in the extract otherwise no point in continuing
360 IF c_extract_line%NOTFOUND THEN
361 CLOSE c_extract_line;
362 fnd_message.set_name('IGS','IGS_HE_NO_DTLS_TO_OP');
363 errbuf := fnd_message.get;
364 fnd_file.put_line(fnd_file.log, errbuf);
365 retcode := 1;
366 RETURN;
367
368 ELSE
369
370 -- Get length and closed_flag of each field
371 -- Store in l_field_lookup
372 -- Should use BULK COLLECT in post 8i database
373 FOR l_field IN c_field_stats(l_extract_dtls.user_return_subclass) LOOP
374 l_field_stat.length := l_field.length;
375 l_field_stat.closed := l_field.closed_flag;
376 l_field_lookup(l_field.field_number) := l_field_stat;
377 END LOOP;
378
379
380 -- For every line in the extract
381 WHILE c_extract_line%FOUND LOOP
382
383 FOR l_extract_field in c_extract_field(l_line_number) LOOP
384
385 -- Detemine value of field
386 -- If field is closed, value = NULL
387 -- If overrides are to be used and override value not blank, value = overide
388 -- Otherwise just get value
389 IF l_field_lookup(l_extract_field.field_number).closed = 'Y' THEN
390 l_final_value := NULL;
391 ELSIF p_use_overrides = 'Y' AND l_extract_field.override_value IS NOT NULL THEN
392 IF l_extract_field.override_value = 'NULL' THEN
393 l_final_value := NULL;
394 ELSE
395 l_final_value := ltrim(rtrim(REPLACE(l_extract_field.override_value,'"','') ));
396 END IF;
397 ELSE
398 l_final_value := ltrim(rtrim(REPLACE(l_extract_field.value,'"','') ));
399 END IF;
400
401
402 -- Get length of value and length of field
403 l_value_field_length := NVL(LENGTH(l_final_value),0) ;
404 l_field_length := l_field_lookup(l_extract_field.field_number).length;
405
406
407 -- Truncate value to field length
408 IF ( l_value_field_length > l_field_length) THEN
409 l_final_value := SUBSTR( l_final_value,1,l_field_length) ;
410 END IF;
411
412
413 -- If file format = fixed then pad value
414 IF p_file_format = 'FIX' AND ( l_value_field_length < l_field_length) THEN
415 l_final_value := RPAD( NVL(l_final_value,' '),l_field_length) ;
416 END IF;
417
418
419 -- If file format = csv then prepend ',' on all but first field
420 IF p_file_format = 'CSV' THEN
421 l_final_value := ltrim(rtrim( REPLACE(l_final_value,',',' ') )) ;
422 IF (c_extract_field%ROWCOUNT > 1) THEN
423 l_final_value := ',' || l_final_value;
424 END IF;
425 END IF;
426
427 -- Write field to file
428 BEGIN
429 utl_file.put (l_file, l_final_value );
430 EXCEPTION
431 WHEN UTL_FILE.WRITE_ERROR THEN
432 fnd_message.set_name('IGS', 'IGS_HE_FILE_WRITE_ERROR');
433 fnd_message.set_token('1', l_filepath || '/' || l_extract_dtls.file_name);
434 fnd_file.put_line(fnd_file.log, fnd_message.get);
435 RAISE;
436 END;
437
438 l_final_value :='';
439
440 END LOOP; -- c_extract_field
441
442 -- Append a new line character at the end and write to file
443 utl_file.new_line (l_file);
444 utl_file.fflush (l_file);
445
446 -- Get next line
447 FETCH c_extract_line INTO l_line_number;
448
449 END LOOP; -- c_extract_line
450
451 -- Get line count
452 l_line_count := c_extract_line%ROWCOUNT;
453
454 END IF;
455
456 CLOSE c_extract_line;
457
458 -- Close file
459 BEGIN
460 IF (utl_file.is_open( l_file )) THEN
461 utl_file.fclose( l_file );
462 END IF;
463 EXCEPTION
464 WHEN OTHERS THEN
465 fnd_message.set_name('IGS','IGS_HE_FILE_CLOSE_ERROR');
466 fnd_message.set_token('1', l_filepath || '/' || l_extract_dtls.file_name);
467 fnd_file.put_line(fnd_file.log, fnd_message.get);
468 errbuf := fnd_message.get ;
469 retcode := 2;
470 RETURN;
471 END;
472
473 -- Update extract criteria with location file has been written to
474 UPDATE igs_he_ext_run_dtls
475 SET file_location = l_filepath
476 WHERE extract_run_id = p_extract_run_id;
477
478 -- Log lines written and filename
479 fnd_message.set_name('IGS','IGS_HE_FILE_LINES_WRITTEN');
480 fnd_message.set_token('NUMLINES', l_line_count);
481 fnd_message.set_token('FILE', l_filepath || '/' || l_extract_dtls.file_name);
482 fnd_file.put_line(fnd_file.log, fnd_message.get);
483
484
485 EXCEPTION
486 WHEN OTHERS THEN
487
488 -- Close any open cursors
489 IF c_extract_field%ISOPEN THEN
490 CLOSE c_extract_field;
491 END IF;
492
493 IF c_extract_line%ISOPEN THEN
494 CLOSE c_extract_line;
495 END IF;
496
497 retcode := 2;
498 Fnd_Message.Set_Name('IGS','IGS_GE_UNHANDLED_EXP');
499 Fnd_Message.Set_Token('NAME','igs_he_create_extract_pkg.create_file - ' ||SQLERRM);
500 fnd_file.put_line(fnd_file.log, fnd_message.get);
501 App_Exception.Raise_Exception;
502
503 END create_file;
504
505
506 END igs_he_create_extract_pkg ;