1 PACKAGE BODY IBY_DISBURSE_UI_API_PUB_PKG AS
2 /*$Header: ibydapib.pls 120.160.12010000.7 2008/09/26 12:31:06 vkarlapu ship $*/
3
4 /*
5 * Declare global variables
6 */
7 G_PKG_NAME CONSTANT VARCHAR2(30) := 'IBY_DISBURSE_UI_API_PUB_PKG';
8
9 /*
10 * List of document statuses that are used / set in this
11 * module.
12 */
13 DOC_STATUS_PMT_REMOVED CONSTANT VARCHAR2(100) := 'REMOVED_PAYMENT_REMOVED';
14 DOC_STATUS_PMT_STOPPED CONSTANT VARCHAR2(100) := 'REMOVED_PAYMENT_STOPPED';
15 DOC_STATUS_PMT_VOIDED CONSTANT VARCHAR2(100) := 'REMOVED_PAYMENT_VOIDED';
16 DOC_STATUS_PMT_SPOILED CONSTANT VARCHAR2(100) := 'REMOVED_PAYMENT_SPOILED';
17 DOC_STATUS_INS_TERM CONSTANT VARCHAR2(100) :=
18 'REMOVED_INSTRUCTION_TERMINATED';
19 DOC_STATUS_REQ_TERM CONSTANT VARCHAR2(100) :=
20 'REMOVED_REQUEST_TERMINATED';
21 DOC_STATUS_VALID CONSTANT VARCHAR2(100) := 'VALIDATED';
22 DOC_STATUS_PAY_CREAT CONSTANT VARCHAR2(100) := 'PAYMENT_CREATED';
23 DOC_STATUS_REJECTED CONSTANT VARCHAR2(100) := 'REJECTED';
24 DOC_STATUS_REMOVED CONSTANT VARCHAR2(100) := 'REMOVED';
25 DOC_STATUS_VOID_SETUP CONSTANT VARCHAR2(100) := 'VOID_BY_SETUP';
26 DOC_STATUS_FAIL_CA CONSTANT VARCHAR2(100) := 'FAILED_BY_CALLING_APP';
27
28 /*
29 * List of payment statuses that are used / set in this
30 * module.
31 */
32 PAY_STATUS_INS_TERM CONSTANT VARCHAR2(100) :=
33 'REMOVED_INSTRUCTION_TERMINATED';
34 PAY_STATUS_REQ_TERM CONSTANT VARCHAR2(100) :=
35 'REMOVED_REQUEST_TERMINATED';
36 PAY_STATUS_CREATED CONSTANT VARCHAR2(100) := 'CREATED';
37 PAY_STATUS_MODIFIED CONSTANT VARCHAR2(100) := 'MODIFIED';
38 PAY_STATUS_MOD_BNK_ACC CONSTANT VARCHAR2(100) :=
39 'MODIFIED_PAYEE_BANK_ACCOUNT';
40 PAY_STATUS_INS_CREAT CONSTANT VARCHAR2(100) := 'INSTRUCTION_CREATED';
41 PAY_STATUS_VOID CONSTANT VARCHAR2(100) := 'VOID';
42 PAY_STATUS_REPRINT CONSTANT VARCHAR2(100) := 'READY_TO_REPRINT';
43 PAY_STATUS_SPOILED CONSTANT VARCHAR2(100) := 'REMOVED_DOCUMENT_SPOILED';
44 PAY_STATUS_ISSUED CONSTANT VARCHAR2(100) := 'ISSUED';
45 PAY_STATUS_SUB_FOR_PRINT CONSTANT VARCHAR2(100) := 'SUBMITTED_FOR_PRINTING';
46 PAY_STATUS_FORMATTED CONSTANT VARCHAR2(100) := 'FORMATTED';
47 PAY_STATUS_TRANSMITTED CONSTANT VARCHAR2(100) := 'TRANSMITTED';
48 PAY_STATUS_ACK CONSTANT VARCHAR2(100) := 'ACKNOWLEDGED';
49 PAY_STATUS_BNK_VALID CONSTANT VARCHAR2(100) := 'BANK_VALIDATED';
50 PAY_STATUS_PAID CONSTANT VARCHAR2(100) := 'PAID';
51 PAY_STATUS_REMOVED CONSTANT VARCHAR2(100) := 'REMOVED';
52 PAY_STATUS_VOID_SETUP CONSTANT VARCHAR2(100) := 'VOID_BY_SETUP';
53 PAY_STATUS_VOID_OVERFLOW CONSTANT VARCHAR2(100) := 'VOID_BY_OVERFLOW';
54 PAY_STATUS_STOPPED CONSTANT VARCHAR2(100) := 'REMOVED_PAYMENT_STOPPED';
55 PAY_STATUS_SETUP_REPRINT CONSTANT VARCHAR2(100) := 'VOID_BY_SETUP_REPRINT';
56 PAY_STATUS_OVERFLOW_REPRINT
57 CONSTANT VARCHAR2(100) := 'VOID_BY_OVERFLOW_REPRINT';
58 PAY_STATUS_REJECTED CONSTANT VARCHAR2(100) := 'REJECTED';
59 /*
60 * List of payment instruction statuses that are used / set in this
61 * module.
62 */
63 INS_STATUS_READY_TO_PRINT CONSTANT VARCHAR2(100) :=
64 'CREATED_READY_FOR_PRINTING';
65 INS_STATUS_READY_TO_FORMAT CONSTANT VARCHAR2(100) :=
66 'CREATED_READY_FOR_FORMATTING';
67 INS_STATUS_FORMAT_TO_PRINT CONSTANT VARCHAR2(100) :=
68 'FORMATTED_READY_FOR_PRINTING';
69 INS_STATUS_PRINTED CONSTANT VARCHAR2(100) :=
70 'PRINTED';
71 INS_STATUS_TERMINATED CONSTANT VARCHAR2(100) := 'TERMINATED';
72 INS_STATUS_FORMATTED CONSTANT VARCHAR2(100) := 'FORMATTED';
73 INS_STATUS_FORMATTED_ELEC CONSTANT VARCHAR2(100) := 'FORMATTED_ELECTRONIC';
74 INS_STATUS_TRANSMITTED CONSTANT VARCHAR2(100) := 'TRANSMITTED';
75
76 /*
77 * List of payment request statuses that are used / set in this
78 * module.
79 */
80 REQ_STATUS_TERMINATED CONSTANT VARCHAR2(100) := 'TERMINATED';
81
82 /*
83 * Paper document usage reasons.
84 */
85 DOC_USE_SPOILED CONSTANT VARCHAR2(100) := 'SPOILED';
86 DOC_USE_ISSUED CONSTANT VARCHAR2(100) := 'ISSUED';
87
88 /*
89 * Payment completion code.
90 */
91 PMT_COMPLETE_YES CONSTANT VARCHAR2(10) := 'YES';
92
93 /*
94 * List of valid processing types on the payment profile.
95 */
96 P_TYPE_PRINTED CONSTANT VARCHAR2(100) := 'PRINTED';
97 P_TYPE_ELECTRONIC CONSTANT VARCHAR2(100) := 'ELECTRONIC';
98
99 /*
100 * List of process types.
101 */
102 PROCESS_TYPE_IMMEDIATE CONSTANT VARCHAR2(100) := 'IMMEDIATE';
103 PROCESS_TYPE_STANDARD CONSTANT VARCHAR2(100) := 'STANDARD';
104 PROCESS_TYPE_MANUAL CONSTANT VARCHAR2(100) := 'MANUAL';
105
106
107 /*--------------------------------------------------------------------
108 | NAME:
109 | payment_stop_request
110 |
111 |
112 | PURPOSE:For Initiating the payment stop process. This procedure should be
113 | called only by AP. This should not be called by IBY.
114 |
115 |
116 | PARAMETERS:
117 | IN p_payment_id -- id of the payment.
118 | p_requested_by -- User id of person who issued the void request.
119 | This id will be stored as an attribute of the
120 | payment.
121 | p_request_reason
122 | p_request_reference
123 | p_request_date
124 |
125 | OUT
126 | x_return_status - Result of the API call:
127 | FND_API.G_RET_STS_SUCCESS indicates that a
128 | callout was invoked successfully.
129 | In this case the caller must COMMIT
130 | the status change.
131 |
132 | FND_API.G_RET_STS_UNEXP_ERROR (or other) indicates
133 | that API did not complete successfully.
134 | In this case, the caller must issue a
135 | ROLLBACK to undo all status changes.
136 | x_msg_count
137 | x_msg_data
138 |
139 |
140 | NOTES:
141 |
142 *---------------------------------------------------------------------*/
143 PROCEDURE payment_stop_request (
144 p_payment_id IN NUMBER,
145 p_requested_by IN NUMBER,
146 p_request_reason IN VARCHAR2,
147 p_request_reference IN VARCHAR2,
148 p_request_date IN DATE,
149 x_return_status OUT nocopy VARCHAR2,
150 x_msg_count OUT nocopy NUMBER,
151 x_msg_data OUT nocopy VARCHAR2)
152 IS
153 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
154 || '.payment_stop_request';
155
156 BEGIN
157 print_debuginfo(l_module_name, 'ENTER');
158
159 UPDATE iby_payments_all
160 SET STOP_REQUEST_PLACED_FLAG = 'Y',
161 STOP_REQUEST_PLACED_BY = p_requested_by,
162 STOP_REQUEST_REASON = p_request_reason,
163 STOP_REQUEST_REFERENCE= p_request_reference,
164 STOP_REQUEST_DATE = p_request_date,
165 STOP_RELEASED_FLAG = 'N',
166 STOP_RELEASED_BY = NULL,
167 STOP_RELEASE_DATE = NULL,
168 STOP_RELEASE_REASON = NULL,
169 STOP_RELEASE_REFERENCE = NULL
170
171 WHERE
172 PAYMENT_ID = p_payment_id;
173
174 x_return_status := FND_API.G_RET_STS_SUCCESS;
175 print_debuginfo(l_module_name, 'EXIT');
176
177 EXCEPTION
178 WHEN OTHERS THEN
179 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
180 x_msg_count := 1;
181 x_msg_data := substr(SQLERRM,1,25);
182
183 print_debuginfo(l_module_name, 'EXIT');
184 END payment_stop_request;
185
186
187 /*--------------------------------------------------------------------
188 | NAME:
189 | payment_stop_release
190 |
191 |
192 | PURPOSE:For Releasing the stop request . This procedure should be
193 | called only by AP. This should not be called by IBY.
194 |
195 |
196 | PARAMETERS:
197 | IN p_payment_id -- payment id
198 | p_released_by -- User id of person who issued the void request.
199 | This id will be stored as an attribute of the
200 | payment.
201 | p_release_reason
202 | p_release_reference
203 | p_release_date
204 |
205 | OUT x_return_status - Result of the API call:
206 | FND_API.G_RET_STS_SUCCESS indicates that a
207 | callout was invoked successfully.
208 | In this case the caller must COMMIT
209 | the status change.
210 |
211 | FND_API.G_RET_STS_UNEXP_ERROR (or other) indicates
212 | that API did not complete successfully.
213 | In this case, the caller must issue a
214 | ROLLBACK to undo all status changes.
215 | x_msg_count
216 | x_msg_data
217 |
218 |
219 | NOTES:
220 |
221 *---------------------------------------------------------------------*/
222 PROCEDURE payment_stop_release (
223 p_payment_id IN NUMBER,
224 p_released_by IN NUMBER,
225 p_release_reason IN VARCHAR2,
226 p_release_reference IN VARCHAR2,
227 p_release_date IN DATE,
228 x_return_status OUT nocopy VARCHAR2,
229 x_msg_count OUT nocopy NUMBER,
230 x_msg_data OUT nocopy VARCHAR2)
231 IS
232 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
233 || '.payment_stop_release';
234 BEGIN
235 print_debuginfo(l_module_name, 'ENTER');
236
237 UPDATE iby_payments_all
238 SET STOP_RELEASED_FLAG = 'Y',
239 STOP_RELEASED_BY = p_released_by,
240 STOP_RELEASE_DATE = p_release_date,
241 STOP_RELEASE_REASON = p_release_reason,
242 STOP_RELEASE_REFERENCE = p_release_reference
243
244 WHERE
245 PAYMENT_ID = p_payment_id;
246
247 x_return_status := FND_API.G_RET_STS_SUCCESS;
248 print_debuginfo(l_module_name, 'EXIT');
249
250 EXCEPTION
251 WHEN OTHERS THEN
252 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
253 x_msg_count := 1;
254 x_msg_data := substr(SQLERRM,1,25);
255
256 print_debuginfo(l_module_name, 'EXIT');
257
258 END payment_stop_release;
259
260
261
262
263
264 /*--------------------------------------------------------------------
265 | NAME:
266 | remove_document_payable
267 |
268 | PURPOSE:
269 | Invokes the callout of the calling app to remove a submitted
270 | document payable from the payment processing cycle.
271 |
272 | The calling application can free up the removed document, and
273 | make it available for submission in a future payment request.
274 |
275 | PARAMETERS:
276 | IN
277 | p_doc_id - ID of the document payable to be removed.
278 | p_doc_status - Current status of the document payable to
279 | be removed.
280 |
281 | OUT
282 | x_return_status - Result of the API call:
283 | FND_API.G_RET_STS_SUCCESS indicates that a
284 | callout was invoked successfully.
285 | In this case the caller must COMMIT
286 | the status change.
287 |
288 | FND_API.G_RET_STS_ERROR (or other) indicates
289 | that API did not complete successfully.
290 | In this case, the caller must issue a
291 | ROLLBACK to undo all status changes.
292 |
293 | RETURNS:
294 |
295 | NOTES:
296 | Internal API, not for public use.
297 |
298 | This API will not do a COMMIT. It is the the callers responsbility
299 | to perform COMMIT / ROLLBACK depending upon the returned status.
300 |
301 | The callout invoked must be handled synchronously by the
302 | calling application. So the COMMIT / ROLLBACK should affect
303 | the changes made to the database by the calling application as
304 | well. This will ensure that IBY and the calling application are
305 | in sync w.r.t. to the specified document payable.
306 |
307 *---------------------------------------------------------------------*/
308 PROCEDURE remove_document_payable (
309 p_doc_id IN NUMBER,
310 p_doc_status IN VARCHAR2,
311 x_return_status OUT NOCOPY VARCHAR2
312 )
313 IS
314
315 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
316 || '.remove_document_payable';
317
318 l_rejection_id NUMBER(15);
319
320 /* used in forming callout procedure name */
321 l_calling_app_id NUMBER;
322 l_app_short_name VARCHAR2(200);
323 l_pkg_name VARCHAR2(200);
324 l_callout_name VARCHAR2(500);
325 l_stmt VARCHAR2(1000);
326
327 /* used in invocation of callout procedure */
328 l_api_version CONSTANT NUMBER := 1.0;
329 l_msg_count NUMBER;
330 l_msg_data VARCHAR2(2000);
331
332 /*
333 * Implementing the callout is optional for the calling app.
334 * If the calling app does not implement the hook, then
335 * the call to the hook will result in ORA-06576 error.
336 *
337 * There is no exception name associated with this code, so
338 * we create one called 'PROCEDURE_NOT_IMPLEMENTED'. If this
339 * exception occurs, it is not fatal: we log the error and
340 * proceed.
341 *
342 * If, on the other hand, the calling app implements the
343 * callout, but the callout throws an exception, it is fatal
344 * and we must abort the program (this will be caught
345 * in WHEN OTHERS block).
346 */
347 PROCEDURE_NOT_IMPLEMENTED EXCEPTION;
348 PRAGMA EXCEPTION_INIT(PROCEDURE_NOT_IMPLEMENTED, -6576);
349
350 BEGIN
351
352 print_debuginfo(l_module_name, 'ENTER');
353
354 FND_MSG_PUB.initialize;
355
356 /*
357 * STATUS CHANGE:
358 *
359 * UI Responsibility:
360 * document status = REMOVED
361 *
362 * API Responsibility:
363 * NONE
364 */
365
366 /*
367 * Get the next available rejected document group id.
368 */
369 SELECT
370 IBY_REJECTED_DOCS_GROUP_S.NEXTVAL
371 INTO
372 l_rejection_id
373 FROM
374 DUAL
375 ;
376
377 /*
378 * Update the removed document with the rejected document
379 * group id. The calling application will identify rejected
380 * documents using this id.
381 */
382 UPDATE
383 IBY_DOCS_PAYABLE_ALL
384 SET
385 rejected_docs_group_id = l_rejection_id
386 WHERE
387 document_payable_id = p_doc_id AND
388 document_status = p_doc_status
389 ;
390
391 /*
392 * Get the application name of the calling app. This
393 * will be used in the callout.
394 */
395 SELECT
396 fnd.application_short_name
397 INTO
398 l_app_short_name
399 FROM
400 FND_APPLICATION fnd,
401 IBY_DOCS_PAYABLE_ALL doc
402 WHERE
403 fnd.application_id = doc.calling_app_id AND
404 doc.document_payable_id = p_doc_id
405 ;
406
407 /*
408 * Get the constructed package name to use in the
409 * call out.
410 */
411 l_pkg_name := construct_callout_pkg_name(l_app_short_name);
412
413 print_debuginfo(l_module_name, 'Constructed package name: '
414 || l_pkg_name);
415
416 IF (l_pkg_name IS NULL) THEN
417
418 print_debuginfo(l_module_name, 'Package name is null. '
419 || 'Raising exception.');
420
421 APP_EXCEPTION.RAISE_EXCEPTION;
422
423 END IF;
424
425
426 /*
427 * Now try to call the external app's implementation of the hook.
428 * The calling app may or may not have implemented the hook, so
429 * it's not fatal if the implementation does not exist.
430 */
431 l_callout_name := l_pkg_name || '.' || 'documents_payable_rejected';
432
433 print_debuginfo(l_module_name, 'Attempting to invoke callout: '
434 || l_callout_name);
435
436 l_stmt := 'CALL '|| l_callout_name || '(:1, :2, :3, :4, :5, :6, :7)';
437
438 BEGIN
439
440 EXECUTE IMMEDIATE
441 (l_stmt)
442 USING
443 IN l_api_version,
444 IN FND_API.G_FALSE,
445 IN FND_API.G_FALSE,
446 OUT x_return_status,
447 OUT l_msg_count,
448 OUT l_msg_data,
449 IN l_rejection_id
450 ;
451
452 /*
453 * If the called procedure did not return success,
454 * raise an exception.
455 */
456 IF (x_return_status IS NULL OR
457 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
458
459 print_debuginfo(l_module_name, 'Fatal: External app callout '''
460 || l_callout_name
461 || ''', returned failure status - '
462 || x_return_status
463 || '. Raising exception.'
464 );
465
466 APP_EXCEPTION.RAISE_EXCEPTION;
467
468 END IF;
469
470 EXCEPTION
471
472 WHEN PROCEDURE_NOT_IMPLEMENTED THEN
473 print_debuginfo(l_module_name, 'Callout "' || l_callout_name
474 || '" not implemented by calling app '
475 || l_app_short_name || '.');
476
477 print_debuginfo(l_module_name, 'Skipping hook call.');
478
479
480 WHEN OTHERS THEN
481 print_debuginfo(l_module_name, 'Fatal: External app callout '''
482 || l_callout_name
483 || ''', generated exception.'
484 );
485
486 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
487 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
488 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
489
490 /*
491 * Propogate exception to caller.
492 */
493 RAISE;
494 END;
495
496 x_return_status := FND_API.G_RET_STS_SUCCESS;
497
498 print_debuginfo(l_module_name, 'EXIT');
499
500 EXCEPTION
501
502 WHEN OTHERS THEN
503
504 print_debuginfo(l_module_name, 'Exception occured when '
505 || 'removing document payable '
506 || p_doc_id
507 || ', with status '
508 || p_doc_status
509 );
510
511 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
512 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
513 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
514 x_return_status := FND_API.G_RET_STS_ERROR;
515
516 print_debuginfo(l_module_name, 'EXIT');
517
518 END remove_document_payable;
519
520 /*--------------------------------------------------------------------
521 | NAME:
522 | remove_documents_payable
523 |
524 | PURPOSE:
525 | Invokes a series of callouts to the calling app to remove
526 | a set of submitted documents payable from the payment processing
527 | cycle.
528 |
529 | The calling application can free up the removed documents, and
530 | make them available for submission in future payment request(s).
531 |
532 | PARAMETERS:
533 | IN
534 | p_doc_list - IDs of the documents payable to be removed.
535 | This should be an array of document payable ids.
536 |
537 | p_doc_status_list - Current statuses of the documents payable to
538 | be removed. This should be an array of statuses.
539 |
540 | OUT
541 | x_return_status - Result of the API call:
542 | FND_API.G_RET_STS_SUCCESS indicates that all
543 | callouts were invoked successfully.
544 | In this case the caller must COMMIT
545 | the status changes.
546 |
547 | FND_API.G_RET_STS_ERROR (or other) indicates
548 | that at least one event did not complete
549 | successfully. In this case, the caller must
550 | issue a ROLLBACK to undo all status changes.
551 |
552 | RETURNS:
553 |
554 | NOTES:
555 | This API will not do a COMMIT. It is the the callers responsbility
556 | to perform COMMIT / ROLLBACK depending upon the returned status.
557 |
558 | The callouts invoked must be handled synchronously by the
559 | calling application. So the COMMIT / ROLLBACK should affect
560 | the changes made to the database by the calling application as
561 | well. This will ensure that IBY and the calling application are
562 | in sync w.r.t. to the specified documents payable.
563 |
564 *---------------------------------------------------------------------*/
565 PROCEDURE remove_documents_payable (
566 p_doc_list IN docPayIDTab,
567 p_doc_status_list IN docPayStatusTab,
568 x_return_status OUT NOCOPY VARCHAR2
569 )
570 IS
571
572 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
573 || '.remove_documents_payable';
574 BEGIN
575
576 print_debuginfo(l_module_name, 'ENTER');
577
578 FND_MSG_PUB.initialize;
579
580 IF (p_doc_list.COUNT = 0 OR p_doc_status_list.COUNT = 0) THEN
581
582 print_debuginfo(l_module_name, 'Error: List of document '
583 || 'payable ids/statuses is empty'
584 || '. Returning failure response .. '
585 );
586
587 x_return_status := FND_API.G_RET_STS_ERROR;
588
589 print_debuginfo(l_module_name, 'EXIT');
590
591 RETURN;
592
593 END IF;
594
595 IF (p_doc_list.COUNT <> p_doc_status_list.COUNT) THEN
596
597 print_debuginfo(l_module_name, 'Error: List of document '
598 || 'payable ids must match list of document payable '
599 || 'statuses'
600 || '. Returning failure response .. '
601 );
602
603 x_return_status := FND_API.G_RET_STS_ERROR;
604
605 print_debuginfo(l_module_name, 'EXIT');
606
607 RETURN;
608
609 END IF;
610
611 /*
612 * Start processing the documents payable, one-by-one.
613 */
614 FOR i IN p_doc_list.FIRST .. p_doc_list.LAST LOOP
615
616 remove_document_payable (
617 p_doc_list(i),
618 p_doc_status_list(i),
619 x_return_status
620 );
621
622 /*
623 * Check if the call to remove the document
624 * payable succeeded.
625 */
626 IF (x_return_status IS NULL OR
627 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
628
629 /*
630 * Even if a single call to remove a doc payable
631 * failed, return failure for the entire API request.
632 */
633 print_debuginfo(l_module_name, 'Removing of document '
634 || p_doc_list(i)
635 || ' failed.'
636 );
637
638 print_debuginfo(l_module_name, 'EXIT');
639
640 /*
641 * It is the callers responsibility to rollback
642 * all the changes.
643 */
644 RETURN;
645
646 END IF;
647
648 END LOOP;
649
650 x_return_status := FND_API.G_RET_STS_SUCCESS;
651
652 print_debuginfo(l_module_name, 'Returning success response ..');
653
654 print_debuginfo(l_module_name, 'EXIT');
655
656 END remove_documents_payable;
657
658 /*--------------------------------------------------------------------
659 | NAME:
660 | remove_payment
661 |
662 |
663 | PURPOSE:
664 | Invokes a callout of the calling app to remove a set of
665 | submitted documents payable from the payment processing
666 | cycle.
667 |
668 | The calling application can free up the removed documents, and
669 | make them available for submission in future payment request(s).
670 |
671 | PARAMETERS:
672 | IN
673 | p_pmt_id - ID of the payment to be removed.
674 |
675 | p_pmt_status_list - Current status of the payment to
676 | be removed.
677 |
678 | OUT
679 | x_return_status - Result of the API call:
680 | FND_API.G_RET_STS_SUCCESS indicates that
681 | the callout was invoked successfully.
682 | In this case the caller must COMMIT
683 | the status changes.
684 |
685 | FND_API.G_RET_STS_ERROR (or other) indicates
686 | that tha API did not complete successfully.
687 | In this case, the caller must issue a
688 | ROLLBACK to undo all status changes.
689 |
690 | RETURNS:
691 |
692 | NOTES:
693 | Internal API, not for public use.
694 |
695 | This API will not do a COMMIT. It is the the callers responsibility
696 | to perform COMMIT / ROLLBACK depending upon the returned status.
697 |
698 | The callout invoked must be handled synchronously by the
699 | calling application. So the COMMIT / ROLLBACK should affect
700 | the changes made to the database by the calling application as
701 | well. This will ensure that IBY and the calling application are
702 | in sync w.r.t. to the specified documents payable.
703 |
704 *---------------------------------------------------------------------*/
705 PROCEDURE remove_payment (
706 p_pmt_id IN NUMBER,
707 p_pmt_status IN VARCHAR2,
708 x_return_status OUT NOCOPY VARCHAR2
709 )
710 IS
711
712 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME || '.remove_payment';
713
714 l_rejection_id NUMBER(15);
715
716 /* used in forming callout procedure name */
717 l_calling_app_id NUMBER;
718 l_app_short_name VARCHAR2(200);
719 l_pkg_name VARCHAR2(200);
720 l_callout_name VARCHAR2(500);
721 l_stmt VARCHAR2(1000);
722
723 /* used in invocation of callout procedure */
724 l_api_version CONSTANT NUMBER := 1.0;
725 l_msg_count NUMBER;
726 l_msg_data VARCHAR2(2000);
727
728 /*
729 * Implementing the callout is optional for the calling app.
730 * If the calling app does not implement the hook, then
731 * the call to the hook will result in ORA-06576 error.
732 *
733 * There is no exception name associated with this code, so
734 * we create one called 'PROCEDURE_NOT_IMPLEMENTED'. If this
735 * exception occurs, it is not fatal: we log the error and
736 * proceed.
737 *
738 * If, on the other hand, the calling app implements the
739 * callout, but the callout throws an exception, it is fatal
740 * and we must abort the program (this will be caught
741 * in WHEN OTHERS block).
742 */
743 PROCEDURE_NOT_IMPLEMENTED EXCEPTION;
744 PRAGMA EXCEPTION_INIT(PROCEDURE_NOT_IMPLEMENTED, -6576);
745
746 BEGIN
747
748 print_debuginfo(l_module_name, 'ENTER');
749
750 FND_MSG_PUB.initialize;
751
752 /*
753 * STATUS CHANGE:
754 *
755 * UI Responsibility:
756 * payment status = REMOVED
757 *
758 * API Responsibility:
759 * document_status = REMOVED_PAYMENT_REMOVED
760 */
761 UPDATE
762 IBY_DOCS_PAYABLE_ALL
763 SET
764 document_status = DOC_STATUS_PMT_REMOVED,
765
766 /*
767 * Fix for bug 4405981:
768 *
769 * The straight through flag should be set to 'N',
770 * if the document was rejected / required manual
771 * intervention.
772 */
773 straight_through_flag = 'N'
774 WHERE
775 payment_id = p_pmt_id
776 ;
777
778 /*
779 * Get the next available rejected document group id.
780 */
781 SELECT
782 IBY_REJECTED_DOCS_GROUP_S.NEXTVAL
783 INTO
784 l_rejection_id
785 FROM
786 DUAL
787 ;
788
789 /*
790 * Update the removed documents with the rejected document
791 * group id. The calling application will identify rejected
792 * documents using this id.
793 */
794 UPDATE
795 IBY_DOCS_PAYABLE_ALL
796 SET
797 rejected_docs_group_id = l_rejection_id
798 WHERE
799 payment_id = p_pmt_id
800 ;
801
802 /*
803 * Get the application name of the calling app. This
804 * will be used in the callout.
805 */
806 SELECT
807 fnd.application_short_name
808 INTO
809 l_app_short_name
810 FROM
811 FND_APPLICATION fnd,
812 IBY_PAYMENTS_ALL pmt,
813 IBY_PAY_SERVICE_REQUESTS req
814 WHERE
815 fnd.application_id = req.calling_app_id AND
816 req.payment_service_request_id = pmt.payment_service_request_id AND
817 pmt.payment_id = p_pmt_id
818 ;
819
820 /*
821 * Get the constructed package name to use in the
822 * call out.
823 */
824 l_pkg_name := construct_callout_pkg_name(l_app_short_name);
825
826 print_debuginfo(l_module_name, 'Constructed package name: '
827 || l_pkg_name);
828
829 IF (l_pkg_name IS NULL) THEN
830
831 print_debuginfo(l_module_name, 'Package name is null. '
832 || 'Raising exception.');
833
834 APP_EXCEPTION.RAISE_EXCEPTION;
835
836 END IF;
837
838 /*
839 * Now try to call the external app's implementation of the hook.
840 * The calling app may or may not have implemented the hook, so
841 * it's not fatal if the implementation does not exist.
842 */
843 l_callout_name := l_pkg_name || '.' || 'documents_payable_rejected';
844
845 print_debuginfo(l_module_name, 'Attempting to invoke callout: '
846 || l_callout_name);
847
848 l_stmt := 'CALL '|| l_callout_name || '(:1, :2, :3, :4, :5, :6, :7)';
849
850 BEGIN
851
852 EXECUTE IMMEDIATE
853 (l_stmt)
854 USING
855 IN l_api_version,
856 IN FND_API.G_FALSE,
857 IN FND_API.G_FALSE,
858 OUT x_return_status,
859 OUT l_msg_count,
860 OUT l_msg_data,
861 IN l_rejection_id
862 ;
863
864 /*
865 * If the called procedure did not return success,
866 * raise an exception.
867 */
868 IF (x_return_status IS NULL OR
869 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
870
871 print_debuginfo(l_module_name, 'Fatal: External app callout '''
872 || l_callout_name
873 || ''', returned failure status - '
874 || x_return_status
875 || '. Raising exception.'
876 );
877
878 APP_EXCEPTION.RAISE_EXCEPTION;
879
880 END IF;
881
882 EXCEPTION
883
884 WHEN PROCEDURE_NOT_IMPLEMENTED THEN
885 print_debuginfo(l_module_name, 'Callout "' || l_callout_name
886 || '" not implemented by calling app '
887 || l_app_short_name || '.');
888
889 print_debuginfo(l_module_name, 'Skipping hook call.');
890
891
892 WHEN OTHERS THEN
893 print_debuginfo(l_module_name, 'Fatal: External app callout '''
894 || l_callout_name
895 || ''', generated exception.'
896 );
897
898 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
899 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
900 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
901
902 /*
903 * Propogate exception to caller.
904 */
905 RAISE;
906 END;
907
908
909 x_return_status := FND_API.G_RET_STS_SUCCESS;
910
911 print_debuginfo(l_module_name, 'EXIT');
912
913 EXCEPTION
914
915 WHEN OTHERS THEN
916
917 print_debuginfo(l_module_name, 'Exception occured when '
918 || 'removing payment '
919 || p_pmt_id
920 || ', with status '
921 || p_pmt_status
922 );
923
924 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
925 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
926 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
927
928 x_return_status := FND_API.G_RET_STS_ERROR;
929
930 print_debuginfo(l_module_name, 'EXIT');
931
932 END remove_payment;
933
934 /*--------------------------------------------------------------------
935 | NAME:
936 | remove_payments
937 |
938 | PURPOSE:
939 | Invokes a series of callouts of the calling app to remove
940 | a set of submitted documents payable from the payment processing
941 | cycle.
942 |
943 | The calling application can free up the removed documents, and
944 | make them available for submission in future payment request(s).
945 |
946 | PARAMETERS:
947 | IN
948 | p_pmt_list - IDs of the payments to be removed.
949 | This should be an array of payment ids. All
950 | the child documents payable of each of the
951 | specified payments will be removed.
952 |
953 | p_pmt_status_list - Current statuses of the payments to
954 | be removed. This should be an array of statuses.
955 |
956 | OUT
957 | x_return_status - Result of the API call:
958 | FND_API.G_RET_STS_SUCCESS indicates that all
959 | the callouts were invoked successfully.
960 | In this case the caller must COMMIT
961 | the status changes.
962 |
963 | FND_API.G_RET_STS_ERROR (or other) indicates
964 | that at least one event did not complete
965 | successfully. In this case, the caller must
966 | issue a ROLLBACK to undo all status changes.
967 |
968 | RETURNS:
969 |
970 | NOTES:
971 | Internal API, not for public use.
972 |
973 | This API will not do a COMMIT. It is the the callers responsbility
974 | to perform COMMIT / ROLLBACK depending upon the returned status.
975 |
976 | The callouts invoked must be handled synchronously by the
977 | calling application. So the COMMIT / ROLLBACK should affect
978 | the changes made to the database by the calling application as
979 | well. This will ensure that IBY and the calling application are
980 | in sync w.r.t. to the specified documents payable.
981 |
982 *---------------------------------------------------------------------*/
983 PROCEDURE remove_payments (
984 p_pmt_list IN pmtIDTab,
985 p_pmt_status_list IN pmtStatusTab,
986 x_return_status OUT NOCOPY VARCHAR2
987 )
988 IS
989
990 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME || '.remove_payments';
991
992 BEGIN
993
994 print_debuginfo(l_module_name, 'ENTER');
995
996 FND_MSG_PUB.initialize;
997
998 IF (p_pmt_list.COUNT = 0 OR p_pmt_status_list.COUNT = 0) THEN
999
1000 print_debuginfo(l_module_name, 'Error: List of payment '
1001 || 'payable ids/statuses is empty'
1002 || '. Returning failure response .. '
1003 );
1004
1005 x_return_status := FND_API.G_RET_STS_ERROR;
1006
1007 print_debuginfo(l_module_name, 'EXIT');
1008
1009 RETURN;
1010
1011 END IF;
1012
1013 IF (p_pmt_list.COUNT <> p_pmt_status_list.COUNT) THEN
1014
1015 print_debuginfo(l_module_name, 'Error: List of payment '
1016 || 'ids must match list of payment statuses. '
1017 || 'Returning failure response .. '
1018 );
1019
1020 x_return_status := FND_API.G_RET_STS_ERROR;
1021
1022 print_debuginfo(l_module_name, 'EXIT');
1023
1024 RETURN;
1025
1026 END IF;
1027
1028 /*
1029 * Start processing the payments, one-by-one.
1030 */
1031 FOR i IN p_pmt_list.FIRST .. p_pmt_list.LAST LOOP
1032
1033 remove_payment (
1034 p_pmt_list(i),
1035 p_pmt_status_list(i),
1036 x_return_status
1037 );
1038
1039 /*
1040 * Check if the call to remove the payment succeeded.
1041 */
1042 IF (x_return_status IS NULL OR
1043 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1044
1045 /*
1046 * Even if a single call to remove a payment
1047 * failed, return failure for the entire API request.
1048 */
1049 print_debuginfo(l_module_name, 'Removing of payment '
1050 || p_pmt_list(i)
1051 || ' failed.'
1052 );
1053
1054 print_debuginfo(l_module_name, 'EXIT');
1055
1056 /*
1057 * It is the callers responsibility to rollback
1058 * all the changes.
1059 */
1060 RETURN;
1061
1062 END IF;
1063
1064 END LOOP;
1065
1066 x_return_status := FND_API.G_RET_STS_SUCCESS;
1067
1068 print_debuginfo(l_module_name, 'Returning success response ..');
1069
1070 print_debuginfo(l_module_name, 'EXIT');
1071
1072 END remove_payments;
1073
1074 /*--------------------------------------------------------------------
1075 | NAME:
1076 | remove_payment_request
1077 |
1078 | PURPOSE:
1079 | Invokes a series of callouts of the calling app to remove
1080 | all the submitted documents payable of the given payment request
1081 | from the payment processing cycle.
1082 |
1083 | The calling application can free up the removed documents, and
1084 | make them available for submission in future payment request(s).
1085 |
1086 | PARAMETERS:
1087 | IN
1088 | p_payreq_id - ID of the payment request which must be removed.
1089 | All documents payable associated with the
1090 | specified payment request will be removed.
1091 |
1092 | OUT
1093 | x_return_status - Result of the API call:
1094 | FND_API.G_RET_STS_SUCCESS indicates that all
1095 | the callouts were invoked successfully.
1096 | In this case the caller must COMMIT
1097 | the status changes.
1098 |
1099 | FND_API.G_RET_STS_ERROR (or other) indicates
1100 | that at least one event did not complete
1101 | successfully. In this case, the caller must
1102 | issue a ROLLBACK to undo all status changes.
1103 |
1104 | RETURNS:
1105 |
1106 | NOTES:
1107 | Internal API, not for public use.
1108 |
1109 | This API will not do a COMMIT. It is the the callers responsbility
1110 | to perform COMMIT / ROLLBACK depending upon the returned status.
1111 |
1112 | The callouts invoked must be handled synchronously by the
1113 | calling application. So the COMMIT / ROLLBACK should affect
1114 | the changes made to the database by the calling application as
1115 | well. This will ensure that IBY and the calling application are
1116 | in sync w.r.t. to the specified documents payable.
1117 |
1118 *---------------------------------------------------------------------*/
1119 PROCEDURE remove_payment_request (
1120 p_payreq_id IN NUMBER,
1121 x_return_status OUT NOCOPY VARCHAR2
1122 )
1123 IS
1124
1125 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME ||
1126 '.remove_payment_request';
1127
1128 l_docs_list IBY_VALIDATIONSETS_PUB.rejectedDocTabType;
1129 l_doc_id_list docPayIDTab;
1130 l_doc_status_list docPayStatusTab;
1131
1132 /*
1133 * Cursor to get list of documents along with their statuses for
1134 * the given payment service request.
1135 */
1136 CURSOR c_docs (p_payreq_id IBY_PAY_SERVICE_REQUESTS.
1137 payment_service_request_id%TYPE)
1138 IS
1139 SELECT
1140 doc.document_payable_id,
1141 doc.document_status
1142 FROM
1143 IBY_DOCS_PAYABLE_ALL doc
1144 WHERE
1145 doc.payment_service_request_id = p_payreq_id
1146 ;
1147
1148 BEGIN
1149
1150 print_debuginfo(l_module_name, 'ENTER');
1151
1152 FND_MSG_PUB.initialize;
1153
1154 /*
1155 * Pick up all documents for this payment request.
1156 */
1157 OPEN c_docs(p_payreq_id);
1158 FETCH c_docs BULK COLLECT INTO l_docs_list;
1159 CLOSE c_docs;
1160
1161 IF (l_docs_list.COUNT <> 0) THEN
1162
1163 /*
1164 * Separate out the payment ids and the payment statuses.
1165 * This is because the rejection API expects these as
1166 * separate arrays.
1167 */
1168 FOR i IN l_docs_list.FIRST .. l_docs_list.LAST LOOP
1169 l_doc_id_list(i) := l_docs_list(i).doc_id;
1170 END LOOP;
1171
1172 FOR i IN l_docs_list.FIRST .. l_docs_list.LAST LOOP
1173 l_doc_status_list(i) := l_docs_list(i).doc_status;
1174 END LOOP;
1175
1176 /*
1177 * Now, remove all the documents of this request.
1178 */
1179 remove_documents_payable (
1180 l_doc_id_list,
1181 l_doc_status_list,
1182 x_return_status
1183 );
1184
1185 /*
1186 * Check if the call to remove the documents succeeded.
1187 */
1188 IF (x_return_status IS NULL OR
1189 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1190
1191 /*
1192 * Even if a single call to remove a document
1193 * failed, return failure for the entire API request.
1194 */
1195 print_debuginfo(l_module_name, 'Removing of documents '
1196 || 'for payment request '
1197 || p_payreq_id
1198 || ' failed.'
1199 );
1200
1201 print_debuginfo(l_module_name, 'EXIT');
1202
1203 /*
1204 * It is the callers responsibility to rollback
1205 * all the changes.
1206 */
1207 RETURN;
1208
1209 END IF;
1210
1211 ELSE
1212
1213 print_debuginfo(l_module_name, 'No documents were found for '
1214 || 'payment request id '
1215 || p_payreq_id
1216 || '. Skipping ..'
1217 );
1218
1219 END IF;
1220
1221 x_return_status := FND_API.G_RET_STS_SUCCESS;
1222
1223 print_debuginfo(l_module_name, 'Returning success response ..');
1224
1225 print_debuginfo(l_module_name, 'EXIT');
1226
1227 END remove_payment_request;
1228
1229 /*--------------------------------------------------------------------
1230 | NAME:
1231 | stop_payment
1232 |
1233 |
1234 | PURPOSE:
1235 | Invokes a callout of the calling app to remove a set of
1236 | submitted documents payable from the payment processing
1237 | cycle.
1238 |
1239 | The calling application can free up the removed documents, and
1240 | make them available for submission in future payment request(s).
1241 |
1242 | PARAMETERS:
1243 | IN
1244 | p_pmt_id - ID of the payment to be stopped.
1245 |
1246 | p_pmt_status_list - Current status of the payment to
1247 | be stopped.
1248 |
1249 | OUT
1250 | x_return_status - Result of the API call:
1251 | FND_API.G_RET_STS_SUCCESS indicates that the
1252 | callout was invoked successfully.
1253 | In this case the caller must COMMIT
1254 | the status changes.
1255 |
1256 | FND_API.G_RET_STS_ERROR (or other) indicates
1257 | that tha API did not complete successfully.
1258 | In this case, the caller must issue a
1259 | ROLLBACK to undo all status changes.
1260 |
1261 | RETURNS:
1262 |
1263 | NOTES:
1264 | Internal API, not for public use.
1265 |
1266 | This API will not do a COMMIT. It is the the callers responsibility
1267 | to perform COMMIT / ROLLBACK depending upon the returned status.
1268 |
1269 | The callouts invoked must be handled synchronously by the
1270 | calling application. So the COMMIT / ROLLBACK should affect
1271 | the changes made to the database by the calling application as
1272 | well. This will ensure that IBY and the calling application are
1273 | in sync w.r.t. to the specified documents payable.
1274 |
1275 *---------------------------------------------------------------------*/
1276 PROCEDURE stop_payment (
1277 p_pmt_id IN NUMBER,
1278 p_pmt_status IN VARCHAR2,
1279 x_return_status OUT NOCOPY VARCHAR2
1280 )
1281 IS
1282
1283 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME ||'.stop_payment ';
1284
1285 l_rejection_id NUMBER(15);
1286
1287 /* used in forming callout procedure name */
1288 l_calling_app_id NUMBER;
1289 l_app_short_name VARCHAR2(200);
1290 l_pkg_name VARCHAR2(200);
1291 l_callout_name VARCHAR2(500);
1292 l_stmt VARCHAR2(1000);
1293
1294 /* used in invocation of callout procedure */
1295 l_api_version CONSTANT NUMBER := 1.0;
1296 l_msg_count NUMBER;
1297 l_msg_data VARCHAR2(2000);
1298
1299
1300 l_instr_id IBY_PAY_INSTRUCTIONS_ALL.payment_instruction_id%TYPE;
1301 l_valid_pmts_count NUMBER;
1302
1303 /*
1304 * Implementing the callout is optional for the calling app.
1305 * If the calling app does not implement the hook, then
1306 * the call to the hook will result in ORA-06576 error.
1307 *
1308 * There is no exception name associated with this code, so
1309 * we create one called 'PROCEDURE_NOT_IMPLEMENTED'. If this
1310 * exception occurs, it is not fatal: we log the error and
1311 * proceed.
1312 *
1313 * If, on the other hand, the calling app implements the
1314 * callout, but the callout throws an exception, it is fatal
1315 * and we must abort the program (this will be caught
1316 * in WHEN OTHERS block).
1317 */
1318 PROCEDURE_NOT_IMPLEMENTED EXCEPTION;
1319 PRAGMA EXCEPTION_INIT(PROCEDURE_NOT_IMPLEMENTED, -6576);
1320
1321 BEGIN
1322
1323 print_debuginfo(l_module_name, 'ENTER');
1324
1325 FND_MSG_PUB.initialize;
1326
1327 /*
1328 * STATUS CHANGE:
1329 *
1330 * UI Responsibility:
1331 * payment status = REMOVED_PAYMENT_STOPPED
1332 *
1333 * API Responsibility:
1334 * document_status = REMOVED_PAYMENT_STOPPED
1335 */
1336 UPDATE
1337 IBY_DOCS_PAYABLE_ALL
1338 SET
1339 document_status = DOC_STATUS_PMT_STOPPED
1340 WHERE
1341 payment_id = p_pmt_id
1342 ;
1343
1344 /*
1345 * Get the next available rejected document group id.
1346 */
1347 SELECT
1348 IBY_REJECTED_DOCS_GROUP_S.NEXTVAL
1349 INTO
1350 l_rejection_id
1351 FROM
1352 DUAL
1353 ;
1354
1355 /*
1356 * Update the removed documents with the rejected document
1357 * group id. The calling application will identify rejected
1358 * documents using this id.
1359 */
1360 UPDATE
1361 IBY_DOCS_PAYABLE_ALL
1362 SET
1363 rejected_docs_group_id = l_rejection_id
1364 WHERE
1365 payment_id = p_pmt_id
1366 ;
1367
1368 /* Bug 6609931 */
1369 BEGIN
1370 SELECT
1371 instr.payment_instruction_id
1372 INTO
1373 l_instr_id
1374 FROM
1375 IBY_PAY_INSTRUCTIONS_ALL instr,
1376 IBY_PAYMENTS_ALL pmt
1377 WHERE
1378 instr.payment_instruction_id = pmt.payment_instruction_id AND
1379 pmt.payment_id = p_pmt_id;
1380 EXCEPTION
1381 WHEN NO_DATA_FOUND THEN
1382 l_instr_id:=null;
1383 END;
1384
1385 /* Bug 7028817*/
1386 /* If the payment is stopped before instruction is created,
1387 should by pass the below logic.
1388 So, having condition based on the instruction id*/
1389
1390 IF l_instr_id IS NOT NULL THEN
1391
1392 -- get the count of valid payments- which are not stopped, voided, removed
1393 -- and overfloW/setup payment- these will not have payment reference number
1394 SELECT
1395 count(*)
1396 INTO
1397 l_valid_pmts_count
1398 FROM
1399 IBY_PAYMENTS_ALL pmt
1400 WHERE
1401 pmt.payment_instruction_id = l_instr_id AND
1402 pmt.payment_reference_number is not null AND
1403 pmt.payment_status NOT IN
1404 (PAY_STATUS_VOID, PAY_STATUS_REMOVED, PAY_STATUS_STOPPED, PAY_STATUS_REJECTED);
1405
1406
1407 print_debuginfo(l_module_name , 'The number of valid payments : ' ||
1408 l_valid_pmts_count);
1409
1410
1411 IF (l_valid_pmts_count = 0) THEN
1412 /*
1413 * * Set the payment instruction status to TERMINATED
1414 * * because no valid payments now exist for this
1415 * * payment instruction.
1416 * */
1417
1418 UPDATE
1419 IBY_PAY_INSTRUCTIONS_ALL
1420 SET
1421 payment_instruction_status = INS_STATUS_TERMINATED
1422 WHERE
1423 payment_instruction_id = l_instr_id;
1424
1425 /* Also since the Payment Instruction is terminated
1426 * we should be unlocking the payment document which this
1427 * instruction may be locking to make it available for other
1428 * Done per bug 6852606
1429 */
1430 print_debuginfo(l_module_name, 'Trying to unlock the payment document as PI termination: ');
1431 UPDATE
1432 CE_PAYMENT_DOCUMENTS
1433 SET
1434 payment_instruction_id = NULL,
1435 /* Bug 6707369
1436 * If some of the documents are skipped, the payment
1437 * document's last issued check number must be updated
1438 */
1439 last_issued_document_number = nvl(
1440 (SELECT MAX(pmt.paper_document_number)
1441 FROM iby_payments_all pmt
1442 WHERE pmt.payment_instruction_id = l_instr_id)
1443 ,last_issued_document_number
1444 )
1445 WHERE
1446 payment_instruction_id = l_instr_id;
1447 print_debuginfo(l_module_name, 'Payment document unlocking successful for PI : ' || l_instr_id);
1448
1449 END IF;
1450
1451 END IF;
1452 /* ending if for the condition based on instruction id(Bug 7028817)*/
1453
1454
1455 /*
1456 * Get the application name of the calling app. This
1457 * will be used in the callout.
1458 */
1459 SELECT
1460 fnd.application_short_name
1461 INTO
1462 l_app_short_name
1463 FROM
1464 FND_APPLICATION fnd,
1465 IBY_PAYMENTS_ALL pmt,
1466 IBY_PAY_SERVICE_REQUESTS req
1467 WHERE
1468 fnd.application_id = req.calling_app_id AND
1469 req.payment_service_request_id = pmt.payment_service_request_id AND
1470 pmt.payment_id = p_pmt_id
1471 ;
1472
1473 /*
1474 * Get the constructed package name to use in the
1475 * call out.
1476 */
1477 l_pkg_name := construct_callout_pkg_name(l_app_short_name);
1478
1479 print_debuginfo(l_module_name, 'Constructed package name: '
1480 || l_pkg_name);
1481
1482 IF (l_pkg_name IS NULL) THEN
1483
1484 print_debuginfo(l_module_name, 'Package name is null. '
1485 || 'Raising exception.');
1486
1487 APP_EXCEPTION.RAISE_EXCEPTION;
1488
1489 END IF;
1490
1491 /*
1492 * Now try to call the external app's implementation of the hook.
1493 * The calling app may or may not have implemented the hook, so
1494 * it's not fatal if the implementation does not exist.
1495 */
1496 l_callout_name := l_pkg_name || '.' || 'documents_payable_rejected';
1497
1498 print_debuginfo(l_module_name, 'Attempting to invoke callout: '
1499 || l_callout_name);
1500
1501 l_stmt := 'CALL '|| l_callout_name || '(:1, :2, :3, :4, :5, :6, :7)';
1502
1503 BEGIN
1504
1505 EXECUTE IMMEDIATE
1506 (l_stmt)
1507 USING
1508 IN l_api_version,
1509 IN FND_API.G_FALSE,
1510 IN FND_API.G_FALSE,
1511 OUT x_return_status,
1512 OUT l_msg_count,
1513 OUT l_msg_data,
1514 IN l_rejection_id
1515 ;
1516
1517 /*
1518 * If the called procedure did not return success,
1519 * raise an exception.
1520 */
1521 IF (x_return_status IS NULL OR
1522 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1523
1524 print_debuginfo(l_module_name, 'Fatal: External app callout '''
1525 || l_callout_name
1526 || ''', returned failure status - '
1527 || x_return_status
1528 || '. Raising exception.'
1529 );
1530
1531 APP_EXCEPTION.RAISE_EXCEPTION;
1532
1533 END IF;
1534
1535 EXCEPTION
1536
1537 WHEN PROCEDURE_NOT_IMPLEMENTED THEN
1538 print_debuginfo(l_module_name, 'Callout "' || l_callout_name
1539 || '" not implemented by calling app '
1540 || l_app_short_name || '.');
1541
1542 print_debuginfo(l_module_name, 'Skipping hook call.');
1543
1544 WHEN OTHERS THEN
1545 print_debuginfo(l_module_name, 'Fatal: External app callout '''
1546 || l_callout_name
1547 || ''', generated exception.'
1548 );
1549
1550 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
1551 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
1552 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
1553
1554 /*
1555 * Propogate exception to caller.
1556 */
1557 RAISE;
1558 END;
1559
1560 x_return_status := FND_API.G_RET_STS_SUCCESS;
1561
1562 print_debuginfo(l_module_name, 'EXIT');
1563
1564 EXCEPTION
1565
1566 WHEN OTHERS THEN
1567
1568 print_debuginfo(l_module_name, 'Exception occured when '
1569 || 'stopping payment '
1570 || p_pmt_id
1571 || ', with status '
1572 || p_pmt_status
1573 );
1574
1575 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
1576 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
1577 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
1578
1579 x_return_status := FND_API.G_RET_STS_ERROR;
1580
1581 print_debuginfo(l_module_name, 'EXIT');
1582
1583 END stop_payment;
1584
1585 /*--------------------------------------------------------------------
1586 | NAME:
1587 | stop_payments
1588 |
1589 | PURPOSE:
1590 | Invokes a series of callouts of the calling app to remove
1591 | a set of submitted documents payable from the payment processing
1592 | cycle.
1593 |
1594 | The calling application can free up the removed documents, and
1595 | make them available for submission in future payment request(s).
1596 |
1597 | PARAMETERS:
1598 | IN
1599 | p_pmt_list - IDs of the payments to be stopped.
1600 | This should be an array of payment ids. All
1601 | the child documents payable of each of the
1602 | specified payments will be removed.
1603 |
1604 | p_pmt_status_list - Current statuses of the payments to
1605 | be stopped. This should be an array of statuses.
1606 |
1607 | OUT
1608 | x_return_status - Result of the API call:
1609 | FND_API.G_RET_STS_SUCCESS indicates that all
1610 | the callouts were invoked successfully.
1611 | In this case the caller must COMMIT
1612 | the status changes.
1613 |
1614 | FND_API.G_RET_STS_ERROR (or other) indicates
1615 | that at least one event did not complete
1616 | successfully. In this case, the caller must
1617 | issue a ROLLBACK to undo all status changes.
1618 |
1619 | RETURNS:
1620 |
1621 | NOTES:
1622 | Internal API, not for public use.
1623 |
1624 | This API will not do a COMMIT. It is the the callers responsbility
1625 | to perform COMMIT / ROLLBACK depending upon the returned status.
1626 |
1627 | The callouts invoked must be handled synchronously by the
1628 | calling application. So the COMMIT / ROLLBACK should affect
1629 | the changes made to the database by the calling application as
1630 | well. This will ensure that IBY and the calling application are
1631 | in sync w.r.t. to the specified documents payable.
1632 |
1633 *---------------------------------------------------------------------*/
1634 PROCEDURE stop_payments (
1635 p_pmt_list IN pmtIDTab,
1636 p_pmt_status_list IN pmtStatusTab,
1637 x_return_status OUT NOCOPY VARCHAR2
1638 )
1639 IS
1640
1641 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME || '.stop_payments';
1642
1643 BEGIN
1644
1645 print_debuginfo(l_module_name, 'ENTER');
1646
1647 FND_MSG_PUB.initialize;
1648
1649 IF (p_pmt_list.COUNT = 0 OR p_pmt_status_list.COUNT = 0) THEN
1650
1651 print_debuginfo(l_module_name, 'Error: List of payment '
1652 || 'payable ids/statuses is empty'
1653 || '. Returning failure response .. '
1654 );
1655
1656 x_return_status := FND_API.G_RET_STS_ERROR;
1657
1658 print_debuginfo(l_module_name, 'EXIT');
1659
1660 RETURN;
1661
1662 END IF;
1663
1664 IF (p_pmt_list.COUNT <> p_pmt_status_list.COUNT) THEN
1665
1666 print_debuginfo(l_module_name, 'Error: List of payment '
1667 || 'ids must match list of payment statuses. '
1668 || 'Returning failure response .. '
1669 );
1670
1671 x_return_status := FND_API.G_RET_STS_ERROR;
1672
1673 print_debuginfo(l_module_name, 'EXIT');
1674
1675 RETURN;
1676
1677 END IF;
1678
1679 /*
1680 * Start processing the payments, one-by-one.
1681 */
1682 FOR i IN p_pmt_list.FIRST .. p_pmt_list.LAST LOOP
1683
1684 stop_payment (
1685 p_pmt_list(i),
1686 p_pmt_status_list(i),
1687 x_return_status
1688 );
1689
1690 /*
1691 * Check if the call to stop the payment succeeded.
1692 */
1693 IF (x_return_status IS NULL OR
1694 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
1695
1696 /*
1697 * Even if a single call to stop a payment
1698 * failed, return failure for the entire API request.
1699 */
1700 print_debuginfo(l_module_name, 'Stopping of payment '
1701 || p_pmt_list(i)
1702 || ' failed.'
1703 );
1704
1705 print_debuginfo(l_module_name, 'EXIT');
1706
1707 /*
1708 * It is the callers responsibility to rollback
1709 * all the changes.
1710 */
1711 RETURN;
1712
1713 END IF;
1714
1715 END LOOP;
1716
1717 x_return_status := FND_API.G_RET_STS_SUCCESS;
1718
1719 print_debuginfo(l_module_name, 'Returning success response ..');
1720
1721 print_debuginfo(l_module_name, 'EXIT');
1722
1723 END stop_payments;
1724
1725 /*--------------------------------------------------------------------
1726 | NAME:
1727 | void_payment
1728 |
1729 | PURPOSE:
1730 | Sets the status of the specified payment id to VOID in the IBY
1731 | tables. This API is used in the AP void and reissue flow to keep
1732 | IBY and AP tables in sync.
1733 |
1734 | This API is meant for AP only and should not be used by the IBY UI.
1735 | There is a separate API for voiding payments from the IBY UI - see
1736 | void_pmt_internal(..) method.
1737 |
1738 | PARAMETERS:
1739 | IN
1740 | p_api_version - Version of the API.
1741 |
1742 | p_init_msg_list - Standard API parameter; default as FND_API.G_FALSE
1743 |
1744 | p_pmt_id - ID of the payment to be voided. This id will map
1745 | to IBY_PAYMENTS_ALL.PAYMENT_ID column.
1746 |
1747 | p_voided_by - User id of person who issued the void request.
1748 | This id will be stored as an attribute of the
1749 | payment.
1750 |
1751 | p_void_date - Date on which the void request was made.
1752 |
1753 | p_void_reason - Reason why this payment needs to be voided.
1754 |
1755 | OUT
1756 | x_return_status - Standard return status. Possible values are:
1757 | FND_API.G_RET_STS_SUCCESS
1758 | API completed successfully. Caller must
1759 | now COMMIT the database changes.
1760 |
1761 | FND_API.G_RET_STS_ERROR
1762 | API call failed. Caller must ROLLBACK any
1763 | base changes.
1764 |
1765 | x_msg_count - Standard msg count
1766 |
1767 | x_msg_data - Standard msg data
1768 |
1769 | RETURNS:
1770 |
1771 | NOTES:
1772 | Public API.
1773 |
1774 | This API will not do a COMMIT. It is the the callers responsbility
1775 | to perform COMMIT / ROLLBACK depending upon the returned status.
1776 |
1777 *---------------------------------------------------------------------*/
1778 PROCEDURE void_payment (
1779 p_api_version IN NUMBER,
1780 p_init_msg_list IN VARCHAR2 DEFAULT FND_API.G_FALSE,
1781 p_pmt_id IN NUMBER,
1782 p_voided_by IN NUMBER,
1783 p_void_date IN DATE,
1784 p_void_reason IN VARCHAR2,
1785 x_return_status OUT NOCOPY VARCHAR2,
1786 x_msg_count OUT NOCOPY NUMBER,
1787 x_msg_data OUT NOCOPY VARCHAR2
1788 )
1789 IS
1790
1791 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME || '.void_payment';
1792 l_calling_app_id NUMBER;
1793
1794 l_api_version CONSTANT NUMBER := 1.0;
1795 l_api_name CONSTANT VARCHAR2(100) := 'void_payment';
1796
1797 l_instr_id IBY_PAY_INSTRUCTIONS_ALL.payment_instruction_id%TYPE;
1798 l_valid_pmts_count
1799 NUMBER;
1800
1801 BEGIN
1802
1803 print_debuginfo(l_module_name, 'ENTER');
1804
1805 print_debuginfo(l_module_name, 'Parameters passed - '
1806 || 'payment id: '
1807 || p_pmt_id
1808 || ', voided by: '
1809 || p_voided_by
1810 || ', void date: '
1811 || p_void_date
1812 || ', void reason: '
1813 || p_void_reason
1814 );
1815
1816 /* Standard call to check for API compatibility */
1817 IF NOT FND_API.Compatible_API_Call(
1818 l_api_version,
1819 p_api_version,
1820 l_api_name,
1821 G_PKG_NAME) THEN
1822
1823 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1824
1825 END IF;
1826
1827 /* Initialize message list if p_init_msg_list is set to TRUE */
1828 IF FND_API.to_boolean(p_init_msg_list) THEN
1829 FND_MSG_PUB.initialize;
1830 END IF;
1831
1832 /* Initialize return status */
1833 x_return_status := FND_API.G_RET_STS_SUCCESS;
1834
1835 /*
1836 * STEP I:
1837 *
1838 * Void the specified payment.
1839 */
1840 UPDATE
1841 IBY_PAYMENTS_ALL
1842 SET
1843 payment_status = PAY_STATUS_VOID,
1844 voided_by = p_voided_by,
1845 void_date = p_void_date,
1846 void_reason = p_void_reason
1847 WHERE
1848 payment_id = p_pmt_id
1849 ;
1850
1851 print_debuginfo(l_module_name, 'Payment '
1852 || p_pmt_id
1853 || ' set to void status ..'
1854 );
1855
1856 /*
1857 * STEP II:
1858 *
1859 * Void the documents linked to this payment.
1860 */
1861 UPDATE
1862 IBY_DOCS_PAYABLE_ALL
1863 SET
1864 document_status = DOC_STATUS_PMT_VOIDED
1865 WHERE
1866 payment_id = p_pmt_id
1867 ;
1868
1869 print_debuginfo(l_module_name, 'Documents of payment '
1870 || p_pmt_id
1871 || ' set to void status ..'
1872 );
1873
1874 /*
1875 * STEP III:
1876 *
1877 * Fix for bug 5017119:
1878 *
1879 * After voiding this payment, check the payment instruction
1880 * to see whether any non-voided / non-removed payments
1881 * exist for this instruction.
1882 *
1883 * If this payment was the last valid payment on the instruction,
1884 * and we just voided it, then set the status of the instruction
1885 * to TERMINATED to signify that this is the final status for
1886 * the instruction.
1887 */
1888
1889 /*
1890 * Fix for bug 5108035:
1891 *
1892 * Don't assume that every payment to be voided will have an
1893 * associated payment instruction id; a manual payment will
1894 * not have a payment instruction id for example.
1895 *
1896 *
1897 * Therefore, if we run into an exception when attempting to
1898 * get the payment instruction of the payment to be voided,
1899 * treat it as non-fatal.
1900 */
1901 BEGIN
1902
1903 SELECT
1904 instr.payment_instruction_id
1905 INTO
1906 l_instr_id
1907 FROM
1908 IBY_PAY_INSTRUCTIONS_ALL instr,
1909 IBY_PAYMENTS_ALL pmt
1910 WHERE
1911 instr.payment_instruction_id = pmt.payment_instruction_id AND
1912 pmt.payment_id = p_pmt_id
1913 ;
1914
1915 print_debuginfo(l_module_name, 'Provided payment '
1916 || p_pmt_id
1917 || ' has payment instruction id '
1918 || l_instr_id
1919 || '. Checking this instruction for any remaining '
1920 || 'valid payments ..'
1921 );
1922
1923 SELECT
1924 count(*)
1925 INTO
1926 l_valid_pmts_count
1927 FROM
1928 IBY_PAYMENTS_ALL pmt
1929 WHERE
1930 pmt.payment_instruction_id = l_instr_id AND
1931 pmt.payment_status NOT IN
1932 (
1933 PAY_STATUS_VOID,
1934 PAY_STATUS_REMOVED
1935 )
1936 ;
1937
1938 print_debuginfo(l_module_name, 'Number of remaining valid payments '
1939 || 'for pmt instruction '
1940 || l_instr_id
1941 || ' is '
1942 || l_valid_pmts_count
1943 );
1944
1945 IF (l_valid_pmts_count = 0) THEN
1946
1947 /*
1948 * Set the payment instruction status to TERMINATED
1949 * because no valid payments now exist for this
1950 * payment instruction.
1951 */
1952 UPDATE
1953 IBY_PAY_INSTRUCTIONS_ALL
1954 SET
1955 payment_instruction_status = INS_STATUS_TERMINATED
1956 WHERE
1957 payment_instruction_id = l_instr_id
1958 ;
1959
1960 print_debuginfo(l_module_name, 'Status of payment instruction '
1961 || l_instr_id
1962 || ' updated to TERMINATED because it has no remaining '
1963 || 'valid payments.'
1964 );
1965
1966 /* Also since the Payment Instruction is terminated
1967 * we should be unlocking the payment document which this
1968 * instruction may be locking to make it available for other
1969 * Done per bug 6852606
1970 */
1971 print_debuginfo(l_module_name, 'Trying to unlock the payment document as PI termination: ');
1972 UPDATE
1973 CE_PAYMENT_DOCUMENTS
1974 SET
1975 payment_instruction_id = NULL,
1976 /* Bug 6707369
1977 * If some of the documents are skipped, the payment
1978 * document's last issued check number must be updated
1979 */
1980 last_issued_document_number = nvl(
1981 (SELECT MAX(pmt.paper_document_number)
1982 FROM iby_payments_all pmt
1983 WHERE pmt.payment_instruction_id = l_instr_id)
1984 ,last_issued_document_number
1985 )
1986 WHERE
1987 payment_instruction_id = l_instr_id;
1988 print_debuginfo(l_module_name, 'Payment document unlocking successful for PI : ' || l_instr_id);
1989
1990 END IF;
1991
1992 EXCEPTION
1993
1994 WHEN OTHERS THEN
1995
1996 print_debuginfo(l_module_name, 'Non-fatal: Exception occured '
1997 || 'when attempting to get parent payment instruction of '
1998 || 'payment '
1999 || p_pmt_id
2000 );
2001
2002 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
2003 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
2004
2005 END;
2006
2007 /*
2008 * Standard call to get message count and if count is 1, get
2009 * message info.
2010 */
2011 FND_MSG_PUB.Count_And_Get(
2012 p_encoded => FND_API.G_FALSE,
2013 p_count => x_msg_count,
2014 p_data => x_msg_data
2015 );
2016
2017 x_return_status := FND_API.G_RET_STS_SUCCESS;
2018 print_debuginfo(l_module_name, 'Returning success response ..');
2019
2020 print_debuginfo(l_module_name, 'EXIT');
2021
2022 EXCEPTION
2023
2024 WHEN OTHERS THEN
2025
2026 print_debuginfo(l_module_name, 'Exception occured when '
2027 || 'attempting to void payment id '
2028 || p_pmt_id
2029 );
2030
2031 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
2032 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
2033 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
2034
2035 x_return_status := FND_API.G_RET_STS_ERROR;
2036
2037 FND_MSG_PUB.Count_And_Get(
2038 p_encoded => FND_API.G_FALSE,
2039 p_count => x_msg_count,
2040 p_data => x_msg_data
2041 );
2042
2043 print_debuginfo(l_module_name, 'Returning error response ..');
2044 print_debuginfo(l_module_name, 'EXIT');
2045
2046 RETURN;
2047
2048 END void_payment;
2049
2050 /*--------------------------------------------------------------------
2051 | NAME:
2052 | void_pmt_internal
2053 |
2054 | PURPOSE:
2055 | Sets the status of the specified payment id to VOID in the IBY
2056 | tables. This API is used in the IBY UI to void a payment.
2057 |
2058 | This API is meant for IBY only and should not be used by AP.
2059 | There is a separate public API for voiding payments from AP - see
2060 | void_payment(..) method.
2061 |
2062 | PARAMETERS:
2063 | IN
2064 | p_api_version - Version of the API.
2065 |
2066 | p_init_msg_list - Standard API parameter; default as FND_API.G_FALSE
2067 |
2068 | p_pmt_id - ID of the payment to be voided. This id will map
2069 | to IBY_PAYMENTS_ALL.PAYMENT_ID column.
2070 |
2071 | p_voided_by - User id of person who issued the void request.
2072 | This id will be stored as an attribute of the
2073 | payment.
2074 |
2075 | p_void_date - Date on which the void request was made.
2076 |
2077 | p_void_reason - Reason why this payment needs to be voided.
2078 |
2079 | OUT
2080 | x_return_status - Standard return status. Possible values are:
2081 | FND_API.G_RET_STS_SUCCESS
2082 | API completed successfully. Caller must
2083 | now COMMIT the database changes.
2084 |
2085 | FND_API.G_RET_STS_ERROR
2086 | API call failed. Caller must ROLLBACK any
2087 | base changes.
2088 |
2089 | x_msg_count - Standard msg count
2090 |
2091 | x_msg_data - Standard msg data
2092 |
2093 | RETURNS:
2094 |
2095 | NOTES:
2096 | Internal API, not for public use.
2097 |
2098 | This API will not do a COMMIT. It is the the callers responsbility
2099 | to perform COMMIT / ROLLBACK depending upon the returned status.
2100 |
2101 *---------------------------------------------------------------------*/
2102 PROCEDURE void_pmt_internal (
2103 p_api_version IN NUMBER,
2104 p_init_msg_list IN VARCHAR2 DEFAULT FND_API.G_FALSE,
2105 p_pmt_id IN NUMBER,
2106 p_voided_by IN NUMBER,
2107 p_void_date IN DATE,
2108 p_void_reason IN VARCHAR2,
2109 x_return_status OUT NOCOPY VARCHAR2,
2110 x_msg_count OUT NOCOPY NUMBER,
2111 x_msg_data OUT NOCOPY VARCHAR2
2112 )
2113 IS
2114
2115 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME || '.void_pmt_internal';
2116 l_calling_app_id NUMBER;
2117
2118 l_api_version CONSTANT NUMBER := 1.0;
2119 l_api_name CONSTANT VARCHAR2(100) := 'void_pmt_internal';
2120
2121 /* used in forming callout procedure name */
2122 l_app_short_name VARCHAR2(200);
2123 l_pkg_name VARCHAR2(200);
2124 l_callout_name VARCHAR2(500);
2125 l_stmt VARCHAR2(1000);
2126
2127 /* used in invocation of callout procedure */
2128 l_msg_count NUMBER;
2129 l_msg_data VARCHAR2(2000);
2130
2131 l_ret_flag VARCHAR2(1) := 'Y';
2132
2133 l_test VARCHAR2(2000);
2134 l_org NUMBER(15);
2135
2136 l_instr_id IBY_PAY_INSTRUCTIONS_ALL.payment_instruction_id%TYPE;
2137
2138 l_valid_pmts_count NUMBER;
2139 l_curr_pmt_status VARCHAR2(200);
2140
2141 /*
2142 * Implementing the callout is optional for the calling app.
2143 * If the calling app does not implement the hook, then
2144 * the call to the hook will result in ORA-06576 error.
2145 *
2146 * There is no exception name associated with this code, so
2147 * we create one called 'PROCEDURE_NOT_IMPLEMENTED'. If this
2148 * exception occurs, it is not fatal: we log the error and
2149 * proceed.
2150 *
2151 * If, on the other hand, the calling app implements the
2152 * callout, but the callout throws an exception, it is fatal
2153 * and we must abort the program (this will be caught
2154 * in WHEN OTHERS block).
2155 */
2156 PROCEDURE_NOT_IMPLEMENTED EXCEPTION;
2157 PRAGMA EXCEPTION_INIT(PROCEDURE_NOT_IMPLEMENTED, -6576);
2158
2159 BEGIN
2160
2161 print_debuginfo(l_module_name, 'ENTER');
2162
2163 /*
2164 * Set the apps context. This is necessary so that
2165 * the calling application can see the org based
2166 * tables associated with this payment.
2167 *
2168 * See bug 4945922.
2169 */
2170 print_debuginfo(l_module_name, 'Setting apps context .. ');
2171
2172 fnd_global.APPS_INITIALIZE(
2173 user_id => fnd_global.user_id,
2174 resp_id => fnd_global.resp_id,
2175 resp_appl_id => fnd_global.resp_appl_id
2176 );
2177
2178 mo_global.init(fnd_global.application_short_name);
2179
2180 print_debuginfo(l_module_name, 'Apps context set [user: '
2181 || fnd_global.user_id
2182 || ', responsbility id: '
2183 || fnd_global.resp_id
2184 || ', responsibility application id: '
2185 || fnd_global.resp_appl_id
2186 || ']'
2187 );
2188
2189 print_debuginfo(l_module_name, 'Apps context [app short name: '
2190 || fnd_global.application_short_name
2191 || ']'
2192 );
2193
2194 /*--- RYAN TEST CODE ---*/
2195 /*---- start ----*/
2196 /*
2197 begin
2198 print_debuginfo(l_module_name, 'Start RYAN test');
2199 select 'row found in moac synonym'
2200 into l_test
2201 from ap_invoices
2202 where invoice_id = 10045;
2203 print_debuginfo(l_module_name, 'End RYAN test: l_test = ' || l_test);
2204 exception
2205 when no_data_found then
2206 print_debuginfo('RYAN TEST: ap_pmt_callout_pkg',
2207 'in no data found exception');
2208 end;
2209 */
2210 /*---- end ----*/
2211
2212 /*--- YING TEST CODE ---*/
2213 /*---- start ----*/
2214 /*
2215 begin
2216 print_debuginfo(l_module_name, 'Start YING test');
2217 select organization_id
2218 into l_org
2219 from ce_security_profiles_v
2220 where organization_type='OPERATING_UNIT';
2221 print_debuginfo(l_module_name, 'End YING test: l_org = ' || l_org);
2222 exception
2223 when no_data_found then
2224 print_debuginfo('YING TEST: org id',
2225 'in no data found exception');
2226 end;
2227 */
2228 /*---- end ----*/
2229
2230 /* Standard call to check for API compatibility */
2231 IF NOT FND_API.Compatible_API_Call(
2232 l_api_version,
2233 p_api_version,
2234 l_api_name,
2235 G_PKG_NAME) THEN
2236
2237 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
2238
2239 END IF;
2240
2241 /* Initialize message list if p_init_msg_list is set to TRUE */
2242 IF FND_API.to_boolean(p_init_msg_list) THEN
2243 FND_MSG_PUB.initialize;
2244 END IF;
2245
2246 /* Initialize return status */
2247 x_return_status := FND_API.G_RET_STS_SUCCESS;
2248
2249 /*
2250 * Fix for bug 5623941:
2251 *
2252 * STEP I:
2253 *
2254 * Before doing anything check if the payment is already
2255 * voided. If it is already voided, we don't need to do anything;
2256 * just exit.
2257 */
2258
2259 /*
2260 * Get the current status of the
2261 * payment into l_curr_pmt_status
2262 */
2263 SELECT
2264 pmt.payment_status
2265 INTO
2266 l_curr_pmt_status
2267 FROM
2268 IBY_PAYMENTS_ALL pmt
2269 WHERE
2270 payment_id = p_pmt_id
2271 ;
2272
2273 IF (l_curr_pmt_status = PAY_STATUS_VOID) THEN
2274
2275 print_debuginfo(l_module_name, 'Payment '
2276 || p_pmt_id
2277 || ' is already voided. Skipping .. '
2278 );
2279
2280 x_return_status := FND_API.G_RET_STS_SUCCESS;
2281
2282 print_debuginfo(l_module_name, 'Returning success response ..');
2283 print_debuginfo(l_module_name, 'EXIT');
2284
2285 RETURN;
2286
2287 END IF;
2288
2289 /*
2290 * STEP II:
2291 *
2292 * Check if the external application allows this payment
2293 * to be voided. If not there is no point in proceeding
2294 * further.
2295 */
2296 is_void_allowed (
2297 p_api_version,
2298 FND_API.G_FALSE,
2299 p_pmt_id,
2300 l_ret_flag,
2301 x_return_status,
2302 x_msg_count,
2303 x_msg_data
2304 );
2305
2306 print_debuginfo(l_module_name, 'Void allowed flag '
2307 || 'after call to is_void_allowed() API: '
2308 || l_ret_flag
2309 );
2310
2311 /*
2312 * If the void allowed flag is not set to 'Y',
2313 * exit the procedure with an error.
2314 */
2315 IF (UPPER(l_ret_flag) <> 'Y') THEN
2316
2317 print_debuginfo(l_module_name, 'Void not allowed. '
2318 || 'Returning failure response.'
2319 );
2320
2321 x_return_status := FND_API.G_RET_STS_ERROR;
2322
2323 FND_MSG_PUB.Count_And_Get(
2324 p_encoded => FND_API.G_FALSE,
2325 p_count => x_msg_count,
2326 p_data => x_msg_data
2327 );
2328
2329 print_debuginfo(l_module_name, 'EXIT');
2330
2331 RETURN;
2332
2333 END IF;
2334
2335 /*
2336 * STEP III:
2337 *
2338 * Void the specified payment.
2339 */
2340 UPDATE
2341 IBY_PAYMENTS_ALL
2342 SET
2343 payment_status = PAY_STATUS_VOID,
2344 voided_by = p_voided_by,
2345 void_date = p_void_date,
2346 void_reason = p_void_reason
2347 WHERE
2348 payment_id = p_pmt_id
2349 ;
2350
2351 /*
2352 * STEP IV:
2353 *
2354 * Void the documents linked to this payment.
2355 */
2356 UPDATE
2357 IBY_DOCS_PAYABLE_ALL
2358 SET
2359 document_status = DOC_STATUS_PMT_VOIDED
2360 WHERE
2361 payment_id = p_pmt_id
2362 ;
2363
2364 /*
2365 * STEP V:
2366 *
2367 * Fix for bug 5017119:
2368 *
2369 * After voiding this payment, check the payment instruction
2370 * to see whether any non-voided / non-removed payments
2371 * exist for this instruction.
2372 *
2373 * If this payment was the last valid payment on the instruction,
2374 * and we just voided it, then set the status of the instruction
2375 * to TERMINATED to signify that this is the final status for
2376 * the instruction.
2377 */
2378 SELECT
2379 instr.payment_instruction_id
2380 INTO
2381 l_instr_id
2382 FROM
2383 IBY_PAY_INSTRUCTIONS_ALL instr,
2384 IBY_PAYMENTS_ALL pmt
2385 WHERE
2386 instr.payment_instruction_id = pmt.payment_instruction_id AND
2387 pmt.payment_id = p_pmt_id
2388 ;
2389
2390 print_debuginfo(l_module_name, 'Provided payment '
2391 || p_pmt_id
2392 || ' has payment instruction id '
2393 || l_instr_id
2394 || '. Checking this instruction for any remaining valid payments ..'
2395 );
2396
2397 SELECT
2398 count(*)
2399 INTO
2400 l_valid_pmts_count
2401 FROM
2402 IBY_PAYMENTS_ALL pmt
2403 WHERE
2404 pmt.payment_instruction_id = l_instr_id AND
2405 pmt.payment_status NOT IN
2406 (
2407 PAY_STATUS_VOID,
2408 PAY_STATUS_REMOVED
2409 )
2410 ;
2411
2412 print_debuginfo(l_module_name, 'Number of remaining valid payments '
2413 || 'for pmt instruction '
2414 || l_instr_id
2415 || ' is '
2416 || l_valid_pmts_count
2417 );
2418
2419 IF (l_valid_pmts_count = 0) THEN
2420
2421 /*
2422 * Set the payment instruction status to TERMINATED
2423 * because no valid payments now exist for this
2424 * payment instruction.
2425 */
2426 UPDATE
2427 IBY_PAY_INSTRUCTIONS_ALL
2428 SET
2429 payment_instruction_status = INS_STATUS_TERMINATED
2430 WHERE
2431 payment_instruction_id = l_instr_id
2432 ;
2433
2434 print_debuginfo(l_module_name, 'Status of payment instruction '
2435 || l_instr_id
2436 || ' updated to TERMINATED because it has no remaining '
2437 || 'valid payments.'
2438 );
2439
2440 /* Also since the Payment Instruction is terminated
2441 * we should be unlocking the payment document which this
2442 * instruction may be locking to make it available for other
2443 * Done per bug 6852606
2444 */
2445 print_debuginfo(l_module_name, 'Trying to unlock the payment document as PI termination: ');
2446 UPDATE
2447 CE_PAYMENT_DOCUMENTS
2448 SET
2449 payment_instruction_id = NULL,
2450 /* Bug 6707369
2451 * If some of the documents are skipped, the payment
2452 * document's last issued check number must be updated
2453 */
2454 last_issued_document_number = nvl(
2455 (SELECT MAX(pmt.paper_document_number)
2456 FROM iby_payments_all pmt
2457 WHERE pmt.payment_instruction_id = l_instr_id)
2458 ,last_issued_document_number
2459 )
2460 WHERE
2461 payment_instruction_id = l_instr_id;
2462 print_debuginfo(l_module_name, 'Payment document unlocking successful for PI : ' || l_instr_id);
2463
2464
2465 END IF;
2466
2467 /*
2468 * STEP VI:
2469 *
2470 * Call external application hook to inform it of
2471 * the voided payments.
2472 */
2473
2474 /*
2475 * Get the application name of the calling app. This
2476 * will be used in the callout.
2477 */
2478 SELECT
2479 fnd.application_short_name
2480 INTO
2481 l_app_short_name
2482 FROM
2483 FND_APPLICATION fnd,
2484 IBY_PAYMENTS_ALL pmt,
2485 IBY_PAY_SERVICE_REQUESTS req
2486 WHERE
2487 fnd.application_id = req.calling_app_id AND
2488 req.payment_service_request_id = pmt.payment_service_request_id AND
2489 pmt.payment_id = p_pmt_id
2490 ;
2491
2492 /*
2493 * Get the constructed package name to use in the
2494 * call out.
2495 */
2496 l_pkg_name := construct_callout_pkg_name(l_app_short_name);
2497
2498 print_debuginfo(l_module_name, 'Constructed package name: '
2499 || l_pkg_name);
2500
2501 IF (l_pkg_name IS NULL) THEN
2502
2503 print_debuginfo(l_module_name, 'Package name is null. '
2504 || 'Raising exception.');
2505
2506 APP_EXCEPTION.RAISE_EXCEPTION;
2507
2508 END IF;
2509
2510 /*
2511 * Now try to call the external app's implementation of the hook.
2512 * The calling app may or may not have implemented the hook, so
2513 * it's not fatal if the implementation does not exist.
2514 */
2515 l_callout_name := l_pkg_name || '.' || 'payment_voided';
2516
2517 print_debuginfo(l_module_name, 'Attempting to invoke callout: '
2518 || l_callout_name);
2519
2520 --l_stmt := 'CALL '|| l_callout_name
2521 -- || '(:1, :2, :3, :4, :5, :6, :7, :8)';
2522
2523 l_stmt := 'BEGIN '|| l_callout_name
2524 || '('
2525 || 'p_api_version => :1, '
2526 || 'p_payment_id => :2, '
2527 || 'p_void_date => :3, '
2528 || 'p_init_msg_list => :4, '
2529 || 'p_commit => :5, '
2530 || 'x_return_status => :6, '
2531 || 'x_msg_count => :7, '
2532 || 'x_msg_data => :8 '
2533 || '); END;'
2534 ;
2535
2536 BEGIN
2537
2538 print_debuginfo(l_module_name, 'Params passed to callout - ');
2539 print_debuginfo(l_module_name, 'p_pmt_id: ' || p_pmt_id);
2540 print_debuginfo(l_module_name, 'p_void_date: ' || p_void_date);
2541
2542 EXECUTE IMMEDIATE
2543 (l_stmt)
2544 USING
2545 IN l_api_version,
2546 IN p_pmt_id,
2547 IN p_void_date,
2548 IN FND_API.G_FALSE,
2549 IN FND_API.G_FALSE, /* commit flag */
2550 OUT x_return_status,
2551 OUT l_msg_count,
2552 OUT l_msg_data
2553 ;
2554
2555 print_debuginfo(l_module_name, 'Finished invoking callout ..');
2556 print_debuginfo(l_module_name, 'Status returned by callout: '
2557 || x_return_status);
2558
2559 /*
2560 * If the called procedure did not return success,
2561 * raise an exception.
2562 */
2563 IF (x_return_status IS NULL OR
2564 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
2565
2566 print_debuginfo(l_module_name, 'Fatal: External app callout '''
2567 || l_callout_name
2568 || ''', returned failure status - '
2569 || x_return_status
2570 || '. Raising exception.'
2571 );
2572
2573 APP_EXCEPTION.RAISE_EXCEPTION;
2574
2575 END IF;
2576
2577 EXCEPTION
2578
2579 WHEN PROCEDURE_NOT_IMPLEMENTED THEN
2580 print_debuginfo(l_module_name, 'Callout "' || l_callout_name
2581 || '" not implemented by calling app '
2582 || l_app_short_name || '.');
2583
2584 print_debuginfo(l_module_name, 'Skipping hook call.');
2585
2586 WHEN OTHERS THEN
2587 print_debuginfo(l_module_name, 'Fatal: External app callout '''
2588 || l_callout_name
2589 || ''', generated exception.'
2590 );
2591
2592 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
2593 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
2594 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
2595
2596 /*
2597 * Propogate exception to caller.
2598 */
2599 RAISE;
2600 END;
2601
2602 /*
2603 * Standard call to get message count and if count is 1, get
2604 * message info.
2605 */
2606 FND_MSG_PUB.Count_And_Get(
2607 p_encoded => FND_API.G_FALSE,
2608 p_count => x_msg_count,
2609 p_data => x_msg_data
2610 );
2611
2612 x_return_status := FND_API.G_RET_STS_SUCCESS;
2613 print_debuginfo(l_module_name, 'Returning success response ..');
2614
2615 print_debuginfo(l_module_name, 'EXIT');
2616
2617 EXCEPTION
2618 WHEN OTHERS THEN
2619
2620 print_debuginfo(l_module_name, 'Exception occured when '
2621 || 'attempting to void payment id '
2622 || p_pmt_id
2623 );
2624
2625 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
2626 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
2627 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
2628
2629 x_return_status := FND_API.G_RET_STS_ERROR;
2630
2631 FND_MSG_PUB.Count_And_Get(
2632 p_encoded => FND_API.G_FALSE,
2633 p_count => x_msg_count,
2634 p_data => x_msg_data
2635 );
2636
2637 print_debuginfo(l_module_name, 'Returning error response ..');
2638 print_debuginfo(l_module_name, 'EXIT');
2639
2640 RETURN;
2641
2642 END void_pmt_internal;
2643
2644 /*--------------------------------------------------------------------
2645 | NAME:
2646 | is_void_allowed
2647 |
2648 |
2649 | PURPOSE:
2650 |
2651 |
2652 | PARAMETERS:
2653 | IN
2654 |
2655 |
2656 | OUT
2657 |
2658 |
2659 | RETURNS:
2660 |
2661 | NOTES:
2662 |
2663 *---------------------------------------------------------------------*/
2664 PROCEDURE is_void_allowed (
2665 p_api_version IN NUMBER,
2666 p_init_msg_list IN VARCHAR2 DEFAULT FND_API.G_FALSE,
2667 p_pmt_id IN NUMBER,
2668 x_return_flag OUT NOCOPY VARCHAR2, /* 'Y'/'N' flag */
2669 x_return_status OUT NOCOPY VARCHAR2,
2670 x_msg_count OUT NOCOPY NUMBER,
2671 x_msg_data OUT NOCOPY VARCHAR2
2672 )
2673 IS
2674
2675 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME || '.is_void_allowed';
2676
2677 /* used in forming callout procedure name */
2678 l_app_short_name VARCHAR2(200);
2679 l_pkg_name VARCHAR2(200);
2680 l_callout_name VARCHAR2(500);
2681 l_stmt VARCHAR2(1000);
2682
2683 /* used in invocation of callout procedure */
2684 l_api_version CONSTANT NUMBER := 1.0;
2685 l_msg_count NUMBER;
2686 l_msg_data VARCHAR2(2000);
2687
2688 l_api_name CONSTANT VARCHAR2(100) := 'is_void_allowed';
2689
2690 /*
2691 * Implementing the callout is optional for the calling app.
2692 * If the calling app does not implement the hook, then
2693 * the call to the hook will result in ORA-06576 error.
2694 *
2695 * There is no exception name associated with this code, so
2696 * we create one called 'PROCEDURE_NOT_IMPLEMENTED'. If this
2697 * exception occurs, it is not fatal: we log the error and
2698 * proceed.
2699 *
2700 * If, on the other hand, the calling app implements the
2701 * callout, but the callout throws an exception, it is fatal
2702 * and we must abort the program (this will be caught
2703 * in WHEN OTHERS block).
2704 */
2705 PROCEDURE_NOT_IMPLEMENTED EXCEPTION;
2706 PRAGMA EXCEPTION_INIT(PROCEDURE_NOT_IMPLEMENTED, -6576);
2707
2708 BEGIN
2709
2710 print_debuginfo(l_module_name, 'ENTER');
2711
2712 /* Standard call to check for API compatibility */
2713 IF NOT FND_API.Compatible_API_Call(
2714 l_api_version,
2715 p_api_version,
2716 l_api_name,
2717 G_PKG_NAME) THEN
2718
2719 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
2720
2721 END IF;
2722
2723 /* Initialize message list if p_init_msg_list is set to TRUE */
2724 IF FND_API.to_boolean(p_init_msg_list) THEN
2725 FND_MSG_PUB.initialize;
2726 END IF;
2727
2728 /* Initialize return status */
2729 x_return_status := FND_API.G_RET_STS_SUCCESS;
2730
2731 /*
2732 * Get the application name of the calling app. This
2733 * will be used in the callout.
2734 */
2735 SELECT
2736 fnd.application_short_name
2737 INTO
2738 l_app_short_name
2739 FROM
2740 FND_APPLICATION fnd,
2741 IBY_PAYMENTS_ALL pmt,
2742 IBY_PAY_SERVICE_REQUESTS req
2743 WHERE
2744 fnd.application_id = req.calling_app_id AND
2745 req.payment_service_request_id = pmt.payment_service_request_id AND
2746 pmt.payment_id = p_pmt_id
2747 ;
2748
2749 /*
2750 * Get the constructed package name to use in the
2751 * call out.
2752 */
2753 l_pkg_name := construct_callout_pkg_name(l_app_short_name);
2754
2755 print_debuginfo(l_module_name, 'Constructed package name: '
2756 || l_pkg_name);
2757
2758 IF (l_pkg_name IS NULL) THEN
2759
2760 print_debuginfo(l_module_name, 'Package name is null. '
2761 || 'Raising exception.');
2762
2763 APP_EXCEPTION.RAISE_EXCEPTION;
2764
2765 END IF;
2766
2767 /*
2768 * Now try to call the external app's implementation of the hook.
2769 * The calling app may or may not have implemented the hook, so
2770 * it's not fatal if the implementation does not exist.
2771 */
2772 l_callout_name := l_pkg_name || '.' || 'void_payment_allowed';
2773
2774 print_debuginfo(l_module_name, 'Attempting to invoke callout: '
2775 || l_callout_name);
2776
2777 l_stmt := 'CALL '|| l_callout_name || '(:1, :2, :3, :4, :5, :6, :7, :8)';
2778
2779 BEGIN
2780
2781 EXECUTE IMMEDIATE
2782 (l_stmt)
2783 USING
2784 IN l_api_version,
2785 IN FND_API.G_FALSE,
2786 IN FND_API.G_FALSE,
2787 IN p_pmt_id,
2788 OUT x_return_flag,
2789 OUT x_return_status,
2790 OUT l_msg_count,
2791 OUT l_msg_data
2792 ;
2793
2794 /*
2795 * If the called procedure did not return success,
2796 * raise an exception.
2797 */
2798 IF (x_return_status IS NULL OR
2799 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
2800
2801 print_debuginfo(l_module_name, 'Fatal: External app callout '''
2802 || l_callout_name
2803 || ''', returned failure status - '
2804 || x_return_status
2805 || '. Raising exception.'
2806 );
2807
2808 APP_EXCEPTION.RAISE_EXCEPTION;
2809
2810 END IF;
2811
2812 EXCEPTION
2813
2814 WHEN PROCEDURE_NOT_IMPLEMENTED THEN
2815 print_debuginfo(l_module_name, 'Callout "' || l_callout_name
2816 || '" not implemented by calling app '
2817 || l_app_short_name || '.');
2818
2819 print_debuginfo(l_module_name, 'Skipping hook call.');
2820
2821 /*
2822 * Fix for bug 5083294:
2823 *
2824 * Default the return flag to 'Y' (meaning
2825 * void is allowed) in case the calling
2826 * application has not implemented this
2827 * callout.
2828 */
2829 x_return_flag := 'Y';
2830
2831 print_debuginfo(l_module_name, 'Defaulting x_return_flag to '
2832 || ''''
2833 || x_return_flag
2834 || ''''
2835 || ' [Meaning: void is allowed by default]'
2836 );
2837
2838 WHEN OTHERS THEN
2839 print_debuginfo(l_module_name, 'Fatal: External app callout '''
2840 || l_callout_name
2841 || ''', generated exception.'
2842 );
2843
2844 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
2845 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
2846 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
2847
2848 /*
2849 * Propogate exception to caller.
2850 */
2851 RAISE;
2852 END;
2853
2854 x_return_status := FND_API.G_RET_STS_SUCCESS;
2855
2856 print_debuginfo(l_module_name, 'EXIT');
2857
2858 EXCEPTION
2859
2860 WHEN OTHERS THEN
2861
2862 print_debuginfo(l_module_name, 'Exception occured when '
2863 || 'checking voidability of payment '
2864 || p_pmt_id
2865 );
2866
2867 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
2868 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
2869 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
2870
2871 x_return_status := FND_API.G_RET_STS_ERROR;
2872
2873 print_debuginfo(l_module_name, 'EXIT');
2874
2875 END is_void_allowed;
2876
2877 /*--------------------------------------------------------------------
2878 | NAME:
2879 | void_pmts_internal
2880 |
2881 | PURPOSE:
2882 | Invokes a series of callouts of the calling app to remove
2883 | a set of submitted documents payable from the payment processing
2884 | cycle.
2885 |
2886 | The calling application can free up the removed documents, and
2887 | make them available for submission in future payment request(s).
2888 |
2889 | PARAMETERS:
2890 | IN
2891 | p_pmt_list - IDs of the payments to be stopped.
2892 | This should be an array of payment ids. All
2893 | the child documents payable of each of the
2894 | specified payments will be removed.
2895 |
2896 | p_pmt_status_list - Current statuses of the payments to
2897 | be stopped. This should be an array of statuses.
2898 |
2899 | p_voided_by - User id of person who issued the void request.
2900 | This id will be stored as an attribute of the
2901 | payment.
2902 |
2903 | p_void_date - Date on which the void request was made.
2904 |
2905 | p_void_reason - Reason why this payment needs to be voided.
2906 |
2907 | OUT
2908 | x_return_status - Result of the API call:
2909 | FND_API.G_RET_STS_SUCCESS indicates that all
2910 | the callouts were invoked successfully.
2911 | In this case the caller must COMMIT
2912 | the status changes.
2913 |
2914 | FND_API.G_RET_STS_ERROR (or other) indicates
2915 | that at least one event did not complete
2916 | successfully. In this case, the caller must
2917 | issue a ROLLBACK to undo all status changes.
2918 |
2919 | RETURNS:
2920 |
2921 | NOTES:
2922 | Internal API, not for public use.
2923 |
2924 | This API will not do a COMMIT. It is the the callers responsbility
2925 | to perform COMMIT / ROLLBACK depending upon the returned status.
2926 |
2927 | The callouts invoked must be handled synchronously by the
2928 | calling application. So the COMMIT / ROLLBACK should affect
2929 | the changes made to the database by the calling application as
2930 | well. This will ensure that IBY and the calling application are
2931 | in sync w.r.t. to the specified documents payable.
2932 |
2933 *---------------------------------------------------------------------*/
2934 PROCEDURE void_pmts_internal (
2935 p_instr_id IN NUMBER,
2936 p_voided_by IN NUMBER,
2937 p_void_date IN DATE,
2938 p_void_reason IN VARCHAR2,
2939 x_return_status OUT NOCOPY VARCHAR2
2940 )
2941 IS
2942
2943 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME || '.void_pmts_internal';
2944
2945 l_api_version CONSTANT NUMBER := 1.0;
2946 l_msg_count NUMBER;
2947 l_msg_data VARCHAR2(2000);
2948
2949 l_pmts_list pmtIDTab;
2950
2951 CURSOR c_payments (p_instr_id IN NUMBER)
2952 IS
2953 SELECT
2954 payment_id
2955 FROM
2956 IBY_PAYMENTS_ALL
2957 WHERE
2958 payment_instruction_id = p_instr_id AND
2959 payments_complete_flag = 'Y'
2960 ;
2961
2962 BEGIN
2963
2964 print_debuginfo(l_module_name, 'ENTER');
2965
2966 FND_MSG_PUB.initialize;
2967
2968 /*
2969 * Pick up all qualifying payments of the payment instruction.
2970 */
2971 OPEN c_payments(p_instr_id);
2972 FETCH c_payments BULK COLLECT INTO l_pmts_list;
2973 CLOSE c_payments;
2974
2975 /*
2976 * Return failure if no payments were found.
2977 */
2978 IF (l_pmts_list.COUNT = 0) THEN
2979
2980 print_debuginfo(l_module_name, 'No completed payments '
2981 || ' were found for payment instruction id '
2982 || p_instr_id
2983 );
2984
2985 x_return_status := FND_API.G_RET_STS_ERROR;
2986
2987 print_debuginfo(l_module_name, 'EXIT');
2988
2989 RETURN;
2990
2991 END IF;
2992
2993 /*
2994 * Start processing the payments, one-by-one.
2995 */
2996 FOR i IN l_pmts_list.FIRST .. l_pmts_list.LAST LOOP
2997
2998 void_pmt_internal (
2999 l_api_version,
3000 FND_API.G_FALSE,
3001 l_pmts_list(i),
3002 p_voided_by,
3003 p_void_date,
3004 p_void_reason,
3005 x_return_status,
3006 l_msg_count,
3007 l_msg_data
3008 );
3009
3010 /*
3011 * Check if the call to stop the payment succeeded.
3012 */
3013 IF (x_return_status IS NULL OR
3014 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
3015
3016 /*
3017 * Even if a single call to remove a payment
3018 * failed, return failure for the entire API request.
3019 */
3020 print_debuginfo(l_module_name, 'Voiding of completed payment '
3021 || l_pmts_list(i)
3022 || ' failed.'
3023 );
3024
3025 print_debuginfo(l_module_name, 'EXIT');
3026
3027 /*
3028 * It is the callers responsibility to rollback
3029 * all the changes.
3030 */
3031 RETURN;
3032
3033 END IF;
3034
3035 END LOOP;
3036
3037 /*
3038 * If we reached here, it means that all payments
3039 * of the given payment instruction have been
3040 * voided successfully.
3041 */
3042 print_debuginfo(l_module_name, 'All payments of payment '
3043 || 'instruction id '
3044 || p_instr_id
3045 || ' voided successfully.'
3046 );
3047
3048 /*
3049 * Fix for bug 5017119:
3050 *
3051 * After voiding all the payments of an instruction,
3052 * change the instruction status to TERMINATED
3053 * so that user cannot take any further action on the
3054 * payment instruction.
3055 */
3056 UPDATE
3057 iby_pay_instructions_all
3058 SET
3059 payment_instruction_status = INS_STATUS_TERMINATED
3060 WHERE
3061 payment_instruction_id = p_instr_id
3062 ;
3063
3064 print_debuginfo(l_module_name, 'Status of payment instruction '
3065 || p_instr_id
3066 || ' set to TERMINATED because all payments have been voided.'
3067 );
3068
3069 x_return_status := FND_API.G_RET_STS_SUCCESS;
3070
3071 print_debuginfo(l_module_name, 'Returning success response ..');
3072
3073 print_debuginfo(l_module_name, 'EXIT');
3074
3075 END void_pmts_internal;
3076
3077 /*--------------------------------------------------------------------
3078 | NAME:
3079 | validate_paper_doc_number
3080 |
3081 | PURPOSE:
3082 | Validates that the given paper document number is valid for the
3083 | given payment document (check stock) id.
3084 |
3085 | PARAMETERS:
3086 | IN
3087 | p_api_version - Version of the API.
3088 |
3089 | p_init_msg_list - Standard API parameter; default as FND_API.G_FALSE
3090 |
3091 | p_payment_doc_id
3092 | - ID of the payment document (check stock) to use.
3093 |
3094 | IN/OUT
3095 | x_paper_doc_num - Paper document number (check number) to use.
3096 | If a value is provided, this value will be validated.
3097 | If no value (i.e., NULL) is provided, then the
3098 | next available paper document number will be
3099 | returned as an output parameter.
3100 |
3101 | OUT
3102 | x_return_status - Standard return status. Possible values are:
3103 | FND_API.G_RET_STS_SUCCESS
3104 | The given paper document number is valid
3105 | for the given payment document.
3106 |
3107 | It is possible that there were warnings.
3108 | Please unwind the FND message stack to
3109 | check if there were any warnings to display
3110 | to the user.
3111 |
3112 | FND_API.G_RET_STS_ERROR
3113 | The given paper document number is invalid.
3114 | Possible reasons are the paper document number
3115 | has already been used, or the paper document
3116 | number is not in the valid range for the given
3117 | payment document.
3118 |
3119 | x_msg_count - Standard msg count
3120 |
3121 | x_msg_data - Standard msg data
3122 |
3123 | RETURNS:
3124 |
3125 | NOTES:
3126 | Public API.
3127 |
3128 | This API will not do a COMMIT/ROLLBACK. There are no database
3129 | state changes implemented by this API. It is a read only API.
3130 |
3131 *---------------------------------------------------------------------*/
3132 PROCEDURE validate_paper_doc_number (
3133 p_api_version IN NUMBER,
3134 p_init_msg_list IN VARCHAR2 DEFAULT FND_API.G_FALSE,
3135 p_payment_doc_id IN NUMBER,
3136 x_paper_doc_num IN OUT NOCOPY NUMBER,
3137 x_return_status OUT NOCOPY VARCHAR2,
3138 x_msg_count OUT NOCOPY NUMBER,
3139 x_msg_data OUT NOCOPY VARCHAR2,
3140 show_warn_msgs_flag IN VARCHAR2 DEFAULT FND_API.G_TRUE
3141 )
3142 IS
3143
3144 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
3145 || '.validate_paper_doc_number';
3146
3147 l_api_version CONSTANT NUMBER := 1.0;
3148 l_api_name CONSTANT VARCHAR2(100) := 'validate_paper_doc_number';
3149
3150 l_error_code VARCHAR2(3000);
3151
3152 l_last_used_check_num NUMBER := 0;
3153 l_next_check_number NUMBER := 0;
3154
3155 l_first_avail_check_num NUMBER := 0;
3156 l_last_avail_check_num NUMBER := 0;
3157 l_pmt_doc_name VARCHAR2(200) := '';
3158 l_used_paper_doc_number NUMBER := 0;
3159
3160 l_flag BOOLEAN;
3161
3162 BEGIN
3163
3164 print_debuginfo(l_module_name, 'ENTER');
3165
3166 /* Standard call to check for API compatibility */
3167 IF NOT FND_API.Compatible_API_Call(
3168 l_api_version,
3169 p_api_version,
3170 l_api_name,
3171 G_PKG_NAME) THEN
3172
3173 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
3174
3175 END IF;
3176
3177 /* Initialize message list if p_init_msg_list is set to TRUE */
3178 IF FND_API.to_boolean(p_init_msg_list) THEN
3179 FND_MSG_PUB.initialize;
3180 END IF;
3181
3182 /* Initialize return status */
3183 x_return_status := FND_API.G_RET_STS_SUCCESS;
3184
3185
3186 /*
3187 * Pull up the details of the paper stock, like the
3188 * last used check number and the last available
3189 * check number.
3190 */
3191 BEGIN
3192
3193 SELECT
3194 NVL(last_issued_document_number, 0),
3195 NVL(first_available_document_num, 0),
3196 NVL(last_available_document_number, -1),
3197 payment_document_name
3198 INTO
3199 l_last_used_check_num,
3200 l_first_avail_check_num,
3201 l_last_avail_check_num,
3202 l_pmt_doc_name
3203 FROM
3204 CE_PAYMENT_DOCUMENTS
3205 WHERE
3206 payment_document_id = p_payment_doc_id
3207 ;
3208
3209 EXCEPTION
3210
3211 WHEN NO_DATA_FOUND THEN
3212
3213 print_debuginfo(l_module_name, 'No payment document '
3214 || 'with payment document id '
3215 || p_payment_doc_id
3216 || ' was found in CE_PAYMENT_DOCUMENTS table.'
3217 );
3218
3219 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
3220 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
3221 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
3222
3223 x_return_status := FND_API.G_RET_STS_ERROR;
3224
3225 l_error_code := 'IBY_INS_NO_PMT_DOC';
3226 FND_MESSAGE.set_name('IBY', l_error_code);
3227
3228 FND_MESSAGE.SET_TOKEN('PMT_DOC_ID',
3229 p_payment_doc_id,
3230 FALSE);
3231
3232 FND_MSG_PUB.ADD;
3233
3234 FND_MSG_PUB.COUNT_AND_GET(
3235 p_count => x_msg_count,
3236 p_data => x_msg_data
3237 );
3238
3239 print_debuginfo(l_module_name, 'Returning error response ..');
3240
3241 print_debuginfo(l_module_name, 'EXIT');
3242
3243 RETURN;
3244
3245
3246 WHEN OTHERS THEN
3247
3248 print_debuginfo(l_module_name, 'Exception occured when '
3249 || 'attempting to get details of payment document id '
3250 || p_payment_doc_id
3251 );
3252
3253 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
3254 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
3255
3256 x_return_status := FND_API.G_RET_STS_ERROR;
3257
3258 l_error_code := 'IBY_PMT_DOC_EXCEPTION';
3259 FND_MESSAGE.set_name('IBY', l_error_code);
3260
3261 FND_MESSAGE.SET_TOKEN('PMT_DOC_ID',
3262 p_payment_doc_id,
3263 FALSE);
3264
3265 FND_MSG_PUB.ADD;
3266
3267 FND_MSG_PUB.COUNT_AND_GET(
3268 p_count => x_msg_count,
3269 p_data => x_msg_data
3270 );
3271
3272 print_debuginfo(l_module_name, 'Returning error response ..');
3273
3274 print_debuginfo(l_module_name, 'EXIT');
3275
3276 RETURN;
3277
3278 END;
3279
3280 /*
3281 * If we reached here, it means that we were able to get
3282 * the details of the provided payment document.
3283 */
3284
3285 /*
3286 * If a null value is provided for the paper document number,
3287 * we have to return the next available paper document number
3288 * and exit.
3289 */
3290 IF (x_paper_doc_num IS NULL) THEN
3291
3292 print_debuginfo(l_module_name, 'Paper document number '
3293 || 'has not been provided. Generating ..'
3294 );
3295
3296 /*
3297 * Loop through the available paper documents until
3298 * we get a paper document number that is -
3299 *
3300 * 1. Not used
3301 * 2. Not greater than the last available document number.
3302 *
3303 * If both these conditions are not satisfied, return an
3304 * error response.
3305 */
3306 x_paper_doc_num := -1;
3307 l_error_code := NULL;
3308
3309 l_next_check_number := l_last_used_check_num;
3310
3311 WHILE (x_paper_doc_num < 0 AND l_error_code IS NULL) LOOP
3312
3313 /*
3314 * Increment the check number by one and check
3315 * if it unused. If it is unused, we can return
3316 * this check number, else we need to increment
3317 * check number by one more and try again in a
3318 * loop.
3319 */
3320 l_next_check_number := l_next_check_number + 1;
3321
3322 x_paper_doc_num := l_next_check_number;
3323
3324 print_debuginfo(l_module_name, 'Generated paper document '
3325 || 'number is '
3326 || x_paper_doc_num
3327 );
3328
3329 /*
3330 * Fix for bug 5005222:
3331 *
3332 * If last available paper document number is not
3333 * specified by the user (-1), assume that there
3334 * are an infinite number of checks available for
3335 * numbering [no upper bound].
3336 */
3337 /* check that we are not out of paper stock */
3338 IF (x_paper_doc_num > l_last_avail_check_num AND
3339 l_last_avail_check_num <> -1) THEN
3340
3341 print_debuginfo(l_module_name, 'Last available '
3342 || 'paper document number is '
3343 || l_last_avail_check_num
3344 );
3345
3346 print_debuginfo(l_module_name, 'Provided payment document '
3347 || p_payment_doc_id
3348 || ' is exhausted. No more paper documents are '
3349 || 'available for issue.'
3350 );
3351
3352 x_return_status := FND_API.G_RET_STS_ERROR;
3353
3354 l_error_code := 'IBY_CHECK_STOCK_EXHAUSTED';
3355 FND_MESSAGE.set_name('IBY', l_error_code);
3356
3357 FND_MSG_PUB.ADD;
3358
3359 FND_MSG_PUB.COUNT_AND_GET(
3360 p_count => x_msg_count,
3361 p_data => x_msg_data
3362 );
3363
3364 print_debuginfo(l_module_name, 'Returning error response ..');
3365
3366
3367 ELSE
3368
3369 /*
3370 * Check if this paper document number has already
3371 * been used.
3372 */
3373 l_flag := checkIfDocUsed(x_paper_doc_num, p_payment_doc_id);
3374
3375 IF (l_flag = TRUE) THEN
3376
3377 print_debuginfo(l_module_name, 'Generated paper document '
3378 || 'number '
3379 || x_paper_doc_num
3380 || ' has been used. Generating next available '
3381 || 'paper doc number ..'
3382 );
3383
3384 /* this will cause the while loop to iterate */
3385 x_paper_doc_num := -1;
3386
3387 ELSE
3388
3389 x_return_status := FND_API.G_RET_STS_SUCCESS;
3390
3391 print_debuginfo(l_module_name, 'Generated paper document '
3392 || 'number '
3393 || x_paper_doc_num
3394 || ' is unused.'
3395 );
3396
3397 print_debuginfo(l_module_name, 'Returning success '
3398 || 'response ..');
3399
3400 END IF; -- if l_flag <> true
3401
3402 END IF; -- if x_paper_doc_num < l_last_avail_check_num
3403
3404 END LOOP;
3405
3406 /* exit at this point as we will not be doing any validations */
3407 print_debuginfo(l_module_name, 'EXIT');
3408
3409 RETURN;
3410
3411 END IF; -- if x_paper_doc_num is null
3412
3413 /*
3414 * Start the paper document number validations.
3415 */
3416
3417 /*
3418 * Provided paper document number cannot be below
3419 * first available paper doc number.
3420 */
3421 IF (x_paper_doc_num < l_first_avail_check_num) THEN
3422
3423 print_debuginfo(l_module_name, 'Provided paper doc number '
3424 || x_paper_doc_num
3425 || ' is below first available document number '
3426 || l_first_avail_check_num
3427 );
3428
3429 x_return_status := FND_API.G_RET_STS_ERROR;
3430
3431 l_error_code := 'IBY_DOC_NUM_BELOW_ALLOWED';
3432 FND_MESSAGE.set_name('IBY', l_error_code);
3433
3434 FND_MESSAGE.SET_TOKEN('FIRST_AVAILABLE_DOC_NUM',
3435 l_first_avail_check_num,
3436 FALSE);
3437
3438 FND_MSG_PUB.ADD;
3439
3440 FND_MSG_PUB.COUNT_AND_GET(
3441 p_count => x_msg_count,
3442 p_data => x_msg_data
3443 );
3444
3445 print_debuginfo(l_module_name, 'Returning error response ..');
3446
3447 print_debuginfo(l_module_name, 'EXIT');
3448
3449 RETURN;
3450
3451 END IF;
3452
3453 /*
3454 * Fix for bug 5005222:
3455 *
3456 * If last available paper document number is not
3457 * specified by the user (-1), assume that there
3458 * are an infinite number of checks available for
3459 * numbering [no upper bound].
3460 */
3461
3462 /*
3463 * Provided paper document number cannot be above
3464 * last available paper doc number.
3465 */
3466 IF (x_paper_doc_num > l_last_avail_check_num AND
3467 l_last_avail_check_num <> -1) THEN
3468
3469 print_debuginfo(l_module_name, 'Last available '
3470 || 'paper document number is '
3471 || l_last_avail_check_num
3472 );
3473
3474 print_debuginfo(l_module_name, 'Provided paper doc number '
3475 || x_paper_doc_num
3476 || ' is above last available document number '
3477 || l_last_avail_check_num
3478 );
3479
3480 x_return_status := FND_API.G_RET_STS_ERROR;
3481
3482 l_error_code := 'IBY_DOC_NUM_ABOVE_ALLOWED';
3483 FND_MESSAGE.set_name('IBY', l_error_code);
3484
3485 FND_MESSAGE.SET_TOKEN('LAST_AVAILABLE_DOC_NUM',
3486 l_last_avail_check_num,
3487 FALSE);
3488
3489 FND_MSG_PUB.ADD;
3490
3491 FND_MSG_PUB.COUNT_AND_GET(
3492 p_count => x_msg_count,
3493 p_data => x_msg_data
3494 );
3495
3496 print_debuginfo(l_module_name, 'Returning error response ..');
3497
3498 print_debuginfo(l_module_name, 'EXIT');
3499
3500 RETURN;
3501
3502 END IF;
3503
3504 /*
3505 * Provided paper document number should not be below
3506 * last issued paper doc number (warning).
3507 */
3508 IF (x_paper_doc_num < l_last_used_check_num) THEN
3509
3510 /*
3511 * This check will only result in a warning message.
3512 * Ignore this check, if the show warnings flag is
3513 * set to false.
3514 *
3515 * This method can be called multiple times in the
3516 * single payments flow, this could result in a large
3517 * number of error messages being put into the message
3518 * stack and displayed to the user.
3519 *
3520 * By setting the show warnings flag to 'false' for
3521 * the single payments flow, the number of potential
3522 * messages displayed to the user is reduced.
3523 */
3524 IF (show_warn_msgs_flag = FND_API.G_TRUE) THEN
3525
3526 print_debuginfo(l_module_name, 'Warning: Provided paper '
3527 || 'doc number '
3528 || x_paper_doc_num
3529 || ' is below last issued document number '
3530 || l_last_used_check_num
3531 );
3532
3533 l_error_code := 'IBY_DOC_NUM_BELOW_ISSUED';
3534 FND_MESSAGE.set_name('IBY', l_error_code);
3535
3536 FND_MSG_PUB.ADD;
3537
3538 FND_MSG_PUB.COUNT_AND_GET(
3539 p_count => x_msg_count,
3540 p_data => x_msg_data
3541 );
3542
3543 END IF;
3544
3545 END IF;
3546
3547 /*
3548 * Check if this paper document number has already
3549 * been used.
3550 */
3551 l_flag := checkIfDocUsed(x_paper_doc_num, p_payment_doc_id);
3552
3553 IF (l_flag = TRUE) THEN
3554
3555 print_debuginfo(l_module_name, 'Provided paper document '
3556 || 'number '
3557 || x_paper_doc_num
3558 || ' has already been used.'
3559 );
3560
3561 x_return_status := FND_API.G_RET_STS_ERROR;
3562
3563 l_error_code := 'IBY_DOC_NUM_USED';
3564 FND_MESSAGE.set_name('IBY', l_error_code);
3565
3566 FND_MSG_PUB.ADD;
3567
3568 FND_MSG_PUB.COUNT_AND_GET(
3569 p_count => x_msg_count,
3570 p_data => x_msg_data
3571 );
3572
3573 print_debuginfo(l_module_name, 'Returning error response ..');
3574
3575 print_debuginfo(l_module_name, 'EXIT');
3576
3577 RETURN;
3578
3579 ELSE
3580
3581 print_debuginfo(l_module_name, 'Provided paper document '
3582 || 'number '
3583 || x_paper_doc_num
3584 || ' is unused.'
3585 );
3586
3587 END IF; -- if l_flag <> true
3588
3589 /*
3590 * If we reached here, it means that both the paper document
3591 * number and the payment document id are valid.
3592 */
3593 print_debuginfo(l_module_name, 'Returning success response ..');
3594
3595 x_return_status := FND_API.G_RET_STS_SUCCESS;
3596
3597 print_debuginfo(l_module_name, 'EXIT');
3598
3599 END validate_paper_doc_number;
3600
3601 /*--------------------------------------------------------------------
3602 | NAME:
3603 | terminate_pmt_instruction
3604 |
3605 |
3606 | PURPOSE:
3607 |
3608 |
3609 | PARAMETERS:
3610 | IN
3611 |
3612 |
3613 | OUT
3614 |
3615 |
3616 | RETURNS:
3617 |
3618 | NOTES:
3619 | Internal API, not for public use.
3620 |
3621 | UPDATE ON MAY-04-2006, rameshsh
3622 | This method was not performing a COMMIT earlier. Due to bug 5206672
3623 | a COMMIT has been added in the code before invoking unlock_pmt_entity(..).
3624 *---------------------------------------------------------------------*/
3625 PROCEDURE terminate_pmt_instruction (
3626 p_instr_id IN NUMBER,
3627 p_instr_status IN VARCHAR2,
3628 x_return_status OUT NOCOPY VARCHAR2
3629 )
3630 IS
3631
3632 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
3633 || '.terminate_pmt_instruction';
3634
3635 l_rejection_id NUMBER(15);
3636
3637 /* used in forming callout procedure name */
3638 l_calling_app_id NUMBER;
3639 l_pkg_name VARCHAR2(200);
3640 l_callout_name VARCHAR2(500);
3641 l_stmt VARCHAR2(1000);
3642
3643 /* used in invocation of callout procedure */
3644 l_api_version CONSTANT NUMBER := 1.0;
3645 l_msg_count NUMBER;
3646 l_msg_data VARCHAR2(2000);
3647
3648 l_appNamesTab appNamesTab;
3649 l_appIdsTab appIdsTab;
3650
3651 l_pmt_doc_id NUMBER(15);
3652 l_pmt_doc_name VARCHAR2(2000);
3653
3654 l_flag BOOLEAN := FALSE;
3655 l_error_code VARCHAR2(3000);
3656
3657 l_ret_status VARCHAR2(300);
3658
3659 l_valid_pmts_count NUMBER;
3660
3661 l_max_paper_document_number NUMBER;
3662 l_min_paper_document_number NUMBER;
3663 l_number_of_payments NUMBER;
3664 l_last_issued NUMBER;
3665 l_document_locked BOOLEAN := TRUE;
3666 l_last_issued_modified NUMBER;
3667 l_irregular_document_numbers EXCEPTION;
3668 /*
3669 * Cursor to pick up names of all calling applications
3670 * associated with a particular payment instruction.
3671 */
3672 CURSOR c_app_names (p_instr_id NUMBER)
3673 IS
3674 SELECT DISTINCT
3675 fnd.application_short_name
3676 FROM
3677 FND_APPLICATION fnd,
3678 IBY_PAYMENTS_ALL pmt,
3679 IBY_PAY_SERVICE_REQUESTS req,
3680 IBY_PAY_INSTRUCTIONS_ALL ins
3681 WHERE
3682 pmt.payment_instruction_id = ins.payment_instruction_id AND
3683 req.payment_service_request_id = pmt.payment_service_request_id AND
3684 fnd.application_id = req.calling_app_id AND
3685 ins.payment_instruction_id = p_instr_id
3686 ;
3687
3688 /*
3689 * Cursor to pick up ids all calling applications
3690 * associated with a particular payment instruction.
3691 */
3692 CURSOR c_app_ids (p_instr_id NUMBER)
3693 IS
3694 SELECT
3695 fnd.application_id
3696 FROM
3697 FND_APPLICATION fnd,
3698 IBY_PAYMENTS_ALL pmt,
3699 IBY_PAY_SERVICE_REQUESTS req,
3700 IBY_PAY_INSTRUCTIONS_ALL ins
3701 WHERE
3702 pmt.payment_instruction_id = ins.payment_instruction_id AND
3703 req.payment_service_request_id = pmt.payment_service_request_id AND
3704 fnd.application_id = req.calling_app_id AND
3705 ins.payment_instruction_id = p_instr_id
3706 ;
3707
3708 /*
3709 * Implementing the callout is optional for the calling app.
3710 * If the calling app does not implement the hook, then
3711 * the call to the hook will result in ORA-06576 error.
3712 *
3713 * There is no exception name associated with this code, so
3714 * we create one called 'PROCEDURE_NOT_IMPLEMENTED'. If this
3715 * exception occurs, it is not fatal: we log the error and
3716 * proceed.
3717 *
3718 * If, on the other hand, the calling app implements the
3719 * callout, but the callout throws an exception, it is fatal
3720 * and we must abort the program (this will be caught
3721 * in WHEN OTHERS block).
3722 */
3723 PROCEDURE_NOT_IMPLEMENTED EXCEPTION;
3724 PRAGMA EXCEPTION_INIT(PROCEDURE_NOT_IMPLEMENTED, -6576);
3725
3726 BEGIN
3727
3728 print_debuginfo(l_module_name, 'ENTER');
3729
3730 FND_MSG_PUB.initialize;
3731
3732 /*
3733 * STATUS CHANGE:
3734 *
3735 * API Responsibility:
3736 * instruction status = TERMINATED
3737 * payment_status = REMOVED_INSTRUCTION_TERMINATED
3738 * document_status = REMOVED_INSTRUCTION_TERMINATED
3739 *
3740 */
3741
3742 /*
3743 * STEP 1:
3744 *
3745 * If the given payment instruction is locked, it means
3746 * that some concurrent program is acting upon the
3747 * pmt instruction at the moment.
3748 *
3749 * To prevent data corruption do not allow the payment
3750 * instruction to be terminated.
3751 */
3752 l_flag := checkIfPmtEntityLocked(p_instr_id, 'PAYMENT_INSTRUCTION');
3753
3754 /* for bug 6196551 */
3755 SELECT
3756 count(*)
3757 INTO
3758 l_valid_pmts_count
3759 FROM
3760 IBY_PAYMENTS_ALL pmt
3761 WHERE
3762 pmt.payment_instruction_id = p_instr_id AND
3763 pmt.payment_status NOT IN
3764 (
3765 PAY_STATUS_VOID,
3766 PAY_STATUS_REMOVED,
3767 PAY_STATUS_STOPPED
3768 );
3769
3770 IF (l_valid_pmts_count=0) THEN
3771 l_flag := FALSE;
3772 END IF;
3773 IF (l_flag = TRUE) THEN
3774
3775 print_debuginfo(l_module_name, 'Payment instruction '
3776 || p_instr_id
3777 || ' has been locked by a concurrent program.'
3778 || ' It cannot be terminated at present.'
3779 );
3780
3781 x_return_status := FND_API.G_RET_STS_ERROR;
3782
3783 l_error_code := 'IBY_INS_LOCKED';
3784 FND_MESSAGE.set_name('IBY', l_error_code);
3785 FND_MSG_PUB.ADD;
3786
3787 --FND_MSG_PUB.COUNT_AND_GET(
3788 -- p_count => x_msg_count,
3789 -- p_data => x_msg_data
3790 -- );
3791
3792 print_debuginfo(l_module_name, 'Returning error response ..');
3793
3794 print_debuginfo(l_module_name, 'EXIT');
3795
3796 RETURN;
3797
3798 ELSE
3799
3800 print_debuginfo(l_module_name, 'Payment instruction '
3801 || p_instr_id
3802 || ' is not locked.'
3803 );
3804
3805 END IF;
3806
3807 /*
3808 * STEP 2:
3809 *
3810 * Update payment instruction, payment and document statuses
3811 * to 'terminated'.
3812 */
3813 UPDATE
3814 iby_pay_instructions_all
3815 SET
3816 payment_instruction_status = INS_STATUS_TERMINATED
3817 WHERE
3818 payment_instruction_id = p_instr_id
3819 ;
3820
3821 BEGIN
3822
3823 UPDATE
3824 IBY_PAYMENTS_ALL
3825 SET
3826 payment_status = PAY_STATUS_INS_TERM
3827 WHERE
3828 payment_instruction_id = p_instr_id AND
3829 (
3830 payment_status <> PAY_STATUS_REMOVED AND
3831 payment_status <> PAY_STATUS_VOID_SETUP AND
3832 payment_status <> PAY_STATUS_VOID_OVERFLOW AND
3833 payment_status <> PAY_STATUS_SPOILED AND
3834 payment_status <> PAY_STATUS_STOPPED AND
3835 payment_status <> PAY_STATUS_INS_TERM AND
3836 payment_status <> PAY_STATUS_REQ_TERM AND
3837 payment_status <> PAY_STATUS_VOID AND
3838 payment_status <> PAY_STATUS_ACK AND
3839 payment_status <> PAY_STATUS_BNK_VALID AND
3840 payment_status <> PAY_STATUS_PAID
3841 )
3842 ;
3843
3844 EXCEPTION
3845
3846 WHEN NO_DATA_FOUND THEN
3847 /*
3848 * Handle gracefully the situation where no payments
3849 * exist for the given request.
3850 */
3851 print_debuginfo(l_module_name, 'No payments in valid '
3852 || 'status exist for payment instruction '
3853 || p_instr_id
3854 );
3855
3856 WHEN OTHERS THEN
3857 print_debuginfo(l_module_name, 'Fatal: Exception occured '
3858 || 'when attempting to update status of payments '
3859 || 'for payment instruction '
3860 || p_instr_id
3861 || '. Aborting program ..'
3862 );
3863 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
3864 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
3865 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
3866
3867 /*
3868 * Propogate exception to caller.
3869 */
3870 RAISE;
3871
3872 END;
3873
3874 BEGIN
3875
3876 UPDATE
3877 IBY_DOCS_PAYABLE_ALL
3878 SET
3879 document_status = DOC_STATUS_INS_TERM,
3880
3881 /*
3882 * Fix for bug 4405981:
3883 *
3884 * The straight through flag should be set to 'N',
3885 * if the document was rejected / required manual
3886 * intervention.
3887 */
3888 straight_through_flag = 'N'
3889
3890 WHERE
3891 payment_id IN
3892 (
3893 SELECT
3894 payment_id
3895 FROM
3896 IBY_PAYMENTS_ALL
3897 WHERE
3898 payment_instruction_id = p_instr_id AND
3899 payment_status = PAY_STATUS_INS_TERM
3900 )
3901 AND
3902 (
3903 document_status <> DOC_STATUS_REJECTED AND
3904 document_status <> DOC_STATUS_REMOVED AND
3905 document_status <> DOC_STATUS_PMT_REMOVED AND
3906 document_status <> DOC_STATUS_PMT_STOPPED AND
3907 document_status <> DOC_STATUS_REQ_TERM AND
3908 document_status <> DOC_STATUS_INS_TERM AND
3909 document_status <> DOC_STATUS_VOID_SETUP AND
3910 document_status <> DOC_STATUS_PMT_VOIDED
3911 )
3912 ;
3913
3914 EXCEPTION
3915
3916 WHEN NO_DATA_FOUND THEN
3917 /*
3918 * Handle gracefully the situation where no documents
3919 * exist for the given payment instruciton.
3920 */
3921 print_debuginfo(l_module_name, 'No payments exist for payment '
3922 || 'instruction '
3923 || p_instr_id
3924 );
3925 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
3926
3927 WHEN OTHERS THEN
3928 print_debuginfo(l_module_name, 'Fatal: Exception occured '
3929 || 'when attempting to update status of payments '
3930 || 'for payment instruction '
3931 || p_instr_id
3932 || '. Aborting program ..'
3933 );
3934 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
3935 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
3936 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
3937
3938 /*
3939 * Propogate exception to caller.
3940 */
3941 RAISE;
3942
3943 END;
3944
3945 /*
3946 * STEP 3:
3947 * Restore the Unused Check numbers and
3948 * Unlock the payment document that has been locked by this payment
3949 * instruction.
3950 */
3951 print_debuginfo(l_module_name, 'Restoring the Unused Check numbers '
3952 || 'by payment instruction '
3953 || p_instr_id
3954 );
3955
3956 /*Restoring the Unused Check numbers*/
3957 /*Modified for Bug 7325373*/
3958 BEGIN
3959 BEGIN
3960 SELECT last_issued_document_number INTO l_last_issued
3961 FROM ce_payment_documents WHERE payment_instruction_id = p_instr_id;
3962 EXCEPTION
3963 WHEN No_Data_Found THEN
3964 l_document_locked := FALSE;
3965 print_debuginfo(l_module_name, 'Payment Document is not locked by the instruction '
3966 || p_instr_id
3967 );
3968 END;
3969 IF(l_document_locked = TRUE) THEN
3970 SELECT Max(paper_document_number), Min(paper_document_number), Count(*)
3971 INTO l_max_paper_document_number, l_min_paper_document_number, l_number_of_payments
3972 FROM iby_payments_all WHERE payment_instruction_id = p_instr_id;
3973
3974 l_last_issued_modified := l_last_issued - l_number_of_payments;
3975 IF ((l_last_issued <> l_max_paper_document_number)
3976 OR ((l_max_paper_document_number - l_min_paper_document_number) <> (l_number_of_payments - 1)))
3977 THEN
3978 RAISE l_irregular_document_numbers;
3979 END IF;
3980
3981 UPDATE
3982 CE_PAYMENT_DOCUMENTS
3983 SET
3984 last_issued_document_number = l_last_issued_modified
3985 WHERE
3986 payment_instruction_id = p_instr_id
3987 RETURNING
3988 payment_document_id,
3989 payment_document_name
3990 INTO
3991 l_pmt_doc_id,
3992 l_pmt_doc_name
3993 ;
3994
3995 print_debuginfo(l_module_name, 'Check number restored for Payment document id '
3996 || l_pmt_doc_id
3997 || ' with name '
3998 || l_pmt_doc_name
3999 );
4000
4001
4002 END IF;
4003 EXCEPTION
4004 WHEN l_irregular_document_numbers THEN
4005 print_debuginfo(l_module_name, 'Fatal: Exception occured '
4006 || 'while restoring the used check numbers.'
4007 || p_instr_id
4008 );
4009 RAISE;
4010
4011 WHEN OTHERS THEN
4012 print_debuginfo(l_module_name, 'Non-Fatal: Exception occured '
4013 || 'while restoring the used check numbers. '
4014 || p_instr_id
4015 );
4016
4017 END;
4018
4019 print_debuginfo(l_module_name, 'Unlocking payment document locked '
4020 || 'by payment instruction '
4021 || p_instr_id
4022 );
4023 /* Unlocking the payment document*/
4024 BEGIN
4025
4026 UPDATE
4027 CE_PAYMENT_DOCUMENTS
4028 SET
4029 payment_instruction_id = NULL
4030 WHERE
4031 payment_instruction_id = p_instr_id
4032 RETURNING
4033 payment_document_id,
4034 payment_document_name
4035 INTO
4036 l_pmt_doc_id,
4037 l_pmt_doc_name
4038 ;
4039
4040 print_debuginfo(l_module_name, 'Payment document id '
4041 || l_pmt_doc_id
4042 || ' with name '
4043 || l_pmt_doc_name
4044 || ' unlocked successfully.'
4045 );
4046
4047 EXCEPTION
4048 WHEN OTHERS THEN
4049
4050 /*
4051 * This is a no-fatal exception. We will log the exception
4052 * and return.
4053 */
4054 print_debuginfo(l_module_name, 'Non-Fatal: Exception occured '
4055 || 'when unlocking pmt document locked by pmt instruction '
4056 || p_instr_id
4057 );
4058
4059 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
4060 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
4061 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
4062
4063 END;
4064
4065 /*
4066 * STEP 4:
4067 *
4068 * Invoke callouts to inform calling applications about the
4069 * terminated documents payable.
4070 */
4071
4072 /*
4073 * Pick up the names of all the applications which have
4074 * payments in the current payment instruction.
4075 *
4076 * Remember, one payment instruction can contain payments
4077 * across multiple calling applications.
4078 */
4079 OPEN c_app_names (p_instr_id);
4080 FETCH c_app_names BULK COLLECT INTO l_appNamesTab;
4081 CLOSE c_app_names;
4082
4083 /*
4084 * Pick up the ids of all the applications which have
4085 * payments in the current payment instruction.
4086 *
4087 * Remember, one payment instruction can contain payments
4088 * across multiple calling applications.
4089 */
4090 OPEN c_app_ids (p_instr_id);
4091 FETCH c_app_ids BULK COLLECT INTO l_appIdsTab;
4092 CLOSE c_app_ids;
4093
4094 /*
4095 * This should normally never happen.
4096 */
4097 IF (l_appIdsTab.COUNT = 0) THEN
4098
4099 print_debuginfo(l_module_name, 'No calling application ids '
4100 || 'were fetched for payment instruction '
4101 || p_instr_id
4102 || ' Possible data corruption. Raising exception ..'
4103 );
4104
4105 APP_EXCEPTION.RAISE_EXCEPTION;
4106
4107 END IF;
4108
4109 /*
4110 * Loop through all the application names, invoking the
4111 * callout of each application.
4112 */
4113 FOR i IN l_appNamesTab.FIRST .. l_appNamesTab.LAST LOOP
4114
4115 /*
4116 * Get the constructed package name to use in the
4117 * call out.
4118 */
4119 l_pkg_name := construct_callout_pkg_name(l_appNamesTab(i));
4120
4121 print_debuginfo(l_module_name, 'Constructed package name: '
4122 || l_pkg_name);
4123
4124 IF (l_pkg_name IS NULL) THEN
4125
4126 print_debuginfo(l_module_name, 'Package name is null. '
4127 || 'Raising exception.');
4128
4129 APP_EXCEPTION.RAISE_EXCEPTION;
4130
4131 END IF;
4132
4133 /*
4134 * Get the next available rejected document group id.
4135 */
4136 SELECT
4137 IBY_REJECTED_DOCS_GROUP_S.NEXTVAL
4138 INTO
4139 l_rejection_id
4140 FROM
4141 DUAL
4142 ;
4143
4144 /*
4145 * Update the terminated documents for this calling app
4146 * with the rejected document group id. The calling
4147 * application will identify rejected documents using
4148 * this id.
4149 */
4150 UPDATE
4151 IBY_DOCS_PAYABLE_ALL
4152 SET
4153 rejected_docs_group_id = l_rejection_id
4154 WHERE
4155 document_status = DOC_STATUS_INS_TERM AND
4156 calling_app_id = l_appIdsTab(i) AND
4157 payment_id IN
4158 (SELECT
4159 payment_id
4160 FROM
4161 IBY_PAYMENTS_ALL
4162 WHERE
4163 payment_instruction_id = p_instr_id AND
4164 payment_status = PAY_STATUS_INS_TERM
4165 )
4166 ;
4167
4168 /*
4169 * Now try to call the external app's implementation of the hook.
4170 * The calling app may or may not have implemented the hook, so
4171 * it's not fatal if the implementation does not exist.
4172 */
4173 l_callout_name := l_pkg_name || '.' || 'documents_payable_rejected';
4174
4175 print_debuginfo(l_module_name, 'Attempting to invoke callout: '
4176 || l_callout_name);
4177
4178 l_stmt := 'CALL '|| l_callout_name || '(:1, :2, :3, :4, :5, :6, :7)';
4179
4180 BEGIN
4181
4182 print_debuginfo(l_module_name, 'Parameter passed to callout - '
4183 || 'l_rejection_id: '
4184 || l_rejection_id
4185 );
4186
4187 EXECUTE IMMEDIATE
4188 (l_stmt)
4189 USING
4190 IN l_api_version,
4191 IN FND_API.G_FALSE,
4192 IN FND_API.G_FALSE,
4193 OUT x_return_status,
4194 OUT l_msg_count,
4195 OUT l_msg_data,
4196 IN l_rejection_id
4197 ;
4198
4199 /*
4200 * If the called procedure did not return success,
4201 * raise an exception.
4202 */
4203 IF (x_return_status IS NULL OR
4204 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
4205
4206 print_debuginfo(l_module_name, 'Fatal: External app callout '''
4207 || l_callout_name
4208 || ''', returned failure status - '
4209 || x_return_status
4210 || '. Raising exception.'
4211 );
4212
4213 APP_EXCEPTION.RAISE_EXCEPTION;
4214
4215 END IF;
4216
4217 EXCEPTION
4218
4219 WHEN PROCEDURE_NOT_IMPLEMENTED THEN
4220 print_debuginfo(l_module_name, 'Callout "' || l_callout_name
4221 || '" not implemented by calling app '
4222 || l_appNamesTab(i) || '.');
4223
4224 print_debuginfo(l_module_name, 'Skipping hook call.');
4225
4226
4227 WHEN OTHERS THEN
4228 print_debuginfo(l_module_name, 'Fatal: External app callout '''
4229 || l_callout_name
4230 || ''', generated exception.'
4231 );
4232
4233 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
4234 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
4235 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
4236
4237 /*
4238 * Propogate exception to caller.
4239 */
4240 RAISE;
4241
4242 END;
4243
4244 END LOOP;
4245
4246 /*
4247 * STEP 5:
4248 *
4249 * Clean up the pmt instruction by unstamping it. In case the
4250 * concurrent request that was handling this pmt instruction
4251 * had aborted with an exception, this step will clean up the data.
4252 */
4253
4254 /*
4255 * Fix for bug 5206672:
4256 *
4257 * If we reached here, then the payment instruction has
4258 * been updated to TERMINATED status and the calling app
4259 * has been informed.
4260 *
4261 * Perform a COMMIT here before calling unlock_pmt_entity(..)
4262 * otherwise a deadlock ensues.
4263 */
4264 COMMIT;
4265
4266 unlock_pmt_entity(
4267 p_instr_id,
4268 'PAYMENT_INSTRUCTION',
4269 l_ret_status
4270 );
4271
4272 x_return_status := FND_API.G_RET_STS_SUCCESS;
4273
4274 print_debuginfo(l_module_name, 'EXIT');
4275
4276 EXCEPTION
4277
4278 WHEN OTHERS THEN
4279
4280 print_debuginfo(l_module_name, 'Exception occured when '
4281 || 'terminating payment instruction '
4282 || p_instr_id
4283 || ', with status '
4284 || p_instr_status
4285 );
4286
4287 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
4288 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
4289 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
4290
4291 x_return_status := FND_API.G_RET_STS_ERROR;
4292
4293 print_debuginfo(l_module_name, 'EXIT');
4294
4295 END terminate_pmt_instruction;
4296
4297 /*--------------------------------------------------------------------
4298 | NAME:
4299 | terminate_pmt_request
4300 |
4301 |
4302 | PURPOSE:
4303 |
4304 |
4305 | PARAMETERS:
4306 | IN
4307 |
4308 |
4309 | OUT
4310 |
4311 |
4312 | RETURNS:
4313 |
4314 | NOTES:
4315 | Internal API, not for public use.
4316 |
4317 | UPDATE ON MAY-05-2006, rameshsh
4318 | This method was not performing a COMMIT earlier. Due to bug 5206672
4319 | a COMMIT has been added in the code before invoking unlock_pmt_entity(..).
4320 |
4321 *---------------------------------------------------------------------*/
4322 PROCEDURE terminate_pmt_request (
4323 p_req_id IN NUMBER,
4324 p_req_status IN VARCHAR2,
4325 x_return_status OUT NOCOPY VARCHAR2
4326 )
4327 IS
4328
4329 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
4330 || '.terminate_pmt_request';
4331
4332 l_rejection_id NUMBER(15);
4333
4334 /* used in forming callout procedure name */
4335 l_calling_app_id NUMBER;
4336 l_app_short_name VARCHAR2(200);
4337 l_pkg_name VARCHAR2(200);
4338 l_callout_name VARCHAR2(500);
4339 l_stmt VARCHAR2(1000);
4340
4341 /* used in invocation of callout procedure */
4342 l_api_version CONSTANT NUMBER := 1.0;
4343 l_msg_count NUMBER;
4344 l_msg_data VARCHAR2(2000);
4345
4346 l_flag BOOLEAN := FALSE;
4347
4348 l_error_code VARCHAR2(3000);
4349 l_ret_status VARCHAR2(300);
4350
4351 /*
4352 * Implementing the callout is optional for the calling app.
4353 * If the calling app does not implement the hook, then
4354 * the call to the hook will result in ORA-06576 error.
4355 *
4356 * There is no exception name associated with this code, so
4357 * we create one called 'PROCEDURE_NOT_IMPLEMENTED'. If this
4358 * exception occurs, it is not fatal: we log the error and
4359 * proceed.
4360 *
4361 * If, on the other hand, the calling app implements the
4362 * callout, but the callout throws an exception, it is fatal
4363 * and we must abort the program (this will be caught
4364 * in WHEN OTHERS block).
4365 */
4366 PROCEDURE_NOT_IMPLEMENTED EXCEPTION;
4367 PRAGMA EXCEPTION_INIT(PROCEDURE_NOT_IMPLEMENTED, -6576);
4368
4369 BEGIN
4370
4371 print_debuginfo(l_module_name, 'ENTER');
4372
4373 print_debuginfo(l_module_name, 'Parameters passed - '
4374 || 'payment request id: '
4375 || p_req_id
4376 || ', payment request status: '
4377 || p_req_status
4378 );
4379
4380 FND_MSG_PUB.initialize;
4381
4382 /*
4383 * STATUS CHANGE:
4384 *
4385 * API Responsibility:
4386 * request status = TERMINATED
4387 * payment_status = REMOVED_REQUEST_TERMINATED
4388 * document_status = REMOVED_REQUEST_TERMINATED
4389 *
4390 */
4391
4392 /*
4393 * STEP 1:
4394 *
4395 * If the given payment request is locked, it means
4396 * that some concurrent program is acting upon the
4397 * ppr at the moment.
4398 *
4399 * To prevent data corruption do not allow the payment
4400 * request to be terminated.
4401 */
4402 l_flag := checkIfPmtEntityLocked(p_req_id, 'PAYMENT_REQUEST');
4403
4404 IF (l_flag = TRUE) THEN
4405
4406 print_debuginfo(l_module_name, 'Payment request '
4407 || p_req_id
4408 || ' has been locked by a concurrent program.'
4409 || ' It cannot be terminated at present.'
4410 );
4411
4412 x_return_status := FND_API.G_RET_STS_ERROR;
4413
4414 l_error_code := 'IBY_PPR_LOCKED';
4415 FND_MESSAGE.set_name('IBY', l_error_code);
4416 FND_MSG_PUB.ADD;
4417
4418 --FND_MSG_PUB.COUNT_AND_GET(
4419 -- p_count => x_msg_count,
4420 -- p_data => x_msg_data
4421 -- );
4422
4423 print_debuginfo(l_module_name, 'Returning error response ..');
4424
4425 print_debuginfo(l_module_name, 'EXIT');
4426
4427 RETURN;
4428
4429 ELSE
4430
4431 print_debuginfo(l_module_name, 'Payment request '
4432 || p_req_id
4433 || ' is not locked.'
4434 );
4435
4436 END IF;
4437
4438 /*
4439 * Fix for bug 5112559:
4440 *
4441 * Before performing any action, first check if any of
4442 * the payments of this ppr are part of a payment instruction,
4443 * if so, do not allow the ppr to be terminated.
4444 */
4445 l_flag := checkIfPmtInInstExists(p_req_id);
4446
4447 IF (l_flag = TRUE) THEN
4448
4449 print_debuginfo(l_module_name, 'The payment request '
4450 || p_req_id
4451 || ' contains at least one payment that is '
4452 || 'part of a payment instruction. Payment '
4453 || 'request cannot be terminated at this stage.'
4454 );
4455
4456 x_return_status := FND_API.G_RET_STS_ERROR;
4457
4458 l_error_code := 'IBY_PPR_TERM_NOT_ALLOWED';
4459 FND_MESSAGE.set_name('IBY', l_error_code);
4460 FND_MSG_PUB.ADD;
4461
4462 --FND_MSG_PUB.COUNT_AND_GET(
4463 -- p_count => x_msg_count,
4464 -- p_data => x_msg_data
4465 -- );
4466
4467 print_debuginfo(l_module_name, 'Returning error response ..');
4468
4469 print_debuginfo(l_module_name, 'EXIT');
4470
4471 RETURN;
4472
4473 END IF;
4474
4475 /*
4476 * STEP 2:
4477 *
4478 * Set the request status to TERMINATED.
4479 */
4480 UPDATE
4481 iby_pay_service_requests
4482 SET
4483 payment_service_request_status = REQ_STATUS_TERMINATED
4484 WHERE
4485 payment_service_request_id = p_req_id
4486 ;
4487
4488
4489 BEGIN
4490
4491 UPDATE
4492 IBY_PAYMENTS_ALL
4493 SET
4494 payment_status = PAY_STATUS_REQ_TERM
4495 WHERE
4496 payment_service_request_id = p_req_id AND
4497 (
4498 payment_status <> PAY_STATUS_REMOVED AND
4499 payment_status <> PAY_STATUS_VOID_SETUP AND
4500 payment_status <> PAY_STATUS_VOID_OVERFLOW AND
4501 payment_status <> PAY_STATUS_SPOILED AND
4502 payment_status <> PAY_STATUS_STOPPED AND
4503 payment_status <> PAY_STATUS_INS_TERM AND
4504 payment_status <> PAY_STATUS_REQ_TERM AND
4505 payment_status <> PAY_STATUS_VOID AND
4506 payment_status <> PAY_STATUS_ACK AND
4507 payment_status <> PAY_STATUS_BNK_VALID AND
4508 payment_status <> PAY_STATUS_PAID
4509 )
4510 ;
4511
4512 EXCEPTION
4513
4514 WHEN NO_DATA_FOUND THEN
4515 /*
4516 * Handle gracefully the situation where no payments
4517 * exist for the given request.
4518 */
4519 print_debuginfo(l_module_name, 'No payments exist for payment '
4520 || 'request '
4521 || p_req_id
4522 );
4523
4524
4525 WHEN OTHERS THEN
4526 print_debuginfo(l_module_name, 'Fatal: Exception occured '
4527 || 'when attempting to update status of payments '
4528 || 'for payment request '
4529 || p_req_id
4530 || '. Aborting program ..'
4531 );
4532 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
4533 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
4534 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
4535
4536 /*
4537 * Propogate exception to caller.
4538 */
4539 RAISE;
4540
4541 END;
4542
4543 /*
4544 * STEP 3:
4545 *
4546 * Set status of documents to TERMINATED.
4547 */
4548 BEGIN
4549
4550 UPDATE
4551 IBY_DOCS_PAYABLE_ALL
4552 SET
4553 document_status = DOC_STATUS_REQ_TERM,
4554
4555 /*
4556 * Fix for bug 4405981:
4557 *
4558 * The straight through flag should be set to 'N',
4559 * if the document was rejected / required manual
4560 * intervention.
4561 */
4562 straight_through_flag = 'N'
4563 WHERE
4564 payment_service_request_id = p_req_id AND
4565 (
4566 document_status <> DOC_STATUS_REJECTED AND
4567 document_status <> DOC_STATUS_REMOVED AND
4568 document_status <> DOC_STATUS_PMT_REMOVED AND
4569 document_status <> DOC_STATUS_PMT_STOPPED AND
4570 document_status <> DOC_STATUS_REQ_TERM AND
4571 document_status <> DOC_STATUS_INS_TERM AND
4572 document_status <> DOC_STATUS_VOID_SETUP AND
4573 document_status <> DOC_STATUS_PMT_VOIDED
4574 )
4575 ;
4576
4577 EXCEPTION
4578
4579 WHEN NO_DATA_FOUND THEN
4580
4581 /*
4582 * Handle gracefully the situation where no documents payable
4583 * exist for the given request.
4584 */
4585 print_debuginfo(l_module_name, 'No docs payable exist for payment '
4586 || 'request '
4587 || p_req_id
4588 || '. Exiting ..'
4589 );
4590
4591 /*
4592 * If no documents payable exist for the given request,
4593 * it is not worth proceeding further.
4594 *
4595 * Return success status to the caller.
4596 */
4597 x_return_status := FND_API.G_RET_STS_SUCCESS;
4598
4599 print_debuginfo(l_module_name, 'EXIT');
4600 RETURN;
4601
4602 WHEN OTHERS THEN
4603 print_debuginfo(l_module_name, 'Fatal: Exception occured '
4604 || 'when attempting to update status of documents '
4605 || 'payable for payment request '
4606 || p_req_id
4607 || '. Aborting program ..'
4608 );
4609 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
4610 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
4611 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
4612
4613 /*
4614 * Propogate exception to caller.
4615 */
4616 RAISE;
4617
4618 END;
4619
4620 /*
4621 * STEP 4:
4622 *
4623 * Inform calling application about rejected documents.
4624 */
4625
4626 /*
4627 * Get the next available rejected document group id.
4628 */
4629 SELECT
4630 IBY_REJECTED_DOCS_GROUP_S.NEXTVAL
4631 INTO
4632 l_rejection_id
4633 FROM
4634 DUAL
4635 ;
4636
4637 /*
4638 * Update the terminated documents with the rejected document
4639 * group id. The calling application will identify rejected
4640 * documents using this id.
4641 */
4642 UPDATE
4643 IBY_DOCS_PAYABLE_ALL
4644 SET
4645 rejected_docs_group_id = l_rejection_id
4646 WHERE
4647 document_status = DOC_STATUS_REQ_TERM AND
4648 payment_service_request_id = p_req_id
4649 ;
4650
4651 /*
4652 * Get the application name of the calling app. This
4653 * will be used in the callout.
4654 */
4655 SELECT
4656 fnd.application_short_name
4657 INTO
4658 l_app_short_name
4659 FROM
4660 FND_APPLICATION fnd,
4661 IBY_PAY_SERVICE_REQUESTS req
4662 WHERE
4663 fnd.application_id = req.calling_app_id AND
4664 req.payment_service_request_id = p_req_id
4665 ;
4666
4667 /*
4668 * Get the constructed package name to use in the
4669 * call out.
4670 */
4671 l_pkg_name := construct_callout_pkg_name(l_app_short_name);
4672
4673 print_debuginfo(l_module_name, 'Constructed package name: '
4674 || l_pkg_name);
4675
4676 IF (l_pkg_name IS NULL) THEN
4677
4678 print_debuginfo(l_module_name, 'Package name is null. '
4679 || 'Raising exception.');
4680
4681 APP_EXCEPTION.RAISE_EXCEPTION;
4682
4683 END IF;
4684
4685 /*
4686 * Now try to call the external app's implementation of the hook.
4687 * The calling app may or may not have implemented the hook, so
4688 * it's not fatal if the implementation does not exist.
4689 */
4690 l_callout_name := l_pkg_name || '.' || 'documents_payable_rejected';
4691
4692 print_debuginfo(l_module_name, 'Attempting to invoke callout: '
4693 || l_callout_name);
4694
4695 print_debuginfo(l_module_name, 'Parameter(s) passed to callout - '
4696 || 'rejection id: '
4697 || l_rejection_id
4698 );
4699
4700 l_stmt := 'CALL '|| l_callout_name || '(:1, :2, :3, :4, :5, :6, :7)';
4701
4702 BEGIN
4703
4704 EXECUTE IMMEDIATE
4705 (l_stmt)
4706 USING
4707 IN l_api_version,
4708 IN FND_API.G_FALSE,
4709 IN FND_API.G_FALSE,
4710 OUT x_return_status,
4711 OUT l_msg_count,
4712 OUT l_msg_data,
4713 IN l_rejection_id
4714 ;
4715
4716 print_debuginfo(l_module_name, 'Parameter(s) returned by callout - '
4717 || 'x_return_status: '
4718 || x_return_status
4719 );
4720
4721 /*
4722 * If the called procedure did not return success,
4723 * raise an exception.
4724 */
4725 IF (x_return_status IS NULL OR
4726 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
4727
4728 print_debuginfo(l_module_name, 'Fatal: External app callout '''
4729 || l_callout_name
4730 || ''', returned failure status - '
4731 || x_return_status
4732 || '. Raising exception.'
4733 );
4734
4735 APP_EXCEPTION.RAISE_EXCEPTION;
4736
4737 END IF;
4738
4739 EXCEPTION
4740
4741 WHEN PROCEDURE_NOT_IMPLEMENTED THEN
4742 print_debuginfo(l_module_name, 'Callout "' || l_callout_name
4743 || '" not implemented by calling app '
4744 || l_app_short_name || '.');
4745
4746 print_debuginfo(l_module_name, 'Skipping hook call.');
4747
4748
4749 WHEN OTHERS THEN
4750 print_debuginfo(l_module_name, 'Fatal: External app callout '''
4751 || l_callout_name
4752 || ''', generated exception.'
4753 );
4754
4755 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
4756 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
4757 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
4758
4759 /*
4760 * Propogate exception to caller.
4761 */
4762 RAISE;
4763 END;
4764
4765 /*
4766 * STEP 5:
4767 *
4768 * Clean up the ppr by unstamping it. In case the
4769 * concurrent request that was handling this ppr
4770 * had aborted with an exception, this step will
4771 * clean up the data.
4772 */
4773
4774 /*
4775 * Fix for bug 5206672:
4776 *
4777 * If we reached here, then the payment request has
4778 * been updated to TERMINATED status and the calling app
4779 * has been informed.
4780 *
4781 * Perform a COMMIT here before calling unlock_pmt_entity(..)
4782 * otherwise a deadlock ensues.
4783 */
4784 COMMIT;
4785
4786 unlock_pmt_entity(
4787 p_req_id,
4788 'PAYMENT_REQUEST',
4789 l_ret_status
4790 );
4791
4792 x_return_status := FND_API.G_RET_STS_SUCCESS;
4793
4794 print_debuginfo(l_module_name, 'EXIT');
4795
4796 EXCEPTION
4797
4798 WHEN OTHERS THEN
4799
4800 print_debuginfo(l_module_name, 'Exception occured when '
4801 || 'terminating payment request '
4802 || p_req_id
4803 || ', with status '
4804 || p_req_status
4805 );
4806
4807 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
4808 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
4809 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
4810
4811 x_return_status := FND_API.G_RET_STS_ERROR;
4812
4813 print_debuginfo(l_module_name, 'EXIT');
4814
4815 END terminate_pmt_request;
4816
4817 /*--------------------------------------------------------------------
4818 | NAME:
4819 | resubmit_pmt_request
4820 |
4821 |
4822 | PURPOSE:
4823 |
4824 |
4825 | PARAMETERS:
4826 | IN
4827 | p_payreq_id The id of the payment request that needs to be
4828 | re-processed by the Build Program.
4829 | OUT
4830 | x_conc_req_id The id of the concurrent request that was launched
4831 | by this API. The user will have to check this
4832 | concurrent request status via SRS UI to know the
4833 | result of the concurrent request. This concurrent
4834 | request will invoke the Build Program for this
4835 | payment request.
4836 | x_error_buf message buffer that stores the cause of the error.
4837 | x_return_status '-1' will be returned in the case of an error
4838 | '0' will be returned if the request completed
4839 | successfully.
4840 |
4841 | RETURNS:
4842 |
4843 | NOTES:
4844 | This method will perform a COMMIT after each functional
4845 | flow is complete. The caller should have finished all database
4846 | operations before making a call this method. The caller should
4847 | not call commit after invoking this method.
4848 |
4849 *---------------------------------------------------------------------*/
4850 PROCEDURE resubmit_pmt_request (
4851 p_payreq_id IN NUMBER,
4852 x_conc_req_id IN OUT NOCOPY NUMBER,
4853 x_error_buf IN OUT NOCOPY VARCHAR2,
4854 x_return_status IN OUT NOCOPY NUMBER
4855 )
4856 IS
4857
4858 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
4859 || '.resubmit_pmt_request';
4860
4861 l_req_attribs IBY_PAY_SERVICE_REQUESTS%ROWTYPE;
4862 l_ret_status VARCHAR2(200);
4863
4864 l_icx_numeric_characters VARCHAR2(30); -- Bug 6411356
4865 l_bool_val boolean; -- Bug 6411356
4866
4867 BEGIN
4868
4869 print_debuginfo(l_module_name, 'ENTER');
4870
4871 FND_MSG_PUB.initialize;
4872
4873 /*
4874 * STATUS CHANGE:
4875 *
4876 * UI Responsibility:
4877 * request status = RETRY_DOCUMENT_VALIDATION |
4878 * RETRY_PAYMENT_CREATION
4879 * payment_status = MODIFIED |
4880 * MODIFIED_PAYEE_BANK_ACCOUNT
4881 *
4882 * API Responsibility:
4883 * NONE
4884 */
4885
4886 /*
4887 * Pick up the attributes of this request; these are
4888 * params like rejection level settings, review
4889 * payments setting etc.
4890 */
4891 SELECT
4892 payment_service_request_id,
4893 calling_app_id,
4894 call_app_pay_service_req_code,
4895 payment_service_request_status,
4896 process_type,
4897 allow_zero_payments_flag,
4898 created_by,
4899 creation_date,
4900 last_updated_by,
4901 last_update_date,
4902 object_version_number,
4903 last_update_login,
4904 internal_bank_account_id,
4905 payment_profile_id,
4906 maximum_payment_amount,
4907 minimum_payment_amount,
4908 document_rejection_level_code,
4909 payment_rejection_level_code,
4910 require_prop_pmts_review_flag,
4911 org_type,
4912 attribute_category,
4913 attribute1,
4914 attribute2,
4915 attribute3,
4916 attribute4,
4917 attribute5,
4918 attribute6,
4919 attribute7,
4920 attribute8,
4921 attribute9,
4922 attribute10,
4923 attribute11,
4924 attribute12,
4925 attribute13,
4926 attribute14,
4927 attribute15,
4928 create_pmt_instructions_flag,
4929 payment_document_id,
4930 request_id
4931 INTO
4932 l_req_attribs
4933 FROM
4934 IBY_PAY_SERVICE_REQUESTS
4935 WHERE
4936 PAYMENT_SERVICE_REQUEST_ID = p_payreq_id
4937 ;
4938
4939 /*
4940 * Now resubmit the payment request by invoking
4941 * the Build Program functional flows again for
4942 * this request.
4943 *
4944 * This method will begin processing the payment
4945 * request from the last processed point. Therefore,
4946 * we need not bother about the last processed point
4947 * here.
4948 *
4949 * This will launch a concurrent request for processing
4950 * the payment request. We will return the concurrent
4951 * request id back to the user.
4952 */
4953
4954
4955 --Bug 6411356
4956 --below code added to set the current nls character setting
4957 --before submitting a child requests.
4958 fnd_profile.get('ICX_NUMERIC_CHARACTERS',l_icx_numeric_characters);
4959 l_bool_val:= FND_REQUEST.SET_OPTIONS( numeric_characters => l_icx_numeric_characters);
4960
4961 x_conc_req_id := FND_REQUEST.SUBMIT_REQUEST(
4962 'IBY',
4963 'IBYBUILD',
4964 '',
4965 '',
4966 FALSE,
4967 ''||l_req_attribs.calling_app_id||'',
4968 ''||l_req_attribs.call_app_pay_service_req_code||'',
4969 ''||l_req_attribs.internal_bank_account_id||'',
4970 ''||l_req_attribs.payment_profile_id||'',
4971 ''||l_req_attribs.allow_zero_payments_flag||'',
4972 ''||l_req_attribs.maximum_payment_amount||'',
4973 ''||l_req_attribs.minimum_payment_amount||'',
4974 ''||l_req_attribs.document_rejection_level_code||'',
4975 ''||l_req_attribs.payment_rejection_level_code||'',
4976 ''||l_req_attribs.require_prop_pmts_review_flag||'',
4977 'N',
4978 '', '', '', '', '', '', '', '', '', '',
4979 '', '', '', '', '', '', '', '', '', '',
4980 '', '', '', '', '', '', '', '', '', '',
4981 '', '', '', '', '', '', '', '', '', '',
4982 '', '', '', '', '', '', '', '', '', '',
4983 '', '', '', '', '', '', '', '', '', '',
4984 '', '', '', '', '', '', '', '', '', '',
4985 '', '', '', '', '', '', '', '', '', '',
4986 '', '', '', '', '', '', ''
4987 );
4988
4989 IF (x_conc_req_id = 0) THEN
4990
4991 print_debuginfo(l_module_name, 'Concurrent program request failed.');
4992 APP_EXCEPTION.RAISE_EXCEPTION;
4993
4994 ELSE
4995
4996 print_debuginfo(l_module_name, 'The concurrent request was '
4997 || 'launched successfully. '
4998 || 'Check concurrent request id :'
4999 || to_char(x_conc_req_id)
5000 );
5001
5002 /*
5003 * Lock the payment request so that the user is not
5004 * allowed to take any action upon this payment
5005 * request until the concurrent request just launched
5006 * has completed.
5007 */
5008 lock_pmt_entity(
5009 p_payreq_id,
5010 'PAYMENT_REQUEST',
5011 x_conc_req_id,
5012 l_ret_status
5013 );
5014
5015 /*
5016 * If we are unable to lock the payment request, abort.
5017 */
5018 IF (l_ret_status <> FND_API.G_RET_STS_SUCCESS) THEN
5019
5020 print_debuginfo(l_module_name, 'Unable to lock payment '
5021 || 'process request: '
5022 || p_payreq_id
5023 || '.'
5024 );
5025
5026 APP_EXCEPTION.RAISE_EXCEPTION;
5027
5028 END IF;
5029
5030 END IF;
5031
5032 x_return_status := 0;
5033 x_error_buf := 'BUILD PROGRAM INVOKED - RESUBMITTING PAYMENT'
5034 || ' REQUEST SUCCEEDED';
5035 print_debuginfo(l_module_name, 'EXIT');
5036
5037 EXCEPTION
5038
5039 WHEN OTHERS THEN
5040
5041 print_debuginfo(l_module_name, 'Exception occured when resubmitting '
5042 || 'payment request id '
5043 || p_payreq_id
5044 );
5045 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
5046 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
5047 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
5048
5049 x_error_buf := 'BUILD PROGRAM ERROR - RESUBMITTING PAYMENT'
5050 || ' REQUEST FAILED';
5051
5052 x_return_status := -1;
5053
5054 print_debuginfo(l_module_name, 'EXIT');
5055
5056 END resubmit_pmt_request;
5057
5058 /*--------------------------------------------------------------------
5059 | NAME:
5060 | resubmit_instruction
5061 |
5062 |
5063 | PURPOSE:
5064 |
5065 |
5066 | PARAMETERS:
5067 | IN
5068 |
5069 |
5070 | OUT
5071 |
5072 |
5073 | RETURNS:
5074 |
5075 | NOTES:
5076 | Internal API, not for public use.
5077 |
5078 *---------------------------------------------------------------------*/
5079 PROCEDURE resubmit_instruction (
5080 p_ins_id IN NUMBER,
5081 x_conc_req_id IN OUT NOCOPY NUMBER,
5082 x_error_buf IN OUT NOCOPY VARCHAR2,
5083 x_return_status IN OUT NOCOPY NUMBER
5084 )
5085 IS
5086
5087 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME || '.resubmit_instruction';
5088 l_str_ret_status VARCHAR2(200);
5089 l_icx_numeric_characters VARCHAR2(30); -- Bug 6411356
5090 l_bool_val boolean; -- Bug 6411356
5091
5092 BEGIN
5093
5094 print_debuginfo(l_module_name, 'ENTER');
5095
5096 FND_MSG_PUB.initialize;
5097
5098 /*
5099 * STATUS CHANGE:
5100 *
5101 * UI Responsibility:
5102 * instruction status = RETRY_CREATION
5103 *
5104 * API Responsibility:
5105 * NONE
5106 */
5107
5108 /*
5109 * This will launch a concurrent request for processing
5110 * the payment instruction. We will return the concurrent
5111 * request id back to the user.
5112 */
5113
5114
5115 --Bug 6411356
5116 --below code added to set the current nls character setting
5117 --before submitting a child requests.
5118 fnd_profile.get('ICX_NUMERIC_CHARACTERS',l_icx_numeric_characters);
5119 l_bool_val:= FND_REQUEST.SET_OPTIONS( numeric_characters => l_icx_numeric_characters);
5120
5121
5122 x_conc_req_id := FND_REQUEST.SUBMIT_REQUEST(
5123 'IBY',
5124 'IBYREPICP',
5125 '',
5126 '',
5127 FALSE,
5128 ''||p_ins_id||'',
5129 '', '', '', '', '', '', '', '', '', '',
5130 '', '', '', '', '', '', '', '', '', '',
5131 '', '', '', '', '', '', '', '', '', '',
5132 '', '', '', '', '', '', '', '', '', '',
5133 '', '', '', '', '', '', '', '', '', '',
5134 '', '', '', '', '', '', '', '', '', '',
5135 '', '', '', '', '', '', '', '', '', '',
5136 '', '', '', '', '', '', '', '', '', '',
5137 '', '', '', '', '', '', '', '', '', '',
5138 '', '', '', '', '', '', ''
5139 );
5140
5141 IF (x_conc_req_id = 0) THEN
5142
5143 print_debuginfo(l_module_name, 'Concurrent program request failed.');
5144 APP_EXCEPTION.RAISE_EXCEPTION;
5145
5146 ELSE
5147
5148 print_debuginfo(l_module_name, 'The concurrent request was '
5149 || 'launched successfully. '
5150 || 'Check concurrent request id :'
5151 || to_char(x_conc_req_id)
5152 );
5153
5154 /*
5155 * Lock the payment instruction so that the user is not
5156 * allowed to take any action upon this payment
5157 * instruction until the concurrent request just launched
5158 * has completed.
5159 */
5160
5161 /*
5162 * Fix for bug 5206725:
5163 *
5164 * Pass a VARCHAR data type for the return status
5165 * instead of a NUMBER data type.
5166 */
5167 lock_pmt_entity(
5168 p_ins_id,
5169 'PAYMENT_INSTRUCTION',
5170 x_conc_req_id,
5171 l_str_ret_status
5172 );
5173
5174 IF (l_str_ret_status <> FND_API.G_RET_STS_SUCCESS) THEN
5175
5176 print_debuginfo(l_module_name, 'Unable to lock payment '
5177 || 'instruction: '
5178 || p_ins_id
5179 || '.'
5180 );
5181
5182 APP_EXCEPTION.RAISE_EXCEPTION;
5183
5184 END IF;
5185
5186 END IF;
5187
5188 x_return_status := 0;
5189 x_error_buf := 'PICP INVOKED - RESUBMITTING PAYMENT'
5190 || ' INSTRUCTION SUCCEEDED';
5191
5192 print_debuginfo(l_module_name, 'EXIT');
5193
5194 EXCEPTION
5195
5196 WHEN OTHERS THEN
5197
5198 print_debuginfo(l_module_name, 'Exception occured when resubmitting '
5199 || 'payment instruction '
5200 || p_ins_id
5201 );
5202 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
5203 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
5204 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
5205
5206 x_error_buf := 'PICP ERROR - RESUBMITTING PAYMENT'
5207 || ' INSTRUCTION FAILED';
5208
5209 x_return_status := -1;
5210
5211 print_debuginfo(l_module_name, 'EXIT');
5212
5213 END resubmit_instruction;
5214
5215 /*--------------------------------------------------------------------
5216 | NAME:
5217 | reprint_prenum_pmt_documents
5218 |
5219 |
5220 | PURPOSE:
5221 | This API should be called if it is required to re-print some of the
5222 | paper documents of a payment instruction. This API should only
5223 | be called with the list of paper documents that were spoilt (not
5224 | with the list of paper documents that were skipped, issued etc.).
5225 |
5226 | The list of used paper documents numbers will be used to insert
5227 | records into the IBY_USED_PAYMENT_DOCS table.
5228 |
5229 | The list of new paper document numbers will be used to update the
5230 | IBY_PAYMENTS_ALL table with the new paper document numbers for
5231 | the corresponding paments. The payment status will then be set to
5232 | READY_FOR_REPRINT.
5233 |
5234 | Finally, this API will invoke the paper printing flow.
5235 |
5236 | This method should only be invoked for reprinting payment documents
5237 | that are prenumbered (paper stock type is 'prenumbered'). For
5238 | reprinting payment documents that are on blank stock use the method
5239 | reprint_blank_pmt_documents().
5240 |
5241 | PARAMETERS:
5242 | IN
5243 | p_instr_id - ID of the payment instruction, for which some
5244 | payments need to be re-printed.
5245 | p_pmt_doc_id - The payment document id (check stock) which
5246 | is to be used for re-printing.
5247 | p_pmt_list - List of payments that are affected by the
5248 | re-print. These payments will be updated with
5249 | new paper document numbers (provided by the user).
5250 | p_new_ppr_docs_list
5251 | - List of new paper document numbers to print
5252 | the provided payments on.
5253 | p_old_ppr_docs_list
5254 | - List of previously used paper document numbers.
5255 | These will be inserted into IBY_USED_PAYMENT_DOCS
5256 | table indicating that they were spoiled.
5257 | p_printer_name - Printer to use for re-printing payments.
5258 |
5259 |
5260 | OUT
5261 | x_return_status - Result of the API call:
5262 | FND_API.G_RET_STS_SUCCESS indicates that the
5263 | reprint process was triggered successfully.
5264 | In this case the caller must COMMIT
5265 | the status change.
5266 |
5267 | FND_API.G_RET_STS_ERROR (or other) indicates
5268 | that API did not complete successfully.
5269 | In this case, the caller must issue a
5270 | ROLLBACK to undo all status changes.
5271 |
5272 | RETURNS:
5273 |
5274 | NOTES:
5275 | Internal API, not for public use.
5276 |
5277 *---------------------------------------------------------------------*/
5278 PROCEDURE reprint_prenum_pmt_documents(
5279 p_instr_id IN NUMBER,
5280 p_pmt_doc_id IN NUMBER,
5281 p_pmt_list IN pmtIDTab,
5282 p_new_ppr_docs_list IN pmtDocsTab,
5283 p_old_ppr_docs_list IN pmtDocsTab,
5284 p_printer_name IN VARCHAR2,
5285 x_return_status OUT NOCOPY VARCHAR2
5286 )
5287 IS
5288
5289 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
5290 || '.reprint_prenum_pmt_documents';
5291
5292 l_pkg_name CONSTANT VARCHAR2(100) := 'AP_AWT_CALLOUT_PKG';
5293
5294 l_callout_name VARCHAR2(500);
5295 l_stmt VARCHAR2(1000);
5296
5297 /* used in invocation of callout procedure */
5298 l_api_version CONSTANT NUMBER := 1.0;
5299 l_msg_count NUMBER;
5300 l_msg_data VARCHAR2(2000);
5301
5302 l_curr_pmt_status VARCHAR2(200);
5303 l_temp_status VARCHAR2(200);
5304
5305 l_last_list_num NUMBER;
5306 l_last_doc_num NUMBER;
5307
5308 /*
5309 * Implementing the hook is optional for the calling app.
5310 * If the calling app does not implement the hook, then
5311 * the call to the hook will result in ORA-06576 error.
5312 *
5313 * There is no exception name associated with this code, so
5314 * we create one called 'PROCEDURE_NOT_IMPLEMENTED'. If this
5315 * exception occurs, it is not fatal: we log the error and
5316 * proceed.
5317 *
5318 * If, on the other hand, the calling app implements the
5319 * hook, but the hook throws an exception, it is fatal
5320 * and we must abort the program (this will be caught
5321 * in WHEN OTHERS block).
5322 */
5323 PROCEDURE_NOT_IMPLEMENTED EXCEPTION;
5324 PRAGMA EXCEPTION_INIT(PROCEDURE_NOT_IMPLEMENTED, -6576);
5325
5326 BEGIN
5327
5328 print_debuginfo(l_module_name, 'ENTER');
5329
5330 FND_MSG_PUB.initialize;
5331
5332 /*
5333 * STATUS CHANGE:
5334 *
5335 * UI Responsibility:
5336 * NONE
5337 *
5338 * API Responsibility:
5339 * paper document use reason = SPOILED
5340 * payment status = READY_TO_REPRINT
5341 */
5342
5343 IF (p_pmt_list.COUNT = 0 OR
5344 p_new_ppr_docs_list.COUNT = 0 OR
5345 p_old_ppr_docs_list.COUNT = 0) THEN
5346
5347 print_debuginfo(l_module_name, 'Error: List of used paper '
5348 || 'document numbers/new paper document numbers/payment '
5349 || 'ids is empty'
5350 || '. Returning failure response .. '
5351 );
5352
5353 x_return_status := FND_API.G_RET_STS_ERROR;
5354
5355 print_debuginfo(l_module_name, 'EXIT');
5356
5357 RETURN;
5358
5359 END IF;
5360
5361 IF (p_pmt_list.COUNT <> p_new_ppr_docs_list.COUNT OR
5362 p_pmt_list.COUNT <> p_old_ppr_docs_list.COUNT) THEN
5363
5364 print_debuginfo(l_module_name, 'Error: List of paper '
5365 || 'doc numbers must match list of payment ids. '
5366 || 'Returning failure response .. '
5367 );
5368
5369 x_return_status := FND_API.G_RET_STS_ERROR;
5370
5371 print_debuginfo(l_module_name, 'EXIT');
5372
5373 RETURN;
5374
5375 END IF;
5376
5377 /*
5378 * STEP 0 .
5379 *
5380 * Setting the printer name supplied
5381 * while reprinting the payment
5382 * instruction
5383 *
5384 */
5385
5386 UPDATE iby_pay_instructions_all ins
5387 SET ins.printer_name = p_printer_name
5388 WHERE ins.payment_instruction_id = p_instr_id;
5389
5390
5391 print_debuginfo(l_module_name, 'Set printer name as '
5392 || p_printer_name
5393 || ' for payment instruction id '
5394 || p_instr_id
5395 );
5396
5397 /*A commit is necessary to avoid deadlock situations*/
5398 COMMIT;
5399
5400 /*
5401 * STEP 1:
5402 *
5403 * Update the IBY_USED_PAYMENT_DOCS table with the list of
5404 * used paper document numbers. Since the user invokes this API
5405 * to reprint the paper documents, it follows that the earlier
5406 * used paper document was spoilt. Therefore, set the status of
5407 * the earlier used paper document to SPOILED.
5408 */
5409
5410 FOR i IN p_old_ppr_docs_list.FIRST .. p_old_ppr_docs_list.LAST LOOP
5411
5412 print_debuginfo(l_module_name, 'Updating paper doc number '
5413 || p_old_ppr_docs_list(i)
5414 || ' of payment document id '
5415 || p_pmt_doc_id
5416 || ' to spoiled status ..'
5417 );
5418
5419 INSERT INTO IBY_USED_PAYMENT_DOCS (
5420 PAYMENT_DOCUMENT_ID,
5421 USED_DOCUMENT_NUMBER,
5422 DATE_USED,
5423 DOCUMENT_USE,
5424 CREATED_BY,
5425 CREATION_DATE,
5426 LAST_UPDATED_BY,
5427 LAST_UPDATE_DATE,
5428 LAST_UPDATE_LOGIN,
5429 OBJECT_VERSION_NUMBER
5430 )
5431 VALUES (
5432 p_pmt_doc_id,
5433 p_old_ppr_docs_list(i),
5434 sysdate,
5435 DOC_USE_SPOILED,
5436 fnd_global.user_id,
5437 sysdate,
5438 fnd_global.user_id,
5439 sysdate,
5440 fnd_global.login_id,
5441 1
5442 );
5443
5444 END LOOP;
5445
5446 /*
5447 * STEP 2:
5448 *
5449 * Update the IBY_PAYMENTS_ALL table with the list of
5450 * new paper document numbers. The payment ids and new
5451 * paper document numbers have been provided in matching
5452 * order. The status of the payment also needs to be
5453 * updated to READY_FOR_REPRINT.
5454 */
5455
5456 FOR i IN p_new_ppr_docs_list.FIRST .. p_new_ppr_docs_list.LAST LOOP
5457
5458 /*
5459 * Get the current status of the
5460 * payment into l_curr_pmt_status
5461 */
5462 SELECT
5463 pmt.payment_status
5464 INTO
5465 l_curr_pmt_status
5466 FROM
5467 IBY_PAYMENTS_ALL pmt
5468 WHERE
5469 payment_id = p_pmt_list(i)
5470 ;
5471
5472 /*
5473 * For debug purposes.
5474 */
5475 IF (l_curr_pmt_status = PAY_STATUS_VOID_SETUP) THEN
5476
5477 l_temp_status := PAY_STATUS_SETUP_REPRINT;
5478
5479 ELSIF (l_curr_pmt_status = PAY_STATUS_VOID_OVERFLOW) THEN
5480
5481 l_temp_status := PAY_STATUS_OVERFLOW_REPRINT;
5482
5483 ELSE
5484
5485 l_temp_status := PAY_STATUS_REPRINT;
5486
5487 END IF;
5488
5489 print_debuginfo(l_module_name, 'Updating status of payment id '
5490 || p_pmt_list(i)
5491 || ' from '
5492 || l_curr_pmt_status
5493 || ' to '
5494 || l_temp_status
5495 );
5496
5497 /*
5498 * Set the payment status to READY_TO_REPRINT
5499 *
5500 * Void and overflow payments are identified by
5501 * their statuses, so we do not want to blindly
5502 * overwrite ther statuses. Instead, set their
5503 * status to special statuses that indicate the
5504 * payment is a setup / overflow payment and
5505 * it must be reprinted.
5506 */
5507 UPDATE
5508 IBY_PAYMENTS_ALL
5509 SET
5510 paper_document_number = p_new_ppr_docs_list(i),
5511 payment_status = DECODE(
5512 l_curr_pmt_status,
5513 PAY_STATUS_VOID_SETUP,
5514 PAY_STATUS_SETUP_REPRINT,
5515 PAY_STATUS_VOID_OVERFLOW,
5516 PAY_STATUS_OVERFLOW_REPRINT,
5517 PAY_STATUS_REPRINT
5518 )
5519 WHERE
5520 payment_id = p_pmt_list(i) AND
5521 payment_instruction_id = p_instr_id
5522 ;
5523
5524 END LOOP;
5525
5526
5527 /*
5528 * STEP 2A:
5529 *
5530 * Fix for bug 5470041:
5531 *
5532 * Update the last issued document number
5533 * in CE_PAYMENT_DOCUMENTS table using the
5534 * greatest document number from the user
5535 * provided list of new document numbers
5536 * for reprinting.
5537 */
5538
5539 l_last_list_num := -1;
5540
5541 FOR i IN p_new_ppr_docs_list.FIRST .. p_new_ppr_docs_list.LAST LOOP
5542
5543 IF (p_new_ppr_docs_list(i) > l_last_list_num) THEN
5544
5545 l_last_list_num := p_new_ppr_docs_list(i);
5546
5547 END IF;
5548
5549 END LOOP;
5550
5551 print_debuginfo(l_module_name, 'Greatest paper document number '
5552 || 'derived from provided list: '
5553 || l_last_list_num
5554 );
5555
5556 /*
5557 * This update uses an extra security check - we
5558 * only update the last issued doc number if the
5559 * provided list contains a doc number greater
5560 * than what is already stored in the database.
5561 */
5562 UPDATE
5563 CE_PAYMENT_DOCUMENTS
5564 SET
5565 last_issued_document_number =
5566 GREATEST(l_last_list_num, last_issued_document_number)
5567 WHERE
5568 payment_document_id = p_pmt_doc_id
5569 RETURNING
5570 last_issued_document_number
5571 INTO
5572 l_last_doc_num
5573 ;
5574
5575 print_debuginfo(l_module_name, 'Payment document id '
5576 || p_pmt_doc_id
5577 || ' updated with last issued doc number set to: '
5578 || l_last_doc_num
5579 );
5580
5581 /*
5582 * STEP 3:
5583 *
5584 * Invoke the hook that handles witholding certificates.
5585 * Every time a paper document is PRINTED | REPRINTED |
5586 * SPOILED, the witholding certificates should be in sync.
5587 */
5588 l_callout_name := l_pkg_name || '.' || 'zx_witholdingCertificatesHook';
5589
5590 print_debuginfo(l_module_name, 'Attempting to call hook: '
5591 || l_callout_name);
5592
5593 l_stmt := 'CALL '|| l_callout_name || '(:1, :2, :3, :4, :5, :6, :7, :8)';
5594
5595 BEGIN
5596
5597 EXECUTE IMMEDIATE
5598 (l_stmt)
5599 USING
5600 IN p_instr_id,
5601 IN 'REPRINT',
5602 IN l_api_version,
5603 IN FND_API.G_FALSE,
5604 IN FND_API.G_FALSE,
5605 OUT x_return_status,
5606 OUT l_msg_count,
5607 OUT l_msg_data
5608 ;
5609
5610 /*
5611 * If the called procedure did not return success,
5612 * raise an exception.
5613 */
5614 IF (x_return_status IS NULL OR
5615 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
5616
5617 print_debuginfo(l_module_name, 'Fatal: External app callout '''
5618 || l_callout_name
5619 || ''', returned failure status - '
5620 || x_return_status
5621 || '. Raising exception.'
5622 );
5623
5624 APP_EXCEPTION.RAISE_EXCEPTION;
5625
5626 END IF;
5627
5628 EXCEPTION
5629
5630 WHEN PROCEDURE_NOT_IMPLEMENTED THEN
5631 print_debuginfo(l_module_name, 'Callout "' || l_callout_name
5632 || '" not implemented by calling app - AP'
5633 );
5634
5635 print_debuginfo(l_module_name, 'Skipping hook call.');
5636
5637
5638 WHEN OTHERS THEN
5639 print_debuginfo(l_module_name, 'Fatal: External app callout '''
5640 || l_callout_name
5641 || ''', generated exception.'
5642 );
5643
5644 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
5645 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
5646 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
5647
5648 /*
5649 * Propogate exception to caller.
5650 */
5651 RAISE;
5652 END;
5653
5654
5655
5656 /*
5657 * STEP 4:
5658 *
5659 * Invoke the print routine to re-print these payments.
5660 */
5661 IBY_FD_POST_PICP_PROGS_PVT.
5662 Run_Post_PI_Programs(
5663 p_instr_id,
5664 'Y'
5665 );
5666
5667 x_return_status := FND_API.G_RET_STS_SUCCESS;
5668
5669 print_debuginfo(l_module_name, 'Returning success response ..');
5670
5671 print_debuginfo(l_module_name, 'EXIT');
5672
5673 EXCEPTION
5674 WHEN OTHERS THEN
5675
5676 print_debuginfo(l_module_name, 'Exception occured when '
5677 || 'performing re-print for payment instruction '
5678 || p_instr_id
5679 );
5680
5681 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
5682 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
5683 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
5684
5685 x_return_status := FND_API.G_RET_STS_ERROR;
5686
5687 print_debuginfo(l_module_name, 'EXIT');
5688
5689 END reprint_prenum_pmt_documents;
5690
5691
5692 /*--------------------------------------------------------------------
5693 | NAME:
5694 | reprint_blank_pmt_documents
5695 |
5696 |
5697 | PURPOSE:
5698 | This API should be called if it is required to re-print some of the
5699 | paper documents of a payment instruction. This API should only
5700 | be called with the list of paper documents that were spoilt (not
5701 | with the list of paper documents that were skipped, issued etc.).
5702 |
5703 | The payment status will then be set to READY_FOR_REPRINT. No paper
5704 | document number adjustment is required because the same paper
5705 | document can be reused for bank paper stock. Only the status of the
5706 | payment will be changed, the exiting paper document number on the
5707 | payment will be untoched.
5708 |
5709 | Finally, this API will invoke the paper printing flow.
5710 |
5711 | This method should only be invoked for reprinting payment
5712 | documents that are printed on blank paper stock (not for
5713 | paper stock type that is 'prenumbered'). For reprinting
5714 | payment documents that are on prenumbered stock use the method
5715 | reprint_prenum_pmt_documents().
5716 |
5717 | PARAMETERS:
5718 | IN
5719 | p_instr_id - ID of the payment instruction, for which some
5720 | payments need to be re-printed.
5721 | p_pmt_list - List of payments that are affected by the
5722 | re-print. The status of these payments will be
5723 | updated to indicate they are ready for reprint.
5724 | p_printer_name - Printer to use for re-printing payments.
5725 |
5726 |
5727 | OUT
5728 | x_return_status - Result of the API call:
5729 | FND_API.G_RET_STS_SUCCESS indicates that the
5730 | reprint process was triggered successfully.
5731 | In this case the caller must COMMIT
5732 | the status change.
5733 |
5734 | FND_API.G_RET_STS_ERROR (or other) indicates
5735 | that API did not complete successfully.
5736 | In this case, the caller must issue a
5737 | ROLLBACK to undo all status changes.
5738 |
5739 | RETURNS:
5740 |
5741 | NOTES:
5742 | Internal API, not for public use.
5743 |
5744 *---------------------------------------------------------------------*/
5745 PROCEDURE reprint_blank_pmt_documents(
5746 p_instr_id IN NUMBER,
5747 p_pmt_list IN pmtIDTab,
5748 p_printer_name IN VARCHAR2,
5749 x_return_status OUT NOCOPY VARCHAR2
5750 )
5751 IS
5752
5753 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
5754 || '.reprint_blank_pmt_documents';
5755
5756 l_curr_pmt_status VARCHAR2(200);
5757
5758 BEGIN
5759
5760 print_debuginfo(l_module_name, 'ENTER');
5761
5762 FND_MSG_PUB.initialize;
5763
5764 /*
5765 * STEP 0 .
5766 *
5767 * Setting the printer name supplied
5768 * while reprinting the payment
5769 * instruction
5770 *
5771 */
5772
5773 UPDATE iby_pay_instructions_all ins
5774 SET ins.printer_name = p_printer_name
5775 WHERE ins.payment_instruction_id = p_instr_id;
5776
5777
5778 print_debuginfo(l_module_name, 'Set printer name as '
5779 || p_printer_name
5780 || ' for payment instruction id '
5781 || p_instr_id
5782 );
5783
5784 /*A commit is necessary to avoid deadlock situations*/
5785 COMMIT;
5786
5787 /*
5788 * STEP 1:
5789 *
5790 * Check whether any payments have been provided.
5791 */
5792 IF (p_pmt_list.COUNT = 0) THEN
5793
5794 print_debuginfo(l_module_name, 'Error: List of payment ids '
5795 || 'is empty'
5796 || '. Returning failure response .. '
5797 );
5798
5799 x_return_status := FND_API.G_RET_STS_ERROR;
5800
5801 print_debuginfo(l_module_name, 'EXIT');
5802
5803 RETURN;
5804
5805 END IF;
5806
5807 /*
5808 * STEP 2:
5809 *
5810 * Update the IBY_PAYMENTS_ALL table with the new status.
5811 * The status of the payment needs to be READY_FOR_REPRINT.
5812 */
5813 FOR i IN p_pmt_list.FIRST .. p_pmt_list.LAST LOOP
5814
5815 /*
5816 * Get the current status of the
5817 * payment into l_curr_pmt_status
5818 */
5819 SELECT
5820 pmt.payment_status
5821 INTO
5822 l_curr_pmt_status
5823 FROM
5824 IBY_PAYMENTS_ALL pmt
5825 WHERE
5826 payment_id = p_pmt_list(i)
5827 ;
5828
5829
5830 /*
5831 * Set the payment status to READY_TO_REPRINT
5832 *
5833 * Void and overflow payments are identified by
5834 * their statuses, so we do not want to blindly
5835 * overwrite ther statuses. Instead, set their
5836 * status to special statuses that indicate the
5837 * payment is a setup / overflow payment and
5838 * it must be reprinted.
5839 */
5840 UPDATE
5841 IBY_PAYMENTS_ALL
5842 SET
5843 payment_status = DECODE(
5844 l_curr_pmt_status,
5845 PAY_STATUS_VOID_SETUP,
5846 PAY_STATUS_SETUP_REPRINT,
5847 PAY_STATUS_VOID_OVERFLOW,
5848 PAY_STATUS_OVERFLOW_REPRINT,
5849 PAY_STATUS_REPRINT
5850 )
5851 WHERE
5852 payment_id = p_pmt_list(i) AND
5853 payment_instruction_id = p_instr_id
5854 ;
5855
5856 END LOOP;
5857
5858
5859 /*
5860 * STEP 3:
5861 *
5862 * Invoke the print routine to re-print these payments.
5863 */
5864 IBY_FD_POST_PICP_PROGS_PVT.
5865 Run_Post_PI_Programs(
5866 p_instr_id,
5867 'Y'
5868 );
5869
5870 x_return_status := FND_API.G_RET_STS_SUCCESS;
5871
5872 print_debuginfo(l_module_name, 'Returning success response ..');
5873
5874 print_debuginfo(l_module_name, 'EXIT');
5875
5876 EXCEPTION
5877 WHEN OTHERS THEN
5878
5879 print_debuginfo(l_module_name, 'Exception occured when '
5880 || 'performing re-print for payment instruction '
5881 || p_instr_id
5882 );
5883
5884 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
5885 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
5886 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
5887
5888 x_return_status := FND_API.G_RET_STS_ERROR;
5889
5890 print_debuginfo(l_module_name, 'EXIT');
5891
5892 END reprint_blank_pmt_documents;
5893
5894 /*--------------------------------------------------------------------
5895 | NAME:
5896 | reprint_payment_instruction
5897 |
5898 | PURPOSE:
5899 | Reprints all the payment documents associated with a payment
5900 | instruction.
5901 |
5902 | Note that in this case, no renumbering of the paper documents
5903 | is required. This API is equivalent to making a fresh print call
5904 | for a payment instruction (only requirement is that the payments of
5905 | the payment instruction be numbered). We simply send the payment
5906 | instruction for printing with the existing payment document numbers.
5907 |
5908 | Do not call this API if printing for the payment instruction has
5909 | already been attempted earlier.
5910 |
5911 | PARAMETERS:
5912 | IN
5913 |
5914 |
5915 | OUT
5916 |
5917 |
5918 | RETURNS:
5919 |
5920 | NOTES:
5921 | Internal API, not for public use.
5922 |
5923 | This procedure performs a COMMIT.
5924 |
5925 *---------------------------------------------------------------------*/
5926 PROCEDURE reprint_payment_instruction (
5927 p_instr_id IN NUMBER,
5928 p_printer_name IN VARCHAR2,
5929 x_return_status OUT NOCOPY VARCHAR2
5930 )
5931 IS
5932
5933 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
5934 || '.reprint_payment_instruction';
5935
5936 BEGIN
5937
5938 print_debuginfo(l_module_name, 'ENTER');
5939
5940 FND_MSG_PUB.initialize;
5941
5942 /*
5943 * STEP 1:
5944 *
5945 * Update the status of the payments of the given
5946 * instruction to indicate that they must be reprinted.
5947 */
5948 print_debuginfo(l_module_name, 'Updating statuses of the '
5949 || 'payments of payment instruction '
5950 || p_instr_id
5951 || ' to formatted ..'
5952 );
5953
5954 UPDATE
5955 IBY_PAYMENTS_ALL
5956 SET
5957 payment_status = PAY_STATUS_FORMATTED
5958 WHERE
5959 payment_instruction_id = p_instr_id
5960 ;
5961
5962 /*
5963 * STEP 2:
5964 *
5965 * Update the status of the payment instruction
5966 * to indicate that it must be re-printed.
5967 */
5968 print_debuginfo(l_module_name, 'Updating status of '
5969 || 'payment instruction '
5970 || p_instr_id
5971 || ' to formatted - ready for printing ..'
5972 );
5973 UPDATE
5974 IBY_PAY_INSTRUCTIONS_ALL
5975 SET
5976 payment_instruction_status = INS_STATUS_FORMAT_TO_PRINT
5977 WHERE
5978 payment_instruction_id = p_instr_id
5979 ;
5980
5981 /*
5982 * This commit is necessary. Otherwise a deadlocked
5983 * condition is created when we try to update the same
5984 * payment instruction with the concurrent request id
5985 * (for handling intermediate statuses).
5986 */
5987 COMMIT;
5988
5989
5990 /*
5991 * STEP 3:
5992 *
5993 * Invoke the print routine to re-print these payments.
5994 */
5995
5996 /*
5997 * Note that reprint flag is 'N' in this case;
5998 * this is to treat the re-print as a fresh print.
5999 */
6000 IBY_FD_POST_PICP_PROGS_PVT.
6001 Run_Post_PI_Programs(
6002 p_instr_id,
6003 'N'
6004 );
6005
6006 x_return_status := FND_API.G_RET_STS_SUCCESS;
6007
6008 print_debuginfo(l_module_name, 'Returning success response ..');
6009
6010 print_debuginfo(l_module_name, 'EXIT');
6011
6012 EXCEPTION
6013 WHEN OTHERS THEN
6014
6015 print_debuginfo(l_module_name, 'Exception occured when '
6016 || 'performing re-print for payment instruction '
6017 || p_instr_id
6018 );
6019
6020 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
6021 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
6022 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
6023
6024 x_return_status := FND_API.G_RET_STS_ERROR;
6025
6026 print_debuginfo(l_module_name, 'EXIT');
6027
6028 END reprint_payment_instruction;
6029
6030
6031 /*--------------------------------------------------------------------
6032 | NAME:
6033 | finalize_print_status
6034 |
6035 |
6036 | PURPOSE:
6037 | Records the final print status for a set of paper documents.
6038 |
6039 | This is an overloaded method. See the other method signature
6040 | for complete documentation.
6041 |
6042 | PARAMETERS:
6043 | IN
6044 |
6045 |
6046 | OUT
6047 |
6048 |
6049 | RETURNS:
6050 |
6051 | NOTES:
6052 | Internal API, not for public use.
6053 |
6054 *---------------------------------------------------------------------*/
6055 PROCEDURE finalize_print_status(
6056 p_instr_id IN NUMBER,
6057 p_pmt_doc_id IN NUMBER,
6058 p_used_docs_list IN paperDocNumTab,
6059 x_return_status OUT NOCOPY VARCHAR2
6060 )
6061 IS
6062 BEGIN
6063
6064 finalize_print_status(
6065 p_instr_id,
6066 p_pmt_doc_id,
6067 p_used_docs_list,
6068 FALSE,
6069 x_return_status
6070 );
6071
6072 END finalize_print_status;
6073
6074 /*--------------------------------------------------------------------
6075 | NAME:
6076 | finalize_print_status
6077 |
6078 |
6079 | PURPOSE:
6080 | Records the final print status for a set of paper documents.
6081 |
6082 | This is an overloaded method. See the other method signature
6083 | for complete documentation.
6084 |
6085 | PARAMETERS:
6086 | IN
6087 |
6088 |
6089 | OUT
6090 |
6091 |
6092 | RETURNS:
6093 |
6094 | NOTES:
6095 | Internal API, not for public use.
6096 |
6097 *---------------------------------------------------------------------*/
6098 PROCEDURE finalize_print_status(
6099 p_instr_id IN NUMBER,
6100 p_pmt_doc_id IN NUMBER,
6101 p_used_docs_list IN paperDocNumTab,
6102 p_used_pmts_list IN paperDocNumTab,
6103 x_return_status OUT NOCOPY VARCHAR2
6104 )
6105 IS
6106 BEGIN
6107
6108 finalize_print_status(
6109 p_instr_id,
6110 p_pmt_doc_id,
6111 p_used_docs_list,
6112 p_used_pmts_list,
6113 FALSE,
6114 x_return_status
6115 );
6116
6117 END finalize_print_status;
6118
6119 /*--------------------------------------------------------------------
6120 | NAME:
6121 | finalize_print_status
6122 |
6123 | PURPOSE:
6124 | Records the final print status for a set of paper documents. This
6125 | API will insert the given set of paper document numbers into the
6126 | IBY_USED_PAYMENT_DOCS table along with the usage reason indicating
6127 | whether the paper document was spoiled.
6128 |
6129 | Note that this API should only be invoked with the list of spoiled
6130 | paper documents. The UI should directly handle the successfully
6131 | printed paper documents. For performance reasons, this API is
6132 | designed only to handle the spoiled paper document case.
6133 |
6134 | This API will set the usage reason for each provided document
6135 | to 'SPOILED' in the IBY_USED_PAYMENT_DOCS table, and it will also
6136 | set the status of the corresponding payment to
6137 | REMOVED_DOCUMENT_SPOILED.
6138 |
6139 | Then, this API will set the status of the successfully printed
6140 | payments to ISSUED status and then invoke the 'mark complete'
6141 | API to mark the payments of this payment instruction as complete.
6142 |
6143 | PARAMETERS:
6144 | IN
6145 | p_pmt_doc_id - The payment document id (check stock id)
6146 | of the given list of paper documents.
6147 | p_used_docs_list - The list of paper documents that have been
6148 | used for printing
6149 | p_use_reason_list - The list of paper document usage reasons. This
6150 | list will contain a lookup code that specifies
6151 | whether the paper document was correctly
6152 | printed or not. Possible values include
6153 | ISSUED | SPOILED. SKIPPED will never be a
6154 | provided reason because skipped documents have
6155 | successfully printed (only numbering is wrong).
6156 | p_submit_postive_pay
6157 | - Flag indicating whether positive pay file
6158 | report needs to be launched after finalizing
6159 | the payments.
6160 |
6161 | OUT
6162 | x_return_status - Result of the API call:
6163 | FND_API.G_RET_STS_SUCCESS indicates that the
6164 | finalization process completed raised
6165 | successfully. In this case the caller must
6166 | COMMIT the status change.
6167 |
6168 | FND_API.G_RET_STS_ERROR (or other) indicates
6169 | that API did not complete successfully.
6170 | In this case, the caller must issue a
6171 | ROLLBACK to undo all status changes.
6172 |
6173 | RETURNS:
6174 |
6175 | NOTES:
6176 | Internal API, not for public use.
6177 |
6178 *---------------------------------------------------------------------*/
6179 PROCEDURE finalize_print_status(
6180 p_instr_id IN NUMBER,
6181 p_pmt_doc_id IN NUMBER,
6182 p_used_docs_list IN paperDocNumTab,
6183 p_submit_postive_pay IN BOOLEAN,
6184 x_return_status OUT NOCOPY VARCHAR2
6185 )
6186 IS
6187
6188 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
6189 || '.finalize_print_status';
6190
6191 l_paper_doc_num IBY_PAYMENTS_ALL.paper_document_number%TYPE;
6192
6193 /* used in invocation of callout procedure */
6194 l_api_version CONSTANT NUMBER := 1.0;
6195 l_msg_count NUMBER;
6196 l_msg_data VARCHAR2(2000);
6197
6198 l_pkg_name CONSTANT VARCHAR2(100) := 'AP_AWT_CALLOUT_PKG';
6199
6200 l_callout_name VARCHAR2(500);
6201 l_stmt VARCHAR2(1000);
6202
6203 /* Bug #6508530 -used for changing status for spoiled payment, document */
6204 l_doc_id_list docPayIDTab;
6205 l_doc_status_list docPayStatusTab;
6206
6207 x_return_status_remove_doc VARCHAR2(200);
6208
6209 CURSOR c_docs (p_pmt_id IBY_PAYMENTS_ALL.
6210 payment_id%TYPE)
6211 IS
6212 SELECT
6213 doc.document_payable_id,
6214 doc.document_status
6215 FROM
6216 IBY_DOCS_PAYABLE_ALL doc
6217 WHERE
6218 doc.payment_id = p_pmt_id
6219
6220 ;
6221
6222
6223 /*
6224 * Implementing the hook is optional for the calling app.
6225 * If the calling app does not implement the hook, then
6226 * the call to the hook will result in ORA-06576 error.
6227 *
6228 * There is no exception name associated with this code, so
6229 * we create one called 'PROCEDURE_NOT_IMPLEMENTED'. If this
6230 * exception occurs, it is not fatal: we log the error and
6231 * proceed.
6232 *
6233 * If, on the other hand, the calling app implements the
6234 * hook, but the hook throws an exception, it is fatal
6235 * and we must abort the program (this will be caught
6236 * in WHEN OTHERS block).
6237 */
6238 PROCEDURE_NOT_IMPLEMENTED EXCEPTION;
6239 PRAGMA EXCEPTION_INIT(PROCEDURE_NOT_IMPLEMENTED, -6576);
6240
6241 BEGIN
6242
6243 print_debuginfo(l_module_name, 'ENTER');
6244
6245 FND_MSG_PUB.initialize;
6246
6247 /*
6248 * STATUS CHANGE:
6249 *
6250 * UI Responsibility:
6251 * NONE
6252 *
6253 * API Responsibility:
6254 * payment instruction status = PRINTED
6255 *
6256 * payment status = REMOVED_DOCUMENT_SPOILED (for spoiled payments)
6257 * payment status = ISSUED (for successful payments)
6258 */
6259
6260 IF (p_used_docs_list.COUNT = 0) THEN
6261
6262 print_debuginfo(l_module_name, 'Error: List of used paper '
6263 || 'document numbers is empty'
6264 || '. Returning failure response .. '
6265 );
6266
6267 x_return_status := FND_API.G_RET_STS_ERROR;
6268
6269 print_debuginfo(l_module_name, 'EXIT');
6270
6271 RETURN;
6272
6273 END IF;
6274
6275 /*
6276 * STEP 1:
6277 *
6278 * Start processing the used paper documents, one-by-one.
6279 *
6280 * This API will only be called with the list of spoiled
6281 * paper documents, so we can set the usage reason for
6282 * each paper document to 'spoiled'.
6283 */
6284 FOR i IN p_used_docs_list.FIRST .. p_used_docs_list.LAST LOOP
6285
6286 INSERT INTO IBY_USED_PAYMENT_DOCS (
6287 PAYMENT_DOCUMENT_ID,
6288 USED_DOCUMENT_NUMBER,
6289 DATE_USED,
6290 DOCUMENT_USE,
6291 CREATED_BY,
6292 CREATION_DATE,
6293 LAST_UPDATED_BY,
6294 LAST_UPDATE_DATE,
6295 LAST_UPDATE_LOGIN,
6296 OBJECT_VERSION_NUMBER
6297 )
6298 VALUES (
6299 p_pmt_doc_id,
6300 p_used_docs_list(i),
6301 sysdate,
6302 DOC_USE_SPOILED,
6303 fnd_global.user_id,
6304 sysdate,
6305 fnd_global.user_id,
6306 sysdate,
6307 fnd_global.login_id,
6308 1
6309 );
6310
6311 END LOOP;
6312
6313 print_debuginfo(l_module_name, 'Finished updating document use table.');
6314
6315 /*
6316 * STEP 2:
6317 *
6318 * Pick up all payments for this payment instruction
6319 * that have the given paper document number one-by-one.
6320 *
6321 * For each such payment, set the payment status to 'SPOILED'.
6322 */
6323 BEGIN
6324
6325 FOR i IN p_used_docs_list.FIRST .. p_used_docs_list.LAST LOOP
6326
6327 l_paper_doc_num := p_used_docs_list(i);
6328 print_debuginfo(l_module_name, 'In the loop, p_used_docs_list('||
6329 i||') :'
6330 || p_used_docs_list(i) );
6331
6332 UPDATE
6333 IBY_PAYMENTS_ALL
6334 SET
6335 payment_status = PAY_STATUS_SPOILED
6336 WHERE
6337 payment_instruction_id = p_instr_id AND
6338 payment_id = p_used_docs_list(i)
6339 ;
6340
6341
6342 print_debuginfo(l_module_name, 'Finished updating payments table');
6343 UPDATE
6344 IBY_DOCS_PAYABLE_ALL
6345 SET
6346 document_status = DOC_STATUS_PMT_SPOILED
6347 WHERE
6348 payment_id = p_used_docs_list(i)
6349 ;
6350
6351 print_debuginfo(l_module_name, 'Finished updating document payable table');
6352
6353 OPEN c_docs(p_used_docs_list(i));
6354 FETCH c_docs BULK COLLECT INTO l_doc_id_list, l_doc_status_list;
6355 CLOSE c_docs;
6356
6357 print_debuginfo(l_module_name, 'The number of doc ids for this '
6358 ||'payment' ||l_doc_id_list.COUNT);
6359
6360 remove_documents_payable (
6361 l_doc_id_list,
6362 l_doc_status_list,
6363 x_return_status_remove_doc
6364 );
6365 print_debuginfo(l_module_name,'Inside loop,after callling'
6366 || 'remove_documents_payable');
6367
6368
6369 IF (x_return_status_remove_doc <> FND_API.G_RET_STS_SUCCESS) THEN
6370
6371 /*
6372 * Even if a single call to remove a document
6373 * failed, return failure for the entire
6374 * API request.
6375 */
6376 print_debuginfo(l_module_name, 'Removing of documents '
6377 || 'for payment instruction id '
6378 || p_instr_id
6379 || ' failed.'
6380 );
6381
6382 print_debuginfo(l_module_name, 'EXIT');
6383
6384 /*
6385 * It is the callers responsibility to rollback
6386 * all the changes.
6387 */
6388 RETURN;
6389
6390 END IF;
6391
6392 END LOOP;
6393
6394 EXCEPTION
6395 WHEN OTHERS THEN
6396 print_debuginfo(l_module_name, 'Fatal: Exception occured '
6397 || 'when attempting to update payment with payment '
6398 || 'instruction id '
6399 || p_instr_id
6400 || ' and paper document number '
6401 || l_paper_doc_num
6402 );
6403
6404 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
6405 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
6406 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
6407
6408 /*
6409 * Propogate exception to caller.
6410 */
6411 RAISE;
6412
6413 END;
6414
6415 print_debuginfo(l_module_name, 'Finished updating payments table.');
6416
6417 /*
6418 * STEP 3:
6419 *
6420 * Invoke the hook that handles witholding certificates.
6421 * Every time a paper document is PRINTED | REPRINTED |
6422 * SPOILED, the witholding certificates should be in sync.
6423 */
6424 l_callout_name := l_pkg_name || '.' || 'zx_witholdingCertificatesHook';
6425
6426 print_debuginfo(l_module_name, 'Attempting to call hook: '
6427 || l_callout_name);
6428
6429 l_stmt := 'CALL '|| l_callout_name || '(:1, :2, :3, :4, :5, :6, :7, :8)';
6430
6431 BEGIN
6432
6433 EXECUTE IMMEDIATE
6434 (l_stmt)
6435 USING
6436 IN p_instr_id,
6437 IN 'SPOILED',
6438 IN l_api_version,
6439 IN FND_API.G_FALSE,
6440 IN FND_API.G_FALSE,
6441 OUT x_return_status,
6442 OUT l_msg_count,
6443 OUT l_msg_data
6444 ;
6445
6446 /*
6447 * If the called procedure did not return success,
6448 * raise an exception.
6449 */
6450 IF (x_return_status IS NULL OR
6451 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
6452
6453 print_debuginfo(l_module_name, 'Fatal: External app callout '''
6454 || l_callout_name
6455 || ''', returned failure status - '
6456 || x_return_status
6457 || '. Raising exception.'
6458 );
6459
6460 APP_EXCEPTION.RAISE_EXCEPTION;
6461
6462 END IF;
6463
6464 EXCEPTION
6465
6466 WHEN PROCEDURE_NOT_IMPLEMENTED THEN
6467 print_debuginfo(l_module_name, 'Callout "' || l_callout_name
6468 || '" not implemented by calling app - AP'
6469 );
6470
6471 print_debuginfo(l_module_name, 'Skipping hook call.');
6472
6473
6474 WHEN OTHERS THEN
6475 print_debuginfo(l_module_name, 'Fatal: External app callout '''
6476 || l_callout_name
6477 || ''', generated exception.'
6478 );
6479
6480 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
6481 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
6482 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
6483
6484 /*
6485 * Propogate exception to caller.
6486 */
6487 RAISE;
6488 END;
6489
6490 /*
6491 * STEP 4:
6492 *
6493 * Change the status of the successful payments of this instruction
6494 * to ISSUED status. The ISSUED status is the final status for a
6495 * paper payment; the payment must be in ISSUED status in order to
6496 * be marked complete.
6497 */
6498 UPDATE
6499 IBY_PAYMENTS_ALL
6500 SET
6501 payment_status = PAY_STATUS_ISSUED
6502 WHERE
6503 payment_instruction_id = p_instr_id AND
6504 (
6505 payment_status IN
6506 (
6507 PAY_STATUS_FORMATTED,
6508 PAY_STATUS_SUB_FOR_PRINT
6509 )
6510 OR
6511 (
6512 process_type = PROCESS_TYPE_IMMEDIATE
6513 )
6514 )
6515 ;
6516
6517 /*
6518 * STEP 5:
6519 *
6520 * Mark all the payments of the given payment instruction
6521 * as complete.
6522 */
6523 print_debuginfo(l_module_name, 'Attempting to mark payments of '
6524 || 'payment instruction '
6525 || p_instr_id
6526 || ' as complete.'
6527 );
6528
6529 mark_all_pmts_complete (
6530 p_instr_id,
6531 p_submit_postive_pay,
6532 x_return_status
6533 );
6534
6535 IF (x_return_status IS NULL OR
6536 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
6537
6538 print_debuginfo(l_module_name, 'Error status '
6539 || x_return_status
6540 || ' was received from the mark_all_pmts_complete() '
6541 || 'method. Raising exception.'
6542 );
6543
6544 APP_EXCEPTION.RAISE_EXCEPTION;
6545
6546 ELSE
6547
6548 print_debuginfo(l_module_name, 'Successfully maked payments '
6549 || 'as complete.'
6550 );
6551
6552 END IF;
6553
6554 /*
6555 * STEP 6:
6556 *
6557 * Change the status of the payment instruction to PRINTED.
6558 */
6559 UPDATE
6560 IBY_PAY_INSTRUCTIONS_ALL
6561 SET
6562 payment_instruction_status = INS_STATUS_PRINTED
6563 WHERE
6564 payment_instruction_id = p_instr_id
6565 ;
6566
6567 print_debuginfo(l_module_name, 'Successfully set payment '
6568 || 'instruction status to PRINTED.'
6569 );
6570
6571 x_return_status := FND_API.G_RET_STS_SUCCESS;
6572
6573 print_debuginfo(l_module_name, 'Returning success response ..');
6574
6575 print_debuginfo(l_module_name, 'EXIT');
6576
6577 EXCEPTION
6578 WHEN OTHERS THEN
6579
6580 print_debuginfo(l_module_name, 'Exception occured when '
6581 || 'recording final print status for payment instruction '
6582 || p_instr_id
6583 );
6584
6585 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
6586 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
6587 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
6588
6589 x_return_status := FND_API.G_RET_STS_ERROR;
6590
6591 print_debuginfo(l_module_name, 'EXIT');
6592
6593 END finalize_print_status;
6594
6595
6596 /*--------------------------------------------------------------------
6597 | NAME:
6598 | finalize_print_status
6599 |
6600 | PURPOSE:
6601 | Records the final print status for a set of paper documents. This
6602 | API will insert the given set of paper document numbers into the
6603 | IBY_USED_PAYMENT_DOCS table along with the usage reason indicating
6604 | whether the paper document was spoiled.
6605 |
6606 | Note that this API should only be invoked with the list of spoiled
6607 | paper documents. The UI should directly handle the successfully
6608 | printed paper documents. For performance reasons, this API is
6609 | designed only to handle the spoiled paper document case.
6610 |
6611 | This API will set the usage reason for each provided document
6612 | to 'SPOILED' in the IBY_USED_PAYMENT_DOCS table, and it will also
6613 | set the status of the corresponding payment to
6614 | REMOVED_DOCUMENT_SPOILED.
6615 |
6616 | Then, this API will set the status of the successfully printed
6617 | payments to ISSUED status and then invoke the 'mark complete'
6618 | API to mark the payments of this payment instruction as complete.
6619 |
6620 | PARAMETERS:
6621 | IN
6622 | p_pmt_doc_id - The payment document id (check stock id)
6623 | of the given list of paper documents.
6624 | p_used_docs_list - The list of paper documents that have been
6625 | used for printing
6626 | p_use_reason_list - The list of paper document usage reasons. This
6627 | list will contain a lookup code that specifies
6628 | whether the paper document was correctly
6629 | printed or not. Possible values include
6630 | ISSUED | SPOILED. SKIPPED will never be a
6631 | provided reason because skipped documents have
6632 | successfully printed (only numbering is wrong).
6633 | p_submit_postive_pay
6634 | - Flag indicating whether positive pay file
6635 | report needs to be launched after finalizing
6636 | the payments.
6637 |
6638 | OUT
6639 | x_return_status - Result of the API call:
6640 | FND_API.G_RET_STS_SUCCESS indicates that the
6641 | finalization process completed raised
6642 | successfully. In this case the caller must
6643 | COMMIT the status change.
6644 |
6645 | FND_API.G_RET_STS_ERROR (or other) indicates
6646 | that API did not complete successfully.
6647 | In this case, the caller must issue a
6648 | ROLLBACK to undo all status changes.
6649 |
6650 | RETURNS:
6651 |
6652 | NOTES:
6653 | Internal API, not for public use.
6654 |
6655 *---------------------------------------------------------------------*/
6656 PROCEDURE finalize_print_status(
6657 p_instr_id IN NUMBER,
6658 p_pmt_doc_id IN NUMBER,
6659 p_used_docs_list IN paperDocNumTab,
6660 p_used_pmts_list IN paperDocNumTab,
6661 p_submit_postive_pay IN BOOLEAN,
6662 x_return_status OUT NOCOPY VARCHAR2
6663 )
6664 IS
6665
6666 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
6667 || '.finalize_print_status';
6668
6669
6670 l_paper_doc_num IBY_PAYMENTS_ALL.paper_document_number%TYPE;
6671 l_payment_status_list docPayStatusTab;
6672 l_skipped_document_number IBY_PAYMENTS_ALL.paper_document_number%TYPE;
6673
6674 /* used in invocation of callout procedure */
6675 l_api_version CONSTANT NUMBER := 1.0;
6676 l_msg_count NUMBER;
6677 l_first_doc_number NUMBER;
6678 l_last_doc_number NUMBER;
6679 l_msg_data VARCHAR2(2000);
6680 l_pkg_name CONSTANT VARCHAR2(100) := 'AP_AWT_CALLOUT_PKG';
6681 l_callout_name VARCHAR2(500);
6682 l_stmt VARCHAR2(1000);
6683
6684 /* Bug #6508530 -used for changing status for spoiled payment, document */
6685 l_doc_id_list docPayIDTab;
6686 l_doc_status_list docPayStatusTab;
6687
6688 x_return_status_remove_doc VARCHAR2(200);
6689
6690 CURSOR c_docs (p_pmt_id IBY_PAYMENTS_ALL.
6691 payment_id%TYPE)
6692 IS
6693 SELECT
6694 doc.document_payable_id,
6695 doc.document_status
6696 FROM
6697 IBY_DOCS_PAYABLE_ALL doc
6698 WHERE
6699 doc.payment_id = p_pmt_id
6700
6701 ;
6702
6703
6704 /*
6705 * Implementing the hook is optional for the calling app.
6706 * If the calling app does not implement the hook, then
6707 * the call to the hook will result in ORA-06576 error.
6708 *
6709 * There is no exception name associated with this code, so
6710 * we create one called 'PROCEDURE_NOT_IMPLEMENTED'. If this
6711 * exception occurs, it is not fatal: we log the error and
6712 * proceed.
6713 *
6714 * If, on the other hand, the calling app implements the
6715 * hook, but the hook throws an exception, it is fatal
6716 * and we must abort the program (this will be caught
6717 * in WHEN OTHERS block).
6718 */
6719 PROCEDURE_NOT_IMPLEMENTED EXCEPTION;
6720 PRAGMA EXCEPTION_INIT(PROCEDURE_NOT_IMPLEMENTED, -6576);
6721
6722 BEGIN
6723
6724 print_debuginfo(l_module_name, 'ENTER');
6725
6726 FND_MSG_PUB.initialize;
6727
6728 /*
6729 * STATUS CHANGE:
6730 *
6731 * UI Responsibility:
6732 * NONE
6733 *
6734 * API Responsibility:
6735 * payment instruction status = PRINTED
6736 *
6737 * payment status = REMOVED_DOCUMENT_SPOILED (for spoiled payments)
6738 * payment status = ISSUED (for successful payments)
6739 */
6740
6741 IF (p_used_docs_list.COUNT = 0) THEN
6742
6743 print_debuginfo(l_module_name, 'Error: List of used paper '
6744 || 'document numbers is empty'
6745 || '. Returning failure response .. '
6746 );
6747
6748 x_return_status := FND_API.G_RET_STS_ERROR;
6749
6750 print_debuginfo(l_module_name, 'EXIT');
6751
6752 RETURN;
6753
6754 END IF;
6755
6756 /*
6757 * STEP 1:
6758 *
6759 * Start processing the used paper documents, one-by-one.
6760 *
6761 * This API will only be called with the list of spoiled
6762 * paper documents, so we can set the usage reason for
6763 * each paper document to 'spoiled'.
6764 */
6765
6766 -- looping through the complete document list
6767 FOR i IN p_used_docs_list.FIRST .. p_used_docs_list.LAST LOOP
6768
6769 -- fetching the payment status for the documents and storing them in an array
6770 SELECT payment_status
6771 INTO l_payment_status_list(i)
6772 FROM IBY_PAYMENTS_ALL
6773 WHERE paper_document_number = p_used_docs_list(i)
6774 AND payment_id = p_used_pmts_list(i)
6775 AND payment_instruction_id = p_instr_id;
6776
6777 print_debuginfo(l_module_name, 'Paper Document Number = ' || p_used_docs_list(i));
6778 print_debuginfo(l_module_name, 'Payment ID : Payment Status = ' || p_used_pmts_list(i) || ':' || l_payment_status_list(i));
6779
6780 BEGIN
6781
6782 -- checking if the document is already skipped earlier
6783 SELECT cedocs.used_document_number
6784 INTO l_skipped_document_number
6785 FROM iby_used_payment_docs cedocs
6786 WHERE cedocs.payment_document_id = p_pmt_doc_id
6787 AND cedocs.used_document_number = p_used_docs_list(i)
6788 AND cedocs.document_use = 'SKIPPED';
6789
6790 EXCEPTION
6791 WHEN NO_DATA_FOUND THEN
6792
6793 --if the document is not skipped earlier insert new
6794 INSERT INTO IBY_USED_PAYMENT_DOCS (
6795 PAYMENT_DOCUMENT_ID,
6796 USED_DOCUMENT_NUMBER,
6797 DATE_USED,
6798 DOCUMENT_USE,
6799 CREATED_BY,
6800 CREATION_DATE,
6801 LAST_UPDATED_BY,
6802 LAST_UPDATE_DATE,
6803 LAST_UPDATE_LOGIN,
6804 OBJECT_VERSION_NUMBER
6805 )
6806 VALUES (
6807 p_pmt_doc_id,
6808 p_used_docs_list(i),
6809 sysdate,
6810 decode(l_payment_status_list(i),'REMOVED_DOCUMENT_SPOILED','SPOILED','ISSUED'),
6811 fnd_global.user_id,
6812 sysdate,
6813 fnd_global.user_id,
6814 sysdate,
6815 fnd_global.login_id,
6816 1
6817 );
6818
6819 print_debuginfo(l_module_name, 'Document number not found, inserting new');
6820 END;
6821
6822 -- updating the document_use in any case
6823 UPDATE IBY_USED_PAYMENT_DOCS
6824 SET DOCUMENT_USE = decode(l_payment_status_list(i),'REMOVED_DOCUMENT_SPOILED','SPOILED','ISSUED')
6825 WHERE payment_document_id = p_pmt_doc_id
6826 AND used_document_number = p_used_docs_list(i);
6827
6828 print_debuginfo(l_module_name, 'Found skipped document number, updating document usage');
6829
6830 END LOOP;
6831
6832 print_debuginfo(l_module_name, 'Finished updating document use table.');
6833
6834 /*
6835 * STEP 1.5:
6836 *
6837 * Managing skipped documents
6838 * Finding out which of the documents are skipped
6839 *
6840 */
6841
6842 l_first_doc_number := p_used_docs_list(p_used_docs_list.FIRST);
6843 l_last_doc_number := p_used_docs_list(p_used_docs_list.LAST);
6844
6845 print_debuginfo(l_module_name, 'l_first_doc_number : ' || l_first_doc_number);
6846 print_debuginfo(l_module_name, 'l_last_doc_number : ' || l_last_doc_number);
6847
6848 -- we will loop through the complete document list and find out the missing numbers
6849 FOR i IN l_first_doc_number .. l_last_doc_number LOOP
6850 l_skipped_document_number:=1;
6851
6852 -- finding out the missing number in the sequence
6853 print_debuginfo(l_module_name, 'finding if skipped ' || i);
6854 FOR j IN p_used_docs_list.FIRST .. p_used_docs_list.LAST LOOP
6855 IF (p_used_docs_list(j)=i) THEN
6856 l_skipped_document_number:=0;
6857 END IF;
6858 END LOOP;
6859
6860 -- if a number is missing in the sequence
6861 IF (l_skipped_document_number=1) THEN
6862 BEGIN
6863
6864 -- check if it already exists in the used_documents_table
6865 SELECT cedocs.used_document_number
6866 INTO l_skipped_document_number
6867 FROM iby_used_payment_docs cedocs
6868 WHERE cedocs.payment_document_id = p_pmt_doc_id
6869 AND cedocs.used_document_number = i;
6870
6871 EXCEPTION
6872 WHEN NO_DATA_FOUND THEN
6873
6874 -- inserting the document as skipped
6875 print_debuginfo(l_module_name, 'inserting as skipped ' || i);
6876 INSERT INTO IBY_USED_PAYMENT_DOCS (
6877 PAYMENT_DOCUMENT_ID,
6878 USED_DOCUMENT_NUMBER,
6879 DATE_USED,
6880 DOCUMENT_USE,
6881 CREATED_BY,
6882 CREATION_DATE,
6883 LAST_UPDATED_BY,
6884 LAST_UPDATE_DATE,
6885 LAST_UPDATE_LOGIN,
6886 OBJECT_VERSION_NUMBER
6887 )
6888 VALUES (
6889 p_pmt_doc_id,
6890 i,
6891 sysdate,
6892 'SKIPPED',
6893 fnd_global.user_id,
6894 sysdate,
6895 fnd_global.user_id,
6896 sysdate,
6897 fnd_global.login_id,
6898 1
6899 );
6900 END;
6901 END IF;
6902
6903 END LOOP;
6904
6905
6906
6907 /*
6908 * STEP 2:
6909 *
6910 * Pick up all payments for this payment instruction
6911 * that have the given paper document number one-by-one.
6912 *
6913 * For each such payment, set the payment status to 'SPOILED'.
6914 */
6915 BEGIN
6916
6917 -- looping through the entire document list
6918 FOR i IN p_used_docs_list.FIRST .. p_used_docs_list.LAST LOOP
6919
6920
6921 print_debuginfo(l_module_name, 'Payment ID : Paper Doc Num : Payment Status = ' || p_used_pmts_list(i) || ' : ' || p_used_docs_list(i) || ' : ' || l_payment_status_list(i));
6922
6923 -- only invoices for those paper_documents which are marked as spoiled are unlocked here
6924 IF ( l_payment_status_list(i) = 'REMOVED_DOCUMENT_SPOILED') THEN
6925
6926 l_paper_doc_num := p_used_docs_list(i);
6927 print_debuginfo(l_module_name, 'In the loop, spoiled document number : ('||i||') :' || p_used_pmts_list(i) );
6928
6929 UPDATE
6930 IBY_PAYMENTS_ALL
6931 SET
6932 payment_status = PAY_STATUS_SPOILED
6933 WHERE
6934 payment_instruction_id = p_instr_id AND
6935 payment_id = p_used_pmts_list(i)
6936 ;
6937
6938
6939 print_debuginfo(l_module_name, 'Finished updating payments table');
6940 UPDATE
6941 IBY_DOCS_PAYABLE_ALL
6942 SET
6943 document_status = DOC_STATUS_PMT_SPOILED
6944 WHERE
6945 payment_id = p_used_pmts_list(i)
6946 ;
6947
6948 print_debuginfo(l_module_name, 'Finished updating document payable table');
6949
6950 OPEN c_docs(p_used_pmts_list(i));
6951 FETCH c_docs BULK COLLECT INTO l_doc_id_list, l_doc_status_list;
6952 CLOSE c_docs;
6953
6954 print_debuginfo(l_module_name, 'The number of doc ids for this '
6955 ||'payment' ||l_doc_id_list.COUNT);
6956
6957 remove_documents_payable (
6958 l_doc_id_list,
6959 l_doc_status_list,
6960 x_return_status_remove_doc
6961 );
6962 print_debuginfo(l_module_name,'Inside loop,after callling'
6963 || 'remove_documents_payable');
6964
6965
6966 IF (x_return_status_remove_doc <> FND_API.G_RET_STS_SUCCESS) THEN
6967
6968 /*
6969 * Even if a single call to remove a document
6970 * failed, return failure for the entire
6971 * API request.
6972 */
6973 print_debuginfo(l_module_name, 'Removing of documents '
6974 || 'for payment instruction id '
6975 || p_instr_id
6976 || ' failed.'
6977 );
6978
6979 print_debuginfo(l_module_name, 'EXIT');
6980
6981 /*
6982 * It is the callers responsibility to rollback
6983 * all the changes.
6984 */
6985 RETURN;
6986
6987 END IF;
6988
6989 END IF;
6990
6991 END LOOP;
6992
6993 EXCEPTION
6994 WHEN OTHERS THEN
6995 print_debuginfo(l_module_name, 'Fatal: Exception occured '
6996 || 'when attempting to update payment with payment '
6997 || 'instruction id '
6998 || p_instr_id
6999 || ' and paper document number '
7000 || l_paper_doc_num
7001 );
7002
7003 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
7004 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
7005 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
7006
7007 /*
7008 * Propogate exception to caller.
7009 */
7010 RAISE;
7011
7012 END;
7013
7014 print_debuginfo(l_module_name, 'Finished updating payments table.');
7015
7016 /*
7017 * STEP 3:
7018 *
7019 * Invoke the hook that handles witholding certificates.
7020 * Every time a paper document is PRINTED | REPRINTED |
7021 * SPOILED, the witholding certificates should be in sync.
7022 */
7023 l_callout_name := l_pkg_name || '.' || 'zx_witholdingCertificatesHook';
7024
7025 print_debuginfo(l_module_name, 'Attempting to call hook: '
7026 || l_callout_name);
7027
7028 l_stmt := 'CALL '|| l_callout_name || '(:1, :2, :3, :4, :5, :6, :7, :8)';
7029
7030 BEGIN
7031
7032 EXECUTE IMMEDIATE
7033 (l_stmt)
7034 USING
7035 IN p_instr_id,
7036 IN 'SPOILED',
7037 IN l_api_version,
7038 IN FND_API.G_FALSE,
7039 IN FND_API.G_FALSE,
7040 OUT x_return_status,
7041 OUT l_msg_count,
7042 OUT l_msg_data
7043 ;
7044
7045 /*
7046 * If the called procedure did not return success,
7047 * raise an exception.
7048 */
7049 IF (x_return_status IS NULL OR
7050 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
7051
7052 print_debuginfo(l_module_name, 'Fatal: External app callout '''
7053 || l_callout_name
7054 || ''', returned failure status - '
7055 || x_return_status
7056 || '. Raising exception.'
7057 );
7058
7059 APP_EXCEPTION.RAISE_EXCEPTION;
7060
7061 END IF;
7062
7063 EXCEPTION
7064
7065 WHEN PROCEDURE_NOT_IMPLEMENTED THEN
7066 print_debuginfo(l_module_name, 'Callout "' || l_callout_name
7067 || '" not implemented by calling app - AP'
7068 );
7069
7070 print_debuginfo(l_module_name, 'Skipping hook call.');
7071
7072
7073 WHEN OTHERS THEN
7074 print_debuginfo(l_module_name, 'Fatal: External app callout '''
7075 || l_callout_name
7076 || ''', generated exception.'
7077 );
7078
7079 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
7080 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
7081 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
7082
7083 /*
7084 * Propogate exception to caller.
7085 */
7086 RAISE;
7087 END;
7088
7089 /*
7090 * STEP 4:
7091 *
7092 * Change the status of the successful payments of this instruction
7093 * to ISSUED status. The ISSUED status is the final status for a
7094 * paper payment; the payment must be in ISSUED status in order to
7095 * be marked complete.
7096 */
7097 UPDATE
7098 IBY_PAYMENTS_ALL
7099 SET
7100 payment_status = PAY_STATUS_ISSUED
7101 WHERE
7102 payment_instruction_id = p_instr_id AND
7103 (
7104 payment_status IN
7105 (
7106 PAY_STATUS_FORMATTED,
7107 PAY_STATUS_SUB_FOR_PRINT
7108 )
7109 OR
7110 (
7111 process_type = PROCESS_TYPE_IMMEDIATE
7112 )
7113 )
7114 ;
7115
7116 /*
7117 * STEP 5:
7118 *
7119 * Mark all the payments of the given payment instruction
7120 * as complete.
7121 */
7122 print_debuginfo(l_module_name, 'Attempting to mark payments of '
7123 || 'payment instruction '
7124 || p_instr_id
7125 || ' as complete.'
7126 );
7127
7128 mark_all_pmts_complete (
7129 p_instr_id,
7130 p_submit_postive_pay,
7131 x_return_status
7132 );
7133
7134 IF (x_return_status IS NULL OR
7135 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
7136
7137 print_debuginfo(l_module_name, 'Error status '
7138 || x_return_status
7139 || ' was received from the mark_all_pmts_complete() '
7140 || 'method. Raising exception.'
7141 );
7142
7143 APP_EXCEPTION.RAISE_EXCEPTION;
7144
7145 ELSE
7146
7147 print_debuginfo(l_module_name, 'Successfully maked payments '
7148 || 'as complete.'
7149 );
7150
7151 END IF;
7152
7153 /*
7154 * STEP 6:
7155 *
7156 * Change the status of the payment instruction to PRINTED.
7157 */
7158 UPDATE
7159 IBY_PAY_INSTRUCTIONS_ALL
7160 SET
7161 payment_instruction_status = INS_STATUS_PRINTED
7162 WHERE
7163 payment_instruction_id = p_instr_id
7164 ;
7165
7166 print_debuginfo(l_module_name, 'Successfully set payment '
7167 || 'instruction status to PRINTED.'
7168 );
7169
7170 x_return_status := FND_API.G_RET_STS_SUCCESS;
7171
7172 print_debuginfo(l_module_name, 'Returning success response ..');
7173
7174 print_debuginfo(l_module_name, 'EXIT');
7175
7176 EXCEPTION
7177 WHEN OTHERS THEN
7178
7179 print_debuginfo(l_module_name, 'Exception occured when '
7180 || 'recording final print status for payment instruction '
7181 || p_instr_id
7182 );
7183
7184 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
7185 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
7186 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
7187
7188 x_return_status := FND_API.G_RET_STS_ERROR;
7189
7190 print_debuginfo(l_module_name, 'EXIT');
7191
7192 END finalize_print_status;
7193
7194 /*--------------------------------------------------------------------
7195 | NAME:
7196 | finalize_instr_print_status
7197 |
7198 | PURPOSE:
7199 | Records the final print status for all the paper documents that
7200 | are part of a payment instruction.
7201 |
7202 | This is an overloaded method. See the other method signature for
7203 | complete documentation.
7204 |
7205 | PARAMETERS:
7206 | IN
7207 |
7208 |
7209 | OUT
7210 |
7211 |
7212 | RETURNS:
7213 |
7214 | NOTES:
7215 | Internal API, not for public use.
7216 |
7217 *---------------------------------------------------------------------*/
7218 PROCEDURE finalize_instr_print_status(
7219 p_instr_id IN NUMBER,
7220 x_return_status OUT NOCOPY VARCHAR2
7221 )
7222 IS
7223 BEGIN
7224
7225 finalize_instr_print_status(
7226 p_instr_id,
7227 FALSE,
7228 x_return_status
7229 );
7230
7231 END finalize_instr_print_status;
7232
7233 /*--------------------------------------------------------------------
7234 | NAME:
7235 | finalize_instr_print_status
7236 |
7237 | PURPOSE:
7238 | Records the final print status for all the paper documents that
7239 | are part of a payment instruction. This API will insert the paper
7240 | document numbers linked to each payment in the instruction into the
7241 | IBY_USED_PAYMENT_DOCS table along with the usage reason indicating
7242 | that the paper document was successfully printed.
7243 |
7244 | This API should only invoked when *all* the payments that are part
7245 | of a payment instruction have been printed successfully.
7246 |
7247 | This API is a light weight alternative to the finalize_print_status()
7248 | API because the caller does not have to provide the list of used
7249 | payment documents along with the usage reason. This API derives the
7250 | list of used payment documents from the payments on the instruction
7251 | and it sets the usage reason for each payment document as 'issued'.
7252 |
7253 | PARAMETERS:
7254 | IN
7255 | p_instr_id - The payment instruction id for which all
7256 | checks were successfully printed.
7257 |
7258 | p_submit_postive_pay
7259 | - Flag indicating whether positive pay file
7260 | report needs to be launched after finalizing
7261 | the payments.
7262 |
7263 | OUT
7264 | x_return_status - Result of the API call:
7265 | FND_API.G_RET_STS_SUCCESS indicates that the
7266 | finalization process completed raised
7267 | successfully. In this case the caller must
7268 | COMMIT the status change.
7269 |
7270 | FND_API.G_RET_STS_ERROR (or other) indicates
7271 | that API did not complete successfully.
7272 | In this case, the caller must issue a
7273 | ROLLBACK to undo all status changes.
7274 |
7275 | RETURNS:
7276 |
7277 | NOTES:
7278 | Internal API, not for public use.
7279 |
7280 *---------------------------------------------------------------------*/
7281 PROCEDURE finalize_instr_print_status(
7282 p_instr_id IN NUMBER,
7283 p_submit_postive_pay IN BOOLEAN,
7284 x_return_status OUT NOCOPY VARCHAR2
7285 )
7286 IS
7287
7288 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
7289 || '.finalize_instr_print_status';
7290
7291 l_pmtDocsTab paperDocNumTab;
7292 l_skipped_document_number IBY_PAYMENTS_ALL.paper_document_number%TYPE;
7293 l_pmt_doc_id NUMBER(15);
7294
7295
7296 /*
7297 * Cursor to pick up all the payment document numbers that
7298 * are linked to payments of a particular payment
7299 * instruction.
7300 */
7301
7302 /*
7303 * Fix for bug 4887500.
7304 *
7305 * When finalizing the status of a payment instruction, the payment
7306 * status may not be in the right status for single payments.
7307 *
7308 * This is because the Post-PICP program performs the status change
7309 * for the payment and since it runs as a separate conc request, it
7310 * may not have completed by the time the single payments API
7311 * calls this post-PICP program and immediately starts to finalize
7312 * the payment status.
7313 *
7314 * Therefore, the best approach would be to not consider the payment
7315 * status when the payment is a single payment (i.e., process type of
7316 * the payment is 'immediate').
7317 */
7318 CURSOR c_pmt_docs (p_instr_id NUMBER)
7319 IS
7320 SELECT
7321 pmt.paper_document_number
7322 FROM
7323 IBY_PAYMENTS_ALL pmt
7324 WHERE
7325 pmt.payment_instruction_id = p_instr_id AND
7326 (
7327 (
7328 pmt.payment_status = PAY_STATUS_FORMATTED OR
7329 pmt.payment_status = PAY_STATUS_SUB_FOR_PRINT
7330 )
7331 OR
7332 (
7333 pmt.process_type = PROCESS_TYPE_IMMEDIATE
7334 )
7335 )
7336 ;
7337
7338 BEGIN
7339
7340 print_debuginfo(l_module_name, 'ENTER');
7341
7342 FND_MSG_PUB.initialize;
7343
7344 /*
7345 * STATUS CHANGE:
7346 *
7347 * UI Responsibility:
7348 * NONE
7349 *
7350 * API Responsibility:
7351 * payment status = ISSUED
7352 * payment instruction status = PRINTED
7353 */
7354
7355 /*
7356 * STEP 1:
7357 *
7358 * Derive list of paper documents associated with the payments
7359 * of this instruction.
7360 */
7361 OPEN c_pmt_docs(p_instr_id);
7362 FETCH c_pmt_docs BULK COLLECT INTO l_pmtDocsTab;
7363 CLOSE c_pmt_docs;
7364
7365 IF (l_pmtDocsTab.COUNT = 0) THEN
7366
7367 print_debuginfo(l_module_name, 'Error: Number of '
7368 || 'paper documents associated with payment instruction '
7369 || p_instr_id
7370 || ' is zero. '
7371 || 'Returning failure response .. '
7372 );
7373
7374 x_return_status := FND_API.G_RET_STS_ERROR;
7375
7376 print_debuginfo(l_module_name, 'EXIT');
7377
7378 RETURN;
7379
7380 END IF;
7381
7382 /*
7383 * STEP 2:
7384 *
7385 * Derive the payment document id (check stock) that was used to
7386 * print the payments of this instruction. The payment document
7387 * id also needs to be inserted into the IBY_USED_PAYMENT_DOCUMENTS
7388 * table.
7389 */
7390 SELECT
7391 payment_document_id
7392 INTO
7393 l_pmt_doc_id
7394 FROM
7395 IBY_PAY_INSTRUCTIONS_ALL
7396 WHERE
7397 payment_instruction_id = p_instr_id
7398 ;
7399
7400 IF (l_pmt_doc_id IS NULL) THEN
7401
7402 print_debuginfo(l_module_name, 'Error: Could not derive '
7403 || 'payment document associated with payment instruction '
7404 || p_instr_id
7405 || '. Returning failure response .. '
7406 );
7407
7408 x_return_status := FND_API.G_RET_STS_ERROR;
7409
7410 print_debuginfo(l_module_name, 'EXIT');
7411
7412 RETURN;
7413
7414 END IF;
7415
7416 /*
7417 * STEP 3:
7418 *
7419 * Insert the paper document numbers and the payment
7420 * doc id we picked up in steps (1) and (2) into the
7421 * IBY_USED_PAYMENT_DOCUMENTS table. Set the usage
7422 * reason for each paper document as 'issued'.
7423 */
7424 FOR i IN l_pmtDocsTab.FIRST .. l_pmtDocsTab.LAST LOOP
7425
7426
7427 BEGIN
7428 -- finding if the document is already skipped earlier
7429 SELECT cedocs.used_document_number
7430 INTO l_skipped_document_number
7431 FROM iby_used_payment_docs cedocs
7432 WHERE cedocs.payment_document_id = l_pmt_doc_id
7433 AND cedocs.used_document_number = l_pmtDocsTab(i)
7434 AND cedocs.document_use = 'SKIPPED';
7435
7436 EXCEPTION
7437 WHEN NO_DATA_FOUND THEN
7438
7439 -- if not skipped earlier, inserting new
7440 INSERT INTO IBY_USED_PAYMENT_DOCS (
7441 PAYMENT_DOCUMENT_ID,
7442 USED_DOCUMENT_NUMBER,
7443 DATE_USED,
7444 DOCUMENT_USE,
7445 CREATED_BY,
7446 CREATION_DATE,
7447 LAST_UPDATED_BY,
7448 LAST_UPDATE_DATE,
7449 LAST_UPDATE_LOGIN,
7450 OBJECT_VERSION_NUMBER
7451 )
7452 VALUES (
7453 l_pmt_doc_id,
7454 l_pmtDocsTab(i),
7455 sysdate,
7456 DOC_USE_ISSUED,
7457 fnd_global.user_id,
7458 sysdate,
7459 fnd_global.user_id,
7460 sysdate,
7461 fnd_global.login_id,
7462 1
7463 );
7464
7465 print_debuginfo(l_module_name, 'Document number not found, inserting new');
7466 END;
7467
7468 -- updating the document_use in any case
7469 UPDATE IBY_USED_PAYMENT_DOCS
7470 SET DOCUMENT_USE = DOC_USE_ISSUED
7471 WHERE payment_document_id = l_pmt_doc_id
7472 AND used_document_number = l_pmtDocsTab(i);
7473
7474
7475 END LOOP;
7476
7477
7478 /*
7479 * STEP 4:
7480 *
7481 * Change the status of the successful payments of this instruction
7482 * to ISSUED status. The ISSUED status is the final status for a
7483 * paper payment; the payment must be in ISSUED status in order to
7484 * be marked complete.
7485 */
7486 UPDATE
7487 IBY_PAYMENTS_ALL
7488 SET
7489 payment_status = PAY_STATUS_ISSUED
7490 WHERE
7491 payment_instruction_id = p_instr_id AND
7492 (
7493 payment_status IN
7494 (
7495 PAY_STATUS_FORMATTED,
7496 PAY_STATUS_SUB_FOR_PRINT
7497 )
7498 OR
7499 (
7500 process_type = PROCESS_TYPE_IMMEDIATE
7501 )
7502 )
7503 ;
7504
7505 /*
7506 * STEP 5:
7507 *
7508 * Mark all the payments of the given payment instruction
7509 * as complete.
7510 */
7511 print_debuginfo(l_module_name,
7512 'Invoking mark payments complete API ..');
7513
7514 mark_all_pmts_complete (
7515 p_instr_id,
7516 p_submit_postive_pay,
7517 x_return_status
7518 );
7519
7520 print_debuginfo(l_module_name, 'Finished invoking mark payments '
7521 || 'complete API ..'
7522 );
7523
7524 IF (x_return_status IS NULL OR
7525 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
7526
7527 print_debuginfo(l_module_name, 'Error: Could not mark '
7528 || 'the payments associated with payment instruction '
7529 || p_instr_id
7530 || ' as complete. Returning failure response .. '
7531 );
7532
7533 x_return_status := FND_API.G_RET_STS_ERROR;
7534
7535 print_debuginfo(l_module_name, 'EXIT');
7536
7537 RETURN;
7538
7539 ELSE
7540
7541 print_debuginfo(l_module_name, 'Payments of '
7542 || 'payment instruction '
7543 || p_instr_id
7544 || ' marked as complete.'
7545 );
7546
7547 END IF;
7548
7549 /*
7550 * STEP 6:
7551 *
7552 * Change the status of the payment instruction to PRINTED.
7553 */
7554 UPDATE
7555 IBY_PAY_INSTRUCTIONS_ALL
7556 SET
7557 payment_instruction_status = INS_STATUS_PRINTED
7558 WHERE
7559 payment_instruction_id = p_instr_id
7560 ;
7561
7562 print_debuginfo(l_module_name, 'Successfully set payment '
7563 || 'instruction status to PRINTED.'
7564 );
7565
7566
7567 x_return_status := FND_API.G_RET_STS_SUCCESS;
7568
7569 print_debuginfo(l_module_name, 'Returning success response ..');
7570
7571 print_debuginfo(l_module_name, 'EXIT');
7572
7573 EXCEPTION
7574 WHEN OTHERS THEN
7575
7576 print_debuginfo(l_module_name, 'Exception occured when '
7577 || 'recording final print status for payments of '
7578 || 'payment instruction '
7579 || p_instr_id
7580 );
7581
7582 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
7583 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
7584 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
7585
7586 x_return_status := FND_API.G_RET_STS_ERROR;
7587
7588 print_debuginfo(l_module_name, 'EXIT');
7589
7590 END finalize_instr_print_status;
7591
7592 /*--------------------------------------------------------------------
7593 | NAME:
7594 | mark_all_pmts_complete
7595 |
7596 | PURPOSE:
7597 | Marks all payments of the given payment instruction as complete.
7598 |
7599 | This method overloads the other mark_all_pmts_complete(..)
7600 | See the other method for complete documentation.
7601 |
7602 | NOTES:
7603 | Internal API, not for public use.
7604 |
7605 | This method does not COMMIT/ROLLBACK. It is the callers responsibility
7606 | to COMMIT/ROLLBACK depending upon the return status.
7607 |
7608 *---------------------------------------------------------------------*/
7609 PROCEDURE mark_all_pmts_complete (
7610 p_instr_id IN NUMBER,
7611 x_return_status OUT NOCOPY VARCHAR2
7612 )
7613 IS
7614
7615 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
7616 || '.mark_all_pmts_complete';
7617 BEGIN
7618
7619 /*
7620 * Call mark_all_pmts_complete(..) with the submit
7621 * positive pay file report flag set to 'no' by
7622 * default.
7623 */
7624 mark_all_pmts_complete(p_instr_id, FALSE, x_return_status);
7625
7626 END mark_all_pmts_complete;
7627
7628 /*--------------------------------------------------------------------
7629 | NAME:
7630 | mark_all_pmts_complete
7631 |
7632 | PURPOSE:
7633 | Marks all payments of the given payment instruction as complete.
7634 | Also marks the status of the payment instruction to complete.
7635 |
7636 | Only payments that are in 'valid' status will be marked complete,
7637 | others will be left untouched. The 'valid' status for a payment
7638 | is dependent upon whether it is a printed payment or an electronic
7639 | payment. Here is list of valid statuses by processing type:
7640 |
7641 | Processing Valid statuses for payments
7642 | Type
7643 | ---------- ---------------------------
7644 | PRINTED ISSUED
7645 |
7646 | ELECTRONIC FORMATTED
7647 | TRANSMITTED
7648 | ACKNOWLEDGED
7649 | BANK_VALIDATED
7650 | PAID
7651 |
7652 | Therefore, the caller must ensure that they set the payment
7653 | status to valid status for all the payments that are to be
7654 | marked complete *before* calling this API.
7655 |
7656 | Once payments are marked as complete, the calling application
7657 | hook 'payments_completed()' is invoked to inform the calling
7658 | app that their payments have been marked complete.
7659 |
7660 | PARAMETERS:
7661 | IN
7662 | p_instr_id - The payment instruction id for which the
7663 | payments need to be marked complete.
7664 |
7665 | p_submit_postive_pay
7666 | - Flag indicating whether positive pay file
7667 | report needs to be launched after marking
7668 | the payments complete.
7669 |
7670 | OUT
7671 | x_return_status - Result of the API call:
7672 | FND_API.G_RET_STS_SUCCESS indicates that
7673 | the mark complete process finished
7674 | successfully. In this case the caller must
7675 | COMMIT the status change.
7676 |
7677 | FND_API.G_RET_STS_ERROR (or other) indicates
7678 | that API did not complete successfully.
7679 | In this case, the caller must issue a
7680 | ROLLBACK to undo all status changes.
7681 |
7682 | RETURNS:
7683 |
7684 | NOTES:
7685 | Internal API, not for public use.
7686 |
7687 | This method does not COMMIT/ROLLBACK. It is the callers responsibility
7688 | to COMMIT/ROLLBACK depending upon the return status.
7689 *---------------------------------------------------------------------*/
7690 PROCEDURE mark_all_pmts_complete (
7691 p_instr_id IN NUMBER,
7692 p_submit_postive_pay IN BOOLEAN,
7693 x_return_status OUT NOCOPY VARCHAR2
7694 )
7695 IS
7696
7697 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
7698 || '.mark_all_pmts_complete';
7699
7700 l_completion_id NUMBER(15);
7701 l_processing_type VARCHAR2(200);
7702 l_process_type VARCHAR2(200);
7703
7704 /* used in forming callout procedure name */
7705 l_calling_app_id NUMBER;
7706 l_app_short_name VARCHAR2(200);
7707 l_pkg_name VARCHAR2(200);
7708 l_callout_name VARCHAR2(500);
7709 l_stmt VARCHAR2(1000);
7710
7711 /* used in invocation of callout procedure */
7712 l_api_version CONSTANT NUMBER := 1.0;
7713 l_msg_count NUMBER;
7714 l_msg_data VARCHAR2(2000);
7715
7716 l_appNamesTab appNamesTab;
7717 l_appIdsTab appIdsTab;
7718
7719 l_pmts_complete_code VARCHAR2(1000);
7720
7721 l_pmt_doc_id NUMBER(15);
7722 l_pmt_doc_name VARCHAR2(2000);
7723
7724 l_doc_count NUMBER(15);
7725 l_pmt_count NUMBER(15);
7726
7727 /*
7728 * These variables are related to kicking off automatic
7729 * reports.
7730 */
7731 l_profile_id IBY_PAYMENT_PROFILES.
7732 payment_profile_id%TYPE;
7733 l_auto_pi_reg_submit_flag
7734 IBY_SYS_PMT_PROFILES_B.
7735 automatic_pi_reg_submit%TYPE;
7736 l_auto_sra_submit_flag
7737 IBY_REMIT_ADVICE_SETUP.
7738 automatic_sra_submit_flag%TYPE;
7739 l_remit_format_code
7740 IBY_REMIT_ADVICE_SETUP.
7741 remittance_advice_format_code%TYPE;
7742 l_pos_pay_format IBY_PAYMENT_PROFILES.
7743 positive_pay_format_code%TYPE;
7744 l_pi_reg_format IBY_SYS_PMT_PROFILES_B.
7745 pi_register_format%TYPE;
7746
7747
7748 l_conc_req_id NUMBER(15);
7749
7750 l_icx_numeric_characters VARCHAR2(30); -- Bug 6411356
7751 l_bool_val boolean; -- Bug 6411356
7752
7753 l_error_code IBY_TRANSACTION_ERRORS.error_code%TYPE;
7754
7755 /*
7756 * Cursor to pick up all calling applications associated
7757 * with a particular payment instruction.
7758 */
7759
7760 /*
7761 * Fix for bug 4901075.
7762 *
7763 * Added distinct clause to select statement so that duplicate
7764 * calling app ids are eliminated.
7765 *
7766 * Otherwise, the call out could be invoked multiple times
7767 * per calling app.
7768 */
7769 CURSOR c_app_names (p_instr_id NUMBER)
7770 IS
7771 SELECT DISTINCT
7772 fnd.application_short_name
7773 INTO
7774 l_app_short_name
7775 FROM
7776 FND_APPLICATION fnd,
7777 IBY_PAYMENTS_ALL pmt,
7778 IBY_PAY_SERVICE_REQUESTS req,
7779 IBY_PAY_INSTRUCTIONS_ALL ins
7780 WHERE
7781 pmt.payment_instruction_id = ins.payment_instruction_id AND
7782 req.payment_service_request_id = pmt.payment_service_request_id AND
7783 fnd.application_id = req.calling_app_id AND
7784 ins.payment_instruction_id = p_instr_id
7785 ;
7786
7787 /*
7788 * Cursor to pick up ids all calling applications
7789 * associated with a particular payment instruction.
7790 */
7791 CURSOR c_app_ids (p_instr_id NUMBER)
7792 IS
7793 SELECT
7794 fnd.application_id
7795 FROM
7796 FND_APPLICATION fnd,
7797 IBY_PAYMENTS_ALL pmt,
7798 IBY_PAY_SERVICE_REQUESTS req,
7799 IBY_PAY_INSTRUCTIONS_ALL ins
7800 WHERE
7801 pmt.payment_instruction_id = ins.payment_instruction_id AND
7802 req.payment_service_request_id = pmt.payment_service_request_id AND
7803 fnd.application_id = req.calling_app_id AND
7804 ins.payment_instruction_id = p_instr_id
7805 ;
7806
7807 /*
7808 * Implementing the callout is optional for the calling app.
7809 * If the calling app does not implement the hook, then
7810 * the call to the hook will result in ORA-06576 error.
7811 *
7812 * There is no exception name associated with this code, so
7813 * we create one called 'PROCEDURE_NOT_IMPLEMENTED'. If this
7814 * exception occurs, it is not fatal: we log the error and
7815 * proceed.
7816 *
7817 * If, on the other hand, the calling app implements the
7818 * callout, but the callout throws an exception, it is fatal
7819 * and we must abort the program (this will be caught
7820 * in WHEN OTHERS block).
7821 */
7822 PROCEDURE_NOT_IMPLEMENTED EXCEPTION;
7823 PRAGMA EXCEPTION_INIT(PROCEDURE_NOT_IMPLEMENTED, -6576);
7824
7825 BEGIN
7826
7827 print_debuginfo(l_module_name, 'ENTER');
7828
7829 FND_MSG_PUB.initialize;
7830
7831 /*
7832 * STEP I:
7833 *
7834 * Get the processing type of this payment instruction.
7835 * The processing type is used as a criterion in selecting
7836 * which payments of this payment instruction are updated
7837 * to completed status.
7838 */
7839 SELECT
7840 prof.processing_type,
7841 inst.payments_complete_code,
7842 inst.process_type
7843 INTO
7844 l_processing_type,
7845 l_pmts_complete_code,
7846 l_process_type
7847 FROM
7848 IBY_PAYMENT_PROFILES prof,
7849 IBY_PAY_INSTRUCTIONS_ALL inst
7850 WHERE
7851 prof.payment_profile_id = inst.payment_profile_id AND
7852 inst.payment_instruction_id = p_instr_id;
7853
7854 print_debuginfo(l_module_name, 'For payment instruction '
7855 || p_instr_id
7856 || ', payment complete code: '
7857 || l_pmts_complete_code
7858 || ' and process type: '
7859 || l_process_type
7860 );
7861
7862 /*
7863 * STEP II:
7864 *
7865 * Check whether we need to mark payments complete
7866 * for the payments of this payment instruction.
7867 *
7868 * Payments should be marked complete should be called
7869 * *except* when:
7870 *
7871 * A. The payments of this payment instruction have already
7872 * been marked complete.
7873 */
7874 IF (UPPER(l_pmts_complete_code) = 'YES') THEN
7875
7876 print_debuginfo(l_module_name, 'Not performing mark pmts '
7877 || 'complete for payment instruction '
7878 || p_instr_id
7879 || ' because payments already marked complete '
7880 || 'for this instruction.'
7881 );
7882
7883 x_return_status := FND_API.G_RET_STS_SUCCESS;
7884 print_debuginfo(l_module_name, 'Returning success response ..');
7885
7886 print_debuginfo(l_module_name, 'EXIT');
7887
7888 RETURN;
7889
7890 END IF;
7891
7892 print_debuginfo(l_module_name, 'Processing type of payment instruction '
7893 || p_instr_id
7894 || ' is '
7895 || l_processing_type
7896 );
7897
7898 /*
7899 * STEP III:
7900 *
7901 * Mark all payments of this payment instruction as
7902 * completed.
7903 */
7904 IF (l_processing_type = P_TYPE_PRINTED) THEN
7905
7906 UPDATE
7907 IBY_PAYMENTS_ALL
7908 SET
7909 payments_complete_flag = 'Y'
7910 WHERE
7911 payment_instruction_id = p_instr_id AND
7912 payment_status = PAY_STATUS_ISSUED
7913 ;
7914
7915 ELSE
7916
7917 /* electronic processing type */
7918
7919 IF (l_process_type <> PROCESS_TYPE_IMMEDIATE) THEN
7920
7921 /* batch payment(s) */
7922
7923 UPDATE
7924 IBY_PAYMENTS_ALL
7925 SET
7926 payments_complete_flag = 'Y'
7927 WHERE
7928 payment_instruction_id = p_instr_id AND
7929 payment_status IN
7930 (
7931 PAY_STATUS_FORMATTED,
7932 PAY_STATUS_TRANSMITTED,
7933 PAY_STATUS_ACK,
7934 PAY_STATUS_BNK_VALID,
7935 PAY_STATUS_PAID
7936 )
7937 ;
7938
7939 ELSE
7940
7941 /* quick/single payment */
7942
7943 /*
7944 * The Post-PICP program is responsible for
7945 * setting the payment status to FORMATTED /
7946 * TRANSMITTED for electronic payments.
7947 *
7948 * However, when mark_all_payments(..) is called
7949 * for single payments, the Post-PICP would have
7950 * not yet executed (because it runs as a separate
7951 * conc program). Therefore, we set the payment
7952 * complete flag to 'Y' here even through the
7953 * payment is not technically complete.
7954 *
7955 * This special handling is applicable only to
7956 * single payments.
7957 */
7958
7959 /*
7960 * Fix for bug 5179474:
7961 *
7962 * The PICP will now set the payment status to
7963 * FORMATTED without waiting for the Post-PICP
7964 * to complete.
7965 *
7966 * Reason for this change is so that the payment
7967 * status and the payment complete flag are in
7968 * sync (as in batch payments scenario).
7969 *
7970 * Therefore, mark the payment complete if the
7971 * payment status is FORMATTED.
7972 */
7973
7974 UPDATE
7975 IBY_PAYMENTS_ALL
7976 SET
7977 payments_complete_flag = 'Y'
7978 WHERE
7979 payment_instruction_id = p_instr_id AND
7980 payment_status IN
7981 (
7982 PAY_STATUS_FORMATTED
7983 )
7984 ;
7985
7986 END IF;
7987
7988 END IF;
7989
7990 print_debuginfo(l_module_name, 'Finished marking payments of '
7991 || 'payment instruction '
7992 || p_instr_id
7993 || ' as complete.'
7994 );
7995
7996 /*
7997 * STEP IV:
7998 *
7999 * Get the 'process type' if this payment instruction.
8000 *
8001 * If this payment instruction has been created as part
8002 * of single payments flow, the process type will be
8003 * IMMEDIATE, else it will be STANDARD.
8004 *
8005 * We need to know the process type because we should not be
8006 * invoking the callout for quick payments (as these are
8007 * automatically marked as complete by AP).
8008 */
8009
8010 /*
8011 * Fix for bug 4923416.
8012 *
8013 * Get the process type from the payment instruction itself
8014 * instead of deriving it from the payments of the instruction.
8015 */
8016 print_debuginfo(l_module_name, 'Process type for pmt instruction '
8017 || p_instr_id
8018 || ' is '
8019 || l_process_type
8020 );
8021
8022 /*
8023 * STEP V:
8024 *
8025 * Mark the given payment instruction as completed.
8026 */
8027
8028 UPDATE
8029 IBY_PAY_INSTRUCTIONS_ALL
8030 SET
8031 payments_complete_code = PMT_COMPLETE_YES
8032 WHERE
8033 payment_instruction_id = p_instr_id
8034 ;
8035
8036 print_debuginfo(l_module_name, 'Finished marking payment instruction '
8037 || p_instr_id
8038 || ' as complete.'
8039 );
8040
8041 /*
8042 * Pick up the names of all the applications which have
8043 * payments in the current payment instruction.
8044 *
8045 * Remember, one payment instruction can contain payments
8046 * across multiple calling applications.
8047 */
8048 OPEN c_app_names (p_instr_id);
8049 FETCH c_app_names BULK COLLECT INTO l_appNamesTab;
8050 CLOSE c_app_names;
8051
8052 /*
8053 * Pick up the ids of all the applications which have
8054 * payments in the current payment instruction.
8055 *
8056 * Remember, one payment instruction can contain payments
8057 * across multiple calling applications.
8058 */
8059 OPEN c_app_ids (p_instr_id);
8060 FETCH c_app_ids BULK COLLECT INTO l_appIdsTab;
8061 CLOSE c_app_ids;
8062
8063 /*
8064 * STEP VI:
8065 *
8066 * Loop through all the application names, invoking the
8067 * callout of each application.
8068 */
8069 FOR i IN l_appNamesTab.FIRST .. l_appNamesTab.LAST LOOP
8070
8071 /*
8072 * Get the constructed package name to use in the
8073 * call out.
8074 */
8075 l_pkg_name := construct_callout_pkg_name(l_appNamesTab(i));
8076
8077 print_debuginfo(l_module_name, 'Constructed package name: '
8078 || l_pkg_name);
8079
8080 IF (l_pkg_name IS NULL) THEN
8081
8082 print_debuginfo(l_module_name, 'Package name is null. '
8083 || 'Raising exception.');
8084
8085 APP_EXCEPTION.RAISE_EXCEPTION;
8086
8087 END IF;
8088
8089
8090 /*
8091 * Get the next available completed payments group id.
8092 */
8093 SELECT
8094 IBY_COMPLETED_PMTS_GROUP_S.NEXTVAL
8095 INTO
8096 l_completion_id
8097 FROM
8098 DUAL
8099 ;
8100
8101 /*
8102 * Update the completed payments for this calling app
8103 * with the completed document group id. The calling
8104 * application will identify completed documents using
8105 * this id.
8106 */
8107 IF (l_processing_type = P_TYPE_PRINTED) THEN
8108
8109 UPDATE
8110 IBY_PAYMENTS_ALL pmt
8111 SET
8112 pmt.completed_pmts_group_id = l_completion_id
8113 WHERE
8114 pmt.payment_instruction_id = p_instr_id AND
8115 pmt.payments_complete_flag = 'Y' AND
8116 payment_status = PAY_STATUS_ISSUED AND
8117 pmt.payment_id IN
8118 (SELECT
8119 doc.payment_id
8120 FROM
8121 IBY_DOCS_PAYABLE_ALL doc
8122 WHERE
8123 doc.payment_id = pmt.payment_id AND
8124 doc.calling_app_id = l_appIdsTab(i)
8125 )
8126 ;
8127
8128 ELSE
8129
8130 UPDATE
8131 IBY_PAYMENTS_ALL pmt
8132 SET
8133 pmt.completed_pmts_group_id = l_completion_id
8134 WHERE
8135 pmt.payment_instruction_id = p_instr_id AND
8136 pmt.payments_complete_flag = 'Y' AND
8137 payment_status IN
8138 (
8139 PAY_STATUS_FORMATTED,
8140 PAY_STATUS_TRANSMITTED,
8141 PAY_STATUS_ACK,
8142 PAY_STATUS_BNK_VALID,
8143 PAY_STATUS_PAID
8144 ) AND
8145 pmt.payment_id IN
8146 (SELECT
8147 doc.payment_id
8148 FROM
8149 IBY_DOCS_PAYABLE_ALL doc
8150 WHERE
8151 doc.payment_id = pmt.payment_id AND
8152 doc.calling_app_id = l_appIdsTab(i)
8153 )
8154 ;
8155
8156 END IF;
8157
8158 /*
8159 * DEBUG PRINT FOR PAYMENTS
8160 *
8161 * Print list of payments marked complete. This is
8162 * very important for debugging AP-IBY boundry issues.
8163 */
8164 print_completed_pmts(l_completion_id);
8165
8166 /*
8167 * Update the documents of the completed payments with
8168 * the completed document group id. This will allow the
8169 * calling app to select the completed documents directly
8170 * if they so wish.
8171 */
8172 UPDATE
8173 IBY_DOCS_PAYABLE_ALL doc
8174 SET
8175 doc.completed_pmts_group_id = l_completion_id
8176 WHERE
8177 doc.document_status <> 'REMOVED' AND /* Bug 6388935- removed
8178 document handling */
8179 doc.payment_id IN
8180 (SELECT
8181 pmt.payment_id
8182 FROM
8183 IBY_PAYMENTS_ALL pmt
8184 WHERE
8185 pmt.completed_pmts_group_id = l_completion_id
8186 )
8187 ;
8188
8189 /*
8190 * DEBUG PRINT FOR DOCUMENTS
8191 *
8192 * Print list of documents payable marked complete. This is
8193 * very important for debugging AP-IBY boundry issues.
8194 */
8195 print_completed_docs(l_completion_id);
8196
8197 /*
8198 * For single payments, do not invoke the callout because
8199 * single payments are automatically confirmed by AP.
8200 *
8201 * Only invoke callout where process type is not immediate.
8202 */
8203 IF (l_process_type <> PROCESS_TYPE_IMMEDIATE) THEN
8204
8205 /*
8206 * Now try to call the external app's implementation of the hook.
8207 * The calling app may or may not have implemented the hook, so
8208 * it's not fatal if the implementation does not exist.
8209 */
8210 l_callout_name := l_pkg_name || '.' || 'payments_completed';
8211
8212 print_debuginfo(l_module_name, 'Attempting to invoke callout: '
8213 || l_callout_name, FND_LOG.LEVEL_UNEXPECTED);
8214
8215 SELECT
8216 count(*)
8217 INTO
8218 l_pmt_count
8219 FROM
8220 IBY_PAYMENTS_ALL pmt
8221 WHERE
8222 pmt.completed_pmts_group_id = l_completion_id
8223 ;
8224
8225 SELECT
8226 count(*)
8227 INTO
8228 l_doc_count
8229 FROM
8230 IBY_DOCS_PAYABLE_ALL doc
8231 WHERE
8232 doc.completed_pmts_group_id = l_completion_id
8233 ;
8234
8235 print_debuginfo(l_module_name, 'Params passed to callout - '
8236 || 'completed pmts group id: '
8237 || l_completion_id,
8238 FND_LOG.LEVEL_UNEXPECTED
8239 );
8240
8241 print_debuginfo(l_module_name, 'Params not passed to callout - '
8242 || 'completed pmts count: '
8243 || l_pmt_count
8244 || ', completed docs count: '
8245 || l_doc_count
8246 );
8247
8248 l_stmt := 'CALL '|| l_callout_name
8249 || '(:1, :2, :3, :4, :5, :6, :7)';
8250
8251 BEGIN
8252
8253 EXECUTE IMMEDIATE
8254 (l_stmt)
8255 USING
8256 IN l_api_version,
8257 IN FND_API.G_FALSE,
8258 IN FND_API.G_FALSE,
8259 OUT x_return_status,
8260 OUT l_msg_count,
8261 OUT l_msg_data,
8262 IN l_completion_id
8263 ;
8264
8265
8266 /*
8267 * If the called procedure did not return success,
8268 * raise an exception.
8269 */
8270 IF (x_return_status IS NULL OR
8271 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
8272
8273 print_debuginfo(l_module_name, 'Fatal: External app '
8274 || 'callout '''
8275 || l_callout_name
8276 || ''', returned failure status - '
8277 || x_return_status
8278 || '. Raising exception.',
8279 FND_LOG.LEVEL_UNEXPECTED
8280 );
8281
8282 APP_EXCEPTION.RAISE_EXCEPTION;
8283
8284 END IF;
8285
8286 EXCEPTION
8287
8288 WHEN PROCEDURE_NOT_IMPLEMENTED THEN
8289 print_debuginfo(l_module_name, 'Callout "'
8290 || l_callout_name
8291 || '" not implemented by calling app '
8292 || l_app_short_name || '.');
8293
8294 print_debuginfo(l_module_name, 'Skipping hook call.');
8295
8296 WHEN OTHERS THEN
8297 print_debuginfo(l_module_name, 'Fatal: External app '
8298 || 'callout '''
8299 || l_callout_name
8300 || ''', generated exception.',
8301 FND_LOG.LEVEL_UNEXPECTED
8302 );
8303
8304 print_debuginfo(l_module_name, 'SQL code: '
8305 || SQLCODE, FND_LOG.LEVEL_UNEXPECTED);
8306 print_debuginfo(l_module_name, 'SQL err msg: '
8307 || SQLERRM, FND_LOG.LEVEL_UNEXPECTED);
8308
8309 /*
8310 * Fix for bug 5608142:
8311 *
8312 * When mark complete API fails, it is most likely
8313 * because document sequencing has not been setup
8314 * correctly.
8315 *
8316 * Populate a message on the message stack so that
8317 * this message can be displayed to the user.
8318 */
8319 l_error_code := 'IBY_COMPL_CALLOUT_ERROR';
8320 FND_MESSAGE.set_name('IBY', l_error_code);
8321
8322 FND_MESSAGE.SET_TOKEN('CALLOUT',
8323 l_callout_name,
8324 FALSE);
8325
8326 /*
8327 * Set the error message on the concurrent
8328 * program output file (to warn user that
8329 * the hook failed).
8330 */
8331 FND_FILE.PUT_LINE(FND_FILE.OUTPUT, FND_MESSAGE.GET);
8332
8333 /*
8334 * Set the message on the error stack
8335 * to display in UI (in case of direct
8336 * API call from UI).
8337 */
8338 FND_MSG_PUB.ADD;
8339
8340 --FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
8341
8342 /*
8343 * Propogate exception to caller.
8344 */
8345 RAISE;
8346
8347 END;
8348
8349 ELSE
8350
8351 print_debuginfo(l_module_name, 'Not attempting to invoke callout '
8352 || 'because this is a single payment.');
8353
8354 END IF;
8355
8356 END LOOP;
8357
8358 /*
8359 * Step VII:
8360 *
8361 * Unlock the payment document that has been locked by this payment
8362 * instruction.
8363 */
8364
8365 /*
8366 * For single payments, the payment document is not locked.
8367 * Consequently, there is no need to unlock it either.
8368 */
8369 IF (l_process_type <> PROCESS_TYPE_IMMEDIATE) THEN
8370
8371 IF (l_processing_type = P_TYPE_PRINTED) THEN
8372
8373 print_debuginfo(l_module_name, 'Unlocking payment document '
8374 || 'locked by payment instruction '
8375 || p_instr_id
8376 );
8377
8378 BEGIN
8379
8380 UPDATE
8381 CE_PAYMENT_DOCUMENTS
8382 SET
8383 payment_instruction_id = NULL,
8384 /* Bug 6707369
8385 * If some of the documents are skipped, the payment
8386 * document's last issued check number must be updated
8387 */
8388 last_issued_document_number = nvl(
8389 (SELECT MAX(pmt.paper_document_number)
8390 FROM iby_payments_all pmt
8391 WHERE pmt.payment_instruction_id = p_instr_id)
8392 ,last_issued_document_number
8393 )
8394 WHERE
8395 payment_instruction_id = p_instr_id
8396 RETURNING
8397 payment_document_id,
8398 payment_document_name
8399 INTO
8400 l_pmt_doc_id,
8401 l_pmt_doc_name
8402 ;
8403
8404 print_debuginfo(l_module_name, 'Payment document id '
8405 || ''''
8406 || l_pmt_doc_id
8407 || ''''
8408 || ' with name '
8409 || ''''
8410 || l_pmt_doc_name
8411 || ''''
8412 || ' unlocked successfully.'
8413 );
8414
8415 EXCEPTION
8416 WHEN OTHERS THEN
8417
8418 /*
8419 * This is a non-fatal exception. We will log the exception
8420 * and return.
8421 */
8422 print_debuginfo(l_module_name, 'Non-Fatal: Exception occured '
8423 || 'when unlocking pmt document locked by pmt instruction '
8424 || p_instr_id
8425 );
8426
8427 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
8428 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
8429
8430 END;
8431
8432 ELSE
8433
8434 print_debuginfo(l_module_name, 'Not attempting to unlock '
8435 || 'payment document because this is an electronic '
8436 || 'instruction'
8437 );
8438
8439 END IF; -- if processing type = PRINTED
8440
8441 ELSE
8442
8443 print_debuginfo(l_module_name, 'Not attempting to unlock '
8444 || 'payment document because this is a single '
8445 || 'payment (payment document was never locked)'
8446 );
8447
8448 END IF; -- process type <> IMMEDIATE
8449
8450 /*
8451 * Step VIII:
8452 *
8453 * Invoke payment related reports if necessary.
8454 *
8455 * These reports are:
8456 * + Final payment instruction register
8457 * + Separate remittance advice report
8458 */
8459
8460 --Bug 6411356
8461 --below code added to set the current nls character setting
8462 --before submitting a child requests.
8463 fnd_profile.get('ICX_NUMERIC_CHARACTERS',l_icx_numeric_characters);
8464
8465 /*
8466 *
8467 * Get the profile id for this payment instruction
8468 * along with the report related settings.
8469 */
8470 SELECT
8471 prof.payment_profile_id,
8472 prof.positive_pay_format_code,
8473 sys_prof.automatic_pi_reg_submit,
8474 sys_prof.pi_register_format,
8475 remit.automatic_sra_submit_flag,
8476 remit.remittance_advice_format_code
8477 INTO
8478 l_profile_id,
8479 l_pos_pay_format,
8480 l_auto_pi_reg_submit_flag,
8481 l_pi_reg_format,
8482 l_auto_sra_submit_flag,
8483 l_remit_format_code
8484 FROM
8485 IBY_PAYMENT_PROFILES prof,
8486 IBY_SYS_PMT_PROFILES_B sys_prof,
8487 IBY_PAY_INSTRUCTIONS_ALL inst,
8488 IBY_REMIT_ADVICE_SETUP remit
8489 WHERE
8490 prof.payment_profile_id = inst.payment_profile_id AND
8491 sys_prof.system_profile_code = prof.system_profile_code AND
8492 remit.system_profile_code = prof.system_profile_code AND
8493 inst.payment_instruction_id = p_instr_id;
8494
8495 print_debuginfo(l_module_name, 'For payment instruction '
8496 || p_instr_id
8497 || ', profile id: '
8498 || l_profile_id
8499 || ', auto pi register submit flag: '
8500 || l_auto_pi_reg_submit_flag
8501 || ', pi register format: '
8502 || l_pi_reg_format
8503 || ', auto remit advice submit flag: '
8504 || l_auto_sra_submit_flag
8505 || ', remittance advice format: '
8506 || l_remit_format_code
8507 || ', positive pay format: '
8508 || l_pos_pay_format
8509 );
8510
8511 /*
8512 * Launch the Final Payment Instruction Register report.
8513 */
8514
8515 /*
8516 * Fix for bug 5732799:
8517 *
8518 * Pass the payment instruction register format as a
8519 * param when launching the payment instruction register
8520 * report.
8521 */
8522 IF (UPPER(l_auto_pi_reg_submit_flag) = 'Y' AND
8523 l_pi_reg_format IS NOT NULL) THEN
8524
8525 /*
8526 * Fix for bug 5407120:
8527 *
8528 * Before kicking off reports / formats make sure that
8529 * the numeric characters delimiter is correctly set
8530 * by using FND_REQUEST.SET_OPTIONS(..).
8531 *
8532 * The argument provided to this method is based on
8533 * the lookup ICX_NUMERIC_CHARACTERS.
8534 *
8535 * Otherwise, the num delimiter would be picked up
8536 * based on NLS territory and could cause problems.
8537 *
8538 * E.g., $10000.52 would be displayed as $10.000,52 for
8539 * PL territory and this causes problems to XML publisher.
8540 */
8541 l_bool_val := FND_REQUEST.SET_OPTIONS(
8542 numeric_characters => l_icx_numeric_characters
8543 );
8544
8545 l_conc_req_id := FND_REQUEST.SUBMIT_REQUEST(
8546 'IBY',
8547 'IBY_FD_FINAL_PMT_REGISTER',
8548 '',
8549 '',
8550 FALSE,
8551 ''||p_instr_id||'',
8552 ''||l_pi_reg_format||'',
8553 '', '', '', '', '', '', '', '', '',
8554 '', '', '', '', '', '', '', '', '', '',
8555 '', '', '', '', '', '', '', '', '', '',
8556 '', '', '', '', '', '', '', '', '', '',
8557 '', '', '', '', '', '', '', '', '', '',
8558 '', '', '', '', '', '', '', '', '', '',
8559 '', '', '', '', '', '', '', '', '', '',
8560 '', '', '', '', '', '', '', '', '', '',
8561 '', '', '', '', '', '', '', '', '', '',
8562 '', '', '', '', '', '', ''
8563 );
8564
8565 IF (l_conc_req_id = 0) THEN
8566
8567 print_debuginfo(l_module_name, 'Request to launch payment '
8568 || 'instruction register report concurrent program failed.');
8569 APP_EXCEPTION.RAISE_EXCEPTION;
8570
8571 ELSE
8572
8573 print_debuginfo(l_module_name, 'Payment instruction register '
8574 || 'report was launched successfully. '
8575 || 'Check concurrent request id :'
8576 || to_char(l_conc_req_id)
8577 );
8578
8579 END IF;
8580
8581 END IF;
8582
8583 /*
8584 * Launch the Separate Remittance Advice report.
8585 */
8586 IF (UPPER(l_auto_sra_submit_flag) = 'Y') THEN
8587
8588 l_bool_val := FND_REQUEST.SET_OPTIONS(
8589 numeric_characters => l_icx_numeric_characters
8590 );
8591
8592 l_conc_req_id := FND_REQUEST.SUBMIT_REQUEST(
8593 'IBY',
8594 'IBY_FD_SRA_FORMAT',
8595 '',
8596 '',
8597 FALSE,
8598 ''||p_instr_id||'',
8599 ''||l_remit_format_code||'',
8600 '', '', '', '', '', '', '', '', '',
8601 '', '', '', '', '', '', '', '', '', '',
8602 '', '', '', '', '', '', '', '', '', '',
8603 '', '', '', '', '', '', '', '', '', '',
8604 '', '', '', '', '', '', '', '', '', '',
8605 '', '', '', '', '', '', '', '', '', '',
8606 '', '', '', '', '', '', '', '', '', '',
8607 '', '', '', '', '', '', '', '', '', '',
8608 '', '', '', '', '', '', '', '', '', '',
8609 '', '', '', '', '', '', ''
8610 );
8611
8612 IF (l_conc_req_id = 0) THEN
8613
8614 print_debuginfo(l_module_name, 'Request to launch separate '
8615 || 'remittance advice report concurrent program failed.');
8616 APP_EXCEPTION.RAISE_EXCEPTION;
8617
8618 ELSE
8619
8620 print_debuginfo(l_module_name, 'Separate remittance advice '
8621 || 'report was launched successfully. '
8622 || 'Check concurrent request id :'
8623 || to_char(l_conc_req_id)
8624 );
8625
8626 END IF;
8627
8628 END IF;
8629
8630
8631 /*
8632 * Launch the Positive Pay program.
8633 */
8634 IF (p_submit_postive_pay = TRUE AND l_pos_pay_format IS NOT NULL) THEN
8635
8636 l_bool_val := FND_REQUEST.SET_OPTIONS(
8637 numeric_characters => l_icx_numeric_characters
8638 );
8639
8640 l_conc_req_id := FND_REQUEST.SUBMIT_REQUEST(
8641 'IBY',
8642 'IBY_FD_POS_PAY_FORMAT',
8643 '',
8644 '',
8645 FALSE,
8646
8647 '', -- do not supply profile
8648 '', -- do not supply from pmt date
8649 '', -- do not supply to pmt date
8650 ''||p_instr_id||'',
8651
8652 '', '', '', '', '', '', '',
8653 '', '', '', '', '', '', '', '', '', '',
8654 '', '', '', '', '', '', '', '', '', '',
8655 '', '', '', '', '', '', '', '', '', '',
8656 '', '', '', '', '', '', '', '', '', '',
8657 '', '', '', '', '', '', '', '', '', '',
8658 '', '', '', '', '', '', '', '', '', '',
8659 '', '', '', '', '', '', '', '', '', '',
8660 '', '', '', '', '', '', '', '', '', '',
8661 '', '', '', '', '', '', ''
8662 );
8663
8664 IF (l_conc_req_id = 0) THEN
8665
8666 print_debuginfo(l_module_name, 'Request to launch positive '
8667 || 'pay concurrent program failed.');
8668 APP_EXCEPTION.RAISE_EXCEPTION;
8669
8670 ELSE
8671
8672 print_debuginfo(l_module_name, 'Positive pay '
8673 || 'program was launched successfully. '
8674 || 'Check concurrent request id :'
8675 || to_char(l_conc_req_id)
8676 );
8677
8678 END IF;
8679
8680 ELSE
8681
8682 /*
8683 * In case we did not launch the positive pay
8684 * program, mention why.
8685 */
8686 IF (p_submit_postive_pay = FALSE) THEN
8687
8688 print_debuginfo(l_module_name, 'Positive pay '
8689 || 'program not launched because submit '
8690 || 'positive pay flag was not set.'
8691 );
8692
8693 ELSE
8694
8695 print_debuginfo(l_module_name, 'Positive pay '
8696 || 'program not launched because positive '
8697 || 'pay format was not set on profile id '
8698 || l_profile_id
8699 );
8700
8701 END IF;
8702
8703 END IF;
8704
8705 x_return_status := FND_API.G_RET_STS_SUCCESS;
8706
8707 print_debuginfo(l_module_name, 'Returning success response ..');
8708
8709 print_debuginfo(l_module_name, 'EXIT');
8710
8711 EXCEPTION
8712
8713 WHEN OTHERS THEN
8714
8715 print_debuginfo(l_module_name, 'Exception occured when '
8716 || 'marking payments complete for payment instruction '
8717 || p_instr_id
8718 );
8719
8720 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
8721 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
8722 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
8723
8724 x_return_status := FND_API.G_RET_STS_ERROR;
8725
8726 print_debuginfo(l_module_name, 'EXIT');
8727
8728 END mark_all_pmts_complete;
8729
8730 /*--------------------------------------------------------------------
8731 | NAME:
8732 | transmit_pmt_instruction
8733 |
8734 |
8735 | PURPOSE:
8736 |
8737 |
8738 | PARAMETERS:
8739 | IN
8740 |
8741 |
8742 | OUT
8743 |
8744 |
8745 | RETURNS:
8746 |
8747 | NOTES:
8748 | Internal API, not for public use.
8749 |
8750 *---------------------------------------------------------------------*/
8751 PROCEDURE transmit_pmt_instruction (
8752 p_instr_id IN NUMBER,
8753 p_trans_status IN VARCHAR2,
8754 p_error_code IN VARCHAR2,
8755 p_error_msg IN VARCHAR2,
8756 x_return_status OUT NOCOPY VARCHAR2
8757 )
8758 IS
8759
8760 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
8761 || '.transmit_pmt_instruction';
8762
8763 BEGIN
8764
8765 print_debuginfo(l_module_name, 'ENTER');
8766 FND_MSG_PUB.initialize;
8767
8768 x_return_status := FND_API.G_RET_STS_SUCCESS;
8769
8770 -- Update payment transaction statuses (instruction, payments, etc.)
8771 IBY_FD_POST_PICP_PROGS_PVT.Post_Results(
8772 p_instr_id,
8773 p_trans_status,
8774 'N',
8775 x_return_status
8776 );
8777
8778 print_debuginfo(l_module_name, 'Return status from Post_Results(..): '
8779 || x_return_status
8780 );
8781
8782 if p_trans_status = 'TRANSMISSION_FAILED' then
8783 IBY_FD_POST_PICP_PROGS_PVT.Insert_Transmission_Error(p_instr_id,
8784 p_error_code,
8785 p_error_msg);
8786 end if;
8787
8788 IF (x_return_status IS NULL OR
8789 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
8790 print_debuginfo(l_module_name, 'Returning error response: '
8791 || x_return_status
8792 );
8793 ELSE
8794 print_debuginfo(l_module_name, 'Returning success response ..');
8795 END IF;
8796
8797 print_debuginfo(l_module_name, 'EXIT');
8798
8799 EXCEPTION
8800 WHEN OTHERS THEN
8801
8802 print_debuginfo(l_module_name, 'Exception occured when '
8803 || 'performing transmit for payment instruction '
8804 || p_instr_id
8805 );
8806
8807 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
8808 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
8809 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
8810
8811 x_return_status := FND_API.G_RET_STS_ERROR;
8812
8813 print_debuginfo(l_module_name, 'EXIT');
8814
8815 END transmit_pmt_instruction;
8816
8817 /*--------------------------------------------------------------------
8818 | NAME:
8819 | construct_callout_pkg_name
8820 |
8821 |
8822 | PURPOSE:
8823 |
8824 |
8825 | PARAMETERS:
8826 | IN
8827 |
8828 |
8829 | OUT
8830 |
8831 |
8832 | RETURNS:
8833 |
8834 | NOTES:
8835 |
8836 *---------------------------------------------------------------------*/
8837 FUNCTION construct_callout_pkg_name (
8838 p_app_short_name IN VARCHAR2
8839 ) RETURN VARCHAR2
8840 IS
8841
8842 l_pkg_prefix VARCHAR2(100);
8843 l_pkg_suffix VARCHAR2(100) := '_PMT_CALLOUT_PKG';
8844 l_pkg_name VARCHAR2(200);
8845
8846 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME ||
8847 '.construct_callout_pkg_name';
8848
8849 BEGIN
8850
8851 print_debuginfo(l_module_name, 'ENTER');
8852 print_debuginfo(l_module_name, 'Provided app short name: '
8853 || p_app_short_name);
8854
8855 IF (p_app_short_name IS NULL) THEN
8856
8857 print_debuginfo(l_module_name, 'No app short name provided. '
8858 || 'Returning null ..'
8859 );
8860
8861 print_debuginfo(l_module_name, 'EXIT');
8862
8863 RETURN NULL;
8864
8865 END IF;
8866
8867 /*
8868 * When we invoke the hook procedure in the external app,
8869 * we must use the hook signature as <package name>.<procedure name>.
8870 *
8871 * For some applications, the application short name cannot
8872 * be directly used in forming the package name.
8873 *
8874 * Example, for AP, the application short name is 'SQLAP',
8875 * but the AP packages begin as 'AP_XXXX'. Therefore,
8876 * we will convert the application short names into package
8877 * prefixes here.
8878 */
8879 CASE p_app_short_name
8880 WHEN 'SQLAP' THEN
8881 l_pkg_prefix := 'AP';
8882 ELSE
8883 l_pkg_prefix := p_app_short_name;
8884 END CASE;
8885
8886 l_pkg_name := l_pkg_prefix || l_pkg_suffix;
8887
8888 print_debuginfo(l_module_name, 'Constructed package name: '
8889 || l_pkg_name);
8890
8891 print_debuginfo(l_module_name, 'EXIT');
8892
8893 RETURN l_pkg_name;
8894
8895 END construct_callout_pkg_name;
8896
8897 /*--------------------------------------------------------------------
8898 | NAME:
8899 | print_debuginfo
8900 |
8901 | PURPOSE:
8902 |
8903 |
8904 | PARAMETERS:
8905 | IN
8906 |
8907 |
8908 | OUT
8909 |
8910 |
8911 | RETURNS:
8912 |
8913 | NOTES:
8914 |
8915 *---------------------------------------------------------------------*/
8916 PROCEDURE print_debuginfo(
8917 p_module IN VARCHAR2,
8918 p_debug_text IN VARCHAR2,
8919 p_debug_level IN VARCHAR2 DEFAULT FND_LOG.LEVEL_STATEMENT
8920 )
8921 IS
8922 l_default_debug_level VARCHAR2(200) := FND_LOG.LEVEL_STATEMENT;
8923 BEGIN
8924
8925 /*
8926 * Set the debug level to the value passed in
8927 * (provided this value is not null).
8928 */
8929 IF (p_debug_level IS NOT NULL) THEN
8930 l_default_debug_level := p_debug_level;
8931 END IF;
8932
8933 /*
8934 * Write the debug message to the concurrent manager log file.
8935 */
8936 IF (l_default_debug_level >= FND_LOG.G_CURRENT_RUNTIME_LEVEL) THEN
8937 iby_build_utils_pkg.print_debuginfo(p_module, p_debug_text,
8938 p_debug_level);
8939 END IF;
8940
8941 END print_debuginfo;
8942
8943 /*--------------------------------------------------------------------
8944 | NAME: get_message_text
8945 |
8946 |
8947 | PURPOSE: This function will return the transalated message text
8948 | for validation errors stored in iby_transaction_errors
8949 | This function should be used from the UI pages.
8950 |
8951 | PARAMETERS:
8952 | IN p_transaction_error_id - Transaction error id for the error
8953 | IN p_error_code - Error code. This paramester is required
8954 | so that the function does not hit the
8955 | iby_transaction_errors table again.
8956 |
8957 | RETURNS: translated message_text
8958 |
8959 | NOTES:
8960 |
8961 *---------------------------------------------------------------------*/
8962 FUNCTION get_message_text (p_transaction_error_id IN NUMBER,
8963 p_error_code IN VARCHAR2)
8964 RETURN VARCHAR2 AS
8965 l_error_mes varchar2(4000);
8966
8967 TYPE l_token_info_rec IS RECORD(
8968 token_name iby_trxn_error_tokens.token_name%TYPE,
8969 token_value iby_trxn_error_tokens.token_value%TYPE,
8970 lookup_type_source iby_trxn_error_tokens.lookup_type_source%TYPE,
8971 meaning fnd_lookups.meaning%TYPE);
8972
8973 TYPE l_token_info_tab IS TABLE OF l_token_info_rec;
8974
8975 l_token_info l_token_info_tab;
8976
8977 CURSOR token_info(c_trxn_error_id IN iby_transaction_errors.transaction_error_id%TYPE) IS
8978 SELECT t.token_name, t.token_value, t.lookup_type_source, l.meaning
8979 FROM iby_trxn_error_tokens t, fnd_lookups l
8980 WHERE t.transaction_error_id = (c_trxn_error_id)
8981 AND t.lookup_type_source = l.lookup_type(+)
8982 AND t.token_value = l.lookup_code(+);
8983
8984 BEGIN
8985
8986 IF (p_transaction_error_id IS NOT NULL AND
8987 p_error_code IS NOT NULL) THEN
8988
8989 FND_MESSAGE.SET_NAME('IBY', p_error_code);
8990
8991 -- get token info if any.
8992 BEGIN
8993 OPEN token_info(p_transaction_error_id);
8994 FETCH token_info
8995 BULK COLLECT INTO l_token_info;
8996 CLOSE token_info;
8997 EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
8998 END;
8999
9000 IF (l_token_info.COUNT > 0) THEN
9001 FOR j IN l_token_info.FIRST..l_token_info.LAST LOOP
9002 IF (l_token_info(j).lookup_type_source IS NULL) THEN
9003 FND_MESSAGE.SET_TOKEN(l_token_info(j).token_name, l_token_info(j).token_value);
9004 ELSE
9005 FND_MESSAGE.SET_TOKEN(l_token_info(j).token_name, l_token_info(j).meaning);
9006 END IF;
9007
9008 END LOOP;
9009 END IF;
9010
9011 END IF;
9012
9013 l_error_mes := FND_MESSAGE.GET;
9014 RETURN l_error_mes;
9015
9016 END get_message_text;
9017
9018 /*--------------------------------------------------------------------
9019 | NAME: get_message_list
9020 |
9021 |
9022 | PURPOSE: This function will return the transalated message text
9023 | for validation errors stored in iby_transaction_errors for an
9024 | specific transaction. This function will return the list of
9025 | messages in html format.
9026 | This function should be used from the UI pages.
9027 |
9028 | PARAMETERS:
9029 | IN p_transaction_id - Transaction id (instruction, payment or document id)
9030 | IN p_transaction_type - Transaction type.
9031 | (PAYMENT, PAYMENT INSTRUCTION, etc.)
9032 |
9033 | RETURNS: translated list of messages for a transaction in html format
9034 |
9035 | NOTES:
9036 |
9037 *---------------------------------------------------------------------*/
9038 FUNCTION get_message_list (p_transaction_id IN NUMBER,
9039 p_transaction_type IN VARCHAR2)
9040 RETURN VARCHAR2 AS
9041
9042 l_contact_mes varchar2(4000);
9043 TYPE l_mes_info_rec IS RECORD (
9044 trxn_error_id iby_transaction_errors.transaction_error_id%TYPE,
9045 error_code iby_transaction_errors.error_code%TYPE);
9046
9047 TYPE l_token_info_rec IS RECORD(
9048 token_name iby_trxn_error_tokens.token_name%TYPE,
9049 token_value iby_trxn_error_tokens.token_value%TYPE,
9050 lookup_type_source iby_trxn_error_tokens.lookup_type_source%TYPE,
9051 meaning fnd_lookups.meaning%TYPE);
9052
9053 TYPE l_mes_info_tab IS TABLE OF l_mes_info_rec;
9054 TYPE l_token_info_tab IS TABLE OF l_token_info_rec;
9055
9056 l_mes_info l_mes_info_tab;
9057 l_token_info l_token_info_tab;
9058
9059 CURSOR trxn_errors IS
9060 SELECT transaction_error_id, error_code
9061 FROM iby_transaction_errors
9062 WHERE transaction_id = p_transaction_id
9063 AND transaction_type = p_transaction_type
9064 AND error_status = 'ACTIVE';
9065
9066 CURSOR token_info(c_trxn_error_id IN iby_transaction_errors.transaction_error_id%TYPE) IS
9067 SELECT t.token_name, t.token_value, t.lookup_type_source, l.meaning
9068 FROM iby_trxn_error_tokens t, fnd_lookups l
9069 WHERE t.transaction_error_id = (c_trxn_error_id)
9070 AND t.lookup_type_source = l.lookup_type(+)
9071 AND t.token_value = l.lookup_code(+);
9072
9073 BEGIN
9074 BEGIN
9075 OPEN trxn_errors;
9076 FETCH trxn_errors
9077 BULK COLLECT INTO l_mes_info;
9078 CLOSE trxn_errors;
9079 EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
9080 END;
9081
9082 IF (l_mes_info.COUNT > 0) THEN
9083 l_contact_mes := '<OL>';
9084 FOR i IN l_mes_info.FIRST..l_mes_info.LAST LOOP
9085 FND_MESSAGE.SET_NAME('IBY',l_mes_info(i).error_code);
9086
9087 -- get token info if any.
9088 BEGIN
9089 OPEN token_info(l_mes_info(i).trxn_error_id);
9090 FETCH token_info
9091 BULK COLLECT INTO l_token_info;
9092 CLOSE token_info;
9093 EXCEPTION WHEN NO_DATA_FOUND THEN NULL;
9094 END;
9095
9096 IF (l_token_info.COUNT > 0) THEN
9097 FOR j IN l_token_info.FIRST..l_token_info.LAST LOOP
9098 IF (l_token_info(j).lookup_type_source IS NULL) THEN
9099 FND_MESSAGE.SET_TOKEN(l_token_info(j).token_name, l_token_info(j).token_value);
9100 ELSE
9101 FND_MESSAGE.SET_TOKEN(l_token_info(j).token_name, l_token_info(j).meaning);
9102 END IF;
9103
9104 END LOOP;
9105 END IF;
9106
9107 l_contact_mes := l_contact_mes||'<LI>'||FND_MESSAGE.GET||'</LI>';
9108
9109 END LOOP;
9110 l_contact_mes := l_contact_mes||'</OL>';
9111
9112 END IF;
9113 RETURN l_contact_mes;
9114 END get_message_list;
9115
9116 /*--------------------------------------------------------------------
9117 | NAME:
9118 | perform_check_print
9119 |
9120 | PURPOSE: This procedure calls the IBY_CHECKNUMBER_PUB.performCheckNumbering
9121 | procedure to lock the payment document and number the payments
9122 |
9123 |
9124 | PARAMETERS:
9125 | IN p_instruction_id - Payment Instruction to print
9126 | IN p_pmt_document_id - Payment document id used to print
9127 | payment instruction
9128 | IN p_printer_name - Printer defined by the user
9129 |
9130 | OUT x_return_status - Return status (S, E, U)
9131 | OUT x_return_message - This error code will indicate if there
9132 | is any error during the numbering of the
9133 | payment instruction or if the payment
9134 | document cannot be locked.
9135 |
9136 | NOTES: This procedure is only called from the Print UI since it will
9137 | number the complete payment instruction.
9138 |
9139 | IMPORTANT NOTE:
9140 | This procedure originally did not perform a COMMIT. However,
9141 | after unexpected behaviors started occuring after lock/unlock
9142 | APIs for handling intermediate statuses were introduced.
9143 |
9144 | These APIs stamp a conc request id against a pmt entity
9145 | (such as a pmt request or pmt instruction) and perform a commit.
9146 |
9147 | If that underlying pmt entity has already been updated, but not
9148 | committed a deadlock condition ensues and this API exits with
9149 | error 'ORA-00060: deadlock detected while waiting for resource'.
9150 |
9151 | Therefore, a COMMIT is performed after the payment instruction
9152 | is updated in this method. The Post-PICP API will lock the
9153 | same payment instruction by stamping the conc request id on it.
9154 | This operation does not fail now because the changes made to the
9155 | payment instruction have already been committed.
9156 |
9157 | See bug 5195769 for an example of this deadlock scenario.
9158 |
9159 *---------------------------------------------------------------------*/
9160 PROCEDURE perform_check_print(
9161 p_instruction_id IN NUMBER,
9162 p_pmt_document_id IN NUMBER,
9163 p_printer_name IN VARCHAR2,
9164 x_return_status IN OUT NOCOPY VARCHAR2,
9165 x_return_message IN OUT NOCOPY VARCHAR2) IS
9166
9167 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME|| '.perform_check_print';
9168 l_instr_status IBY_PAY_INSTRUCTIONS_ALL.payment_instruction_status%TYPE;
9169
9170 l_error_code VARCHAR2(3000);
9171
9172 l_msg_count NUMBER;
9173 l_msg_data VARCHAR2(4000);
9174
9175 BEGIN
9176
9177 print_debuginfo(l_module_name, 'ENTER');
9178
9179 FND_MSG_PUB.initialize;
9180
9181 /*
9182 * Get the status of the provided payment instruction.
9183 */
9184 BEGIN
9185
9186 SELECT
9187 payment_instruction_status
9188 INTO
9189 l_instr_status
9190 FROM
9191 IBY_PAY_INSTRUCTIONS_ALL
9192 WHERE
9193 payment_instruction_id = p_instruction_id
9194 ;
9195
9196 EXCEPTION
9197 WHEN OTHERS THEN
9198
9199 print_debuginfo(l_module_name, 'Fatal: Exception occured '
9200 || 'when attempting to get status of payment '
9201 || 'instruction '
9202 || p_instruction_id
9203 || '. Aborting ..'
9204 );
9205
9206 l_error_code := 'IBY_INS_NOT_FOUND';
9207 FND_MESSAGE.set_name('IBY', l_error_code);
9208
9209 FND_MESSAGE.SET_TOKEN('INS_ID',
9210 p_instruction_id,
9211 FALSE);
9212 FND_MSG_PUB.add;
9213 x_return_message := FND_MESSAGE.get;
9214
9215 /*
9216 * Propogate exception.
9217 */
9218 RAISE;
9219 END;
9220
9221 print_debuginfo(l_module_name, 'Status of payment instruction '
9222 || p_instruction_id
9223 || ' is '
9224 || l_instr_status
9225 );
9226
9227 /*
9228 * First check whether the provided payment instruction
9229 * is in the right status.
9230 */
9231 IF (l_instr_status <> INS_STATUS_READY_TO_PRINT AND
9232 l_instr_status <> INS_STATUS_READY_TO_FORMAT AND
9233 l_instr_status <> INS_STATUS_FORMAT_TO_PRINT) THEN
9234
9235 print_debuginfo(l_module_name, 'Payment instruction '
9236 || p_instruction_id
9237 || ' is in status '
9238 || l_instr_status
9239 || '. Cannot print this instruction ..'
9240 );
9241
9242 l_error_code := 'IBY_INS_NOT_PRINT_STATUS';
9243 FND_MESSAGE.set_name('IBY', l_error_code);
9244
9245 FND_MESSAGE.SET_TOKEN('INS_ID',
9246 p_instruction_id,
9247 FALSE);
9248
9249 FND_MESSAGE.SET_TOKEN('BAD_STATUS',
9250 l_instr_status,
9251 FALSE);
9252 FND_MSG_PUB.add;
9253 x_return_message := FND_MESSAGE.get;
9254
9255 APP_EXCEPTION.RAISE_EXCEPTION;
9256
9257 END IF;
9258
9259 /*
9260 * If we reached here, the payment instruction is the
9261 * correct status.
9262 *
9263 * Update the printer associated with this payment instruction
9264 * with the provided printer name. The Post-PICP modules
9265 * will use this printer for printing the checks.
9266 */
9267 UPDATE
9268 IBY_PAY_INSTRUCTIONS_ALL
9269 SET
9270 printer_name = p_printer_name
9271 WHERE
9272 payment_instruction_id = p_instruction_id
9273 ;
9274
9275 /*
9276 * Fix for bug 5195769:
9277 *
9278 * This commit is necessary. Otherwise a deadlocked
9279 * condition is created when we try to update the same
9280 * payment instruction with the concurrent request id
9281 * (for handling intermediate statuses).
9282 */
9283 COMMIT;
9284
9285 /*
9286 * Lastly invoke numbering and/or printing depending
9287 * upon the status of the payment instruction.
9288 */
9289 IF (l_instr_status = INS_STATUS_FORMAT_TO_PRINT) THEN
9290
9291 /*
9292 * This means that this payment instruction is
9293 * already formatted. Only printing is required.
9294 */
9295 BEGIN
9296
9297 print_debuginfo(l_module_name, 'Going to invoke '
9298 || 'extract and format operation for payment instruction '
9299 || p_instruction_id
9300 );
9301
9302 IBY_FD_POST_PICP_PROGS_PVT.
9303 Run_Post_PI_Programs(
9304 p_instruction_id,
9305 'N'
9306 );
9307
9308 print_debuginfo(l_module_name, 'Extract and format '
9309 || 'operation completed successfully.'
9310 );
9311
9312 EXCEPTION
9313 WHEN OTHERS THEN
9314
9315 print_debuginfo(l_module_name, 'Extract and '
9316 || 'format operation generated '
9317 || 'exception for payment instruction '
9318 || p_instruction_id
9319 );
9320
9321 l_error_code := 'IBY_INS_BACKEND_ERROR';
9322 FND_MESSAGE.set_name('IBY', l_error_code);
9323
9324 FND_MESSAGE.SET_TOKEN('INS_ID',
9325 p_instruction_id,
9326 FALSE);
9327 FND_MSG_PUB.add;
9328 x_return_message := FND_MESSAGE.get;
9329
9330 /*
9331 * Propagate exception.
9332 */
9333 RAISE;
9334
9335 END;
9336
9337 ELSE
9338
9339 /*
9340 * This means that this payment instruction is not
9341 * yet numbered. Invoke the numbering flow.
9342 */
9343 IBY_CHECKNUMBER_PUB.performCheckNumbering(
9344 p_instruction_id,
9345 p_pmt_document_id,
9346 NULL,
9347 x_return_status,
9348 x_return_message,
9349 l_msg_count,
9350 l_msg_data
9351 );
9352
9353 IF (x_return_status IS NULL OR
9354 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
9355
9356 print_debuginfo(l_module_name, 'Check numbering '
9357 || 'operation failed for payment instruction '
9358 || p_instruction_id
9359 || ' with error message: '
9360 || x_return_message
9361 );
9362
9363 APP_EXCEPTION.RAISE_EXCEPTION;
9364
9365 END IF;
9366
9367 /*
9368 * After numbering, invoke the printing flow.
9369 */
9370 BEGIN
9371
9372 print_debuginfo(l_module_name, 'Invoking extract and '
9373 || 'format operation for payment instruction '
9374 || p_instruction_id
9375 );
9376
9377 IBY_FD_POST_PICP_PROGS_PVT.
9378 Run_Post_PI_Programs(
9379 p_instruction_id,
9380 'N'
9381 );
9382
9383 print_debuginfo(l_module_name, 'Extract and format '
9384 || 'operation completed successfully'
9385 );
9386
9387 EXCEPTION
9388 WHEN OTHERS THEN
9389
9390 l_error_code := 'IBY_INS_BACKEND_ERROR';
9391 FND_MESSAGE.set_name('IBY', l_error_code);
9392
9393 FND_MESSAGE.SET_TOKEN('INS_ID',
9394 p_instruction_id,
9395 FALSE);
9396 FND_MSG_PUB.add;
9397 x_return_message := FND_MESSAGE.get;
9398
9399 print_debuginfo(l_module_name, 'Extract and '
9400 || 'format operation generated '
9401 || 'exception for payment instruction '
9402 || p_instruction_id
9403 );
9404
9405 /*
9406 * Propagate exception.
9407 */
9408 RAISE;
9409
9410 END;
9411
9412 END IF;
9413
9414 /*
9415 * Return success.
9416 */
9417 print_debuginfo(l_module_name, 'Returning success response ..');
9418 x_return_status := FND_API.G_RET_STS_SUCCESS;
9419
9420 print_debuginfo(l_module_name, 'EXIT');
9421
9422 EXCEPTION
9423 WHEN OTHERS THEN
9424
9425 print_debuginfo(l_module_name, 'Exception occured when '
9426 || 'performing check print'
9427 );
9428
9429 print_debuginfo(l_module_name, 'SQL code: '
9430 || SQLCODE);
9431 print_debuginfo(l_module_name, 'SQL err msg: '
9432 || SQLERRM);
9433 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
9434
9435 print_debuginfo(l_module_name, 'Returning failure response .. '
9436 );
9437
9438 /*
9439 * The error message would have already been set.
9440 * Just set the error status here.
9441 */
9442 x_return_status := FND_API.G_RET_STS_ERROR;
9443
9444 print_debuginfo(l_module_name, 'EXIT');
9445
9446 END perform_check_print;
9447
9448 /*--------------------------------------------------------------------
9449 | NAME:
9450 | checkIfDocUsed
9451 |
9452 | PURPOSE:
9453 | Checks if a given paper document number has already been used.
9454 | A used paper document implies that a check has already been
9455 | printed for the given paper document number.
9456 |
9457 |
9458 | PARAMETERS:
9459 | IN
9460 | p_paper_doc_num - Paper document number (check number) to verify.
9461 |
9462 | p_pmt_document_id - Payment document id (check stock) that this
9463 | paper document number belongs to.
9464 | OUT
9465 | NONE
9466 |
9467 | RETURNS:
9468 | TRUE - if the paper document number has already been used.
9469 | FALSE - if the paper document number has not been used.
9470 |
9471 | NOTES:
9472 |
9473 *---------------------------------------------------------------------*/
9474 FUNCTION checkIfDocUsed(
9475 p_paper_doc_num IN NUMBER,
9476 p_pmt_document_id IN NUMBER
9477 ) RETURN BOOLEAN
9478 IS
9479
9480 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
9481 || '.checkIfDocUsed';
9482
9483 l_flag BOOLEAN;
9484 l_used_paper_doc_number NUMBER := 0;
9485
9486 BEGIN
9487
9488 /*
9489 * Check if this paper document number has already
9490 * been used by searching the the IBY_USED_PAYMENT_DOCS
9491 * table.
9492 */
9493 SELECT
9494 used_document_number
9495 INTO
9496 l_used_paper_doc_number
9497 FROM
9498 IBY_USED_PAYMENT_DOCS
9499 WHERE
9500 payment_document_id = p_pmt_document_id AND
9501 used_document_number = p_paper_doc_num AND
9502 document_use <> 'SKIPPED'
9503 ;
9504
9505 /*
9506 * If we reached here, it means that a row has been
9507 * found in the IBY_USED_PAYMENT_DOCS table for the
9508 * given (paper doc number, payment document id)
9509 * combination. This means that the paper document
9510 * is used.
9511 *
9512 * Set the return flag to true.
9513 */
9514 l_flag := TRUE;
9515
9516 print_debuginfo(l_module_name, 'Returning TRUE.');
9517 RETURN l_flag;
9518
9519 EXCEPTION
9520
9521 WHEN NO_DATA_FOUND THEN
9522
9523 /* now rows means success */
9524 print_debuginfo(l_module_name, 'Paper document '
9525 || 'number '
9526 || p_paper_doc_num
9527 || ' is unused.'
9528 );
9529
9530 /* set the return flag to false */
9531 l_flag := FALSE;
9532
9533 print_debuginfo(l_module_name, 'Returning FALSE.');
9534 RETURN l_flag;
9535
9536 WHEN OTHERS THEN
9537
9538 print_debuginfo(l_module_name, 'Exception occured when '
9539 || 'attempting to get details of paper document '
9540 || p_paper_doc_num
9541 || ' from IBY_USED_PAYMENT_DOCS table.'
9542 );
9543
9544 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
9545 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
9546
9547 print_debuginfo(l_module_name, 'Unexpected error. '
9548 || 'Raising exception ..');
9549
9550 APP_EXCEPTION.RAISE_EXCEPTION;
9551
9552 END checkIfDocUsed;
9553
9554 /*--------------------------------------------------------------------
9555 | NAME:
9556 | insert_conc_request
9557 |
9558 | PURPOSE:
9559 | Inserts a given concurrent request id into the
9560 | IBY_PROCESS_CONC_REQUESTS table for audit purposes.
9561 |
9562 | PARAMETERS:
9563 | IN
9564 | p_object_id The id of the payment entity. This can be
9565 | a payment id, a payment request id or a payment
9566 | instruction id.
9567 |
9568 | p_object_type The type of the payment entity. This can be
9569 | one of the following
9570 | PAYMENT
9571 | PAYMENT_REQUEST
9572 | PAYMENT_INSTRUCTION
9573 |
9574 | p_conc_request_id The concurrent request id.
9575 |
9576 | p_completed_flag Flag indicating whether the concurrent request
9577 | has completed.
9578 |
9579 | OUT
9580 | x_return_status Return status (S, E, U)
9581 |
9582 | RETURNS:
9583 |
9584 | NOTES:
9585 |
9586 *---------------------------------------------------------------------*/
9587 PROCEDURE insert_conc_request(
9588 p_object_id IN NUMBER,
9589 p_object_type IN VARCHAR2,
9590 p_conc_request_id IN NUMBER,
9591 p_completed_flag IN VARCHAR2 DEFAULT 'N',
9592 x_return_status IN OUT NOCOPY VARCHAR2
9593 )
9594 IS
9595
9596 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME|| '.insert_conc_request';
9597
9598 BEGIN
9599
9600 print_debuginfo(l_module_name, 'ENTER');
9601
9602 print_debuginfo(l_module_name, 'Inserting conc request id '
9603 || p_conc_request_id
9604 || ' into IBY_PROCESS_CONC_REQUESTS for object id '
9605 || p_object_id
9606 || ' with object type '
9607 || p_object_type
9608 );
9609
9610 INSERT INTO IBY_PROCESS_CONC_REQUESTS
9611 (
9612 OBJECT_ID, /* 1 */
9613 OBJECT_TYPE,
9614 REQUEST_ID,
9615 COMPLETED_FLAG,
9616 CREATED_BY, /* 5 */
9617 CREATION_DATE,
9618 LAST_UPDATED_BY,
9619 LAST_UPDATE_DATE,
9620 LAST_UPDATE_LOGIN,
9621 OBJECT_VERSION_NUMBER /* 10 */
9622 )
9623 VALUES
9624 (
9625 p_object_id, /* 1 */
9626 p_object_type,
9627 p_conc_request_id,
9628 p_completed_flag,
9629 fnd_global.user_id, /* 5 */
9630 sysdate,
9631 fnd_global.user_id,
9632 sysdate,
9633 fnd_global.login_id,
9634 1 /* 10 */
9635 )
9636 ;
9637
9638 x_return_status := FND_API.G_RET_STS_SUCCESS;
9639 print_debuginfo(l_module_name, 'EXIT');
9640
9641 EXCEPTION
9642 WHEN OTHERS THEN
9643
9644 print_debuginfo(l_module_name, 'Exception occured when '
9645 || 'inserting conc request id '
9646 || p_conc_request_id
9647 || ' into IBY_PROCESS_CONC_REQUESTS for object id '
9648 || p_object_id
9649 || ' with object type '
9650 || p_object_type
9651 || '.'
9652 );
9653
9654 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
9655 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
9656
9657 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
9658 x_return_status := FND_API.G_RET_STS_ERROR;
9659
9660 print_debuginfo(l_module_name, 'EXIT');
9661
9662 END insert_conc_request;
9663
9664 /*--------------------------------------------------------------------
9665 | NAME:
9666 | lock_pmt_entity
9667 |
9668 | PURPOSE:
9669 | Stamps the given payment entity with the given concurrent
9670 | request id to lock the entity.
9671 |
9672 | The IBY UI will not allow any follow on operation on a payment
9673 | entity that is locked.
9674 |
9675 | Locking/unlocking is the mechanism by which to preserve
9676 | data integrity of payment entities which are in transient
9677 | statuses.
9678 |
9679 | This method also inserts the provided concurrent request into
9680 | IBY_PROCESS_CONC_REQUESTS table for audit purposes.
9681 |
9682 | PARAMETERS:
9683 | IN
9684 | p_object_id The id of the payment entity. This can be
9685 | a payment id, a payment request id or a payment
9686 | instruction id.
9687 |
9688 | p_object_type The type of the payment entity. This can be
9689 | one of the following
9690 | PAYMENT
9691 | PAYMENT_REQUEST
9692 | PAYMENT_INSTRUCTION
9693 |
9694 | p_conc_request_id The concurrent request id to stamp the payment
9695 | entity with. If NULL is provided, the value of
9696 | FND_GLOBAL.CONC_REQUEST_ID will be used.
9697 |
9698 | OUT
9699 | x_return_status Return status (S, E, U)
9700 |
9701 | RETURNS:
9702 |
9703 | NOTES:
9704 | This method is implemented as an autonomous transaction
9705 | so that a COMMIT can be performed on the payment entity
9706 | without side effects on the main transaction.
9707 |
9708 *---------------------------------------------------------------------*/
9709 PROCEDURE lock_pmt_entity(
9710 p_object_id IN NUMBER,
9711 p_object_type IN VARCHAR2,
9712 p_conc_request_id IN NUMBER DEFAULT NULL,
9713 x_return_status IN OUT NOCOPY VARCHAR2
9714 )
9715 IS
9716 PRAGMA AUTONOMOUS_TRANSACTION;
9717
9718 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME|| '.lock_pmt_entity';
9719 l_conc_request_id NUMBER;
9720
9721 BEGIN
9722
9723 print_debuginfo(l_module_name, 'ENTER');
9724
9725 FND_MSG_PUB.initialize;
9726
9727 print_debuginfo(l_module_name, 'Input params - '
9728 || 'object id: '
9729 || p_object_id
9730 || ', object type: '
9731 || p_object_type
9732 );
9733
9734 /*
9735 * STEP 1:
9736 *
9737 * If the concurrent request id has not been provided,
9738 * derive it from the current context.
9739 */
9740 IF (p_conc_request_id IS NULL) THEN
9741
9742 print_debuginfo(l_module_name, 'Concurrent request id not '
9743 || 'provided. Deriving from context ..'
9744 );
9745
9746 l_conc_request_id := FND_GLOBAL.conc_request_id;
9747
9748 ELSE
9749
9750 print_debuginfo(l_module_name, 'Concurrent request id '
9751 || 'provided as input param: '
9752 || p_conc_request_id
9753 );
9754
9755 l_conc_request_id := p_conc_request_id;
9756
9757 END IF;
9758
9759 /*
9760 * STEP 2:
9761 *
9762 * Stamp the given entity with the provided concurrent request id.
9763 */
9764 IF (p_object_type = 'PAYMENT_REQUEST') THEN
9765
9766 UPDATE
9767 IBY_PAY_SERVICE_REQUESTS req
9768 SET
9769 req.request_id = l_conc_request_id
9770 WHERE
9771 req.payment_service_request_id = p_object_id
9772 ;
9773
9774 ELSIF (p_object_type = 'PAYMENT_INSTRUCTION') THEN
9775
9776 UPDATE
9777 IBY_PAY_INSTRUCTIONS_ALL inst
9778 SET
9779 inst.request_id = l_conc_request_id
9780 WHERE
9781 inst.payment_instruction_id = p_object_id
9782 ;
9783
9784 ELSIF (p_object_type = 'PAYMENT') THEN
9785
9786 UPDATE
9787 IBY_PAYMENTS_ALL pmt
9788 SET
9789 pmt.request_id = l_conc_request_id
9790 WHERE
9791 pmt.payment_id = p_object_id
9792 ;
9793
9794 ELSE
9795
9796 print_debuginfo(l_module_name, 'Unknown payment entity type '
9797 || p_object_type
9798 || ' provided. Raising exception .. '
9799 );
9800
9801 APP_EXCEPTION.RAISE_EXCEPTION;
9802
9803 END IF;
9804
9805 /*
9806 * STEP 3:
9807 *
9808 * Insert concurrent request into audit table.
9809 */
9810
9811 print_debuginfo(l_module_name, 'Inserting cp into audit table');
9812
9813 insert_conc_request(
9814 p_object_id,
9815 p_object_type,
9816 l_conc_request_id,
9817 'N',
9818 x_return_status
9819 );
9820
9821 print_debuginfo(l_module_name, 'Return status from '
9822 || 'insert_conc_request(..) call = '
9823 || x_return_status
9824 );
9825
9826
9827 IF (x_return_status IS NULL OR
9828 x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
9829
9830 print_debuginfo(l_module_name, 'Audit of conc request '
9831 || l_conc_request_id
9832 || ' failed. Returning error response .. '
9833 );
9834
9835 /*
9836 * Undo any database changes made in this method.
9837 */
9838 ROLLBACK;
9839
9840 print_debuginfo(l_module_name, 'EXIT');
9841 RETURN;
9842
9843 END IF;
9844
9845 /*
9846 * STEP 4:
9847 *
9848 * Finally, perform a COMMIT to lock the payment entity
9849 * with a concurrent request id.
9850 */
9851 COMMIT;
9852
9853 x_return_status := FND_API.G_RET_STS_SUCCESS;
9854 print_debuginfo(l_module_name, 'Returning success response ..');
9855
9856 print_debuginfo(l_module_name, 'EXIT');
9857
9858 EXCEPTION
9859 WHEN OTHERS THEN
9860
9861 print_debuginfo(l_module_name, 'Exception occured when locking '
9862 || 'pmt entity.');
9863
9864 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
9865 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
9866
9867 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
9868
9869 ROLLBACK;
9870
9871 x_return_status := FND_API.G_RET_STS_ERROR;
9872
9873 print_debuginfo(l_module_name, 'EXIT');
9874
9875 END lock_pmt_entity;
9876
9877 /*--------------------------------------------------------------------
9878 | NAME:
9879 | unlock_pmt_entity
9880 |
9881 | PURPOSE:
9882 | Nulls out the concurrent request id on given payment entity
9883 | to unlock the entity.
9884 |
9885 | The IBY UI will not allow any follow on operation on a payment
9886 | entity that is locked.
9887 |
9888 | Locking/unlocking is the mechanism by which to preserve
9889 | data integrity of payment entities which are in transient
9890 | statuses.
9891 |
9892 | PARAMETERS:
9893 | IN
9894 | p_object_id The id of the payment entity. This can be
9895 | a payment id, a payment request id or a payment
9896 | instruction id.
9897 |
9898 | p_object_type The type of the payment entity. This can be
9899 | one of the following
9900 | PAYMENT
9901 | PAYMENT_REQUEST
9902 | PAYMENT_INSTRUCTION
9903 |
9904 | OUT
9905 | x_return_status Return status (S, E, U)
9906 |
9907 | RETURNS:
9908 |
9909 | NOTES:
9910 | This method is implemented as an autonomous transaction
9911 | so that a COMMIT can be performed on the payment entity
9912 | without side effects on the main transaction.
9913 |
9914 *---------------------------------------------------------------------*/
9915 PROCEDURE unlock_pmt_entity(
9916 p_object_id IN NUMBER,
9917 p_object_type IN VARCHAR2,
9918 x_return_status IN OUT NOCOPY VARCHAR2
9919 )
9920 IS
9921 PRAGMA AUTONOMOUS_TRANSACTION;
9922
9923 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME|| '.unlock_pmt_entity';
9924
9925 BEGIN
9926
9927 print_debuginfo(l_module_name, 'ENTER');
9928
9929 print_debuginfo(l_module_name, 'Input params - '
9930 || 'object id: '
9931 || p_object_id
9932 || ', object type: '
9933 || p_object_type
9934 );
9935
9936 /*
9937 * STEP 1:
9938 *
9939 * Unstamp the given entity with the provided concurrent request id.
9940 */
9941 IF (p_object_type = 'PAYMENT_REQUEST') THEN
9942
9943 UPDATE
9944 IBY_PAY_SERVICE_REQUESTS req
9945 SET
9946 req.request_id = NULL
9947 WHERE
9948 req.payment_service_request_id = p_object_id
9949 ;
9950
9951 ELSIF (p_object_type = 'PAYMENT_INSTRUCTION') THEN
9952
9953 UPDATE
9954 IBY_PAY_INSTRUCTIONS_ALL inst
9955 SET
9956 inst.request_id = NULL
9957 WHERE
9958 inst.payment_instruction_id = p_object_id
9959 ;
9960
9961 ELSIF (p_object_type = 'PAYMENT') THEN
9962
9963 UPDATE
9964 IBY_PAYMENTS_ALL pmt
9965 SET
9966 pmt.request_id = NULL
9967 WHERE
9968 pmt.payment_id = p_object_id
9969 ;
9970
9971 ELSE
9972
9973 print_debuginfo(l_module_name, 'Unknown payment entity type '
9974 || p_object_type
9975 || ' provided. Raising exception .. '
9976 );
9977
9978 APP_EXCEPTION.RAISE_EXCEPTION;
9979
9980 END IF;
9981
9982 /*
9983 * STEP 3:
9984 *
9985 * Finally, perform a COMMIT to unlock the payment entity
9986 * with a concurrent request id.
9987 */
9988 COMMIT;
9989
9990 x_return_status := FND_API.G_RET_STS_SUCCESS;
9991 print_debuginfo(l_module_name, 'Returning success response ..');
9992
9993 print_debuginfo(l_module_name, 'EXIT');
9994
9995 EXCEPTION
9996 WHEN OTHERS THEN
9997
9998 print_debuginfo(l_module_name, 'Exception occured when unlocking '
9999 || 'pmt entity.');
10000
10001 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
10002 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
10003
10004 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
10005
10006 ROLLBACK;
10007
10008 x_return_status := FND_API.G_RET_STS_ERROR;
10009
10010 print_debuginfo(l_module_name, 'EXIT');
10011
10012 END unlock_pmt_entity;
10013
10014 /*--------------------------------------------------------------------
10015 | NAME:
10016 | populatePaymentFunctions
10017 |
10018 |
10019 | PURPOSE:
10020 | Populate the payment functions that user has access to
10021 |
10022 | PARAMETERS:
10023 | IN
10024 |
10025 |
10026 | OUT
10027 |
10028 |
10029 | RETURNS:
10030 |
10031 | NOTES:
10032 |
10033 *---------------------------------------------------------------------*/
10034 PROCEDURE populatePaymentFunctions(
10035 x_return_status IN OUT NOCOPY VARCHAR2,
10036 x_return_message IN OUT NOCOPY VARCHAR2) IS
10037
10038 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
10039 || '.populatePaymentFunctions';
10040 l_func varchar2(30);
10041 l_bool boolean;
10042 l_count number;
10043 cursor c_pay_function is
10044 select lookup_code
10045 from fnd_lookups
10046 where lookup_type='IBY_PAYMENT_FUNCTIONS';
10047
10048 begin
10049
10050 FND_MSG_PUB.initialize;
10051
10052 -- first check whether the payment function is populated or not
10053 begin
10054 select count(1)
10055 into l_count
10056 from IBY_USER_PAY_FUNS_GT;
10057 exception
10058 WHEN OTHERS THEN
10059
10060 /* now rows means success */
10061 print_debuginfo(l_module_name, 'Exception in select ');
10062 null;
10063 end;
10064
10065 if(l_count<>0) then
10066 x_return_status := FND_API.G_RET_STS_SUCCESS;
10067 return;
10068 end if;
10069
10070 OPEN c_pay_function;
10071 loop
10072 FETCH c_pay_function INTO l_func;
10073 exit when c_pay_function%NOTFOUND;
10074 -- check security
10075 l_bool := fnd_function.test_instance(
10076 'IBY_' || l_func,
10077 null,
10078 null,
10079 null,
10080 null,
10081 null,
10082 null,
10083 fnd_global.user_name);
10084
10085 if(l_bool) then
10086 --print_debuginfo(l_module_name, 'User has access to:' || l_func);
10087 insert into IBY_USER_PAY_FUNS_GT(payment_function)
10088 values(l_func);
10089 end if;
10090 end loop;
10091 close c_pay_function;
10092
10093 x_return_status := FND_API.G_RET_STS_SUCCESS;
10094 return;
10095 EXCEPTION
10096
10097 WHEN OTHERS THEN
10098 print_debuginfo(l_module_name, 'SQL err msg: '
10099 || SQLERRM);
10100 print_debuginfo(l_module_name, 'Returning failure response .. '
10101 );
10102 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
10103 /*
10104 * The error message would have already been set.
10105 * Just set the error status here.
10106 */
10107 x_return_status := FND_API.G_RET_STS_ERROR;
10108
10109 print_debuginfo(l_module_name, 'EXIT');
10110
10111 end populatePaymentFunctions;
10112
10113 /*--------------------------------------------------------------------
10114 | NAME:
10115 | checkUserAccess
10116 |
10117 |
10118 | PURPOSE:
10119 | Check whether the user has access to all the org. or payment function
10120 | of a particular object.
10121 |
10122 | PARAMETERS:
10123 | IN
10124 |
10125 |
10126 | OUT
10127 |
10128 |
10129 | RETURNS:
10130 |
10131 | NOTES:
10132 |
10133 *---------------------------------------------------------------------*/
10134 PROCEDURE checkUserAccess(
10135 p_object_id IN NUMBER,
10136 p_object_type IN VARCHAR2,
10137 x_access_flag IN OUT NOCOPY VARCHAR2,
10138 x_return_status IN OUT NOCOPY VARCHAR2,
10139 x_return_message IN OUT NOCOPY VARCHAR2)
10140 IS
10141 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
10142 || '.checkUserAccess';
10143
10144 l_function_count NUMBER:=0;
10145 l_org_count NUMBER:=0;
10146 l_msg_count NUMBER:=0;
10147 l_message_code VARCHAR2(30);
10148 begin
10149
10150 -- initiate the return parameter
10151 print_debuginfo(l_module_name, 'ENTER');
10152
10153 FND_MSG_PUB.initialize;
10154 populatePaymentFunctions(x_return_status, x_return_message);
10155 x_access_flag:='N';
10156
10157 /* Initialize return status */
10158 x_return_status := FND_API.G_RET_STS_SUCCESS;
10159
10160 select count(1)
10161 into l_function_count
10162 from iby_process_functions pfun
10163 where object_id=p_object_id
10164 and object_type=p_object_type
10165 and pfun.payment_function not in
10166 (select payment_function
10167 from IBY_USER_PAY_FUNS_GT
10168 );
10169 print_debuginfo(l_module_name, 'Number of Missing Payment Function:' ||l_function_count);
10170
10171 select count(1)
10172 into l_org_count
10173 from iby_process_orgs porg
10174 where object_id=p_object_id
10175 and object_type=p_object_type
10176 and porg.org_id not in
10177 (select organization_id
10178 from ce_security_profiles_v cep
10179 where cep.organization_type=porg.org_type
10180 );
10181 print_debuginfo(l_module_name, 'Number of Missing Org:' ||l_org_count);
10182
10183 -- check the user access
10184 if(l_function_count<>0 OR l_org_count <>0) THEN
10185
10186 print_debuginfo(l_module_name, 'User doesnt have full access to the payment request or payment instruction');
10187
10188 -- return error message for different object type
10189
10190 if(p_object_type='PAYMENT_REQUEST') then
10191 l_message_code :='IBY_FD_ACCESS_REQUEST_ERROR';
10192 else
10193 l_message_code :='IBY_FD_ACCESS_INSTR_ERROR';
10194
10195 end if;
10196
10197
10198 FND_MESSAGE.set_name('IBY', l_message_code);
10199 FND_MSG_PUB.add;
10200
10201 x_return_status := FND_API.G_RET_STS_ERROR;
10202
10203 FND_MSG_PUB.Count_And_Get(
10204 p_encoded => FND_API.G_FALSE,
10205 p_count => l_msg_count,
10206 p_data => x_return_message
10207 );
10208
10209 print_debuginfo(l_module_name, 'Returning error response ..');
10210 print_debuginfo(l_module_name, 'Error count:' || l_msg_count);
10211 print_debuginfo(l_module_name, 'Error Text:' || x_return_message);
10212 print_debuginfo(l_module_name, 'EXIT');
10213 end if;
10214
10215 EXCEPTION
10216 WHEN OTHERS THEN
10217 print_debuginfo(l_module_name, 'SQL err msg: '
10218 || SQLERRM);
10219 print_debuginfo(l_module_name, 'Returning failure response .. '
10220 );
10221 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
10222 /*
10223 * The error message would have already been set.
10224 * Just set the error status here.
10225 */
10226 x_return_status := FND_API.G_RET_STS_ERROR;
10227
10228 print_debuginfo(l_module_name, 'EXIT');
10229 end checkUserAccess;
10230
10231 /*--------------------------------------------------------------------
10232 | NAME:
10233 | checkIfAllPmtsTerminated
10234 |
10235 | PURPOSE:
10236 | Checks if all payments of a given payment instruction
10237 | have been terminated.
10238 |
10239 | PARAMETERS:
10240 | IN
10241 | p_instr_id - Payment instruction id to verify.
10242 |
10243 | OUT
10244 | NONE
10245 |
10246 | RETURNS:
10247 | TRUE - if all payments have been terminated.
10248 | FALSE - if at least one non-terminated payment exists.
10249 |
10250 | NOTES:
10251 |
10252 *---------------------------------------------------------------------*/
10253 FUNCTION checkIfAllPmtsTerminated(
10254 p_instr_id IN NUMBER
10255 ) RETURN BOOLEAN
10256 IS
10257
10258 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
10259 || '.checkIfAllPmtsTerminated';
10260
10261 l_flag BOOLEAN := FALSE;
10262
10263 l_all_pmts_count NUMBER;
10264 l_term_pmts_count NUMBER;
10265
10266 BEGIN
10267
10268 print_debuginfo(l_module_name, 'ENTER');
10269
10270 SELECT
10271 COUNT(*)
10272 INTO
10273 l_all_pmts_count
10274 FROM
10275 IBY_PAYMENTS_ALL pmt
10276 WHERE
10277 pmt.payment_instruction_id = p_instr_id
10278 ;
10279
10280
10281 print_debuginfo(l_module_name, 'Count of all payments in pmt instr '
10282 || p_instr_id
10283 || ' = '
10284 || l_all_pmts_count
10285 );
10286
10287 SELECT
10288 COUNT(*)
10289 INTO
10290 l_term_pmts_count
10291 FROM
10292 IBY_PAYMENTS_ALL pmt
10293 WHERE
10294 pmt.payment_instruction_id = p_instr_id
10295 AND
10296 pmt.payment_status = PAY_STATUS_REQ_TERM
10297 ;
10298
10299 print_debuginfo(l_module_name, 'Count of terminated payments in '
10300 || 'pmt instr '
10301 || p_instr_id
10302 || ' = '
10303 || l_all_pmts_count
10304 );
10305
10306 /*
10307 * If all payments have been terminated return TRUE.
10308 */
10309 IF (l_all_pmts_count = l_term_pmts_count) THEN
10310
10311 print_debuginfo(l_module_name, 'All payments in pmt instr '
10312 || p_instr_id
10313 || ' have been terminated. Returning TRUE.'
10314 );
10315
10316 l_flag := TRUE;
10317
10318 ELSE
10319
10320 print_debuginfo(l_module_name, 'At least one payment in pmt instr '
10321 || p_instr_id
10322 || ' has not been terminated. Returning FALSE.'
10323 );
10324
10325 l_flag := FALSE;
10326
10327 END IF;
10328
10329 print_debuginfo(l_module_name, 'EXIT');
10330
10331 RETURN l_flag;
10332
10333 EXCEPTION
10334
10335 WHEN OTHERS THEN
10336
10337 print_debuginfo(l_module_name, 'Exception occured when '
10338 || 'checking if all pmts of pmt instruction '
10339 || p_instr_id
10340 || ' were terminated.'
10341 );
10342
10343 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
10344 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
10345
10346 l_flag := FALSE;
10347 print_debuginfo(l_module_name, 'Returning FALSE.');
10348 print_debuginfo(l_module_name, 'EXIT');
10349
10350 RETURN l_flag;
10351
10352 END checkIfAllPmtsTerminated;
10353
10354 /*--------------------------------------------------------------------
10355 | NAME:
10356 | checkIfPmtInInstExists
10357 |
10358 | PURPOSE:
10359 | Checks if all payments of a given payment instruction
10360 | have been terminated.
10361 |
10362 | PARAMETERS:
10363 | IN
10364 | p_payreq_id - Payment request to verify.
10365 |
10366 | OUT
10367 | NONE
10368 |
10369 | RETURNS:
10370 | TRUE - if at least one payment of the ppr is part of
10371 | an instruction.
10372 | FALSE - if none of the payments of the ppr are part of
10373 | an instruction.
10374 |
10375 | NOTES:
10376 | This method is meant exclusively to be used by the
10377 | terminate_pmt_request(..) API. Do not use call this
10378 | method for other general purposes.
10379 |
10380 |
10381 | -- IMPORTANT --
10382 | This method locks rows in the IBY_PAYMENTS_ALL table and
10383 | expects that the caller will commit/rollback to release lock.
10384 |
10385 *---------------------------------------------------------------------*/
10386 FUNCTION checkIfPmtInInstExists(
10387 p_payreq_id IN NUMBER
10388 ) RETURN BOOLEAN
10389 IS
10390
10391 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
10392 || '.checkIfPmtInInstExists';
10393
10394 l_flag BOOLEAN := FALSE;
10395 l_test VARCHAR2(200);
10396
10397 l_all_pmts_count NUMBER;
10398 l_term_pmts_count NUMBER;
10399
10400 BEGIN
10401
10402 print_debuginfo(l_module_name, 'ENTER');
10403
10404 /*
10405 * This method is called by terminate_pmt_request(..)
10406 * to check if any of the payments are part of a payment
10407 * instruction.
10408 *
10409 * TIME T1: This method returns FALSE
10410 * implying that none of the
10411 * payments of the ppr are part
10412 * of any payment instruction.
10413 *
10414 * TIME T2: PICP runs and picks up payments
10415 * of which some payments are from this
10416 * ppr.
10417 *
10418 * TIME T3: terminate_pmt_request(..) terminates
10419 * a ppr based on the return value of
10420 * this method. Now, we have an payment
10421 * instruction that contains a payment
10422 * from this ppr that has been terminated.
10423 * This situation is wrong and should never
10424 * occur.
10425 *
10426 * To prevent this situation, we lock the payments
10427 * table first, before attempting to terminate
10428 * a ppr.
10429 *
10430 * This lock will get released when the UI peforms a
10431 * COMMIT / ROLLBACK action based on the return value
10432 * of the terminate_pmt_request(..) API.
10433 */
10434
10435 /*
10436 * Instead of locking the entire table only lock the
10437 * rows that we are interested in (explicit locking).
10438 */
10439 -- LOCK TABLE IBY_PAYMENTS_ALL IN EXCLUSIVE MODE;
10440
10441 SELECT
10442 pmt.payment_id
10443 INTO
10444 l_test
10445 FROM
10446 IBY_PAYMENTS_ALL pmt
10447 WHERE
10448 pmt.payment_instruction_id IS NOT NULL
10449 AND
10450 pmt.payment_service_request_id = p_payreq_id
10451 FOR UPDATE
10452 ;
10453
10454 /*
10455 * Now check whether the payments of this request
10456 * are linked to any payment instructions.
10457 */
10458 SELECT
10459 'TRUE'
10460 INTO
10461 l_test
10462 FROM
10463 DUAL
10464 WHERE
10465 EXISTS
10466 (
10467 SELECT
10468 pmt.payment_id
10469 FROM
10470 IBY_PAYMENTS_ALL pmt
10471 WHERE
10472 pmt.payment_instruction_id IS NOT NULL
10473 AND
10474 pmt.payment_service_request_id = p_payreq_id
10475 )
10476 ;
10477
10478 IF (l_test = 'TRUE') THEN
10479 l_flag := TRUE;
10480 print_debuginfo(l_module_name, 'Returning flag as TRUE.');
10481 ELSE
10482 l_flag := FALSE;
10483 print_debuginfo(l_module_name, 'Returning flag as FALSE.');
10484 END IF;
10485
10486 print_debuginfo(l_module_name, 'EXIT');
10487
10488 RETURN l_flag;
10489
10490 EXCEPTION
10491
10492 WHEN NO_DATA_FOUND THEN
10493
10494 print_debuginfo(l_module_name, 'Payment request id '
10495 || p_payreq_id
10496 || ' does not contain any payments.'
10497 );
10498
10499 /*
10500 * This ppr only contains documents and no payments.
10501 *
10502 * Therefore, allow this ppr to be terminated by
10503 * returning FALSE.
10504 */
10505 l_flag := FALSE;
10506 print_debuginfo(l_module_name, 'Returning FALSE.');
10507 print_debuginfo(l_module_name, 'EXIT');
10508
10509 RETURN l_flag;
10510
10511 WHEN OTHERS THEN
10512
10513 print_debuginfo(l_module_name, 'Exception occured when '
10514 || 'checking if any pmts of pmt request '
10515 || p_payreq_id
10516 || ' were part of a pmt instruction.'
10517 );
10518
10519 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
10520 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
10521
10522 /*
10523 * In case of an exception, play safe and return TRUE.
10524 *
10525 * The terminate_pmt_request(..) API will not allow the
10526 * request to be terminated.
10527 */
10528 l_flag := TRUE;
10529 print_debuginfo(l_module_name, 'Returning TRUE.');
10530 print_debuginfo(l_module_name, 'EXIT');
10531
10532 RETURN l_flag;
10533
10534 END checkIfPmtInInstExists;
10535
10536 /*--------------------------------------------------------------------
10537 | NAME:
10538 | finalize_electronic_instr
10539 |
10540 |
10541 | PURPOSE:
10542 |
10543 |
10544 | PARAMETERS:
10545 | IN
10546 |
10547 |
10548 | OUT
10549 |
10550 |
10551 | RETURNS:
10552 |
10553 | NOTES:
10554 | Internal API, not for public use.
10555 |
10556 *---------------------------------------------------------------------*/
10557 PROCEDURE finalize_electronic_instr(
10558 p_instr_id IN NUMBER,
10559 x_return_status IN OUT NOCOPY VARCHAR2
10560 )
10561 IS
10562
10563 l_module_name CONSTANT VARCHAR2(200)
10564 := G_PKG_NAME ||
10565 '.finalize_electronic_instr';
10566
10567 l_flag BOOLEAN := FALSE;
10568
10569 BEGIN
10570
10571 print_debuginfo(l_module_name, 'ENTER');
10572 FND_MSG_PUB.initialize;
10573
10574 /*
10575 * STEP 1:
10576 *
10577 * Check if payment instruction transmission is outside
10578 * the system.
10579 *
10580 * Update the payment instruction and payment statuses
10581 * to final statuses accordingly.
10582 */
10583 l_flag := checkIfInstrXmitOutsideSystem(p_instr_id);
10584
10585 IF (l_flag = TRUE) THEN
10586
10587 UPDATE
10588 IBY_PAY_INSTRUCTIONS_ALL inst
10589 SET
10590 inst.payment_instruction_status = INS_STATUS_FORMATTED_ELEC
10591 WHERE
10592 inst.payment_instruction_id = p_instr_id
10593 ;
10594
10595 UPDATE
10596 IBY_PAYMENTS_ALL pmt
10597 SET
10598 pmt.payment_status = PAY_STATUS_FORMATTED
10599 WHERE
10600 pmt.payment_instruction_id = p_instr_id
10601 ;
10602
10603 ELSE
10604
10605 UPDATE
10606 IBY_PAY_INSTRUCTIONS_ALL inst
10607 SET
10608 inst.payment_instruction_status = INS_STATUS_TRANSMITTED
10609 WHERE
10610 inst.payment_instruction_id = p_instr_id
10611 ;
10612
10613 UPDATE
10614 IBY_PAYMENTS_ALL pmt
10615 SET
10616 pmt.payment_status = PAY_STATUS_TRANSMITTED
10617 WHERE
10618 pmt.payment_instruction_id = p_instr_id
10619 ;
10620
10621 END IF;
10622
10623 /*
10624 * STEP 2:
10625 *
10626 * Mark the payment instruction and payments complete.
10627 */
10628 print_debuginfo(l_module_name,
10629 'Invoking mark payments complete API ..');
10630
10631 mark_all_pmts_complete(p_instr_id, x_return_status);
10632
10633 print_debuginfo(l_module_name, 'Returning status: '
10634 || x_return_status
10635 );
10636
10637 print_debuginfo(l_module_name, 'EXIT');
10638
10639 EXCEPTION
10640 WHEN OTHERS THEN
10641
10642 print_debuginfo(l_module_name, 'Exception occured when '
10643 || 'finalizing electronic payment instruction '
10644 || p_instr_id
10645 || '.'
10646 );
10647
10648 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
10649 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
10650
10651 x_return_status := FND_API.G_RET_STS_ERROR;
10652
10653 print_debuginfo(l_module_name, 'Returning error status: '
10654 || x_return_status
10655 );
10656 print_debuginfo(l_module_name, 'EXIT');
10657
10658 END finalize_electronic_instr;
10659
10660 /*--------------------------------------------------------------------
10661 | NAME:
10662 | checkIfInstrXmitOutsideSystem
10663 |
10664 |
10665 | PURPOSE:
10666 |
10667 |
10668 | PARAMETERS:
10669 | IN
10670 |
10671 |
10672 | OUT
10673 |
10674 |
10675 | RETURNS:
10676 |
10677 | NOTES:
10678 | Internal API, not for public use.
10679 |
10680 *---------------------------------------------------------------------*/
10681 FUNCTION checkIfInstrXmitOutsideSystem(
10682 p_instr_id IN NUMBER
10683 ) RETURN BOOLEAN
10684 IS
10685
10686 l_module_name CONSTANT VARCHAR2(200)
10687 := G_PKG_NAME
10688 || '.checkIfInstrXmitOutsideSystem';
10689
10690 l_flag BOOLEAN := FALSE;
10691 l_test VARCHAR2(200);
10692
10693 BEGIN
10694
10695 print_debuginfo(l_module_name, 'ENTER');
10696
10697 /*
10698 * If the transmit configuration id linked to the profile
10699 * on a payment instruction is null, it means that transmit
10700 * configuration has not been set up for that profile.
10701 *
10702 * This implies that the payment instruction needs to be
10703 * transmitted outside the system (i.e., using an external
10704 * application).
10705 */
10706 SELECT
10707 'TRUE'
10708 INTO
10709 l_test
10710 FROM
10711 DUAL
10712 WHERE
10713 EXISTS
10714 (
10715 SELECT
10716 instr.payment_instruction_id
10717 FROM
10718 IBY_PAY_INSTRUCTIONS_ALL instr,
10719 IBY_PAYMENT_PROFILES prof
10720 WHERE
10721 instr.payment_instruction_id = p_instr_id
10722 AND
10723 prof.payment_profile_id = instr.payment_profile_id
10724 AND
10725 prof.transmit_configuration_id IS NULL
10726 )
10727 ;
10728
10729 IF (l_test = 'TRUE') THEN
10730 l_flag := TRUE;
10731 print_debuginfo(l_module_name, 'Transmission is outside the system.');
10732 print_debuginfo(l_module_name, 'Returning flag as TRUE.');
10733 ELSE
10734 l_flag := FALSE;
10735 print_debuginfo(l_module_name, 'Transmission is inside the system.');
10736 print_debuginfo(l_module_name, 'Returning flag as FALSE.');
10737 END IF;
10738
10739 print_debuginfo(l_module_name, 'EXIT');
10740
10741 RETURN l_flag;
10742
10743 EXCEPTION
10744
10745 WHEN OTHERS THEN
10746
10747 print_debuginfo(l_module_name, 'Exception occured when '
10748 || 'checking if instruction '
10749 || p_instr_id
10750 || ' needs to be transmitted using external system(s).'
10751 );
10752
10753 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
10754 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
10755
10756 /*
10757 * In case of an exception, play safe and return TRUE.
10758 *
10759 * The user will have to transmit the payment instruction
10760 * outside of IBY using some external application.
10761 */
10762 l_flag := TRUE;
10763 print_debuginfo(l_module_name, 'Transmission will have to be '
10764 || 'outside the system (irrespective of setting).');
10765 print_debuginfo(l_module_name, 'Returning TRUE.');
10766 print_debuginfo(l_module_name, 'EXIT');
10767
10768 RETURN l_flag;
10769
10770 END checkIfInstrXmitOutsideSystem;
10771
10772 /*--------------------------------------------------------------------
10773 | NAME:
10774 | checkIfPmtEntityLocked
10775 |
10776 |
10777 | PURPOSE:
10778 | Checks if a given payment entity is locked (i.e., stamped
10779 | with a concurrent request id).
10780 |
10781 | PARAMETERS:
10782 | IN
10783 |
10784 |
10785 | OUT
10786 |
10787 |
10788 | RETURNS:
10789 |
10790 | NOTES:
10791 | Internal API, not for public use.
10792 |
10793 *---------------------------------------------------------------------*/
10794 FUNCTION checkIfPmtEntityLocked(
10795 p_object_id IN NUMBER,
10796 p_object_type IN VARCHAR2
10797 ) RETURN BOOLEAN
10798 IS
10799 l_module_name CONSTANT VARCHAR2(200)
10800 := G_PKG_NAME || '.checkIfPmtEntityLocked';
10801
10802 l_flag BOOLEAN := FALSE;
10803 l_test VARCHAR2(200);
10804
10805 BEGIN
10806
10807 print_debuginfo(l_module_name, 'ENTER');
10808
10809 IF (p_object_type = 'PAYMENT_REQUEST') THEN
10810
10811 SELECT
10812 'TRUE'
10813 INTO
10814 l_test
10815 FROM
10816 DUAL
10817 WHERE
10818 EXISTS
10819 (
10820 SELECT
10821 req.payment_service_request_id
10822 FROM
10823 IBY_PAY_SERVICE_REQUESTS req
10824 WHERE
10825 req.payment_service_request_id = p_object_id
10826 AND
10827 req.request_id IS NOT NULL
10828 )
10829 ;
10830
10831 ELSIF (p_object_type = 'PAYMENT_INSTRUCTION') THEN
10832
10833 SELECT
10834 'TRUE'
10835 INTO
10836 l_test
10837 FROM
10838 DUAL
10839 WHERE
10840 EXISTS
10841 (
10842 SELECT
10843 inst.payment_instruction_id
10844 FROM
10845 IBY_PAY_INSTRUCTIONS_ALL inst
10846 WHERE
10847 inst.payment_instruction_id = p_object_id
10848 AND
10849 inst.request_id IS NOT NULL
10850 )
10851 ;
10852
10853 ELSIF (p_object_type = 'PAYMENT') THEN
10854
10855 SELECT
10856 'TRUE'
10857 INTO
10858 l_test
10859 FROM
10860 DUAL
10861 WHERE
10862 EXISTS
10863 (
10864 SELECT
10865 pmt.payment_id
10866 FROM
10867 IBY_PAYMENTS_ALL pmt
10868 WHERE
10869 pmt.payment_id = p_object_id
10870 AND
10871 pmt.request_id IS NOT NULL
10872 )
10873 ;
10874
10875 ELSE
10876
10877 print_debuginfo(l_module_name, 'Unknown payment entity type '
10878 || p_object_type
10879 || ' provided. Raising exception .. '
10880 );
10881
10882 APP_EXCEPTION.RAISE_EXCEPTION;
10883
10884 END IF;
10885
10886 IF (l_test = 'TRUE') THEN
10887 l_flag := TRUE;
10888 print_debuginfo(l_module_name, 'Returning flag as TRUE.');
10889 ELSE
10890 l_flag := FALSE;
10891 print_debuginfo(l_module_name, 'Returning flag as FALSE.');
10892 END IF;
10893
10894 print_debuginfo(l_module_name, 'EXIT');
10895
10896 RETURN l_flag;
10897
10898 EXCEPTION
10899
10900 /*
10901 * Fix for bug 5195694:
10902 *
10903 * If no row was found, it means that the
10904 * payment entity is not locked.
10905 */
10906 WHEN NO_DATA_FOUND THEN
10907
10908 print_debuginfo(l_module_name, 'Pmt entity id '
10909 || p_object_id
10910 || ' of type '
10911 || p_object_type
10912 || ' is not locked.'
10913 );
10914
10915 l_flag := FALSE;
10916 print_debuginfo(l_module_name, 'Returning FALSE.');
10917 print_debuginfo(l_module_name, 'EXIT');
10918
10919 RETURN l_flag;
10920
10921 WHEN OTHERS THEN
10922
10923 print_debuginfo(l_module_name, 'Exception occured when '
10924 || 'checking if pmt entity id '
10925 || p_object_id
10926 || ' of type '
10927 || p_object_type
10928 || ' is locked.'
10929 );
10930
10931 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
10932 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
10933
10934 /*
10935 * In case of an exception, play safe and return TRUE.
10936 *
10937 * The user will assume that the pmt entity is locked.
10938 */
10939 l_flag := TRUE;
10940 print_debuginfo(l_module_name, 'Treating payment entity as locked.');
10941 print_debuginfo(l_module_name, 'Returning TRUE.');
10942 print_debuginfo(l_module_name, 'EXIT');
10943
10944 RETURN l_flag;
10945
10946 END checkIfPmtEntityLocked;
10947
10948 -- The procedure to submit a request set
10949 /*--------------------------------------------------------------------
10950 | NAME:
10951 | submit_masking_req_set
10952 |
10953 |
10954 | PURPOSE:
10955 |
10956 | PARAMETERS:
10957 | IN
10958 |
10959 |
10960 | OUT
10961 |
10962 |
10963 | RETURNS:
10964 |
10965 | NOTES:
10966 |
10967 *---------------------------------------------------------------------*/
10968 PROCEDURE submit_masking_req_set (
10969 x_request_id OUT NOCOPY NUMBER,
10970 x_return_status OUT NOCOPY VARCHAR2,
10971 x_msg_count OUT NOCOPY NUMBER,
10972 x_msg_data OUT NOCOPY VARCHAR2
10973 ) IS
10974 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME || '.submit_masking_req_set';
10975
10976 l_api_version CONSTANT NUMBER := 1.0;
10977 l_msg_count NUMBER;
10978 l_msg_data VARCHAR2(2000);
10979
10980 l_phase VARCHAR2(200);
10981 l_success BOOLEAN;
10982 submit_failed EXCEPTION;
10983
10984 BEGIN
10985 print_debuginfo(l_module_name, 'ENTER');
10986
10987 x_return_status := FND_API.G_RET_STS_SUCCESS;
10988 FND_MSG_PUB.initialize;
10989
10990 /* set the context for the request set IBY_SECURITY_MASKING_REQ_SET */
10991 l_success := fnd_submit.set_request_set('IBY', 'IBY_SECURITY_MASKING_REQ_SET');
10992 l_phase := 'After set request set.';
10993
10994 if ( l_success ) then
10995
10996 /* submit program IBY_CREDITCARD_MASKING which is in stage STAGE1 */
10997 l_success := fnd_submit.submit_program('IBY','IBY_CREDITCARD_MASKING', 'STAGE1',
10998 '','','','','','','','','','','','','','','','','','','','',
10999 '','','','','','','','','','','','','','','','','','','','',
11000 '','','','','','','','','','','','','','','','','','','','',
11001 '','','','','','','','','','','','','','','','','','','','',
11002 '','','','','','','','','','','','','','','','','','','','');
11003 l_phase := 'After submit program 1.';
11004 if ( not l_success ) then
11005 raise submit_failed;
11006 end if;
11007
11008 /* submit program IBY_EXT_BANKACCT_MASKING which is in stage STAGE1 */
11009 l_success := fnd_submit.submit_program('IBY','IBY_EXT_BANKACCT_MASKING', 'STAGE1',
11010 '','','','','','','','','','','','','','','','','','','','',
11011 '','','','','','','','','','','','','','','','','','','','',
11012 '','','','','','','','','','','','','','','','','','','','',
11013 '','','','','','','','','','','','','','','','','','','','',
11014 '','','','','','','','','','','','','','','','','','','','');
11015 l_phase := 'After submit program 2.';
11016 if ( not l_success ) then
11017 raise submit_failed;
11018 end if;
11019
11020 /* Submit the Request set */
11021 x_request_id := fnd_submit.submit_set(null,FALSE);
11022 l_phase := 'After submit request set.';
11023
11024 else
11025 l_phase := 'Failed after set request set.';
11026 raise submit_failed;
11027 end if;
11028 EXCEPTION
11029 WHEN submit_failed THEN
11030 x_return_status := FND_API.G_RET_STS_ERROR;
11031 print_debuginfo(l_module_name, 'Exception submit_failed - ' || l_phase);
11032 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
11033
11034 WHEN others THEN
11035 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
11036 print_debuginfo(l_module_name, 'Exception others.');
11037 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
11038 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
11039 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
11040
11041 END submit_masking_req_set;
11042
11043 -- The procedure to submit a request set
11044 /*--------------------------------------------------------------------
11045 | NAME:
11046 | submit_decrypt_req_set
11047 |
11048 |
11049 | PURPOSE:
11050 |
11051 | PARAMETERS:
11052 | IN
11053 |
11054 |
11055 | OUT
11056 |
11057 |
11058 | RETURNS:
11059 |
11060 | NOTES:
11061 |
11062 *---------------------------------------------------------------------*/
11063 PROCEDURE submit_decrypt_req_set (
11064 x_request_id OUT NOCOPY NUMBER,
11065 x_return_status OUT NOCOPY VARCHAR2,
11066 x_msg_count OUT NOCOPY NUMBER,
11067 x_msg_data OUT NOCOPY VARCHAR2
11068 ) IS
11069 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME || '.submit_decrypt_req_set';
11070
11071 l_api_version CONSTANT NUMBER := 1.0;
11072 l_msg_count NUMBER;
11073 l_msg_data VARCHAR2(2000);
11074
11075 l_phase VARCHAR2(200);
11076 l_success BOOLEAN;
11077 submit_failed EXCEPTION;
11078
11079 BEGIN
11080 print_debuginfo(l_module_name, 'ENTER');
11081
11082 x_return_status := FND_API.G_RET_STS_SUCCESS;
11083 FND_MSG_PUB.initialize;
11084
11085 /* set the context for the request set IBY_SECURITY_DECRYPT_REQ_SET */
11086 l_success := fnd_submit.set_request_set('IBY', 'IBY_SECURITY_DECRYPT_REQ_SET');
11087 l_phase := 'After set request set.';
11088
11089 if ( l_success ) then
11090
11091 /* submit program IBY_CREDITCARD_DECRYPTION which is in stage STAGE1 */
11092 l_success := fnd_submit.submit_program('IBY','IBY_CREDITCARD_DECRYPTION', 'STAGE1',
11093 '','','','','','','','','','','','','','','','','','','','',
11094 '','','','','','','','','','','','','','','','','','','','',
11095 '','','','','','','','','','','','','','','','','','','','',
11096 '','','','','','','','','','','','','','','','','','','','',
11097 '','','','','','','','','','','','','','','','','','','','');
11098 l_phase := 'After submit program 1.';
11099 if ( not l_success ) then
11100 raise submit_failed;
11101 end if;
11102
11103 /* submit program IBY_EXT_BANKACCT_DECRYPTION which is in stage STAGE1 */
11104 l_success := fnd_submit.submit_program('IBY','IBY_EXT_BANKACCT_DECRYPTION', 'STAGE1',
11105 '','','','','','','','','','','','','','','','','','','','',
11106 '','','','','','','','','','','','','','','','','','','','',
11107 '','','','','','','','','','','','','','','','','','','','',
11108 '','','','','','','','','','','','','','','','','','','','',
11109 '','','','','','','','','','','','','','','','','','','','');
11110 l_phase := 'After submit program 2.';
11111 if ( not l_success ) then
11112 raise submit_failed;
11113 end if;
11114
11115 /* submit program IBY_TRXN_EXTENSION_DECRYPTION which is in stage STAGE1 */
11116 l_success := fnd_submit.submit_program('IBY','IBY_TRXN_EXTENSION_DECRYPTION', 'STAGE1',
11117 '','','','','','','','','','','','','','','','','','','','',
11118 '','','','','','','','','','','','','','','','','','','','',
11119 '','','','','','','','','','','','','','','','','','','','',
11120 '','','','','','','','','','','','','','','','','','','','',
11121 '','','','','','','','','','','','','','','','','','','','');
11122 l_phase := 'After submit program 3.';
11123 if ( not l_success ) then
11124 raise submit_failed;
11125 end if;
11126
11127 /* submit program IBY_TX_CREDITCARD_DECRYPTION which is in stage STAGE1 */
11128 l_success := fnd_submit.submit_program('IBY','IBY_TX_CREDITCARD_DECRYPTION', 'STAGE1',
11129 '','','','','','','','','','','','','','','','','','','','',
11130 '','','','','','','','','','','','','','','','','','','','',
11131 '','','','','','','','','','','','','','','','','','','','',
11132 '','','','','','','','','','','','','','','','','','','','',
11133 '','','','','','','','','','','','','','','','','','','','');
11134 l_phase := 'After submit program 4.';
11135 if ( not l_success ) then
11136 raise submit_failed;
11137 end if;
11138
11139 /* Submit the Request set */
11140 x_request_id := fnd_submit.submit_set(null,FALSE);
11141 l_phase := 'After submit request set.';
11142
11143 else
11144 l_phase := 'Failed after set request set.';
11145 raise submit_failed;
11146 end if;
11147 EXCEPTION
11148 WHEN submit_failed THEN
11149 x_return_status := FND_API.G_RET_STS_ERROR;
11150 print_debuginfo(l_module_name, 'Exception submit_failed - ' || l_phase);
11151 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
11152
11153 WHEN others THEN
11154 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
11155 print_debuginfo(l_module_name, 'Exception others.');
11156 print_debuginfo(l_module_name, 'SQL code: ' || SQLCODE);
11157 print_debuginfo(l_module_name, 'SQL err msg: '|| SQLERRM);
11158 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
11159
11160 END submit_decrypt_req_set;
11161
11162 /*--------------------------------------------------------------------
11163 | NAME:
11164 | get_conc_request_status
11165 |
11166 | PURPOSE:
11167 | Get the concurrent request id status using the FND API.
11168 |
11169 | PARAMETERS:
11170 | IN x_request_id
11171 |
11172 | RETURNS: x_request_status (SUCCESS, ERROR, PENDING)
11173 |
11174 | NOTES:
11175 | Internal API, not for public use.
11176 | This API is used by the FD Dashboard to determine if a request
11177 | has terminated with error.
11178 |
11179 *---------------------------------------------------------------------*/
11180 FUNCTION get_conc_request_status (
11181 x_request_id IN NUMBER)
11182 RETURN VARCHAR2 AS
11183
11184 v_call_status BOOLEAN;
11185 v_req_phase_t VARCHAR2(80);
11186 v_req_status_t VARCHAR2(80);
11187 v_req_phase_c VARCHAR2(30);
11188 v_req_status_c VARCHAR2(30);
11189 v_message VARCHAR2(240);
11190 v_request_id iby_payments_all.request_id%TYPE;
11191
11192 x_return_status VARCHAR2(30) := 'PENDING';
11193
11194 BEGIN
11195 IF (x_request_id IS NOT NULL) THEN
11196 v_request_id := x_request_id;
11197 -- call FND API to get request status
11198 v_call_status := FND_CONCURRENT.get_request_status(
11199 v_request_id,
11200 null, null,
11201 v_req_phase_t, v_req_status_t,
11202 v_req_phase_c, v_req_status_c,
11203 v_message);
11204
11205 IF (v_call_status) THEN
11206 IF (v_req_phase_c = 'COMPLETE') THEN
11207 IF (v_req_status_c IN ('ERROR', 'CANCELLED', 'TERMINATED')) THEN
11208 x_return_status := 'ERROR';
11209 END IF;
11210 END IF;
11211 ELSE
11212 x_return_status := 'ERROR';
11213 END IF;
11214 ELSE
11215 x_return_status := 'SUCCESS';
11216 END IF;
11217
11218 RETURN x_return_status;
11219 END get_conc_request_status;
11220
11221 /*--------------------------------------------------------------------
11222 | NAME:
11223 | print_completed_pmts
11224 |
11225 |
11226 | PURPOSE:
11227 | Prints list of payments marked complete using the provided
11228 | completion group id.
11229 |
11230 | This function is used for debugging purposes.
11231 |
11232 | PARAMETERS:
11233 | IN
11234 |
11235 |
11236 | OUT
11237 |
11238 |
11239 | RETURNS:
11240 |
11241 | NOTES:
11242 | Internal API, not for public use.
11243 |
11244 *---------------------------------------------------------------------*/
11245 PROCEDURE print_completed_pmts(
11246 p_completion_id IN NUMBER
11247 )
11248 IS
11249 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
11250 || '.print_completed_pmts';
11251
11252 l_pmts_list pmtIDTab;
11253
11254 /*
11255 * Cursor to pick up all payment ids associated with the
11256 * provided completion id.
11257 */
11258 CURSOR c_pmt_ids (p_complete_id NUMBER)
11259 IS
11260 SELECT
11261 pmt.payment_id
11262 FROM
11263 IBY_PAYMENTS_ALL pmt
11264 WHERE
11265 pmt.completed_pmts_group_id = p_complete_id
11266 ;
11267
11268 BEGIN
11269
11270 print_debuginfo(l_module_name, 'ENTER');
11271 print_debuginfo(l_module_name, 'completion id: ' || p_completion_id);
11272
11273 FND_MSG_PUB.initialize;
11274
11275 OPEN c_pmt_ids (p_completion_id);
11276 FETCH c_pmt_ids BULK COLLECT INTO l_pmts_list;
11277 CLOSE c_pmt_ids;
11278
11279 IF (l_pmts_list.COUNT > 0) THEN
11280
11281 print_debuginfo(l_module_name, 'List of completed payments - ');
11282
11283 FOR i IN l_pmts_list.FIRST .. l_pmts_list.LAST LOOP
11284
11285 print_debuginfo(l_module_name, 'pmt id: ' || l_pmts_list(i));
11286
11287 END LOOP;
11288
11289 ELSE
11290
11291 print_debuginfo(l_module_name, 'No completed payments '
11292 || 'were retrieved using completion id '
11293 || p_completion_id
11294 );
11295
11296 END IF;
11297
11298 print_debuginfo(l_module_name, 'EXIT');
11299
11300 EXCEPTION
11301 WHEN OTHERS THEN
11302
11303 /*
11304 * This is a non-fatal exception. We will log the exception
11305 * and return.
11306 */
11307 print_debuginfo(l_module_name, 'Non-Fatal: Exception occured '
11308 || 'when trying to print completed payments using '
11309 || 'completion id: '
11310 || p_completion_id
11311 );
11312
11313 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
11314 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
11315 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
11316
11317 END print_completed_pmts;
11318
11319
11320 /*--------------------------------------------------------------------
11321 | NAME:
11322 | print_completed_docs
11323 |
11324 |
11325 | PURPOSE:
11326 | Prints list of documents payable marked complete using the
11327 | provided completion group id.
11328 |
11329 | This function is used for debugging purposes.
11330 |
11331 | PARAMETERS:
11332 | IN
11333 |
11334 |
11335 | OUT
11336 |
11337 |
11338 | RETURNS:
11339 |
11340 | NOTES:
11341 | Internal API, not for public use.
11342 |
11343 *---------------------------------------------------------------------*/
11344 PROCEDURE print_completed_docs(
11345 p_completion_id IN NUMBER
11346 )
11347 IS
11348 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
11349 || '.print_completed_docs';
11350
11351 l_docs_list docPayIDTab;
11352
11353 /*
11354 * Cursor to pick up all document ids associated with the
11355 * provided completion id.
11356 */
11357 CURSOR c_doc_ids (p_complete_id NUMBER)
11358 IS
11359 SELECT
11360 doc.document_payable_id
11361 FROM
11362 IBY_DOCS_PAYABLE_ALL doc
11363 WHERE
11364 doc.completed_pmts_group_id = p_complete_id
11365 ;
11366
11367 BEGIN
11368
11369 print_debuginfo(l_module_name, 'ENTER');
11370 print_debuginfo(l_module_name, 'completion id: ' || p_completion_id);
11371
11372 FND_MSG_PUB.initialize;
11373
11374 OPEN c_doc_ids (p_completion_id);
11375 FETCH c_doc_ids BULK COLLECT INTO l_docs_list;
11376 CLOSE c_doc_ids;
11377
11378 IF (l_docs_list.COUNT > 0) THEN
11379
11380 print_debuginfo(l_module_name, 'List of completed documents - ');
11381
11382 FOR i IN l_docs_list.FIRST .. l_docs_list.LAST LOOP
11383
11384 print_debuginfo(l_module_name, 'doc id: ' || l_docs_list(i));
11385
11386 END LOOP;
11387
11388 ELSE
11389
11390 print_debuginfo(l_module_name, 'No completed documents '
11391 || 'were retrieved using completion id '
11392 || p_completion_id
11393 );
11394
11395 END IF;
11396
11397 print_debuginfo(l_module_name, 'EXIT');
11398
11399 EXCEPTION
11400 WHEN OTHERS THEN
11401
11402 /*
11403 * This is a non-fatal exception. We will log the exception
11404 * and return.
11405 */
11406 print_debuginfo(l_module_name, 'Non-Fatal: Exception occured '
11407 || 'when trying to print completed documents using '
11408 || 'completion id: '
11409 || p_completion_id
11410 );
11411
11412 print_debuginfo(l_module_name, 'SQLCODE: ' || SQLCODE);
11413 print_debuginfo(l_module_name, 'SQLERRM: ' || SQLERRM);
11414 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
11415
11416 END print_completed_docs;
11417
11418
11419 /*--------------------------------------------------------------------
11420 | NAME:
11421 | is_security_function_valid
11422 |
11423 | PURPOSE:
11424 | This API will return Y or N is the security function passed
11425 | is assigned to the user. This function wraps the
11426 | FND_FUNCTION.TEST API.
11427 |
11428 | PARAMETERS:
11429 | IN x_security_function_name
11430 |
11431 | RETURNS: x_function_valid (Y, N)
11432 |
11433 | NOTES:
11434 | Internal API, not for public use.
11435 | This API is used by the taks list page to determine if a user is
11436 | available to do the setup for the Shared, FD or FC tasks.
11437 |
11438 *---------------------------------------------------------------------*/
11439 FUNCTION is_security_function_valid (
11440 x_security_function_name IN VARCHAR2)
11441 RETURN VARCHAR2 AS
11442
11443 x_return_status VARCHAR2(30) := 'N';
11444
11445 BEGIN
11446
11447 IF fnd_function.test(x_security_function_name) THEN
11448 x_return_status := 'Y';
11449 END IF;
11450
11451 RETURN x_return_status;
11452 END is_security_function_valid;
11453
11454
11455
11456 /*--------------------------------------------------------------------
11457 | NAME:
11458 | Rejected_user_acc
11459 |
11460 |
11461 | PURPOSE:
11462 | Checks whether the user has access to all the org. or payment function
11463 | of rejected or removed entities ( documents or payments) for a
11464 | given payment service request.
11465 |
11466 | PARAMETERS:
11467 | IN
11468 |
11469 |
11470 | OUT
11471 |
11472 |
11473 | RETURNS:
11474 |
11475 | NOTES:
11476 | Internal API, not for public use.
11477 |
11478 *---------------------------------------------------------------------*/
11479 PROCEDURE Rejected_user_acc(
11480 p_pay_service_request_id IN NUMBER,
11481 x_inaccessible_entities OUT NOCOPY VARCHAR2,
11482 x_return_status IN OUT NOCOPY VARCHAR2,
11483 x_return_message IN OUT NOCOPY VARCHAR2)
11484 IS
11485 l_module_name CONSTANT VARCHAR2(200) := G_PKG_NAME
11486 || '.Rejected_user_acc';
11487
11488 l_doc_function_count NUMBER:=0;
11489 l_doc_org_count NUMBER:=0;
11490 l_pmt_org_count NUMBER:=0;
11491 BEGIN
11492
11493
11494 print_debuginfo(l_module_name, 'ENTER');
11495 --Initializing the out parameter
11496 x_inaccessible_entities :='N';
11497
11498 FND_MSG_PUB.initialize;
11499
11500 /*Initializing security through CE for populating the
11501 ce related global tables*/
11502 CEP_STANDARD.init_security();
11503
11504 populatePaymentFunctions(x_return_status, x_return_message);
11505
11506 /* Initialize return status */
11507 x_return_status := FND_API.G_RET_STS_SUCCESS;
11508
11509 select count(1)
11510 into l_doc_function_count
11511 FROM IBY_DOCS_PAYABLE_ALL docs
11512 where docs.document_status IN
11513 ( 'REJECTED',
11514 'FAILED_BY_RELATED_DOCUMENT',
11515 'FAILED_BY_REJECTION_LEVEL',
11516 'FAILED_BY_CALLING_APP',
11517 'REMOVED',
11518 'REMOVED_PAYMENT_REMOVED',
11519 'REMOVED_REQUEST_TERMINATED',
11520 'REMOVED_INSTRUCTION_TERMINATED',
11521 'REMOVED_PAYMENT_STOPPED',
11522 'REMOVED_PAYMENT_VOIDED')
11523 AND docs.payment_service_request_id = p_pay_service_request_id
11524 and docs.payment_function not in
11525 (select payment_function
11526 from IBY_USER_PAY_FUNS_GT
11527 );
11528 print_debuginfo(l_module_name, 'Number of Missing Payment Function for rejected documents:' ||l_doc_function_count);
11529
11530 select count(1)
11531 into l_doc_org_count
11532 FROM IBY_DOCS_PAYABLE_ALL docs
11533 where docs.document_status IN
11534 ( 'REJECTED',
11535 'FAILED_BY_RELATED_DOCUMENT',
11536 'FAILED_BY_REJECTION_LEVEL',
11537 'FAILED_BY_CALLING_APP',
11538 'REMOVED',
11539 'REMOVED_PAYMENT_REMOVED',
11540 'REMOVED_REQUEST_TERMINATED',
11541 'REMOVED_INSTRUCTION_TERMINATED',
11542 'REMOVED_PAYMENT_STOPPED',
11543 'REMOVED_PAYMENT_VOIDED')
11544 AND docs.payment_service_request_id = p_pay_service_request_id
11545 and docs.org_id not in
11546 (select organization_id
11547 from ce_security_profiles_v cep
11548 where cep.organization_type=docs.org_type
11549 );
11550
11551 print_debuginfo(l_module_name, 'Number of Missing Orgs for rejected documents:' ||l_doc_org_count);
11552
11553
11554 select count(1)
11555 into l_pmt_org_count
11556 FROM iby_payments_all payments
11557 where payments.payment_status IN
11558 ('FAILED_BY_REJECTION_LEVEL',
11559 'FAILED_BY_CALLING_APP',
11560 'REMOVED',
11561 'REMOVED_REQUEST_TERMINATED',
11562 'REMOVED_INSTRUCTION_TERMINATED',
11563 'REMOVED_DOCUMENT_SPOILED',
11564 'REMOVED_PAYMENT_STOPPED',
11565 'VOID')
11566 and payments.org_id not in
11567 (select organization_id
11568 from ce_security_profiles_v cep
11569 where cep.organization_type=payments.org_type
11570 );
11571 print_debuginfo(l_module_name, 'Number of Missing Org for rejected payments:' ||l_pmt_org_count);
11572
11573 -- check the user access
11574 if(l_doc_function_count<>0 OR l_doc_org_count <>0 OR l_pmt_org_count <>0) THEN
11575
11576 print_debuginfo(l_module_name, 'User doesnt have full access to the Rejected documents or Rejected Payments for a given payment process Request');
11577
11578 x_inaccessible_entities:='Y';
11579 print_debuginfo(l_module_name, 'Returning Y for x_inaccessible_entities');
11580
11581 end if;
11582 print_debuginfo(l_module_name, 'EXIT');
11583
11584 EXCEPTION
11585 WHEN OTHERS THEN
11586 print_debuginfo(l_module_name, 'SQL err msg: '
11587 || SQLERRM);
11588 print_debuginfo(l_module_name, 'Returning failure response .. '
11589 );
11590 FND_MSG_PUB.add_exc_msg(G_PKG_NAME, l_module_name, null);
11591 /*
11592 * The error message would have already been set.
11593 * Just set the error status here.
11594 */
11595 x_return_status := FND_API.G_RET_STS_ERROR;
11596
11597 print_debuginfo(l_module_name, 'EXIT');
11598
11599
11600 END Rejected_user_acc;
11601
11602
11603
11604 END IBY_DISBURSE_UI_API_PUB_PKG;
11605