DBA Data[Home] [Help]

PACKAGE BODY: APPS.AR_BFB_UTILS_PVT

Source


1 package body ar_bfb_utils_pvt as
2 /* $Header: ARBFBUTB.pls 120.10.12010000.6 2008/12/11 20:54:35 mraymond ship $ */
3 
4 /* Global table definitions */
5   TYPE l_trx_id_type IS TABLE OF ra_customer_trx_all.customer_trx_id%type
6         INDEX BY BINARY_INTEGER;
7   TYPE l_term_id_type IS TABLE OF ra_customer_trx_all.term_id%type
8         INDEX BY BINARY_INTEGER;
9 
10 PG_DEBUG varchar2(1) := NVL(FND_PROFILE.value('AFLOG_ENABLED'), 'N');
11 
12  FUNCTION ar_day_of_week( the_date in date ) return number  is
13  m number ;
14  y number ;
15  d number;
16  l_dow NUMBER;
17 
18  begin
19 
20  select to_char(the_date, 'MM' ) - 3 into m from dual;
21  select to_char(the_date, 'YYYY' ) into y from dual;
22  select to_char(the_date, 'DD' ) into d from dual;
23 
24     if ( m < 0 ) then
25       m := m + 12;
26       y := y - 1;
27     end if;
28 
29     l_dow :=   1 +
30                   ( d + floor( ( 19 + 31 * m ) / 12 ) +
31                     y + floor(y/4) - floor(y/100) + floor(y/400) ) mod 7 ;
32 
33  return l_dow;
34  END ar_day_of_week;
35 
36 
37 function get_billing_date (p_billing_cycle_id IN NUMBER,
38                            p_billing_date     IN DATE
39                            ) RETURN DATE IS
40 
41 l_billing_date DATE;
42 
43 BEGIN
44 
45    -- passed in p_billing_date is a valid date, use it
46    --Modified the logic to pick start_date when billing_date passed is less than start_date
47   select min(trunc(billable_date))
48    into l_billing_date
49   from ar_cons_bill_cycles_b cy,
50        ar_cons_bill_cycle_dates cyd
51   where cy.billing_cycle_id = p_billing_cycle_id
52     and cy.billing_cycle_id = cyd.billing_cycle_id
53     and cyd.billable_date
54          between trunc(greatest(nvl(p_billing_date,sysdate), nvl(cy.START_DATE, sysdate)))
55            and (trunc(greatest(nvl(p_billing_date,sysdate), nvl(cy.START_DATE, sysdate)))  + decode(cy.cycle_frequency,
56                                        'DAILY',   1*nvl(cy.REPEAT_DAILY,0),
57                                        'WEEKLY',  7*nvl(cy.REPEAT_WEEKLY,0),
58                                        'MONTHLY', 31*nvl(cy.REPEAT_MONTHLY,0),
59                                        0));
60    return l_billing_date;
61 
62 EXCEPTION
63 WHEN NO_DATA_FOUND THEN
64 
65    l_billing_date := null;
66 
67    return l_billing_date;
68 
69 END get_billing_date;
70 
71 function get_bill_process_date (p_billing_cycle_id IN NUMBER,
72                                 p_billing_date     IN DATE,
73                                 p_last_bill_date     IN DATE DEFAULT sysdate
74                              ) RETURN DATE IS
75 
76 l_billing_date DATE;
77 
78 BEGIN
79 
80  if p_billing_date > nvl(p_last_bill_date, sysdate) then
81    select max(billable_date)
82    into   l_billing_date
83    from   ar_cons_bill_cycle_dates
84    where  billing_cycle_id = p_billing_cycle_id
85    and    billable_date between  trunc(p_last_bill_date) and trunc(p_billing_date);
86  else
87    select max(billable_date)
88    into   l_billing_date
89    from   ar_cons_bill_cycle_dates
90    where  billing_cycle_id = p_billing_cycle_id
91    and    billable_date between trunc(p_billing_date) and trunc(p_last_bill_date);
92  end if;
93 
94    return l_billing_date;
95 END;
96 
97 -- checks if entered date is a valid billing date
98 function is_valid_billing_date(p_billing_cycle_id IN NUMBER,
99                                p_entered_date IN DATE) RETURN VARCHAR2 IS
100 BEGIN
101 
102 return('Y');
103 
104 
105 END;
106 
107 function get_due_date ( p_billing_date in DATE,
108                         p_payment_term_id in NUMBER) RETURN DATE IS
109 
110 dued     NUMBER;
111 duedom   NUMBER;
112 duemf    NUMBER;
113 due_date  DATE;
114 l_char_date varchar2(30);
115 begin
116 
117   select due_days,
118          due_day_of_month,
119          due_months_forward
120     into dued,
121          duedom,
122          duemf
123     from ra_terms_lines
124    where term_id = p_payment_term_id;
125 
126   if dued is not null then
127      due_date := p_billing_date + dued;
128   elsif duedom is not null then
129    -- if duedom is greater than last day of that month, change it to last day.
130        if duedom > to_number(substr(to_char(last_day(p_billing_date),'DD/MM/YYYY'),1,2)) then
131         duedom := to_number(substr(to_char(last_day(p_billing_date),'DD/MM/YYYY'),1,2));
132        end if;
133 
134      l_char_date := substr(to_char(p_billing_date,'MM/DD/YYYY'),1,3) ||
135                          duedom || substr(to_char(p_billing_date,'MM/DD/YYYY'),6,5);
136      due_date := to_date(l_char_date,'MM/DD/YYYY');
137      due_date := add_months(due_date, duemf);
138   end if;
139 
140   return due_date;
141 end;
142 
143 function is_payment_term_bfb( p_payment_term_id  IN NUMBER) RETURN VARCHAR2 IS
144 
145 bill_cycle_id NUMBER;
146 
147 BEGIN
148 
149    select billing_cycle_id
150      into bill_cycle_id
151      from ra_terms
152     where term_id = p_payment_term_id;
153 
154    if bill_cycle_id is not null then
155       RETURN 'Y';
156    else
157       RETURN 'N';
158    end if;
159 
160 EXCEPTION
161 WHEN NO_DATA_FOUND THEN
162    RETURN 'N';
163 END is_payment_term_bfb;
164 
165 /* Overloaded function, parameter passed in is NAME instead of ID */
166 function is_payment_term_bfb( p_payment_term_name  IN VARCHAR2) RETURN VARCHAR2 IS
167 
168 bill_cycle_id NUMBER;
169 
170 BEGIN
171 
172    select billing_cycle_id
173      into bill_cycle_id
174      from ra_terms
175     where name = p_payment_term_name;
176 
177    if bill_cycle_id is not null then
178       RETURN 'Y';
179    else
180       RETURN 'N';
181    end if;
182 
183 EXCEPTION
184 WHEN NO_DATA_FOUND THEN
185    RETURN 'N';
186 END is_payment_term_bfb;
187 
188 function get_bill_level( p_cust_account_id IN NUMBER,
189                          p_site_use_id     IN NUMBER DEFAULT NULL) RETURN VARCHAR2 IS
190 
191 bfb_level      VARCHAR2(1);
192 BEGIN
193 
194    -- the cons_bill_level is driven by the value at the account level profile
195    select decode(cp.cons_bill_level,'ACCOUNT','A','SITE','S','N')
196      into bfb_level
197      from hz_customer_profiles cp
198     where cp.cust_account_id = p_cust_account_id
199       and cp.site_use_id IS NULL;
200 
201    return bfb_level;
202 
203 EXCEPTION
204 WHEN NO_DATA_FOUND THEN
205    return 'N';
206 END get_bill_level;
207 
208 function get_billing_cycle (p_payment_term_id in NUMBER) RETURN NUMBER IS
209 
210 bill_cycle_id NUMBER;
211 BEGIN
212 
213    select billing_cycle_id
214      into bill_cycle_id
215      from ra_terms
216     where term_id = p_payment_term_id;
217 
218    return bill_cycle_id;
219 EXCEPTION
220 WHEN NO_DATA_FOUND THEN
221    return 0;
222 END get_billing_cycle;
223 
224 function get_cycle_type (p_bill_cycle_id IN NUMBER) RETURN VARCHAR2 IS
225 
226 cycle_type VARCHAR2(30);
227 
228 BEGIN
229 
230    select bill_cycle_type
231      into cycle_type
232      from ar_cons_bill_cycles_b
233     where billing_cycle_id = p_bill_cycle_id;
234 
235    return cycle_type;
236 EXCEPTION
237 WHEN NO_DATA_FOUND THEN
238    return null;
239 END get_cycle_type;
240 
241 function get_open_rec(p_cust_trx_type_id IN NUMBER) RETURN VARCHAR2 IS
242 
243 open_rec VARCHAR2(1);
244 BEGIN
245    select nvl(accounting_affect_flag,'Y')
246      into open_rec
247      from ra_cust_trx_types
248     where cust_trx_type_id = p_cust_trx_type_id;
249 
250    return open_rec;
251 EXCEPTION
252 WHEN NO_DATA_FOUND THEN
253    return 'Y';
254 END get_open_rec;
255 
256 
257 function get_default_term( p_trx_type_id      IN NUMBER,
258                            p_trx_date         IN DATE,
259                            p_org_id           IN NUMBER,
260                            p_bill_to_site     IN NUMBER,
261                            p_bill_to_customer IN NUMBER) RETURN NUMBER IS
262 
263 l_default_term NUMBER;
264 BEGIN
265 
266    select nvl(su.payment_term_id,
267                decode(spt.billing_cycle_id,
268                       -- if cycle is NULL
269                       NULL, nvl(sp.standard_terms,
270                                 decode(apt.billing_cycle_id,
271                                        -- if cycle is NULL
272                                        NULL, nvl(nvl(ap.standard_terms, tt.default_term) , -94) ,
273                                        -- if cycle is NOT NULL
274                                        -92)),
275                       -- if cycle is NOT NULL
276                       decode(ap.cons_bill_level,
277                              -- if bill level = Account
278                              'ACCOUNT', nvl(ap.standard_terms, -93),
279                              -- if bill level = Site
280                              'SITE', nvl(nvl(sp.standard_terms, ap.standard_terms), -95)
281                              -- if bill level is not set
282                              , -91)))
283    into   l_default_term
284    from   ra_cust_trx_types     tt,
285           hz_customer_profiles  ap,
286           hz_customer_profiles  sp,
287           hz_cust_site_uses     su,
288           ra_terms_b            apt,
289           ra_terms_b            spt
290    where  p_trx_type_id = tt.cust_trx_type_id
291    and    p_org_id = tt.org_id
292    and    p_bill_to_site = su.site_use_id
293    and    p_bill_to_customer = ap.cust_account_id
294    and    ap.site_use_id is null
295    and    p_bill_to_customer = sp.cust_account_id (+)
296    and    su.site_use_id = sp.site_use_id (+)
297    and    ap.standard_terms = apt.term_id (+)
298    and    sysdate between nvl(apt.start_date_active, sysdate) and
299           nvl(apt.end_date_active, sysdate)
300    and    sp.standard_terms = spt.term_id (+)
301    and    sysdate between nvl(spt.start_date_active, sysdate) and
302           nvl(spt.end_date_active, sysdate);
303 
304 return l_default_term;
305 
306 END get_default_term;
307 
308 /* Procedure that bulk updates the term_ids on imported transactions
309    using the predefined algorithm for BFB/ECBI.  Takes a request
310    ID in and processes all invoices in that request batch.  Also
311    inserts errors into ra_interface_errors for those situations
312    where the term is in conflict with the setups */
313 
314 PROCEDURE validate_and_default_term( p_request_id     IN NUMBER,
315                                      p_error_count  IN OUT NOCOPY NUMBER)
316 IS
317 
318 CURSOR c_terms(p_request_id NUMBER) IS
319 select
320     decode(invt.billing_cycle_id,
321            NULL, decode(decode(ap.cons_bill_level,'SITE',sp.override_terms,ap.override_terms),
322                         'Y',  trx.term_id,
323                         nvl(su.payment_term_id,
324                             decode(spt.billing_cycle_id,
325                                    NULL, nvl(sp.standard_terms,
326                                              decode(apt.billing_cycle_id,
327                                                NULL, nvl(nvl(ap.standard_terms, tt.default_term) , -94),
328                                                -92)),
329                                    decode(ap.cons_bill_level,
330                                           'ACCOUNT', nvl(ap.standard_terms, -93),
331                                           'SITE', nvl(nvl(sp.standard_terms, ap.standard_terms), -95),
332                                           -91)))),
333            nvl(su.payment_term_id,
334                decode(spt.billing_cycle_id,
335                       NULL, nvl(sp.standard_terms,
336                                 decode(apt.billing_cycle_id,
337                                        NULL, nvl(nvl(ap.standard_terms, tt.default_term) , -94) ,
338                                        -92)),
339                       decode(ap.cons_bill_level,
340                              'ACCOUNT', nvl(ap.standard_terms, -93),
341                              'SITE', nvl(nvl(sp.standard_terms, ap.standard_terms), -95)
342                              , -91))))  new_term_id, trx.customer_trx_id
343 from   ra_customer_trx       trx,
344        ra_cust_trx_types     tt,
345        hz_customer_profiles  ap,
346        hz_customer_profiles  sp,
347        hz_cust_site_uses     su,
348        ra_terms_b            sut,
349        ra_terms_b            apt,
350        ra_terms_b            spt,
351        ra_terms_b            ttt,
352        ra_terms_b            invt
353 where  trx.request_id = p_request_id
354 and    trx.previous_customer_trx_id IS NULL -- invoices only
355 and    trx.term_id = invt.term_id
356 and    trx.cust_trx_type_id = tt.cust_trx_type_id
357 and    trx.org_id = tt.org_id
358 and    tt.default_term = ttt.term_id (+)
359 and    trx.trx_date between nvl(ttt.start_date_active, trx.trx_date) and
360                             nvl(ttt.end_date_active,   trx.trx_date)
361 and    trx.bill_to_site_use_id = su.site_use_id
362 and    su.payment_term_id = sut.term_id (+)
363 and    trx.trx_date between nvl(sut.start_date_active, trx.trx_date) and
364                             nvl(sut.end_date_active,   trx.trx_date)
365 and    trx.bill_to_customer_id = ap.cust_account_id
366 and    ap.site_use_id is null
367 and    NVL(ap.cons_inv_flag, 'N') = 'Y' -- 7575555
368 and    trx.bill_to_customer_id = sp.cust_account_id (+)
369 and    trx.bill_to_site_use_id = sp.site_use_id (+)
370 and    ap.standard_terms = apt.term_id (+)
371 and    trx.trx_date between nvl(apt.start_date_active, trx.trx_date) and
372                             nvl(apt.end_date_active,   trx.trx_date)
373 and    sp.standard_terms = spt.term_id (+)
374 and    trx.trx_date between nvl(spt.start_date_active, trx.trx_date) and
375                             nvl(spt.end_date_active,   trx.trx_date);
376 
377   t_trx_id          l_trx_id_type;
378   t_term_id         l_term_id_type;
379 
380   l_rows_selected   number;
381   l_rows_processed  number;
382   l_rows_rejected   number;
383   l_rows_updated    number;
384   l_msg_91          fnd_new_messages.message_text%type;
385   l_msg_92          fnd_new_messages.message_text%type;
386   l_msg_93          fnd_new_messages.message_text%type;
387   l_msg_94          fnd_new_messages.message_text%type;
388   l_msg_95          fnd_new_messages.message_text%type;
389 BEGIN
390   IF PG_DEBUG in ('Y', 'C') THEN
391      arp_standard.debug('ar_bfb_utils_pvt.validate_and_default_term()+');
392      arp_standard.debug('  request_id = ' || p_request_id);
393   END IF;
394 
395   /* Fetch rows (transactions) for processing */
396   /* 7575555 - we now only fetch records where the account-level cons_inv_flag = Y.
397      others are skipped (not defaulted at all).  In general, a transaction must
398      have a term assigned to it long before this code executes. */
399   OPEN c_terms(p_request_id);
400      FETCH c_terms BULK COLLECT INTO
401                              t_term_id,
402                              t_trx_id;
403 
404      l_rows_selected := c_terms%ROWCOUNT;
405 
406   CLOSE c_terms;
407 
408   IF l_rows_selected > 0
409   THEN
410      /* Process what we've got */
411      IF PG_DEBUG in ('Y', 'C') THEN
412         arp_standard.debug('  rows selected = ' || l_rows_selected);
413      END IF;
414 
415      /* Bulk update of transaction terms
416         NOTE:  This excludes those in error or null */
417      FORALL i IN t_trx_id.FIRST..t_trx_id.LAST
418         UPDATE ra_customer_trx trx
422 
419            SET term_id             = t_term_id(i)
420          WHERE trx.customer_trx_id = t_trx_id(i)
421            AND NVL(t_term_id(i), -99) > 0;
423      l_rows_processed := SQL%ROWCOUNT;
424 
425      /* Now, for those that we didn't process because they
426         were in error, we need to insert the correct error
427         message into RA_INTERFACE_ERRORS */
428      IF NVL(l_rows_processed,0) < l_rows_selected
429      THEN
430         /* Get error messages for bulk insert */
431         fnd_message.set_name('AR', 'AR_BFB_TERM_BILL_LEVEL_NULL');
432         l_msg_91 := fnd_message.get;
433         fnd_message.set_name('AR', 'AR_BFB_TERM_BILL_LEVEL_WRONG');
434         l_msg_92 := fnd_message.get;
435         fnd_message.set_name('AR', 'AR_BFB_TERM_MISSING_AT_ACCT');
436         l_msg_93 := fnd_message.get;
437         fnd_message.set_name('AR', 'AR_BFB_TERM_NO_DEFAULT');
438         l_msg_94 := fnd_message.get;
439         fnd_message.set_name('AR', 'AR_BFB_TERM_NO_BFB_DEFAULT');
440         l_msg_95 := fnd_message.get;
441 
442         /* process the errors */
443         FORALL err IN t_trx_id.FIRST..t_trx_id.LAST
444            INSERT into RA_INTERFACE_ERRORS
445              (interface_line_id,
446               message_text,
447               org_id)
448            SELECT line.customer_trx_line_id,
449                   DECODE(t_term_id(err),
450                       -91,l_msg_91,
451                       -92,l_msg_92,
452                       -93,l_msg_93,
453                       -94,l_msg_94,
454                       -95,l_msg_95),
455                   line.org_id
456            FROM  RA_CUSTOMER_TRX_LINES line
457            WHERE line.customer_trx_id = t_trx_id(err)
458            AND   t_term_id(err) < 0;
459 
460        l_rows_rejected := SQL%ROWCOUNT;
461      END IF;
462   ELSE
463      /* Nothing to process */
464      IF PG_DEBUG in ('Y', 'C') THEN
465           arp_standard.debug('  NO ROWS TO PROCESS');
466      END IF;
467   END IF;
468 
469   p_error_count := l_rows_rejected;
470 
471   IF PG_DEBUG in ('Y', 'C') THEN
472      arp_standard.debug('  rows processed = ' || l_rows_updated);
473      arp_standard.debug('  rows rejected  = ' || l_rows_rejected);
474      arp_standard.debug('ar_bfb_utils_pvt.validate_and_default_term()-');
475   END IF;
476 
477 END validate_and_default_term;
478 
479 PROCEDURE POPULATE(p_billing_cycle_id IN NUMBER) IS
480 
481  /* ----Number of Years Billing dates will be generated for ---*/
482  l_years_to_process  NUMBER := 10;
483 
484  l_billing_month_year varchar2(50);
485  trxday   NUMBER;
486  trxmo    NUMBER;
487  billday  NUMBER;
488  bill_date DATE;
489  i  number;
490  k number;
491  l_current_date date;
492  l_billing_week number;
493  l_start_date date;
494  l_cycle_frequency varchar2(30);
495  l_next_billing_date date;
496  l_last_day varchar2(1);
497  l_month_days varchar2(10);
498  l_repeat_frequency number;
499  l_skip_weekends varchar2(1);
500  l_last_billed_date date;
501  l_billing_month varchar2(20);
502  l_billing_year  varchar2(20);
503 
504  l_day_type   varchar2(1);
505  l_char_date1   varchar2(30);
506  l_mon_day_of_week varchar2(30);
507  l_last_day_month_insert_flag varchar2(1); -- Added for Bug 7476810
508  TYPE day_tab_type IS TABLE OF VARCHAR2(1) INDEX BY BINARY_INTEGER;
509  daytab   day_tab_type;
510 
511  TYPE week_tab_type IS TABLE OF VARCHAR2(1) INDEX BY BINARY_INTEGER;
512  week_tab   week_tab_type;
513 
514 BEGIN
515 
516   ------------------------------------------------
517   ---Look at billing cycle ID and find the type
518   ------------------------------------------------
519   select cycle_frequency ,
520          decode(cycle_frequency, 'MONTHLY', repeat_monthly ,
521                                  'WEEKLY', repeat_weekly,
522                                  'DAILY', repeat_daily ) repeat_frequency,
523          skip_weekends,
524          day_type,
525          trunc(start_date)
526   into l_cycle_frequency ,
527        l_repeat_frequency , l_skip_weekends, l_day_type,l_start_date
528   from ar_cons_bill_cycles_b
529   where billing_cycle_id = p_billing_cycle_id;
530 
531 
532  ------------------------------------------------
533  ---DAILY
534  ------------------------------------------------
535  IF l_cycle_frequency = 'DAILY' THEN
536 
537    l_next_billing_date := l_start_date;
538 
539    loop
540 
541       ------------------------------------------------
542       ---Skip weekends flag is Y
543       ------------------------------------------------
544       if  l_skip_weekends  = 'Y' THEN
545 
546          if ar_day_of_week(l_next_billing_date) = 6  then
547             l_next_billing_date := l_next_billing_date + 2;
548          elsif
549              ar_day_of_week(l_next_billing_date) = 7 THEN
550              l_next_billing_date := l_next_billing_date + 1;
551          end if;
552 
553      end if;
554 
555     --------------------------------------------------------
556      --Exit if required years processed
557     --------------------------------------------------------
561      end if;
558 
559      if  l_next_billing_date  >= trunc( l_start_date + 365*l_years_to_process) then
560          exit;
562 
563     --------------------------------------------------------
564      --Insert the Bill Date in the table
565     --------------------------------------------------------
566       INSERT INTO AR_CONS_BILL_CYCLE_DATES (
567                   BILLING_CYCLE_ID ,
568                   BILLABLE_DATE    ,
569                   CREATED_BY       ,
570                   CREATION_DATE    ,
571                   LAST_UPDATE_LOGIN,
572                   LAST_UPDATE_DATE ,
573                   LAST_UPDATED_BY  )
574              values
575                 ( p_billing_cycle_id,
576                   l_next_billing_date,
577                   fnd_global.user_id,
578                   sysdate,
579                   fnd_global.user_id,
580                   sysdate,
581                   fnd_global.user_id);
582 
583     l_next_billing_date :=  l_next_billing_date + l_repeat_frequency  ;
584    end loop;
585 
586 
587 
588  --------------------------------------------------------
589  --WEEKLY
590  --------------------------------------------------------
591  ELSIF l_cycle_frequency = 'WEEKLY' THEN
592 
593   /* Logic for populating the Billing Date for a Weekly Billing Cycle has been modified as per the Bug-7139182 to extend the validation for 'saturday' and 'sunday' */
594 
595   l_current_date := l_start_date;
596 
597   select day_monday, day_tuesday, day_wednesday, day_thursday, day_friday, day_saturday, day_sunday
598   into week_tab(2), week_tab(3), week_tab(4), week_tab(5), week_tab(6),week_tab(7),week_tab(1)
599   from AR_CONS_BILL_CYCLES_B
600   where billing_cycle_id = p_billing_cycle_id;
601 
602   k := to_char(l_current_date,'D'); -- This variable is used to index for the start date of the Billing Cycle
603 	                            -- k=1 indicates 'Sunday' and k=7 indicates 'Saturday'
604   i := 1; -- This variable is used to check if seven consecutive days have been passed
605 
606  loop
607 
608   if week_tab(k) = 'Y' then
609     l_next_billing_date := l_current_date;
610 
611      --------------------------------------------------------
612      --Exit if required years processed
613     --------------------------------------------------------
614     if (l_next_billing_date > (l_start_date + 365*l_years_to_process)) then
615          exit;
616     end if;
617 
618      --------------------------------------------------------
619      --Insert the Bill Date in the table
620      --------------------------------------------------------
621     INSERT INTO AR_CONS_BILL_CYCLE_DATES (
622                   BILLING_CYCLE_ID ,
623                   BILLABLE_DATE    ,
624                   CREATED_BY       ,
625                   CREATION_DATE    ,
626                   LAST_UPDATE_LOGIN,
627                   LAST_UPDATE_DATE ,
628                   LAST_UPDATED_BY  )
629      values
630                 ( p_billing_cycle_id,
631                   l_next_billing_date,
632                   fnd_global.user_id,
633                   sysdate,
634                   fnd_global.user_id,
635                   sysdate,
636                   fnd_global.user_id);
637      end if;
638 
639   k :=k+1;
640   i :=i+1;
641 
642     if k = 8 then
643      k := 1;
644     end if;
645 
646      ----------------------------------------------------------------------------------------------------
647      --  Moving the date forward depending upon the 'Repeat Frequency' selected for the Billing Cycle.
648      ----------------------------------------------------------------------------------------------------
649 
650     if i = 8 then
651       l_current_date := l_current_date + (l_repeat_frequency-1)*7;
652       i := 1;
653     end if;
654 
655    l_current_date := l_current_date + 1;
656 
657   end loop;
658 
659  --------------------------------------------------------
660  --MONTHLY
661  --------------------------------------------------------
662  ELSIF l_cycle_frequency = 'MONTHLY' THEN
663 
664    i := 0;
665    loop
666      i := i + 1;
667      if i = 1 then
668           l_billing_month_year :=   to_char(l_start_date, 'MM/RRRR' );
669           l_billing_month :=   to_char(l_start_date, 'MM' );
670           l_billing_year :=   to_char(l_start_date, 'RRRR' );
671      else
672          l_char_date1 := '01/'||l_billing_month_year;
673 
674          l_billing_month_year :=
675                 to_char(add_months(to_date(l_char_date1,
676                              'DD/MM/RRRR'),l_repeat_frequency), 'MM/RRRR');
677           l_billing_month :=
678                to_char(to_date(l_char_date1, 'DD/MM/RRRR'),'MM');
679           l_billing_year :=
680               to_char(to_date(l_char_date1,'DD/MM/RRRR'),'RRRR');
681 
682     end if;
683 
684     l_month_days := to_char(LAST_DAY(to_date('01/'||l_billing_month_year,'DD/MM/RRRR')),'DD');
685     /* Bug 7476810. Initializing the variable l_last_day_month_insert_flag each
686        time to 'N' at the start of the new month */
687     l_last_day_month_insert_flag := 'N';
688     --------------------------------------------------------
689      --Exit if required years processed
690     --------------------------------------------------------
691     if (l_start_date + 365*l_years_to_process)
692              < to_date('01/'||l_billing_month_year,'DD/MM/RRRR') then
693       exit;
694     end if;
695 
696    --------------------------------------------------------
697      --Get the Billing Day
698    --------------------------------------------------------
699    select day_1, day_2, day_3, day_4, day_5,
700           day_6, day_7, day_8, day_9, day_10,
701           day_11, day_12, day_13, day_14, day_15,
702           day_16, day_17, day_18, day_19, day_20,
703           day_21, day_22, day_23, day_24, day_25,
704           day_26, day_27, day_28, day_29, day_30, day_31, last_day
705    into daytab(1), daytab(2), daytab(3), daytab(4), daytab(5),
706         daytab(6), daytab(7), daytab(8), daytab(9), daytab(10),
707         daytab(11), daytab(12), daytab(13), daytab(14), daytab(15),
708         daytab(16), daytab(17), daytab(18), daytab(19), daytab(20),
709         daytab(21), daytab(22), daytab(23), daytab(24), daytab(25),
710         daytab(26), daytab(27), daytab(28), daytab(29), daytab(30), daytab(31),
711         l_last_day
712    from ar_cons_bill_cycles_b
713   where billing_cycle_id = p_billing_cycle_id;
714 
715   if l_last_day = 'Y' THEN
716      daytab(31) := 'Y';
717   end if;
718 
719    for i in 1 .. 31 loop
720      /* Bug 7476810. If the last day of the month is inserted in the table as a
721         billling date, then dont insert the last date again. */
722      if daytab(i) = 'Y' and  l_last_day_month_insert_flag = 'N'  then
723 
724         if i >=  l_month_days then
725          l_last_day_month_insert_flag := 'Y';
726          l_char_date1 := l_month_days||'/'||substr(l_billing_month_year,1,7);
727          l_next_billing_date :=
728                  to_date(l_char_date1,'DD/MM/RRRR');
729         else
730             l_char_date1 := i||'/'||substr(l_billing_month_year,1,7);
731 
732           l_next_billing_date :=
733                  to_date(l_char_date1,'DD/MM/RRRR');
734         end if;
735    /* Changes for Bug 7365237: - Start
736       Fix for the Bug 7365237 will ensure that duplicate values (combination of billing_cycle_id and billable_date)
737       would not be inserted in the table AR_CONS_BILL_CYCLE_DATES */
738         if l_day_type = 'W' and ar_day_of_week(l_next_billing_date) in (6,7) then
739          if ar_day_of_week(l_next_billing_date) = 6 then
740             -- If the billable day is 'Saturday', make the coming monday as billable day and skip Saturday.
741             daytab(i+2) := 'Y';
742          elsif ar_day_of_week(l_next_billing_date) = 7 THEN
743             -- If the billable day is 'Sunday', make the coming monday as billable day and skip Saturday.
744             daytab(i+1) := 'Y';
745          end if;
746         else -- if the day_type is not 'W' or if the day is not a Weekend (Saturday or Sunday)
747             --------------------------------------------------------
748              --Insert the Bill Date in the table
749             --------------------------------------------------------
750                INSERT INTO AR_CONS_BILL_CYCLE_DATES (
751                           BILLING_CYCLE_ID ,
752                           BILLABLE_DATE    ,
756                           LAST_UPDATE_DATE ,
753                           CREATED_BY       ,
754                           CREATION_DATE    ,
755                           LAST_UPDATE_LOGIN,
757                           LAST_UPDATED_BY  )
758                      values
759                         ( p_billing_cycle_id,
760                           l_next_billing_date,
761                           fnd_global.user_id,
762                           sysdate,
763                           fnd_global.user_id,
764                           sysdate,
765                           fnd_global.user_id);
766         end if;
767        -- Changes for Bug 7365237: - End
768      end if;
769    end loop;
770   end loop;
771 
772  END IF ; ---Monthly
773 
774 
775 
776 END POPULATE;
777 
778 end ar_bfb_utils_pvt;