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