DBA Data[Home] [Help]

PACKAGE BODY: APPS.IGS_EN_SPA_TERMS_API

Source


1 PACKAGE BODY IGS_EN_SPA_TERMS_API AS
2 /* $Header: IGSENB1B.pls 120.14 2005/11/28 02:26:46 appldev noship $ */
3 
4 CURSOR c_term_exists(cp_person_id IGS_PE_PERSON.person_id%TYPE,
5                      cp_program_cd IGS_PS_VER.course_cd%TYPE,
6                      cp_program_version IGS_PS_VER.version_number%TYPE,
7                      cp_term_cal_type IGS_CA_INST.cal_type%TYPE,
8                      cp_term_sequence_number IGS_CA_INST.sequence_number%TYPE) IS
9 SELECT spat.term_record_id
10        FROM IGS_EN_SPA_TERMS spat, igs_ps_ver cv1
11        WHERE spat.person_id = cp_person_id
12        AND   spat.term_cal_type = cp_term_cal_type
13        AND   spat.term_sequence_number = cp_term_sequence_number
14        AND   cv1.course_cd = spat.program_cd
15        AND   cv1.version_number = spat.program_version
16        AND
17        (    (
18                  NVL(FND_PROFILE.VALUE('CAREER_MODEL_ENABLED'),'N') = 'Y'
19                  AND  cv1.course_type = (SELECT cv2.course_type
20                                FROM IGS_PS_VER cv2
21                                WHERE cv2.course_cd      = cp_program_cd
22                                AND   cv2.version_number = cp_program_version)
23             )
24             OR
25             (   NVL(FND_PROFILE.VALUE('CAREER_MODEL_ENABLED'),'N') = 'N'
26                 AND spat.program_cd = cp_program_cd
27             )
28        );
29 
30 PROCEDURE set_spa_term_cal_type(p_spa_term_cal_type IN VARCHAR2)
31 AS
32 BEGIN
33         g_spa_term_cal_type := p_spa_term_cal_type;
34 END;
35 
36 PROCEDURE set_spa_term_sequence_number(p_spa_term_sequence_number IN NUMBER)
37 AS
38 BEGIN
39         g_spa_term_sequence_number := p_spa_term_sequence_number;
40 END;
41 
42 PROCEDURE validate_term_rec(p_term_rec EN_SPAT_REC_TYPE%TYPE) AS
43 
44 -- Check if the term calendar is subordinate to the acad cal type
45 -- as defined in its term record
46 cursor c_term_acad IS
47 SELECT 'x'
48 FROM  igs_ca_inst_rel
49 WHERE sub_cal_type = p_term_rec.term_cal_type
50 AND   sub_ci_sequence_number = p_term_rec.term_sequence_number
51 AND   sup_cal_type = p_term_rec.acad_cal_type;
52 
53 -- Check if the program offering option with the values specified
54 -- in term record exists
55 cursor c_coo_valid IS
56 SELECT 'x'
57 FROM igs_ps_ofr_opt
58 WHERE coo_id = p_term_rec.coo_id
59 AND   location_cd = p_term_rec.location_cd
60 AND   version_number = p_term_rec.program_version
61 AND   attendance_type = p_term_rec.attendance_type
62 AND   attendance_mode = p_term_rec.attendance_mode
63 AND   cal_type = p_term_rec.acad_cal_type
64 AND   course_cd = p_term_rec.program_cd;
65 
66 l_dummy VARCHAR2(1);
67 BEGIN
68     OPEN c_term_acad;
69     FETCH c_term_acad INTO l_dummy;
70     IF (c_term_acad%NOTFOUND) THEN
71           CLOSE c_term_acad;
72 
73           FND_MESSAGE.SET_NAME('IGS','IGS_EN_TERM_VALID_FAILED');
74           IGS_GE_MSG_STACK.ADD;
75           APP_EXCEPTION.RAISE_EXCEPTION;
76     END IF;
77     CLOSE c_term_acad;
78     OPEN c_coo_valid;
79     FETCH c_coo_valid INTO l_dummy;
80     IF (c_coo_valid%NOTFOUND) THEN
81         CLOSE c_coo_valid;
82         FND_MESSAGE.SET_NAME('IGS','IGS_EN_TERM_VALID_FAILED');
83         IGS_GE_MSG_STACK.ADD;
84         APP_EXCEPTION.RAISE_EXCEPTION;
85     END IF;
86     CLOSE c_coo_valid;
87 
88 END validate_term_rec;
89 
90 
91 FUNCTION find_key_effective_for(p_person_id IN IGS_PE_PERSON.PERSON_ID%TYPE,
92                 p_term_cal_type IN igs_ca_inst.cal_type%TYPE,
93                 p_term_sequence_number IN igs_ca_inst.sequence_number%TYPE) RETURN VARCHAR2
94 AS
95 -- Check if key term record exists for the passed in term calendar
96 cursor c_key_record_exists IS
97 select program_cd from igs_en_spa_terms where person_id = p_person_id
98 and key_program_flag = 'Y'
99 and term_cal_type = p_term_cal_type
100 and term_sequence_number = p_term_sequence_number;
101 
102 -- Check the oldest key term record in terms table
103 CURSOR c_oldest_term IS
104 SELECT program_cd, acad_cal_type
105 FROM igs_en_spa_terms spat, igs_ca_inst ca1
106 WHERE person_id = p_person_id
107 AND   spat.term_cal_type = ca1.cal_type
108 AND   spat.term_sequence_number = ca1.sequence_number
109 AND   spat.key_program_flag = 'Y'
110 ORDER BY ca1.start_dt ASC;
111 
112 -- Check the key term record before this term
113 CURSOR c_key_from_prev_term IS
114 select program_cd, acad_cal_type from igs_en_spa_terms spat, igs_ca_inst ca1, igs_ca_inst ca2
115 where key_program_flag = 'Y'
116 and person_id = p_person_id
117 and ca1.cal_type = term_cal_type
118 and ca1.sequence_number = term_sequence_number
119 and ca2.cal_type = p_term_cal_type
120 and ca2.sequence_number = p_term_sequence_number
121 and ca1.start_dt < ca2.start_dt order by ca1.start_dt desc;
122 
123 -- Key program as in student program attempt and its academic calendar
124 CURSOR c_key_from_spa IS
125 select course_cd, cal_type from igs_en_stdnt_ps_att where person_id = p_person_id and key_program ='Y';
126 
127 -- Check if the academic calendar for the key determined is same as that of passed in term.
128 CURSOR c_key_in_same_acad(cp_acad_cal_type IGS_CA_INST.CAL_TYPE%TYPE) IS
129 SELECT 'x'
130 FROM igs_ca_inst_rel
131 WHERE sub_cal_type = p_term_cal_type
132 and   sub_ci_sequence_number = p_term_sequence_number
133 and sup_cal_type = cp_acad_cal_type;
134 
135 l_program_cd IGS_PS_VER.course_cd%TYPE;
136 l_dummy VARCHAR2(1);
137 l_acad_cal_type IGS_CA_INST.CAL_TYPE%TYPE;
138 BEGIN
139 OPEN c_key_record_exists;
140 FETCH c_key_record_exists INTO l_program_cd;
141 IF (c_key_record_exists%FOUND) THEN
142         CLOSE c_key_record_exists;
143         RETURN l_program_cd;
144 END IF;
145 CLOSE c_key_record_exists;
146 OPEN c_key_from_prev_term;
147 FETCH c_key_from_prev_term INTO l_program_cd, l_acad_cal_type;
148 IF (c_key_from_prev_term%NOTFOUND) THEN
149         OPEN c_oldest_term;
150         FETCH c_oldest_term INTO l_program_cd, l_acad_cal_type;
151         IF  c_oldest_term%NOTFOUND THEN
152                 OPEN c_key_from_spa;
153                 FETCH c_key_from_spa INTO l_program_cd, l_acad_cal_type;
154                 CLOSE c_key_from_spa;
155         END IF;
156         CLOSE c_oldest_term;
157 END IF;
158 CLOSE c_key_from_prev_term;
159 OPEN c_key_in_same_acad(l_acad_cal_type);
160 FETCH c_key_in_same_acad INTO l_dummy;
161 IF c_key_in_same_acad%NOTFOUND THEN
162      return NULL;
163 ELSE
164         return l_program_cd;
165 END IF;
166 END find_key_effective_for;
167 
168 PROCEDURE get_effective_attribute_values(p_person_id IN NUMBER,
169                         p_program_cd IN VARCHAR2,
170                         p_term_cal_type IN VARCHAR2,
171                         p_term_sequence_number IN NUMBER, p_term_rec OUT NOCOPY EN_SPAT_REC_TYPE%TYPE) AS
172 
173   -- ## Get the term details information for the effective term
174   CURSOR c_term IS
175     SELECT * from igs_en_spa_terms
176     WHERE person_id = p_person_id
177     AND   program_cd = p_program_cd
178     AND   term_cal_type = p_term_cal_type
179     AND   term_sequence_number = p_term_sequence_number;
180 
181   -- ## get the term record values for a term which is previous to the effective term
182   CURSOR c_prev_term IS
183           SELECT
184             SPAT.*
185           FROM
186             IGS_EN_SPA_TERMS SPAT,
187             IGS_CA_INST CI1,
188             IGS_CA_INST CI2
189           WHERE
190             SPAT.PERSON_ID = p_person_id AND
191             spat.program_cd = p_program_cd AND
192             SPAT.TERM_CAL_TYPE = CI2.CAL_TYPE AND
193             SPAT.TERM_SEQUENCE_NUMBER =     CI2.SEQUENCE_NUMBER AND
194             CI1.CAL_TYPE = p_term_cal_type AND
195             CI1.SEQUENCE_NUMBER = p_term_sequence_number     AND
196             CI1.START_DT > CI2.START_DT AND
197             SPAT.ACAD_CAL_TYPE IN (SELECT SUP_CAL_TYPE
198                                    FROM IGS_CA_INST_REL
199                                    WHERE SUB_CAL_TYPE = P_TERM_CAL_TYPE
200                                    AND SUB_CI_SEQUENCE_NUMBER = P_TERM_SEQUENCE_NUMBER)
201           ORDER BY CI2.START_DT DESC;
202 
203 -- ## get the SPA values for the passed in program attempt
204 CURSOR c_spa IS
205 SELECT person_id,
206        course_cd,
207        version_number,
208        cal_type,
209        key_program,
210        location_cd,
211        attendance_mode,
212        attendance_type,
213        fee_cat,
214        coo_id,
215        IGS_PR_CLASS_STD_ID
216 FROM igs_en_stdnt_ps_att
217 WHERE person_id = p_person_id
218 AND course_cd = p_program_cd;
219 
220 l_program_cd IGS_PS_VER.COURSE_CD%TYPE;
221 
222 BEGIN
223 --## 1. If term record exists for the effective term then get the attribute details
224 --##    from it, set in EN_SPAT_REC_TYPE and exit
225 --## 2. Term record not found for effective term, hence move on to a term record
226 --##    which is immediately in the past and get the attribute information and
227 --##    set it in EN_SPAT_REC_TYPE and exit
228 --## 3. If no term record is found for the program attempt then get the attribute
229 --##    information from the SPA.
230 
231     OPEN c_term;
232     FETCH c_term INTO p_term_rec;
233     IF (c_term%FOUND) THEN
234         CLOSE c_term;
235         p_term_rec.person_id := p_person_id;
236         p_term_rec.program_cd := p_program_cd;
237         p_term_rec.term_cal_type := p_term_cal_type;
238         p_term_rec.term_sequence_number := p_term_sequence_number;
239         RETURN;
240      ELSE
241         CLOSE c_term;
242      END IF;
243 
244 
245      OPEN c_prev_term;
246      FETCH c_prev_term INTO p_term_rec;
247      IF (c_prev_term%FOUND) THEN
248         CLOSE c_prev_term;
249         p_term_rec.person_id := p_person_id;
250         p_term_rec.program_cd := p_program_cd;
251         p_term_rec.term_cal_type := p_term_cal_type;
252         p_term_rec.term_sequence_number := p_term_sequence_number;
253      ELSE
254         CLOSE c_prev_term;
255         OPEN c_spa;
256         FETCH c_spa INTO p_term_rec.person_id,
257                  p_term_rec.program_cd,
258                  p_term_rec.program_version,
259                  p_term_Rec.acad_cal_type,
260                  p_term_rec.key_program_flag,
261                  p_term_rec.location_cd,
262                  p_term_rec.attendance_mode,
263                  p_term_rec.attendance_type,
264                  p_term_rec.fee_cat,
265                  p_term_rec.coo_id,
266                  p_term_rec.class_standing_id;
267 
268           p_term_rec.person_id := p_person_id;
269           p_term_rec.program_cd := p_program_cd;
270           p_term_rec.term_cal_type := p_term_cal_type;
271           p_term_rec.term_sequence_number := p_term_sequence_number;
272           CLOSE c_spa;
273        END IF;
274        l_program_cd := find_key_effective_for(
275                 p_person_id => p_person_id,
276                 p_term_cal_type => p_term_cal_type,
277                 p_term_sequence_number => p_term_sequence_number);
278        IF l_program_cd = p_program_cd THEN
279            p_term_rec.key_program_flag := 'Y';
280        ELSE
281            p_term_rec.key_program_flag := 'N';
282        END IF;
283 
284 END get_effective_attribute_values;
285 
286 PROCEDURE set_param_attributes
287 (
288 p_person_id IN NUMBER,
289 p_program_cd IN VARCHAR2,
290 p_term_cal_type IN VARCHAR2,
291 p_term_sequence_number IN NUMBER,
292 p_coo_id IN NUMBER,
293 p_key_program_flag IN VARCHAR2,
294 p_fee_cat IN VARCHAR2,
295 p_class_standing_id IN NUMBER,
296 p_plan_sht_status IN VARCHAR2,
297 p_old_term_rec IN EN_SPAT_REC_TYPE%TYPE,
298 p_new_term_rec IN OUT NOCOPY  EN_SPAT_REC_TYPE%TYPE,
299 p_program_changed IN BOOLEAN
300 )  AS
301 /*   p_old_term_rec is input record
302      p_new_term_rec is the output record
303      - Set the changed attributes in p_new_term_rec
304      - All attributes which are not changing, use the values in p_old_term_rec
305 */
306 CURSOR c_prg_attributes IS
307 SELECT  version_number,
308         location_cd,
309         attendance_type,
310         attendance_mode,
311         cal_type
312 FROM    igs_ps_ofr_opt
313 WHERE coo_id = p_coo_id;
314 BEGIN
315 
316         p_new_term_rec := p_old_term_rec;
317         IF p_program_changed THEN
318             p_new_term_rec := NULL;
319             get_effective_attribute_values (
320                         p_person_id => p_person_id,
321                         p_program_cd => p_program_cd,
322                         p_term_cal_type => p_term_cal_type,
323                         p_term_sequence_number => p_term_sequence_number,
324                         p_term_rec => p_new_term_rec);
325 
326             p_new_term_rec.term_cal_type := p_term_cal_type;
327             p_new_term_rec.term_sequence_number := p_term_sequence_number;
328         END IF;
329 
330         IF (p_coo_id <> -1) THEN
331                 p_new_term_rec.coo_id := p_coo_id;
332                 OPEN c_prg_attributes;
333                 FETCH c_prg_attributes INTO p_new_term_rec.program_version,
334                                             p_new_term_rec.location_cd,
335                                             p_new_term_rec.attendance_type,
336                                             p_new_term_rec.attendance_mode,
337                                             p_new_term_rec.acad_cal_type;
338                 CLOSE c_prg_attributes;
339 
340         END IF;
341         IF (p_key_program_flag <> FND_API.G_MISS_CHAR) THEN
342                 p_new_term_rec.key_program_flag := p_key_program_flag;
343         END IF;
344         IF (p_fee_cat = FND_API.G_MISS_CHAR) THEN
345           null;
346         ELSE
347                 p_new_term_rec.fee_cat := p_fee_cat;
348         END IF;
349         IF (p_class_standing_id = -1) THEN
350             NULL;
351         ELSE
352                 p_new_term_rec.class_standing_id := p_class_standing_id;
353         END IF;
354         IF (p_plan_sht_status = FND_API.G_MISS_CHAR) THEN
355             null;
356         ELSE
357                 p_new_term_rec.plan_sht_status := p_plan_sht_status;
358         END IF;
359 
360 END set_param_attributes;
361 
362 
363 PROCEDURE find_and_create_key_record(p_person_id IN NUMBER, p_term_cal_type IN VARCHAR2,p_term_sequence_number IN NUMBER) AS
364 l_key_program VARCHAR2(100);
365 l_message_name varchar2(2000);
366 BEGIN
367     l_key_program := find_key_effective_for(p_person_id, p_term_cal_type, p_term_sequence_number);
368     IF l_key_program IS NOT NULL THEN
369         create_update_term_rec(  -- can it be check_and_create
370             p_person_id => p_person_id,
371             p_program_cd => l_key_program,
372             p_term_cal_type => p_term_cal_type,
373             p_term_sequence_number => p_term_sequence_number,
374             p_ripple_frwrd => FALSE,
375             p_update_rec => FALSE,
376             p_message_name => l_message_name);
377     END IF;
378 END;
379 PROCEDURE check_term_exists(
380 p_person_id IN NUMBER,
381 p_program_cd IN VARCHAR2,
382 p_program_version IN NUMBER,
383 p_term_cal_type IN VARCHAR2,
384 p_term_sequence_number IN NUMBER,
385 p_insert_rec OUT NOCOPY BOOLEAN,
386 p_term_record_id OUT NOCOPY NUMBER) AS
387 /* -----------------------------------------------------------------------
388    Created By        : Susmitha Tutta
389    Date Created By   : 16-Mar-2004
390    Purpose           : Checks whether a term record exists and returns
391                       term_record_id and p_insert_rec = FALSE if exists.
392                       If term doesn't exist returns p_insert_rec = TRUE.
393 
394    Change History
395    Who         When        What
396    ----------------------------------------------------------------------*/
397 
398 vc_career_model_enabled VARCHAR2(1);
399 CURSOR c_term_rec_exists(cp_person_id IGS_PE_PERSON.person_id%TYPE,
400                      cp_program_cd IGS_PS_VER.course_cd%TYPE,
401                      cp_program_version IGS_PS_VER.version_number%TYPE,
402                      cp_term_cal_type IGS_CA_INST.cal_type%TYPE,
406        WHERE spat.person_id = cp_person_id
403                      cp_term_sequence_number IGS_CA_INST.sequence_number%TYPE) IS
404 SELECT spat.term_record_id
405        FROM IGS_EN_SPA_TERMS spat, igs_ps_ver cv1
407        AND   spat.term_cal_type = cp_term_cal_type
408        AND   spat.term_sequence_number = cp_term_sequence_number
409        AND   cv1.course_cd = spat.program_cd
410        AND   cv1.version_number = spat.program_version
411        AND
412        (    (
413                  NVL(FND_PROFILE.VALUE('CAREER_MODEL_ENABLED'),'N') = 'Y'
414                  AND  cv1.course_type = (SELECT cv2.course_type
415                                FROM IGS_PS_VER cv2
416                                WHERE cv2.course_cd      = cp_program_cd
417                                AND   cv2.version_number = cp_program_version)
418             )
419             OR
420             (   NVL(FND_PROFILE.VALUE('CAREER_MODEL_ENABLED'),'N') = 'N'
421                 AND spat.program_cd = cp_program_cd
422             )
423        );
424 
425 vr_term_rec c_term_rec_exists%ROWTYPE;
426 BEGIN
427 
428    p_insert_rec := TRUE;
429 
430   OPEN c_term_rec_exists (p_person_id,
431                           p_program_cd,
432                           p_program_version,
433                           p_term_cal_type,
434                           p_term_sequence_number) ;
435   -- fetch term record details
436   FETCH c_term_rec_exists INTO vr_term_rec;
437    -- if term record details are found for passed parameters
438    -- new term record need not be created
439    IF c_term_rec_exists%FOUND THEN
440             -- set flag to indicate that no insert be allowed
441             p_insert_rec := FALSE;
442             -- retrieve rowid for the term record to be updated
443             p_term_record_id := vr_term_rec.term_record_id;
444    END IF;
445    CLOSE c_term_rec_exists;
446 
447 END check_term_exists;
448 
449 PROCEDURE check_and_create(
450 p_term_rec IN EN_SPAT_REC_TYPE%TYPE,
451 p_update_rec  IN BOOLEAN DEFAULT FALSE,
452 p_program_changed IN BOOLEAN DEFAULT FALSE
453 ) AS
454     vc_row_id VARCHAR2(25);
455 
456     -- flag to indicate whether term record details should be inserted or not
457     -- defailt TRUE
458     v_insert_rec BOOLEAN;
459 
460     l_rowid VARCHAR2(25);
461     l_term_record_id IGS_EN_SPA_TERMS.TERM_RECORD_ID%TYPE;
462 
463 
464     -- cursor to fetch rowid for given term record details
465     -- used in updating an existing term record
466     Cursor cur_spat (cp_term_record_id IN NUMBER) IS
467     SELECT spat.rowid, spat.program_cd, spat.acad_cal_type
468     FROM IGS_EN_SPA_TERMS spat
469     WHERE spat.term_record_id = cp_term_record_id;
470 
471     vc_cur_spat_rec cur_spat%ROWTYPE;
472     CURSOR c_check_planning_sheet (p_person_id        IGS_EN_PLAN_UNITS.PERSON_ID%TYPE,
473                                    p_course_cd        IGS_EN_PLAN_UNITS.COURSE_CD%TYPE,
474                                    p_term_cal_type    IGS_EN_PLAN_UNITS.TERM_CAL_TYPE%TYPE,
475                                    p_term_ci_sequence IGS_EN_PLAN_UNITS.TERM_CI_SEQUENCE_NUMBER%TYPE
476                                     ) IS
477            SELECT person_id
478            FROM   IGS_EN_PLAN_UNITS
479            WHERE  person_id               = p_person_id
480            AND    course_cd               = p_course_cd
481            AND    term_cal_type           = p_term_cal_type
482            AND    term_ci_sequence_number = p_term_ci_sequence
483            AND    cart_error_flag         = 'N';
484 
485     v_planning_sheet_rec c_check_planning_sheet%ROWTYPE;
486     l_plan_sht_status      IGS_EN_SPA_TERMS.PLAN_SHT_STATUS%TYPE;
487 BEGIN
488 
489   OPEN c_term_exists (p_term_rec.person_id,p_term_rec.program_cd,
490        p_term_rec.program_version,p_term_rec.term_cal_type,
491        p_term_rec.term_sequence_number);
492   FETCH c_term_exists INTO l_term_record_id;
493   IF (c_term_exists%NOTFOUND) THEN
494     v_insert_rec := TRUE;
495   ELSE
496     v_insert_rec := FALSE;
497   END IF;
498   CLOSE c_term_exists;
499 
500   IF v_insert_rec=TRUE THEN
501 
502 
503     -- call table handler to insert new term record details
504     l_term_record_id := NULL;
505     l_rowid := NULL;
506 
507     IGS_EN_SPA_TERMS_PKG.insert_row(
508         x_rowid                => l_rowid,
509         x_term_record_id       => l_term_record_id,
510         x_person_id            => p_term_rec.person_id,
511         x_program_cd           => p_term_rec.program_cd,
512         x_program_version      => p_term_rec.program_version,
513         x_acad_cal_type        => p_term_rec.acad_cal_type,
514         x_term_cal_type        => p_term_rec.term_cal_type,
515         x_term_sequence_number => p_term_rec.term_sequence_number,
516         x_key_program_flag     => p_term_rec.key_program_flag,
517         x_location_cd          => p_term_rec.location_cd,
518         x_attendance_mode      => p_term_rec.attendance_mode,
519         x_attendance_type      => p_term_rec.attendance_type,
520         x_fee_cat              => p_term_rec.fee_cat,
521         x_coo_id               => p_term_rec.coo_id,
522         x_class_standing_id    => p_term_rec.class_standing_id,
523         x_attribute_category   => null,
524         x_attribute1           => null,
528         x_attribute5           => null,
525         x_attribute2           => null,
526         x_attribute3           => null,
527         x_attribute4           => null,
529         x_attribute6           => null,
530         x_attribute7           => null,
531         x_attribute8           => null,
532         x_attribute9           => null,
533         x_attribute10          => null,
534         x_attribute11          => null,
535         x_attribute12          => null,
536         x_attribute13          => null,
537         x_attribute14          => null,
538         x_attribute15          => null,
539         x_attribute16          => null,
540         x_attribute17          => null,
541         x_attribute18          => null,
542         x_attribute19          => null,
543         x_attribute20          => null,
544         x_mode                 => 'R',
545         x_plan_sht_status      => NVL(p_term_rec.plan_sht_status, 'NONE')
546       );
547 
548 
549    -- if update flag is set to TRUE
550    ELSIF p_update_rec=TRUE THEN
551 
552 -- in career mode, check if the primary program is changing,
553 -- in case the primary program is chaning then change the program code
554 -- and other related parameters as well in the term records.
555 -- If the primary program is not changing in the current updated
556 -- then do not ripple forward the changes to other programs in the
557 -- same career.
558 -- After the program transfer build, the only place from where
559 -- the primary program can be switched in the program transfer
560 -- page. Hence we check if the call to the term API was initialized
561 -- from the page/program transfer API. in that case the program
562 -- code would be rippled forward otherwise it wont.
563 -- To identify if the call has be initialized from the program transfer
564 -- the logic would use a global variable.
565 
566     OPEN cur_spat(l_term_record_id);
567     FETCH cur_spat INTO vc_cur_spat_rec ;
568     CLOSE cur_spat;
569 
570     l_plan_sht_status := p_term_rec.plan_sht_status;
571     IF l_plan_sht_status IS NULL OR l_plan_sht_status = FND_API.G_MISS_CHAR THEN
572       l_plan_sht_status := 'NONE';
573     END IF;
574     IF (p_program_changed OR p_term_rec.acad_cal_type <> vc_cur_spat_rec.acad_cal_type ) THEN
575         --check for planning sheet exist.
576         OPEN c_check_planning_sheet(p_term_rec.person_id, p_term_rec.program_cd,
577                 p_term_rec.term_cal_type,p_term_rec.term_sequence_number);
578         FETCH c_check_planning_sheet INTO v_planning_sheet_rec;
579         IF c_check_planning_sheet%FOUND THEN
580            l_plan_sht_status := 'SKIP';
581         END IF;
582         CLOSE c_check_planning_sheet;
583    END IF;
584 
585 
586    -- if rowid for term record was found
587    -- term record details exist and will be updated
588     -- call table handler to update term record details
589 
590 
591     IGS_EN_SPA_TERMS_PKG.update_row(
592         x_rowid                => vc_cur_spat_rec.rowid,
593         x_term_record_id       => p_term_rec.term_record_id,
594         x_person_id            => p_term_rec.person_id,
595         x_program_cd           => p_term_rec.program_cd,
596         x_program_version      => p_term_rec.program_version,
597         x_acad_cal_type        => p_term_rec.acad_cal_type,
598         x_term_cal_type        => p_term_rec.term_cal_type,
599         x_term_sequence_number => p_term_rec.term_sequence_number,
600         x_key_program_flag     => p_term_rec.key_program_flag,
601         x_location_cd          => p_term_rec.location_cd,
602         x_attendance_mode      => p_term_rec.attendance_mode,
603         x_attendance_type      => p_term_rec.attendance_type,
604         x_fee_cat              => p_term_rec.fee_cat,
605         x_coo_id               => p_term_rec.coo_id,
606         x_class_standing_id    => p_term_rec.class_standing_id,
607         x_attribute_category   => p_term_rec.attribute_category,
608         x_attribute1           => p_term_rec.attribute1,
609         x_attribute2           => p_term_rec.attribute2,
610         x_attribute3           => p_term_rec.attribute3,
611         x_attribute4           => p_term_rec.attribute4,
612         x_attribute5           => p_term_rec.attribute5,
613         x_attribute6           => p_term_rec.attribute6,
614         x_attribute7           => p_term_rec.attribute7,
615         x_attribute8           => p_term_rec.attribute8,
616         x_attribute9           => p_term_rec.attribute9,
617         x_attribute10          => p_term_rec.attribute10,
618         x_attribute11          => p_term_rec.attribute11,
619         x_attribute12          => p_term_rec.attribute12,
620         x_attribute13          => p_term_rec.attribute13,
621         x_attribute14          => p_term_rec.attribute14,
622         x_attribute15          => p_term_rec.attribute15,
623         x_attribute16          => p_term_rec.attribute16,
624         x_attribute17          => p_term_rec.attribute17,
625         x_attribute18          => p_term_rec.attribute18,
626         x_attribute19          => p_term_rec.attribute19,
627         x_attribute20          => p_term_rec.attribute20,
628         x_mode                 => 'R',
629         x_plan_sht_status      => l_plan_sht_status
630       );
631 
632   END IF;
633 
634 END check_and_create;
635 
636 
637 
638 PROCEDURE ripple_frwd
639 (
640 p_person_id IN NUMBER,
644 p_coo_id IN NUMBER,
641 p_program_cd IN VARCHAR2,
642 p_term_cal_type IN VARCHAR2,
643 p_term_sequence_number IN NUMBER,
645 p_fee_cat IN VARCHAR2,
646 p_class_standing_id IN NUMBER,
647 p_term_rec IN EN_SPAT_REC_TYPE%TYPE,
648 p_program_changed IN BOOLEAN
649 )  AS
650 --## PROCEDURE DESCRIPTION:
651 --## the attribute values for the effective term are mirrored onto the
652 --## the future term records (that exist in the term records table and
653 --## are in future to the effective term).
654 
655       -- cursor to fetch term records occuring in future
656     CURSOR c_future_terms (cp_chk_othr_prms VARCHAR2,
657                         cp_program_version NUMBER,
658                         cp_acad_cal_type igs_ca_inst.cal_type%TYPE) IS
659     SELECT spat.*
660     FROM IGS_EN_SPA_TERMS spat,
661          IGS_CA_INST_REL cr,
662          IGS_CA_INST_REL cr2,
663          IGS_CA_INST ci,
664          IGS_PS_VER cv
665     WHERE cr.sup_cal_type            = cp_acad_cal_type
666     AND   cr.sub_cal_type            = p_term_cal_type
667     AND   cr.sub_ci_sequence_number  = p_term_sequence_number
668     AND   cr.sup_cal_type            = cr2.sup_cal_type
669     AND   cr2.sub_cal_type           = spat.term_cal_type
670     AND   cr2.sub_ci_sequence_number = spat.term_sequence_number
671     AND   spat.person_id             = p_person_id
672     AND   ci.cal_type                = cr2.sub_cal_type
673     AND   ci.sequence_number         = cr2.sub_ci_sequence_number
674     AND   exists (SELECT 'x'
675                   FROM   IGS_CA_INST cii
676                   WHERE  cal_type = p_term_cal_type
677                   AND    sequence_number = p_term_sequence_number
678                   AND ci.start_dt >= cii.start_dt)
679     AND   ci.sequence_number         <> p_term_sequence_number
680     AND   cv.course_cd               = spat.program_cd
681     AND   cv.version_number          = spat.program_version
682     AND (
683          (
684              cp_chk_othr_prms = 'Y' AND
685              cv.course_type = (SELECT course_type
686                                 FROM IGS_PS_VER cv2
687                                 WHERE cv2.course_cd      = p_program_cd
688                                 AND   cv2.version_number = cp_program_version)
689           )
690     OR
691     ( cp_chk_othr_prms <> 'Y'  AND  spat.program_cd = p_program_cd));
692 
693 
694     vc_career_model_enabled VARCHAR2(1);
695     vd_start_dt IGS_CA_INST.START_DT%TYPE;
696     v_program_changed BOOLEAN;
697     v_check_othr_prgms VARCHAR2(1);
698     v_changed_term_rec EN_SPAT_REC_TYPE%TYPE;
699 BEGIN
700 
701  -- check if Career Model is enabled for the System and if called from program transfer
702  IF (p_program_changed AND NVL(fnd_profile.value('CAREER_MODEL_ENABLED'),'N') = 'Y' ) THEN
703     v_check_othr_prgms := 'Y';
704  ELSE
705     v_check_othr_prgms := 'N';
706  END IF;
707   -- Select all the term records for the passed in person id,
708   -- term calendar and academic calendar either in the same program (in program mode)
709   -- or in the same career (in the career mode)
710   FOR vr_future_term_rec
711    IN c_future_terms
712         (v_check_othr_prgms,
713          p_term_rec.program_version,
714          p_term_rec.acad_cal_type) LOOP
715 
716         IF (NOT p_program_changed AND vr_future_term_rec.program_cd <> p_term_rec.program_cd ) THEN
717                 null;
718         ELSE
719 
720               set_param_attributes(
721                              p_person_id  => p_person_id,
722                              p_program_cd => p_program_cd,
723                              p_term_cal_type => vr_future_term_rec.term_cal_type,
724                              p_term_sequence_number => vr_future_term_rec.term_sequence_number,
725                              p_coo_id => p_coo_id,
726                              p_key_program_flag => FND_API.G_MISS_CHAR,
727                              p_fee_cat => p_fee_cat,
728                              p_class_standing_id => p_class_standing_id,
729                              p_plan_sht_status => FND_API.G_MISS_CHAR,
730                              p_old_term_rec => vr_future_term_rec,
731                              p_new_term_rec => v_changed_term_rec,
732                              p_program_changed => p_program_changed);
733 
734                 CHECK_AND_CREATE(
735                           p_term_rec => v_changed_term_rec,
736                           p_update_rec            => TRUE,
737                           p_program_changed => p_program_changed);
738         END IF;
739 
740   END LOOP;
741 
742 END ripple_frwd;
743 
744 
745 PROCEDURE backward_gap_fill
746 (
747 p_term_rec IN EN_SPAT_REC_TYPE%TYPE
748 ) AS
749     TYPE t_ref_cur IS REF CURSOR;
750     c_backward_gap_exists t_ref_cur;
751 
752     v_backward_gap_exists_stmt VARCHAR2 (4000);
753 
754     v_context_cal_type        IGS_CA_INST.CAL_TYPE%TYPE;
755     v_context_sequence_number IGS_CA_INST.SEQUENCE_NUMBER%TYPE;
756     v_next_cal_type           IGS_CA_INST.CAL_TYPE%TYPE;
757     v_next_sequence_number    IGS_CA_INST.SEQUENCE_NUMBER%TYPE;
758 
759     v_person_id               IGS_EN_SPA_TERMS.PERSON_ID%TYPE;
760     v_program_cd              IGS_EN_SPA_TERMS.PROGRAM_CD%TYPE;
761     v_program_version         IGS_EN_SPA_TERMS.PROGRAM_VERSION%TYPE;
765     v_location_cd             IGS_EN_SPA_TERMS.LOCATION_CD%TYPE;
762     v_coo_id                  IGS_EN_SPA_TERMS.COO_ID%TYPE;
763     v_acad_cal_type           IGS_EN_SPA_TERMS.ACAD_CAL_TYPE%TYPE;
764     v_key_program_flag        IGS_EN_SPA_TERMS.KEY_PROGRAM_FLAG%TYPE;
766     v_attendance_mode         IGS_EN_SPA_TERMS.ATTENDANCE_MODE%TYPE;
767     v_attendance_type         IGS_EN_SPA_TERMS.ATTENDANCE_TYPE%TYPE;
768     v_fee_cat                 IGS_EN_SPA_TERMS.FEE_CAT%TYPE;
769     v_class_standing_id       IGS_EN_SPA_TERMS.CLASS_STANDING_ID%TYPE;
770 
771     -- cursor to fetch backward term gaps
772     CURSOR c_backward_gap(cp_context_cal_type IGS_CA_INST.CAL_TYPE%TYPE,
773                           cp_context_sequence_number IGS_CA_INST.SEQUENCE_NUMBER%TYPE,
774                           cp_next_cal_type IGS_CA_INST.CAL_TYPE%TYPE,
775                           cp_next_sequence_number IGS_CA_INST.SEQUENCE_NUMBER%TYPE)
776         IS
777         SELECT  ci.cal_type, ci.sequence_number, ci.start_dt,
778                 ci.alternate_code, ci.description
779         FROM igs_ca_inst ci,
780             igs_ca_inst endterm,
781             igs_ca_inst beginterm,
782             igs_ca_type ct,
783             igs_ca_stat cs,
784             igs_ca_inst_rel cr,
785             igs_ca_inst_rel cr2,
786             igs_ca_type ct2
787         WHERE ci.cal_type               = cr.sub_cal_type
788         AND   ci.sequence_number        = cr.sub_ci_sequence_number
789         AND   cr.sup_cal_type           = ct2.cal_type
790         AND   ct2.s_cal_cat             = 'ACADEMIC'
791         AND   cr.sup_cal_type           = cr2.sup_cal_type
792         AND   beginterm.cal_type        = cr2.sub_cal_type
793         AND   beginterm.sequence_number = cr2.sub_ci_sequence_number
794         AND   ci.start_dt               >= beginterm.start_dt
795         AND   ci.start_dt               < endterm.start_dt
796         AND   endterm.cal_type          = cp_next_cal_type
797         AND   endterm.sequence_number   = cp_next_sequence_number
798         AND   beginterm.cal_type        = cp_context_cal_type
799         AND   beginterm.sequence_number = cp_context_sequence_number
800         AND   ci.sequence_number        <> endterm.sequence_number
801         AND   ci.sequence_number        <> beginterm.sequence_number
802         AND   ct.cal_type               = ci.cal_type
803         AND   ct.s_cal_cat              = 'LOAD'
804         AND   cs.cal_status             = ci.cal_status
805         AND   cs.s_cal_status           =  'ACTIVE'
806         ORDER BY ci.start_dt ASC;
807 
808     -- checks if a term record exists in the same term for the given person
809     -- and academic calendar
810     v_term_rec EN_SPAT_REC_TYPE%TYPE;
811      vc_career_model_enabled varchar2(1);
812 BEGIN
813    -- fetch if Career Model is enabled for the System or not
814    vc_career_model_enabled := nvl(fnd_profile.value('CAREER_MODEL_ENABLED'),'N');
815     v_term_rec := p_term_rec;
816    -- if Career Model is enabled
817    -- if Career Model is enabled
818    IF vc_career_model_enabled = 'Y' THEN
819 
820        -- set query statement to fetch any backward gap terms
821        v_backward_gap_exists_stmt := 'SELECT CI2.CAL_TYPE,
822                                          CI2.SEQUENCE_NUMBER,
823                                          CI.CAL_TYPE,
824                                          CI.SEQUENCE_NUMBER,
825                                          SPT.PERSON_ID,
826                                          SPT.PROGRAM_CD,
827                                          SPT.PROGRAM_VERSION,
828                                          SPT.COO_ID,
829                                          SPT.ACAD_CAL_TYPE,
830                                          SPT.KEY_PROGRAM_FLAG,
831                                          SPT.LOCATION_CD,
832                                          SPT.ATTENDANCE_MODE,
833                                          SPT.ATTENDANCE_TYPE,
834                                          SPT.FEE_CAT,
835                                          SPT.CLASS_STANDING_ID
836                                   FROM IGS_EN_SPA_TERMS SPT,
837                                        IGS_PS_VER CV,
838                                        IGS_CA_INST CI,
839                                        IGS_CA_INST CI2
840                                   WHERE SPT.PERSON_ID = :1
841                                   AND   SPT.PROGRAM_CD = CV.COURSE_CD
842                                   AND   SPT.PROGRAM_VERSION = CV.VERSION_NUMBER
843                                   AND   CV.COURSE_TYPE IN (SELECT CV2.COURSE_TYPE
844                                                            FROM IGS_PS_VER CV2
845                                                            WHERE CV2.COURSE_CD = :2
846                                                            AND CV2.VERSION_NUMBER = :3)
847                                   AND   CI2.CAL_TYPE = SPT.TERM_CAL_TYPE
848                                   AND   CI2.SEQUENCE_NUMBER = SPT.TERM_SEQUENCE_NUMBER
849                                   AND   CI.CAL_TYPE = :4
850                                   AND   CI.SEQUENCE_NUMBER = :5
851                                   AND   SPT.ACAD_CAL_TYPE = :6
852                                   AND   CI2.START_DT < CI.START_DT
853                                   AND   CI2.SEQUENCE_NUMBER <> CI.SEQUENCE_NUMBER
854                                   ORDER BY CI2.START_DT DESC';
855 
856     -- open cursor to fetch backward gap terms
857       OPEN c_backward_gap_exists FOR v_backward_gap_exists_stmt
861             p_term_rec.term_cal_type,
858       USING p_term_rec.person_id,
859             p_term_rec.program_cd,
860             p_term_rec.program_version,
862             p_term_rec.term_sequence_number,
863             p_term_rec.acad_cal_type;
864 
865   ELSE   -- if career model is not enabled
866     -- set query statement to fetch any backward gap terms
867     v_backward_gap_exists_stmt := 'SELECT CI2.CAL_TYPE,
868                                          CI2.SEQUENCE_NUMBER,
869                                          CI.CAL_TYPE,
870                                          CI.SEQUENCE_NUMBER,
871                                          SPT.PERSON_ID,
872                                          SPT.PROGRAM_CD,
873                                          SPT.PROGRAM_VERSION,
874                                          SPT.COO_ID,
875                                          SPT.ACAD_CAL_TYPE,
876                                          SPT.KEY_PROGRAM_FLAG,
877                                          SPT.LOCATION_CD,
878                                          SPT.ATTENDANCE_MODE,
879                                          SPT.ATTENDANCE_TYPE,
880                                          SPT.FEE_CAT,
881                                          SPT.CLASS_STANDING_ID
882                                   FROM IGS_EN_SPA_TERMS SPT,
883                                        IGS_CA_INST CI,
884                                        IGS_CA_INST CI2
885                                   WHERE SPT.PERSON_ID = :1
886                                   AND   SPT.PROGRAM_CD = :2
887                                   AND   CI2.CAL_TYPE = SPT.TERM_CAL_TYPE
888                                   AND   CI2.SEQUENCE_NUMBER = SPT.TERM_SEQUENCE_NUMBER
889                                   AND   CI.CAL_TYPE = :3
890                                   AND   CI.SEQUENCE_NUMBER = :4
891                                   AND   SPT.ACAD_CAL_TYPE = :6
892                                   AND   CI2.START_DT < CI.START_DT
893                                   AND   CI2.SEQUENCE_NUMBER <> CI.SEQUENCE_NUMBER
894                                   ORDER BY CI2.START_DT DESC';
895       -- open cursor to fetch backward gap terms
896       OPEN c_backward_gap_exists FOR v_backward_gap_exists_stmt
897       USING p_term_rec.person_id,
898             p_term_rec.program_cd,
899             p_term_rec.term_cal_type,
900             p_term_rec.term_sequence_number,
901             p_term_rec.acad_cal_type;
902 
903  END IF;
904 
905   --fetch backward gap terms
906   FETCH c_backward_gap_exists INTO v_context_cal_type,
907                                    v_context_sequence_number,
908                                    v_next_cal_type,
909                                    v_next_sequence_number,
910                                    v_term_rec.person_id,
911                                    v_term_rec.program_cd,
912                                    v_term_rec.program_version,
913                                    v_term_rec.coo_id,
914                                    v_term_rec.acad_cal_type,
915                                    v_term_rec.key_program_flag,
916                                    v_term_rec.location_cd,
917                                    v_term_rec.attendance_mode,
918                                    v_term_rec.attendance_type,
919                                    v_term_rec.fee_cat,
920                                    v_term_rec.class_standing_id;
921 
922   -- if no backward term gaps exist
923   IF c_backward_gap_exists%NOTFOUND THEN
924     CLOSE c_backward_gap_exists;
925     RETURN;
926 
927   -- if backward term gaps exist
928   ELSE
929     CLOSE c_backward_gap_exists;
930   END IF;
931 
932   -- fetch backward gap term records
933   FOR vr_backward_gap_rec IN c_backward_gap(v_context_cal_type,
934                                           v_context_sequence_number,
935                                           v_next_cal_type,
936                                           v_next_sequence_number) LOOP
937       v_term_rec.term_cal_type := vr_backward_gap_rec.cal_type;
938       v_term_rec.term_sequence_number := vr_backward_gap_rec.sequence_number;
939       v_term_rec.plan_sht_status := 'NONE';
940       IF (v_term_rec.program_cd = find_key_effective_for(v_term_rec.person_id,
941                                                          vr_backward_gap_rec.cal_type,
942                                                          vr_backward_gap_rec.sequence_number)) THEN
943 
944                 v_term_rec.key_program_flag := 'Y';
945           ELSE
946 
947         v_term_rec.key_program_flag := 'N';
948           END IF;
949 
950           check_and_create(
951                         p_term_rec              => v_term_rec,
952                         p_update_rec    => FALSE);
953 
954   END LOOP;
955 
956 END backward_gap_fill;
957 
958 PROCEDURE forward_gap_fill
959 (
960 p_term_rec IN EN_SPAT_REC_TYPE%TYPE
961 )
962 AS
963  /* -----------------------------------------------------------------------
964    Created By        : rvangala
965    Date Created By   : 18-Nov-2003
966    Purpose           : Checks if any term future or forward gaps exists,
967                        and updates them if necessary.
968 
969    Change History
970    Who         When        What
971   stutta   31-Dec-2004   Modified c_forward_gap to pickup only records whose
975   ----------------------------------------------------------------------*/
972                          start date is < the next calendar( not <= next calendar)
973                          This is to avoid the same calendar being consider a
974                          future and past calendar.
976     TYPE t_ref_cur IS REF CURSOR;
977     c_forward_gap_exists t_ref_cur;
978 
979     v_forward_gap_exists_stmt VARCHAR2(4000);
980 
981     vc_curr_cal_type        IGS_CA_INST.CAL_TYPE%TYPE;
982     vn_curr_sequence_number IGS_CA_INST.SEQUENCE_NUMBER%TYPE;
983     vc_next_cal_type           IGS_CA_INST.CAL_TYPE%TYPE;
984     vn_next_sequence_number    IGS_CA_INST.SEQUENCE_NUMBER%TYPE;
985 
986     vn_person_id               IGS_EN_SPA_TERMS.PERSON_ID%TYPE;
987     vc_program_cd              IGS_EN_SPA_TERMS.PROGRAM_CD%TYPE;
988     vn_program_version         IGS_EN_SPA_TERMS.PROGRAM_VERSION%TYPE;
989     vn_coo_id                  IGS_EN_SPA_TERMS.COO_ID%TYPE;
990     vc_acad_cal_type           IGS_EN_SPA_TERMS.ACAD_CAL_TYPE%TYPE;
991     vc_key_program_flag        IGS_EN_SPA_TERMS.KEY_PROGRAM_FLAG%TYPE;
992     vc_location_cd             IGS_EN_SPA_TERMS.LOCATION_CD%TYPE;
993     vc_attendance_mode         IGS_EN_SPA_TERMS.ATTENDANCE_MODE%TYPE;
994     vc_attendance_type         IGS_EN_SPA_TERMS.ATTENDANCE_TYPE%TYPE;
995     vc_fee_cat                 IGS_EN_SPA_TERMS.FEE_CAT%TYPE;
996     vc_class_standing_id          IGS_EN_SPA_TERMS.CLASS_STANDING_ID%TYPE;
997 
998     CURSOR c_forward_gap (cp_next_cal_type IGS_CA_INST.CAL_TYPE%TYPE,
999                           cp_next_sequence_number IGS_CA_INST.SEQUENCE_NUMBER%TYPE,
1000                           cp_curr_cal_type IGS_CA_INST.CAL_TYPE%TYPE,
1001                           cp_curr_sequence_number IGS_CA_INST.SEQUENCE_NUMBER%TYPE)
1002         IS
1003         SELECT ci.cal_type, ci.sequence_number,
1004                ci.start_dt, ci.alternate_code, ci.description
1005         FROM IGS_CA_INST ci,
1006              IGS_CA_INST ci2,
1007              IGS_CA_INST ci3,
1008              IGS_CA_TYPE ct,
1009              IGS_CA_STAT cs,
1010              IGS_CA_INST_REL cr,
1011              IGS_CA_INST_REL cr2,
1012              IGS_CA_TYPE ct2
1013         WHERE ci.cal_type          = cr.sub_cal_type
1014         AND   ci.sequence_number   = cr.sub_ci_sequence_number
1015         AND   cr.sup_cal_type      = ct2.cal_type
1016         AND   ct2.s_cal_cat        = 'ACADEMIC'
1017         AND   cr.sup_cal_type      = cr2.sup_cal_type
1018         AND   ci2.cal_type         = cr2.sub_cal_type
1019         AND   ci2.sequence_number  = cr2.sub_ci_sequence_number
1020         AND   ci.start_dt          < ci3.start_dt
1021         AND   ci.start_dt          >= ci2.start_dt
1022         AND   ci2.cal_type         = cp_curr_cal_type
1023         AND   ci2.sequence_number  = cp_curr_sequence_number
1024         AND   ci3.cal_type         = cp_next_cal_type
1025         AND   ci3.sequence_number  = cp_next_sequence_number
1026         AND   ci.sequence_number   <> ci2.sequence_number
1027         AND   ci.sequence_number   <> ci3.sequence_number
1028         AND   ct.cal_type          = ci.cal_type
1029         AND   ct.s_cal_cat         = 'LOAD'
1030         AND   cs.cal_status        = ci.cal_status
1031         AND   cs.s_cal_status      = 'ACTIVE'
1032         ORDER BY  ci.start_dt ASC;
1033 
1034     CURSOR c_other_recs ( cp_term_cal_type IGS_CA_INST.CAL_TYPE%TYPE,
1035                       cp_term_sequence_number IGS_CA_INST.SEQUENCE_NUMBER%TYPE,
1036                       cp_program_cd IGS_PS_VER.COURSE_CD%TYPE) IS
1037         SELECT *
1038         FROM  IGS_EN_SPA_TERMS
1039         WHERE person_id            = p_term_rec.person_id
1040         AND   program_cd           <> cp_program_cd
1041         AND   term_cal_type        = cp_term_cal_type
1042         AND   term_sequence_number = cp_term_sequence_number
1043         AND   acad_cal_type        = p_term_rec.acad_cal_type
1044         AND   key_program_flag     = 'Y';
1045 
1046     vc_career_model_enabled VARCHAR2(1);
1047     v_term_rec EN_SPAT_REC_TYPE%TYPE;
1048 
1049 BEGIN
1050 
1051    -- fetch if Career Model is enabled for the System or not
1052    vc_career_model_enabled := NVL(fnd_profile.value('CAREER_MODEL_ENABLED'),'N');
1053 
1054    -- if Career Model is enabled
1055   IF vc_career_model_enabled = 'Y' THEN
1056 
1057     -- set query statement to fetch term record
1058     v_forward_gap_exists_stmt := 'SELECT CI2.CAL_TYPE,
1059                                          CI2.SEQUENCE_NUMBER,
1060                                          CI.CAL_TYPE,
1061                                          CI.SEQUENCE_NUMBER
1062                                   FROM IGS_EN_SPA_TERMS SPT,
1063                                        IGS_PS_VER CV,
1064                                        IGS_CA_INST CI,
1065                                        IGS_CA_INST CI2
1066                                   WHERE SPT.PERSON_ID = :1
1067                                   AND   SPT.PROGRAM_CD = CV.COURSE_CD
1068                                   AND   SPT.PROGRAM_VERSION = CV.VERSION_NUMBER
1069                                   AND   CV.COURSE_TYPE IN (SELECT CV2.COURSE_TYPE
1070                                                            FROM IGS_PS_VER CV2
1071                                                            WHERE CV2.COURSE_CD = :2
1072                                                            AND CV2.VERSION_NUMBER = :3)
1073                                   AND   CI2.CAL_TYPE = SPT.TERM_CAL_TYPE
1074                                   AND   CI2.SEQUENCE_NUMBER = SPT.TERM_SEQUENCE_NUMBER
1075                                   AND   CI.CAL_TYPE = :4
1079                                   AND   CI2.SEQUENCE_NUMBER <> CI.SEQUENCE_NUMBER
1076                                   AND   CI.SEQUENCE_NUMBER = :5
1077                                   AND   SPT.ACAD_CAL_TYPE = :6
1078                                   AND   CI2.START_DT >= CI.START_DT
1080                                   ORDER BY CI2.START_DT ASC';
1081 
1082   -- if Career Model is not enabled
1083   ELSE
1084     -- set query statement to fetch term record
1085     v_forward_gap_exists_stmt := 'SELECT CI2.CAL_TYPE,
1086                                          CI2.SEQUENCE_NUMBER,
1087                                          CI.CAL_TYPE,
1088                                          CI.SEQUENCE_NUMBER
1089                                   FROM IGS_EN_SPA_TERMS SPT,
1090                                        IGS_CA_INST CI,
1091                                        IGS_CA_INST CI2
1092                                   WHERE SPT.PERSON_ID = :1
1093                                   AND   SPT.PROGRAM_CD = :2
1094                                   AND   CI2.CAL_TYPE = SPT.TERM_CAL_TYPE
1095                                   AND   CI2.SEQUENCE_NUMBER = SPT.TERM_SEQUENCE_NUMBER
1096                                   AND   CI.CAL_TYPE = :3
1097                                   AND   CI.SEQUENCE_NUMBER = :4
1098                                   AND   SPT.ACAD_CAL_TYPE = :5
1099                                   AND   CI2.START_DT >= CI.START_DT
1100                                   AND   CI2.SEQUENCE_NUMBER <> CI.SEQUENCE_NUMBER
1101                                   ORDER BY CI2.START_DT ASC';
1102    END IF;
1103 
1104    IF vc_career_model_enabled = 'Y' THEN
1105    -- fetch term record details
1106     OPEN c_forward_gap_exists FOR v_forward_gap_exists_stmt
1107      USING  p_term_rec.person_id,
1108             p_term_rec.program_cd,
1109             p_term_rec.program_version,
1110             p_term_rec.term_cal_type,
1111             p_term_rec.term_sequence_number,
1112             p_term_rec.acad_cal_type;
1113     ELSE
1114         OPEN c_forward_gap_exists FOR v_forward_gap_exists_stmt
1115          USING  p_term_rec.person_id,
1116                 p_term_rec.program_cd,
1117                 p_term_rec.term_cal_type,
1118                 p_term_rec.term_sequence_number,
1119                 p_term_rec.acad_cal_type;
1120    END IF;
1121    FETCH c_forward_gap_exists INTO vc_next_cal_type,
1122                                    vn_next_sequence_number,
1123                                    vc_curr_cal_type,
1124                                    vn_curr_sequence_number;
1125 
1126   -- if term record was not found
1127   IF c_forward_gap_exists%NOTFOUND THEN
1128     CLOSE c_forward_gap_exists;
1129     RETURN;
1130 
1131   -- if term record was found
1132   ELSE
1133     CLOSE c_forward_gap_exists;
1134   END IF;
1135 
1136     v_term_rec := p_term_rec;
1137     -- fetch forward calendars
1138     FOR vr_forward_gap_rec IN c_forward_gap(vc_next_cal_type,
1139                                             vn_next_sequence_number,
1140                                             vc_curr_cal_type,
1141                                             vn_curr_sequence_number) LOOP
1142     v_term_rec.term_cal_type :=vr_forward_gap_rec.cal_type;
1143     v_term_rec.term_sequence_number :=vr_forward_gap_rec.sequence_number;
1144     v_term_rec.plan_sht_status := 'NONE';
1145 
1146         IF (v_term_rec.program_cd = find_key_effective_for(v_term_rec.person_id,
1147                                                        vc_curr_cal_type,
1148                                                        vn_curr_sequence_number)) THEN
1149                 v_term_rec.key_program_flag := 'Y';
1150     ELSE
1151         v_term_rec.key_program_flag := 'N';
1152     END IF;
1153 
1154     -- create term record for future term
1155     check_and_create(
1156           p_term_rec     => v_term_rec,
1157           p_update_rec   => TRUE);
1158 
1159   END LOOP;
1160 
1161 END forward_gap_fill;
1162 
1163 
1164 
1165 
1166 
1167 PROCEDURE create_update_term_rec(
1168 p_person_id IN NUMBER ,
1169 p_program_cd IN VARCHAR2,
1170 p_term_cal_type IN VARCHAR2,
1171 p_term_sequence_NUMBER IN NUMBER,
1172 p_ripple_frwrd IN boolean,
1173 p_update_rec IN BOOLEAN,
1174 p_message_name OUT NOCOPY VARCHAR2,
1175 p_coo_id IN NUMBER DEFAULT -1,
1176 p_key_program_flag IN VARCHAR2 DEFAULT FND_API.G_MISS_CHAR,
1177 p_fee_cat IN VARCHAR2 DEFAULT FND_API.G_MISS_CHAR,
1178 p_class_standing_id IN NUMBER DEFAULT -1,
1179 p_plan_sht_status IN VARCHAR2 DEFAULT FND_API.G_MISS_CHAR,
1180 p_program_changed IN BOOLEAN DEFAULT FALSE
1181 )
1182 AS
1183 cursor c_valid_term IS
1184 SELECT 'x' FROM IGS_CA_INST ca, IGS_CA_TYPE ct
1185 WHERE ca.cal_type = p_term_cal_type
1186 AND   ca.sequence_number = p_term_sequence_number
1187 AND ca.cal_type = ct.cal_type
1188 and ct.s_cal_cat = 'LOAD';
1189 
1190 
1191 l_dummy VARCHAR2(1);
1192 l_term_id IGS_EN_SPA_TERMS.term_record_id%TYPE;
1193 l_insert_rec BOOLEAN;
1194 new_term_rec EN_SPAT_REC_TYPE%TYPE;
1195 old_term_rec EN_SPAT_REC_TYPE%TYPE;
1196 l_username VARCHAR2(20);
1197 
1198 
1199 BEGIN
1200 
1201     -- ## Checking whether term instance is a valid value.
1202         IF (p_term_cal_type IS NULL OR p_term_sequence_number IS NULL) THEN
1203 
1204           p_message_name := 'IGS_EN_INVALID_LOAD_CAL' ;
1205           FND_MESSAGE.SET_NAME('IGS',p_message_name);
1209     ELSE
1206           IGS_GE_MSG_STACK.ADD;
1207           APP_EXCEPTION.RAISE_EXCEPTION;
1208 
1210       OPEN c_valid_term;
1211             FETCH c_valid_term INTO l_dummy;
1212         IF (c_valid_term%NOTFOUND) THEN
1213             p_message_name := 'IGS_EN_INVALID_LOAD_CAL' ;
1214             FND_MESSAGE.SET_NAME('IGS',p_message_name);
1215             IGS_GE_MSG_STACK.ADD;
1216             APP_EXCEPTION.RAISE_EXCEPTION;
1217         END IF;
1218     END IF;
1219 
1220 
1221         -- Get the attribute values which are effective in the passed in term.
1222         -- It returns a record variable as out paramter which contains are effective attribute values.
1223         get_effective_attribute_values(p_person_id => p_person_id,
1224                                         p_program_cd => p_program_cd,
1225                                         p_term_cal_type => p_term_cal_type,
1226                                         p_term_sequence_number => p_term_sequence_number,
1227                                         p_term_rec => old_term_rec);
1228 
1229 
1230         set_param_attributes(
1231                              p_person_id  => p_person_id,
1232                              p_program_cd => p_program_cd,
1233                              p_term_cal_type => p_term_cal_type,
1234                              p_term_sequence_number => p_term_sequence_number,
1235                              p_coo_id => p_coo_id,
1236                              p_key_program_flag => p_key_program_flag,
1237                              p_fee_cat => p_fee_cat,
1238                              p_class_standing_id => p_class_standing_id,
1239                              p_plan_sht_status => p_plan_sht_status,
1240                              p_old_term_rec => old_term_rec,
1241                              p_new_term_rec => new_term_rec,
1242                              p_program_changed => p_program_changed);
1243 
1244         validate_term_rec(p_term_rec => new_term_rec);
1245         IF (p_ripple_frwrd) THEN
1246                 ripple_frwd(
1247                 p_person_id => p_person_id,
1248                 p_program_cd => p_program_cd,
1249                 p_coo_id =>p_coo_id ,
1250                 p_term_cal_type => p_term_cal_type,
1251                 p_term_sequence_number => p_term_sequence_number,
1252                 p_fee_cat => p_fee_cat,
1253                 p_class_standing_id => p_class_standing_id,
1254                 p_term_rec => old_term_rec,
1255                 p_program_changed => p_program_changed);
1256         END IF;
1257 
1258         OPEN c_term_exists (old_term_rec.person_id,old_term_rec.program_cd,
1259            old_term_rec.program_version,old_term_rec.term_cal_type,
1260            old_term_rec.term_sequence_number);
1261         FETCH c_term_exists INTO l_term_id;
1262         IF (c_term_exists%NOTFOUND) THEN
1263                l_insert_rec := TRUE;
1264         ELSE
1265                l_insert_rec := FALSE;
1266         END IF;
1267         CLOSE c_term_exists;
1268         -- All attributes whose values have been passed in for the call have changed.
1269         -- Hence set those attributes which have a value passed to create_update_term_Rec .
1270 
1271 
1272         IF l_insert_rec THEN
1273 
1274                 backward_gap_fill(new_term_rec);
1275 
1276                 check_and_create(p_term_rec => new_term_rec,
1277                                  p_update_rec  => TRUE,
1278                                  p_program_changed => p_program_changed);
1279 
1280                 forward_gap_fill(new_term_rec);
1281         ELSE
1282                 -- If the record already exists then no gaps need not be filled.
1283                 -- Only update the term record with the changed values
1284 
1285                         check_and_create(p_term_rec => new_term_rec,
1286                                          p_update_rec  => TRUE,
1287                                  p_program_changed => p_program_changed);
1288         END IF;
1289         IF (p_key_program_flag = 'Y') THEN
1290 
1291                 change_key_program_to(p_person_id,
1292                                         p_program_cd,
1293                                         p_term_cal_type,
1294                                         p_term_sequence_number, new_term_rec);
1295         END IF;
1296 
1297 
1298 
1299 END create_update_term_rec;
1300 
1301 
1302 PROCEDURE change_key_program_to(
1303 p_person_id IN NUMBER,
1304 p_program_cd IN VARCHAR2,
1305 p_term_cal_type IN VARCHAR2,
1306 p_term_sequence_NUMBER IN NUMBER,
1307 p_term_rec IN EN_SPAT_REC_TYPE%TYPE) AS
1308 
1309 CURSOR c_future_key_terms IS
1310 SELECT spat.rowid, spat.*
1311 FROM igs_en_spa_terms spat, igs_ca_inst ca1, igs_ca_inst ca2
1312 WHERE ca1.cal_type = spat.term_cal_type
1313 AND   ca1.sequence_number = spat.term_sequence_number
1314 AND       ca2.cal_type = p_term_cal_type
1315 AND   ca2.sequence_number = p_term_sequence_number
1316 AND   ca1.start_dt >= ca2.start_dt
1317 and   spat.person_id = p_person_id
1318 AND   spat.key_program_flag = 'Y';
1319 
1320 CURSOR c_latest_term_in_acad IS  -- check if the latest term in acad is for this program
1321 SELECT spat.rowid, spat.program_cd, term_cal_type, term_sequence_number
1322 FROM   igs_en_spa_terms spat, igs_ca_inst ca, igs_ca_inst_rel cir
1323 WHERE  spat.person_id = p_person_id
1324 AND    ca.cal_type = spat.term_cal_type
1328 AND    cir.sup_cal_type = spat.acad_cal_type
1325 AND    ca.sequence_number = spat.term_sequence_number
1326 AND    cir.sub_cal_type = p_term_cal_type
1327 AND    cir.sub_ci_sequence_number = p_term_sequence_number
1329 ORDER BY ca.start_dt DESC;
1330 
1331 CURSOR c_dest_term IS
1332 SELECT spat.rowid, spat.term_record_id
1333 FROM   igs_en_spa_terms spat
1334 WHERE person_id = p_person_id
1335 AND   program_cd = p_program_cd
1336 AND   term_cal_type = p_term_cal_type
1337 AND   term_sequence_number = p_term_sequence_number;
1338 
1339 CURSOR c_dest_fut_terms IS
1340 SELECT spat.rowid,spat.*
1341     FROM IGS_EN_SPA_TERMS spat,
1342          IGS_CA_INST_REL cr,
1343          IGS_CA_INST_REL cr2,
1344          IGS_CA_INST ci,
1345          IGS_PS_VER cv
1346     WHERE cr.sub_cal_type            = p_term_cal_type
1347     AND   cr.sub_ci_sequence_number  = p_term_sequence_number
1348     AND   cr.sup_cal_type            = cr2.sup_cal_type
1349     AND   cr2.sub_cal_type           = spat.term_cal_type
1350     AND   cr2.sub_ci_sequence_number = spat.term_sequence_number
1351     AND   spat.person_id             = p_person_id
1352     AND   ci.cal_type                = cr2.sub_cal_type
1353     AND   ci.sequence_number         = cr2.sub_ci_sequence_number
1354     AND   ci.start_dt                >=
1355                  (SELECT start_dt
1356                   FROM   IGS_CA_INST
1357                   WHERE  cal_type = cr.sub_cal_type
1358                   AND    sequence_number = cr.sub_ci_sequence_number)
1359     AND   ci.sequence_number         <> p_term_sequence_number
1360     AND   cv.course_cd               = spat.program_cd
1361     AND   cv.version_number          = spat.program_version
1362     AND   spat.program_cd = p_program_cd;
1363 
1364 l_term_cal IGS_CA_INST.CAL_TYPE%TYPE;
1365 l_term_seq IGS_CA_INST.SEQUENCE_NUMBER%TYPE;
1366 l_message_name VARCHAR2(2000);
1367 l_term_rec EN_SPAT_REC_TYPE%TYPE;
1368 l_rowid ROWID;
1369 l_term_id IGS_EN_SPA_TERMS.term_record_id%TYPE;
1370 l_program_cd IGS_PS_VER.COURSE_CD%TYPE;
1371 
1372 BEGIN
1373     l_term_rec := p_term_rec;
1374         -- Reset all future key term records as Non-Key
1375         FOR rec_future_key_terms IN c_future_key_terms LOOP
1376 
1377                 IGS_EN_SPA_TERMS_PKG.update_row(
1378                         x_rowid                => rec_future_key_terms.rowid,
1379                         x_term_record_id       => rec_future_key_terms.term_record_id,
1380                         x_person_id            => rec_future_key_terms.person_id,
1381                         x_program_cd           => rec_future_key_terms.program_cd,
1382                         x_program_version      => rec_future_key_terms.program_version,
1383                         x_acad_cal_type        => rec_future_key_terms.acad_cal_type,
1384                         x_term_cal_type        => rec_future_key_terms.term_cal_type,
1385                         x_term_sequence_number => rec_future_key_terms.term_sequence_number,
1386                         x_key_program_flag     => 'N',
1387                         x_location_cd          => rec_future_key_terms.location_cd,
1388                         x_attendance_mode      => rec_future_key_terms.attendance_mode,
1389                         x_attendance_type      => rec_future_key_terms.attendance_type,
1390                         x_fee_cat              => rec_future_key_terms.fee_cat,
1391                         x_coo_id               => rec_future_key_terms.coo_id,
1392                         x_class_standing_id    => rec_future_key_terms.class_standing_id,
1393                         x_attribute_category   => rec_future_key_terms.attribute_category,
1394                         x_attribute1           => rec_future_key_terms.attribute1,
1395                         x_attribute2           => rec_future_key_terms.attribute2,
1396                         x_attribute3           => rec_future_key_terms.attribute3,
1397                         x_attribute4           => rec_future_key_terms.attribute4,
1398                         x_attribute5           => rec_future_key_terms.attribute5,
1399                         x_attribute6           => rec_future_key_terms.attribute6,
1400                         x_attribute7           => rec_future_key_terms.attribute7,
1401                         x_attribute8           => rec_future_key_terms.attribute8,
1402                         x_attribute9           => rec_future_key_terms.attribute9,
1403                         x_attribute10          => rec_future_key_terms.attribute10,
1404                         x_attribute11          => rec_future_key_terms.attribute11,
1405                         x_attribute12          => rec_future_key_terms.attribute12,
1406                         x_attribute13          => rec_future_key_terms.attribute13,
1407                         x_attribute14          => rec_future_key_terms.attribute14,
1408                         x_attribute15          => rec_future_key_terms.attribute15,
1409                         x_attribute16          => rec_future_key_terms.attribute16,
1410                         x_attribute17          => rec_future_key_terms.attribute17,
1411                         x_attribute18          => rec_future_key_terms.attribute18,
1412                         x_attribute19          => rec_future_key_terms.attribute19,
1413                         x_attribute20          => rec_future_key_terms.attribute20,
1414                         x_mode                 => 'R',
1415                         x_plan_sht_status      => rec_future_key_terms.plan_sht_status
1416                   );
1417         END LOOP;
1418         OPEN c_dest_term;
1419         FETCH c_dest_term INTO l_rowid, l_term_id;
1420         CLOSE c_dest_term;
1421         -- Update the destination term record as Key
1422         IGS_EN_SPA_TERMS_PKG.update_row(
1423                         x_rowid                => l_rowid,
1424                         x_term_record_id       => l_term_id,
1425                         x_person_id            => l_term_rec.person_id,
1426                         x_program_cd           => l_term_rec.program_cd,
1427                         x_program_version      => l_term_rec.program_version,
1428                         x_acad_cal_type        => l_term_rec.acad_cal_type,
1429                         x_term_cal_type        => l_term_rec.term_cal_type,
1430                         x_term_sequence_number => l_term_rec.term_sequence_number,
1431                         x_key_program_flag     => 'Y',
1432                         x_location_cd          => l_term_rec.location_cd,
1433                         x_attendance_mode      => l_term_rec.attendance_mode,
1434                         x_attendance_type      => l_term_rec.attendance_type,
1435                         x_fee_cat              => l_term_rec.fee_cat,
1436                         x_coo_id               => l_term_rec.coo_id,
1437                         x_class_standing_id    => l_term_rec.class_standing_id,
1438                         x_attribute_category   => l_term_rec.attribute_category,
1439                         x_attribute1           => l_term_rec.attribute1,
1440                         x_attribute2           => l_term_rec.attribute2,
1441                         x_attribute3           => l_term_rec.attribute3,
1442                         x_attribute4           => l_term_rec.attribute4,
1443                         x_attribute5           => l_term_rec.attribute5,
1444                         x_attribute6           => l_term_rec.attribute6,
1445                         x_attribute7           => l_term_rec.attribute7,
1446                         x_attribute8           => l_term_rec.attribute8,
1447                         x_attribute9           => l_term_rec.attribute9,
1448                         x_attribute10          => l_term_rec.attribute10,
1449                         x_attribute11          => l_term_rec.attribute11,
1450                         x_attribute12          => l_term_rec.attribute12,
1451                         x_attribute13          => l_term_rec.attribute13,
1452                         x_attribute14          => l_term_rec.attribute14,
1453                         x_attribute15          => l_term_rec.attribute15,
1454                         x_attribute16          => l_term_rec.attribute16,
1455                         x_attribute17          => l_term_rec.attribute17,
1456                         x_attribute18          => l_term_rec.attribute18,
1457                         x_attribute19          => l_term_rec.attribute19,
1458                         x_attribute20          => l_term_rec.attribute20,
1459                         x_mode                 => 'R',
1460                         x_plan_sht_status      => NVL(l_term_rec.plan_sht_status,'NONE')
1461                   );
1462     FOR rec_dest_fut_terms IN c_dest_fut_terms LOOP
1463 
1464         -- Set all destination future terms as Key terms.
1465 
1466         IGS_EN_SPA_TERMS_PKG.update_row(
1467                         x_rowid                => rec_dest_fut_terms.rowid,
1468                         x_term_record_id       => rec_dest_fut_terms.term_record_id,
1469                         x_person_id            => rec_dest_fut_terms.person_id,
1470                         x_program_cd           => rec_dest_fut_terms.program_cd,
1471                         x_program_version      => rec_dest_fut_terms.program_version,
1472                         x_acad_cal_type        => rec_dest_fut_terms.acad_cal_type,
1473                         x_term_cal_type        => rec_dest_fut_terms.term_cal_type,
1474                         x_term_sequence_number => rec_dest_fut_terms.term_sequence_number,
1475                         x_key_program_flag     => 'Y',
1476                         x_location_cd          => rec_dest_fut_terms.location_cd,
1477                         x_attendance_mode      => rec_dest_fut_terms.attendance_mode,
1478                         x_attendance_type      => rec_dest_fut_terms.attendance_type,
1479                         x_fee_cat              => rec_dest_fut_terms.fee_cat,
1480                         x_coo_id               => rec_dest_fut_terms.coo_id,
1481                         x_class_standing_id    => rec_dest_fut_terms.class_standing_id,
1482                         x_attribute_category   => rec_dest_fut_terms.attribute_category,
1483                         x_attribute1           => rec_dest_fut_terms.attribute1,
1484                         x_attribute2           => rec_dest_fut_terms.attribute2,
1485                         x_attribute3           => rec_dest_fut_terms.attribute3,
1486                         x_attribute4           => rec_dest_fut_terms.attribute4,
1487                         x_attribute5           => rec_dest_fut_terms.attribute5,
1488                         x_attribute6           => rec_dest_fut_terms.attribute6,
1489                         x_attribute7           => rec_dest_fut_terms.attribute7,
1490                         x_attribute8           => rec_dest_fut_terms.attribute8,
1491                         x_attribute9           => rec_dest_fut_terms.attribute9,
1492                         x_attribute10          => rec_dest_fut_terms.attribute10,
1493                         x_attribute11          => rec_dest_fut_terms.attribute11,
1494                         x_attribute12          => rec_dest_fut_terms.attribute12,
1495                         x_attribute13          => rec_dest_fut_terms.attribute13,
1496                         x_attribute14          => rec_dest_fut_terms.attribute14,
1497                         x_attribute15          => rec_dest_fut_terms.attribute15,
1498                         x_attribute16          => rec_dest_fut_terms.attribute16,
1499                         x_attribute17          => rec_dest_fut_terms.attribute17,
1500                         x_attribute18          => rec_dest_fut_terms.attribute18,
1501                         x_attribute19          => rec_dest_fut_terms.attribute19,
1502                         x_attribute20          => rec_dest_fut_terms.attribute20,
1503                         x_mode                 => 'R',
1504                         x_plan_sht_status      => rec_dest_fut_terms.plan_sht_status
1505                   );
1506         END LOOP;
1507 
1508 
1509 
1510 END change_key_program_to;
1511 
1512 FUNCTION get_spat_fee_cat(
1513 p_person_id IN NUMBER,
1514 p_program_cd IN VARCHAR2,
1515 p_term_cal_type IN VARCHAR2,
1516 p_term_sequence_NUMBER IN NUMBER
1517 ) RETURN VARCHAR2
1518 AS
1519   -- ## Get the term details information for the effective term
1520   CURSOR c_term IS
1521     SELECT fee_cat from igs_en_spa_terms
1522     WHERE person_id = p_person_id
1523     AND   program_cd = p_program_cd
1524     AND   term_cal_type = p_term_cal_type
1525     AND   term_sequence_number = p_term_sequence_number;
1526 
1527   -- ## get the term record values for a term which is previous to the effective term
1528   CURSOR c_prev_term IS
1529           SELECT
1530             SPAT.fee_cat
1531           FROM
1532             IGS_EN_SPA_TERMS SPAT,
1533             IGS_CA_INST CI1,
1534             IGS_CA_INST CI2
1535           WHERE
1536             SPAT.PERSON_ID = p_person_id AND
1537             spat.program_cd = p_program_cd AND
1538             SPAT.TERM_CAL_TYPE = CI2.CAL_TYPE AND
1539             SPAT.TERM_SEQUENCE_NUMBER =     CI2.SEQUENCE_NUMBER AND
1540             CI1.CAL_TYPE = p_term_cal_type AND
1541             CI1.SEQUENCE_NUMBER = p_term_sequence_number     AND
1542             CI1.START_DT > CI2.START_DT AND
1543             SPAT.ACAD_CAL_TYPE IN (SELECT SUP_CAL_TYPE
1544                                    FROM IGS_CA_INST_REL
1545                                    WHERE SUB_CAL_TYPE = CI1.CAL_TYPE
1546                                    AND SUB_CI_SEQUENCE_NUMBER = CI1.SEQUENCE_NUMBER)
1547           ORDER BY CI2.START_DT DESC;
1548 
1549 -- ## get the SPA values for the passed in program attempt
1550 CURSOR c_spa IS
1551 SELECT fee_cat
1552 FROM igs_en_stdnt_ps_att
1553 WHERE person_id = p_person_id
1554 AND course_cd = p_program_cd;
1555 
1556 l_fee_cat igs_en_spa_terms.fee_cat%TYPE;
1557 
1558 BEGIN
1559 --## 1. If term record exists for the effective term then get the attribute details
1560 --##    from it, set in EN_SPAT_REC_TYPE and exit
1561 --## 2. Term record not found for effective term, hence move on to a term record
1562 --##    which is immediately in the past and get the attribute information and
1563 --##    set it in EN_SPAT_REC_TYPE and exit
1564 --## 3. If no term record is found for the program attempt then get the attribute
1565 --##    information from the SPA.
1566 
1567     OPEN c_term;
1568     FETCH c_term INTO l_fee_cat;
1569     IF (c_term%FOUND) THEN
1570         CLOSE c_term;
1571 
1572         RETURN l_fee_cat;
1573      END IF;
1574      CLOSE c_term;
1575 
1576      OPEN c_prev_term;
1577      FETCH c_prev_term INTO l_fee_cat;
1578      IF (c_prev_term%FOUND) THEN
1579         CLOSE c_prev_term;
1580         RETURN l_fee_cat;
1581      ELSE
1582         CLOSE c_prev_term;
1583         OPEN c_spa;
1584         FETCH c_spa INTO l_fee_cat;
1585      END IF;
1586      return l_fee_cat;
1587 END get_spat_fee_cat;
1588 
1589 FUNCTION get_spat_class_standing(
1590 p_person_id IN NUMBER,
1591 p_program_cd IN VARCHAR2,
1592 p_term_cal_type IN VARCHAR2,
1593 p_term_sequence_NUMBER IN NUMBER
1594 ) RETURN NUMBER
1595 AS
1596 
1597   -- ## Get the term details information for the effective term
1598   CURSOR c_term IS
1599     SELECT class_standing_id from igs_en_spa_terms
1600     WHERE person_id = p_person_id
1601     AND   program_cd = p_program_cd
1602     AND   term_cal_type = p_term_cal_type
1603     AND   term_sequence_number = p_term_sequence_number;
1604 
1605   -- ## get the term record values for a term which is previous to the effective term
1606   CURSOR c_prev_term IS
1607           SELECT
1608             SPAT.class_standing_id
1609           FROM
1610             IGS_EN_SPA_TERMS SPAT,
1611             IGS_CA_INST CI1,
1612             IGS_CA_INST CI2
1613           WHERE
1614             SPAT.PERSON_ID = p_person_id AND
1615             spat.program_cd = p_program_cd AND
1616             SPAT.TERM_CAL_TYPE = CI2.CAL_TYPE AND
1617             SPAT.TERM_SEQUENCE_NUMBER =     CI2.SEQUENCE_NUMBER AND
1618             CI1.CAL_TYPE = p_term_cal_type AND
1619             CI1.SEQUENCE_NUMBER = p_term_sequence_number     AND
1620             CI1.START_DT > CI2.START_DT AND
1621             SPAT.ACAD_CAL_TYPE IN (SELECT SUP_CAL_TYPE
1622                                    FROM IGS_CA_INST_REL
1623                                    WHERE SUB_CAL_TYPE = CI1.CAL_TYPE
1624                                    AND SUB_CI_SEQUENCE_NUMBER = CI1.SEQUENCE_NUMBER)
1625           ORDER BY CI2.START_DT DESC;
1626 
1627 -- ## get the SPA values for the passed in program attempt
1628 CURSOR c_spa IS
1629 SELECT IGS_PR_CLASS_STD_ID
1630 FROM igs_en_stdnt_ps_att
1631 WHERE person_id = p_person_id
1632 AND course_cd = p_program_cd;
1633 
1634 l_class_standing igs_en_spa_terms.class_standing_id%TYPE;
1635 
1636 BEGIN
1637 --## 1. If term record exists for the effective term then get the attribute details
1638 --##    from it, set in EN_SPAT_REC_TYPE and exit
1639 --## 2. Term record not found for effective term, hence move on to a term record
1640 --##    which is immediately in the past and get the attribute information and
1641 --##    set it in EN_SPAT_REC_TYPE and exit
1642 --## 3. If no term record is found for the program attempt then get the attribute
1643 --##    information from the SPA.
1644 
1645     OPEN c_term;
1646     FETCH c_term INTO l_class_standing;
1647     IF (c_term%FOUND) THEN
1648         CLOSE c_term;
1649 
1650         RETURN l_class_standing;
1651      END IF;
1652      CLOSE c_term;
1653 
1654      OPEN c_prev_term;
1655      FETCH c_prev_term INTO l_class_standing;
1656      IF (c_prev_term%FOUND) THEN
1657         CLOSE c_prev_term;
1658         RETURN l_class_standing;
1659      ELSE
1660         CLOSE c_prev_term;
1661         OPEN c_spa;
1662         FETCH c_spa INTO l_class_standing;
1663      END IF;
1664      return l_class_standing;
1665 END get_spat_class_standing;
1666 
1667 FUNCTION get_spat_coo_id(
1668 p_person_id IN NUMBER,
1669 p_program_cd IN VARCHAR2,
1670 p_term_cal_type IN VARCHAR2,
1671 p_term_sequence_NUMBER IN NUMBER
1672 ) RETURN NUMBER
1673 AS
1674 
1675   -- ## Get the term details information for the effective term
1676   CURSOR c_term IS
1677     SELECT coo_id from igs_en_spa_terms
1678     WHERE person_id = p_person_id
1679     AND   program_cd = p_program_cd
1680     AND   term_cal_type = p_term_cal_type
1681     AND   term_sequence_number = p_term_sequence_number;
1682 
1683   -- ## get the term record values for a term which is previous to the effective term
1684   CURSOR c_prev_term IS
1685           SELECT
1686             SPAT.coo_id
1687           FROM
1688             IGS_EN_SPA_TERMS SPAT,
1689             IGS_CA_INST CI1,
1690             IGS_CA_INST CI2
1691           WHERE
1692             SPAT.PERSON_ID = p_person_id AND
1693             spat.program_cd = p_program_cd AND
1694             SPAT.TERM_CAL_TYPE = CI2.CAL_TYPE AND
1695             SPAT.TERM_SEQUENCE_NUMBER =     CI2.SEQUENCE_NUMBER AND
1696             CI1.CAL_TYPE = p_term_cal_type AND
1697             CI1.SEQUENCE_NUMBER = p_term_sequence_number     AND
1698             CI1.START_DT > CI2.START_DT AND
1699             SPAT.ACAD_CAL_TYPE IN (SELECT SUP_CAL_TYPE
1700                                    FROM IGS_CA_INST_REL
1701                                    WHERE SUB_CAL_TYPE = CI1.CAL_TYPE
1702                                    AND SUB_CI_SEQUENCE_NUMBER = CI1.SEQUENCE_NUMBER)
1703           ORDER BY CI2.START_DT DESC;
1704 
1705 -- ## get the SPA values for the passed in program attempt
1706 CURSOR c_spa IS
1707 SELECT coo_id
1708 FROM igs_en_stdnt_ps_att
1709 WHERE person_id = p_person_id
1710 AND course_cd = p_program_cd;
1711 
1712 l_coo_id igs_en_spa_terms.coo_id%TYPE;
1713 
1714 BEGIN
1715 --## 1. If term record exists for the effective term then get the attribute details
1716 --##    from it, set in EN_SPAT_REC_TYPE and exit
1717 --## 2. Term record not found for effective term, hence move on to a term record
1718 --##    which is immediately in the past and get the attribute information and
1719 --##    set it in EN_SPAT_REC_TYPE and exit
1720 --## 3. If no term record is found for the program attempt then get the attribute
1721 --##    information from the SPA.
1722 
1723     OPEN c_term;
1724     FETCH c_term INTO l_coo_id;
1725     IF (c_term%FOUND) THEN
1726         CLOSE c_term;
1727 
1728         RETURN l_coo_id;
1729      END IF;
1730      CLOSE c_term;
1731 
1732      OPEN c_prev_term;
1733      FETCH c_prev_term INTO l_coo_id;
1734      IF (c_prev_term%FOUND) THEN
1735         CLOSE c_prev_term;
1736         RETURN l_coo_id;
1737      ELSE
1738         CLOSE c_prev_term;
1739         OPEN c_spa;
1740         FETCH c_spa INTO l_coo_id;
1741      END IF;
1742      return l_coo_id;
1743 END get_spat_coo_id;
1744 
1745 FUNCTION get_spat_att_type (
1746             p_person_id IN NUMBER,
1747             p_program_cd IN VARCHAR2,
1748             p_term_cal_type IN VARCHAR2,
1749             p_term_sequence_NUMBER IN NUMBER
1750             ) RETURN VARCHAR2
1751 AS
1752 
1753   -- ## Get the term details information for the effective term
1754   CURSOR c_term IS
1755     SELECT attendance_type from igs_en_spa_terms
1756     WHERE person_id = p_person_id
1757     AND   program_cd = p_program_cd
1758     AND   term_cal_type = p_term_cal_type
1759     AND   term_sequence_number = p_term_sequence_number;
1760 
1761   -- ## get the term record values for a term which is previous to the effective term
1762   CURSOR c_prev_term IS
1763           SELECT
1764             SPAT.attendance_type
1765           FROM
1766             IGS_EN_SPA_TERMS SPAT,
1767             IGS_CA_INST CI1,
1768             IGS_CA_INST CI2
1769           WHERE
1770             SPAT.PERSON_ID = p_person_id AND
1771             spat.program_cd = p_program_cd AND
1772             SPAT.TERM_CAL_TYPE = CI2.CAL_TYPE AND
1773             SPAT.TERM_SEQUENCE_NUMBER =     CI2.SEQUENCE_NUMBER AND
1774             CI1.CAL_TYPE = p_term_cal_type AND
1775             CI1.SEQUENCE_NUMBER = p_term_sequence_number     AND
1776             CI1.START_DT > CI2.START_DT AND
1777             SPAT.ACAD_CAL_TYPE IN (SELECT SUP_CAL_TYPE
1778                                    FROM IGS_CA_INST_REL
1779                                    WHERE SUB_CAL_TYPE = CI1.CAL_TYPE
1780                                    AND SUB_CI_SEQUENCE_NUMBER = CI1.SEQUENCE_NUMBER)
1781           ORDER BY CI2.START_DT DESC;
1782 
1783 -- ## get the SPA values for the passed in program attempt
1784 CURSOR c_spa IS
1785 SELECT attendance_type
1786 FROM igs_en_stdnt_ps_att
1787 WHERE person_id = p_person_id
1788 AND course_cd = p_program_cd;
1789 
1790 l_attendance_type igs_en_spa_terms.attendance_type%TYPE;
1791 
1792 BEGIN
1793 --## 1. If term record exists for the effective term then get the attribute details
1794 --##    from it, set in EN_SPAT_REC_TYPE and exit
1795 --## 2. Term record not found for effective term, hence move on to a term record
1796 --##    which is immediately in the past and get the attribute information and
1797 --##    set it in EN_SPAT_REC_TYPE and exit
1798 --## 3. If no term record is found for the program attempt then get the attribute
1799 --##    information from the SPA.
1800 
1801     OPEN c_term;
1802     FETCH c_term INTO l_attendance_type;
1803     IF (c_term%FOUND) THEN
1804         CLOSE c_term;
1805 
1806         RETURN l_attendance_type;
1807      END IF;
1808      CLOSE c_term;
1809 
1810      OPEN c_prev_term;
1811      FETCH c_prev_term INTO l_attendance_type;
1812      IF (c_prev_term%FOUND) THEN
1813         CLOSE c_prev_term;
1814         RETURN l_attendance_type;
1815      ELSE
1816         CLOSE c_prev_term;
1817         OPEN c_spa;
1818         FETCH c_spa INTO l_attendance_type;
1819      END IF;
1820      return l_attendance_type;
1821 END get_spat_att_type;
1822 
1823 FUNCTION get_spat_att_mode(
1824 p_person_id IN NUMBER,
1825 p_program_cd IN VARCHAR2,
1826 p_term_cal_type IN VARCHAR2,
1827 p_term_sequence_NUMBER IN NUMBER
1828 ) RETURN VARCHAR2
1829 AS
1830 
1831   -- ## Get the term details information for the effective term
1832   CURSOR c_term IS
1833     SELECT attendance_mode from igs_en_spa_terms
1834     WHERE person_id = p_person_id
1835     AND   program_cd = p_program_cd
1836     AND   term_cal_type = p_term_cal_type
1837     AND   term_sequence_number = p_term_sequence_number;
1838 
1839   -- ## get the term record values for a term which is previous to the effective term
1840   CURSOR c_prev_term IS
1841           SELECT
1842             SPAT.attendance_mode
1843           FROM
1844             IGS_EN_SPA_TERMS SPAT,
1845             IGS_CA_INST CI1,
1846             IGS_CA_INST CI2
1847           WHERE
1848             SPAT.PERSON_ID = p_person_id AND
1849             spat.program_cd = p_program_cd AND
1850             SPAT.TERM_CAL_TYPE = CI2.CAL_TYPE AND
1851             SPAT.TERM_SEQUENCE_NUMBER =     CI2.SEQUENCE_NUMBER AND
1852             CI1.CAL_TYPE = p_term_cal_type AND
1853             CI1.SEQUENCE_NUMBER = p_term_sequence_number     AND
1854             CI1.START_DT > CI2.START_DT AND
1855             SPAT.ACAD_CAL_TYPE IN (SELECT SUP_CAL_TYPE
1856                                    FROM IGS_CA_INST_REL
1857                                    WHERE SUB_CAL_TYPE = CI1.CAL_TYPE
1858                                    AND SUB_CI_SEQUENCE_NUMBER = CI1.SEQUENCE_NUMBER)
1859           ORDER BY CI2.START_DT DESC;
1860 
1861 -- ## get the SPA values for the passed in program attempt
1862 CURSOR c_spa IS
1863 SELECT attendance_mode
1864 FROM igs_en_stdnt_ps_att
1865 WHERE person_id = p_person_id
1866 AND course_cd = p_program_cd;
1867 
1868 l_attendance_mode igs_en_spa_terms.attendance_mode%TYPE;
1869 
1870 BEGIN
1871 --## 1. If term record exists for the effective term then get the attribute details
1872 --##    from it, set in EN_SPAT_REC_TYPE and exit
1873 --## 2. Term record not found for effective term, hence move on to a term record
1874 --##    which is immediately in the past and get the attribute information and
1875 --##    set it in EN_SPAT_REC_TYPE and exit
1876 --## 3. If no term record is found for the program attempt then get the attribute
1877 --##    information from the SPA.
1878 
1879     OPEN c_term;
1880     FETCH c_term INTO l_attendance_mode;
1881     IF (c_term%FOUND) THEN
1882         CLOSE c_term;
1883 
1884         RETURN l_attendance_mode;
1888      OPEN c_prev_term;
1885      END IF;
1886      CLOSE c_term;
1887 
1889      FETCH c_prev_term INTO l_attendance_mode;
1890      IF (c_prev_term%FOUND) THEN
1891         CLOSE c_prev_term;
1892         RETURN l_attendance_mode;
1893      ELSE
1894         CLOSE c_prev_term;
1895         OPEN c_spa;
1896         FETCH c_spa INTO l_attendance_mode;
1897      END IF;
1898      return l_attendance_mode;
1899 END get_spat_att_mode;
1900 
1901 FUNCTION get_spat_location(
1902 p_person_id IN NUMBER,
1903 p_program_cd IN VARCHAR2,
1904 p_term_cal_type IN VARCHAR2,
1905 p_term_sequence_NUMBER IN NUMBER
1906 ) RETURN VARCHAR2
1907 AS
1908 
1909   -- ## Get the term details information for the effective term
1910   CURSOR c_term IS
1911     SELECT location_cd from igs_en_spa_terms
1912     WHERE person_id = p_person_id
1913     AND   program_cd = p_program_cd
1914     AND   term_cal_type = p_term_cal_type
1915     AND   term_sequence_number = p_term_sequence_number;
1916 
1917   -- ## get the term record values for a term which is previous to the effective term
1918   CURSOR c_prev_term IS
1919           SELECT
1920             SPAT.location_cd
1921           FROM
1922             IGS_EN_SPA_TERMS SPAT,
1923             IGS_CA_INST CI1,
1924             IGS_CA_INST CI2
1925           WHERE
1926             SPAT.PERSON_ID = p_person_id AND
1927             spat.program_cd = p_program_cd AND
1928             SPAT.TERM_CAL_TYPE = CI2.CAL_TYPE AND
1929             SPAT.TERM_SEQUENCE_NUMBER =     CI2.SEQUENCE_NUMBER AND
1930             CI1.CAL_TYPE = p_term_cal_type AND
1931             CI1.SEQUENCE_NUMBER = p_term_sequence_number     AND
1932             CI1.START_DT > CI2.START_DT AND
1933             SPAT.ACAD_CAL_TYPE IN (SELECT SUP_CAL_TYPE
1934                                    FROM IGS_CA_INST_REL
1935                                    WHERE SUB_CAL_TYPE = CI1.CAL_TYPE
1936                                    AND SUB_CI_SEQUENCE_NUMBER = CI1.SEQUENCE_NUMBER)
1937           ORDER BY CI2.START_DT DESC;
1938 
1939 -- ## get the SPA values for the passed in program attempt
1940 CURSOR c_spa IS
1941 SELECT location_cd
1942 FROM igs_en_stdnt_ps_att
1943 WHERE person_id = p_person_id
1944 AND course_cd = p_program_cd;
1945 
1946 l_location_cd igs_en_spa_terms.location_cd%TYPE;
1947 
1948 BEGIN
1949 --## 1. If term record exists for the effective term then get the attribute details
1950 --##    from it, set in EN_SPAT_REC_TYPE and exit
1951 --## 2. Term record not found for effective term, hence move on to a term record
1952 --##    which is immediately in the past and get the attribute information and
1953 --##    set it in EN_SPAT_REC_TYPE and exit
1954 --## 3. If no term record is found for the program attempt then get the attribute
1955 --##    information from the SPA.
1956 
1957     OPEN c_term;
1958     FETCH c_term INTO l_location_cd;
1959     IF (c_term%FOUND) THEN
1960         CLOSE c_term;
1961 
1962         RETURN l_location_cd;
1963      END IF;
1964      CLOSE c_term;
1965 
1966      OPEN c_prev_term;
1967      FETCH c_prev_term INTO l_location_cd;
1968      IF (c_prev_term%FOUND) THEN
1969         CLOSE c_prev_term;
1970         RETURN l_location_cd;
1971      ELSE
1972         CLOSE c_prev_term;
1973         OPEN c_spa;
1974         FETCH c_spa INTO l_location_cd;
1975      END IF;
1976      return l_location_cd;
1977 END get_spat_location;
1978 
1979 FUNCTION get_spat_program_version(
1980 p_person_id IN NUMBER,
1981 p_program_cd IN VARCHAR2,
1982 p_term_cal_type IN VARCHAR2,
1983 p_term_sequence_NUMBER IN NUMBER
1984 ) RETURN NUMBER
1985 AS
1986 
1987   -- ## Get the term details information for the effective term
1988   CURSOR c_term IS
1989     SELECT program_version from igs_en_spa_terms
1990     WHERE person_id = p_person_id
1991     AND   program_cd = p_program_cd
1992     AND   term_cal_type = p_term_cal_type
1993     AND   term_sequence_number = p_term_sequence_number;
1994 
1995   -- ## get the term record values for a term which is previous to the effective term
1996   CURSOR c_prev_term IS
1997           SELECT
1998             SPAT.program_version
1999           FROM
2000             IGS_EN_SPA_TERMS SPAT,
2001             IGS_CA_INST CI1,
2002             IGS_CA_INST CI2
2003           WHERE
2004             SPAT.PERSON_ID = p_person_id AND
2005             spat.program_cd = p_program_cd AND
2006             SPAT.TERM_CAL_TYPE = CI2.CAL_TYPE AND
2007             SPAT.TERM_SEQUENCE_NUMBER =     CI2.SEQUENCE_NUMBER AND
2008             CI1.CAL_TYPE = p_term_cal_type AND
2009             CI1.SEQUENCE_NUMBER = p_term_sequence_number     AND
2010             CI1.START_DT > CI2.START_DT AND
2011             SPAT.ACAD_CAL_TYPE IN (SELECT SUP_CAL_TYPE
2012                                    FROM IGS_CA_INST_REL
2013                                    WHERE SUB_CAL_TYPE = CI1.CAL_TYPE
2014                                    AND SUB_CI_SEQUENCE_NUMBER = CI1.SEQUENCE_NUMBER)
2015           ORDER BY CI2.START_DT DESC;
2016 
2017 -- ## get the SPA values for the passed in program attempt
2018 CURSOR c_spa IS
2019 SELECT version_number
2020 FROM igs_en_stdnt_ps_att
2021 WHERE person_id = p_person_id
2022 AND course_cd = p_program_cd;
2023 
2027 --## 1. If term record exists for the effective term then get the attribute details
2024 l_program_version igs_en_spa_terms.program_version%TYPE;
2025 
2026 BEGIN
2028 --##    from it, set in EN_SPAT_REC_TYPE and exit
2029 --## 2. Term record not found for effective term, hence move on to a term record
2030 --##    which is immediately in the past and get the attribute information and
2031 --##    set it in EN_SPAT_REC_TYPE and exit
2032 --## 3. If no term record is found for the program attempt then get the attribute
2033 --##    information from the SPA.
2034 
2035     OPEN c_term;
2036     FETCH c_term INTO l_program_version;
2037     IF (c_term%FOUND) THEN
2038         CLOSE c_term;
2039 
2040         RETURN l_program_version;
2041      END IF;
2042      CLOSE c_term;
2043 
2044      OPEN c_prev_term;
2045      FETCH c_prev_term INTO l_program_version;
2046      IF (c_prev_term%FOUND) THEN
2047         CLOSE c_prev_term;
2048         RETURN l_program_version;
2049      ELSE
2050         CLOSE c_prev_term;
2051         OPEN c_spa;
2052         FETCH c_spa INTO l_program_version;
2053      END IF;
2054      return l_program_version;
2055 END get_spat_program_version;
2056 
2057 PROCEDURE delete_terms_for_program(
2058 p_person_id IN NUMBER,
2059 p_program_cd IN VARCHAR2) AS
2060 l_term_cal_type IGS_CA_INST.cal_type%TYPE;
2061 l_term_sequence_number IGS_CA_INST.sequence_number%TYPE;
2062 l_acad_cal_type IGS_CA_INST.cal_type%TYPE;
2063 l_acad_ci_seq_num IGS_CA_INST.sequence_number%TYPE;
2064 l_load_ci_alt_code IGS_CA_INST.alternate_code%TYPE;
2065 l_load_ci_start_dt  DATE;
2066 l_load_ci_end_dt DATE;
2067 l_message_name  VARCHAR2(200);
2068 CURSOR c_future_terms(cp_term_cal_type IGS_CA_INST.cal_type%TYPE, cp_term_seq_num IGS_CA_INST.sequence_number%TYPE) IS
2069 select spat.rowid, spat.person_id, spat.program_cd, spat.term_cal_type,spat.term_sequence_number, spat.fee_cat
2070 from igs_en_spa_terms spat, igs_ca_inst c1, igs_ca_inst c2
2071 where person_id = p_person_id
2072 and   program_cd = p_program_cd
2073 and   term_cal_type = c1.cal_type
2074 and   term_sequence_number = c1.sequence_number
2075 and   cp_term_cal_type = c2.cal_type
2076 and   cp_term_seq_num = c2.sequence_number
2077 and   c1.start_dt >= c2.start_dt
2078 for update nowait;
2079 l_fee_assessed VARCHAR2(1);
2080 l_message VARCHAR2(2000);
2081 BEGIN
2082     igs_en_gen_015.enrp_get_eff_load_ci(p_person_id, p_program_cd, SYSDATE,
2083                         l_acad_cal_type,
2084                         l_acad_ci_seq_num,
2085                         l_term_cal_type,
2086                         l_term_sequence_number,
2087                         l_load_ci_alt_code,
2088                         l_load_ci_start_dt,
2089                         l_load_ci_end_dt,
2090                         l_message_name);
2091 
2092     for rec_future_terms IN c_future_terms(l_term_cal_type, l_term_sequence_number)
2093     LOOP
2094 
2095             -- key/pirmary will never be unconfirmed if there is an alternate program that can
2096             -- be made key/primary.
2097             -- If this is the only primary key program then its unconfirmed and SPA key program is set as 'N'
2098             -- Hence there is no need to find an alternate key primary delete_row(rowid);
2099             -- If fee is assessed for a term, then donot delete such term record.
2100             igs_fi_gen_008.chk_spa_rec_exists(
2101                              p_n_person_id    => rec_future_terms.person_id,
2102                              p_v_course_cd    => rec_future_terms.program_cd,
2103                              p_v_load_cal_type=> rec_future_terms.term_cal_type,
2104                              p_n_load_ci_seq  => rec_future_terms.term_sequence_number,
2105                              p_v_fee_cat      => rec_future_terms.fee_cat,
2106                              p_v_status       => l_fee_assessed,
2107                              p_v_message      => l_message);
2108             IF  l_fee_assessed = 'N' THEN
2109               --
2110                   igs_en_spa_terms_pkg.delete_row(rec_future_terms.rowid);
2111             END IF;
2112 
2113 
2114     END LOOP;
2115 
2116 END;
2117 FUNCTION get_spat_key_prog_flag(
2118 p_person_id IN NUMBER,
2119 p_program_cd IN VARCHAR2,
2120 p_term_cal_type IN VARCHAR2,
2121 p_term_sequence_NUMBER IN NUMBER
2122 ) RETURN VARCHAR2 AS
2123 l_key_program IGS_PS_VER.COURSE_CD%TYPE;
2124 BEGIN
2125         l_key_program := find_key_effective_for(p_person_id,p_term_cal_type, p_term_sequence_NUMBER);
2126         if (p_program_cd  = l_key_program) THEN
2127             RETURN 'Y';
2128         ELSE
2129             RETURN 'N';
2130         END IF;
2131 END get_spat_key_prog_flag;
2132 
2133 
2134 FUNCTION get_miss_char RETURN VARCHAR2 AS
2135 BEGIN
2136    RETURN FND_API.G_MISS_CHAR;
2137 END;
2138 FUNCTION get_spat_att_type_desc (
2139             p_person_id IN NUMBER,
2140             p_program_cd IN VARCHAR2,
2141             p_term_cal_type IN VARCHAR2,
2142             p_term_sequence_NUMBER IN NUMBER
2143             ) RETURN VARCHAR2 AS
2144 l_att_type igs_en_atd_type.attendance_type%TYPE;
2145 l_att_desc igs_en_atd_type.description%TYPE;
2146 CURSOR c_att_desc (cp_att_type igs_en_atd_type.attendance_type%TYPE) IS
2147 SELECT description
2148 FROM igs_en_atd_type
2149 WHERE attendance_type = cp_att_type;
2150 
2151 BEGIN
2155                             p_term_cal_type,
2152     l_att_type := get_spat_att_type(
2153                             p_person_id,
2154                             p_program_cd,
2156                             p_term_sequence_NUMBER);
2157     OPEN c_att_desc(l_att_type);
2158     FETCH c_att_desc INTO l_att_desc;
2159     CLOSE c_att_desc;
2160     RETURN l_att_desc;
2161 END;
2162 
2163 FUNCTION get_spat_att_mode_desc (
2164             p_person_id IN NUMBER,
2165             p_program_cd IN VARCHAR2,
2166             p_term_cal_type IN VARCHAR2,
2167             p_term_sequence_NUMBER IN NUMBER
2168             ) RETURN VARCHAR2 AS
2169 l_att_mode igs_en_atd_mode.attendance_mode%TYPE;
2170 l_att_desc igs_en_atd_mode.description%TYPE;
2171 CURSOR c_att_desc (cp_att_mode igs_en_atd_mode.attendance_mode%TYPE) IS
2172 SELECT description
2173 FROM igs_en_atd_mode
2174 WHERE attendance_mode = cp_att_mode;
2175 
2176 BEGIN
2177     l_att_mode := get_spat_att_mode(
2178                             p_person_id,
2179                             p_program_cd,
2180                             p_term_cal_type,
2181                             p_term_sequence_NUMBER);
2182     OPEN c_att_desc(l_att_mode);
2183     FETCH c_att_desc INTO l_att_desc;
2184     CLOSE c_att_desc;
2185     RETURN l_att_desc;
2186 END;
2187 
2188 FUNCTION get_spat_location_desc (
2189             p_person_id IN NUMBER,
2190             p_program_cd IN VARCHAR2,
2191             p_term_cal_type IN VARCHAR2,
2192             p_term_sequence_NUMBER IN NUMBER
2193             ) RETURN VARCHAR2 AS
2194 l_loc igs_ad_location.location_cd%TYPE;
2195 l_loc_desc igs_ad_location.description%TYPE;
2196 CURSOR c_loc_desc (cp_loc igs_ad_location.location_cd%TYPE) IS
2197 SELECT description
2198 FROM igs_ad_location
2199 WHERE location_cd = cp_loc;
2200 
2201 BEGIN
2202     l_loc := get_spat_location(
2203                             p_person_id,
2204                             p_program_cd,
2205                             p_term_cal_type,
2206                             p_term_sequence_NUMBER);
2207     OPEN c_loc_desc(l_loc);
2208     FETCH c_loc_desc INTO l_loc_desc;
2209     CLOSE c_loc_desc;
2210     RETURN l_loc_desc;
2211 END;
2212 
2213 
2214 FUNCTION get_spat_primary_prg(
2215 p_person_id IN NUMBER,
2216 p_program_cd IN VARCHAR2,
2217 p_term_cal_type IN VARCHAR2,
2218 p_term_sequence_NUMBER IN NUMBER
2219 ) RETURN VARCHAR2
2220 AS
2221 /* -----------------------------------------------------------------------
2222    Created By        : rvangala
2223    Date Created By   : 18-Nov-2003
2224    Purpose           : Check whether the given program is a primary or
2225                        secondary program in the given term.
2226                        Returns PRIMARY, SECONDARY OR NULL
2227 
2228    Change History
2229    Who         When        What
2230   stutta    31-Dec-2004  Added cursor cur_c3prev to pick up previous term
2231                          records for the career, if no record is found for
2232                          the term passed in as parameter.
2233   ----------------------------------------------------------------------*/
2234 
2235     -- cursor to check whether program is a term record
2236     CURSOR cur_c1 IS
2237         SELECT 'x'
2238         FROM igs_en_spa_terms spat
2239         WHERE
2240         spat.person_id            = p_person_id AND
2241         spat.program_cd           = p_program_cd AND
2242         spat.term_cal_type        = p_term_cal_type AND
2243         spat.term_sequence_number = p_term_sequence_number;
2244 
2245     -- cursor to retrieve course_type for given program and person
2246     CURSOR cur_c2 IS
2247         SELECT ps.course_type
2248         FROM igs_ps_ver ps,
2249              igs_en_stdnt_ps_att spa
2250         WHERE
2251         spa.course_cd      = p_program_cd AND
2252         spa.person_id      = p_person_id AND
2253         spa.course_cd      = ps.course_cd AND
2254         spa.version_number = ps.version_number;
2255 
2256     -- cursor to check whether term record exists for some other program
2257     -- for the student in same career
2258     CURSOR cur_c3(p_program_type IN VARCHAR2) IS
2259         SELECT 'x'
2260         FROM igs_en_spa_terms spat
2261         WHERE spat.person_id      = p_person_id AND
2262         p_program_type = (SELECT course_type FROM igs_ps_ver
2263                            WHERE course_cd = spat.program_cd
2264                            AND version_number = spat.program_version)
2265         AND spat.term_cal_type        = p_term_cal_type
2266         AND spat.term_sequence_number = p_term_sequence_number;
2267 
2268       CURSOR ci_start_dt (cp_cal_type IGS_CA_INST.CAL_TYPE%TYPE,
2269                           cp_ci_Sequence_number IGS_CA_INST.SEQUENCE_NUMBER%TYPE) IS
2270       SELECT start_dt
2271       FROM   IGS_CA_INST
2272       WHERE cal_type = cp_cal_type
2273       AND sequence_number = cp_ci_Sequence_number;
2274 
2275       CURSOR cur_c3prev (cp_person_id igs_en_spa_terms.person_id%TYPE,
2276                          cp_program_type igs_ps_ver.course_type%TYPE,
2277                          cp_start_dt IGS_CA_INST.START_DT%TYPE) IS
2278       SELECT
2279         SPAT.PROGRAM_CD
2280       FROM
2281         IGS_EN_SPA_TERMS SPAT,
2282         IGS_CA_INST CI2
2283       WHERE
2284         SPAT.PERSON_ID = cp_person_id AND
2285         cp_program_type = (SELECT course_type
2286                            FROM igs_ps_ver cv
2287                            WHERE spat.program_cd = cv.course_cd
2288                            AND spat.program_version = cv.version_number) AND
2289         SPAT.TERM_CAL_TYPE = CI2.CAL_TYPE AND
2290         SPAT.TERM_SEQUENCE_NUMBER = CI2.SEQUENCE_NUMBER AND
2291         CI2.START_DT < cp_start_dt
2292       ORDER BY CI2.START_DT DESC;
2293 
2294     -- cursor to check whether given program for person exists in
2295     -- program attempt table
2296     CURSOR cur_c4 IS
2297         SELECT primary_program_type
2298         FROM igs_en_stdnt_ps_att
2299         WHERE
2300         person_id = p_person_id AND
2301         course_cd = p_program_cd;
2302 
2303 
2304      l_primary_prg IGS_EN_STDNT_PS_ATT.PRIMARY_PROGRAM_TYPE%TYPE;
2305      l_profile VARCHAR2(1);
2306      l_program_type IGS_PS_VER.COURSE_TYPE%TYPE;
2307      l_check VARCHAR2(1);
2308      l_program_cd IGS_EN_STDNT_PS_ATT.COURSE_CD%TYPE;
2309      l_start_dt IGS_CA_INST.START_DT%TYPE;
2310 
2311 BEGIN
2312 
2313  -- check whether Career profile is set or not
2314  l_profile :=NVL(fnd_profile.value('CAREER_MODEL_ENABLED'),'N');
2315 
2316  -- if system is in Career model
2317  IF l_profile='Y' THEN
2318    OPEN cur_c1;
2319    FETCH cur_c1 INTO l_primary_prg;
2320 
2321    -- check term record exists for given program,
2322    -- if  record exists then it is the Primary program
2323    IF cur_c1%FOUND THEN
2324     l_primary_prg:='PRIMARY';
2325 
2326    -- if term record for program does not exist
2327    ELSE
2328       -- retrieve course_type for program
2329       OPEN  cur_c2;
2330       FETCH cur_c2 INTO l_program_type;
2331       CLOSE cur_c2;
2332 
2333       -- and check whether term record exists for some other program for
2334       -- student in same career
2335       OPEN cur_c3(l_program_type);
2336       FETCH cur_c3 INTO l_check;
2337 
2338       -- if term record exists for some other program for student in same career
2339       -- return SECONDARY
2340       IF cur_c3%FOUND THEN
2341          l_primary_prg := 'SECONDARY';
2342 
2343       ELSE
2344         -- check if any previous term record exists for this career.
2345          OPEN ci_start_dt(p_term_cal_type, p_term_sequence_number);
2346          FETCH ci_start_dt INTO l_start_dt;
2347          CLOSE ci_start_dt;
2348          OPEN cur_c3prev(p_person_id, l_program_type, l_start_dt);
2349          FETCH cur_c3prev INTO l_program_cd;
2350          IF cur_c3prev%FOUND THEN -- if a previous term record is found for this career.
2351              IF l_program_cd = p_program_cd THEN
2352                -- This program is primary is the previous term
2353                 l_primary_prg := 'PRIMARY';
2354              ELSE
2355                -- some other program is primary in previous term for the career
2356                  l_primary_prg := 'SECONDARY';
2357              END IF;
2358          ELSE
2359              -- check whether given program for person exists in
2360              -- program attempt table
2361              OPEN cur_c4;
2362              FETCH cur_c4 INTO l_primary_prg;
2363 
2364              -- if given program for person exists in program attempt table
2365              -- return primary_program_type value obtained
2366              IF cur_c4%FOUND THEN
2367                l_primary_prg:=l_primary_prg;
2368 
2369              -- if given program for person does not exist in program attempt table
2370              -- return null
2371              ELSE
2372                l_primary_prg :=null;
2373              END IF;
2374 
2375              CLOSE cur_c4;
2376            END IF;
2377            CLOSE cur_c3prev;
2378       END IF;
2379 
2380       CLOSE cur_c3;
2381 
2382    END IF;
2383 
2384    CLOSE cur_c1;
2385  END IF;
2386 
2387  RETURN l_primary_prg;
2388 END get_spat_primary_prg;
2389 
2390 
2391 PROCEDURE validate_terms(
2392 p_person_id IN NUMBER
2393 )
2394 AS
2395 /* -----------------------------------------------------------------------
2396    Created By        : rvangala
2397    Date Created By   : 18-Nov-2003
2398    Purpose           : Validates number of terms containing key program
2399                        for given person id
2400    Change History
2401    Who         When        What
2402 
2403   ----------------------------------------------------------------------*/
2404 
2405     -- cursor to fetch distinct term records for given person id
2406     CURSOR c_distinct_terms IS
2407       SELECT DISTINCT term_cal_type, term_sequence_number
2408       FROM            IGS_EN_SPA_TERMS
2409       WHERE           person_id = p_person_id;
2410 
2411     -- cursor to fetch number of terms containing key program for given
2412     -- person id, term cal type and sequence number
2413     CURSOR c_count_key (cp_term_cal_type IGS_CA_INST.CAL_TYPE%TYPE,
2414                         cp_term_sequence_number IGS_CA_INST.SEQUENCE_NUMBER%TYPE)
2415       IS
2416       SELECT COUNT(key_program_flag)
2417       FROM   IGS_EN_SPA_TERMS
2418       WHERE  person_id            = p_person_id
2419       AND    term_cal_type        = cp_term_cal_type
2420       AND    term_sequence_number = cp_term_sequence_number
2421       AND    key_program_flag     = 'Y';
2422 
2423     vn_key_count     NUMBER(1);
2424 
2425 BEGIN
2426     -- loop through the distinct term records for given person id
2427     FOR vr_distinct_terms_rec IN c_distinct_terms LOOP
2428 
2429         vn_key_count := 0;
2430 
2431         -- fetch number of terms containing key program
2432         OPEN c_count_key(vr_distinct_terms_rec.term_cal_type,
2433                          vr_distinct_terms_rec.term_sequence_number);
2434         FETCH c_count_key INTO vn_key_count;
2435         CLOSE c_count_key;
2436 
2437         -- if number of terms containing key program is greater than 1
2438         IF vn_key_count > 1 THEN
2439           FND_MESSAGE.SET_NAME('IGS','IGS_EN_MORE_KEY_IN_TERM');
2440           app_exception.raise_exception;
2441         END IF;
2442 
2443      END LOOP;
2444 
2445 END validate_terms;
2446 
2447 FUNCTION get_curr_term(
2448 p_cal_type IN VARCHAR2
2449 ) RETURN VARCHAR2
2450 AS
2451 /* -----------------------------------------------------------------------
2452    Created By        : rvangala
2453    Date Created By   : 18-Nov-2003
2454    Purpose           : Returns the sequence number for the current term, for
2455                        the given academic calendar
2456 
2457    Change History
2458    rvangala   17-Feb-2004    Added formatting to the return value from the
2459                              function, Bug #3441941
2460 
2461   ----------------------------------------------------------------------*/
2462 
2463     --local variables
2464     l_load_cal_type      IGS_CA_INST.CAL_TYPE%TYPE;
2465     l_load_ci_seq_num    IGS_CA_INST.SEQUENCE_NUMBER%TYPE;
2466     l_load_ci_alt_code   IGS_CA_INST.ALTERNATE_CODE%TYPE;
2467     l_load_ci_start_dt   DATE;
2468     l_load_ci_end_dt     DATE;
2469     l_message_name       VARCHAR2(80);
2470 
2471     l_curr_term          VARCHAR2(100);
2472 
2473 BEGIN
2474 
2475     -- call package igs_en_gen_015 to retrieve sequence number for current term
2476     -- for given academic calendar
2477     igs_en_gen_015.get_curr_acad_term_cal(
2478         p_acad_cal_type       => p_cal_type,
2479         p_effective_dt        => SYSDATE,
2480         p_load_cal_type       => l_load_cal_type,
2481         p_load_ci_seq_num     => l_load_ci_seq_num,
2482         p_load_ci_alt_code    => l_load_ci_alt_code,
2483         p_load_ci_start_dt    => l_load_ci_start_dt,
2484         p_load_ci_end_dt      => l_load_ci_end_dt,
2485         p_message_name        => l_message_name);
2486 
2487      -- concatenate term calendar sequence number and term calendar type
2488      l_curr_term :=RPAD(l_load_ci_seq_num,6,' ') || l_load_cal_type;
2489 
2490      RETURN l_curr_term;
2491 
2492 END get_curr_term;
2493 
2494 
2495 FUNCTION get_prev_term(
2496 p_cal_type IN VARCHAR2
2497 ) RETURN VARCHAR2
2498 AS
2499 /* -----------------------------------------------------------------------
2500    Created By        : rvangala
2501    Date Created By   : 18-Nov-2003
2502    Purpose           : Returns the sequence number for the immediate previous
2503                        term for the current term, for the given academic
2504                        calendar
2505 
2506    Change History
2507    rvangala   17-Feb-2004    Added formatting in select clause to pick
2508                              results from cur_c1, Bug #3441941
2509 
2510   ----------------------------------------------------------------------*/
2511 
2512     -- cursor to fetch immediate previous term for current term, for the
2513     -- given academic calendar
2514     CURSOR cur_c1(p_cur_term_cal IN VARCHAR2,
2515                   p_cur_term_seq_num IN NUMBER) IS
2516         SELECT RPAD(ci2.sequence_number,6,' ') || ci2.cal_Type
2517         FROM igs_ca_inst ci2,
2518             igs_ca_inst_rel cir,
2519             igs_ca_type ct,
2523         ci2.cal_type        = cir.sub_cal_type AND
2520             igs_ca_inst ci1,
2521             igs_ca_stat cs
2522         WHERE
2524         ci2.sequence_number = cir.sub_ci_sequence_number AND
2525         cir.sup_cal_type    = p_cal_type AND
2526         ci2.cal_type        = ct.cal_type AND
2527         ct.s_cal_cat        = 'LOAD' AND
2528         cs.cal_status       = ci1.cal_status AND
2529         cs.s_cal_status     = 'ACTIVE' AND
2530         ci1.cal_type        = p_cur_term_cal AND
2531         ci1.sequence_number = p_cur_term_seq_num AND
2532         ci2.start_dt        < ci1.start_dt
2533         ORDER BY            ci2.start_dt DESC;
2534 
2535     --local variables
2536     l_load_cal_type      IGS_CA_INST.CAL_TYPE%TYPE;
2537     l_load_ci_seq_num    IGS_CA_INST.SEQUENCE_NUMBER%TYPE;
2538     l_load_ci_alt_code   IGS_CA_INST.ALTERNATE_CODE%TYPE;
2539     l_load_ci_start_dt   DATE;
2540     l_load_ci_end_dt     DATE;
2541     l_message_name       VARCHAR2(80);
2542 
2543     l_prev_term          VARCHAR2(100);
2544 BEGIN
2545     -- call package igs_en_gen_015 to retrieve sequence number for current term
2546     -- for given academic calendar
2547     igs_en_gen_015.get_curr_acad_term_cal(
2548         p_acad_cal_type       => p_cal_type,
2549         p_effective_dt        => SYSDATE,
2550         p_load_cal_type       => l_load_cal_type,
2551         p_load_ci_seq_num     => l_load_ci_seq_num,
2552         p_load_ci_alt_code    => l_load_ci_alt_code,
2553         p_load_ci_start_dt    => l_load_ci_start_dt,
2554         p_load_ci_end_dt      => l_load_ci_end_dt,
2555         p_message_name        => l_message_name);
2556 
2557    -- fetch immediate previous term for the current term
2558    OPEN cur_c1(l_load_cal_type,l_load_ci_seq_num);
2559    FETCH cur_c1 INTO l_prev_term;
2560    CLOSE cur_c1;
2561 
2562    RETURN l_prev_term;
2563 END get_prev_term;
2564 
2565 
2566 FUNCTION get_next_term(
2567 p_cal_type IN VARCHAR2
2568 ) RETURN VARCHAR2
2569 AS
2570 /* -----------------------------------------------------------------------
2571    Created By        : rvangala
2572    Date Created By   : 18-Nov-2003
2573    Purpose           : Returns the sequence number for the immediate next term
2574                        for the current term, for the given academic calendar
2575 
2576    Change History
2577    rvangala   17-Feb-2004    Added formatting in select clause to pick
2578                              results from cur_c1, Bug #3441941
2579 
2580   ----------------------------------------------------------------------*/
2581 
2582     -- cursor to fetch immediate next term for current term, for the
2583     -- given academic calendar
2584     CURSOR cur_c1(p_cur_term_cal IN VARCHAR2,
2585                    p_cur_term_seq_num IN NUMBER) IS
2586         SELECT RPAD(ci2.sequence_number,6,' ') || ci2.cal_type
2587         FROM igs_ca_inst ci2,
2588             igs_ca_inst_rel cir,
2589             igs_ca_type ct,
2590             igs_ca_inst ci1,
2591             igs_ca_stat cs
2592         WHERE
2593         ci2.cal_type        = cir.sub_cal_type AND
2594         ci2.sequence_number = cir.sub_ci_sequence_number AND
2595         cir.sup_cal_type    = p_cal_type AND
2596         ci2.cal_type        = ct.cal_type AND
2597         ct.s_cal_cat        = 'LOAD' AND
2598         cs.cal_status       = ci1.cal_status AND
2599         cs.s_cal_status     = 'ACTIVE' AND
2600         ci1.cal_type        = p_cur_term_cal AND
2601         ci1.sequence_number = p_cur_term_seq_num AND
2602         ci2.start_dt        > ci1.start_dt
2603         ORDER BY            ci2.start_dt;
2604 
2605     --local variables
2606     l_load_cal_type      IGS_CA_INST.CAL_TYPE%TYPE;
2607     l_load_ci_seq_num    IGS_CA_INST.SEQUENCE_NUMBER%TYPE;
2608     l_load_ci_alt_code   IGS_CA_INST.ALTERNATE_CODE%TYPE;
2609     l_load_ci_start_dt   DATE;
2610     l_load_ci_end_dt     DATE;
2611     l_message_name       VARCHAR2(80);
2612 
2613     l_next_term          VARCHAR2(100);
2614 BEGIN
2615     -- call package igs_en_gen_015 to retrieve sequence number for current term
2616     -- for given academic calendar
2617     igs_en_gen_015.get_curr_acad_term_cal(
2618         p_acad_cal_type       => p_cal_type,
2619         p_effective_dt        => SYSDATE,
2620         p_load_cal_type       => l_load_cal_type,
2621         p_load_ci_seq_num     => l_load_ci_seq_num,
2622         p_load_ci_alt_code    => l_load_ci_alt_code,
2623         p_load_ci_start_dt    => l_load_ci_start_dt,
2624         p_load_ci_end_dt      => l_load_ci_end_dt,
2625         p_message_name        => l_message_name);
2626 
2627    -- fetch immediate next term for the current term
2628    OPEN cur_c1(l_load_cal_type,l_load_ci_seq_num);
2629    FETCH cur_c1 INTO l_next_term;
2630    CLOSE cur_c1;
2631 
2632    RETURN l_next_term;
2633 END get_next_term;
2634 
2635 
2636 FUNCTION get_spat_acad_cal_type(
2637 p_person_id IN NUMBER,
2638 p_program_cd IN VARCHAR2,
2639 p_term_cal_type IN VARCHAR2,
2640 p_term_sequence_NUMBER IN NUMBER
2641 ) RETURN VARCHAR2 AS
2642   -- ## Get the term details information for the effective term
2643   CURSOR c_term IS
2644     SELECT acad_cal_type from igs_en_spa_terms
2645     WHERE person_id = p_person_id
2646     AND   program_cd = p_program_cd
2647     AND   term_cal_type = p_term_cal_type
2648     AND   term_sequence_number = p_term_sequence_number;
2649 
2650   -- ## get the term record values for a term which is previous to the effective term
2651   CURSOR c_prev_term IS
2652           SELECT
2653             SPAT.acad_cal_type
2654           FROM
2655             IGS_EN_SPA_TERMS SPAT,
2656             IGS_CA_INST CI1,
2657             IGS_CA_INST CI2
2658           WHERE
2659             SPAT.PERSON_ID = p_person_id AND
2660             spat.program_cd = p_program_cd AND
2661             SPAT.TERM_CAL_TYPE = CI2.CAL_TYPE AND
2662             SPAT.TERM_SEQUENCE_NUMBER =     CI2.SEQUENCE_NUMBER AND
2663             CI1.CAL_TYPE = p_term_cal_type AND
2664             CI1.SEQUENCE_NUMBER = p_term_sequence_number     AND
2665             CI1.START_DT > CI2.START_DT AND
2666             SPAT.ACAD_CAL_TYPE IN (SELECT SUP_CAL_TYPE
2667                                    FROM IGS_CA_INST_REL
2668                                    WHERE SUB_CAL_TYPE = CI1.CAL_TYPE
2669                                    AND SUB_CI_SEQUENCE_NUMBER = CI1.SEQUENCE_NUMBER)
2670           ORDER BY CI2.START_DT DESC;
2671 
2672 -- ## get the SPA values for the passed in program attempt
2673 CURSOR c_spa IS
2674 SELECT cal_type
2675 FROM igs_en_stdnt_ps_att
2676 WHERE person_id = p_person_id
2677 AND course_cd = p_program_cd;
2678 
2679 l_acad_cal_type igs_en_spa_terms.acad_cal_type%TYPE;
2680 
2681 BEGIN
2682 --## 1. If term record exists for the effective term then get the attribute details
2683 --##    from it, set in EN_SPAT_REC_TYPE and exit
2684 --## 2. Term record not found for effective term, hence move on to a term record
2685 --##    which is immediately in the past and get the attribute information and
2686 --##    set it in EN_SPAT_REC_TYPE and exit
2687 --## 3. If no term record is found for the program attempt then get the attribute
2688 --##    information from the SPA.
2689 
2690     OPEN c_term;
2691     FETCH c_term INTO l_acad_cal_type;
2692     IF (c_term%FOUND) THEN
2693         CLOSE c_term;
2694 
2695         RETURN l_acad_cal_type;
2696      END IF;
2697      CLOSE c_term;
2698 
2699      OPEN c_prev_term;
2700      FETCH c_prev_term INTO l_acad_cal_type;
2701      IF (c_prev_term%FOUND) THEN
2702         CLOSE c_prev_term;
2703         RETURN l_acad_cal_type;
2704      ELSE
2705         CLOSE c_prev_term;
2706         OPEN c_spa;
2707         FETCH c_spa INTO l_acad_cal_type;
2708         CLOSE c_spa;
2709      END IF;
2710      RETURN l_acad_cal_type;
2711 END get_spat_acad_cal_type;
2712 
2713 
2714 END IGS_EN_SPA_TERMS_API;