DBA Data[Home] [Help]

PACKAGE BODY: APPS.IGS_CA_GEN_002

Source


1 PACKAGE BODY IGS_CA_GEN_002 AS
2 /* $Header: IGSCA02B.pls 115.6 2002/11/28 22:56:30 nsidana ship $ */
3 
4   /******************************************************************
5   Created By         :
6   Date Created By    :
7   Purpose            :
8   remarks            :
9   Change History
10   Who		When            What
11   schodava	08-Jul-02	Bug # 2442220
12 				Modified function calp_clc_daio_cnstrt
13   ******************************************************************/
14 
15 FUNCTION calp_clc_daio_cnstrt(
16   p_dt_alias IN VARCHAR2 ,
17   p_sequence_number IN NUMBER ,
18   p_cal_type IN VARCHAR2 ,
19   p_ci_sequence_number IN NUMBER ,
20   p_alias_val IN DATE ,
21   p_message_name OUT NOCOPY varchar2 )
22 RETURN DATE AS
23 /*************************************************************
24  Created By :
25  Date Created By :
26  Purpose :
27  Know limitations, enhancements or remarks
28  Change History
29  Who             When		What
30  schodava	 08-Jul-02	Bug # 2442220
31 				To improve the performance of this procedure,
32 				modified local functions calpl_holiday_resolve
33 				and calpl_inst_break_resolve.
34 				Replaced 2 complex cursors by 4 simple cursors.
35  (reverse chronological order - newest change first)
36 ***************************************************************/
37 
38 BEGIN	-- calp_clc_daio_cnstrt
39 	-- This module accepts a IGS_CA_DA_INST date value which has been derived
40 	-- from a IGS_CA_DA_OFST, attempts to resolve any dt_alias_offset_constrts
41 	-- which exist for the IGS_CA_DA_OFST and then returns the modified date
42 	-- value. Refer to S_DT_OFFSET_CONSTRAINT_TYPE table for list of valid
43 	-- constraint types.
44 DECLARE
45 	cst_must	CONSTANT	VARCHAR2(10)	:= 'MUST';
46 	cst_must_not	CONSTANT	VARCHAR2(10)	:= 'MUST NOT';
47 	cst_monday	CONSTANT	VARCHAR2(10)	:= 'MONDAY';
48 	cst_tuesday	CONSTANT	VARCHAR2(10)	:= 'TUESDAY';
49 	cst_wednesday	CONSTANT	VARCHAR2(10)	:= 'WEDNESDAY';
50 	cst_thursday	CONSTANT	VARCHAR2(10)	:= 'THURSDAY';
51 	cst_friday	CONSTANT	VARCHAR2(10)	:= 'FRIDAY';
52 	cst_saturday	CONSTANT	VARCHAR2(10)	:= 'SATURDAY';
53 	cst_sunday	CONSTANT	VARCHAR2(10)	:= 'SUNDAY';
54 	cst_week_day	CONSTANT	VARCHAR2(10)	:= 'WEEK DAY';
55 	cst_holiday	CONSTANT	VARCHAR2(10)	:= 'HOLIDAY';
56 	cst_inst_break	CONSTANT	VARCHAR2(10)	:= 'INST BREAK';
57 	cst_active	CONSTANT	VARCHAR2(10)	:= 'ACTIVE';
58 	-- replaced declarations of the following integers to PLS_INTEGER,
59 	-- from NUMBER(5), to improve the performance of the procedure.
60 	v_mod_count			PLS_INTEGER;
61 	v_constraint_count		PLS_INTEGER;
62 	v_loop_count			PLS_INTEGER;
63 	v_message_name	                VARCHAR2(30) ;
64 	v_alias_val	                IGS_CA_DA_INST.absolute_val%TYPE;
65 	---------------------------------------------------------
66 	-- Function: calpl_holiday_resolve
67 	-- This function try to resolve the constraint when the
68 	-- s_dt_alias_offset_type = 'HOLIDAY'
69 	---------------------------------------------------------
70 	FUNCTION calpl_holiday_resolve (
71 		p_s_dt_offset_cnstrt_type
72 				IGS_CA_DA_OFFCNT.S_DT_OFFSET_CONSTRAINT_TYPE%TYPE,
73 		p_cnstrt_condition			IGS_CA_DA_OFFCNT.constraint_condition%TYPE,
74 		p_cnstrt_resolution		IGS_CA_DA_OFFCNT.constraint_resolution%TYPE,
75 		p_mod_count			IN OUT NOCOPY	PLS_INTEGER,
76 		p_alias_val			IN OUT NOCOPY	DATE)
77 	RETURN varchar2
78 	AS
79 	BEGIN
80 	DECLARE
81 		v_changed		BOOLEAN;
82 		v_dummy			VARCHAR2(1);
83 		v_tmp_mod_count		PLS_INTEGER;
84 		v_tmp_alias_val		DATE;
85 		v_max_alias_val		DATE	DEFAULT NULL;
86 		v_min_alias_val		DATE	DEFAULT NULL;
87 
88 		-- Replaced cursor c_m_alias_val by 2 cursors
89 		-- c_m_alias_val1 and c_m_alias_val2.
90 		-- The cursor c_m_alias_val was using the group functions
91 		-- max and min, causing a performance issue.
92 		-- Replaced it with 2 cursors, which use and ORDER BY clause instead of a function.
93 		-- Also, included the calendar instance sequence number in the join condition
94 		-- between the dai and ci tables, to improve the performance of the cursor.
95 		-- The FK between the 2 tables is a composite one of cal_type and sequence_number.
96 
97 		CURSOR c_m_alias_val1 IS
98 			SELECT	TRUNC(dai.absolute_val)
99 			FROM	IGS_CA_DA_INST	dai,
100 				IGS_CA_INST		ci,
101 				IGS_CA_TYPE		ct,
102 				IGS_CA_STAT		cs
103 			WHERE	dai.CAL_TYPE		= ci.CAL_TYPE AND
104 				dai.ci_sequence_number  = ci.sequence_number AND
105 				ci.CAL_TYPE		= ct.CAL_TYPE	AND
106 				ct.S_CAL_CAT		= cst_holiday	AND
107 				cs.CAL_STATUS		= ci.CAL_STATUS	AND
108 				cs.s_cal_status		= cst_active
109 			ORDER BY dai.absolute_val ASC;
110 
111 		CURSOR c_m_alias_val2 IS
112 			SELECT	TRUNC(dai.absolute_val)
113 			FROM	IGS_CA_DA_INST	dai,
114 				IGS_CA_INST		ci,
115 				IGS_CA_TYPE		ct,
116 				IGS_CA_STAT		cs
117 			WHERE	dai.CAL_TYPE		= ci.CAL_TYPE AND
118 				dai.ci_sequence_number  = ci.sequence_number AND
119 				ci.CAL_TYPE		= ct.CAL_TYPE	AND
120 				ct.S_CAL_CAT		= cst_holiday	AND
121 				cs.CAL_STATUS		= ci.CAL_STATUS	AND
122 				cs.s_cal_status		= cst_active
123 			ORDER BY dai.absolute_val DESC;
124 
125 		CURSOR c_holiday (
126 				cp_alias_val		IGS_CA_DA_INST.absolute_val%TYPE) IS
127 			SELECT	'x'
128 			FROM	IGS_CA_TYPE ct
129 			WHERE	ct.S_CAL_CAT		= cst_holiday	AND
130 			EXISTS	(SELECT	'x'
131 				 FROM	IGS_CA_INST ci,
132 					IGS_CA_STAT cs
133 				WHERE	ci.CAL_TYPE = ct.CAL_TYPE	AND
134 					ci.CAL_STATUS = cs.CAL_STATUS	AND
135 					cs.s_cal_status = cst_active	AND
136 					EXISTS 	(SELECT	'x'
137 					 	 FROM	IGS_CA_DA_INST dai
138 						 WHERE	dai.CAL_TYPE = ct.CAL_TYPE	AND
139 							TRUNC(dai.absolute_val) = cp_alias_val));
140 	BEGIN
141 
142 		OPEN c_m_alias_val1;
143 		FETCH c_m_alias_val1 INTO	v_min_alias_val;
144 		CLOSE c_m_alias_val1;
145 
146 		OPEN c_m_alias_val2;
147 		FETCH c_m_alias_val2 INTO	v_max_alias_val;
148 		CLOSE c_m_alias_val2;
149 
150 
151 		IF v_max_alias_val IS NULL	AND
152 				v_min_alias_val IS NULL THEN
153 			-- No HOLIDAY date alias instances have been defined which can be resolved.
154 			IF p_cnstrt_condition = cst_must_not THEN
155 				-- constraint does not require resolving
156 				RETURN null;
157 			ELSE
158 				-- constraint cannot be resolved
159 				RETURN ('IGS_CA_HOLIDAY_CONST_UNRSLVD');
160 			END IF;
161 		ELSE
162 			IF	p_cnstrt_condition = cst_must THEN
163 				IF	(p_alias_val	> v_max_alias_val AND
164 				 	 p_cnstrt_resolution >0 ) OR
165 					(p_alias_val	< v_min_alias_val AND
166 				 	 p_cnstrt_resolution <0 ) THEN
167 					-- constraint cannot be resolved
168 					RETURN ('IGS_CA_HOLIDAY_CONS_UNRSVLD');
169 				END IF;
170 			END IF;
171 			v_tmp_alias_val := p_alias_val;
172 			v_tmp_mod_count := p_mod_count;
173 			LOOP
174 				v_changed := FALSE;
175 				OPEN c_holiday (v_tmp_alias_val);
176 				FETCH c_holiday INTO v_dummy;
177 				IF c_holiday%FOUND THEN
178 					CLOSE c_holiday;
179 					IF p_cnstrt_condition = cst_must_not THEN
180 						--update the date value and test again.
181 						v_tmp_alias_val := v_tmp_alias_val + p_cnstrt_resolution;
182 						v_tmp_mod_count := v_tmp_mod_count + 1;
183 						v_changed := TRUE;
184 					END IF;
185 				ELSE	-- record not found
186 					CLOSE c_holiday;
187 					IF p_cnstrt_condition = cst_must THEN
188 						--update the date value and test again.
189 						v_tmp_alias_val := v_tmp_alias_val + p_cnstrt_resolution;
190 						v_tmp_mod_count := v_tmp_mod_count + 1;
191 						IF	(v_tmp_alias_val	> v_max_alias_val AND
192 						 	 p_cnstrt_resolution	>0 ) OR
193 							(v_tmp_alias_val	< v_min_alias_val AND
194 						 	 p_cnstrt_resolution 	<0 ) THEN
195 							-- constraint cannot be resolved
196 							RETURN ('IGS_CA_HOLIDAY_CONS_UNRSVLD');
197 						END IF;
198 						v_changed := TRUE;
199 					END IF;
200 				END IF;
201 				EXIT WHEN v_changed = FALSE;
202 			END LOOP;
203 			-- resolve success or no resolving needed.
204 			p_alias_val := v_tmp_alias_val;
205 			p_mod_count := v_tmp_mod_count;
206 			RETURN null;
207 		END IF;
208 	EXCEPTION
209 		WHEN OTHERS THEN
210 			IF c_m_alias_val1%ISOPEN THEN
211 				CLOSE c_m_alias_val1;
212 			END IF;
213 			IF c_m_alias_val2%ISOPEN THEN
214 				CLOSE c_m_alias_val2;
215 			END IF;
216 			IF c_holiday%ISOPEN THEN
217 				CLOSE c_holiday;
218 			END IF;
219 			RAISE;
220 	END;
221 	END calpl_holiday_resolve;
222 	---------------------------------------------------------
223 	-- Function: calpl_inst_break_resolve
224 	-- This function try to resolve the constraint when the
225 	-- s_dt_alias_offset_type = 'INST BREAK'
226 	---------------------------------------------------------
227 	FUNCTION calpl_inst_break_resolve (
228 		p_s_dt_offset_cnstrt_type
229 			IGS_CA_DA_OFFCNT.S_DT_OFFSET_CONSTRAINT_TYPE%TYPE,
230 		p_cnstrt_condition			IGS_CA_DA_OFFCNT.constraint_condition%TYPE,
231 		p_cnstrt_resolution		IGS_CA_DA_OFFCNT.constraint_resolution%TYPE,
232 		p_mod_count			IN OUT NOCOPY	PLS_INTEGER,
233 		p_alias_val			IN OUT NOCOPY	DATE)
234 	RETURN varchar2
235 	AS
236 	BEGIN
237 	DECLARE
238 		v_changed		BOOLEAN;
239 		v_dummy			VARCHAR2(1);
240 		v_tmp_mod_count		PLS_INTEGER;
241 		v_tmp_alias_val		DATE;
242 		v_max_alias_val		DATE	DEFAULT NULL;
243 		v_min_alias_val		DATE	DEFAULT NULL;
244 
245 		-- Replaced cursor c_m_alias_val2 by 2 cursors
246 		-- c_m_alias_val2a and c_m_alias_val2b.
247 		-- The cursor c_m_alias_val2 was using the group functions
248 		-- max and min, causing a performance issue.
249 		-- Replaced it with 2 cursors, which use and ORDER BY clause instead of a function.
250 
251 			CURSOR c_m_alias_val2a IS
252 			SELECT	TRUNC(dai2.absolute_val)
253 			FROM	IGS_CA_DA_INST		dai1,
254 				IGS_CA_DA_INST		dai2,
255 				IGS_CA_DA_INST_PAIR	daip,
256 				IGS_CA_INST		ci,
257 				IGS_CA_TYPE		ct,
258 				IGS_CA_STAT		cs
259 			WHERE	ci.CAL_TYPE		= ct.CAL_TYPE				AND
260 				ct.S_CAL_CAT		= cst_holiday				AND
261 				cs.CAL_STATUS		= ci.CAL_STATUS				AND
262 				cs.s_cal_status		= cst_active				AND
263 				dai1.CAL_TYPE		= ci.CAL_TYPE				AND
264 				dai1.DT_ALIAS		= daip.DT_ALIAS				AND
265 				dai1.sequence_number	= daip.dai_sequence_number		AND
266 				dai1.CAL_TYPE		= daip.CAL_TYPE				AND
267 				dai1.ci_sequence_number = daip.ci_sequence_number		AND
268 				dai2.DT_ALIAS		= daip.related_dt_alias			AND
269 				dai2.sequence_number	= daip.related_dai_sequence_number	AND
270 				dai2.CAL_TYPE		= daip.related_cal_type			AND
271 				dai2.ci_sequence_number = daip.related_ci_sequence_number
272 			ORDER BY dai2.absolute_val DESC;
273 
274 			CURSOR c_m_alias_val2b IS
275 			SELECT	TRUNC(dai1.absolute_val)
276 			FROM	IGS_CA_DA_INST		dai1,
277 				IGS_CA_DA_INST		dai2,
278 				IGS_CA_DA_INST_PAIR	daip,
279 				IGS_CA_INST		ci,
280 				IGS_CA_TYPE		ct,
281 				IGS_CA_STAT		cs
282 			WHERE	ci.CAL_TYPE		= ct.CAL_TYPE				AND
283 				ct.S_CAL_CAT		= cst_holiday				AND
284 				cs.CAL_STATUS		= ci.CAL_STATUS				AND
285 				cs.s_cal_status		= cst_active				AND
286 				dai1.CAL_TYPE		= ci.CAL_TYPE				AND
287 				dai1.DT_ALIAS		= daip.DT_ALIAS				AND
288 				dai1.sequence_number	= daip.dai_sequence_number		AND
289 				dai1.CAL_TYPE		= daip.CAL_TYPE				AND
290 				dai1.ci_sequence_number = daip.ci_sequence_number		AND
291 				dai2.DT_ALIAS		= daip.related_dt_alias			AND
292 				dai2.sequence_number	= daip.related_dai_sequence_number	AND
293 				dai2.CAL_TYPE		= daip.related_cal_type			AND
294 				dai2.ci_sequence_number = daip.related_ci_sequence_number
295 			ORDER BY dai1.absolute_val ASC;
296 
297 		CURSOR c_instbreak (
298 				cp_alias_val		IGS_CA_DA_INST.absolute_val%TYPE) IS
299 			SELECT	'x'
300 			FROM	IGS_CA_TYPE ct
301 			WHERE	ct.S_CAL_CAT = cst_holiday	AND
302 			EXISTS	(SELECT	'x'
303 				 FROM	IGS_CA_INST ci,
304 					IGS_CA_STAT cs
305 				 WHERE	ci.CAL_TYPE	= ct.CAL_TYPE	AND
306 					ci.CAL_STATUS	= cs.CAL_STATUS	AND
307 					cs.s_cal_status	= cst_active	AND
308 					EXISTS	(SELECT	'x'
309 					FROM	IGS_CA_DA_INST dai1,
310 						IGS_CA_DA_INST dai2,
311 						IGS_CA_DA_INST_PAIR daip
312 					WHERE	dai1.CAL_TYPE	= ct.CAL_TYPE	AND
313 						dai1.DT_ALIAS	 = daip.DT_ALIAS    AND
314  						dai1.sequence_number	= daip.dai_sequence_number  AND
315  						dai1.CAL_TYPE	= daip.CAL_TYPE    AND
316  						dai1.ci_sequence_number	= daip.ci_sequence_number  AND
317 						dai2.DT_ALIAS	= daip.related_dt_alias   AND
318  						dai2.sequence_number	= daip.related_dai_sequence_number AND
319 	 					dai2.CAL_TYPE	= daip.related_cal_type   AND
320 						dai2.ci_sequence_number	= daip.related_ci_sequence_number AND
321 						 cp_alias_val BETWEEN TRUNC(dai1.absolute_val) AND
322 							TRUNC(dai2.absolute_val)));
323 	BEGIN
324 		OPEN c_m_alias_val2a;
325 		FETCH c_m_alias_val2a INTO v_max_alias_val;
326 		CLOSE c_m_alias_val2a;
327 
328 		OPEN c_m_alias_val2b;
329 		FETCH c_m_alias_val2b INTO v_min_alias_val;
330 		CLOSE c_m_alias_val2b;
331 
332 		IF v_max_alias_val IS NULL	AND
333 				v_min_alias_val IS NULL THEN
334 			-- No HOLIDAY date alias instances have been defined which can be resolved.
335 			IF p_cnstrt_condition = cst_must_not THEN
336 				-- constraint does not require resolving
337 				RETURN null;
338 			ELSE
339 				-- constraint cannot be resolved
340 				RETURN ('IGS_CA_INSTBREAK_CONST_UNRSLV');
341 			END IF;
342 		ELSE
343 			IF	p_cnstrt_condition = cst_must THEN
344 				IF	(p_alias_val	> v_max_alias_val AND
345 				 	 p_cnstrt_resolution >0 ) OR
346 					(p_alias_val	< v_min_alias_val AND
347 				 	 p_cnstrt_resolution <0 ) THEN
348 					-- constraint cannot be resolved
349 					RETURN ('IGS_CA_INSTBREAK_CONS_UNRSVLD');
350 				END IF;
351 			END IF;
352 			v_tmp_alias_val := p_alias_val;
353 			v_tmp_mod_count := p_mod_count;
354 			LOOP
355 				v_changed := FALSE;
356 				OPEN c_instbreak (v_tmp_alias_val);
357 				FETCH c_instbreak INTO v_dummy;
358 				IF c_instbreak%FOUND THEN
359 					CLOSE c_instbreak;
360 					IF p_cnstrt_condition = cst_must_not THEN
361 						--update the date value and test again.
362 						v_tmp_alias_val := v_tmp_alias_val + p_cnstrt_resolution;
363 						v_tmp_mod_count := v_tmp_mod_count + 1;
364 						v_changed := TRUE;
365 					END IF;
366 				ELSE	-- record not found
367 					CLOSE c_instbreak;
368 					IF p_cnstrt_condition = cst_must THEN
369 						--update the date value and test again.
370 						v_tmp_alias_val := v_tmp_alias_val + p_cnstrt_resolution;
371 						v_tmp_mod_count := v_tmp_mod_count + 1;
372 						IF	(v_tmp_alias_val	> v_max_alias_val AND
373 						 	 p_cnstrt_resolution	>0 ) OR
374 							(v_tmp_alias_val	< v_min_alias_val AND
375 						 	 p_cnstrt_resolution	<0 ) THEN
376 							-- constraint cannot be resolved
377 							RETURN ('IGS_CA_INSTBREAK_CONS_UNRSVLD');
378 						END IF;
379 						v_changed := TRUE;
380 					END IF;
381 				END IF;
382 				EXIT WHEN v_changed = FALSE;
383 			END LOOP;
384 			-- resolve success or no resolving needed.
385 			p_alias_val := v_tmp_alias_val;
386 			p_mod_count := v_tmp_mod_count;
387 			RETURN NULL;
388 		END IF;
389 	EXCEPTION
390 		WHEN OTHERS THEN
391 			IF c_m_alias_val2a%ISOPEN THEN
392 				CLOSE c_m_alias_val2a;
393 			END IF;
394 			IF c_m_alias_val2b%ISOPEN THEN
395 				CLOSE c_m_alias_val2b;
396 			END IF;
397 			IF c_instbreak%ISOPEN THEN
398 				CLOSE c_instbreak;
399 			END IF;
400 			RAISE;
401 	END;
402 	END calpl_inst_break_resolve;
403 	---------------------------------------------------------
404 	-- Procedure: calpl_constraint_resolve
405 	---------------------------------------------------------
406 	PROCEDURE calpl_constraint_resolve (
407 		p_constraint_count		IN OUT NOCOPY	PLS_INTEGER,
408 		p_mod_count			IN OUT NOCOPY	PLS_INTEGER,
409 		p_alias_val			IN OUT NOCOPY	IGS_CA_DA_INST.absolute_val%TYPE,
410 		p_message_name			OUT NOCOPY	VARCHAR2 )
411 	AS
412 	BEGIN	-- This local procedure is try to resolve the clashed constraint record.
413 	DECLARE
414 		v_msg_name			VARCHAR2(30) ;
415 		v_changed			BOOLEAN;
416 		CURSOR c_daoc IS
417 			SELECT	daoc.S_DT_OFFSET_CONSTRAINT_TYPE,
418 				daoc.constraint_condition,
419 				daoc.constraint_resolution
420 			FROM	IGS_CA_DA_INST_OFCNT	 daoc
421 			WHERE	daoc.DT_ALIAS			= p_dt_alias	AND
422 				daoc.dai_sequence_number		= p_sequence_number	AND
423 				daoc.CAL_TYPE			= p_cal_type	AND
424 				daoc.ci_sequence_number 		= p_ci_sequence_number;
425 	BEGIN
426 		v_msg_name := null;
427 		FOR v_daoc_rec IN c_daoc LOOP
428 			p_constraint_count := p_constraint_count + 1;
429 			IF v_daoc_rec.S_DT_OFFSET_CONSTRAINT_TYPE IN (	cst_monday,
430 									cst_tuesday,
431 									cst_wednesday,
432 									cst_thursday,
433 									cst_friday,
434 									cst_saturday,
435 									cst_sunday)	THEN
436 				IF v_daoc_rec.constraint_condition = cst_must	THEN
437 					-- Use an inner loop to check and resolve any clash.
438 					WHILE RTRIM(TO_CHAR(p_alias_val,'DAY')) <>
439 								v_daoc_rec.S_DT_OFFSET_CONSTRAINT_TYPE LOOP
440 						p_alias_val := p_alias_val + v_daoc_rec.constraint_resolution;
441 						p_mod_count := p_mod_count + 1;
442 					END LOOP;
443 				ELSE	-- NUST NOT
444 					-- Use an inner loop to check and resolve any clash.
445 					WHILE RTRIM(TO_CHAR(p_alias_val,'DAY')) =
446 								v_daoc_rec.S_DT_OFFSET_CONSTRAINT_TYPE LOOP
447 						p_alias_val := p_alias_val + v_daoc_rec.constraint_resolution;
448 						p_mod_count := p_mod_count + 1;
449 					END LOOP;
450 				END IF;
451 			ELSIF 	v_daoc_rec.S_DT_OFFSET_CONSTRAINT_TYPE = cst_week_day THEN
452 				IF v_daoc_rec.constraint_condition = cst_must	THEN
453 					-- Use an inner loop to check and resolve any clash.
454 					WHILE RTRIM(TO_CHAR(p_alias_val,'DAY')) NOT IN (cst_monday,
455 											cst_tuesday,
456 											cst_wednesday,
457 											cst_thursday,
458 											cst_friday) LOOP
459 						p_alias_val := p_alias_val + v_daoc_rec.constraint_resolution;
460 						p_mod_count := p_mod_count + 1;
461 					END LOOP;
462 				ELSE	-- MUST NOT
463 					-- Use an inner loop to check and resolve any clash.
464 					WHILE RTRIM(TO_CHAR(p_alias_val,'DAY')) IN (	cst_monday,
465 											cst_tuesday,
466 											cst_wednesday,
467 											cst_thursday,
468 											cst_friday) LOOP
469 						p_alias_val := p_alias_val + v_daoc_rec.constraint_resolution;
470 						p_mod_count := p_mod_count + 1;
471 					END LOOP;
472 				END IF;
473 			ELSIF	v_daoc_rec.S_DT_OFFSET_CONSTRAINT_TYPE = cst_holiday THEN
474 				-- If the constraint type is 'HOLIDAY', check that the date does not clash
475 				-- against any date alias instance values in HOLIDAY calendars if the
476 				-- condition is 'MUST NOT' or that it matches a date alias instance value
477 				-- in a HOLIDAY calendar if the condition is 'MUST'.
478 				v_msg_name := calpl_holiday_resolve (
479 									v_daoc_rec.S_DT_OFFSET_CONSTRAINT_TYPE,
480 									v_daoc_rec.constraint_condition,
481 									v_daoc_rec.constraint_resolution,
482 									p_mod_count,
483 									p_alias_val);
484 				IF v_msg_name IS NOT NULL THEN
485 					p_message_name := v_msg_name;
486 				END IF;
487 			ELSIF	v_daoc_rec.S_DT_OFFSET_CONSTRAINT_TYPE = cst_inst_break THEN
488 				--If the constraint type is 'INST BREAK', check that the date does not fall
489 				-- between the dates defined by any date alias instance pairs in HOLIDAY
490 				-- calendars if the condition is 'MUST NOT' or that it does if the
491 				-- condition is 'MUST'.
492 				-- Use an inner loop to match the date against all defined DAIP's.
493 				-- Find the start and end dates of any DAI Pair.
494 				v_msg_name := calpl_inst_break_resolve (
495 									v_daoc_rec.S_DT_OFFSET_CONSTRAINT_TYPE,
496 									v_daoc_rec.constraint_condition,
497 									v_daoc_rec.constraint_resolution,
498 									p_mod_count,
499 									p_alias_val);
500 				IF v_msg_name IS NOT NULL THEN
501 					p_message_name := v_msg_name;
502 				END IF;
503 			END IF;
504 		END LOOP;	-- daoc loop
505 	EXCEPTION
506 		WHEN OTHERS THEN
507 			IF c_daoc%ISOPEN THEN
508 				CLOSE c_daoc;
509 			END IF;
510 			RAISE;
511 	END;
512 	END calpl_constraint_resolve;
513 BEGIN
514 	-- Set default value.
515 	p_message_name := null;
516 	v_message_name := null;
517 	v_mod_count :=0;
518 	v_constraint_count := 0;
519 	v_loop_count := 0;
520 	-- 1. Check parameters
521 	IF (		p_dt_alias		IS NULL	OR
522 			p_sequence_number	IS NULL 	OR
523 			p_cal_type		IS NULL	OR
524 			p_ci_sequence_number	IS NULL	OR
525 			p_alias_val		IS NULL) THEN
526 		RETURN p_alias_val;
527 	END IF;
528 	-- 2. Check if any constraints exist for the date alias.
529 	--    If not, no further processing required.
530 	v_alias_val := TRUNC(p_alias_val);
531 	-- 3. Set counters to be used to determine if the date constraints are
532 	--    unresolvable.
533 	WHILE v_loop_count <= 10 LOOP
534 		-- 4. Use a loop to select each existiong constraint record.
535 		--    and check the constraint against the date and if a clash exists,
536 		--    attempt to resolve it.
537 		calpl_constraint_resolve (
538 					v_constraint_count,
539 					v_mod_count,
540 					v_alias_val,
541 					v_message_name);
542 		IF v_message_name IS NOT NULL THEN
543 			p_message_name := v_message_name;
544 		END IF;
545 		IF v_mod_count > 0	AND
546 				v_constraint_count > 1	THEN
547 			-- Value has been modified by a constraint, so reset the counters and loop
548 			-- through constraints again to ensure that changing the value for one
549 			-- constraint, has not caused to clash with another constraint it had
550 			-- already satisfied.
551 			v_mod_count := 0;
552 			v_constraint_count := 0;
553 			v_loop_count := v_loop_count + 1;
554 		ELSE
555 			RETURN v_alias_val;
556 		END IF;
557 	END LOOP; -- v_loop_count<=10
558 	-- Constraint is deemed unresolvable
559 	p_message_name := ('IGS_CA_ATTEMPT_TORESOLVE_FAIL');
560 	RETURN p_alias_val;
561 END;
562 END calp_clc_daio_cnstrt;
563 --
564 
565 FUNCTION calp_clc_dao_cnstrt(
566   p_dt_alias IN VARCHAR2 ,
567   p_alias_val IN DATE ,
568   p_message_name OUT NOCOPY varchar2 )
569 RETURN DATE AS
570 	gv_other_detail		VARCHAR2(255);
571 BEGIN	-- calp_clc_dao_cnstrt
572 	-- This module accepts a IGS_CA_DA_INST date value which has been derived
573 	-- from a IGS_CA_DA_OFST, attempts to resolve any dt_alias_offset_constrts
574 	-- which exist for the IGS_CA_DA_OFST and then returns the modified date
575 	-- value. Refer to S_DT_OFFSET_CONSTRAINT_TYPE table for list of valid
576 	-- constraint types.
577 DECLARE
578 	cst_must	CONSTANT	VARCHAR2(10)	:= 'MUST';
579 	cst_must_not	CONSTANT	VARCHAR2(10)	:= 'MUST NOT';
580 	cst_monday	CONSTANT	VARCHAR2(10)	:= 'MONDAY';
581 	cst_tuesday	CONSTANT	VARCHAR2(10)	:= 'TUESDAY';
582 	cst_wednesday	CONSTANT	VARCHAR2(10)	:= 'WEDNESDAY';
583 	cst_thursday	CONSTANT	VARCHAR2(10)	:= 'THURSDAY';
584 	cst_friday	CONSTANT	VARCHAR2(10)	:= 'FRIDAY';
585 	cst_saturday	CONSTANT	VARCHAR2(10)	:= 'SATURDAY';
586 	cst_sunday	CONSTANT	VARCHAR2(10)	:= 'SUNDAY';
587 	cst_week_day	CONSTANT	VARCHAR2(10)	:= 'WEEK DAY';
588 	cst_holiday	CONSTANT	VARCHAR2(10)	:= 'HOLIDAY';
589 	cst_inst_break	CONSTANT	VARCHAR2(10)	:= 'INST BREAK';
590 	cst_active	CONSTANT	VARCHAR2(10)	:= 'ACTIVE';
591 	v_mod_count			NUMBER(5);
592 	v_constraint_count		NUMBER(5);
593 	v_loop_count			NUMBER(5);
594 	v_message_name	 varchar2(30);
595 	v_alias_val	IGS_CA_DA_INST.absolute_val%TYPE;
596 	---------------------------------------------------------
597 	-- Function: calpl_holiday_resolve
598 	-- This function try to resolve the constraint when the
599 	-- s_dt_alias_offset_type = 'HOLIDAY'
600 	---------------------------------------------------------
601 	FUNCTION calpl_holiday_resolve (
602 		p_s_dt_offset_cnstrt_type
603 				IGS_CA_DA_OFFCNT.S_DT_OFFSET_CONSTRAINT_TYPE%TYPE,
604 		p_cnstrt_condition			IGS_CA_DA_OFFCNT.constraint_condition%TYPE,
605 		p_cnstrt_resolution			IGS_CA_DA_OFFCNT.constraint_resolution%TYPE,
606 		p_mod_count			IN OUT NOCOPY	NUMBER,
607 		p_alias_val			IN OUT NOCOPY	DATE)
608 	RETURN VARCHAR2
609 	AS
610 	BEGIN
611 	DECLARE
612 		v_changed		BOOLEAN;
613 		v_dummy			VARCHAR2(1);
614 		v_tmp_mod_count		NUMBER;
615 		v_tmp_alias_val		DATE;
616 		v_max_alias_val		DATE	DEFAULT NULL;
617 		v_min_alias_val		DATE	DEFAULT NULL;
618 		CURSOR c_m_alias_val IS
619 			SELECT	TRUNC(max(dai.absolute_val)), TRUNC(min(dai.absolute_val))
620 			FROM	IGS_CA_DA_INST	dai,
621 				IGS_CA_INST		ci,
622 				IGS_CA_TYPE		ct,
623 				IGS_CA_STAT		cs
624 			WHERE	ci.CAL_TYPE		= ct.CAL_TYPE	AND
625 				ct.S_CAL_CAT		= cst_holiday	AND
626 				cs.s_cal_status		= ci.CAL_STATUS	AND
627 				cs.s_cal_status		= cst_active	AND
628 				dai.CAL_TYPE		= ci.CAL_TYPE;
629 		CURSOR c_holiday (
630 				cp_alias_val		IGS_CA_DA_INST.absolute_val%TYPE) IS
631 			SELECT	'x'
632 			FROM	IGS_CA_TYPE ct
633 			WHERE	ct.S_CAL_CAT		= cst_holiday	AND
634 			EXISTS	(SELECT	'x'
635 				 FROM	IGS_CA_INST ci,
636 					IGS_CA_STAT cs
637 				WHERE	ci.CAL_TYPE	= ct.CAL_TYPE	AND
638 					ci.CAL_STATUS	= cs.CAL_STATUS	AND
639 					cs.s_cal_status	= cst_active	AND
640 					EXISTS 	(SELECT	'x'
641 					 	 FROM	IGS_CA_DA_INST dai
642 						 WHERE	dai.CAL_TYPE = ct.CAL_TYPE	AND
643 							TRUNC(dai.absolute_val)= cp_alias_val));
644 	BEGIN
645 		OPEN c_m_alias_val;
646 		FETCH c_m_alias_val INTO	v_max_alias_val,
647 						v_min_alias_val;
648 		CLOSE c_m_alias_val;
649 		IF v_max_alias_val IS NULL	AND
650 				v_min_alias_val IS NULL THEN
651 			-- No HOLIDAY date alias instances have been defined which can be resolved.
652 			IF p_cnstrt_condition = cst_must_not THEN
653 				-- constraint does not require resolving
654 				RETURN null;
655 			ELSE
656 				-- constraint cannot be resolved
657 				RETURN ('IGS_CA_HOLIDAY_CONST_UNRSLVD');
658 			END IF;
659 		ELSE
660 			IF	p_cnstrt_condition = cst_must THEN
661 				IF	(p_alias_val	> v_max_alias_val AND
662 				 	 p_cnstrt_resolution >0 ) OR
663 					(p_alias_val	< v_min_alias_val AND
664 				 	 p_cnstrt_resolution <0 ) THEN
665 					-- constraint cannot be resolved
666 					RETURN ('IGS_CA_HOLIDAY_CONS_UNRSVLD');
667 				END IF;
668 			END IF;
669 			v_tmp_alias_val := p_alias_val;
670 			v_tmp_mod_count := p_mod_count;
671 			LOOP
672 				v_changed := FALSE;
673 				OPEN c_holiday (v_tmp_alias_val);
674 				FETCH c_holiday INTO v_dummy;
675 				IF c_holiday%FOUND THEN
676 					CLOSE c_holiday;
677 					IF p_cnstrt_condition = cst_must_not THEN
678 						--update the date value and test again.
679 						v_tmp_alias_val := v_tmp_alias_val + p_cnstrt_resolution;
680 						v_tmp_mod_count := v_tmp_mod_count + 1;
681 						v_changed := TRUE;
682 					END IF;
683 				ELSE	-- record not found
684 					CLOSE c_holiday;
685 					IF p_cnstrt_condition = cst_must THEN
686 						--update the date value and test again.
687 						v_tmp_alias_val := v_tmp_alias_val + p_cnstrt_resolution;
688 						v_tmp_mod_count := v_tmp_mod_count + 1;
689 						IF	(v_tmp_alias_val	> v_max_alias_val AND
690 						 	 p_cnstrt_resolution	>0 ) OR
691 							(v_tmp_alias_val	< v_min_alias_val AND
692 						 	 p_cnstrt_resolution 	<0 ) THEN
693 							-- constraint cannot be resolved
694 							RETURN ('IGS_CA_HOLIDAY_CONS_UNRSVLD');
695 						END IF;
696 						v_changed := TRUE;
697 					END IF;
698 				END IF;
699 				EXIT WHEN v_changed = FALSE;
700 			END LOOP;
701 			-- resolve success or no resolving needed.
702 			p_alias_val := v_tmp_alias_val;
703 			p_mod_count := v_tmp_mod_count;
704 			RETURN null;
705 		END IF;
706 	EXCEPTION
707 		WHEN OTHERS THEN
708 			IF c_m_alias_val%ISOPEN THEN
709 				CLOSE c_m_alias_val;
710 			END IF;
711 			IF c_holiday%ISOPEN THEN
712 				CLOSE c_holiday;
713 			END IF;
714 			RAISE;
715 	END;
716 	END calpl_holiday_resolve;
717 	---------------------------------------------------------
718 	-- Function: calpl_inst_break_resolve
719 	-- This function try to resolve the constraint when the
720 	-- s_dt_alias_offset_type = 'INST BREAK'
721 	---------------------------------------------------------
722 	FUNCTION calpl_inst_break_resolve (
723 		p_s_dt_offset_cnstrt_type
724 			IGS_CA_DA_OFFCNT.S_DT_OFFSET_CONSTRAINT_TYPE%TYPE,
725 		p_cnstrt_condition			IGS_CA_DA_OFFCNT.constraint_condition%TYPE,
726 		p_cnstrt_resolution			IGS_CA_DA_OFFCNT.constraint_resolution%TYPE,
727 		p_mod_count			IN OUT NOCOPY	NUMBER,
728 		p_alias_val			IN OUT NOCOPY	DATE)
729 	RETURN varchar2
730 	AS
731 	BEGIN
732 	DECLARE
733 		v_changed		BOOLEAN;
734 		v_dummy			VARCHAR2(1);
735 		v_tmp_mod_count		NUMBER;
736 		v_tmp_alias_val		DATE;
737 		v_max_alias_val		DATE	DEFAULT NULL;
738 		v_min_alias_val		DATE	DEFAULT NULL;
739 		CURSOR c_m_alias_val2 IS
740 			SELECT	TRUNC(MAX(dai2.absolute_val)), TRUNC(MIN(dai1.absolute_val))
741 			FROM	IGS_CA_DA_INST		dai1,
742 				IGS_CA_DA_INST		dai2,
743 				IGS_CA_DA_INST_PAIR	daip,
744 				IGS_CA_INST		ci,
745 				IGS_CA_TYPE		ct,
746 				IGS_CA_STAT		cs
747 			WHERE	ci.CAL_TYPE		= ct.CAL_TYPE				AND
748 				ct.S_CAL_CAT		= cst_holiday				AND
749 				cs.s_cal_status		= ci.CAL_STATUS				AND
750 				cs.s_cal_status		= cst_active				AND
751 				dai1.CAL_TYPE		= ci.CAL_TYPE				AND
752 				dai1.DT_ALIAS		= daip.DT_ALIAS				AND
753 				dai1.sequence_number	= daip.dai_sequence_number		AND
754 				dai1.CAL_TYPE		= daip.CAL_TYPE				AND
755 				dai1.ci_sequence_number = daip.ci_sequence_number		AND
756 				dai2.DT_ALIAS		= daip.related_dt_alias			AND
757 				dai2.sequence_number	= daip.related_dai_sequence_number	AND
758 				dai2.CAL_TYPE		= daip.related_cal_type			AND
759 				dai2.ci_sequence_number = daip.related_ci_sequence_number;
760 		CURSOR c_instbreak (
761 				cp_alias_val		IGS_CA_DA_INST.absolute_val%TYPE) IS
762 			SELECT	'x'
763 			FROM	IGS_CA_TYPE ct
764 			WHERE	ct.S_CAL_CAT = cst_holiday	AND
765 			EXISTS	(SELECT	'x'
766 				 FROM	IGS_CA_INST ci,
767 					IGS_CA_STAT cs
768 				 WHERE	ci.CAL_TYPE	= ct.CAL_TYPE	AND
769 					ci.CAL_STATUS	= cs.CAL_STATUS	AND
770 					cs.s_cal_status	= cst_active	AND
771 					EXISTS	(SELECT	'x'
772 					FROM	IGS_CA_DA_INST dai1,
773 						IGS_CA_DA_INST dai2,
774 						IGS_CA_DA_INST_PAIR daip
775 					WHERE	dai1.CAL_TYPE	= ct.CAL_TYPE	AND
776 						dai1.DT_ALIAS	 = daip.DT_ALIAS    AND
777  						dai1.sequence_number	= daip.dai_sequence_number  AND
778  						dai1.CAL_TYPE	= daip.CAL_TYPE    AND
779  						dai1.ci_sequence_number	= daip.ci_sequence_number  AND
780 						dai2.DT_ALIAS	= daip.related_dt_alias   AND
781  						dai2.sequence_number	= daip.related_dai_sequence_number AND
782 	 					dai2.CAL_TYPE	= daip.related_cal_type   AND
783 						dai2.ci_sequence_number	= daip.related_ci_sequence_number AND
784 						 cp_alias_val BETWEEN TRUNC(dai1.absolute_val) AND
785 							TRUNC(dai2.absolute_val)));
786 	BEGIN
787 		OPEN c_m_alias_val2;
788 		FETCH c_m_alias_val2 INTO	v_max_alias_val,
789 						v_min_alias_val;
790 		CLOSE c_m_alias_val2;
791 		IF v_max_alias_val IS NULL	AND
792 				v_min_alias_val IS NULL THEN
793 			-- No HOLIDAY date alias instances have been defined which can be resolved.
794 			IF p_cnstrt_condition = cst_must_not THEN
795 				-- constraint does not require resolving
796 				RETURN null;
797 			ELSE
798 				-- constraint cannot be resolved
799 				RETURN ('IGS_CA_INSTBREAK_CONST_UNRSLV');
800 			END IF;
801 		ELSE
802 			IF	p_cnstrt_condition = cst_must THEN
803 				IF	(p_alias_val	> v_max_alias_val AND
804 				 	 p_cnstrt_resolution >0 ) OR
805 					(p_alias_val	< v_min_alias_val AND
806 				 	 p_cnstrt_resolution <0 ) THEN
807 					-- constraint cannot be resolved
808 					RETURN ('IGS_CA_INSTBREAK_CONS_UNRSVLD');
809 				END IF;
810 			END IF;
811 			v_tmp_alias_val := p_alias_val;
812 			v_tmp_mod_count := p_mod_count;
813 			LOOP
814 				v_changed := FALSE;
815 				OPEN c_instbreak (v_tmp_alias_val);
816 				FETCH c_instbreak INTO v_dummy;
817 				IF c_instbreak%FOUND THEN
818 					CLOSE c_instbreak;
819 					IF p_cnstrt_condition = cst_must_not THEN
820 						--update the date value and test again.
821 						v_tmp_alias_val := v_tmp_alias_val + p_cnstrt_resolution;
822 						v_tmp_mod_count := v_tmp_mod_count + 1;
823 						v_changed := TRUE;
824 					END IF;
825 				ELSE	-- record not found
826 					CLOSE c_instbreak;
827 					IF p_cnstrt_condition = cst_must THEN
828 						--update the date value and test again.
829 						v_tmp_alias_val := v_tmp_alias_val + p_cnstrt_resolution;
830 						v_tmp_mod_count := v_tmp_mod_count + 1;
831 						IF	(v_tmp_alias_val	> v_max_alias_val AND
832 						 	 p_cnstrt_resolution	>0 ) OR
833 							(v_tmp_alias_val	< v_min_alias_val AND
834 						 	 p_cnstrt_resolution	<0 ) THEN
835 							-- constraint cannot be resolved
836 							RETURN ('IGS_CA_INSTBREAK_CONS_UNRSVLD');
837 						END IF;
838 						v_changed := TRUE;
839 					END IF;
840 				END IF;
841 				EXIT WHEN v_changed = FALSE;
842 			END LOOP;
843 			-- resolve success or no resolving needed.
844 			p_alias_val := v_tmp_alias_val;
845 			p_mod_count := v_tmp_mod_count;
846 			RETURN null;
847 		END IF;
848 	EXCEPTION
849 		WHEN OTHERS THEN
850 			IF c_m_alias_val2%ISOPEN THEN
851 				CLOSE c_m_alias_val2;
852 			END IF;
853 			IF c_instbreak%ISOPEN THEN
854 				CLOSE c_instbreak;
855 			END IF;
856 			RAISE;
857 	END;
858 	END calpl_inst_break_resolve;
859 	---------------------------------------------------------
860 	-- Procedure: calpl_constraint_resolve
861 	---------------------------------------------------------
862 	PROCEDURE calpl_constraint_resolve (
863 		p_constraint_count		IN OUT NOCOPY	NUMBER,
864 		p_mod_count			IN OUT NOCOPY	NUMBER,
865 		p_alias_val			IN OUT NOCOPY	IGS_CA_DA_INST.absolute_val%TYPE,
866 		p_message_name			OUT NOCOPY	 varchar2)
867 	AS
868 	BEGIN	-- This local procedure is try to resolve the clashed constraint record.
869 	DECLARE
870 		v_msg_name			 VARCHAR2(30);
871 		v_changed			BOOLEAN;
872 		CURSOR c_daoc IS
873 			SELECT	daoc.S_DT_OFFSET_CONSTRAINT_TYPE,
874 				daoc.constraint_condition,
875 				daoc.constraint_resolution
876 			FROM	IGS_CA_DA_OFFCNT	 daoc
877 			WHERE	daoc.DT_ALIAS			= p_dt_alias;
878 	BEGIN
879 		v_msg_name := NULL;
880 		FOR v_daoc_rec IN c_daoc LOOP
881 			p_constraint_count := p_constraint_count + 1;
882 			IF v_daoc_rec.S_DT_OFFSET_CONSTRAINT_TYPE IN (	cst_monday,
883 									cst_tuesday,
884 									cst_wednesday,
885 									cst_thursday,
886 									cst_friday,
887 									cst_saturday,
888 									cst_sunday)	THEN
889 				IF v_daoc_rec.constraint_condition = cst_must	THEN
890 					-- Use an inner loop to check and resolve any clash.
891 					WHILE RTRIM(TO_CHAR(p_alias_val,'DAY')) <>
892 								v_daoc_rec.S_DT_OFFSET_CONSTRAINT_TYPE LOOP
893 						p_alias_val := p_alias_val + v_daoc_rec.constraint_resolution;
894 						p_mod_count := p_mod_count + 1;
895 					END LOOP;
896 				ELSE	-- NUST NOT
897 					-- Use an inner loop to check and resolve any clash.
898 					WHILE RTRIM(TO_CHAR(p_alias_val,'DAY')) =
899 								v_daoc_rec.S_DT_OFFSET_CONSTRAINT_TYPE LOOP
900 						p_alias_val := p_alias_val + v_daoc_rec.constraint_resolution;
901 						p_mod_count := p_mod_count + 1;
902 					END LOOP;
903 				END IF;
904 			ELSIF 	v_daoc_rec.S_DT_OFFSET_CONSTRAINT_TYPE = cst_week_day THEN
905 				IF v_daoc_rec.constraint_condition = cst_must	THEN
906 					-- Use an inner loop to check and resolve any clash.
907 					WHILE RTRIM(TO_CHAR(p_alias_val,'DAY')) NOT IN (cst_monday,
908 											cst_tuesday,
909 											cst_wednesday,
910 											cst_thursday,
911 											cst_friday) LOOP
912 						p_alias_val := p_alias_val + v_daoc_rec.constraint_resolution;
913 						p_mod_count := p_mod_count + 1;
914 					END LOOP;
915 				ELSE	-- MUST NOT
916 					-- Use an inner loop to check and resolve any clash.
917 					WHILE RTRIM(TO_CHAR(p_alias_val,'DAY')) IN (	cst_monday,
918 											cst_tuesday,
919 											cst_wednesday,
920 											cst_thursday,
921 											cst_friday) LOOP
922 						p_alias_val := p_alias_val + v_daoc_rec.constraint_resolution;
923 						p_mod_count := p_mod_count + 1;
924 					END LOOP;
925 				END IF;
926 			ELSIF	v_daoc_rec.S_DT_OFFSET_CONSTRAINT_TYPE = cst_holiday THEN
927 				-- If the constraint type is 'HOLIDAY', check that the date does not clash
928 				-- against any date alias instance values in HOLIDAY calendars if the
929 				-- condition is 'MUST NOT' or that it matches a date alias instance value
930 				-- in a HOLIDAY calendar if the condition is 'MUST'.
931 				v_msg_name := calpl_holiday_resolve (
932 									v_daoc_rec.S_DT_OFFSET_CONSTRAINT_TYPE,
933 									v_daoc_rec.constraint_condition,
934 									v_daoc_rec.constraint_resolution,
935 									p_mod_count,
936 									p_alias_val);
937 				IF v_msg_name IS NOT NULL THEN
938 					p_message_name := v_msg_name;
939 				END IF;
940 			ELSIF	v_daoc_rec.S_DT_OFFSET_CONSTRAINT_TYPE = cst_inst_break THEN
941 				--If the constraint type is 'INST BREAK', check that the date does not fall
942 				-- between the dates defined by any date alias instance pairs in HOLIDAY
943 				-- calendars if the condition is 'MUST NOT' or that it does if the
944 				-- condition is 'MUST'.
945 				-- Use an inner loop to match the date against all defined DAIP's.
946 				-- Find the start and end dates of any DAI Pair.
947 				v_msg_name := calpl_inst_break_resolve (
948 									v_daoc_rec.S_DT_OFFSET_CONSTRAINT_TYPE,
949 									v_daoc_rec.constraint_condition,
950 									v_daoc_rec.constraint_resolution,
951 									p_mod_count,
952 									p_alias_val);
953 				IF v_msg_name IS NOT NULL THEN
954 					p_message_name := v_msg_name;
955 				END IF;
956 			END IF;
957 		END LOOP;	-- daoc loop
958 	EXCEPTION
959 		WHEN OTHERS THEN
960 			IF c_daoc%ISOPEN THEN
961 				CLOSE c_daoc;
962 			END IF;
963 			RAISE;
964 	END;
965 	END calpl_constraint_resolve;
966 BEGIN
967 	-- Set default value.
968 	p_message_name := NULL;
969 	v_message_name := NULL;
970 	v_mod_count :=0;
971 	v_constraint_count := 0;
972 	v_loop_count := 0;
973 	-- 1. Check parameters
974 	IF (		p_dt_alias		IS NULL	OR
975 			p_alias_val		IS NULL) THEN
976 		RETURN p_alias_val;
977 	END IF;
978 	-- 2. Check if any constraints exist for the date alias.
979 	--    If not, no further processing required.
980 	IF IGS_CA_VAL_DAOC.calp_val_daoc_exist (
981 					p_dt_alias,
982 					v_message_name) = TRUE THEN
983 		RETURN p_alias_val;
984 	END IF;
985 	v_alias_val := TRUNC(p_alias_val);
986 	-- 3. Set counters to be used to determine if the date constraints are
987 	--    unresolvable.
988 	WHILE v_loop_count <= 10 LOOP
989 		-- 4. Use a loop to select each existiong constraint record.
990 		--    and check the constraint against the date and if a clash exists,
991 		--    attempt to resolve it.
992 		calpl_constraint_resolve (
993 					v_constraint_count,
994 					v_mod_count,
995 					v_alias_val,
996 					v_message_name);
997 		IF v_message_name <> 0 THEN
998 			p_message_name := v_message_name;
999 		END IF;
1000 		IF v_mod_count > 0	AND
1001 				v_constraint_count > 1	THEN
1002 			-- Value has been modified by a constraint, so reset the counters and loop
1003 			-- through constraints again to ensure that changing the value for one
1004 			-- constraint, has not caused to clash with another constraint it had
1005 			-- already satisfied.
1006 			v_mod_count := 0;
1007 			v_constraint_count := 0;
1008 			v_loop_count := v_loop_count + 1;
1009 		ELSE
1010 			RETURN v_alias_val;
1011 		END IF;
1012 	END LOOP; -- v_loop_count<=10
1013 	-- Constraint is deemed unresolvable
1014 	p_message_name := 'IGS_CA_ATTEMPT_TORESOLVE_FAIL';
1015 	RETURN p_alias_val;
1016 END;
1017 END calp_clc_dao_cnstrt;
1018 --
1019 FUNCTION CALP_CLC_DT_FROM_DA(
1020   p_cal_type IN VARCHAR2 ,
1021   p_ci_sequence_number IN NUMBER ,
1022   p_dt_alias IN VARCHAR2 ,
1023   p_message_name OUT NOCOPY VARCHAR2 )
1024 RETURN DATE AS
1025 	v_other_detail	VARCHAR(255);
1026 	v_alias_value	DATE;
1027 	v_dt_alias_offset_rec	IGS_CA_DA_OFST%ROWTYPE;
1028 	v_dt_alias_instance_rec	IGS_CA_DA_INST_V%ROWTYPE;
1029 	v_date_offset		DATE := NULL;
1030 	CURSOR	c_dt_alias_offset
1031 	IS
1032 	SELECT 	*
1033 	FROM	IGS_CA_DA_OFST
1034 	WHERE	DT_ALIAS = p_dt_alias;
1035 	CURSOR	c_dt_alias_instance
1036 	IS
1037 	SELECT 	*
1038 	FROM	IGS_CA_DA_INST_V
1039 	WHERE	DT_ALIAS = v_dt_alias_offset_rec.offset_dt_alias and
1040 		CAL_TYPE = p_cal_type and
1041 		ci_sequence_number = p_ci_sequence_number
1042 	ORDER BY 	alias_val ASC;
1043 BEGIN
1044  	BEGIN
1045 		OPEN c_dt_alias_offset;
1046 		LOOP
1047 			FETCH 	c_dt_alias_offset
1048 			INTO	v_dt_alias_offset_rec;
1049 			EXIT WHEN c_dt_alias_offset%NOTFOUND;
1050 		END LOOP;
1051 		EXCEPTION
1052 		WHEN NO_DATA_FOUND THEN
1053 			p_message_name := NULL;
1054 			v_alias_value := NULL;
1055 			RETURN v_alias_value;
1056 	END;
1057 	BEGIN
1058 		OPEN 	c_dt_alias_instance;
1059 		LOOP
1060 			FETCH 	c_dt_alias_instance
1061 			INTO	v_dt_alias_instance_rec;
1062 			EXIT;
1063 		END LOOP;
1064 		v_alias_value := v_dt_alias_instance_rec.alias_val;
1065 		IF (NVL(v_dt_alias_offset_rec.year_offset,0) <> 0) THEN
1066 			v_alias_value := add_months(v_dt_alias_instance_rec.alias_val,
1067 						   (v_dt_alias_offset_rec.year_offset * 12));
1068 		END IF;
1069 		IF (NVL(v_dt_alias_offset_rec.month_offset,0) <> 0) THEN
1070 			v_alias_value := add_months(v_alias_value,
1071 						    v_dt_alias_offset_rec.month_offset);
1072 		END IF;
1073 		IF (NVL(v_dt_alias_offset_rec.week_offset,0) <> 0) THEN
1074 			v_alias_value := v_alias_value +
1075 				        (v_dt_alias_offset_rec.week_offset * 7);
1076 		END IF;
1077 		IF (NVL(v_dt_alias_offset_rec.day_offset,0) <> 0) THEN
1078 			v_alias_value := v_alias_value +
1079 					 v_dt_alias_offset_rec.day_offset;
1080 		END IF;
1081 		CLOSE 	c_dt_alias_instance;
1082 		EXCEPTION
1083 		WHEN NO_DATA_FOUND THEN
1084 			p_message_name :='IGS_CA_DTALIAS_NOT_PRESENT';
1085 			v_alias_value := NULL;
1086 			RETURN v_alias_value;
1087 	END;
1088 	IF(c_dt_alias_offset%ISOPEN) THEN
1089 		CLOSE c_dt_alias_offset;
1090 	END IF;
1091 	IF(c_dt_alias_instance%ISOPEN) THEN
1092 		CLOSE c_dt_alias_instance;
1093 	END IF;
1094 	RETURN v_alias_value;
1095 END calp_clc_dt_from_da;
1096 --
1097 FUNCTION CALP_CLC_DT_FROM_DAI(
1098   p_ci_sequence_number IN NUMBER ,
1099   p_cal_type IN VARCHAR2 ,
1100   p_dt_alias IN VARCHAR2 ,
1101   p_dai_sequence_number IN NUMBER ,
1102   p_message_name OUT NOCOPY VARCHAR2 )
1103 RETURN DATE AS
1104 	gv_other_detail		VARCHAR2(255);
1105 BEGIN	-- calp_clc_dt_from_dai
1106 	-- Calculate a IGS_CA_DA_INST.alias_value from a
1107 	-- IGS_CA_DA_INST_OFST.
1108 DECLARE
1109 	CURSOR c_daio IS
1110 		SELECT 	daio.DT_ALIAS,
1111 			daio.dai_sequence_number,
1112 			daio.CAL_TYPE,
1113 			daio.ci_sequence_number,
1114 			daio.offset_dt_alias,
1115 			daio.offset_dai_sequence_number,
1116 			daio.offset_cal_type,
1117 			daio.offset_ci_sequence_number,
1118 			daio.day_offset,
1119 			daio.week_offset,
1120 			daio.month_offset,
1121 			daio.year_offset
1122 		FROM	IGS_CA_DA_INST_OFST daio
1123 		WHERE	daio.DT_ALIAS 			= p_dt_alias AND
1124 			daio.dai_sequence_number 	= p_dai_sequence_number AND
1125 			daio.CAL_TYPE 			= p_cal_type AND
1126 			daio.ci_sequence_number 	= p_ci_sequence_number;
1127 	v_c_daio_rec		c_daio%ROWTYPE;
1128 	CURSOR c_dai IS
1129 		SELECT 	dai.DT_ALIAS,
1130 			dai.sequence_number,
1131 			dai.CAL_TYPE,
1132 			dai.ci_sequence_number,
1133 			dai.absolute_val
1134 		FROM	IGS_CA_DA_INST	dai
1135 		WHERE	dai.DT_ALIAS 		= v_c_daio_rec.offset_dt_alias AND
1136 			dai.sequence_number 	= v_c_daio_rec.offset_dai_sequence_number AND
1137 			dai.CAL_TYPE 		= v_c_daio_rec.offset_cal_type AND
1138 			dai.ci_sequence_number 	= v_c_daio_rec.offset_ci_sequence_number;
1139 	CURSOR c_daioc IS
1140 		SELECT 	daioc.DT_ALIAS,
1141 			daioc.dai_sequence_number,
1142 			daioc.CAL_TYPE,
1143 			daioc.ci_sequence_number
1144 		FROM	IGS_CA_DA_INST_OFCNT	daioc
1145 		WHERE	daioc.DT_ALIAS 		= p_dt_alias AND
1146 			daioc.dai_sequence_number 	= p_dai_sequence_number AND
1147 			daioc.CAL_TYPE 		= p_cal_type AND
1148 			daioc.ci_sequence_number 	= p_ci_sequence_number;
1149 	v_c_dai_rec		c_dai%ROWTYPE;
1150 	v_c_daioc_rec		c_daioc%ROWTYPE;
1151 	v_alias_value		DATE DEFAULT NULL;
1152 	dt_alias_inst_offset_c_row	IGS_CA_DA_INST_OFCNT%ROWTYPE;
1153 	v_other_detail		VARCHAR(255);
1154 BEGIN
1155 	p_message_name :=NULL;
1156 	-- Find IGS_CA_DA_INST_OFST
1157 	OPEN c_daio;
1158 	FETCH c_daio INTO v_c_daio_rec;
1159 	IF (c_daio%NOTFOUND) THEN
1160 		CLOSE c_daio;
1161 		p_message_name := 'IGS_CA_NO_DATE_ALIAS';
1162 		v_alias_value := NULL;
1163 		RETURN v_alias_value;
1164 	END IF;
1165 	CLOSE c_daio;
1166 	-- Find IGS_CA_DA_INST
1167 	OPEN c_dai;
1168 	FETCH c_dai INTO v_c_dai_rec;
1169 	IF (c_dai%NOTFOUND) THEN
1170 		CLOSE c_dai;
1171 		v_alias_value := NULL;
1172 		RETURN v_alias_value;
1173 	END IF;
1174 	CLOSE c_dai;
1175 	-- Calculate alias_value
1176 	IF v_c_dai_rec.absolute_val IS NULL THEN
1177 		v_alias_value := calp_clc_dt_from_dai(
1178 				v_c_daio_rec.offset_ci_sequence_number,
1179 				v_c_daio_rec.offset_cal_type,
1180 				v_c_daio_rec.offset_dt_alias,
1181 				v_c_daio_rec.offset_dai_sequence_number,
1182 				p_message_name);
1183 	ELSE
1184 		v_alias_value := v_c_dai_rec.absolute_val;
1185 	END IF;
1186 	IF (NVL(v_c_daio_rec.year_offset,0) <> 0) THEN
1187 		v_alias_value :=
1188 		add_months(v_alias_value, (v_c_daio_rec.year_offset * 12));
1189 	END IF;
1190 	IF (NVL(v_c_daio_rec.month_offset,0) <> 0) THEN
1191 		v_alias_value :=
1192 		add_months(v_alias_value, v_c_daio_rec.month_offset);
1193 	END IF;
1194 	IF (NVL(v_c_daio_rec.week_offset,0) <> 0) THEN
1195 		v_alias_value :=
1196 		v_alias_value + (v_c_daio_rec.week_offset * 7);
1197 	END IF;
1198 	IF (NVL(v_c_daio_rec.day_offset,0) <> 0) THEN
1199 		v_alias_value :=
1200 		v_alias_value + v_c_daio_rec.day_offset;
1201 	END IF;
1202 	-- Following code relating to the resolution of offset constraints has been
1203 	-- disabled due to performance issues.
1204 	-- Test if offset constraints exist.
1205 	OPEN c_daioc;
1206 	FETCH c_daioc INTO v_c_daioc_rec;
1207 	IF (c_daioc%NOTFOUND) THEN
1208 		CLOSE c_daioc;
1209 		RETURN v_alias_value;
1210 	END IF;
1211 	CLOSE c_daioc;
1212 	-- Resolve the offset constraints.
1213 	v_alias_value := calp_clc_daio_cnstrt(
1214 				p_dt_alias,
1215 				p_dai_sequence_number,
1216 				p_cal_type,
1217 				p_ci_sequence_number,
1218 				v_alias_value,
1219 				p_message_name);
1220 	RETURN v_alias_value;
1221 EXCEPTION
1222 	WHEN OTHERS THEN
1223 		IF (c_daio%ISOPEN) THEN
1224 			CLOSE c_daio;
1225 		END IF;
1226 		IF (c_dai%ISOPEN) THEN
1227 			CLOSE c_dai;
1228 		END IF;
1229 		RAISE;
1230 END;
1231 END calp_clc_dt_from_dai;
1232 --
1233 FUNCTION CALP_CLC_WK_OF_MONTH(
1234   p_indate IN DATE )
1235 RETURN INTEGER AS
1236 BEGIN
1237 DECLARE
1238     v_first_date DATE;
1239     v_month_str VARCHAR(255);
1240     v_first_dt_str VARCHAR(255);
1241     v_first_day NUMBER;
1242     v_wk_of_month NUMBER;
1243 BEGIN
1244     -- Find out NOCOPY first date/day of this month
1245     v_month_str    := TO_CHAR(p_indate, 'MM/YYYY');
1246     v_first_dt_str := '01/' || v_month_str;
1247     v_first_date   := TO_DATE(v_first_dt_str, 'DD/MM/YYYY' );
1248     -- Get the day (number) of the week  for the first date,
1249     -- giving the offset in days for the whole month.
1250     v_first_day    := TO_NUMBER(TO_CHAR(v_first_date,'D'));
1251     v_wk_of_month  := TO_NUMBER((TO_CHAR(p_indate, 'DD') +
1252 				 v_first_day - 1) / 7);
1253     RETURN CEIL(v_wk_of_month);
1254 END;
1255 END calp_clc_wk_of_month;
1256 --
1257 FUNCTION calp_val_ci_cat(
1258   p_cal_type IN VARCHAR2 ,
1259   p_message_name OUT NOCOPY VARCHAR2)
1260 RETURN BOOLEAN AS
1261 	v_other_detail	VARCHAR2(255);
1262 	v_closed_ind	IGS_CA_TYPE.closed_ind%TYPE;
1263 	CURSOR c_get_closed_ind IS
1264 		SELECT closed_ind
1265 		FROM IGS_CA_TYPE
1266 		WHERE CAL_TYPE = p_cal_type;
1267 BEGIN
1268 	p_message_name := NULL;
1269 	OPEN c_get_closed_ind;
1270 	FETCH c_get_closed_ind INTO v_closed_ind;
1271 	IF (c_get_closed_ind%NOTFOUND) THEN
1272 		CLOSE c_get_closed_ind;
1273 		RETURN TRUE;
1274 	END IF;
1275 	CLOSE c_get_closed_ind;
1276 	IF (v_closed_ind = 'N') THEN
1277 		RETURN TRUE;
1278 	ELSE
1279 		p_message_name := 'IGS_CA_CALTYPE_CLOSED';
1280 		RETURN FALSE;
1281 	END IF;
1282 
1283 END calp_val_ci_cat;
1284 --
1285 FUNCTION CALS_CLC_DT_FROM_DAI(
1286   p_ci_sequence_number IN NUMBER ,
1287   p_cal_type IN VARCHAR2 ,
1288   p_dt_alias IN VARCHAR2 ,
1289   p_dai_sequence_number IN NUMBER )
1290 RETURN DATE AS
1291 v_message_name	VARCHAR2(30);
1292 BEGIN
1293 	RETURN calp_clc_dt_from_dai(p_ci_sequence_number,
1294 				p_cal_type,
1295 				p_dt_alias,
1296 				p_dai_sequence_number,
1297 				v_message_name);
1298 END cals_clc_dt_from_dai;
1299 --
1300 END IGS_CA_GEN_002 ;