DBA Data[Home] [Help]

PACKAGE BODY: APPS.FND_CONC_RELEASE_CLASS_UTILS

Source


1 package body FND_CONC_RELEASE_CLASS_UTILS as
2 /* $Header: AFCPCRCB.pls 120.2.12010000.2 2009/11/24 22:04:12 jtoruno ship $ */
3 
4 
5 
6 
7 -- Name
8 --  calc_specific_startdate
9 -- Purpose
10 --  Given a requested start date and the class info for a Specific schedule,
11 --  return the next date that a request should run according to this schedule.
12 --  May return null if no valid date found.
13 --
14 function calc_specific_startdate(req_sdate in date,
15                                  class_info in varchar2) return date is
16 
17   found        number;
18   offset       number;
19   temp_date    date;
20   dow          number; -- day of week 1 for Sun, 7 for Sat
21   dom          number; -- day of month between 1 to 31
22   nextdom      number;
23   weekno       number; -- no of week in month
24   moy          number; -- month of year between 1 to 12
25   datespec     boolean; -- true if some date is specified
26   dayspec      boolean; -- true if some week day is specified
27 begin
28     found := 0;
29     offset := 0;
30 
31     /* find first schedule time after sysdate then subtract a day */
32 
33     temp_date := req_sdate + floor(trunc(sysdate - req_sdate));
34 
35       -- handle 56 bits code for advance scheduling
36       if (LENGTH(class_info) = 56) then
37 
38           -- check if any of date is specified
39           -- ie if either of bit from 1 to 32 is set
40           if (SUBSTR(class_info, 1, 32) = 0) then
41               datespec := false;
42           else
43               datespec := true;
44           end if;
45 
46           -- check if any of the day is specified
47           -- ie if either of bit from 33 to 39 is set
48           if (SUBSTR(class_info, 33, 7) = 0) then
49               dayspec := false;
50           else
51               dayspec := true;
52           end if;
53       end if;
54 
55 
56     /* find next day where day of week or month is executable.
57        Day of week complexity is to avoid problems with calendars
58        where weekday numbering is different.  Nextdom is for finding
59        if its the last day of the month.  Class info in this case is a
60        bitfield: first 31 are for dom, 32 is last dom, 33-39 is dow */
61 
62    /* 8590269 - Advanced Sched for dates within a year of the current date were
63       not properly getting calculated since loop only went for 31 days from
64       current day.  offset is now avail for a full year from current date. */
65 
66     while (offset < 365) and (found = 0) loop
67       offset := offset + 1;
68       dow := MOD(trunc(TO_NUMBER(TO_CHAR(temp_date+1+offset,'J'))),7) + 1;
69       dom := TO_NUMBER(TO_CHAR(temp_date+offset,'DD'));
70       nextdom := TO_NUMBER(TO_CHAR(temp_date+1+offset,'DD'));
71 
72       -- handle 56 bits code
73       if (LENGTH(class_info) = 56) then
74       begin
75           moy := TO_NUMBER(TO_CHAR(temp_date + offset,'MM'));
76           weekno := TO_NUMBER(TO_CHAR(temp_date + offset,'W'));
77 
78           if (SUBSTR(class_info,44 + moy,1) = '1') /* if month is specified */ then
79           begin
80           -- see if there is some matching schedule
81           -- either day of month is matched OR (its last day of month and week is current week
82              if ( ((SUBSTR(class_info,dom,1) = '1') or ((SUBSTR(class_info,32,1) = '1') and (nextdom = 1)))
83              or ( (SUBSTR(class_info,dow + 32,1) = '1') and (SUBSTR(class_info,weekno + 39,1) = '1')) ) then
84                  found := 1;
85              end if;
86           end;
87           end if;
88       end;
89       else
90       -- handle 39 bits code as usual for backward compatibility
91           if (SUBSTR(class_info,dom,1) = '1') or /* if date matches */
92              ((SUBSTR(class_info,32,1) = '1') and (nextdom = 1)) or
93              (SUBSTR(class_info,dow + 32,1) = '1') then
94                   found := 1;
95           end if;
96       end if;
97     end loop;
98 
99     /* the bitfield must be all zeros...we don't have to take this abuse */
100     if found = 0 then return null;
101     else return greatest(req_sdate, temp_date + offset);
102     end if;
103 
104 end calc_specific_startdate;
105 
106 
107 -- Name
108 --  parse_named_periodic_schedule
109 -- Purpose
110 --  Given an application name and a Periodic schedule name,
111 --  return the interval, interval unit, interval type, start_date and end date
112 --  for this schedule.
113 --  Values will be null if the schedule is not found or an error occurs.
114 --
115 procedure parse_named_periodic_schedule(p_application 	 in varchar2,
116 			                p_class_name 	 in varchar2,
117                                         p_repeat_interval      out nocopy number,
118                                         p_repeat_interval_unit out nocopy varchar2,
119                                         p_repeat_interval_type out nocopy varchar2,
120                                         p_start_date           out nocopy date,
121                                         p_repeat_end           out nocopy date) is
122 
123    p_rel_class_app_id    number;
124    p_rel_class_id        number;
125 begin
126    p_repeat_interval      := null;
127    p_repeat_interval_unit := null;
128    p_repeat_interval_type := null;
129    p_repeat_end           := null;
130    p_start_date           := null;
131 
132    select a.application_id, c.release_class_id
133    into   p_rel_class_app_id, p_rel_class_id
134    from   fnd_conc_release_classes c, fnd_application a
135    where  upper(release_class_name)       = upper(p_class_name)
136    and    c.application_id                = a.application_id
137    and    a.application_short_name = upper(p_application);
138 
139    parse_periodic_schedule(p_rel_class_app_id, p_rel_class_id,
140                            p_repeat_interval,
141                            p_repeat_interval_unit,
142                            p_repeat_interval_type,
143                            p_start_date,
144                            p_repeat_end);
145 
146 
147 exception
148    when no_data_found then
149      return;
150 
151 end parse_named_periodic_schedule;
152 
153 
154 
155 -- Name
156 --  parse_periodic_schedule
157 -- Purpose
158 --  Given an application id and a Periodic schedule id,
159 --  return the interval, interval unit, interval type, start_date and end date
160 --  for this schedule.
161 --  Values will be null if the schedule is not found or an error occurs.
162 --
163 procedure parse_periodic_schedule(p_rel_class_app_id in number,
164                                   p_rel_class_id     in number,
165                                   p_repeat_interval      out nocopy number,
166                                   p_repeat_interval_unit out nocopy varchar2,
167                                   p_repeat_interval_type out nocopy varchar2,
168                                   p_start_date           out nocopy date,
169                                   p_repeat_end           out nocopy date) is
170 
171    c1            number;
172    c2            number;
173    sch_type      varchar2(1);
174    curr_info     varchar2(64);
175    req_date      date;
176    tmp_interval  number;
177 begin
178    p_repeat_interval      := null;
179    p_repeat_interval_unit := null;
180    p_repeat_interval_type := null;
181    p_repeat_end           := null;
182    p_start_date           := null;
183 
184    select class_info, class_type, date1, date2
185      into curr_info, sch_type, req_date, p_repeat_end
186      from fnd_conc_release_classes
187      where application_id = p_rel_class_app_id
188      and   release_class_id = p_rel_class_id;
189 
190    if sch_type <> 'P' then
191       return;
192    end if;
193 
194    c1 := instr(curr_info, ':', 1, 1);
195    c2 := instr(curr_info, ':', 1, 2);
196 
197    -- interval is the first field
198    p_repeat_interval := to_number(substr(curr_info, 1, (c1-1)));
199 
200    -- interval unit
201    select decode(substr(curr_info, c1+1, 1),
202                  'M', 'MONTHS', 'D', 'DAYS', 'H', 'HOURS', 'N', 'MINUTES')
203      into p_repeat_interval_unit
204      from dual;
205 
206    -- interval type
207    select decode(substr(curr_info, (c2+1), 1), 'C', 'END', 'START')
208      into p_repeat_interval_type
209      from dual;
210 
211 
212    -- now figure out the correct requested start date
213    select floor((sysdate - req_date) / DECODE(p_repeat_interval_unit,
214 		 'MINUTES', GREATEST(p_repeat_interval,1) / 1440,
215                  'HOURS', GREATEST(p_repeat_interval,1/60) / 24,
216                  'DAYS', GREATEST(p_repeat_interval,1/1440),
217                  'MONTHS', GREATEST(p_repeat_interval,1) * 31,1))
218    into tmp_interval
219    from dual;
220 
221    if (tmp_interval > 0)  then
222      select req_date +
223             DECODE(p_repeat_interval_unit,
224 		   'MINUTES', tmp_interval * GREATEST(p_repeat_interval,1) / 1440,
225                    'HOURS', tmp_interval * GREATEST(p_repeat_interval,1/60) / 24,
226                    'DAYS', tmp_interval * GREATEST(p_repeat_interval,1/1440),
227                    'MONTHS', ADD_MONTHS(req_date, tmp_interval * p_repeat_interval)-req_date,
228 		   1)
229      into req_date
230      from dual;
231    end if;
232 
233    while (req_date < sysdate) loop
234        select req_date +
235                 DECODE(p_repeat_interval_unit,
236 		 'MINUTES', GREATEST(p_repeat_interval,1) / 1440,
237                  'HOURS', GREATEST(p_repeat_interval,1/60) / 24,
238                  'DAYS', GREATEST(p_repeat_interval,1/1440),
239                  'MONTHS', ADD_MONTHS(req_date,p_repeat_interval)-req_date,
240 		 1)
241        into req_date
242        from dual;
243      end loop;
244 
245 
246    p_start_date := req_date;
247 
248 exception
249    when no_data_found then
250       null;
251 
252 end parse_periodic_schedule;
253 
254 -- Name
255 --  assign_specific_sch
256 -- Purpose
257 --  this function assigns specific schedule to a request
258 --  return true if successful
259 --  May return false if unsuccessful
260 --
261 function assign_specific_sch (req_id in number,
262                               class_info in varchar2,
263                               start_date in date,
264                               end_date in date) return boolean is
265 
266   relseqno              number;
267   relclassname          varchar2(20);
268   relclass_insert_error exception;
269   dual_no_rows	        exception;
270   dual_too_many_rows    exception;
271 
272 begin
273 
274     begin
275         Select Fnd_Conc_Release_Classes_S.nextval
276         Into relseqno
277         From Sys.Dual;
278 
279         exception
280             when no_data_found then
281                 raise dual_no_rows;
282             when too_many_rows then
283                 raise dual_too_many_rows;
284             when others then
285                 raise;
286     end;
287 
288     relclassname := 'RSRUN:0-' || TO_CHAR(relseqno);
289 
290     Insert Into fnd_conc_release_classes (application_id, release_class_id, release_class_name, owner_req_id, enabled_flag,
291     creation_date, created_by, last_update_date, last_updated_by, last_update_login, updated_flag, date1, date2, class_type,
292     class_info)
293     Values (0 , relseqno, relclassname, req_id, 'Y', Sysdate, FND_GLOBAL.conc_login_id, Sysdate,
294     FND_GLOBAL.conc_login_id, FND_GLOBAL.conc_login_id, 'N', start_date, end_date, 'S', class_info);
295 
296     if (sql%rowcount = 0) then
297         raise relclass_insert_error;
298     end if;
299 
300     INSERT INTO Fnd_Conc_Release_Classes_TL (application_id, release_class_id, language, source_lang,
301     user_release_class_name,last_update_date, last_updated_by, last_update_login, creation_date, created_by)
302     Select 0, relseqno, L.LANGUAGE_CODE, userenv('LANG'), relclassname,
303     Sysdate, FND_GLOBAL.conc_login_id, FND_GLOBAL.conc_login_id, Sysdate, FND_GLOBAL.conc_login_id from FND_LANGUAGES L
304     where L.INSTALLED_FLAG in ('I', 'B');
305 
306     if (sql%rowcount = 0) then
307         raise relclass_insert_error;
308     end if;
309 
310     -- modify FND_CONCURRENT_REQUESTS to set the release class id for this request
311     update Fnd_Concurrent_Requests set release_class_id=relseqno, release_class_app_id=0 where request_id=req_id;
312 
313     if (sql%rowcount = 0) then
314         raise relclass_insert_error;
315     end if;
316 
317     return (true);
318 
319     exception
320     when relclass_insert_error then
321         fnd_message.set_name ('FND', 'CONC-RelClass insert failed');
322         fnd_message.set_token ('APPLICATION', 0, FALSE);
323         fnd_message.set_token ('CLASS', relseqno, FALSE);
324         return (false);
325     when dual_no_rows then
326         fnd_message.set_name ('FND', 'No Rows in Dual');
327         return (false);
328     when dual_too_many_rows then
329         fnd_message.set_name ('FND', 'Too many rows in Dual');
330         return (false);
331     when others then
332         fnd_message.set_name ('FND', 'SQL-Generic error');
333         fnd_message.set_token ('ERRNO', sqlcode, FALSE);
334         fnd_message.set_token ('REASON', sqlerrm, FALSE);
338 end assign_specific_sch;
335         fnd_message.set_token ('ROUTINE', 'assign_specific_sch: others', FALSE);
336         return (false);
337 
339 
340 
341 end FND_CONC_RELEASE_CLASS_UTILS;